diff --git a/.gitmodules b/.gitmodules index 5199bdb4d..9ac26001d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -20,3 +20,15 @@ [submodule "supportlibs/jni.hpp"] path = supportlibs/jni.hpp url = https://github.com/RetroShare/jni.hpp.git +[submodule "openpgpsdk"] + path = openpgpsdk + url = ../OpenPGP-SDK + branch = master +[submodule "libbitdht"] + path = libbitdht + url = ../BitDHT + branch = master +[submodule "libretroshare"] + path = libretroshare + url = ../libretroshare + branch = master diff --git a/libbitdht b/libbitdht new file mode 160000 index 000000000..b7307cd0b --- /dev/null +++ b/libbitdht @@ -0,0 +1 @@ +Subproject commit b7307cd0bfc2d197bd09f9cec0058bbbb4e235dc diff --git a/libbitdht/CMakeLists.txt b/libbitdht/CMakeLists.txt deleted file mode 100644 index af352651c..000000000 --- a/libbitdht/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -# RetroShare decentralized communication platform -# -# Copyright (C) 2021 Gioacchino Mazzurco -# Copyright (C) 2021 AsociaciĆ³n Civil Altermundi -# -# SPDX-License-Identifier: CC0-1.0 - -cmake_minimum_required (VERSION 2.8.12) -project(bitdht) - -file( - GLOB BITDHT_SOURCES - src/bitdht/*.c src/bitdht/*.cc src/udp/*.cc src/util/*.cc ) - -add_library(${PROJECT_NAME} ${BITDHT_SOURCES}) - -target_include_directories( - ${PROJECT_NAME} - PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) diff --git a/libbitdht/src/README.txt b/libbitdht/src/README.txt deleted file mode 100644 index a1dff67e4..000000000 --- a/libbitdht/src/README.txt +++ /dev/null @@ -1,25 +0,0 @@ -# SPDX-FileCopyrightText: (C) 2004-2019 Retroshare Team -# SPDX-License-Identifier: CC0-1.0 - -What's in the Package ---------------------------------------------------------------- -bitdht - base BitDHT Code. -util - generic utils for networking and threading. -udp - UDP interfacing code. -lib - Where the library is created. -tests - basic unit tests. -example - example code of how to use libbitdht. -libbitdht.pro - build script for Qt's qmake. -README.txt - this file. - - -HOWTO libbitdht. ----------------------------------------------- -This version is build using Qt's qmake system. - -1) Install Qt's qmake system: libqt-dev -2) type ./qmake -3) type ./make -4) check out the example and tests to learn how to interface with libbitdht. - - diff --git a/libbitdht/src/bitdht/bdaccount.cc b/libbitdht/src/bitdht/bdaccount.cc deleted file mode 100644 index 57de177f7..000000000 --- a/libbitdht/src/bitdht/bdaccount.cc +++ /dev/null @@ -1,133 +0,0 @@ -/******************************************************************************* - * bitdht/bdaccount.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "bitdht/bdaccount.h" - -#include -#include - -#include -#include - - -#define LPF_FACTOR (0.90) - -bdAccount::bdAccount() - :mNoStats(BDACCOUNT_NUM_ENTRIES), - mCountersOut(BDACCOUNT_NUM_ENTRIES), mCountersRecv(BDACCOUNT_NUM_ENTRIES), - mLpfOut(BDACCOUNT_NUM_ENTRIES), mLpfRecv(BDACCOUNT_NUM_ENTRIES), - mLabel(BDACCOUNT_NUM_ENTRIES) -{ - - mLabel[BDACCOUNT_MSG_OUTOFDATEPING] = "OUTOFDATEPING "; - mLabel[BDACCOUNT_MSG_PING] = "PING "; - mLabel[BDACCOUNT_MSG_PONG] = "PONG "; - mLabel[BDACCOUNT_MSG_QUERYNODE] = "QUERYNODE "; - mLabel[BDACCOUNT_MSG_QUERYHASH] = "QUERYHASH "; - mLabel[BDACCOUNT_MSG_REPLYFINDNODE] = "REPLYFINDNODE "; - mLabel[BDACCOUNT_MSG_REPLYQUERYHASH] = "REPLYQUERYHASH "; - - mLabel[BDACCOUNT_MSG_POSTHASH] = "POSTHASH "; - mLabel[BDACCOUNT_MSG_REPLYPOSTHASH] = "REPLYPOSTHASH "; - - mLabel[BDACCOUNT_MSG_CONNECTREQUEST] = "CONNECTREQUEST "; - mLabel[BDACCOUNT_MSG_CONNECTREPLY] = "CONNECTREPLY "; - mLabel[BDACCOUNT_MSG_CONNECTSTART] = "CONNECTSTART "; - mLabel[BDACCOUNT_MSG_CONNECTACK] = "CONNECTACK "; - - resetStats(); -} - - -void bdAccount::incCounter(uint32_t idx, bool out) -{ - if ((signed) idx > mNoStats-1) - { - std::cerr << "bdAccount::incCounter() Invalid Index"; - std::cerr << std::endl; - } - - if (out) - { - mCountersOut[idx]++; - } - else - { - mCountersRecv[idx]++; - } - return; -} - - -void bdAccount::doStats() -{ - int i; - for(i = 0; i < mNoStats; i++) - { - mLpfOut[i] *= (LPF_FACTOR) ; - mLpfOut[i] += (1.0 - LPF_FACTOR) * mCountersOut[i]; - - mLpfRecv[i] *= (LPF_FACTOR) ; - mLpfRecv[i] += (1.0 - LPF_FACTOR) * mCountersRecv[i]; - } - resetCounters(); -} - -void bdAccount::printStats(std::ostream &out) -{ - int i; - out << " Send Recv: "; - out << std::endl; - for(i = 0; i < mNoStats; i++) - { - - out << "Send" << mLabel[i] << " : " << std::setw(10) << mLpfOut[i]; - out << " "; - out << "Recv" << mLabel[i] << " : " << std::setw(10) << mLpfRecv[i]; - out << std::endl; - } -} - -void bdAccount::resetCounters() -{ - int i; - for(i = 0; i < mNoStats; i++) - { - mCountersOut[i] = 0; - mCountersRecv[i] = 0; - } -} - -void bdAccount::resetStats() -{ - int i; - for(i = 0; i < mNoStats; i++) - { - mLpfOut[i] = 0; - mLpfRecv[i] = 0; - } - resetCounters(); -} - - - - diff --git a/libbitdht/src/bitdht/bdaccount.h b/libbitdht/src/bitdht/bdaccount.h deleted file mode 100644 index 7116e3ced..000000000 --- a/libbitdht/src/bitdht/bdaccount.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef BITDHT_ACCOUNT_H -#define BITDHT_ACCOUNT_H - -/******************************************************************************* - * bitdht/bdaccount.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include -#include -#include - -#define BDACCOUNT_MSG_OUTOFDATEPING 0 -#define BDACCOUNT_MSG_PING 1 -#define BDACCOUNT_MSG_PONG 2 -#define BDACCOUNT_MSG_QUERYNODE 3 -#define BDACCOUNT_MSG_QUERYHASH 4 -#define BDACCOUNT_MSG_REPLYFINDNODE 5 -#define BDACCOUNT_MSG_REPLYQUERYHASH 6 - -#define BDACCOUNT_MSG_POSTHASH 7 -#define BDACCOUNT_MSG_REPLYPOSTHASH 8 - -#define BDACCOUNT_MSG_CONNECTREQUEST 9 -#define BDACCOUNT_MSG_CONNECTREPLY 10 -#define BDACCOUNT_MSG_CONNECTSTART 11 -#define BDACCOUNT_MSG_CONNECTACK 12 - -#define BDACCOUNT_NUM_ENTRIES 13 - -class bdAccount -{ - public: - - bdAccount(); - - void incCounter(uint32_t idx, bool out); - void doStats(); - void printStats(std::ostream &out); - void resetCounters(); - void resetStats(); - - private: - - int mNoStats; - - std::vector mCountersOut; - std::vector mCountersRecv; - - std::vector mLpfOut; - std::vector mLpfRecv; - - std::vector mLabel; - // Statistics. -}; - - - -#endif // BITDHT_ACCOUNT_H diff --git a/libbitdht/src/bitdht/bdboot.txt b/libbitdht/src/bitdht/bdboot.txt deleted file mode 100644 index 273a35afc..000000000 --- a/libbitdht/src/bitdht/bdboot.txt +++ /dev/null @@ -1,267 +0,0 @@ -1.162.168.21 8956 -2.6.224.136 17320 -5.116.142.222 13755 -5.189.185.57 6968 -5.202.101.3 4000 -5.227.124.122 1024 -5.227.124.122 20600 -5.227.124.122 64196 -5.39.94.218 6991 -5.79.102.9 6881 -5.89.120.163 2457 -14.117.182.22 1091 -14.8.109.32 17160 -23.115.236.180 42375 -24.153.98.173 1024 -24.38.199.13 10583 -27.150.87.242 1123 -27.151.179.38 51413 -27.152.212.182 1424 -31.24.186.40 16143 -31.36.78.93 30020 -31.44.90.218 51413 -37.120.213.132 19525 -37.14.113.18 3815 -37.146.76.158 51413 -37.187.105.230 5169 -37.232.184.93 6881 -37.46.150.58 51413 -39.111.152.200 17527 -39.154.68.57 28007 -42.200.116.4 18578 -42.3.188.207 19771 -45.176.111.21 1434 -45.32.43.51 49091 -45.76.218.165 52911 -45.77.214.200 44350 -46.172.86.23 46039 -46.223.161.46 23693 -46.237.96.68 16536 -46.52.174.214 24012 -46.7.227.47 27644 -46.7.9.41 21374 -49.64.73.215 51413 -49.74.50.28 60893 -49.75.73.147 51413 -49.79.26.15 51413 -49.83.226.50 20864 -49.83.241.222 51413 -52.9.197.152 6881 -58.209.188.12 20994 -59.149.118.196 51413 -59.2.250.243 57099 -59.6.53.18 57437 -60.104.89.4 51413 -60.124.114.239 16925 -60.178.44.27 1050 -60.99.229.14 20617 -61.223.34.21 17881 -61.227.127.222 22223 -61.239.28.169 18873 -62.210.82.193 51413 -64.191.5.92 56891 -65.92.141.96 58361 -67.215.246.10 6881 -68.151.213.83 20047 -69.40.178.254 50793 -71.34.2.150 8053 -72.95.247.56 12956 -73.157.77.166 5477 -74.109.243.24 7250 -74.140.153.59 24757 -74.72.13.99 9613 -76.29.106.98 41447 -77.202.207.190 33034 -77.21.64.116 22222 -77.245.14.94 9910 -78.131.78.35 51238 -78.158.1.15 7433 -78.231.125.98 12162 -78.242.250.55 55946 -79.164.245.5 49001 -80.147.23.201 32746 -80.200.171.90 16294 -80.99.222.34 51414 -81.171.17.30 42254 -82.221.103.244 6881 -82.235.78.193 44097 -82.244.32.78 43518 -82.64.181.170 38240 -82.64.249.25 51413 -82.64.44.119 51413 -82.65.164.218 15726 -82.65.68.9 51413 -82.77.146.109 53713 -83.46.92.34 50000 -84.195.46.218 54600 -84.40.106.115 12046 -85.149.0.42 21045 -86.121.194.1 51413 -86.98.50.30 21455 -87.123.166.45 4145 -87.169.199.211 10496 -88.7.217.202 31348 -88.99.25.154 38051 -89.135.26.33 51413 -89.17.134.184 10327 -89.245.86.20 32417 -89.253.118.133 8621 -90.101.94.104 20780 -90.151.95.110 2199 -90.219.241.30 51413 -90.219.8.170 11916 -91.121.136.132 59001 -91.123.72.241 49001 -91.142.65.40 51413 -91.173.208.204 16300 -91.211.245.40 7369 -91.92.194.144 1031 -91.98.96.76 5385 -92.244.238.115 3115 -92.97.68.210 58000 -93.100.182.236 32249 -93.11.175.113 22948 -93.115.202.240 64493 -93.152.132.9 12332 -94.154.81.100 12345 -94.222.188.14 29299 -95.211.117.105 62086 -95.219.143.102 10360 -95.222.119.133 43087 -95.42.138.33 16550 -96.39.191.231 52000 -99.192.24.198 52552 -103.226.250.79 3521 -103.82.242.163 8083 -104.156.238.118 34731 -104.237.149.26 64879 -107.155.5.39 6881 -109.129.202.63 11076 -109.148.168.121 21651 -109.24.244.111 33334 -110.81.114.66 24732 -111.175.84.3 6881 -111.216.9.68 13493 -113.105.18.227 16001 -113.194.69.53 53858 -113.219.200.7 12935 -113.252.78.238 23474 -113.68.239.87 6396 -113.69.96.171 51443 -114.188.193.161 22555 -114.231.190.193 51413 -114.232.201.253 30350 -114.32.153.245 26233 -114.32.1.94 7788 -114.38.137.40 24062 -114.75.44.238 6881 -115.133.66.181 9460 -115.205.157.105 51413 -116.1.193.182 51413 -117.247.200.35 5353 -117.60.240.145 35709 -117.60.62.8 51413 -117.93.101.232 51413 -118.123.245.182 5060 -119.177.21.161 27048 -119.64.245.112 56265 -121.171.118.184 11566 -121.178.169.67 49259 -121.234.117.237 15398 -122.116.102.22 14054 -123.202.146.112 23118 -123.217.135.139 7830 -128.68.229.32 51413 -134.209.114.242 8000 -139.28.218.4 34826 -142.113.115.71 26453 -148.251.68.55 50000 -148.70.53.219 2551 -150.117.108.250 21902 -150.117.44.190 25052 -151.224.15.227 51413 -157.157.157.41 51413 -161.97.102.243 51902 -162.208.6.211 51413 -167.179.83.227 60220 -168.70.68.30 18325 -169.0.60.179 64494 -171.5.165.129 6881 -172.104.76.77 60542 -172.104.93.28 35617 -172.98.144.81 19186 -173.176.138.246 9545 -173.199.70.134 39045 -173.212.205.73 51432 -173.212.219.143 6881 -174.89.174.228 51413 -175.197.1.120 52574 -176.9.8.143 58250 -178.118.86.145 51413 -178.162.139.87 10029 -178.32.220.92 6881 -178.67.121.182 49001 -182.138.217.58 6881 -182.138.90.72 50288 -182.139.213.160 39587 -183.131.239.178 57835 -183.22.252.15 21568 -185.126.33.59 50024 -185.156.175.187 1025 -185.157.221.247 25401 -185.252.60.243 49001 -185.45.195.156 28074 -185.45.195.181 28185 -185.45.195.190 28136 -185.61.148.114 64879 -188.133.192.123 19967 -188.235.1.208 7890 -188.240.208.187 51413 -192.181.103.63 19627 -192.241.151.29 6881 -193.242.205.145 49001 -193.77.153.124 59835 -194.176.114.54 51413 -194.35.233.206 20124 -195.154.172.169 36097 -195.154.172.169 38340 -195.154.172.169 48043 -195.154.172.169 48799 -195.154.179.2 22794 -195.154.179.2 41210 -195.154.179.2 42687 -195.154.179.2 49156 -195.154.179.2 50385 -195.154.179.2 50944 -195.154.181.225 37558 -195.191.246.240 1026 -196.191.92.25 22937 -197.157.219.137 22629 -197.61.66.105 24612 -198.13.48.70 37360 -199.254.238.193 15374 -200.63.107.82 13323 -201.241.63.68 38705 -203.130.242.178 28280 -203.213.61.76 50559 -207.154.222.13 51111 -210.195.211.60 49771 -210.6.145.50 15207 -212.102.42.202 7611 -212.129.19.188 27096 -212.129.19.188 29812 -212.129.19.188 50117 -212.129.19.188 51965 -212.129.33.59 6881 -212.32.231.67 51413 -212.86.51.7 65148 -213.136.79.7 11910 -218.161.100.192 51413 -218.219.199.148 18753 -220.189.94.56 13279 -222.211.148.83 8080 -222.77.110.143 46016 -223.116.81.154 10655 -223.16.153.107 51413 -223.26.31.77 21440 -223.65.101.235 25159 diff --git a/libbitdht/src/bitdht/bdboot_generate.sh b/libbitdht/src/bitdht/bdboot_generate.sh deleted file mode 100755 index 97618f0df..000000000 --- a/libbitdht/src/bitdht/bdboot_generate.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash - -< - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . - -LICENSE - -< bdboot.txt --------------------------------- -README - -function check_dht_host() -{ - mHost="$1" - mPort="$2" - - sudo nmap -oG - -sU -p $mPort $mHost | grep open | \ - awk '{print $2" "$5}' | awk -F/ '{print $1}' -} - -cat | while read line; do - hostIP="$(echo $line | awk '{print $1}')" - hostPort="$(echo $line | awk '{print $2}')" - check_dht_host $hostIP $hostPort -done - -check_dht_host router.utorrent.com 6881 -check_dht_host router.bittorrent.com 6881 -check_dht_host dht.libtorrent.org 25401 -check_dht_host dht.transmissionbt.com 6881 - diff --git a/libbitdht/src/bitdht/bdconnection.cc b/libbitdht/src/bitdht/bdconnection.cc deleted file mode 100644 index 494e076f3..000000000 --- a/libbitdht/src/bitdht/bdconnection.cc +++ /dev/null @@ -1,3528 +0,0 @@ -/******************************************************************************* - * bitdht/bdconnection.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include -#include "bitdht/bdiface.h" - -#include "bitdht/bdnode.h" -#include "bitdht/bdquerymgr.h" -#include "bitdht/bdconnection.h" -#include "bitdht/bdmsgs.h" -#include "bitdht/bdstddht.h" -#include "util/bdnet.h" -#include "util/bdrandom.h" -#include "util/bdstring.h" - -/* - * #define DEBUG_PROXY_CONNECTION 1 - * #define DEBUG_NODE_CONNECTION 1 - * #define DEBUG_NODE_CONNECTION_EXTRA 1 - * #define DEBUG_CONNECTION_DELAY 1 - */ - -//#define DEBUG_PROXY_CONNECTION 1 -//#define DEBUG_NODE_CONNECTION 1 -//#define DEBUG_CONNECTION_DELAY 1 - - -#define BITDHT_CR_PAUSE_SHORT_PERIOD 1 -#define BITDHT_CR_PAUSE_START_PERIOD 10 - -#define MAX_NUM_RETRIES 3 - -uint32_t createConnectionErrorCode(uint32_t userProvided, uint32_t fallback, uint32_t point); - -/************************************************************************************************************ -******************************************** Connection Config ********************************************** -************************************************************************************************************/ - -bdConnectManager::bdConnectManager(bdNodeId *ownId, bdSpace *space, bdQueryManager *qmgr, bdDhtFunctions *fns, bdNodePublisher *pub) - :mOwnId(*ownId), mNodeSpace(space), mQueryMgr(qmgr), mFns(fns), mPub(pub) -{ - defaultConnectionOptions(); -} - - - - -void bdConnectManager::defaultConnectionOptions() -{ - /* by default we want to help people proxy connections. - * As this involves no interaction at higher levels, - * we want ALL BitDHT clients to support - unless explicitly disabled. - */ - - setConnectionOptions(BITDHT_CONNECT_MODE_PROXY, - BITDHT_CONNECT_OPTION_AUTOPROXY); -} - -void bdConnectManager::setConnectionOptions(uint32_t allowedModes, uint32_t flags) -{ - mConfigAllowedModes = allowedModes; - mConfigAutoProxy = false; - - if (flags & BITDHT_CONNECT_OPTION_AUTOPROXY) - { - mConfigAutoProxy = true; - } - -} - -/* Setup Relay Mode */ -void bdConnectManager::setRelayMode(uint32_t mode) -{ - mRelayMode = mode; -} - - -void bdConnectManager::shutdownConnections() -{ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::shutdownConnections() Brutal Shutdown of the following connections: "; - std::cerr << std::endl; - - printConnections(); -#endif - - mConnectionRequests.clear(); - mConnections.clear(); - -} - -void bdConnectManager::printConnections() -{ - std::cerr << "bdConnectManager::printConnections()"; - std::cerr << std::endl; - - std::map::iterator it; - for(it = mConnectionRequests.begin(); it != mConnectionRequests.end(); it++) - { - std::cerr << "bdConnectManager::printConnections() Connect Request:"; - std::cerr << std::endl; - std::cerr << it->second; - std::cerr << std::endl; - } - - std::map::iterator tit; - for(tit = mConnections.begin(); tit != mConnections.end(); tit++) - { - std::cerr << "bdConnectManager::printConnections() ConnectAttempt:"; - std::cerr << std::endl; - std::cerr << tit->second; - std::cerr << std::endl; - } -} - - - - - - -/************************************************************************************************************ -****************************************** Connection Initiation ******************************************** -************************************************************************************************************/ - - -/* This is called to initialise a connection. - * the callback could be with regard to: - * a Direct EndPoint. - * a Proxy Proxy, or an Proxy EndPoint. - * a Relay Proxy, or an Relay EndPoint. - * - * We have two alternatives: - * 1) Direct Endpoint. - * 2) Using a Proxy. - */ - -int bdConnectManager::requestConnection(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t delay, uint32_t start) -{ - /* check if connection obj already exists */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::requestConnection() Mode: " << mode; - std::cerr << " Start: " << start; - std::cerr << " Target: "; - mFns->bdPrintNodeId(std::cerr, target); - std::cerr << " Local NetAddress: " << inet_ntoa(laddr->sin_addr); - std::cerr << ":" << ntohs(laddr->sin_port); - std::cerr << std::endl; -#endif - - if (!start) - { - return killConnectionRequest(laddr, target, mode); - } - - if (!(mConfigAllowedModes & mode)) - { - /* MODE not supported */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::requestConnection() Mode Not Supported"; - std::cerr << std::endl; -#endif - return 0; - } - - // Seems like a dumb one, but the testing picked it up. - if (*target == mOwnId) - { - /* MODE not supported */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::requestConnection() WARNING Not allowing connection to self"; - std::cerr << std::endl; -#endif - return 0; - } - - if (mode == BITDHT_CONNECT_MODE_DIRECT) - { - return requestConnection_direct(laddr, target); - } - else - { - return requestConnection_proxy(laddr, target, mode, delay); - } -} - -int bdConnectManager::checkExistingConnectionAttempt(bdNodeId *target) -{ - std::map::iterator it; - it = mConnectionRequests.find(*target); - if (it != mConnectionRequests.end()) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::checkExistingConnectAttempt() Found Existing Connection!"; - std::cerr << std::endl; -#endif - return 1; - } - return 0; -} - - -int bdConnectManager::killConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode) -{ - /* remove unused parameter warnings */ - (void) laddr; - (void) mode; - - /* check if connection obj already exists */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::killConnectionRequest() Mode: " << mode; - std::cerr << " Target: "; - mFns->bdPrintNodeId(std::cerr, target); - std::cerr << " Local NetAddress: " << inet_ntoa(laddr->sin_addr); - std::cerr << ":" << ntohs(laddr->sin_port); - std::cerr << std::endl; -#endif - - std::map::iterator it; - it = mConnectionRequests.find(*target); - if (it == mConnectionRequests.end()) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::killConnectionRequest() ERROR Request not there!"; - std::cerr << std::endl; -#endif - return 0; - } - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::killConnectionRequest() Flagging Connection Request as DONE"; - std::cerr << std::endl; -#endif - - time_t now = time(NULL); - it->second.mState = BITDHT_CONNREQUEST_DONE; - it->second.mStateTS = now; - it->second.mErrCode = BITDHT_CONNECT_ERROR_SOURCE_START | - BITDHT_CONNECT_ERROR_USER; - - -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::killConnectionRequest() Flagging Connection Request as DONE"; - std::cerr << std::endl; - // Print Connection Attempt. - std::cerr << it->second << std::endl; -#endif - - return 1; -} - - - - -#define MIN_START_DIRECT_COUNT 1 -#define MIN_START_PROXY_COUNT 3 -#define MED_START_PROXY_COUNT 5 -#define CONNECT_NUM_PROXY_ATTEMPTS 10 - - -int bdConnectManager::requestConnection_direct(struct sockaddr_in *laddr, bdNodeId *target) -{ - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::requestConnection_direct()"; - std::cerr << std::endl; -#endif - /* create a bdConnect, and put into the queue */ - bdConnectionRequest connreq; - - if (checkExistingConnectionAttempt(target)) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::requestConnection_direct() Existing ConnectionRequest... NOOP"; - std::cerr << std::endl; -#endif - return 0; - } - - connreq.setupDirectConnection(laddr, target); - - std::list goodProxies; - std::list::iterator pit; - mQueryMgr->result(target, goodProxies); - for(pit = goodProxies.begin(); pit != goodProxies.end(); pit++) - { - connreq.mGoodProxies.push_back(bdProxyId(*pit, BD_PI_SRC_QUERYRESULT, 0)); - } - - /* now look in the bdSpace as well */ - if (connreq.mGoodProxies.size() < MIN_START_DIRECT_COUNT) - { - int number = CONNECT_NUM_PROXY_ATTEMPTS; - int with_flag = BITDHT_PEER_STATUS_DHT_ENGINE_VERSION; - std::list matchIds; - std::list::iterator it; - std::list::iterator git; - - mNodeSpace->find_node(target, number, matchIds, with_flag); - - /* merge lists (costly should use sets or something) */ - for(it = matchIds.begin(); it != matchIds.end(); it++) - { - for(git = connreq.mGoodProxies.begin(); git != connreq.mGoodProxies.end(); git++) - { - if (git->id == *it) - break; - } - - if (git == connreq.mGoodProxies.end()) - { - connreq.mGoodProxies.push_back(bdProxyId(*it, BD_PI_SRC_NODESPACE_ENGINEVERSION, 0)); - } - } - } - - /* Actually if we lots of ids at this point... its likely that something is wrong - */ - - if (connreq.mGoodProxies.size() > 1) - { - std::cerr << "bdConnectManager::requestConnection_direct() ERROR Multiple Peers for DIRECT connection"; - std::cerr << std::endl; - } - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::requestConnection_direct() CRINITSTATE Init Connection State"; - std::cerr << std::endl; - std::cerr << connreq; - std::cerr << std::endl; -#endif - - /* push connect onto queue, for later completion */ - - mConnectionRequests[*target] = connreq; - - /* connection continued via iterator */ - return 1; -} - - -int bdConnectManager::requestConnection_proxy(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t delay) -{ - -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy()"; - std::cerr << std::endl; -#endif - - - if (checkExistingConnectionAttempt(target)) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy() Existing ConnectionRequest... NOOP"; - std::cerr << std::endl; -#endif - return 0; - } - - /* create a bdConnect, and put into the queue */ - bdConnectionRequest connreq; - connreq.setupProxyConnection(laddr, target, mode, delay); - - /**** - * We want different behaviour here - depending on whether it is a proxy or a relay request - * furthermore if we are in relay server mode - we should only use those. - * - * Try to unify logic. - * - * Proxy - take potential proxies... - * - if RelayServerMode then relays. - * - take friends, friends of friends. - * - * Relay - - * - if RelayServerMode take relays. - * - take friends, friends of friends - * - take potential proxies. - */ - - - /* get the proxy lists from existing query */ - std::list::iterator pit; - std::list goodProxies; - std::list potentialProxies; - mQueryMgr->proxies(target, goodProxies); - mQueryMgr->potentialProxies(target, potentialProxies); - - /* check any potential proxies, must be same DHT Type */ - for(pit = potentialProxies.begin(); pit != potentialProxies.end(); ) - { - /* check the type in bdSpace */ - if (checkPeerForFlag(&(*pit), BITDHT_PEER_STATUS_DHT_ENGINE_VERSION)) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy() Shifting Pot -> Good: "; - mFns->bdPrintId(std::cerr, &(*pit)); - std::cerr << std::endl; -#endif - goodProxies.push_back(*pit); - pit = potentialProxies.erase(pit); - } - else - { - pit++; - } - } - - /* in proxy mode - put Good Proxies First */ - if (mode == BITDHT_CONNECT_MODE_PROXY) - { - for(pit = goodProxies.begin(); pit != goodProxies.end(); pit++) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy() Adding Good Proxy: "; - mFns->bdPrintId(std::cerr, &(*pit)); - std::cerr << std::endl; -#endif - connreq.mGoodProxies.push_back(bdProxyId(*pit, BD_PI_SRC_QUERYPROXY, 0)); - } - } - - - if (mRelayMode) - { - /* Add Relay Servers */ -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy() In RelayMode... adding Relays"; -#endif - - std::list excluding; - std::multimap nearest; - - int number = CONNECT_NUM_PROXY_ATTEMPTS; - - mNodeSpace->find_nearest_nodes_with_flags(target, number, excluding, nearest, - BITDHT_PEER_STATUS_DHT_RELAY_SERVER); - - std::multimap::iterator it; - for(it = nearest.begin(); it != nearest.end(); it++) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy() Adding Relay Server: "; - mFns->bdPrintId(std::cerr, &(it->second)); - std::cerr << std::endl; -#endif - connreq.mGoodProxies.push_back(bdProxyId(it->second, BD_PI_SRC_NODESPACE_SERVER, 0)); - } - } - - { - std::list excluding; - std::multimap nearest; - - int number = CONNECT_NUM_PROXY_ATTEMPTS; - - mNodeSpace->find_nearest_nodes_with_flags(target, number, excluding, nearest, - BITDHT_PEER_STATUS_DHT_FRIEND); - - std::multimap::iterator it; - for(it = nearest.begin(); it != nearest.end(); it++) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy() Adding Friend: "; - mFns->bdPrintId(std::cerr, &(it->second)); - std::cerr << std::endl; -#endif - connreq.mGoodProxies.push_back(bdProxyId(it->second, BD_PI_SRC_NODESPACE_FRIEND, 0)); - } - } - - - /* in relay mode - Good Proxies are the BackUp */ - if (mode == BITDHT_CONNECT_MODE_RELAY) - { - for(pit = goodProxies.begin(); pit != goodProxies.end(); pit++) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy() Adding Good Proxy: "; - mFns->bdPrintId(std::cerr, &(*pit)); - std::cerr << std::endl; -#endif - connreq.mGoodProxies.push_back(bdProxyId(*pit, BD_PI_SRC_QUERYPROXY, 0)); - } - } - - // Final Desperate Measures! - if (connreq.mGoodProxies.size() < MED_START_PROXY_COUNT) - { - std::list excluding; - std::multimap nearest; - - int number = CONNECT_NUM_PROXY_ATTEMPTS; - - mNodeSpace->find_nearest_nodes_with_flags(target, number, excluding, nearest, - BITDHT_PEER_STATUS_DHT_FOF); - - std::multimap::iterator it; - for(it = nearest.begin(); it != nearest.end(); it++) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy() Querying FOF: "; - mFns->bdPrintId(std::cerr, &(it->second)); - std::cerr << std::endl; -#endif - //connreq.mGoodProxies.push_back(it->second); - mPub->send_query(&(it->second), target, true); - } - } - - - /* if we don't have enough proxies ... ping the potentials */ - if (connreq.mGoodProxies.size() < MED_START_PROXY_COUNT) - { - /* unknown, add to potential list, and ping! */ - for(pit = potentialProxies.begin(); pit != potentialProxies.end(); pit++) - { - - connreq.mPotentialProxies.push_back(*pit); - // If the pings come back will be handled by - // updatePotentialConnectionProxy() - - mPub->send_ping(&(*pit)); - -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy() Pinging Potential Proxy"; - mFns->bdPrintId(std::cerr, &(*pit)); - std::cerr << std::endl; -#endif - } - } - - /*** ORIGINAL CODE - TRIES TO PING/SEARCH PEERS - INSTEAD OF JUST TRYING THEM - * NOT SURE WHAT THE BEST PLAN IS..... - * LEAVE THIS CODE HERE FOR REFERENCE.... - ***/ - -#if 0 - // Final Desperate Measures! - if (connreq.mGoodProxies.size() < MED_START_PROXY_COUNT) - { - /* now find closest acceptable peers, - * and trigger a search for target... - * this will hopefully find more suitable proxies. - */ - - std::list excluding; - std::multimap nearest; - - - int number = CONNECT_NUM_PROXY_ATTEMPTS; - - mNodeSpace->find_nearest_nodes_with_flags(target, number, excluding, nearest, - BITDHT_PEER_STATUS_DHT_FOF | - BITDHT_PEER_STATUS_DHT_FRIEND); - - // just ask for the same number of closest (above doesn't return anything atm) - //int nFound = nearest.size(); - //number = CONNECT_NUM_PROXY_ATTEMPTS - nFound; - - mNodeSpace->find_nearest_nodes_with_flags(target, number, excluding, nearest, - BITDHT_PEER_STATUS_DHT_ENGINE_VERSION ); - - std::multimap::iterator it; - for(it = nearest.begin(); it != nearest.end(); it++) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy() is Entry it connected to Friend? : "; - mFns->bdPrintId(std::cerr, &(it->second)); - std::cerr << std::endl; -#endif - - //bdNodeId midId; - //mFns->bdRandomMidId(target, &(it->second.id), &midId); - /* trigger search */ - //mPub->send_query(&(it->second), &midId); - mPub->send_query(&(it->second), target); - } - } -#endif - - - if (connreq.mGoodProxies.size() < 1) - { - std::cerr << "bdConnectManager::requestConnection_proxy() ERROR initial proxyList.size() == 0"; - std::cerr << std::endl; - } - - if (connreq.mGoodProxies.size() < MIN_START_PROXY_COUNT) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy() WARNING initial proxyList.size() == SMALL PAUSING"; - std::cerr << std::endl; -#endif - - time_t now = time(NULL); - /* PAUSE the connection Attempt, so we can wait for responses */ - connreq.mState = BITDHT_CONNREQUEST_PAUSED; - connreq.mPauseTS = now + BITDHT_CR_PAUSE_START_PERIOD; - } - -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::requestConnection_proxy() CRINITSTATE Init Connection State"; - std::cerr << std::endl; - std::cerr << connreq; - std::cerr << std::endl; -#endif - - - /* push connect onto queue, for later completion */ - mConnectionRequests[*target] = connreq; - - return 1; -} - - - - -void bdConnectManager::addPotentialConnectionProxy(const bdId *srcId, const bdId *target) -{ -#ifdef DEBUG_NODE_CONNECTION_EXTRA - std::cerr << "bdConnectManager::addPotentialConnectionProxy() "; - std::cerr << " srcId: "; - bdStdPrintId(std::cerr, srcId); - std::cerr << " target: "; - bdStdPrintId(std::cerr, target); - std::cerr << std::endl; -#endif - - if (!srcId) - { - /* not one of our targets... drop it */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::addPotentialConnectionProxy() srcID = NULL, useless to us"; - std::cerr << std::endl; -#endif - return; - } - - std::map::iterator it; - it = mConnectionRequests.find(target->id); - if (it == mConnectionRequests.end()) - { - /* not one of our targets... drop it */ -#ifdef DEBUG_NODE_CONNECTION_EXTRA - std::cerr << "bdConnectManager::addPotentialConnectionProxy() Dropping Not one of Our Targets"; - std::cerr << std::endl; -#endif - return; - } - - if (it->second.mMode == BITDHT_CONNECT_MODE_DIRECT) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::addPotentialConnectionProxy() Dropping Target is DIRECT"; - std::cerr << std::endl; -#endif - return; - } - - /* This is one is strange elsewhere.... srcId = targetId. - * This means that peer is actually reachable! and we should be connecting directly. - * however there is not much we can do about it here. Really up to higher level logic. - */ - if (srcId->id == target->id) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::addPotentialConnectionProxy() ERROR srcId.id == target.id (more of a WARNING)"; - std::cerr << std::endl; - std::cerr << "bdConnectManager::addPotentialConnectionProxy() NB: This means peer is actually reachable...."; - std::cerr << std::endl; - std::cerr << "bdConnectManager::addPotentialConnectionProxy() and we should be connecting directly. Oh Well!"; - std::cerr << std::endl; -#endif - return; - } - - if (checkPeerForFlag(srcId, BITDHT_PEER_STATUS_DHT_ENGINE_VERSION)) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::addPotentialConnectionProxy() Src passes FLAG test"; - std::cerr << std::endl; -#endif - it->second.addGoodProxy(srcId); - } - else - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::addPotentialConnectionProxy() Dropping SrcId failed FLAG test"; - std::cerr << std::endl; -#endif - } -} - - -int bdConnectManager::checkPeerForFlag(const bdId *id, uint32_t with_flag) -{ - /* check the type in bdSpace */ - bdPeer peer; - if (mNodeSpace->find_exactnode(id, peer)) - { - if (peer.mPeerFlags & with_flag) - { - return 1; - } - } - /* XXX eventually we'll need to check against extra peer lists. - * with our friends, etc - * - * ideally we'll track this info in the query! - */ - - return 0; -} - - -void bdConnectManager::updatePotentialConnectionProxy(const bdId *id, uint32_t mode) -{ - if (mode & BITDHT_PEER_STATUS_DHT_ENGINE_VERSION) - { -#ifdef DEBUG_NODE_CONNECTION_EXTRA - std::cerr << "bdConnectManager::updatePotentialConnectionProxy() Peer is GOOD : "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; - std::cerr << "bdConnectManager::updatePotentialConnectionProxy() checking Connection Requests"; - std::cerr << std::endl; -#endif - /* good peer, see if any of our connectionrequests can use it */ - std::map::iterator it; - for(it = mConnectionRequests.begin(); it != mConnectionRequests.end(); it++) - { - it->second.checkGoodProxyPeer(id); - } - } -} - - -int bdConnectManager::tickConnections() -{ - iterateConnectionRequests(); - iterateConnections(); - - return 1; -} - - -void bdConnectManager::iterateConnectionRequests() -{ - time_t now = time(NULL); - - std::list eraseList; - std::list::iterator eit; - - std::map::iterator it; - for(it = mConnectionRequests.begin(); it != mConnectionRequests.end(); it++) - { - bool erase = false; - -#ifdef DEBUG_NODE_CONNECTION_EXTRA - std::cerr << "bdConnectManager::iterateConnectionAttempt() Request is:"; - std::cerr << std::endl; - std::cerr << it->second; - std::cerr << std::endl; -#endif - - /* check status of connection */ - if (it->second.mState == BITDHT_CONNREQUEST_READY) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::iterateConnectionAttempt() Request is READY, starting"; - std::cerr << std::endl; -#endif - - /* kick off the connection if possible */ - // goes to BITDHT_CONNREQUEST_INPROGRESS; - if (!startConnectionAttempt(&(it->second))) - { -#ifdef DEBUG_NODE_CONNECTION - // FAILS if proxy is bad / nonexistent - std::cerr << "bdConnectManager::iterateConnectionAttempt() Failed startup => KILLED"; - std::cerr << std::endl; - std::cerr << it->second; - std::cerr << std::endl; -#endif - - it->second.mErrCode = BITDHT_CONNECT_ERROR_SOURCE_START | - BITDHT_CONNECT_ERROR_OUTOFPROXY; - it->second.mState = BITDHT_CONNREQUEST_DONE; - it->second.mStateTS = now; - - } - } - else if (it->second.mState == BITDHT_CONNREQUEST_PAUSED) - { - /* forced pause, with period specified at PAUSE point */ - if (now > it->second.mPauseTS) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::iterateConnectionAttempt() PAUSED has reached timout -> READY"; - std::cerr << std::endl; -#endif - - /* if we have run out of proxies, or recycled too many times. kill it */ - if (it->second.mGoodProxies.size() == 0) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::iterateConnectionAttempt() no more proxies => DONE"; - std::cerr << std::endl; -#endif - - it->second.mErrCode = BITDHT_CONNECT_ERROR_SOURCE_START | - BITDHT_CONNECT_ERROR_OUTOFPROXY; - it->second.mState = BITDHT_CONNREQUEST_DONE; - it->second.mStateTS = now; - } - else if ((unsigned) it->second.mRecycled > it->second.mGoodProxies.size() * MAX_NUM_RETRIES) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::iterateConnectionAttempt() to many retries => DONE"; - std::cerr << std::endl; -#endif - - it->second.mErrCode = BITDHT_CONNECT_ERROR_SOURCE_START | - BITDHT_CONNECT_ERROR_TOOMANYRETRY; - it->second.mState = BITDHT_CONNREQUEST_DONE; - it->second.mStateTS = now; - } - else - { - /* timeout and restart */ - it->second.mState = BITDHT_CONNREQUEST_READY; - it->second.mStateTS = now; - } - } - } - else if (it->second.mState == BITDHT_CONNREQUEST_INPROGRESS) - { - /* single connection attempt */ - if (now - it->second.mStateTS > BITDHT_CONNREQUEST_TIMEOUT_INPROGRESS) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::iterateConnectionAttempt() INPROGRESS has reached timout -> READY"; - std::cerr << std::endl; - std::cerr << it->second; - std::cerr << std::endl; -#endif - - /* timeout and restart */ - it->second.mState = BITDHT_CONNREQUEST_PAUSED; - it->second.mStateTS = now; - it->second.mPauseTS = now + BITDHT_CR_PAUSE_SHORT_PERIOD; - } - } - else if (it->second.mState == BITDHT_CONNREQUEST_EXTCONNECT) - { - /* connection completed, doing UDP connection */ - if (now - it->second.mStateTS > BITDHT_CONNREQUEST_TIMEOUT_CONNECT) - { - std::cerr << "bdConnectManager::iterateConnectionAttempt() ERROR EXTCONNECT has reached timout -> SHOULD NEVER HAPPEN... KILL this query:"; - std::cerr << std::endl; - std::cerr << it->second; - std::cerr << std::endl; - - /* timeout and restart */ - it->second.mErrCode = BITDHT_CONNECT_ERROR_SOURCE_START | - BITDHT_CONNECT_ERROR_PROTOCOL; - it->second.mState = BITDHT_CONNREQUEST_DONE; - it->second.mStateTS = now; - } - } - else if (it->second.mState == BITDHT_CONNREQUEST_DONE) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::iterateConnectionAttempt() DONE -> erase"; - std::cerr << std::endl; - std::cerr << it->second; - std::cerr << std::endl; -#endif - - erase = true; - - } - - // Cleanup - if (now - it->second.mStateTS > BITDHT_CONNREQUEST_MAX_AGE) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::iterateConnectionAttempt() Should clean Old ConnReq???: "; - std::cerr << std::endl; - std::cerr << it->second; - std::cerr << std::endl; -#endif - } - - if (erase) - { - /* do callback */ - bdId srcId; - bdId proxyId; - bdId destId; - - destId.id = it->second.mTarget; - int param = 0; - callbackConnect(&srcId, &proxyId, &destId, it->second.mMode, - BD_PROXY_CONNECTION_START_POINT, param, - BITDHT_CONNECT_CB_REQUEST, it->second.mErrCode); - - /* cleanup */ - eraseList.push_back(it->first); - } - } - - for(eit = eraseList.begin(); eit != eraseList.end(); eit++) - { - it = mConnectionRequests.find(*eit); - if (it != mConnectionRequests.end()) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::iterateConnectionAttempt() Erasing Old Connection Request: "; - std::cerr << std::endl; - std::cerr << it->second; - std::cerr << std::endl; -#endif - - mConnectionRequests.erase(it); - } - } -} - - - -int bdConnectManager::startConnectionAttempt(bdConnectionRequest *req) -{ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::startConnectionAttempt() ConnReq: "; - std::cerr << std::endl; - std::cerr << *req; - std::cerr << std::endl; -#endif - - if (req->mGoodProxies.size() < 1) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::startConnectionAttempt() No Potential Proxies... delaying attempt"; - std::cerr << std::endl; -#endif - return 0; - } - - bdId proxyId; - bdId srcConnAddr; - bdId destConnAddr; - - int mode = req->mMode; - - /* calculate the delay... accounting for the time since the request */ - time_t now = time(NULL); - int timeElapsed = (now - req->mRequestTS); - int delay = req->mDelay - timeElapsed; - int absDelay = 0; - if (delay > 0) - { - absDelay = delay; - } -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::startConnectionAttempt() TimeSinceReq: " << timeElapsed << " Original Delay: " << req->mDelay; - std::cerr << " AbsDelay: " << absDelay; - std::cerr << std::endl; -#endif - - destConnAddr.id = req->mTarget; - bdsockaddr_clear(&(destConnAddr.addr)); - - srcConnAddr.id = mOwnId; - srcConnAddr.addr = req->mLocalAddr; - - bdProxyId pidset = req->mGoodProxies.front(); - proxyId = pidset.id; - req->mGoodProxies.pop_front(); - - req->mCurrentAttempt = proxyId; - req->mCurrentSrcType = pidset.srcType; - - //req->mPeersTried.push_back(proxyId); - - req->mState = BITDHT_CONNREQUEST_INPROGRESS; - req->mStateTS = time(NULL); - - if (mode == BITDHT_CONNECT_MODE_DIRECT) - { - // ONE BUG I HAVE SEEN. - if (!(req->mTarget == proxyId.id)) - { - std::cerr << "bdConnectManager::startConnectionAttempt() ERROR Trying to use a Proxy for DIRECT"; - std::cerr << std::endl; - - return 0; - } - } - else - { - if (req->mTarget == proxyId.id) - { - std::cerr << "bdConnectManager::startConnectionAttempt() ERROR Trying connect direct for PROXY|RELAY"; - std::cerr << std::endl; - - return 0; - } - } - - - return startConnectionAttempt(&proxyId, &srcConnAddr, &destConnAddr, mode, absDelay); -} - - - -/************************************************************************************************************ -****************************************** Outgoing Triggers ************************************************ -************************************************************************************************************/ - -/************************************************************************************************************ -****************************************** Outgoing Triggers ************************************************ -************************************************************************************************************/ - -/************************************************************************************************************ -*************************************** Connection Requests Callback **************************************** -************************************************************************************************************/ - -/* Lots of Callbacks come through here... The Connection Request gets flagged, and the message - * get passed on up if necessary. - */ - -void bdConnectManager::callbackConnectRequest(bdId *srcId, bdId *proxyId, bdId *destId, - int mode, int point, int param, int cbtype, int errcode) -{ - /* Check if we are the originator of the Connect Request. If so, then we do stuff to the CR. - */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "mode: " << mode; - std::cerr << " point: " << point; - std::cerr << " param: " << param; - std::cerr << " cbtype: " << cbtype; - std::cerr << " errcode: " << errcode; - std::cerr << std::endl; - - std::cerr << "\tsrcId: "; - bdStdPrintId(std::cerr, srcId); - std::cerr << std::endl; - std::cerr << "\tproxyId: "; - bdStdPrintId(std::cerr, proxyId); - std::cerr << std::endl; - std::cerr << "\tdestId: "; - bdStdPrintId(std::cerr, destId); - std::cerr << std::endl; -#endif - - - if (point != BD_PROXY_CONNECTION_START_POINT) - { - /* ONLY ONE CASE THAT GOES HERE -> for sanity testing */ - if ((cbtype == BITDHT_CONNECT_CB_START) && (point == BD_PROXY_CONNECTION_END_POINT)) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() END & START checking ConnectRequest state"; - std::cerr << std::endl; -#endif - - // Reverse lookup (srcId). - std::map::iterator it = mConnectionRequests.find(srcId->id); - if (it != mConnectionRequests.end()) - { - if (it->second.mState == BITDHT_CONNREQUEST_INPROGRESS) - { - /* AT THIS POINT - WE SHOULD SWITCH IT INTO EXTCONNECT MODE????, - * which will timeout - if it fails... - * THIS is effectively the end of the connection attempt anyway. - * if UDP succeeds or fails, will Kill either way. - */ - std::cerr << "bdConnectManager::callbackConnectRequest() ERROR ALT CR also in progress!"; - std::cerr << std::endl; - - } - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() WARNING Switching ALT CR to EXTCONNECT Mode"; - std::cerr << std::endl; -#endif - - time_t now = time(NULL); - it->second.mState = BITDHT_CONNREQUEST_EXTCONNECT; - it->second.mStateTS = now; - - } - else - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() No ALT CR - Good"; - std::cerr << std::endl; -#endif - - } - callbackConnect(srcId, proxyId, destId, mode, point, param, cbtype, errcode); - return; - } - - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "ERROR point != START, should not be receiving this callback, ignoring"; - std::cerr << std::endl; - return; - } - - /* now find our peer in the map */ - std::map::iterator it = mConnectionRequests.find(destId->id); - if (it == mConnectionRequests.end()) - { - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "ERROR no associated Connection Request, ignoring"; - std::cerr << std::endl; - return; - } - bdConnectionRequest *cr = &(it->second); - time_t now = time(NULL); - - /* what types of cbtype can we get? - * BITDHT_CONNECT_CB_AUTH not as START - * BITDHT_CONNECT_CB_PENDING not as START - * BITDHT_CONNECT_CB_START YES important, change state to PAUSED and pass up - * BITDHT_CONNECT_CB_PROXY not as START - * BITDHT_CONNECT_CB_FAILED YES most important, trigger next one - */ - - switch(cbtype) - { - default: // all fallthrough. - case BITDHT_CONNECT_CB_AUTH: - case BITDHT_CONNECT_CB_PENDING: - case BITDHT_CONNECT_CB_PROXY: - { - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "ERROR unexpected CBTYPE: AUTH/PENDING/PROXY/other. ignoring"; - std::cerr << std::endl; - return; - } - - case BITDHT_CONNECT_CB_FAILED: - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "Connection FAILED.... determining if fatal/recycle/next"; - std::cerr << std::endl; -#endif - - // one more big switch statement, to decide: fatal/delay/or next - // default is move to next proxy/peer. - bool fatal = false; - bool recycle = false; - - int errtype = errcode & BITDHT_CONNECT_ERROR_MASK_TYPE; - int errsrc = errcode & BITDHT_CONNECT_ERROR_MASK_SOURCE; - - switch(errtype) - { - default: - // (These could be fatal or recycle cases... but really ERROR, try NEXT. - case BITDHT_CONNECT_ERROR_GENERIC: - case BITDHT_CONNECT_ERROR_PROTOCOL: - case BITDHT_CONNECT_ERROR_TIMEOUT: // SHould never receive. - { - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "ERROR unexpected errcode: " << errcode; - std::cerr << std::endl; - } - break; - - // FATAL ONES. - case BITDHT_CONNECT_ERROR_UNREACHABLE: // END has Unstable ExtAddr. ONLY(PROXYMODE,END) - { - if ((errsrc == BITDHT_CONNECT_ERROR_SOURCE_END) && - (mode == BITDHT_CONNECT_MODE_PROXY)) - { - // fatal. - fatal = true; - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "END says UNREACHABLE. FATAL ;("; - std::cerr << std::endl; -#endif - } - else - { - // error. - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "ERROR, UNREACHABLE, but !END"; - std::cerr << std::endl; - } - } - break; - case BITDHT_CONNECT_ERROR_AUTH_DENIED: // END won't accept conn END|PROXY, RELAY|PROXY - { - if (errsrc == BITDHT_CONNECT_ERROR_SOURCE_END) - { - // fatal. - fatal = true; - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "END says AUTH_DENIED, fatal"; - std::cerr << std::endl; -#endif - } - else if (errsrc == BITDHT_CONNECT_ERROR_SOURCE_MID) - { - // next. (unlikely). -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "WARNING MID says AUTH_DENIED"; - std::cerr << std::endl; -#endif - } - else - { - // error. - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "ERROR strange AUTH_DENIED"; - std::cerr << std::endl; - } - } - break; - case BITDHT_CONNECT_ERROR_UNSUPPORTED: // mode is unsupprted. fatal or next ANY/ANY - { - if (errsrc == BITDHT_CONNECT_ERROR_SOURCE_END) - { - // fatal. - fatal = true; - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "END says UNSUPPORTED, fatal"; - std::cerr << std::endl; -#endif - } - else if (errsrc == BITDHT_CONNECT_ERROR_SOURCE_MID) - { - // next. -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "MID says UNSUPPORTED"; - std::cerr << std::endl; -#endif - - } - else - { - // error. - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "ERROR strange UNSUPPORTED"; - std::cerr << std::endl; - - } - } - break; - - // RECYCLE PROXY - case BITDHT_CONNECT_ERROR_TEMPUNAVAIL: // only END | PROXY, no extAddress - { - if (errsrc == BITDHT_CONNECT_ERROR_SOURCE_END) - { - fatal = true; - //recycle = true; - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "END says TEMPUNAVAIL, fatal (retried at higher level)"; - std::cerr << std::endl; -#endif - } - else - { - // next. - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "ERROR strange TEMPUNAVAIL"; - std::cerr << std::endl; - - } - } - break; - case BITDHT_CONNECT_ERROR_DUPLICATE: // similar attempt. delay/recycle (ANY/ANY) - { - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << " DUPLICATE, fatal"; - std::cerr << std::endl; -#endif - - fatal = true; - //recycle = true; - } - break; - case BITDHT_CONNECT_ERROR_OVERLOADED: // not more space. PROXY in RELAY mode. - { - if ((errsrc == BITDHT_CONNECT_ERROR_SOURCE_MID) && - (mode == BITDHT_CONNECT_MODE_RELAY)) - { - recycle = true; - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "MID says OVERLOADED, recycle"; - std::cerr << std::endl; -#endif - - } - else - { - //ERROR. - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "ERROR strange OVERLOADED"; - std::cerr << std::endl; - } - } - break; - - // NEXT PROXY. - case BITDHT_CONNECT_ERROR_NOADDRESS: //Proxy doesn't know peer MID/(RELAY|PROXY) - { - if (errsrc == BITDHT_CONNECT_ERROR_SOURCE_MID) - { - // could recycle? probably still won't work. -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "MID says NOADDRESS"; - std::cerr << std::endl; -#endif - } - else - { - //ERROR. - std::cerr << "bdConnectManager::callbackConnectRequest() "; - std::cerr << "ERROR strange NOADDRESS"; - std::cerr << std::endl; - } - } - break; - } // end of error code switch. - - // Now act on the decision. - if (fatal) - { - /* kill connection request, do callback */ - /* setup for next one */ - cr->mState = BITDHT_CONNREQUEST_DONE; - } - else - { - if (recycle) - { - /* rotate around */ - cr->mGoodProxies.push_back(bdProxyId(cr->mCurrentAttempt, cr->mCurrentSrcType, errcode)); - cr->mRecycled++; - } - else - { - cr->mPeersTried.push_back(bdProxyId(cr->mCurrentAttempt, cr->mCurrentSrcType, errcode)); - } - - /* setup for next one */ - cr->mState = BITDHT_CONNREQUEST_PAUSED; - cr->mPauseTS = now + BITDHT_CR_PAUSE_SHORT_PERIOD; - } - - cr->mStateTS = now; - cr->mErrCode = errcode; - - /* just pass on the callbackConnect() */ - callbackConnect(srcId, proxyId, destId, mode, point, param, cbtype, errcode); - - return; // CALLBACK FINISHED for FAILURE CODES. - - } - break; - case BITDHT_CONNECT_CB_START: - { - - cr->mState = BITDHT_CONNREQUEST_EXTCONNECT; - cr->mStateTS = now; - - callbackConnect(srcId, proxyId, destId, mode, point, param, cbtype, errcode); - - } - break; - } -} - - - -/************************************************************************************************************ -************************************** END of Connection Requests ******************************************* -************************************************************************************************************/ - -/************************************************************************************************************ -****************************************** Outgoing Triggers ************************************************ -************************************************************************************************************/ - -/*** Called by iterator. - * initiates the connection startup - * - * srcConnAddr must contain Own ID + Connection Port (DHT or TOU depending on Mode). - * - * For a DIRECT Connection: proxyId == destination Id, and mode == DIRECT. - * - * For RELAY | PROXY Connection: - * - * In all cases, destConnAddr doesn't need to contain a valid address. - */ - -int bdConnectManager::startConnectionAttempt(bdId *proxyId, bdId *srcConnAddr, bdId *destConnAddr, int mode, int delay) -{ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::startConnectionAttempt()"; - std::cerr << std::endl; -#endif - - if (!(mConfigAllowedModes & mode)) - { - /* MODE not supported */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::startConnectionAttempt() ERROR Mode Not Supported"; - std::cerr << std::endl; -#endif - return 0; - } - - /* Check for existing Connection */ - bdConnection *conn = findExistingConnectionBySender(proxyId, srcConnAddr, destConnAddr); - if (conn) - { - /* ERROR */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::startConnectAttempt() ERROR EXISTING CONNECTION"; - std::cerr << std::endl; -#endif - return 0; - } - - - /* Switch the order of peers around to test for "opposite connections" */ - if (NULL != findSimilarConnection(&(destConnAddr->id), &(srcConnAddr->id))) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::startConnectAttempt() WARNING Found Similar Connection. returning 0"; - std::cerr << std::endl; -#endif - - return 0; - } - - - { - // DO A CALLBACK to TELL higher levels, we are starting a connection attempt. - int point = BD_PROXY_CONNECTION_START_POINT; - int cbtype = BITDHT_CONNECT_CB_REQUEST; - int errcode = 0; - int param = 0; - callbackConnect(srcConnAddr, proxyId, destConnAddr, mode, point, param, cbtype, errcode); - } - - /* INSTALL a NEW CONNECTION */ - // not offically playing by the rules, but it should work. - conn = newConnectionBySender(proxyId, srcConnAddr, destConnAddr); - - if (mode == BITDHT_CONNECT_MODE_DIRECT) - { - /* proxy is the real peer address, destConnAddr has an invalid address */ - conn->ConnectionSetupDirect(proxyId, srcConnAddr); - } - else - { - conn->ConnectionSetup(proxyId, srcConnAddr, destConnAddr, mode, delay); - } - - - int msgtype = BITDHT_MSG_TYPE_CONNECT_REQUEST; - int status = BITDHT_CONNECT_ANSWER_OKAY; - mPub->send_connect_msg(&(conn->mProxyId), msgtype, - &(conn->mSrcConnAddr), &(conn->mDestConnAddr), conn->mMode, conn->mMaxDelay, status); - - return 1; -} - -/* This will be called in response to a callback. - * the callback could be with regard to: - * a Direct EndPoint. - * a Proxy Proxy, or an Proxy EndPoint. - * a Relay Proxy, or an Relay EndPoint. - * - * If we are going to store the minimal amount in the bdNode about connections, - * then the parameters must contain all the information: - * - * case 1: - * - */ - -void bdConnectManager::AuthConnectionOk(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc, int bandwidth, int delay) -{ - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionOk()"; - std::cerr << std::endl; -#endif - - /* Check for existing Connection */ - bdConnection *conn = findExistingConnection(&(srcId->id), &(proxyId->id), &(destId->id)); - if (!conn) - { - /* ERROR */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionOk() ERROR NO EXISTING CONNECTION"; - std::cerr << std::endl; -#endif - return; - } - - /* we need to continue the connection */ - if (mode == BITDHT_CONNECT_MODE_DIRECT) - { - if (conn->mState == BITDHT_CONNECTION_WAITING_AUTH) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionOk() Direct Connection, in WAITING_AUTH state... Authorising Direct Connect"; - std::cerr << std::endl; -#endif - /* This pushes it into the START/ACK cycle, - * which handles messages elsewhere - */ - conn->AuthoriseDirectConnection(srcId, proxyId, destId, mode, loc); - } - else - { - /* ERROR */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionOk() ERROR Direct Connection, !WAITING_AUTH state... Ignoring"; - std::cerr << std::endl; -#endif - - } - return; - } - - if (loc == BD_PROXY_CONNECTION_END_POINT) - { - if (conn->mState == BITDHT_CONNECTION_WAITING_AUTH) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionOk() Proxy End Connection, in WAITING_AUTH state... Authorising"; - std::cerr << std::endl; -#endif - /*** XXX MUST RECEIVE THE ADDRESS FROM DEST for connection */ - conn->AuthoriseEndConnection(srcId, proxyId, destId, mode, loc, delay); - - /* we respond to the proxy which will finalise connection */ - int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; - int status = BITDHT_CONNECT_ANSWER_OKAY; - mPub->send_connect_msg(&(conn->mProxyId), msgtype, - &(conn->mSrcConnAddr), &(conn->mDestConnAddr), conn->mMode, conn->mMaxDelay, status); - - return; - } - else - { - - /* ERROR */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionOk() ERROR Proxy End Connection, !WAITING_AUTH state... Ignoring"; - std::cerr << std::endl; -#endif - } - } - - if (conn->mState == BITDHT_CONNECTION_WAITING_AUTH) - { - /* otherwise we are the proxy (for either), pass on the request */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionOk() Proxy Mid Connection, in WAITING_AUTH state... Authorising"; - std::cerr << std::endl; -#endif - - /* SEARCH for IP:Port of destination is done before AUTH */ - conn->AuthoriseProxyConnection(srcId, proxyId, destId, mode, loc, bandwidth); - - int msgtype = BITDHT_MSG_TYPE_CONNECT_REQUEST; - int status = BITDHT_CONNECT_ANSWER_OKAY; - int param = 0; - mPub->send_connect_msg(&(conn->mDestId), msgtype, - &(conn->mSrcConnAddr), &(conn->mDestConnAddr), conn->mMode, param, status); - } - else - { - /* ERROR */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionOk() ERROR Proxy Mid Connection, !WAITING_AUTH state... Ignoring"; - std::cerr << std::endl; -#endif - } - - return; -} - - - - -void bdConnectManager::AuthConnectionNo(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc, int errCode) -{ - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionNo()"; - std::cerr << std::endl; -#endif - - /* Check for existing Connection */ - bdConnection *conn = findExistingConnection(&(srcId->id), &(proxyId->id), &(destId->id)); - if (!conn) - { - /* ERROR */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionNo() ERROR NO EXISTING CONNECTION"; - std::cerr << std::endl; -#endif - return; - } - - /* we need indicate failure of the connection */ - int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; - uint32_t status = createConnectionErrorCode(errCode, BITDHT_CONNECT_ERROR_AUTH_DENIED, conn->mPoint); - - if (mode == BITDHT_CONNECT_MODE_DIRECT) - { - /* we respond to the proxy which will finalise connection */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionNo() Direct End Connection Cleaning up"; - std::cerr << std::endl; -#endif - mPub->send_connect_msg(&(conn->mSrcId), msgtype, - &(conn->mSrcConnAddr), &(conn->mDestConnAddr), mode, 0, status); - - cleanConnection(&(srcId->id), &(proxyId->id), &(destId->id)); - return; - } - - if (loc == BD_PROXY_CONNECTION_END_POINT) - { - /* we respond to the proxy which will finalise connection */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionNo() Proxy End Connection Cleaning up"; - std::cerr << std::endl; -#endif - mPub->send_connect_msg(&(conn->mProxyId), msgtype, - &(conn->mSrcConnAddr), &(conn->mDestConnAddr), mode, 0, status); - - cleanConnection(&(srcId->id), &(proxyId->id), &(destId->id)); - - return; - } - - /* otherwise we are the proxy (for either), reply FAIL */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::AuthConnectionNo() Proxy Mid Connection Cleaning up"; - std::cerr << std::endl; -#endif - mPub->send_connect_msg(&(conn->mSrcId), msgtype, - &(conn->mSrcConnAddr), &(conn->mDestConnAddr), mode, 0, status); - - cleanConnection(&(srcId->id), &(proxyId->id), &(destId->id)); - - return; -} - - - - - -void bdConnectManager::iterateConnections() -{ - std::map::iterator it; - std::list eraseList; - time_t now = time(NULL); - - for(it = mConnections.begin(); it != mConnections.end(); it++) - { - if (now - it->second.mLastEvent > BD_CONNECTION_MAX_TIMEOUT) - { - /* cleanup event */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::iterateConnections() Connection Timed Out: " << (it->first); - std::cerr << std::endl; -#endif - eraseList.push_back(it->first); - continue; - } - - /* Can I add a Quick Kill for connections that just haven't worked? TODO */ - - if ((it->second.mState == BITDHT_CONNECTION_WAITING_ACK) && - (now - it->second.mLastStart > BD_CONNECTION_START_RETRY_PERIOD)) - { - if (it->second.mRetryCount > BD_CONNECTION_START_MAX_RETRY) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::iterateConnections() Start/ACK cycle, Too many iterations: " << it->first; - std::cerr << std::endl; -#endif - /* connection failed! cleanup */ - if ((it->second.mMode != BITDHT_CONNECT_MODE_PROXY) || (!mConfigAutoProxy)) - { - uint32_t errCode = createConnectionErrorCode(0, - BITDHT_CONNECT_ERROR_TIMEOUT,it->second.mPoint); - int param = 0; - callbackConnect(&(it->second.mSrcId),&(it->second.mProxyId), - &(it->second.mDestId), it->second.mMode, it->second.mPoint, param, - BITDHT_CONNECT_CB_FAILED, errCode); - } - - /* add to erase list */ - eraseList.push_back(it->first); - } - else - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::iterateConnections() Start/ACK cycle, Retransmitting START: " << it->first; - std::cerr << std::endl; -#endif - it->second.mLastStart = now; - it->second.mRetryCount++; - - int bandwidth = it->second.mBandwidth; - int delay = it->second.mMaxDelay; - time_t elapsedTime = (time(NULL) - it->second.mConnectionStartTS); - int remainingDelay = delay - elapsedTime; - if (remainingDelay < 0) - { - remainingDelay = 0; - } - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::iterateConnections() Start/ACK cycle: remaining Delay: " << remainingDelay; - std::cerr << std::endl; - std::cerr << "bdConnectManager::iterateConnections() Start/ACK cycle: Bandwidth: " << bandwidth; - std::cerr << std::endl; -#endif - - // Must calculate the correct delay's here!!!! - int delayOrBandwidth = remainingDelay; - if (it->second.mMode == BITDHT_CONNECT_MODE_RELAY) - { - delayOrBandwidth = bandwidth; - } - - if (!it->second.mSrcAck) - { - int msgtype = BITDHT_MSG_TYPE_CONNECT_START; - mPub->send_connect_msg(&(it->second.mSrcId), msgtype, - &(it->second.mSrcConnAddr), &(it->second.mDestConnAddr), - it->second.mMode, delayOrBandwidth, BITDHT_CONNECT_ANSWER_OKAY); - } - if (!it->second.mDestAck) - { - int msgtype = BITDHT_MSG_TYPE_CONNECT_START; - mPub->send_connect_msg(&(it->second.mDestId), msgtype, - &(it->second.mSrcConnAddr), &(it->second.mDestConnAddr), - it->second.mMode, delayOrBandwidth, BITDHT_CONNECT_ANSWER_OKAY); - } - } - } - } - - /* clean up */ - while(eraseList.size() > 0) - { - bdProxyTuple tuple = eraseList.front(); - eraseList.pop_front(); - - std::map::iterator eit = mConnections.find(tuple); - mConnections.erase(eit); - } -} - - - - -/************************************************************************************************************ -****************************************** Callback Functions ******************************************** -************************************************************************************************************/ - - -void bdConnectManager::callbackConnect(bdId *srcId, bdId *proxyId, bdId *destId, - int mode, int point, int param, int cbtype, int errcode) -{ - /* This is overloaded at a higher level */ - mPub->callbackConnect(srcId, proxyId, destId, mode, point, param, cbtype, errcode); -} - - -/************************************************************************************************************ -************************************** ProxyTuple + Connection State **************************************** -************************************************************************************************************/ - -int operator<(const bdProxyTuple &a, const bdProxyTuple &b) -{ - if (a.srcId < b.srcId) - { - return 1; - } - - if (a.srcId == b.srcId) - { - if (a.proxyId < b.proxyId) - { - return 1; - } - else if (a.proxyId == b.proxyId) - { - if (a.destId < b.destId) - { - return 1; - } - } - } - return 0; -} - -int operator==(const bdProxyTuple &a, const bdProxyTuple &b) -{ - if ((a.srcId == b.srcId) && (a.proxyId == b.proxyId) && (a.destId == b.destId)) - { - return 1; - } - return 0; -} - -std::ostream &operator<<(std::ostream &out, const bdProxyTuple &t) -{ - out << "[---"; - bdStdPrintNodeId(out, &(t.srcId)); - out << "---"; - bdStdPrintNodeId(out, &(t.proxyId)); - out << "---"; - bdStdPrintNodeId(out, &(t.destId)); - out << "---]"; - - return out; -} - -bdConnection::bdConnection() -{ - /* DUMMY INITIALISATION FOR ALL DATA - DON"T THINK IT MATTERS - * But keeps Valgrind happy - */ - - /* Connection State, and TimeStamp of Update */ - mState = 0; - mLastEvent = 0; - // - ///* Addresses of Start/Proxy/End Nodes */ - //bdId mSrcId; - //bdId mDestId; - //bdId mProxyId; - // - ///* Where we are in the connection, - //* and what connection mode. - //*/ - mPoint = 0; - mMode = 0; - // - ///* must have ip:ports of connection ends (if proxied) */ - //bdId mSrcConnAddr; - //bdId mDestConnAddr; - // - mBandwidth = 0; - mMaxDelay = 0; - mConnectionStartTS = 0; - - // - ///* START/ACK Finishing ****/ - mLastStart = 0; /* timer for retries */ - mRetryCount = 0; /* retry counter */ - // - mSrcAck = false; - mDestAck = false; - // - //// Completion TS. - mCompletedTS = 0; -} - - /* heavy check, used to check for alternative connections, coming from other direction - * Caller must switch src/dest to use it properly (otherwise it'll find your connection!) - */ -bdConnection *bdConnectManager::findSimilarConnection(bdNodeId *srcId, bdNodeId *destId) -{ - std::map::iterator it; - for(it = mConnections.begin(); it != mConnections.end(); it++) - { - if ((it->first.srcId == *srcId) && (it->first.destId == *destId)) - { - /* found similar connection */ - return &(it->second); - } - } - return NULL; -} - -bdConnection *bdConnectManager::findExistingConnection(bdNodeId *srcId, bdNodeId *proxyId, bdNodeId *destId) -{ - bdProxyTuple tuple(srcId, proxyId, destId); - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::findExistingConnection() Looking For: " << tuple << std::endl; -#endif - - std::map::iterator it = mConnections.find(tuple); - if (it == mConnections.end()) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::findExistingConnection() Failed to Find: " << tuple << std::endl; -#endif - return NULL; - } - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::findExistingConnection() Found: " << tuple << std::endl; -#endif - return &(it->second); -} - -bdConnection *bdConnectManager::newConnection(bdNodeId *srcId, bdNodeId *proxyId, bdNodeId *destId) -{ - bdProxyTuple tuple(srcId, proxyId, destId); - bdConnection conn; - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::newConnection() Installing: " << tuple << std::endl; -#endif - - mConnections[tuple] = conn; - std::map::iterator it = mConnections.find(tuple); - if (it == mConnections.end()) - { - std::cerr << "bdConnectManager::newConnection() ERROR Installing: " << tuple << std::endl; - return NULL; - } - return &(it->second); -} - -int bdConnectManager::cleanConnection(bdNodeId *srcId, bdNodeId *proxyId, bdNodeId *destId) -{ - bdProxyTuple tuple(srcId, proxyId, destId); - bdConnection conn; - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::cleanConnection() Removing: " << tuple << std::endl; -#endif - - std::map::iterator it = mConnections.find(tuple); - if (it == mConnections.end()) - { - std::cerr << "bdConnectManager::cleanConnection() ERROR Removing: " << tuple << std::endl; - return 0; - } - mConnections.erase(it); - - return 1; -} - - -int bdConnectManager::determinePosition(bdNodeId */*sender*/, bdNodeId *src, bdNodeId *dest) -{ - int pos = BD_PROXY_CONNECTION_UNKNOWN_POINT; - if (mOwnId == *src) - { - pos = BD_PROXY_CONNECTION_START_POINT; - } - else if (mOwnId == *dest) - { - pos = BD_PROXY_CONNECTION_END_POINT; - } - else - { - pos = BD_PROXY_CONNECTION_MID_POINT; - } - return pos; -} - -int bdConnectManager::determineProxyId(bdNodeId *sender, bdNodeId *src, bdNodeId *dest, bdNodeId *proxyId) -{ - int pos = determinePosition(sender, src, dest); - switch(pos) - { - case BD_PROXY_CONNECTION_START_POINT: - case BD_PROXY_CONNECTION_END_POINT: - *proxyId = *sender; - return 1; - break; - default: - case BD_PROXY_CONNECTION_MID_POINT: - *proxyId = mOwnId; - return 1; - break; - } - return 0; -} - - - -bdConnection *bdConnectManager::findExistingConnectionBySender(bdId *sender, bdId *src, bdId *dest) -{ - bdNodeId proxyId; - bdNodeId *senderId = &(sender->id); - bdNodeId *srcId = &(src->id); - bdNodeId *destId = &(dest->id); - determineProxyId(senderId, srcId, destId, &proxyId); - - return findExistingConnection(srcId, &proxyId, destId); -} - -bdConnection *bdConnectManager::newConnectionBySender(bdId *sender, bdId *src, bdId *dest) -{ - bdNodeId proxyId; - bdNodeId *senderId = &(sender->id); - bdNodeId *srcId = &(src->id); - bdNodeId *destId = &(dest->id); - determineProxyId(senderId, srcId, destId, &proxyId); - - return newConnection(srcId, &proxyId, destId); -} - - -int bdConnectManager::cleanConnectionBySender(bdId *sender, bdId *src, bdId *dest) -{ - bdNodeId proxyId; - bdNodeId *senderId = &(sender->id); - bdNodeId *srcId = &(src->id); - bdNodeId *destId = &(dest->id); - determineProxyId(senderId, srcId, destId, &proxyId); - - return cleanConnection(srcId, &proxyId, destId); -} - - -/************************************************************************************************************ -****************************************** Received Connect Msgs ******************************************** -************************************************************************************************************/ - - -/* This function is triggered by a CONNECT_REQUEST message. - * it will occur on both the Proxy/Dest in the case of a Proxy (PROXY | RELAY) and on the Dest (DIRECT) nodes. - * - * In all cases, we store the request and ask for authentication. - * - */ - - - -int bdConnectManager::recvedConnectionRequest(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int delay) -{ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionRequest()"; - std::cerr << std::endl; -#endif - - if (!(mConfigAllowedModes & mode)) - { - /* MODE not supported */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionRequest() WARNING Mode Not Supported"; - std::cerr << std::endl; -#endif - /* reply existing connection */ - int pos = determinePosition(&(id->id), &(srcConnAddr->id), &(destConnAddr->id)); - uint32_t status = createConnectionErrorCode(0, BITDHT_CONNECT_ERROR_UNSUPPORTED, pos); - - int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; - mPub->send_connect_msg(id, msgtype, srcConnAddr, destConnAddr, mode, 0, status); - - return 0; - } - - /* Check for existing Connection */ - bdConnection *conn = findExistingConnectionBySender(id, srcConnAddr, destConnAddr); - if (conn) - { - /* Likely ERROR: Warning */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionRequest() WARNING Existing Connection: "; - std::cerr << std::endl; - std::cerr << std::endl; -#endif - /* reply existing connection */ - uint32_t status = createConnectionErrorCode(0, BITDHT_CONNECT_ERROR_DUPLICATE, conn->mPoint); - - int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; - int param = 0; - mPub->send_connect_msg(id, msgtype, srcConnAddr, destConnAddr, mode, param, status); - - return 0; - } - - - /* Switch the order of peers around to test for "opposite connections" */ - if (NULL != findSimilarConnection(&(destConnAddr->id), &(srcConnAddr->id))) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionRequest() WARNING Found Similar Connection. Replying NO"; - std::cerr << std::endl; -#endif - - /* reply existing connection */ - int pos = determinePosition(&(id->id), &(srcConnAddr->id), &(destConnAddr->id)); - uint32_t status = createConnectionErrorCode(0, BITDHT_CONNECT_ERROR_DUPLICATE, pos); - - int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; - int param = 0; - mPub->send_connect_msg(id, msgtype, srcConnAddr, destConnAddr, mode, param, status); - return 0; - } - - /* INSTALL a NEW CONNECTION */ - conn = bdConnectManager::newConnectionBySender(id, srcConnAddr, destConnAddr); - - int point = 0; - if (mode == BITDHT_CONNECT_MODE_DIRECT) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionRequest() Installing DIRECT CONNECTION"; - std::cerr << std::endl; -#endif - - /* we are actually the end node, store stuff, get auth and on with it! */ - point = BD_PROXY_CONNECTION_END_POINT; - - conn->ConnectionRequestDirect(id, srcConnAddr, destConnAddr); - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionRequest() Connection State:"; - std::cerr << std::endl; - std::cerr << *conn; - std::cerr << std::endl; -#endif - int param = 0; - callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), - conn->mMode, conn->mPoint, param, BITDHT_CONNECT_CB_AUTH, - BITDHT_CONNECT_ERROR_NONE); - } - else - { - /* check if we are proxy, or end point */ - bool areProxy = (srcConnAddr->id == id->id); - if (areProxy) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionRequest() We are MID Point for Proxy / Relay Connection."; - std::cerr << std::endl; -#endif - - point = BD_PROXY_CONNECTION_MID_POINT; - - /* SEARCH for IP:Port of destination before AUTH */ - int numNodes = 10; - std::list matchingIds; - - std::cerr << "bdConnectManager::recvedConnectionRequest() WARNING searching for \"VERSION\" flag... TO FIX LATER"; - std::cerr << std::endl; - - uint32_t with_flag = BITDHT_PEER_STATUS_DHT_ENGINE_VERSION; - //BITDHT_PEER_STATUS_DHT_APPL | BITDHT_PEER_STATUS_DHT_APPL_VERSION); - - bool proxyOk = false; - bdId destId; - - if (mNodeSpace->find_node(&(destConnAddr->id), numNodes, matchingIds, with_flag)) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionRequest() Found Suitable Destination Addr"; - std::cerr << std::endl; -#endif - - if (matchingIds.size() > 1) - { - /* WARNING multiple matches */ - std::cerr << "bdConnectManager::recvedConnectionRequest() WARNING Found Multiple Matching Destination Addr"; - std::cerr << std::endl; - } - - proxyOk = true; - destId = matchingIds.front(); - } - - if (proxyOk) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionRequest() Proxy Addr Ok: "; - bdStdPrintId(std::cerr, destConnAddr); - std::cerr << "asking for AUTH to continue"; - std::cerr << std::endl; -#endif - - conn->ConnectionRequestProxy(id, srcConnAddr, &mOwnId, &destId, mode, delay); - - /* ALLOW AUTO AUTH for MID Proxy Connections. */ - if ((mConfigAutoProxy) && (mode == BITDHT_CONNECT_MODE_PROXY)) - { - AuthConnectionOk(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), - conn->mMode, conn->mPoint, 0, 0); - } - else - { - - int param = 0; - callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), - conn->mMode, conn->mPoint, param, BITDHT_CONNECT_CB_AUTH, - BITDHT_CONNECT_ERROR_NONE); - } - } - else - { - /* clean up connection... its not going to work */ -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionRequest() WARNING No Proxy Addr, Shutting Connect Attempt"; - std::cerr << std::endl; -#endif - - - /* send FAIL message to SRC */ - int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; - uint32_t status = createConnectionErrorCode(0, BITDHT_CONNECT_ERROR_NOADDRESS, point); - int param = 0; - mPub->send_connect_msg(id, msgtype, srcConnAddr, destConnAddr, mode, param, status); - - - /* WILL NEED CALLBACK FOR FAILED PROXY ATTEMPT - TO SUPPORT RELAYS PROPERLY - * NODE needs to know PEERS to potentially WHITELIST! - */ - if (mRelayMode == BITDHT_RELAYS_SERVER) - { -#ifdef DEBUG_PROXY_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionRequest() In RelayServer Mode, doing FAIL callbackConnect()"; - std::cerr << std::endl; -#endif - - bdId proxyId; - proxyId.id = mOwnId; - callbackConnect(srcConnAddr, &proxyId, destConnAddr, mode, point, param, BITDHT_CONNECT_CB_AUTH, - BITDHT_CONNECT_ERROR_NOADDRESS); - } - - /* remove connection */ - bdConnectManager::cleanConnectionBySender(id, srcConnAddr, destConnAddr); - } - } - else - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionRequest() END Proxy/Relay Connection, asking for AUTH to continue"; - std::cerr << std::endl; -#endif - - point = BD_PROXY_CONNECTION_END_POINT; - - conn->ConnectionRequestEnd(id, srcConnAddr, destConnAddr, mode); - - int param = 0; - callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), - conn->mMode, conn->mPoint, param, BITDHT_CONNECT_CB_AUTH, - BITDHT_CONNECT_ERROR_NONE); - } - } - return 1; -} - - -/* This function is triggered by a CONNECT_REPLY message. - * it will occur on either the Proxy or Source. And indicates YES / NO to the connection, - * as well as supplying address info to the proxy. - * - */ - -int bdConnectManager::recvedConnectionReply(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int delay, int status) -{ - /* retrieve existing connection data */ - bdConnection *conn = findExistingConnectionBySender(id, srcConnAddr, destConnAddr); - if (!conn) - { - /* ERROR */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionReply() ERROR NO EXISTING CONNECTION"; - std::cerr << std::endl; -#endif - return 0; - } - - switch(conn->mPoint) - { - case BD_PROXY_CONNECTION_START_POINT: - case BD_PROXY_CONNECTION_END_POINT: /* NEVER EXPECT THIS */ - case BD_PROXY_CONNECTION_UNKNOWN_POINT: /* NEVER EXPECT THIS */ - default: /* NEVER EXPECT THIS */ - { - - - /* Only situation we expect this, is if the connection is not allowed. - * DEST has sent back an ERROR Message - */ - uint32_t errCode = BITDHT_CONNECT_ERROR_GENERIC; - if ((status != BITDHT_CONNECT_ANSWER_OKAY) && (conn->mPoint == BD_PROXY_CONNECTION_START_POINT)) - { - /* connection is killed */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionReply() WARNING Connection Rejected. Error: "; - std::cerr << decodeConnectionError(status); - std::cerr << ", Killing It: "; - std::cerr << std::endl; - std::cerr << *conn; - std::cerr << std::endl; -#endif - errCode = status; // Pass on the Error Message. - - } - else - { - /* ERROR in protocol */ - std::cerr << "bdConnectManager::recvedConnectionReply() ERROR Unexpected Message, Killing It: "; - std::cerr << std::endl; - std::cerr << *conn; - std::cerr << std::endl; - errCode = createConnectionErrorCode(0, BITDHT_CONNECT_ERROR_PROTOCOL, conn->mPoint ); - } - - /* do Callback for Failed Connection */ - if (conn->mPoint == BD_PROXY_CONNECTION_START_POINT) - { - /* As we started the connection, callback internally first! */ - int param = 0; - callbackConnectRequest(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), - conn->mMode, conn->mPoint, param, BITDHT_CONNECT_CB_FAILED, errCode); - } - else - { - int param = 0; - callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), - conn->mMode, conn->mPoint, param, BITDHT_CONNECT_CB_FAILED, errCode); - } - - /* Kill Connection always */ - cleanConnectionBySender(id, srcConnAddr, destConnAddr); - - return 0; - } - break; - - case BD_PROXY_CONNECTION_MID_POINT: - { - /* We are proxy. and OK / NOK for connection proceed. - */ - - if ((status == BITDHT_CONNECT_ANSWER_OKAY) && (conn->mState == BITDHT_CONNECTION_WAITING_REPLY)) - { - /* OK, continue connection! */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionReply() @MIDPOINT. Reply + State OK, continuing connection"; - std::cerr << std::endl; -#endif - - /* Upgrade Connection to Finishing Mode */ - conn->upgradeProxyConnectionToFinish(id, srcConnAddr, destConnAddr, mode, delay, status); - - /* do Callback for Pending Connection */ - /* DONT CALLBACK in AutoProxy Mode: (PROXY & mConfigAutoProxy) */ - if ((conn->mMode != BITDHT_CONNECT_MODE_PROXY) || (!mConfigAutoProxy)) - { - int param = 0; - callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), - conn->mMode, conn->mPoint, param, BITDHT_CONNECT_CB_PENDING, - BITDHT_CONNECT_ERROR_NONE); - } - - return 1; - } - else - { - - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionReply() WARNING @MIDPOINT recved Error: "; - std::cerr << decodeConnectionError(status); - std::cerr << " Killing It: "; - std::cerr << std::endl; - std::cerr << *conn; - std::cerr << std::endl; -#endif - - uint32_t errCode = status; - if (errCode == BITDHT_CONNECT_ERROR_NONE) - { - errCode = createConnectionErrorCode(0, - BITDHT_CONNECT_ERROR_PROTOCOL, conn->mPoint ); - } - - /* do Callback for Failed Connection */ - /* DONT CALLBACK in AutoProxy Mode: (PROXY & mConfigAutoProxy) */ - if ((conn->mMode != BITDHT_CONNECT_MODE_PROXY) || (!mConfigAutoProxy)) - { - int param = 0; - callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), - conn->mMode, conn->mPoint, param, BITDHT_CONNECT_CB_FAILED, errCode); - } - - - /* send on message to SRC */ - int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; - int param = 0; - mPub->send_connect_msg(&(conn->mSrcId), msgtype, &(conn->mSrcConnAddr), &(conn->mDestConnAddr), mode, param, errCode); - - /* connection is killed */ - cleanConnectionBySender(id, srcConnAddr, destConnAddr); - } - return 0; - } - break; - } - return 0; -} - - -/* This function is triggered by a CONNECT_START message. - * it will occur on both the Src/Dest in the case of a Proxy (PROXY | RELAY) and on the Src (DIRECT) nodes. - * - * parameters are checked against pending connections. - * Acks are set, and connections completed if possible (including callback!). - */ - -int bdConnectManager::recvedConnectionStart(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int delayOrBandwidth) -{ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionStart()"; - std::cerr << std::endl; -#endif - - /* retrieve existing connection data */ - bdConnection *conn = findExistingConnectionBySender(id, srcConnAddr, destConnAddr); - if (!conn) - { - /* ERROR */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionStart() ERROR NO EXISTING CONNECTION"; - std::cerr << std::endl; -#endif - return 0; - } - - - if (conn->mPoint == BD_PROXY_CONNECTION_MID_POINT) - { - std::cerr << "bdConnectManager::recvedConnectionStart() ERROR We Are Connection MID Point"; - std::cerr << std::endl; - /* ERROR */ - } - - /* check state */ - if ((conn->mState != BITDHT_CONNECTION_WAITING_START) && (conn->mState != BITDHT_CONNECTION_COMPLETED)) - { - /* ERROR */ - std::cerr << "bdConnectManager::recvedConnectionStart() ERROR State != WAITING_START && != COMPLETED"; - std::cerr << std::endl; - - return 0; - } - - /* ALL Okay, Send ACK */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionStart() Passed basic tests, Okay to send ACK"; - std::cerr << std::endl; -#endif - - int msgtype = BITDHT_MSG_TYPE_CONNECT_ACK; - int status = BITDHT_CONNECT_ANSWER_OKAY; - mPub->send_connect_msg(id, msgtype, &(conn->mSrcId), &(conn->mDestId), mode, 0, status); - - /* do complete Callback */ - - /* flag as completed */ - if (conn->mState != BITDHT_CONNECTION_COMPLETED) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionStart() Switching State to COMPLETED, doing callback"; - std::cerr << std::endl; -#endif - - int param = delayOrBandwidth; - int bandwidth = 0; - int delay = 0; - if (conn->mMode == BITDHT_CONNECT_MODE_RELAY) - { - bandwidth = param; - } - else - { - delay = param; - } - - conn->CompleteConnection(id, srcConnAddr, destConnAddr, bandwidth, delay); - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionStart() Connection State: "; - std::cerr << *conn; - std::cerr << std::endl; -#endif - - - if (conn->mPoint == BD_PROXY_CONNECTION_START_POINT) - { - /* internal callback first */ - callbackConnectRequest(&(conn->mSrcConnAddr),&(conn->mProxyId),&(conn->mDestConnAddr), - conn->mMode, conn->mPoint, param, BITDHT_CONNECT_CB_START, - BITDHT_CONNECT_ERROR_NONE); - - } - else - { - /* internal callback first */ - callbackConnectRequest(&(conn->mSrcConnAddr),&(conn->mProxyId),&(conn->mDestConnAddr), - conn->mMode, conn->mPoint, param, BITDHT_CONNECT_CB_START, - BITDHT_CONNECT_ERROR_NONE); - } - - } - else - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionStart() Just sent duplicate ACK"; - std::cerr << std::endl; -#endif - } - /* don't delete, if ACK is lost, we want to be able to re-respond */ - - return 1; -} - - -/* This function is triggered by a CONNECT_ACK message. - * it will occur on both the Proxy (PROXY | RELAY) and on the Dest (DIRECT) nodes. - * - * parameters are checked against pending connections. - * Acks are set, and connections completed if possible (including callback!). - */ - -int bdConnectManager::recvedConnectionAck(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int /*mode*/) -{ - /* retrieve existing connection data */ - bdConnection *conn = findExistingConnectionBySender(id, srcConnAddr, destConnAddr); - if (!conn) - { - /* ERROR */ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionAck() ERROR NO EXISTING CONNECTION"; - std::cerr << std::endl; -#endif - return 0; - } - - if (conn->mPoint == BD_PROXY_CONNECTION_START_POINT) - { - /* ERROR */ - std::cerr << "bdConnectManager::recvedConnectionAck() ERROR ACK received at START POINT"; - std::cerr << std::endl; - - return 0; - } - - /* check state */ - if (conn->mState != BITDHT_CONNECTION_WAITING_ACK) - { - /* ERROR */ - std::cerr << "bdConnectManager::recvedConnectionAck() ERROR conn->mState != WAITING_ACK, actual State: " << conn->mState; - std::cerr << std::endl; - - return 0; - } - - if (id->id == srcConnAddr->id) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionAck() from Src, marking So"; - std::cerr << std::endl; -#endif - - /* recved Ack from source */ - conn->mSrcAck = true; - } - else if (id->id == destConnAddr->id) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionAck() from Dest, marking So"; - std::cerr << std::endl; -#endif - /* recved Ack from dest */ - conn->mDestAck = true; - } - - if (conn->mSrcAck && conn->mDestAck) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::recvedConnectionAck() ACKs from Both Src & Dest, Connection Complete: callback & cleanup"; - std::cerr << std::endl; -#endif - - /* connection complete! cleanup */ - if (conn->mMode == BITDHT_CONNECT_MODE_DIRECT) - { -// int mode = conn->mMode | BITDHT_CONNECT_ANSWER_OKAY; - /* callback to connect to Src address! */ - // Slightly different callback, use ConnAddr for start message! - // Also callback to ConnectionRequest first. - // ACTUALLY we are END, so shouldn't (AT This Point do this). - // MUST callback via ConnectRequest - to prevent duplicate REQUESTS. - int param = 0; - callbackConnectRequest(&(conn->mSrcConnAddr),&(conn->mProxyId),&(conn->mDestId), - conn->mMode, conn->mPoint, param, BITDHT_CONNECT_CB_START, - BITDHT_CONNECT_ERROR_NONE); - - } - else - { - /* DONT CALLBACK in AutoProxy Mode: (PROXY & mConfigAutoProxy) */ - if ((conn->mMode != BITDHT_CONNECT_MODE_PROXY) || (!mConfigAutoProxy)) - { - int param = 0; - callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), - conn->mMode, conn->mPoint, param, BITDHT_CONNECT_CB_PROXY, - BITDHT_CONNECT_ERROR_NONE); - } - - - } - - /* Finished Connection! */ - cleanConnectionBySender(id, srcConnAddr, destConnAddr); - } - return 1; -} - - - -/************************************************************************************************************ -********************************* Connection / ConnectionRequest Functions ********************************** -************************************************************************************************************/ - -// Initialise a new Connection (request by User) - -// Any Connection initialised at Source (START_POINT), prior to Auth. -int bdConnection::ConnectionSetup(bdId *proxyId, bdId *srcConnAddr, bdId *destId, int mode, int delay) -{ - mState = BITDHT_CONNECTION_WAITING_START; /* or REPLY, no AUTH required */ - mLastEvent = time(NULL); - mSrcId = *srcConnAddr; /* self, IP unknown */ - mDestId = *destId; /* dest, IP unknown */ - mProxyId = *proxyId; /* full proxy/dest address */ - - mPoint = BD_PROXY_CONNECTION_START_POINT; - mMode = mode; - - mSrcConnAddr = *srcConnAddr; /* self, full ID/IP */ - mDestConnAddr = *destId; /* IP unknown */ - - mBandwidth = 0; - mMaxDelay = delay; - mConnectionStartTS = time(NULL); - -#ifdef DEBUG_CONNECTION_DELAY - std::cerr << "bdConnection::ConnectionSetup(): delay: " << mMaxDelay; - std::cerr << std::endl; -#endif - - /* clear IP Addresses to enforce this */ - bdsockaddr_clear(&(mSrcId.addr)); - bdsockaddr_clear(&(mDestId.addr)); - bdsockaddr_clear(&(mDestConnAddr.addr)); - - /* don't bother with START/ACK parameters */ - - return 1; -} - -int bdConnection::ConnectionSetupDirect(bdId *destId, bdId *srcConnAddr) -{ - mState = BITDHT_CONNECTION_WAITING_START; /* or REPLY, no AUTH required */ - mLastEvent = time(NULL); - mSrcId = *srcConnAddr; /* self, IP unknown */ - mDestId = *destId; /* full proxy/dest address */ - mProxyId = *destId; /* full proxy/dest address */ - - mPoint = BD_PROXY_CONNECTION_START_POINT; - mMode = BITDHT_CONNECT_MODE_DIRECT; - - mSrcConnAddr = *srcConnAddr; /* self, full ID/IP */ - mDestConnAddr = *destId; /* IP unknown */ - - mBandwidth = 0; - mMaxDelay = 0; - mConnectionStartTS = time(NULL); - - /* clear IP Addresses to enforce this */ - bdsockaddr_clear(&(mSrcId.addr)); - bdsockaddr_clear(&(mDestConnAddr.addr)); - - /* don't bother with START/ACK parameters */ - - return 1; -} - - - -// Initialise a new Connection. (receiving a Connection Request) -// Direct Connection initialised at Destination (END_POINT), prior to Auth. -int bdConnection::ConnectionRequestDirect(bdId *id, bdId *srcConnAddr, bdId *destId) -{ - mState = BITDHT_CONNECTION_WAITING_AUTH; - mLastEvent = time(NULL); - mSrcId = *id; /* peer ID/IP known */ - mDestId = *destId; /* self, IP unknown */ - mProxyId = *id; /* src ID/IP known */ - - mPoint = BD_PROXY_CONNECTION_END_POINT; - mMode = BITDHT_CONNECT_MODE_DIRECT; - - mSrcConnAddr = *srcConnAddr; /* connect address ID/IP known */ - mDestConnAddr = *destId; /* self IP unknown */ - - mBandwidth = 0; - mMaxDelay = 0; - mConnectionStartTS = time(NULL); - - /* clear IP Addresses to enforce this */ - bdsockaddr_clear(&(mDestId.addr)); - bdsockaddr_clear(&(mDestConnAddr.addr)); - - /* don't bother with START/ACK parameters */ - - return 1; -} - - -// Proxy Connection initialised at Proxy (MID_POINT), prior to Auth. -int bdConnection::ConnectionRequestProxy(bdId *id, bdId *srcConnAddr, bdNodeId *ownId, bdId *destId, int mode, int delay) -{ - mState = BITDHT_CONNECTION_WAITING_AUTH; - mLastEvent = time(NULL); - mSrcId = *id; /* ID/IP Known */ - mDestId = *destId; /* destination, ID/IP known */ - mProxyId.id = *ownId; /* own id, must be set for callback, IP Unknown */ - - mPoint = BD_PROXY_CONNECTION_MID_POINT; - mMode = mode; - - mSrcConnAddr = *srcConnAddr; - mDestConnAddr = *destId; /* other peer, IP unknown */ - - mBandwidth = 0; - mMaxDelay = delay; - mConnectionStartTS = time(NULL); - -#ifdef DEBUG_CONNECTION_DELAY - std::cerr << "bdConnection::ConnectionRequestProxy(): received Initial delay: " << mMaxDelay; - std::cerr << std::endl; -#endif - - /* clear IP Addresses to enforce this */ - bdsockaddr_clear(&(mProxyId.addr)); - bdsockaddr_clear(&(mDestConnAddr.addr)); - - /* don't bother with START/ACK parameters */ - - return 1; -} - - -// Proxy Connection initialised at Destination (END_POINT), prior to Auth. -int bdConnection::ConnectionRequestEnd(bdId *id, bdId *srcId, bdId *destId, int mode) -{ - mState = BITDHT_CONNECTION_WAITING_AUTH; - mLastEvent = time(NULL); - mSrcId = *srcId; /* src IP unknown */ - mDestId = *destId; /* self, IP unknown */ - mProxyId = *id; /* src of message, full ID/IP of proxy */ - - mPoint = BD_PROXY_CONNECTION_END_POINT; - mMode = mode; - - mSrcConnAddr = *srcId; /* ID, not IP */ - mDestConnAddr = *destId; /* ID, not IP */ - - mBandwidth = 0; - mMaxDelay = 0; - mConnectionStartTS = time(NULL); - - /* clear IP Addresses to enforce this */ - bdsockaddr_clear(&(mSrcId.addr)); - bdsockaddr_clear(&(mDestId.addr)); - bdsockaddr_clear(&(mSrcConnAddr.addr)); - bdsockaddr_clear(&(mDestConnAddr.addr)); - - /* don't bother with START/ACK parameters */ - - return 1; -} - -// Received AUTH, step up to next stage. -// Search for dest ID/IP is done before AUTH. so actually nothing to do here, except set the state -int bdConnection::AuthoriseProxyConnection(bdId */*srcId*/, bdId */*proxyId*/, bdId */*destId*/, int /*mode*/, int /*loc*/, int bandwidth) -{ - mState = BITDHT_CONNECTION_WAITING_REPLY; - mLastEvent = time(NULL); - - //mSrcId, (peer) (ID/IP known) - //mDestId (other peer) (ID/IP known) - //mProxyId (self) (IP unknown) - - // mPoint, mMode should be okay. - - mBandwidth = bandwidth; - //mMaxDelay Already set. - //mConnectionStartTS Already Set - -#ifdef DEBUG_CONNECTION_DELAY - std::cerr << "bdConnection::AuthoriseProxyConnection(): received Bandwidth Limitation: " << mBandwidth; - std::cerr << std::endl; -#endif - - // mSrcConnAddr (ID/IP known) - // mDestConnAddr is still pending. - - /* clear IP Addresses to enforce this */ - bdsockaddr_clear(&(mProxyId.addr)); - bdsockaddr_clear(&(mDestConnAddr.addr)); - - /* don't bother with START/ACK parameters */ - - return 1; -} - - -/* we are end of a Proxy Connection */ -int bdConnection::AuthoriseEndConnection(bdId */*srcId*/, bdId */*proxyId*/, bdId *destConnAddr, int /*mode*/, int /*loc*/, int delay) -{ - mState = BITDHT_CONNECTION_WAITING_START; - mLastEvent = time(NULL); - - //mSrcId, (peer) should be okay. (IP unknown) - //mDestId (self) doesn't matter. (IP unknown) - //mProxyId (peer) should be okay. (ID/IP known) - - // mPoint, mMode should be okay. - - //mBandwidth not set by us. - time_t elapsedTime = (time(NULL) - mConnectionStartTS); - mMaxDelay = delay + elapsedTime; // relative to mConnectionStartTS. - //mConnectionStartTS // Already Set - -#ifdef DEBUG_CONNECTION_DELAY - std::cerr << "bdConnection::AuthoriseEndConnection(): adjusting delay: " << delay << " by elapsedTime: " << elapsedTime; - std::cerr << " for MaxDelay: " << mMaxDelay; - std::cerr << std::endl; -#endif - - // mSrcConnAddr should be okay. (IP unknown) - // Install the correct destConnAddr. (just received) - mDestConnAddr = *destConnAddr; - - /* clear IP Addresses to enforce this */ - bdsockaddr_clear(&(mSrcId.addr)); - bdsockaddr_clear(&(mDestId.addr)); - bdsockaddr_clear(&(mSrcConnAddr.addr)); - - - // Initialise the START/ACK Parameters. - mRetryCount = 0; - mLastStart = 0; - mSrcAck = false; - mDestAck = true; // Automatic ACK, as it is from us. - mCompletedTS = 0; - - return 1; -} - - - - -// Auth of the Direct Connection, means we move straight to WAITING_ACK mode. -int bdConnection::AuthoriseDirectConnection(bdId */*srcId*/, bdId */*proxyId*/, bdId *destConnAddr, int /*mode*/, int /*loc*/) -{ - mState = BITDHT_CONNECTION_WAITING_ACK; - mLastEvent = time(NULL); - - //mSrcId, (peer) should be okay. (ID/IP known) - //mDestId (self) doesn't matter. (IP Unknown) - //mProxyId (peer) should be okay. (ID/IP known) - - // mPoint, mMode should be okay. - - //mBandwidth doesn't matter - //mMaxDelay doesn't matter - //mConnectionStartTS // Already Set - - // mSrcConnAddr should be okay. (ID/IP known) - // Install the correct destConnAddr. (just received) - mDestConnAddr = *destConnAddr; - - /* clear IP Addresses to enforce this */ - bdsockaddr_clear(&(mDestId.addr)); - - // Should we check for these? This will not help for the Dest address, as we just blanked it above! */ - checkForDefaultConnectAddress(); - - // Initialise the START/ACK Parameters. - mRetryCount = 0; - mLastStart = 0; - mSrcAck = false; - mDestAck = true; // Automatic ACK, as it is from us. - mCompletedTS = 0; - - return 1; -} - -// Proxy Connection => at Proxy, Ready to send out Start and get back ACKs!! -int bdConnection::upgradeProxyConnectionToFinish(bdId */*id*/, bdId */*srcConnAddr*/, bdId *destConnAddr, int /*mode*/, int secondDelay, int /*status*/) -{ - mState = BITDHT_CONNECTION_WAITING_ACK; - mLastEvent = time(NULL); - - //mSrcId,mDestId should be okay. (ID/IP okay) - //mProxyId, not set, doesn't matter. (IP Unknown) - - // mPoint, mMode should be okay. - - //mBandwidth already set. - time_t elapsedTime = (time(NULL) - mConnectionStartTS); - int remainingDelayOne = mMaxDelay - elapsedTime; - if (secondDelay > remainingDelayOne) - { - /* maxDelay provided by Peer 2.... update calculations */ - mMaxDelay = secondDelay + elapsedTime; // relative to mConnectionStartTS. - } - //mConnectionStartTS // Already Set - -#ifdef DEBUG_CONNECTION_DELAY - std::cerr << "bdConnection::upgradeProxyConnectionToFinish(): elapsedTime: " << elapsedTime << " remainingDelayOne: "; - std::cerr << remainingDelayOne << " secondDelay: " << secondDelay << " => maxDelay: " << mMaxDelay; - std::cerr << std::endl; -#endif - - - if ((secondDelay > 100 || mMaxDelay > 100) || (mBandwidth > 1050)) - { - std::cerr << "bdConnection::upgradeProxyConnectionToFinish(): ERROR Bandwidth or Delay rather large"; - std::cerr << std::endl; - } -#ifdef DEBUG_CONNECTION_DELAY -#endif - - - // mSrcConnAddr should be okay. (ID/IP known) - // Install the correct destConnAddr. (just received) - mDestConnAddr = *destConnAddr; - - /* clear IP Addresses to enforce this */ - bdsockaddr_clear(&(mProxyId.addr)); - - checkForDefaultConnectAddress(); - - // Initialise the START/ACK Parameters. - mRetryCount = 0; - mLastStart = 0; - mSrcAck = false; - mDestAck = false; - mCompletedTS = 0; - - return 1; -} - - -// Final Sorting out of Addresses. -// This is called at the Connection Ends, on receiving the START message. -// This will contain either Bandwidth or Delay. -int bdConnection::CompleteConnection(bdId */*id*/, bdId *srcConnAddr, bdId *destConnAddr, int bandwidth, int delay) -{ - /* Store Final Addresses */ - time_t now = time(NULL); - - mState = BITDHT_CONNECTION_COMPLETED; - mCompletedTS = now; - mLastEvent = now; - - mBandwidth = bandwidth; // Received from the Proxy (in the case of a Relay). - time_t elapsedTime = (time(NULL) - mConnectionStartTS); - int remainingOrigDelay = mMaxDelay - elapsedTime; - if (delay > remainingOrigDelay) - { - /* maxDelay provided by Peer 2.... update calculations */ - mMaxDelay = delay + elapsedTime; // relative to mConnectionStartTS. - } - - - if ((delay > 100 || mMaxDelay > 100) || (mBandwidth > 1050)) - { - std::cerr << "bdConnection::CompleteConnection(): ERROR Bandwidth or Delay rather large"; - std::cerr << std::endl; - } -#ifdef DEBUG_CONNECTION_DELAY -#endif - -#ifdef DEBUG_CONNECTION_DELAY - std::cerr << "bdConnection::CompleteConnection(): Bandwidth: " << mBandwidth; - std::cerr << std::endl; - std::cerr << "bdConnection::CompleteConnection(): elapsedTime: " << elapsedTime << " remainingOrigDelay: "; - std::cerr << remainingOrigDelay << " newDelay: " << delay << " => maxDelay: " << mMaxDelay; - std::cerr << std::endl; -#endif - - if (delay < remainingOrigDelay) - { - // ERROR - std::cerr << "bdConnection::CompleteConnection(): ERROR delay: " << delay << " is smaller than remainingOrigDelay: "; - std::cerr << remainingOrigDelay; - std::cerr << std::endl; - } - - // Received Definitive Final Addresses from Proxy. - // These have to be done by proxy, as its the only one who know both our addresses. - - mSrcConnAddr = *srcConnAddr; - mDestConnAddr = *destConnAddr; - - checkForDefaultConnectAddress(); - - return 1; -} - - - -int bdConnection::checkForDefaultConnectAddress() -{ - // We can check if the DestConnAddr / SrcConnAddr are real. - // If there is nothing there, we assume that that want to connect on the - // same IP:Port as the DHT Node. - - if (mSrcConnAddr.addr.sin_addr.s_addr == 0) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::checkForDefaultConnectAddress() SrcConnAddr.addr is BLANK, installing Dht Node Address"; - std::cerr << std::endl; -#endif - - mSrcConnAddr.addr = mSrcId.addr; - } - - if (mDestConnAddr.addr.sin_addr.s_addr == 0) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectManager::checkForDefaultConnectAddress() DestConnAddr.addr is BLANK, installing Dht Node Address"; - std::cerr << std::endl; -#endif - - mDestConnAddr.addr = mDestId.addr; - } - - return 1; - -} - - -int bdConnectionRequest::setupDirectConnection(struct sockaddr_in *laddr, bdNodeId *target) -{ - mState = BITDHT_CONNREQUEST_READY; - mStateTS = time(NULL); - mPauseTS = 0; - mTarget = *target; - mLocalAddr = *laddr; - mMode = BITDHT_CONNECT_MODE_DIRECT; - mRecycled = 0; - mErrCode = 0; - - mDelay = 0; - mRequestTS = time(NULL); - - return 1; -} - -int bdConnectionRequest::setupProxyConnection(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t delay) -{ - mState = BITDHT_CONNREQUEST_READY; - mStateTS = time(NULL); - mPauseTS = 0; - mTarget = *target; - mLocalAddr = *laddr; - mMode = mode; - mRecycled = 0; - mErrCode = 0; - - mDelay = delay; - mRequestTS = time(NULL); - - return 1; -} - -/* this is a good proxy peer (with flags already checked). - * if it is in the potential proxy list, then we can add it into the good proxy list. - */ - -int bdConnectionRequest::checkGoodProxyPeer(const bdId *id) -{ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectionRequest::checkProxyPeer() "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - - std::list::iterator it = std::find(mPotentialProxies.begin(), mPotentialProxies.end(), *id); - if (it != mPotentialProxies.end()) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectionRequest::checkProxyPeer() Found in PotentialProxies List, adding in"; - std::cerr << std::endl; -#endif - - it = mPotentialProxies.erase(it); - - /* now add it in */ - addGoodProxy(id); - } - return 1; -} - - -int bdConnectionRequest::addGoodProxy(const bdId *srcId) -{ -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectionRequest::addGoodProxy() "; - bdStdPrintId(std::cerr, srcId); - std::cerr << std::endl; -#endif - - if (*srcId == mCurrentAttempt) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectionRequest::addGoodProxy() Duplicate with CurrentAttempt"; - std::cerr << std::endl; -#endif - return 0; - } - - std::list::iterator it; - for(it = mPeersTried.begin(); it != mPeersTried.end(); it++) - { - if (*srcId == it->id) - break; - } - - if (it == mPeersTried.end()) - { - for(it = mGoodProxies.begin(); it != mGoodProxies.end(); it++) - { - if (*srcId == it->id) - break; - } - - if (it == mGoodProxies.end()) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectionRequest::addGoodProxy() CRINITSTATE Found New Proxy: "; - bdStdPrintId(std::cerr, srcId); - std::cerr << std::endl; -#endif - - mGoodProxies.push_back(bdProxyId(*srcId, BD_PI_SRC_ADDGOODPROXY, 0)); - - /* if it is potentialProxies then remove */ - std::list::iterator pit; - pit = std::find(mPotentialProxies.begin(), mPotentialProxies.end(), *srcId); - if (pit != mPotentialProxies.end()) - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectionRequest::addGoodProxy() Removing from PotentialProxy List"; - std::cerr << std::endl; -#endif - - pit = mPotentialProxies.erase(pit); - } - return 1; - } - else - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectionRequest::addGoodProxy() Duplicate in mPotentialProxies List"; - std::cerr << std::endl; -#endif - } - } - else - { -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdConnectionRequest::addGoodProxy() Already tried this peer"; - std::cerr << std::endl; -#endif - } - return 0; -} - - -std::ostream &operator<<(std::ostream &out, const bdConnectionRequest &req) -{ - time_t now = time(NULL); - out << "bdConnectionRequest: "; - out << "State: " << req.mState; - out << " StateTS: " << now - req.mStateTS; - out << " Recycled: " << req.mRecycled; - out << std::endl; - out << "\tTargetId: "; - bdStdPrintNodeId(out, &(req.mTarget)); - out << std::endl; - out << "\tMode: " << req.mMode; - out << std::endl; - out << "\tDelay: " << req.mDelay; - out << " RequestTS: " << now - req.mRequestTS; - out << std::endl; - - out << "CurrentAttempt:"; - bdStdPrintId(out, &(req.mCurrentAttempt)); - out << std::endl; - - out << "GoodProxies:"; - out << std::endl; - - std::list::const_iterator it; - std::list::const_iterator pit; - for(it = req.mGoodProxies.begin(); it != req.mGoodProxies.end(); it++) - { - out << "\t"; - bdStdPrintId(out, &(it->id)); - out << ", " << it->proxySrcType(); - out << ", " << decodeConnectionError(it->errcode); - out << std::endl; - } - - out << "PotentialProxies:"; - out << std::endl; - - for(pit = req.mPotentialProxies.begin(); pit != req.mPotentialProxies.end(); pit++) - { - out << "\t"; - bdStdPrintId(out, &(*pit)); - out << std::endl; - } - - out << "PeersTried:"; - out << std::endl; - - for(it = req.mPeersTried.begin(); it != req.mPeersTried.end(); it++) - { - out << "\t"; - bdStdPrintId(out, &(it->id)); - out << ", " << it->proxySrcType(); - out << ", " << decodeConnectionError(it->errcode); - out << std::endl; - } - return out; -} - -std::ostream &operator<<(std::ostream &out, const bdConnection &conn) -{ - time_t now = time(NULL); - out << "bdConnection: "; - out << "State: " << conn.mState; - out << " LastEvent: " << now - conn.mLastEvent; - out << " Point: " << conn.mPoint; - out << " Mode: " << conn.mMode; - out << std::endl; - - out << "\tsrcId: "; - bdStdPrintId(out, &(conn.mSrcId)); - out << std::endl; - out << "\tproxyId: "; - bdStdPrintId(out, &(conn.mProxyId)); - out << std::endl; - out << "\tdestId: "; - bdStdPrintId(out, &(conn.mDestId)); - out << std::endl; - - out << "\tsrcConnAddr: "; - bdStdPrintId(out, &(conn.mSrcConnAddr)); - out << std::endl; - - out << "\tdestConnAddr: "; - bdStdPrintId(out, &(conn.mDestConnAddr)); - out << std::endl; - - out << "\tretryCount: " << conn.mRetryCount; - out << " retryCount: " << conn.mLastStart; - out << " srcAck: " << conn.mSrcAck; - out << " destAck: " << conn.mDestAck; - out << " completedTS: " << now - conn.mCompletedTS; - - out << "\tBandwidth: " << conn.mBandwidth; - out << " maxDelay: " << conn.mMaxDelay; - out << " startTS: " << now - conn.mConnectionStartTS; - - out << std::endl; - - return out; - -} - - -uint32_t createConnectionErrorCode(uint32_t userProvided, uint32_t fallback, uint32_t point) -{ - int status = userProvided & BITDHT_CONNECT_ERROR_MASK_TYPE; - if (status == BITDHT_CONNECT_ERROR_NONE) - { - status = fallback; - } - /* backup, backup. */ - if (status == BITDHT_CONNECT_ERROR_NONE) - { - status = BITDHT_CONNECT_ERROR_GENERIC; /* FALLBACK ERROR CODE */ - } - - switch(point) - { - case BD_PROXY_CONNECTION_START_POINT: - status |= BITDHT_CONNECT_ERROR_SOURCE_START; - break; - case BD_PROXY_CONNECTION_MID_POINT: - status |= BITDHT_CONNECT_ERROR_SOURCE_MID; - break; - case BD_PROXY_CONNECTION_END_POINT: - status |= BITDHT_CONNECT_ERROR_SOURCE_END; - break; - } - - return status; -} - - - -std::string decodeConnectionErrorType(uint32_t errcode) -{ - uint32_t errtype = errcode & BITDHT_CONNECT_ERROR_MASK_TYPE; - std::string namedtype = "UNKNOWN"; - switch(errtype) - { - default: - bd_sprintf_append(namedtype, "(%lu)", errtype); - break; - case BITDHT_CONNECT_ERROR_GENERIC: - namedtype = "GENERIC"; - break; - case BITDHT_CONNECT_ERROR_PROTOCOL: - namedtype = "PROTOCOL"; - break; - case BITDHT_CONNECT_ERROR_TIMEOUT: - namedtype = "TIMEOUT"; - break; - case BITDHT_CONNECT_ERROR_TEMPUNAVAIL: - namedtype = "TEMPUNAVAIL"; - break; - case BITDHT_CONNECT_ERROR_NOADDRESS: - namedtype = "NOADDRESS"; - break; - case BITDHT_CONNECT_ERROR_UNREACHABLE: - namedtype = "UNREACHABLE"; - break; - case BITDHT_CONNECT_ERROR_UNSUPPORTED: - namedtype = "UNSUPPORTED"; - break; - case BITDHT_CONNECT_ERROR_OVERLOADED: - namedtype = "OVERLOADED"; - break; - case BITDHT_CONNECT_ERROR_AUTH_DENIED: - namedtype = "AUTH_DENIED"; - break; - case BITDHT_CONNECT_ERROR_DUPLICATE: - namedtype = "DUPLICATE"; - break; - case BITDHT_CONNECT_ERROR_TOOMANYRETRY: - namedtype = "TOOMANYRETRY"; - break; - case BITDHT_CONNECT_ERROR_OUTOFPROXY: - namedtype = "OUTOFPROXY"; - break; - case BITDHT_CONNECT_ERROR_USER: - namedtype = "USER DEFINED"; - break; - } - return namedtype; -} - - -std::string decodeConnectionErrorSource(uint32_t errcode) -{ - uint32_t errsrc = errcode & BITDHT_CONNECT_ERROR_MASK_SOURCE; - std::string namedtype = "ERROR SRC UNKNOWN"; - switch(errsrc) - { - default: - bd_sprintf_append(namedtype, "(%lu)", errsrc); - break; - case BITDHT_CONNECT_ERROR_SOURCE_START: - namedtype = "START"; - break; - case BITDHT_CONNECT_ERROR_SOURCE_MID: - namedtype = "MID"; - break; - case BITDHT_CONNECT_ERROR_SOURCE_END: - namedtype = "END"; - break; - case BITDHT_CONNECT_ERROR_SOURCE_OTHER: - namedtype = "OTHER"; - break; - } - return namedtype; -} - - -#if 0 -std::string decodeConnectionErrorCRMove(uint32_t errcode) -{ - uint32_t errcr = errcode & BITDHT_CONNECT_ERROR_MASK_CRMOVE; - std::string namedtype = "UNKNOWN"; - switch(errcr) - { - default: - break; - case 0: - namedtype = "REMOTE"; - break; - case BITDHT_CONNECT_ERROR_CRMOVE_FATAL: - namedtype = "FATAL"; - break; - case BITDHT_CONNECT_ERROR_SOURCE_NOMOREIDS: - namedtype = "NOMOREIDS"; - break; - case BITDHT_CONNECT_ERROR_SOURCE_NEXTID: - namedtype = "NEXTID"; - break; - case BITDHT_CONNECT_ERROR_CRMOVE_PAUSED: - namedtype = "PAUSED"; - break; - } - return namedtype; -} -#endif - - - -std::string decodeConnectionError(uint32_t errcode) -{ - std::string totalerror; - if (!errcode) - { - totalerror = "NoError"; - } - else - { - //totalerror = decodeConnectionErrorCRMove(errcode); - //totalerror += ":"; - totalerror = decodeConnectionErrorSource(errcode); - totalerror += ":"; - totalerror += decodeConnectionErrorType(errcode); - } - - return totalerror; -} - -std::string bdProxyId::proxySrcType() const -{ - std::string str("Unknown"); - - switch (srcType) { - case BD_PI_SRC_QUERYRESULT: - str = "QueryResult"; - break; - case BD_PI_SRC_QUERYPROXY: - str = "QueryProxy"; - break; - case BD_PI_SRC_NODESPACE_FRIEND: - str = "NodeSpaceFriend"; - break; - case BD_PI_SRC_NODESPACE_SERVER: - str = "NodeSpaceServer"; - break; - case BD_PI_SRC_NODESPACE_ENGINEVERSION: - str = "NodeSpaceEngineVersion"; - break; - case BD_PI_SRC_ADDGOODPROXY: - str = "AddGoodProxy"; - break; - case BD_PI_SRC_UNKNOWN: - default: - break; - } - return str; -} - diff --git a/libbitdht/src/bitdht/bdconnection.h b/libbitdht/src/bitdht/bdconnection.h deleted file mode 100644 index c55d95c09..000000000 --- a/libbitdht/src/bitdht/bdconnection.h +++ /dev/null @@ -1,314 +0,0 @@ -/******************************************************************************* - * bitdht/bdconnection.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef BITDHT_CONNECTION_H -#define BITDHT_CONNECTION_H - -#include "bitdht/bdiface.h" - -class bdQueryManager; -class bdNodePublisher; - -/************************************************************************************************************ -************************************** ProxyTuple + Connection State **************************************** -************************************************************************************************************/ - -#define BITDHT_CONNREQUEST_READY 1 -#define BITDHT_CONNREQUEST_PAUSED 2 -#define BITDHT_CONNREQUEST_INPROGRESS 3 -#define BITDHT_CONNREQUEST_EXTCONNECT 4 -#define BITDHT_CONNREQUEST_DONE 5 - -#define BITDHT_CONNREQUEST_TIMEOUT_CONNECT 300 // MAKE THIS LARGE - SHOULD NEVER HAPPEN. -#define BITDHT_CONNREQUEST_TIMEOUT_INPROGRESS 30 -#define BITDHT_CONNREQUEST_MAX_AGE 60 - - -#define BITDHT_CONNECTION_WAITING_AUTH 1 -#define BITDHT_CONNECTION_WAITING_REPLY 2 -#define BITDHT_CONNECTION_WAITING_START 3 -#define BITDHT_CONNECTION_WAITING_ACK 4 -#define BITDHT_CONNECTION_COMPLETED 5 - - -#define BD_CONNECTION_START_RETRY_PERIOD 3 // Should only take a couple of seconds to get reply. -#define BD_CONNECTION_START_MAX_RETRY 3 -#define BD_CONNECTION_MAX_TIMEOUT 20 /* should be quick */ - - - -class bdProxyTuple -{ - public: - bdProxyTuple() { return; } - bdProxyTuple(bdNodeId *s, bdNodeId *p, bdNodeId *d) - :srcId(*s), proxyId(*p), destId(*d) { return; } - - bdNodeId srcId; - bdNodeId proxyId; - bdNodeId destId; -}; - -std::ostream &operator<<(std::ostream &out, const bdProxyTuple &t); -int operator<(const bdProxyTuple &a, const bdProxyTuple &b); -int operator==(const bdProxyTuple &a, const bdProxyTuple &b); - - -class bdConnection -{ - public: - bdConnection(); - - /** Functions to tweak the connection status */ - - // User initialised Connection. - int ConnectionSetup(bdId *proxyId, bdId *srcConnAddr, bdId *destConnAddr, int mode, int delay); - int ConnectionSetupDirect(bdId *destId, bdId *srcConnAddr); - - // Initialise a new Connection. (receiving a Connection Request) - int ConnectionRequestDirect(bdId *id, bdId *srcConnAddr, bdId *destConnAddr); - int ConnectionRequestProxy(bdId *id, bdId *srcConnAddr, bdNodeId *ownId, bdId *destConnAddr, int mode, int delay); - int ConnectionRequestEnd(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode); - - // Setup Finishing Stage, (receiving a Connection Reply). - int upgradeProxyConnectionToFinish(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int delay, int status); - - int AuthoriseDirectConnection(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc); - int AuthoriseProxyConnection(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc, int bandwidth); - int AuthoriseEndConnection(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc, int delay); - - int CompleteConnection(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int bandwidth, int delay); - - int checkForDefaultConnectAddress(); - - /* Connection State, and TimeStamp of Update */ - int mState; - time_t mLastEvent; - - /* Addresses of Start/Proxy/End Nodes */ - bdId mSrcId; - bdId mDestId; - bdId mProxyId; - - /* Where we are in the connection, - * and what connection mode. - */ - int mPoint; - int mMode; - - /* must have ip:ports of connection ends (if proxied) */ - bdId mSrcConnAddr; - bdId mDestConnAddr; - - int mBandwidth; - int mMaxDelay; - time_t mConnectionStartTS; - - /* START/ACK Finishing ****/ - time_t mLastStart; /* timer for retries */ - int mRetryCount; /* retry counter */ - - bool mSrcAck; - bool mDestAck; - - // Completion TS. - time_t mCompletedTS; - - -}; - -#define BD_PI_SRC_UNKNOWN 0 -#define BD_PI_SRC_QUERYRESULT 1 -#define BD_PI_SRC_QUERYPROXY 2 -#define BD_PI_SRC_NODESPACE_FRIEND 3 -#define BD_PI_SRC_NODESPACE_SERVER 4 -#define BD_PI_SRC_NODESPACE_ENGINEVERSION 5 -#define BD_PI_SRC_ADDGOODPROXY 6 - - -class bdProxyId -{ -public: - bdProxyId(const bdId &in_id, uint32_t in_srctype, uint32_t in_errcode) - :id(in_id), srcType(in_srctype), errcode(in_errcode) { return; } - - bdProxyId() :srcType(BD_PI_SRC_UNKNOWN), errcode(0) { return; } - - std::string proxySrcType() const; - - bdId id; - uint32_t srcType; - uint32_t errcode; -}; - - -class bdConnectionRequest -{ -public: - bdConnectionRequest() : mMode(0), mState(0), mStateTS(0), mPauseTS(0), mErrCode(0), mDelay(0), mRequestTS(0), mRecycled(0), mCurrentSrcType(0) - { - bdsockaddr_clear(&mLocalAddr); - } - -public: - int setupDirectConnection(struct sockaddr_in *laddr, bdNodeId *target); - int setupProxyConnection(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t delay); - - int addGoodProxy(const bdId *srcId); - int checkGoodProxyPeer(const bdId *Id); - - bdNodeId mTarget; - struct sockaddr_in mLocalAddr; - int mMode; - - int mState; - time_t mStateTS; - - time_t mPauseTS; - uint32_t mErrCode; - - int mDelay; - time_t mRequestTS; // reference Time for mDelay. - - std::list mGoodProxies; - std::list mPotentialProxies; - //std::list mGoodProxies; - int mRecycled; - - bdId mCurrentAttempt; - uint32_t mCurrentSrcType; - - std::list mPeersTried; - //std::list mPeersTried; -}; - -std::ostream &operator<<(std::ostream &out, const bdConnectionRequest &req); -std::ostream &operator<<(std::ostream &out, const bdConnection &conn); - - -/********* - * The Connection Management Class. - * this encapsulates all of the functionality.. - * except for a couple of message in/outs + callback. - */ - -class bdConnectManager -{ - public: - - bdConnectManager(bdNodeId *ownid, bdSpace *space, bdQueryManager *qmgr, bdDhtFunctions *fns, bdNodePublisher *pub); - - - /* connection functions */ - void requestConnection(bdNodeId *id, uint32_t modes); - void allowConnection(bdNodeId *id, uint32_t modes); - - - /* high level */ - - void shutdownConnections(); - void printConnections(); - - /* Connections: Configuration */ - void defaultConnectionOptions(); - virtual void setConnectionOptions(uint32_t allowedModes, uint32_t flags); - - /* Connections: Initiation */ - - int requestConnection(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t delay, uint32_t start); - int requestConnection_direct(struct sockaddr_in *laddr, bdNodeId *target); - int requestConnection_proxy(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t delay); - - int killConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode); - - int checkExistingConnectionAttempt(bdNodeId *target); - void addPotentialConnectionProxy(const bdId *srcId, const bdId *target); - void updatePotentialConnectionProxy(const bdId *id, uint32_t mode); - - int checkPeerForFlag(const bdId *id, uint32_t with_flag); - - int tickConnections(); - void iterateConnectionRequests(); - int startConnectionAttempt(bdConnectionRequest *req); - - // internal Callback -> normally continues to callbackConnect(). - void callbackConnectRequest(bdId *srcId, bdId *proxyId, bdId *destId, - int mode, int point, int param, int cbtype, int errcode); - - /* Connections: Outgoing */ - - int startConnectionAttempt(bdId *proxyId, bdId *srcConnAddr, bdId *destConnAddr, int mode, int delay); - void AuthConnectionOk(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc, int bandwidth, int delay); - void AuthConnectionNo(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc, int errcode); - void iterateConnections(); - - - /* Connections: Utility State */ - - bdConnection *findExistingConnection(bdNodeId *srcId, bdNodeId *proxyId, bdNodeId *destId); - bdConnection *newConnection(bdNodeId *srcId, bdNodeId *proxyId, bdNodeId *destId); - int cleanConnection(bdNodeId *srcId, bdNodeId *proxyId, bdNodeId *destId); - - int determinePosition(bdNodeId *sender, bdNodeId *src, bdNodeId *dest); - int determineProxyId(bdNodeId *sender, bdNodeId *src, bdNodeId *dest, bdNodeId *proxyId); - - bdConnection *findSimilarConnection(bdNodeId *srcId, bdNodeId *destId); - bdConnection *findExistingConnectionBySender(bdId *sender, bdId *src, bdId *dest); - bdConnection *newConnectionBySender(bdId *sender, bdId *src, bdId *dest); - int cleanConnectionBySender(bdId *sender, bdId *src, bdId *dest); - - // Overloaded Generalised Connection Callback. - virtual void callbackConnect(bdId *srcId, bdId *proxyId, bdId *destId, - int mode, int point, int param, int cbtype, int errcode); - - /* Connections: */ - int recvedConnectionRequest(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int delay); - int recvedConnectionReply(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int delay, int status); - int recvedConnectionStart(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int delayOrBandwidth); - int recvedConnectionAck(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode); - - /* setup Relay Mode */ - void setRelayMode(uint32_t mode); - - private: - - std::map mConnections; - std::map mConnectionRequests; - - uint32_t mConfigAllowedModes; - bool mConfigAutoProxy; - - uint32_t mRelayMode; - - /****************************** Connection Code (in bdconnection.cc) ****************************/ - - private: - - bdNodeId mOwnId; - bdSpace *mNodeSpace; - bdQueryManager *mQueryMgr; - bdDhtFunctions *mFns; - bdNodePublisher *mPub; -}; - - -#endif // BITDHT_CONNECTION_H diff --git a/libbitdht/src/bitdht/bdfilter.cc b/libbitdht/src/bitdht/bdfilter.cc deleted file mode 100644 index 1ba7d3aca..000000000 --- a/libbitdht/src/bitdht/bdfilter.cc +++ /dev/null @@ -1,318 +0,0 @@ -/******************************************************************************* - * bitdht/bdfilter.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "bitdht/bdfilter.h" -#include "bitdht/bdmanager.h" -#include "util/bdfile.h" - -#include -#include -#include -#include -#include - -/** - * #define DEBUG_FILTER 1 -**/ -#define BDFILTER_ENTRY_DROP_PERIOD (7 * 24 * 3600) - -bdFilter::bdFilter(const std::string &fname, const bdNodeId *ownid, uint32_t filterFlags, bdDhtFunctions *fns, bdNodeManager *manager) -{ - /* */ - mOwnId = *ownid; - mFns = fns; - mFilename = fname ; - - loadBannedIpFile() ; - - mFilterFlags = filterFlags; - mNodeManager = manager; -} - -void bdFilter::writeBannedIpFile() -{ - std::string filetmp = mFilename + ".tmp" ; - - FILE *fd = fopen(filetmp.c_str(), "w"); - - if (!fd) - { - std::cerr << "(EE) bdFilter::writeBannedIpFile() FAILED to Open File " << mFilename << std::endl; - return; - } - - for( std::map::iterator it=mFiltered.begin();it!=mFiltered.end();++it) - { - fprintf(fd, "%s %u %lu %lu\n", bdnet_inet_ntoa(it->second.mAddr.sin_addr).c_str(), it->second.mFilterFlags, it->second.mFilterTS, it->second.mLastSeen) ; -#ifdef DEBUG_FILTER - fprintf(stderr, "Storing Peer Address: %s \n", bdnet_inet_ntoa(it->second.mAddr.sin_addr).c_str()) ; -#endif - - } - fclose(fd); - - if(!bdFile::renameFile(filetmp,mFilename)) - std::cerr << "Could not rename file !!" << std::endl; -#ifdef DEBUG_FILTER - else - std::cerr << "Successfully renamed file " << filetmp << " to " << mFilename << std::endl; -#endif -} - -void bdFilter::loadBannedIpFile() -{ - char line[10240]; - char addr_str[10240]; - - struct sockaddr_in addr; - memset(&addr, 0, sizeof(struct sockaddr_in)); - addr.sin_family = PF_INET; - - FILE *fd = fopen(mFilename.c_str(),"r") ; - - if(fd == NULL) - { - std::cerr << "(EE) Cannot load filter file " << mFilename << std::endl; - return ; - } - - while(line == fgets(line, 10240, fd)) - { - uint32_t filter_flags ; - unsigned long long int filter_ts ; - unsigned long long int last_seen ; - - if (4 == sscanf(line, "%s %u %llu %llu", addr_str, &filter_flags,&filter_ts,&last_seen)) - { - if (bdnet_inet_aton(addr_str, &(addr.sin_addr))) - { - addr.sin_port = 0; - - bdFilteredPeer peer; - - peer.mAddr = addr; - peer.mFilterTS = filter_ts; - peer.mLastSeen = last_seen; - peer.mFilterFlags = filter_flags; - - mFiltered[addr.sin_addr.s_addr] = peer ; - #ifdef DEBUG_FILTER - std::cerr << "Loaded filtered IP: " << std::string(addr_str) << " last seen: " << last_seen << ", TS=" << filter_ts << std::endl; - #endif - } - } - } - - fclose(fd); -} - -//bool bdFilter::filtered(std::list &answer) -//{ -// answer = mFiltered; -// return (answer.size() > 0); -//} - -bool bdFilter::filteredIPs(std::list &answer) -{ - std::map::iterator it; - for(it = mFiltered.begin(); it != mFiltered.end(); it++) - { - answer.push_back(it->second.mAddr); - } - return (answer.size() > 0); -} - -int bdFilter::checkPeer(const bdId *id, uint32_t mode) -{ - bool add = false; - uint32_t flags = 0; - if ((mFilterFlags & BITDHT_FILTER_REASON_OWNID) && - isOwnIdWithoutBitDhtFlags(id, mode)) - { - add = true; - flags |= BITDHT_FILTER_REASON_OWNID; - } - - if (add) - { - bool isNew = addPeerToFilter(id->addr, flags); - - if (isNew) - { - return 1; - } - } - - return 0; -} - -int bdFilter::addPeerToFilter(const struct sockaddr_in& addr, uint32_t flags) -{ - std::map::iterator it = mFiltered.find(addr.sin_addr.s_addr) ; - - if(it != mFiltered.end()) - { - it->second.mLastSeen = time(NULL); - it->second.mFilterFlags |= flags; - } - else - { - time_t now = time(NULL); - bdFilteredPeer fp; - - fp.mAddr = addr; - fp.mAddr.sin_port = 0; - fp.mFilterFlags = flags; - fp.mFilterTS = now; - fp.mLastSeen = now; - - uint32_t saddr = addr.sin_addr.s_addr; - - mFiltered[saddr] = fp; - - std::cerr << "Adding New Banned Ip Address: " << bdnet_inet_ntoa(addr.sin_addr); - std::cerr << std::endl; - } - writeBannedIpFile() ; - - return true; -} - -// void bdFilter::loadFilteredPeers(const std::list& peers) -// { -// for(std::list::iterator it = peers.begin(); it != peers.end();++it) -// { -// #ifdef DEBUG_FILTER -// std::cerr << "Loading filtered peer " << inet_ntoa(it->mAddr.sin_addr) << " Flags: " << it->mFilterFlags << " FilterTS: " -// << now - it->mFilterTS << " LastSeen: " << now - it->mLastSeen << std::endl; -// #endif -// uint32_t saddr = it->mAddr.sin_addr.s_addr; -// mFiltered[saddr] = *it ; -// } -// } -void bdFilter::getFilteredPeers(std::list& peers) -{ - for(std::map::iterator it = mFiltered.begin(); it != mFiltered.end();++it) - peers.push_back(it->second) ; -} -/* fast check if the addr is in the structure */ -int bdFilter::addrOkay(struct sockaddr_in *addr) -{ - // first check upper layer - bool isAvailable, isBanned; - mNodeManager->doIsBannedCallback(addr, &isAvailable, &isBanned); - - if(isAvailable) { -#ifdef DEBUG_FILTER - std::cerr << "bdFilter::addrOkay addr: " << inet_ntoa(addr->sin_addr) << " result from upper layer: " << (isBanned ? "banned" : "ok") << std::endl; -#endif - return !isBanned; - } else { - // fallback to own ban list - - std::map::const_iterator it = mFiltered.find(addr->sin_addr.s_addr); - if (it == mFiltered.end()) - return 1; // Address is Okay - } - -#ifdef DEBUG_FILTER - std::cerr << "Detected Packet From Banned Ip Address: " << inet_ntoa(addr->sin_addr); - std::cerr << std::endl; -#endif - return 0; -} - - -bool bdFilter::isOwnIdWithoutBitDhtFlags(const bdId *id, uint32_t peerFlags) -{ - if (peerFlags & BITDHT_PEER_STATUS_RECV_PONG) - { - if (peerFlags & BITDHT_PEER_STATUS_DHT_ENGINE) - { - /* okay! */ - return false; - } - - /* now check distance */ - bdMetric dist; - mFns->bdDistance(&mOwnId, &(id->id), &dist); - int bucket = mFns->bdBucketDistance(&dist); - - /* if they match us... kill it */ - if (bucket == 0) - { - return true; - } - } - return false; -} - - -/* periodically we want to cleanup the filter.... - * if we haven't had an IP address reported as filtered for several hours. - * remove it from the list. - */ - -bool bdFilter::cleanupFilter() -{ -#ifdef DEBUG_FILTER - std::cerr << "bdFilter: Checking current filter List:" << std::endl; -#endif - - time_t now = time(NULL); - time_t dropTime = now - BDFILTER_ENTRY_DROP_PERIOD; - - for(std::map::iterator it = mFiltered.begin(); it != mFiltered.end();) - { -#ifdef DEBUG_FILTER - std::cerr << "\t" << bdnet_inet_ntoa(it->second.mAddr.sin_addr); - std::cerr << " Flags: " << it->second.mFilterFlags; - std::cerr << " FilterTS: " << now - it->second.mFilterTS; - std::cerr << " LastSeen: " << now - it->second.mLastSeen; -#endif - - if (it->second.mLastSeen < dropTime) - { - /* remove from filter */ -#ifdef DEBUG_FILTER - std::cerr << " OLD DROPPING" << std::endl; -#endif - std::map::iterator tmp(it) ; - ++tmp ; - - mFiltered.erase(it); - it = tmp ; - } - else - { -#ifdef DEBUG_FILTER - std::cerr << " OK" << std::endl; -#endif - it++; - } - } - - return true; -} - - - diff --git a/libbitdht/src/bitdht/bdfilter.h b/libbitdht/src/bitdht/bdfilter.h deleted file mode 100644 index 27d32a7d4..000000000 --- a/libbitdht/src/bitdht/bdfilter.h +++ /dev/null @@ -1,84 +0,0 @@ -/******************************************************************************* - * bitdht/bdfilter.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef BITDHT_FILTER_H -#define BITDHT_FILTER_H - -#include "bitdht/bdiface.h" -#include - -/* Query result flags are in bdiface.h */ - -#define BITDHT_FILTER_REASON_OWNID 0x0001 - -class bdFilteredPeer -{ - public: - struct sockaddr_in mAddr; - uint32_t mFilterFlags; /* reasons why we are filtering */ - time_t mFilterTS; - time_t mLastSeen; -}; - -class bdNodeManager; - -class bdFilter -{ - public: - bdFilter(const std::string& fname, const bdNodeId *ownid, uint32_t filterFlags, bdDhtFunctions *fns, bdNodeManager *manager); - - // get the answer. -//bool filtered(std::list &answer); -bool filteredIPs(std::list &answer); - -//void loadFilteredPeers(const std::list& peers) ; -void getFilteredPeers(std::list &peers); - -int checkPeer(const bdId *id, uint32_t peerFlags); - -int addrOkay(struct sockaddr_in *addr); -int addPeerToFilter(const struct sockaddr_in &addr, uint32_t flags); - -bool cleanupFilter(); - -void loadBannedIpFile() ; -void writeBannedIpFile() ; - -private: - -bool isOwnIdWithoutBitDhtFlags(const bdId *id, uint32_t peerFlags); - - // searching for - bdNodeId mOwnId; - uint32_t mFilterFlags; - - std::map mFiltered; - bdDhtFunctions *mFns; - std::string mFilename ; - - // have access to the manager for isBanned callback - bdNodeManager* mNodeManager; -}; - - -#endif - diff --git a/libbitdht/src/bitdht/bdfriendlist.cc b/libbitdht/src/bitdht/bdfriendlist.cc deleted file mode 100644 index 487f0a75c..000000000 --- a/libbitdht/src/bitdht/bdfriendlist.cc +++ /dev/null @@ -1,243 +0,0 @@ -/******************************************************************************* - * bitdht/bdfriendlist.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "bitdht/bdfriendlist.h" -#include "bitdht/bdstddht.h" -#include "bitdht/bdpeer.h" - -#include - -/***** - * #define DEBUG_FRIENDLIST 1 - ****/ - -bdFriendEntry::bdFriendEntry() -{ - mFlags = 0; - mLastSeen = 0; -} - -bool bdFriendEntry::addrKnown(struct sockaddr_in *addr) -{ - if (mFlags & BD_FRIEND_ENTRY_ADDR_OK) - { - if (mFlags & BD_FRIEND_ENTRY_ONLINE) - { - *addr = mPeerId.addr; - return true; - } - - - if (time(NULL) - mLastSeen < BD_FRIEND_ENTRY_TIMEOUT) - { - *addr = mPeerId.addr; - return true; - } - } - return false; -} - -uint32_t bdFriendEntry::getPeerFlags() -{ - return mFlags & BD_FRIEND_ENTRY_MASK_KNOWN; -} - - -bdFriendList::bdFriendList(const bdNodeId *ownId) -{ - bdId tmpId; - tmpId.id = *ownId; - updatePeer(&tmpId, BD_FRIEND_ENTRY_SELF); -} - -/****** - * Simple logic: timestamp is set with address. - * if ONLINE, then address will be dropped as soon as OFFLINE. - * if ADDR_OK, then address will be dropped after XX seconds. - * - * ONLINE - will be used with friends. - * ADDR_OK - will potentially be used for friends of friends (but not for now). - *****/ - - /* catch-all interface function */ -bool bdFriendList::updatePeer(const bdId *id, uint32_t flags) -{ -#ifdef DEBUG_FRIENDLIST - std::cerr << "bdFriendList::updatePeer() Peer("; - bdStdPrintId(std::cerr, id); - std::cerr << ") Flags: " << flags; - std::cerr << std::endl; -#endif - - std::map::iterator it; - it = mPeers.find(id->id); - if (it == mPeers.end()) - { - bdFriendEntry entry; - entry.mPeerId.id = id->id; - entry.mFlags = 0; - entry.mLastSeen = 0; - - mPeers[id->id] = entry; - it = mPeers.find(id->id); - } - - /* update all */ - it->second.mFlags = flags; - if (it->second.mFlags & (BD_FRIEND_ENTRY_ADDR_OK | BD_FRIEND_ENTRY_ONLINE)) - { - it->second.mFlags |= BD_FRIEND_ENTRY_ADDR_OK; - - it->second.mPeerId.addr = id->addr; - it->second.mLastSeen = time(NULL); - } - return true; -} - -bool bdFriendList::removePeer(const bdNodeId *id) -{ - /* see if it exists... */ - std::map::iterator it; - it = mPeers.find(*id); - if (it == mPeers.end()) - { -#ifdef DEBUG_FRIENDLIST - std::cerr << "bdFriendList::removeFriend() Peer("; - bdStdPrintNodeId(std::cerr, id); - std::cerr << ") is unknown!"; - std::cerr << std::endl; -#endif - - return false; - } - - mPeers.erase(*id); - - return true; -} - -bool bdFriendList::findPeerEntry(const bdNodeId *id, bdFriendEntry &entry) -{ - /* see if it exists... */ - std::map::iterator it; - it = mPeers.find(*id); - if (it == mPeers.end()) - { -#ifdef DEBUG_FRIENDLIST - std::cerr << "bdFriendList::getPeerEntry() Peer("; - bdStdPrintNodeId(std::cerr, id); - std::cerr << ") is unknown!"; - std::cerr << std::endl; -#endif - - return false; - } - - entry = it->second; - - - return true; -} - - -bool bdFriendList::findPeersWithFlags(uint32_t flags, std::list &peerList) -{ -#ifdef DEBUG_FRIENDLIST - std::cerr << "bdFriendList::findPeersWithFlags(" << flags << ")"; - std::cerr << std::endl; -#endif - - /* see if it exists... */ - std::map::iterator it; - for(it = mPeers.begin(); it != mPeers.end(); it++) - { - /* if they have ALL of the flags we specified */ - if ((it->second.getPeerFlags() & flags) == flags) - { -#ifdef DEBUG_FRIENDLIST - std::cerr << "bdFriendList::findPeersWithFlags() Found: "; - bdStdPrintNodeId(std::cerr, id); - std::cerr << std::endl; -#endif - peerList.push_back(it->second.mPeerId.id); - } - } - return (peerList.size() > 0); -} - - - -bool bdFriendList::print(std::ostream &out) -{ - time_t now = time(NULL); - - out << "bdFriendList::print()"; - out << std::endl; - - std::map::iterator it; - for(it = mPeers.begin(); it != mPeers.end(); it++) - { - bdStdPrintId(out, &(it->second.mPeerId)); - out << " Flags: " << it->second.mFlags; - out << " Seen: " << now - it->second.mLastSeen; - out << std::endl; - } - - return true; -} - - - - -bdPeerQueue::bdPeerQueue() -{ - return; -} - -bool bdPeerQueue::queuePeer(const bdId *id, uint32_t flags) -{ - bdFriendEntry entry; - entry.mPeerId = *id; - entry.mFlags = flags; - entry.mLastSeen = time(NULL); - - mPeerQueue.push_back(entry); - return true; -} - -bool bdPeerQueue::popPeer(bdId *id, uint32_t &flags) -{ - if (mPeerQueue.size() > 0) - { - bdFriendEntry entry = mPeerQueue.front(); - mPeerQueue.pop_front(); - *id = entry.mPeerId; - flags = entry.mFlags; - - return true; - } - - return false; -} - - - diff --git a/libbitdht/src/bitdht/bdfriendlist.h b/libbitdht/src/bitdht/bdfriendlist.h deleted file mode 100644 index a58888ed8..000000000 --- a/libbitdht/src/bitdht/bdfriendlist.h +++ /dev/null @@ -1,101 +0,0 @@ -/******************************************************************************* - * bitdht/bdfriendlist.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef BITDHT_FRIEND_LIST_H -#define BITDHT_FRIEND_LIST_H - -/* - * This class maintains a list of current friends and friends-of-friends. - * It should also be updated when a peer's address has been identified. - * - * It is used for selecting preferential peers for DHT Connections. - * and for detecting bad peers that are duplicating real RS peers. - * - */ - - -#include "bitdht/bdiface.h" -#include - -#define BD_FRIEND_ENTRY_TIMEOUT 10 - - -//#define BD_FRIEND_ENTRY_ONLINE 0x0001 -//#define BD_FRIEND_ENTRY_ADDR_OK 0x0002 - -//#define BD_FRIEND_ENTRY_WHITELIST BITDHT_PEER_STATUS_DHT_WHITELIST -//#define BD_FRIEND_ENTRY_FOF BITDHT_PEER_STATUS_DHT_FOF -//#define BD_FRIEND_ENTRY_FRIEND BITDHT_PEER_STATUS_DHT_FRIEND -//#define BD_FRIEND_ENTRY_RELAY_SERVER BITDHT_PEER_STATUS_DHT_RELAY_SERVER - -//#define BD_FRIEND_ENTRY_SELF BITDHT_PEER_STATUS_DHT_SELF - -//#define BD_FRIEND_ENTRY_MASK_KNOWN BITDHT_PEER_STATUS_MASK_KNOWN - -class bdFriendEntry -{ - public: - bdFriendEntry(); - -bool addrKnown(struct sockaddr_in *addr); -uint32_t getPeerFlags(); - - bdId mPeerId; - uint32_t mFlags; - time_t mLastSeen; -}; - -class bdFriendList -{ - - public: - bdFriendList(const bdNodeId *ownid); - -bool updatePeer(const bdId *id, uint32_t flags); -bool removePeer(const bdNodeId *id); - -bool findPeerEntry(const bdNodeId *id, bdFriendEntry &entry); -bool findPeersWithFlags(uint32_t flags, std::list &peerList); - -bool print(std::ostream &out); - private: - - std::map mPeers; -}; - -class bdPeerQueue -{ - - public: - bdPeerQueue(); - -bool queuePeer(const bdId *id, uint32_t flags); -bool popPeer(bdId *id, uint32_t &flags); - - private: - - std::list mPeerQueue; -}; - - -#endif - diff --git a/libbitdht/src/bitdht/bdhash.cc b/libbitdht/src/bitdht/bdhash.cc deleted file mode 100644 index 5eabd3d95..000000000 --- a/libbitdht/src/bitdht/bdhash.cc +++ /dev/null @@ -1,283 +0,0 @@ -/******************************************************************************* - * bitdht/bdhash.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "bitdht/bdhash.h" -#include "bitdht/bdstddht.h" -#include - -bdHashEntry::bdHashEntry(std::string value, std::string secret, time_t lifetime, time_t store) - :mValue(value), mStoreTS(store), mSecret(secret), mLifetime(lifetime) -{ - return; -} - - -/**************************** class bdHashSet ********************************/ - -bdHashSet::bdHashSet(bdNodeId *id) - :mId(*id) -{ - return; -} - -int bdHashSet::search(std::string key, uint32_t maxAge, std::list &entries) -{ - std::multimap::iterator sit, eit, it; - sit = mEntries.lower_bound(key); - eit = mEntries.upper_bound(key); - - time_t now = time(NULL); - - for(it = sit; it != eit; it++) - { - time_t age = now - it->second.mStoreTS; - if (age < (int32_t) maxAge) - { - entries.push_back(it->second); - } - } - return (0 < entries.size()); -} - -/*** - * With modification. - * If there is no secret -> it cannot be deleted (must timeout), but can be extended. - * If there is a secret -> must include it to modify. - * - * Therefore if identical entry without secret comes along - what do I do? - * -> create duplicate? - */ - -int bdHashSet::modify(std::string key, bdHashEntry *entry, uint32_t modFlags) -{ - std::multimap::iterator sit, eit, it; - sit = mEntries.lower_bound(key); - eit = mEntries.upper_bound(key); - - time_t now = time(NULL); - - bool updated = false; - for(it = sit; it != eit; it++) - { - /* check it all */ - if (it->second.mValue == entry->mValue) - { - bool noSecret = (it->second.mSecret == ""); - bool sameSecret = (it->second.mSecret == entry->mSecret); - bool update = false; - - if (noSecret && sameSecret) - { - /* only allowed to increase lifetime */ - if (modFlags == BITDHT_HASH_ENTRY_ADD) - { - time_t existKillTime = it->second.mLifetime + it->second.mStoreTS; - time_t newKillTime = entry->mLifetime + now; - if (newKillTime > existKillTime) - { - update = true; - } - } - } - else if (sameSecret) - { - if (modFlags == BITDHT_HASH_ENTRY_ADD) - { - update = true; - } - else if (modFlags == BITDHT_HASH_ENTRY_DELETE) - { - /* do it here */ - mEntries.erase(it); - return 1; - } - } - - if (update) - { - it->second.mStoreTS = now; - it->second.mLifetime = entry->mLifetime; - updated = true; - } - } - } - - if ((!updated) && (modFlags == BITDHT_HASH_ENTRY_ADD)) - { - /* create a new entry */ - bdHashEntry newEntry(entry->mValue, entry->mSecret, entry->mLifetime, now); - mEntries.insert(std::pair(key, newEntry)); - updated = true; - } - return updated; -} - -int bdHashSet::printHashSet(std::ostream &out) -{ - time_t now = time(NULL); - std::multimap::iterator it; - out << "Hash: "; - bdStdPrintNodeId(out, &mId); // Allowing "Std" as we dont need dht functions everywhere. - out << std::endl; - - for(it = mEntries.begin(); it != mEntries.end();it++) - { - time_t age = now - it->second.mStoreTS; - out << "\tK:" << bdStdConvertToPrintable(it->first); - out << " V:" << bdStdConvertToPrintable(it->second.mValue); - out << " A:" << age << " L:" << it->second.mLifetime; - out << " S:" << bdStdConvertToPrintable(it->second.mSecret); - out << std::endl; - } - return 1; -} - - - - -int bdHashSet::cleanupHashSet(uint32_t maxAge) -{ - time_t now = time(NULL); - - /* this is nasty... but don't know how to effectively remove from multimaps - * * Must do full repeat for each removal. - */ - - std::multimap::iterator it; - for(it = mEntries.begin(); it != mEntries.end();) - { - time_t age = now - it->second.mStoreTS; - if ((age > (int32_t) maxAge) || (age > it->second.mLifetime)) - { - mEntries.erase(it); - it = mEntries.begin(); - } - else - { - it++; - } - } - return 1; -} - - - - - - -/******************************* class bdHashSpace ***************************/ - -bdHashSpace::bdHashSpace() -{ - return; -} - - /* accessors */ -int bdHashSpace::search(bdNodeId *id, std::string key, uint32_t maxAge, std::list &entries) -{ - std::map::iterator it; - it = mHashTable.find(*id); - if (it == mHashTable.end()) - { - /* no entry */ - return 1; - } - - return it->second.search(key, maxAge, entries); -} - -int bdHashSpace::modify(bdNodeId *id, std::string key, bdHashEntry *entry, uint32_t modFlags) -{ - std::map::iterator it; - it = mHashTable.find(*id); - if (it == mHashTable.end()) - { - if (modFlags == BITDHT_HASH_ENTRY_DELETE) - { - /* done already */ - return 1; - } - - //mHashTable[*id] = bdHashSet(id); - mHashTable.insert(std::pair(*id, bdHashSet(id))); - it = mHashTable.find(*id); - } - - return it->second.modify(key, entry, modFlags); -} - -int bdHashSpace::printHashSpace(std::ostream &out) -{ - std::map::iterator it; - out << "bdHashSpace::printHashSpace()" << std::endl; - out << "--------------------------------------------" << std::endl; - - for(it = mHashTable.begin(); it != mHashTable.end(); it++) - { - it->second.printHashSet(out); - } - out << "--------------------------------------------" << std::endl; - return 1; -} - -int bdHashSpace::cleanHashSpace(bdNodeId *min, bdNodeId *max, time_t maxAge) -{ - std::map::iterator it; - std::list eraseList; - std::list::iterator eit; - - for(it = mHashTable.begin(); it != mHashTable.end(); it++) - { - if ((it->first < *min) || - (*max < it->first)) - { - /* schedule for erasure */ - eraseList.push_back(it->first); - } - else - { - /* clean up Hash Set */ - it->second.cleanupHashSet(maxAge); - } - } - - /* cleanup */ - while(eraseList.size() > 0) - { - bdNodeId &eId = eraseList.front(); - it = mHashTable.find(eId); - if (it != mHashTable.end()) - { - mHashTable.erase(it); - } - } - return 1; -} - - -int bdHashSpace::clear() -{ - mHashTable.clear(); - return 1; -} - - diff --git a/libbitdht/src/bitdht/bdhash.h b/libbitdht/src/bitdht/bdhash.h deleted file mode 100644 index 680169665..000000000 --- a/libbitdht/src/bitdht/bdhash.h +++ /dev/null @@ -1,85 +0,0 @@ -/******************************************************************************* - * bitdht/bdhash.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef BITDHT_HASH_SPACE_H -#define BITDHT_HASH_SPACE_H - -#include "bitdht/bdpeer.h" - -#include -#include -#include - -#define BITDHT_HASH_ENTRY_ADD 1 -#define BITDHT_HASH_ENTRY_DELETE 2 - -class bdHashEntry -{ - public: - - bdHashEntry(std::string value, std::string secret, time_t lifetime, time_t store); - std::string mValue; - time_t mStoreTS; - - /* These are nice features that OpenDHT had */ - std::string mSecret; - time_t mLifetime; -}; - - -class bdHashSet -{ - public: - - bdHashSet(bdNodeId *id); - -int search(std::string key, uint32_t maxAge, std::list &entries); -int modify(std::string key, bdHashEntry *entry, uint32_t modFlags); -int printHashSet(std::ostream &out); -int cleanupHashSet(uint32_t maxAge); - - bdNodeId mId; - std::multimap mEntries; -}; - -class bdHashSpace -{ - public: - - bdHashSpace(); - - /* accessors */ -int search(bdNodeId *id, std::string key, uint32_t maxAge, std::list &entries); -int modify(bdNodeId *id, std::string key, bdHashEntry *entry, uint32_t modFlags); - -int printHashSpace(std::ostream&); -int cleanHashSpace(bdNodeId *min, bdNodeId *max, time_t maxAge); -int clear(); - - private: - - std::map mHashTable; -}; - - -#endif - diff --git a/libbitdht/src/bitdht/bdhistory.cc b/libbitdht/src/bitdht/bdhistory.cc deleted file mode 100644 index 05bb73fa0..000000000 --- a/libbitdht/src/bitdht/bdhistory.cc +++ /dev/null @@ -1,647 +0,0 @@ -/******************************************************************************* - * bitdht/bdhistory.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - - -#include "bitdht/bdhistory.h" -#include "bitdht/bdstddht.h" -#include "bitdht/bdmsgs.h" -#include - -#define MIN_RESEND_PERIOD 60 - -bdMsgHistoryList::bdMsgHistoryList() -:mPeerVersion("Unknown") -{ - return; -} - - - -void bdMsgHistoryList::addMsg(time_t ts, uint32_t msgType, bool incoming, const bdNodeId *aboutId) -{ -// std::cerr << "bdMsgHistoryList::addMsg()"; -// std::cerr << std::endl; - - bdMsgHistoryItem msg(msgType, incoming, aboutId); - msgHistory.insert(std::make_pair(ts, msg)); -} - -void bdMsgHistoryList::setPeerType(time_t /* ts */, std::string version) -{ - mPeerVersion = version; -} - -int bdMsgHistoryList::msgCount(time_t start_ts, time_t end_ts) -{ - std::multimap::iterator sit, eit, it; - sit = msgHistory.lower_bound(start_ts); - eit = msgHistory.upper_bound(end_ts); - int count = 0; - for (it = sit; it != eit; it++, count++) ; // empty loop. - - return count; -} - -bool bdMsgHistoryList::msgClear(time_t before) -{ - if (before == 0) - { - msgHistory.clear(); - return true; - } - - // Delete the old stuff in the list. - while((msgHistory.begin() != msgHistory.end()) && (msgHistory.begin()->first < before)) - { - msgHistory.erase(msgHistory.begin()); - } - - // return true if empty. - if (msgHistory.begin() == msgHistory.end()) - { - return true; - } - return false; -} - -void bdMsgHistoryList::msgClear() -{ - msgHistory.clear(); -} - - -void bdMsgHistoryList::clearHistory() -{ - msgClear(); -} - -void bdMsgHistoryList::printHistory(std::ostream &out, int mode, time_t start_ts, time_t end_ts) -{ - //out << "AGE: MSGS => incoming, <= outgoing" << std::endl; - std::multimap::iterator sit, eit, it; - sit = msgHistory.lower_bound(start_ts); - eit = msgHistory.upper_bound(end_ts); - time_t curr_ts = 0; - bool time_changed = false; - bool first_line = true; - - for(it = sit; it != eit; it++) - { - time_changed = false; - if (curr_ts != it->first) - { - curr_ts = it->first; - time_changed = true; - } - switch(mode) - { - default: - { - /* print one line per ts */ - if (time_changed) - { - if (!first_line) - { - /* finish existing line */ - out << " " << std::endl; - } - else - { - first_line = false; - } - out << "\tTS: " << time(NULL) - curr_ts << " "; - } - - std::string name; - bitdht_msgtype(it->second.msgType, name); - - if (it->second.incoming) - { - out << "( =I> "; - } - else - { - out << "( second.aboutId.data[0] == 0) - && (it->second.aboutId.data[3] == 0) - && (it->second.aboutId.data[3] == 0) - && (it->second.aboutId.data[3] == 0)) - { - /* don't print anything */ - } - else - { - bdStdPrintNodeId(out, &(it->second.aboutId)); - } - out << " )"; - - } - break; - } // end of switch. - } - - /* finish up last line */ - if (!first_line) - { - out << " " << std::endl; - } -} - - -bool bdMsgHistoryList::canSend() -{ - std::cerr << "bdMsgHistoryList::canSend()"; - - std::multimap::reverse_iterator rit; - - rit = msgHistory.rbegin(); - if (rit != msgHistory.rend()) - { - time_t now = time(NULL); - if (now - rit->first > MIN_RESEND_PERIOD) - { - std::cerr << " OVER RESEND_PERIOD... true"; - std::cerr << std::endl; - - return true; - } - } - - if (msgHistory.size() % 2 == 0) - { - std::cerr << " SIZE: " << msgHistory.size() << " % 2 = 0 ... true"; - std::cerr << std::endl; - - return true; - } - - std::cerr << " false"; - std::cerr << std::endl; - - return false; -} - -bool bdMsgHistoryList::validPeer() -{ - std::cerr << "bdMsgHistoryList::validPeer()"; - - std::multimap::iterator it; - - for(it = msgHistory.begin(); it != msgHistory.end(); it++) - { - if (it->second.incoming) - { - std::cerr << " Incoming Msg... so validPeer"; - std::cerr << std::endl; - - return true; - } - } - - std::cerr << " false"; - std::cerr << std::endl; - - return false; -} - - -#define MAX_PING_PER_MINUTE 2 -#define MAX_QUERY_PER_MINUTE 2 - -bool bdMsgHistoryList::analysePeer() - -{ - /* analyse and print out details of the peers messages */ - bool flagged = false; - - //out << "AGE: MSGS => incoming, <= outgoing" << std::endl; - std::multimap::iterator sit, eit, it; - sit = msgHistory.begin(); - eit = msgHistory.end(); - if (sit == eit) - { - // nothing here. - return false; - } - - time_t start_ts = sit->first; - time_t end_ts = msgHistory.rbegin()->first; // must exist. - - - // don't divide by zero. - if (end_ts - start_ts < 60) - { - end_ts = start_ts + 60; - } - - - /* what do we want to analyse? */ - - /* if we have sent / recved too many queries or pings */ - - int in_ping = 0; - int out_ping = 0; - int in_query = 0; - int out_query = 0; - int in_other = 0; - int out_other = 0; - - for(it = sit; it != eit; it++) - { - if (it->second.incoming) - { - switch(it->second.msgType) - { - case BITDHT_MSG_TYPE_PING: - in_ping++; - break; - case BITDHT_MSG_TYPE_FIND_NODE: - in_query++; - break; - default: - in_other++; - break; - } - } - else - { - switch(it->second.msgType) - { - case BITDHT_MSG_TYPE_PING: - out_ping++; - break; - case BITDHT_MSG_TYPE_FIND_NODE: - out_query++; - break; - default: - out_other++; - break; - } - } - - } - - float in_ping_per_min = in_ping * 60.0 / (end_ts - start_ts); - float out_ping_per_min = out_ping * 60.0 / (end_ts - start_ts); - float in_query_per_min = in_query * 60.0 / (end_ts - start_ts); - float out_query_per_min = out_query * 60.0 / (end_ts - start_ts); - - if ((in_ping_per_min > MAX_PING_PER_MINUTE) || - (out_ping_per_min > MAX_PING_PER_MINUTE) || - (in_query_per_min > MAX_PING_PER_MINUTE) || - (out_query_per_min > MAX_PING_PER_MINUTE)) - { - flagged = true; - } - - if (flagged) - { - /* print header */ - std::ostream &out = std::cerr; - out << "BdHistoryAnalysis has flagged peer: "; - bdStdPrintId(out, &mId); - out << std::endl; - - out << "PeerType: " << mPeerVersion; - out << std::endl; - - out << "Ping In Per Min : " << in_ping_per_min << std::endl; - out << "Ping Out Per Min : " << out_ping_per_min << std::endl; - out << "Query In Per Min : " << in_query_per_min << std::endl; - out << "Query Out Per Min: " << out_query_per_min << std::endl; - - out << "Message History: "; - out << std::endl; - - printHistory(out, 0, 0, time(NULL)); - } - return true; -} - -bdHistory::bdHistory(time_t store_period) - :mStorePeriod(store_period) { return; } - -void bdHistory::addMsg(const bdId *id, bdToken * /*transId*/, uint32_t msgType, bool incoming, const bdNodeId *aboutId) -{ - //std::cerr << "bdHistory::addMsg() "; - //bdStdPrintId(std::cerr, id); - //std::cerr << std::endl; - - time_t now = time(NULL); - - std::map::iterator it; - bdMsgHistoryList &histRef = mHistory[*id]; /* will instaniate empty */ - histRef.mId = *id; - histRef.addMsg(now, msgType, incoming, aboutId); - - /* add to mMsgTimeline */ - mMsgTimeline.insert(std::make_pair(now, MsgRegister(id, msgType, incoming, aboutId))); -} - -void bdHistory::setPeerType(const bdId *id, std::string version) -{ - std::map::iterator it; - bdMsgHistoryList &histRef = mHistory[*id]; /* will instaniate empty */ - histRef.setPeerType(time(NULL), version); -} - -void bdHistory::printMsgs() -{ - /* print and clear msgs */ - std::ostream &out = std::cerr; - - std::cerr << "bdHistory::printMsgs()"; - std::cerr << std::endl; - - - std::map ::iterator it; - for(it = mHistory.begin(); it != mHistory.end(); it++) - { - if (it->second.msgCount(0, time(NULL))) // all msg count. - { - /* print header */ - out << "Msgs for "; - bdStdPrintId(out, &(it->first)); - out << " v:" << it->second.mPeerVersion; - out << std::endl; - - it->second.printHistory(out, 0, 0, time(NULL)); - } - } - - out << "Msg Timeline:"; - time_t now = time(NULL); - std::multimap::iterator hit; - for(hit = mMsgTimeline.begin(); hit != mMsgTimeline.end(); hit++) - { - out << now - hit->first << " "; - bdStdPrintId(out, &(hit->second.id)); - - if (hit->second.incoming) - { - out << " =I> "; - } - else - { - out << " second.msgType, name)) - { - out << name; - } - else - { - out << "UNKNOWN MSG"; - } - out << std::endl; - } -} - - -void bdHistory::cleanupOldMsgs() -{ - std::cerr << "bdHistory::cleanupOldMsgs()"; - std::cerr << std::endl; - - if (mStorePeriod == 0) - { - return; // no cleanup - } - - std::set to_cleanup; - std::set::iterator cit; - - time_t before = time(NULL) - mStorePeriod; - - // Delete the old stuff in the list. - while((mMsgTimeline.begin() != mMsgTimeline.end()) && (mMsgTimeline.begin()->first < before)) - { - std::multimap::iterator it = mMsgTimeline.begin(); - to_cleanup.insert(it->second.id); - mMsgTimeline.erase(it); - } - - // remove old msgs, delete entry if its empty. - std::map::iterator hit; - for(cit = to_cleanup.begin(); cit != to_cleanup.end(); cit++) - { - hit = mHistory.find(*cit); - if (hit != mHistory.end()) - { - if (hit->second.msgClear(before)) - { - // don't erase actual entry (so we remember peer type). - //mHistory.erase(hit); - } - } - } -} - - - -void bdHistory::clearHistory() -{ - // Switched to a alternative clear, so we don't drop peers, and remember their type. - //mHistory.clear(); - - - std::map ::iterator it; - for(it = mHistory.begin(); it != mHistory.end(); it++) - { - it->second.clearHistory(); - } -} - -bool bdHistory::canSend(const bdId *id) -{ - - std::map ::iterator it; - it = mHistory.find(*id); - if (it != mHistory.end()) - { - return (it->second.canSend()); - } - - /* if not found - then can send */ - return true; -} - - -bool bdHistory::validPeer(const bdId *id) -{ - std::map ::iterator it; - it = mHistory.find(*id); - if (it != mHistory.end()) - { - return (it->second.validPeer()); - } - - /* if not found - then can send */ - return false; -} - -bool bdHistory::analysePeers() -{ - std::map ::iterator it; - for(it = mHistory.begin(); it != mHistory.end(); it++) - { - it->second.analysePeer(); - } - return true; -} - - - -/* Temp data class. */ -class TypeStats -{ - public: - - TypeStats() :nodes(0) { return; } - - std::map incoming, outgoing; - int nodes; - - -void printStats(std::ostream &out, const TypeStats *refStats) -{ - std::map::iterator it; - std::map::const_iterator rit; - - out << " Nodes: " << nodes; - if (refStats) - { - out << " (" << 100.0 * nodes / (float) refStats->nodes << " %)"; - } - out << std::endl; - - out << " Incoming Msgs"; - out << std::endl; - for(it = incoming.begin(); it != incoming.end(); it++) - { - uint32_t count = 0; - if (refStats) - { - rit = refStats->incoming.find(it->first); - if (rit != refStats->incoming.end()) - { - count = rit->second; - } - } - printStatsLine(out, it->first, it->second, count); - } - - out << " Outgoing Msgs"; - out << std::endl; - for(it = outgoing.begin(); it != outgoing.end(); it++) - { - uint32_t count = 0; - if (refStats) - { - rit = refStats->outgoing.find(it->first); - if (rit != refStats->outgoing.end()) - { - count = rit->second; - } - } - printStatsLine(out, it->first, it->second, count); - } -} - - - -void printStatsLine(std::ostream &out, uint32_t msgType, uint32_t count, uint32_t global) -{ - std::string name; - bitdht_msgtype(msgType, name); - out << "\t" << name << " " << count; - if (global != 0) - { - out << " (" << 100.0 * count / (float) global << " %)"; - } - out << std::endl; -} - -}; /* end of TypeStats */ - -bool bdHistory::peerTypeAnalysis() -{ - - std::map mTypeStats; - TypeStats globalStats; - - std::map ::iterator it; - for(it = mHistory.begin(); it != mHistory.end(); it++) - { - if (it->second.msgHistory.empty()) - { - continue; - } - - std::string version = it->second.mPeerVersion; - // group be first two bytes. - version = it->second.mPeerVersion.substr(0,2); - TypeStats &stats = mTypeStats[version]; - - stats.nodes++; - globalStats.nodes++; - - std::multimap::iterator lit; - for (lit = it->second.msgHistory.begin(); lit != it->second.msgHistory.end(); lit++) - { - if (lit->second.incoming) - { - stats.incoming[lit->second.msgType]++; - globalStats.incoming[lit->second.msgType]++; - } - else - { - stats.outgoing[lit->second.msgType]++; - globalStats.outgoing[lit->second.msgType]++; - } - } - } - - - std::map::iterator tit; - for(tit = mTypeStats.begin(); tit != mTypeStats.end(); tit++) - { - std::cerr << "Stats for Peer Type: " << tit->first; - std::cerr << std::endl; - tit->second.printStats(std::cerr, &globalStats); - } - - std::cerr << "Global Stats: "; - std::cerr << std::endl; - - globalStats.printStats(std::cerr, NULL); - return true; - -} - - - diff --git a/libbitdht/src/bitdht/bdhistory.h b/libbitdht/src/bitdht/bdhistory.h deleted file mode 100644 index 79e420d92..000000000 --- a/libbitdht/src/bitdht/bdhistory.h +++ /dev/null @@ -1,147 +0,0 @@ -/******************************************************************************* - * bitdht/bdhistory.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef BITDHT_HISTORY_H -#define BITDHT_HISTORY_H - -#include "bitdht/bdpeer.h" -#include "bitdht/bdobj.h" -#include "bitdht/bdstddht.h" -#include - -#define MSG_TYPE_DIRECTION_MASK 0x000f0000 - -#define MSG_DIRECTION_INCOMING 0x00010000 -#define MSG_DIRECTION_OUTGOING 0x00020000 - -/**** DEBUGGING HISTORY ****/ - -class MsgRegister -{ - public: - MsgRegister() { return; } - MsgRegister(const bdId *inId, uint32_t inMsgType, bool inIncoming, const bdNodeId *inAboutId) - :id(*inId), msgType(inMsgType), incoming(inIncoming) - { - if (inAboutId) - { - aboutId = *inAboutId; - } - else - { - bdStdZeroNodeId(&aboutId); - } - - return; - } - - bdId id; - uint32_t msgType; - bool incoming; - bdNodeId aboutId; // filled in for queries. -}; - - -class bdMsgHistoryItem -{ - public: - bdMsgHistoryItem() - :msgType(0), incoming(false) - { - bdStdZeroNodeId(&aboutId); - return; - } - - bdMsgHistoryItem(uint32_t inMsgType, bool inIncoming, const bdNodeId *inAboutId) - :msgType(inMsgType), incoming(inIncoming) - { - if (inAboutId) - { - aboutId = *inAboutId; - } - else - { - bdStdZeroNodeId(&aboutId); - } - - return; - } - - uint32_t msgType; - bool incoming; - bdNodeId aboutId; // filled in for queries. -}; - - -class bdMsgHistoryList -{ - public: - bdMsgHistoryList(); -void addMsg(time_t ts, uint32_t msgType, bool incoming, const bdNodeId *aboutId); -void setPeerType(time_t ts, std::string version); -int msgCount(time_t start_ts, time_t end_ts); -bool msgClear(time_t before); // 0 => clear all. -void msgClear(); -void printHistory(std::ostream &out, int mode, time_t start_ts, time_t end_ts); -bool analysePeer(); -void clearHistory(); - -bool canSend(); -bool validPeer(); - - std::multimap msgHistory; - std::string mPeerVersion; - bdId mId; -}; - - - -class bdHistory -{ - public: - bdHistory(time_t store_period); - -void addMsg(const bdId *id, bdToken *transId, uint32_t msgType, bool incoming, const bdNodeId *aboutId); -void setPeerType(const bdId *id, std::string version); -void printMsgs(); - -void cleanupOldMsgs(); -void clearHistory(); -bool analysePeers(); -bool peerTypeAnalysis(); - -bool canSend(const bdId *id); -bool validPeer(const bdId *id); - - /* recent history */ - //std::list lastMsgs; - std::map mHistory; - std::multimap mMsgTimeline; - - int mStorePeriod; - -}; - - - -#endif - diff --git a/libbitdht/src/bitdht/bdiface.h b/libbitdht/src/bitdht/bdiface.h deleted file mode 100644 index 4e571ccdb..000000000 --- a/libbitdht/src/bitdht/bdiface.h +++ /dev/null @@ -1,413 +0,0 @@ -/******************************************************************************* - * bitdht/bdiface.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef BIT_DHT_INTERFACE_H -#define BIT_DHT_INTERFACE_H - -#include -#include -#include -#include -#include - -#include "util/bdnet.h" - -/* - * Functions and Classes required for Interfacing with the BitDht. - * This should be the sole header file required to talk to Dht. - * ... though setting it up will require including udpbitdht.h as well. - * - */ - -#define BITDHT_KEY_LEN 20 -#define BITDHT_KEY_INTLEN 5 -#define BITDHT_KEY_BITLEN 160 - - - - -#define BITDHT_MAX_PKTSIZE 1024 - -#define BITDHT_TTL 64 - -#define BITDHT_SEARCH_ONE_SHOT 1 -#define BITDHT_SEARCH_REPEATING 2 - -class bdNodeId -{ - public: - unsigned char data[BITDHT_KEY_LEN]; -}; - -class bdMetric: public bdNodeId {}; - -class bdId -{ - public: - - bdId(); - bdId(bdNodeId in_id, struct sockaddr_in in_addr); - - struct sockaddr_in addr; - bdNodeId id; -}; - -#define BITDHT_LIKELY_SAME_NO 0x00000000 -#define BITDHT_LIKELY_SAME_YES 0x00000001 -#define BITDHT_LIKELY_SAME_PORT_CHANGED 0x00000002 -#define BITDHT_LIKELY_SAME_LOC_CHANGED 0x00000004 -#define BITDHT_LIKELY_SAME_IDENTICAL 0x00000008 - - -class bdDhtFunctions -{ - public: - -// bdDhtFunctions(); - /* setup variables */ -virtual uint16_t bdNumBuckets() = 0; -virtual uint16_t bdNodesPerBucket() = 0; /* used for bdspace */ -virtual uint16_t bdNumQueryNodes() = 0; /* used for queries */ -virtual uint16_t bdBucketBitSize() = 0; - -virtual int bdDistance(const bdNodeId *n1, const bdNodeId *n2, bdMetric *metric) = 0; -virtual int bdBucketDistance(const bdNodeId *n1, const bdNodeId *n2) = 0; -virtual int bdBucketDistance(const bdMetric *metric) = 0; - -virtual bool bdSimilarId(const bdId *id1, const bdId *id2) = 0; -virtual bool bdUpdateSimilarId(bdId *dest, const bdId *src) = 0; - -virtual void bdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *mid) = 0; - -virtual void bdPrintId(std::ostream &out, const bdId *a) = 0; -virtual void bdPrintNodeId(std::ostream &out, const bdNodeId *a) = 0; - -}; - - - -// DHT MODES -#define BITDHT_MODE_TRAFFIC_MASK 0x00000f00 -#define BITDHT_MODE_RELAYSERVER_MASK 0x0000f000 - -// These are not ORd - only one can apply. -#define BITDHT_MODE_TRAFFIC_HIGH 0x00000100 -#define BITDHT_MODE_TRAFFIC_MED 0x00000200 -#define BITDHT_MODE_TRAFFIC_LOW 0x00000300 -#define BITDHT_MODE_TRAFFIC_TRICKLE 0x00000400 -#define BITDHT_MODE_TRAFFIC_DEFAULT BITDHT_MODE_TRAFFIC_LOW - -// These are not ORd - only one can apply. -#define BITDHT_MODE_RELAYSERVERS_IGNORED 0x00001000 -#define BITDHT_MODE_RELAYSERVERS_FLAGGED 0x00002000 -#define BITDHT_MODE_RELAYSERVERS_ONLY 0x00003000 -#define BITDHT_MODE_RELAYSERVERS_SERVER 0x00004000 - - -/* NODE OPTIONS */ -#define BITDHT_OPTIONS_MAINTAIN_UNSTABLE_PORT 0x00000001 -#define BITDHT_OPTIONS_ENABLE_RELAYS 0x00000002 - - -/* peer flags - * order is important! - * higher bits = more priority. - * BITDHT_PEER_STATUS_RECVPING - * BITDHT_PEER_STATUS_RECVPONG - * BITDHT_PEER_STATUS_RECVNODES - * BITDHT_PEER_STATUS_RECVHASHES - * BITDHT_PEER_STATUS_DHT_ENGINE (dbXXxx) - * BITDHT_PEER_STATUS_DHT_APPL (XXRSxx) - * BITDHT_PEER_STATUS_DHT_VERSION (XXxx50) - * - */ - -#define BITDHT_PEER_STATUS_MASK_RECVD 0x000000ff -#define BITDHT_PEER_STATUS_MASK_DHT 0x0000ff00 -#define BITDHT_PEER_STATUS_MASK_KNOWN 0x00ff0000 - -#define BITDHT_PEER_STATUS_RECV_PING 0x00000001 -#define BITDHT_PEER_STATUS_RECV_PONG 0x00000002 -#define BITDHT_PEER_STATUS_RECV_NODES 0x00000004 -#define BITDHT_PEER_STATUS_RECV_HASHES 0x00000008 -#define BITDHT_PEER_STATUS_RECV_CONNECT_MSG 0x00000010 - -#define BITDHT_PEER_STATUS_DHT_ENGINE 0x00000100 -#define BITDHT_PEER_STATUS_DHT_ENGINE_VERSION 0x00000200 -#define BITDHT_PEER_STATUS_DHT_APPL 0x00000400 -#define BITDHT_PEER_STATUS_DHT_APPL_VERSION 0x00000800 - -#define BITDHT_PEER_STATUS_DHT_WHITELIST 0x00010000 -#define BITDHT_PEER_STATUS_DHT_FOF 0x00020000 -#define BITDHT_PEER_STATUS_DHT_FRIEND 0x00040000 -#define BITDHT_PEER_STATUS_DHT_RELAY_SERVER 0x00080000 // (Flag must be enabled) -#define BITDHT_PEER_STATUS_DHT_SELF 0x00100000 - - -// EXTRA FLAGS are our internal thoughts about the peer. -#define BITDHT_PEER_EXFLAG_MASK_BASIC 0x000000ff -#define BITDHT_PEER_EXFLAG_UNSTABLE 0x00000001 // Port changes. -#define BITDHT_PEER_EXFLAG_ATTACHED 0x00000002 // We will ping in heavily. (if unstable) -#define BITDHT_PEER_EXFLAG_BADPEER 0x00000004 // For testing, we flag rather than discard. - - - - - -#define BITDHT_CONNECT_MODE_DIRECT 0x00000001 -#define BITDHT_CONNECT_MODE_PROXY 0x00000002 -#define BITDHT_CONNECT_MODE_RELAY 0x00000004 - -#define BITDHT_CONNECT_OPTION_AUTOPROXY 0x00000001 - -// STATUS CODES. == 0 is okay, != 0 is error. -#define BITDHT_CONNECT_ANSWER_OKAY 0x00000000 -#define BITDHT_CONNECT_ERROR_NONE (BITDHT_CONNECT_ANSWER_OKAY) - -#define BITDHT_CONNECT_ERROR_MASK_TYPE 0x0000ffff -#define BITDHT_CONNECT_ERROR_MASK_SOURCE 0x00ff0000 -#define BITDHT_CONNECT_ERROR_MASK_CRMOVE 0xff000000 - -#define BITDHT_CONNECT_ERROR_SOURCE_START 0x00010000 -#define BITDHT_CONNECT_ERROR_SOURCE_MID 0x00020000 -#define BITDHT_CONNECT_ERROR_SOURCE_END 0x00040000 -#define BITDHT_CONNECT_ERROR_SOURCE_OTHER 0x00080000 - -#define BITDHT_CONNECT_ERROR_CRMOVE_FATAL 0x01000000 -#define BITDHT_CONNECT_ERROR_CRMOVE_NOMOREIDS 0x02000000 -#define BITDHT_CONNECT_ERROR_CRMOVE_NEXTID 0x04000000 -#define BITDHT_CONNECT_ERROR_CRMOVE_PAUSED 0x08000000 - -// ERROR CODES. -#define BITDHT_CONNECT_ERROR_GENERIC 0x00000001 -#define BITDHT_CONNECT_ERROR_PROTOCOL 0x00000002 -#define BITDHT_CONNECT_ERROR_TIMEOUT 0x00000003 -#define BITDHT_CONNECT_ERROR_TEMPUNAVAIL 0x00000004 // Haven't got ext address yet. -#define BITDHT_CONNECT_ERROR_NOADDRESS 0x00000005 // Can't find the peer in tables. -#define BITDHT_CONNECT_ERROR_UNREACHABLE 0x00000006 // Symmetric NAT - -#define BITDHT_CONNECT_ERROR_UNSUPPORTED 0x00000007 -#define BITDHT_CONNECT_ERROR_OVERLOADED 0x00000008 -#define BITDHT_CONNECT_ERROR_AUTH_DENIED 0x00000009 -#define BITDHT_CONNECT_ERROR_DUPLICATE 0x0000000a - -// These are slightly special ones used for CB_REQUEST -#define BITDHT_CONNECT_ERROR_TOOMANYRETRY 0x0000000b -#define BITDHT_CONNECT_ERROR_OUTOFPROXY 0x0000000c -#define BITDHT_CONNECT_ERROR_USER 0x0000000d - - -/*************/ -// FRIEND_ENTRY_FLAGS... used by updateKnownPeers(). - -#define BD_FRIEND_ENTRY_ONLINE 0x0001 -#define BD_FRIEND_ENTRY_ADDR_OK 0x0002 - -#define BD_FRIEND_ENTRY_WHITELIST BITDHT_PEER_STATUS_DHT_WHITELIST -#define BD_FRIEND_ENTRY_FOF BITDHT_PEER_STATUS_DHT_FOF -#define BD_FRIEND_ENTRY_FRIEND BITDHT_PEER_STATUS_DHT_FRIEND -#define BD_FRIEND_ENTRY_RELAY_SERVER BITDHT_PEER_STATUS_DHT_RELAY_SERVER - -#define BD_FRIEND_ENTRY_SELF BITDHT_PEER_STATUS_DHT_SELF - -#define BD_FRIEND_ENTRY_MASK_KNOWN BITDHT_PEER_STATUS_MASK_KNOWN - - - - -/* Definitions of bdSpace Peer and Bucket are publically available, - * so we can expose the bucket entries for the gui. - */ - -class bdPeer -{ - public: - bdPeer():mPeerFlags(0), mLastSendTime(0), mLastRecvTime(0), mFoundTime(0), mExtraFlags(0) { return; } - - bdId mPeerId; - uint32_t mPeerFlags; - time_t mLastSendTime; - time_t mLastRecvTime; - time_t mFoundTime; /* time stamp that peer was found */ - - uint32_t mExtraFlags; -}; - -class bdBucket -{ - public: - - bdBucket(); - /* list so we can queue properly */ - std::list entries; -}; - -class bdQueryStatus -{ - public: - uint32_t mStatus; - uint32_t mQFlags; - std::list mResults; -}; - -class bdQuerySummary -{ - public: - - bdNodeId mId; - bdMetric mLimit; - uint32_t mState; - time_t mQueryTS; - uint32_t mQueryFlags; - int32_t mSearchTime; - - int32_t mQueryIdlePeerRetryPeriod; // seconds between retries. - - // closest peers - std::multimap mClosest; - std::multimap mPotentialPeers; - std::list mProxiesUnknown; - std::list mProxiesFlagged; -}; - - - - -/* Status options */ -#define BITDHT_QUERY_READY 1 -#define BITDHT_QUERY_QUERYING 2 -#define BITDHT_QUERY_FAILURE 3 -#define BITDHT_QUERY_FOUND_CLOSEST 4 -#define BITDHT_QUERY_PEER_UNREACHABLE 5 -#define BITDHT_QUERY_SUCCESS 6 - -/* Query Flags */ -#define BITDHT_QFLAGS_NONE 0x0000 -#define BITDHT_QFLAGS_DISGUISE 0x0001 // Don't search directly for target. -#define BITDHT_QFLAGS_DO_IDLE 0x0002 -#define BITDHT_QFLAGS_INTERNAL 0x0004 // runs through startup. (limited callback) -#define BITDHT_QFLAGS_UPDATES 0x0008 // Do regular updates. - -/* Connect Callback Flags */ -#define BITDHT_CONNECT_CB_AUTH 1 -#define BITDHT_CONNECT_CB_PENDING 2 -#define BITDHT_CONNECT_CB_START 3 -#define BITDHT_CONNECT_CB_PROXY 4 -#define BITDHT_CONNECT_CB_FAILED 5 -#define BITDHT_CONNECT_CB_REQUEST 6 - -#define BD_PROXY_CONNECTION_UNKNOWN_POINT 0 -#define BD_PROXY_CONNECTION_START_POINT 1 -#define BD_PROXY_CONNECTION_MID_POINT 2 -#define BD_PROXY_CONNECTION_END_POINT 3 - -#define BITDHT_INFO_CB_TYPE_BADPEER 1 - -/* Relay Modes */ -#define BITDHT_RELAYS_OFF 0 -#define BITDHT_RELAYS_ON 1 -#define BITDHT_RELAYS_ONLY 2 -#define BITDHT_RELAYS_SERVER 3 - - -class BitDhtCallback -{ - public: -// ~BitDhtCallback(); - - // dummy cos not needed for standard dht behaviour; - virtual int dhtNodeCallback(const bdId * /*id*/, uint32_t /*peerflags*/) { return 0; } - - // must be implemented. - virtual int dhtPeerCallback(const bdId *id, uint32_t status) = 0; - virtual int dhtValueCallback(const bdNodeId *id, std::string key, uint32_t status) = 0; - - // connection callback. Not required for basic behaviour, but forced for initial development. - virtual int dhtConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId *destId, - uint32_t mode, uint32_t point, uint32_t param, uint32_t cbtype, uint32_t errcode) = 0; /* { return 0; } */ - - // Generic Info callback - initially will be used to provide bad peers. - virtual int dhtInfoCallback(const bdId *id, uint32_t type, uint32_t flags, std::string info) = 0; - - // ask upper layer whether an IP is banned or not - // must not be implemented - // when set it will be used instead of the own ban list - // return code is used to express availability/absence - virtual int dhtIsBannedCallback(const sockaddr_in */*addr*/, bool */*isBanned*/) { return 0;} -}; - - -class BitDhtInterface -{ - public: - - /* bad peer notification */ -virtual void addBadPeer(const struct sockaddr_in &addr, uint32_t source, uint32_t reason, uint32_t age) = 0; - - /* Friend Tracking */ -virtual void updateKnownPeer(const bdId *id, uint32_t type, uint32_t flags) = 0; - - /***** Request Lookup (DHT Peer & Keyword) *****/ -virtual void addFindNode(bdNodeId *id, uint32_t mode) = 0; -virtual void removeFindNode(bdNodeId *id) = 0; -virtual void findDhtValue(bdNodeId *id, std::string key, uint32_t mode) = 0; - - /***** Connections Requests *****/ -virtual bool ConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t delay, uint32_t start) = 0; -virtual void ConnectionAuth(bdId *srcId, bdId *proxyId, bdId *destId, uint32_t mode, uint32_t loc, - uint32_t bandwidth, uint32_t delay, uint32_t answer) = 0; -virtual void ConnectionOptions(uint32_t allowedModes, uint32_t flags) = 0; - -virtual bool setAttachMode(bool on) = 0; - - - /***** Add / Remove Callback Clients *****/ -virtual void addCallback(BitDhtCallback *cb) = 0; -virtual void removeCallback(BitDhtCallback *cb) = 0; - - /***** Get Results Details *****/ -virtual int getDhtPeerAddress(const bdNodeId *id, struct sockaddr_in &from) = 0; -virtual int getDhtValue(const bdNodeId *id, std::string key, std::string &value) = 0; -virtual int getDhtBucket(const int idx, bdBucket &bucket) = 0; - -virtual int getDhtQueries(std::map &queries) = 0; -virtual int getDhtQueryStatus(const bdNodeId *id, bdQuerySummary &query) = 0; - - /* stats and Dht state */ -virtual int startDht() = 0; -virtual int stopDht() = 0; -virtual int stateDht() = 0; /* STOPPED, STARTING, ACTIVE, FAILED */ -virtual uint32_t statsNetworkSize() = 0; -virtual uint32_t statsBDVersionSize() = 0; /* same version as us! */ - -virtual uint32_t setDhtMode(uint32_t dhtFlags) = 0; -}; - - -// general helper functions for decoding error messages. -std::string decodeConnectionError(uint32_t errcode); -std::string decodeConnectionErrorCRMove(uint32_t errcode); -std::string decodeConnectionErrorSource(uint32_t errcode); -std::string decodeConnectionErrorType(uint32_t errcode); - - -#endif - diff --git a/libbitdht/src/bitdht/bdmanager.cc b/libbitdht/src/bitdht/bdmanager.cc deleted file mode 100644 index dadbfb264..000000000 --- a/libbitdht/src/bitdht/bdmanager.cc +++ /dev/null @@ -1,1485 +0,0 @@ -/******************************************************************************* - * bitdht/bdmanager.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -/******* - * Node Manager. - ******/ - -/****************************************** - * 1) Maintains a list of ids to search for. - * 2) Sets up initial search for own node. - * 3) Checks on status of queries. - * 4) Callback on successful searches. - * - * This is pretty specific to RS requirements. - ****/ - -#include "bitdht/bdiface.h" -#include "bitdht/bdstddht.h" -#include "bitdht/bdmanager.h" -#include "bitdht/bdmsgs.h" -#include "bitdht/bencode.h" -#include "bitdht/bdquerymgr.h" -#include "bitdht/bdfilter.h" - -#include -#include -#include - -#include "util/bdnet.h" -#include "util/bdrandom.h" -#include "util/bdstring.h" - -/*** - * #define DEBUG_MGR 1 - * #define DEBUG_MGR_PKT 1 - ***/ - -//#define DEBUG_MGR 1 - -//#define LOCAL_NET_FLAG (BITDHT_PEER_STATUS_DHT_APPL) -#define LOCAL_NET_FLAG (BITDHT_PEER_STATUS_DHT_ENGINE) -// This is eventually what we want. -//#define LOCAL_NET_FLAG (BITDHT_PEER_STATUS_DHT_ENGINE_VERSION) - -#define QUERY_UPDATE_PERIOD 8 // under refresh period - so it'll happen at the MAX_REFRESH_PERIOD - - -bdNodeManager::bdNodeManager(bdNodeId *id, std::string dhtVersion, std::string bootfile, std::string bootfilebak, const std::string& filterfile, bdDhtFunctions *fns) - :bdNode(id, dhtVersion, bootfile, bootfilebak,filterfile, fns, this) -{ - mMode = BITDHT_MGR_STATE_OFF; - mDhtFns = fns; - mModeTS = 0 ; - mStartTS = 0; - mSearchingDone = false; - mSearchTS = 0; - - mNetworkSize = 0; - mBdNetworkSize = 0; - - std::string bfilter = "edff727f3a49f55c0504ad99d4282f7a26b3f69b59ebc6ca496879c6805a0aa567dffb755f17fdfd44dd24180bf2b61ebfbe68e9a53e79d7893f002140882daf7efbfed66f36eb170064208286040001fbefbbbbef1fa7fdf4a21128d050a208cd3a529a7efdc672c8255130e022b134bc6c77dfbf455d054349c575774d427b"; - - mBloomFilter.setFilterBits(bfilter); - -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::bdNodeManager() ID: "; - mDhtFns->bdPrintNodeId(std::cerr, id); - std::cerr << std::endl; -#endif - - mLocalNetEnhancements = true; -} - -int bdNodeManager::stopDht() -{ - time_t now = time(NULL); - - /* clean up node */ - shutdownNode(); - - /* flag queries as inactive */ - /* check if exists already */ - std::map::iterator it; - for(it = mActivePeers.begin(); it != mActivePeers.end(); it++) - { - it->second.mStatus = BITDHT_QUERY_READY; - } - - /* set state flag */ - mMode = BITDHT_MGR_STATE_OFF; - mModeTS = now; - - return 1; -} - -int bdNodeManager::startDht() -{ - time_t now = time(NULL); - - /* set startup mode */ - restartNode(); - - mMode = BITDHT_MGR_STATE_STARTUP; - mModeTS = now; - - mStartTS = now; - mSearchingDone = false; - mSearchTS = now; - - return 1; -} - - /* STOPPED, STARTING, ACTIVE, FAILED */ -int bdNodeManager::stateDht() -{ - return mMode; -} - -uint32_t bdNodeManager::statsNetworkSize() -{ - return mNetworkSize; -} - -/* same version as us! */ -uint32_t bdNodeManager::statsBDVersionSize() -{ - return mBdNetworkSize; -} - -uint32_t bdNodeManager::setDhtMode(uint32_t dhtFlags) -{ - /* handle options here? */ - setNodeDhtMode(dhtFlags); - - return dhtFlags; -} - - -bool bdNodeManager::setAttachMode(bool on) -{ - if (on) - { - setNodeOptions(BITDHT_OPTIONS_MAINTAIN_UNSTABLE_PORT); - } - else - { - setNodeOptions(0); - } - return on; -} - - /* Friend Tracking */ -void bdNodeManager::addBadPeer(const struct sockaddr_in &/*addr*/, uint32_t /*source*/, uint32_t /*reason*/, uint32_t /*age*/) -{ - std::cerr << "bdNodeManager::addBadPeer() not implemented yet!"; - std::cerr << std::endl; -} - -void bdNodeManager::updateKnownPeer(const bdId *id, uint32_t /* type */, uint32_t flags) -{ - mFriendList.updatePeer(id, flags); -} - -void bdNodeManager::addFindNode(bdNodeId *id, uint32_t qflags) -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::addFindNode() "; - mDhtFns->bdPrintNodeId(std::cerr, id); - std::cerr << std::endl; -#endif - /* check if exists already */ - std::map::iterator it; - it = mActivePeers.find(*id); - if (it != mActivePeers.end()) - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::addFindNode() Found existing...."; - std::cerr << std::endl; -#endif - return; - } - - /* add to map */ - bdQueryPeer peer; - peer.mId.id = (*id); - peer.mStatus = BITDHT_QUERY_READY; //QUERYING; - peer.mQFlags = qflags; - - peer.mDhtAddr.sin_addr.s_addr = 0; - peer.mDhtAddr.sin_port = 0; - - peer.mCallbackTS = 0; - - mActivePeers[*id] = peer; -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::addFindNode() Added QueryPeer as READY...."; - std::cerr << std::endl; -#endif - //addQuery(id, qflags | BITDHT_QFLAGS_DISGUISE); - return; -} - - /* finds a queued query, and starts it */ -void bdNodeManager::startQueries() -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::startQueries() "; - std::cerr << std::endl; -#endif - /* check if exists already */ - std::map::iterator it; - for(it = mActivePeers.begin(); it != mActivePeers.end(); it++) - { - if (it->second.mStatus == BITDHT_QUERY_READY) - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::startQueries() Found READY Query."; - std::cerr << std::endl; -#endif - it->second.mStatus = BITDHT_QUERY_QUERYING; - - uint32_t qflags = it->second.mQFlags | BITDHT_QFLAGS_DISGUISE; - mQueryMgr->addQuery(&(it->first), qflags); - - // add all queries at the same time! - //return; - } - } - return; -} - - -void bdNodeManager::removeFindNode(bdNodeId *id) -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::removeFindNode() "; - mDhtFns->bdPrintNodeId(std::cerr, id); - std::cerr << std::endl; -#endif - std::map::iterator it; - it = mActivePeers.find(*id); - if (it == mActivePeers.end()) - { - return; - } - - /* cleanup any actions */ - mQueryMgr->clearQuery(&(it->first)); - //clearPing(&(it->first)); - - /* remove from map */ - mActivePeers.erase(it); - return; -} - -void bdNodeManager::iteration() -{ - - time_t now = time(NULL); - time_t modeAge = now - mModeTS; - switch(mMode) - { - case BITDHT_MGR_STATE_OFF: - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::iteration(): OFF"; - std::cerr << std::endl; -#endif - } - break; - - case BITDHT_MGR_STATE_STARTUP: - /* 10 seconds startup .... then switch to ACTIVE */ - - if (modeAge > MAX_STARTUP_TIME) - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::iteration(): STARTUP -> REFRESH"; - std::cerr << std::endl; -#endif - bdNodeId id; - getOwnId(&id); - mQueryMgr->addQuery(&id, BITDHT_QFLAGS_DO_IDLE | BITDHT_QFLAGS_DISGUISE); - - mMode = BITDHT_MGR_STATE_FINDSELF; - mModeTS = now; - } - break; - - case BITDHT_MGR_STATE_FINDSELF: - /* 60 seconds further startup .... then switch to ACTIVE - * if we reach TRANSITION_OP_SPACE_SIZE before this time, transition immediately... - * if, after 60 secs, we haven't reached MIN_OP_SPACE_SIZE, restart.... - */ - -#define TRANSITION_OP_SPACE_SIZE 50 /* 1 query / sec, should take 12-15 secs */ -#define MAX_FINDSELF_TIME 180 /* increased, as std rate has been dropped */ -#define MIN_OP_SPACE_SIZE 10 -// testing parameters. -//#define MAX_FINDSELF_TIME 10 -//#define MIN_OP_SPACE_SIZE 2 // for testing. self + oneother. - - { - uint32_t nodeSpaceSize = mNodeSpace.calcSpaceSize(); - -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::iteration() Finding Oneself: "; - std::cerr << "NodeSpace Size:" << nodeSpaceSize; - std::cerr << std::endl; -#endif - - if (nodeSpaceSize > TRANSITION_OP_SPACE_SIZE) - { - mMode = BITDHT_MGR_STATE_REFRESH; - mModeTS = now; - } - - if (modeAge > MAX_FINDSELF_TIME) - { - if (nodeSpaceSize >= MIN_OP_SPACE_SIZE) - { - mMode = BITDHT_MGR_STATE_REFRESH; - mModeTS = now; - } - else - { - mMode = BITDHT_MGR_STATE_FAILED; - mModeTS = now; - } - } - } - - break; - - case BITDHT_MGR_STATE_ACTIVE: - if (modeAge >= MAX_REFRESH_TIME) - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::iteration(): ACTIVE -> REFRESH"; - std::cerr << std::endl; -#endif - mMode = BITDHT_MGR_STATE_REFRESH; - mModeTS = now; - } - - break; - - case BITDHT_MGR_STATE_REFRESH: - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::iteration(): REFRESH -> ACTIVE"; - std::cerr << std::endl; -#endif - /* select random ids, and perform searchs to refresh space */ - mMode = BITDHT_MGR_STATE_ACTIVE; - mModeTS = now; - -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::iteration(): Starting Query"; - std::cerr << std::endl; -#endif - - startQueries(); - -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::iteration(): Updating Stores"; - std::cerr << std::endl; -#endif - - updateStore(); - -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::iteration(): Cleaning up Filter (should do less frequently)"; - std::cerr << std::endl; -#endif - - mFilterPeers.cleanupFilter(); - - -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::iteration(): Do App Search"; - std::cerr << std::endl; -#endif - - - /* This stuff is only important for "LocalNet based Features */ - if (mLocalNetEnhancements) - { - /* run a random search for ourselves, from own App DHT peer */ - QueryRandomLocalNet(); - -#define SEARCH_MAX_SIZE 10 - if (mBdNetworkSize < SEARCH_MAX_SIZE) - { -#ifdef DEBUG_MGR - std::cerr << "Local Netsize: " << mBdNetworkSize << " to small...searching"; - std::cerr << std::endl; -#endif - - /* if the network size is very small */ - SearchForLocalNet(); - mSearchingDone = false; - } - else - { - if (!mSearchingDone) - { - mSearchingDone = true; - mSearchTS = now; -#ifdef DEBUG_MGR - std::cerr << "Completed LocalNet Search in : " << mSearchTS-mStartTS; - std::cerr << std::endl; -#endif - } - } - } - -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::iteration(): REFRESH "; - std::cerr << std::endl; -#endif - - status(); /* calculates mNetworkSize */ - -#ifdef DEBUG_MGR - mAccount.printStats(std::cerr); -#endif - - /* Finally, Fail, and restart if we lose all peers */ - uint32_t nodeSpaceSize = mNodeSpace.calcSpaceSize(); - if (nodeSpaceSize < MIN_OP_SPACE_SIZE) - { - std::cerr << "bdNodeManager::iteration(): SpaceSize to Small: " << nodeSpaceSize; - std::cerr << std::endl; - std::cerr << "bdNodeManager::iteration(): REFRESH ==> FAILED"; - std::cerr << std::endl; - - mMode = BITDHT_MGR_STATE_FAILED; - mModeTS = now; - } - } - break; - - case BITDHT_MGR_STATE_QUIET: - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::iteration(): QUIET"; - std::cerr << std::endl; -#endif - - - } - break; - - default: - case BITDHT_MGR_STATE_FAILED: - { - std::cerr << "bdNodeManager::iteration(): FAILED ==> STARTUP"; - std::cerr << std::endl; -#ifdef DEBUG_MGR -#endif - stopDht(); - startDht(); - } - break; - } - - if (mMode == BITDHT_MGR_STATE_OFF) - { - bdNode::iterationOff(); - } - else - { - /* tick parent */ - bdNode::iteration(); - } -} - - /* NB: This is a bit of a hack, the code is duplicated from bdnode & bdquery. - * should use fn calls into their functions for good generality - */ - -#define RANDOM_SEARCH_FRAC (0.1) - -int bdNodeManager::QueryRandomLocalNet() -{ - bdId id; - bdNodeId targetNodeId; - - uint32_t withFlag = LOCAL_NET_FLAG; - if (mNodeSpace.findRandomPeerWithFlag(id, withFlag)) - { - /* if we've got a very small network size... then ask them about a random peer. - * (so we get there 159/158 boxes! - */ - bool isRandom = false; - if ((mBdNetworkSize < SEARCH_MAX_SIZE) || (RANDOM_SEARCH_FRAC > bdRandom::random_f32())) - { - bdStdRandomNodeId(&targetNodeId); - isRandom = true; - } - else - { - /* calculate mid point */ - mDhtFns->bdRandomMidId(&mOwnId, &(id.id), &targetNodeId); - } - - /* do standard find_peer message */ - mQueryMgr->addWorthyPeerSource(&id); /* Tell BitDHT that we really want to ping their peers */ - send_query(&id, &targetNodeId, true); - -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::QueryRandomLocalNet() Querying : "; - mDhtFns->bdPrintId(std::cerr, &id); - std::cerr << " searching for : "; - mDhtFns->bdPrintNodeId(std::cerr, &targetNodeId); - - bdMetric dist; - mDhtFns->bdDistance(&targetNodeId, &(mOwnId), &dist); - int bucket = mDhtFns->bdBucketDistance(&dist); - std::cerr << " in Bucket: " << bucket; - std::cerr << std::endl; -#endif - - if (isRandom) - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::QueryRandomLocalNet() Search is Random!"; - std::cerr << std::endl; -#endif - } - - return 1; - } - else - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::QueryRandomLocalNet() No LocalNet Peer Found"; - std::cerr << std::endl; -#endif - } - - return 0; -} - - - -void bdNodeManager::SearchForLocalNet() -{ - - -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::SearchForLocalNet()"; - std::cerr << std::endl; -#endif - - /* Check how many "Search Queries" we've got going. */ - - /* check queries */ - std::map::iterator it; - std::map queryStatus; - - - mQueryMgr->QueryStatus(queryStatus); - - int numSearchQueries = 0; - for(it = queryStatus.begin(); it != queryStatus.end(); it++) - { - if (it->second.mQFlags & BITDHT_QFLAGS_INTERNAL) - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::SearchForLocalNet() Existing Internal Search: "; - mDhtFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << std::endl; -#endif - - numSearchQueries++; - } - } - -#define MAX_SEARCH_QUERIES 5 - - for(;numSearchQueries < MAX_SEARCH_QUERIES; numSearchQueries++) - { - /* install a new query */ - bdNodeId targetNodeId; - - /* get something that filter approves of */ - bool filterOk = false; - int i; - -#define MAX_FILTER_ATTEMPTS 3000 - - for(i = 0; (!filterOk) && (i < MAX_FILTER_ATTEMPTS); i++) - { - bdStdRandomNodeId(&targetNodeId); - std::string tststr; - bdStdPrintNodeId(tststr, &targetNodeId, false); - - if (mBloomFilter.test(tststr)) - { - filterOk = true; - } - } - - if (filterOk) - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::SearchForLocalNet() " << i << " Attempts to find OkNode: "; - mDhtFns->bdPrintNodeId(std::cerr, &targetNodeId); - std::cerr << std::endl; -#endif - } - else - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::SearchForLocalNet() Failed to Find FilterOk this time: "; - mDhtFns->bdPrintNodeId(std::cerr, &targetNodeId); - std::cerr << std::endl; -#endif - } - - - uint32_t qflags = BITDHT_QFLAGS_INTERNAL | BITDHT_QFLAGS_DISGUISE; - mQueryMgr->addQuery(&targetNodeId, qflags); - -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::SearchForLocalNet() Adding New Internal Search: "; - mDhtFns->bdPrintNodeId(std::cerr, &(targetNodeId)); - std::cerr << std::endl; -#endif - } -} - - -int bdNodeManager::status() -{ - /* do status of bdNode */ -#ifdef DEBUG_MGR - printState(); -#endif - - checkStatus(); - checkBadPeerStatus(); - - /* update the network numbers */ - mNetworkSize = mNodeSpace.calcNetworkSize(); - mBdNetworkSize = mNodeSpace.calcNetworkSizeWithFlag( - LOCAL_NET_FLAG); - -#ifdef DEBUG_MGR - std::cerr << "BitDHT NetworkSize: " << mNetworkSize << std::endl; - std::cerr << "BitDHT App NetworkSize: " << mBdNetworkSize << std::endl; -#endif - - return 1; -} - - -int bdNodeManager::checkStatus() -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus()"; - std::cerr << std::endl; -#endif - - /* check queries */ - std::map::iterator it; - std::map queryStatus; - - - mQueryMgr->QueryStatus(queryStatus); - - for(it = queryStatus.begin(); it != queryStatus.end(); it++) - { - bool doPing = false; - bool doRemove = false; - bool doCallback = false; - bool doSaveAddress = false; - uint32_t callbackStatus = 0; - - switch(it->second.mStatus) - { - default: - case BITDHT_QUERY_QUERYING: - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus() Query in Progress id: "; - mDhtFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << std::endl; -#endif - } - break; - - case BITDHT_QUERY_FAILURE: - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus() Query Failed: id: "; - mDhtFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << std::endl; -#endif - // BAD. - doRemove = true; - doCallback = true; - callbackStatus = BITDHT_MGR_QUERY_FAILURE; - } - break; - - case BITDHT_QUERY_FOUND_CLOSEST: - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus() Found Closest: id: "; - mDhtFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << std::endl; -#endif - - doRemove = true; - doCallback = true; - callbackStatus = BITDHT_MGR_QUERY_PEER_OFFLINE; - } - break; - - case BITDHT_QUERY_PEER_UNREACHABLE: - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus() the Peer Online but Unreachable: id: "; - mDhtFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << std::endl; -#endif - - doRemove = true; - doCallback = true; - callbackStatus = BITDHT_MGR_QUERY_PEER_UNREACHABLE; - } - break; - - case BITDHT_QUERY_SUCCESS: - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus() Found Query: id: "; - mDhtFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << std::endl; -#endif - //foundId = - doRemove = true; - doCallback = true; - doSaveAddress = true; - callbackStatus = BITDHT_MGR_QUERY_PEER_ONLINE; - } - break; - } - - /* remove done queries */ - if (doRemove) - { - if (it->second.mQFlags & BITDHT_QFLAGS_DO_IDLE) - { - doRemove = false; - } - } - - if (doRemove) - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus() Removing query: id: "; - mFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << std::endl; -#endif - mQueryMgr->clearQuery(&(it->first)); - } - - /* FIND in activePeers */ - std::map::iterator pit; - pit = mActivePeers.find(it->first); - - if (pit == mActivePeers.end()) - { - /* only internal! - disable Callback / Ping */ - doPing = false; - doCallback = false; -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus() Internal: no cb for id: "; - mDhtFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << std::endl; -#endif - } - else - { - if (pit->second.mStatus == it->second.mStatus) - { - /* status is unchanged */ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus() Status unchanged for : "; - mFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << " status: " << it->second.mStatus; - std::cerr << std::endl; -#endif - - - time_t now = time(NULL); - /* now we check if we've done a callback before... */ - if (it->second.mQFlags & BITDHT_QFLAGS_UPDATES) - { - if (now - pit->second.mCallbackTS > QUERY_UPDATE_PERIOD) - { - // keep flags. -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus() Doing Update Callback for"; - mFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << " status: " << it->second.mStatus; - std::cerr << std::endl; -#endif - } - else - { - /* no callback this time */ - doPing = false; - doCallback = false; - } - } - else - { - doPing = false; - doCallback = false; - } - } - else - { - -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus() Updating External Status for : "; - mFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << " to: " << it->second.mStatus; - std::cerr << std::endl; -#endif - /* update status */ - pit->second.mStatus = it->second.mStatus; - } - - if (doSaveAddress) - { - if (it->second.mResults.size() > 0) - { - pit->second.mDhtAddr = it->second.mResults.front().addr; - } - else - { - pit->second.mDhtAddr.sin_addr.s_addr = 0; - pit->second.mDhtAddr.sin_port = 0; - } - } - - /* add successful queries to ping list */ - if (doPing) - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus() Starting Ping (TODO): id: "; - mFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << std::endl; -#endif - /* add first matching peer */ - //addPeerPing(foundId); - } - - /* callback on new successful queries */ - if (doCallback) - { -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::checkStatus() Doing Callback: id: "; - mFns->bdPrintNodeId(std::cerr, &(it->first)); - std::cerr << std::endl; -#endif - - time_t now = time(NULL); - pit->second.mCallbackTS = now; - bdId id(it->first,pit->second.mDhtAddr); - doPeerCallback(&id, callbackStatus); - } - } - } - return 1; -} - -#if 0 -bdNodeManager::checkPingStatus() -{ - - /* check queries */ - std::map::iterator it; - std::map pingStatus; - - PingStatus(pingStatus); - - for(it = pingStatus.begin(); it != pingStatus.end(); it++) - { - switch(it->second.mStatus) - { - case BITDHT_QUERY_QUERYING: - { - - } - break; - - case BITDHT_QUERY_FAILURE: - { - // BAD. - doRemove = true; - } - break; - - case BITDHT_QUERY_FOUND_CLOSEST: - { - - doRemove = true; - } - break; - - case BITDHT_QUERY_SUCCESS: - { - foundId = - doRemove = true; - } - break; - } - - /* remove done queries */ - if (doRemove) - { - clearQuery(it->first); - } - - /* add successful queries to ping list */ - if (doPing) - { - /* add first matching peer */ - addPeerPing(foundId); - } - - /* callback on new successful queries */ - if (doCallback) - { - - } - } -} -#endif - -int bdNodeManager::checkBadPeerStatus() -{ - bdId id; - uint32_t flags; - std::string nullstr; - - while(mBadPeerQueue.popPeer(&id, flags)) - { - doInfoCallback(&id, BITDHT_INFO_CB_TYPE_BADPEER, flags, nullstr); - } - return 1; -} - -int bdNodeManager::SearchOutOfDate() -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::SearchOutOfDate()"; - std::cerr << std::endl; -#endif - - std::map::iterator it; - - /* search for out-of-date peers */ - for(it = mActivePeers.begin(); it != mActivePeers.end(); it++) - { -#if 0 - if (old) - { - addQuery(it->first); - } -#endif - } - - return 1; -} - - - - /***** Functions to Call down to bdNodeManager ****/ - /* Request DHT Peer Lookup */ - /* Request Keyword Lookup */ - -void bdNodeManager::findDhtValue(bdNodeId * /*id*/, std::string /*key*/, uint32_t /*mode*/) -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::findDhtValue() TODO"; - std::cerr << std::endl; -#endif -} - - - /***** Get Results Details *****/ -int bdNodeManager::getDhtPeerAddress(const bdNodeId *id, struct sockaddr_in &from) -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::getDhtPeerAddress() Id: "; - mDhtFns->bdPrintNodeId(std::cerr, id); - std::cerr << " ... ? TODO" << std::endl; -#else - (void) id; -#endif - - std::map::iterator pit; - pit = mActivePeers.find(*id); - - std::cerr << "bdNodeManager::getDhtPeerAddress() Id: "; - mDhtFns->bdPrintNodeId(std::cerr, id); - std::cerr << std::endl; - - if (pit != mActivePeers.end()) - { - std::cerr << "bdNodeManager::getDhtPeerAddress() Found ActiveQuery"; - std::cerr << std::endl; - - if (pit->second.mStatus == BITDHT_QUERY_SUCCESS) - { - from = pit->second.mDhtAddr; - - std::cerr << "bdNodeManager::getDhtPeerAddress() Found Peer Address:"; - std::cerr << bdnet_inet_ntoa(from.sin_addr) << ":" << htons(from.sin_port); - std::cerr << std::endl; - - return 1; - } - } - return 0; - -} - -int bdNodeManager::getDhtValue(const bdNodeId *id, std::string key, std::string & /*value*/) -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::getDhtValue() Id: "; - mDhtFns->bdPrintNodeId(std::cerr, id); - std::cerr << " key: " << key; - std::cerr << " ... ? TODO" << std::endl; -#else - (void) id; - (void) key; -#endif - - return 1; -} - -int bdNodeManager::getDhtBucket(const int idx, bdBucket &bucket) -{ - return mNodeSpace.getDhtBucket(idx, bucket); -} - -int bdNodeManager::getDhtQueries(std::map &queries) -{ - mQueryMgr->QueryStatus(queries); - return 1; -} - -int bdNodeManager::getDhtQueryStatus(const bdNodeId *id, bdQuerySummary &query) -{ - return mQueryMgr->QuerySummary(id, query); -} - - - /***** Add / Remove Callback Clients *****/ -void bdNodeManager::addCallback(BitDhtCallback *cb) -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::addCallback()"; - std::cerr << std::endl; -#endif - /* search list */ - std::list::iterator it; - it = std::find(mCallbacks.begin(), mCallbacks.end(), cb); - if (it == mCallbacks.end()) - { - /* add it */ - mCallbacks.push_back(cb); - } -} - -void bdNodeManager::removeCallback(BitDhtCallback *cb) -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::removeCallback()"; - std::cerr << std::endl; -#endif - /* search list */ - std::list::iterator it; - it = std::find(mCallbacks.begin(), mCallbacks.end(), cb); - if (it == mCallbacks.end()) - { - /* not found! */ - return; - } - it = mCallbacks.erase(it); -} - - -void bdNodeManager::addPeer(const bdId *id, uint32_t peerflags) -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::addPeer() Overloaded (doing Callback)"; - std::cerr << std::endl; -#endif - doNodeCallback(id, peerflags); - - // call parent. - bdNode::addPeer(id, peerflags); - - return; -} - - - -void bdNodeManager::doNodeCallback(const bdId *id, uint32_t peerflags) -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::doNodeCallback() "; - mDhtFns->bdPrintId(std::cerr, id); - std::cerr << "peerflags: " << peerflags; - std::cerr << std::endl; -#endif - - /* search list */ - std::list::iterator it; - for(it = mCallbacks.begin(); it != mCallbacks.end(); it++) - { - (*it)->dhtNodeCallback(id, peerflags); - } - return; -} - -void bdNodeManager::doPeerCallback(const bdId *id, uint32_t status) -{ - -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::doPeerCallback()"; - mDhtFns->bdPrintId(std::cerr, id); - std::cerr << "status: " << status; - std::cerr << std::endl; -#endif - - /* search list */ - std::list::iterator it; - for(it = mCallbacks.begin(); it != mCallbacks.end(); it++) - { - (*it)->dhtPeerCallback(id, status); - } - return; -} - -void bdNodeManager::doValueCallback(const bdNodeId *id, std::string key, uint32_t status) -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::doValueCallback()"; - std::cerr << std::endl; -#endif - /* search list */ - std::list::iterator it; - for(it = mCallbacks.begin(); it != mCallbacks.end(); it++) - { - (*it)->dhtValueCallback(id, key, status); - } - return; -} - - -void bdNodeManager::doInfoCallback(const bdId *id, uint32_t type, uint32_t flags, std::string info) -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::doInfoCallback()"; - std::cerr << std::endl; -#endif - /* search list */ - std::list::iterator it; - for(it = mCallbacks.begin(); it != mCallbacks.end(); it++) - { - (*it)->dhtInfoCallback(id, type, flags, info); - } - return; -} - -void bdNodeManager::doIsBannedCallback(const sockaddr_in *addr, bool *isAvailable, bool *isBanned) -{ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::doIsBannedCallback()"; - std::cerr << std::endl; -#endif - /* search list */ - std::list::iterator it; - *isBanned = false; - *isAvailable = false; - for(it = mCallbacks.begin(); it != mCallbacks.end(); it++) - { - // set isBanned to true as soon as one callback answers with true - bool banned; - if((*it)->dhtIsBannedCallback(addr, &banned)) - { - *isBanned = *isBanned || banned; - *isAvailable = true; - } - } -} - - -#define BITDHT_IDENTITY_STRING_V1 "d1:" -#define BITDHT_IDENTITY_SIZE_V1 3 -#define BITDHT_PACKET_MIN_SIZE 4 - - /******************* Internals *************************/ -int bdNodeManager::isBitDhtPacket(char *data, int size, struct sockaddr_in & from) - -{ - - /* use a very simple initial check */ - if (size < BITDHT_PACKET_MIN_SIZE) - return 0; - - return (0 == strncmp(data, BITDHT_IDENTITY_STRING_V1, BITDHT_IDENTITY_SIZE_V1)); - - /* Below is the old version! */ - - -#ifdef DEBUG_MGR_PKT - std::cerr << "bdNodeManager::isBitDhtPacket() *******************************"; - std::cerr << " from " << inet_ntoa(from.sin_addr); - std::cerr << ":" << ntohs(from.sin_port); - std::cerr << std::endl; - { - /* print the fucker... only way to catch bad ones */ - std::string out; - for(int i = 0; i < size; i++) - { - if (isascii(data[i])) - { - out += data[i]; - } - else - { - bd_sprintf_append(out, "[%02lx]", (uint32_t) data[i]); - } - if ((i % 16 == 0) && (i != 0)) - { - out += "\n"; - } - } - std::cerr << out; - } - std::cerr << "bdNodeManager::isBitDhtPacket() *******************************"; - std::cerr << std::endl; -#else - (void) from; -#endif - - /* try to parse it! */ - /* convert to a be_node */ - be_node *node = be_decoden(data, size); - if (!node) - { - /* invalid decode */ -#ifdef DEBUG_MGR - std::cerr << "bdNodeManager::isBitDhtPacket() be_decode failed. dropping"; - std::cerr << std::endl; - std::cerr << "bdNodeManager::BadPacket ******************************"; - std::cerr << " from " << inet_ntoa(from.sin_addr); - std::cerr << ":" << ntohs(from.sin_port); - std::cerr << std::endl; - { - /* print the fucker... only way to catch bad ones */ - std::string out; - for(int i = 0; i < size; i++) - { - if (isascii(data[i])) - { - out += data[i]; - } - else - { - bd_sprintf_append(out, "[%02lx]", (uint32_t) data[i]); - } - if ((i % 16 == 0) && (i != 0)) - { - out += "\n"; - } - } - std::cerr << out; - } - std::cerr << "bdNodeManager::BadPacket ******************************"; - std::cerr << std::endl; -#endif - return 0; - } - - /* find message type */ - uint32_t beType = beMsgType(node); - int ans = (beType != BITDHT_MSG_TYPE_UNKNOWN); - be_free(node); - -#ifdef DEBUG_MGR_PKT - if (ans) - { - std::cerr << "bdNodeManager::isBitDhtPacket() YES"; - std::cerr << std::endl; - } - else - { - std::cerr << "bdNodeManager::isBitDhtPacket() NO: Unknown Type"; - std::cerr << std::endl; - } - -#endif - return ans; -} - - -bdDebugCallback::~bdDebugCallback() -{ -} - -int bdDebugCallback::dhtPeerCallback(const bdId *id, uint32_t status) -{ - /* remove unused parameter warnings */ - (void) status; - -#ifdef DEBUG_MGR - std::cerr << "bdDebugCallback::dhtPeerCallback() Id: "; -#endif - bdStdPrintId(std::cerr, id); -#ifdef DEBUG_MGR - std::cerr << " status: " << std::hex << status << std::dec << std::endl; -#endif - return 1; -} - -int bdDebugCallback::dhtValueCallback(const bdNodeId *id, std::string key, uint32_t status) -{ - /* remove unused parameter warnings */ - (void) key; - (void) status; - -#ifdef DEBUG_MGR - std::cerr << "bdDebugCallback::dhtValueCallback() Id: "; -#endif - bdStdPrintNodeId(std::cerr, id); -#ifdef DEBUG_MGR - std::cerr << " key: " << key; - std::cerr << " status: " << std::hex << status << std::dec << std::endl; -#endif - - return 1; -} - - - - - -/******************* Connection Stuff ********************/ - - - -bool bdNodeManager::ConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t delay, uint32_t start) -{ - std::cerr << "bdNodeManager::ConnectionRequest()"; - std::cerr << std::endl; - - return mConnMgr->requestConnection(laddr, target, mode, delay, start); -} - -void bdNodeManager::ConnectionAuth(bdId *srcId, bdId *proxyId, bdId *destId, uint32_t mode, uint32_t loc, uint32_t bandwidth, uint32_t delay, uint32_t answer) -{ - std::cerr << "bdNodeManager::ConnectionAuth()"; - std::cerr << std::endl; - - if (answer == BITDHT_CONNECT_ANSWER_OKAY) - { - mConnMgr->AuthConnectionOk(srcId, proxyId, destId, mode, loc, bandwidth, delay); - } - else - { - mConnMgr->AuthConnectionNo(srcId, proxyId, destId, mode, loc, answer); - } -} - -void bdNodeManager::ConnectionOptions(uint32_t allowedModes, uint32_t flags) -{ - mConnMgr->setConnectionOptions(allowedModes, flags); -} - - - /***** Connections Requests *****/ - - // Overloaded from bdnode for external node callback. -void bdNodeManager::callbackConnect(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int point, int param, int cbtype, int errcode) -{ - std::cerr << "bdNodeManager::callbackConnect()"; - std::cerr << std::endl; - -#ifdef DEBUG_MGR -#endif - /* search list */ - std::list::iterator it; - for(it = mCallbacks.begin(); it != mCallbacks.end(); it++) - { - (*it)->dhtConnectCallback(srcId, proxyId, destId, mode, point, param, cbtype, errcode); - } - return; -} - -int bdDebugCallback::dhtConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId *destId, - uint32_t mode, uint32_t point, uint32_t param, uint32_t cbtype, uint32_t errcode) -{ - /* remove unused parameter warnings */ - (void) srcId; - (void) proxyId; - (void) destId; - (void) mode; - (void) point; - (void) param; - (void) cbtype; - (void) errcode; - -#ifdef DEBUG_MGR - std::cerr << "bdDebugCallback::dhtConnectCallback() Type: " << cbtype; - std::cerr << " errCode: " << errcode; - std::cerr << " srcId: "; - bdStdPrintId(std::cerr, srcId); - std::cerr << " proxyId: "; - bdStdPrintId(std::cerr, proxyId); - std::cerr << " destId: "; - bdStdPrintId(std::cerr, destId); - std::cerr << " mode: " << mode; - std::cerr << " param: " << param; - std::cerr << " point: " << point << std::endl; -#endif - - return 1; -} - - -int bdDebugCallback::dhtInfoCallback(const bdId *id, uint32_t type, uint32_t flags, std::string info) -{ - /* remove unused parameter warnings */ - (void) id; - (void) type; - (void) flags; - (void) info; - -#ifdef DEBUG_MGR - std::cerr << "bdDebugCallback::dhtInfoCallback() Type: " << type; - std::cerr << " Id: "; - bdStdPrintId(std::cerr, id); - std::cerr << " flags: " << flags; - std::cerr << " info: " << info; - std::cerr << std::endl; -#endif - - return 1; -} - - - diff --git a/libbitdht/src/bitdht/bdmanager.h b/libbitdht/src/bitdht/bdmanager.h deleted file mode 100644 index e1440c154..000000000 --- a/libbitdht/src/bitdht/bdmanager.h +++ /dev/null @@ -1,209 +0,0 @@ -/******************************************************************************* - * bitdht/bdmanager.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef BITDHT_MANAGER_H -#define BITDHT_MANAGER_H - -/******* - * Node Manager. - ******/ - -/****************************************** - * 1) Maintains a list of ids to search for. - * 2) Sets up initial search for own node. - * 3) Checks on status of queries. - * 4) Callback on successful searches. - * - * This is pretty specific to RS requirements. - ****/ - -#define BITDHT_PS_MASK_ACTIONS (0x000000ff) -#define BITDHT_PS_MASK_STATE (0x0000ff00) - -#define BITDHT_PS_ACTION_SEARCHING (0x00000001) -#define BITDHT_PS_ACTION_WAITING (0x00000002) -#define BITDHT_PS_ACTION_PINGING (0x00000004) - -#define BITDHT_PS_STATE_UNKNOWN (0x00000100) -#define BITDHT_PS_STATE_OFFLINE (0x00000200) -#define BITDHT_PS_STATE_ONLINE (0x00000400) -#define BITDHT_PS_STATE_CONNECTED (0x00000800) - -#include "bitdht/bdiface.h" -#include "bitdht/bdnode.h" -#include "util/bdbloom.h" - - - -class bdQueryPeer -{ - public: - bdId mId; - uint32_t mStatus; - uint32_t mQFlags; - //time_t mLastQuery; - //time_t mLastFound; - struct sockaddr_in mDhtAddr; - time_t mCallbackTS; // for UPDATES flag. -}; - - -#define BITDHT_MGR_STATE_OFF 0 -#define BITDHT_MGR_STATE_STARTUP 1 -#define BITDHT_MGR_STATE_FINDSELF 2 -#define BITDHT_MGR_STATE_ACTIVE 3 -#define BITDHT_MGR_STATE_REFRESH 4 -#define BITDHT_MGR_STATE_QUIET 5 -#define BITDHT_MGR_STATE_FAILED 6 - -#define MAX_STARTUP_TIME 10 -#define MAX_REFRESH_TIME 10 - -#define BITDHT_MGR_QUERY_FAILURE 1 -#define BITDHT_MGR_QUERY_PEER_OFFLINE 2 -#define BITDHT_MGR_QUERY_PEER_UNREACHABLE 3 -#define BITDHT_MGR_QUERY_PEER_ONLINE 4 - - -/*** NB: Nothing in here is protected by mutexes - * must be done at a higher level! - ***/ - -class bdNodeManager: public bdNode, public BitDhtInterface -{ - public: - bdNodeManager(bdNodeId *id, std::string dhtVersion, std::string bootfile, std::string bootfilebak, const std::string &filterfile, bdDhtFunctions *fns); - - -void iteration(); - - /***** Functions to Call down to bdNodeManager ****/ - - - /* Friend Tracking */ -virtual void addBadPeer(const struct sockaddr_in &addr, uint32_t source, uint32_t reason, uint32_t age); -virtual void updateKnownPeer(const bdId *id, uint32_t type, uint32_t flags); - - /* Request DHT Peer Lookup */ - /* Request Keyword Lookup */ -virtual void addFindNode(bdNodeId *id, uint32_t mode); -virtual void removeFindNode(bdNodeId *id); -virtual void findDhtValue(bdNodeId *id, std::string key, uint32_t mode); - - /***** Add / Remove Callback Clients *****/ -virtual void addCallback(BitDhtCallback *cb); -virtual void removeCallback(BitDhtCallback *cb); - - /***** Get Results Details *****/ -virtual int getDhtPeerAddress(const bdNodeId *id, struct sockaddr_in &from); -virtual int getDhtValue(const bdNodeId *id, std::string key, std::string &value); -virtual int getDhtBucket(const int idx, bdBucket &bucket); - -virtual int getDhtQueries(std::map &queries); -virtual int getDhtQueryStatus(const bdNodeId *id, bdQuerySummary &query); - - /***** Connection Interface ****/ -virtual bool ConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t delay, uint32_t start); -virtual void ConnectionAuth(bdId *srcId, bdId *proxyId, bdId *destId, - uint32_t mode, uint32_t loc, uint32_t bandwidth, uint32_t delay, uint32_t answer); -virtual void ConnectionOptions(uint32_t allowedModes, uint32_t flags); - -virtual bool setAttachMode(bool on); - - /* stats and Dht state */ -virtual int startDht(); -virtual int stopDht(); -virtual int stateDht(); /* STOPPED, STARTING, ACTIVE, FAILED */ -virtual uint32_t statsNetworkSize(); -virtual uint32_t statsBDVersionSize(); /* same version as us! */ - -virtual uint32_t setDhtMode(uint32_t dhtFlags); - - /******************* Internals *************************/ - - // Overloaded from bdnode for external node callback. -virtual void addPeer(const bdId *id, uint32_t peerflags); - // Overloaded from bdnode for external node callback. -virtual void callbackConnect(bdId *srcId, bdId *proxyId, bdId *destId, - int mode, int point, int param, int cbtype, int errcode); - -int isBitDhtPacket(char *data, int size, struct sockaddr_in &from); - - // this function is used by bdFilter (must be public!) -void doIsBannedCallback(const sockaddr_in *addr, bool *isAvailable, bool* isBanned); - -private: - - -void doNodeCallback(const bdId *id, uint32_t peerflags); -void doPeerCallback(const bdId *id, uint32_t status); -void doValueCallback(const bdNodeId *id, std::string key, uint32_t status); -void doInfoCallback(const bdId *id, uint32_t type, uint32_t flags, std::string info); - -int status(); -int checkStatus(); -int checkPingStatus(); -int checkBadPeerStatus(); -int SearchOutOfDate(); -void startQueries(); - -int QueryRandomLocalNet(); -void SearchForLocalNet(); - - std::map mActivePeers; - std::list mCallbacks; - - uint32_t mMode; - time_t mModeTS; - - time_t mStartTS; - time_t mSearchTS; - bool mSearchingDone; - - bdDhtFunctions *mDhtFns; - - uint32_t mNetworkSize; - uint32_t mBdNetworkSize; - - bdBloom mBloomFilter; - - bool mLocalNetEnhancements; - - /* future node functions */ - //addPeerPing(foundId); - //clearPing(it->first); - //PingStatus(it->first); -}; - -class bdDebugCallback: public BitDhtCallback -{ - public: - ~bdDebugCallback(); -virtual int dhtPeerCallback(const bdId *id, uint32_t status); -virtual int dhtValueCallback(const bdNodeId *id, std::string key, uint32_t status); -virtual int dhtConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId *destId, - uint32_t mode, uint32_t point, uint32_t param, uint32_t cbtype, uint32_t errcode); -virtual int dhtInfoCallback(const bdId *id, uint32_t type, uint32_t flags, std::string info); - -}; - - -#endif diff --git a/libbitdht/src/bitdht/bdmsgs.cc b/libbitdht/src/bitdht/bdmsgs.cc deleted file mode 100644 index 07114dbab..000000000 --- a/libbitdht/src/bitdht/bdmsgs.cc +++ /dev/null @@ -1,1087 +0,0 @@ -/******************************************************************************* - * bitdht/bdmsgs.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include -#include -#include -#include "bitdht/bencode.h" -#include "bitdht/bdmsgs.h" - - -int create_ping_message(); -int response_ping_message(); - -int find_node_message(); -int response_node_message(); - -int get_peers_message(); -int response_peers_message(); -int response_closestnodes_message(); - - /* -ping Query = {"t":"aa", "y":"q", "q":"ping", "a":{"id":"abcdefghij0123456789"}} -bencoded = d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe - */ - -/**** - * #define DEBUG_MSG_DUMP 1 - * #define DEBUG_MSG_TYPE 1 - * #define DEBUG_MSGS 1 - ****/ - - -int bitdht_create_ping_msg(bdToken *tid, bdNodeId *id, bdToken *vid, char *msg, int avail) -{ -#ifdef DEBUG_MSGS - fprintf(stderr, "bitdht_create_ping_msg()\n"); -#endif - - be_node *dict = be_create_dict(); - be_node *iddict = be_create_dict(); - be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); - - be_add_keypair(iddict, "id", idnode); - - be_node *pingnode = be_create_str("ping"); - be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); - be_node *qynode = be_create_str("q"); - - be_add_keypair(dict, "a", iddict); - - be_add_keypair(dict, "q", pingnode); - be_add_keypair(dict, "t", tidnode); - be_add_keypair(dict, "y", qynode); - - if (vid) - { - be_node *vnode = be_create_str_wlen((char *) vid->data, vid->len); - be_add_keypair(dict, "v", vnode); - } - - -#ifdef DEBUG_MSG_DUMP - /* dump answer */ - be_dump(dict); -#endif - - int blen = be_encode(dict, msg, avail); - be_free(dict); - - return blen; - - -} - - - /* -Response = {"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"}} -bencoded = d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re - */ - -int bitdht_response_ping_msg(bdToken *tid, bdNodeId *id, bdToken *vid, - char *msg, int avail) -{ -#ifdef DEBUG_MSGS - fprintf(stderr, "bitdht_response_ping_msg()\n"); -#endif - - be_node *dict = be_create_dict(); - - be_node *iddict = be_create_dict(); - be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); - - be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); - be_node *yqrnode = be_create_str("r"); - - be_node *vnode = be_create_str_wlen((char *) vid->data, vid->len); - - be_add_keypair(iddict, "id", idnode); - be_add_keypair(dict, "r", iddict); - - be_add_keypair(dict, "t", tidnode); - be_add_keypair(dict, "y", yqrnode); - be_add_keypair(dict, "v", vnode); - -#ifdef DEBUG_MSG_DUMP - /* dump answer */ - be_dump(dict); -#endif - - int blen = be_encode(dict, msg, avail); - be_free(dict); - - return blen; -} - - - /* -find_node Query = {"t":"aa", "y":"q", "q":"find_node", "a": {"id":"abcdefghij0123456789", "target":"mnopqrstuvwxyz123456"}} -bencoded = d1:ad2:id20:abcdefghij01234567896:target20:mnopqrstuvwxyz123456e1:q9:find_node1:t2:aa1:y1:qe - */ - - -int bitdht_find_node_msg(bdToken *tid, bdNodeId *id, bdNodeId *target, bool localoption, - char *msg, int avail) -{ -#ifdef DEBUG_MSGS - fprintf(stderr, "bitdht_find_node_msg()\n"); -#endif - - be_node *dict = be_create_dict(); - - be_node *iddict = be_create_dict(); - be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); - be_node *targetnode = be_create_str_wlen((char *) target->data, BITDHT_KEY_LEN); - - be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); - be_node *yqrnode = be_create_str("q"); - be_node *findnode = be_create_str("find_node"); - - be_add_keypair(iddict, "id", idnode); - be_add_keypair(iddict, "target", targetnode); - be_add_keypair(dict, "a", iddict); - - be_add_keypair(dict, "t", tidnode); - be_add_keypair(dict, "y", yqrnode); - be_add_keypair(dict, "q", findnode); - - if (localoption) - { - be_node *optionnode = be_create_str("l"); - be_add_keypair(dict, "o", optionnode); - } - -#ifdef DEBUG_MSG_DUMP - /* dump answer */ - be_dump(dict); -#endif - - int blen = be_encode(dict, msg, avail); - be_free(dict); - - return blen; -} - - - - /* -Response = {"t":"aa", "y":"r", "r": {"id":"0123456789abcdefghij", "nodes": "def456..."}} -bencoded = d1:rd2:id20:0123456789abcdefghij5:nodes9:def456...e1:t2:aa1:y1:re - */ - -int bitdht_resp_node_msg(bdToken *tid, bdNodeId *id, std::list &nodes, - char *msg, int avail) -{ -#ifdef DEBUG_MSGS - fprintf(stderr, "bitdht_resp_node_msg()\n"); -#endif - - be_node *dict = be_create_dict(); - - be_node *replydict = be_create_dict(); - be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); - be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); - - be_node *peersnode = makeCompactNodeIdString(nodes); - - be_node *yqrnode = be_create_str("r"); - - be_add_keypair(replydict, "id", idnode); - be_add_keypair(replydict, "nodes", peersnode); - - be_add_keypair(dict, "t", tidnode); - be_add_keypair(dict, "y", yqrnode); - be_add_keypair(dict, "r", replydict); - -#ifdef DEBUG_MSG_DUMP - /* dump answer */ - be_dump(dict); -#endif - - int blen = be_encode(dict, msg, avail); - be_free(dict); - -#ifdef DEBUG_MSG_DUMP - fprintf(stderr, "bitdht_resp_node_msg() len = %d / %d\n", blen, avail); -#endif - - return blen; -} - - - /* -get_peers Query = {"t":"aa", "y":"q", "q":"get_peers", "a": {"id":"abcdefghij0123456789", "info_hash":"mnopqrstuvwxyz123456"}} -bencoded = d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz123456e1:q9:get_peers1:t2:aa1:y1:qe - */ - -int bitdht_get_peers_msg(bdToken *tid, bdNodeId *id, bdNodeId *info_hash, - char *msg, int avail) -{ -#ifdef DEBUG_MSGS - fprintf(stderr, "bitdht_get_peers_msg()\n"); -#endif - - be_node *dict = be_create_dict(); - - be_node *iddict = be_create_dict(); - be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); - be_node *hashnode = be_create_str_wlen((char *) info_hash->data, BITDHT_KEY_LEN); - - be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); - be_node *yqrnode = be_create_str("q"); - be_node *findnode = be_create_str("get_peers"); - - be_add_keypair(iddict, "id", idnode); - be_add_keypair(iddict, "info_hash", hashnode); - be_add_keypair(dict, "a", iddict); - - be_add_keypair(dict, "t", tidnode); - be_add_keypair(dict, "y", yqrnode); - be_add_keypair(dict, "q", findnode); - -#ifdef DEBUG_MSG_DUMP - /* dump answer */ - be_dump(dict); -#endif - - int blen = be_encode(dict, msg, avail); - be_free(dict); - - return blen; -} - - - /* -Response with peers = {"t":"aa", "y":"r", "r": {"id":"abcdefghij0123456789", "token":"aoeusnth", "values": ["axje.u", "idhtnm"]}} -bencoded = d1:rd2:id20:abcdefghij01234567895:token8:aoeusnth6:valuesl6:axje.u6:idhtnmee1:t2:aa1:y1:re - */ - -int bitdht_peers_reply_hash_msg(bdToken *tid, bdNodeId *id, - bdToken *token, std::list &values, - char *msg, int avail) -{ -#ifdef DEBUG_MSGS - fprintf(stderr, "bitdht_peers_reply_hash_msg()\n"); -#endif - - be_node *dict = be_create_dict(); - - be_node *replydict = be_create_dict(); - be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); - - be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); - be_node *tokennode = be_create_str_wlen((char *) token->data, token->len); - be_node *valuesnode = makeCompactPeerIds(values); - - be_node *yqrnode = be_create_str("r"); - - be_add_keypair(replydict, "id", idnode); - be_add_keypair(replydict, "token", tokennode); - be_add_keypair(replydict, "values", valuesnode); - - be_add_keypair(dict, "t", tidnode); - be_add_keypair(dict, "y", yqrnode); - be_add_keypair(dict, "r", replydict); - -#ifdef DEBUG_MSG_DUMP - /* dump answer */ - be_dump(dict); -#endif - - int blen = be_encode(dict, msg, avail); - be_free(dict); - - return blen; -} - - /** - -Response with closest nodes = {"t":"aa", "y":"r", "r": {"id":"abcdefghij0123456789", "token":"aoeusnth", "nodes": "def456..."}} -bencoded = d1:rd2:id20:abcdefghij01234567895:nodes9:def456...5:token8:aoeusnthe1:t2:aa1:y1:re - - **/ - - -int bitdht_peers_reply_closest_msg(bdToken *tid, bdNodeId *id, - bdToken *token, std::list &nodes, - char *msg, int avail) -{ -#ifdef DEBUG_MSGS - fprintf(stderr, "bitdht_peers_reply_closest_msg()\n"); -#endif - - be_node *dict = be_create_dict(); - - be_node *replydict = be_create_dict(); - be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); - be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); - be_node *tokennode = be_create_str_wlen((char *) token->data, token->len); - - be_node *peersnode = makeCompactNodeIdString(nodes); - - be_node *yqrnode = be_create_str("r"); - - be_add_keypair(replydict, "id", idnode); - be_add_keypair(replydict, "token", tokennode); - be_add_keypair(replydict, "nodes", peersnode); - - be_add_keypair(dict, "t", tidnode); - be_add_keypair(dict, "y", yqrnode); - be_add_keypair(dict, "r", replydict); - -#ifdef DEBUG_MSG_DUMP - /* dump answer */ - be_dump(dict); -#endif - - int blen = be_encode(dict, msg, avail); - be_free(dict); - - return blen; -} - - - -/**** FINAL TWO MESSAGES! ***/ - -/**** -announce_peers Query = {"t":"aa", "y":"q", "q":"announce_peer", "a": {"id":"abcdefghij0123456789", "info_hash":"mnopqrstuvwxyz123456", "port": 6881, "token": "aoeusnth"}} -bencoded = d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz1234564:porti6881e5:token8:aoeusnthe1:q13:announce_peer1:t2:aa1:y1:qe - -****/ - -int bitdht_announce_peers_msg(bdToken *tid, bdNodeId *id, bdNodeId *info_hash, uint32_t port, bdToken *token, char *msg, int avail) -{ -#ifdef DEBUG_MSGS - fprintf(stderr, "bitdht_announce_peers_msg()\n"); -#endif - - be_node *dict = be_create_dict(); - be_node *iddict = be_create_dict(); - - be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); - - be_node *hashnode = be_create_str_wlen((char *) info_hash->data, BITDHT_KEY_LEN); - be_node *portnode = be_create_int(port); - be_node *tokennode = be_create_str_wlen((char *) token->data, token->len); - - be_add_keypair(iddict, "id", idnode); - be_add_keypair(iddict, "info_hash", hashnode); - be_add_keypair(iddict, "port", portnode); - be_add_keypair(iddict, "token", tokennode); - - be_node *announcenode = be_create_str("announce_peer"); - be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); - be_node *qynode = be_create_str("q"); - - be_add_keypair(dict, "a", iddict); - - be_add_keypair(dict, "q", announcenode); - be_add_keypair(dict, "t", tidnode); - be_add_keypair(dict, "y", qynode); - -#ifdef DEBUG_MSG_DUMP - /* dump answer */ - be_dump(dict); -#endif - - int blen = be_encode(dict, msg, avail); - be_free(dict); - - return blen; - -} - - -/***** -Response to Announce Peers = {"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"}} -bencoded = d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re -****/ - -/**** - * NB: This is the same as a PONG msg! - ***/ - -int bitdht_reply_announce_msg(bdToken *tid, bdNodeId *id, - char *msg, int avail) -{ -#ifdef DEBUG_MSGS - fprintf(stderr, "bitdht_response_ping_msg()\n"); -#endif - - be_node *dict = be_create_dict(); - - be_node *iddict = be_create_dict(); - be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); - - be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); - be_node *yqrnode = be_create_str("r"); - - be_add_keypair(iddict, "id", idnode); - be_add_keypair(dict, "r", iddict); - - be_add_keypair(dict, "t", tidnode); - be_add_keypair(dict, "y", yqrnode); - -#ifdef DEBUG_MSG_DUMP - /* dump answer */ - be_dump(dict); -#endif - - int blen = be_encode(dict, msg, avail); - be_free(dict); - - return blen; -} - - - -/************************ Parsing Messages ********************* - * - */ - -be_node *beMsgGetDictNode(be_node *node, const char *key) -{ - /* make sure its a dictionary */ - if (node->type != BE_DICT) - { - return NULL; - } - - /* get dictionary entry 'y' */ - int i; - for(i = 0; node->val.d[i].val; i++) - { - if (0 == strcmp(key, node->val.d[i].key)) - { - return node->val.d[i].val; - } - } - return NULL; -} - - - -int beMsgMatchString(be_node *n, const char *str, int len) -{ - if (n->type != BE_STR) - { - return 0; - } - if (len != be_str_len(n)) - { - return 0; - } - - int i; - for(i = 0; i < len; i++) - { - if (n->val.s[i] != str[i]) - return 0; - } - return 1; -} - - -uint32_t beMsgGetY(be_node *n) -{ - be_node *val = beMsgGetDictNode(n, "y"); - - if(val == NULL) - return BE_Y_UNKNOWN ; - - if (val->type != BE_STR) - { - return BE_Y_UNKNOWN; - } - - if (val->val.s[0] == 'q') - { - return BE_Y_Q; - } - else if (val->val.s[0] == 'r') - { - return BE_Y_R; - } - - return BE_Y_UNKNOWN; -} - - - -uint32_t beMsgType(be_node *n) -{ - /* check for - * y: q or r - */ - uint32_t beY = beMsgGetY(n); - -#ifdef DEBUG_MSG_TYPE - std::cerr << "bsMsgType() beY: " << beY << std::endl; -#endif - - if (beY == BE_Y_UNKNOWN) - { -#ifdef DEBUG_MSG_TYPE - std::cerr << "bsMsgType() UNKNOWN MSG TYPE" << std::endl; -#endif - - return BITDHT_MSG_TYPE_UNKNOWN; - } - - if (beY == BE_Y_Q) /* query */ - { -#ifdef DEBUG_MSG_TYPE - std::cerr << "bsMsgType() QUERY MSG TYPE" << std::endl; -#endif - be_node *query = beMsgGetDictNode(n, "q"); - - if(query == NULL) - return BITDHT_MSG_TYPE_UNKNOWN; - - if (beMsgMatchString(query, "ping", 4)) - { -#ifdef DEBUG_MSG_TYPE - std::cerr << "bsMsgType() QUERY:ping MSG TYPE" << std::endl; -#endif - return BITDHT_MSG_TYPE_PING; - } - else if (beMsgMatchString(query, "find_node", 9)) - { -#ifdef DEBUG_MSG_TYPE - std::cerr << "bsMsgType() QUERY:find_node MSG TYPE" << std::endl; -#endif - return BITDHT_MSG_TYPE_FIND_NODE; - } - else if (beMsgMatchString(query, "get_peers", 9)) - { -#ifdef DEBUG_MSG_TYPE - std::cerr << "bsMsgType() QUERY:get_peers MSG TYPE" << std::endl; -#endif - return BITDHT_MSG_TYPE_GET_HASH; - } - else if (beMsgMatchString(query, "announce_peer", 13)) - { -#ifdef DEBUG_MSG_TYPE - std::cerr << "bsMsgType() QUERY:announce_peer MSG TYPE" << std::endl; -#endif - return BITDHT_MSG_TYPE_POST_HASH; - } - else if (beMsgMatchString(query, "connect", 7)) - { -#ifdef DEBUG_MSG_TYPE - std::cerr << "bsMsgType() QUERY:connect MSG TYPE" << std::endl; -#endif - return BITDHT_MSG_TYPE_CONNECT; - } -#ifdef DEBUG_MSG_TYPE - std::cerr << "bsMsgType() QUERY:UNKNOWN MSG TYPE, dumping dict" << std::endl; - /* dump answer */ - be_dump(n); -#endif - return BITDHT_MSG_TYPE_UNKNOWN; - } - - if (beY != BE_Y_R) - { -#ifdef DEBUG_MSG_TYPE - std::cerr << "bsMsgType() UNKNOWN2 MSG TYPE" << std::endl; -#endif - return BITDHT_MSG_TYPE_UNKNOWN; - } - -#ifdef DEBUG_MSG_TYPE - std::cerr << "bsMsgType() REPLY MSG TYPE" << std::endl; -#endif - - /* otherwise a reply or - invalid - pong {"id":"mnopqrstuvwxyz123456"} - reply_neigh { "id":"0123456789abcdefghij", "nodes": "def456..."}} - reply_hash { "id":"abcdefghij0123456789", "token":"aoeusnth", "values": ["axje.u", "idhtnm"]}} - reply_near { "id":"abcdefghij0123456789", "token":"aoeusnth", "nodes": "def456..."} - */ - - be_node *reply = beMsgGetDictNode(n, "r"); - if (!reply) - { - return BITDHT_MSG_TYPE_UNKNOWN; - } - - be_node *id = beMsgGetDictNode(reply, "id"); - be_node *token = beMsgGetDictNode(reply, "token"); - be_node *values = beMsgGetDictNode(reply, "values"); - be_node *nodes = beMsgGetDictNode(reply, "nodes"); - - if (!id) - { - return BITDHT_MSG_TYPE_UNKNOWN; - } - - if (token && values) - { - /* reply hash */ - return BITDHT_MSG_TYPE_REPLY_HASH; - } - else if (token && nodes) - { - /* reply near */ - return BITDHT_MSG_TYPE_REPLY_NEAR; - } - else if (nodes) - { - /* reply neigh */ - return BITDHT_MSG_TYPE_REPLY_NODE; - } - else - { - /* pong */ - return BITDHT_MSG_TYPE_PONG; - } - /* TODO reply_post */ - //return BITDHT_MSG_TYPE_REPLY_POST; - /* can't get here! */ - return BITDHT_MSG_TYPE_UNKNOWN; -} - -/* extract specific types here */ - -int beMsgGetToken(be_node *n, bdToken &token) -{ - if (n->type != BE_STR) - { - return 0; - } - int len = be_str_len(n); - - if(len > BITDHT_TOKEN_MAX_LEN) - return 0 ; - - for(int i = 0; i < len; i++) - { - token.data[i] = n->val.s[i]; - } - token.len = len; - return 1; -} - -int beMsgGetNodeId(be_node *n, bdNodeId &nodeId) -{ - if (n->type != BE_STR) - { - return 0; - } - int len = be_str_len(n); - if (len != BITDHT_KEY_LEN) - { - return 0; - } - for(int i = 0; i < len; i++) - { - nodeId.data[i] = n->val.s[i]; - } - return 1; -} - -be_node *makeCompactNodeIdString(std::list &nodes) -{ - int len = BITDHT_COMPACTNODEID_LEN * nodes.size(); - std::string cni; - std::list::iterator it; - for(it = nodes.begin(); it != nodes.end(); it++) - { - cni += encodeCompactNodeId(&(*it)); - } - - - be_node *cninode = be_create_str_wlen((char *) cni.c_str(), len); - return cninode; -} - -be_node *makeCompactPeerIds(std::list &values) -{ - be_node *valuesnode = be_create_list(); - std::list::iterator it; - for(it = values.begin(); it != values.end(); it++) - { - be_node *val1 = be_create_str_wlen((char *) it->c_str(), it->length()); - be_add_list(valuesnode, val1); - } - return valuesnode; -} - - -int beMsgGetListBdIds(be_node *n, std::list &nodes) -{ - /* extract the string pointer, and size */ - /* split into parts */ - - if (n->type != BE_STR) - { - return 0; - } - - int len = be_str_len(n); - int count = len / BITDHT_COMPACTNODEID_LEN; - for(int i = 0; i < count; i++) - { - bdId id; - if (decodeCompactNodeId(&id, &(n->val.s[i*BITDHT_COMPACTNODEID_LEN]), BITDHT_COMPACTNODEID_LEN)) - { - nodes.push_back(id); - } - } - return 1; -} - -int beMsgGetBdId(be_node *n, bdId &id) -{ - /* extract the string pointer, and size */ - /* split into parts */ - - if (n->type != BE_STR) - { - return 0; - } - - int len = be_str_len(n); - if (len < BITDHT_COMPACTNODEID_LEN) - { - return 0; - } - if (decodeCompactNodeId(&id, n->val.s, BITDHT_COMPACTNODEID_LEN)) - { - return 1; - } - return 0; -} - -std::string encodeCompactNodeId(bdId *id) -{ - std::string enc; - for(int i = 0; i < BITDHT_KEY_LEN; i++) - { - enc += id->id.data[i]; - } - /* convert ip address (already in network order) */ - enc += encodeCompactPeerId(&(id->addr)); - return enc; -} - -int decodeCompactNodeId(bdId *id, char *enc, int len) -{ - if (len < BITDHT_COMPACTNODEID_LEN) - { - return 0; - } - - for(int i = 0; i < BITDHT_KEY_LEN; i++) - { - id->id.data[i] = enc[i]; - } - - char *ipenc = &(enc[BITDHT_COMPACTNODEID_LEN - BITDHT_COMPACTPEERID_LEN]); - if (!decodeCompactPeerId(&(id->addr), ipenc, BITDHT_COMPACTPEERID_LEN)) - { - return 0; - } - - return 1; -} - -std::string encodeCompactPeerId(struct sockaddr_in *addr) -{ - std::string encstr; - char enc[BITDHT_COMPACTPEERID_LEN]; - uint32_t *ip = (uint32_t *) (enc); - uint16_t *port = (uint16_t *) (&enc[4]); - (*ip) = addr->sin_addr.s_addr; - (*port) = addr->sin_port; - - encstr.append(enc, BITDHT_COMPACTPEERID_LEN); - return encstr; -} - -int decodeCompactPeerId(struct sockaddr_in *addr, char *enc, int len) -{ - if (len < BITDHT_COMPACTPEERID_LEN) - return 0; - - memset(addr, 0, sizeof(struct sockaddr_in)); - - //uint32_t *ip = (uint32_t *) (enc); - uint16_t *port = (uint16_t *) (&enc[4]); - - memcpy(& addr->sin_addr.s_addr, enc, sizeof(in_addr_t)); // aligned version of "addr->sin_addr.s_addr = (*ip); " - addr->sin_port = (*port); - addr->sin_family = AF_INET; - - return 1; -} - - -int beMsgGetListStrings(be_node *n, std::list &values) -{ - if (n->type != BE_LIST) - { - return 0; - } - for(int i = 0; n->val.l[i] != NULL; i++) - { - be_node *val = n->val.l[i]; - - if (val == NULL || val->type != BE_STR) - return 0; - - int len = be_str_len(val); - std::string str; - str.append(val->val.s, len); - values.push_back(str); - } - return 1; -} - - -int beMsgGetUInt32(be_node *n, uint32_t *port) -{ - if (n->type != BE_INT) - { - return 0; - } - *port = n->val.i; - return 1; -} - - - - - - - -/******************************************************************************************************************** - * CONNECTION EXTENSIONS - * - */ - - /* -ping Query = {"t":"aa", "y":"q", "q":"ping", "a":{"id":"abcdefghij0123456789"}} -bencoded = d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe - */ - - /* -Response = {"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"}} -bencoded = d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re - */ - - /* -find_node Query = {"t":"aa", "y":"q", "q":"find_node", "a": {"id":"abcdefghij0123456789", "target":"mnopqrstuvwxyz123456"}} -bencoded = d1:ad2:id20:abcdefghij01234567896:target20:mnopqrstuvwxyz123456e1:q9:find_node1:t2:aa1:y1:qe - */ - -#if 0 -int bitdht_find_node_msg(bdToken *tid, bdNodeId *id, bdNodeId *target, - char *msg, int avail) -{ -#ifdef DEBUG_MSGS - fprintf(stderr, "bitdht_find_node_msg()\n"); -#endif - - be_node *dict = be_create_dict(); - - be_node *iddict = be_create_dict(); - be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); - be_node *targetnode = be_create_str_wlen((char *) target->data, BITDHT_KEY_LEN); - - be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); - be_node *yqrnode = be_create_str("q"); - be_node *findnode = be_create_str("find_node"); - - be_add_keypair(iddict, "id", idnode); - be_add_keypair(iddict, "target", targetnode); - be_add_keypair(dict, "a", iddict); - - be_add_keypair(dict, "t", tidnode); - be_add_keypair(dict, "y", yqrnode); - be_add_keypair(dict, "q", findnode); - -#ifdef DEBUG_MSG_DUMP - /* dump answer */ - be_dump(dict); -#endif - - int blen = be_encode(dict, msg, avail); - be_free(dict); - - return blen; -} -#endif - -/**** - * Thinking about the format of this message. - * id: ownId is stanard in all other messages, so should keep the same!. - * src: - * target: - * mode: d,p or r - * - * A -> B -> C - * direct: A ------> B - * ---> id:A src:A target:B mode:d - * <--- id:B src:A target:B mode:d a:OK - * - * proxy: A ------> B -------> C - * A->B id:A src:A target:C mode:p q - * - * a) - * B->A id:B src:A target:C mode:p r:NOK - * - * b) - * B->C id:B src:A target:C mode:p q - * C->B id:C src:A target:C mode:p r:NOK - * B->A id:B src:A target:C mode:p r:NOK - * - * c) - * B->C id:B src:A target:C mode:p q - * C->B id:C src:A target:C mode:p r:OK - * B->A id:B src:A target:C mode:p r:OK - * connect happens. - * Dropped packets will affect this! - * - * - * REQUIRED BITS FOR A MESSAGE - * 1) DIRECT - * -> REQUEST, ownId, targetId, transId, mode. - * -> RESPONSE, ownId, targetId, transId, mode, answer. - * - * 2) PROXY - */ - - -int bitdht_connect_genmsg(bdToken *tid, bdNodeId *id, int msgtype, bdId *src, bdId *dest, int mode, int param, int status, char *msg, int avail) -{ -#ifdef DEBUG_MSGS - fprintf(stderr, "bitdht_connect_genmsg()\n"); -#endif - - be_node *dict = be_create_dict(); - - be_node *iddict = be_create_dict(); - - be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); - - std::string srcEnc = encodeCompactNodeId(src); - std::string destEnc = encodeCompactNodeId(dest); - - be_node *srcnode = be_create_str_wlen(srcEnc.c_str(), BITDHT_COMPACTNODEID_LEN); - be_node *destnode = be_create_str_wlen(destEnc.c_str(), BITDHT_COMPACTNODEID_LEN); - be_node *typenode = be_create_int(msgtype); - be_node *statusnode = be_create_int(status); - be_node *modenode = be_create_int(mode); - be_node *paramnode = be_create_int(param); - - be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); - be_node *yqrnode = be_create_str("q"); - be_node *cmdnode = be_create_str("connect"); - - be_add_keypair(iddict, "id", idnode); - be_add_keypair(iddict, "src", srcnode); - be_add_keypair(iddict, "dest", destnode); - be_add_keypair(iddict, "mode", modenode); - be_add_keypair(iddict, "param", paramnode); - be_add_keypair(iddict, "status", statusnode); - be_add_keypair(iddict, "type", typenode); - - be_add_keypair(dict, "a", iddict); - - be_add_keypair(dict, "t", tidnode); - be_add_keypair(dict, "y", yqrnode); - be_add_keypair(dict, "q", cmdnode); - -#ifdef DEBUG_MSG_DUMP - /* dump answer */ - be_dump(dict); -#endif - - int blen = be_encode(dict, msg, avail); - be_free(dict); - - return blen; -} - - - -bool bitdht_msgtype(uint32_t msg_type, std::string &name) -{ - switch(msg_type) - { - case BITDHT_MSG_TYPE_PING: - name = "PING"; - break; - case BITDHT_MSG_TYPE_PONG: - name = "PONG"; - break; - case BITDHT_MSG_TYPE_FIND_NODE: - name = "FIND_NODE"; - break; - case BITDHT_MSG_TYPE_REPLY_NODE: - name = "REPLY_NODE"; - break; - case BITDHT_MSG_TYPE_GET_HASH: - name = "GET_HASH"; - break; - case BITDHT_MSG_TYPE_REPLY_HASH: - name = "REPLY_HASH"; - break; - case BITDHT_MSG_TYPE_REPLY_NEAR: - name = "REPLY_NEAR"; - break; - case BITDHT_MSG_TYPE_POST_HASH: - name = "POST_HASH"; - break; - case BITDHT_MSG_TYPE_REPLY_POST: - name = "REPLY_POST"; - break; - - case BITDHT_MSG_TYPE_CONNECT: - name = "CONNECT"; - break; - case BITDHT_MSG_TYPE_CONNECT_REQUEST: - name = "CONNECT_REQUEST"; - break; - case BITDHT_MSG_TYPE_CONNECT_REPLY: - name = "CONNECT_REPLY"; - break; - case BITDHT_MSG_TYPE_CONNECT_START: - name = "CONNECT_START"; - break; - case BITDHT_MSG_TYPE_CONNECT_ACK: - name = "CONNECT_ACK"; - break; - default: - name = "UNKNOWN"; - return false; - break; - } - - return true; -} - - - diff --git a/libbitdht/src/bitdht/bdmsgs.h b/libbitdht/src/bitdht/bdmsgs.h deleted file mode 100644 index 99a26d76a..000000000 --- a/libbitdht/src/bitdht/bdmsgs.h +++ /dev/null @@ -1,127 +0,0 @@ -/******************************************************************************* - * bitdht/bdmsgs.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef BITDHT_MSGS_H -#define BITDHT_MSGS_H - -#include -#include -#include -#include "bitdht/bencode.h" -#include "bitdht/bdobj.h" -#include "bitdht/bdpeer.h" - -#define BITDHT_MSG_TYPE_UNKNOWN 0 -#define BITDHT_MSG_TYPE_PING 1 -#define BITDHT_MSG_TYPE_PONG 2 -#define BITDHT_MSG_TYPE_FIND_NODE 3 -#define BITDHT_MSG_TYPE_REPLY_NODE 4 -#define BITDHT_MSG_TYPE_GET_HASH 5 -#define BITDHT_MSG_TYPE_REPLY_HASH 6 -#define BITDHT_MSG_TYPE_REPLY_NEAR 7 -#define BITDHT_MSG_TYPE_POST_HASH 8 -#define BITDHT_MSG_TYPE_REPLY_POST 9 - - - -// THESE ARE EXTENSIONS -#define BITDHT_MSG_TYPE_CONNECT 20 - -// CONNECTIONS. -#define BITDHT_MSG_TYPE_CONNECT_REQUEST 101 -#define BITDHT_MSG_TYPE_CONNECT_REPLY 102 -#define BITDHT_MSG_TYPE_CONNECT_START 103 -#define BITDHT_MSG_TYPE_CONNECT_ACK 104 - -// FANCY HASHES. - - -#define BITDHT_COMPACTNODEID_LEN 26 -#define BITDHT_COMPACTPEERID_LEN 6 - -#define BE_Y_UNKNOWN 0 -#define BE_Y_R 1 -#define BE_Y_Q 2 - - -/****** Known BD Version Strings ******/ - -#define BITDHT_VID_RS1 1 -#define BITDHT_VID_UT 2 - - -int bitdht_create_ping_msg(bdToken *tid, bdNodeId *id, bdToken *vid, char *msg, int avail); -int bitdht_response_ping_msg(bdToken *tid, bdNodeId *id, bdToken *vid, char *msg, int avail); -int bitdht_find_node_msg(bdToken *tid, bdNodeId *id, bdNodeId *target, bool localnet, char *msg, int avail); -int bitdht_resp_node_msg(bdToken *tid, bdNodeId *id, std::list &nodes, - char *msg, int avail); -int bitdht_get_peers_msg(bdToken *tid, bdNodeId *id, bdNodeId *info_hash, - char *msg, int avail); -int bitdht_peers_reply_hash_msg(bdToken *tid, bdNodeId *id, - bdToken *token, std::list &values, - char *msg, int avail); -int bitdht_peers_reply_closest_msg(bdToken *tid, bdNodeId *id, - bdToken *token, std::list &nodes, - char *msg, int avail); -int bitdht_announce_peers_msg(bdToken *tid, bdNodeId *id, bdNodeId *info_hash, - uint32_t port, bdToken *token, char *msg, int avail); -int bitdht_reply_announce_msg(bdToken *tid, bdNodeId *id, - char *msg, int avail); - - -// Extensions. -int bitdht_connect_genmsg(bdToken *tid, bdNodeId *id, int msgtype, bdId *src, bdId *dest, int mode, int param, int status, char *msg, int avail); - - -//int response_peers_message() -//int response_closestnodes_message() - -be_node *beMsgGetDictNode(be_node *node, const char *key); -int beMsgMatchString(be_node *n, const char *str, int len); -uint32_t beMsgGetY(be_node *n); -uint32_t beMsgType(be_node *n); - -bool bitdht_msgtype(uint32_t msg_type, std::string &name); - - -uint32_t convertBdVersionToVID(bdVersion *version); - -be_node *makeCompactPeerIds(std::list &values); -be_node *makeCompactNodeIdString(std::list &nodes); - -int beMsgGetToken(be_node *n, bdToken &token); -int beMsgGetNodeId(be_node *n, bdNodeId &nodeId); -int beMsgGetBdId(be_node *n, bdId &id); -int beMsgGetListBdIds(be_node *n, std::list &nodes); - -int beMsgGetListStrings(be_node *n, std::list &values); -int beMsgGetUInt32(be_node *n, uint32_t *port); - -/* Low Level conversion functions */ -int decodeCompactPeerId(struct sockaddr_in *addr, char *enc, int len); -std::string encodeCompactPeerId(struct sockaddr_in *addr); - -int decodeCompactNodeId(bdId *id, char *enc, int len); -std::string encodeCompactNodeId(bdId *id); - - - -#endif diff --git a/libbitdht/src/bitdht/bdnode.cc b/libbitdht/src/bitdht/bdnode.cc deleted file mode 100644 index 5d3e4fd25..000000000 --- a/libbitdht/src/bitdht/bdnode.cc +++ /dev/null @@ -1,2478 +0,0 @@ -/******************************************************************************* - * bitdht/bdnode.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "bitdht/bdnode.h" - -#include "bitdht/bencode.h" -#include "bitdht/bdmsgs.h" - -#include "bitdht/bdquerymgr.h" -#include "bitdht/bdfilter.h" - -#include "util/bdnet.h" -#include "util/bdrandom.h" -#include "util/bdstring.h" - -#include -#include - -#include -#include - - -#define BITDHT_QUERY_START_PEERS 10 -#define BITDHT_QUERY_NEIGHBOUR_PEERS 8 - -#define BITDHT_MAX_REMOTE_QUERY_AGE 3 // 3 seconds, keep it fresh. -#define MAX_REMOTE_PROCESS_PER_CYCLE 5 - -/**** - * #define USE_HISTORY 1 - * - * #define DEBUG_NODE_MULTIPEER 1 - * #define DEBUG_NODE_PARSE 1 - - * #define DEBUG_NODE_MSGS 1 - * #define DEBUG_NODE_ACTIONS 1 - - * #define DEBUG_NODE_MSGIN 1 - * #define DEBUG_NODE_MSGOUT 1 - * - * #define DISABLE_BAD_PEER_FILTER 1 - * - ***/ - -//#define DISABLE_BAD_PEER_FILTER 1 - -//#define USE_HISTORY 1 - -#define HISTORY_PERIOD 60 - -bdNode::bdNode(bdNodeId *ownId, std::string dhtVersion, const std::string& bootfile, const std::string &bootfilebak, const std::string& filterfile, bdDhtFunctions *fns, bdNodeManager *manager) - :mNodeSpace(ownId, fns), - mFilterPeers(filterfile,ownId, BITDHT_FILTER_REASON_OWNID, fns, manager), - mQueryMgr(NULL), - mConnMgr(NULL), - mOwnId(*ownId), mDhtVersion(dhtVersion), mStore(bootfile, bootfilebak, fns), mFns(fns), - mFriendList(ownId), mHistory(HISTORY_PERIOD) -{ - init(); /* (uses this pointers) stuff it - do it here! */ -} - -void bdNode::init() -{ - mQueryMgr = new bdQueryManager(&mNodeSpace, mFns, this); - mConnMgr = new bdConnectManager(&mOwnId, &mNodeSpace, mQueryMgr, mFns, this); - - //setNodeOptions(BITDHT_OPTIONS_MAINTAIN_UNSTABLE_PORT); - setNodeOptions(0); - - mNodeDhtMode = 0; - setNodeDhtMode(BITDHT_MODE_TRAFFIC_DEFAULT); - -} -bool bdNode::getFilteredPeers(std::list& peers) -{ - mFilterPeers.getFilteredPeers(peers) ; - return true ; -} -// -//void bdNode::loadFilteredPeers(const std::list& peers) -//{ -// mFilterPeers.loadFilteredPeers(peers) ; -//} -/* Unfortunately I've ended up with 2 calls down through the heirarchy... - * not ideal - must clean this up one day. - */ - -#define ATTACH_NUMBER 5 -void bdNode::setNodeOptions(uint32_t optFlags) -{ - mNodeOptionFlags = optFlags; - if (optFlags & BITDHT_OPTIONS_MAINTAIN_UNSTABLE_PORT) - { - mNodeSpace.setAttachedFlag(BITDHT_PEER_STATUS_DHT_ENGINE | BITDHT_PEER_STATUS_DHT_ENGINE_VERSION, ATTACH_NUMBER); - } - else - { - mNodeSpace.setAttachedFlag(BITDHT_PEER_STATUS_DHT_ENGINE | BITDHT_PEER_STATUS_DHT_ENGINE_VERSION, 0); - } -} - -#define BDNODE_HIGH_MSG_RATE 50 -#define BDNODE_MED_MSG_RATE 10 -#define BDNODE_LOW_MSG_RATE 5 -#define BDNODE_TRICKLE_MSG_RATE 3 - -/* So we are setting this up so you can independently update each parameter.... - * if the mask is empty - it'll use the previous parameter. - * - */ - - -uint32_t bdNode::setNodeDhtMode(uint32_t dhtFlags) -{ - std::cerr << "bdNode::setNodeDhtMode(" << dhtFlags << "), origFlags: " << mNodeDhtMode; - std::cerr << std::endl; - - uint32_t origFlags = mNodeDhtMode; - - - uint32_t traffic = dhtFlags & BITDHT_MODE_TRAFFIC_MASK; - if (traffic) - { - switch(traffic) - { - default: - case BITDHT_MODE_TRAFFIC_LOW: - mMaxAllowedMsgs = BDNODE_LOW_MSG_RATE; - break; - case BITDHT_MODE_TRAFFIC_MED: - mMaxAllowedMsgs = BDNODE_MED_MSG_RATE; - break; - case BITDHT_MODE_TRAFFIC_HIGH: - mMaxAllowedMsgs = BDNODE_HIGH_MSG_RATE; - break; - case BITDHT_MODE_TRAFFIC_TRICKLE: - mMaxAllowedMsgs = BDNODE_TRICKLE_MSG_RATE; - break; - } - } - else - { - dhtFlags |= (origFlags & BITDHT_MODE_TRAFFIC_MASK); - } - - uint32_t relay = dhtFlags & BITDHT_MODE_RELAYSERVER_MASK; - if ((relay) && (relay != (origFlags & BITDHT_MODE_RELAYSERVER_MASK))) - { - /* changed */ - switch(relay) - { - default: - case BITDHT_MODE_RELAYSERVERS_IGNORED: - mRelayMode = BITDHT_RELAYS_OFF; - dropRelayServers(); - break; - case BITDHT_MODE_RELAYSERVERS_FLAGGED: - mRelayMode = BITDHT_RELAYS_ON; - pingRelayServers(); - break; - case BITDHT_MODE_RELAYSERVERS_ONLY: - mRelayMode = BITDHT_RELAYS_ONLY; - pingRelayServers(); - break; - case BITDHT_MODE_RELAYSERVERS_SERVER: - mRelayMode = BITDHT_RELAYS_SERVER; - pingRelayServers(); - break; - } - mConnMgr->setRelayMode(mRelayMode); - } - else - { - dhtFlags |= (origFlags & BITDHT_MODE_RELAYSERVER_MASK); - } - - mNodeDhtMode = dhtFlags; - - std::cerr << "bdNode::setNodeDhtMode() newFlags: " << mNodeDhtMode; - std::cerr << std::endl; - - return dhtFlags; -} - - -void bdNode::getOwnId(bdNodeId *id) -{ - *id = mOwnId; -} - -/***** Startup / Shutdown ******/ -void bdNode::restartNode() -{ - mAccount.resetStats(); - - mStore.reloadFromStore(); - - /* setup */ - bdPeer peer; - while(mStore.getPeer(&peer)) - { - addPotentialPeer(&(peer.mPeerId), NULL); - } -} - - -void bdNode::shutdownNode() -{ - /* clear the queries */ - mQueryMgr->shutdownQueries(); - mConnMgr->shutdownConnections(); - - mRemoteQueries.clear(); - - /* clear the space */ - mNodeSpace.clear(); - mHashSpace.clear(); - - /* clear other stuff */ - mPotentialPeers.clear(); - mStore.clear(); - - /* clean up any outgoing messages */ - while(mOutgoingMsgs.size() > 0) - { - bdNodeNetMsg *msg = mOutgoingMsgs.front(); - mOutgoingMsgs.pop_front(); - - /* cleanup message */ - delete msg; - } -} - - -/* Crappy initial store... use bdspace as answer */ -void bdNode::updateStore() -{ - mStore.writeStore(); -} - -bool bdNode::addressBanned(const sockaddr_in& raddr) -{ - return !mFilterPeers.addrOkay(const_cast(&raddr)) ; -} - -void bdNode::printState() -{ - std::cerr << "bdNode::printState() for Peer: "; - mFns->bdPrintNodeId(std::cerr, &mOwnId); - std::cerr << std::endl; - - mNodeSpace.printDHT(); - - mQueryMgr->printQueries(); - mConnMgr->printConnections(); - - std::cerr << "Outstanding Potential Peers: " << mPotentialPeers.size(); - std::cerr << std::endl; - -#ifdef USE_HISTORY - mHistory.cleanupOldMsgs(); - mHistory.printMsgs(); - mHistory.analysePeers(); - mHistory.peerTypeAnalysis(); - - // Incoming Query Analysis. - std::cerr << "Outstanding Query Requests: " << mRemoteQueries.size(); - std::cerr << std::endl; - - mQueryHistory.printMsgs(); -#endif - - mAccount.printStats(std::cerr); -} - -void bdNode::iterationOff() -{ - /* clean up any incoming messages */ - while(mIncomingMsgs.size() > 0) - { - bdNodeNetMsg *msg = mIncomingMsgs.front(); - mIncomingMsgs.pop_front(); - - /* cleanup message */ - delete msg; - } -} - -void bdNode::iteration() -{ -#ifdef DEBUG_NODE_MULTIPEER - std::cerr << "bdNode::iteration() of Peer: "; - mFns->bdPrintNodeId(std::cerr, &mOwnId); - std::cerr << std::endl; -#endif - - /* process incoming msgs */ - while(mIncomingMsgs.size() > 0) - { - bdNodeNetMsg *msg = mIncomingMsgs.front(); - mIncomingMsgs.pop_front(); - - recvPkt(msg->data, msg->mSize, msg->addr); - - /* cleanup message */ - delete msg; - } - - - /* assume that this is called once per second... limit the messages - * in theory, a query can generate up to 10 peers (which will all require a ping!). - * we want to handle all the pings we can... so we don't hold up the process. - * but we also want enough queries to keep things moving. - * so allow up to 90% of messages to be pings. - * - * ignore responses to other peers... as the number is very small generally - * - * The Rate IS NOW DEFINED IN NodeDhtMode. - */ - - int allowedPings = 0.9 * mMaxAllowedMsgs; - int sentMsgs = 0; - int sentPings = 0; - -#define BDNODE_MAX_POTENTIAL_PEERS_MULTIPLIER 5 - - /* Disable Queries if our Ping Queue is too long */ - if (mPotentialPeers.size() > mMaxAllowedMsgs * BDNODE_MAX_POTENTIAL_PEERS_MULTIPLIER) - { -#ifdef DEBUG_NODE_MULTIPEER - std::cerr << "bdNode::iteration() Disabling Queries until PotentialPeer Queue reduced"; - std::cerr << std::endl; -#endif - allowedPings = mMaxAllowedMsgs; - } - - - while((mPotentialPeers.size() > 0) && (sentMsgs < allowedPings)) - { - /* check history ... is we have pinged them already... - * then simulate / pretend we have received a pong, - * and don't bother sending another ping. - */ - - bdId pid = mPotentialPeers.front(); - mPotentialPeers.pop_front(); - - - /* don't send too many queries ... check history first */ -#if 0 -#ifdef USE_HISTORY - if (mHistory.validPeer(&pid)) - { - /* just add as peer */ - -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::iteration() Pinging Known Potential Peer : "; - mFns->bdPrintId(std::cerr, &pid); - std::cerr << std::endl; -#endif - - } -#endif -#endif - - /**** TEMP ****/ - - { - send_ping(&pid); - - sentMsgs++; - sentPings++; - -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::iteration() Pinging Potential Peer : "; - mFns->bdPrintId(std::cerr, &pid); - std::cerr << std::endl; -#endif - - } - - } - - /* allow each query to send up to one query... until maxMsgs has been reached */ - int sentQueries = mQueryMgr->iterateQueries(mMaxAllowedMsgs-sentMsgs); - sentMsgs += sentQueries; - - -#ifdef DEBUG_NODE_ACTIONS - std::cerr << "bdNode::iteration() maxMsgs: " << maxMsgs << " sentPings: " << sentPings; - std::cerr << " / " << allowedPings; - std::cerr << " sentQueries: " << sentQueries; - std::cerr << std::endl; -#endif - - /* process remote query too */ - processRemoteQuery(); - - std::list peerIds; - std::list::iterator oit; - mNodeSpace.scanOutOfDatePeers(peerIds); - - for(oit = peerIds.begin(); oit != peerIds.end(); oit++) - { - send_ping(&(*oit)); - mAccount.incCounter(BDACCOUNT_MSG_OUTOFDATEPING, true); - -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::iteration() Pinging Out-Of-Date Peer: "; - mFns->bdPrintId(std::cerr, &(*oit)); - std::cerr << std::endl; -#endif - } - - // Handle Connection loops. - mConnMgr->tickConnections(); - - mAccount.doStats(); -} - - - -/*************************************************************************************** - *************************************************************************************** - ***************************************************************************************/ - -void bdNode::send_ping(bdId *id) -{ - bdToken transId; - genNewTransId(&transId); - - msgout_ping(id, &transId); -} - - -void bdNode::send_query(bdId *id, bdNodeId *targetNodeId, bool localnet) -{ - /* push out query */ - bdToken transId; - genNewTransId(&transId); - - msgout_find_node(id, &transId, targetNodeId, localnet); - -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::send_query() Find Node Req for : "; - mFns->bdPrintId(std::cerr, &id); - std::cerr << " searching for : "; - mFns->bdPrintNodeId(std::cerr, &targetNodeId); - std::cerr << std::endl; -#endif -} - - -void bdNode::send_connect_msg(bdId *id, int msgtype, bdId *srcAddr, bdId *destAddr, int mode, int param, int status) -{ - /* push out query */ - bdToken transId; - genNewTransId(&transId); - - msgout_connect_genmsg(id, &transId, msgtype, srcAddr, destAddr, mode, param, status); - -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::send_connect_msg() to: "; - mFns->bdPrintId(std::cerr, &id); - std::cerr << std::endl; -#endif -} - - -void bdNode::checkPotentialPeer(bdId *id, bdId *src) -{ - /* Check BadPeer Filters for Potential Peers too */ - - /* first check the filters */ - if (!mFilterPeers.addrOkay(&(id->addr))) - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::checkPotentialPeer("; - mFns->bdPrintId(std::cerr, id); - std::cerr << ") BAD ADDRESS!!!! SHOULD DISCARD POTENTIAL PEER"; - std::cerr << std::endl; -#endif - - return; - } - - /* is it masquarading? */ - bdFriendEntry entry; - if (mFriendList.findPeerEntry(&(id->id), entry)) - { - struct sockaddr_in knownAddr; - if (entry.addrKnown(&knownAddr)) - { - if (knownAddr.sin_addr.s_addr != id->addr.sin_addr.s_addr) - { -#ifndef DISABLE_BAD_PEER_FILTER - std::cerr << "bdNode::checkPotentialPeer("; - mFns->bdPrintId(std::cerr, id); - std::cerr << ") MASQUERADING AS KNOWN PEER - FLAGGING AS BAD"; - std::cerr << std::endl; - - // Stores in queue for later callback and desemination around the network. - mBadPeerQueue.queuePeer(id, 0); - - mFilterPeers.addPeerToFilter(id->addr, 0); - - std::list filteredIPs; - mFilterPeers.filteredIPs(filteredIPs); - mStore.filterIpList(filteredIPs); - - return; -#endif - } - } - } - - bool isWorthyPeer = mQueryMgr->checkPotentialPeer(id, src); - - if (isWorthyPeer) - { - addPotentialPeer(id, src); - - } - - if (src) // src can be NULL! - { - mConnMgr->addPotentialConnectionProxy(src, id); // CAUTION: Order switched! - } - -} - - -void bdNode::addPotentialPeer(bdId *id, bdId * /*src*/) -{ - mPotentialPeers.push_back(*id); -} - - // virtual so manager can do callback. - // peer flags defined in bdiface.h -void bdNode::addPeer(const bdId *id, uint32_t peerflags) -{ - -#ifdef DEBUG_NODE_ACTIONS - fprintf(stderr, "bdNode::addPeer("); - mFns->bdPrintId(std::cerr, id); - fprintf(stderr, ")\n"); -#endif - - /* first check the filters */ - if (mFilterPeers.checkPeer(id, peerflags)) - { - std::cerr << "bdNode::addPeer("; - mFns->bdPrintId(std::cerr, id); - std::cerr << ", " << std::hex << peerflags << std::dec; - std::cerr << ") FAILED the BAD PEER FILTER!!!! DISCARDING MSG"; - std::cerr << std::endl; - - std::list filteredIPs; - mFilterPeers.filteredIPs(filteredIPs); - mStore.filterIpList(filteredIPs); - - mBadPeerQueue.queuePeer(id, peerflags); - - return; - } - - /* next we check if it is a friend, whitelist etc, and adjust flags */ - bdFriendEntry entry; - - if (mFriendList.findPeerEntry(&(id->id), entry)) - { - /* found! */ - peerflags |= entry.getPeerFlags(); // translates internal into general ones. - - struct sockaddr_in knownAddr; - if (entry.addrKnown(&knownAddr)) - { - if (knownAddr.sin_addr.s_addr != id->addr.sin_addr.s_addr) - { -#ifndef DISABLE_BAD_PEER_FILTER - std::cerr << "bdNode::addPeer("; - mFns->bdPrintId(std::cerr, id); - std::cerr << ", " << std::hex << peerflags << std::dec; - std::cerr << ") MASQUERADING AS KNOWN PEER - FLAGGING AS BAD"; - std::cerr << std::endl; - - - // Stores in queue for later callback and desemination around the network. - mBadPeerQueue.queuePeer(id, peerflags); - - mFilterPeers.addPeerToFilter(id->addr, peerflags); - - std::list filteredIPs; - mFilterPeers.filteredIPs(filteredIPs); - mStore.filterIpList(filteredIPs); - - // DO WE EXPLICITLY NEED TO DO THIS, OR WILL THEY JUST BE DROPPED? - //mNodeSpace.remove_badpeer(id); - //mQueryMgr->remove_badpeer(id); - - // FLAG in NodeSpace (Should be dropped very quickly anyway) - mNodeSpace.flagpeer(id, 0, BITDHT_PEER_EXFLAG_BADPEER); - - return; -#endif - } - } - } - - mQueryMgr->addPeer(id, peerflags); - mNodeSpace.add_peer(id, peerflags); - - bdPeer peer; - peer.mPeerId = *id; - peer.mPeerFlags = peerflags; - peer.mLastRecvTime = time(NULL); - mStore.addStore(&peer); - - // Finally we pass to connections for them to use. - mConnMgr->updatePotentialConnectionProxy(id, peerflags); - - -//#define DISPLAY_BITDHTNODES 1 -#ifdef DISPLAY_BITDHTNODES - /* TEMP to extract IDS for BloomFilter */ - if (peerflags & BITDHT_PEER_STATUS_DHT_ENGINE) - { - std::cerr << "bdNode::addPeer() FOUND BITDHT PEER"; - std::cerr << std::endl; - mFns->bdPrintNodeId(std::cerr, &(id->id)); - std::cerr << std::endl; - } -#endif -} - -/************************************ Process Remote Query *************************/ - -/* increased the allowed processing rate from 1/sec => 5/sec */ -void bdNode::processRemoteQuery() -{ - int nProcessed = 0; - time_t oldTS = time(NULL) - BITDHT_MAX_REMOTE_QUERY_AGE; - while(nProcessed < MAX_REMOTE_PROCESS_PER_CYCLE) - { - /* extra exit clause */ - if (mRemoteQueries.size() < 1) - { -#ifdef USE_HISTORY - if (nProcessed) - { - mQueryHistory.cleanupOldMsgs(); - } -#endif - return; - } - - bdRemoteQuery &query = mRemoteQueries.front(); - - // filtering. - bool badPeer = false; -#ifdef USE_HISTORY - // store result in badPeer to activate the filtering. - mQueryHistory.addIncomingQuery(query.mQueryTS, &(query.mId), &(query.mQuery)); -#endif - - /* discard older ones (stops queue getting overloaded) */ - if ((query.mQueryTS > oldTS) && (!badPeer)) - { - /* recent enough to process! */ - nProcessed++; - - switch(query.mQueryType) - { - case BD_QUERY_NEIGHBOURS: - case BD_QUERY_LOCALNET: - { - /* search bdSpace for neighbours */ - - std::list nearList; - std::multimap nearest; - std::multimap::iterator it; - - if (query.mQueryType == BD_QUERY_LOCALNET) - { - std::list excludeList; - mNodeSpace.find_nearest_nodes_with_flags(&(query.mQuery), - BITDHT_QUERY_NEIGHBOUR_PEERS, - excludeList, nearest, BITDHT_PEER_STATUS_DHT_APPL); - } - else - { - if (mRelayMode == BITDHT_RELAYS_SERVER) - { - std::list excludeList; - mNodeSpace.find_nearest_nodes_with_flags(&(query.mQuery), - BITDHT_QUERY_NEIGHBOUR_PEERS, - excludeList, nearest, BITDHT_PEER_STATUS_DHT_RELAY_SERVER); - } - else - { - mNodeSpace.find_nearest_nodes(&(query.mQuery), BITDHT_QUERY_NEIGHBOUR_PEERS, nearest); - } - } - - for(it = nearest.begin(); it != nearest.end(); it++) - { - nearList.push_back(it->second); - } - msgout_reply_find_node(&(query.mId), &(query.mTransId), nearList); -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::processRemoteQuery() Reply to Find Node: "; - mFns->bdPrintId(std::cerr, &(query.mId)); - std::cerr << " searching for : "; - mFns->bdPrintNodeId(std::cerr, &(query.mQuery)); - std::cerr << ", found " << nearest.size() << " nodes "; - std::cerr << std::endl; -#endif - - break; - } - case BD_QUERY_HASH: - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::processRemoteQuery() Reply to Query Node: "; - mFns->bdPrintId(std::cerr, &(query.mId)); - std::cerr << " TODO"; - std::cerr << std::endl; -#endif - - /* TODO */ - /* for now drop */ - /* unprocess! */ - nProcessed--; - break; - } - default: - { - /* drop */ - /* unprocess! */ - nProcessed--; - break; - } - } - - - - } - else - { - if (badPeer) - { - std::cerr << "bdNode::processRemoteQuery() Query from BadPeer: Discarding: "; - } -#ifdef DEBUG_NODE_MSGS - else - { - std::cerr << "bdNode::processRemoteQuery() Query Too Old: Discarding: "; - } -#endif -#ifdef DEBUG_NODE_MSGS - mFns->bdPrintId(std::cerr, &(query.mId)); - std::cerr << std::endl; -#endif - } - - mRemoteQueries.pop_front(); - - } - -#ifdef USE_HISTORY - mQueryHistory.cleanupOldMsgs(); -#endif -} - - - - - -/************************************ Message Buffering ****************************/ - - /* interaction with outside world */ -int bdNode::outgoingMsg(struct sockaddr_in *addr, char *msg, int *len) -{ - if (mOutgoingMsgs.size() > 0) - { - bdNodeNetMsg *bdmsg = mOutgoingMsgs.front(); - //bdmsg->print(std::cerr); - mOutgoingMsgs.pop_front(); - //bdmsg->print(std::cerr); - - /* truncate if necessary */ - if (bdmsg->mSize < *len) - { - //std::cerr << "bdNode::outgoingMsg space(" << *len << ") msgsize(" << bdmsg->mSize << ")"; - //std::cerr << std::endl; - *len = bdmsg->mSize; - } - else - { - //std::cerr << "bdNode::outgoingMsg space(" << *len << ") small - trunc from: " - //<< bdmsg->mSize; - //std::cerr << std::endl; - } - - - memcpy(msg, bdmsg->data, *len); - *addr = bdmsg->addr; - - //bdmsg->print(std::cerr); - - delete bdmsg; - return 1; - } - return 0; -} - -void bdNode::incomingMsg(struct sockaddr_in *addr, char *msg, int len) -{ - /* check against the filter */ - if (mFilterPeers.addrOkay(addr)) - { - bdNodeNetMsg *bdmsg = new bdNodeNetMsg(msg, len, addr); - mIncomingMsgs.push_back(bdmsg); - } -#ifdef DEBUG_NODE_MSGOUT - else - { - std::cerr << "bdNode::incomingMsg() Incoming Packet Filtered"; - std::cerr << std::endl; - } -#endif -} - -/************************************ Message Handling *****************************/ - -/* Outgoing Messages */ - -void bdNode::msgout_ping(bdId *id, bdToken *transId) -{ -#ifdef DEBUG_NODE_MSGOUT - std::cerr << "bdNode::msgout_ping() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " To: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - - // THIS IS CRASHING HISTORY. - // LIKELY ID is not always valid! - // Either PotentialPeers or Out-Of-Date Peers. - //registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_PING); - - bdId dupId(*id); - registerOutgoingMsg(&dupId, transId, BITDHT_MSG_TYPE_PING, NULL); - - /* generate message, send to udp */ - bdToken vid; - uint32_t vlen = BITDHT_TOKEN_MAX_LEN; - if (mDhtVersion.size() < vlen) - { - vlen = mDhtVersion.size(); - } - memcpy(vid.data, mDhtVersion.c_str(), vlen); - vid.len = vlen; - - /* create string */ - char msg[10240]; - int avail = 10240; - - int blen = bitdht_create_ping_msg(transId, &(mOwnId), &vid, msg, avail-1); - sendPkt(msg, blen, id->addr); - - mAccount.incCounter(BDACCOUNT_MSG_PING, true); - -} - - -void bdNode::msgout_pong(bdId *id, bdToken *transId) -{ -#ifdef DEBUG_NODE_MSGOUT - std::cerr << "bdNode::msgout_pong() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " Version: " << version; - std::cerr << " To: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - - registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_PONG, NULL); - - /* generate message, send to udp */ - bdToken vid; - uint32_t vlen = BITDHT_TOKEN_MAX_LEN; - if (mDhtVersion.size() < vlen) - { - vlen = mDhtVersion.size(); - } - memcpy(vid.data, mDhtVersion.c_str(), vlen); - vid.len = vlen; - - char msg[10240]; - int avail = 10240; - - int blen = bitdht_response_ping_msg(transId, &(mOwnId), &vid, msg, avail-1); - - sendPkt(msg, blen, id->addr); - - mAccount.incCounter(BDACCOUNT_MSG_PONG, true); - -} - - -void bdNode::msgout_find_node(bdId *id, bdToken *transId, bdNodeId *query, bool localnet) -{ -#ifdef DEBUG_NODE_MSGOUT - std::cerr << "bdNode::msgout_find_node() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " To: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " Query: "; - mFns->bdPrintNodeId(std::cerr, query); - std::cerr << std::endl; -#endif - - registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_FIND_NODE, query); - - - - char msg[10240]; - int avail = 10240; - - int blen = bitdht_find_node_msg(transId, &(mOwnId), query, localnet, msg, avail-1); - - sendPkt(msg, blen, id->addr); - - mAccount.incCounter(BDACCOUNT_MSG_QUERYNODE, true); - -} - -void bdNode::msgout_reply_find_node(bdId *id, bdToken *transId, std::list &peers) -{ - char msg[10240]; - int avail = 10240; - - registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_REPLY_NODE, NULL); - - mAccount.incCounter(BDACCOUNT_MSG_REPLYFINDNODE, true); - - int blen = bitdht_resp_node_msg(transId, &(mOwnId), peers, msg, avail-1); - - sendPkt(msg, blen, id->addr); - -#ifdef DEBUG_NODE_MSGOUT - std::cerr << "bdNode::msgout_reply_find_node() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " To: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " Peers:"; - std::list::iterator it; - for(it = peers.begin(); it != peers.end(); it++) - { - std::cerr << " "; - mFns->bdPrintId(std::cerr, &(*it)); - } - std::cerr << std::endl; -#endif -} - -/***************** - * SECOND HALF - * - *****/ - -void bdNode::msgout_get_hash(bdId *id, bdToken *transId, bdNodeId *info_hash) -{ -#ifdef DEBUG_NODE_MSGOUT - std::cerr << "bdNode::msgout_get_hash() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " To: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " InfoHash: "; - mFns->bdPrintNodeId(std::cerr, info_hash); - std::cerr << std::endl; -#endif - - char msg[10240]; - int avail = 10240; - - registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_GET_HASH, info_hash); - - - int blen = bitdht_get_peers_msg(transId, &(mOwnId), info_hash, msg, avail-1); - - sendPkt(msg, blen, id->addr); - - mAccount.incCounter(BDACCOUNT_MSG_QUERYHASH, true); - -} - -void bdNode::msgout_reply_hash(bdId *id, bdToken *transId, bdToken *token, std::list &values) -{ -#ifdef DEBUG_NODE_MSGOUT - std::cerr << "bdNode::msgout_reply_hash() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " To: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " Token: "; - bdPrintToken(std::cerr, token); - - std::cerr << " Peers: "; - std::list::iterator it; - for(it = values.begin(); it != values.end(); it++) - { - std::cerr << " "; - bdPrintCompactPeerId(std::cerr, *it); - } - std::cerr << std::endl; -#endif - - char msg[10240]; - int avail = 10240; - - registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_REPLY_HASH, NULL); - - int blen = bitdht_peers_reply_hash_msg(transId, &(mOwnId), token, values, msg, avail-1); - - sendPkt(msg, blen, id->addr); - - mAccount.incCounter(BDACCOUNT_MSG_REPLYQUERYHASH, true); - -} - -void bdNode::msgout_reply_nearest(bdId *id, bdToken *transId, bdToken *token, std::list &nodes) -{ -#ifdef DEBUG_NODE_MSGOUT - std::cerr << "bdNode::msgout_reply_nearest() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " To: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " Token: "; - bdPrintToken(std::cerr, token); - std::cerr << " Nodes:"; - - std::list::iterator it; - for(it = nodes.begin(); it != nodes.end(); it++) - { - std::cerr << " "; - mFns->bdPrintId(std::cerr, &(*it)); - } - std::cerr << std::endl; -#endif - - char msg[10240]; - int avail = 10240; - - registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_REPLY_NEAR, NULL); - - - - int blen = bitdht_peers_reply_closest_msg(transId, &(mOwnId), token, nodes, msg, avail-1); - - sendPkt(msg, blen, id->addr); - mAccount.incCounter(BDACCOUNT_MSG_REPLYQUERYHASH, true); - - -} - -void bdNode::msgout_post_hash(bdId *id, bdToken *transId, bdNodeId *info_hash, uint32_t port, bdToken *token) -{ -#ifdef DEBUG_NODE_MSGOUT - std::cerr << "bdNode::msgout_post_hash() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " To: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " Info_Hash: "; - mFns->bdPrintNodeId(std::cerr, info_hash); - std::cerr << " Port: " << port; - std::cerr << " Token: "; - bdPrintToken(std::cerr, token); - std::cerr << std::endl; -#endif - - char msg[10240]; - int avail = 10240; - - registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_POST_HASH, info_hash); - - - int blen = bitdht_announce_peers_msg(transId,&(mOwnId),info_hash,port,token,msg,avail-1); - - sendPkt(msg, blen, id->addr); - mAccount.incCounter(BDACCOUNT_MSG_POSTHASH, true); - - -} - -void bdNode::msgout_reply_post(bdId *id, bdToken *transId) -{ -#ifdef DEBUG_NODE_MSGOUT - std::cerr << "bdNode::msgout_reply_post() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " To: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - - /* generate message, send to udp */ - char msg[10240]; - int avail = 10240; - - registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_REPLY_POST, NULL); - - int blen = bitdht_reply_announce_msg(transId, &(mOwnId), msg, avail-1); - - sendPkt(msg, blen, id->addr); - mAccount.incCounter(BDACCOUNT_MSG_REPLYPOSTHASH, true); - -} - - -void bdNode::sendPkt(char *msg, int len, struct sockaddr_in addr) -{ - //fprintf(stderr, "bdNode::sendPkt(%d) to %s:%d\n", - // len, inet_ntoa(addr.sin_addr), htons(addr.sin_port)); - - /* filter outgoing packets */ - if (mFilterPeers.addrOkay(&addr)) - { - bdNodeNetMsg *bdmsg = new bdNodeNetMsg(msg, len, &addr); - //bdmsg->print(std::cerr); - mOutgoingMsgs.push_back(bdmsg); - //bdmsg->print(std::cerr); - } - else - { - std::cerr << "bdNode::sendPkt() Outgoing Packet Filtered"; - std::cerr << std::endl; - } - - return; -} - - -/********************* Incoming Messages *************************/ -/* - * These functions are holding up udp queue -> so quickly - * parse message, and get on with it! - */ - -void bdNode::recvPkt(char *msg, int len, struct sockaddr_in addr) -{ -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() msg[" << len << "] = "; - for(int i = 0; i < len; i++) - { - if ((msg[i] > 31) && (msg[i] < 127)) - { - std::cerr << msg[i]; - } - else - { - std::cerr << "[" << (int) msg[i] << "]"; - } - } - std::cerr << std::endl; -#endif - - /* convert to a be_node */ - be_node *node = be_decoden(msg, len); - if (!node) - { - /* invalid decode */ -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() Failure to decode. Dropping Msg"; - std::cerr << std::endl; - std::cerr << "message length: " << len; - std::cerr << std::endl; - std::cerr << "msg[] = "; - for(int i = 0; i < len; i++) - { - if ((msg[i] > 31) && (msg[i] < 127)) - { - std::cerr << msg[i]; - } - else - { - std::cerr << "[" << (int) msg[i] << "]"; - } - } - std::cerr << std::endl; -#endif - return; - } - - /* find message type */ - uint32_t beType = beMsgType(node); - bool beQuery = (BE_Y_Q == beMsgGetY(node)); - - if (!beType) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() Invalid Message Type. Dropping Msg"; - std::cerr << std::endl; -#endif - /* invalid message */ - be_free(node); - return; - } - - /************************* handle token (all) **************************/ - be_node *be_transId = beMsgGetDictNode(node, "t"); - bdToken transId; - if (be_transId) - { - beMsgGetToken(be_transId, transId); - } - else - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() TransId Failure. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - - /************************* handle data (all) **************************/ - - /* extract common features */ - char dictkey[2] = "r"; - if (beQuery) - { - dictkey[0] = 'a'; - } - - be_node *be_data = beMsgGetDictNode(node, dictkey); - if (!be_data) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() Missing Data Body. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - - /************************** handle id (all) ***************************/ - be_node *be_id = beMsgGetDictNode(be_data, "id"); - bdNodeId id; - if(!be_id || !beMsgGetNodeId(be_id, id)) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() Missing Peer Id. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - - /************************ handle version (optional:pong) **************/ - be_node *be_version = NULL; - bdToken versionId; - if ((beType == BITDHT_MSG_TYPE_PONG) || (beType == BITDHT_MSG_TYPE_PING)) - { - be_version = beMsgGetDictNode(node, "v"); - if (!be_version) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() NOTE: PONG missing Optional Version."; - std::cerr << std::endl; -#endif - } - } - - if (be_version) - { - beMsgGetToken(be_version, versionId); - } - - /************************ handle options (optional:bitdht extension) **************/ - be_node *be_options = beMsgGetDictNode(node, "o"); - bool localnet = false; - if (be_options) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() Found Options Node, localnet"; - std::cerr << std::endl; -#endif - localnet = true; - } - - /*********** handle target (query) or info_hash (get_hash) ************/ - bdNodeId target_info_hash; - be_node *be_target = NULL; - if (beType == BITDHT_MSG_TYPE_FIND_NODE) - { - be_target = beMsgGetDictNode(be_data, "target"); - if (!be_target) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() Missing Target / Info_Hash. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - - } - else if ((beType == BITDHT_MSG_TYPE_GET_HASH) || - (beType == BITDHT_MSG_TYPE_POST_HASH)) - { - be_target = beMsgGetDictNode(be_data, "info_hash"); - if (!be_target) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() Missing Target / Info_Hash. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - } - - if (be_target) - { - beMsgGetNodeId(be_target, target_info_hash); - } - - /*********** handle nodes (reply_query or reply_near) *****************/ - std::list nodes; - be_node *be_nodes = NULL; - if ((beType == BITDHT_MSG_TYPE_REPLY_NODE) || - (beType == BITDHT_MSG_TYPE_REPLY_NEAR)) - { - be_nodes = beMsgGetDictNode(be_data, "nodes"); - if (!be_nodes) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() Missing Nodes. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - } - - if (be_nodes) - { - beMsgGetListBdIds(be_nodes, nodes); - } - - /******************* handle values (reply_hash) ***********************/ - std::list values; - be_node *be_values = NULL; - if (beType == BITDHT_MSG_TYPE_REPLY_HASH) - { - be_values = beMsgGetDictNode(be_data, "values"); - if (!be_values) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() Missing Values. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - } - - if (be_values) - { - beMsgGetListStrings(be_values, values); - } - - /************ handle token (reply_hash, reply_near, post hash) ********/ - bdToken token; - be_node *be_token = NULL; - if ((beType == BITDHT_MSG_TYPE_REPLY_HASH) || - (beType == BITDHT_MSG_TYPE_REPLY_NEAR) || - (beType == BITDHT_MSG_TYPE_POST_HASH)) - { - be_token = beMsgGetDictNode(be_data, "token"); - if (!be_token) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() Missing Token. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - } - - if (be_token) - { - beMsgGetToken(be_transId, transId); - } - - /****************** handle port (post hash) ***************************/ - uint32_t port; - be_node *be_port = NULL; - if (beType == BITDHT_MSG_TYPE_POST_HASH) - { - be_port = beMsgGetDictNode(be_data, "port"); - if (!be_port) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() POST_HASH Missing Port. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - } - - if (be_port) - { - beMsgGetUInt32(be_port, &port); - } - - /****************** handle Connect (lots) ***************************/ - bdId connSrcAddr; - bdId connDestAddr; - uint32_t connMode; - uint32_t connParam = 0; - uint32_t connStatus; - uint32_t connType; - - be_node *be_ConnSrcAddr = NULL; - be_node *be_ConnDestAddr = NULL; - be_node *be_ConnMode = NULL; - be_node *be_ConnParam = NULL; - be_node *be_ConnStatus = NULL; - be_node *be_ConnType = NULL; - if (beType == BITDHT_MSG_TYPE_CONNECT) - { - /* SrcAddr */ - be_ConnSrcAddr = beMsgGetDictNode(be_data, "src"); - if (!be_ConnSrcAddr) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() CONNECT Missing SrcAddr. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - - /* DestAddr */ - be_ConnDestAddr = beMsgGetDictNode(be_data, "dest"); - if (!be_ConnDestAddr) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() CONNECT Missing DestAddr. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - - /* Mode */ - be_ConnMode = beMsgGetDictNode(be_data, "mode"); - if (!be_ConnMode) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() CONNECT Missing Mode. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - - /* Param */ - be_ConnParam = beMsgGetDictNode(be_data, "param"); - if (!be_ConnParam) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() CONNECT Missing Param. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - - /* Status */ - be_ConnStatus = beMsgGetDictNode(be_data, "status"); - if (!be_ConnStatus) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() CONNECT Missing Status. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - - /* Type */ - be_ConnType = beMsgGetDictNode(be_data, "type"); - if (!be_ConnType) - { -#ifdef DEBUG_NODE_PARSE - std::cerr << "bdNode::recvPkt() CONNECT Missing Type. Dropping Msg"; - std::cerr << std::endl; -#endif - be_free(node); - return; - } - } - - if (be_ConnSrcAddr) - { - beMsgGetBdId(be_ConnSrcAddr, connSrcAddr); - } - - if (be_ConnDestAddr) - { - beMsgGetBdId(be_ConnDestAddr, connDestAddr); - } - - if (be_ConnMode) - { - beMsgGetUInt32(be_ConnMode, &connMode); - } - - if (be_ConnParam) - { - beMsgGetUInt32(be_ConnParam, &connParam); - } - - if (be_ConnStatus) - { - beMsgGetUInt32(be_ConnStatus, &connStatus); - } - - if (be_ConnType) - { - beMsgGetUInt32(be_ConnType, &connType); - } - - - - /****************** Bits Parsed Ok. Process Msg ***********************/ - /* Construct Source Id */ - bdId srcId(id, addr); - - if (be_target) - { - registerIncomingMsg(&srcId, &transId, beType, &target_info_hash); - } - else - { - registerIncomingMsg(&srcId, &transId, beType, NULL); - } - - switch(beType) - { - case BITDHT_MSG_TYPE_PING: /* a: id, transId */ - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::recvPkt() Responding to Ping : "; - mFns->bdPrintId(std::cerr, &srcId); - std::cerr << std::endl; -#endif - if (be_version) - { - msgin_ping(&srcId, &transId, &versionId); - } - else - { - msgin_ping(&srcId, &transId, NULL); - } - break; - } - case BITDHT_MSG_TYPE_PONG: /* r: id, transId */ - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::recvPkt() Received Pong from : "; - mFns->bdPrintId(std::cerr, &srcId); - std::cerr << std::endl; -#endif - if (be_version) - { - msgin_pong(&srcId, &transId, &versionId); - } - else - { - msgin_pong(&srcId, &transId, NULL); - } - - break; - } - case BITDHT_MSG_TYPE_FIND_NODE: /* a: id, transId, target */ - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::recvPkt() Req Find Node from : "; - mFns->bdPrintId(std::cerr, &srcId); - std::cerr << " Looking for: "; - mFns->bdPrintNodeId(std::cerr, &target_info_hash); - std::cerr << std::endl; -#endif - msgin_find_node(&srcId, &transId, &target_info_hash, localnet); - break; - } - case BITDHT_MSG_TYPE_REPLY_NODE: /* r: id, transId, nodes */ - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::recvPkt() Received Reply Node from : "; - mFns->bdPrintId(std::cerr, &srcId); - std::cerr << std::endl; -#endif - msgin_reply_find_node(&srcId, &transId, nodes); - break; - } - case BITDHT_MSG_TYPE_GET_HASH: /* a: id, transId, info_hash */ - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::recvPkt() Received SearchHash : "; - mFns->bdPrintId(std::cerr, &srcId); - std::cerr << " for Hash: "; - mFns->bdPrintNodeId(std::cerr, &target_info_hash); - std::cerr << std::endl; -#endif - msgin_get_hash(&srcId, &transId, &target_info_hash); - break; - } - case BITDHT_MSG_TYPE_REPLY_HASH: /* r: id, transId, token, values */ - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::recvPkt() Received Reply Hash : "; - mFns->bdPrintId(std::cerr, &srcId); - std::cerr << std::endl; -#endif - msgin_reply_hash(&srcId, &transId, &token, values); - break; - } - case BITDHT_MSG_TYPE_REPLY_NEAR: /* r: id, transId, token, nodes */ - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::recvPkt() Received Reply Near : "; - mFns->bdPrintId(std::cerr, &srcId); - std::cerr << std::endl; -#endif - msgin_reply_nearest(&srcId, &transId, &token, nodes); - break; - } - case BITDHT_MSG_TYPE_POST_HASH: /* a: id, transId, info_hash, port, token */ - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::recvPkt() Post Hash from : "; - mFns->bdPrintId(std::cerr, &srcId); - std::cerr << " to post: "; - mFns->bdPrintNodeId(std::cerr, &target_info_hash); - std::cerr << " with port: " << port; - std::cerr << std::endl; -#endif - msgin_post_hash(&srcId, &transId, &target_info_hash, port, &token); - break; - } - case BITDHT_MSG_TYPE_REPLY_POST: /* r: id, transId */ - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::recvPkt() Reply Post from: "; - mFns->bdPrintId(std::cerr, &srcId); - std::cerr << std::endl; -#endif - msgin_reply_post(&srcId, &transId); - break; - } - case BITDHT_MSG_TYPE_CONNECT: /* a: id, src, dest, mode, status, type */ - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::recvPkt() ConnectMsg from: "; - mFns->bdPrintId(std::cerr, &srcId); - std::cerr << std::endl; -#endif - msgin_connect_genmsg(&srcId, &transId, connType, - &connSrcAddr, &connDestAddr, - connMode, connParam, connStatus); - break; - } - default: - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::recvPkt() ERROR"; - std::cerr << std::endl; -#endif - /* ERROR */ - break; - } - } - - be_free(node); - return; -} - -/* Input: id, token. - * Response: pong(id, token) - */ - -void bdNode::msgin_ping(bdId *id, bdToken *transId, bdToken *versionId) -{ -#ifdef DEBUG_NODE_MSGIN - std::cerr << "bdNode::msgin_ping() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " To: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - - mAccount.incCounter(BDACCOUNT_MSG_PING, false); - - /* peer is alive */ - uint32_t peerflags = BITDHT_PEER_STATUS_RECV_PING; /* no id typically, so cant get version */ - peerflags |= parseVersion(versionId); - addPeer(id, peerflags); - - /* reply */ - msgout_pong(id, transId); - -} - -/* Input: id, token, (+optional version) - * Response: store peer. - */ - -void bdNode::msgin_pong(bdId *id, bdToken *transId, bdToken *versionId) -{ -#ifdef DEBUG_NODE_MSGIN - std::cerr << "bdNode::msgin_pong() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " Version: TODO!"; // << version; - std::cerr << " To: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << std::endl; -#else - (void) transId; -#endif - - uint32_t peerflags = BITDHT_PEER_STATUS_RECV_PONG; - peerflags |= parseVersion(versionId); - - mAccount.incCounter(BDACCOUNT_MSG_PONG, false); - addPeer(id, peerflags); -} - - -uint32_t bdNode::parseVersion(bdToken *versionId) -{ - /* recv pong, and peer is alive. add to DHT */ - //uint32_t vId = 0; // TODO XXX convertBdVersionToVID(versionId); - - /* calculate version match with peer */ - bool sameDhtEngine = false; - bool sameDhtVersion = false; - bool sameAppl = false; - bool sameApplVersion = false; - - if (versionId) - { - -#ifdef DEBUG_NODE_MSGIN - std::cerr << "bdNode::parseVersion() Peer Version: "; - for(int i = 0; i < versionId->len; i++) - { - std::cerr << versionId->data[i]; - } - std::cerr << std::endl; -#endif - -#ifdef USE_HISTORY - std::string version; - for(int i = 0; i < versionId->len; i++) - { - if (isalnum(versionId->data[i])) - { - version += versionId->data[i]; - } - else - { - version += 'X'; - } - } - mHistory.setPeerType(id, version); -#endif - - /* check two bytes */ - if ((versionId->len >= 2) && (mDhtVersion.size() >= 2) && - (versionId->data[0] == mDhtVersion[0]) && (versionId->data[1] == mDhtVersion[1])) - { - sameDhtEngine = true; - } - - /* check two bytes. - * Due to Old Versions not having this field, we need to check that they are numbers. - * We have a Major version, and minor version.... - * This flag is set if Major is same, and minor is greater or equal to our version. - */ - if ((versionId->len >= 4) && (mDhtVersion.size() >= 4)) - { - if ((isdigit(versionId->data[2]) && isdigit(versionId->data[3])) && - (versionId->data[2] == mDhtVersion[2]) && (versionId->data[3] >= mDhtVersion[3])) - { - sameDhtVersion = true; - } - } - - if ((sameDhtVersion) && (!sameDhtEngine)) - { - sameDhtVersion = false; -#ifdef DEBUG_NODE_MSGIN - std::cerr << "bdNode::parseVersion() STRANGE Peer Version: "; - for(uint32_t i = 0; i < versionId->len; i++) - { - std::cerr << versionId->data[i]; - } - std::cerr << std::endl; -#endif - } - - /* check two bytes */ - if ((versionId->len >= 6) && (mDhtVersion.size() >= 6) && - (versionId->data[4] == mDhtVersion[4]) && (versionId->data[5] == mDhtVersion[5])) - { - sameAppl = true; - } - - - /* check two bytes */ - if ((versionId->len >= 8) && (mDhtVersion.size() >= 8)) - { - if ((isdigit(versionId->data[6]) && isdigit(versionId->data[7])) && - (versionId->data[6] == mDhtVersion[6]) && (versionId->data[7] >= mDhtVersion[7])) - { - sameApplVersion = true; - } - } - } - else - { - -#ifdef DEBUG_NODE_MSGIN - std::cerr << "bdNode::parseVersion() No Version"; - std::cerr << std::endl; -#endif - } - - uint32_t peerflags = BITDHT_PEER_STATUS_RECV_PONG; /* should have id too */ - if (sameDhtEngine) - { - peerflags |= BITDHT_PEER_STATUS_DHT_ENGINE; - } - if (sameDhtVersion) - { - peerflags |= BITDHT_PEER_STATUS_DHT_ENGINE_VERSION; - } - if (sameAppl) - { - peerflags |= BITDHT_PEER_STATUS_DHT_APPL; - } - if (sameApplVersion) - { - peerflags |= BITDHT_PEER_STATUS_DHT_APPL_VERSION; - } - return peerflags; -} - - - -/* Input: id, token, queryId */ - -void bdNode::msgin_find_node(bdId *id, bdToken *transId, bdNodeId *query, bool localnet) -{ -#ifdef DEBUG_NODE_MSGIN - std::cerr << "bdNode::msgin_find_node() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " From: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " Query: "; - mFns->bdPrintNodeId(std::cerr, query); - std::cerr << std::endl; -#endif - - mAccount.incCounter(BDACCOUNT_MSG_QUERYNODE, false); - - - /* store query... */ - uint32_t query_type = BD_QUERY_NEIGHBOURS; - if (localnet) - { - query_type = BD_QUERY_LOCALNET; - } - queueQuery(id, query, transId, query_type); - - - uint32_t peerflags = 0; /* no id, and no help! */ - addPeer(id, peerflags); -} - -void bdNode::msgin_reply_find_node(bdId *id, bdToken *transId, std::list &nodes) -{ - std::list::iterator it; - -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::msgin_reply_find_node() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " From: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " Peers:"; - for(it = nodes.begin(); it != nodes.end(); it++) - { - std::cerr << " "; - mFns->bdPrintId(std::cerr, &(*it)); - } - std::cerr << std::endl; -#else - (void) transId; -#endif - - mAccount.incCounter(BDACCOUNT_MSG_REPLYFINDNODE, false); - - /* add neighbours to the potential list */ - for(it = nodes.begin(); it != nodes.end(); it++) - { - checkPotentialPeer(&(*it), id); - } - - /* received reply - so peer must be good */ - uint32_t peerflags = BITDHT_PEER_STATUS_RECV_NODES; /* no id ;( */ - addPeer(id, peerflags); -} - -/********* THIS IS THE SECOND STAGE - * - */ - -void bdNode::msgin_get_hash(bdId *id, bdToken *transId, bdNodeId *info_hash) -{ - - -#ifdef DEBUG_NODE_MSGIN - std::cerr << "bdNode::msgin_get_hash() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " From: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " InfoHash: "; - mFns->bdPrintNodeId(std::cerr, info_hash); - std::cerr << std::endl; -#endif - - - mAccount.incCounter(BDACCOUNT_MSG_QUERYHASH, false); - - /* generate message, send to udp */ - queueQuery(id, info_hash, transId, BD_QUERY_HASH); - -} - -void bdNode::msgin_reply_hash(bdId *id, bdToken *transId, bdToken *token, std::list &values) -{ - mAccount.incCounter(BDACCOUNT_MSG_REPLYQUERYHASH, false); - -#ifdef DEBUG_NODE_MSGIN - std::cerr << "bdNode::msgin_reply_hash() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " From: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " Token: "; - bdPrintToken(std::cerr, token); - - std::cerr << " Peers: "; - std::list::iterator it; - for(it = values.begin(); it != values.end(); it++) - { - std::cerr << " "; - bdPrintCompactPeerId(std::cerr, *it); - } - std::cerr << std::endl; -#else - (void) id; - (void) transId; - (void) token; - (void) values; -#endif -} - -void bdNode::msgin_reply_nearest(bdId *id, bdToken *transId, bdToken *token, std::list &nodes) -{ - mAccount.incCounter(BDACCOUNT_MSG_REPLYQUERYHASH, false); - -#ifdef DEBUG_NODE_MSGIN - std::cerr << "bdNode::msgin_reply_nearest() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " From: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " Token: "; - bdPrintToken(std::cerr, token); - std::cerr << " Nodes:"; - - std::list::iterator it; - for(it = nodes.begin(); it != nodes.end(); it++) - { - std::cerr << " "; - mFns->bdPrintId(std::cerr, &(*it)); - } - std::cerr << std::endl; -#else - (void) id; - (void) transId; - (void) token; - (void) nodes; -#endif -} - - - -void bdNode::msgin_post_hash(bdId *id, bdToken *transId, bdNodeId *info_hash, uint32_t port, bdToken *token) -{ - - mAccount.incCounter(BDACCOUNT_MSG_POSTHASH, false); - -#ifdef DEBUG_NODE_MSGIN - std::cerr << "bdNode::msgin_post_hash() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " From: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " Info_Hash: "; - mFns->bdPrintNodeId(std::cerr, info_hash); - std::cerr << " Port: " << port; - std::cerr << " Token: "; - bdPrintToken(std::cerr, token); - std::cerr << std::endl; -#else - (void) id; - (void) transId; - (void) info_hash; - (void) port; - (void) token; -#endif - -} - - -void bdNode::msgin_reply_post(bdId *id, bdToken *transId) -{ - /* generate message, send to udp */ - mAccount.incCounter(BDACCOUNT_MSG_REPLYPOSTHASH, false); - -#ifdef DEBUG_NODE_MSGIN - std::cerr << "bdNode::msgin_reply_post() TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " From: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << std::endl; -#else - (void) id; - (void) transId; -#endif -} - - - -/************************************************************************************************************ -******************************************** Message Interface ********************************************** -************************************************************************************************************/ - -/* Outgoing Messages */ -std::string getConnectMsgType(int msgtype) -{ - switch(msgtype) - { - case BITDHT_MSG_TYPE_CONNECT_REQUEST: - return "ConnectRequest"; - break; - case BITDHT_MSG_TYPE_CONNECT_REPLY: - return "ConnectReply"; - break; - case BITDHT_MSG_TYPE_CONNECT_START: - return "ConnectStart"; - break; - case BITDHT_MSG_TYPE_CONNECT_ACK: - return "ConnectAck"; - break; - default: - return "ConnectUnknown"; - break; - } -} - -void bdNode::msgout_connect_genmsg(bdId *id, bdToken *transId, int msgtype, bdId *srcAddr, bdId *destAddr, int mode, int param, int status) -{ -#ifdef DEBUG_NODE_MSGOUT - std::cerr << "bdConnectManager::msgout_connect_genmsg() Type: " << getConnectMsgType(msgtype); - std::cerr << " TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " To: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " SrcAddr: "; - mFns->bdPrintId(std::cerr, srcAddr); - std::cerr << " DestAddr: "; - mFns->bdPrintId(std::cerr, destAddr); - std::cerr << " Mode: " << mode; - std::cerr << " Param: " << param; - std::cerr << " Status: " << status; - std::cerr << std::endl; -#endif - - switch(msgtype) - { - default: - case BITDHT_MSG_TYPE_CONNECT_REQUEST: - mAccount.incCounter(BDACCOUNT_MSG_CONNECTREQUEST, true); - break; - case BITDHT_MSG_TYPE_CONNECT_REPLY: - mAccount.incCounter(BDACCOUNT_MSG_CONNECTREPLY, true); - break; - case BITDHT_MSG_TYPE_CONNECT_START: - mAccount.incCounter(BDACCOUNT_MSG_CONNECTSTART, true); - break; - case BITDHT_MSG_TYPE_CONNECT_ACK: - mAccount.incCounter(BDACCOUNT_MSG_CONNECTACK, true); - break; - } - - registerOutgoingMsg(id, transId, msgtype, NULL); - - /* create string */ - char msg[10240]; - int avail = 10240; - - int blen = bitdht_connect_genmsg(transId, &(mOwnId), msgtype, srcAddr, destAddr, mode, param, status, msg, avail-1); - sendPkt(msg, blen, id->addr); -} - - -void bdNode::msgin_connect_genmsg(bdId *id, bdToken *transId, int msgtype, - bdId *srcAddr, bdId *destAddr, int mode, int param, int status) -{ - std::list::iterator it; - -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdConnectManager::msgin_connect_genmsg() Type: " << getConnectMsgType(msgtype); - std::cerr << " TransId: "; - bdPrintTransId(std::cerr, transId); - std::cerr << " From: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << " SrcAddr: "; - mFns->bdPrintId(std::cerr, srcAddr); - std::cerr << " DestAddr: "; - mFns->bdPrintId(std::cerr, destAddr); - std::cerr << " Mode: " << mode; - std::cerr << " Param: " << param; - std::cerr << " Status: " << status; - std::cerr << std::endl; -#else - (void) transId; -#endif - - /* switch to actual work functions */ - uint32_t peerflags = 0; - switch(msgtype) - { - case BITDHT_MSG_TYPE_CONNECT_REQUEST: - peerflags = BITDHT_PEER_STATUS_RECV_CONNECT_MSG; - mAccount.incCounter(BDACCOUNT_MSG_CONNECTREQUEST, false); - - - mConnMgr->recvedConnectionRequest(id, srcAddr, destAddr, mode, param); - - break; - case BITDHT_MSG_TYPE_CONNECT_REPLY: - peerflags = BITDHT_PEER_STATUS_RECV_CONNECT_MSG; - mAccount.incCounter(BDACCOUNT_MSG_CONNECTREPLY, false); - - mConnMgr->recvedConnectionReply(id, srcAddr, destAddr, mode, param, status); - - break; - case BITDHT_MSG_TYPE_CONNECT_START: - peerflags = BITDHT_PEER_STATUS_RECV_CONNECT_MSG; - mAccount.incCounter(BDACCOUNT_MSG_CONNECTSTART, false); - - mConnMgr->recvedConnectionStart(id, srcAddr, destAddr, mode, param); - - break; - case BITDHT_MSG_TYPE_CONNECT_ACK: - peerflags = BITDHT_PEER_STATUS_RECV_CONNECT_MSG; - mAccount.incCounter(BDACCOUNT_MSG_CONNECTACK, false); - - mConnMgr->recvedConnectionAck(id, srcAddr, destAddr, mode); - - break; - default: - break; - } - - /* received message - so peer must be good */ - addPeer(id, peerflags); - -} - - - - - - - - - - - -/****************** Other Functions ******************/ - -void bdNode::genNewToken(bdToken *token) -{ -#ifdef DEBUG_NODE_ACTIONS - fprintf(stderr, "bdNode::genNewToken()"); - fprintf(stderr, ")\n"); -#endif - - // XXX is this a good way to do it? - // Variable length, from 4 chars up to lots... 10? - // leave for the moment, but fix. - std::string num; - bd_sprintf(num, "%04lx", bdRandom::random_u32()); - int len = num.size(); - if (len > BITDHT_TOKEN_MAX_LEN) - len = BITDHT_TOKEN_MAX_LEN; - - for(int i = 0; i < len; i++) - { - token->data[i] = num[i]; - } - token->len = len; - -} - -uint32_t transIdCounter = 0; -void bdNode::genNewTransId(bdToken *token) -{ - /* generate message, send to udp */ -#ifdef DEBUG_NODE_ACTIONS - fprintf(stderr, "bdNode::genNewTransId()"); - fprintf(stderr, ")\n"); -#endif - - std::string num; - bd_sprintf(num, "%02lx", transIdCounter++); - int len = num.size(); - if (len > BITDHT_TOKEN_MAX_LEN) - len = BITDHT_TOKEN_MAX_LEN; - - for(int i = 0; i < len; i++) - { - token->data[i] = num[i]; - } - token->len = len; -} - - -/* Store Remote Query for processing */ -int bdNode::queueQuery(bdId *id, bdNodeId *query, bdToken *transId, uint32_t query_type) -{ -#ifdef DEBUG_NODE_ACTIONS - std::cerr << "bdnode::queueQuery()" << std::endl; -#endif - - mRemoteQueries.push_back(bdRemoteQuery(id, query, transId, query_type)); - - return 1; -} - -/*************** Register Transaction Ids *************/ - -void bdNode::registerOutgoingMsg(bdId *id, bdToken *transId, uint32_t msgType, bdNodeId *aboutId) -{ - -#ifdef DEBUG_MSG_CHECKS - std::cerr << "bdNode::registerOutgoingMsg("; - mFns->bdPrintId(std::cerr, id); - std::cerr << ", " << msgType << ")"; - std::cerr << std::endl; -#else - (void) id; - (void) msgType; -#endif - -#ifdef USE_HISTORY - - // splitting up - to see if we can isolate the crash causes. - switch(msgType) - { - // disabled types (which appear to crash it!) - case BITDHT_MSG_TYPE_PING: - if (!id) - { - return; - } - if ((id->id.data[0] == 0) - && (id->id.data[1] == 0) - && (id->id.data[2] == 0) - && (id->id.data[3] == 0)) - { - return; - } - break; - case BITDHT_MSG_TYPE_UNKNOWN: - case BITDHT_MSG_TYPE_PONG: - case BITDHT_MSG_TYPE_FIND_NODE: - case BITDHT_MSG_TYPE_REPLY_NODE: - case BITDHT_MSG_TYPE_GET_HASH: - case BITDHT_MSG_TYPE_REPLY_HASH: - case BITDHT_MSG_TYPE_REPLY_NEAR: - case BITDHT_MSG_TYPE_POST_HASH: - case BITDHT_MSG_TYPE_REPLY_POST: - break; - } - - // This line appears to cause crashes on OSX. - mHistory.addMsg(id, transId, msgType, false, aboutId); -#else - (void) transId; - (void) aboutId; -#endif - - - -/**** -#define BITDHT_MSG_TYPE_UNKNOWN 0 -#define BITDHT_MSG_TYPE_PING 1 -#define BITDHT_MSG_TYPE_PONG 2 -#define BITDHT_MSG_TYPE_FIND_NODE 3 -#define BITDHT_MSG_TYPE_REPLY_NODE 4 -#define BITDHT_MSG_TYPE_GET_HASH 5 -#define BITDHT_MSG_TYPE_REPLY_HASH 6 -#define BITDHT_MSG_TYPE_REPLY_NEAR 7 -#define BITDHT_MSG_TYPE_POST_HASH 8 -#define BITDHT_MSG_TYPE_REPLY_POST 9 -***/ - -} - - - -uint32_t bdNode::registerIncomingMsg(bdId *id, bdToken *transId, uint32_t msgType, bdNodeId *aboutId) -{ - -#ifdef DEBUG_MSG_CHECKS - std::cerr << "bdNode::registerIncomingMsg("; - mFns->bdPrintId(std::cerr, id); - std::cerr << ", " << msgType << ")"; - std::cerr << std::endl; -#else - (void) id; - (void) msgType; -#endif - -#ifdef USE_HISTORY - mHistory.addMsg(id, transId, msgType, true, aboutId); -#else - (void) transId; - (void) aboutId; -#endif - - return 0; -} - -void bdNode::cleanupTransIdRegister() -{ - return; -} - - - -/*************** Internal Msg Storage *****************/ - -bdNodeNetMsg::bdNodeNetMsg(char *msg, int len, struct sockaddr_in *in_addr) - :data(NULL), mSize(len), addr(*in_addr) -{ - data = (char *) malloc(len); - - if(data == NULL) - { - std::cerr << "(EE) " << __PRETTY_FUNCTION__ << ": ERROR. cannot allocate memory for " << len << " bytes." << std::endl; - return ; - } - - memcpy(data, msg, len); - //print(std::cerr); -} - -void bdNodeNetMsg::print(std::ostream &out) -{ - out << "bdNodeNetMsg::print(" << mSize << ") to " - << bdnet_inet_ntoa(addr.sin_addr) << ":" << htons(addr.sin_port); - out << std::endl; -} - - -bdNodeNetMsg::~bdNodeNetMsg() -{ - free(data); -} - - - -/**************** In/Out of Relay Mode ******************/ - -void bdNode::dropRelayServers() -{ - /* We leave them there... just drop the flags */ - uint32_t flags = BITDHT_PEER_STATUS_DHT_RELAY_SERVER; - std::list peerList; - std::list::iterator it; - - mFriendList.findPeersWithFlags(flags, peerList); - for(it = peerList.begin(); it != peerList.end(); it++) - { - mFriendList.removePeer(&(*it)); - } - - mNodeSpace.clean_node_flags(flags); -} - -void bdNode::pingRelayServers() -{ - /* if Relay's have been switched on, do search/ping to locate servers */ -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::pingRelayServers()"; - std::cerr << std::endl; -#endif - - bool doSearch = true; - - uint32_t flags = BITDHT_PEER_STATUS_DHT_RELAY_SERVER; - std::list peerList; - std::list::iterator it; - - mFriendList.findPeersWithFlags(flags, peerList); - for(it = peerList.begin(); it != peerList.end(); it++) - { - if (doSearch) - { - uint32_t qflags = BITDHT_QFLAGS_INTERNAL | BITDHT_QFLAGS_DISGUISE; - mQueryMgr->addQuery(&(*it), qflags); - -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdNode::pingRelayServers() Adding Internal Search for Relay Server: "; - mFns->bdPrintNodeId(std::cerr, &(*it)); - std::cerr << std::endl; -#endif - - } - else - { - /* try ping - if we have an address??? */ - - } - } -} - - diff --git a/libbitdht/src/bitdht/bdnode.h b/libbitdht/src/bitdht/bdnode.h deleted file mode 100644 index 39abbb435..000000000 --- a/libbitdht/src/bitdht/bdnode.h +++ /dev/null @@ -1,284 +0,0 @@ -/******************************************************************************* - * bitdht/bdnode.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef BITDHT_NODE_H -#define BITDHT_NODE_H - -#include "bitdht/bdpeer.h" -#include "bitdht/bdquery.h" -#include "bitdht/bdstore.h" -#include "bitdht/bdobj.h" -#include "bitdht/bdhash.h" -#include "bitdht/bdhistory.h" -#include "bitdht/bdfilter.h" - -#include "bitdht/bdconnection.h" -#include "bitdht/bdaccount.h" - -#include "bitdht/bdfriendlist.h" - -class bdFilter; - - -#define BD_QUERY_NEIGHBOURS 1 -#define BD_QUERY_LOCALNET 2 -#define BD_QUERY_HASH 3 - -/********************************** - * Running a node.... - * - * run(). - * loops through and checks out of date peers. - * handles searches. - * prints out dht Table. - * - -The node handles the i/o traffic from peers. -It - - - -ping, return -peers, return -hash store, return -hash get, return - - - -respond queue. - -query queue. - - - - - -input -> call into recvFunction() -output -> call back to Udp(). - - - - - *********/ - -class bdFilteredPeer ; -class bdNodeManager; - -class bdNodeNetMsg -{ - - public: - bdNodeNetMsg(char *data, int size, struct sockaddr_in *addr); - ~bdNodeNetMsg(); - - void print(std::ostream &out); - - char *data; - int mSize; - struct sockaddr_in addr; - -}; - -class bdNodePublisher -{ - public: - /* simplified outgoing msg functions (for the managers) */ - virtual void send_ping(bdId *id) = 0; /* message out */ - virtual void send_query(bdId *id, bdNodeId *targetNodeId, bool localnet) = 0; /* message out */ - virtual void send_connect_msg(bdId *id, int msgtype, - bdId *srcAddr, bdId *destAddr, int mode, int param, int status) = 0; - - // internal Callback -> normally continues to callbackConnect(). - virtual void callbackConnect(bdId *srcId, bdId *proxyId, bdId *destId, - int mode, int point, int param, int cbtype, int errcode) = 0; - -}; - - -class bdNode: public bdNodePublisher -{ - public: - - bdNode(bdNodeId *id, std::string dhtVersion, const std::string& bootfile, const std::string& bootfilebak, const std::string& filterfile, - bdDhtFunctions *fns, bdNodeManager* manager); - - void init(); /* sets up the self referential classes (mQueryMgr & mConnMgr) */ - - void setNodeOptions(uint32_t optFlags); - uint32_t setNodeDhtMode(uint32_t dhtFlags); - - /* startup / shutdown node */ - void restartNode(); - void shutdownNode(); - - void getOwnId(bdNodeId *id); - - // virtual so manager can do callback. - // peer flags defined in bdiface.h - virtual void addPeer(const bdId *id, uint32_t peerflags); - - void printState(); - void checkPotentialPeer(bdId *id, bdId *src); - void addPotentialPeer(bdId *id, bdId *src); - - void iterationOff(); - void iteration(); - void processRemoteQuery(); - void updateStore(); - - bool addressBanned(const sockaddr_in &raddr) ; - bool getFilteredPeers(std::list &peers); - //void loadFilteredPeers(const std::list &peers); - - /* simplified outgoing msg functions (for the managers) */ - virtual void send_ping(bdId *id); /* message out */ - virtual void send_query(bdId *id, bdNodeId *targetNodeId, bool localnet); /* message out */ - virtual void send_connect_msg(bdId *id, int msgtype, - bdId *srcAddr, bdId *destAddr, int mode, int param, int status); - -// This is implemented in bdManager. -// virtual void callbackConnect(bdId *srcId, bdId *proxyId, bdId *destId, -// int mode, int point, int param, int cbtype, int errcode); - - /* interaction with outside world (Accessed by controller to deliver us msgs) */ -int outgoingMsg(struct sockaddr_in *addr, char *msg, int *len); -void incomingMsg(struct sockaddr_in *addr, char *msg, int len); - - // For Relay Mode switching. -void dropRelayServers(); -void pingRelayServers(); - -// Below is internal Management of incoming / outgoing messages. - -private: - - /* internal interaction with network */ -void sendPkt(char *msg, int len, struct sockaddr_in addr); -void recvPkt(char *msg, int len, struct sockaddr_in addr); - - - /* output functions (send msg) */ - void msgout_ping(bdId *id, bdToken *transId); - void msgout_pong(bdId *id, bdToken *transId); - void msgout_find_node(bdId *id, bdToken *transId, bdNodeId *query, bool localnet); - void msgout_reply_find_node(bdId *id, bdToken *transId, - std::list &peers); - void msgout_get_hash(bdId *id, bdToken *transId, bdNodeId *info_hash); - void msgout_reply_hash(bdId *id, bdToken *transId, - bdToken *token, std::list &values); - void msgout_reply_nearest(bdId *id, bdToken *transId, - bdToken *token, std::list &peers); - - void msgout_post_hash(bdId *id, bdToken *transId, bdNodeId *info_hash, - uint32_t port, bdToken *token); - void msgout_reply_post(bdId *id, bdToken *transId); - - - /* input functions (once mesg is parsed) */ - uint32_t parseVersion(bdToken *versionId); - void msgin_ping(bdId *id, bdToken *token, bdToken *versionId); - void msgin_pong(bdId *id, bdToken *transId, bdToken *versionId); - - void msgin_find_node(bdId *id, bdToken *transId, bdNodeId *query, bool localnet); - void msgin_reply_find_node(bdId *id, bdToken *transId, - std::list &entries); - - void msgin_get_hash(bdId *id, bdToken *transId, bdNodeId *nodeid); - void msgin_reply_hash(bdId *id, bdToken *transId, - bdToken *token, std::list &values); - void msgin_reply_nearest(bdId *id, bdToken *transId, - bdToken *token, std::list &nodes); - - void msgin_post_hash(bdId *id, bdToken *transId, - bdNodeId *info_hash, uint32_t port, bdToken *token); - void msgin_reply_post(bdId *id, bdToken *transId); - - void msgout_connect_genmsg(bdId *id, bdToken *transId, int msgtype, - bdId *srcAddr, bdId *destAddr, int mode, int param, int status); - void msgin_connect_genmsg(bdId *id, bdToken *transId, int msgtype, - bdId *srcAddr, bdId *destAddr, int mode, int param, int status); - - - - /* token handling */ - void genNewToken(bdToken *token); - int queueQuery(bdId *id, bdNodeId *query, bdToken *transId, uint32_t query_type); - - /* transId handling */ - void genNewTransId(bdToken *token); - void registerOutgoingMsg(bdId *id, bdToken *transId, uint32_t msgType, bdNodeId *aboutId); - uint32_t registerIncomingMsg(bdId *id, bdToken *transId, uint32_t msgType, bdNodeId *aboutId); - - void cleanupTransIdRegister(); - - - void doStats(); - - /********** Variables **********/ - private: - - /**** Some Variables are Protected to allow inherited classes to use *****/ - protected: - - bdSpace mNodeSpace; - bdFilter mFilterPeers; - - bdQueryManager *mQueryMgr; - bdConnectManager *mConnMgr; - - bdNodeId mOwnId; - bdId mLikelyOwnId; // Try to workout own id address. - std::string mDhtVersion; - - bdAccount mAccount; - bdStore mStore; - - bdDhtFunctions *mFns; - bdHashSpace mHashSpace; - - bdFriendList mFriendList; - bdPeerQueue mBadPeerQueue; - - bdHistory mHistory; /* for understanding the DHT */ - - bdQueryHistory mQueryHistory; /* for determining old peers */ - - private: - - uint32_t mNodeOptionFlags; - uint32_t mNodeDhtMode; - - uint32_t mMaxAllowedMsgs; - uint32_t mRelayMode; - - - std::list mRemoteQueries; - - std::list mPotentialPeers; - - std::list mOutgoingMsgs; - std::list mIncomingMsgs; - -}; - - - -#endif // BITDHT_NODE_H diff --git a/libbitdht/src/bitdht/bdobj.cc b/libbitdht/src/bitdht/bdobj.cc deleted file mode 100644 index 9832796d2..000000000 --- a/libbitdht/src/bitdht/bdobj.cc +++ /dev/null @@ -1,48 +0,0 @@ -/******************************************************************************* - * bitdht/bdobj.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "bitdht/bdobj.h" - - -void bdPrintTransId(std::ostream &out, bdToken *transId) -{ - //out << transId->data; - bdPrintToken(out, transId); - return; -} - - -void bdPrintToken(std::ostream &out, bdToken *token) -{ - for(unsigned int i = 0; i < token->len; i++) - { - out << std::hex << (uint32_t) token->data[i]; - } - out << std::dec; -} - -void bdPrintCompactPeerId(std::ostream &out, std::string /*cpi*/ ) -{ - out << "DummyCompactPeerId"; -} - - diff --git a/libbitdht/src/bitdht/bdobj.h b/libbitdht/src/bitdht/bdobj.h deleted file mode 100644 index d193c59a8..000000000 --- a/libbitdht/src/bitdht/bdobj.h +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************* - * bitdht/bdobj.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef BITDHT_OBJECTS_H -#define BITDHT_OBJECTS_H - -#define BITDHT_TOKEN_MAX_LEN 20 - -#include -#include - -class bdToken -{ - public: - bdToken() :len(0) { return; } - uint32_t len; - unsigned char data[BITDHT_TOKEN_MAX_LEN]; -}; - -class bdCompactIds -{ - public: - bdCompactIds() :len(0) { return; } - uint32_t len; - unsigned char data[BITDHT_TOKEN_MAX_LEN]; -}; - -class bdVersion -{ - public: - bdVersion() :len(0) { return; } - uint32_t len; - unsigned char data[BITDHT_TOKEN_MAX_LEN]; -}; - -void bdPrintTransId(std::ostream &out, bdToken *transId); -void bdPrintToken(std::ostream &out, bdToken *transId); -void bdPrintCompactPeerId(std::ostream &out, std::string cpi); - -#endif - diff --git a/libbitdht/src/bitdht/bdpeer.cc b/libbitdht/src/bitdht/bdpeer.cc deleted file mode 100644 index 65cfb31b5..000000000 --- a/libbitdht/src/bitdht/bdpeer.cc +++ /dev/null @@ -1,1276 +0,0 @@ -/******************************************************************************* - * bitdht/bdpeer.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "bitdht/bdpeer.h" -#include "util/bdnet.h" -#include "util/bdrandom.h" -#include "util/bdstring.h" -#include "bitdht/bdiface.h" - -#include -#include -#include - -#include -#include - -/** - * #define BITDHT_DEBUG 1 -**/ - -void bdSockAddrInit(struct sockaddr_in *addr) -{ - memset(addr, 0, sizeof(struct sockaddr_in)); - addr->sin_family = AF_INET; -} - -bdId::bdId() -{ - /* blank everything */ - bdSockAddrInit(&addr); - memset(&id.data, 0, BITDHT_KEY_LEN); -} - - -bdId::bdId(bdNodeId in_id, struct sockaddr_in in_addr) -{ - /* this bit is to ensure the address is valid for windows / osx */ - bdSockAddrInit(&addr); - addr.sin_addr.s_addr = in_addr.sin_addr.s_addr; - addr.sin_port = in_addr.sin_port; - - for(int i = 0; i < BITDHT_KEY_LEN; i++) - { - id.data[i] = in_id.data[i]; - } -}; - - -void bdZeroNodeId(bdNodeId *id) -{ - uint32_t *a_data = (uint32_t *) id->data; - for(int i = 0; i < BITDHT_KEY_INTLEN; i++) - { - a_data[i] = 0; - } - return; -} - - -int operator<(const bdNodeId &a, const bdNodeId &b) -{ -#if 0 - std::cerr << "operator<("); - bdPrintNodeId(std::cerr, &a); - std::cerr << ","; - bdPrintNodeId(std::cerr, &b); - std::cerr << ")" << std::endl; -#endif - - uint8_t *a_data = (uint8_t *) a.data; - uint8_t *b_data = (uint8_t *) b.data; - for(int i = 0; i < BITDHT_KEY_LEN; i++) - { - if (*a_data < *b_data) - { - //fprintf(stderr, "Return 1, at i = %d\n", i); - return 1; - } - else if (*a_data > *b_data) - { - //fprintf(stderr, "Return 0, at i = %d\n", i); - return 0; - } - a_data++; - b_data++; - } - //fprintf(stderr, "Return 0, at i = KEYLEN\n"); - return 0; -} - -#if 0 -int operator<(const struct sockaddr_in &a, const struct sockaddr_in &b) -{ - /* else NodeIds the same - check id addresses */ - if (a.sin_addr.s_addr < b.sin_addr.s_addr) - return 1; - if (b.sin_addr.s_addr > a.sin_addr.s_addr) - return 0; - - if (a.sin_port < b.sin_port) - return 1; - - return 0; -} -#endif - -int operator<(const bdId &a, const bdId &b) -{ - if (a.id < b.id) - return 1; - if (b.id < a.id) - return 0; - - /* else NodeIds the same - check id addresses */ - if (a.addr.sin_addr.s_addr < b.addr.sin_addr.s_addr) - return 1; - if (b.addr.sin_addr.s_addr > a.addr.sin_addr.s_addr) - return 0; - - if (a.addr.sin_port < b.addr.sin_port) - return 1; - - return 0; -} - - -int operator==(const bdNodeId &a, const bdNodeId &b) -{ - uint8_t *a_data = (uint8_t *) a.data; - uint8_t *b_data = (uint8_t *) b.data; - for(int i = 0; i < BITDHT_KEY_LEN; i++) - { - if (*a_data < *b_data) - { - return 0; - } - else if (*a_data > *b_data) - { - return 0; - } - a_data++; - b_data++; - } - return 1; -} - -int operator==(const bdId &a, const bdId &b) -{ - if (!(a.id == b.id)) - return 0; - - if ((a.addr.sin_addr.s_addr == b.addr.sin_addr.s_addr) && - (a.addr.sin_port == b.addr.sin_port)) - { - return 1; - } - return 0; -} - - - -bdBucket::bdBucket() -{ - return; -} - -bdSpace::bdSpace(bdNodeId *ownId, bdDhtFunctions *fns) - :mOwnId(*ownId), mFns(fns) -{ - /* make some space for data */ - buckets.resize(mFns->bdNumBuckets()); - - mAttachTS = 0; - mAttachedFlags = 0; - mAttachedCount = 0; - - return; -} - - /* empty the buckets */ -int bdSpace::clear() -{ - std::vector::iterator it; - /* iterate through the buckets, and sort by distance */ - for(it = buckets.begin(); it != buckets.end(); it++) - { - it->entries.clear(); - } - return 1; -} - -int bdSpace::setAttachedFlag(uint32_t withflags, int count) -{ - mAttachedFlags = withflags; - mAttachedCount = count; - mAttachTS = 0; - return 1; -} - -int bdSpace::find_nearest_nodes_with_flags(const bdNodeId *id, int number, - std::list /* excluding */, - std::multimap &nearest, uint32_t with_flags) -{ - std::multimap closest; - std::multimap::iterator mit; - - bdMetric dist; - mFns->bdDistance(id, &(mOwnId), &dist); - -#ifdef DEBUG_BD_SPACE - int bucket = mFns->bdBucketDistance(&dist); - - std::cerr << "bdSpace::find_nearest_nodes(NodeId:"; - mFns->bdPrintNodeId(std::cerr, id); - - std::cerr << " Number: " << number; - std::cerr << " Query Bucket #: " << bucket; - std::cerr << std::endl; -#endif - - std::vector::iterator it; - std::list::iterator eit; - /* iterate through the buckets, and sort by distance */ - for(it = buckets.begin(); it != buckets.end(); it++) - { - for(eit = it->entries.begin(); eit != it->entries.end(); eit++) - { - if ((!with_flags) || ((with_flags & eit->mPeerFlags) == with_flags)) - { - mFns->bdDistance(id, &(eit->mPeerId.id), &dist); - closest.insert(std::pair(dist, eit->mPeerId)); - -#if 0 - std::cerr << "Added NodeId: "; - bdPrintNodeId(std::cerr, &(eit->mPeerId.id)); - std::cerr << " Metric: "; - bdPrintNodeId(std::cerr, &(dist)); - std::cerr << std::endl; -#endif - } - } - } - - /* take the first number of nodes */ - int i = 0; - for(mit = closest.begin(); (mit != closest.end()) && (i < number); mit++, i++) - { - mFns->bdDistance(&(mOwnId), &(mit->second.id), &dist); - -#ifdef DEBUG_BD_SPACE - int iBucket = mFns->bdBucketDistance(&(mit->first)); - - std::cerr << "Closest " << i << ": "; - mFns->bdPrintNodeId(std::cerr, &(mit->second.id)); - std::cerr << " Bucket: " << iBucket; - std::cerr << std::endl; -#endif - - -#if 0 - std::cerr << "\tNodeId: "; - mFns->bdPrintNodeId(std::cerr, &(mit->second.id)); - std::cerr << std::endl; - - std::cerr << "\tOwn Id: "; - mFns->bdPrintNodeId(std::cerr, &(mOwnId)); - std::cerr << std::endl; - - std::cerr << " Us Metric: "; - mFns->bdPrintNodeId(std::cerr, &dist); - std::cerr << " Bucket: " << oBucket; - std::cerr << std::endl; - - std::cerr << "\tFindId: "; - mFns->bdPrintNodeId(std::cerr, id); - std::cerr << std::endl; - - std::cerr << " Id Metric: "; - mFns->bdPrintNodeId(std::cerr, &(mit->first)); - std::cerr << " Bucket: " << iBucket; - std::cerr << std::endl; -#endif - - nearest.insert(*mit); - } - -#ifdef DEBUG_BD_SPACE - std::cerr << "#Nearest: " << (int) nearest.size(); - std::cerr << " #Closest: " << (int) closest.size(); - std::cerr << " #Requested: " << number; - std::cerr << std::endl << std::endl; -#endif - - return 1; -} - -int bdSpace::find_nearest_nodes(const bdNodeId *id, int number, - std::multimap &nearest) -{ - std::list excluding; - uint32_t with_flag = 0; - - return find_nearest_nodes_with_flags(id, number, excluding, nearest, with_flag); -} - - -/* This is much cheaper than find nearest... we only look in the one bucket - */ - -int bdSpace::find_node(const bdNodeId *id, int number, std::list &matchIds, uint32_t with_flags) -{ - bdMetric dist; - mFns->bdDistance(id, &(mOwnId), &dist); - int buckno = mFns->bdBucketDistance(&dist); - -#ifdef DEBUG_BD_SPACE - std::cerr << "bdSpace::find_node(NodeId:"; - mFns->bdPrintNodeId(std::cerr, id); - std::cerr << ")"; - - std::cerr << " Number: " << number; - std::cerr << " Bucket #: " << buckno; - std::cerr << std::endl; -#else - (void)number; -#endif - - bdBucket &buck = buckets[buckno]; - - std::list::iterator eit; - int matchCount = 0; - for(eit = buck.entries.begin(); eit != buck.entries.end(); eit++) - { -#ifdef DEBUG_BD_SPACE - std::cerr << "bdSpace::find_node() Checking Against Peer: "; - mFns->bdPrintId(std::cerr, &(eit->mPeerId)); - std::cerr << " withFlags: " << eit->mPeerFlags; - std::cerr << std::endl; -#endif - - if ((!with_flags) || ((with_flags & eit->mPeerFlags) == with_flags)) - { - if (*id == eit->mPeerId.id) - { - matchIds.push_back(eit->mPeerId); - matchCount++; - -#ifdef DEBUG_BD_SPACE - std::cerr << "bdSpace::find_node() Found Matching Peer: "; - mFns->bdPrintId(std::cerr, &(eit->mPeerId)); - std::cerr << " withFlags: " << eit->mPeerFlags; - std::cerr << std::endl; -#endif - } - } - else - { - if (*id == eit->mPeerId.id) - { - //matchIds.push_back(eit->mPeerId); - //matchCount++; - -#ifdef DEBUG_BD_SPACE - std::cerr << "bdSpace::find_node() Found (WITHOUT FLAGS) Matching Peer: "; - mFns->bdPrintId(std::cerr, &(eit->mPeerId)); - std::cerr << " withFlags: " << eit->mPeerFlags; - std::cerr << std::endl; -#endif - } - } - } - -#ifdef DEBUG_BD_SPACE - std::cerr << "bdSpace::find_node() Found " << matchCount << " Matching Peers"; - std::cerr << std::endl << std::endl; -#endif - - return matchCount; -} - -/* even cheaper again... no big lists */ -int bdSpace::find_exactnode(const bdId *id, bdPeer &peer) -{ - bdMetric dist; - mFns->bdDistance(&(id->id), &(mOwnId), &dist); - int buckno = mFns->bdBucketDistance(&dist); - -#ifdef DEBUG_BD_SPACE - std::cerr << "bdSpace::find_exactnode(Id:"; - mFns->bdPrintId(std::cerr, id); - std::cerr << ")"; - - std::cerr << " Bucket #: " << buckno; - std::cerr << std::endl; -#endif - - bdBucket &buck = buckets[buckno]; - - std::list::iterator eit; - for(eit = buck.entries.begin(); eit != buck.entries.end(); eit++) - { - if (*id == eit->mPeerId) - { -#ifdef DEBUG_BD_SPACE - std::cerr << "bdSpace::find_exactnode() Found Matching Peer: "; - mFns->bdPrintId(std::cerr, &(eit->mPeerId)); - std::cerr << " withFlags: " << eit->mPeerFlags; - std::cerr << std::endl; -#endif - - peer = (*eit); - return 1; - } - } -#ifdef DEBUG_BD_SPACE - std::cerr << "bdSpace::find_exactnode() WARNING Failed to find Matching Peer: "; - std::cerr << std::endl; -#endif - - return 0; -} - - - -int bdSpace::clean_node_flags(uint32_t flags) -{ - std::cerr << "bdSpace::clean_node_flags(" << flags << ")"; - std::cerr << std::endl; - - int count = 0; - std::vector::iterator bit; - for(bit = buckets.begin(); bit != buckets.end(); bit++) - { - std::list::iterator eit; - for(eit = bit->entries.begin(); eit != bit->entries.end(); eit++) - { - if (flags & eit->mPeerFlags) - { -#ifdef DEBUG_BD_SPACE - std::cerr << "bdSpace::clean_node_flags() Found Match: "; - mFns->bdPrintId(std::cerr, &(eit->mPeerId)); - std::cerr << " withFlags: " << eit->mPeerFlags; - std::cerr << std::endl; -#endif - - count++; - eit->mPeerFlags &= ~flags; - } - } - } -#ifdef DEBUG_BD_SPACE - std::cerr << "bdSpace::clean_node_flags() Cleaned " << count << " Matching Peers"; - std::cerr << std::endl; -#endif - - return count; -} - - - -#define BITDHT_ATTACHED_SEND_PERIOD 17 - -int bdSpace::scanOutOfDatePeers(std::list &peerIds) -{ - /* - * - */ - bool doAttached = (mAttachedCount > 0); - uint32_t attachedCount = 0; - - std::map closest; - std::map::iterator mit; - - std::vector::iterator it; - std::list::iterator eit; - time_t ts = time(NULL); - - /* iterate through the buckets, and sort by distance */ - for(it = buckets.begin(); it != buckets.end(); it++) - { - for(eit = it->entries.begin(); eit != it->entries.end(); ) - { - bool added = false; - if (doAttached) - { - if (eit->mExtraFlags & BITDHT_PEER_EXFLAG_ATTACHED) - { - /* add to send list, if we haven't pinged recently */ - if ((ts - eit->mLastSendTime > BITDHT_ATTACHED_SEND_PERIOD ) && - (ts - eit->mLastRecvTime > BITDHT_ATTACHED_SEND_PERIOD )) - { - peerIds.push_back(eit->mPeerId); - eit->mLastSendTime = ts; - added = true; - } - attachedCount++; - } - } - - - /* timeout on last send time! */ - if ((!added) && (ts - eit->mLastSendTime > BITDHT_MAX_SEND_PERIOD )) - { - /* We want to ping a peer iff: - * 1) They are out-of-date: mLastRecvTime is too old. - * 2) They don't have 0x0001 flag (we haven't received a PONG) and never sent. - */ - if ((ts - eit->mLastRecvTime > BITDHT_MAX_SEND_PERIOD ) || - !(eit->mPeerFlags & BITDHT_PEER_STATUS_RECV_PONG)) - { - peerIds.push_back(eit->mPeerId); - eit->mLastSendTime = ts; - } - } - - - /* we also want to remove very old entries (should it happen here?) - * which are not pushed out by newer entries (will happen in for closer buckets) - */ - - bool discard = false; - /* discard very old entries */ - if (ts - eit->mLastRecvTime > BITDHT_DISCARD_PERIOD) - { - discard = true; - } - - /* discard peers which have not responded to anything (ie have no flags set) */ - /* changed into have not id'ed themselves, as we've added ping to list of flags. */ - if ((ts - eit->mFoundTime > BITDHT_MAX_RESPONSE_PERIOD ) && - !(eit->mPeerFlags & BITDHT_PEER_STATUS_RECV_PONG)) - { - discard = true; - } - - - /* INCREMENT */ - if (discard) - { - eit = it->entries.erase(eit); - } - else - { - eit++; - } - } - } - -#define ATTACH_UPDATE_PERIOD 600 - - if ((ts - mAttachTS > ATTACH_UPDATE_PERIOD) || (attachedCount != mAttachedCount)) - { - //std::cerr << "Updating ATTACH Stuff"; - //std::cerr << std::endl; - updateAttachedPeers(); /* XXX TEMP HACK to look at stability */ - mAttachTS = ts; - } - - return (peerIds.size()); -} - - -/* Attached should be changed to preferentially choose the ones we want - * If we have RELAYS enabled - then we want them to attach to the RELAYS - * Not sure about this yet! - * - * Have to think about it a bit more. (and redesign code to handle multiple passes) - */ - -int bdSpace::updateAttachedPeers() -{ - /* - * - */ - bool doAttached = (mAttachedCount > 0); - uint32_t attachedCount = 0; - - // Must scan through - otherwise we can never remove Attached state. - // It is only once every 10 minutes or so! -#if 0 - if (!doAttached) - { - return 0; - } -#endif - - std::map closest; - std::map::iterator mit; - - std::vector::iterator it; - std::list::reverse_iterator eit; - - - /* skip the first bucket, as we don't want to ping ourselves! */ - it = buckets.begin(); - if (it != buckets.end()) - { - it++; - } - - /* iterate through the buckets (sorted by distance) */ - for(; it != buckets.end(); it++) - { - /* start from the back, as these are the most recently seen (and more likely to be the old ATTACHED) */ - for(eit = it->entries.rbegin(); eit != it->entries.rend(); eit++) - { - if (doAttached) - { - if ((eit->mPeerFlags & mAttachedFlags) == mAttachedFlags) - { - /* flag as attached */ - eit->mExtraFlags |= BITDHT_PEER_EXFLAG_ATTACHED; - - /* inc count, and cancel search if we've found them */ - attachedCount++; - if (attachedCount >= mAttachedCount) - { - doAttached = false; - } - } - else - { - eit->mExtraFlags &= ~BITDHT_PEER_EXFLAG_ATTACHED; - } - } - else - { - eit->mExtraFlags &= ~BITDHT_PEER_EXFLAG_ATTACHED; - } - } - } - return 1; -} - - - - -/* Called to add or update peer. - * sorts bucket lists by lastRecvTime. - * updates requested node. - */ - -/* peer flags - * order is important! - * higher bits = more priority. - * BITDHT_PEER_STATUS_RECVPING - * BITDHT_PEER_STATUS_RECVPONG - * BITDHT_PEER_STATUS_RECVNODES - * BITDHT_PEER_STATUS_RECVHASHES - * BITDHT_PEER_STATUS_DHT_ENGINE (dbXXxx) - * BITDHT_PEER_STATUS_DHT_APPL (XXRSxx) - * BITDHT_PEER_STATUS_DHT_VERSION (XXxx50) - * - */ - -int bdSpace::add_peer(const bdId *id, uint32_t peerflags) -{ - /* find the peer */ - bool add = false; - time_t ts = time(NULL); - -#ifdef DEBUG_BD_SPACE - fprintf(stderr, "bdSpace::add_peer()\n"); -#endif - - /* calculate metric */ - bdMetric met; - mFns->bdDistance(&(mOwnId), &(id->id), &met); - int bucket = mFns->bdBucketDistance(&met); - -#ifdef DEBUG_BD_SPACE - fprintf(stderr, "peer:"); - mFns->bdPrintId(std::cerr, id); - fprintf(stderr, " bucket: %d", bucket); - fprintf(stderr, "\n"); -#endif - - /* select correct bucket */ - bdBucket &buck = buckets[bucket]; - - - std::list::iterator it; - - /* calculate the score for this new peer */ - uint32_t minScore = peerflags; - - /* loop through ids, to find it */ - for(it = buck.entries.begin(); it != buck.entries.end(); it++) - { - /* similar id check */ - if (mFns->bdSimilarId(id, &(it->mPeerId))) - { - bdPeer peer = *it; - it = buck.entries.erase(it); - - peer.mLastRecvTime = ts; - peer.mPeerFlags |= peerflags; /* must be cumulative ... so can do online, replynodes, etc */ - - /* also update port from incoming id, as we have definitely recved from it */ - if (mFns->bdUpdateSimilarId(&(peer.mPeerId), id)) - { - /* updated it... must be Unstable */ - peer.mExtraFlags |= BITDHT_PEER_EXFLAG_UNSTABLE; - } - - buck.entries.push_back(peer); - -#ifdef DEBUG_BD_SPACE - std::cerr << "Peer already in bucket: moving to back of the list" << std::endl; -#endif - - return 1; - } - - /* find lowest score */ - if (it->mPeerFlags < minScore) - { - minScore = it->mPeerFlags; - } - } - - /* not in the list! */ - - if (buck.entries.size() < mFns->bdNodesPerBucket()) - { -#ifdef DEBUG_BD_SPACE - std::cerr << "Bucket not full: allowing add" << std::endl; -#endif - add = true; - } - else - { - /* check head of list */ - bdPeer &peer = buck.entries.front(); - if (ts - peer.mLastRecvTime > BITDHT_MAX_RECV_PERIOD) - { -#ifdef DEBUG_BD_SPACE - std::cerr << "Dropping Out-of-Date peer in bucket" << std::endl; -#endif - buck.entries.pop_front(); - add = true; - } - else if (peerflags > minScore) - { - /* find one to drop */ - for(it = buck.entries.begin(); it != buck.entries.end(); it++) - { - if (it->mPeerFlags == minScore) - { - /* delete low priority peer */ - it = buck.entries.erase(it); - add = true; - break; - } - } - -#ifdef DEBUG_BD_SPACE - std::cerr << "Inserting due to Priority: minScore: " << minScore - << " new Peer Score: " << peerscore << << std::endl; -#endif - } - else - { -#ifdef DEBUG_BD_SPACE - std::cerr << "No Out-Of-Date peers in bucket... dropping new entry" << std::endl; -#endif - } - } - - if (add) - { - bdPeer newPeer; - - newPeer.mPeerId = *id; - newPeer.mLastRecvTime = ts; - newPeer.mLastSendTime = 0; // ts; //???? - newPeer.mFoundTime = ts; - newPeer.mPeerFlags = peerflags; - newPeer.mExtraFlags = 0; - - buck.entries.push_back(newPeer); - -#ifdef DEBUG_BD_SPACE - /* useful debug */ - std::cerr << "bdSpace::add_peer() Added Bucket["; - std::cerr << bucket << "] Entry: "; - mFns->bdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - } - return add; -} - - /* flag peer */ -bool bdSpace::flagpeer(const bdId *id, uint32_t flags, uint32_t ex_flags) -{ -#ifdef DEBUG_BD_SPACE - fprintf(stderr, "bdSpace::flagpeer()\n"); -#endif - - /* calculate metric */ - bdMetric met; - mFns->bdDistance(&(mOwnId), &(id->id), &met); - int bucket = mFns->bdBucketDistance(&met); - - - /* select correct bucket */ - bdBucket &buck = buckets[bucket]; - - /* loop through ids, to find it */ - std::list::iterator it; - for(it = buck.entries.begin(); it != buck.entries.end(); it++) - { - /* similar id check */ - if (mFns->bdSimilarId(id, &(it->mPeerId))) - { -#ifdef DEBUG_BD_SPACE - fprintf(stderr, "peer:"); - mFns->bdPrintId(std::cerr, id); - fprintf(stderr, " bucket: %d", bucket); - fprintf(stderr, "\n"); - fprintf(stderr, "Original Flags: %x Extra: %x\n", - it->mPeerFlags, it->mExtraFlags); -#endif - it->mPeerFlags |= flags; - it->mExtraFlags |= ex_flags; - -#ifdef DEBUG_BD_SPACE - fprintf(stderr, "Updated Flags: %x Extra: %x\n", - it->mPeerFlags, it->mExtraFlags); -#endif - } - } - return true; -} - -/* print tables. - */ - -int bdSpace::printDHT() -{ - std::map closest; - std::map::iterator mit; - - std::vector::iterator it; - std::list::iterator eit; - - /* iterate through the buckets, and sort by distance */ - int i = 0; - -#ifdef BITDHT_DEBUG - fprintf(stderr, "bdSpace::printDHT()\n"); - for(it = buckets.begin(); it != buckets.end(); it++, i++) - { - if (it->entries.size() > 0) - { - fprintf(stderr, "Bucket %d ----------------------------\n", i); - } - - for(eit = it->entries.begin(); eit != it->entries.end(); eit++) - { - bdMetric dist; - mFns->bdDistance(&(mOwnId), &(eit->mPeerId.id), &dist); - - fprintf(stderr, " Metric: "); - mFns->bdPrintNodeId(std::cerr, &(dist)); - fprintf(stderr, " Id: "); - mFns->bdPrintId(std::cerr, &(eit->mPeerId)); - fprintf(stderr, " PeerFlags: %08x", eit->mPeerFlags); - fprintf(stderr, "\n"); - } - } -#endif - - fprintf(stderr, "--------------------------------------\n"); - fprintf(stderr, "DHT Table Summary --------------------\n"); - fprintf(stderr, "--------------------------------------\n"); - - /* little summary */ - unsigned long long sum = 0; - unsigned long long no_peers = 0; - uint32_t count = 0; - bool doPrint = false; - bool doAvg = false; - - i = 0; - for(it = buckets.begin(); it != buckets.end(); it++, i++) - { - int size = it->entries.size(); - int shift = BITDHT_KEY_BITLEN - i; - bool toBig = false; - - if (shift > BITDHT_ULLONG_BITS - mFns->bdBucketBitSize() - 1) - { - toBig = true; - shift = BITDHT_ULLONG_BITS - mFns->bdBucketBitSize() - 1; - } - unsigned long long no_nets = ((unsigned long long) 1 << shift); - - /* use doPrint so it acts as a single switch */ - if (size && !doAvg && !doPrint) - { - doAvg = true; - } - - if (size && !doPrint) - { - doPrint = true; - } - - if (size == 0) - { - /* reset counters - if empty slot - to discount outliers in average */ - sum = 0; - no_peers = 0; - count = 0; - } - - if (doPrint) - { - if (size) - fprintf(stderr, "Bucket %d: %d peers: ", i, size); -#ifdef BITDHT_DEBUG - else - fprintf(stderr, "Bucket %d: %d peers: ", i, size); -#endif - } - if (toBig) - { - if (size) - { - if (doPrint) - bd_fprintf(stderr, "Estimated NetSize >> %llu\n", no_nets); - } - else - { -#ifdef BITDHT_DEBUG - if (doPrint) - bd_fprintf(stderr, " Bucket = Net / >> %llu\n", no_nets); -#endif - } - } - else - { - no_peers = no_nets * size; - if (size) - { - if (doPrint) - bd_fprintf(stderr, "Estimated NetSize = %llu\n", no_peers); - } - else - { - -#ifdef BITDHT_DEBUG - if (doPrint) - bd_fprintf(stderr, " Bucket = Net / %llu\n", no_nets); -#endif - - } - } - if (doPrint && doAvg && !toBig) - { - if (size == mFns->bdNodesPerBucket()) - { - /* last average */ - doAvg = false; - } - if (no_peers != 0) - { - sum += no_peers; - count++; -#ifdef BITDHT_DEBUG - fprintf(stderr, "Est: %d: %llu => %llu / %d\n", - i, no_peers, sum, count); -#endif - } - } - - } - if (count == 0) - { - fprintf(stderr, "Zero Network Size (count = 0)\n"); - } - else - { - bd_fprintf(stderr, "Estimated Network Size = (%llu / %d) = %llu\n", sum, count, sum / count); - } - - return 1; -} - - -int bdSpace::getDhtBucket(const int idx, bdBucket &bucket) -{ - if ((idx < 0) || (idx > (int) buckets.size() - 1 )) - { - return 0; - } - bucket = buckets[idx]; - return 1; -} - -uint32_t bdSpace::calcNetworkSize() -{ - return calcNetworkSizeWithFlag(~0u) ; -} - -uint32_t bdSpace::calcNetworkSizeWithFlag(uint32_t withFlag) -{ - std::vector::iterator it; - - /* little summary */ - unsigned long long sum = 0; - unsigned long long no_peers = 0; - uint32_t count = 0; - -#ifdef BITDHT_DEBUG - std::cerr << "Estimating DHT network size. Flags=" << std::hex << withFlag << std::dec << std::endl; -#endif - - int i = 0; - for(it = buckets.begin(); it != buckets.end(); it++, i++) - { - int size = 0; - std::list::iterator lit; - for(lit = it->entries.begin(); lit != it->entries.end(); lit++) - if (withFlag & lit->mPeerFlags) - size++; - - int shift = BITDHT_KEY_BITLEN - i; - - if (shift > BITDHT_ULLONG_BITS - mFns->bdBucketBitSize() - 1) - continue ; - - unsigned long long no_nets = ((unsigned long long) 1 << shift); - - no_peers = no_nets * size; - - if(size < mFns->bdNodesPerBucket() && size > 0) - { - sum += no_peers; - count++; - } - -#ifdef BITDHT_DEBUG - if(size > 0) - std::cerr << " Bucket " << shift << ": " << size << " / " << mFns->bdNodesPerBucket() << " peers. no_nets=" << no_nets << ". no_peers=" << no_peers << "." << std::endl; -#endif - } - - - uint32_t NetSize = 0; - if (count != 0) - NetSize = sum / count; - -#ifdef BITDHT_DEBUG - std::cerr << "Estimated net size: " << NetSize << ". Old style estimate: " << calcNetworkSizeWithFlag_old(withFlag) << std::endl; -#endif - - return NetSize; -} - -/* (csoler) This is the old method for computing the DHT size estimate. The method is based on averaging the - * estimate given by each bucket: n 2^b where n is the bucket size and b is the number of similar bits - * in this bucket. The idea is that buckets that are not empty nor full give a estimate of the network - * size. - * - * The existing implementation of this method was not using all non empty/full buckets, in order to avoid - * outliers, but this method is also biased, and tends to give a lower value (because it skips the largest buckets) - * especially when the network is very sparse. - * - * The new implementation respects the original estimate without bias, but it still notoriously wrong. Only averaging - * the estimate over a large period of time would produce a reliable value. - */ -uint32_t bdSpace::calcNetworkSizeWithFlag_old(uint32_t withFlag) -{ - std::vector::iterator it; - - /* little summary */ - unsigned long long sum = 0; - unsigned long long no_peers = 0; - uint32_t count = 0; - uint32_t totalcount = 0; - bool doPrint = false; - bool doAvg = false; - - int i = 0; - for(it = buckets.begin(); it != buckets.end(); it++, i++) - { - int size = 0; - std::list::iterator lit; - for(lit = it->entries.begin(); lit != it->entries.end(); lit++) - { - if (withFlag & lit->mPeerFlags) - { - size++; - } - } - - totalcount += size; - - int shift = BITDHT_KEY_BITLEN - i; - bool toBig = false; - - if (shift > BITDHT_ULLONG_BITS - mFns->bdBucketBitSize() - 1) - { - toBig = true; - shift = BITDHT_ULLONG_BITS - mFns->bdBucketBitSize() - 1; - } - unsigned long long no_nets = ((unsigned long long) 1 << shift); - - - /* use doPrint so it acts as a single switch */ - if (size && !doAvg && !doPrint) - { - doAvg = true; - } - - if (size && !doPrint) - { - doPrint = true; - } - - if (size == 0) - { - /* reset counters - if empty slot - to discount outliers in average */ - sum = 0; - no_peers = 0; - count = 0; - } - - if (!toBig) - { - no_peers = no_nets * size; - } - - if (doPrint && doAvg && !toBig) - { - if (size == mFns->bdNodesPerBucket()) - { - /* last average */ - doAvg = false; - } - if (no_peers != 0) - { - sum += no_peers; - count++; - } - } - } - - - uint32_t NetSize = 0; - if (count != 0) - { - NetSize = sum / count; - } - - //std::cerr << "bdSpace::calcNetworkSize() : " << NetSize; - //std::cerr << std::endl; - - return NetSize; -} - -uint32_t bdSpace::calcSpaceSize() -{ - std::vector::iterator it; - - /* little summary */ - uint32_t totalcount = 0; - for(it = buckets.begin(); it != buckets.end(); it++) - { - totalcount += it->entries.size(); - } - return totalcount; -} - -uint32_t bdSpace::calcSpaceSizeWithFlag(uint32_t withFlag) -{ - std::vector::iterator it; - - /* little summary */ - uint32_t totalcount = 0; - - it = buckets.begin(); - if (it != buckets.end()) - { - it++; /* skip own bucket! */ - } - for(; it != buckets.end(); it++) - { - int size = 0; - std::list::iterator lit; - for(lit = it->entries.begin(); lit != it->entries.end(); lit++) - { - if (withFlag & lit->mPeerFlags) - { - size++; - } - } - totalcount += size; - } - return totalcount; -} - - /* special function to enable DHT localisation (i.e find peers from own network) */ -bool bdSpace::findRandomPeerWithFlag(bdId &id, uint32_t withFlag) -{ - std::vector::iterator it; - uint32_t totalcount = calcSpaceSizeWithFlag(withFlag); - - if(totalcount == 0) - return false ; - - uint32_t rnd = bdRandom::random_u32() % totalcount; - uint32_t i = 0; - uint32_t buck = 0; - - //std::cerr << "bdSpace::findRandomPeerWithFlag()"; - //std::cerr << std::endl; - - it = buckets.begin(); - if (it != buckets.end()) - { - it++; /* skip own bucket! */ - buck++; - } - for(; it != buckets.end(); it++, buck++) - { - std::list::iterator lit; - for(lit = it->entries.begin(); lit != it->entries.end(); lit++) - { - if (withFlag & lit->mPeerFlags) - { - if (i == rnd) - { -#ifdef BITDHT_DEBUG - std::cerr << "bdSpace::findRandomPeerWithFlag() found #" << i; - std::cerr << " in bucket #" << buck; - std::cerr << std::endl; -#endif - /* found */ - id = lit->mPeerId; - return true; - } - i++; - } - } - } - std::cerr << "bdSpace::findRandomPeerWithFlag() failed to find " << rnd << " / " << totalcount; - std::cerr << std::endl; -#ifdef BITDHT_DEBUG -#endif - - return false; -} - diff --git a/libbitdht/src/bitdht/bdpeer.h b/libbitdht/src/bitdht/bdpeer.h deleted file mode 100644 index d663a7ecd..000000000 --- a/libbitdht/src/bitdht/bdpeer.h +++ /dev/null @@ -1,212 +0,0 @@ -/******************************************************************************* - * bitdht/bdpeer.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef BITDHT_PEER_H -#define BITDHT_PEER_H - -#include "bitdht/bdiface.h" -#include - -/******* - * These type of parameters are now DHT Function dependent - * -#define BITDHT_BUCKET_SIZE 20 -#define BITDHT_BUCKET_SIZE_BITS 5 - -#define BITDHT_N_BUCKETS BITDHT_KEY_BITLEN - * - * - ***/ - -/*** - * DEFINED in bdiface.h - * #define BITDHT_KEY_LEN 20 - * #define BITDHT_KEY_INTLEN 5 - * #define BITDHT_KEY_BITLEN 160 - ***/ - -#define BITDHT_ULLONG_BITS 64 - -#define BITDHT_MAX_RESPONSE_PERIOD (15) -#define BITDHT_MAX_SEND_PERIOD 300 // 5 minutes. -#define BITDHT_MAX_RECV_PERIOD (BITDHT_MAX_SEND_PERIOD + BITDHT_MAX_RESPONSE_PERIOD) // didn't respond to a ping. - -// Properly out of date. -#define BITDHT_DISCARD_PERIOD (2 * BITDHT_MAX_SEND_PERIOD + BITDHT_MAX_RESPONSE_PERIOD) // didn't respond to two pings. - -// Must have a FLAG by this time. (Make it really quick - so we through away the rubbish). - - -#include -#include -#include -#include - -/**** - * DEFINED in bdiface.h - * - * class bdNodeId - * { - * public: - * unsigned char data[BITDHT_KEY_LEN]; - * }; - ****/ - - -/**** - * DEFINED in bdiface.h - * - -class bdMetric: public bdNodeId {}; - -class bdId -{ - public: - - bdId(); - bdId(bdNodeId in_id, struct sockaddr_in in_addr); - - struct sockaddr_in addr; - bdNodeId id; -}; - * - *********/ - - - -//void bdRandomNodeId(bdNodeId *id); - -// Only Functions that are common for all Dhts. -// zero, basic comparisons.. -void bdZeroNodeId(bdNodeId *id); - -//void bdRandomId(bdId *id); -//int bdDistance(const bdNodeId *a, const bdNodeId *b, bdMetric *r); -//int bdBucketDistance(const bdMetric *m); -//int bdBucketDistance(const bdNodeId *a, const bdNodeId *b); -//int operator<(const bdMetric &a, const bdMetric &b); - -//int operator<(const struct sockaddr_in &a, const struct sockaddr_in &b); - -int operator<(const bdNodeId &a, const bdNodeId &b); -int operator<(const bdId &a, const bdId &b); -int operator==(const bdNodeId &a, const bdNodeId &b); -int operator==(const bdId &a, const bdId &b); - -//void bdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *mid); - -//void bdPrintId(std::ostream &out, const bdId *a); -//void bdPrintNodeId(std::ostream &out, const bdNodeId *a); - -//std::string bdConvertToPrintable(std::string input); - -/**** - * DEFINED in bdiface.h - * - -class bdPeer -{ - public: - - bdId mPeerId; - uint32_t mPeerFlags; - time_t mLastSendTime; - time_t mLastRecvTime; - time_t mFoundTime; // time stamp that peer was found -}; - - -class bdBucket -{ - public: - - bdBucket(); - - // list so we can queue properly - std::list entries; -}; - * - * - *****/ - -class bdSpace -{ - public: - - bdSpace(bdNodeId *ownId, bdDhtFunctions *fns); - -int clear(); - -int setAttachedFlag(uint32_t withflags, int count); - - /* accessors */ -int find_nearest_nodes(const bdNodeId *id, int number, - std::multimap &nearest); - -int find_nearest_nodes_with_flags(const bdNodeId *id, int number, - std::list excluding, - std::multimap &nearest, uint32_t with_flag); - -int find_node(const bdNodeId *id, int number, - std::list &matchIds, uint32_t with_flag); -int find_exactnode(const bdId *id, bdPeer &peer); - -// switched to more efficient single sweep. -//int out_of_date_peer(bdId &id); // side-effect updates, send flag on peer. -int scanOutOfDatePeers(std::list &peerIds); -int updateAttachedPeers(); - -int add_peer(const bdId *id, uint32_t mode); -int printDHT(); -int getDhtBucket(const int idx, bdBucket &bucket); - -uint32_t calcNetworkSize(); -uint32_t calcNetworkSizeWithFlag(uint32_t withFlag); -uint32_t calcNetworkSizeWithFlag_old(uint32_t withFlag); -uint32_t calcSpaceSize(); -uint32_t calcSpaceSizeWithFlag(uint32_t withFlag); - - /* special function to enable DHT localisation (i.e find peers from own network) */ -bool findRandomPeerWithFlag(bdId &id, uint32_t withFlag); - - /* strip out flags - to switch in/out of relay mode */ -int clean_node_flags(uint32_t flags); - - /* to add later */ -int updateOwnId(bdNodeId *newOwnId); - - /* flag peer */ -bool flagpeer(const bdId *id, uint32_t flags, uint32_t ex_flags); - - private: - - std::vector buckets; - bdNodeId mOwnId; - bdDhtFunctions *mFns; - - uint32_t mAttachedFlags; - uint32_t mAttachedCount; - time_t mAttachTS; -}; - - -#endif - diff --git a/libbitdht/src/bitdht/bdquery.cc b/libbitdht/src/bitdht/bdquery.cc deleted file mode 100644 index f9b77002d..000000000 --- a/libbitdht/src/bitdht/bdquery.cc +++ /dev/null @@ -1,1198 +0,0 @@ -/******************************************************************************* - * bitdht/bdquery.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "bitdht/bdquery.h" -#include "bitdht/bdstddht.h" -#include "util/bdnet.h" - -#include -#include -#include - -/** - * #define DEBUG_QUERY 1 -**/ - -#define EXPECTED_REPLY 10 // Speed up queries -#define QUERY_IDLE_RETRY_PEER_PERIOD 600 // 10min = (mFns->bdNumQueryNodes() * 60) -#define MAX_QUERY_IDLE_PERIOD 1200 // 20min. - - -/************************************************************ - * bdQuery logic: - * 1) as replies come in ... maintain list of M closest peers to ID. - * 2) select non-queried peer from list, and query. - * 3) halt when we have asked all M closest peers about the ID. - * - * Flags can be set to disguise the target of the search. - * This involves - */ - -bdQuery::bdQuery(const bdNodeId *id, std::list &startList, uint32_t queryFlags, - bdDhtFunctions *fns) -{ - /* */ - mId = *id; - mFns = fns; - - time_t now = time(NULL); - std::list::iterator it; - for(it = startList.begin(); it != startList.end(); it++) - { - bdPeer peer; - peer.mLastSendTime = 0; - peer.mLastRecvTime = 0; - peer.mPeerFlags = 0; - peer.mFoundTime = now; - peer.mPeerId = *it; - - bdMetric dist; - - mFns->bdDistance(&mId, &(peer.mPeerId.id), &dist); - - mClosest.insert(std::pair(dist, peer)); - - - } - - mState = BITDHT_QUERY_QUERYING; - mQueryFlags = queryFlags; - mQueryTS = now; - mSearchTime = 0; - mClosestListSize = (int) (1.5 * mFns->bdNumQueryNodes()); - mPotPeerCleanTS = now; - - mQueryIdlePeerRetryPeriod = QUERY_IDLE_RETRY_PEER_PERIOD; - mRequiredPeerFlags = BITDHT_PEER_STATUS_DHT_ENGINE_VERSION; // XXX to update later. - - /* setup the limit of the search - * by default it is setup to 000000 = exact match - */ - bdZeroNodeId(&mLimit); -} - -bool bdQuery::result(std::list &answer) -{ - /* get all the matches to our query */ - std::multimap::iterator sit, eit; - sit = mClosest.begin(); - eit = mClosest.upper_bound(mLimit); - int i = 0; - for(; sit != eit; sit++) - { - if ((sit->second).mLastRecvTime != 0) - { - answer.push_back(sit->second.mPeerId); - i++; - } - } - return (i > 0); -} - - -int bdQuery::nextQuery(bdId &id, bdNodeId &targetNodeId) -{ - if ((mState != BITDHT_QUERY_QUERYING) && !(mQueryFlags & BITDHT_QFLAGS_DO_IDLE)) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "NextQuery() Query is done\n"); -#endif - return 0; - } - - /* search through through list, find closest not queried */ - time_t now = time(NULL); - - /* update IdlePeerRetry */ - if ((now - mQueryTS) / 2 > mQueryIdlePeerRetryPeriod) - { - mQueryIdlePeerRetryPeriod = (now-mQueryTS) / 2; - if (mQueryIdlePeerRetryPeriod > MAX_QUERY_IDLE_PERIOD) - { - mQueryIdlePeerRetryPeriod = MAX_QUERY_IDLE_PERIOD; - } - } - - bool notFinished = false; - std::multimap::iterator it; - int i = 0; - for(it = mClosest.begin(); it != mClosest.end(); it++, i++) - { - bool queryPeer = false; - - /* if never queried */ - if (it->second.mLastSendTime == 0) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "NextQuery() Found non-sent peer. queryPeer = true : "); - mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); - std::cerr << std::endl; -#endif - queryPeer = true; - } - - /* re-request every so often */ - if ((!queryPeer) && (mQueryFlags & BITDHT_QFLAGS_DO_IDLE) && - (now - it->second.mLastSendTime > mQueryIdlePeerRetryPeriod)) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "NextQuery() Found out-of-date. queryPeer = true : "); - mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); - std::cerr << std::endl; -#endif - queryPeer = true; - } - - /* expecting every peer to be up-to-date is too hard... - * enough just to have received lists from each - * - replacement policy will still work. - * - * Need to wait at least EXPECTED_REPLY, to make sure their answers are pinged - */ - - if (((it->second.mLastRecvTime == 0) || (now - it->second.mLastRecvTime < EXPECTED_REPLY)) && - (i < mFns->bdNumQueryNodes())) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "NextQuery() Never Received @Idx(%d) notFinished = true: ", i); - mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); - std::cerr << std::endl; -#endif - notFinished = true; - } - - if (queryPeer) - { - id = it->second.mPeerId; - it->second.mLastSendTime = now; - - if (mQueryFlags & BITDHT_QFLAGS_DISGUISE) - { - /* calc Id mid point between Target and Peer */ - bdNodeId midRndId; - mFns->bdRandomMidId(&mId, &(id.id), &midRndId); - - targetNodeId = midRndId; - } - else - { - targetNodeId = mId; - } -#ifdef DEBUG_QUERY - fprintf(stderr, "NextQuery() Querying Peer: "); - mFns->bdPrintId(std::cerr, &id); - std::cerr << std::endl; -#endif - return 1; - } - } - - /* allow query to run for a minimal amount of time - * This is important as startup - when we might not have any peers. - * Probably should be handled elsewhere. - */ - time_t age = now - mQueryTS; - - if (age < BITDHT_MIN_QUERY_AGE) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "NextQuery() under Min Time: Query not finished / No Query\n"); -#endif - return 0; - } - - if (age > BITDHT_MAX_QUERY_AGE) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "NextQuery() over Max Time: Query force to Finish\n"); -#endif - /* fall through and stop */ - } - else if ((mClosest.size() < mFns->bdNumQueryNodes()) || (notFinished)) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "NextQuery() notFinished | !size(): Query not finished / No Query\n"); -#endif - /* not full yet... */ - return 0; - } - -#ifdef DEBUG_QUERY - fprintf(stderr, "NextQuery() Finished\n"); -#endif - - /* if we get here - query finished */ - if (mState == BITDHT_QUERY_QUERYING) - { - /* store query time */ - mSearchTime = now - mQueryTS; - } - - /* cleanup PotentialPeers before doing the final State */; - removeOldPotentialPeers(); - /* check if we found the node */ - if (mClosest.size() > 0) - { - if (((mClosest.begin()->second).mPeerId.id == mId) && - ((mClosest.begin()->second).mLastRecvTime != 0)) - { - mState = BITDHT_QUERY_SUCCESS; - } - else if ((mPotentialPeers.begin()->second).mPeerId.id == mId) - { - mState = BITDHT_QUERY_PEER_UNREACHABLE; - } - else - { - mState = BITDHT_QUERY_FOUND_CLOSEST; - } - } - else - { - mState = BITDHT_QUERY_FAILURE; - } - return 0; -} - -int bdQuery::addClosestPeer(const bdId *id, uint32_t mode) -{ - bdMetric dist; - time_t ts = time(NULL); - - mFns->bdDistance(&mId, &(id->id), &dist); - -#ifdef DEBUG_QUERY - fprintf(stderr, "bdQuery::addPeer("); - mFns->bdPrintId(std::cerr, id); - fprintf(stderr, ", %u)\n", mode); -#endif - - std::multimap::iterator it, sit, eit; - sit = mClosest.lower_bound(dist); - eit = mClosest.upper_bound(dist); - int i = 0; - int actualCloser = 0; - int toDrop = 0; - // switched end condition to upper_bound to provide stability for NATTED peers. - // we will favour the older entries! - for(it = mClosest.begin(); it != eit; it++, i++, actualCloser++) - { - time_t sendts = ts - it->second.mLastSendTime; - bool hasSent = (it->second.mLastSendTime != 0); - bool hasReply = (it->second.mLastRecvTime >= it->second.mLastSendTime); - if ((hasSent) && (!hasReply) && (sendts > EXPECTED_REPLY)) - { - i--; /* dont count this one */ - toDrop++; - } - } - // Counts where we are. -#ifdef DEBUG_QUERY - fprintf(stderr, "Searching.... %di = %d - %d peers closer than this one\n", i, actualCloser, toDrop); -#endif - - - if (i > mClosestListSize - 1) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "Distance to far... dropping\n"); -#endif - /* drop it */ - return 0; - } - - for(it = sit; it != eit; it++, i++) - { - /* full id check */ - if (mFns->bdSimilarId(id, &(it->second.mPeerId))) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "Peer Already here!\n"); -#endif - if (mode) - { - /* also update port from incoming id, as we have definitely recved from it */ - if (mFns->bdUpdateSimilarId(&(it->second.mPeerId), id)) - { - /* updated it... must be Unstable */ - it->second.mExtraFlags |= BITDHT_PEER_EXFLAG_UNSTABLE; - } - } - if (mode & BITDHT_PEER_STATUS_RECV_NODES) - { - /* only update recvTime if sendTime > checkTime.... (then its our query) */ -#ifdef DEBUG_QUERY - fprintf(stderr, "Updating LastRecvTime\n"); -#endif - it->second.mLastRecvTime = ts; - it->second.mPeerFlags |= mode; - } - return 1; - } - } - -#ifdef DEBUG_QUERY - fprintf(stderr, "Peer not in Query\n"); -#endif - /* firstly drop unresponded (bit ugly - but hard structure to extract from) */ - int j; - for(j = 0; j < toDrop; j++) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "Dropping Peer that dont reply\n"); -#endif - for(it = mClosest.begin(); it != mClosest.end(); ++it) - { - time_t sendts = ts - it->second.mLastSendTime; - bool hasSent = (it->second.mLastSendTime != 0); - bool hasReply = (it->second.mLastRecvTime >= it->second.mLastSendTime); - - if ((hasSent) && (!hasReply) && (sendts > EXPECTED_REPLY)) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "Dropped: "); - mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); - fprintf(stderr, "\n"); -#endif - mClosest.erase(it); - break ; - } - } - } - - /* trim it back */ - while(mClosest.size() > (uint32_t) (mClosestListSize - 1)) - { - std::multimap::iterator it; - it = mClosest.end(); - if (!mClosest.empty()) - { - it--; -#ifdef DEBUG_QUERY - fprintf(stderr, "Removing Furthest Peer: "); - mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); - fprintf(stderr, "\n"); -#endif - - mClosest.erase(it); - } - } - -#ifdef DEBUG_QUERY - fprintf(stderr, "bdQuery::addPeer(): Closer Peer!: "); - mFns->bdPrintId(std::cerr, id); - fprintf(stderr, "\n"); -#endif - - /* add it in */ - bdPeer peer; - peer.mPeerId = *id; - peer.mPeerFlags = mode; - peer.mLastSendTime = 0; - peer.mLastRecvTime = 0; - peer.mFoundTime = ts; - - if (mode & BITDHT_PEER_STATUS_RECV_NODES) - { - peer.mLastRecvTime = ts; - } - - mClosest.insert(std::pair(dist, peer)); - return 1; -} - - -/******************************************************************************************* - ********************************* Add Peer Interface ************************************* - *******************************************************************************************/ - -/**** These functions are called by bdNode to add peers to the query - * They add/update the three sets of lists. - * - * int bdQuery::addPeer(const bdId *id, uint32_t mode) - * Proper message from a peer. - * - * int bdQuery::addPotentialPeer(const bdId *id, const bdId *src, uint32_t srcmode) - * This returns 1 if worthy of pinging, 0 if to ignore. - */ - -#define PEER_MESSAGE 0 -#define FIND_NODE_RESPONSE 1 - -int bdQuery::addPeer(const bdId *id, uint32_t mode) -{ - addClosestPeer(id, mode); - updatePotentialPeer(id, mode, PEER_MESSAGE); - updateProxy(id, mode); - return 1; -} - -int bdQuery::addPotentialPeer(const bdId *id, const bdId *src, uint32_t srcmode) -{ - // is it a Potential Proxy? Always Check This. - addProxy(id, src, srcmode); - - int worthy = worthyPotentialPeer(id); - int shouldPing = 0; - if (worthy) - { - shouldPing = updatePotentialPeer(id, 0, FIND_NODE_RESPONSE); - } - return shouldPing; -} - - -/******************************************************************************************* - ********************************* Closest Peer ******************************************** - *******************************************************************************************/ - - -/******************************************************************************************* - ******************************** Potential Peer ******************************************* - *******************************************************************************************/ - - - - -/******* - * Potential Peers are a list of the closest answers to our queries. - * Lots of these peers will not be reachable.... so will only exist in this list. - * They will also never have there PeerFlags set ;( - * - */ - - -/*** utility functions ***/ - -int bdQuery::worthyPotentialPeer(const bdId *id) -{ - bdMetric dist; - mFns->bdDistance(&mId, &(id->id), &dist); - -#ifdef DEBUG_QUERY - std::cerr << "bdQuery::worthyPotentialPeer("; - mFns->bdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - - /* we check if this is a worthy potential peer.... - * if it is already in mClosest -> false. old peer. - * if it is > mClosest.rbegin() -> false. too far way. - */ - - std::multimap::iterator it, sit, eit; - sit = mClosest.lower_bound(dist); - eit = mClosest.upper_bound(dist); - - /* check if outside range, & bucket is full */ - if ((sit == mClosest.end()) && (mClosest.size() >= mFns->bdNumQueryNodes())) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "Peer to far away for Potential\n"); -#endif - return 0; /* too far way */ - } - - - for(it = sit; it != eit; it++) - { - if (mFns->bdSimilarId(id, &(it->second.mPeerId))) - { - // Not updating Full Peer Id here... as inspection function. -#ifdef DEBUG_QUERY - fprintf(stderr, "Peer already in mClosest\n"); -#endif - return 0; - } - } - - return 1; /* either within mClosest Range (but not there!), or there aren't enough peers */ -} - - -/***** - * - * mLastSendTime ... is the last FIND_NODE_RESPONSE that we returned 1. (indicating to PING). - * mLastRecvTime ... is the last time we received an updatei about/from them - * - * The update is dependent on the flags passed in the function call. (saves duplicate code). - * - * - * XXX IMPORTANT TO DECIDE WHAT IS RETURNED HERE. - * original algorithm return 0 if exists in potential peers, 1 if unknown. - * This is used to limit the number of pings to non-responding potentials. - * - * MUST think about this. Need to install HISTORY tracking again. to look at the statistics. - * - * It is important that the potential Peers list extends all the way back to == mClosest().end(). - * Otherwise we end up with [TARGET] .... [ POTENTIAL ] ..... [ CLOSEST ] ...... - * and the gap between POT and CLOSEST will get hammered with pings. - * - */ - -#define MIN_PING_POTENTIAL_PERIOD 300 - -int bdQuery::updatePotentialPeer(const bdId *id, uint32_t mode, uint32_t addType) -{ - bdMetric dist; - time_t now = time(NULL); - - mFns->bdDistance(&mId, &(id->id), &dist); - - std::multimap::iterator it, sit, eit; - sit = mPotentialPeers.lower_bound(dist); - eit = mPotentialPeers.upper_bound(dist); - - for(it = sit; it != eit; it++) - { - if (mFns->bdSimilarId(id, &(it->second.mPeerId))) - { - - it->second.mPeerFlags |= mode; - it->second.mLastRecvTime = now; - if (addType == FIND_NODE_RESPONSE) - { - // We could lose peers here by not updating port... but should be okay. - if (now - it->second.mLastSendTime > MIN_PING_POTENTIAL_PERIOD) - { - it->second.mLastSendTime = now; - return 1; - } - } - else if (mode) - { - /* also update port from incoming id, as we have definitely recved from it */ - if (mFns->bdUpdateSimilarId(&(it->second.mPeerId), id)) - { - /* updated it... must be Unstable */ - it->second.mExtraFlags |= BITDHT_PEER_EXFLAG_UNSTABLE; - } - } - return 0; - } - } - -// Removing this check - so that we can have varying length PotentialPeers. -// Peer will always be added, then probably removed straight away. - -#if 0 - /* check if outside range, & bucket is full */ - if ((sit == mPotentialPeers.end()) && (mPotentialPeers.size() >= mFns->bdNumQueryNodes())) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "Peer to far away for Potential\n"); -#endif - return 0; - } -#endif - - /* add it in */ - bdPeer peer; - peer.mPeerId = *id; - peer.mPeerFlags = mode; - peer.mFoundTime = now; - peer.mLastRecvTime = now; - peer.mLastSendTime = 0; - if (addType == FIND_NODE_RESPONSE) - { - peer.mLastSendTime = now; - } - - mPotentialPeers.insert(std::pair(dist, peer)); - -#ifdef DEBUG_QUERY - fprintf(stderr, "Flagging as Potential Peer!\n"); -#endif - - trimPotentialPeers_toClosest(); - - return 1; -} - - -int bdQuery::trimPotentialPeers_FixedLength() -{ - /* trim it back */ - while(mPotentialPeers.size() > (uint32_t) (mFns->bdNumQueryNodes())) - { - std::multimap::iterator it; - it = mPotentialPeers.end(); - it--; // must be more than 1 peer here? -#ifdef DEBUG_QUERY - fprintf(stderr, "Removing Furthest Peer: "); - mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); - fprintf(stderr, "\n"); -#endif - mPotentialPeers.erase(it); - } - return 1; -} - - -int bdQuery::trimPotentialPeers_toClosest() -{ - if (mPotentialPeers.size() <= (uint32_t) (mFns->bdNumQueryNodes())) - return 1; - - std::multimap::reverse_iterator it; - it = mClosest.rbegin(); - bdMetric lastClosest = it->first; - - /* trim it back */ - while(mPotentialPeers.size() > (uint32_t) (mFns->bdNumQueryNodes())) - { - std::multimap::iterator it; - it = mPotentialPeers.end(); - it--; // must be more than 1 peer here? - if (lastClosest < it->first) - { -#ifdef DEBUG_QUERY - fprintf(stderr, "Removing Furthest Peer: "); - mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); - fprintf(stderr, "\n"); -#endif - mPotentialPeers.erase(it); - } - else - { - return 1; - } - } - return 1; -} - - -/* as Potential Peeers are to determine if a peer is CLOSEST or UNREACHABLE - * we need to drop ones that we haven't heard about in ages. - * - * only do this in IDLE mode... - * The timeout period is dependent on our RetryPeriod. - */ - -#define POT_PEER_CLEAN_PERIOD 60 -#define POT_PEER_RECV_TIMEOUT_PERIOD (mQueryIdlePeerRetryPeriod + EXPECTED_REPLY) - -int bdQuery::removeOldPotentialPeers() -{ - if (!(mQueryFlags & BITDHT_QFLAGS_DO_IDLE)) - { - return 0; - } - - time_t now = time(NULL); - if (now - mPotPeerCleanTS < POT_PEER_CLEAN_PERIOD) - { - return 0; - } - - mPotPeerCleanTS = now; - - /* painful loop */ - std::multimap::iterator it; - for(it = mPotentialPeers.begin(); it != mPotentialPeers.end();) - { - /* which timestamp do we care about? */ - if (now - it->second.mLastRecvTime > POT_PEER_RECV_TIMEOUT_PERIOD) - { -#ifdef DEBUG_QUERY - std::cerr << "bdQuery::removeOldPotentialPeers() removing: "; - mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); - fprintf(stderr, "\n"); -#endif - std::multimap::iterator it2 = it; - ++it2 ; - mPotentialPeers.erase(it); - it = it2 ; - - // Unfortunately have to start again... as pointers invalidated. - //it = mPotentialPeers.begin(); - } - else - { - ++it; - } - } - return 1 ; -} - - - -/******************************************************************************************* - ******************************** Potential Proxies **************************************** - *******************************************************************************************/ - -/******** - * Potential Proxies. a list of peers that have returned our target in response to a query. - * - * We are particularly interested in peers with specific flags... - * But all the peers have been pinged already by the time they reach this list. - * So there are two options: - * 1) Track everythings mode history - which is a waste of resources. - * 2) Store the list, and ping later. - * - * We will store these in two lists: Flags & Unknown. - * we keep the most recent of each, and move around as required. - * - * we could also check the Closest/PotentialPeer lists to grab the flags, - * for an unknown peer? - * - * All Functions manipulating PotentialProxies are here. - * We need several functions: - * - * For Extracting Proxies. -bool bdQuery::proxies(std::list &answer) -bool bdQuery::potentialProxies(std::list &answer) - * - * For Adding/Updating Proxies. -int bdQuery::addProxy(const bdId *id, const bdId *src, uint32_t srcmode) -int bdQuery::updateProxy(const bdId *id, uint32_t mode) - * - */ - -/*** Two Functions to extract Proxies... ***/ -bool bdQuery::proxies(std::list &answer) -{ - /* get all the matches to our query */ - std::list::iterator it; - int i = 0; - for(it = mProxiesFlagged.begin(); it != mProxiesFlagged.end(); it++, i++) - { - answer.push_back(it->mPeerId); - } - return (i > 0); -} - -bool bdQuery::potentialProxies(std::list &answer) -{ - /* get all the matches to our query */ - std::list::iterator it; - int i = 0; - for(it = mProxiesUnknown.begin(); it != mProxiesUnknown.end(); it++, i++) - { - answer.push_back(it->mPeerId); - } - return (i > 0); -} - - - -int bdQuery::addProxy(const bdId *id, const bdId *src, uint32_t srcmode) -{ - bdMetric dist; - time_t now = time(NULL); - - mFns->bdDistance(&mId, &(id->id), &dist); - - /* finally if it is an exact match, add as potential proxy */ - int bucket = mFns->bdBucketDistance(&dist); - if ((bucket != 0) || (src == NULL)) - { - /* not a potential proxy */ - return 0; - } - -#ifdef DEBUG_QUERY - fprintf(stderr, "Bucket = 0, Have Potential Proxy!\n"); -#endif - - bool found = false; - if (updateProxyList(src, srcmode, mProxiesUnknown)) - { - found = true; - } - - if (!found) - { - if (updateProxyList(src, srcmode, mProxiesFlagged)) - { - found = true; - } - } - - if (!found) - { - /* if we get here. its not in the list */ -#ifdef DEBUG_QUERY - fprintf(stderr, "Adding Source to Proxy List:\n"); -#endif - bdPeer peer; - peer.mPeerId = *src; - peer.mPeerFlags = srcmode; - peer.mLastSendTime = 0; - peer.mLastRecvTime = now; - peer.mFoundTime = now; - - /* add it in */ - if ((srcmode & mRequiredPeerFlags) == mRequiredPeerFlags) - { - mProxiesFlagged.push_front(peer); - } - else - { - mProxiesUnknown.push_front(peer); - } - } - - - trimProxies(); - - return 1; -} - - -int bdQuery::updateProxy(const bdId *id, uint32_t mode) -{ - if (!updateProxyList(id, mode, mProxiesUnknown)) - { - updateProxyList(id, mode, mProxiesFlagged); - } - - trimProxies(); - return 1; -} - - -/**** Utility functions that do all the work! ****/ - -int bdQuery::updateProxyList(const bdId *id, uint32_t mode, std::list &searchProxyList) -{ - std::list::iterator it; - for(it = searchProxyList.begin(); it != searchProxyList.end(); it++) - { - if (mFns->bdSimilarId(id, &(it->mPeerId))) - { - /* found it ;( */ -#ifdef DEBUG_QUERY - std::cerr << "bdQuery::updateProxyList() Found peer, updating"; - std::cerr << std::endl; -#endif - - time_t now = time(NULL); - if (mode) - { - /* also update port from incoming id, as we have definitely recved from it */ - if (mFns->bdUpdateSimilarId(&(it->mPeerId), id)) - { - /* updated it... must be Unstable */ - it->mExtraFlags |= BITDHT_PEER_EXFLAG_UNSTABLE; - } - } - it->mPeerFlags |= mode; - it->mLastRecvTime = now; - - /* now move it to the front of required list... - * note this could be exactly the same list as &searchProxyList, or a different one! - */ - - bdPeer peer = *it; - it = searchProxyList.erase(it); - - if ((peer.mPeerFlags & mRequiredPeerFlags) == mRequiredPeerFlags) - { - mProxiesFlagged.push_front(peer); - } - else - { - mProxiesUnknown.push_front(peer); - } - - return 1; - break; - } - } - - return 0; -} - -#define MAX_POTENTIAL_PROXIES 10 - -int bdQuery::trimProxies() -{ - - /* drop excess Potential Proxies */ - while(mProxiesUnknown.size() > MAX_POTENTIAL_PROXIES) - { - mProxiesUnknown.pop_back(); - } - - while(mProxiesFlagged.size() > MAX_POTENTIAL_PROXIES) - { - mProxiesFlagged.pop_back(); - } - return 1; -} - - -/******************************************************************************************* - ******************************** Potential Proxies **************************************** - *******************************************************************************************/ - - - -/* print query. - */ - -int bdQuery::printQuery() -{ -#ifdef DEBUG_QUERY - fprintf(stderr, "bdQuery::printQuery()\n"); -#endif - - time_t ts = time(NULL); - fprintf(stderr, "Query for: "); - mFns->bdPrintNodeId(std::cerr, &mId); - fprintf(stderr, " Query State: %d", mState); - fprintf(stderr, " Query Age %ld secs", ts-mQueryTS); - if (mState >= BITDHT_QUERY_FAILURE) - { - fprintf(stderr, " Search Time: %d secs", mSearchTime); - } - fprintf(stderr, "\n"); - -#ifdef DEBUG_QUERY - fprintf(stderr, "Closest Available Peers:\n"); - std::multimap::iterator it; - for(it = mClosest.begin(); it != mClosest.end(); it++) - { - fprintf(stderr, "Id: "); - mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); - fprintf(stderr, " Bucket: %d ", mFns->bdBucketDistance(&(it->first))); - fprintf(stderr," Flags: %x", it->second.mPeerFlags); - fprintf(stderr," Found: %ld ago", ts-it->second.mFoundTime); - fprintf(stderr," LastSent: %ld ago", ts-it->second.mLastSendTime); - fprintf(stderr," LastRecv: %ld ago", ts-it->second.mLastRecvTime); - fprintf(stderr, "\n"); - } - - fprintf(stderr, "\nClosest Potential Peers:\n"); - for(it = mPotentialPeers.begin(); it != mPotentialPeers.end(); it++) - { - fprintf(stderr, "Id: "); - mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); - fprintf(stderr, " Bucket: %d ", mFns->bdBucketDistance(&(it->first))); - fprintf(stderr," Flags: %x", it->second.mPeerFlags); - fprintf(stderr," Found: %ld ago", ts-it->second.mFoundTime); - fprintf(stderr," LastSent: %ld ago", ts-it->second.mLastSendTime); - fprintf(stderr," LastRecv: %ld ago", ts-it->second.mLastRecvTime); - fprintf(stderr, "\n"); - } -#else - // shortened version. - fprintf(stderr, "Closest Available Peer: "); - std::multimap::iterator it = mClosest.begin(); - if (it != mClosest.end()) - { - mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); - fprintf(stderr, " Bucket: %d ", mFns->bdBucketDistance(&(it->first))); - fprintf(stderr," Flags: %x", it->second.mPeerFlags); - fprintf(stderr," Found: %ld ago", ts-it->second.mFoundTime); - fprintf(stderr," LastSent: %ld ago", ts-it->second.mLastSendTime); - fprintf(stderr," LastRecv: %ld ago", ts-it->second.mLastRecvTime); - } - fprintf(stderr, "\n"); - - fprintf(stderr, "Closest Potential Peer: "); - it = mPotentialPeers.begin(); - if (it != mPotentialPeers.end()) - { - mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); - fprintf(stderr, " Bucket: %d ", mFns->bdBucketDistance(&(it->first))); - fprintf(stderr," Flags: %x", it->second.mPeerFlags); - fprintf(stderr," Found: %ld ago", ts-it->second.mFoundTime); - fprintf(stderr," LastSent: %ld ago", ts-it->second.mLastSendTime); - fprintf(stderr," LastRecv: %ld ago", ts-it->second.mLastRecvTime); - } - fprintf(stderr, "\n"); - -#endif - std::list::iterator lit; - fprintf(stderr, "Flagged Proxies:\n"); - for(lit = mProxiesFlagged.begin(); lit != mProxiesFlagged.end(); lit++) - { - fprintf(stderr, "ProxyId: "); - mFns->bdPrintId(std::cerr, &(lit->mPeerId)); - fprintf(stderr," Flags: %x", it->second.mPeerFlags); - fprintf(stderr," Found: %ld ago", ts-lit->mFoundTime); - fprintf(stderr," LastSent: %ld ago", ts-lit->mLastSendTime); - fprintf(stderr," LastRecv: %ld ago", ts-lit->mLastRecvTime); - fprintf(stderr, "\n"); - } - - fprintf(stderr, "Potential Proxies:\n"); - for(lit = mProxiesUnknown.begin(); lit != mProxiesUnknown.end(); lit++) - { - fprintf(stderr, "ProxyId: "); - mFns->bdPrintId(std::cerr, &(lit->mPeerId)); - fprintf(stderr," Flags: %x", it->second.mPeerFlags); - fprintf(stderr," Found: %ld ago", ts-lit->mFoundTime); - fprintf(stderr," LastSent: %ld ago", ts-lit->mLastSendTime); - fprintf(stderr," LastRecv: %ld ago", ts-lit->mLastRecvTime); - fprintf(stderr, "\n"); - } - - return 1; -} - - - - -/********************************* Remote Query **************************************/ - -#define QUERY_HISTORY_LIMIT 10 // Typically get max of 4-6 per 10minutes. -#define QUERY_HISTORY_PERIOD 600 - -bdRemoteQuery::bdRemoteQuery(bdId *id, bdNodeId *query, bdToken *transId, uint32_t query_type) - :mId(*id), mQuery(*query), mTransId(*transId), mQueryType(query_type) -{ - mQueryTS = time(NULL); -} - - - - -bdQueryHistoryList::bdQueryHistoryList() - :mBadPeer(false) -{ - -} - - -bool bdQueryHistoryList::addIncomingQuery(time_t recvd, const bdNodeId *aboutId) -{ - mList.insert(std::make_pair(recvd, *aboutId)); - mBadPeer = (mList.size() > QUERY_HISTORY_LIMIT); - return mBadPeer; -} - - -// returns true if empty. -bool bdQueryHistoryList::cleanupMsgs(time_t before) -{ - if (before == 0) - { - mList.clear(); - return true; - } - - // Delete the old stuff in the list. - while((mList.begin() != mList.end()) && (mList.begin()->first < before)) - { - mList.erase(mList.begin()); - } - - // return true if empty. - if (mList.begin() == mList.end()) - { - return true; - } - return false; -} - -bdQueryHistory::bdQueryHistory() - :mStorePeriod(QUERY_HISTORY_PERIOD) -{ - return; -} - -bool bdQueryHistory::addIncomingQuery(time_t recvd, const bdId *id, const bdNodeId *aboutId) -{ - std::map::iterator it; - - it = mHistory.find(*id); - if (it == mHistory.end()) - { - mHistory[*id] = bdQueryHistoryList(); - it = mHistory.find(*id); - } - - return (it->second).addIncomingQuery(recvd, aboutId); -} - -bool bdQueryHistory::isBadPeer(const bdId *id) -{ - std::map::iterator it; - - it = mHistory.find(*id); - if (it == mHistory.end()) - { - return false; - } - - return it->second.mBadPeer; -} - - -void bdQueryHistory::cleanupOldMsgs() -{ - if (mStorePeriod == 0) - { - return; // no cleanup. - } - - time_t before = time(NULL) - mStorePeriod; - std::map::iterator it; - for(it = mHistory.begin(); it != mHistory.end(); ) - { - if (it->second.cleanupMsgs(before)) - { - std::map::iterator tit(it); - ++tit; - mHistory.erase(it); - it = tit; - } - else - { - ++it; - } - } -} - - -void bdQueryHistory::printMsgs() -{ - std::ostream &out = std::cerr; - - out << "bdQueryHistory::printMsgs() IncomingQueries in last " << mStorePeriod; - out << " secs" << std::endl; - - std::map::iterator it; - for(it = mHistory.begin(); it != mHistory.end(); it++) - { - out << "\t"; - bdStdPrintId(out, &(it->first)); - out << " " << it->second.mList.size(); - if (it->second.mBadPeer) - { - out << " BadPeer"; - } - out << std::endl; - } -} - - - - - - - - - diff --git a/libbitdht/src/bitdht/bdquery.h b/libbitdht/src/bitdht/bdquery.h deleted file mode 100644 index 4cb08f165..000000000 --- a/libbitdht/src/bitdht/bdquery.h +++ /dev/null @@ -1,157 +0,0 @@ -/******************************************************************************* - * bitdht/bdquery.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef BITDHT_QUERY_H -#define BITDHT_QUERY_H - -#include "bitdht/bdiface.h" -#include "bitdht/bdpeer.h" -#include "bitdht/bdobj.h" - -/* Query result flags are in bdiface.h */ - -#define BITDHT_MIN_QUERY_AGE 10 -#define BITDHT_MAX_QUERY_AGE 300 /* Query Should take <1 minute, so 5 minutes sounds reasonable */ - -class bdQuery -{ - public: - bdQuery(const bdNodeId *id, std::list &startList, uint32_t queryFlags, - bdDhtFunctions *fns); - - // get the answer. -bool result(std::list &answer); -bool proxies(std::list &answer); -bool potentialProxies(std::list &answer); - - // returning results get passed to all queries. -//void addNode(const bdId *id, int mode); -int nextQuery(bdId &id, bdNodeId &targetId); -int addPeer(const bdId *id, uint32_t mode); -int addPotentialPeer(const bdId *id, const bdId *src, uint32_t srcmode); -int printQuery(); - - // searching for - bdNodeId mId; - bdMetric mLimit; - uint32_t mState; - time_t mQueryTS; - uint32_t mQueryFlags; - int32_t mSearchTime; - - int32_t mQueryIdlePeerRetryPeriod; // seconds between retries. - - //private: - - // Closest Handling Fns. -int addClosestPeer(const bdId *id, uint32_t mode); - - // Potential Handling Fns. -int worthyPotentialPeer(const bdId *id); -int updatePotentialPeer(const bdId *id, uint32_t mode, uint32_t addType); -int trimPotentialPeers_FixedLength(); -int trimPotentialPeers_toClosest(); -int removeOldPotentialPeers(); - - // Proxy Handling Fns. -int addProxy(const bdId *id, const bdId *src, uint32_t srcmode); -int updateProxy(const bdId *id, uint32_t mode); -int updateProxyList(const bdId *id, uint32_t mode, std::list &searchProxyList); -int trimProxies(); - - - // closest peers. - std::multimap mClosest; - std::multimap mPotentialPeers; - time_t mPotPeerCleanTS; // periodic cleanup of PotentialPeers. - - uint32_t mRequiredPeerFlags; - std::list mProxiesUnknown; - std::list mProxiesFlagged; - - int mClosestListSize; - bdDhtFunctions *mFns; - -}; - -#if 0 - -class bdQueryStatus -{ - public: - uint32_t mStatus; - uint32_t mQFlags; - std::list mResults; -}; - -#endif - - - -/* this is just a container class. - * we locally seach for this, once then discard. - */ -class bdRemoteQuery -{ - public: - bdRemoteQuery(bdId *id, bdNodeId *query, bdToken *transId, uint32_t query_type); - - bdId mId; - bdNodeId mQuery; - bdToken mTransId; - uint32_t mQueryType; - - time_t mQueryTS; -}; - - - -class bdQueryHistoryList -{ - public: - bdQueryHistoryList(); - -bool addIncomingQuery(time_t recvd, const bdNodeId *aboutId); // calcs and returns mBadPeer -bool cleanupMsgs(time_t before); // returns true if empty. - - bool mBadPeer; - std::multimap mList; -}; - -class bdQueryHistory -{ - public: - bdQueryHistory(); - -bool addIncomingQuery(time_t recvd, const bdId *id, const bdNodeId *aboutId); -void printMsgs(); - -void cleanupOldMsgs(); - -bool isBadPeer(const bdId *id); - - int mStorePeriod; - std::map mHistory; -}; - - -#endif - diff --git a/libbitdht/src/bitdht/bdquerymgr.cc b/libbitdht/src/bitdht/bdquerymgr.cc deleted file mode 100644 index 70f58ce90..000000000 --- a/libbitdht/src/bitdht/bdquerymgr.cc +++ /dev/null @@ -1,379 +0,0 @@ -/******************************************************************************* - * bitdht/bdquerymgr.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "bitdht/bdquerymgr.h" -#include "bitdht/bdnode.h" - -#include -#include -#include -#include - -#include -#include - - -#define BITDHT_QUERY_START_PEERS 10 -#define BITDHT_QUERY_NEIGHBOUR_PEERS 8 -#define BITDHT_MAX_REMOTE_QUERY_AGE 10 - -/**** - * #define DEBUG_NODE_MULTIPEER 1 - * #define DEBUG_NODE_MSGS 1 - * #define DEBUG_NODE_ACTIONS 1 - - * #define DEBUG_NODE_MSGIN 1 - * #define DEBUG_NODE_MSGOUT 1 - ***/ - -//#define DEBUG_NODE_MSGS 1 - - -bdQueryManager::bdQueryManager(bdSpace *space, bdDhtFunctions *fns, bdNodePublisher *pub) - :mNodeSpace(space), mFns(fns), mPub(pub) -{ -} - -/***** Startup / Shutdown ******/ -void bdQueryManager::shutdownQueries() -{ - /* clear the queries */ - std::list::iterator it; - for(it = mLocalQueries.begin(); it != mLocalQueries.end();it++) - { - delete (*it); - } - - mLocalQueries.clear(); -} - - -void bdQueryManager::printQueries() -{ - std::cerr << "bdQueryManager::printQueries()"; - std::cerr << std::endl; - - int i = 0; - std::list::iterator it; - for(it = mLocalQueries.begin(); it != mLocalQueries.end(); it++, i++) - { - fprintf(stderr, "Query #%d:\n", i); - (*it)->printQuery(); - fprintf(stderr, "\n"); - } -} - - -int bdQueryManager::iterateQueries(int maxQueries) -{ -#ifdef DEBUG_NODE_MULTIPEER - std::cerr << "bdQueryManager::iterateQueries() of Peer: "; - mFns->bdPrintNodeId(std::cerr, &mOwnId); - std::cerr << std::endl; -#endif - - /* allow each query to send up to one query... until maxMsgs has been reached */ - int numQueries = mLocalQueries.size(); - int sentQueries = 0; - int i = 0; - - bdId id; - bdNodeId targetNodeId; - - while((i < numQueries) && (sentQueries < maxQueries)) - { - bdQuery *query = mLocalQueries.front(); - mLocalQueries.pop_front(); - mLocalQueries.push_back(query); - - /* go through the possible queries */ - if (query->nextQuery(id, targetNodeId)) - { -#ifdef DEBUG_NODE_MSGS - std::cerr << "bdQueryManager::iteration() send_query("; - mFns->bdPrintId(std::cerr, &id); - std::cerr << ","; - mFns->bdPrintNodeId(std::cerr, &targetNodeId); - std::cerr << ")"; - std::cerr << std::endl; -#endif - mPub->send_query(&id, &targetNodeId, false); - sentQueries++; - } - i++; - } - -#ifdef DEBUG_NODE_ACTIONS - std::cerr << "bdQueryManager::iteration() maxMsgs: " << maxMsgs << " sentPings: " << sentPings; - std::cerr << " / " << allowedPings; - std::cerr << " sentQueries: " << sentQueries; - std::cerr << " / " << numQueries; - std::cerr << std::endl; -#endif - - //printQueries(); - - return sentQueries; -} - - -bool bdQueryManager::checkPotentialPeer(bdId *id, bdId *src) -{ - bool isWorthyPeer = false; - /* also push to queries */ - std::list::iterator it; - for(it = mLocalQueries.begin(); it != mLocalQueries.end(); it++) - { - if ((*it)->addPotentialPeer(id, src, 0)) - { - isWorthyPeer = true; - } - } - - if (!isWorthyPeer) - { - isWorthyPeer = checkWorthyPeerSources(src); - } - - return isWorthyPeer; -} - - -void bdQueryManager::addPeer(const bdId *id, uint32_t peerflags) -{ - -#ifdef DEBUG_NODE_ACTIONS - fprintf(stderr, "bdQueryManager::addPeer("); - mFns->bdPrintId(std::cerr, id); - fprintf(stderr, ")\n"); -#endif - - /* iterate through queries */ - std::list::iterator it; - for(it = mLocalQueries.begin(); it != mLocalQueries.end(); it++) - { - (*it)->addPeer(id, peerflags); - } -} - - -/************************************ Query Details *************************/ -void bdQueryManager::addQuery(const bdNodeId *id, uint32_t qflags) -{ - - std::list startList; - std::multimap nearest; - std::multimap::iterator it; - - mNodeSpace->find_nearest_nodes(id, BITDHT_QUERY_START_PEERS, nearest); - -#ifdef DEBUG_NODE_ACTIONS - fprintf(stderr, "bdQueryManager::addQuery("); - mFns->bdPrintNodeId(std::cerr, id); - fprintf(stderr, ")\n"); -#endif - - for(it = nearest.begin(); it != nearest.end(); it++) - { - startList.push_back(it->second); - } - - bdQuery *query = new bdQuery(id, startList, qflags, mFns); - mLocalQueries.push_back(query); -} - - -void bdQueryManager::clearQuery(const bdNodeId *rmId) -{ - std::list::iterator it; - for(it = mLocalQueries.begin(); it != mLocalQueries.end();) - { - if ((*it)->mId == *rmId) - { - bdQuery *query = (*it); - it = mLocalQueries.erase(it); - delete query; - } - else - { - it++; - } - } -} - -void bdQueryManager::QueryStatus(std::map &statusMap) -{ - std::list::iterator it; - for(it = mLocalQueries.begin(); it != mLocalQueries.end(); it++) - { - bdQueryStatus status; - status.mStatus = (*it)->mState; - status.mQFlags = (*it)->mQueryFlags; - (*it)->result(status.mResults); - statusMap[(*it)->mId] = status; - } -} - -int bdQueryManager::QuerySummary(const bdNodeId *id, bdQuerySummary &query) -{ - std::list::iterator it; - for(it = mLocalQueries.begin(); it != mLocalQueries.end(); it++) - { - if ((*it)->mId == *id) - { - query.mId = (*it)->mId; - query.mLimit = (*it)->mLimit; - query.mState = (*it)->mState; - query.mQueryTS = (*it)->mQueryTS; - query.mQueryFlags = (*it)->mQueryFlags; - query.mSearchTime = (*it)->mSearchTime; - query.mClosest = (*it)->mClosest; - query.mPotentialPeers = (*it)->mPotentialPeers; - query.mProxiesUnknown = (*it)->mProxiesUnknown; - query.mProxiesFlagged = (*it)->mProxiesFlagged; - query.mQueryIdlePeerRetryPeriod = (*it)->mQueryIdlePeerRetryPeriod; - - return 1; - } - } - return 0; -} - -/* Extract Results from Peer Queries */ - -#define BDQRYMGR_RESULTS 1 -#define BDQRYMGR_PROXIES 2 -#define BDQRYMGR_POTPROXIES 3 - -int bdQueryManager::getResults(bdNodeId *target, std::list &answer, int querytype) -{ - - /* grab any peers from any existing query */ - int results = 0; - std::list::iterator qit; - for(qit = mLocalQueries.begin(); qit != mLocalQueries.end(); qit++) - { - if (!((*qit)->mId == (*target))) - { - continue; - } - -#ifdef DEBUG_NODE_CONNECTION - std::cerr << "bdQueryManager::getResults() Found Matching Query"; - std::cerr << std::endl; -#endif - switch(querytype) - { - default: - case BDQRYMGR_RESULTS: - results = (*qit)->result(answer); - break; - case BDQRYMGR_PROXIES: - results = (*qit)->proxies(answer); - break; - case BDQRYMGR_POTPROXIES: - results = (*qit)->potentialProxies(answer); - break; - } - /* will only be one matching query.. so end loop */ - return results; - } - return 0; -} - - -int bdQueryManager::result(bdNodeId *target, std::list &answer) -{ - return getResults(target, answer, BDQRYMGR_RESULTS); -} - -int bdQueryManager::proxies(bdNodeId *target, std::list &answer) -{ - return getResults(target, answer, BDQRYMGR_PROXIES); -} - -int bdQueryManager::potentialProxies(bdNodeId *target, std::list &answer) -{ - return getResults(target, answer, BDQRYMGR_POTPROXIES); -} - - -/************ WORTHY PEERS **********/ - -#define MAX_WORTHY_PEER_AGE 15 - -void bdQueryManager::addWorthyPeerSource(bdId *src) -{ - time_t now = time(NULL); - - bdPeer peer; - peer.mPeerId = *src; - peer.mFoundTime = now; - -#ifdef DEBUG_NODE_ACTIONS - std::cerr << "bdQueryManager::addWorthyPeerSource("; - mFns->bdPrintId(std::cerr, src); - std::cerr << ")" << std::endl; -#endif - - mWorthyPeerSources.push_back(peer); -} - -bool bdQueryManager::checkWorthyPeerSources(bdId *src) -{ - if (!src) - return false; - - time_t now = time(NULL); - std::list::iterator it; - for(it = mWorthyPeerSources.begin(); it != mWorthyPeerSources.end(); ) - { - if (now - it->mFoundTime > MAX_WORTHY_PEER_AGE) - { -#ifdef DEBUG_NODE_ACTIONS - std::cerr << "bdQueryManager::checkWorthyPeerSource() Discard old Source: "; - mFns->bdPrintId(std::cerr, &(it->mPeerId)); - std::cerr << std::endl; -#endif - - it = mWorthyPeerSources.erase(it); - } - else - { - if (it->mPeerId == *src) - { -#ifdef DEBUG_NODE_ACTIONS - std::cerr << "bdQueryManager::checkWorthyPeerSource("; - mFns->bdPrintId(std::cerr, src); - std::cerr << ") = true" << std::endl; -#endif - - return true; - } - it++; - } - } - return false; -} - - - diff --git a/libbitdht/src/bitdht/bdquerymgr.h b/libbitdht/src/bitdht/bdquerymgr.h deleted file mode 100644 index 355781244..000000000 --- a/libbitdht/src/bitdht/bdquerymgr.h +++ /dev/null @@ -1,73 +0,0 @@ -/******************************************************************************* - * bitdht/bdquerymgr.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef BITDHT_QUERY_MANAGER_H -#define BITDHT_QUERY_MANAGER_H - -#include "bitdht/bdquery.h" -class bdNodePublisher; - - -class bdQueryManager -{ - public: - - bdQueryManager(bdSpace *space, bdDhtFunctions *fns, bdNodePublisher *pub); - - void shutdownQueries(); - void printQueries(); - - int iterateQueries(int maxqueries); - - bool checkPotentialPeer(bdId *id, bdId *src); - void addPeer(const bdId *id, uint32_t peerflags); - - void addQuery(const bdNodeId *id, uint32_t qflags); - void clearQuery(const bdNodeId *id); - void QueryStatus(std::map &statusMap); - int QuerySummary(const bdNodeId *id, bdQuerySummary &query); - - int result(bdNodeId *target, std::list &answer); - int proxies(bdNodeId *target, std::list &answer); - int potentialProxies(bdNodeId *target, std::list &answer); - - // extra "Worthy Peers" we will want to ping. - void addWorthyPeerSource(bdId *src); - bool checkWorthyPeerSources(bdId *src); - - private: - - int getResults(bdNodeId *target, std::list &answer, int querytype); - - /* NB: No Mutex Protection... Single threaded, Mutex at higher level! - */ - - bdSpace *mNodeSpace; - bdDhtFunctions *mFns; - bdNodePublisher *mPub; - - std::list mLocalQueries; - std::list mWorthyPeerSources; -}; - - - -#endif // BITDHT_QUERY_MANAGER_H diff --git a/libbitdht/src/bitdht/bdstddht.cc b/libbitdht/src/bitdht/bdstddht.cc deleted file mode 100644 index eac5c148e..000000000 --- a/libbitdht/src/bitdht/bdstddht.cc +++ /dev/null @@ -1,347 +0,0 @@ -/******************************************************************************* - * bitdht/bdstddht.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "bitdht/bdstddht.h" -#include "bitdht/bdpeer.h" -#include "util/bdrandom.h" -#include "util/bdstring.h" - -#include -#include -#include -#include - -#include -#include - -/** - * #define BITDHT_DEBUG 1 -**/ - -void bdStdRandomId(bdId *id) -{ - bdStdRandomNodeId(&(id->id)); - id->addr.sin_addr.s_addr = bdRandom::random_u32(); - id->addr.sin_port = (bdRandom::random_u32() % USHRT_MAX); - - return; -} - -void bdStdRandomNodeId(bdNodeId *id) -{ - uint32_t *a_data = (uint32_t *) id->data; - for(int i = 0; i < BITDHT_KEY_INTLEN; i++) - { - a_data[i] = bdRandom::random_u32(); - } - return; -} - -void bdStdZeroNodeId(bdNodeId *id) -{ - uint32_t *a_data = (uint32_t *) id->data; - for(int i = 0; i < BITDHT_KEY_INTLEN; i++) - { - a_data[i] = 0; - } - return; -} - -// Ignore differences in port.... -// must be careful which one we accept after this. -// can could end-up with the wrong port. -// However this only matters with firewalled peers anyway. -// So not too serious. -bool bdStdSimilarId(const bdId *n1, const bdId *n2) -{ - if (n1->id == n2->id) - { - if (n1->addr.sin_addr.s_addr == n2->addr.sin_addr.s_addr) - { - return true; - } - } - return false; -} - -bool bdStdUpdateSimilarId(bdId *dest, const bdId *src) -{ - /* only difference that's currently allowed */ - if (dest->addr.sin_port == src->addr.sin_port) - { - /* no update required */ - return false; - } - - dest->addr.sin_port = src->addr.sin_port; - return true; -} - - -/* fills in bdNodeId r, with XOR of a and b */ -int bdStdDistance(const bdNodeId *a, const bdNodeId *b, bdMetric *r) -{ - uint8_t *a_data = (uint8_t *) a->data; - uint8_t *b_data = (uint8_t *) b->data; - uint8_t *ans = (uint8_t *) r->data; - for(int i = 0; i < BITDHT_KEY_LEN; i++) - { - *(ans++) = *(a_data++) ^ *(b_data++); - } - return 1; -} - -void bdStdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *midId) -{ - bdMetric dist; - - /* get distance between a & c */ - bdStdDistance(target, other, &dist); - - /* generate Random Id */ - bdStdRandomNodeId(midId); - - /* zero bits of Random Id until under 1/2 of distance - * done in bytes for ease... matches one extra byte than distance = 0 - * -> hence wierd order of operations - */ - //bool done = false; - for(int i = 0; i < BITDHT_KEY_LEN; i++) - { - midId->data[i] = target->data[i]; - - if (dist.data[i] != 0) - break; - } -} - -int bdStdLoadNodeId(bdNodeId *id, std::string input) -{ - uint8_t *a_data = (uint8_t *) id->data; - uint32_t reqlen = BITDHT_KEY_LEN * 2; - if (input.size() < reqlen) - { - return 0; - } - - for(int i = 0; i < BITDHT_KEY_LEN; i++) - { - char ch1 = input[2 * i]; - char ch2 = input[2 * i + 1]; - uint8_t value1 = 0; - uint8_t value2 = 0; - - /* do char1 */ - if (ch1 >= '0' && ch1 <= '9') - value1 = (ch1 - '0'); - else if (ch1 >= 'A' && ch1 <= 'F') - value1 = (ch1 - 'A' + 10); - else if (ch1 >= 'a' && ch1 <= 'f') - value1 = (ch1 - 'a' + 10); - - /* do char2 */ - if (ch2 >= '0' && ch2 <= '9') - value2 = (ch2 - '0'); - else if (ch2 >= 'A' && ch2 <= 'F') - value2 = (ch2 - 'A' + 10); - else if (ch2 >= 'a' && ch2 <= 'f') - value2 = (ch2 - 'a' + 10); - - a_data[i] = (value1 << 4) + value2; - } - return 1; -} - -std::string bdStdConvertToPrintable(std::string input) -{ - std::string out; - for(uint32_t i = 0; i < input.length(); i++) - { - /* sensible chars */ - if ((input[i] > 31) && (input[i] < 127)) - { - out += input[i]; - } - else - { - bd_sprintf_append(out, "[0x%x]", (uint32_t) input[i]); - } - } - return out; -} - -void bdStdPrintNodeId(std::ostream &out, const bdNodeId *a) -{ - std::string s; - bdStdPrintNodeId(s, a, true); - out << s; -} - -void bdStdPrintNodeId(std::string &out, const bdNodeId *a, bool append) -{ - if (!append) - { - out.clear(); - } - - for(int i = 0; i < BITDHT_KEY_LEN; i++) - { - bd_sprintf_append(out, "%02x", (uint32_t) (a->data)[i]); - } -} - -void bdStdPrintId(std::ostream &out, const bdId *a) -{ - std::string s; - bdStdPrintId(s, a, false); - out << s; -} - -void bdStdPrintId(std::string &out, const bdId *a, bool append) -{ - bdStdPrintNodeId(out, &(a->id), append); - bd_sprintf_append(out, " ip:%s:%u", bdnet_inet_ntoa(a->addr.sin_addr).c_str(), ntohs(a->addr.sin_port)); -} - -/* returns 0-160 depending on bucket */ -int bdStdBucketDistance(const bdNodeId *a, const bdNodeId *b) -{ - bdMetric m; - bdStdDistance(a, b, &m); - return bdStdBucketDistance(&m); -} - -/* returns 0-160 depending on bucket */ -int bdStdBucketDistance(const bdMetric *m) -{ - for(int i = 0; i < BITDHT_KEY_BITLEN; i++) - { - int bit = BITDHT_KEY_BITLEN - i - 1; - int byte = i / 8; - int bbit = 7 - (i % 8); - unsigned char comp = (1 << bbit); - -#ifdef BITDHT_DEBUG - fprintf(stderr, "bdStdBucketDistance: bit:%d byte:%d bbit:%d comp:%x, data:%x\n", bit, byte, bbit, comp, m->data[byte]); -#endif - - if (comp & m->data[byte]) - { - return bit; - } - } - return 0; -} - - -bdStdDht::bdStdDht() -{ - return; -} - /* setup variables */ -uint16_t bdStdDht::bdNumBuckets() -{ - - return BITDHT_STANDARD_N_BUCKETS; -} - -uint16_t bdStdDht::bdNodesPerBucket() /* used for bdspace */ -{ - return BITDHT_STANDARD_BUCKET_SIZE; -} - -uint16_t bdStdDht::bdNumQueryNodes() /* used for queries */ -{ - return BITDHT_STANDARD_BUCKET_SIZE; -} - -uint16_t bdStdDht::bdBucketBitSize() -{ - return BITDHT_STANDARD_BUCKET_SIZE_BITS; -} - -int bdStdDht::bdDistance(const bdNodeId *n1, const bdNodeId *n2, class bdMetric *metric) -{ - return bdStdDistance(n1, n2, metric); -} - -int bdStdDht::bdBucketDistance(const bdNodeId *n1, const bdNodeId *n2) -{ - return bdStdBucketDistance(n1, n2); -} - -int bdStdDht::bdBucketDistance(const bdMetric *metric) -{ - return bdStdBucketDistance(metric); -} - - -bool bdStdDht::bdSimilarId(const bdId *id1, const bdId *id2) -{ - return bdStdSimilarId(id1, id2); -} - - -bool bdStdDht::bdUpdateSimilarId(bdId *dest, const bdId *src) -{ - return bdStdUpdateSimilarId(dest, src); -} - - -void bdStdDht::bdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *mid) -{ - return bdStdRandomMidId(target, other, mid); -} - - -void bdStdDht::bdPrintId(std::ostream &out, const bdId *a) -{ - return bdStdPrintId(out, a); -} - -void bdStdDht::bdPrintNodeId(std::ostream &out, const bdNodeId *a) -{ - return bdStdPrintNodeId(out, a); -} - - -/**************************/ - -bdModDht::bdModDht() - :mNodesPerBucket(BITDHT_STANDARD_BUCKET_SIZE) -{ - return; -} - -void bdModDht::setNodesPerBucket(uint16_t nodesPerBucket) -{ - mNodesPerBucket = nodesPerBucket; - return; -} - - -uint16_t bdModDht::bdNodesPerBucket() /* used for bdspace */ -{ - return mNodesPerBucket; -} - - diff --git a/libbitdht/src/bitdht/bdstddht.h b/libbitdht/src/bitdht/bdstddht.h deleted file mode 100644 index d38c19724..000000000 --- a/libbitdht/src/bitdht/bdstddht.h +++ /dev/null @@ -1,100 +0,0 @@ -/******************************************************************************* - * bitdht/bdstddht.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef BITDHT_STANDARD_DHT_H -#define BITDHT_STANDARD_DHT_H - -#include "bitdht/bdiface.h" - -#define BITDHT_STANDARD_BUCKET_SIZE 10 // 20 too many per query? -#define BITDHT_STANDARD_BUCKET_SIZE_BITS 5 - -#define BITDHT_STANDARD_N_BUCKETS BITDHT_KEY_BITLEN - -#include -#include -#include -#include - - - - -void bdStdRandomNodeId(bdNodeId *id); -void bdStdZeroNodeId(bdNodeId *id); - -void bdStdRandomId(bdId *id); -int bdStdDistance(const bdNodeId *a, const bdNodeId *b, bdMetric *r); -int bdStdBucketDistance(const bdMetric *m); -int bdStdBucketDistance(const bdNodeId *a, const bdNodeId *b); - -void bdStdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *mid); - -int bdStdLoadNodeId(bdNodeId *id, std::string input); - -void bdStdPrintId(std::ostream &out, const bdId *a); -void bdStdPrintId(std::string &out, const bdId *a, bool append); -void bdStdPrintNodeId(std::ostream &out, const bdNodeId *a); -void bdStdPrintNodeId(std::string &out, const bdNodeId *a, bool append); - -std::string bdStdConvertToPrintable(std::string input); - -//uint32_t bdStdSimilarNode(const bdId*, const bdId*); - - -class bdStdDht: public bdDhtFunctions -{ - public: - - bdStdDht(); - /* setup variables */ -virtual uint16_t bdNumBuckets(); -virtual uint16_t bdNodesPerBucket(); /* used for bdspace */ -virtual uint16_t bdNumQueryNodes(); /* used for queries */ -virtual uint16_t bdBucketBitSize(); - -virtual int bdDistance(const bdNodeId *n1, const bdNodeId *n2, bdMetric *metric); -virtual int bdBucketDistance(const bdNodeId *n1, const bdNodeId *n2); -virtual int bdBucketDistance(const bdMetric *metric); - -virtual bool bdSimilarId(const bdId *id1, const bdId *id2); -virtual bool bdUpdateSimilarId(bdId *dest, const bdId *src); /* returns true if update was necessary */ - -virtual void bdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *mid); - -virtual void bdPrintId(std::ostream &out, const bdId *a); -virtual void bdPrintNodeId(std::ostream &out, const bdNodeId *a); - -}; - -class bdModDht: public bdStdDht -{ - public: - bdModDht(); -virtual void setNodesPerBucket(uint16_t nodesPerBucket); -virtual uint16_t bdNodesPerBucket(); /* used for bdspace */ - - private: - uint16_t mNodesPerBucket; -}; - - -#endif - diff --git a/libbitdht/src/bitdht/bdstore.cc b/libbitdht/src/bitdht/bdstore.cc deleted file mode 100644 index 2cce6840c..000000000 --- a/libbitdht/src/bitdht/bdstore.cc +++ /dev/null @@ -1,269 +0,0 @@ -/******************************************************************************* - * bitdht/bdstore.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "bitdht/bdstore.h" -#include "util/bdnet.h" -#include "util/bdfile.h" - -#include -#include - -//#define DEBUG_STORE 1 - -bdStore::bdStore(std::string file, std::string backupfile, bdDhtFunctions *fns) - :mFns(fns) -{ -#ifdef DEBUG_STORE - std::cerr << "bdStore::bdStore(" << file << ")"; - std::cerr << std::endl; -#endif - - /* read data from file */ - mStoreFile = file; - mStoreFileBak = backupfile; - - reloadFromStore(); -} - -int bdStore::clear() -{ - mIndex = 0; - store.clear(); - return 1; -} - -int bdStore::reloadFromStore() -{ - int result = reloadFromStore(mStoreFile); - if( result != 0 && store.size() > 0){ - return result; - } else if(mStoreFileBak != "") { //Nothing loaded, try the backup file - return reloadFromStore(mStoreFileBak); - } else { - return 0; - } -} - -int bdStore::reloadFromStore(std::string file) -{ - clear(); - - FILE *fd = fopen(file.c_str(), "r"); - if (!fd) - { - fprintf(stderr, "Failed to Open File: %s ... No Peers\n", file.c_str()); - return 0; - } - - - char line[10240]; - char addr_str[10240]; - struct sockaddr_in addr; - addr.sin_family = PF_INET; - unsigned short port; - - while(line == fgets(line, 10240, fd)) - { - if (2 == sscanf(line, "%s %hd", addr_str, &port)) - { - if (bdnet_inet_aton(addr_str, &(addr.sin_addr))) - { - addr.sin_port = htons(port); - bdPeer peer; - bdZeroNodeId(&(peer.mPeerId.id)); - peer.mPeerId.addr = addr; - peer.mLastSendTime = 0; - peer.mLastRecvTime = 0; - store.push_back(peer); -#ifdef DEBUG_STORE - fprintf(stderr, "Read: %s %d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); -#endif - } - } - } - - fclose(fd); - -#ifdef DEBUG_STORE - fprintf(stderr, "Read %ld Peers\n", (long) store.size()); -#endif - - return 1; - -} - -// This is a very ugly function! -int bdStore::getPeer(bdPeer *peer) -{ -#ifdef DEBUG_STORE - fprintf(stderr, "bdStore::getPeer() %ld Peers left\n", (long) store.size()); -#endif - - std::list::iterator it; - int i = 0; - for(it = store.begin(); (it != store.end()) && (i < mIndex); it++, i++) ; /* empty loop */ - if (it != store.end()) - { - *peer = *it; - mIndex++; - return 1; - } - return 0; -} - -int bdStore::filterIpList(const std::list &filteredIPs) -{ - // Nasty O(n^2) iteration over 500 entries!!!. - // hope its not used to often. - - std::list::const_iterator it; - for(it = filteredIPs.begin(); it != filteredIPs.end(); it++) - { - std::list::iterator sit; - for(sit = store.begin(); sit != store.end();) - { - if (it->sin_addr.s_addr == sit->mPeerId.addr.sin_addr.s_addr) - { - std::cerr << "bdStore::filterIpList() Found Bad entry in Store. Erasing!"; - std::cerr << std::endl; - - sit = store.erase(sit); - } - else - { - sit++; - } - } - } - return 1; -} - - - -#define MAX_ENTRIES 500 - - /* maintain a sorted list */ -void bdStore::addStore(bdPeer *peer) -{ -#ifdef DEBUG_STORE - std::cerr << "bdStore::addStore() "; - mFns->bdPrintId(std::cerr, &(peer->mPeerId)); - std::cerr << std::endl; -#endif - - /* remove old entry */ - - std::list::iterator it; - for(it = store.begin(); it != store.end(); ) - { - if ((it->mPeerId.addr.sin_addr.s_addr == peer->mPeerId.addr.sin_addr.s_addr) && - (it->mPeerId.addr.sin_port == peer->mPeerId.addr.sin_port)) - { -#ifdef DEBUG_STORE - std::cerr << "bdStore::addStore() Removed Existing Entry: "; - mFns->bdPrintId(std::cerr, &(it->mPeerId)); - std::cerr << std::endl; -#endif - it = store.erase(it); - } - else - { - it++; - } - } - -#ifdef DEBUG_STORE - std::cerr << "bdStore::addStore() Push_back"; - std::cerr << std::endl; -#endif - store.push_back(*peer); - - while(store.size() > MAX_ENTRIES) - { -#ifdef DEBUG_STORE - std::cerr << "bdStore::addStore() pop_front()"; - std::cerr << std::endl; -#endif - store.pop_front(); - } -} - -void bdStore::writeStore(std::string file) -{ - /* write out store */ -#ifdef DEBUG_STORE - fprintf(stderr, "bdStore::writeStore(%s) = %d entries\n", file.c_str(), store.size()); -#endif - - if (store.size() < 0.9 * MAX_ENTRIES) - { - /* don't save yet! */ -#ifdef DEBUG_STORE - fprintf(stderr, "bdStore::writeStore() Delaying until more entries\n"); -#endif - return; - } - - std::string filetmp = file + ".tmp" ; - - FILE *fd = fopen(filetmp.c_str(), "w"); - - if (!fd) - { -#ifdef DEBUG_STORE -#endif - fprintf(stderr, "bdStore::writeStore() FAILED to Open File\n"); - return; - } - - std::list::iterator it; - for(it = store.begin(); it != store.end(); it++) - { - fprintf(fd, "%s %d\n", bdnet_inet_ntoa(it->mPeerId.addr.sin_addr).c_str(), ntohs(it->mPeerId.addr.sin_port)); -#ifdef DEBUG_STORE - fprintf(stderr, "Storing Peer Address: %s %d\n", inet_ntoa(it->mPeerId.addr.sin_addr), ntohs(it->mPeerId.addr.sin_port)); -#endif - - } - fclose(fd); - - if(!bdFile::renameFile(filetmp,file)) - std::cerr << "Could not rename file !!" << std::endl; -#ifdef DEBUG_STORE - else - std::cerr << "Successfully renamed file " << filetmp << " to " << file << std::endl; -#endif -} - -void bdStore::writeStore() -{ -#if 0 - if (mStoreFile == "") - { - return; - } -#endif - return writeStore(mStoreFile); -} - - - diff --git a/libbitdht/src/bitdht/bdstore.h b/libbitdht/src/bitdht/bdstore.h deleted file mode 100644 index 2202f0553..000000000 --- a/libbitdht/src/bitdht/bdstore.h +++ /dev/null @@ -1,54 +0,0 @@ -/******************************************************************************* - * bitdht/bdstore.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef BITDHT_STORE_H -#define BITDHT_STORE_H - -#include -#include "bitdht/bdiface.h" -#include "bitdht/bdpeer.h" - -class bdStore -{ -public: - - bdStore(std::string file, std::string backupfile, bdDhtFunctions *fns); - - int reloadFromStore(); /* for restarts */ - int reloadFromStore(std::string file); - int filterIpList(const std::list &filteredIPs); - int clear(); - - int getPeer(bdPeer *peer); - void addStore(bdPeer *peer); - void writeStore(std::string file); - void writeStore(); - -protected: - std::string mStoreFile; - std::string mStoreFileBak; - std::list store; - int mIndex; - bdDhtFunctions *mFns; -}; - - -#endif diff --git a/libbitdht/src/bitdht/bencode.c b/libbitdht/src/bitdht/bencode.c deleted file mode 100644 index a496f5bc3..000000000 --- a/libbitdht/src/bitdht/bencode.c +++ /dev/null @@ -1,649 +0,0 @@ -/******************************************************************************* - * bitdht/bdencode.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * by Mike Frysinger * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -/* - * This implementation isn't optimized at all as I wrote it to support - * a bogus system. I have no real interest in this format. Feel free - * to send me patches (so long as you don't copyright them and you release - * your changes into the public domain as well). - */ - -#include -#include /* malloc() realloc() free() strtoll() */ -#include /* memset() */ -#include "util/bdstring.h" - -#include "bitdht/bencode.h" - -/*** - * #define BE_DEBUG_DECODE 1 - * #define BE_DEBUG 1 // controlled from Makefile too. - ***/ - -#ifdef BE_DEBUG_DECODE - #include /* debug */ -#endif - -static be_node *be_alloc(be_type type) -{ - be_node *ret = (be_node *) malloc(sizeof(*ret)); - if (ret) { - memset(ret, 0x00, sizeof(*ret)); - ret->type = type; - } - return ret; -} - -static long long _be_decode_int(const char **data, long long *data_len) -{ - char *endp; - long long ret = strtoll(*data, &endp, 10); - *data_len -= (endp - *data); - *data = endp; - -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode_int(pnt: %p, rem: %lld) = %lld\n", *data, *data_len, ret); -#endif - return ret; -} - -long long be_str_len(be_node *node) -{ - long long ret = 0; - if (node->val.s) - memcpy(&ret, node->val.s - sizeof(ret), sizeof(ret)); - return ret; -} - -static char *_be_decode_str(const char **data, long long *data_len) -{ -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode_str(pnt: %p, rem: %lld)\n", *data, *data_len); -#endif - long long sllen = _be_decode_int(data, data_len); - long slen = sllen; - unsigned long len; - char *ret = NULL; - - /* slen is signed, so negative values get rejected */ - if (sllen < 0) - { -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode_str() reject bad length\n"); -#endif - return ret; - } - - /* reject attempts to allocate large values that overflow the - * size_t type which is used with malloc() - */ - if (sizeof(long long) != sizeof(long)) - if (sllen != slen) - { -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode_str() reject large_values\n"); -#endif - return ret; - } - - /* make sure we have enough data left */ - if (sllen > *data_len - 1) - { -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode_str() reject large_values\n"); -#endif - return ret; - } - - /* switch from signed to unsigned so we don't overflow below */ - len = slen; - - if (**data == ':') { - char *_ret = (char *) malloc(sizeof(sllen) + len + 1); - - if(_ret == NULL) - { - fprintf(stderr, "(EE) bencode::_be_decode_str(): " - "ERROR. cannot allocate memory for %lu bytes.\n" - , len+1+sizeof(sllen) ); - return ret; - } - - memcpy(_ret, &sllen, sizeof(sllen)); - ret = _ret + sizeof(sllen); - memcpy(ret, *data + 1, len); - ret[len] = '\0'; - *data += len + 1; - *data_len -= len + 1; - -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode_str() read %ld bytes\n", len+1); -#endif - } - else - { -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode_str() reject missing :\n"); -#endif - } - return ret; -} - -static be_node *_be_decode(const char **data, long long *data_len) -{ -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode(pnt: %p, rem: %lld)\n", *data, *data_len); -#endif - be_node *ret = NULL; - - if (!*data_len) - { -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode() reject invalid datalen\n"); -#endif - return ret; - } - - switch (**data) { - /* lists */ - case 'l': { - unsigned int i = 0; -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode() found list\n"); -#endif - - ret = be_alloc(BE_LIST); - - --(*data_len); - ++(*data); - while (**data != 'e') { -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode() list get item (%d)\n", i); -#endif - ret->val.l = (be_node **) realloc(ret->val.l, (i + 2) * sizeof(*ret->val.l)); - ret->val.l[i] = _be_decode(data, data_len); - if (ret->val.l[i] == NULL) - { - /* failed decode - kill decode */ -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode() failed list decode - kill\n"); -#endif - be_free(ret); - return NULL; - } - ++i; - } - --(*data_len); - ++(*data); - - /* empty list case. */ - if (i == 0) - { - ret->val.l = (be_node **) realloc(ret->val.l, 1 * sizeof(*ret->val.l)); - } - - ret->val.l[i] = NULL; - - return ret; - } - - /* dictionaries */ - case 'd': { - unsigned int i = 0; -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode() found dictionary\n"); -#endif - - ret = be_alloc(BE_DICT); - - --(*data_len); - ++(*data); - while (**data != 'e') { -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode() dictionary get key (%d)\n", i); -#endif - ret->val.d = (be_dict *) realloc(ret->val.d, (i + 2) * sizeof(*ret->val.d)); - ret->val.d[i].key = _be_decode_str(data, data_len); -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode() dictionary get val\n"); -#endif - ret->val.d[i ].val = _be_decode(data, data_len); - ret->val.d[i+1].val = NULL ; // ensures termination of loops based on 0x0 value, otherwise, uninitialized - // memory occurs if(ret->val.d[i].key == 0x0 && ret->val.d[i].val != NULL) - // when calling be_free 8 lines below this point... - - if ((ret->val.d[i].key == NULL) || (ret->val.d[i].val == NULL)) - { - /* failed decode - kill decode */ -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode() failed dict decode - kill\n"); -#endif - be_free(ret); - return NULL; - } - ++i; - } - --(*data_len); - ++(*data); - - /* empty dictionary case. */ - if (i == 0) - { - ret->val.d = (be_dict *) realloc(ret->val.d, 1 * sizeof(*ret->val.d)); - } - - - ret->val.d[i].val = NULL; - return ret; - } - - /* integers */ - case 'i': { - ret = be_alloc(BE_INT); -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode() found int\n"); -#endif - - --(*data_len); - ++(*data); - ret->val.i = _be_decode_int(data, data_len); - if (**data != 'e') - { -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode() reject data != e - kill\n"); -#endif - be_free(ret); - return NULL; - } - --(*data_len); - ++(*data); - - return ret; - } - - /* byte strings */ - case '0'...'9': { - ret = be_alloc(BE_STR); -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode() found string\n"); -#endif - - ret->val.s = _be_decode_str(data, data_len); - - return ret; - } - - /* invalid */ - default: -#ifdef BE_DEBUG_DECODE - fprintf(stderr, "bencode::_be_decode() found invalid - kill\n"); -#endif - return NULL; - break; - } - - return ret; -} - -be_node *be_decoden(const char *data, long long len) -{ - return _be_decode(&data, &len); -} - -be_node *be_decode(const char *data) -{ - return be_decoden(data, strlen(data)); -} - -static inline void _be_free_str(char *str) -{ - if (str) - free(str - sizeof(long long)); -} -void be_free(be_node *node) -{ - switch (node->type) { - case BE_STR: - _be_free_str(node->val.s); - break; - - case BE_INT: - break; - - case BE_LIST: { - unsigned int i; - for (i = 0; node->val.l[i]; ++i) - be_free(node->val.l[i]); - free(node->val.l); - break; - } - - case BE_DICT: { - unsigned int i; - for (i = 0; node->val.d[i].val; ++i) { - _be_free_str(node->val.d[i].key); - be_free(node->val.d[i].val); - } - free(node->val.d); - break; - } - } - free(node); -} - -#ifdef BE_DEBUG -#include -#include - -static void _be_dump_indent(ssize_t indent) -{ - while (indent-- > 0) - printf(" "); -} -static void _be_dump(be_node *node, ssize_t indent) -{ - size_t i; - - _be_dump_indent(indent); - indent = abs(indent); - - switch (node->type) { - case BE_STR: - be_dump_str(node); - //printf("str = %s (len = %lli)\n", node->val.s, be_str_len(node)); - break; - - case BE_INT: - printf("int = %lli\n", node->val.i); - break; - - case BE_LIST: - puts("list ["); - - for (i = 0; node->val.l[i]; ++i) - _be_dump(node->val.l[i], indent + 1); - - _be_dump_indent(indent); - puts("]"); - break; - - case BE_DICT: - puts("dict {"); - - for (i = 0; node->val.d[i].val; ++i) { - _be_dump_indent(indent + 1); - printf("%s => ", node->val.d[i].key); - _be_dump(node->val.d[i].val, -(indent + 1)); - } - - _be_dump_indent(indent); - puts("}"); - break; - } -} -void be_dump(be_node *node) -{ - _be_dump(node, 0); -} - -void be_dump_str(be_node *node) -{ - if (node->type != BE_STR) - { - printf("be_dump_str(): error not a string\n"); - return; - } - - int len = be_str_len(node); - int i = 0; - printf("str[%d] = ", len); - for(i = 0; i < len; i++) - { - /* sensible chars */ - if ((node->val.s[i] > 31) && (node->val.s[i] < 127)) - { - printf("%c", node->val.s[i]); - } - else - { - printf("[%d]", node->val.s[i]); - } - } - printf("\n"); -} - - -#endif - -/******************** New Functions added by drBob ************* - * Output bencode - * - */ - -int be_encode(be_node *node, char *str, int len) -{ - size_t i; - int loc = 0; - - switch (node->type) { - case BE_STR: - bd_snprintf(str, len, "%lli:", be_str_len(node)); - loc += strlen(&(str[loc])); - - memcpy(&(str[loc]), node->val.s, be_str_len(node)); - loc += be_str_len(node); - break; - - case BE_INT: - bd_snprintf(str, len, "i%llie", node->val.i); - loc += strlen(&(str[loc])); - break; - - case BE_LIST: - - snprintf(str, len, "l"); - loc += 1; - - for (i = 0; node->val.l[i]; ++i) - { - loc += be_encode(node->val.l[i], &(str[loc]), len-loc); - } - - snprintf(&(str[loc]), len - loc, "e"); - loc += 1; - - break; - - case BE_DICT: - snprintf(str, len, "d"); - loc += 1; - - for (i = 0; node->val.d[i].val; ++i) { - - /* assumption that key must be ascii! */ - snprintf(&(str[loc]), len-loc, "%i:%s", - (int) strlen(node->val.d[i].key), - node->val.d[i].key); - loc += strlen(&(str[loc])); - loc += be_encode(node->val.d[i].val, &(str[loc]), len-loc); - } - - snprintf(&(str[loc]), len - loc, "e"); - loc += 1; - - break; - } - return loc; -} - -/* hackish way to create nodes! */ -be_node *be_create_dict() -{ - be_node *n = be_decode("de"); - return n; -} - - -be_node *be_create_list() -{ - be_node *n = be_decode("le"); - return n; -} - -be_node *be_create_str(const char *str) -{ - - /* must */ - be_node *n = NULL; - int len = strlen(str); - long long int sllen = len; - char *_ret = (char *) malloc(sizeof(sllen) + len + 1); - if(_ret == NULL) - { - fprintf(stderr, "(EE) bencode::be_create_str(): " - "ERROR. cannot allocate memory for %lu bytes.\n" - , len+1+sizeof(sllen) ); - return n; - } - char *ret = NULL; - n = be_alloc(BE_STR); - - memcpy(_ret, &sllen, sizeof(sllen)); - ret = _ret + sizeof(sllen); - memcpy(ret, str, len); - ret[len] = '\0'; - - n->val.s = ret; - - return n; -} - -be_node *be_create_str_wlen(const char *str, int len) /* not including \0 */ -{ - - /* must */ - be_node *n = NULL; - long long int sllen = len; - char *_ret = (char *) malloc(sizeof(sllen) + len + 1); - if(_ret == NULL) - { - fprintf(stderr, "(EE) bencode::be_create_str_wlen(): " - "ERROR. cannot allocate memory for %lu bytes.\n" - , len+1+sizeof(sllen) ); - return n; - } - char *ret = NULL; - n = be_alloc(BE_STR); - - memcpy(_ret, &sllen, sizeof(sllen)); - ret = _ret + sizeof(sllen); - memcpy(ret, str, len); - ret[len] = '\0'; - - n->val.s = ret; - - return n; -} - -be_node *be_create_int(long long int num) -{ - /* must */ - be_node *n = be_alloc(BE_INT); - n->val.i = num; - return n; -} - -int be_add_keypair(be_node *dict, const char *str, be_node *node) -{ - int i = 0; - - /* only if dict type */ - if (dict->type != BE_DICT) - { - return 0; - } - - // get to end of dict. - for(i = 0; dict->val.d[i].val; i++) - ;//Silent empty body for loop for clang - - //fprintf(stderr, "be_add_keypair() i = %d\n",i); - - /* realloc space */ - dict->val.d = (be_dict *) realloc(dict->val.d, (i + 2) * sizeof(*dict->val.d)); - - /* stupid key storage system */ - int len = strlen(str); - long long int sllen = len; - char *_ret = (char *) malloc(sizeof(sllen) + len + 1); - if(_ret == NULL) - { - fprintf(stderr, "(EE) bencode::be_create_str_wlen(): " - "ERROR. cannot allocate memory for %lu bytes.\n" - , len+1+sizeof(sllen) ); - return 0; - } - char *ret = NULL; - - //fprintf(stderr, "be_add_keypair() key len = %d\n",len); - - memcpy(_ret, &sllen, sizeof(sllen)); - ret = _ret + sizeof(sllen); - memcpy(ret, str, len); - ret[len] = '\0'; - - dict->val.d[i].key = ret; - dict->val.d[i].val = node; - i++; - dict->val.d[i].val = NULL; - - return 1; -} - - -int be_add_list(be_node *list, be_node *node) -{ - int i = 0; - - /* only if dict type */ - if (list->type != BE_LIST) - { - return 0; - } - - // get to end of dict. - for(i = 0; list->val.l[i]; i++) - ;//Silent empty body for loop for clang - - /* realloc space */ - list->val.l = (be_node **) realloc(list->val.l, (i + 2) * sizeof(*list->val.l)); - list->val.l[i] = node; - ++i; - list->val.l[i] = NULL; - - return 1; -} - - - - diff --git a/libbitdht/src/bitdht/bencode.h b/libbitdht/src/bitdht/bencode.h deleted file mode 100644 index 4e733b66f..000000000 --- a/libbitdht/src/bitdht/bencode.h +++ /dev/null @@ -1,92 +0,0 @@ -/******************************************************************************* - * bitdht/bdencode.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * by Mike Frysinger * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef _BENCODE_H -#define _BENCODE_H - -/* USAGE: - * - pass the string full of the bencoded data to be_decode() - * - parse the resulting tree however you like - * - call be_free() on the tree to release resources - */ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - BE_STR, - BE_INT, - BE_LIST, - BE_DICT, -} be_type; - -struct be_dict; -struct be_node; - -/* - * XXX: the "val" field of be_dict and be_node can be confusing ... - */ - -typedef struct be_dict { - char *key; - struct be_node *val; -} be_dict; - -typedef struct be_node { - be_type type; - union { - char *s; - long long i; - struct be_node **l; - struct be_dict *d; - } val; -} be_node; - -extern long long be_str_len(be_node *node); -// This function uses strlen, so is unreliable. -//extern be_node *be_decode(const char *bencode); -extern be_node *be_decoden(const char *bencode, long long bencode_len); -extern void be_free(be_node *node); -extern void be_dump(be_node *node); -extern void be_dump_str(be_node *node); - -// New Functions for the other half of the work - encoding */ - -extern int be_encode(be_node *node, char *str, int len); - - -// Creating the data structure. -extern int be_add_list(be_node *list, be_node *node); -extern int be_add_keypair(be_node *dict, const char *str, be_node *node); -extern be_node *be_create_int(long long int num); -extern be_node *be_create_list(); -extern be_node *be_create_str(const char *str); -extern be_node *be_create_str_wlen(const char *str, int len); /* not including \0 */ -extern be_node *be_create_dict(); - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/libbitdht/src/example/bdboot.txt b/libbitdht/src/example/bdboot.txt deleted file mode 100644 index 1d0d204af..000000000 --- a/libbitdht/src/example/bdboot.txt +++ /dev/null @@ -1,500 +0,0 @@ -77.196.18.56 22750 -77.84.97.16 31837 -213.174.60.46 17919 -50.113.92.209 6881 -184.89.243.73 43344 -210.195.47.196 19861 -83.49.197.212 61627 -184.145.109.37 31067 -180.18.98.235 29543 -186.254.61.185 40200 -78.213.113.102 9182 -89.92.251.113 16946 -195.240.45.224 6881 -188.142.164.252 43063 -41.45.41.123 18636 -219.84.184.204 61337 -95.26.91.94 6881 -79.114.193.207 17966 -83.213.185.157 43235 -37.110.127.110 6881 -178.35.204.111 6881 -174.48.201.143 41918 -109.214.57.82 1042 -121.214.57.226 51413 -90.184.93.164 22828 -98.214.166.21 38072 -50.0.146.178 51413 -81.13.253.217 46370 -81.249.29.121 7812 -92.80.201.189 20026 -95.37.18.51 59118 -50.53.143.88 57568 -180.183.213.112 11823 -112.206.13.117 41825 -79.169.77.54 63189 -76.174.205.156 8605 -2.1.187.15 50269 -175.151.131.80 16001 -82.7.124.219 12334 -217.209.125.15 26155 -93.181.201.89 54631 -197.87.68.102 25317 -183.109.112.49 58359 -203.198.141.201 7453 -82.192.32.151 58864 -184.146.76.179 13586 -37.107.121.203 18429 -186.54.1.246 38354 -184.18.8.33 8784 -77.101.130.178 61762 -109.8.154.28 19120 -74.96.156.188 31749 -94.96.167.130 64130 -93.81.126.53 6881 -79.136.243.46 46486 -78.29.75.248 6881 -114.42.47.178 9089 -31.147.61.11 23853 -193.253.220.184 6881 -80.57.45.239 28239 -72.192.215.39 30028 -91.74.119.134 49246 -85.250.43.217 41490 -188.176.218.22 35407 -98.119.4.86 1024 -89.143.138.33 64606 -46.138.37.148 59039 -178.120.85.170 24550 -67.185.95.9 32173 -98.197.42.116 19866 -114.38.21.113 7694 -77.46.26.128 38127 -93.80.96.134 23683 -60.241.209.107 57588 -171.97.173.243 9327 -50.43.117.21 42660 -87.244.169.128 55807 -94.190.105.157 6881 -178.122.199.251 16480 -76.88.254.191 27137 -112.120.144.128 60152 -77.249.124.77 49187 -165.132.236.14 25390 -87.16.197.67 20787 -80.103.109.43 55260 -195.234.21.119 6881 -176.212.60.108 60378 -178.185.98.43 12420 -124.149.151.181 33603 -85.220.66.170 35131 -109.130.31.27 11460 -72.223.102.189 11614 -111.15.147.164 16001 -83.202.163.16 6881 -92.246.22.40 33576 -94.41.249.131 10613 -95.24.101.211 6881 -98.232.199.100 29721 -174.101.153.252 38195 -91.157.230.16 1885 -109.211.143.205 13722 -84.123.4.247 29043 -112.209.16.158 19102 -114.34.46.63 6881 -85.138.230.74 56197 -62.169.127.9 26665 -211.217.2.251 41870 -81.221.84.77 20214 -109.197.191.45 19604 -46.118.116.209 20711 -46.42.23.240 53559 -199.127.250.15 29015 -78.220.115.99 49482 -71.232.195.149 56530 -84.123.59.159 13963 -213.251.184.146 64347 -67.164.23.233 7119 -86.194.215.166 14316 -89.224.149.142 25365 -94.23.49.143 8000 -78.119.193.151 55227 -78.222.160.139 37995 -89.209.82.248 12425 -178.137.112.35 14571 -94.23.0.84 51582 -78.247.176.4 18105 -90.41.206.239 30502 -78.241.70.65 22014 -98.194.6.21 51413 -174.119.150.115 17065 -189.5.22.202 52412 -93.124.97.171 49001 -186.4.42.27 20837 -24.144.184.102 14888 -78.173.175.56 53453 -79.114.14.206 4602 -109.184.163.146 11789 -98.200.252.137 18502 -79.82.130.49 20757 -5.165.66.132 63326 -46.29.147.201 20232 -114.32.184.15 25962 -94.21.70.206 50541 -92.98.171.108 51413 -188.49.25.79 46883 -90.149.227.168 49241 -92.99.221.105 51405 -123.139.45.71 16001 -68.98.108.234 24290 -88.169.60.195 17108 -114.37.154.22 16120 -121.219.232.47 65073 -46.119.196.109 19075 -123.110.104.200 29499 -77.73.46.124 28966 -87.253.26.85 45934 -176.108.146.88 6881 -188.187.45.126 43757 -92.2.212.97 15078 -178.140.169.137 22922 -114.38.14.84 16958 -80.98.106.227 9773 -86.169.117.185 51938 -201.53.229.60 1041 -65.95.191.51 51413 -24.78.8.98 6884 -90.204.42.12 48402 -76.7.214.210 35875 -88.155.36.246 15856 -78.227.88.161 23191 -62.83.111.85 36398 -130.43.29.146 52526 -88.170.61.126 32761 -85.246.109.226 6890 -82.237.40.39 39052 -95.239.56.106 62200 -71.187.209.2 22274 -178.148.68.18 53318 -78.163.220.242 31758 -188.235.149.202 63083 -119.201.103.241 62715 -83.87.5.5 43317 -201.83.71.123 50579 -83.6.22.221 52512 -95.54.76.150 56930 -207.255.112.154 6881 -188.121.244.133 10980 -41.212.221.164 33050 -178.168.58.44 23476 -142.161.41.171 41788 -211.133.168.214 44631 -220.18.72.3 64774 -70.114.155.3 34892 -97.85.86.199 6890 -119.74.54.94 6881 -114.34.239.242 22647 -67.128.168.196 11524 -86.145.211.200 49330 -72.230.75.87 21095 -31.35.57.129 13924 -190.60.48.165 41301 -213.245.41.143 40018 -95.104.80.193 6881 -120.208.30.229 16001 -93.105.81.215 21000 -93.96.13.136 12181 -190.88.179.253 20701 -58.7.210.130 51413 -195.222.95.57 51413 -121.223.47.224 41563 -85.219.118.111 27483 -78.43.137.174 10409 -77.71.220.234 62357 -85.107.182.248 19486 -37.235.207.247 30166 -176.97.212.163 22523 -88.230.184.110 25432 -94.44.164.74 60966 -95.188.23.129 42927 -78.242.168.94 34153 -62.93.99.6 28010 -78.105.105.87 42127 -208.101.109.128 53329 -164.215.87.224 57073 -87.106.187.29 20277 -91.121.114.171 58846 -80.42.246.251 20502 -188.72.98.36 15503 -176.31.248.87 6338 -118.160.199.38 63400 -174.71.20.57 52193 -113.161.204.192 6881 -2.94.72.90 27587 -89.204.110.192 6881 -76.121.38.23 58982 -93.95.160.156 13118 -122.174.156.164 15004 -94.155.59.112 57833 -176.49.172.107 49001 -23.16.200.217 51413 -60.241.87.17 24478 -108.242.252.38 39304 -201.252.144.11 15506 -92.125.17.239 25548 -114.79.138.158 60635 -76.103.79.28 36151 -77.71.69.65 12087 -138.199.66.212 26174 -119.131.41.152 1231 -119.202.178.119 45249 -78.141.127.164 55618 -88.245.188.55 28097 -217.165.53.221 24579 -46.22.234.12 14916 -98.199.98.228 32970 -203.213.94.200 14161 -66.197.135.74 9870 -213.167.206.125 38106 -80.83.245.36 6993 -112.203.171.200 25932 -105.236.34.74 43961 -92.49.5.186 38678 -46.61.12.234 49001 -91.148.14.62 11206 -95.37.162.145 14476 -68.192.162.202 31159 -68.209.239.148 50375 -75.185.11.189 23993 -178.72.159.43 47954 -118.160.199.38 61182 -75.142.21.2 56117 -46.187.88.219 48529 -98.127.163.114 53062 -94.245.153.136 23040 -109.174.3.81 51413 -77.232.162.51 14257 -94.96.112.204 35187 -118.160.199.38 51651 -5.13.18.103 24121 -79.226.190.78 18189 -95.90.236.216 41463 -83.134.60.207 10267 -118.160.199.38 51532 -176.31.109.159 24586 -99.242.88.203 21704 -88.174.176.173 56969 -84.151.248.98 61500 -123.195.214.39 20846 -94.62.25.152 39020 -89.33.72.233 1398 -92.37.27.83 37375 -83.110.225.79 17257 -178.36.198.215 22849 -112.234.202.158 16001 -188.231.143.20 6881 -5.12.126.206 34538 -62.65.216.158 13414 -92.43.189.45 3140 -79.9.144.222 29037 -93.77.32.187 57408 -91.247.142.205 58199 -85.114.60.149 17582 -119.196.44.47 51763 -178.88.3.227 33031 -76.30.131.83 49366 -86.168.167.166 55451 -212.45.81.173 16427 -188.224.10.109 46059 -82.178.114.74 50836 -78.55.114.191 42839 -85.54.211.184 17283 -95.135.101.164 55829 -209.195.77.83 34603 -79.153.101.234 11154 -71.63.225.31 21053 -184.147.116.143 49025 -88.186.230.88 12048 -89.132.181.63 61498 -95.84.208.14 9372 -79.93.218.69 28681 -64.113.125.178 61127 -174.100.51.253 44460 -88.3.236.194 10926 -109.194.234.36 14342 -68.106.225.140 47417 -78.24.231.166 6881 -84.40.80.3 6890 -177.5.36.152 12588 -68.82.32.238 18307 -64.121.118.201 61270 -75.40.21.238 51413 -99.59.129.46 26141 -79.95.171.102 11092 -67.71.140.245 15582 -95.32.187.214 14778 -213.112.177.129 43304 -81.51.97.133 40039 -89.133.89.51 55846 -79.18.246.192 20356 -109.124.197.42 31559 -182.53.45.3 14895 -74.219.135.69 30239 -95.111.0.20 34295 -84.154.235.198 59678 -93.58.14.83 51413 -213.114.48.42 38511 -46.48.90.11 55025 -5.2.58.49 49001 -92.139.252.16 36535 -94.68.144.118 10009 -75.187.202.104 44822 -84.52.169.26 10838 -114.32.211.85 30116 -75.69.72.31 51413 -118.160.199.38 63151 -142.59.218.136 11300 -118.160.199.38 63619 -118.160.199.38 59277 -82.47.63.231 26035 -67.8.141.69 63990 -223.18.249.29 7221 -82.136.113.22 6881 -86.100.227.142 50497 -188.186.13.95 21313 -24.128.39.166 5223 -31.8.136.66 11996 -82.137.118.90 26474 -84.217.43.156 45620 -217.29.187.23 62523 -108.254.5.66 58192 -182.177.228.43 31532 -118.160.199.38 60134 -67.167.180.162 11451 -188.164.212.104 28566 -95.196.203.111 59402 -213.27.20.223 53410 -178.44.187.32 52209 -70.83.35.78 31982 -1.172.161.190 17526 -78.237.111.89 45254 -188.25.246.130 16313 -67.173.33.90 33134 -212.49.47.32 19949 -176.214.214.73 64892 -173.73.46.92 52828 -71.237.6.246 41304 -70.113.2.167 45645 -88.84.191.25 30536 -87.2.74.180 6783 -96.63.15.208 34651 -76.181.135.146 17016 -79.168.31.62 2622 -95.153.169.40 19697 -88.217.36.182 2924 -119.96.130.9 12038 -90.225.103.241 40066 -78.106.178.64 46183 -220.136.37.144 27075 -92.87.167.73 55624 -188.232.61.83 6881 -183.89.3.101 10618 -111.242.54.149 15979 -120.146.228.149 6881 -67.242.169.143 6886 -31.8.71.71 10170 -78.236.77.65 32026 -91.137.168.238 27616 -93.109.84.235 21443 -77.34.44.71 35691 -109.209.40.17 55542 -83.157.77.228 7812 -88.233.167.39 20620 -69.176.171.40 11254 -93.11.175.201 41027 -50.71.135.98 20332 -69.181.169.181 7313 -46.8.136.196 57085 -180.64.39.48 14708 -46.211.113.5 49001 -142.163.53.182 58144 -90.38.76.72 4699 -83.252.23.84 10699 -78.163.181.120 16519 -221.118.191.176 17563 -184.41.75.34 57537 -99.192.77.139 33333 -88.174.167.76 30032 -46.116.177.103 22754 -94.103.196.139 54378 -188.77.246.133 35496 -217.76.184.18 51413 -108.160.185.132 31530 -50.83.34.19 23846 -193.77.159.24 43611 -80.14.161.164 51789 -114.185.184.10 23151 -82.235.101.26 7816 -92.83.188.95 10477 -46.180.245.79 53580 -46.37.83.122 37389 -86.29.220.199 28527 -92.137.208.191 29253 -85.167.249.218 55649 -221.127.216.99 21461 -130.89.165.24 10110 -99.60.78.40 18894 -49.145.59.194 38935 -92.247.248.50 23666 -5.149.211.210 22277 -176.226.153.243 61967 -174.117.49.59 13052 -121.141.14.57 30323 -83.155.218.188 51413 -129.21.122.81 32785 -46.118.83.183 12324 -92.255.208.221 34798 -212.21.13.209 56909 -220.120.236.151 11393 -37.218.190.131 35691 -46.41.109.26 39584 -2.51.116.185 63433 -67.86.174.199 33605 -212.74.222.13 38345 -115.240.98.113 51413 -37.59.55.58 51413 -109.72.144.240 41290 -207.224.196.66 10731 -78.128.52.177 24574 -79.138.67.151 47942 -50.201.138.122 10228 -176.9.113.77 61059 -94.21.30.143 63448 -178.89.100.227 6881 -91.67.129.216 1210 -82.232.212.66 55826 -78.228.230.130 12577 -79.175.106.234 12684 -213.231.145.208 12306 -97.106.156.54 63552 -79.176.173.50 33043 -75.70.84.67 52856 -31.220.168.41 35190 -1.161.107.196 31811 -80.98.158.177 29436 -88.148.233.194 38081 -184.166.72.229 63472 -93.186.192.165 39020 -151.25.110.226 49289 -178.45.159.135 31825 -98.225.11.98 51769 -109.28.82.4 33620 -90.16.53.195 31338 -223.219.73.227 17107 -92.96.51.71 56237 -112.173.11.227 63314 -37.229.60.103 6881 -90.29.226.250 14329 -182.210.49.84 11993 -177.32.251.226 27655 -189.54.195.49 50555 diff --git a/libbitdht/src/example/bdhandler.cc b/libbitdht/src/example/bdhandler.cc deleted file mode 100644 index 0b8766a5a..000000000 --- a/libbitdht/src/example/bdhandler.cc +++ /dev/null @@ -1,349 +0,0 @@ -/* - * libretroshare/src/dht: bdhandler.h - * - * BitDht example interface - * - * Copyright 2009-2010 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include -#include -#include -#include - -#include - -#include "bdhandler.h" - - -/**** - * This example bitdht app is designed to perform a single shot DHT search. - * Ww want to minimise the dht work, and number of UDP packets sent. - * - * This means we need to add: - * - don't search for App network. (libbitdht option) - * - don't bother filling up Space. (libbitdht option) - * - Programmatically add bootstrap peers. (libbitdht option) - * - */ - - - -/* This is a conversion callback class - */ - -class BdCallback: public BitDhtCallback -{ - public: - - BdCallback(BitDhtHandler *parent) - :mParent(parent) { return; } - -virtual int dhtNodeCallback(const bdId *id, uint32_t peerflags) -{ - return mParent->NodeCallback(id, peerflags); -} - -virtual int dhtPeerCallback(const bdId *id, uint32_t status) -{ - return mParent->PeerCallback(id, status); -} - -virtual int dhtValueCallback(const bdNodeId *id, std::string key, uint32_t status) -{ - return mParent->ValueCallback(id, key, status); -} - -virtual int dhtConnectCallback(const bdId*, const bdId*, const bdId*, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t) -{ - return 1; -} - -virtual int dhtInfoCallback(const bdId*, uint32_t, uint32_t, std::string) -{ - return 1; -} - - private: - - BitDhtHandler *mParent; -}; - - -BitDhtHandler::BitDhtHandler(bdNodeId *ownId, uint16_t port, std::string appId, std::string bootstrapfile) -{ - std::cerr << "BitDhtHandler::BitDhtHandler()" << std::endl; - std::cerr << "Using Id: "; - bdStdPrintNodeId(std::cerr, ownId); - std::cerr << std::endl; - - std::cerr << "Using Bootstrap File: " << bootstrapfile; - std::cerr << std::endl; - std::cerr << "Converting OwnId to bdNodeId...."; - std::cerr << std::endl; - - /* standard dht behaviour */ - bdDhtFunctions *stdfns = new bdStdDht(); - - std::cerr << "BitDhtHandler() startup ... creating UdpBitDht"; - std::cerr << std::endl; - - /* create dht */ - struct sockaddr_in local; - memset(&local, 0, sizeof(local)); - local.sin_family = AF_INET; - local.sin_addr.s_addr = 0; - local.sin_port = htons(port); - - mStack = new UdpStack(local); - - mUdpBitDht = new UdpBitDht(mStack, ownId, appId, bootstrapfile, stdfns); - mStack->addReceiver(mUdpBitDht); - - /* setup callback to here */ - BdCallback *bdcb = new BdCallback(this); - mUdpBitDht->addCallback(bdcb); - - std::cerr << "BitDhtHandler() starting threads and dht"; - std::cerr << std::endl; - - mUdpBitDht->start(); /* starts up the bitdht thread */ - - /* setup best mode for quick search */ - uint32_t dhtFlags = BITDHT_MODE_TRAFFIC_MED | BITDHT_MODE_RELAYSERVERS_IGNORED; - mUdpBitDht->setDhtMode(dhtFlags); - mUdpBitDht->setAttachMode(false); - - /* switch on the dht too */ - mUdpBitDht->startDht(); -} - - /* pqiNetAssist - external interface functions */ -void BitDhtHandler::enable(bool on) -{ - std::cerr << "p3BitDht::enable(" << on << ")"; - std::cerr << std::endl; - if (on) - { - mUdpBitDht->startDht(); - } - else - { - mUdpBitDht->stopDht(); - } -} - -void BitDhtHandler::shutdown() /* blocking call */ -{ - mUdpBitDht->stopDht(); -} - - -void BitDhtHandler::restart() -{ - mUdpBitDht->stopDht(); - mUdpBitDht->startDht(); -} - -bool BitDhtHandler::getEnabled() -{ - return (mUdpBitDht->stateDht() != 0); -} - -bool BitDhtHandler::getActive() -{ - return (mUdpBitDht->stateDht() >= BITDHT_MGR_STATE_ACTIVE); -} - - - - - /* pqiNetAssistConnect - external interface functions */ - /* add / remove peers */ -bool BitDhtHandler::FindNode(bdNodeId *peerId) -{ - std::cerr << "BitDhtHandler::FindNode("; - bdStdPrintNodeId(std::cerr, peerId); - std::cerr << ")" << std::endl; - - - BssResult res; - res.id.id = *peerId; - res.mode = BSS_SINGLE_SHOT; - res.status = 0; - - { - bdStackMutex stack(resultsMtx); /********** MUTEX LOCKED *************/ - mSearchNodes[*peerId] = res; - } - - /* add in peer */ - mUdpBitDht->addFindNode(peerId, BITDHT_QFLAGS_DISGUISE); - - return true ; -} - -bool BitDhtHandler::DropNode(bdNodeId *peerId) -{ - std::cerr << "BitDhtHandler::DropNode("; - bdStdPrintNodeId(std::cerr, peerId); - std::cerr << ")" << std::endl; - std::cerr << std::endl; - - /* remove in peer */ - mUdpBitDht->removeFindNode(peerId); - - bdStackMutex stack(resultsMtx); /********** MUTEX LOCKED *************/ - - /* find the node from our list */ - std::map::iterator it; - it = mSearchNodes.find(*peerId); - if (it != mSearchNodes.end()) - { - std::cerr << "BitDhtHandler::DropNode() Found NodeId, removing"; - std::cerr << std::endl; - - mSearchNodes.erase(it); - } - return true ; -} - - -bool BitDhtHandler::SearchResult(bdId *id, uint32_t &status) -{ - bdStackMutex stack(resultsMtx); /********** MUTEX LOCKED *************/ - - /* find the node from our list */ - std::map::iterator it; - it = mSearchNodes.find(id->id); - if (it != mSearchNodes.end()) - { - if (it->second.status != 0) - { - std::cerr << "BitDhtHandler::SearchResults() Found Results"; - std::cerr << std::endl; - status = it->second.status; - *id = it->second.id; - return true; - } - - std::cerr << "BitDhtHandler::SearchResults() No Results Yet"; - std::cerr << std::endl; - return false; - } - - std::cerr << "BitDhtHandler::SearchResults() ERROR: No Search Entry"; - std::cerr << std::endl; - return false; -} - - -/********************** Callback Functions **************************/ - -int BitDhtHandler::NodeCallback(const bdId *id, uint32_t peerflags) -{ -#ifdef DEBUG_BITDHT - std::cerr << "BitDhtHandler::NodeCallback()"; - bdStdPrintNodeId(std::cerr, &(id->id)); - std::cerr << " flags: " << peerflags; - std::cerr << std::endl; -#endif - - return 0; -} - -int BitDhtHandler::PeerCallback(const bdId *id, uint32_t status) -{ - std::cerr << "BitDhtHandler::PeerCallback() NodeId: "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; - - bdStackMutex stack(resultsMtx); /********** MUTEX LOCKED *************/ - - /* find the node from our list */ - std::map::iterator it; - it = mSearchNodes.find(id->id); - if (it == mSearchNodes.end()) - { - std::cerr << "BitDhtHandler::PeerCallback() Unknown NodeId !!! "; - std::cerr << std::endl; - - return 1; - } - it->second.status = status; - - bool connect = false; - switch(status) - { - case BITDHT_MGR_QUERY_FAILURE: - /* do nothing */ - std::cerr << "BitDhtHandler::PeerCallback() QUERY FAILURE ... do nothin "; - std::cerr << std::endl; - - - break; - - case BITDHT_MGR_QUERY_PEER_OFFLINE: - /* do nothing */ - - std::cerr << "BitDhtHandler::PeerCallback() QUERY PEER OFFLINE ... do nothin "; - std::cerr << std::endl; - - break; - - case BITDHT_MGR_QUERY_PEER_UNREACHABLE: - /* do nothing */ - - std::cerr << "BitDhtHandler::PeerCallback() QUERY PEER UNREACHABLE ... saving address "; - std::cerr << std::endl; - it->second.id = *id; - - break; - - case BITDHT_MGR_QUERY_PEER_ONLINE: - /* do something */ - - std::cerr << "BitDhtHandler::PeerCallback() QUERY PEER ONLINE ... saving address"; - std::cerr << std::endl; - - it->second.id = *id; - break; - } - return 1; -} - - - -int BitDhtHandler::ValueCallback(const bdNodeId *id, std::string key, uint32_t status) -{ - std::cerr << "BitDhtHandler::ValueCallback() NOOP for NOW"; - std::cerr << std::endl; - - std::cerr << "BitDhtHandler::ValueCallback()"; - bdStdPrintNodeId(std::cerr, id); - std::cerr << " key: " << key; - std::cerr << " status: " << status; - std::cerr << std::endl; - - /* ignore for now */ - return 0; -} - diff --git a/libbitdht/src/example/bdhandler.h b/libbitdht/src/example/bdhandler.h deleted file mode 100644 index c0c942db6..000000000 --- a/libbitdht/src/example/bdhandler.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * libbitdht/src/example/bdhandler.h - * - * BitDht interface example - * - * Copyright 2009-2010 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#ifndef BITDHT_HANDLER_H -#define BITDHT_HANDLER_H - -#include -#include - -#include "udp/udpstack.h" -#include "udp/udpbitdht.h" -#include "bitdht/bdiface.h" - -/*** This class can be overloaded to use the XXXXCallback() Functions *****/ -class BitDhtIntCallback; - - -class BssResult -{ - public: - bdId id; - uint32_t mode; // single shot - uint32_t status; // SEARCHING, FAILURE, FOUND, MULTIPLE HITS. -}; - -#define BSS_SINGLE_SHOT 0x0001 - - -class BitDhtHandler -{ - - public: - - BitDhtHandler(bdNodeId *ownId, uint16_t port, std::string appId, std::string bootstrapfile); - -void enable(bool on); -void shutdown(); /* blocking call */ -void restart(); - -bool getEnabled(); -bool getActive(); - -bool FindNode(bdNodeId *peerId); -bool DropNode(bdNodeId *peerId); - -virtual int NodeCallback(const bdId *id, uint32_t peerflags); -virtual int PeerCallback(const bdId *id, uint32_t status); -virtual int ValueCallback(const bdNodeId *id, std::string key, uint32_t status); - -bool SearchResult(bdId *id, uint32_t &status); - - private: - - /* real DHT classes */ - UdpStack *mStack; - UdpBitDht *mUdpBitDht; - - bdMutex resultsMtx; /* for all class data (below) */ - - std::map mSearchNodes; -}; - - -#endif /* BITDHT_HANDLER_H */ - diff --git a/libbitdht/src/example/bootstrap_fn.cc b/libbitdht/src/example/bootstrap_fn.cc deleted file mode 100644 index 0288087f0..000000000 --- a/libbitdht/src/example/bootstrap_fn.cc +++ /dev/null @@ -1,84 +0,0 @@ - - -#include "bitdht/bdiface.h" -#include "bitdht/bdstddht.h" -#include "bdhandler.h" - -#include "bootstrap_fn.h" - -bool bdSingleShotFindPeer(const std::string bootstrapfile, const std::string peerId, std::string &peer_ip, uint16_t &peer_port) -{ - /* startup dht : with a random id! */ - bdNodeId ownId; - bdStdRandomNodeId(&ownId); - - uint16_t port = 6775; - std::string appId = "bsId"; - BitDhtHandler dht(&ownId, port, appId, bootstrapfile); - - /* install search node */ - bdNodeId searchId; - if (!bdStdLoadNodeId(&searchId, peerId)) - { - std::cerr << "bdSingleShotFindPeer(): Invalid Input Id: " << peerId; - return false; - } - - std::cerr << "bssdht: searching for Id: "; - bdStdPrintNodeId(std::cerr, &searchId); - std::cerr << std::endl; - - dht.FindNode(&searchId); - - /* run your program */ - bdId resultId; - uint32_t status; - - resultId.id = searchId; - - while(false == dht.SearchResult(&resultId, status)) - { - sleep(10); - } - - std::cerr << "bdSingleShotFindPeer(): Found Result:" << std::endl; - - std::cerr << "\tId: "; - bdStdPrintId(std::cerr, &resultId); - std::cerr << std::endl; - - std::cerr << "\tstatus: " << status; - std::cerr << std::endl; - - dht.shutdown(); - - if ((status == BITDHT_QUERY_PEER_UNREACHABLE) || - (status == BITDHT_QUERY_SUCCESS)) - { - - peer_ip = bdnet_inet_ntoa(resultId.addr.sin_addr); - peer_port = ntohs(resultId.addr.sin_port); - - std::cerr << "Answer: "; - std::cerr << std::endl; - std::cerr << "\tPeer IpAddress: " << peer_ip; - std::cerr << std::endl; - std::cerr << "\tPeer Port: " << peer_port; - std::cerr << std::endl; - } - else - { - std::cerr << "Sorry, Cant be found!"; - std::cerr << std::endl; - } - - return true; -} - - - - - - - - diff --git a/libbitdht/src/example/bootstrap_fn.h b/libbitdht/src/example/bootstrap_fn.h deleted file mode 100644 index 19ff6d714..000000000 --- a/libbitdht/src/example/bootstrap_fn.h +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - - -/* NOTE. At the moment only the bootstrapfile is actually used. - * peerId is ignored (a random peerId is searched for). ip & port are not filled in either. - * - * This is mainly to finish testing. - * - * Once the best form of the return functions is decided (ipv4 structure, or strings). - * this can be finished off. - * - */ - -bool bdSingleShotFindPeer(const std::string bootstrapfile, const std::string peerId, std::string &ip, uint16_t &port); - diff --git a/libbitdht/src/example/bssdht.cc b/libbitdht/src/example/bssdht.cc deleted file mode 100644 index 97f006260..000000000 --- a/libbitdht/src/example/bssdht.cc +++ /dev/null @@ -1,72 +0,0 @@ - -#include "bootstrap_fn.h" -#include -#include - -void args(char *name) -{ - std::cerr << std::endl; - std::cerr << "Dht Single Shot Searcher"; - std::cerr << std::endl; - std::cerr << "Usage:"; - std::cerr << std::endl; - std::cerr << "\t" << name << " -p "; - std::cerr << std::endl; - std::cerr << std::endl; - std::cerr << "NB: The PeerId is Required to Run"; - std::cerr << std::endl; - std::cerr << std::endl; -} - - -int main(int argc, char **argv) -{ - - std::string bootstrapfile = "bdboot.txt"; - std::string peerId; - std::string ip; - uint16_t port; - int c; - bool havePeerId = false; - - - while((c = getopt(argc, argv,"p:")) != -1) - { - switch (c) - { - case 'p': - peerId = optarg; - havePeerId = true; - break; - default: - args(argv[0]); - return 1; - break; - } - } - - if (!havePeerId) - { - args(argv[0]); - return 1; - } - - - std::cerr << "bssdht: starting up"; - std::cerr << std::endl; - - bdSingleShotFindPeer(bootstrapfile, peerId, ip, port); - - std::cerr << "bssdht: finished"; - std::cerr << std::endl; - - return 1; -} - - - - - - - - diff --git a/libbitdht/src/libbitdht.pro b/libbitdht/src/libbitdht.pro deleted file mode 100644 index 2e0013b36..000000000 --- a/libbitdht/src/libbitdht.pro +++ /dev/null @@ -1,177 +0,0 @@ -# RetroShare main qmake build script -# -# Copyright (C) 2004-2019, Retroshare Team -# -# This program is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. -# See the GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with this program. If not, see . -# -# SPDX-FileCopyrightText: Retroshare Team -# SPDX-License-Identifier: LGPL-3.0-or-later - -!include("../../retroshare.pri"): error("Could not include file ../../retroshare.pri") - -TEMPLATE = lib -CONFIG += staticlib -CONFIG -= qt -TARGET = bitdht -DESTDIR = lib - -!include("use_libbitdht.pri"):error("Including") - -QMAKE_CXXFLAGS *= -DBE_DEBUG - -################################# Linux ########################################## -linux-* { - QMAKE_CC = $${QMAKE_CXX} -} - -linux-g++ { - OBJECTS_DIR = temp/linux-g++/obj -} - -linux-g++-64 { - OBJECTS_DIR = temp/linux-g++-64/obj -} - -unix { - data_files.path = "$${DATA_DIR}" - data_files.files = bitdht/bdboot.txt - INSTALLS += data_files -} - -android-* { - # see https://community.kde.org/Necessitas/Assets - bdboot.files=bitdht/bdboot.txt - bdboot.path=/assets/values - INSTALLS += bdboot -} - -#################### Cross compilation for windows under Linux #################### - -win32-x-g++ { - OBJECTS_DIR = temp/win32xgcc/obj - # These have been replaced by _WIN32 && __MINGW32__ - # DEFINES *= WINDOWS_SYS WIN32 WIN_CROSS_UBUNTU - QMAKE_CXXFLAGS *= -Wmissing-include-dirs - QMAKE_CC = i586-mingw32msvc-g++ - QMAKE_LIB = i586-mingw32msvc-ar - QMAKE_AR = i586-mingw32msvc-ar - DEFINES *= STATICLIB WIN32 - - INCLUDEPATH *= /usr/i586-mingw32msvc/include ${HOME}/.wine/drive_c/pthreads/include/ -} -################################# Windows ########################################## - -win32 { - QMAKE_CC = $${QMAKE_CXX} - OBJECTS_DIR = temp/obj - MOC_DIR = temp/moc - DEFINES *= STATICLIB WIN32_LEAN_AND_MEAN - # These have been replaced by _WIN32 && __MINGW32__ - #DEFINES *= WINDOWS_SYS WIN32 STATICLIB MINGW - - # Switch off optimization for release version - QMAKE_CXXFLAGS_RELEASE -= -O2 - QMAKE_CXXFLAGS_RELEASE += -O0 - QMAKE_CFLAGS_RELEASE -= -O2 - QMAKE_CFLAGS_RELEASE += -O0 - - # Switch on optimization for debug version - #QMAKE_CXXFLAGS_DEBUG += -O2 - #QMAKE_CFLAGS_DEBUG += -O2 -} - -################################# MacOSX ########################################## - -mac { - QMAKE_CC = $${QMAKE_CXX} - OBJECTS_DIR = temp/obj - MOC_DIR = temp/moc -} - -################################# FreeBSD ########################################## - -freebsd-* { -} - -################################# OpenBSD ########################################## - -openbsd-* { -} - -################################# Haiku ########################################## - -haiku-* { - DESTDIR = lib -} - -################################### COMMON stuff ################################## -################################### COMMON stuff ################################## - -DEPENDPATH += . -INCLUDEPATH += . - -HEADERS += \ - bitdht/bdiface.h \ - bitdht/bencode.h \ - bitdht/bdobj.h \ - bitdht/bdmsgs.h \ - bitdht/bdpeer.h \ - bitdht/bdquery.h \ - bitdht/bdhash.h \ - bitdht/bdstore.h \ - bitdht/bdnode.h \ - bitdht/bdmanager.h \ - bitdht/bdstddht.h \ - bitdht/bdhistory.h \ - util/bdnet.h \ - util/bdthreads.h \ - util/bdrandom.h \ - util/bdfile.h \ - util/bdstring.h \ - udp/udplayer.h \ - udp/udpstack.h \ - udp/udpbitdht.h \ - bitdht/bdconnection.h \ - bitdht/bdfilter.h \ - bitdht/bdaccount.h \ - bitdht/bdquerymgr.h \ - util/bdbloom.h \ - bitdht/bdfriendlist.h \ - -SOURCES += \ - bitdht/bencode.c \ - bitdht/bdobj.cc \ - bitdht/bdmsgs.cc \ - bitdht/bdpeer.cc \ - bitdht/bdquery.cc \ - bitdht/bdhash.cc \ - bitdht/bdstore.cc \ - bitdht/bdnode.cc \ - bitdht/bdmanager.cc \ - bitdht/bdstddht.cc \ - bitdht/bdhistory.cc \ - util/bdnet.cc \ - util/bdthreads.cc \ - util/bdrandom.cc \ - util/bdfile.cc \ - util/bdstring.cc \ - udp/udplayer.cc \ - udp/udpstack.cc \ - udp/udpbitdht.cc \ - bitdht/bdconnection.cc \ - bitdht/bdfilter.cc \ - bitdht/bdaccount.cc \ - bitdht/bdquerymgr.cc \ - util/bdbloom.cc \ - bitdht/bdfriendlist.cc \ diff --git a/libbitdht/src/tests/bdbloom_makefilter.cc b/libbitdht/src/tests/bdbloom_makefilter.cc deleted file mode 100644 index ee3c6e4b8..000000000 --- a/libbitdht/src/tests/bdbloom_makefilter.cc +++ /dev/null @@ -1,90 +0,0 @@ -/* - * bitdht/bdbloom_test.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - -#include -#include "util/bdbloom.h" -#include "bitdht/bdstddht.h" -#include - -#define N_TESTS 100 - -int main(int argc, char **argv) -{ - /* read from the file */ - if (argc < 2) - { - std::cerr << "Missing Hash File"; - std::cerr << std::endl; - } - - FILE *fd = fopen(argv[1], "r"); - if (!fd) - { - std::cerr << "Failed to Open File: " << argv[1]; - std::cerr << std::endl; - return 1; - } - - char line[1000]; - - bdBloom filter; - - int nHashes = 0; - while(fgets(line, 1000-1, fd)) - { - std::string hash = line; - std::cerr << "Read Hash: " << hash; - std::cerr << std::endl; - - filter.add(hash); - nHashes++; - } - fclose(fd); - - filter.printFilter(std::cerr); - - int bits = filter.countBits(); - int filterBits = filter.filterBits(); - std::cerr << "Filter Bits Set: " << bits; - std::cerr << std::endl; - - double possible = ((double) bits) * bits; - double max = ((double) filterBits) * filterBits; - std::cerr << "Therefore Possible Finds: " << possible << "/" << max << " = %" << 100 * possible / max; - std::cerr << std::endl; - std::cerr << "With Insertions: " << nHashes; - std::cerr << std::endl; - - std::cerr << std::endl; - std::cerr << std::endl; - - std::cerr << "Filter String: " << filter.getFilter() << std::endl; - std::cerr << std::endl; - std::cerr << std::endl; - - return 1; -} - - diff --git a/libbitdht/src/tests/bdbloom_test.cc b/libbitdht/src/tests/bdbloom_test.cc deleted file mode 100644 index d0aefb947..000000000 --- a/libbitdht/src/tests/bdbloom_test.cc +++ /dev/null @@ -1,164 +0,0 @@ -/* - * bitdht/bdbloom_test.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - -#include -#include "util/bdbloom.h" -#include "bitdht/bdstddht.h" -#include - -#define N_TESTS 100 - -int main(int argc, char **argv) -{ - - /* Do this multiple times */ - int i; - - - bdBloom filter; - - std::list testIds; - std::list::iterator it; - - for(i = 0; i < N_TESTS; i++) - { - bdNodeId targetId; - bdStdRandomNodeId(&targetId); - testIds.push_back(targetId); - } - - std::cerr << "Test bdBloom Filter...." << std::endl; - for(it = testIds.begin(); it != testIds.end(); it++) - { - bdNodeId targetId = *it; - - std::cerr << "-------------------------------------------------" << std::endl; - std::cerr << "Inserting : "; - std::ostringstream str; - bdStdPrintNodeId(str, &targetId); - std::cerr << str.str(); - std::cerr << std::endl; - - filter.add(str.str()); - - filter.printFilter(std::cerr); - } - - std::string fs1 = filter.getFilter(); - /* now extract, and reinsert filter */ - bdBloom filter2; - filter2.setFilterBits(fs1); - - std::string fs2 = filter2.getFilter(); - filter2.printFilter(std::cerr); - - if (fs1 == fs2) - { - std::cerr << "SUCCESS: Filter Correctly Transferred!"; - std::cerr << std::endl; - } - else - { - std::cerr << "FAILURE: Filter Not Transferred!"; - std::cerr << std::endl; - } - - - for(it = testIds.begin(); it != testIds.end(); it++) - { - bdNodeId targetId = *it; - - std::cerr << "-------------------------------------------------" << std::endl; - std::cerr << "Testing : "; - std::cerr << std::endl; - - std::ostringstream str; - bdStdPrintNodeId(str, &targetId); - std::cerr << str.str() << std::endl; - - if (filter2.test(str.str())) - { - std::cerr << "SUCCESS: Filter Found Entry"; - std::cerr << std::endl; - } - else - { - std::cerr << "FAILURE: Filter Didn't Found Entry"; - std::cerr << std::endl; - } - } - - int bits = filter.countBits(); - int filterBits = filter.filterBits(); - std::cerr << "Filter Bits Set: " << bits; - std::cerr << std::endl; - - double possible = ((double) bits) * bits; - double max = ((double) filterBits) * filterBits; - std::cerr << "Therefore Possible Finds: " << possible << "/" << max << " = %" << 100 * possible / max; - std::cerr << std::endl; - std::cerr << "With Insertions: " << N_TESTS; - std::cerr << std::endl; - -#define FINAL_TESTS (1000000) - int found = 0; - int didnt = 0; - for(i = 0; i < FINAL_TESTS; i++) - { - if ((i != 0) && (i % 100000 == 0)) - { - std::cerr << "Run " << i << " Checks" << std::endl; - } - - bdNodeId targetId; - bdStdRandomNodeId(&targetId); - std::ostringstream str; - bdStdPrintNodeId(str, &targetId); - - if (filter2.test(str.str())) - { - found++; - } - else - { - didnt++; - } - } - - std::cerr << "Final Stats: " << FINAL_TESTS << " random checks done"; - std::cerr << std::endl; - std::cerr << "\t" << found << " " << 100.0 * ((double) found) / FINAL_TESTS << "% found"; - std::cerr << std::endl; - std::cerr << "\t" << didnt << " " << 100.0 * ((double) didnt) / FINAL_TESTS << "% didnt"; - std::cerr << std::endl; - - - - - - return 1; -} - - diff --git a/libbitdht/src/tests/bdboot.txt b/libbitdht/src/tests/bdboot.txt deleted file mode 100644 index 3a2f6b2b2..000000000 --- a/libbitdht/src/tests/bdboot.txt +++ /dev/null @@ -1,500 +0,0 @@ -50.193.28.158 36327 -88.181.96.123 11328 -99.37.188.41 29653 -88.72.55.221 12254 -76.103.79.28 36151 -78.219.65.122 18814 -50.80.44.10 60059 -82.66.32.246 39882 -89.88.138.23 50082 -93.9.151.183 41948 -60.35.23.158 12641 -93.181.45.102 62514 -41.249.53.96 52932 -82.227.12.97 46602 -89.156.177.7 29920 -178.236.129.166 56294 -46.173.64.63 44300 -86.73.179.122 59624 -209.195.101.75 44444 -76.114.41.44 13750 -188.103.108.41 1580 -74.192.244.156 23315 -91.217.90.22 58541 -27.32.169.219 57166 -175.196.134.95 6890 -99.229.202.165 36801 -119.14.195.27 60485 -112.206.13.117 41825 -87.89.253.70 52870 -203.186.173.169 22508 -122.168.241.122 16167 -113.250.99.211 3319 -87.106.249.208 4281 -97.90.151.69 54641 -81.249.29.121 7812 -24.122.0.38 5007 -79.119.57.255 48324 -84.237.250.67 60736 -72.208.178.104 46970 -93.7.211.121 35220 -82.126.138.5 31165 -98.21.67.18 56158 -174.101.153.252 38195 -70.184.208.133 1664 -173.12.200.5 5996 -5.39.78.183 7777 -212.178.8.49 61787 -81.38.140.98 37021 -189.4.28.74 28817 -90.55.204.2 38814 -183.89.101.187 63939 -175.208.45.169 32911 -124.86.6.169 14743 -58.168.9.105 36962 -89.178.158.14 54494 -86.23.51.76 44444 -111.119.227.15 26632 -68.82.46.243 31651 -91.20.211.178 57166 -89.85.171.145 32926 -75.126.109.30 15009 -88.170.61.126 32761 -82.237.40.39 39052 -80.101.24.220 17412 -95.84.208.14 9372 -109.212.31.106 4662 -80.98.106.227 9773 -67.197.115.77 33457 -212.43.36.251 20273 -129.21.122.81 32785 -109.187.235.96 49414 -93.66.62.37 59880 -81.169.151.138 42157 -67.252.30.196 41576 -77.176.247.93 7812 -178.65.138.159 52160 -178.17.18.206 8028 -96.53.93.210 56028 -80.236.120.181 14451 -37.24.108.103 2000 -95.171.138.138 42342 -88.72.55.221 37933 -89.133.71.20 14968 -96.250.108.15 45291 -86.74.221.169 36035 -111.50.223.158 16001 -46.33.251.143 11789 -159.224.9.168 57529 -74.4.200.21 45569 -77.224.214.10 7886 -91.237.165.36 55393 -71.65.115.24 60705 -180.245.74.54 10065 -89.229.5.2 1040 -178.129.19.231 53510 -76.23.105.94 47088 -76.121.226.114 47476 -108.77.112.69 51413 -24.246.67.233 55806 -95.25.123.108 17701 -142.161.104.76 16956 -90.56.162.201 53163 -62.99.25.102 22309 -116.14.209.177 59826 -213.87.123.121 20587 -83.165.11.132 9481 -122.150.77.71 6890 -77.236.180.89 24819 -84.24.96.215 6881 -98.176.147.218 62776 -79.82.130.49 20757 -78.43.137.174 10409 -74.136.3.207 43112 -95.133.243.200 7509 -71.232.162.47 10580 -209.195.104.126 6881 -178.82.162.111 36190 -175.173.87.138 16001 -72.218.218.39 6881 -84.252.26.117 10264 -46.166.104.222 50700 -86.52.88.196 52333 -188.186.142.97 22222 -63.227.112.135 40297 -110.171.80.30 50831 -62.16.187.208 60193 -41.221.124.3 12720 -122.86.88.153 5831 -46.29.209.84 6881 -83.165.111.199 63885 -80.98.162.185 51413 -176.73.16.252 34976 -24.188.113.226 42817 -88.207.42.112 51187 -85.230.147.123 58371 -50.92.78.248 41837 -94.212.214.204 52385 -86.52.180.140 6881 -94.23.198.174 51413 -212.198.182.174 18060 -78.234.129.171 33797 -125.186.188.58 6881 -94.210.26.194 16981 -109.64.246.237 23252 -86.201.102.163 51413 -75.82.14.204 37960 -172.1.72.173 31558 -86.71.169.12 32682 -37.110.130.32 61724 -61.64.143.4 59026 -202.79.36.129 58060 -88.254.55.5 53323 -84.39.4.247 6881 -31.151.104.160 51413 -201.87.14.68 50129 -24.246.26.61 51151 -101.103.182.123 36511 -95.111.64.209 10076 -89.224.149.142 25365 -46.21.211.0 18488 -49.49.27.110 13392 -60.185.230.42 64770 -188.27.125.50 51464 -212.21.6.250 64885 -114.243.240.207 53212 -89.40.161.33 29112 -14.145.16.208 18746 -186.204.50.237 17198 -124.115.12.153 2043 -47.54.129.97 47411 -109.200.116.239 17972 -213.16.182.12 25128 -217.20.73.188 35691 -182.177.193.44 10083 -80.222.111.127 35847 -79.94.175.146 41542 -74.141.87.159 55574 -95.37.172.1 11051 -77.100.104.142 54078 -80.184.19.34 35010 -94.180.203.42 6881 -37.201.168.34 48690 -95.28.111.83 11777 -84.208.143.35 50422 -188.186.45.35 17670 -90.146.80.87 26792 -122.121.191.214 47448 -31.181.0.236 6881 -99.242.88.203 21704 -176.31.109.159 32450 -62.93.99.6 28010 -95.90.236.216 41463 -95.132.145.53 17125 -222.216.168.211 50260 -182.96.166.223 4565 -111.92.19.48 46488 -88.170.61.126 7465 -216.49.152.239 59312 -108.46.182.176 23053 -59.19.172.14 58485 -159.224.26.228 13839 -184.147.15.149 64385 -41.98.81.187 10109 -90.5.180.162 18619 -81.198.134.16 6881 -66.229.51.242 51413 -82.11.60.187 55393 -62.194.99.138 18011 -178.151.1.128 20702 -84.98.19.169 36650 -84.224.105.232 13220 -68.115.149.90 49710 -37.205.70.166 35691 -85.232.130.42 62207 -83.158.230.144 55555 -83.246.216.234 49001 -92.233.249.147 55582 -41.108.95.129 12262 -83.152.236.89 58730 -115.220.147.35 7076 -78.106.26.128 26900 -84.101.22.120 55512 -89.142.253.198 10520 -151.64.241.149 51346 -95.168.12.60 63676 -213.46.147.163 38512 -85.130.52.88 25279 -90.193.28.149 22222 -79.132.25.126 59243 -111.250.206.117 25332 -99.230.144.57 34023 -112.192.66.172 1242 -58.170.183.148 16308 -110.76.72.49 13412 -80.9.174.99 58943 -84.98.243.248 13291 -91.148.138.106 17006 -173.193.242.231 25025 -173.193.242.231 37448 -84.244.2.193 27947 -78.45.13.229 19014 -173.193.242.231 22859 -119.154.190.187 43623 -213.65.128.142 55595 -78.234.140.58 8080 -92.142.60.155 6881 -189.59.195.217 64931 -122.169.6.171 35672 -178.47.227.162 33893 -46.246.67.243 64453 -46.119.144.241 49001 -174.36.55.75 18688 -94.243.89.164 57848 -209.140.255.87 20785 -62.77.128.245 51413 -91.211.177.3 20588 -81.84.65.143 12157 -68.228.230.85 20862 -108.90.48.119 51413 -24.212.131.70 48665 -85.23.70.134 53440 -217.55.204.253 12652 -31.180.94.141 35691 -109.152.61.125 57213 -92.136.246.118 13888 -178.34.229.72 30185 -94.24.202.64 30012 -123.202.103.167 33351 -109.71.206.215 6881 -89.70.19.188 26238 -59.180.22.196 20921 -189.73.206.149 55505 -46.130.66.188 60070 -183.10.152.135 47269 -41.233.124.184 13394 -112.139.59.213 12821 -89.2.143.130 18263 -217.210.76.120 30274 -178.149.61.10 19539 -96.233.255.79 50924 -124.121.88.187 63778 -119.204.207.162 30894 -103.14.61.48 53600 -46.63.62.162 10219 -77.41.141.187 6881 -83.110.90.167 42603 -61.78.82.158 29484 -85.0.20.26 6881 -94.236.128.96 50907 -99.230.119.14 1755 -108.13.168.252 62118 -84.125.19.21 42646 -74.141.87.159 55998 -86.125.209.88 62846 -37.43.117.187 40595 -95.104.110.103 47173 -76.78.36.229 36258 -97.94.141.117 63650 -49.49.90.217 14706 -94.6.23.192 39715 -46.232.228.161 5439 -186.133.30.205 15189 -46.186.48.179 61088 -31.134.17.73 32518 -98.229.16.76 13046 -89.211.153.176 63047 -95.16.10.140 12057 -46.149.41.106 49001 -178.204.78.171 28106 -94.51.214.102 6881 -178.127.223.150 23171 -203.141.138.201 42247 -95.53.43.124 19988 -66.11.189.123 16723 -178.46.157.54 54330 -85.87.178.219 23203 -83.114.210.35 51413 -178.78.33.173 49001 -95.191.57.183 28277 -111.241.72.105 63166 -190.213.94.37 13819 -114.34.93.16 6881 -80.201.144.250 16648 -217.148.57.194 52856 -46.180.187.212 20308 -59.143.213.135 36841 -115.241.104.112 54040 -58.182.18.125 11840 -202.160.16.7 58808 -78.230.94.4 63082 -188.254.157.48 40307 -78.162.174.165 24173 -88.196.203.160 47372 -182.164.124.199 48810 -121.102.203.62 20440 -219.246.57.153 16001 -2.61.38.78 25590 -99.98.96.67 13178 -125.114.50.210 1056 -90.193.128.203 61929 -94.14.5.83 58485 -37.193.160.216 57423 -58.115.35.67 11257 -182.235.129.91 16001 -186.36.145.147 42376 -128.68.147.228 6881 -200.119.228.231 17654 -88.89.110.64 26602 -115.79.234.94 36463 -80.193.158.59 49348 -78.73.114.77 11385 -90.54.174.104 20963 -218.151.52.146 16617 -46.161.143.220 49735 -188.18.80.97 6881 -37.212.44.31 10638 -89.223.99.150 49001 -65.4.130.12 50221 -186.74.22.89 45612 -95.58.93.119 28709 -209.6.69.225 56332 -85.103.248.197 27524 -174.45.1.123 6881 -118.171.185.18 19917 -87.90.247.194 39695 -213.222.142.58 28962 -69.253.233.190 44895 -88.172.121.96 30728 -222.226.45.246 26333 -82.245.33.128 25515 -178.44.235.211 19597 -121.168.129.77 60375 -121.45.206.235 23987 -217.162.186.254 39835 -83.222.112.119 58903 -178.74.53.50 22389 -61.70.254.221 62238 -119.56.48.165 16001 -93.148.114.59 12721 -88.251.154.23 17808 -188.79.87.245 15489 -46.119.165.133 58378 -76.94.95.223 25698 -88.188.193.27 26118 -123.211.1.4 27072 -101.68.107.193 25086 -95.147.47.122 26085 -123.243.64.132 35587 -186.89.157.161 15024 -174.106.96.168 56049 -109.148.234.144 60557 -89.178.224.73 28557 -85.104.92.129 10002 -99.228.252.24 37108 -61.62.254.10 32181 -2.50.255.118 36581 -176.49.163.194 23892 -90.23.214.138 63347 -119.36.38.104 62888 -109.122.3.81 6881 -86.99.199.68 25025 -84.120.63.7 11837 -188.60.197.229 16629 -89.110.207.136 13761 -213.57.37.242 44892 -75.90.96.145 31951 -99.247.185.46 36957 -76.227.224.238 24196 -217.27.215.96 6882 -213.33.236.230 65360 -77.5.35.67 43398 -83.108.63.210 61452 -24.12.46.116 23073 -173.193.242.231 36660 -71.94.186.218 10322 -109.228.185.71 6881 -175.205.72.185 59696 -200.120.153.187 57279 -1.64.32.1 11212 -89.233.243.128 33881 -89.3.35.16 8010 -219.99.6.250 54921 -79.95.171.102 11092 -126.13.14.150 17431 -58.208.74.237 6600 -114.245.149.20 9371 -78.233.157.35 40874 -84.226.253.50 6881 -69.14.60.243 61616 -50.33.142.137 52383 -188.242.78.174 33213 -71.237.6.246 41304 -41.107.85.131 10010 -89.222.164.45 39809 -88.186.107.212 42344 -195.132.158.234 22855 -82.122.102.50 25612 -76.255.133.138 31677 -24.130.61.50 28383 -98.165.83.165 3661 -99.55.140.166 50473 -75.109.50.114 25562 -87.106.187.29 20277 -24.247.183.167 2365 -82.228.100.167 42278 -109.214.57.82 1042 -77.196.18.56 22750 -66.177.205.21 8086 -82.231.237.146 9517 -176.31.248.87 6338 -2.6.66.21 45350 -79.153.101.234 11154 -24.247.179.164 8929 -71.63.225.31 21053 -83.157.77.228 7812 -108.59.72.193 2398 -88.127.44.139 15998 -64.121.118.201 61270 -90.38.76.72 4699 -67.173.33.90 33134 -88.217.36.182 2924 -2.236.14.214 55556 -109.194.233.11 6881 -178.187.47.44 53127 -126.29.214.91 42242 -41.178.247.176 24977 -37.59.34.186 41497 -82.225.11.196 38136 -195.132.158.49 61570 -78.105.105.87 42127 -94.23.204.135 30392 -178.63.84.76 51413 -78.237.111.89 45254 -76.189.121.236 31548 -24.85.183.150 9646 -88.181.149.119 5018 -126.130.125.117 24435 -65.15.247.19 51319 -176.31.109.159 24586 -176.31.127.140 44137 -89.93.149.195 57218 -88.165.34.61 51449 -188.242.97.188 35390 -107.15.22.183 10392 -24.211.20.89 62868 -74.108.4.175 17391 -80.185.95.18 18365 -146.247.80.210 38204 -27.4.216.128 57962 -88.238.170.69 26026 -74.215.38.97 50596 -87.89.75.85 42176 -115.188.217.116 62348 -98.250.89.141 13038 -93.11.175.201 41027 -174.109.14.220 51413 -114.79.170.114 27462 -84.22.157.13 28498 -180.183.210.31 21257 -42.113.246.104 10775 diff --git a/libbitdht/src/tests/bdmetric_test.cc b/libbitdht/src/tests/bdmetric_test.cc deleted file mode 100644 index d0865794e..000000000 --- a/libbitdht/src/tests/bdmetric_test.cc +++ /dev/null @@ -1,264 +0,0 @@ -/* - * bitdht/bdmetric_test.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include "bitdht/bdpeer.h" -#include "bitdht/bdstddht.h" -#include -#include - - -#include "utest.h" - -bool test_metric_explicit(); -bool test_metric_random(); - -INITTEST(); - -int main(int argc, char **argv) -{ - std::cerr << "libbitdht: " << argv[0] << std::endl; - - test_metric_explicit(); - - FINALREPORT("libbitdht: Metric Tests"); - return TESTRESULT(); -} - -bool test_metric_explicit() -{ - std::cerr << "test_metric_explicit:" << std::endl; - -#define NUM_IDS 6 - - /* create some ids */ - bdId id[NUM_IDS]; - int i, j; - - /* create a set of known ids ... and - * check the metrics are what we expect. - */ - - for(i = 0; i < NUM_IDS; i++) - { - bdZeroNodeId(&(id[i].id)); - } - - /* test the zero node works */ - for(i = 0; i < NUM_IDS; i++) - { - for(j = 0; j < BITDHT_KEY_LEN; j++) - { - CHECK(id[i].id.data[j] == 0); - } - } - - for(i = 0; i < NUM_IDS; i++) - { - for(j = i; j < NUM_IDS; j++) - { - id[j].id.data[BITDHT_KEY_LEN - i - 1] = 1; - } - } - - for(i = 0; i < NUM_IDS; i++) - { - fprintf(stderr, "id[%d]:", i+1); - bdStdPrintId(std::cerr,&(id[i])); - fprintf(stderr, "\n"); - } - - /* now do the sums */ - bdMetric met; - bdMetric met2; - int bdist = 0; - - for(i = 0; i < 6; i++) - { - for(j = i+1; j < 6; j++) - { - bdStdDistance(&(id[i].id), &(id[j].id), &met); - - fprintf(stderr, "%d^%d:", i, j); - bdStdPrintNodeId(std::cerr,&met); - fprintf(stderr, "\n"); - - bdist = bdStdBucketDistance(&met); - fprintf(stderr, " bucket: %d\n", bdist); - } - } - -#if 0 - int c1 = met < met2; - int c2 = met2 < met; - - fprintf(stderr, "1^2<1^3? : %d 1^3<1^2?: %d\n", c1, c2); -#endif - - - REPORT("Test Byte Manipulation"); - //FAILED("Couldn't Bind to socket"); - - return 1; -} - - - -bool test_metric_random() -{ - std::cerr << "test_metric_random:" << std::endl; - - /* create some ids */ - bdId id1; - bdId id2; - bdId id3; - bdId id4; - bdId id5; - bdId id6; - - bdStdRandomId(&id1); - bdStdRandomId(&id2); - bdStdRandomId(&id3); - bdStdRandomId(&id4); - bdStdRandomId(&id5); - bdStdRandomId(&id6); - - fprintf(stderr, "id1:"); - bdStdPrintId(std::cerr,&id1); - fprintf(stderr, "\n"); - - fprintf(stderr, "id2:"); - bdStdPrintId(std::cerr,&id2); - fprintf(stderr, "\n"); - - fprintf(stderr, "id3:"); - bdStdPrintId(std::cerr,&id3); - fprintf(stderr, "\n"); - - fprintf(stderr, "id4:"); - bdStdPrintId(std::cerr,&id4); - fprintf(stderr, "\n"); - - fprintf(stderr, "id5:"); - bdStdPrintId(std::cerr,&id5); - fprintf(stderr, "\n"); - - fprintf(stderr, "id6:"); - bdStdPrintId(std::cerr,&id6); - fprintf(stderr, "\n"); - - /* now do the sums */ - bdMetric met; - bdMetric met2; - int bdist = 0; - bdStdDistance(&(id1.id), &(id2.id), &met); - - fprintf(stderr, "1^2:"); - bdStdPrintNodeId(std::cerr,&met); - fprintf(stderr, "\n"); - bdist = bdStdBucketDistance(&met); - fprintf(stderr, " bucket: %d\n", bdist); - - bdStdDistance(&(id1.id), &(id3.id), &met2); - bdist = bdStdBucketDistance(&met2); - - fprintf(stderr, "1^3:"); - bdStdPrintNodeId(std::cerr,&met2); - fprintf(stderr, "\n"); - fprintf(stderr, " bucket: %d\n", bdist); - - int c1 = met < met2; - int c2 = met2 < met; - - fprintf(stderr, "1^2<1^3? : %d 1^3<1^2?: %d\n", c1, c2); - - - bdStdDistance(&(id1.id), &(id4.id), &met2); - bdist = bdStdBucketDistance(&met2); - - fprintf(stderr, "1^4:"); - bdStdPrintNodeId(std::cerr,&met2); - fprintf(stderr, "\n"); - fprintf(stderr, " bucket: %d\n", bdist); - - c1 = met < met2; - c2 = met2 < met; - - fprintf(stderr, "1^2<1^4? : %d 1^4<1^2?: %d\n", c1, c2); - - bdStdDistance(&(id1.id), &(id5.id), &met); - bdist = bdStdBucketDistance(&met); - - fprintf(stderr, "1^5:"); - bdStdPrintNodeId(std::cerr,&met); - fprintf(stderr, "\n"); - fprintf(stderr, " bucket: %d\n", bdist); - - bdStdDistance(&(id1.id), &(id6.id), &met); - bdist = bdStdBucketDistance(&met); - - fprintf(stderr, "1^6:"); - bdStdPrintNodeId(std::cerr,&met); - fprintf(stderr, "\n"); - fprintf(stderr, " bucket: %d\n", bdist); - - bdStdDistance(&(id2.id), &(id3.id), &met); - bdist = bdStdBucketDistance(&met); - - fprintf(stderr, "2^3:"); - bdStdPrintNodeId(std::cerr,&met); - fprintf(stderr, "\n"); - fprintf(stderr, " bucket: %d\n", bdist); - - - fprintf(stderr, "id1:"); - bdStdPrintId(std::cerr,&id1); - fprintf(stderr, "\n"); - - fprintf(stderr, "id2:"); - bdStdPrintId(std::cerr,&id2); - fprintf(stderr, "\n"); - - fprintf(stderr, "id3:"); - bdStdPrintId(std::cerr,&id3); - fprintf(stderr, "\n"); - - fprintf(stderr, "id4:"); - bdStdPrintId(std::cerr,&id4); - fprintf(stderr, "\n"); - - fprintf(stderr, "id5:"); - bdStdPrintId(std::cerr,&id5); - fprintf(stderr, "\n"); - - fprintf(stderr, "id6:"); - bdStdPrintId(std::cerr,&id6); - fprintf(stderr, "\n"); - - - return 1; -} - - diff --git a/libbitdht/src/tests/bdmgr_multitest.cc b/libbitdht/src/tests/bdmgr_multitest.cc deleted file mode 100644 index cfed76862..000000000 --- a/libbitdht/src/tests/bdmgr_multitest.cc +++ /dev/null @@ -1,186 +0,0 @@ -/* - * bitdht/bdmgr_multitest.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include "bitdht/bdmanager.h" -#include "bitdht/bdstddht.h" -#include "udp/udplayer.h" -#include "util/bdrandom.h" - -#include - -/********************************************************************************** - * tests of multi bdnodes all connected together. - * in these cases, the networking step is shortcut and the ip addresses ignored. - * instead the port number is used as an index to peers. - * - * test1() - * Small cross seeding, and static list of peers. - * Set it going - and see what happens. - */ - -std::map nodes; -std::map addrIdx; - -int main(int argc, char **argv) -{ - time_t sim_time = 600; - time_t starttime = time(NULL); - int n_nodes = 1000; - std::map::iterator it; - std::map::iterator nit; - std::map::iterator ait; - - int i, j; - - bdDhtFunctions *fns = new bdStdDht(); - - std::cerr << "bdmgr_multitest() Setting up Nodes" << std::endl; - /* setup nodes */ - for(i = 0; i < n_nodes; i++) - { - bdId id; - - bdStdRandomId(&id); - - //id.addr.sin_port = htons(i); - //((uint32_t *) (id.id.data))[0] = i * 16 * 16; /* force this so the sort order is maintained! */ - std::cerr << "bdmgr_multitest() Id: "; - fns->bdPrintId(std::cerr, &id); - std::cerr << std::endl; - - bdNodeManager *mgr = new bdNodeManager(&(id.id), "bdTEST", "", fns); - - /* Store in nodes */ - nodes[id] = mgr; - /* Store in indices */ - addrIdx[id.addr] = id; - - } - - std::cerr << "bdmgr_multitest() Cross Seeding" << std::endl; - /* do a little cross seeding */ - for(nit = nodes.begin(); nit != nodes.end(); nit++) - { - for(j = 0; j < 2; j++) - { - int peeridx = bdRandom::random_u32() % n_nodes; - for(i = 0, it = nodes.begin(); - (i < peeridx) && (it != nodes.end()); i++, it++) - { - /* empty */ - } - if (it != nodes.end()) - { - nit->second->addPotentialPeer((bdId *) &(it->first), NULL); - } - } - } - - /* ready to run */ - - std::cerr << "bdmgr_multitest() Simulation Time....." << std::endl; - i = 0; - while(time(NULL) < starttime + sim_time) - { - i++; - std::cerr << "bdmgr_multitest() Iteration: " << i << std::endl; - - for(it = nodes.begin(), j = 0; it != nodes.end(); it++, j++) - { - /* extract messages to go -> and deliver */ -#define MAX_MSG_SIZE 10240 - struct sockaddr_in addr; - char data[MAX_MSG_SIZE]; - int len = MAX_MSG_SIZE; - - while(it->second->outgoingMsg(&addr, data, &len)) - { - std::cerr << "bdmgr_multitest() Msg from Peer: " << j; - - /* find the peer */ - ait = addrIdx.find(addr); - nit = nodes.end(); - if (ait != addrIdx.end()) - { - nit = nodes.find(ait->second); - std::cerr << " For: "; - fns->bdPrintId(std::cerr, &(nit->first)); - std::cerr << std::endl; - } - else - { - std::cerr << " For Unknown Destination"; - std::cerr << std::endl; - - } - - if (nit != nodes.end()) - { - /* set from address */ - nit->second->incomingMsg( (sockaddr_in *) &(it->first.addr), data, len); - } - /* reset message size */ - len = MAX_MSG_SIZE; - } - } - - for(it = nodes.begin(), j = 0; it != nodes.end(); it++, j++) - { - /* tick */ - std::cerr << "bdmgr_multitest() Ticking peer: " << j << std::endl; - it->second->iteration(); - } - - - /* have a rest */ - sleep(1); - } - - std::cerr << "bdmgr_multitest() Displying States"<< std::endl; - for(it = nodes.begin(), j = 0; it != nodes.end(); it++, j++) - { - /* tick */ - std::cerr << "bdmgr_multitest() Peer State: " << j << std::endl; - it->second->printState(); - } - -} - - - - - - - - - - - - - - - - diff --git a/libbitdht/src/tests/bdmidids_test.cc b/libbitdht/src/tests/bdmidids_test.cc deleted file mode 100644 index de52975cb..000000000 --- a/libbitdht/src/tests/bdmidids_test.cc +++ /dev/null @@ -1,96 +0,0 @@ -/* - * bitdht/bdmidids_test.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include "bitdht/bdpeer.h" -#include "bitdht/bdstddht.h" -#include - -int main(int argc, char **argv) -{ - - /* Do this multiple times */ - int i, j; - - std::cerr << "Test Mid Peer Intersection....." << std::endl; - for(i = 0; i < 10; i++) - { - bdNodeId targetId; - bdNodeId peerId; - - bdStdRandomNodeId(&targetId); - bdStdRandomNodeId(&peerId); - - std::cerr << "-------------------------------------------------" << std::endl; - - for(j = 0; j < 10; j++) - { - - bdNodeId midId; - - bdStdRandomMidId(&targetId, &peerId, &midId); - - bdMetric TPmetric; - bdMetric TMmetric; - bdMetric PMmetric; - - bdStdDistance(&targetId, &peerId, &TPmetric); - bdStdDistance(&targetId, &midId, &TMmetric); - bdStdDistance(&peerId, &midId, &PMmetric); - - int TPdist = bdStdBucketDistance(&TPmetric); - int TMdist = bdStdBucketDistance(&TMmetric); - int PMdist = bdStdBucketDistance(&PMmetric); - - std::cerr << "Target: "; - bdStdPrintNodeId(std::cerr,&targetId); - std::cerr << " Peer: "; - bdStdPrintNodeId(std::cerr,&peerId); - std::cerr << std::endl; - - std::cerr << "\tTarget ^ Peer: "; - bdStdPrintNodeId(std::cerr,&TPmetric); - std::cerr << " Bucket: " << TPdist; - std::cerr << std::endl; - - std::cerr << "\tTarget ^ Mid: "; - bdStdPrintNodeId(std::cerr,&TMmetric); - std::cerr << " Bucket: " << TMdist; - std::cerr << std::endl; - - std::cerr << "\tPeer ^ Mid: "; - bdStdPrintNodeId(std::cerr,&PMmetric); - std::cerr << " Bucket: " << PMdist; - std::cerr << std::endl; - - /* now save mid to peer... and repeat */ - peerId = midId; - } - } - - return 1; -} - - diff --git a/libbitdht/src/tests/bdmsgs_test.cc b/libbitdht/src/tests/bdmsgs_test.cc deleted file mode 100644 index cdfaed7d2..000000000 --- a/libbitdht/src/tests/bdmsgs_test.cc +++ /dev/null @@ -1,102 +0,0 @@ - -/* - * bitdht/bdmsgs_test.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include "bitdht/bdmsgs.h" -#include "bitdht/bdstddht.h" -#include - -/******************************************************************* - * Test of bencode message creation functions in bdmsgs.cc - * - * Create a couple of each type. - */ - -#define MAX_MESSAGE_LEN 10240 - -int main(int argc, char **argv) -{ - /***** create messages *****/ - char msg[MAX_MESSAGE_LEN]; - int avail = MAX_MESSAGE_LEN -1; - - bdToken tid; - bdToken vid; - bdToken token; - - - bdNodeId ownId; - bdNodeId peerId; - bdNodeId target; - bdNodeId info_hash; - - bdStdRandomNodeId(&ownId); - bdStdRandomNodeId(&peerId); - bdStdRandomNodeId(&target); - bdStdRandomNodeId(&info_hash); - - std::list nodes; - std::list values; - - /* setup tokens */ - strncpy((char*)tid.data, "tid", 4); - strncpy((char*)vid.data, "RS50", 5); - strncpy((char*)token.data, "ToKEn", 6); - - tid.len = 3; - vid.len = 4; - token.len = 5; - - /* setup lists */ - for(int i = 0; i < 8; i++) - { - bdId rndId; - bdStdRandomId(&rndId); - - nodes.push_back(rndId); - values.push_back("values"); - } - - uint32_t port = 1234; - - bitdht_create_ping_msg(&tid, &ownId, msg, avail); - bitdht_response_ping_msg(&tid, &ownId, &vid, msg, avail); - - bitdht_find_node_msg(&tid, &ownId, &target, msg, avail); - bitdht_resp_node_msg(&tid, &ownId, nodes, msg, avail); - - bitdht_get_peers_msg(&tid, &ownId, &info_hash, msg, avail); - bitdht_peers_reply_hash_msg(&tid, &ownId, &token, values, msg, avail); - bitdht_peers_reply_closest_msg(&tid, &ownId, &token, nodes, msg, avail); - - bitdht_announce_peers_msg(&tid, &ownId, &info_hash, port, &token, msg, avail); - bitdht_reply_announce_msg(&tid, &ownId, msg, avail); - - - return 1; -} - - diff --git a/libbitdht/src/tests/bdnode_multitest1.cc b/libbitdht/src/tests/bdnode_multitest1.cc deleted file mode 100644 index 5e1a6ebca..000000000 --- a/libbitdht/src/tests/bdnode_multitest1.cc +++ /dev/null @@ -1,185 +0,0 @@ -/* - * bitdht/bdnode_multitest1.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include "bitdht/bdnode.h" -#include "bitdht/bdstddht.h" -#include "util/bdrandom.h" - -#include - -/********************************************************************************** - * tests of multi bdnodes all connected together. - * in these cases, the networking step is shortcut and the ip addresses ignored. - * instead the port number is used as an index to peers. - * - * test1() - * Small cross seeding, and static list of peers. - * Set it going - and see what happens. - */ - -std::map nodes; -std::map portIdx; - -int main(int argc, char **argv) -{ - time_t sim_time = 60; - time_t starttime = time(NULL); - int n_nodes = 10; - std::map::iterator it; - std::map::iterator nit; - std::map::iterator pit; - - int i, j; - - bdDhtFunctions *fns = new bdStdDht(); - - std::cerr << "bdnode_multitest1() Setting up Nodes" << std::endl; - /* setup nodes */ - for(i = 0; i < n_nodes; i++) - { - bdId id; - - bdStdRandomId(&id); - - id.addr.sin_port = htons(i); - ((uint32_t *) (id.id.data))[0] = i * 16 * 16; /* force this so the sort order is maintained! */ - std::cerr << "bdnode_multitest1() Id: "; - fns->bdPrintId(std::cerr, &id); - std::cerr << std::endl; - - bdNode *node = new bdNode(&(id.id), "bdTEST", "", fns); - - /* Store in nodes */ - nodes[id] = node; - /* Store in indices */ - portIdx[i] = id; - - } - - std::cerr << "bdnode_multitest1() Cross Seeding" << std::endl; - /* do a little cross seeding */ - for(i = 0; i < n_nodes; i++) - { - bdId nid = portIdx[i]; - bdNode *node = nodes[nid]; - - for(j = 0; j < 5; j++) - { - int peeridx = bdRandom::random_u32() % n_nodes; - - bdId pid = portIdx[peeridx]; - node->addPotentialPeer(&pid, NULL); - } - } - - /* ready to run */ - - std::cerr << "bdnode_multitest1() Simulation Time....." << std::endl; - i = 0; - while(time(NULL) < starttime + sim_time) - { - i++; - std::cerr << "bdnode_multitest1() Iteration: " << i << std::endl; - - for(it = nodes.begin(), j = 0; it != nodes.end(); it++, j++) - { - /* extract messages to go -> and deliver */ -#define MAX_MSG_SIZE 10240 - struct sockaddr_in addr; - char data[MAX_MSG_SIZE]; - int len = MAX_MSG_SIZE; - - while(it->second->outgoingMsg(&addr, data, &len)) - { - std::cerr << "bdnode_multitest1() Msg from Peer: " << j; - - /* find the peer */ - int peeridx = htons(addr.sin_port); - pit = portIdx.find(peeridx); - nit = nodes.end(); - if (pit != portIdx.end()) - { - nit = nodes.find(pit->second); - std::cerr << " For: "; - fns->bdPrintId(std::cerr, &(nit->first)); - std::cerr << std::endl; - } - else - { - std::cerr << " For Unknown Destination"; - std::cerr << std::endl; - - } - - if (nit != nodes.end()) - { - /* set from address */ - nit->second->incomingMsg( (sockaddr_in *) &(it->first.addr), data, len); - } - /* reset message size */ - len = MAX_MSG_SIZE; - } - } - - for(it = nodes.begin(), j = 0; it != nodes.end(); it++, j++) - { - /* tick */ - std::cerr << "bdnode_multitest1() Ticking peer: " << j << std::endl; - it->second->iteration(); - } - - if (i % 5 == 0) - { - std::cerr << "bdnode_multitest1() Displying States"<< std::endl; - for(it = nodes.begin(), j = 0; it != nodes.end(); it++, j++) - { - /* tick */ - std::cerr << "bdnode_multitest1() Peer State: " << j << std::endl; - it->second->printState(); - } - } - - - /* have a rest */ - sleep(1); - } -} - - - - - - - - - - - - - - - - diff --git a/libbitdht/src/tests/bdnode_test.cc b/libbitdht/src/tests/bdnode_test.cc deleted file mode 100644 index 848a27e7c..000000000 --- a/libbitdht/src/tests/bdnode_test.cc +++ /dev/null @@ -1,90 +0,0 @@ -/* - * bitdht/bdnode_test.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - -#include "bitdht/bdpeer.h" -#include "bitdht/bdstddht.h" -#include "bitdht/bdquery.h" -#include "bitdht/bdnode.h" - -#define N_PEERS_TO_ADD_INIT 10 -#define N_PEERS_TO_ADD 11 -#define N_PEERS_TO_START 10 -#define N_PEERS_TO_PRINT 1 -#define N_QUERIES 2 - -int main(int argc, char **argv) -{ - - /* create some ids */ - bdDhtFunctions *fns = new bdStdDht(); - - bdNodeId ownId; - bdStdRandomNodeId(&ownId); - - bdNode node(&ownId, "bdTEST","./dht.log", fns); - - int i = 0; - for (i = 0; i < N_PEERS_TO_ADD_INIT; i++) - { - bdId tmpId; - bdStdRandomId(&tmpId); - - node.addPeer(&tmpId, 0); - } - - node.printState(); - -#if 0 - for(i = 0; i < N_QUERIES; i++) - { - /* create a query */ - bdNodeId queryId; - bdStdRandomNodeId(&queryId); - - node.addQuery(&queryId, 0); - } -#endif - - node.printState(); - - for (i = 0; i < N_PEERS_TO_ADD; i++) - { - bdId tmpId; - bdStdRandomId(&tmpId); - - node.addPeer(&tmpId, 0); - - if (i % N_PEERS_TO_PRINT == 0) - { - node.printState(); - node.iteration(); - sleep(5); - } - } - - return 1; -} - - diff --git a/libbitdht/src/tests/bdnode_test2.cc b/libbitdht/src/tests/bdnode_test2.cc deleted file mode 100644 index 1e4b16b68..000000000 --- a/libbitdht/src/tests/bdnode_test2.cc +++ /dev/null @@ -1,56 +0,0 @@ -/* - * bitdht/bdnode_test2.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - -#include "bitdht/bdpeer.h" -#include "bitdht/bdstddht.h" -#include "bitdht/bdquery.h" -#include "bitdht/bdnode.h" - -#define N_PEERS_TO_ADD_INIT 10 -#define N_PEERS_TO_ADD 11 -#define N_PEERS_TO_START 10 -#define N_PEERS_TO_PRINT 1 -#define N_QUERIES 2 - -int main(int argc, char **argv) -{ - - /* create some ids */ - bdNodeId ownId; - bdStdRandomNodeId(&ownId); - bdDhtFunctions *fns = new bdStdDht(); - - bdNode node(&ownId, "bdTEST", "./dht.log", fns); - - while(1) - { - node.iteration(); - sleep(1); - } - - return 1; -} - - diff --git a/libbitdht/src/tests/bdquery_test.cc b/libbitdht/src/tests/bdquery_test.cc deleted file mode 100644 index b4c8e980b..000000000 --- a/libbitdht/src/tests/bdquery_test.cc +++ /dev/null @@ -1,83 +0,0 @@ -/* - * bitdht/bdquery_test.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include "bitdht/bdpeer.h" -#include "bitdht/bdstddht.h" -#include "bitdht/bdquery.h" - -#define N_PEERS_TO_ADD 10000 -#define N_PEERS_TO_PRINT 1000 -#define N_PEERS_TO_START 10 - -int main(int argc, char **argv) -{ - - /* create some ids */ - bdNodeId ownId; - bdStdRandomNodeId(&ownId); - - bdDhtFunctions *fns = new bdStdDht(); - - bdSpace space(&ownId, fns); - int i = 0; - for (i = 0; i < N_PEERS_TO_ADD; i++) - { - bdId tmpId; - bdStdRandomId(&tmpId); - - space.add_peer(&tmpId, 0); - } - - space.printDHT(); - - /* create a query */ - bdId queryId; - bdStdRandomId(&queryId); - - - - std::list startList; - std::multimap nearest; - std::multimap::iterator it; - - space.find_nearest_nodes(&(queryId.id), N_PEERS_TO_START, nearest); - - for(it = nearest.begin(); it != nearest.end(); it++) - { - startList.push_back(it->second); - } - - bdQuery query(&(queryId.id), startList, BITDHT_QFLAGS_DISGUISE, fns); - - /* */ - - query.printQuery(); - - - return 1; -} - - diff --git a/libbitdht/src/tests/bdspace_test.cc b/libbitdht/src/tests/bdspace_test.cc deleted file mode 100644 index ead78c683..000000000 --- a/libbitdht/src/tests/bdspace_test.cc +++ /dev/null @@ -1,60 +0,0 @@ -/* - * bitdht/bdspace_test.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include "bitdht/bdpeer.h" -#include "bitdht/bdstddht.h" - -#define N_PEERS_TO_ADD 10000 -#define N_PEERS_TO_PRINT 1000 - -int main(int argc, char **argv) -{ - - /* create some ids */ - bdNodeId ownId; - bdStdRandomNodeId(&ownId); - bdDhtFunctions *fns = new bdStdDht(); - - bdSpace space(&ownId, fns); - int i = 0; - for (i = 0; i < N_PEERS_TO_ADD; i++) - { - bdId tmpId; - bdStdRandomId(&tmpId); - - space.add_peer(&tmpId, 0); - - if (i % N_PEERS_TO_PRINT == 0) - { - space.printDHT(); - } - } - space.printDHT(); - - return 1; -} - - diff --git a/libbitdht/src/tests/bdspace_test2.cc b/libbitdht/src/tests/bdspace_test2.cc deleted file mode 100644 index ca9e7f024..000000000 --- a/libbitdht/src/tests/bdspace_test2.cc +++ /dev/null @@ -1,67 +0,0 @@ -/* - * bitdht/bdspace_test2.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include "bitdht/bdpeer.h" -#include "bitdht/bdstddht.h" - -#define N_PEERS_TO_ADD 10000 -#define N_PEERS_TO_TEST 100 -#define N_PEERS_TO_FIND 10 - -int main(int argc, char **argv) -{ - - /* create some ids */ - bdNodeId ownId; - bdStdRandomNodeId(&ownId); - bdDhtFunctions *fns = new bdStdDht(); - - bdSpace space(&ownId, fns); - int i = 0; - for (i = 0; i < N_PEERS_TO_ADD; i++) - { - bdId tmpId; - bdStdRandomId(&tmpId); - space.add_peer(&tmpId, 0); - } - - space.printDHT(); - - - /* now generate random id's and test closeness */ - for(i = 0; i < N_PEERS_TO_TEST; i++) - { - bdId tmpId; - bdStdRandomId(&tmpId); - std::multimap list2; - - space.find_nearest_nodes(&(tmpId.id), N_PEERS_TO_FIND, list2); - } - - return 1; -} - - diff --git a/libbitdht/src/tests/bdstore_test.cc b/libbitdht/src/tests/bdstore_test.cc deleted file mode 100644 index c1207def5..000000000 --- a/libbitdht/src/tests/bdstore_test.cc +++ /dev/null @@ -1,47 +0,0 @@ -/* - * bitdht/bdstore_test.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include "bitdht/bdstore.h" -#include "bitdht/bdstddht.h" - -#include -#include - -int main(int argc, char **argv) -{ - /* load store */ - if (argc < 2) - { - fprintf(stderr, "Missing Store File\n"); - exit(1); - } - - bdDhtFunctions *fns = new bdStdDht(); - bdStore store(argv[1], fns); - return 1; -} - - diff --git a/libbitdht/src/tests/bdudp_test.cc b/libbitdht/src/tests/bdudp_test.cc deleted file mode 100644 index 4b9d581bd..000000000 --- a/libbitdht/src/tests/bdudp_test.cc +++ /dev/null @@ -1,66 +0,0 @@ -/* - * bitdht/bdudp_test.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include "bitdht/bdpeer.h" -#include "bitdht/bdquery.h" -#include "udp/udpbitdht.h" - -#define N_PEERS_TO_ADD 10000 -#define N_PEERS_TO_PRINT 1000 -#define N_PEERS_TO_START 10 - -int main(int argc, char **argv) -{ - - /* create some ids */ - bdId ownId; - bdRandomId(&ownId); - - - struct sockaddr_in local; - local.sin_addr.s_addr = 0; - local.sin_port = htons(7812); - std::string bootstrapfile = "dht.log"; - - bdId bid; - - bid.addr = local; - bid.id = ownId.id; - - UdpBitDht ubd(local, 0, &bid, bootstrapfile); - - - - while(1) - { - ubd.tick(); - sleep(1); - } - - return 1; -} - - diff --git a/libbitdht/src/tests/bencode_test.cc b/libbitdht/src/tests/bencode_test.cc deleted file mode 100644 index 8d35c0678..000000000 --- a/libbitdht/src/tests/bencode_test.cc +++ /dev/null @@ -1,182 +0,0 @@ -/* - * bitdht/bencode_test.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include "bitdht/bencode.h" -#include - -int main(int argc, char **argv) -{ - - char msg[100]; - - msg[0] = 'd'; - msg[1] = '1'; - msg[2] = ':'; - msg[3] = 't'; - msg[4] = 'L'; - msg[5] = 'b'; - msg[6] = 'U'; - msg[7] = 0xd9; - msg[8] = 0xfa; - msg[9] = 0xff; - msg[10] = 0xff; - msg[11] = 0xff; - msg[12] = 0xff; - msg[13] = '\n'; - msg[14] = 'H'; - msg[15] = '#'; - msg[16] = '#'; - msg[17] = '#'; - msg[18] = '#'; - msg[19] = '#'; - msg[20] = '#'; - msg[21] = '#'; - - be_node *n = be_decoden(msg, 16); - - if (n) - { - be_dump(n); - be_free(n); - } - else - { - fprintf(stderr, "didn't crash!\n"); - } - - msg[0] = 'd'; - msg[1] = '1'; - msg[2] = ':'; - msg[3] = 'a'; - msg[4] = 'L'; - msg[5] = 0x8d; - msg[6] = 0xd6; - msg[7] = '\r'; - msg[8] = 0x9d; - msg[9] = ';'; - msg[10] = 0xff; - msg[11] = 0xff; - msg[12] = 0xff; - msg[13] = 0xff; - msg[14] = 'H'; - msg[15] = '#'; - msg[16] = '#'; - msg[17] = '#'; - msg[18] = '#'; - msg[19] = '#'; - msg[20] = '#'; - msg[21] = '#'; - - n = be_decoden(msg, 14); - - if (n) - { - be_dump(n); - be_free(n); - } - else - { - fprintf(stderr, "didn't crash!\n"); - } - - msg[0] = 'd'; - msg[1] = '1'; - msg[2] = ':'; - msg[3] = 't'; - msg[4] = '4'; - msg[5] = ':'; - msg[6] = 'a'; - msg[7] = 'b'; - msg[8] = 'c'; - msg[9] = 'd'; - msg[10] = '1'; - msg[11] = ':'; - msg[12] = 'y'; - msg[13] = '1'; - msg[14] = ':'; - msg[15] = 'r'; - msg[16] = '1'; - msg[17] = ':'; - msg[18] = 'r'; - msg[19] = 'd'; - msg[20] = '2'; - msg[21] = ':'; - msg[22] = 'i'; - msg[23] = 'd'; - msg[24] = '2'; - msg[25] = '0'; - msg[26] = ':'; - msg[27] = '1'; - msg[28] = '2'; - msg[29] = '3'; - msg[30] = '4'; - msg[31] = '5'; - msg[32] = '6'; - msg[33] = '7'; - msg[34] = '8'; - msg[35] = '9'; - msg[36] = '0'; - msg[37] = 'a'; - msg[38] = 'b'; - msg[39] = 'c'; - msg[40] = 'd'; - msg[41] = 'e'; - msg[42] = 'f'; - msg[43] = 'g'; - msg[44] = 'h'; - msg[45] = 'i'; - msg[46] = '.'; - msg[47] = '5'; - msg[48] = ':'; - msg[49] = 'n'; - msg[50] = 'o'; - msg[51] = 'd'; - msg[52] = 'e'; - msg[53] = 's'; - msg[54] = '2'; - msg[55] = '0'; - msg[56] = '8'; - msg[57] = ':'; - msg[58] = '\0'; - msg[59] = '\0'; - msg[60] = '\0'; - - n = be_decoden(msg, 58); - - if (n) - { - be_dump(n); - be_free(n); - } - else - { - fprintf(stderr, "didn't crash!\n"); - } - - return 1; -} - - diff --git a/libbitdht/src/tests/scripts/checks.mk b/libbitdht/src/tests/scripts/checks.mk deleted file mode 100644 index dfccbdedf..000000000 --- a/libbitdht/src/tests/scripts/checks.mk +++ /dev/null @@ -1,19 +0,0 @@ -#Basic checks - -ifndef TEST_TOP_DIR -dummy: - echo "TEST_TOP_DIR is not defined in your makefile" -endif - -ifneq ($(OS),Linux) - ifneq ($(OS),MacOSX) - ifndef PTHREADS_DIR -dummy: - echo "you must define PTHREADS_DIR before you can compile" - - endif - endif -endif - - - diff --git a/libbitdht/src/tests/scripts/config-cygwin.mk b/libbitdht/src/tests/scripts/config-cygwin.mk deleted file mode 100644 index ec4518f68..000000000 --- a/libbitdht/src/tests/scripts/config-cygwin.mk +++ /dev/null @@ -1,118 +0,0 @@ -ifneq ($(OS),Cygwin) -dummy: - echo "ERROR Cygwin configuration file included, but (OS != Cygwin) - -endif - -############ LINUX CONFIGURATION ######################## - -# flags for components.... -PQI_USE_XPGP = 1 -#PQI_USE_PROXY = 1 -#PQI_USE_CHANNELS = 1 -#USE_FILELOOK = 1 - -########################################################################### - -#### DrBobs Versions.... Please Don't Delete. -### Comment out if needed. -ALT_SRC_ROOT=/cygdrive/c/home/rmfern/prog/MinGW -SRC_ROOT=../../../.. - -PTHREADS_DIR=$(ALT_SRC_ROOT)/pthreads/pthreads.2 - -################### - -#ALT_SRC_ROOT=/cygdrive/c/RetroShareBuild/src -#SRC_ROOT=/cygdrive/c/RetroShareBuild/src - -#PTHREADS_DIR=$(ALT_SRC_ROOT)/pthreads-w32-2-8-0-release - -################### - -ZLIB_DIR=$(ALT_SRC_ROOT)/zlib-1.2.3 - -SSL_DIR=$(SRC_ROOT)/openssl-0.9.7g-xpgp-0.1c -UPNPC_DIR=$(SRC_ROOT)/miniupnpc-1.0 - -include $(RS_TOP_DIR)/scripts/checks.mk - -############ ENFORCE DIRECTORY NAMING ######################## - -CC = g++ -RM = /bin/rm -RANLIB = ranlib -LIBDIR = $(RS_TOP_DIR)/lib -LIBRS = $(LIBDIR)/libretroshare.a - -# Unix: Linux/Cygwin -INCLUDE = -I $(RS_TOP_DIR) - -ifdef PQI_DEBUG - CFLAGS = -Wall -g $(INCLUDE) -else - CFLAGS = -Wall -O2 $(INCLUDE) -endif - -ifdef PQI_USE_XPGP - INCLUDE += -I $(SSL_DIR)/include -endif - -ifdef PQI_USE_XPGP - CFLAGS += -DPQI_USE_XPGP -endif - -ifdef PQI_USE_PROXY - CFLAGS += -DPQI_USE_PROXY -endif - -ifdef PQI_USE_CHANNELS - CFLAGS += -DPQI_USE_CHANNELS -endif - -ifdef USE_FILELOOK - CFLAGS += -DUSE_FILELOOK -endif - - -RSCFLAGS = -Wall -g $(INCLUDE) - -######################################################################### -# OS Compile Options -######################################################################### - -# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) -BIOCC = gcc - -# Cygwin - ?same? as Linux flags -BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -m486 -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM - -######################################################################### -# OS specific Linking. -######################################################################### - -# for static pthread libs.... -WININC += -DPTW32_STATIC_LIB -WININC += -mno-cygwin -mwindows -fno-exceptions -WININC += -DWINDOWS_SYS - -WINLIB = -lws2_32 -luuid -lole32 -liphlpapi -WINLIB += -lcrypt32 -lwinmm - -CFLAGS += -I$(PTHREADS_DIR) $(WININC) -CFLAGS += -I$(ZLIB_DIR) - -LIBS = -L$(LIBDIR) -lretroshare -ifdef PQI_USE_XPGP - LIBS += -L$(SSL_DIR) -endif - -LIBS += -lssl -lcrypto -LIBS += -L$(UPNPC_DIR) -lminiupnpc -LIBS += -L$(ZLIB_DIR) -lz -LIBS += -L$(PTHREADS_DIR) -lpthreadGC2d -LIBS += $(WINLIB) - -RSCFLAGS += $(WININC) - - diff --git a/libbitdht/src/tests/scripts/config-linux.mk b/libbitdht/src/tests/scripts/config-linux.mk deleted file mode 100644 index 182f9c39a..000000000 --- a/libbitdht/src/tests/scripts/config-linux.mk +++ /dev/null @@ -1,41 +0,0 @@ - -ifneq ($(OS),Linux) -dummy: - echo "ERROR Linux configuration file included, but (OS != Linux) - -endif - -############ LINUX CONFIGURATION ######################## - -include $(TEST_TOP_DIR)/scripts/checks.mk - -############ ENFORCE DIRECTORY NAMING ######################## - -CC = g++ -RM = /bin/rm -RANLIB = ranlib -LIBDIR = $(LIB_TOP_DIR)/lib -LIBRS = $(LIBDIR)/libretroshare.a - -# Unix: Linux/Cygwin -INCLUDE = -I $(LIB_TOP_DIR) -CFLAGS = -Wall -g $(INCLUDE) -CFLAGS += ${DEFINES} -D BE_DEBUG - -######################################################################### -# OS Compile Options -######################################################################### - -######################################################################### -# OS specific Linking. -######################################################################### - -LIBS = -L$(LIBDIR) -lbitdht -LIBS += -lpthread -#LIBS += $(XLIB) -ldl -lz -#LIBS += -lupnp -#LIBS += -lgpgme -# -#RSLIBS = $(LIBS) - - diff --git a/libbitdht/src/tests/scripts/config-macosx.mk b/libbitdht/src/tests/scripts/config-macosx.mk deleted file mode 100644 index ecf95733d..000000000 --- a/libbitdht/src/tests/scripts/config-macosx.mk +++ /dev/null @@ -1,81 +0,0 @@ - -ifneq ($(OS),MacOSX) -dummy: - echo "ERROR MacOSX configuration file included, but (OS != MacOSX) - -endif - -############ MACOSX CONFIGURATION ######################## - - -# FLAGS to decide if we want i386 Build or ppc Build -# -# - -# MAC_I386_BUILD = 1 -# MAC_PPC_BUILD = 1 - -MAC_I386_BUILD = 1 -#MAC_PPC_BUILD = 1 - -ifndef MAC_I386_BUILD - MAC_PPC_BUILD = 1 -endif - -include $(TEST_TOP_DIR)/scripts/checks.mk - -############ ENFORCE DIRECTORY NAMING ######################## - -CC = g++ -RM = /bin/rm - -RANLIB = ranlib - -# Dummy ranlib -> can't do it until afterwards with universal binaries. -# RANLIB = ls -l - -LIBDIR = $(LIB_TOP_DIR)/lib -LIBRS = $(LIBDIR)/libretroshare.a - -OPT_DIR = /opt/local -OPT_INCLUDE = $(OPT_DIR)/include -OPT_LIBS = $(OPT_DIR)/lib - -INCLUDE = -I $(LIB_TOP_DIR) -#-I $(OPT_INCLUDE) -#CFLAGS = -Wall -O3 -CFLAGS = -Wall -g - -# Flags for architecture builds. -ifdef MAC_I386_BUILD - CFLAGS += -arch i386 -endif - -ifdef MAC_PPC_BUILD - CFLAGS += -arch ppc -endif - -CFLAGS += $(INCLUDE) - -# This Line is for Universal BUILD for 10.4 + 10.5 -# (but unlikely to work unless Qt Libraries are build properly) -#CFLAGS += -isysroot /Developer/SDKs/MacOSX10.5.sdk - -######################################################################### -# OS Compile Options -######################################################################### - -######################################################################### -# OS specific Linking. -######################################################################### - -#LIBS = -Wl,-search_paths_first - -# for Univeral BUILD -# LIBS += -arch ppc -arch i386 -# LIBS += -Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk -arch ppc -arch i386 - -#LIBS += -Wl,-syslibroot,/Developer/SDKs/MacOSX10.5.sdk -LIBS += -L$(LIBDIR) -lbitdht - - diff --git a/libbitdht/src/tests/scripts/config-mingw.mk b/libbitdht/src/tests/scripts/config-mingw.mk deleted file mode 100644 index c0040ac4e..000000000 --- a/libbitdht/src/tests/scripts/config-mingw.mk +++ /dev/null @@ -1,138 +0,0 @@ -#ifneq ($(OS),"Win ") -#dummy: -# echo "ERROR OS = $(OS)" -# echo "ERROR MinGW configuration file included, but (OS != Win) -# -#endif - -############ LINUX CONFIGURATION ######################## - -# flags for components.... -#PQI_USE_XPGP = 1 -#PQI_USE_PROXY = 1 -#PQI_USE_CHANNELS = 1 -#USE_FILELOOK = 1 - -########################################################################### - -#### DrBobs Versions.... Please Don't Delete. -### Comment out if needed. -SRC_ROOT_PKG=/home/Mark/prog/retroshare/package/rs-win-v0.5.0/src -SRC_ROOT_GPG=/local - -#ALT_SRC_ROOT=/cygdrive/c/home/rmfern/prog/MinGW -#SRC_ROOT=../../../.. - -PTHREADS_DIR=$(SRC_ROOT_PKG)/pthreads-w32-2-8-0/Pre-built.2 -ZLIB_DIR=$(SRC_ROOT_PKG)/zlib-1.2.3 -SSL_DIR=$(SRC_ROOT_PKG)/openssl-tmp -UPNPC_DIR=$(SRC_ROOT_PKG)/miniupnpc-1.3 - -########################################################################### - -#### Enable this section for compiling with MSYS/MINGW compile -#SRC_ROOT=/home/linux - -#SSL_DIR=$(SRC_ROOT)/OpenSSL -#GPGME_DIR=$(SRC_ROOT)/gpgme-1.1.8 -#GPG_ERROR_DIR=$(SRC_ROOT)/libgpg-error-1.7 - -#ZLIB_DIR=$(SRC_ROOT)/zlib-1.2.3 -#UPNPC_DIR=$(SRC_ROOT)/miniupnpc-1.0 -#PTHREADS_DIR=$(SRC_ROOT)/pthreads-w32-2-8-0-release - -include $(RS_TOP_DIR)/scripts/checks.mk - -############ ENFORCE DIRECTORY NAMING ####################################### - -CC = g++ -RM = /bin/rm -RANLIB = ranlib -LIBDIR = $(RS_TOP_DIR)/lib -LIBRS = $(LIBDIR)/libretroshare.a - -# Unix: Linux/Cygwin -INCLUDE = -I $(RS_TOP_DIR) - -ifdef PQI_DEBUG - CFLAGS = -Wall -g $(INCLUDE) -else - CFLAGS = -Wall -O2 $(INCLUDE) -endif - -# These aren't used anymore.... really. -ifdef PQI_USE_XPGP - CFLAGS += -DPQI_USE_XPGP -endif - -ifdef PQI_USE_PROXY - CFLAGS += -DPQI_USE_PROXY -endif - -ifdef PQI_USE_CHANNELS - CFLAGS += -DPQI_USE_CHANNELS -endif - -ifdef USE_FILELOOK - CFLAGS += -DUSE_FILELOOK -endif - - -# SSL / pthreads / Zlib -# included by default for Windows compilation. -INCLUDE += -I $(SSL_DIR)/include -INCLUDE += -I$(PTHREADS_DIR) -INCLUDE += -I$(ZLIB_DIR) - - -######################################################################### -# OS Compile Options -######################################################################### - -# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) -BIOCC = gcc - -# Cygwin - ?same? as Linux flags -BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -m486 -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM -BIOCFLAGS += -DWINDOWS_SYS - -######################################################################### -# OS specific Linking. -######################################################################### - -# for static pthread libs.... -#WININC += -DPTW32_STATIC_LIB -#WININC += -mno-cygwin -mwindows -fno-exceptions - -WININC += -DWINDOWS_SYS - -WINLIB = -lws2_32 -luuid -lole32 -liphlpapi -WINLIB += -lcrypt32 -lwinmm - -CFLAGS += -I$(SSL_DIR)/include -CFLAGS += -I$(PTHREADS_DIR)/include -CFLAGS += -I$(ZLIB_DIR) -CFLAGS += -I$(SRC_ROOT_GPG)/include - -### Enable this for GPGME and GPG ERROR dirs -#CFLAGS += -I$(GPGME_DIR)/src -#CFLAGS += -I$(GPG_ERROR_DIR)/src - -CFLAGS += $(WININC) - - - -LIBS = -L$(LIBDIR) -lretroshare - -LIBS += -L$(SSL_DIR) - -LIBS += -lssl -lcrypto -LIBS += -L$(UPNPC_DIR) -lminiupnpc -LIBS += -L$(ZLIB_DIR) -lz -LIBS += -L$(PTHREADS_DIR) -lpthreadGC2d -LIBS += $(WINLIB) - -#RSCFLAGS = -Wall -g $(INCLUDE) -#RSCFLAGS += $(WININC) - - diff --git a/libbitdht/src/tests/scripts/config.mk b/libbitdht/src/tests/scripts/config.mk deleted file mode 100644 index 0859a4799..000000000 --- a/libbitdht/src/tests/scripts/config.mk +++ /dev/null @@ -1,27 +0,0 @@ - -# determine which operating system -# -########################################################################### -#Define OS. -# -OS = Linux -#OS = MacOSX -#OS = Cygwin -#OS = Win # MinGw. -########################################################################### - -ifeq ($(OS),Linux) - include $(TEST_TOP_DIR)/scripts/config-linux.mk -else - ifeq ($(OS),MacOSX) - include $(TEST_TOP_DIR)/scripts/config-macosx.mk - else - ifeq ($(OS),Cygwin) - include $(TEST_TOP_DIR)/scripts/config-cygwin.mk - else - include $(TEST_TOP_DIR)/scripts/config-mingw.mk - endif - endif -endif - -########################################################################### diff --git a/libbitdht/src/tests/scripts/regress.mk b/libbitdht/src/tests/scripts/regress.mk deleted file mode 100644 index f80b48451..000000000 --- a/libbitdht/src/tests/scripts/regress.mk +++ /dev/null @@ -1,25 +0,0 @@ - -testoutputfiles = $(foreach tt,$(1),$(tt).tstout) - -%.tstout : %.sh - -sh ./$< > $@ 2>&1 - -%.tstout : % - -./$< > $@ 2>&1 - -TESTOUT = $(call testoutputfiles,$(TESTS)) - -.phony : tests regress retest clobber - -tests: $(TESTS) - -regress: $(TESTOUT) - @-echo "--------------- SUCCESS (count):" - @-grep -c SUCCESS $(TESTOUT) - @-echo "--------------- FAILURE REPORTS:" - @-grep FAILURE $(TESTOUT) || echo no failures - @-echo "--------------- end" - -retest: - -/bin/rm $(TESTOUT) - diff --git a/libbitdht/src/tests/scripts/rules.mk b/libbitdht/src/tests/scripts/rules.mk deleted file mode 100644 index 9166e80a4..000000000 --- a/libbitdht/src/tests/scripts/rules.mk +++ /dev/null @@ -1,19 +0,0 @@ - -# defines required / used. -# -# CFLAGS -# -# - -.cc.o: - $(CC) $(CFLAGS) -c $< - -clean: - -/bin/rm $(EXECOBJ) $(TESTOBJ) - -clobber: clean retest - -/bin/rm $(EXEC) $(TESTS) - - -include $(TEST_TOP_DIR)/scripts/regress.mk - diff --git a/libbitdht/src/tests/udpbitdht_nettest.cc b/libbitdht/src/tests/udpbitdht_nettest.cc deleted file mode 100644 index 0dbb634b2..000000000 --- a/libbitdht/src/tests/udpbitdht_nettest.cc +++ /dev/null @@ -1,278 +0,0 @@ -/* - * bitdht/udpbitdht_nettest.cc - * - * BitDHT: An Flexible DHT library. - * - * Copyright 2010 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 3 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "bitdht@lunamutt.com". - * - */ - - -#include "udp/udpbitdht.h" -#include "udp/udpstack.h" -#include "bitdht/bdstddht.h" - -#include -#include - -/******************************************************************* - * DHT test program. - * - * - * Create a couple of each type. - */ - -#define MAX_MESSAGE_LEN 10240 - -int args(char *name) -{ - std::cerr << "Usage: " << name; - std::cerr << " -p "; - std::cerr << " -b "; - std::cerr << " -u "; - std::cerr << " -q "; - std::cerr << " -r (do dht restarts) "; - std::cerr << " -j (do join test) "; - std::cerr << std::endl; - return 1; -} - -#define DEF_PORT 7500 - -#define MIN_DEF_PORT 1001 -#define MAX_DEF_PORT 16000 - -#define DEF_BOOTFILE "bdboot.txt" - -int main(int argc, char **argv) -{ - int c; - int port = DEF_PORT; - std::string bootfile = DEF_BOOTFILE; - std::string uid; - bool setUid = false; - bool doRandomQueries = false; - bool doRestart = false; - bool doThreadJoin = false; - int noQueries = 0; - - while((c = getopt(argc, argv,"rjp:b:u:q:")) != -1) - { - switch (c) - { - case 'r': - doRestart = true; - break; - case 'j': - doThreadJoin = true; - break; - case 'p': - { - int tmp_port = atoi(optarg); - if ((tmp_port > MIN_DEF_PORT) && (tmp_port < MAX_DEF_PORT)) - { - port = tmp_port; - std::cerr << "Port: " << port; - std::cerr << std::endl; - } - else - { - std::cerr << "Invalid Port"; - std::cerr << std::endl; - args(argv[0]); - return 1; - } - - } - break; - case 'b': - { - bootfile = optarg; - std::cerr << "Bootfile: " << bootfile; - std::cerr << std::endl; - } - break; - case 'u': - { - setUid = true; - uid = optarg; - std::cerr << "UID: " << uid; - std::cerr << std::endl; - } - break; - case 'q': - { - doRandomQueries = true; - noQueries = atoi(optarg); - std::cerr << "Doing Random Queries"; - std::cerr << std::endl; - } - break; - - default: - { - args(argv[0]); - return 1; - } - break; - } - } - - - bdDhtFunctions *fns = new bdStdDht(); - - bdNodeId id; - - /* start off with a random id! */ - bdStdRandomNodeId(&id); - - if (setUid) - { - int len = uid.size(); - if (len > 20) - { - len = 20; - } - - for(int i = 0; i < len; i++) - { - id.data[i] = uid[i]; - } - } - - std::cerr << "Using NodeId: "; - fns->bdPrintNodeId(std::cerr, &id); - std::cerr << std::endl; - - /* setup the udp port */ - struct sockaddr_in local; - memset(&local, 0, sizeof(local)); - local.sin_family = AF_INET; - local.sin_addr.s_addr = 0; - local.sin_port = htons(port); - UdpStack *udpstack = new UdpStack(local); - - /* create bitdht component */ - std::string dhtVersion = "dbTEST"; - UdpBitDht *bitdht = new UdpBitDht(udpstack, &id, dhtVersion, bootfile, fns); - - /* add in the stack */ - udpstack->addReceiver(bitdht); - - /* register callback display */ - bdDebugCallback *cb = new bdDebugCallback(); - bitdht->addCallback(cb); - - /* startup threads */ - //udpstack->start(); - bitdht->start(); - - - - - /* do a couple of random continuous searchs. */ - - uint32_t mode = BITDHT_QFLAGS_DO_IDLE; - - int count = 0; - int running = 1; - - std::cerr << "Starting Dht: "; - std::cerr << std::endl; - bitdht->startDht(); - - - if (doRandomQueries) - { - for(int i = 0; i < noQueries; i++) - { - bdNodeId rndId; - bdStdRandomNodeId(&rndId); - - std::cerr << "BitDht Launching Random Search: "; - bdStdPrintNodeId(std::cerr, &rndId); - std::cerr << std::endl; - - bitdht->addFindNode(&rndId, mode); - - } - } - - while(1) - { - sleep(60); - - std::cerr << "BitDht State: "; - std::cerr << bitdht->stateDht(); - std::cerr << std::endl; - - std::cerr << "Dht Network Size: "; - std::cerr << bitdht->statsNetworkSize(); - std::cerr << std::endl; - - std::cerr << "BitDht Network Size: "; - std::cerr << bitdht->statsBDVersionSize(); - std::cerr << std::endl; - - if (++count == 2) - { - /* switch to one-shot searchs */ - mode = 0; - } - - if (doThreadJoin) - { - /* change address */ - if (count % 2 == 0) - { - - std::cerr << "Resetting UdpStack: "; - std::cerr << std::endl; - - udpstack->resetAddress(local); - } - } - if (doRestart) - { - if (count % 2 == 1) - { - if (running) - { - - std::cerr << "Stopping Dht: "; - std::cerr << std::endl; - - bitdht->stopDht(); - running = 0; - } - else - { - std::cerr << "Starting Dht: "; - std::cerr << std::endl; - - bitdht->startDht(); - running = 1; - } - } - } - } - return 1; -} - - diff --git a/libbitdht/src/tests/utest.h b/libbitdht/src/tests/utest.h deleted file mode 100644 index 1ebd9875a..000000000 --- a/libbitdht/src/tests/utest.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _UNIT_TEST_MACROS_H__ -#define _UNIT_TEST_MACROS_H__ - -#include - -#define TFAILURE( s ) printf( "FAILURE: " __FILE__ ":%-4d %s\n", __LINE__, s ) -#define TSUCCESS( s ) printf( "SUCCESS: " __FILE__ ":%-4d %s\n", __LINE__, s ) - -/* careful with this line (no protection) */ -#define INITTEST() int ok = 1; int gok = 1; - -/* declare the variables */ -extern int ok; -extern int gok; - -#define CHECK( b ) do { if ( ! (b) ) { ok = 0; TFAILURE( #b ); } } while(0) -#define FAILED( s ) do { ok = 0; TFAILURE( s ); } while(0) -#define REPORT( s ) do { if ( ! (ok) ) { ok = 0; TFAILURE( s ); } else { TSUCCESS( s );} gok &= ok; ok = 1; } while(0) -#define REPORT2( b, s ) do { if ( ! (b) ) { ok = 0; TFAILURE( s ); } else { TSUCCESS( s );} gok &= ok; ok = 1; } while(0) -#define FINALREPORT( s ) do { gok &= ok; ok = 1; if ( ! (gok) ) { TFAILURE( s ); } else { TSUCCESS( s );} } while(0) -#define TESTRESULT() (!gok) - -#endif diff --git a/libbitdht/src/udp/udpbitdht.cc b/libbitdht/src/udp/udpbitdht.cc deleted file mode 100644 index 066faf54d..000000000 --- a/libbitdht/src/udp/udpbitdht.cc +++ /dev/null @@ -1,373 +0,0 @@ -/******************************************************************************* - * bitdht/udpbitdht.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "udp/udpbitdht.h" -#include "bitdht/bdpeer.h" -#include "bitdht/bdstore.h" -#include "bitdht/bdmsgs.h" -#include "bitdht/bencode.h" - -#include -#include /* for usleep() */ -#include -#include - -#include - -#include "util/bdnet.h" - -/* - * #define DEBUG_UDP_BITDHT 1 - * - * #define BITDHT_VERSION_ANONYMOUS 1 - */ - -//#define DEBUG_UDP_BITDHT 1 - -#define BITDHT_VERSION_IDENTIFER 1 - -// Original RS 0.5.0/0.5.1 version, is un-numbered. -//#define BITDHT_VERSION "00" // First Release of BitDHT with Connections (Proxy Support + Dht Stun) -//#define BITDHT_VERSION "01" // Testing Connections (Proxy Only) -#define BITDHT_VERSION "02" // Completed Relay Connections from svn 4766 -//#define BITDHT_VERSION "04" // Full DHT implementation.? - -/*************************************/ - -UdpBitDht::UdpBitDht(UdpPublisher *pub, bdNodeId *id, std::string appVersion, std::string bootstrapfile, std::string bootstrapfilebak, const std::string& filteredipfile, bdDhtFunctions *fns) - :UdpSubReceiver(pub), dhtMtx(true)//, mFns(fns) -{ - std::string usedVersion; - -#ifdef BITDHT_VERSION_IDENTIFER - usedVersion = "BD"; - usedVersion += BITDHT_VERSION; -#endif - usedVersion += appVersion; - -#ifdef BITDHT_VERSION_ANONYMOUS - usedVersion = ""; /* blank it */ -#endif - - clearDataTransferred(); - - /* setup nodeManager */ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - mBitDhtManager = new bdNodeManager(id, usedVersion, bootstrapfile, bootstrapfilebak, filteredipfile, fns); -} - - -UdpBitDht::~UdpBitDht() -{ - return; -} - - - /*********** External Interface to the World ************/ - - /***** Functions to Call down to bdNodeManager ****/ - /* Friend Tracking */ -void UdpBitDht::addBadPeer(const struct sockaddr_in &addr, uint32_t source, uint32_t reason, uint32_t age) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - mBitDhtManager->addBadPeer(addr, source, reason, age); -} - - -void UdpBitDht::updateKnownPeer(const bdId *id, uint32_t type, uint32_t flags) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - mBitDhtManager->updateKnownPeer(id, type, flags); -} - - /* Request DHT Peer Lookup */ - /* Request Keyword Lookup */ -void UdpBitDht::addFindNode(bdNodeId *id, uint32_t mode) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - mBitDhtManager->addFindNode(id, mode); -} - -void UdpBitDht::removeFindNode(bdNodeId *id) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - mBitDhtManager->removeFindNode(id); -} - -void UdpBitDht::findDhtValue(bdNodeId *id, std::string key, uint32_t mode) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - mBitDhtManager->findDhtValue(id, key, mode); -} - - /***** Add / Remove Callback Clients *****/ -void UdpBitDht::addCallback(BitDhtCallback *cb) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - mBitDhtManager->addCallback(cb); -} - -void UdpBitDht::removeCallback(BitDhtCallback *cb) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - mBitDhtManager->removeCallback(cb); -} - -bool UdpBitDht::ConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t delay, uint32_t start) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->ConnectionRequest(laddr, target, mode, delay, start); -} - - - -void UdpBitDht::ConnectionAuth(bdId *srcId, bdId *proxyId, bdId *destId, uint32_t mode, uint32_t loc, - uint32_t bandwidth, uint32_t delay, uint32_t answer) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - mBitDhtManager->ConnectionAuth(srcId, proxyId, destId, mode, loc, bandwidth, delay, answer); -} - -void UdpBitDht::ConnectionOptions(uint32_t allowedModes, uint32_t flags) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - mBitDhtManager->ConnectionOptions(allowedModes, flags); -} - -bool UdpBitDht::setAttachMode(bool on) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->setAttachMode(on); -} - - -int UdpBitDht::getDhtPeerAddress(const bdNodeId *id, struct sockaddr_in &from) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->getDhtPeerAddress(id, from); -} - -int UdpBitDht::getDhtValue(const bdNodeId *id, std::string key, std::string &value) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->getDhtValue(id, key, value); -} - -int UdpBitDht::getDhtBucket(const int idx, bdBucket &bucket) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->getDhtBucket(idx, bucket); -} - - - -int UdpBitDht::getDhtQueries(std::map &queries) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->getDhtQueries(queries); -} - -int UdpBitDht::getDhtQueryStatus(const bdNodeId *id, bdQuerySummary &query) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->getDhtQueryStatus(id, query); -} - -bool UdpBitDht::isAddressBanned(const sockaddr_in &raddr) -{ - return mBitDhtManager->addressBanned(raddr) ; -} - -bool UdpBitDht::getListOfBannedIps(std::list& ipl) -{ - return mBitDhtManager->getFilteredPeers(ipl) ; -} - - - - /* stats and Dht state */ -int UdpBitDht:: startDht() -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->startDht(); -} - -int UdpBitDht:: stopDht() -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->stopDht(); -} - -int UdpBitDht::stateDht() -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->stateDht(); -} - -uint32_t UdpBitDht::statsNetworkSize() -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->statsNetworkSize(); -} - -uint32_t UdpBitDht::statsBDVersionSize() -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->statsBDVersionSize(); -} - -uint32_t UdpBitDht::setDhtMode(uint32_t dhtFlags) -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - return mBitDhtManager->setDhtMode(dhtFlags); -} - - - /******************* Internals *************************/ - - /***** Iteration / Loop Management *****/ - - /*** Overloaded from UdpSubReceiver ***/ -int UdpBitDht::recvPkt(void *data, int size, struct sockaddr_in &from) -{ - /* pass onto bitdht */ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - /* check packet suitability */ - if (mBitDhtManager->isBitDhtPacket((char *) data, size, from)) - { - - mReadBytes += size; - mBitDhtManager->incomingMsg(&from, (char *) data, size); - return 1; - } - return 0; -} - -int UdpBitDht::status(std::ostream &out) -{ - out << "UdpBitDht::status()" << std::endl; - - return 1; -} - -void UdpBitDht::clearDataTransferred() -{ - /* pass onto bitdht */ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - mReadBytes = 0; - mWriteBytes = 0; -} - - -void UdpBitDht::getDataTransferred(uint32_t &read, uint32_t &write) -{ - { - /* pass onto bitdht */ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - read = mReadBytes; - write = mWriteBytes; - } - clearDataTransferred(); -} - - - /*** Overloaded from iThread ***/ -#define MAX_MSG_PER_TICK 100 -#define TICK_PAUSE_USEC 20000 /* 20ms secs .. max messages = 50 x 100 = 5000 */ - -void UdpBitDht::run() -{ - while(1) - { - while(tick()) - { - usleep(TICK_PAUSE_USEC); - } - - { - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - mBitDhtManager->iteration(); - } - sleep(1); - } -} - - -int UdpBitDht::tick() -{ - bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ - - /* pass on messages from the node */ - int i = 0; - char data[BITDHT_MAX_PKTSIZE]; - struct sockaddr_in toAddr; - int size = BITDHT_MAX_PKTSIZE; - - while((i < MAX_MSG_PER_TICK) && (mBitDhtManager->outgoingMsg(&toAddr, data, &size))) - { -#ifdef DEBUG_UDP_BITDHT - std::cerr << "UdpBitDht::tick() outgoing msg(" << size << ") to " << toAddr; - std::cerr << std::endl; -#endif - - mWriteBytes += size; - sendPkt(data, size, toAddr, BITDHT_TTL); - - // iterate - i++; - size = BITDHT_MAX_PKTSIZE; // reset msg size! - } - - if (i == MAX_MSG_PER_TICK) - { - return 1; /* keep on ticking */ - } - return 0; -} - - - diff --git a/libbitdht/src/udp/udpbitdht.h b/libbitdht/src/udp/udpbitdht.h deleted file mode 100644 index 38088edfb..000000000 --- a/libbitdht/src/udp/udpbitdht.h +++ /dev/null @@ -1,127 +0,0 @@ -/******************************************************************************* - * udp/udpbitdht.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef UDP_BIT_DHT_CLASS_H -#define UDP_BIT_DHT_CLASS_H - -#include -#include -#include - -#include "udp/udpstack.h" -#include "bitdht/bdiface.h" -#include "bitdht/bdmanager.h" - -/* - * This implements a UdpSubReceiver class to allow the DHT to talk to the network. - * The parser is very strict - and will try to not pick up anyone else's messages. - * - * Mutexes are implemented at this level protecting the whole of the DHT code. - * This class is also a thread - enabling it to do callback etc. - */ - -// class BitDhtCallback defined in bdiface.h - - -class UdpBitDht: public UdpSubReceiver, public bdThread, public BitDhtInterface -{ - public: - - UdpBitDht(UdpPublisher *pub, bdNodeId *id, std::string dhtVersion, std::string bootstrapfile, std::string bootstrapfilebak, const std::string& filteredipfile,bdDhtFunctions *fns); -virtual ~UdpBitDht(); - - - /*********** External Interface to the World (BitDhtInterface) ************/ - - /***** Functions to Call down to bdNodeManager ****/ - - /* Friend Tracking */ -virtual void addBadPeer(const struct sockaddr_in &addr, uint32_t source, uint32_t reason, uint32_t age); -virtual void updateKnownPeer(const bdId *id, uint32_t type, uint32_t flags); - - /* Request DHT Peer Lookup */ - /* Request Keyword Lookup */ -virtual void addFindNode(bdNodeId *id, uint32_t mode); -virtual void removeFindNode(bdNodeId *id); -virtual void findDhtValue(bdNodeId *id, std::string key, uint32_t mode); - - /***** Add / Remove Callback Clients *****/ -virtual void addCallback(BitDhtCallback *cb); -virtual void removeCallback(BitDhtCallback *cb); - - /***** Connections Requests *****/ -virtual bool ConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t delay, uint32_t start); -virtual void ConnectionAuth(bdId *srcId, bdId *proxyId, bdId *destId, uint32_t mode, uint32_t loc, - uint32_t bandwidth, uint32_t delay, uint32_t answer); -virtual void ConnectionOptions(uint32_t allowedModes, uint32_t flags); -virtual bool setAttachMode(bool on); - - /***** Get Results Details *****/ -virtual int getDhtPeerAddress(const bdNodeId *id, struct sockaddr_in &from); -virtual int getDhtValue(const bdNodeId *id, std::string key, std::string &value); -virtual int getDhtBucket(const int idx, bdBucket &bucket); - -virtual int getDhtQueries(std::map &queries); -virtual int getDhtQueryStatus(const bdNodeId *id, bdQuerySummary &query); - - virtual bool isAddressBanned(const sockaddr_in &raddr) ; - virtual bool getListOfBannedIps(std::list &ipl); - - /* stats and Dht state */ -virtual int startDht(); -virtual int stopDht(); -virtual int stateDht(); -virtual uint32_t statsNetworkSize(); -virtual uint32_t statsBDVersionSize(); -virtual uint32_t setDhtMode(uint32_t dhtFlags); - -void getDataTransferred(uint32_t &read, uint32_t &write); - - /******************* Internals *************************/ - /***** Iteration / Loop Management *****/ - - /*** Overloaded from UdpSubReceiver ***/ -virtual int recvPkt(void *data, int size, struct sockaddr_in &from); -virtual int status(std::ostream &out); - - - /*** Overloaded from iThread ***/ -virtual void run(); - - /**** do whats to be done ***/ -int tick(); -private: - -void clearDataTransferred(); - - bdMutex dhtMtx; /* for all class data (below) */ - bdNodeManager *mBitDhtManager; - //bdDhtFunctions *mFns; - - - uint32_t mReadBytes; - uint32_t mWriteBytes; - - -}; - - -#endif diff --git a/libbitdht/src/udp/udplayer.cc b/libbitdht/src/udp/udplayer.cc deleted file mode 100644 index 1a82c3d81..000000000 --- a/libbitdht/src/udp/udplayer.cc +++ /dev/null @@ -1,772 +0,0 @@ -/******************************************************************************* - * udp/udplayer.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2004-2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "udp/udplayer.h" -#include "util/bdrandom.h" -#include "util/bdstring.h" - -#include -#include -#include -#include -#include -#ifndef WIN32 -#include -#endif - -/*** - * #define UDP_ENABLE_BROADCAST 1 - * #define UDP_LOOPBACK_TESTING 1 - * #define DEBUG_UDP_LAYER 1 - ***/ - -//#define DEBUG_UDP_LAYER 1 - -static const int UDP_DEF_TTL = 64; - -/* NB: This #define makes the listener open 0.0.0.0:X port instead - * of a specific port - this helps library communicate on systems - * with multiple interfaces or unique network setups. - * - * - It should always be used! - * - * #define OPEN_UNIVERSAL_PORT 1 - * - */ - -#define OPEN_UNIVERSAL_PORT 1 - - -class udpPacket -{ - public: - udpPacket(struct sockaddr_in *addr, void *dta, int dlen) - :raddr(*addr), len(dlen) - { - data = malloc(len); - - if(data != NULL) - memcpy(data, dta, len); - else - std::cerr << "(EE) error in memory allocation in " << __PRETTY_FUNCTION__ << std::endl; - } - - ~udpPacket() - { - if (data) - { - free(data); - data = NULL; - len = 0; - } - } - - struct sockaddr_in raddr; - void *data; - int len; -}; - -//std::ostream &operator<<(std::ostream &out, const struct sockaddr_in &addr) -std::ostream &operator<<(std::ostream &out, struct sockaddr_in &addr) -{ - out << "[" << bdnet_inet_ntoa(addr.sin_addr) << ":"; - out << htons(addr.sin_port) << "]"; - return out; -} - -bool operator==(const struct sockaddr_in &addr, const struct sockaddr_in &addr2) -{ - if (addr.sin_family != addr2.sin_family) - return false; - if (addr.sin_addr.s_addr != addr2.sin_addr.s_addr) - return false; - if (addr.sin_port != addr2.sin_port) - return false; - return true; -} - - -bool operator<(const struct sockaddr_in &addr, const struct sockaddr_in &addr2) -{ - if (addr.sin_family != addr2.sin_family) - return (addr.sin_family < addr2.sin_family); - if (addr.sin_addr.s_addr != addr2.sin_addr.s_addr) - return (addr.sin_addr.s_addr < addr2.sin_addr.s_addr); - if (addr.sin_port != addr2.sin_port) - return (addr.sin_port < addr2.sin_port); - return false; -} - -std::string printPkt(void *d, int size) -{ - std::string out = "Packet:**********************"; - for(int i = 0; i < size; i++) - { - if (i % 16 == 0) - out += "\n"; - bd_sprintf_append(out, "%2x ", (unsigned int) ((unsigned char *) d)[i]); - } - out += "\n**********************\n"; - return out; -} - - -std::string printPktOffset(unsigned int offset, void *d, unsigned int size) -{ - std::string out = "Packet:**********************\n"; - bd_sprintf_append(out, "Offset: %x -> %x\n", offset, offset + size); - out += "Packet:**********************"; - - unsigned int j = offset % 16; - if (j != 0) - { - out += "\n"; - bd_sprintf_append(out, "%6x: ", (unsigned int) offset - j); - for(unsigned int i = 0; i < j; i++) - { - out += "xx "; - } - } - for(unsigned int i = offset; i < offset + size; i++) - { - if (i % 16 == 0) - { - out += "\n"; - bd_sprintf_append(out, "%6x: ", (unsigned int) i); - } - bd_sprintf(out, "%2x ", (unsigned int) ((unsigned char *) d)[i-offset]); - } - out += "\n**********************\n"; - return out; -} - - - -UdpLayer::UdpLayer(UdpReceiver *udpr, struct sockaddr_in &local) - :recv(udpr), laddr(local), errorState(0), ttl(UDP_DEF_TTL) -{ - openSocket(); - return; -} - -int UdpLayer::status(std::ostream &out) -{ - out << "UdpLayer::status()" << std::endl; - out << "localaddr: " << laddr << std::endl; - out << "sockfd: " << sockfd << std::endl; - out << std::endl; - return 1; -} - -int UdpLayer::reset(struct sockaddr_in &local) -{ -#ifdef DEBUG_UDP_LAYER - std::cerr << "UdpLayer::reset()" << std::endl; -#endif - - /* stop the old thread */ - { - bdStackMutex stack(sockMtx); /********** LOCK MUTEX *********/ -#ifdef DEBUG_UDP_LAYER - std::cerr << "UdpLayer::reset() setting stopThread flag" << std::endl; -#endif - stopThread = true; - } -#ifdef DEBUG_UDP_LAYER - std::cerr << "UdpLayer::reset() joining" << std::endl; -#endif - - join(); - -#ifdef DEBUG_UDP_LAYER - std::cerr << "UdpLayer::reset() closing socket" << std::endl; -#endif - closeSocket(); - -#ifdef DEBUG_UDP_LAYER - std::cerr << "UdpLayer::reset() resetting variables" << std::endl; -#endif - laddr = local; - errorState = 0; - ttl = UDP_DEF_TTL; - -#ifdef DEBUG_UDP_LAYER - std::cerr << "UdpLayer::reset() opening socket" << std::endl; -#endif - openSocket(); - - return 1 ; -} - - -int UdpLayer::closeSocket() -{ - /* close socket if open */ - sockMtx.lock(); /********** LOCK MUTEX *********/ - - if (sockfd > 0) - { - bdnet_close(sockfd); - } - - sockMtx.unlock(); /******** UNLOCK MUTEX *********/ - return 1; -} - -void UdpLayer::run() -{ - return recv_loop(); -} - -/* higher level interface */ -void UdpLayer::recv_loop() -{ - size_t maxsize = 16000; - void *inbuf = malloc(maxsize); - - if(inbuf == NULL) - { - std::cerr << "(EE) Error in memory allocation of size " << maxsize - << " in " << __PRETTY_FUNCTION__ << std::endl; - return; - } - - int status; - struct timeval timeout; - - while(1) - { - for(;;) - { - /* check if we need to stop */ - bool toStop = false; - { - bdStackMutex stack(sockMtx); (void) stack; - toStop = stopThread; - } - - if (toStop) - { -#ifdef DEBUG_UDP_LAYER - std::cerr << "UdpLayer::recv_loop() stopping thread" << std::endl; -#endif - free(inbuf); - stop(); - return; // Avoid compiler warning about usage of inbuf after free - } - - fd_set rset; - FD_ZERO(&rset); - FD_SET(sockfd, &rset); - timeout.tv_sec = 0; - timeout.tv_usec = 500000; // 500 ms timeout - status = select(sockfd+1, &rset, NULL, NULL, &timeout); - if (status > 0) break; // data available, go read it -#ifdef DEBUG_UDP_LAYER - else if (status < 0) std::cerr << "UdpLayer::recv_loop() Error: " - << bdnet_errno() << std::endl; -#endif - }; - - int nsize = static_cast(maxsize); - struct sockaddr_in from; - if (0 < receiveUdpPacket(inbuf, &nsize, from)) - { -#ifdef DEBUG_UDP_LAYER - std::cerr << "UdpLayer::readPkt() from : " << from << std::endl - << printPkt(inbuf, nsize); -#endif - recv->recvPkt(inbuf, nsize, from); // pass to reciever. - } -#ifdef DEBUG_UDP_LAYER - else std::cerr << "UdpLayer::readPkt() not ready" << from << std::endl; -#endif - } -} - - -int UdpLayer::sendPkt(const void *data, int size, const sockaddr_in &to, int ttl) -{ - /* if ttl is different -> set it */ - if (ttl != getTTL()) - { - setTTL(ttl); - } - - /* and send! */ -#ifdef DEBUG_UDP_LAYER - std::cerr << "UdpLayer::sendPkt() to: " << to << std::endl; - std::cerr << printPkt((void *) data, size); -#endif - sendUdpPacket(data, size, to); - return size; -} - -/* setup connections */ -int UdpLayer::openSocket() -{ - sockMtx.lock(); /********** LOCK MUTEX *********/ - - /* make a socket */ - sockfd = bdnet_socket(PF_INET, SOCK_DGRAM, 0); -#ifdef DEBUG_UDP_LAYER - std::cerr << "UpdStreamer::openSocket()" << std::endl; -#endif - /* bind to address */ - - -#ifdef UDP_LOOPBACK_TESTING - bdnet_inet_aton("127.0.0.1", &(laddr.sin_addr)); -#endif - -#ifdef OPEN_UNIVERSAL_PORT - struct sockaddr_in tmpaddr = laddr; - tmpaddr.sin_addr.s_addr = 0; - if (0 != bdnet_bind(sockfd, (struct sockaddr *) (&tmpaddr), sizeof(tmpaddr))) -#else - if (0 != bdnet_bind(sockfd, (struct sockaddr *) (&laddr), sizeof(laddr))) -#endif - { -#ifdef DEBUG_UDP_LAYER - std::cerr << "Socket Failed to Bind to : " << laddr << std::endl; - std::cerr << "Error: " << bdnet_errno() << std::endl; -#endif - errorState = EADDRINUSE; - //exit(1); - - sockMtx.unlock(); /******** UNLOCK MUTEX *********/ - return -1; - } - - if (-1 == bdnet_fcntl(sockfd, F_SETFL, O_NONBLOCK)) - { -#ifdef DEBUG_UDP_LAYER - std::cerr << "Failed to Make Non-Blocking" << std::endl; -#endif - } - -#ifdef UDP_ENABLE_BROADCAST - /* Setup socket for broadcast. */ - int val = 1; - if (-1 == setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &val, sizeof(int))) - { -#ifdef DEBUG_UDP_LAYER - std::cerr << "Failed to Make Socket Broadcast" << std::endl; -#endif - } -#endif - - errorState = 0; - -#ifdef DEBUG_UDP_LAYER - std::cerr << "Socket Bound to : " << laddr << std::endl; -#endif - - sockMtx.unlock(); /******** UNLOCK MUTEX *********/ - -#ifdef DEBUG_UDP_LAYER - std::cerr << "Setting TTL to " << UDP_DEF_TTL << std::endl; -#endif - setTTL(UDP_DEF_TTL); - clearDataTransferred(); // clear statistics. - - // start up our thread. - { - bdStackMutex stack(sockMtx); /********** LOCK MUTEX *********/ - stopThread = false; - } - start(); - - return 1; - -} - -int UdpLayer::setTTL(int t) -{ - sockMtx.lock(); /********** LOCK MUTEX *********/ - - int err = bdnet_setsockopt(sockfd, IPPROTO_IP, IP_TTL, &t, sizeof(int)); - ttl = t; - - sockMtx.unlock(); /******** UNLOCK MUTEX *********/ - -#ifdef DEBUG_UDP_LAYER - std::cerr << "UdpLayer::setTTL(" << t << ") returned: " << err; - std::cerr << std::endl; -#endif - - return err; -} - -int UdpLayer::getTTL() -{ - sockMtx.lock(); /********** LOCK MUTEX *********/ - - int t = ttl; - - sockMtx.unlock(); /******** UNLOCK MUTEX *********/ - - return t; -} - -/* monitoring / updates */ -int UdpLayer::okay() -{ - sockMtx.lock(); /********** LOCK MUTEX *********/ - - bool nonFatalError = ((errorState == 0) || - (errorState == EAGAIN) || - (errorState == EINPROGRESS)); - - sockMtx.unlock(); /******** UNLOCK MUTEX *********/ - -#ifdef DEBUG_UDP_LAYER - if (!nonFatalError) - { - std::cerr << "UdpLayer::NOT okay(): Error: " << errorState << std::endl; - } - -#endif - - return nonFatalError; -} - -int UdpLayer::tick() -{ -#ifdef DEBUG_UDP_LAYER - std::cerr << "UdpLayer::tick()" << std::endl; -#endif - return 1; -} - -void UdpLayer::getDataTransferred(uint32_t &read, uint32_t &write) -{ - sockMtx.lock(); /********** LOCK MUTEX *********/ - - read = readBytes; - write = writeBytes; - - sockMtx.unlock(); /******** UNLOCK MUTEX *********/ - - clearDataTransferred(); -} - -void UdpLayer::clearDataTransferred() -{ - sockMtx.lock(); /********** LOCK MUTEX *********/ - - readBytes = 0; - writeBytes = 0; - - sockMtx.unlock(); /******** UNLOCK MUTEX *********/ -} - -/******************* Internals *************************************/ - -int UdpLayer::receiveUdpPacket(void *data, int *size, struct sockaddr_in &from) -{ - struct sockaddr_in fromaddr; - socklen_t fromsize = sizeof(fromaddr); - int insize = *size; - - sockMtx.lock(); /********** LOCK MUTEX *********/ - - insize = bdnet_recvfrom(sockfd,data,insize,0, - (struct sockaddr*)&fromaddr,&fromsize); - - if (0 < insize) - { - readBytes += insize; - } - - sockMtx.unlock(); /******** UNLOCK MUTEX *********/ - - if (0 < insize) - { -#ifdef DEBUG_UDP_LAYER - std::cerr << "receiveUdpPacket() from: " << fromaddr; - std::cerr << " Size: " << insize; - std::cerr << std::endl; -#endif - *size = insize; - from = fromaddr; - return insize; - } - return -1; -} - -int UdpLayer::sendUdpPacket(const void *data, int size, const struct sockaddr_in &to) -{ - /* send out */ -#ifdef DEBUG_UDP_LAYER - std::cerr << "UdpLayer::sendUdpPacket(): size: " << size; - std::cerr << " To: " << to << std::endl; -#endif - struct sockaddr_in toaddr = to; - - sockMtx.lock(); /********** LOCK MUTEX *********/ - - bdnet_sendto(sockfd, data, size, 0, - (struct sockaddr *) &(toaddr), - sizeof(toaddr)); - - writeBytes += size; - - sockMtx.unlock(); /******** UNLOCK MUTEX *********/ - return 1; -} - - -/**************************** LossyUdpLayer - for Testing **************/ - - -LossyUdpLayer::LossyUdpLayer(UdpReceiver *udpr, - struct sockaddr_in &local, double frac) - :UdpLayer(udpr, local), lossFraction(frac) -{ - return; -} -LossyUdpLayer::~LossyUdpLayer() { return; } - -int LossyUdpLayer::receiveUdpPacket(void *data, int *size, struct sockaddr_in &from) -{ - if (0 < UdpLayer::receiveUdpPacket(data, size, from)) - { - float prob = bdRandom::random_f32(); - if (prob < lossFraction) - { - /* discard */ - //std::cerr << "LossyUdpLayer::receiveUdpPacket() Dropping packet!"; - //std::cerr << std::endl; - //std::cerr << printPkt(data, *size); - //std::cerr << std::endl; - std::cerr << "LossyUdpLayer::receiveUdpPacket() Packet (" << *size << ") Dropped!"; - std::cerr << std::endl; - - *size = 0; - return -1; - } - - return *size; - } - return -1; -} - -int LossyUdpLayer::sendUdpPacket(const void *data, int size, const struct sockaddr_in &to) -{ - double prob = (1.0 * (rand() / (RAND_MAX + 1.0))); - - if (prob < lossFraction) - { - /* discard */ - - //std::cerr << "LossyUdpLayer::sendUdpPacket() Dropping packet!"; - //std::cerr << std::endl; - //std::cerr << printPkt((void *) data, size); - //std::cerr << std::endl; - std::cerr << "LossyUdpLayer::sendUdpPacket() Packet (" << size << ") Dropped!"; - std::cerr << std::endl; - - return size; - } - - // otherwise read normally; - return UdpLayer::sendUdpPacket(data, size, to); -} - -/**************************** LossyUdpLayer - for Testing **************/ - -PortRange::PortRange() :lport(0), uport(0) { return; } -PortRange::PortRange(uint16_t lp, uint16_t up) :lport(lp), uport(up) { return; } - -bool PortRange::inRange(uint16_t port) -{ - if (port < lport) - { - return false; - } - - if (port > uport) - { - return false; - } - return true; -} - - - -RestrictedUdpLayer::RestrictedUdpLayer(UdpReceiver *udpr, - struct sockaddr_in &local) - :UdpLayer(udpr, local) -{ - return; -} -RestrictedUdpLayer::~RestrictedUdpLayer() { return; } - -void RestrictedUdpLayer::addRestrictedPortRange(int lp, int up) -{ - PortRange pr(lp, up); - mLostPorts.push_back(pr); -} - -int RestrictedUdpLayer::receiveUdpPacket(void *data, int *size, struct sockaddr_in &from) -{ - if (0 < UdpLayer::receiveUdpPacket(data, size, from)) - { - /* check the port against list */ - uint16_t inPort = ntohs(from.sin_port); - - std::list::iterator it; - for(it = mLostPorts.begin(); it != mLostPorts.end(); it++) - { - if (it->inRange(inPort)) - { -#ifdef DEBUG_UDP_LAYER - std::cerr << "RestrictedUdpLayer::receiveUdpPacket() Dropping packet"; - std::cerr << ", Port(" << inPort << ") in restricted range!"; - std::cerr << std::endl; - //std::cerr << printPkt(data, *size); - //std::cerr << std::endl; -#endif - - *size = 0; - return -1; - - } - - } - -#ifdef DEBUG_UDP_LAYER - std::cerr << "RestrictedUdpLayer::receiveUdpPacket() Accepting packet"; - std::cerr << ", Port(" << inPort << ") in Okay range!"; - std::cerr << std::endl; -#endif - /* acceptable port */ - return *size; - } - return -1; -} - -int RestrictedUdpLayer::sendUdpPacket(const void *data, int size, const struct sockaddr_in &to) -{ - /* check the port against list */ - uint16_t outPort = ntohs(to.sin_port); - - std::list::iterator it; - for(it = mLostPorts.begin(); it != mLostPorts.end(); it++) - { - if (it->inRange(outPort)) - { - /* drop */ -#ifdef DEBUG_UDP_LAYER - std::cerr << "RestrictedUdpLayer::sendUdpPacket() Dropping packet"; - std::cerr << ", Port(" << outPort << ") in restricted range!"; - std::cerr << std::endl; - //std::cerr << printPkt(data, *size); - //std::cerr << std::endl; -#endif - - return size; - } - - - } - -#ifdef DEBUG_UDP_LAYER - std::cerr << "RestrictedUdpLayer::sendUdpPacket() Sending packet"; - std::cerr << ", Port(" << outPort << ") in Okay range!"; - std::cerr << std::endl; -#endif - - // otherwise read normally; - return UdpLayer::sendUdpPacket(data, size, to); -} - - -#define STARTUP_PERIOD 60 - -TimedUdpLayer::TimedUdpLayer(UdpReceiver *udpr, - struct sockaddr_in &local) - :UdpLayer(udpr, local) -{ - mStartTime = time(NULL) + STARTUP_PERIOD; - mActive = false; - return; -} - -TimedUdpLayer::~TimedUdpLayer() { return; } - -int TimedUdpLayer::receiveUdpPacket(void *data, int *size, struct sockaddr_in &from) -{ - if (0 < UdpLayer::receiveUdpPacket(data, size, from)) - { - if (!mActive) - { - if (time(NULL) < mStartTime) - { -#ifdef DEBUG_UDP_LAYER -#endif - std::cerr << "TimedUdpLayer::receiveUdpPacket() Dropping packet (Too Early)"; - std::cerr << std::endl; - //std::cerr << printPkt(data, *size); - //std::cerr << std::endl; - - *size = 0; - return -1; - - } - - mActive = true; - - } - - /* acceptable port */ - return *size; - } - return -1; -} - -int TimedUdpLayer::sendUdpPacket(const void *data, int size, const struct sockaddr_in &to) -{ - if (!mActive) - { - if (time(NULL) < mStartTime) - { - /* drop */ -#ifdef DEBUG_UDP_LAYER -#endif - std::cerr << "TimedUdpLayer::sendUdpPacket() Dropping packet (Too Early)"; - std::cerr << std::endl; - return size; - } - - /* else activate */ - mActive = true; - } - - // otherwise read normally; - return UdpLayer::sendUdpPacket(data, size, to); -} - - - - diff --git a/libbitdht/src/udp/udplayer.h b/libbitdht/src/udp/udplayer.h deleted file mode 100644 index 06e76c647..000000000 --- a/libbitdht/src/udp/udplayer.h +++ /dev/null @@ -1,188 +0,0 @@ -/******************************************************************************* - * udp/udplayer.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2004-2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef BITDHT_UDP_LAYER_H -#define BITDHT_UDP_LAYER_H - -#include "util/bdthreads.h" -#include "util/bdnet.h" - -#include -#include -#include - -/* careful - duplicate definitions */ -//std::ostream &operator<<(std::ostream &out, const struct sockaddr_in &addr); -std::ostream &operator<<(std::ostream &out, struct sockaddr_in &addr); - -bool operator==(const struct sockaddr_in &addr, const struct sockaddr_in &addr2); -bool operator<(const struct sockaddr_in &addr, const struct sockaddr_in &addr2); - -std::string printPkt(void *d, int size); -std::string printPktOffset(unsigned int offset, void *d, unsigned int size); - - -/* UdpLayer ..... is the bottom layer which - * just sends and receives Udp packets. - */ - -class UdpReceiver -{ - public: -virtual ~UdpReceiver() {} -virtual int recvPkt(void *data, int size, struct sockaddr_in &from) = 0; -virtual int status(std::ostream &out) = 0; -}; - -class UdpPublisher -{ - public: -virtual ~UdpPublisher() {} -virtual int sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl) = 0; -}; - - -class UdpLayer: public bdThread -{ - public: - - UdpLayer(UdpReceiver *recv, struct sockaddr_in &local); -virtual ~UdpLayer() { return; } - -int reset(struct sockaddr_in &local); /* calls join, close, openSocket */ -void getDataTransferred(uint32_t &read, uint32_t &write); - -int status(std::ostream &out); - - /* setup connections */ - int closeSocket(); - int openSocket(); - - /* RsThread functions */ -virtual void run(); /* called once the thread is started */ - -void recv_loop(); /* uses callback to UdpReceiver */ - - /* Higher Level Interface */ - //int readPkt(void *data, int *size, struct sockaddr_in &from); - int sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl); - - /* monitoring / updates */ - int okay(); - int tick(); - - - /* data */ - /* internals */ - protected: - -virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from); -virtual int sendUdpPacket(const void *data, int size, const struct sockaddr_in &to); - - int setTTL(int t); - int getTTL(); - - /* low level */ - private: - -void clearDataTransferred(); - - UdpReceiver *recv; - - struct sockaddr_in laddr; /* local addr */ - - uint32_t readBytes; - uint32_t writeBytes; - - int errorState; - int sockfd; - int ttl; - bool stopThread; - - bdMutex sockMtx; -}; - - -/* For Testing - drops packets */ -class LossyUdpLayer: public UdpLayer -{ - public: - LossyUdpLayer(UdpReceiver *udpr, struct sockaddr_in &local, double frac); -virtual ~LossyUdpLayer(); - - protected: - -virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from); -virtual int sendUdpPacket(const void *data, int size, const struct sockaddr_in &to); - - double lossFraction; -}; - -class PortRange -{ - public: - PortRange(); - PortRange(uint16_t lp, uint16_t up); - - bool inRange(uint16_t port); - - uint16_t lport; - uint16_t uport; -}; - - -/* For Testing - drops packets */ -class RestrictedUdpLayer: public UdpLayer -{ - public: - RestrictedUdpLayer(UdpReceiver *udpr, struct sockaddr_in &local); -virtual ~RestrictedUdpLayer(); - -void addRestrictedPortRange(int lp, int up); - - protected: - -virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from); -virtual int sendUdpPacket(const void *data, int size, const struct sockaddr_in &to); - - std::list mLostPorts; -}; - - -/* For Testing - drops packets all packets for initial minute (simulates TTL) */ -class TimedUdpLayer: public UdpLayer -{ - public: - TimedUdpLayer(UdpReceiver *udpr, struct sockaddr_in &local); -virtual ~TimedUdpLayer(); - - protected: - -virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from); -virtual int sendUdpPacket(const void *data, int size, const struct sockaddr_in &to); - - time_t mStartTime; - bool mActive; - -}; - - -#endif diff --git a/libbitdht/src/udp/udpproxylayer.h b/libbitdht/src/udp/udpproxylayer.h deleted file mode 100644 index 939bdabf8..000000000 --- a/libbitdht/src/udp/udpproxylayer.h +++ /dev/null @@ -1,181 +0,0 @@ -/******************************************************************************* - * libbitdht/src/udp/udpproxylayer.h * - * * - * Copyright 2004 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef BITDHT_UDP_LAYER_H -#define BITDHT_UDP_LAYER_H - -#include "util/bdthreads.h" -#include "util/bdnet.h" - -#include -#include -#include - -/* careful - duplicate definitions */ -//std::ostream &operator<<(std::ostream &out, const struct sockaddr_in &addr); -std::ostream &operator<<(std::ostream &out, struct sockaddr_in &addr); - -bool operator==(const struct sockaddr_in &addr, const struct sockaddr_in &addr2); -bool operator<(const struct sockaddr_in &addr, const struct sockaddr_in &addr2); - -std::string printPkt(void *d, int size); -std::string printPktOffset(unsigned int offset, void *d, unsigned int size); - - -/* UdpLayer ..... is the bottom layer which - * just sends and receives Udp packets. - */ - -class UdpReceiver -{ - public: -virtual ~UdpReceiver() {} -virtual int recvPkt(void *data, int size, struct sockaddr_in &from) = 0; -virtual int status(std::ostream &out) = 0; -}; - -class UdpPublisher -{ - public: -virtual ~UdpPublisher() {} -virtual int sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl) = 0; -}; - - -class UdpLayer: public bdThread -{ - public: - - UdpLayer(UdpReceiver *recv, struct sockaddr_in &local); -virtual ~UdpLayer() { return; } - -int reset(struct sockaddr_in &local); /* calls join, close, openSocket */ - -int status(std::ostream &out); - - /* setup connections */ - int closeSocket(); - int openSocket(); - - /* RsThread functions */ -virtual void run(); /* called once the thread is started */ - -void recv_loop(); /* uses callback to UdpReceiver */ - - /* Higher Level Interface */ - //int readPkt(void *data, int *size, struct sockaddr_in &from); - int sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl); - - /* monitoring / updates */ - int okay(); - int tick(); - - - /* data */ - /* internals */ - protected: - -virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from); -virtual int sendUdpPacket(const void *data, int size, const struct sockaddr_in &to); - - int setTTL(int t); - int getTTL(); - - /* low level */ - private: - - UdpReceiver *recv; - - struct sockaddr_in laddr; /* local addr */ - - int errorState; - int sockfd; - int ttl; - bool stopThread; - - bdMutex sockMtx; -}; - - -/* For Testing - drops packets */ -class LossyUdpLayer: public UdpLayer -{ - public: - LossyUdpLayer(UdpReceiver *udpr, struct sockaddr_in &local, double frac); -virtual ~LossyUdpLayer(); - - protected: - -virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from); -virtual int sendUdpPacket(const void *data, int size, const struct sockaddr_in &to); - - double lossFraction; -}; - -class PortRange -{ - public: - PortRange(); - PortRange(uint16_t lp, uint16_t up); - - bool inRange(uint16_t port); - - uint16_t lport; - uint16_t uport; -}; - - -/* For Testing - drops packets */ -class RestrictedUdpLayer: public UdpLayer -{ - public: - RestrictedUdpLayer(UdpReceiver *udpr, struct sockaddr_in &local); -virtual ~RestrictedUdpLayer(); - -void addRestrictedPortRange(int lp, int up); - - protected: - -virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from); -virtual int sendUdpPacket(const void *data, int size, const struct sockaddr_in &to); - - std::list mLostPorts; -}; - - -/* For Testing - drops packets all packets for initial minute (simulates TTL) */ -class TimedUdpLayer: public UdpLayer -{ - public: - TimedUdpLayer(UdpReceiver *udpr, struct sockaddr_in &local); -virtual ~TimedUdpLayer(); - - protected: - -virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from); -virtual int sendUdpPacket(const void *data, int size, const struct sockaddr_in &to); - - time_t mStartTime; - bool mActive; - -}; - - -#endif diff --git a/libbitdht/src/udp/udpstack.cc b/libbitdht/src/udp/udpstack.cc deleted file mode 100644 index fdf8eb9cf..000000000 --- a/libbitdht/src/udp/udpstack.cc +++ /dev/null @@ -1,252 +0,0 @@ -/******************************************************************************* - * udp/udpstack.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "udp/udpstack.h" - -#include -#include -#include -#include - -#include - -/*** - * #define DEBUG_UDP_RECV 1 - ***/ - -//#define DEBUG_UDP_RECV 1 - - -UdpStack::UdpStack(struct sockaddr_in &local) - :udpLayer(NULL), laddr(local) -{ - openSocket(); - return; -} - -UdpStack::UdpStack(int testmode, struct sockaddr_in &local) - :udpLayer(NULL), laddr(local) -{ - std::cerr << "UdpStack::UdpStack() Evoked in TestMode" << std::endl; - if (testmode == UDP_TEST_LOSSY_LAYER) - { - std::cerr << "UdpStack::UdpStack() Installing LossyUdpLayer" << std::endl; - udpLayer = new LossyUdpLayer(this, laddr, UDP_TEST_LOSSY_FRAC); - } - else if (testmode == UDP_TEST_RESTRICTED_LAYER) - { - std::cerr << "UdpStack::UdpStack() Installing RestrictedUdpLayer" << std::endl; - udpLayer = new RestrictedUdpLayer(this, laddr); - } - else if (testmode == UDP_TEST_TIMED_LAYER) - { - std::cerr << "UdpStack::UdpStack() Installing TimedUdpLayer" << std::endl; - udpLayer = new TimedUdpLayer(this, laddr); - } - else - { - std::cerr << "UdpStack::UdpStack() Installing Standard UdpLayer" << std::endl; - // standard layer - openSocket(); - } - return; -} - -UdpLayer *UdpStack::getUdpLayer() /* for testing only */ -{ - return udpLayer; -} - -bool UdpStack::getLocalAddress(struct sockaddr_in &local) -{ - local = laddr; - return true; -} - -bool UdpStack::resetAddress(struct sockaddr_in &local) -{ -#ifdef DEBUG_UDP_RECV - std::cerr << "UdpStack::resetAddress(" << local << ")"; - std::cerr << std::endl; -#endif - laddr = local; - - return udpLayer->reset(local); -} - - - -/* higher level interface */ -int UdpStack::recvPkt(void *data, int size, struct sockaddr_in &from) -{ - /* print packet information */ -#ifdef DEBUG_UDP_RECV - std::cerr << "UdpStack::recvPkt(" << size << ") from: " << from; - std::cerr << std::endl; -#endif - - bdStackMutex stack(stackMtx); /********** LOCK MUTEX *********/ - - std::list::iterator it; - for(it = mReceivers.begin(); it != mReceivers.end(); it++) - { - // See if they want the packet. - if ((*it)->recvPkt(data, size, from)) - { -#ifdef DEBUG_UDP_RECV - std::cerr << "UdpStack::recvPkt(" << size << ") from: " << from; - std::cerr << std::endl; -#endif - break; - } - } - return 1; -} - -int UdpStack::sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl) -{ - /* print packet information */ -#ifdef DEBUG_UDP_RECV - std::cerr << "UdpStack::sendPkt(" << size << ") ttl: " << ttl; - std::cerr << " to: " << to; - std::cerr << std::endl; -#endif - - /* send to udpLayer */ - return udpLayer->sendPkt(data, size, to, ttl); -} - -int UdpStack::status(std::ostream &out) -{ - { - bdStackMutex stack(stackMtx); /********** LOCK MUTEX *********/ - - out << "UdpStack::status()" << std::endl; - out << "localaddr: " << laddr << std::endl; - out << "UdpStack::SubReceivers:" << std::endl; - std::list::iterator it; - int i = 0; - for(it = mReceivers.begin(); it != mReceivers.end(); it++, i++) - { - out << "\tReceiver " << i << " --------------------" << std::endl; - (*it)->status(out); - } - out << "--------------------" << std::endl; - out << std::endl; - } - - udpLayer->status(out); - - return 1; -} - -/* setup connections */ -int UdpStack::openSocket() -{ - udpLayer = new UdpLayer(this, laddr); - return 1; -} - -/* monitoring / updates */ -int UdpStack::okay() -{ - return udpLayer->okay(); -} - -int UdpStack::close() -{ - /* TODO */ - return 1; -} - - - /* add a TCPonUDP stream */ -int UdpStack::addReceiver(UdpReceiver *recv) -{ - bdStackMutex stack(stackMtx); /********** LOCK MUTEX *********/ - - /* check for duplicate */ - std::list::iterator it; - it = std::find(mReceivers.begin(), mReceivers.end(), recv); - if (it == mReceivers.end()) - { - mReceivers.push_back(recv); - return 1; - } - - /* otherwise its already there! */ - -#ifdef DEBUG_UDP_RECV - std::cerr << "UdpStack::addReceiver() Recv already exists!" << std::endl; - std::cerr << "UdpStack::addReceiver() ERROR" << std::endl; -#endif - - return 0; -} - -int UdpStack::removeReceiver(UdpReceiver *recv) -{ - bdStackMutex stack(stackMtx); /********** LOCK MUTEX *********/ - - /* check for duplicate */ - std::list::iterator it; - it = std::find(mReceivers.begin(), mReceivers.end(), recv); - if (it != mReceivers.end()) - { - mReceivers.erase(it); - return 1; - } - - /* otherwise its not there! */ - -#ifdef DEBUG_UDP_RECV - std::cerr << "UdpStack::removeReceiver() Recv dont exist!" << std::endl; - std::cerr << "UdpStack::removeReceiver() ERROR" << std::endl; -#endif - - return 0; -} - - - -/*****************************************************************************************/ - -UdpSubReceiver::UdpSubReceiver(UdpPublisher *pub) - :mPublisher(pub) -{ - return; -} - -int UdpSubReceiver::sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl) -{ - /* print packet information */ -#ifdef DEBUG_UDP_RECV - std::cerr << "UdpSubReceiver::sendPkt(" << size << ") ttl: " << ttl; - std::cerr << " to: " << to; - std::cerr << std::endl; -#endif - - /* send to udpLayer */ - return mPublisher->sendPkt(data, size, to, ttl); -} - - diff --git a/libbitdht/src/udp/udpstack.h b/libbitdht/src/udp/udpstack.h deleted file mode 100644 index 31b8ec324..000000000 --- a/libbitdht/src/udp/udpstack.h +++ /dev/null @@ -1,114 +0,0 @@ -/******************************************************************************* - * udp/udpstack.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef BITDHT_UDP_STACK_RECEIVER_H -#define BITDHT_UDP_STACK_RECEIVER_H - -#include "util/bdthreads.h" -#include "util/bdnet.h" - -#include -#include -#include - -#include -#include - -#include "udp/udplayer.h" - -/* UdpStackReceiver is a Generic Receiver of info from a UdpLayer class. - * it provides a UdpReceiver class, and accepts a stack of UdpReceivers, - * which will be iterated through (in-order) until someone accepts the packet. - * - * It is important to order these Receivers correctly! - * - * This infact becomes the holder of the UdpLayer, and all controls - * go through the StackReceiver. - */ - -class UdpSubReceiver: public UdpReceiver -{ - public: - UdpSubReceiver(UdpPublisher *pub); - - /* calls mPublisher->sendPkt */ -virtual int sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl); - /* callback for recved data (overloaded from UdpReceiver) */ -//virtual int recvPkt(void *data, int size, struct sockaddr_in &from) = 0; - - UdpPublisher *mPublisher; -}; - - -#define UDP_TEST_LOSSY_LAYER 1 -#define UDP_TEST_RESTRICTED_LAYER 2 -#define UDP_TEST_TIMED_LAYER 3 - -#define UDP_TEST_LOSSY_FRAC (0.10) - -class UdpStack: public UdpReceiver, public UdpPublisher -{ - public: - - UdpStack(struct sockaddr_in &local); - UdpStack(int testmode, struct sockaddr_in &local); -virtual ~UdpStack() { return; } - -UdpLayer *getUdpLayer(); /* for testing only */ - -bool getLocalAddress(struct sockaddr_in &local); -bool resetAddress(struct sockaddr_in &local); - - - /* add in a receiver */ -int addReceiver(UdpReceiver *recv); -int removeReceiver(UdpReceiver *recv); - - /* Packet IO */ - /* pass-through send packets */ -virtual int sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl); - /* callback for recved data (overloaded from UdpReceiver) */ - -virtual int recvPkt(void *data, int size, struct sockaddr_in &from); - -int status(std::ostream &out); - - /* setup connections */ - int openSocket(); - - /* monitoring / updates */ - int okay(); -// int tick(); - - int close(); - - private: - - UdpLayer *udpLayer; - - bdMutex stackMtx; /* for all class data (below) */ - - struct sockaddr_in laddr; /* local addr */ - - std::list mReceivers; -}; - -#endif diff --git a/libbitdht/src/use_libbitdht.pri b/libbitdht/src/use_libbitdht.pri deleted file mode 100644 index 5758393af..000000000 --- a/libbitdht/src/use_libbitdht.pri +++ /dev/null @@ -1,25 +0,0 @@ -# RetroShare main qmake build script -# -# Copyright (C) 2004-2019, Retroshare Team -# -# This program is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. -# See the GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with this program. If not, see . -# -# SPDX-FileCopyrightText: Retroshare Team -# SPDX-License-Identifier: LGPL-3.0-or-later - -DEPENDPATH *= $$system_path($$clean_path($${PWD}/../../libbitdht/src)) -INCLUDEPATH *= $$system_path($$clean_path($${PWD}/../../libbitdht/src)) -LIBS *= -L$$system_path($$clean_path($${OUT_PWD}/../../libbitdht/src/lib/)) -lbitdht - -!equals(TARGET, bitdht):PRE_TARGETDEPS *= $$system_path($$clean_path($${OUT_PWD}/../../libbitdht/src/lib/libbitdht.a)) diff --git a/libbitdht/src/util/bdbloom.cc b/libbitdht/src/util/bdbloom.cc deleted file mode 100644 index 739e2c793..000000000 --- a/libbitdht/src/util/bdbloom.cc +++ /dev/null @@ -1,402 +0,0 @@ -/******************************************************************************* - * util/bdbloom.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "util/bdbloom.h" -#include "util/bdstring.h" - -#include -#include - -#if defined(_WIN32) || defined(__MINGW32__) -#include -#endif - -/* Bloom Filter implementation */ - - -bloomFilter::bloomFilter(int m, int k) -{ - mBits.resize(m); - mHashFns.resize(k); - - mFilterBits = m; - mNoHashs = k; - mNoElements = 0; - - int i; - for(i = 0; i < m; i++) - { - mBits[i] = 0; - } - - for(i = 0; i < k; i++) - { - mHashFns[i] = NULL; - } - -} - -uint8_t convertCharToUint8(char ch1, char ch2) -{ - uint8_t value1 = 0; - uint8_t value2 = 0; - - /* do char1 */ - if (ch1 >= '0' && ch1 <= '9') - value1 = (ch1 - '0'); - else if (ch1 >= 'A' && ch1 <= 'F') - value1 = (ch1 - 'A' + 10); - else if (ch1 >= 'a' && ch1 <= 'f') - value1 = (ch1 - 'a' + 10); - - /* do char2 */ - if (ch2 >= '0' && ch2 <= '9') - value2 = (ch2 - '0'); - else if (ch2 >= 'A' && ch2 <= 'F') - value2 = (ch2 - 'A' + 10); - else if (ch2 >= 'a' && ch2 <= 'f') - value2 = (ch2 - 'a' + 10); - - uint8_t output = (value1 << 4) + value2; - return output; -} - -#define BITS_PER_BYTE (8) - -int bloomFilter::setFilterBits(const std::string &hex) -{ - uint32_t bytes = (mFilterBits / BITS_PER_BYTE); - if (mFilterBits % BITS_PER_BYTE) - { - bytes++; - } - - if (hex.size() < bytes * 2) - { - return 0; - } - - // convert to binary array. - uint8_t *tmparray = (uint8_t *) malloc(bytes); - - if(tmparray == NULL) - { - std::cerr << "(EE) Error. Cannot allocate memory for " << bytes << " bytes in " << __PRETTY_FUNCTION__ << std::endl; - return 0; - } - - uint32_t i = 0; - - for(i = 0; i < bytes; i++) - { - tmparray[i] = convertCharToUint8(hex[2 * i], hex[2 * i + 1]); - } - - - for(i = 0; i < mFilterBits; i++) - { - int byte = i / BITS_PER_BYTE; - int bit = i % BITS_PER_BYTE; - uint8_t value = (tmparray[byte] & (1 << bit)); - - if (value) - { - mBits[i] = 1; - } - else - { - mBits[i] = 0; - } - } - - free(tmparray); - return 1; -} - -std::string bloomFilter::getFilter() -{ - /* extract filter as a hex string */ - int bytes = (mFilterBits / BITS_PER_BYTE); - if (mFilterBits % BITS_PER_BYTE) - { - bytes++; - } - - if (bytes==0) - { - std::cerr << "(EE) Error. Cannot allocate memory for 0 byte in " << __PRETTY_FUNCTION__ << std::endl; - return std::string(); - } - // convert to binary array. - uint8_t *tmparray = (uint8_t *) malloc(bytes); - - if(tmparray == NULL) - { - std::cerr << "(EE) Error. Cannot allocate memory for " << bytes << " bytes in " << __PRETTY_FUNCTION__ << std::endl; - return std::string(); - } - - int i,j; - - for(i = 0; i < bytes; i++) - { - tmparray[i] = 0; - for(j = 0; j < BITS_PER_BYTE; j++) - { - int bit = i * BITS_PER_BYTE + j; - if (mBits[bit]) - { - tmparray[i] |= (1 << j); - } - } - } - - std::string out; - for(int i = 0; i < bytes; i++) - { - bd_sprintf_append(out, "%02lx", (uint32_t) (tmparray)[i]); - } - - free(tmparray); - - return out; -} - -void bloomFilter::setBit(int bit) -{ - mBits[bit] = 1; - -} - - -bool bloomFilter::isBitSet(int bit) -{ - return (mBits[bit] == 1); -} - -uint32_t bloomFilter::filterBits() -{ - return mFilterBits; -} - -uint32_t bloomFilter::countBits() -{ - int count = 0; - uint32_t i; - for(i = 0; i < mFilterBits; i++) - { - if (mBits[i]) - { - count++; - } - } - return count; -} - - -void bloomFilter::printFilter(std::ostream &out) -{ - out << "bloomFilter: m = " << mFilterBits; - out << " k = " << mNoHashs; - out << " n = " << mNoElements; - out << std::endl; - - out << "BITS: "; - uint32_t i; - for(i = 0; i < mFilterBits; i++) - { - if ((i > 0) && (i % 32 == 0)) - { - out << std::endl; - out << "BITS: "; - } - if (mBits[i]) - { - out << "1"; - } - else - { - out << "0"; - } - } - out << std::endl; - out << "STR: " << getFilter(); - out << std::endl; -} - -void bloomFilter::setHashFunction(int idx, uint32_t (*hashfn)(const std::string &)) -{ - mHashFns[idx] = hashfn; -} - -void bloomFilter::add(const std::string &hex) -{ - uint32_t (*hashfn)(const std::string &); - uint32_t i; - for(i = 0; i < mNoHashs; i++) - { - hashfn = mHashFns[i]; - - int bit = hashfn(hex); - - setBit(bit); - } - - mNoElements++; - -} - -bool bloomFilter::test(const std::string &hex) -{ - uint32_t (*hashfn)(const std::string &); - uint32_t i; - for(i = 0; i < mNoHashs; i++) - { - hashfn = mHashFns[i]; - - int bit = hashfn(hex); - - if (!isBitSet(bit)) - { - return false; - } - } - return true; -} - -uint32_t getFirst10BitsAsNumber(const std::string &input) -{ - if (input.size() < 8) - { - std::cerr << "getFirst10BitsAsNumber() ERROR Size too small!"; - std::cerr << std::endl; - return 0; - } - - uint8_t data[4]; - - data[0] = convertCharToUint8(input[0], input[1]); - data[1] = convertCharToUint8(input[2], input[3]); - data[2] = convertCharToUint8(input[4], input[5]); - data[3] = convertCharToUint8(input[6], input[7]); - - uint32_t val = ((data[0] & 0xff) << 2) + ((data[1] & 0xc0) >> 6); - -#ifdef DEBUG_BLOOM - std::cerr << "getFirst10BitsAsNumber() input: " << input; - std::cerr << std::endl; - std::cerr << "getFirst10BitsAsNumber() "; - std::cerr << " data[0]: " << std::hex << (uint32_t) data[0]; - std::cerr << " data[1]: " << (uint32_t) data[1]; - std::cerr << " data[2]: " << (uint32_t) data[2]; - std::cerr << " data[3]: " << (uint32_t) data[3]; - std::cerr << " val: " << std::dec << (uint32_t) val; - std::cerr << std::endl; -#endif - - return val; -} - -uint32_t getSecond10BitsAsNumber(const std::string &input) -{ - if (input.size() < 8) - { - std::cerr << "getSecond10BitsAsNumber() ERROR Size too small!"; - std::cerr << std::endl; - return 0; - } - - uint8_t data[4]; - - data[0] = convertCharToUint8(input[0], input[1]); - data[1] = convertCharToUint8(input[2], input[3]); - data[2] = convertCharToUint8(input[4], input[5]); - data[3] = convertCharToUint8(input[6], input[7]); - - uint32_t val = ((data[1] & 0x3f) << 4) + ((data[2] & 0xf0) >> 4); - -#ifdef DEBUG_BLOOM - std::cerr << "getSecond10BitsAsNumber() input: " << input; - std::cerr << std::endl; - std::cerr << "getSecond10BitsAsNumber() "; - std::cerr << " data[0]: " << std::hex << (uint32_t) data[0]; - std::cerr << " data[1]: " << (uint32_t) data[1]; - std::cerr << " data[2]: " << (uint32_t) data[2]; - std::cerr << " data[3]: " << (uint32_t) data[3]; - std::cerr << " val: " << std::dec << (uint32_t) val; - std::cerr << std::endl; -#endif - - return val; -} - - -uint32_t getMid10BitsAsNumber(const std::string &input) -{ - if (input.size() < 8) - { - std::cerr << "getMid10BitsAsNumber() ERROR Size too small!"; - std::cerr << std::endl; - return 0; - } - - uint8_t data[4]; - - data[0] = convertCharToUint8(input[0], input[1]); - data[1] = convertCharToUint8(input[2], input[3]); - data[2] = convertCharToUint8(input[4], input[5]); - data[3] = convertCharToUint8(input[6], input[7]); - - uint32_t val = ((data[0] & 0x07) << 7) + ((data[1] & 0x7f) >> 1); - -#ifdef DEBUG_BLOOM - std::cerr << "getMid10BitsAsNumber() input: " << input; - std::cerr << std::endl; - std::cerr << "getMid10BitsAsNumber() "; - std::cerr << " data[0]: " << std::hex << (uint32_t) data[0]; - std::cerr << " data[1]: " << (uint32_t) data[1]; - std::cerr << " data[2]: " << (uint32_t) data[2]; - std::cerr << " data[3]: " << (uint32_t) data[3]; - std::cerr << " val: " << std::dec << (uint32_t) val; - std::cerr << std::endl; -#endif - - return val; -} - - -#define BDFILTER_M 1024 -#define BDFILTER_K 3 - -bdBloom::bdBloom() - :bloomFilter(BDFILTER_M, BDFILTER_K) -{ - /* set the fns. */ - setHashFunction(0, getFirst10BitsAsNumber); - setHashFunction(1, getSecond10BitsAsNumber); - setHashFunction(2, getMid10BitsAsNumber); -} - - - - - diff --git a/libbitdht/src/util/bdbloom.h b/libbitdht/src/util/bdbloom.h deleted file mode 100644 index 8ffd13f1e..000000000 --- a/libbitdht/src/util/bdbloom.h +++ /dev/null @@ -1,74 +0,0 @@ -/******************************************************************************* - * util/bdbloom.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef BITDHT_BLOOM_H -#define BITDHT_BLOOM_H - -#include -#include - -#include -#include - - -class bloomFilter -{ - public: - - bloomFilter(int m, int k); - -int setFilterBits(const std::string &hex); -std::string getFilter(); - -void printFilter(std::ostream &out); - -bool test(const std::string &hex); // takes first m bits. -void add(const std::string &hex); -uint32_t countBits(); -uint32_t filterBits(); - - protected: -void setHashFunction(int idx, uint32_t (*hashfn)(const std::string &)); - - private: -void setBit(int bit); -bool isBitSet(int bit); - - std::vector mBits; - std::vector mHashFns; - - uint32_t mFilterBits; - uint32_t mNoHashs; - uint32_t mNoElements; -}; - - -/* our specific implementation */ -class bdBloom: public bloomFilter -{ - public: - - bdBloom(); -}; - - -#endif - diff --git a/libbitdht/src/util/bdfile.cc b/libbitdht/src/util/bdfile.cc deleted file mode 100644 index bcd2eb64b..000000000 --- a/libbitdht/src/util/bdfile.cc +++ /dev/null @@ -1,75 +0,0 @@ -/******************************************************************************* - * util/bdfile.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifdef WIN32 -#include -#endif - -#include -#include -#include -#include "bdfile.h" - -namespace librs { - namespace util { - bool ConvertUtf8ToUtf16(const std::string& source, std::wstring& dest) ; - } -} - -bool bdFile::renameFile(const std::string& from, const std::string& to) -{ - int loops = 0; - -#ifdef WIN32 - std::wstring f; - librs::util::ConvertUtf8ToUtf16(from, f); - std::wstring t; - librs::util::ConvertUtf8ToUtf16(to, t); - - while (!MoveFileEx(f.c_str(), t.c_str(), MOVEFILE_REPLACE_EXISTING)) -#else - std::string f(from),t(to) ; - - while (rename(from.c_str(), to.c_str()) < 0) -#endif - { -#ifdef WIN32 - if (GetLastError() != ERROR_ACCESS_DENIED) -#else - if (errno != EACCES) -#endif - /* set errno? */ - return false ; -#ifdef WIN32 - Sleep(100000); /* us */ -#else - usleep(100000); /* us */ -#endif - - if (loops >= 30) - return false ; - - loops++; - } - - return true ; -} - diff --git a/libbitdht/src/util/bdfile.h b/libbitdht/src/util/bdfile.h deleted file mode 100644 index 5228f986a..000000000 --- a/libbitdht/src/util/bdfile.h +++ /dev/null @@ -1,30 +0,0 @@ -/******************************************************************************* - * util/bdfile.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include - -class bdFile -{ - public: - static bool renameFile(const std::string& from, const std::string& to) ; -} ; diff --git a/libbitdht/src/util/bdnet.cc b/libbitdht/src/util/bdnet.cc deleted file mode 100644 index ba8c33553..000000000 --- a/libbitdht/src/util/bdnet.cc +++ /dev/null @@ -1,363 +0,0 @@ -/******************************************************************************* - * util/bdnet.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "bdnet.h" -#include "bdstring.h" - -#include -#include -#include - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#if defined(_WIN32) || defined(__MINGW32__) - -//#define BDNET_DEBUG - -/* error handling */ -int bdnet_int_errno; - -int bdnet_errno() -{ - return bdnet_int_errno; -} - -int bdnet_init() -{ - std::cerr << "bdnet_init()" << std::endl; - bdnet_int_errno = 0; - - // Windows Networking Init. - WORD wVerReq = MAKEWORD(2,2); - WSADATA wsaData; - - if (0 != WSAStartup(wVerReq, &wsaData)) - { - std::cerr << "Failed to Startup Windows Networking"; - std::cerr << std::endl; - } - else - { - std::cerr << "Started Windows Networking"; - std::cerr << std::endl; - } - - return 0; -} - -/* check if we can modify the TTL on a UDP packet */ -int bdnet_checkTTL(int fd) -{ - std::cerr << "bdnet_checkTTL()" << std::endl; - int optlen = 4; - char optval[optlen]; - - int ret = getsockopt(fd, IPPROTO_IP, IP_TTL, optval, &optlen); - //int ret = getsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, optval, &optlen); - if (ret == SOCKET_ERROR) - { - ret = -1; - bdnet_int_errno = bdnet_w2u_errno(WSAGetLastError()); - std::cerr << "bdnet_checkTTL() Failed!"; - std::cerr << std::endl; - } - else - { - std::cerr << "bdnet_checkTTL() :"; - std::cerr << (int) optval[0] << ":"; - std::cerr << (int) optval[1] << ":"; - std::cerr << (int) optval[2] << ":"; - std::cerr << (int) optval[3] << ": RET: "; - std::cerr << ret << ":"; - std::cerr << std::endl; - } - return ret; -} - -int bdnet_close(int fd) -{ - std::cerr << "bdnet_close()" << std::endl; - return closesocket(fd); -} - -int bdnet_socket(int domain, int type, int protocol) -{ - int osock = socket(domain, type, protocol); - std::cerr << "bdnet_socket()" << std::endl; - - if ((unsigned) osock == INVALID_SOCKET) - { - // Invalidate socket Unix style. - osock = -1; - bdnet_int_errno = bdnet_w2u_errno(WSAGetLastError()); - } - bdnet_checkTTL(osock); - return osock; -} - -int bdnet_bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen) -{ - std::cerr << "bdnet_bind()" << std::endl; - int ret = bind(sockfd,my_addr,addrlen); - if (ret != 0) - { - /* store unix-style error - */ - - ret = -1; - bdnet_int_errno = bdnet_w2u_errno(WSAGetLastError()); - } - return ret; -} - -int bdnet_fcntl(int fd, int cmd, long arg) -{ - int ret; - - unsigned long int on = 1; - std::cerr << "bdnet_fcntl()" << std::endl; - - /* can only do NONBLOCK at the moment */ - if ((cmd != F_SETFL) || (arg != O_NONBLOCK)) - { - std::cerr << "bdnet_fcntl() limited to fcntl(fd, F_SETFL, O_NONBLOCK)"; - std::cerr << std::endl; - bdnet_int_errno = EOPNOTSUPP; - return -1; - } - - ret = ioctlsocket(fd, FIONBIO, &on); - - if (ret != 0) - { - /* store unix-style error - */ - - ret = -1; - bdnet_int_errno = bdnet_w2u_errno(WSAGetLastError()); - } - return ret; -} - -int bdnet_setsockopt(int s, int level, int optname, - const void *optval, socklen_t optlen) -{ - std::cerr << "bdnet_setsockopt() val:" << *((int *) optval) << std::endl; - std::cerr << "bdnet_setsockopt() len:" << optlen << std::endl; - if ((level != IPPROTO_IP) || (optname != IP_TTL)) - { - std::cerr << "bdnet_setsockopt() limited to "; - std::cerr << "setsockopt(fd, IPPROTO_IP, IP_TTL, ....)"; - std::cerr << std::endl; - bdnet_int_errno = EOPNOTSUPP; - return -1; - } - - int ret = setsockopt(s, level, optname, (const char *) optval, optlen); - //int ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (const char *) optval, optlen); - if (ret == SOCKET_ERROR) - { - ret = -1; - bdnet_int_errno = bdnet_w2u_errno(WSAGetLastError()); - } - bdnet_checkTTL(s); - return ret; -} - -ssize_t bdnet_recvfrom(int s, void *buf, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen) -{ -#ifdef BDNET_DEBUG - std::cerr << "bdnet_recvfrom()" << std::endl; -#endif - int ret = recvfrom(s, (char *) buf, len, flags, from, fromlen); - if (ret == SOCKET_ERROR) - { - ret = -1; - bdnet_int_errno = bdnet_w2u_errno(WSAGetLastError()); - } - return ret; -} - -ssize_t bdnet_sendto(int s, const void *buf, size_t len, int flags, - const struct sockaddr *to, socklen_t tolen) -{ -#ifdef BDNET_DEBUG - std::cerr << "bdnet_sendto()" << std::endl; -#endif - int ret = sendto(s, (const char *) buf, len, flags, to, tolen); - if (ret == SOCKET_ERROR) - { - ret = -1; - bdnet_int_errno = bdnet_w2u_errno(WSAGetLastError()); - } - return ret; -} - -int bdnet_w2u_errno(int err) -{ - /* switch */ - std::cerr << "tou_net_w2u_errno(" << err << ")" << std::endl; - switch(err) - { - case WSAEINPROGRESS: - return EINPROGRESS; - break; - case WSAEWOULDBLOCK: - return EINPROGRESS; - break; - case WSAENETUNREACH: - return ENETUNREACH; - break; - case WSAETIMEDOUT: - return ETIMEDOUT; - break; - case WSAEHOSTDOWN: - return EHOSTDOWN; - break; - case WSAECONNREFUSED: - return ECONNREFUSED; - break; - case WSAEADDRINUSE: - return EADDRINUSE; - break; - case WSAEUSERS: - return EUSERS; - break; - /* This one is returned for UDP recvfrom, when nothing there - * but not a real error... translate into EINPROGRESS - */ - case WSAECONNRESET: - std::cerr << "tou_net_w2u_errno(" << err << ")"; - std::cerr << " = WSAECONNRESET ---> EINPROGRESS"; - std::cerr << std::endl; - return EINPROGRESS; - break; - /*** - * - case WSAECONNRESET: - return ECONNRESET; - break; - * - ***/ - - case WSANOTINITIALISED: - std::cerr << "tou_net_w2u_errno(" << err << ") WSANOTINITIALISED. Fix Your Code!"; - std::cerr << std::endl; - break; - default: - std::cerr << "tou_net_w2u_errno(" << err << ") Unknown"; - std::cerr << std::endl; - break; - } - - return ECONNREFUSED; /* sensible default? */ -} - -int bdnet_inet_aton(const char *name, struct in_addr *addr) -{ - return (((*addr).s_addr = inet_addr(name)) != INADDR_NONE); -} - -#ifndef __MINGW64_VERSION_MAJOR -int sleep(unsigned int sec) -{ - Sleep(sec * 1000); - return 0; -} -#endif - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#else // UNIX - -/* Unix Version is easy -> just call the unix fn - */ - -#include /* for close definition */ - -/* the universal interface */ -int bdnet_init() { return 0; } -int bdnet_errno() { return errno; } - - -/* check if we can modify the TTL on a UDP packet */ -int bdnet_checkTTL(int /*fd*/) { return 1;} - - -int bdnet_inet_aton(const char *name, struct in_addr *addr) -{ - return inet_aton(name, addr); -} - -int bdnet_close(int fd) { return close(fd); } - -int bdnet_socket(int domain, int type, int protocol) -{ - return socket(domain, type, protocol); -} - -int bdnet_bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen) -{ - return bind(sockfd,my_addr,addrlen); -} - -int bdnet_fcntl(int fd, int cmd, long arg) -{ - return fcntl(fd, cmd, arg); -} - -int bdnet_setsockopt(int s, int level, int optname, - const void *optval, socklen_t optlen) -{ - return setsockopt(s, level, optname, optval, optlen); -} - -ssize_t bdnet_recvfrom(int s, void *buf, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen) -{ - return recvfrom(s, buf, len, flags, from, fromlen); -} - -ssize_t bdnet_sendto(int s, const void *buf, size_t len, int flags, - const struct sockaddr *to, socklen_t tolen) -{ - return sendto(s, buf, len, flags, to, tolen); -} - - -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - -void bdsockaddr_clear(struct sockaddr_in *addr) -{ - memset(addr, 0, sizeof(*addr)); -} - -/* thread-safe version of inet_ntoa */ - -std::string bdnet_inet_ntoa(struct in_addr in) -{ - std::string str; - uint8_t *bytes = (uint8_t *) &(in.s_addr); - bd_sprintf(str, "%u.%u.%u.%u", (int) bytes[0], (int) bytes[1], (int) bytes[2], (int) bytes[3]); - return str; -} diff --git a/libbitdht/src/util/bdnet.h b/libbitdht/src/util/bdnet.h deleted file mode 100644 index 89ecfa710..000000000 --- a/libbitdht/src/util/bdnet.h +++ /dev/null @@ -1,174 +0,0 @@ -/******************************************************************************* - * util/bdnet.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef BITDHT_UNIVERSAL_NETWORK_HEADER -#define BITDHT_UNIVERSAL_NETWORK_HEADER - -#include -#include - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#if defined(_WIN32) || defined(__MINGW32__) - -#include - -#include /* for ssize_t */ -typedef uint32_t in_addr_t; - -#else // UNIX - -#include -#include -#include -#include - -#include -#include - -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - - -/* C Interface */ -#ifdef __cplusplus -extern "C" { -#endif - -/******* - * This defines a (unix-like) universal networking layer - * that should function on both windows and unix. (C - interface) - * - * This is of course only a subset of the full interface. - * functions required are: - * - * int bdnet_close(int fd); - * int bdnet_socket(int domain, int type, int protocol); - * int bdnet_bind(int sockfd, const struct sockaddr *my_addr, - * socklen_t addrlen); - * int bdnet_fcntl(int fd, int cmd, long arg); - * int bdnet_setsockopt(int s, int level, int optname, - * const void *optval, socklen_t optlen); - * ssize_t bdnet_recvfrom(int s, void *buf, size_t len, int flags, - * struct sockaddr *from, socklen_t *fromlen); - * ssize_t bdnet_sendto(int s, const void *buf, size_t len, int flags, - * const struct sockaddr *to, socklen_t tolen); - * - * There are some non-standard ones as well: - * int bdnet_errno(); for internal networking errors - * int bdnet_init(); required for windows - * int bdnet_checkTTL(); a check if we can modify the ttl - */ - - -/* the universal interface */ -int bdnet_errno(); /* for internal networking errors */ -int bdnet_init(); /* required for windows */ -int bdnet_close(int fd); -int bdnet_socket(int domain, int type, int protocol); -int bdnet_bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen); -int bdnet_fcntl(int fd, int cmd, long arg); -int bdnet_setsockopt(int s, int level, int optname, - const void *optval, socklen_t optlen); -ssize_t bdnet_recvfrom(int s, void *buf, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen); -ssize_t bdnet_sendto(int s, const void *buf, size_t len, int flags, - const struct sockaddr *to, socklen_t tolen); - -/* address filling */ -int bdnet_inet_aton(const char *name, struct in_addr *addr); -/* check if we can modify the TTL on a UDP packet */ -int bdnet_checkTTL(int fd); - -void bdsockaddr_clear(struct sockaddr_in *addr); - -/* Extra stuff to declare for windows error handling (mimics unix errno) - */ - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#if defined(_WIN32) || defined(__MINGW32__) - -// Some Network functions that are missing from windows. -//in_addr_t inet_netof(struct in_addr addr); -//in_addr_t inet_network(char *inet_name); -//int inet_aton(const char *name, struct in_addr *addr); - - -// definitions for fcntl (NON_BLOCK) (random?) -#define F_SETFL 0x1010 -#define O_NONBLOCK 0x0100 - -// definitions for setsockopt (TTL) (random?) -//#define IPPROTO_IP 0x0011 -//#define IP_TTL 0x0110 - -/* define the Unix Error Codes that we use... - * NB. we should make the same, but not necessary - */ - -#define EAGAIN 11 -#define EUSERS 87 - -#define EHOSTDOWN 112 - -#ifndef __MINGW64_VERSION_MAJOR -#define EWOULDBLOCK EAGAIN - -#define ENOTSOCK 88 - -#define EOPNOTSUPP 95 - -#define EADDRINUSE 98 -#define EADDRNOTAVAIL 99 -#define ENETDOWN 100 -#define ENETUNREACH 101 - -#define ECONNRESET 104 - -#define ETIMEDOUT 10060 // value from pthread.h -#define ECONNREFUSED 111 -#define EHOSTUNREACH 113 -#define EALREADY 114 -#define EINPROGRESS 115 -#endif - -int bdnet_w2u_errno(int error); - -/* also put the sleep commands in here (where else to go) - * ms uses millisecs. - * void Sleep(int ms); - */ -#ifndef __MINGW64_VERSION_MAJOR -int sleep(unsigned int sec); -#endif - -#endif // END of WINDOWS defines. -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - -#ifdef __cplusplus -} /* C Interface */ -#endif - -/* thread-safe version of inet_ntoa */ -std::string bdnet_inet_ntoa(struct in_addr in); - -#endif /* BITDHT_UNIVERSAL_NETWORK_HEADER */ diff --git a/libbitdht/src/util/bdrandom.cc b/libbitdht/src/util/bdrandom.cc deleted file mode 100644 index 93a0352dd..000000000 --- a/libbitdht/src/util/bdrandom.cc +++ /dev/null @@ -1,120 +0,0 @@ -/******************************************************************************* - * util/bdrandom.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright (C) 2010 Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include -#include -#include -#include -#include "util/bdrandom.h" - -uint32_t bdRandom::index = 0 ; -std::vector bdRandom::MT(bdRandom::N,0u) ; -bdMutex bdRandom::rndMtx ; - -#if (defined(_WIN32) || defined(__MINGW32__)) && !defined(WIN_PTHREADS_H) -static bool auto_seed = bdRandom::seed( (time(NULL) + ((uint32_t) pthread_self().p)*0x1293fe)^0x18e34a12 ) ; -#else - #ifdef __APPLE__ - static bool auto_seed = bdRandom::seed( (time(NULL) + pthread_mach_thread_np(pthread_self())*0x1293fe + (getpid()^0x113ef76b))^0x18e34a12 ) ; - #elif defined(__FreeBSD__) || (__HAIKU__) - // since this is completely insecure anyway, just kludge for now - static bool auto_seed = bdRandom::seed(time(NULL)); - #elif defined(__OpenBSD__) - static bool auto_seed = bdRandom::seed(arc4random()); - #else - static bool auto_seed = bdRandom::seed( (time(NULL) + pthread_self()*0x1293fe + (getpid()^0x113ef76b))^0x18e34a12 ) ; - #endif -#endif -bool bdRandom::seed(uint32_t s) -{ - bdStackMutex mtx(rndMtx) ; - - MT.resize(N,0) ; // because MT might not be already resized - - uint32_t j ; - MT[0]= s & 0xffffffffUL; - for (j=1; j> 30)) + j) & 0xffffffffUL ; - - return true ; -} - -void bdRandom::locked_next_state() -{ - for(uint32_t i=0;i> 1) ; - - if((y & 1) == 1) - MT[i] = MT[i] ^ 0x9908b0df ; - } - index = 0 ; -} - -uint32_t bdRandom::random_u32() -{ - uint32_t y; - - { - bdStackMutex mtx(rndMtx) ; - - y = MT[index++] ; - - if(index == N) - locked_next_state(); - } - - // Tempering - y ^= (y >> 11); - y ^= (y << 7 ) & 0x9d2c5680UL; - y ^= (y << 15) & 0xefc60000UL; - y ^= (y >> 18); - - return y; -} - -uint64_t bdRandom::random_u64() -{ - return ((uint64_t)random_u32() << 32ul) + random_u32() ; -} - -float bdRandom::random_f32() -{ - return random_u32() / (float)(~(uint32_t)0) ; -} - -double bdRandom::random_f64() -{ - return random_u64() / (double)(~(uint64_t)0) ; -} - -std::string bdRandom::random_alphaNumericString(uint32_t len) -{ - std::string s = "" ; - - for(uint32_t i=0;i * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef BITDHT_UTILS_BDRANDOM_H -#define BITDHT_UTILS_BDRANDOM_H - -/* This Source Code is basically a direct copy of libretroshare's RsRandom. - * the function names have just been renamed. drbob - */ - -// bdRandom contains a random number generator that is -// - thread safe -// - system independant -// - fast -// - NOT CRYPTOGRAPHICALLY SAFE -// - DO NOT USE FOR ANYTHING REQUIRING STRONG UNPREDICTABLE RANDOMNESS -// -// The implementation is adapted from the Mersenne Twister page of Wikipedia. -// -// http://en.wikipedia.org/wiki/Mersenne_twister - -// FIXME(ben): MT is not cryptographically safe. - -#include -#include "util/bdthreads.h" - -class bdRandom -{ - public: - static uint32_t random_u32() ; - static uint64_t random_u64() ; - static float random_f32() ; - static double random_f64() ; - - static bool seed(uint32_t s) ; - - static std::string random_alphaNumericString(uint32_t length) ; - - private: - static bdMutex rndMtx ; - - static const uint32_t N = 624; - static const uint32_t M = 397; - - static const uint32_t MATRIX_A = 0x9908b0dfUL; - static const uint32_t UMASK = 0x80000000UL; - static const uint32_t LMASK = 0x7fffffffUL; - - static void locked_next_state() ; - static uint32_t index ; - static std::vector MT ; -}; - -#endif diff --git a/libbitdht/src/util/bdstring.cc b/libbitdht/src/util/bdstring.cc deleted file mode 100644 index 3808e0c68..000000000 --- a/libbitdht/src/util/bdstring.cc +++ /dev/null @@ -1,97 +0,0 @@ -/******************************************************************************* - * util/bdstring.h * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright (C) 2010 Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "bdstring.h" - -#ifdef _WIN32 -#include -#include -#else -#include -#include -#endif -#include - -#ifdef _WIN32 -// asprintf() and vasprintf() are missing in Win32 -static int vasprintf(char **sptr, const char *fmt, va_list argv) -{ - int wanted = __mingw_vsnprintf(*sptr = NULL, 0, fmt, argv); - if ((wanted > 0) && ((*sptr = (char*) malloc(wanted + 1)) != NULL)) { - return __mingw_vsprintf(*sptr, fmt, argv); - } - - return wanted; -} - -//static int asprintf(char **sptr, const char *fmt, ...) -//{ -// int retval; -// va_list argv; -// va_start( argv, fmt ); -// retval = vasprintf(sptr, fmt, argv); -// va_end(argv); -// return retval; -//} -#endif - -int bd_sprintf(std::string &str, const char *fmt, ...) -{ - char *buffer = NULL; - va_list ap; - - va_start(ap, fmt); - int retval = vasprintf(&buffer, fmt, ap); - va_end(ap); - - if (retval >= 0) { - if (buffer) { - str = buffer; - free(buffer); - } else { - str.clear(); - } - } else { - str.clear(); - } - - return retval; -} - -int bd_sprintf_append(std::string &str, const char *fmt, ...) -{ - va_list ap; - char *buffer = NULL; - - va_start(ap, fmt); - int retval = vasprintf(&buffer, fmt, ap); - va_end(ap); - - if (retval >= 0) { - if (buffer) { - str.append(buffer); - free(buffer); - } - } - - return retval; -} diff --git a/libbitdht/src/util/bdstring.h b/libbitdht/src/util/bdstring.h deleted file mode 100644 index e9160c663..000000000 --- a/libbitdht/src/util/bdstring.h +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************* - * util/bdstring.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright (C) 2010 Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef BITDHT_UTILS_BDSTRING_H -#define BITDHT_UTILS_BDSTRING_H - -#ifdef WIN32 -// for proper handling of %ll -#define bd_snprintf __mingw_snprintf -#define bd_fprintf __mingw_fprintf -#else -#define bd_snprintf snprintf -#define bd_fprintf fprintf -#endif - -#ifdef __cplusplus - // These definitions are only available for C++ Modules. - #include - - int bd_sprintf(std::string &str, const char *fmt, ...); - int bd_sprintf_append(std::string &str, const char *fmt, ...); -#endif - -#endif diff --git a/libbitdht/src/util/bdthreads.cc b/libbitdht/src/util/bdthreads.cc deleted file mode 100644 index 3fce7ff43..000000000 --- a/libbitdht/src/util/bdthreads.cc +++ /dev/null @@ -1,167 +0,0 @@ -/******************************************************************************* - * util/bdthread.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright (C) 2004-2010 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "bdthreads.h" -#include /* for usleep() */ - -/******* - * #define DEBUG_THREADS 1 - *******/ - -//#define DEBUG_THREADS 1 - -#ifdef DEBUG_THREADS - #include -#endif - -extern "C" void* bdthread_init(void* p) -{ -#ifdef DEBUG_THREADS - std::cerr << "bdthread_init()"; - std::cerr << std::endl; -#endif - - bdThread *thread = (bdThread *) p; - if (!thread) - { -#ifdef DEBUG_THREADS - std::cerr << "bdthread_init() Error Invalid thread pointer."; - std::cerr << std::endl; -#endif - return 0; - } - thread -> run(); - return 0; -} - - -pthread_t createThread(bdThread &thread) -{ - pthread_t tid; - void *data = (void *) (&thread); - -#ifdef DEBUG_THREADS - std::cerr << "createThread() creating a bdThread"; - std::cerr << std::endl; -#endif - - thread.mMutex.lock(); - { - pthread_create(&tid, 0, &bdthread_init, data); - thread.mTid = tid; - } - -#ifdef DEBUG_THREADS - std::cerr << "createThread() created Thread.mTid: "; - -#if defined(_WIN32) || defined(__MINGW32__) - std::cerr << "WIN32: Cannot print mTid "; -#else - std::cerr << thread.mTid; -#endif - std::cerr << std::endl; - -#endif - - thread.mMutex.unlock(); - - - - return tid; - -} - -bdThread::bdThread() -{ - -#ifdef DEBUG_THREADS - std::cerr << "bdThread::bdThread()"; - std::cerr << std::endl; -#endif - -#if defined(_WIN32) || defined(__MINGW32__) - memset (&mTid, 0, sizeof(mTid)); -#else - mTid = 0; -#endif -} - -void bdThread::join() /* waits for the the mTid thread to stop */ -{ -#ifdef DEBUG_THREADS - std::cerr << "bdThread::join() Called! Waiting for Thread.mTid: "; - -#if defined(_WIN32) || defined(__MINGW32__) - std::cerr << "WIN32: Cannot print mTid "; -#else - std::cerr << mTid; -#endif - - std::cerr << std::endl; -#endif - - mMutex.lock(); - { -#if defined(_WIN32) || defined(__MINGW32__) || defined(__APPLE__) - /* Its a struct in Windows compile and the member .p ist checked in the pthreads library */ -#else - if(mTid > 0) -#endif - pthread_join(mTid, NULL); - -#ifdef DEBUG_THREADS - std::cerr << "bdThread::join() Joined Thread.mTid: "; - -#if defined(_WIN32) || defined(__MINGW32__) - std::cerr << "WIN32: Cannot print mTid "; -#else - std::cerr << mTid; -#endif - - std::cerr << std::endl; - std::cerr << "bdThread::join() Setting mTid = 0"; - std::cerr << std::endl; -#endif - -#if defined(_WIN32) || defined(__MINGW32__) - memset (&mTid, 0, sizeof(mTid)); -#else - mTid = 0; -#endif - - } - mMutex.unlock(); - -} - -void bdThread::stop() -{ -#ifdef DEBUG_THREADS - std::cerr << "bdThread::stop() Called!"; - std::cerr << std::endl; -#endif - - pthread_exit(NULL); -} - - - diff --git a/libbitdht/src/util/bdthreads.h b/libbitdht/src/util/bdthreads.h deleted file mode 100644 index 34c48b1bc..000000000 --- a/libbitdht/src/util/bdthreads.h +++ /dev/null @@ -1,97 +0,0 @@ -/******************************************************************************* - * util/bdthread.cc * - * * - * BitDHT: An Flexible DHT library. * - * * - * Copyright (C) 2004-2010 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef BITDHT_THREADS_H -#define BITDHT_THREADS_H - -#include -#include -#include - -/* Thread Wrappers */ - -class bdMutex -{ - public: - - bdMutex(bool recursive = false) - { - /* remove unused parameter warnings */ - (void) recursive; - -#if 0 // TESTING WITHOUT RECURSIVE - if(recursive) - { - pthread_mutexattr_t att ; - pthread_mutexattr_init(&att) ; - pthread_mutexattr_settype(&att,PTHREAD_MUTEX_RECURSIVE) ; - - if( pthread_mutex_init(&realMutex, &att)) - std::cerr << "ERROR: Could not initialize mutex !" << std::endl ; - } - else -#endif - if( pthread_mutex_init(&realMutex, NULL)) - std::cerr << "ERROR: Could not initialize mutex !" << std::endl ; - } - - ~bdMutex() { pthread_mutex_destroy(&realMutex); } - void lock() { pthread_mutex_lock(&realMutex); } - void unlock() { pthread_mutex_unlock(&realMutex); } - bool trylock() { return (0 == pthread_mutex_trylock(&realMutex)); } - - private: - pthread_mutex_t realMutex; -}; - -class bdStackMutex -{ - public: - - bdStackMutex(bdMutex &mtx): mMtx(mtx) { mMtx.lock(); } - ~bdStackMutex() { mMtx.unlock(); } - - private: - bdMutex &mMtx; -}; - -class bdThread; - -/* to create a thread! */ -pthread_t createThread(bdThread &thread); - -class bdThread -{ - public: - bdThread(); -virtual ~bdThread() { return; } - -virtual void start() { createThread(*this); } -virtual void run() = 0; /* called once the thread is started */ -virtual void join(); /* waits for the mTid thread to stop */ -virtual void stop(); /* calls pthread_exit() */ - - pthread_t mTid; - bdMutex mMutex; -}; - - -#endif diff --git a/libretroshare b/libretroshare new file mode 160000 index 000000000..8044b19bb --- /dev/null +++ b/libretroshare @@ -0,0 +1 @@ +Subproject commit 8044b19bb1e51a8446164813fe826b612c0b1e7a diff --git a/libretroshare/.gitattributes b/libretroshare/.gitattributes deleted file mode 100644 index 00a51aff5..000000000 --- a/libretroshare/.gitattributes +++ /dev/null @@ -1,6 +0,0 @@ -# -# https://help.github.com/articles/dealing-with-line-endings/ -# -# These are explicitly windows files and should use crlf -*.bat text eol=crlf - diff --git a/libretroshare/.gitignore b/libretroshare/.gitignore deleted file mode 100644 index 2ed2cdd3f..000000000 --- a/libretroshare/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Ignore Gradle project-specific cache directory -.gradle - -# Ignore Gradle build output directory -build - -# Ignore Gradle local options -local.properties diff --git a/libretroshare/CMakeLists.txt b/libretroshare/CMakeLists.txt deleted file mode 100644 index 64dd17dd9..000000000 --- a/libretroshare/CMakeLists.txt +++ /dev/null @@ -1,457 +0,0 @@ -# RetroShare decentralized communication platform -# -# Copyright (C) 2021 Gioacchino Mazzurco -# Copyright (C) 2021 AsociaciĆ³n Civil Altermundi -# -# SPDX-License-Identifier: CC0-1.0 - -cmake_minimum_required (VERSION 3.18.0) -project(retroshare) - -include(CMakeDependentOption) - -set(FETCHCONTENT_QUIET OFF) -include(FetchContent) - -# sqlcipher -option( - RS_SQLCIPHER - "SQLCipher encryption for GXS database" - ON ) - -# rs_gxs_send_all -option( - RS_GXS_SEND_ALL - "GXS distribute all available messages on request, indipendently from \ - local sync timer" - ON ) - -# bitdht -option( - RS_BITDHT - "Use bitdht (BitTorrent DHT own implementation) to look for online peers" - ON ) - -# use_dht_stunner -cmake_dependent_option( - RS_BITDHT_STUNNER - "Use bitdht (BitTorrent DHT own implementation) for NAT type discovery and \ - attempt the STUN (Session Traversal Utilities for NAT)" - ON - "RS_BITDHT" - OFF ) - -# use_dht_stunner_ext_ip -cmake_dependent_option( - RS_BITDHT_STUNNER_EXT_IP - "Use bitdht (BitTorrent DHT own implementation) stunner to figure out our \ - external IP. As this purely relying on random DHT peers that answer our \ - request, it can easily be abused. Therefore, it is turned off by default." - OFF - "RS_BITDHT_STUNNER" - OFF ) - -# rs_jsonapi -option( - RS_JSON_API - "Use restbed to expose libretroshare as JSON API via HTTP" - OFF ) - -# rs_deep_forums_index -option( - RS_FORUM_DEEP_INDEX - "Xapian based full text index and search of GXS forums" - OFF ) - -# rs_broadcast_discovery -option( - RS_BRODCAST_DISCOVERY - "Local area network peer discovery via udp-discovery-cpp" - ON ) - -# rs_dh_init_check -option( - RS_DH_PRIME_INIT_CHECK - "Check Diffie Hellman prime at each startup. This is not necessary and on \ - all Android mobile phones tested this take at least one minute at startup \ - which is untolerable for most phone users." - ON ) - -option( - RS_MINIUPNPC - "Forward ports in NAT router via miniupnpc" - ON ) - -cmake_dependent_option( - RS_LIBUPNP - "Forward ports in NAT router via libupnp (unstable)" - OFF - "NOT RS_MINIUPNPC" - OFF ) - -option( - RS_LIBRETROSHARE_STATIC - "Build RetroShare static library" - ON ) - -cmake_dependent_option( - RS_LIBRETROSHARE_SHARED - "Build RetroShare shared library" - OFF - "NOT RS_LIBRETROSHARE_STATIC" - OFF ) - -# rs_deprecatedwarning -option( - RS_WARN_DEPRECATED - "Print warning about RetroShare deprecated components usage during build" - ON ) - -# rs_cppwarning -option( - RS_WARN_LESS - "Silence a few at the moment very common warnings about RetroShare \ - components during build" - OFF ) - -# rs_v07_changes -option( - RS_V07_BREAKING_CHANGES - "Enable retro-compatibility breaking changes planned for RetroShare 0.7.0" - OFF ) - -set( - RS_DATA_DIR - "${CMAKE_INSTALL_PREFIX}/share/retroshare" - CACHE STRING - "Path where to install RetroShare system wide data" ) - -option( - RS_EXPORT_JNI_ONLOAD - "Export libretroshare JNI_OnLoad. See src/rs_android/rsjni.cpp for details" - ON ) - -################################################################################ - -find_package(Git REQUIRED) - -#function(check_submodule sPath) -# if(NOT EXISTS "${sPath}/.git" ) -# message("Initializing submodule ${sPath}") -# execute_process( -# COMMAND "${GIT_EXECUTABLE}" submodule update --init -# WORKING_DIRECTORY "${sPath}" -# COMMAND_ECHO STDERR -# COMMAND_ERROR_IS_FATAL ANY) -# endif() -#endfunction() - -################################################################################ - -include(src/CMakeLists.txt) -list(TRANSFORM RS_SOURCES PREPEND src/) -list(TRANSFORM RS_PUBLIC_HEADERS PREPEND src/) - -if(RS_LIBRETROSHARE_STATIC) - add_library(${PROJECT_NAME} STATIC ${RS_SOURCES}) -endif(RS_LIBRETROSHARE_STATIC) - -if(RS_LIBRETROSHARE_SHARED) - add_library(${PROJECT_NAME} SHARED ${RS_SOURCES}) - - ## Ensure statically linked libraries such as openpgpsdk are compiled with - ## PIC Which is needed for shared library - set(CMAKE_POSITION_INDEPENDENT_CODE ON) -endif(RS_LIBRETROSHARE_SHARED) - -target_include_directories( - ${PROJECT_NAME} - PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) - -install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) - -# TODO: install public headers - -find_package(OpenSSL REQUIRED) -target_include_directories(${PROJECT_NAME} PRIVATE ${OPENSSL_INCLUDE_DIR}) -target_link_libraries(${PROJECT_NAME} PRIVATE OpenSSL::SSL OpenSSL::Crypto) - -################################################################################ - -set(OPENPGPSDK_DEVEL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../openpgpsdk/") -if(EXISTS "${OPENPGPSDK_DEVEL_DIR}/.git" ) - message( - CHECK_PASS - "openpgpsdk submodule found at ${OPENPGPSDK_DEVEL_DIR} using it" ) - add_subdirectory(${OPENPGPSDK_DEVEL_DIR} ${CMAKE_BINARY_DIR}/openpgpsdk) -else() - FetchContent_Declare( - openpgpsdk - GIT_REPOSITORY "https://gitlab.com/RetroShare/openpgpsdk.git" - GIT_TAG "origin/master" - GIT_SHALLOW TRUE - GIT_PROGRESS TRUE - TIMEOUT 10 - ) - FetchContent_MakeAvailable(openpgpsdk) -endif() - -target_link_libraries(${PROJECT_NAME} PRIVATE openpgpsdk) - -################################################################################ - -if(RS_BITDHT) - set(BITDHT_DEVEL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../libbitdht/") - if(EXISTS "${BITDHT_DEVEL_DIR}/.git" ) - message( - CHECK_PASS - "BitDHT submodule found at ${BITDHT_DEVEL_DIR} using it" ) - add_subdirectory(${BITDHT_DEVEL_DIR} ${CMAKE_BINARY_DIR}/bitdht) - set(RS_BITDHT_DIR "${BITDHT_DEVEL_DIR}") - else() - FetchContent_Declare( - bitdht - GIT_REPOSITORY "https://gitlab.com/RetroShare/bitdht.git" - GIT_TAG "origin/master" - GIT_SHALLOW TRUE - GIT_PROGRESS TRUE - TIMEOUT 10 - ) - FetchContent_MakeAvailable(bitdht) - - set(RS_BITDHT_DIR "${bitdht_SOURCE_DIR}") - endif() - - add_compile_definitions(RS_USE_BITDHT) - target_link_libraries(${PROJECT_NAME} PRIVATE bitdht) - - if(RS_BITDHT_STUNNER) - add_compile_definitions(RS_USE_DHT_STUNNER) - - if(RS_BITDHT_STUNNER_EXT_IP) - # TODO: Refactor this define to use proper naming - add_compile_definitions(ALLOW_DHT_STUNNER) - endif(RS_BITDHT_STUNNER_EXT_IP) - endif(RS_BITDHT_STUNNER) -endif(RS_BITDHT) - -################################################################################ - -if(RS_JSON_API) - find_package(Doxygen REQUIRED) - find_package(Python3 REQUIRED) - - set( - JSON_API_GENERATOR_WORK_DIR - "${CMAKE_BINARY_DIR}/jsonapi-generator.workdir/" ) - - set( - JSON_API_GENERATOR_DOXYFILE - "${JSON_API_GENERATOR_WORK_DIR}/jsonapi-generator-doxygen.conf" ) - - set( - JSONAPI_GENERATOR_OUTPUT_DIR - "${JSON_API_GENERATOR_WORK_DIR}/src/" ) - - set( - JSONAPI_GENERATOR_SOURCE_DIR - "${CMAKE_CURRENT_SOURCE_DIR}/src/jsonapi/" ) - - set( - JSONAPI_GENERATOR_EXECUTABLE - "${JSONAPI_GENERATOR_SOURCE_DIR}/jsonapi-generator.py" ) - - file( - COPY "src/jsonapi/jsonapi-generator-doxygen.conf" - DESTINATION "${JSON_API_GENERATOR_WORK_DIR}" ) - - file( - APPEND - "${JSON_API_GENERATOR_DOXYFILE}" - "OUTPUT_DIRECTORY=${JSONAPI_GENERATOR_OUTPUT_DIR}\n" - "INPUT=${CMAKE_CURRENT_SOURCE_DIR}" ) - - add_custom_command( - OUTPUT - "${JSONAPI_GENERATOR_OUTPUT_DIR}/jsonapi-includes.inl" - "${JSONAPI_GENERATOR_OUTPUT_DIR}/jsonapi-wrappers.inl" - COMMAND ${DOXYGEN_EXECUTABLE} ${JSON_API_GENERATOR_DOXYFILE} - COMMAND - ${Python3_EXECUTABLE} ${JSONAPI_GENERATOR_EXECUTABLE} - ${JSONAPI_GENERATOR_SOURCE_DIR} ${JSONAPI_GENERATOR_OUTPUT_DIR} - MAIN_DEPENDENCY "${JSONAPI_GENERATOR_EXECUTABLE}" - DEPENDS ${JSON_API_GENERATOR_DOXYFILE} ${RS_PUBLIC_HEADERS} ) - - target_sources( - ${PROJECT_NAME} PRIVATE - "${JSONAPI_GENERATOR_OUTPUT_DIR}/jsonapi-includes.inl" - "${JSONAPI_GENERATOR_OUTPUT_DIR}/jsonapi-wrappers.inl" ) - - include_directories(${JSONAPI_GENERATOR_OUTPUT_DIR}) - - set(BUILD_TESTS OFF CACHE BOOL "Do not build restbed tests") - set(BUILD_SSL OFF CACHE BOOL "Do not build restbed SSL support") - - FetchContent_Declare( - restbed - GIT_REPOSITORY "https://github.com/Corvusoft/restbed.git" - GIT_TAG "4.8" - GIT_SUBMODULES dependency/asio dependency/catch - GIT_SHALLOW TRUE - GIT_PROGRESS TRUE - TIMEOUT 10 - ) - FetchContent_MakeAvailable(restbed) - - target_link_libraries(${PROJECT_NAME} PRIVATE restbed) - - ## TODO: work around target_include_directories should be added upstream - include_directories(${restbed_SOURCE_DIR}/source/) - - add_compile_definitions(RS_JSONAPI) -endif(RS_JSON_API) - -################################################################################ - -if(RS_FORUM_DEEP_INDEX) - find_package(Xapian REQUIRED) - target_link_libraries(${PROJECT_NAME} PRIVATE ${XAPIAN_LIBRARIES}) - - add_compile_definitions(RS_DEEP_FORUMS_INDEX) -endif(RS_FORUM_DEEP_INDEX) - -################################################################################ - -## TODO: Check if https://github.com/rbock/sqlpp11 or -## https://github.com/rbock/sqlpp17 may improve GXS code -if(RS_SQLCIPHER) - find_library(RS_SQL_LIB "sqlcipher" REQUIRED) - find_path( - RS_SQL_LIB_INCLUDE "sqlcipher/sqlite3.h" - PATH_SUFFIXES "include" "includes" - REQUIRED ) - target_include_directories( - ${PROJECT_NAME} - PRIVATE "${RS_SQL_LIB_INCLUDE}/sqlcipher" ) - target_link_libraries(${PROJECT_NAME} PRIVATE ${RS_SQL_LIB}) -else() - add_compile_definitions(NO_SQLCIPHER) - find_package(SQLite3 REQUIRED) - target_link_libraries(${PROJECT_NAME} PRIVATE SQLite::SQLite3) -endif() - -add_compile_definitions( - SQLITE_HAS_CODEC - RS_ENABLE_GXS - GXS_ENABLE_SYNC_MSGS - RS_USE_GXS_DISTANT_SYNC - RS_GXS_TRANS - V07_NON_BACKWARD_COMPATIBLE_CHANGE_001 - V07_NON_BACKWARD_COMPATIBLE_CHANGE_002 - V07_NON_BACKWARD_COMPATIBLE_CHANGE_003 ) - -if(RS_V07_BREAKING_CHANGES) - add_compile_definitions( - V07_NON_BACKWARD_COMPATIBLE_CHANGE_004 - V07_NON_BACKWARD_COMPATIBLE_CHANGE_UNNAMED ) -endif() - -if(RS_DH_PRIME_INIT_CHECK) - add_compile_definitions(RS_DISABLE_DIFFIE_HELLMAN_INIT_CHECK) -endif(RS_DH_PRIME_INIT_CHECK) - -if(RS_MINIUPNPC) - add_compile_definitions(RS_USE_LIBMINIUPNPC) -endif(RS_MINIUPNPC) - -if(RS_LIBUPNP) - message(FATAL_ERROR "UPnP support via libupnp is currently not supported") - #add_compile_definitions(RS_USE_LIBUPNP) -endif(RS_LIBUPNP) - -if(RS_GXS_SEND_ALL) - add_compile_definitions(RS_GXS_SEND_ALL) -endif(RS_GXS_SEND_ALL) - -if(RS_BRODCAST_DISCOVERY) - ## TODO: upstream option to disable tests building - set(BUILD_EXAMPLE OFF CACHE BOOL "Do not build udp-discovery-cpp examples") - set(BUILD_TOOL OFF CACHE BOOL "Do not build udp-discovery-tool application") - FetchContent_Declare( - udp-discovery-cpp - GIT_REPOSITORY "https://github.com/truvorskameikin/udp-discovery-cpp.git" - GIT_TAG "origin/master" - GIT_SHALLOW TRUE - GIT_PROGRESS TRUE - TIMEOUT 10 - ) - FetchContent_MakeAvailable(udp-discovery-cpp) - - target_link_libraries(${PROJECT_NAME} PRIVATE udp-discovery) - - ## TODO: Temporary work around target_include_directories should be added - ## upstream - include_directories(${udp-discovery-cpp_SOURCE_DIR}) -endif(RS_BRODCAST_DISCOVERY) - -if(NOT RS_WARN_DEPRECATED) - add_compile_definitions(RS_NO_WARN_DEPRECATED) - target_compile_options( - ${PROJECT_NAME} PRIVATE - -Wno-deprecated -Wno-deprecated-declarations ) -endif(NOT RS_WARN_DEPRECATED) - -if(RS_WARN_LESS) - add_compile_definitions(RS_NO_WARN_CPP) - - target_compile_options( - ${PROJECT_NAME} PRIVATE - -Wno-cpp -Wno-inconsistent-missing-override ) -endif(RS_WARN_LESS) - -################################################################################ - -if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - add_compile_definitions(RS_DATA_DIR="${RS_DATA_DIR}") -endif(CMAKE_SYSTEM_NAME STREQUAL "Linux") - -################################################################################ - -if(RS_EXPORT_JNI_ONLOAD) - add_compile_definitions(RS_LIBRETROSHARE_EXPORT_JNI_ONLOAD) -endif(RS_EXPORT_JNI_ONLOAD) - -################################################################################ - -#if(CMAKE_SYSTEM_NAME STREQUAL "Android") -if(RS_ANDROID) - FetchContent_Declare( - jni-hpp - GIT_REPOSITORY "https://gitlab.com/RetroShare/jni-hpp.git" - GIT_TAG "origin/master" - GIT_SHALLOW TRUE - GIT_PROGRESS TRUE - TIMEOUT 10 - ) - FetchContent_MakeAvailable(jni-hpp) - - include_directories(${jni-hpp_SOURCE_DIR}/include) - - if(RS_BITDHT) - set(RS_ANDROID_ASSETS_DIR "${CMAKE_BINARY_DIR}/android-assets") - set(RS_ANDROID_VALUES_DIR "${RS_ANDROID_ASSETS_DIR}/values") - file(MAKE_DIRECTORY "${RS_ANDROID_VALUES_DIR}") - file( - COPY "${RS_BITDHT_DIR}/src/bitdht/bdboot.txt" - DESTINATION "${RS_ANDROID_VALUES_DIR}" ) - set( - ANDROID_ASSETS_DIRECTORIES - "${RS_ANDROID_ASSETS_DIR};${ANDROID_ASSETS_DIRECTORIES}" ) - endif(RS_BITDHT) -endif(RS_ANDROID) -#endif(CMAKE_SYSTEM_NAME STREQUAL "Android") - -################################################################################ - -## Useful to debug CMake -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) diff --git a/libretroshare/build.gradle b/libretroshare/build.gradle deleted file mode 100644 index 69eeb1d02..000000000 --- a/libretroshare/build.gradle +++ /dev/null @@ -1,226 +0,0 @@ -/* - * libretroshare Android AAR library gradle builder - * - * Copyright (C) 2022 Gioacchino Mazzurco - * Copyright (C) 2022 AsociaciĆ³n Civil Altermundi - * - * SPDX-License-Identifier: CC0-1.0 - */ - -buildscript -{ - repositories - { - // The order in which you list these repositories matter. - google() - mavenCentral() - } - - dependencies - { - classpath 'com.android.tools.build:gradle:7.1.+' - } -} - -allprojects -{ - repositories - { - // The order in which you list these repositories matter. - google() - mavenCentral() - } -} - -ext.buildLibretroshareNativeLib = -{ - pApiLevel, /* Android API level */ - pAbi, /* Arch name as seen in AAR native libraries directories */ - pNdkPath, /* Android NDK path */ - pReuseToolchain = true /* If true reuse previously built toochain */ -> - - /* Convert pAbi into corresponding prepare toolchain ANDROID_NDK_ARCH */ - def toolchainArch = "unsupported" - def libcxxsharedTriple = "unsupported" - switch(pAbi) - { - case "armeabi-v7a": - toolchainArch = "arm"; - libcxxsharedTriple = "arm-linux-androideabi"; - break; - case "arm64-v8a": - toolchainArch = "arm64"; - libcxxsharedTriple = "aarch64-linux-android"; - break; - default: - throw new GradleException( - "buildLibretroshareNativeLib unsupported pAbi: $pAbi" ); - break; - } - - def toolchainsWorkdir = "${buildDir}/native_toolchains/" - mkdir toolchainsWorkdir - - def currToolchainPath = "$toolchainsWorkdir/$pApiLevel-$toolchainArch/" - - // Todo: use proper way to resolve the script path - def toolChainScriptPath = "${projectDir}/../build_scripts/Android/prepare-toolchain-clang.sh" - - if(!pReuseToolchain || !file(currToolchainPath).exists()) - { - exec - { - workingDir toolchainsWorkdir - environment "ANDROID_NDK_PATH", pNdkPath - environment "NATIVE_LIBS_TOOLCHAIN_PATH", currToolchainPath - environment "ANDROID_PLATFORM_VER", pApiLevel - environment "ANDROID_NDK_ARCH", toolchainArch - commandLine toolChainScriptPath /*, 'build_libretroshare'*/ - } - } - else - {/* - exec - { - workingDir toolchainsWorkdir - environment "ANDROID_NDK_PATH", pNdkPath - environment "NATIVE_LIBS_TOOLCHAIN_PATH", currToolchainPath - environment "ANDROID_PLATFORM_VER", pApiLevel - environment "ANDROID_NDK_ARCH", toolchainArch - commandLine toolChainScriptPath, 'build_libretroshare' - }*/ - } - - def nativeLibsDir = "${buildDir}/native_libs-$pApiLevel/" - mkdir nativeLibsDir - - def currAbiLibDir = "${nativeLibsDir}/$pAbi/" - mkdir currAbiLibDir - copy - { - from "${currToolchainPath}/sysroot/usr/lib/libretroshare.so" - into currAbiLibDir - } - - copy - { - from "${currToolchainPath}/sysroot/usr/lib/${libcxxsharedTriple}/libc++_shared.so" - into currAbiLibDir - } -} - -apply plugin: 'com.android.library' -apply plugin: 'maven-publish' - -android -{ - // see https://stackoverflow.com/questions/27301867/what-is-compilesdkversion - compileSdkVersion 21 - - sourceSets - { - main - { - java.srcDirs = [ 'src/rs_android/' ] - manifest.srcFile 'src/rs_android/AndroidManifest.xml' - assets.srcDirs = [ "${buildDir}/libretroshare-build/android-assets/" ] - jniLibs.srcDirs = [ "${buildDir}/native_libs-16" ] - } - - minApi16 - { - jniLibs.srcDirs = [ "${buildDir}/native_libs-16" ] - } - - minApi21 - { - jniLibs.srcDirs = [ "${buildDir}/native_libs-21" ] - } - - minApi24 - { - jniLibs.srcDirs = [ "${buildDir}/native_libs-24" ] - } - } - - lintOptions - { - disable 'LongLogTag' - } - - flavorDimensions 'api' - - def currNdk = android.getNdkDirectory().getAbsolutePath() - - productFlavors - { - minApi16 - { - minSdkVersion '16' - targetSdkVersion '16' - - def currApi = minSdkVersion.mApiLevel - versionNameSuffix "-API_${currApi}" - - buildLibretroshareNativeLib(currApi, "armeabi-v7a", currNdk) - } - - minApi21 - { - minSdkVersion '21' - targetSdkVersion '21' - - def currApi = minSdkVersion.mApiLevel - versionNameSuffix "-API_${currApi}" - - buildLibretroshareNativeLib(currApi, "arm64-v8a", currNdk) - buildLibretroshareNativeLib(currApi, "armeabi-v7a", currNdk) - } - - minApi24 - { - minSdkVersion '24' - targetSdkVersion '28' - - def currApi = minSdkVersion.mApiLevel - versionNameSuffix "-API_${currApi}" - - buildLibretroshareNativeLib(currApi, "arm64-v8a", currNdk) - buildLibretroshareNativeLib(currApi, "armeabi-v7a", currNdk) - } - } - - publishing - { - multipleVariants - { - allVariants() - } - } -} - -afterEvaluate -{ - publishing - { - // see https://developer.android.com/reference/tools/gradle-api/7.1/com/android/build/api/dsl/LibraryPublishing - publications - { - android.libraryVariants.each - { - variant -> - - publishing.publications.create(variant.name, MavenPublication) - { - from components.findByName(variant.name) - groupId = 'org.retroshare.service' - // -${variant.flavorName} - artifactId "${rootProject.name}-${variant.name}" - version "0.6.6" - - artifacts = [ "${buildDir}/outputs/aar/${rootProject.name}-${variant.flavorName}-${variant.buildType.name}.aar" ] - } - } - } - } -} diff --git a/libretroshare/gradle/wrapper/gradle-wrapper.jar b/libretroshare/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 7454180f2..000000000 Binary files a/libretroshare/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/libretroshare/gradle/wrapper/gradle-wrapper.properties b/libretroshare/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index ffed3a254..000000000 --- a/libretroshare/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/libretroshare/gradlew b/libretroshare/gradlew deleted file mode 100755 index 744e882ed..000000000 --- a/libretroshare/gradlew +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env sh - -# -# Copyright 2015 the original author or authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MSYS* | MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=`expr $i + 1` - done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -exec "$JAVACMD" "$@" diff --git a/libretroshare/gradlew.bat b/libretroshare/gradlew.bat deleted file mode 100644 index 107acd32c..000000000 --- a/libretroshare/gradlew.bat +++ /dev/null @@ -1,89 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/libretroshare/misc/Android/Dockerfile b/libretroshare/misc/Android/Dockerfile deleted file mode 100644 index 490a247c9..000000000 --- a/libretroshare/misc/Android/Dockerfile +++ /dev/null @@ -1,117 +0,0 @@ -## To prepare an image suitable as base for Gitlab CI use -## image name must match gitlab repository name, you can play just with the tag -## the part after : -# export CI_IMAGE_NAME="registry.gitlab.com/retroshare/retroshare:android_arm_base" -# docker build --squash --tag "${CI_IMAGE_NAME}" \ -# --build-arg QT_INSTALLER_JWT_TOKEN="your qt JWT token goes here" . -# -# To build Android ARMv8 (64 bit) package pass also -# export CI_IMAGE_NAME="registry.gitlab.com/retroshare/retroshare:android_arm64_base" -# --build-arg ANDROID_NDK_ARCH=arm64 --build-arg ANDROID_PLATFORM_VER=21 - -## --squash is very important in case of GitlabCI shared runners as they are -## limited to 25GB disk size - -## To push it to gitlab CI registry you need first to login and the to push -# docker login registry.gitlab.com -# docker push ${CI_IMAGE_NAME} - -## To extract the generated APK easily you can run after the build complete -# docker cp \ -# $(docker create --rm ${CI_IMAGE_NAME}):/retroshare-service-android-build/android-build/build/outputs/apk/debug/android-build-debug.apk \ -# /tmp/RetroShare_Android_Service.apk - - -FROM ubuntu:20.04 - -ENV DEBIAN_FRONTEND=noninteractive -ENV APT_UNAT="--assume-yes --quiet" - -RUN apt-get update $APT_UNAT && apt-get upgrade --show-upgraded $APT_UNAT && \ - apt-get clean $APT_UNAT -RUN apt-get install --no-install-recommends $APT_UNAT \ - bash build-essential bzip2 cmake curl chrpath doxygen \ - git p7zip python qt5-default qttools5-dev tclsh unzip wget zip - -# Dependencies to create Android pkg -RUN apt-get install --no-install-recommends $APT_UNAT \ - openjdk-8-jre openjdk-8-jdk openjdk-8-jdk-headless gradle - -ARG FRESHCLONE=0 -ARG REPO_URL=https://gitlab.com/RetroShare/RetroShare.git -ARG REPO_BRANCH=master -ARG REPO_DEPTH="--depth 2000" - -RUN git clone $REPO_DEPTH $REPO_URL -b $REPO_BRANCH && cd RetroShare && \ - git fetch --tags - -ENV PREPARE_TOOLCHAIN="/RetroShare/build_scripts/Android/prepare-toolchain-clang.sh" -ENV NATIVE_LIBS_TOOLCHAIN_PATH="/android-toolchain/" - -ARG ANDROID_PLATFORM_VER=16 -ARG ANDROID_NDK_ARCH=arm - -ENV ANDROID_SDK_PATH="/opt/android-sdk" -ENV ANDROID_HOME="$ANDROID_SDK_PATH" -ENV ANDROID_SDK_ROOT="$ANDROID_SDK_PATH" - -ENV ANDROID_NDK_PATH="/opt/android-ndk" -ENV ANDROID_NDK_ROOT="$ANDROID_NDK_PATH" - -ENV PATH="$PATH:$ANDROID_HOME/tools" -ENV PATH="$PATH:$ANDROID_HOME/platform-tools" -ENV JAVA_HOME="/usr/lib/jvm/java-8-openjdk-amd64/" - -RUN mkdir /bCache -WORKDIR /bCache - -## Quick HACK to ease development -#COPY prepare-toolchain-clang.sh $PREPARE_TOOLCHAIN - -RUN $PREPARE_TOOLCHAIN install_android_sdk -RUN $PREPARE_TOOLCHAIN install_android_ndk -RUN $PREPARE_TOOLCHAIN - -ARG QT_INSTALLER_JWT_TOKEN -RUN $PREPARE_TOOLCHAIN install_qt_android -# Avoid Qt account details leak into the image -RUN rm -f /root/.local/share/Qt/qtaccount.ini -# Shrink image by removing unneeded Qt components -RUN rm -r \ - $NATIVE_LIBS_TOOLCHAIN_PATH/Qt/Docs/ \ - $NATIVE_LIBS_TOOLCHAIN_PATH/Qt/Examples/ \ - $NATIVE_LIBS_TOOLCHAIN_PATH/Qt/Tools/ - -RUN mkdir /jsonapi-generator-build -WORKDIR /jsonapi-generator-build/ -RUN qmake ../RetroShare/jsonapi-generator/src/ \ - CONFIG+=no_retroshare_plugins \ - CONFIG+=no_retroshare_service CONFIG+=no_retroshare_gui \ - CONFIG+=rs_jsonapi CONFIG+=no_rs_sam3_libsam3 && \ - make -j$(nproc) - -RUN mkdir /retroshare-service-android-build -WORKDIR /retroshare-service-android-build -ARG RS_SERVICE_QMAKE_EXTRA_OPTS -RUN $($PREPARE_TOOLCHAIN get_qt_dir | head -n 1)/bin/qmake ../RetroShare \ - -spec android-clang \ - CONFIG+=retroshare_service CONFIG+=rs_jsonapi \ - RS_UPNP_LIB=miniupnpc \ - JSONAPI_GENERATOR_EXE=/jsonapi-generator-build/jsonapi-generator \ - NATIVE_LIBS_TOOLCHAIN_PATH=$NATIVE_LIBS_TOOLCHAIN_PATH \ - CONFIG+=no_retroshare_gui CONFIG+=no_rs_service_webui_terminal_password \ - CONFIG+=no_rs_service_terminal_login \ - CONFIG+=no_rs_sam3 CONFIG+=no_rs_sam3_libsam3 \ - $RS_SERVICE_QMAKE_EXTRA_OPTS -RUN make -j$(nproc) -RUN make install INSTALL_ROOT=/retroshare-service-android-build/android-build/ -RUN $($PREPARE_TOOLCHAIN get_qt_dir | head -n 1)/bin/androiddeployqt \ - --input retroshare-service/src/android-libretroshare-service.so-deployment-settings.json \ - --output android-build --android-platform android-$ANDROID_PLATFORM_VER \ - --jdk $JAVA_HOME --gradle - - -RUN rm -rf /bCache - -# Clean apt cache -RUN apt-get clean && rm -rf /var/lib/apt/lists/* diff --git a/libretroshare/misc/Android/README.asciidoc b/libretroshare/misc/Android/README.asciidoc deleted file mode 100644 index c47974161..000000000 --- a/libretroshare/misc/Android/README.asciidoc +++ /dev/null @@ -1,400 +0,0 @@ -= RetroShare development on Android - -// SPDX-FileCopyrightText: RetroShare Team -// SPDX-License-Identifier: CC-BY-SA-4.0 - - -Compiling an application for Android is not as easy as one would imagine, -expecially one like RetroShare that has a big codebase and is not well -documented. This document is aimed to empower the reader so she can hopefully -succed or at least have a significant help in compiling her own RetroShare APK -installable on Android. - - -== Preparing The Environement - -First of all setup your Qt for Android development environement following the -guide on the link:http://doc.qt.io/qt-5/androidgs.html[Qt for android web site]. -At this point you should have Android SDK, Android NDK, and Qt for Android -working fine, and you should be capable of executing on an Android emulator or -on your Android phone Qt for Android examples. - -But RetroShare is not as simple to compile as those examples. The good news is -that Android NDK ships all the necessary to build a custom toolchain that is -suitable to build RetroShare. -In order to build the toolchain with needed libraries RetroShare provides the -+android-prepare-toolchain.sh+ script; before you execute it you should define -some variables the script cannot determine in an easy and reliable manner by -itself in your terminal. - -[source,bash] -------------------------------------------------------------------------------- -## The path where Android NDK is installed in your system -export ANDROID_NDK_PATH="/opt/android-ndk/" - -## The path where your fresh compiled toolchain will be installed, make sure -## the parent exists -export NATIVE_LIBS_TOOLCHAIN_PATH="${HOME}/Builds/android-toolchains/retroshare-android/" - -## The CPU architecture of the Android device you want to target -export ANDROID_NDK_ARCH="arm" - -## The Android API level the Android device you want to target -export ANDROID_PLATFORM_VER="16" - -## The number of core that yout host CPU have (just to speed up compilation) set -## it to 1 if unsure -export HOST_NUM_CPU=1 - -./android-prepare-toolchain.sh -------------------------------------------------------------------------------- - - -== Preparing Qt Creator - -Now that your environement is set up you should configure Qt Creator for Android -following the -link:http://doc.qt.io/qtcreator/creator-developing-android.html[official guide]. -At the end of this step your Qt Creator should recognize the Android compiler -and the Qt for Android kit. - -Your Kit is now ready to use. Now you can open RetroShare as a Qt Creator -project and in the Projects left menu add the newly created kit if not already -present, so you can select it on the build type selection button down on the -left. - -Now you need to set properly a few options like `JSONAPI_GENERATOR_EXE` and -disable some of RetroShare modules like `retroshare-gui` that are not available -on Android so you will have to go to - -_Qt Creator left pane -> Projects -> Build and Run -> Android SOMESTUFF kit -> -Build Steps -> qmake -> Additional arguments_ + - -and add the following configurations (change `Your_Path` according to your -deployment) - -[source,makefile] -------------------------------------------------------------------------------- -CONFIG+=retroshare_service CONFIG+=rs_jsonapi CONFIG+=no_keywords -RS_UPNP_LIB=miniupnpc -JSONAPI_GENERATOR_EXE=Your_Path/jsonapi-generator/src/jsonapi-generator -NATIVE_LIBS_TOOLCHAIN_PATH=Your_Path/retroshare-android-16-arm/ -CONFIG+=no_retroshare_gui CONFIG+=no_rs_service_webui_terminal_password -CONFIG+=no_rs_service_terminal_login -CONFIG+=no_rs_sam3 CONFIG+=no_rs_sam3_libsam3 -------------------------------------------------------------------------------- - -TIP: Some versions of QtCreator try to find the Android SDK in -`/opt/android/sdk`. A workaround to this is to make a symbolic link there -pointing to your SDK installation path, like -+mkdir -p /opt/android/sdk && ln -s /home/user/android-sdk-linux -/opt/android/sdk+ - - -== Quircks - -=== Protected Apps - -On some Android devices like +Huawei ALE-L21+ background applications are -killed when screen is turned off unless they are in the _protected app_ list. -At moment seems apps developers don't have a way to have the application -_protected_ by default, unless the phone vendor decide the app is _popular_ so -the user have to enable _protection_ for RetroShare manually on those mobile -phones. + - -{empty} + -To enable enable _protection_: +Android menu -> Settings -> Privacy & security --> Protected apps -> RetroShare+ + -{empty} + - -Other devices may offer similar _features_ please report them. - - -=== APK signature mismatch - -If you try to install a RetroShare APK that comes from a different source -(eg: if you try to upgrade from F-Droid when you originally installed an APK -build by yourself) Android will prevent that from happening. In that case the -only solution is to uninstall the app and then install the new APK but if you do -it also the application data and your precious cryptographic keys, friend list -etc. will be lost forever. -To avoid that you can attempt to manually backup and then restore from the -command-line (`adb backup` seems not working either) to change the app source -without erasing the appliation data. - -CAUTION: Following steps require root access on your Android device - -.Backup RetroShare Android application data -[source,bash] --------------------------------------------------------------------------------- -export ORIG_DIR="/data/data/org.retroshare.android.qml_app" -export BACKUP_DIR="org.retroshare.android.qml_app.backup" - -adb root - -adb shell am force-stop org.retroshare.android.qml_app -sleep 1s - -mkdir ${BACKUP_DIR} - -# Avoid adb pull failing -adb shell rm ${ORIG_DIR}/files/.retroshare/libresapi.sock -adb pull ${ORIG_DIR}/files/ ${BACKUP_DIR}/files/ --------------------------------------------------------------------------------- - -After this you should be able to uninstall the old APK with your preferred -method, as example from the command-line. - -.Uninstall RetroShare Android from the command-line -[source,bash] --------------------------------------------------------------------------------- -adb uninstall org.retroshare.android.qml_app --------------------------------------------------------------------------------- - -Now you can install a different signature APK and then restore the application -data with the following commands. - -[source,bash] --------------------------------------------------------------------------------- -export ORIG_DIR="/data/data/org.retroshare.android.qml_app" -export BACKUP_DIR="org.retroshare.android.qml_app.backup" - -adb root - -## Launch the app to make sure the parent directory exists and has proper owner -adb shell monkey -p org.retroshare.android.qml_app -c android.intent.category.LAUNCHER 1 -sleep 1s - -adb shell am force-stop org.retroshare.android.qml_app -sleep 1s - - -APP_OWNER="$(adb shell busybox ls -lnd ${ORIG_DIR} | awk '{print $3":"$4}')" -adb shell rm -rf ${ORIG_DIR}/files -adb push ${BACKUP_DIR}/files/ ${ORIG_DIR}/files/ -adb shell busybox chown -R ${APP_OWNER} ${ORIG_DIR}/files/ --------------------------------------------------------------------------------- - -Opening RetroShare android app now should show your old profile. - - -== Debugging with GDB - -If building RetroShare Android package seems tricky, setting up a functional -debugging environement for it feels like black magic. This section is meant to -help you doing it with less headache and hopefully in a reproducible way. - -Unfortunately at the time of the last update to this guide, Qt build system -strips debugging symbols from the package and from the buildroot also if you -compile with debugging enabled. Fiddling with `qmake` configurations and -variables like `CONFIG+=debug`, `CONFIG+=force_debug_info` or `QMAKE_STRIP` -either as commandline arguments or inside retroshare `.pro` and `.pri` files is -uneffective. IMHO Qt should handle this on itself so it is probably worth -reporting a bug to them. So to workaround this problem you need to fiddle a bit -with the Android NDK. In my case I always keep +Debug+ or +Release+ suffix in -my build directory name depending on what kind of build it is, so I use this -information and modify `llvm-strip` in a way that it will strip only if stripped -file path doesn't contain +Debug+. - -.Modify llvm-strip inside Android NDK --------------------------------------------------------------------------------- -## Set ANDROID_NDK_PATH to your Android NDK installation path -export ANDROID_NDK_PATH="/opt/android-ndk/" - -## Define a convenience variable with llvm-strip path -export ANDROID_NDK_LLVM_STRIP="${ANDROID_NDK_PATH}/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip" - -## If not existing yer create a backup of the original llvm-strip -[ -f "${ANDROID_NDK_LLVM_STRIP}.back" ] || - cp "${ANDROID_NDK_LLVM_STRIP}" "${ANDROID_NDK_LLVM_STRIP}.back" - -## Create a new llvm-strip that does nothing if the argument path contains Debug -cat > "${ANDROID_NDK_LLVM_STRIP}" << LLVMSTRIPTRICK -#!/bin/bash - -echo "\${2}" | grep -q Debug || - "${ANDROID_NDK_LLVM_STRIP}.back" --strip-all "\${2}" - -LLVMSTRIPTRICK - -## Eventually you can revert back simply by running -# `mv "${ANDROID_NDK_LLVM_STRIP}.back" "${ANDROID_NDK_LLVM_STRIP}"` --------------------------------------------------------------------------------- - - -To attach to the `retroshare-service` running on Android you need also to pull a -debugging sysroot out of your device first, RetroShare sources provides an -helper script to do that. - -.Prepare debugging sysroot with helper script -[source,bash] --------------------------------------------------------------------------------- -## Set RetroShare source path -export RS_SOURCE_DIR="${HOME}/Development/rs-develop" - -## Optionally set your device ID first available will be used, you can run -## `adb devices` to list available devices. -#export ANDROID_SERIAL="YT013PSPGK" - -## Optionally set a path where to save the debugging sysroot otherwise default -## is used. -#export DEBUG_SYSROOT="${HOME}/Builds/debug_sysroot/${ANDROID_SERIAL}/" - -## Run the helper script -${RS_SOURCE_DIR}/build_scripts/Android/pull_sysroot.sh --------------------------------------------------------------------------------- - -.Prepare Android NDK GDB configurations -[source,bash] --------------------------------------------------------------------------------- -## Optionally set Qt version variable consistently with your installation -export QT_VERSION="5.12.7" - -## Optionally set Qt architecture variable consistently with Android device -export QT_ARCH="arm64_v8a" - -## Optionally set Qt path variable consistently with your installation -export QT_DIR="/opt/Qt-${QT_VERSION}/${QT_VERSION}/" - -## Optionally set RetroShare buildroot path -export RS_BUILD_DIR="${HOME}/Builds/RetroShare-Android_for_${QT_ARCH}_Clang_Qt_${QT_VERSION//./_}_android_${QT_ARCH}-Debug/" - -## Optionally set gdb config file path -export GDB_CONFIGS_FILE="${HOME}/Builds/gdb_configs_${QT_ARCH}" - -## Generate Android NDK GDB configuration -${RS_SOURCE_DIR}/build_scripts/Android/generate_gdb_init_commands.sh --------------------------------------------------------------------------------- - - -You will need to run the following steps everytime you want to debug -`retroshare-service` on Android. - -Make sure `retroshare-service` is running on your connected Android device. - -.Run GDB server on your Android device from your host console -[source,bash] --------------------------------------------------------------------------------- -${RS_SOURCE_DIR}/build_scripts/Android/start_gdbserver.sh --------------------------------------------------------------------------------- - - -.Run Android NDK GDB on your workstation and attach -[source,bash] --------------------------------------------------------------------------------- -## Start NDK gdb -${ANDROID_NDK_PATH}/prebuilt/linux-x86_64/bin/gdb - -## Instruct GDB how and where to find debugging symbols -(gdb) source $GDB_CONFIGS_FILE - -## Connect to the gdbserver running on the phone -(gdb) target remote 127.0.01:5039 - -## Have fun debugging -(gdb) --------------------------------------------------------------------------------- - - -== Debugging with Qt Creator - -WARNING: As of the last update to this guide, debugging retroshare-service -running on Android via Qt creator doesn't wrok even with all the trickery -explained in this section, you better learn how to debug with GDB reading -carefully previous section. - -Qt Creator actually support debugging only for the foreground activity, so to -debug what's happening in the core extra trickery is needed. - -- Run the App in Debug mode from QtCreator "Start Debugging" button -- Enable QtCreator debugger console view Menu->Window->Debugger Log -- Run +show solib-search-path+ in the QtCreator GDB console -- Take note of the output you get in the right pane of the console -- Thanks https://stackoverflow.com/a/31164313 for the idea - -TIP: QtCreator GDB console seems a bit buggy and easly trigger timeout -message when a command is run, in that case attempt to run the command while the -debugging is paused or at breakpoint, or with other similar tricks. - -CAUTION: Following steps require root access on your Android device - -Now on your phone yuo need to authorize root access to applications, then once -you plug your sacrifical Android phone run this commands - -.Run gdbserver as root on Android phone -[source,bash] --------------------------------------------------------------------------------- -## Open a shell from your workstation on the connected Android phone -adb shell - -## take the note of the phone IP address -ip address show - -## Gain root permissions on the shell -su - -## Attach with gdbserver and listen on one TCP port -gdbserver :4567 --attach $(pgrep org.retroshare.android.qml_app:rs) --------------------------------------------------------------------------------- - - -.Prepare and run Android NDK GDB on your workstation -[source,bash] --------------------------------------------------------------------------------- -## Setup some convenience variables -NDK_GDB="${ANDROID_NDK_PATH}/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gdb" -RS_BUILD_PATH="${HOME}/Builds/RetroShare-Android_for_armeabi_v7a_GCC_4_9_Qt_5_9_2_android_armv7-Debug/" - -## Start Android NDK GDB of your phone architecture passing the executable -$NDK_GDB $RS_BUILD_PATH/retroshare-android-service/src/libretroshare-android-service.so - -## Instruct GDB how and where to find debugging symbols -(gdb) set auto-solib-add on -(gdb) set solib-search-path THE:BIG:LIST:OF:DIRECTORIES:YOU:TAKE:NOTE:BEFORE - -## Connect to the gdbserver running on the phone -(gdb) target remote $PHONE_IP:4567 - -## Have fun debugging -(gdb) --------------------------------------------------------------------------------- - -TIP: Some time WiFi power saving on Android mess with the GDB connection, -to prevent that from appening open another +adb shell+ and live +ping+ toward -your work-station running - -== Embedding into other Android packages - -As showed by https://elrepo.io/[elRepo.io] developers it is possible and quite -easy to embed `retroshare-service` into other Android packages see description - -https://gitlab.com/elRepo.io/elRepo.io-android/-/blob/master/README.adoc - -And implementation details - -https://gitlab.com/elRepo.io/elRepo.io-android/-/blob/master/android/app/build.gradle - - -== Furter Readings - -- link:http://doc.qt.io/qt-5/android-support.html[] -- link:https://developer.android.com/ndk/guides/libs.html[] -- link:retroshare://forum?name=Compiling%20nogui%20for%20android&id=8fd22bd8f99754461e7ba1ca8a727995&msgid=4e0f92330600bba9cf978f384f4b7b2f2ca64eff[] -- link:retroshare://file?name=Android%20Native%20Development%20Kit%20Cookbook.pdf&size=29214468&hash=0123361c1b14366ce36118e82b90faf7c7b1b136[] -- link:https://groups.google.com/forum/#!topic/android-developers/srATPaL0aRU[] -- link:https://stackoverflow.com/questions/31638986/protected-apps-setting-on-huawei-phones-and-how-to-handle-it[] -- link:https://tthtlc.wordpress.com/2012/09/19/how-to-do-remote-debugging-via-gdbserver-running-inside-the-android-phone/[] -- link:https://source.android.com/devices/tech/debug/[] -- link:https://source.android.com/devices/tech/debug/gdb[] -- link:https://fw4spl-org.github.io/fw4spl-blog/2015/07/27/Native-debugging-on-Android-with-QtCreator.html[] -- link:https://fragglet.livejournal.com/19646.html[] -- link:https://github.com/android-ndk/ndk/issues/773[How to build without using standalone toolchain?] - -== License - -Copyright (C) 2016-2021 Gioacchino Mazzurco + -Copyright (C) 2020-2021 AsociaciĆ³n Civil Altermundi + - -This work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License. - -image::https://i.creativecommons.org/l/by-sa/4.0/88x31.png[Creative Commons License, link=http://creativecommons.org/licenses/by-sa/4.0/] diff --git a/libretroshare/misc/Android/generate_gdb_init_commands.sh b/libretroshare/misc/Android/generate_gdb_init_commands.sh deleted file mode 100755 index 3a9883950..000000000 --- a/libretroshare/misc/Android/generate_gdb_init_commands.sh +++ /dev/null @@ -1,85 +0,0 @@ -#!/bin/bash - -# Script to prepare Android NDK GDB configurations to debug retroshare-service -# -# Copyright (C) 2020 Gioacchino Mazzurco -# Copyright (C) 2020 AsociaciĆ³n Civil Altermundi -# -# This program is free software: you can redistribute it and/or modify it under -# the terms of the GNU Affero General Public License as published by the -# Free Software Foundation, version 3. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. -# See the GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License along -# with this program. If not, see - - -## Define default value for variable, take two arguments, $1 variable name, -## $2 default variable value, if the variable is not already define define it -## with default value. -function define_default_value() -{ - VAR_NAME="${1}" - DEFAULT_VALUE="${2}" - - [ -z "${!VAR_NAME}" ] && export ${VAR_NAME}="${DEFAULT_VALUE}" -} - -define_default_value QT_VERSION "5.12.4" -define_default_value QT_ARCH "arm64_v8a" -define_default_value QT_DIR "/opt/Qt-${QT_VERSION}/${QT_VERSION}/" -define_default_value ANDROID_SERIAL "$(adb devices | head -n 2 | tail -n 1 | awk '{print $1}')" -define_default_value RS_BUILD_DIR "${HOME}/Builds/RetroShare-Android_for_${QT_ARCH}_Clang_Qt_${QT_VERSION//./_}_android_${QT_ARCH}-Debug/" -define_default_value RS_SOURCE_DIR "${HOME}/Development/rs-develop/" -define_default_value DEBUG_SYSROOT "${HOME}/Builds/debug_sysroot/${ANDROID_SERIAL}/" -define_default_value GDB_CONFIGS_FILE "${HOME}/Builds/gdb_configs_${QT_ARCH}" - -scanDir() -{ - find "$1" -type d -not -path '*/\.git/*' | tr '\n' ':' >> $GDB_CONFIGS_FILE -} - -putSeparator() -{ - echo >> $GDB_CONFIGS_FILE - echo >> $GDB_CONFIGS_FILE -} - -echo "set sysroot ${DEBUG_SYSROOT}" > $GDB_CONFIGS_FILE -putSeparator - -echo "set auto-solib-add on" >> $GDB_CONFIGS_FILE -echo -n "set solib-search-path " >> $GDB_CONFIGS_FILE -scanDir "${RS_BUILD_DIR}" -scanDir "${DEBUG_SYSROOT}" -scanDir "${QT_DIR}/android_${QT_ARCH}/lib/" -scanDir "${QT_DIR}/android_${QT_ARCH}/plugins/" -scanDir "${QT_DIR}/android_${QT_ARCH}/qml/" -putSeparator - -echo -n "directory " >> $GDB_CONFIGS_FILE -scanDir ${RS_SOURCE_DIR}/jsonapi-generator/src -scanDir ${RS_SOURCE_DIR}/libbitdht/src -scanDir ${RS_SOURCE_DIR}/openpgpsdk/src -scanDir ${RS_SOURCE_DIR}/libretroshare/src -scanDir ${RS_SOURCE_DIR}/retroshare-service/src -scanDir ${RS_SOURCE_DIR}/supportlibs/rapidjson/include/ -scanDir ${RS_SOURCE_DIR}/supportlibs/restbed/source/ -scanDir ${RS_SOURCE_DIR}/supportlibs/udp-discovery-cpp/ -scanDir ${RS_SOURCE_DIR}/supportlibs/restbed/dependency/asio/asio/include/ -scanDir ${RS_SOURCE_DIR}/supportlibs/restbed/dependency/catch/include/ -putSeparator - -## see https://stackoverflow.com/questions/28972367/gdb-backtrace-without-stopping -echo "catch signal SIGSEGV" >> $GDB_CONFIGS_FILE -echo "commands - bt - continue - end" >> $GDB_CONFIGS_FILE -putSeparator - -echo GDB_CONFIGS_FILE=$GDB_CONFIGS_FILE diff --git a/libretroshare/misc/Android/prepare-toolchain-clang.sh b/libretroshare/misc/Android/prepare-toolchain-clang.sh deleted file mode 100755 index 4519d591d..000000000 --- a/libretroshare/misc/Android/prepare-toolchain-clang.sh +++ /dev/null @@ -1,920 +0,0 @@ -#!/bin/bash - -# Script to prepare RetroShare Android package building toolchain -# -# Copyright (C) 2016-2021 Gioacchino Mazzurco -# Copyright (C) 2020-2021 AsociaciĆ³n Civil Altermundi -# -# This program is free software: you can redistribute it and/or modify it under -# the terms of the GNU Affero General Public License as published by the -# Free Software Foundation, version 3. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. -# See the GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License along -# with this program. If not, see -# -# SPDX-FileCopyrightText: Retroshare Team -# SPDX-License-Identifier: AGPL-3.0-only - - -## Define default value for variable, take two arguments, $1 variable name, -## $2 default variable value, if the variable is not already define define it -## with default value. -function define_default_value() -{ - VAR_NAME="${1}" - DEFAULT_VALUE="${2}" - - [ -z "${!VAR_NAME}" ] && export ${VAR_NAME}="${DEFAULT_VALUE}" || true -} - -## You are supposed to provide the following variables according to your system setup -define_default_value ANDROID_NDK_PATH "/opt/android-ndk/" -define_default_value ANDROID_NDK_ARCH "arm" -define_default_value ANDROID_PLATFORM_VER "16" -define_default_value NATIVE_LIBS_TOOLCHAIN_PATH "${HOME}/Builds/android-toolchains/retroshare-android-${ANDROID_PLATFORM_VER}-${ANDROID_NDK_ARCH}/" -define_default_value HOST_NUM_CPU $(nproc) - -define_default_value ANDROID_SDK_INSTALL "false" -define_default_value ANDROID_SDK_TOOLS_VERSION "3859397" -define_default_value ANDROID_SDK_TOOLS_SHA256 444e22ce8ca0f67353bda4b85175ed3731cae3ffa695ca18119cbacef1c1bea0 -define_default_value ANDROID_SDK_VERSION "29.0.3" - -define_default_value ANDROID_NDK_INSTALL "false" -define_default_value ANDROID_NDK_VERSION "r21" -define_default_value ANDROID_NDK_SHA256 b65ea2d5c5b68fb603626adcbcea6e4d12c68eb8a73e373bbb9d23c252fc647b - -define_default_value BZIP2_SOURCE_VERSION "1.0.6" -define_default_value BZIP2_SOURCE_SHA256 a2848f34fcd5d6cf47def00461fcb528a0484d8edef8208d6d2e2909dc61d9cd - -define_default_value OPENSSL_SOURCE_VERSION "1.1.1c" -define_default_value OPENSSL_SOURCE_SHA256 f6fb3079ad15076154eda9413fed42877d668e7069d9b87396d0804fdb3f4c90 - -define_default_value SQLITE_SOURCE_YEAR "2018" -define_default_value SQLITE_SOURCE_VERSION "3250200" -define_default_value SQLITE_SOURCE_SHA256 da9a1484423d524d3ac793af518cdf870c8255d209e369bd6a193e9f9d0e3181 - -define_default_value SQLCIPHER_SOURCE_VERSION "4.4.3" -define_default_value SQLCIPHER_SOURCE_SHA256 b8df69b998c042ce7f8a99f07cf11f45dfebe51110ef92de95f1728358853133 - -define_default_value LIBUPNP_SOURCE_VERSION "1.8.4" -define_default_value LIBUPNP_SOURCE_SHA256 976c3e4555604cdd8391ed2f359c08c9dead3b6bf131c24ce78e64d6669af2ed - -define_default_value QT_ANDROID_VIA_INSTALLER "false" -define_default_value QT_VERSION "5.12.11" -define_default_value QT_INSTALLER_VERSION "4.1.1" -define_default_value QT_INSTALLER_SHA256 1266ffd0d1b0e466244e3bc8422975c1aa9d96745b6bb28d422f7f92df11f34c -define_default_value QT_INSTALLER_JWT_TOKEN "" -define_default_value QT_INSTALL_PATH "${NATIVE_LIBS_TOOLCHAIN_PATH}/Qt/" - -define_default_value QT_ANDROID_INSTALLER_SHA256 a214084e2295c9a9f8727e8a0131c37255bf724bfc69e80f7012ba3abeb1f763 - -define_default_value RESTBED_SOURCE_REPO "https://github.com/Corvusoft/restbed.git" -define_default_value RESTBED_SOURCE_VERSION f74f9329dac82e662c1d570b7cd72c192b729eb4 - -define_default_value UDP_DISCOVERY_CPP_SOURCE "https://github.com/truvorskameikin/udp-discovery-cpp.git" -define_default_value UDP_DISCOVERY_CPP_VERSION "develop" - -define_default_value XAPIAN_SOURCE_VERSION "1.4.7" -define_default_value XAPIAN_SOURCE_SHA256 13f08a0b649c7afa804fa0e85678d693fd6069dd394c9b9e7d41973d74a3b5d3 - -define_default_value RAPIDJSON_SOURCE_VERSION "1.1.0" -define_default_value RAPIDJSON_SOURCE_SHA256 bf7ced29704a1e696fbccf2a2b4ea068e7774fa37f6d7dd4039d0787f8bed98e - -define_default_value MINIUPNPC_SOURCE_VERSION "2.1.20190625" -define_default_value MINIUPNPC_SOURCE_SHA256 8723f5d7fd7970de23635547700878cd29a5c2bb708b5e5475b2d1d2510317fb - -# zlib and libpng versions walks toghether -define_default_value ZLIB_SOURCE_VERSION "1.2.11" -define_default_value ZLIB_SOURCE_SHA256 4ff941449631ace0d4d203e3483be9dbc9da454084111f97ea0a2114e19bf066 - -define_default_value LIBPNG_SOURCE_VERSION "1.6.37" -define_default_value LIBPNG_SOURCE_SHA256 505e70834d35383537b6491e7ae8641f1a4bed1876dbfe361201fc80868d88ca - -define_default_value LIBJPEG_SOURCE_VERSION "9d" -define_default_value LIBJPEG_SOURCE_SHA256 6c434a3be59f8f62425b2e3c077e785c9ce30ee5874ea1c270e843f273ba71ee - -define_default_value TIFF_SOURCE_VERSION "4.2.0" -define_default_value TIFF_SOURCE_SHA256 eb0484e568ead8fa23b513e9b0041df7e327f4ee2d22db5a533929dfc19633cb - -define_default_value CIMG_SOURCE_VERSION "2.9.7" -define_default_value CIMG_SOURCE_SHA256 595dda9718431a123b418fa0db88e248c44590d47d9b1646970fa0503e27fa5c - -define_default_value PHASH_SOURCE_REPO "https://gitlab.com/g10h4ck/pHash.git" -define_default_value PHASH_SOURCE_VERSION origin/android-ndk - -define_default_value MVPTREE_SOURCE_REPO "https://github.com/starkdg/mvptree.git" -define_default_value MVPTREE_SOURCE_VERSION origin/master - -define_default_value REPORT_DIR "$(pwd)/$(basename ${NATIVE_LIBS_TOOLCHAIN_PATH})_build_report/" - -define_default_value RS_SRC_DIR "$(realpath $(dirname $BASH_SOURCE)/../../)" - - -cArch="" -eABI="" -cmakeABI="" - -case "${ANDROID_NDK_ARCH}" in -"arm") - cArch="${ANDROID_NDK_ARCH}" - eABI="eabi" - ;; -"arm64") - cArch="aarch64" - eABI="" - ;; -"x86") - cArch="i686" - eABI="" - ;; -"x86_64") - echo "ANDROID_NDK_ARCH=${ANDROID_NDK_ARCH} not supported yet" - exit -1 - cArch="??" - eABI="" -esac - -export SYSROOT="${NATIVE_LIBS_TOOLCHAIN_PATH}/sysroot/" -export PREFIX="${SYSROOT}/usr/" -export CC="${NATIVE_LIBS_TOOLCHAIN_PATH}/bin/${cArch}-linux-android${eABI}-clang" -export CXX="${NATIVE_LIBS_TOOLCHAIN_PATH}/bin/${cArch}-linux-android${eABI}-clang++" -export AR="${NATIVE_LIBS_TOOLCHAIN_PATH}/bin/${cArch}-linux-android${eABI}-ar" -export RANLIB="${NATIVE_LIBS_TOOLCHAIN_PATH}/bin/${cArch}-linux-android${eABI}-ranlib" - -# Used to instruct cmake to explicitely ignore host libraries -export HOST_IGNORE_PREFIX="/usr/" - - -## $1 filename, $2 sha256 hash -function check_sha256() -{ - echo ${2} "${1}" | sha256sum -c &> /dev/null -} - -## $1 filename, $2 sha256 hash, $3 url -function verified_download() -{ - FILENAME="$1" - SHA256="$2" - URL="$3" - - check_sha256 "${FILENAME}" "${SHA256}" || - { - rm -rf "${FILENAME}" - - wget -O "${FILENAME}" "$URL" || - { - echo "Failed downloading ${FILENAME} from $URL" - exit 1 - } - - check_sha256 "${FILENAME}" "${SHA256}" || - { - echo "SHA256 mismatch for ${FILENAME} from ${URL} expected sha256 ${SHA256} got $(sha256sum ${FILENAME} | awk '{print $1}')" - exit 1 - } - } -} - -# This function is the result of reading and testing many many stuff be very -# careful editing it -function andro_cmake() -{ -# Using android.toolchain.cmake as documented here -# https://developer.android.com/ndk/guides/cmake seens to break more things then -# it fixes :-\ - - cmakeProc="" - case "${ANDROID_NDK_ARCH}" in - "arm") - cmakeProc="armv7-a" - ;; - "arm64") - cmakeProc="aarch64" - ;; - "x86") - cmakeProc="i686" - ;; - "x86_64") - cmakeProc="x86_64" - ;; - *) - echo "Unhandled NDK architecture ${ANDROID_NDK_ARCH}" - exit -1 - ;; - esac - - _hi="$HOST_IGNORE_PREFIX" - - cmake \ - -DCMAKE_SYSTEM_PROCESSOR=$cmakeProc \ - -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ - -DCMAKE_PREFIX_PATH="${PREFIX}" \ - -DCMAKE_SYSTEM_PREFIX_PATH="${PREFIX}" \ - -DCMAKE_INCLUDE_PATH="${PREFIX}/include" \ - -DCMAKE_SYSTEM_INCLUDE_PATH="${PREFIX}/include" \ - -DCMAKE_LIBRARY_PATH="${PREFIX}/lib" \ - -DCMAKE_SYSTEM_LIBRARY_PATH="${PREFIX}/lib" \ - -DCMAKE_INSTALL_PREFIX="${PREFIX}" \ - -DCMAKE_IGNORE_PATH="$_hi/include;$_hi/lib;$_hi/lib64" \ - $@ - - # It is probably ok to do not touch CMAKE_PROGRAM_PATH and - # CMAKE_SYSTEM_PROGRAM_PATH -} - -function git_source_get() -{ - sourceDir="$1" ; shift #$1 - sourceRepo="$1" ; shift #$2 - sourceVersion="$1" ; shift #$3 - # extra paramethers are treated as submodules - - [ -d "$sourceDir" ] && - { - pushd "$sourceDir" - actUrl="$(git remote get-url origin)" - [ "$actUrl" != "$sourceRepo" ] && rm -rf "${sourceDir}" - popd - } || true - - [ -d $sourceDir ] || git clone "$sourceRepo" "$sourceDir" - pushd $sourceDir - - git fetch --all - git reset --hard ${sourceVersion} - - while [ "$1" != "" ] ; do - git submodule update --init "$1" - pushd "$1" - git reset --hard - shift - popd - done - - popd -} - -declare -A TASK_REGISTER - -function task_register() -{ - TASK_REGISTER[$1]=true -} - -function task_unregister() -{ - # we may simply wipe them but we could benefit from keeping track of - # unregistered tasks too - TASK_REGISTER[$1]=false -} - -function task_logfile() -{ - echo "$REPORT_DIR/$1.log" -} - -function task_run() -{ - mTask="$1" ; shift - - [ "${TASK_REGISTER[$mTask]}" != "true" ] && - { - echo "Attempt to run not registered task $mTask $@" - return -1 - } - - logFile="$(task_logfile $mTask)" - if [ -f "$logFile" ] ; then - echo "Task $mTask already run more details at $logFile" - else - date | tee > "$logFile" - $mTask $@ |& tee --append "$logFile" - mRetval="${PIPESTATUS[0]}" - echo "Task $mTask return ${mRetval} more details at $logFile" - date | tee --append "$logFile" - return ${mRetval} - fi -} - -function task_zap() -{ - rm -f "$(task_logfile $1)" -} - -DUPLICATED_INCLUDES_LIST_FILE="${REPORT_DIR}/duplicated_includes_list" -DUPLICATED_INCLUDES_DIR="${REPORT_DIR}/duplicated_includes/" - -task_register install_android_sdk -install_android_sdk() -{ - tFile="sdk-tools-linux-${ANDROID_SDK_TOOLS_VERSION}.zip" - - verified_download "${tFile}" "${ANDROID_SDK_TOOLS_SHA256}" \ - "https://dl.google.com/android/repository/${tFile}" - - unzip "${tFile}" - mkdir -p "$ANDROID_SDK_PATH" - rm -rf "$ANDROID_SDK_PATH/tools/" - mv --verbose tools/ "$ANDROID_SDK_PATH/tools/" - - # Install Android SDK - yes | $ANDROID_SDK_PATH/tools/bin/sdkmanager --licenses && \ - $ANDROID_SDK_PATH/tools/bin/sdkmanager --update - $ANDROID_SDK_PATH/tools/bin/sdkmanager "platforms;android-$ANDROID_PLATFORM_VER" - $ANDROID_SDK_PATH/tools/bin/sdkmanager "build-tools;$ANDROID_SDK_VERSION" -} - -task_register install_android_ndk -install_android_ndk() -{ - tFile="android-ndk-${ANDROID_NDK_VERSION}-linux-x86_64.zip" - - verified_download "${tFile}" "${ANDROID_NDK_SHA256}" \ - "https://dl.google.com/android/repository/${tFile}" - - unzip "${tFile}" - mkdir -p "$ANDROID_NDK_PATH" - rm -rf "$ANDROID_NDK_PATH" - mv --verbose "android-ndk-${ANDROID_NDK_VERSION}/" "$ANDROID_NDK_PATH/" -} - -## More information available at https://android.googlesource.com/platform/ndk/+/ics-mr0/docs/STANDALONE-TOOLCHAIN.html -task_register bootstrap_toolchain -bootstrap_toolchain() -{ - rm -rf "${NATIVE_LIBS_TOOLCHAIN_PATH}" - ${ANDROID_NDK_PATH}/build/tools/make_standalone_toolchain.py --verbose \ - --arch ${ANDROID_NDK_ARCH} --install-dir ${NATIVE_LIBS_TOOLCHAIN_PATH} \ - --api ${ANDROID_PLATFORM_VER} - - # Avoid problems with arm64 some libraries installing on lib64 - ln -s "${PREFIX}/lib/" "${PREFIX}/lib64" - - pushd "${PREFIX}/include/" - find . -not -type d > "${DUPLICATED_INCLUDES_LIST_FILE}" - popd -} - -## This avoid include errors due to -isystem and -I ordering issue -task_register deduplicate_includes -deduplicate_includes() -{ - while read delFile ; do - mNewPath="${DUPLICATED_INCLUDES_DIR}/$delFile" - mkdir --verbose --parents "$(dirname "$mNewPath")" - mv --verbose "${PREFIX}/include/$delFile" "$mNewPath" - done < "${DUPLICATED_INCLUDES_LIST_FILE}" -} - -task_register reduplicate_includes -reduplicate_includes() -{ - pushd "${DUPLICATED_INCLUDES_DIR}" - find . -not -type d | while read delFile ; do - mv --verbose "${delFile}" "${PREFIX}/include/$delFile" - done - popd -} - -# $1 optional prefix prepended only if return value is not empty -# $2 optional suffix appended only if return value is not empty -task_register get_qt_arch -get_qt_arch() -{ - local QT_VERSION_COMP="$(echo $QT_VERSION | awk -F. '{print $1*1000000+$2*1000+$3}')" - local QT_ARCH="" - - # Qt >= 5.15.0 ships all Android architectures toghether - [ "$QT_VERSION_COMP" -lt "5015000" ] && - { - case "${ANDROID_NDK_ARCH}" in - "arm") - QT_ARCH="armv7" - ;; - "arm64") - QT_ARCH="arm64_v8a" - ;; - "x86") - QT_ARCH="x86" - ;; - esac - - echo "$1$QT_ARCH$2" - } -} - -task_register get_qt_dir -get_qt_dir() -{ - echo "${QT_INSTALL_PATH}/${QT_VERSION}/android$(get_qt_arch _)/" -} - -## More information available at https://wiki.qt.io/Online_Installer_4.x -task_register install_qt_android -install_qt_android() -{ - [ "$QT_INSTALLER_JWT_TOKEN" == "" ] && - { - echo "To run Qt installer QT_INSTALLER_JWT_TOKEN environement variable \ -need to be set to a valid JWT token see https://wiki.qt.io/Online_Installer_4.x" - return -1 - } - - QT_VERSION_CODE="$(echo $QT_VERSION | tr -d .)" - QT_INSTALLER="qt-unified-linux-x86_64-${QT_INSTALLER_VERSION}-online.run" - tMajDotMinVer="$(echo $QT_INSTALLER_VERSION | awk -F. '{print $1"."$2}')" - verified_download $QT_INSTALLER $QT_INSTALLER_SHA256 \ - "https://master.qt.io/archive/online_installers/${tMajDotMinVer}/${QT_INSTALLER}" - - chmod a+x ${QT_INSTALLER} - QT_QPA_PLATFORM=minimal ./${QT_INSTALLER} \ - install qt.qt5.${QT_VERSION_CODE}.android$(get_qt_arch _) \ - --accept-licenses --accept-obligations --confirm-command \ - --default-answer --no-default-installations \ - --root "${QT_INSTALL_PATH}" -} - -## More information available at retroshare://file?name=Android%20Native%20Development%20Kit%20Cookbook.pdf&size=29214468&hash=0123361c1b14366ce36118e82b90faf7c7b1b136 -task_register build_bzlib -build_bzlib() -{ - B_dir="bzip2-${BZIP2_SOURCE_VERSION}" - rm -rf $B_dir - - verified_download $B_dir.tar.gz $BZIP2_SOURCE_SHA256 \ - http://distfiles.gentoo.org/distfiles/bzip2-${BZIP2_SOURCE_VERSION}.tar.gz - - tar -xf $B_dir.tar.gz - cd $B_dir - sed -i "/^CC=.*/d" Makefile - sed -i "/^AR=.*/d" Makefile - sed -i "/^RANLIB=.*/d" Makefile - sed -i "/^LDFLAGS=.*/d" Makefile - sed -i "s/^all: libbz2.a bzip2 bzip2recover test/all: libbz2.a bzip2 bzip2recover/" Makefile - make -j${HOST_NUM_CPU} - make install PREFIX=${PREFIX} -# sed -i "/^CC=.*/d" Makefile-libbz2_so -# make -f Makefile-libbz2_so -j${HOST_NUM_CPU} -# cp libbz2.so.1.0.6 ${SYSROOT}/usr/lib/libbz2.so - cd .. -} - -## More information available at http://doc.qt.io/qt-5/opensslsupport.html -task_register build_openssl -build_openssl() -{ - B_dir="openssl-${OPENSSL_SOURCE_VERSION}" - rm -rf $B_dir - - verified_download $B_dir.tar.gz $OPENSSL_SOURCE_SHA256 \ - https://www.openssl.org/source/$B_dir.tar.gz - - tar -xf $B_dir.tar.gz - cd $B_dir -## We link openssl statically to avoid android silently sneaking in his own -## version of libssl.so (we noticed this because it had some missing symbol -## that made RS crash), the crash in some android version is only one of the -## possible problems the fact that android insert his own binary libssl.so pose -## non neglegible security concerns. - oBits="32" - [[ ${ANDROID_NDK_ARCH} =~ .*64.* ]] && oBits=64 - - ANDROID_NDK="${ANDROID_NDK_PATH}" PATH="${SYSROOT}/bin/:${PATH}" \ - ./Configure linux-generic${oBits} -fPIC --prefix="${PREFIX}" \ - --openssldir="${SYSROOT}/etc/ssl" -# sed -i 's/LIBNAME=$$i LIBVERSION=$(SHLIB_MAJOR).$(SHLIB_MINOR) \\/LIBNAME=$$i \\/g' Makefile -# sed -i '/LIBCOMPATVERSIONS=";$(SHLIB_VERSION_HISTORY)" \\/d' Makefile - - # Avoid documentation build which is unneded and time consuming - echo "exit 0; " > util/process_docs.pl - - make -j${HOST_NUM_CPU} - make install - rm -f ${PREFIX}/lib/libssl.so* - rm -f ${PREFIX}/lib/libcrypto.so* - cd .. -} - -task_register build_sqlite -build_sqlite() -{ - B_dir="sqlite-autoconf-${SQLITE_SOURCE_VERSION}" - rm -rf $B_dir - - verified_download $B_dir.tar.gz $SQLITE_SOURCE_SHA256 \ - https://www.sqlite.org/${SQLITE_SOURCE_YEAR}/$B_dir.tar.gz - - tar -xf $B_dir.tar.gz - cd $B_dir - ./configure --with-pic --prefix="${PREFIX}" --host=${cArch}-linux - make -j${HOST_NUM_CPU} - make install - rm -f ${PREFIX}/lib/libsqlite3.so* - cd .. -} - -task_register build_sqlcipher -build_sqlcipher() -{ - task_run build_sqlite - - B_dir="sqlcipher-${SQLCIPHER_SOURCE_VERSION}" - rm -rf $B_dir - - T_file="${B_dir}.tar.gz" - - verified_download $T_file $SQLCIPHER_SOURCE_SHA256 \ - https://github.com/sqlcipher/sqlcipher/archive/v${SQLCIPHER_SOURCE_VERSION}.tar.gz - - tar -xf $T_file - cd $B_dir -# case "${ANDROID_NDK_ARCH}" in -# "arm64") -# # SQLCipher config.sub is outdated and doesn't recognize newer architectures -# rm config.sub -# autoreconf --verbose --install --force -# automake --add-missing --copy --force-missing -# ;; -# esac - ./configure --with-pic --build=$(sh ./config.guess) \ - --host=${cArch}-linux \ - --prefix="${PREFIX}" --with-sysroot="${SYSROOT}" \ - --enable-tempstore=yes \ - --disable-tcl --disable-shared \ - CFLAGS="-DSQLITE_HAS_CODEC" LDFLAGS="${PREFIX}/lib/libcrypto.a" - make -j${HOST_NUM_CPU} - make install - cd .. -} - -task_register build_libupnp -build_libupnp() -{ - B_dir="pupnp-release-${LIBUPNP_SOURCE_VERSION}" - B_ext=".tar.gz" - B_file="${B_dir}${B_ext}" - rm -rf $B_dir - - verified_download $B_file $LIBUPNP_SOURCE_SHA256 \ - https://github.com/mrjimenez/pupnp/archive/release-${LIBUPNP_SOURCE_VERSION}${B_ext} - - tar -xf $B_file - cd $B_dir - ./bootstrap -## liupnp must be configured as static library because if not the linker will -## look for libthreadutils.so.6 at runtime that cannot be packaged on android -## as it supports only libname.so format for libraries, thus resulting in a -## crash at startup. - ./configure --with-pic --enable-static --disable-shared --disable-samples \ - --disable-largefile \ - --prefix="${PREFIX}" --host=${cArch}-linux - make -j${HOST_NUM_CPU} - make install - cd .. -} - -task_register build_rapidjson -build_rapidjson() -{ - B_dir="rapidjson-${RAPIDJSON_SOURCE_VERSION}" - D_file="${B_dir}.tar.gz" - verified_download $D_file $RAPIDJSON_SOURCE_SHA256 \ - https://github.com/Tencent/rapidjson/archive/v${RAPIDJSON_SOURCE_VERSION}.tar.gz - tar -xf $D_file - cp -r "${B_dir}/include/rapidjson/" "${PREFIX}/include/rapidjson" -} - -task_register build_restbed -build_restbed() -{ - S_dir="restbed" - B_dir="${S_dir}-build" - git_source_get "$S_dir" "$RESTBED_SOURCE_REPO" "${RESTBED_SOURCE_VERSION}" \ - "dependency/asio" "dependency/catch" - - rm -rf "$B_dir"; mkdir "$B_dir" - pushd "$B_dir" - andro_cmake -DBUILD_TESTS=OFF -DBUILD_SSL=OFF -B. -H../${S_dir} - make -j${HOST_NUM_CPU} - make install - popd -} - -task_register build_udp-discovery-cpp -build_udp-discovery-cpp() -{ - S_dir="udp-discovery-cpp" - [ -d $S_dir ] || git clone $UDP_DISCOVERY_CPP_SOURCE $S_dir - cd $S_dir - git checkout $UDP_DISCOVERY_CPP_VERSION - cd .. - - B_dir="udp-discovery-cpp-build" - rm -rf ${B_dir}; mkdir ${B_dir}; cd ${B_dir} - andro_cmake -B. -H../$S_dir - make -j${HOST_NUM_CPU} - cp libudp-discovery.a "${PREFIX}/lib/" - cp ../$S_dir/*.hpp "${PREFIX}/include/" - cd .. -} - -task_register build_xapian -build_xapian() -{ - B_dir="xapian-core-${XAPIAN_SOURCE_VERSION}" - D_file="$B_dir.tar.xz" - verified_download $D_file $XAPIAN_SOURCE_SHA256 \ - https://oligarchy.co.uk/xapian/${XAPIAN_SOURCE_VERSION}/$D_file - rm -rf $B_dir - tar -xf $D_file - cd $B_dir - B_endiannes_detection_failure_workaround="ac_cv_c_bigendian=no" - B_large_file="" - [ "${ANDROID_PLATFORM_VER}" -lt "24" ] && B_large_file="--disable-largefile" - ./configure ${B_endiannes_detection_failure_workaround} ${B_large_file} \ - --with-pic \ - --disable-backend-inmemory --disable-backend-remote \ - --disable--backend-chert --enable-backend-glass \ - --host=${cArch}-linux --enable-static --disable-shared \ - --prefix="${PREFIX}" --with-sysroot="${SYSROOT}" - make -j${HOST_NUM_CPU} - make install - cd .. -} - -task_register build_miniupnpc -build_miniupnpc() -{ - S_dir="miniupnpc-${MINIUPNPC_SOURCE_VERSION}" - B_dir="miniupnpc-${MINIUPNPC_SOURCE_VERSION}-build" - D_file="$S_dir.tar.gz" - verified_download $D_file $MINIUPNPC_SOURCE_SHA256 \ - http://miniupnp.free.fr/files/${D_file} - rm -rf $S_dir $B_dir - tar -xf $D_file - mkdir $B_dir - cd $B_dir - andro_cmake \ - -DUPNPC_BUILD_STATIC=TRUE \ - -DUPNPC_BUILD_SHARED=FALSE \ - -DUPNPC_BUILD_TESTS=FALSE \ - -DUPNPC_BUILD_SAMPLE=FALSE \ - -B. -S../$S_dir - make -j${HOST_NUM_CPU} - make install - cd .. -} - -task_register build_zlib -build_zlib() -{ - S_dir="zlib-${ZLIB_SOURCE_VERSION}" - B_dir="zlib-${ZLIB_SOURCE_VERSION}-build" - D_file="$S_dir.tar.xz" - verified_download $D_file $ZLIB_SOURCE_SHA256 \ - http://www.zlib.net/${D_file} - rm -rf $S_dir $B_dir - tar -xf $D_file - mkdir $B_dir - cd $B_dir - andro_cmake -B. -S../$S_dir - make -j${HOST_NUM_CPU} - make install - rm -f ${PREFIX}/lib/libz.so* - cd .. -} - -task_register build_libpng -build_libpng() -{ - task_run build_zlib - - S_dir="libpng-${LIBPNG_SOURCE_VERSION}" - B_dir="libpng-${LIBPNG_SOURCE_VERSION}-build" - D_file="$S_dir.tar.xz" - verified_download $D_file $LIBPNG_SOURCE_SHA256 \ - https://download.sourceforge.net/libpng/${D_file} - rm -rf $S_dir $B_dir - tar -xf $D_file - - # libm is part of bionic An android - sed -i -e 's/find_library(M_LIBRARY m)/set(M_LIBRARY "")/' $S_dir/CMakeLists.txt - - # Disable hardware acceleration as they are problematic for Android - # compilation and are not supported by all phones, it is necessary to fiddle - # with CMakeLists.txt as libpng 1.6.37 passing it as cmake options seems not - # working properly - # https://github.com/imagemin/optipng-bin/issues/97 - # https://github.com/opencv/opencv/issues/7600 - echo "add_definitions(-DPNG_ARM_NEON_OPT=0)" >> $S_dir/CMakeLists.txt - - mkdir $B_dir - pushd $B_dir - - HW_OPT="OFF" -# [ "$ANDROID_PLATFORM_VER" -ge "22" ] && HW_OPT="ON" - - andro_cmake \ - -DPNG_SHARED=OFF \ - -DPNG_STATIC=ON \ - -DPNG_TESTS=OFF \ - -DPNG_HARDWARE_OPTIMIZATIONS=$HW_OPT \ - -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \ - -B. -S../$S_dir - make -j${HOST_NUM_CPU} - make install - popd -} - -task_register build_libjpeg -build_libjpeg() -{ - S_dir="jpeg-${LIBJPEG_SOURCE_VERSION}" - D_file="jpegsrc.v${LIBJPEG_SOURCE_VERSION}.tar.gz" - verified_download $D_file $LIBJPEG_SOURCE_SHA256 \ - https://www.ijg.org/files/$D_file - rm -rf $S_dir - tar -xf $D_file - cd $S_dir - ./configure --with-pic --prefix="${PREFIX}" --host=${cArch}-linux - make -j${HOST_NUM_CPU} - make install - rm -f ${PREFIX}/lib/libjpeg.so* - cd .. -} - -task_register build_tiff -build_tiff() -{ - S_dir="tiff-${TIFF_SOURCE_VERSION}" - B_dir="${S_dir}-build" - D_file="tiff-${TIFF_SOURCE_VERSION}.tar.gz" - - verified_download $D_file $TIFF_SOURCE_SHA256 \ - https://download.osgeo.org/libtiff/${D_file} - - rm -rf $S_dir $B_dir - tar -xf $D_file - mkdir $B_dir - - # Disable tools building, not needed for retroshare, and depending on some - # OpenGL headers not available on Android - echo "" > $S_dir/tools/CMakeLists.txt - - # Disable tests building, not needed for retroshare, and causing linker - # errors - echo "" > $S_dir/test/CMakeLists.txt - - # Disable extra tools building, not needed for retroshare, and causing - # linker errors - echo "" > $S_dir/contrib/CMakeLists.txt - - # Disable more unneded stuff - echo "" > $S_dir/build/CMakeLists.txt - echo "" > $S_dir/html/CMakeLists.txt - echo "" > $S_dir/man/CMakeLists.txt - echo "" > $S_dir/port/CMakeLists.txt - - # Change to static library build - sed -i 's\add_library(tiff\add_library(tiff STATIC\' \ - $S_dir/libtiff/CMakeLists.txt - - cd $B_dir - #TODO: build dependecies to support more formats - andro_cmake \ - -Dlibdeflate=OFF -Djbig=OFF -Dlzma=OFF -Dzstd=OFF -Dwebp=OFF \ - -Djpeg12=OFF \ - -Dcxx=OFF \ - -B. -S../$S_dir - make -j${HOST_NUM_CPU} - make install - cd .. -} - -task_register build_cimg -build_cimg() -{ - task_run build_libpng - task_run build_libjpeg - task_run build_tiff - - S_dir="CImg-${CIMG_SOURCE_VERSION}" - D_file="CImg_${CIMG_SOURCE_VERSION}.zip" - - verified_download $D_file $CIMG_SOURCE_SHA256 \ - https://cimg.eu/files/${D_file} - - unzip -o $D_file - - cp --archive --verbose "$S_dir/CImg.h" "$PREFIX/include/" -} - -task_register build_phash -build_phash() -{ - task_run build_cimg - - S_dir="pHash" - B_dir="${S_dir}-build" - - git_source_get "$S_dir" "$PHASH_SOURCE_REPO" "${PHASH_SOURCE_VERSION}" - - rm -rf $B_dir; mkdir $B_dir ; pushd $B_dir - andro_cmake -DPHASH_DYNAMIC=OFF -DPHASH_STATIC=ON -B. -H../pHash - make -j${HOST_NUM_CPU} - make install - popd -} - -task_register fetch_jni_hpp -fetch_jni_hpp() -{ - local rDir="supportlibs/jni.hpp/" - - [ "$(ls "${RS_SRC_DIR}/${rDir}" | wc -l)" -gt "4" ] || - git -C ${RS_SRC_DIR} submodule update --init ${rDir} -} - -task_register build_mvptree -build_mvptree() -{ - S_dir="mvptree" - B_dir="${S_dir}-build" - - git_source_get "$S_dir" "$MVPTREE_SOURCE_REPO" "${MVPTREE_SOURCE_VERSION}" - rm -rf $B_dir; mkdir $B_dir ; pushd $B_dir - andro_cmake -B. -H../${S_dir} - make -j${HOST_NUM_CPU} - make install - popd -} - -task_register build_libretroshare -build_libretroshare() -{ - S_dir="/home/gio/Development/rs-develop/libretroshare" - B_dir="libretroshare-build" - -# -DCMAKE_SYSTEM_NAME="Android" \ -# -DCMAKE_ANDROID_NDK="$ANDROID_NDK_PATH" \ -# -DCMAKE_SYSTEM_VERSION=$ANDROID_PLATFORM_VER \ - -# -D RS_FORUM_DEEP_INDEX=ON -D RS_JSON_API=ON \ - - rm -rf $B_dir; mkdir $B_dir ; pushd $B_dir - andro_cmake -B. -H${S_dir} -DCMAKE_BUILD_TYPE=Release \ - -D RS_ANDROID=ON -D RS_WARN_DEPRECATED=OFF -D RS_WARN_LESS=ON \ - -D RS_LIBRETROSHARE_STATIC=OFF -D RS_LIBRETROSHARE_SHARED=ON \ - -D RS_BRODCAST_DISCOVERY=ON -D RS_EXPORT_JNI_ONLOAD=ON - make -j${HOST_NUM_CPU} - make install - popd -} - -task_register get_native_libs_toolchain_path -get_native_libs_toolchain_path() -{ - echo ${NATIVE_LIBS_TOOLCHAIN_PATH} -} - -task_register build_default_toolchain -build_default_toolchain() -{ - task_run bootstrap_toolchain || return $? - task_run build_bzlib || return $? - task_run build_openssl || return $? - task_run build_sqlcipher || return $? - task_run build_rapidjson || return $? -# task_run build_restbed || return $? -# task_run build_udp-discovery-cpp || return $? - task_run build_xapian || return $? - task_run build_miniupnpc || return $? - task_run build_phash || return $? -# task_run fetch_jni_hpp || return $? - task_run build_libretroshare || return $? -# task_run deduplicate_includes || return $? - task_run get_native_libs_toolchain_path || return $? -} - -if [ "$1" == "" ]; then - rm -rf "$REPORT_DIR" - mkdir -p "$REPORT_DIR" - cat "$0" > "$REPORT_DIR/build_script" - env > "$REPORT_DIR/build_env" - build_default_toolchain -else - # do not delete report directory in this case so we can reuse material - # produced by previous run, like deduplicated includes - mkdir -p "$REPORT_DIR" - while [ "$1" != "" ] ; do - task_zap $1 - task_run $1 || exit $? - shift - done -fi diff --git a/libretroshare/misc/Android/pull_sysroot.sh b/libretroshare/misc/Android/pull_sysroot.sh deleted file mode 100755 index d474610e4..000000000 --- a/libretroshare/misc/Android/pull_sysroot.sh +++ /dev/null @@ -1,90 +0,0 @@ -#!/bin/bash - -# Script to pull debugging sysroot from Android devices -# -# Copyright (C) 2020 Gioacchino Mazzurco -# Copyright (C) 2020 AsociaciĆ³n Civil Altermundi -# -# This program is free software: you can redistribute it and/or modify it under -# the terms of the GNU Affero General Public License as published by the -# Free Software Foundation, version 3. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. -# See the GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License along -# with this program. If not, see - -<<"ASCIIDOC" - -Pull files from Android device to prepare a debugging sysroot -Inspired by: -https://fw4spl-org.github.io/fw4spl-blog/2015/07/27/Native-debugging-on-Android-with-QtCreator.html - -The goal is to have a local copy of the sysroot of the connected device. -For that we use the command `adb pull ` - -We will get a copy of: - -- `/system/lib/` -- `/vendor/lib/` -- `libc.so` -- `libcutils.so` - -As well as the binaries `linker` and `app_process` - -IMPORTANT: -from one device to another, the remote file `app_process` can be a binary file -or a symlink to a binary file - which is NOT ok for us. -That's so we will try to pull every known possible variants of `app_process`, -e.g. `app_process32` or `app_process_init` - -ASCIIDOC - - -## Define default value for variable, take two arguments, $1 variable name, -## $2 default variable value, if the variable is not already define define it -## with default value. -function define_default_value() -{ - VAR_NAME="${1}" - DEFAULT_VALUE="${2}" - - [ -z "${!VAR_NAME}" ] && export ${VAR_NAME}="${DEFAULT_VALUE}" -} - -define_default_value ANDROID_SERIAL "$(adb devices | head -n 2 | tail -n 1 | awk '{print $1}')" -define_default_value DEBUG_SYSROOT "${HOME}/Builds/debug_sysroot/${ANDROID_SERIAL}/" - -rm -rf "${DEBUG_SYSROOT}" - -for mDir in "/system/lib/" "/vendor/lib/"; do - mkdir -p "${DEBUG_SYSROOT}/${mDir}" - # adb pull doesn't behave like rsync dirA/ dirB/ so avoid nesting the - # directory by deleting last one before copying - rmdir "${DEBUG_SYSROOT}/${mDir}" - adb pull "${mDir}" "${DEBUG_SYSROOT}/${mDir}" -done - -# Retrieve the specific binaries - some of these adb commands will fail, since -# some files may not exist, but that's ok. - -mkdir -p "${DEBUG_SYSROOT}/system/bin/" -for mBin in "/system/bin/linker" "/system/bin/app_process" \ - "/system/bin/app_process_init" "/system/bin/app_process32" \ - "/system/bin/app_process64" ; do - adb pull "${mBin}" "${DEBUG_SYSROOT}/${mBin}" -done - -# Verify which variants of the specific binaries could be pulled -echo -echo "Found the following specific binaries:" -echo -ls -1 "${DEBUG_SYSROOT}/system/bin/"* -ls -1 "${DEBUG_SYSROOT}/system/lib/libc.so"* -ls -1 "${DEBUG_SYSROOT}/system/lib/libcutils.so"* -echo - -echo DEBUG_SYSROOT="${DEBUG_SYSROOT}" diff --git a/libretroshare/misc/Android/start_gdbserver.sh b/libretroshare/misc/Android/start_gdbserver.sh deleted file mode 100755 index 1fd751e67..000000000 --- a/libretroshare/misc/Android/start_gdbserver.sh +++ /dev/null @@ -1,116 +0,0 @@ -#!/bin/bash - -# Script to start gdbserver on Android device and attach to retroshare-service -# -# Copyright (C) 2020 Gioacchino Mazzurco -# Copyright (C) 2020 AsociaciĆ³n Civil Altermundi -# -# This program is free software: you can redistribute it and/or modify it under -# the terms of the GNU Affero General Public License as published by the -# Free Software Foundation, version 3. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. -# See the GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License along -# with this program. If not, see - -<<"ASCIIDOC" - -Start gdbserver on Android device and attach it to the retroshare service -process - -Inspired by: -https://fw4spl-org.github.io/fw4spl-blog/2015/07/27/Native-debugging-on-Android-with-QtCreator.html - -ASCIIDOC - - -## Define default value for variable, take two arguments, $1 variable name, -## $2 default variable value, if the variable is not already define define it -## with default value. -function define_default_value() -{ - VAR_NAME="${1}" - DEFAULT_VALUE="${2}" - - [ -z "${!VAR_NAME}" ] && export ${VAR_NAME}="${DEFAULT_VALUE}" || true -} - -define_default_value ANDROID_APK_PACKAGE "org.retroshare.service" -define_default_value ANDROID_PROCESS_NAME "org.retroshare.service:rs" -define_default_value ANDROID_INSTALL_PATH "" -define_default_value LIB_GDB_SERVER_PATH "" -define_default_value ANDROID_SERIAL "$(adb devices | head -n 2 | tail -n 1 | awk '{print $1}')" -define_default_value GDB_SERVER_PORT 5039 - -adb_ushell() -{ - adb shell run-as ${ANDROID_APK_PACKAGE} $@ -} - -[ -z "${ANDROID_INSTALL_PATH}" ] && -{ - ANDROID_INSTALL_PATH="$(adb_ushell pm path "${ANDROID_APK_PACKAGE}")" - ANDROID_INSTALL_PATH="$(dirname ${ANDROID_INSTALL_PATH#"package:"})" - [ -z "${ANDROID_INSTALL_PATH}" ] && - cat < -# Copyright (C) 2021 AsociaciĆ³n Civil Altermundi -# -# SPDX-License-Identifier: CC0-1.0 - -list( - APPEND RS_PUBLIC_HEADERS - retroshare/rsexpr.h - retroshare/rsgxsdistsync.h - retroshare/rsiface.h - retroshare/rsrtt.h - retroshare/rsbanlist.h - retroshare/rsconfig.h - retroshare/rsdisc.h - retroshare/rsflags.h - retroshare/rsgrouter.h - retroshare/rsgxsflags.h - retroshare/rsgxsservice.h - retroshare/rsgxstrans.h - retroshare/rsgxstunnel.h - retroshare/rsids.h - retroshare/rsnotify.h - retroshare/rsphoto.h - retroshare/rsplugin.h - retroshare/rsreputations.h - retroshare/rsservicecontrol.h - retroshare/rstokenservice.h - retroshare/rsturtle.h - retroshare/rsgossipdiscovery.h - retroshare/rsgxscommon.h - retroshare/rsposted.h - retroshare/rsstatus.h - retroshare/rsversion.h - retroshare/rsgxsifacehelper.h - retroshare/rshistory.h - retroshare/rsidentity.h - retroshare/rsmsgs.h - retroshare/rsgxschannels.h - retroshare/rsgxscircles.h - retroshare/rsgxsiface.h - retroshare/rsgxsifacetypes.h - retroshare/rstypes.h - retroshare/rsgxsforums.h - retroshare/rsevents.h - retroshare/rsfiles.h - retroshare/rsinit.h - retroshare/rspeers.h ) - -list( - APPEND RS_SOURCES - chat/distantchat.cc - chat/p3chatservice.cc - chat/rschatitems.cc - chat/distributedchat.cc - crypto/chacha20.cpp - crypto/hashstream.cc - crypto/rsaes.cc - crypto/rscrypto.cpp ) - -if(RS_BITDHT) - list( - APPEND RS_PUBLIC_HEADERS - retroshare/rsdht.h ) - - list( - APPEND RS_SOURCES - dht/connectstatebox.cc - dht/p3bitdht.cc - dht/p3bitdht_interface.cc - dht/p3bitdht_peernet.cc - dht/p3bitdht_peers.cc - dht/p3bitdht_relay.cc ) -endif(RS_BITDHT) - -list( - APPEND RS_SOURCES - file_sharing/filelist_io.cc - file_sharing/rsfilelistitems.cc - file_sharing/file_tree.cc - file_sharing/directory_updater.cc - file_sharing/p3filelists.cc - file_sharing/hash_cache.cc - file_sharing/dir_hierarchy.cc - file_sharing/directory_storage.cc - ft/ftchunkmap.cc - ft/ftfilecreator.cc - ft/ftfileprovider.cc - ft/ftfilesearch.cc - ft/ftturtlefiletransferitem.cc - ft/fttransfermodule.cc - ft/ftcontroller.cc - ft/ftdatamultiplex.cc - ft/ftextralist.cc - ft/ftserver.cc ) - -list( - APPEND RS_SOURCES - grouter/groutermatrix.cc - grouter/grouteritems.cc - grouter/p3grouter.cc ) - -list( - APPEND RS_SOURCES - gxs/rsgxsdata.cc - gxs/rsgxsrequesttypes.cc - gxs/gxssecurity.cc - gxs/gxstokenqueue.cc - gxs/rsdataservice.cc - gxs/rsgxsdataaccess.cc - gxs/rsgxsnetutils.cc - gxs/rsgxsnettunnel.cc - gxs/rsgxsutil.cc - gxs/rsnxsobserver.cpp - gxs/rsgenexchange.cc - gxs/rsgxsnetservice.cc ) - -list( - APPEND RS_SOURCES - gxstrans/p3gxstransitems.cc - gxstrans/p3gxstrans.cc ) - -list( - APPEND RS_SOURCES - gxstunnel/rsgxstunnelitems.cc - gxstunnel/p3gxstunnel.cc ) - -if(RS_JSON_API) - list( - APPEND RS_PUBLIC_HEADERS - retroshare/rsjsonapi.h ) - - list( - APPEND RS_SOURCES - jsonapi/jsonapi.cpp ) -endif(RS_JSON_API) - -list( - APPEND RS_SOURCES - pgp/pgpkeyutil.cc - pgp/pgpauxutils.cc - pgp/pgphandler.cc - pgp/rscertificate.cc ) - -#./plugins/dlfcn_win32.cc -#./plugins/dlfcn_win32.h -#./plugins/pluginmanager.h -#./plugins/rscacheservice.h -#./plugins/rspqiservice.h -#./plugins/pluginmanager.cc - -list( - APPEND RS_SOURCES - pqi/pqibin.cc - pqi/pqiipset.cc - pqi/pqiloopback.cc - pqi/pqimonitor.cc - pqi/pqipersongrp.cc - pqi/pqiqos.cc - pqi/pqiqosstreamer.cc - pqi/pqisslproxy.cc - pqi/pqistore.cc - pqi/authgpg.cc - pqi/p3cfgmgr.cc - pqi/p3notify.cc - pqi/p3servicecontrol.cc - pqi/pqinetstatebox.cc - pqi/pqiperson.cc - pqi/pqiservice.cc - pqi/pqissllistener.cc - pqi/pqissludp.cc - pqi/pqithreadstreamer.cc - pqi/sslfns.cc - pqi/authssl.cc - pqi/p3historymgr.cc - pqi/p3linkmgr.cc - pqi/pqihandler.cc - pqi/pqistreamer.cc - pqi/p3netmgr.cc - pqi/p3peermgr.cc - pqi/pqinetwork.cc - pqi/pqissl.cc - pqi/pqisslpersongrp.cc ) - -#./pqi/pqissli2psam3.cpp -#./pqi/pqissli2psam3.h - -list( - APPEND RS_SOURCES - rsitems/rsbanlistitems.cc - rsitems/rsbwctrlitems.cc - rsitems/rsconfigitems.cc - rsitems/rsfiletransferitems.cc - rsitems/rsgxscommentitems.cc - rsitems/rsgxsforumitems.cc - rsitems/rsgxsiditems.cc - rsitems/rsgxsrecognitems.cc - rsitems/rsgxsreputationitems.cc - rsitems/rsgxsupdateitems.cc - rsitems/rshistoryitems.cc - rsitems/rsrttitems.cc - rsitems/rsserviceinfoitems.cc ) - -#retroshare/rswiki.h -#./rsitems/rswikiitems.cc -#./rsitems/rswikiitems.h -#./rsitems/rswireitems.h - -list( - APPEND RS_SOURCES - rsitems/rsgxschannelitems.cc - rsitems/rsgxscircleitems.cc - rsitems/rsgxsitems.cc - rsitems/rsmsgitems.cc ) - -#./rsitems/rsphotoitems.cc -#./rsitems/rsphotoitems.h -#./rsitems/rsposteditems.cc -#./rsitems/rsposteditems.h -#./rsitems/rswireitems.cc -#retroshare/rswire.h - -list( - APPEND RS_SOURCES - rsitems/rsnxsitems.cc ) - -list( - APPEND RS_SOURCES - rsserver/p3status.cc - rsserver/p3face-config.cc - rsserver/p3face-info.cc - rsserver/p3history.cc - rsserver/p3serverconfig.cc - rsserver/rsloginhandler.cc - rsserver/p3face-server.cc - rsserver/p3msgs.cc - rsserver/p3peers.cc - rsserver/rsaccounts.cc - rsserver/rsinit.cc ) - -list( - APPEND RS_SOURCES - serialiser/rsbaseserial.cc - serialiser/rsserializable.cc - serialiser/rstlvaddrs.cc - serialiser/rstlvbanlist.cc - serialiser/rstlvbase.cc - serialiser/rstlvbinary.cc - serialiser/rstlvfileitem.cc - serialiser/rstlvgenericmap.inl - serialiser/rstlvgenericparam.cc - serialiser/rstlvidset.cc - serialiser/rstlvimage.cc - serialiser/rstlvitem.cc - serialiser/rstlvkeys.cc - serialiser/rstlvkeyvalue.cc - serialiser/rstlvstring.cc - serialiser/rsserializer.cc - serialiser/rstypeserializer.cc - serialiser/rsserial.cc ) - -# ./services/autoproxy -#./services/autoproxy/p3i2psam3.cpp -#./services/autoproxy/p3i2psam3.h - -list( - APPEND RS_SOURCES - services/autoproxy/rsautoproxymonitor.cc - services/p3bwctrl.cc - services/p3heartbeat.cc - services/p3service.cc - services/p3serviceinfo.cc - services/p3statusservice.cc - services/p3banlist.cc - services/p3rtt.cc - services/rseventsservice.cc - services/p3gxscircles.cc - services/p3gxscommon.cc - services/p3gxsreputation.cc - services/p3msgservice.cc - services/p3idservice.cc - services/p3gxschannels.cc - services/p3gxsforums.cc ) - -#./services/p3wiki.cc -#./services/p3wiki.h -#./services/p3wire.cc -#./services/p3wire.h - -#./services/p3photoservice.cc -#./services/p3photoservice.h -#./services/p3postbase.cc -#./services/p3postbase.h -#./services/p3posted.cc -#./services/p3posted.h - -if(RS_BRODCAST_DISCOVERY) - list( - APPEND RS_PUBLIC_HEADERS - retroshare/rsbroadcastdiscovery.h ) - - list( - APPEND RS_SOURCES - services/broadcastdiscoveryservice.cc ) -endif(RS_BRODCAST_DISCOVERY) - -list( - APPEND RS_SOURCES - tcponudp/tcppacket.cc - tcponudp/tcpstream.cc - tcponudp/tou.cc - tcponudp/udppeer.cc - tcponudp/bss_tou.cc - tcponudp/udprelay.cc ) - -if(RS_BITDHT_STUNNER) - list( - APPEND RS_SOURCES - tcponudp/udpstunner.cc ) -endif(RS_BITDHT_STUNNER) - -list( - APPEND RS_SOURCES - turtle/rsturtleitem.cc - turtle/p3turtle.cc ) - -list( - APPEND RS_SOURCES -# util/contentvalue.cc -# util/exampletst.c -# util/rsdbbind.cc -# util/rsdiscspace.cc - util/rsexpr.cc - util/rsprint.cc -# util/rsrecogn.cc -# util/rssharedptr.h -# util/rstickevent.cc - util/rstime.cc - util/smallobject.cc -# util/retrodb.cc - util/rsbase64.cc - util/rsjson.cc -# util/rskbdinput.cc - util/rsrandom.cc - util/rsstring.cc - util/rsurl.cc - util/folderiterator.cc - util/rsdir.cc - util/rsfile.cc - util/dnsresolver.cc - util/extaddrfinder.cc - util/rsdebug.cc - util/rsdnsutils.cc - util/rsnet.cc - util/rsnet_ss.cc - util/rsthreads.cc ) - -# util/i2pcommon.cpp -# util/i2pcommon.h - -if(RS_FORUM_DEEP_INDEX) - list( - APPEND RS_SOURCES - deep_search/commonutils.cpp - deep_search/forumsindex.cpp ) -endif(RS_FORUM_DEEP_INDEX) - - -#./deep_search/filesflacindexer.hpp -#./deep_search/filesoggindexer.hpp -#./deep_search/filestaglibindexer.hpp -#./deep_search/filesindex.cpp -#./deep_search/filesindex.hpp -#./deep_search/channelsindex.cpp -#./deep_search/channelsindex.hpp - -list( - APPEND RS_SOURCES - gossipdiscovery/gossipdiscoveryitems.cc - gossipdiscovery/p3gossipdiscovery.cc ) - -if(RS_MINIUPNPC) -list( - APPEND RS_SOURCES - rs_upnp/upnphandler_miniupnp.cc ) -endif(RS_MINIUPNPC) - -#./rs_upnp/UPnPBase.cpp -#./rs_upnp/upnphandler_libupnp.cc -#./rs_upnp/upnptest.cc -#./rs_upnp/upnputil.cc - -#if(CMAKE_SYSTEM_NAME STREQUAL "Android") -if(RS_ANDROID) - list( - APPEND RS_SOURCES - rs_android/errorconditionwrap.cpp - rs_android/retroshareserviceandroid.cpp - rs_android/rsjni.cpp ) -endif() diff --git a/libretroshare/src/Doxyfile b/libretroshare/src/Doxyfile deleted file mode 100644 index 0f5cec54a..000000000 --- a/libretroshare/src/Doxyfile +++ /dev/null @@ -1,1633 +0,0 @@ -# SPDX-FileCopyrightText: (C) 2004-2019 Retroshare Team -# SPDX-License-Identifier: CC0-1.0 - -# Doxyfile 1.7.1 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = "RetroShare libretroshare" - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = /var/www/notdefine/retroshare/libretroshare - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. - -CREATE_SUBDIRS = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, -# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = YES - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) - -JAVADOC_AUTOBRIEF = NO - -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 8 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given extension. -# Doxygen has a built-in mapping, but you can override or extend it using this -# tag. The format is ext=language, where ext is a file extension, and language -# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, -# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make -# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C -# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions -# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. - -EXTENSION_MAPPING = - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen to replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. - -TYPEDEF_HIDES_STRUCT = NO - -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penality. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will rougly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols - -SYMBOL_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = YES - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = YES - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = YES - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = YES - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespace are hidden. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen -# will list include files with double quotes in the documentation -# rather than with sharp brackets. - -FORCE_LOCAL_INCLUDES = NO - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen -# will sort the (brief and detailed) documentation of class members so that -# constructors and destructors are listed first. If set to NO (the default) -# the constructors will appear in the respective orders defined by -# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. -# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO -# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = YES - -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = YES - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. -# This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated -# output files in an output format independent way. The create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. -# You can optionally specify a file name after the option, if omitted -# DoxygenLayout.xml will be used as the name of the layout file. - -LAYOUT_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be abled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. - -WARN_NO_PARAMDOC = NO - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 - -FILE_PATTERNS = - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are excluded -# from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. -# If FILTER_PATTERNS is specified, this tag will be -# ignored. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. -# Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. -# The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. -# Otherwise they will link to the documentation. - -REFERENCES_LINK_SOURCE = YES - -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = NO - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = - -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. -# Doxygen will adjust the colors in the stylesheet and background images -# according to this color. Hue is specified as an angle on a colorwheel, -# see http://en.wikipedia.org/wiki/Hue for more information. -# For instance the value 0 represents red, 60 is yellow, 120 is green, -# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. -# The allowed range is 0 to 359. - -HTML_COLORSTYLE_HUE = 220 - -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of -# the colors in the HTML output. For a value of 0 the output will use -# grayscales only. A value of 255 will produce the most vivid colors. - -HTML_COLORSTYLE_SAT = 100 - -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to -# the luminance component of the colors in the HTML output. Values below -# 100 gradually make the output lighter, whereas values above 100 make -# the output darker. The value divided by 100 is the actual gamma applied, -# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, -# and 100 does not change the gamma. - -HTML_COLORSTYLE_GAMMA = 80 - -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting -# this to NO can help when comparing the output of multiple runs. - -HTML_TIMESTAMP = YES - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). - -HTML_DYNAMIC_SECTIONS = YES - -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. - -GENERATE_DOCSET = NO - -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify -# the documentation publisher. This should be a reverse domain-name style -# string, e.g. com.mycompany.MyDocSet.documentation. - -DOCSET_PUBLISHER_ID = org.doxygen.Publisher - -# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. - -DOCSET_PUBLISHER_NAME = Publisher - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. - -CHM_INDEX_ENCODING = - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated -# that can be used as input for Qt's qhelpgenerator to generate a -# Qt Compressed Help (.qch) of the generated HTML documentation. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace - -QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders - -QHP_VIRTUAL_FOLDER = doc - -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to -# add. For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see -# -# Qt Help Project / Custom Filters. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's -# filter section matches. -# -# Qt Help Project / Filter Attributes. - -QHP_SECT_FILTER_ATTRS = - -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. - -QHG_LOCATION = - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files -# will be generated, which together with the HTML files, form an Eclipse help -# plugin. To install this plugin and make it available under the help contents -# menu in Eclipse, the contents of the directory containing the HTML and XML -# files needs to be copied into the plugins directory of eclipse. The name of -# the directory within the plugins directory should be the same as -# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before -# the help appears. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have -# this name. - -ECLIPSE_DOC_ID = org.doxygen.Project - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 4 - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to YES, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). -# Windows users are probably better off using the HTML help feature. - -GENERATE_TREEVIEW = NONE - -# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list. - -USE_INLINE_TREES = NO - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open -# links to external symbols imported via tag files in a separate window. - -EXT_LINKS_IN_WINDOW = NO - -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. - -FORMULA_FONTSIZE = 10 - -# Use the FORMULA_TRANPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are -# not supported properly for IE 6.0, but are supported on all modern browsers. -# Note that when changing this option you need to delete any form_*.png files -# in the HTML output before the changes have effect. - -FORMULA_TRANSPARENT = YES - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box -# for the HTML output. The underlying search engine uses javascript -# and DHTML and should work on any modern browser. Note that when using -# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets -# (GENERATE_DOCSET) there is already a search function so this one should -# typically be disabled. For large projects the javascript based search engine -# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. - -SEARCHENGINE = YES - -# When the SERVER_BASED_SEARCH tag is enabled the search engine will be -# implemented using a PHP enabled web server instead of at the web client -# using Javascript. Doxygen will generate the search PHP script and index -# file to put on the web server. The advantage of the server -# based approach is that it scales better to large projects and allows -# full text search. The disadvances is that it is more difficult to setup -# and does not have live searching capabilities. - -SERVER_BASED_SEARCH = NO - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. -# Note that when enabling USE_PDFLATEX this option is only used for -# generating bitmaps for formulas in the HTML output, but not in the -# Makefile that is written to the output directory. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4wide - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = YES - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = YES - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -# If LATEX_SOURCE_CODE is set to YES then doxygen will include -# source code with syntax highlighting in the LaTeX output. -# Note that which sources are shown also depends on other settings -# such as SOURCE_BROWSER. - -LATEX_SOURCE_CODE = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. -# This is useful -# if you want to understand what is going on. -# On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. - -PREDEFINED = - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse -# the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option is superseded by the HAVE_DOT option below. This is only a -# fallback. It is recommended to install and use dot, since it yields more -# powerful graphs. - -CLASS_DIAGRAMS = YES - -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see -# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -MSCGEN_PATH = - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = YES - -# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is -# allowed to run in parallel. When set to 0 (the default) doxygen will -# base this on the number of processors available in the system. You can set it -# explicitly to a value larger than 0 to get control over the balance -# between CPU load and processing speed. - -DOT_NUM_THREADS = 0 - -# By default doxygen will write a font called FreeSans.ttf to the output -# directory and reference it in all dot files that doxygen generates. This -# font does not include all possible unicode characters however, so when you need -# these (or just want a differently looking font) you can specify the font name -# using DOT_FONTNAME. You need need to make sure dot is able to find the font, -# which can be done by putting it in a standard location or by setting the -# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory -# containing the font. - -DOT_FONTNAME = FreeSans - -# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. -# The default size is 10pt. - -DOT_FONTSIZE = 10 - -# By default doxygen will tell dot to use the output directory to look for the -# FreeSans.ttf font (which doxygen will put there itself). If you specify a -# different font using DOT_FONTNAME you can set the path where dot -# can find it using this tag. - -DOT_FONTPATH = - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for groups, showing the direct groups dependencies - -GROUP_GRAPHS = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = YES - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH and HAVE_DOT options are set to YES then -# doxygen will generate a call dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable call graphs -# for selected functions only using the \callgraph command. - -CALL_GRAPH = YES - -# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then -# doxygen will generate a caller dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable caller -# graphs for selected functions only using the \callergraph command. - -CALLER_GRAPH = YES - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include -# relations between the files in the directories. - -DIRECTORY_GRAPH = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. - -DOT_IMAGE_FORMAT = png - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found in the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the -# number of direct children of the root node in a graph is already larger than -# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note -# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. - -DOT_GRAPH_MAX_NODES = 50 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by -# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. - -MAX_DOT_GRAPH_DEPTH = 0 - -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not -# seem to support this out of the box. Warning: Depending on the platform used, -# enabling this option may lead to badly anti-aliased labels on the edges of -# a graph (i.e. they become hard to read). - -DOT_TRANSPARENT = YES - -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) -# support this, this feature is disabled by default. - -DOT_MULTI_TARGETS = NO - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES diff --git a/libretroshare/src/chat/distantchat.cc b/libretroshare/src/chat/distantchat.cc deleted file mode 100644 index 621e92229..000000000 --- a/libretroshare/src/chat/distantchat.cc +++ /dev/null @@ -1,389 +0,0 @@ -/******************************************************************************* - * libretroshare/src/chat: distantchat.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include -#include - -#include "openssl/rand.h" -#include "openssl/dh.h" -#include "openssl/err.h" - -#include "crypto/rsaes.h" -#include "util/rsmemory.h" -#include "util/rsprint.h" - -#include "rsitems/rsmsgitems.h" - -#include "retroshare/rsmsgs.h" -#include "retroshare/rsidentity.h" -#include "retroshare/rsiface.h" - -#include "rsserver/p3face.h" -#include "services/p3idservice.h" -#include "gxs/gxssecurity.h" -#include "turtle/p3turtle.h" -#include "retroshare/rsids.h" -#include "distantchat.h" - -//#define DEBUG_DISTANT_CHAT - -#ifdef DEBUG_DISTANT_CHAT - -#include - -uint32_t msecs_of_day() -{ - timeval tv ; - gettimeofday(&tv,NULL) ; - return tv.tv_usec / 1000 ; -} -#define DISTANT_CHAT_DEBUG() std::cerr << time(NULL) << "." << std::setfill('0') << std::setw(3) << msecs_of_day() << " : DISTANT_CHAT : " << __FUNCTION__ << " : " -#endif - -//static const uint32_t DISTANT_CHAT_KEEP_ALIVE_TIMEOUT = 6 ; // send keep alive packet so as to avoid tunnel breaks. - -//static const uint32_t RS_DISTANT_CHAT_DH_STATUS_UNINITIALIZED = 0x0000 ; -//static const uint32_t RS_DISTANT_CHAT_DH_STATUS_HALF_KEY_DONE = 0x0001 ; -//static const uint32_t RS_DISTANT_CHAT_DH_STATUS_KEY_AVAILABLE = 0x0002 ; - -static const uint32_t DISTANT_CHAT_GXS_TUNNEL_SERVICE_ID = 0xa0001 ; - -DistantChatService::DistantChatService() : - // default: accept everyone - mDistantChatPermissions(RS_DISTANT_CHAT_CONTACT_PERMISSION_FLAG_FILTER_NONE), - mGxsTunnels(nullptr), mDistantChatMtx("distant chat") {} - -void DistantChatService::connectToGxsTunnelService(RsGxsTunnelService *tr) -{ - mGxsTunnels = tr ; - tr->registerClientService(DISTANT_CHAT_GXS_TUNNEL_SERVICE_ID,this) ; -} - -bool DistantChatService::handleOutgoingItem(RsChatItem *item) -{ - RsGxsTunnelId tunnel_id ; - - { - RS_STACK_MUTEX(mDistantChatMtx) ; - - std::map::const_iterator it=mDistantChatContacts.find(DistantChatPeerId(item->PeerId())); - - if(it == mDistantChatContacts.end()) - return false ; - } - -#ifdef CHAT_DEBUG - DISTANT_CHAT_DEBUG() << "p3ChatService::handleOutgoingItem(): sending to " << item->PeerId() << ": interpreted as a distant chat virtual peer id." << std::endl; -#endif - - uint32_t size = RsChatSerialiser().size(item) ; - RsTemporaryMemory mem(size) ; - - if(!RsChatSerialiser().serialise(item,mem,&size)) - { - std::cerr << "(EE) serialisation error. Something's really wrong!" << std::endl; - return false; - } -#ifdef DEBUG_DISTANT_CHAT - DISTANT_CHAT_DEBUG() << " sending: " << RsUtil::BinToHex(mem,size,100) << std::endl; - DISTANT_CHAT_DEBUG() << " size: " << std::dec << size << std::endl; - DISTANT_CHAT_DEBUG() << " hash: " << RsDirUtil::sha1sum(mem,size) << std::endl; -#endif - - mGxsTunnels->sendData( RsGxsTunnelId(item->PeerId()),DISTANT_CHAT_GXS_TUNNEL_SERVICE_ID,mem,size); - return true; -} - -void DistantChatService::handleRecvChatStatusItem(RsChatStatusItem *cs) -{ - if(cs->flags & RS_CHAT_FLAG_CONNEXION_REFUSED) - { -#ifdef DEBUG_DISTANT_CHAT - DISTANT_CHAT_DEBUG() << "(II) Distant chat: received notification that peer refuses conversation." << std::endl; -#endif - RsServer::notify()->notifyChatStatus(ChatId(DistantChatPeerId(cs->PeerId())),"Connexion refused by distant peer!") ; - } - - if(cs->flags & RS_CHAT_FLAG_CLOSING_DISTANT_CONNECTION) - markDistantChatAsClosed(DistantChatPeerId(cs->PeerId())) ; - - // nothing more to do, because the decryption routing will update the last_contact time when decrypting. - - if(cs->flags & RS_CHAT_FLAG_KEEP_ALIVE) - std::cerr << "DistantChatService::handleRecvChatStatusItem(): received keep alive packet for inactive chat! peerId=" << cs->PeerId() << std::endl; -} - -bool DistantChatService::acceptDataFromPeer(const RsGxsId& gxs_id,const RsGxsTunnelId& tunnel_id,bool am_I_client_side) -{ - if(am_I_client_side) // always accept distant chat when we're the client side. - return true ; - - bool res = true ; - - if(mDistantChatPermissions & RS_DISTANT_CHAT_CONTACT_PERMISSION_FLAG_FILTER_NON_CONTACTS) - res = (rsIdentity!=NULL) && rsIdentity->isARegularContact(gxs_id) ; - - if(mDistantChatPermissions & RS_DISTANT_CHAT_CONTACT_PERMISSION_FLAG_FILTER_EVERYBODY) - res = false ; - - if(!res) - { -#ifdef DEBUG_DISTANT_CHAT - DISTANT_CHAT_DEBUG() << "(II) refusing distant chat from peer " << gxs_id << ". Sending a notification back to tunnel " << tunnel_id << std::endl; -#endif - RsChatStatusItem *item = new RsChatStatusItem ; - item->flags = RS_CHAT_FLAG_CONNEXION_REFUSED ; - item->status_string.clear() ; // is not used yet! But could be set in GUI to some message (??). - item->PeerId(RsPeerId(tunnel_id)) ; - - // we do not use handleOutGoingItem() because there's no distant chat contact, as the chat is refused. - - uint32_t size = RsChatSerialiser().size(item) ; - RsTemporaryMemory mem(size) ; - - if(!RsChatSerialiser().serialise(item,mem,&size)) - { - std::cerr << "(EE) serialisation error. Something's really wrong!" << std::endl; - return false; - } - -#ifdef DEBUG_DISTANT_CHAT - DISTANT_CHAT_DEBUG() << " sending: " << RsUtil::BinToHex(mem,size,100) << std::endl; - DISTANT_CHAT_DEBUG() << " size: " << std::dec << std::endl; - DISTANT_CHAT_DEBUG() << " hash: " << RsDirUtil::sha1sum(mem,size) << std::endl; -#endif - - mGxsTunnels->sendData( RsGxsTunnelId(item->PeerId()),DISTANT_CHAT_GXS_TUNNEL_SERVICE_ID,mem,size); - } - - return res ; -} - -void DistantChatService::notifyTunnelStatus( const RsGxsTunnelId& tunnel_id, uint32_t tunnel_status ) -{ -#ifdef DEBUG_DISTANT_CHAT - DISTANT_CHAT_DEBUG() << "DistantChatService::notifyTunnelStatus(): got notification " << std::hex << tunnel_status << std::dec << " for tunnel " << tunnel_id << std::endl; -#endif - - switch(tunnel_status) - { - default: - case RsGxsTunnelService::RS_GXS_TUNNEL_STATUS_UNKNOWN: std::cerr << "(EE) don't know how to handle RS_GXS_TUNNEL_STATUS_UNKNOWN !" << std::endl; - break ; - - case RsGxsTunnelService::RS_GXS_TUNNEL_STATUS_CAN_TALK: RsServer::notify()->notifyChatStatus(ChatId(DistantChatPeerId(tunnel_id)),"Tunnel is secured. You can talk!") ; - RsServer::notify()->notifyPeerStatusChanged(tunnel_id.toStdString(),RS_STATUS_ONLINE) ; - break ; - - case RsGxsTunnelService::RS_GXS_TUNNEL_STATUS_TUNNEL_DN: RsServer::notify()->notifyChatStatus(ChatId(DistantChatPeerId(tunnel_id)),"Tunnel is down...") ; - RsServer::notify()->notifyPeerStatusChanged(tunnel_id.toStdString(),RS_STATUS_OFFLINE) ; - break ; - - case RsGxsTunnelService::RS_GXS_TUNNEL_STATUS_REMOTELY_CLOSED: RsServer::notify()->notifyChatStatus(ChatId(DistantChatPeerId(tunnel_id)),"Tunnel is down...") ; - RsServer::notify()->notifyPeerStatusChanged(tunnel_id.toStdString(),RS_STATUS_OFFLINE) ; - break ; - } -} - -void DistantChatService::receiveData( const RsGxsTunnelId& tunnel_id, unsigned char* data, uint32_t data_size) -{ -#ifdef DEBUG_DISTANT_CHAT - DISTANT_CHAT_DEBUG() << "DistantChatService::receiveData(): got data of size " << std::dec << data_size << " for tunnel " << tunnel_id << std::endl; - DISTANT_CHAT_DEBUG() << " received: " << RsUtil::BinToHex(data,data_size,100) << std::endl; - DISTANT_CHAT_DEBUG() << " hash: " << RsDirUtil::sha1sum(data,data_size) << std::endl; - DISTANT_CHAT_DEBUG() << " deserialising..." << std::endl; -#endif - - // always make the contact up to date. This is useful for server side, which doesn't know about the chat until it - // receives the first item. - { - RS_STACK_MUTEX(mDistantChatMtx) ; - - RsGxsTunnelService::GxsTunnelInfo tinfo; - if(!mGxsTunnels->getTunnelInfo(tunnel_id,tinfo)) - return ; - - // Check if the data is accepted. We cannot prevent the creation of tunnels at the level of p3GxsTunnels, since tunnels are shared between services. - // however, - - DistantChatContact& contact(mDistantChatContacts[DistantChatPeerId(tunnel_id)]) ; - - contact.to_id = tinfo.destination_gxs_id ; - contact.from_id = tinfo.source_gxs_id ; - } - - RsItem *item = RsChatSerialiser().deserialise(data,&data_size) ; - - if(item != NULL) - { - item->PeerId(RsPeerId(tunnel_id)) ; // just in case, but normally this is already done. - - handleIncomingItem(item) ; - RsServer::notify()->notifyListChange(NOTIFY_LIST_PRIVATE_INCOMING_CHAT, NOTIFY_TYPE_ADD); - } - else - std::cerr << " (EE) item could not be deserialised!" << std::endl; -} - -void DistantChatService::markDistantChatAsClosed(const DistantChatPeerId& dcpid) -{ - mGxsTunnels->closeExistingTunnel( - RsGxsTunnelId(dcpid), DISTANT_CHAT_GXS_TUNNEL_SERVICE_ID ); - - RS_STACK_MUTEX(mDistantChatMtx) ; - - std::map::iterator it = mDistantChatContacts.find(dcpid) ; - - if(it != mDistantChatContacts.end()) - mDistantChatContacts.erase(it) ; -} - -bool DistantChatService::initiateDistantChatConnexion( - const RsGxsId& to_gxs_id, const RsGxsId& from_gxs_id, - DistantChatPeerId& dcpid, uint32_t& error_code, bool notify ) -{ - RsGxsTunnelId tunnel_id ; - - if(!mGxsTunnels->requestSecuredTunnel(to_gxs_id,from_gxs_id,tunnel_id,DISTANT_CHAT_GXS_TUNNEL_SERVICE_ID,error_code)) - return false ; - - dcpid = DistantChatPeerId(tunnel_id) ; - - DistantChatContact& dc_contact(mDistantChatContacts[dcpid]) ; - - dc_contact.from_id = from_gxs_id ; - dc_contact.to_id = to_gxs_id ; - - error_code = RS_DISTANT_CHAT_ERROR_NO_ERROR ; - - if(notify) - { - // Make a self message to raise the chat window - RsChatMsgItem *item = new RsChatMsgItem; - item->message = "[Starting distant chat. Please wait for secure tunnel"; - item->message += " to be established]"; - item->chatFlags = RS_CHAT_FLAG_PRIVATE; - item->sendTime = time(NULL); - item->PeerId(RsPeerId(tunnel_id)); - handleRecvChatMsgItem(item); - delete item ; - } - - return true ; -} - -bool DistantChatService::getDistantChatStatus(const DistantChatPeerId& tunnel_id, DistantChatPeerInfo& cinfo) -{ - RS_STACK_MUTEX(mDistantChatMtx); - - RsGxsTunnelService::GxsTunnelInfo tinfo; - - if(!mGxsTunnels->getTunnelInfo(RsGxsTunnelId(tunnel_id),tinfo)) return false; - - cinfo.to_id = tinfo.destination_gxs_id; - cinfo.own_id = tinfo.source_gxs_id; - cinfo.pending_items = tinfo.pending_data_packets; - cinfo.peer_id = tunnel_id; - - switch(tinfo.tunnel_status) - { - case RsGxsTunnelService::RS_GXS_TUNNEL_STATUS_CAN_TALK : cinfo.status = RS_DISTANT_CHAT_STATUS_CAN_TALK; break; - case RsGxsTunnelService::RS_GXS_TUNNEL_STATUS_TUNNEL_DN: cinfo.status = RS_DISTANT_CHAT_STATUS_TUNNEL_DN; break; - case RsGxsTunnelService::RS_GXS_TUNNEL_STATUS_REMOTELY_CLOSED: cinfo.status = RS_DISTANT_CHAT_STATUS_REMOTELY_CLOSED; break; - case RsGxsTunnelService::RS_GXS_TUNNEL_STATUS_UNKNOWN: - default: - cinfo.status = RS_DISTANT_CHAT_STATUS_UNKNOWN; break; - } - - return true; -} - -bool DistantChatService::closeDistantChatConnexion(const DistantChatPeerId &tunnel_id) -{ - mGxsTunnels->closeExistingTunnel(RsGxsTunnelId(tunnel_id), DISTANT_CHAT_GXS_TUNNEL_SERVICE_ID) ; - - // also remove contact. Or do we wait for the notification? - - return true ; -} - -uint32_t DistantChatService::getDistantChatPermissionFlags() -{ - return mDistantChatPermissions ; -} -bool DistantChatService::setDistantChatPermissionFlags(uint32_t flags) -{ - if(mDistantChatPermissions != flags) - { - mDistantChatPermissions = flags ; -#ifdef DEBUG_DISTANT_CHAT - DISTANT_CHAT_DEBUG() << "(II) Changing distant chat permissions to " << flags << ". Existing openned chats will however remain active until closed" << std::endl; -#endif - triggerConfigSave() ; - } - - return true ; -} - -void DistantChatService::addToSaveList(std::list& list) const -{ - /* Save permission flags */ - - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; - RsTlvKeyValue kv; - kv.key = "DISTANT_CHAT_PERMISSION_FLAGS" ; - kv.value = RsUtil::NumberToString(mDistantChatPermissions) ; - - vitem->tlvkvs.pairs.push_back(kv) ; - - list.push_back(vitem) ; -} -bool DistantChatService::processLoadListItem(const RsItem *item) -{ - const RsConfigKeyValueSet *vitem = NULL ; - - if(NULL != (vitem = dynamic_cast(item))) - for(std::list::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) - if(kit->key == "DISTANT_CHAT_PERMISSION_FLAGS") - { -#ifdef DEBUG_DISTANT_CHAT - DISTANT_CHAT_DEBUG() << "Loaded distant chat permission flags: " << kit->value << std::endl ; -#endif - if (!kit->value.empty()) - { - std::istringstream is(kit->value) ; - - uint32_t tmp ; - is >> tmp ; - - if(tmp < 3) - mDistantChatPermissions = tmp ; - else - std::cerr << "(EE) Invalid value read for DistantChatPermission flags in config: " << tmp << std::endl; - } - - return true; - } - - return false ; -} - diff --git a/libretroshare/src/chat/distantchat.h b/libretroshare/src/chat/distantchat.h deleted file mode 100644 index eda55da49..000000000 --- a/libretroshare/src/chat/distantchat.h +++ /dev/null @@ -1,109 +0,0 @@ -/******************************************************************************* - * libretroshare/src/chat: distantchat.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#pragma once - -#include -#include -#include - -class RsGixs ; - -static const uint32_t DISTANT_CHAT_AES_KEY_SIZE = 16 ; - -/** - * Public interface only uses DistandChatPeerId, but internally, this is - * converted into a RsGxsTunnelId - */ -class DistantChatService: public RsGxsTunnelService::RsGxsTunnelClientService -{ -public: - DistantChatService() ; - - virtual void triggerConfigSave()=0 ; - bool processLoadListItem(const RsItem *item) ; - void addToSaveList(std::list& list) const; - - /** - * Creates the invite if the public key of the distant peer is available. - * On success, stores the invite in the map above, so that we can respond - * to tunnel requests. */ - bool initiateDistantChatConnexion( const RsGxsId& to_gxs_id, - const RsGxsId &from_gxs_id, - DistantChatPeerId& dcpid, - uint32_t &error_code, - bool notify = true ); - bool closeDistantChatConnexion(const DistantChatPeerId &tunnel_id) ; - - // Sets flags to only allow connexion from some people. - - uint32_t getDistantChatPermissionFlags() ; - bool setDistantChatPermissionFlags(uint32_t flags) ; - - // Returns the status of a distant chat contact. The contact is defined by the tunnel id (turned into a DistantChatPeerId) because - // each pair of talking GXS id needs to be treated separately - - virtual bool getDistantChatStatus(const DistantChatPeerId &tunnel_id, DistantChatPeerInfo& cinfo) ; - - // derived in p3ChatService, so as to pass down some info - virtual void handleIncomingItem(RsItem *) = 0; - virtual bool handleRecvChatMsgItem(RsChatMsgItem *& ci)=0 ; - - bool handleOutgoingItem(RsChatItem *) ; - bool handleRecvItem(RsChatItem *) ; - void handleRecvChatStatusItem(RsChatStatusItem *cs) ; - -private: - struct DistantChatContact - { - RsGxsId from_id ; - RsGxsId to_id ; - }; - // This maps contains the current peers to talk to with distant chat. - // - std::map mDistantChatContacts ; // current peers we can talk to - - // Permission handling - - uint32_t mDistantChatPermissions ; - - // Overloaded from RsGxsTunnelClientService - -public: - virtual void connectToGxsTunnelService(RsGxsTunnelService *tunnel_service) ; - -private: - virtual bool acceptDataFromPeer( - const RsGxsId& gxs_id, const RsGxsTunnelId& tunnel_id, - bool am_I_client_side); - virtual void notifyTunnelStatus( - const RsGxsTunnelId& tunnel_id, uint32_t tunnel_status); - virtual void receiveData( - const RsGxsTunnelId& id, unsigned char* data, uint32_t data_size ); - - // Utility functions. - - void markDistantChatAsClosed(const DistantChatPeerId& dcpid) ; - - RsGxsTunnelService *mGxsTunnels ; - RsMutex mDistantChatMtx ; -}; diff --git a/libretroshare/src/chat/distributedchat.cc b/libretroshare/src/chat/distributedchat.cc deleted file mode 100644 index cacd68e08..000000000 --- a/libretroshare/src/chat/distributedchat.cc +++ /dev/null @@ -1,2207 +0,0 @@ -/******************************************************************************* - * libretroshare/src/chat: distributedchat.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include -#include -#include -#include - -#include "util/rsprint.h" -#include "util/rsmemory.h" -#include "distributedchat.h" - -#include "pqi/p3historymgr.h" -#include "retroshare/rspeers.h" -#include "retroshare/rsiface.h" -#include "retroshare/rsidentity.h" -#include "rsserver/p3face.h" -#include "gxs/rsgixs.h" -#include "services/p3idservice.h" - -//#define DEBUG_CHAT_LOBBIES 1 - -static const int CONNECTION_CHALLENGE_MAX_COUNT = 20 ; // sends a connection challenge every 20 messages -static const rstime_t CONNECTION_CHALLENGE_MAX_MSG_AGE = 30 ; // maximum age of a message to be used in a connection challenge -static const int CONNECTION_CHALLENGE_MIN_DELAY = 15 ; // sends a connection at most every 15 seconds -static const int LOBBY_CACHE_CLEANING_PERIOD = 10 ; // clean lobby caches every 10 secs (remove old messages) - -static const rstime_t MAX_KEEP_MSG_RECORD = 1200 ; // keep msg record for 1200 secs max. -static const rstime_t MAX_KEEP_INACTIVE_NICKNAME = 180 ; // keep inactive nicknames for 3 mn max. -static const rstime_t MAX_DELAY_BETWEEN_LOBBY_KEEP_ALIVE = 120 ; // send keep alive packet every 2 minutes. -static const rstime_t MAX_KEEP_PUBLIC_LOBBY_RECORD = 60 ; // keep inactive lobbies records for 60 secs max. -static const rstime_t MIN_DELAY_BETWEEN_PUBLIC_LOBBY_REQ = 20 ; // don't ask for lobby list more than once every 30 secs. -static const rstime_t LOBBY_LIST_AUTO_UPDATE_TIME = 121 ; // regularly ask for available lobbies every 5 minutes, to allow auto-subscribe to work - -static const uint32_t MAX_ALLOWED_LOBBIES_IN_LIST_WARNING = 50 ; -//static const uint32_t MAX_MESSAGES_PER_SECONDS_NUMBER = 5 ; // max number of messages from a given peer in a window for duration below -static const uint32_t MAX_MESSAGES_PER_SECONDS_PERIOD = 10 ; // duration window for max number of messages before messages get dropped. - -#define IS_PUBLIC_LOBBY(flags) (flags & RS_CHAT_LOBBY_FLAGS_PUBLIC ) -#define IS_PGP_SIGNED_LOBBY(flags) (flags & RS_CHAT_LOBBY_FLAGS_PGP_SIGNED) -#define IS_CONNEXION_CHALLENGE(flags) (flags & RS_CHAT_LOBBY_FLAGS_CHALLENGE ) - -#define EXTRACT_PRIVACY_FLAGS(flags) (ChatLobbyFlags(flags.toUInt32()) * (RS_CHAT_LOBBY_FLAGS_PUBLIC | RS_CHAT_LOBBY_FLAGS_PGP_SIGNED)) - -DistributedChatService::DistributedChatService(uint32_t serv_type,p3ServiceControl *sc,p3HistoryMgr *hm, RsGixs *is) - : mServType(serv_type),mDistributedChatMtx("Distributed Chat"), mServControl(sc), mHistMgr(hm),mGixs(is) -{ - _time_shift_average = 0.0f ; - _should_reset_lobby_counts = false ; - last_visible_lobby_info_request_time = 0 ; -} - -void DistributedChatService::flush() -{ - static rstime_t last_clean_time_lobby = 0 ; - static rstime_t last_req_chat_lobby_list = 0 ; - - rstime_t now = time(NULL) ; - - if(last_clean_time_lobby + LOBBY_CACHE_CLEANING_PERIOD < now) - { - cleanLobbyCaches() ; - last_clean_time_lobby = now ; - - // also make sure that the default identity is not null - - if(_default_identity.isNull()) - { - std::list ids ; - mGixs->getOwnIds(ids) ; - - if(!ids.empty()) - { - _default_identity = ids.front() ; - triggerConfigSave() ; - } - } - } - if(last_req_chat_lobby_list + LOBBY_LIST_AUTO_UPDATE_TIME < now) - { - std::vector visible_lobbies_tmp ; - getListOfNearbyChatLobbies(visible_lobbies_tmp) ; - - if (visible_lobbies_tmp.empty()){ - last_req_chat_lobby_list = now-LOBBY_LIST_AUTO_UPDATE_TIME+MIN_DELAY_BETWEEN_PUBLIC_LOBBY_REQ; - } else { - last_req_chat_lobby_list = now ; - } - } -} - -bool DistributedChatService::handleRecvChatLobbyMsgItem(RsChatMsgItem *ci) -{ - // check if it's a lobby msg, in which case we replace the peer id by the lobby's virtual peer id. - // - RsChatLobbyMsgItem *cli = dynamic_cast(ci) ; - - if(cli == NULL) - return true ; // the item is handled correctly if it's not a lobby item ;-) - - rstime_t now = time(NULL) ; - - if(now+100 > (rstime_t) cli->sendTime + MAX_KEEP_MSG_RECORD) // the message is older than the max cache keep plus 100 seconds ! It's too old, and is going to make an echo! - { - std::cerr << "Received severely outdated lobby event item (" << now - (rstime_t)cli->sendTime << " in the past)! Dropping it!" << std::endl; - std::cerr << "Message item is:" << std::endl; - cli->print(std::cerr) ; - std::cerr << std::endl; - return false ; - } - if(now+600 < (rstime_t) cli->sendTime) // the message is from the future. Drop it. more than 10 minutes - { - std::cerr << "Received event item from the future (" << (rstime_t)cli->sendTime - now << " seconds in the future)! Dropping it!" << std::endl; - std::cerr << "Message item is:" << std::endl; - cli->print(std::cerr) ; - std::cerr << std::endl; - return false ; - } - - if( rsReputations->overallReputationLevel(cli->signature.keyId) == - RsReputationLevel::LOCALLY_NEGATIVE ) - { - std::cerr << "(WW) Received lobby msg/item from banned identity " << cli->signature.keyId << ". Dropping it." << std::endl; - return false ; - } - if(!checkSignature(cli,cli->PeerId())) // check the object's signature and possibly request missing keys - { - std::cerr << "Signature mismatched for this lobby event item. Item will be dropped: " << std::endl; - cli->print(std::cerr) ; - std::cerr << std::endl; - return false; - } - - // add a routing clue for this peer/GXSid combination. This is quite reliable since the lobby transport is almost instantaneous - - rsGRouter->addRoutingClue(GRouterKeyId(cli->signature.keyId),cli->PeerId()) ; - - ChatLobbyFlags fl ; - - // delete items that are not for us, as early as possible. - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - // send upward for display - - std::map::const_iterator it = _chat_lobbys.find(cli->lobby_id) ; - - if(it == _chat_lobbys.end()) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Chatlobby for id " << std::hex << cli->lobby_id << " has no record. Dropping the msg." << std::dec << std::endl; -#endif - return false; - } - fl = it->second.lobby_flags ; - } - if(IS_PGP_SIGNED_LOBBY(fl)) - { - RsIdentityDetails details; - - if(!rsIdentity->getIdDetails(cli->signature.keyId,details)) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "(WW) cannot get ID " << cli->signature.keyId << " for checking signature of lobby item." << std::endl; -#endif - return false; - } - - if(!(details.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED)) - { - std::cerr << "(WW) Received a lobby msg/item that is not PGP-authed (id=" << cli->signature.keyId << "), whereas the lobby flags require it. Rejecting!" << std::endl; - - return false ; - } - } - - if(!bounceLobbyObject(cli,cli->PeerId())) // forwards the message to friends, keeps track of subscribers, etc. - return false; - - // setup the peer id to the virtual peer id of the lobby. - // - RsPeerId virtual_peer_id ; - getVirtualPeerId(cli->lobby_id,virtual_peer_id) ; - cli->PeerId(virtual_peer_id) ; - - //name = cli->nick; - //popupChatFlag = RS_POPUP_CHATLOBBY; - - RsServer::notify()->AddPopupMessage(RS_POPUP_CHATLOBBY, ChatId(cli->lobby_id).toStdString(), cli->signature.keyId.toStdString(), cli->message); /* notify private chat message */ - - return true ; -} - -bool DistributedChatService::checkSignature(RsChatLobbyBouncingObject *obj,const RsPeerId& peer_id) -{ - // Always request the key. If not present, it will be asked to the peer id who sent this item. - - std::list peer_list ; - peer_list.push_back(peer_id) ; - - // network pre-request key to allow message authentication. - - mGixs->requestKey(obj->signature.keyId,peer_list,RsIdentityUsage(RsServiceType::CHAT, - RsIdentityUsage::CHAT_LOBBY_MSG_VALIDATION, - RsGxsGroupId(), - RsGxsMessageId(), - RsGxsMessageId(), - RsGxsMessageId(), - obj->lobby_id)); - - uint32_t size = RsChatSerialiser(RsSerializationFlags::SIGNATURE) - .size(dynamic_cast(obj)); - RsTemporaryMemory memory(size) ; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Checking object signature: " << std::endl; - std::cerr << " signature id: " << obj->signature.keyId << std::endl; -#endif - - if( !RsChatSerialiser(RsSerializationFlags::SIGNATURE) - .serialise(dynamic_cast(obj),memory,&size) ) - { - std::cerr << " (EE) Cannot serialise message item. " << std::endl; - return false ; - } - - uint32_t error_status ; - RsIdentityUsage use_info(RsServiceType::CHAT, - RsIdentityUsage::CHAT_LOBBY_MSG_VALIDATION, - RsGxsGroupId(), - RsGxsMessageId(), - RsGxsMessageId(), - RsGxsMessageId(), - obj->lobby_id) ; - - if(!mGixs->validateData(memory,size,obj->signature,false,use_info,error_status)) - { - bool res = false ; - - switch(error_status) - { - case RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE: -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "(WW) Key is not is cache. Cannot verify." << std::endl; -#endif - res =true ; - break ; - case RsGixs::RS_GIXS_ERROR_SIGNATURE_MISMATCH: std::cerr << "(EE) Signature mismatch. Spoofing/MITM?." << std::endl; - res =false ; - break ; - default: break ; - } - return res; - } - - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " signature: CHECKS" << std::endl; -#endif - - return true ; -} - -bool DistributedChatService::getVirtualPeerId(const ChatLobbyId& id,ChatLobbyVirtualPeerId& vpid) -{ - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Was asked for virtual peer name of " << std::hex << id << std::dec<< std::endl; -#endif - std::map::const_iterator it(_chat_lobbys.find(id)) ; - - if(it == _chat_lobbys.end()) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " not found!! " << std::endl; -#endif - return false ; - } - - vpid = it->second.virtual_peer_id ; -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " returning " << vpid << std::endl; -#endif - return true ; -} - -void DistributedChatService::locked_printDebugInfo() const -{ - std::cerr << "Recorded lobbies: " << std::endl; - rstime_t now = time(NULL) ; - - for( std::map::const_iterator it(_chat_lobbys.begin()) ;it!=_chat_lobbys.end();++it) - { - std::cerr << " Lobby id\t\t: " << std::hex << it->first << std::dec << std::endl; - std::cerr << " Lobby name\t\t: " << it->second.lobby_name << std::endl; - std::cerr << " Lobby topic\t\t: " << it->second.lobby_topic << std::endl; - std::cerr << " nick name\t\t: " << it->second.gxs_id << std::endl; - std::cerr << " Lobby type\t\t: " << ((IS_PUBLIC_LOBBY(it->second.lobby_flags))?"Public":"Private") << std::endl; - std::cerr << " Lobby security\t\t: " << ((IS_PGP_SIGNED_LOBBY(it->second.lobby_flags))?"PGP-signed IDs required":"Anon IDs accepted") << std::endl; - std::cerr << " Lobby peer id\t: " << it->second.virtual_peer_id << std::endl; - std::cerr << " Challenge count\t: " << it->second.connexion_challenge_count << std::endl; - std::cerr << " Last activity\t: " << now - it->second.last_activity << " seconds ago." << std::endl; - std::cerr << " Cached messages\t: " << it->second.msg_cache.size() << std::endl; - - for(std::map::const_iterator it2(it->second.msg_cache.begin());it2!=it->second.msg_cache.end();++it2) - std::cerr << " " << std::hex << it2->first << std::dec << " time=" << now - it2->second << " secs ago" << std::endl; - - std::cerr << " Participating friends: " << std::endl; - - for(std::set::const_iterator it2(it->second.participating_friends.begin());it2!=it->second.participating_friends.end();++it2) - std::cerr << " " << *it2 << std::endl; - - std::cerr << " Participating nick names: " << std::endl; - - for(std::map::const_iterator it2(it->second.gxs_ids.begin());it2!=it->second.gxs_ids.end();++it2) - std::cerr << " " << it2->first << ": " << now - it2->second << " secs ago" << std::endl; - - } - - std::cerr << "Visible public lobbies: " << std::endl; - - for( std::map::const_iterator it(_visible_lobbies.begin()) ;it!=_visible_lobbies.end();++it) - { - std::cerr << " " << std::hex << it->first << " name = " << std::dec << it->second.lobby_name << it->second.lobby_topic << std::endl; - for(std::set::const_iterator it2(it->second.participating_friends.begin());it2!=it->second.participating_friends.end();++it2) - std::cerr << " With friend: " << *it2 << std::endl; - } - - std::cerr << "Chat lobby flags: " << std::endl; - - for( std::map::const_iterator it(_known_lobbies_flags.begin()) ;it!=_known_lobbies_flags.end();++it) - std::cerr << " \"" << std::hex << it->first << "\" flags = " << it->second << std::dec << std::endl; -} - -bool DistributedChatService::locked_bouncingObjectCheck(RsChatLobbyBouncingObject *obj,const RsPeerId& peer_id,uint32_t lobby_count) -{ - static std::map > message_counts ; - - std::ostringstream os ; - os << obj->lobby_id ; - - std::string pid = peer_id.toStdString() + "_" + os.str() ; - - // Check for the number of peers in the lobby. First look into visible lobbies, because the number - // of peers there is more accurate. If non existant (because it's a private lobby), take the count from - // the current lobby list. - // - std::map::const_iterator it = _visible_lobbies.find(obj->lobby_id) ; - - if(it != _visible_lobbies.end()) - lobby_count = it->second.total_number_of_peers ; - else - { - std::map::const_iterator it = _chat_lobbys.find(obj->lobby_id) ; - - if(it != _chat_lobbys.end()) - lobby_count = it->second.gxs_ids.size() ; - else - { - std::cerr << "DistributedChatService::locked_bouncingObjectCheck(): weird situation: cannot find lobby in visible lobbies nor current lobbies. Dropping message. If you see this, contact the developers." << std::endl; - return false ; - } - } - - // max objects per second: lobby_count * 1/MAX_DELAY_BETWEEN_LOBBY_KEEP_ALIVE objects per second. - // So in cache, there is in average that number times MAX_MESSAGES_PER_SECONDS_PERIOD - // - float max_cnt = std::max(10.0f, 10*lobby_count / (float)MAX_DELAY_BETWEEN_LOBBY_KEEP_ALIVE * MAX_MESSAGES_PER_SECONDS_PERIOD) ; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "lobby_count=" << lobby_count << std::endl; - std::cerr << "Got msg for peer " << pid << std::dec << ". Limit is " << max_cnt << ". List is " ; - for(std::list::const_iterator it(message_counts[pid].begin());it!=message_counts[pid].end();++it) - std::cerr << *it << " " ; - std::cerr << std::endl; -#endif - - rstime_t now = time(NULL) ; - - std::list& lst = message_counts[pid] ; - - // Clean old messages time stamps from the list. - // - while(!lst.empty() && lst.front() + MAX_MESSAGES_PER_SECONDS_PERIOD < now) - lst.pop_front() ; - - if(lst.size() > max_cnt) - { - std::cerr << "(WW) more than " << max_cnt << " messages forwarded by peer " << pid << ". Message from \"" << obj->nick << "\" will not be forwarded." << std::endl; - return false; - } - else - lst.push_back(now) ; - - return true ; -} - -// This function should be used for all types of chat messages. But this requires a non backward compatible change in -// chat protocol. To be done for version 0.6 -// -void DistributedChatService::checkSizeAndSendLobbyMessage(RsChatItem *msg) -{ - // Multiple-parts messaging has been disabled in lobbies, because of the following issues: - // 1 - it breaks signatures because the subid of each sub-item is changed (can be fixed) - // 2 - it breaks (can be fixed as well) - // 3 - it is unreliable since items are not guarrantied to all arrive in the end (cannot be fixed) - // 4 - large objects can be used to corrupt end peers (cannot be fixed) - // - static const uint32_t MAX_ITEM_SIZE = 32000 ; - - if(RsChatSerialiser().size(msg) > MAX_ITEM_SIZE) - { - std::cerr << "(EE) Chat item exceeds maximum serial size. It will be dropped." << std::endl; - delete msg ; - return ; - } - sendChatItem(msg) ; -} - -bool DistributedChatService::handleRecvItem(RsChatItem *item) -{ - switch(item->PacketSubType()) - { - case RS_PKT_SUBTYPE_CHAT_LOBBY_SIGNED_EVENT: handleRecvChatLobbyEventItem (dynamic_cast(item)) ; break ; - case RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE_DEPRECATED: handleRecvLobbyInvite_Deprecated (dynamic_cast(item)) ; break ; // to be removed (deprecated since May 2017) - case RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE: handleRecvLobbyInvite (dynamic_cast(item)) ; break ; - case RS_PKT_SUBTYPE_CHAT_LOBBY_CHALLENGE: handleConnectionChallenge (dynamic_cast(item)) ; break ; - case RS_PKT_SUBTYPE_CHAT_LOBBY_UNSUBSCRIBE: handleFriendUnsubscribeLobby (dynamic_cast(item)) ; break ; - case RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_REQUEST: handleRecvChatLobbyListRequest (dynamic_cast(item)) ; break ; - case RS_PKT_SUBTYPE_CHAT_LOBBY_LIST: handleRecvChatLobbyList (dynamic_cast(item)) ; break ; - default: return false ; - } - return true ; -} - -void DistributedChatService::handleRecvChatLobbyListRequest(RsChatLobbyListRequestItem *clr) -{ - // make a lobby list item - // - RsChatLobbyListItem *item = new RsChatLobbyListItem; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Peer " << clr->PeerId() << " requested the list of public chat lobbies." << std::endl; -#endif - - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - for(std::map::const_iterator it(_chat_lobbys.begin());it!=_chat_lobbys.end();++it) - { - const ChatLobbyEntry& lobby(it->second) ; - - if(IS_PUBLIC_LOBBY(lobby.lobby_flags) || - (lobby.previously_known_peers.find(clr->PeerId()) != lobby.previously_known_peers.end() - ||lobby.participating_friends.find(clr->PeerId()) != lobby.participating_friends.end()) ) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Adding lobby " << std::hex << it->first << std::dec << " \"" - << it->second.lobby_name << it->second.lobby_topic << "\" count=" << it->second.gxs_ids.size() << std::endl; -#endif - - VisibleChatLobbyInfo info ; - - info.id = it->first ; - info.name = it->second.lobby_name ; - info.topic = it->second.lobby_topic ; - info.count = it->second.gxs_ids.size() ; - info.flags = ChatLobbyFlags(EXTRACT_PRIVACY_FLAGS(it->second.lobby_flags)) ; - - item->lobbies.push_back(info) ; - } -#ifdef DEBUG_CHAT_LOBBIES - else - std::cerr << " Not adding private lobby " << std::hex << it->first << std::dec << std::endl ; -#endif - } - } - - item->PeerId(clr->PeerId()) ; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Sending list to " << clr->PeerId() << std::endl; -#endif - sendChatItem(item); -} - -void DistributedChatService::handleRecvChatLobbyList(RsChatLobbyListItem *item) -{ - if(item->lobbies.size() > MAX_ALLOWED_LOBBIES_IN_LIST_WARNING) - std::cerr << "Warning: Peer " << item->PeerId() << "(" << rsPeers->getPeerName(item->PeerId()) << ") is sending a lobby list of " << item->lobbies.size() << " lobbies. This is unusual, and probably a attempt to crash you." << std::endl; - - std::list chatLobbyToSubscribe; - std::list invitationNeeded ; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Received chat lobby list from friend " << item->PeerId() << ", " << item->lobbies.size() << " elements." << std::endl; -#endif - { - rstime_t now = time(NULL) ; - - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - for(uint32_t i=0;ilobbies.size() && i < MAX_ALLOWED_LOBBIES_IN_LIST_WARNING;++i) - { - VisibleChatLobbyRecord& rec(_visible_lobbies[item->lobbies[i].id]) ; - - rec.lobby_id = item->lobbies[i].id ; - rec.lobby_name = item->lobbies[i].name ; - rec.lobby_topic = item->lobbies[i].topic ; - rec.participating_friends.insert(item->PeerId()) ; - - if(_should_reset_lobby_counts) - rec.total_number_of_peers = item->lobbies[i].count ; - else - rec.total_number_of_peers = std::max(rec.total_number_of_peers,item->lobbies[i].count) ; - - rec.last_report_time = now ; - rec.lobby_flags = EXTRACT_PRIVACY_FLAGS(item->lobbies[i].flags) ; - - std::map::const_iterator it(_known_lobbies_flags.find(item->lobbies[i].id)) ; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " lobby id " << std::hex << item->lobbies[i].id << std::dec << ", " << item->lobbies[i].name - << ", " << item->lobbies[i].count << " participants" << std::endl; -#endif - if(it != _known_lobbies_flags.end() && (it->second & RS_CHAT_LOBBY_FLAGS_AUTO_SUBSCRIBE)) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " lobby is flagged as autosubscribed. Adding it to subscribe list." << std::endl; -#endif - ChatLobbyId clid = item->lobbies[i].id; - if(_chat_lobbys.find(clid) == _chat_lobbys.end()) - chatLobbyToSubscribe.push_back(clid); - } - - // for subscribed lobbies, check that item->PeerId() is among the participating friends. If not, add him! - - std::map::iterator it2 = _chat_lobbys.find(item->lobbies[i].id) ; - - if(it2 != _chat_lobbys.end() && it2->second.participating_friends.find(item->PeerId()) == it2->second.participating_friends.end()) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " lobby is currently subscribed but friend is not participating already -> adding to partipating friends and sending invite." << std::endl; -#endif - it2->second.participating_friends.insert(item->PeerId()) ; - invitationNeeded.push_back(item->lobbies[i].id) ; - } - } - } - - std::list::iterator it; - for (it = chatLobbyToSubscribe.begin(); it != chatLobbyToSubscribe.end(); ++it) - { - RsGxsId gxsId = _lobby_default_identity[*it]; - if (gxsId.isNull()) - gxsId = _default_identity; - - //Check if gxsId can connect to this lobby - ChatLobbyFlags flags(0); - std::map::const_iterator vlIt = _visible_lobbies.find(*it) ; - if(vlIt != _visible_lobbies.end()) - flags = vlIt->second.lobby_flags; - else - { - std::map::const_iterator clIt = _chat_lobbys.find(*it) ; - - if(clIt != _chat_lobbys.end()) - flags = clIt->second.lobby_flags; - } - - RsIdentityDetails idd ; - if(!rsIdentity->getIdDetails(gxsId,idd)) - std::cerr << "(EE) Lobby auto-subscribe: Can't get Id detail for:" << gxsId.toStdString().c_str() << std::endl; - else - { - if(IS_PGP_SIGNED_LOBBY(flags) - && !(idd.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED) ) - { - std::cerr << "(EE) Attempt to auto-subscribe to signed lobby with non signed Id. Remove it." << std::endl; - setLobbyAutoSubscribe(*it, false); - } else { - joinVisibleChatLobby(*it,gxsId); - } - } - } - - for(std::list::const_iterator it = invitationNeeded.begin();it!=invitationNeeded.end();++it) - invitePeerToLobby(*it,item->PeerId(),false) ; - - RsServer::notify()->notifyListChange(NOTIFY_LIST_CHAT_LOBBY_LIST, NOTIFY_TYPE_ADD) ; - _should_reset_lobby_counts = false ; -} - -void DistributedChatService::addTimeShiftStatistics(int D) -{ - static const int S = 50 ; // accuracy up to 2^50 second. Quite conservative! - static int total = 0 ; - static std::vector log_delay_histogram(S,0) ; - - int delay = (D<0)?(-D):D ; - - if(delay < 0) - delay = -delay ; - - // compute log2. - int l = 0 ; - while(delay > 0) delay >>= 1, ++l ; - - int bin = std::min(S-1,l) ; - ++log_delay_histogram[bin] ; - ++total ; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "New delay stat item. delay=" << D << ", log=" << bin << " total=" << total << ", histogram = " ; - - for(int i=0;i 30) - { - float t = 0.0f ; - int i=0 ; - for(;i0 so i is incremented - if(log_delay_histogram[i-1] == 0) return ; // cannot happen, either, but let's be cautious. - - float expected = ( i * (log_delay_histogram[i-1] - t + total*0.5) + (i-1) * (t - total*0.5) ) / (float)log_delay_histogram[i-1] - 1; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << ". Expected delay: " << expected << std::endl ; -#endif - - if(expected > 9) // if more than 20 samples - RsServer::notify()->notifyChatLobbyTimeShift( (int)pow(2.0f,expected)) ; - - total = 0.0f ; - log_delay_histogram.clear() ; - log_delay_histogram.resize(S,0) ; - } -#ifdef DEBUG_CHAT_LOBBIES - else - std::cerr << std::endl; -#endif -} - -void DistributedChatService::handleRecvChatLobbyEventItem(RsChatLobbyEventItem *item) -{ - ChatLobbyFlags fl ; - - // delete items that are not for us, as early as possible. - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - // send upward for display - - std::map::const_iterator it = _chat_lobbys.find(item->lobby_id) ; - - if(it == _chat_lobbys.end()) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Chatlobby for id " << std::hex << item->lobby_id << " has no record. Dropping the msg." << std::dec << std::endl; -#endif - return ; - } - fl = it->second.lobby_flags ; - } - - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Received ChatLobbyEvent item of type " << (int)(item->event_type) << ", and string=" << item->string1 << std::endl; -#endif - rstime_t now = time(nullptr); - - if( rsReputations->overallReputationLevel(item->signature.keyId) == - RsReputationLevel::LOCALLY_NEGATIVE ) - { - std::cerr << "(WW) Received lobby msg/item from banned identity " << item->signature.keyId << ". Dropping it." << std::endl; - return ; - } - if(!checkSignature(item,item->PeerId())) // check the object's signature and possibly request missing keys - { - std::cerr << "Signature mismatched for this lobby event item: " << std::endl; - item->print(std::cerr) ; - std::cerr << std::endl; - return ; - } - - if(IS_PGP_SIGNED_LOBBY(fl)) - { - RsIdentityDetails details; - - if(!rsIdentity->getIdDetails(item->signature.keyId,details)) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "(WW) cannot get ID " << item->signature.keyId << " for checking signature of lobby item." << std::endl; -#endif - return ; - } - - if(!(details.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED)) - { - std::cerr << "(WW) Received a lobby msg/item that is not PGP-authed (ID=" << item->signature.keyId << "), whereas the lobby flags require it. Rejecting!" << std::endl; - return ; - } - } - addTimeShiftStatistics((int)now - (int)item->sendTime) ; - - if(now+100 > (rstime_t) item->sendTime + MAX_KEEP_MSG_RECORD) // the message is older than the max cache keep minus 100 seconds ! It's too old, and is going to make an echo! - { - std::cerr << "Received severely outdated lobby event item (" << now - (rstime_t)item->sendTime << " in the past)! Dropping it!" << std::endl; - std::cerr << "Message item is:" << std::endl; - item->print(std::cerr) ; - std::cerr << std::endl; - return ; - } - if(now+600 < (rstime_t) item->sendTime) // the message is from the future more than 10 minutes - { - std::cerr << "Received event item from the future (" << (rstime_t)item->sendTime - now << " seconds in the future)! Dropping it!" << std::endl; - std::cerr << "Message item is:" << std::endl; - item->print(std::cerr) ; - std::cerr << std::endl; - return ; - } - // add a routing clue for this peer/GXSid combination. This is quite reliable since the lobby transport is almost instantaneous - rsGRouter->addRoutingClue(GRouterKeyId(item->signature.keyId),item->PeerId()) ; - - if(! bounceLobbyObject(item,item->PeerId())) - return ; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " doing specific job for this status item." << std::endl; -#endif - - if(item->event_type == RS_CHAT_LOBBY_EVENT_PEER_LEFT) // if a peer left. Remove its nickname from the list. - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " removing nickname " << item->nick << " from lobby " << std::hex << item->lobby_id << std::dec << std::endl; -#endif - - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it = _chat_lobbys.find(item->lobby_id) ; - - if(it != _chat_lobbys.end()) - { - std::map::iterator it2(it->second.gxs_ids.find(item->signature.keyId)) ; - - if(it2 != it->second.gxs_ids.end()) - { - it->second.gxs_ids.erase(it2) ; -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " removed id " << item->signature.keyId << " from lobby " << std::hex << item->lobby_id << std::dec << std::endl; -#endif - } -#ifdef DEBUG_CHAT_LOBBIES - else - std::cerr << " (EE) nickname " << item->nick << " not in participant nicknames list!" << std::endl; -#endif - } - } - else if(item->event_type == RS_CHAT_LOBBY_EVENT_PEER_JOINED) // if a joined left. Add its nickname to the list. - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " adding nickname " << item->nick << " to lobby " << std::hex << item->lobby_id << std::dec << std::endl; -#endif - - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it = _chat_lobbys.find(item->lobby_id) ; - - if(it != _chat_lobbys.end()) - { - it->second.gxs_ids[item->signature.keyId] = time(NULL) ; -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " added nickname " << item->nick << " from lobby " << std::hex << item->lobby_id << std::dec << std::endl; -#endif - // trigger a keep alive packets so as to inform the new participant of our presence in the chatroom - it->second.last_keep_alive_packet_time = 0 ; - } - } - else if(item->event_type == RS_CHAT_LOBBY_EVENT_KEEP_ALIVE) // keep alive packet. - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " adding nickname " << item->nick << " to lobby " << std::hex << item->lobby_id << std::dec << std::endl; -#endif - - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it = _chat_lobbys.find(item->lobby_id) ; - - if(it != _chat_lobbys.end()) - { - it->second.gxs_ids[item->signature.keyId] = time(NULL) ; -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " added nickname " << item->nick << " from lobby " << std::hex << item->lobby_id << std::dec << std::endl; -#endif - } - } - - RsServer::notify()->notifyChatLobbyEvent(item->lobby_id,item->event_type,item->signature.keyId,item->string1); -} - -void DistributedChatService::getListOfNearbyChatLobbies(std::vector& visible_lobbies) -{ - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - visible_lobbies.clear() ; - - for(std::map::const_iterator it(_visible_lobbies.begin());it!=_visible_lobbies.end();++it) - visible_lobbies.push_back(it->second) ; - } - - rstime_t now = time(NULL) ; - - if(now > MIN_DELAY_BETWEEN_PUBLIC_LOBBY_REQ + last_visible_lobby_info_request_time) - { - std::set ids ; - mServControl->getPeersConnected(mServType, ids); - - for(std::set::const_iterator it(ids.begin());it!=ids.end();++it) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " asking list of public lobbies to " << *it << std::endl; -#endif - RsChatLobbyListRequestItem *item = new RsChatLobbyListRequestItem ; - item->PeerId(*it) ; - - sendChatItem(item); - } - last_visible_lobby_info_request_time = now ; - _should_reset_lobby_counts = true ; - } -} - -// returns: -// true: the object is not a duplicate and should be used -// false: the object is a duplicate or there is an error, and it should be destroyed. -// -bool DistributedChatService::bounceLobbyObject(RsChatLobbyBouncingObject *item,const RsPeerId& peer_id) -{ - rstime_t now = time(NULL) ; - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ -#ifdef DEBUG_CHAT_LOBBIES - locked_printDebugInfo() ; // debug - - std::cerr << "Handling ChatLobbyMsg " << std::hex << item->msg_id << ", lobby id " << item->lobby_id << ", from peer id " << peer_id << std::endl; -#endif - - // send upward for display - - std::map::iterator it(_chat_lobbys.find(item->lobby_id)) ; - - if(it == _chat_lobbys.end()) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Chatlobby for id " << std::hex << item->lobby_id << " has no record. Dropping the msg." << std::dec << std::endl; -#endif - return false ; - } - - ChatLobbyEntry& lobby(it->second) ; - - // Adds the peer id to the list of friend participants, even if it's not original msg source - - if(peer_id != mServControl->getOwnId()) - lobby.participating_friends.insert(peer_id) ; - - lobby.gxs_ids[item->signature.keyId] = now ; - - // Checks wether the msg is already recorded or not - - std::map::iterator it2(lobby.msg_cache.find(item->msg_id)) ; - - if(it2 != lobby.msg_cache.end()) // found! - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Msg already received at time " << it2->second << ". Dropping!" << std::endl ; -#endif - it2->second = now ; // update last msg seen time, to prevent echos. - return false ; - } -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Msg not received already. Adding in cache, and forwarding!" << std::endl ; -#endif - - lobby.msg_cache[item->msg_id] = now ; - lobby.last_activity = now ; - - // Check that if we have a lobby bouncing object, it's not flooding the lobby - if(!locked_bouncingObjectCheck(item,peer_id,lobby.participating_friends.size())) - return false; - - // Forward to allparticipating friends, except this peer. - - for(std::set::const_iterator it(lobby.participating_friends.begin());it!=lobby.participating_friends.end();++it) - if((*it)!=peer_id && mServControl->isPeerConnected(mServType, *it)) - { - RsChatLobbyBouncingObject *obj2 = item->duplicate() ; // makes a copy - RsChatItem *item2 = dynamic_cast(obj2) ; - - assert(item2 != NULL) ; - - item2->PeerId(*it) ; // replaces the virtual peer id with the actual destination. - - checkSizeAndSendLobbyMessage(item2) ; - } - - ++lobby.connexion_challenge_count ; - - return true ; -} - -void DistributedChatService::sendLobbyStatusString(const ChatLobbyId& lobby_id,const std::string& status_string) -{ - sendLobbyStatusItem(lobby_id,RS_CHAT_LOBBY_EVENT_PEER_STATUS,status_string) ; -} - -/** - * Inform other Clients of a nickname change - * - * as example for updating their ChatLobby Blocklist for muted peers - * */ -void DistributedChatService::sendLobbyStatusPeerChangedNickname(const ChatLobbyId& lobby_id, const std::string& newnick) -{ - sendLobbyStatusItem(lobby_id,RS_CHAT_LOBBY_EVENT_PEER_CHANGE_NICKNAME, newnick) ; -} - - -void DistributedChatService::sendLobbyStatusPeerLeaving(const ChatLobbyId& lobby_id) -{ - sendLobbyStatusItem(lobby_id,RS_CHAT_LOBBY_EVENT_PEER_LEFT,std::string()) ; -} - -void DistributedChatService::sendLobbyStatusNewPeer(const ChatLobbyId& lobby_id) -{ - sendLobbyStatusItem(lobby_id,RS_CHAT_LOBBY_EVENT_PEER_JOINED,std::string()) ; -} - -void DistributedChatService::sendLobbyStatusKeepAlive(const ChatLobbyId& lobby_id) -{ - sendLobbyStatusItem(lobby_id,RS_CHAT_LOBBY_EVENT_KEEP_ALIVE,std::string()) ; -} - -void DistributedChatService::sendLobbyStatusItem(const ChatLobbyId& lobby_id,int type,const std::string& status_string) -{ - RsChatLobbyEventItem item ; - - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - item.event_type = type ; - item.string1 = status_string ; - item.sendTime = time(NULL) ; - - if(! locked_initLobbyBouncableObject(lobby_id,item)) - return ; - } - RsPeerId ownId = mServControl->getOwnId(); - bounceLobbyObject(&item,ownId) ; -} - -bool DistributedChatService::locked_initLobbyBouncableObject(const ChatLobbyId& lobby_id,RsChatLobbyBouncingObject& item) -{ - // get a pointer to the info for that chat lobby. - // - std::map::iterator it(_chat_lobbys.find(lobby_id)) ; - - if(it == _chat_lobbys.end()) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Chatlobby for id " << std::hex << lobby_id << " has no record. This is a serious error!!" << std::dec << std::endl; -#endif - return false; - } - ChatLobbyEntry& lobby(it->second) ; - - // chat lobby stuff - // - do - { - item.msg_id = RSRandom::random_u64(); - } - while( lobby.msg_cache.find(item.msg_id) != lobby.msg_cache.end() ) ; - - RsIdentityDetails details ; - if(!rsIdentity || !rsIdentity->getIdDetails(lobby.gxs_id,details)) - { - std::cerr << "(EE) Cannot send chat lobby object. Signign identity " << lobby.gxs_id << " is unknown." << std::endl; - return false ; - } - - item.lobby_id = lobby_id ; - item.nick = details.mNickname ; - item.signature.TlvClear() ; - item.signature.keyId = lobby.gxs_id ; - - // now sign the object, if the lobby expects it - - uint32_t size = RsChatSerialiser(RsSerializationFlags::SIGNATURE) - .size(dynamic_cast(&item)); - RsTemporaryMemory memory(size) ; - - if( !RsChatSerialiser(RsSerializationFlags::SIGNATURE) - .serialise(dynamic_cast(&item),memory,&size) ) - { - std::cerr << "(EE) Cannot sign message item. " << std::endl; - return false ; - } - - uint32_t error_status ; - - if(!mGixs->signData(memory,size,lobby.gxs_id,item.signature,error_status)) - { - switch(error_status) - { - case RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE: std::cerr << "(EE) Cannot sign item: key not available for ID " << lobby.gxs_id << std::endl; - break ; - default: std::cerr << "(EE) Cannot sign item: unknown error" << std::endl; - break ; - } - return false ; - } - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " signature done." << std::endl; - - // check signature - if(!mGixs->validateData(memory,item.signed_serial_size(),item.signature,true,error_status)) - { - std::cerr << "(EE) Cannot check message item. " << std::endl; - return false ; - } - std::cerr << " signature checks!" << std::endl; - std::cerr << " Item dump:" << std::endl; - item.print(std::cerr,2) ; -#endif - - return true ; -} - -bool DistributedChatService::sendLobbyChat(const ChatLobbyId& lobby_id, const std::string& msg) -{ -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Sending chat lobby message to lobby " << std::hex << lobby_id << std::dec << std::endl; - std::cerr << "msg:" << std::endl; - std::cerr << msg << std::endl; -#endif - - RsChatLobbyMsgItem item ; - - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - // chat msg stuff - // - item.chatFlags = RS_CHAT_FLAG_LOBBY | RS_CHAT_FLAG_PRIVATE; - item.sendTime = time(NULL); - item.recvTime = item.sendTime; - item.message = msg; - item.parent_msg_id = 0; - - // gives a random msg id, setup the nickname, and signs the item. - - if(! locked_initLobbyBouncableObject(lobby_id,item)) - return false; - } - - RsPeerId ownId = rsPeers->getOwnId(); - - bounceLobbyObject(&item, ownId) ; - - ChatMessage message; - message.chatflags = 0; - message.chat_id = ChatId(lobby_id); - message.msg = msg; - message.lobby_peer_gxs_id = item.signature.keyId; - message.recvTime = item.recvTime; - message.sendTime = item.sendTime; - message.incoming = false; - message.online = true; - RsServer::notify()->notifyChatMessage(message); - mHistMgr->addMessage(message); - - return true ; -} - -void DistributedChatService::handleConnectionChallenge(RsChatLobbyConnectChallengeItem *item) -{ - // Look into message cache of all lobbys to handle the challenge. - // -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "DistributedChatService::handleConnectionChallenge(): received connection challenge:" << std::endl; - std::cerr << " Challenge code = 0x" << std::hex << item->challenge_code << std::dec << std::endl; - std::cerr << " Peer Id = " << item->PeerId() << std::endl; -#endif - - rstime_t now = time(NULL) ; - ChatLobbyId lobby_id ; - const RsPeerId& ownId = rsPeers->getOwnId(); - - bool found = false ; - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - for(std::map::iterator it(_chat_lobbys.begin());it!=_chat_lobbys.end() && !found;++it) - for(std::map::const_iterator it2(it->second.msg_cache.begin());it2!=it->second.msg_cache.end() && !found;++it2) - if(it2->second + CONNECTION_CHALLENGE_MAX_MSG_AGE + 5 > now) // any msg not older than 5 seconds plus max challenge count is fine. - { - uint64_t code = makeConnexionChallengeCode(ownId,it->first,it2->first) ; -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Lobby_id = 0x" << std::hex << it->first << ", msg_id = 0x" << it2->first << ": code = 0x" << code << std::dec << std::endl ; -#endif - if(code == item->challenge_code) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Challenge accepted for lobby " << std::hex << it->first << ", for chat msg " << it2->first << std::dec << std::endl ; - std::cerr << " Sending connection request to peer " << item->PeerId() << std::endl; -#endif - - lobby_id = it->first ; - found = true ; - - // also add the peer to the list of participating friends - it->second.participating_friends.insert(item->PeerId()) ; - } - } - } - - if(found) // send invitation. As the peer already has the lobby, the invitation will most likely be accepted. - invitePeerToLobby(lobby_id, item->PeerId(),true) ; -#ifdef DEBUG_CHAT_LOBBIES - else - std::cerr << " Challenge denied: no existing cached msg has matching Id." << std::endl; -#endif -} - -void DistributedChatService::sendConnectionChallenge(ChatLobbyId lobby_id) -{ - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Sending connection challenge to friends for lobby 0x" << std::hex << lobby_id << std::dec << std::endl ; -#endif - - // look for a msg in cache. Any recent msg is fine. - - std::map::const_iterator it = _chat_lobbys.find(lobby_id) ; - - if(it == _chat_lobbys.end()) - { - std::cerr << "ERROR: sendConnectionChallenge(): could not find lobby 0x" << std::hex << lobby_id << std::dec << std::endl; - return ; - } - - rstime_t now = time(NULL) ; - ChatLobbyMsgId msg_id = 0 ; - - for(std::map::const_iterator it2(it->second.msg_cache.begin());it2!=it->second.msg_cache.end();++it2) - if(it2->second + CONNECTION_CHALLENGE_MAX_MSG_AGE > now) // any msg not older than 20 seconds is fine. - { - msg_id = it2->first ; -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Using msg id 0x" << std::hex << it2->first << std::dec << std::endl; -#endif - break ; - } - - if(msg_id == 0) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " No suitable message found in cache. Probably not enough activity !!" << std::endl; -#endif - return ; - } - - // Broadcast to all direct friends - - std::set ids ; - mServControl->getPeersConnected(mServType, ids); - - for(std::set::const_iterator it(ids.begin());it!=ids.end();++it) - { - RsChatLobbyConnectChallengeItem *item = new RsChatLobbyConnectChallengeItem ; - - uint64_t code = makeConnexionChallengeCode(*it,lobby_id,msg_id) ; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Sending collexion challenge code 0x" << std::hex << code << std::dec << " to peer " << *it << std::endl; -#endif - item->PeerId(*it) ; - item->challenge_code = code ; - - sendChatItem(item); - } -} - -uint64_t DistributedChatService::makeConnexionChallengeCode(const RsPeerId& peer_id,ChatLobbyId lobby_id,ChatLobbyMsgId msg_id) -{ - uint64_t result = 0 ; - - for(uint32_t i=0;i> 35 ; - result += result << 6 ; - result ^= peer_id.toByteArray()[i] * lobby_id ; - result += result << 26 ; - result ^= result >> 13 ; - } - return result ; -} - -void DistributedChatService::getChatLobbyList(std::list& clids) -{ - // fill up a dummy list for now. - - clids.clear() ; - - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - for(std::map::const_iterator it(_chat_lobbys.begin());it!=_chat_lobbys.end();++it) - clids.push_back(it->first) ; -} - -bool DistributedChatService::getChatLobbyInfo(const ChatLobbyId& id,ChatLobbyInfo& info) -{ - // fill up a dummy list for now. - - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - - std::map::const_iterator it = _chat_lobbys.find(id) ; - - if(it != _chat_lobbys.end()) - { - info = it->second ; - return true ; - } - else - return false ; -} - -void DistributedChatService::invitePeerToLobby(const ChatLobbyId& lobby_id, const RsPeerId& peer_id,bool connexion_challenge) -{ -#ifdef DEBUG_CHAT_LOBBIES - if(connexion_challenge) - std::cerr << "Sending connection challenge accept to peer " << peer_id << " for lobby "<< std::hex << lobby_id << std::dec << std::endl; - else - std::cerr << "Sending invitation to peer " << peer_id << " to lobby "<< std::hex << lobby_id << std::dec << std::endl; -#endif - - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it = _chat_lobbys.find(lobby_id) ; - - if(it == _chat_lobbys.end()) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " invitation send: canceled. Lobby " << lobby_id << " not found!" << std::endl; -#endif - return ; - } - - RsChatLobbyInviteItem *item = new RsChatLobbyInviteItem ; - - item->lobby_id = lobby_id ; - item->lobby_name = it->second.lobby_name ; - item->lobby_topic = it->second.lobby_topic ; - item->lobby_flags = connexion_challenge?RS_CHAT_LOBBY_FLAGS_CHALLENGE:(it->second.lobby_flags) ; - item->PeerId(peer_id) ; - - sendChatItem(item) ; - - //FOR BACKWARD COMPATIBILITY - {// to be removed (deprecated since May 2017) - RsChatLobbyInviteItem_Deprecated *item = new RsChatLobbyInviteItem_Deprecated ; - - item->lobby_id = lobby_id ; - item->lobby_name = it->second.lobby_name ; - item->lobby_topic = it->second.lobby_topic ; - item->lobby_flags = connexion_challenge?RS_CHAT_LOBBY_FLAGS_CHALLENGE:(it->second.lobby_flags) ; - item->PeerId(peer_id) ; - - sendChatItem(item) ; - } -} - -// to be removed (deprecated since May 2017) -void DistributedChatService::handleRecvLobbyInvite_Deprecated(RsChatLobbyInviteItem_Deprecated *item) -{ -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Received deprecated invite to lobby from " << item->PeerId() << " to lobby " << std::hex << item->lobby_id << std::dec << ", named " << item->lobby_name << item->lobby_topic << std::endl; -#endif - RsChatLobbyInviteItem newItem ; - - newItem.lobby_id = item->lobby_id ; - newItem.lobby_name = item->lobby_name ; - newItem.lobby_topic = item->lobby_topic ; - newItem.lobby_flags = item->lobby_flags ; - newItem.PeerId( item->PeerId() ); - - handleRecvLobbyInvite(&newItem); // The item is not deleted inside this function. -} - -void DistributedChatService::handleRecvLobbyInvite(RsChatLobbyInviteItem *item) -{ -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Received invite to lobby from " << item->PeerId() << " to lobby " << std::hex << item->lobby_id << std::dec << ", named " << item->lobby_name << item->lobby_topic << std::endl; -#endif - - // 1 - store invite in a cache - // - // 1.1 - if the lobby is already setup, add the peer to the communicating peers. - // - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - std::map::iterator it = _chat_lobbys.find(item->lobby_id) ; - - if(it != _chat_lobbys.end()) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Lobby already exists. " << std::endl; - std::cerr << " privacy levels: " << item->lobby_flags << " vs. " << it->second.lobby_flags ; -#endif - - if ((!IS_CONNEXION_CHALLENGE(item->lobby_flags)) && EXTRACT_PRIVACY_FLAGS(item->lobby_flags) != EXTRACT_PRIVACY_FLAGS(it->second.lobby_flags)) - { - std::cerr << " : Don't match. Cancelling." << std::endl; - return ; - } -#ifdef DEBUG_CHAT_LOBBIES - else - std::cerr << " : Match!" << std::endl; - - std::cerr << " Adding new friend " << item->PeerId() << " to lobby." << std::endl; -#endif - - // to be removed (deprecated since May 2017) - { //Update Topics if have received deprecated before (withou topic) - if(it->second.lobby_topic.empty() && !item->lobby_topic.empty()) - it->second.lobby_topic = item->lobby_topic; - } - - it->second.participating_friends.insert(item->PeerId()) ; - return ; - } - - // to be removed (deprecated since May 2017) - {//check if invitation is already received by deprecated version - std::map::const_iterator it(_lobby_invites_queue.find( item->lobby_id)) ; - if(it != _lobby_invites_queue.end()) - return ; - } - // Don't record the invitation if it's a challenge response item or a lobby we don't have. - // - if(IS_CONNEXION_CHALLENGE(item->lobby_flags)) - return ; - - // no, then create a new invitation entry in the cache. - - ChatLobbyInvite invite ; - invite.lobby_id = item->lobby_id ; - invite.peer_id = item->PeerId() ; - invite.lobby_name = item->lobby_name ; - invite.lobby_topic = item->lobby_topic ; - invite.lobby_flags = item->lobby_flags ; - - _lobby_invites_queue[item->lobby_id] = invite ; - } - // 2 - notify the gui to ask the user. - RsServer::notify()->notifyListChange(NOTIFY_LIST_CHAT_LOBBY_INVITATION, NOTIFY_TYPE_ADD); -} - -void DistributedChatService::getPendingChatLobbyInvites(std::list& invites) -{ - invites.clear() ; - - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - for(std::map::const_iterator it(_lobby_invites_queue.begin());it!=_lobby_invites_queue.end();++it) - invites.push_back(it->second) ; -} - - -bool DistributedChatService::acceptLobbyInvite(const ChatLobbyId& lobby_id,const RsGxsId& identity) -{ - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Accepting chat lobby "<< lobby_id << std::endl; -#endif - - std::map::iterator it = _lobby_invites_queue.find(lobby_id) ; - - if(it == _lobby_invites_queue.end()) - { - std::cerr << " (EE) lobby invite not in cache!!" << std::endl; - return false; - } - - //std::map::const_iterator vid = _visible_lobbies.find(lobby_id) ; - - //When invited to new Lobby, it is not visible. - //if(_visible_lobbies.end() == vid) - //{ - // std::cerr << " (EE) Cannot subscribe a non visible chat lobby!!" << std::endl; - // return false ; - //} - - RsIdentityDetails det ; - if( (!rsIdentity->getIdDetails(identity,det)) || !(det.mFlags & RS_IDENTITY_FLAGS_IS_OWN_ID)) - { - std::cerr << " (EE) Cannot subscribe with identity " << identity << " because it is not ours! Something's wrong here." << std::endl; - return false ; - } - - if( (it->second.lobby_flags & RS_CHAT_LOBBY_FLAGS_PGP_SIGNED ) && !(det.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED)) - { - std::cerr << " (EE) Cannot subscribe with identity " << identity << " because it is unsigned and the lobby requires signed ids only." << std::endl; - return false ; - } - - if(_chat_lobbys.find(lobby_id) != _chat_lobbys.end()) - { - std::cerr << " (II) Lobby already exists. Weird." << std::endl; - return true ; - } - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Creating new Lobby entry." << std::endl; -#endif - rstime_t now = time(NULL) ; - - ChatLobbyEntry entry ; - entry.participating_friends.insert(it->second.peer_id) ; - entry.lobby_flags = it->second.lobby_flags ; - entry.gxs_id = identity ; - entry.lobby_id = lobby_id ; - entry.lobby_name = it->second.lobby_name ; - entry.lobby_topic = it->second.lobby_topic ; - entry.virtual_peer_id = makeVirtualPeerId(lobby_id) ; - entry.connexion_challenge_count = 0 ; - entry.last_activity = now ; - entry.last_connexion_challenge_time = now ; - entry.joined_lobby_packet_sent = false; - entry.last_keep_alive_packet_time = now ; - - _chat_lobbys[lobby_id] = entry ; - - _lobby_invites_queue.erase(it) ; // remove the invite from cache. - - // we should also send a message to the lobby to tell we're here. - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Pushing new msg item to incoming msgs." << std::endl; -#endif - RsChatLobbyMsgItem *item = new RsChatLobbyMsgItem; - item->lobby_id = entry.lobby_id ; - item->msg_id = 0 ; - item->parent_msg_id = 0 ; - item->nick = "Chat room management" ; - item->message = std::string("Welcome to chat lobby") ; - item->PeerId(entry.virtual_peer_id) ; - item->chatFlags = RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_LOBBY ; - - locked_storeIncomingMsg(item) ; - } -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Notifying of new recvd msg." << std::endl ; -#endif - - RsServer::notify()->notifyListChange(NOTIFY_LIST_PRIVATE_INCOMING_CHAT, NOTIFY_TYPE_ADD); - RsServer::notify()->notifyListChange(NOTIFY_LIST_CHAT_LOBBY_LIST, NOTIFY_TYPE_ADD); - - // send AKN item - sendLobbyStatusNewPeer(lobby_id) ; - - return true ; -} - -ChatLobbyVirtualPeerId DistributedChatService::makeVirtualPeerId(ChatLobbyId lobby_id) -{ - uint8_t bytes[RsPeerId::SIZE_IN_BYTES] ; - memset(bytes,0,RsPeerId::SIZE_IN_BYTES) ; - memcpy(bytes,&lobby_id,sizeof(lobby_id)) ; - - return ChatLobbyVirtualPeerId(bytes) ; -} - - -bool DistributedChatService::denyLobbyInvite(const ChatLobbyId& lobby_id) -{ - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Denying chat lobby invite to "<< lobby_id << std::endl; -#endif - std::map::iterator it = _lobby_invites_queue.find(lobby_id) ; - - if(it == _lobby_invites_queue.end()) - { - std::cerr << " (EE) lobby invite not in cache!!" << std::endl; - return false; - } - - _lobby_invites_queue.erase(it) ; - - return true; -} - -bool DistributedChatService::joinVisibleChatLobby(const ChatLobbyId& lobby_id,const RsGxsId& gxs_id) -{ - RsIdentityDetails det ; - if( (!rsIdentity->getIdDetails(gxs_id,det)) || !(det.mFlags & RS_IDENTITY_FLAGS_IS_OWN_ID)) - { - std::cerr << " (EE) Cannot subscribe with identity " << gxs_id << " because it is not ours! Something's wrong here." << std::endl; - return false ; - } - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Joining public chat lobby " << std::hex << lobby_id << std::dec << std::endl; -#endif - std::list invited_friends ; - - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - // create a unique id. - // - std::map::const_iterator it(_visible_lobbies.find(lobby_id)) ; - - if(it == _visible_lobbies.end()) - { - std::cerr << " lobby is not a known public chat lobby. Sorry!" << std::endl; - return false ; - } - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " lobby found. Initiating join sequence..." << std::endl; -#endif - - if(_chat_lobbys.find(lobby_id) != _chat_lobbys.end()) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " lobby already in participating list. Returning!" << std::endl; -#endif - return true ; - } - - if( (it->second.lobby_flags & RS_CHAT_LOBBY_FLAGS_PGP_SIGNED ) && !(det.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED)) - { - std::cerr << " (EE) Cannot subscribe with identity " << gxs_id << " because it is unsigned and the lobby requires signed ids only." << std::endl; - return false ; - } - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " Creating new lobby entry." << std::endl; -#endif - rstime_t now = time(NULL) ; - - ChatLobbyEntry entry ; - - entry.lobby_flags = it->second.lobby_flags ;//RS_CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC ; - entry.participating_friends.clear() ; - entry.gxs_id = gxs_id ; - entry.lobby_id = lobby_id ; - entry.lobby_name = it->second.lobby_name ; - entry.lobby_topic = it->second.lobby_topic ; - entry.virtual_peer_id = makeVirtualPeerId(lobby_id) ; - entry.connexion_challenge_count = 0 ; - entry.last_activity = now ; - entry.last_connexion_challenge_time = now ; - entry.joined_lobby_packet_sent = false; - entry.last_keep_alive_packet_time = now ; - - for(std::set::const_iterator it2(it->second.participating_friends.begin());it2!=it->second.participating_friends.end();++it2) - { - invited_friends.push_back(*it2) ; - entry.participating_friends.insert(*it2) ; - } - _chat_lobbys[lobby_id] = entry ; - } - - setLobbyAutoSubscribe(lobby_id,true); - - triggerConfigSave(); // so that we save the subscribed lobbies - - for(std::list::const_iterator it(invited_friends.begin());it!=invited_friends.end();++it) - invitePeerToLobby(lobby_id,*it) ; - - RsServer::notify()->notifyListChange(NOTIFY_LIST_CHAT_LOBBY_LIST, NOTIFY_TYPE_ADD) ; - sendLobbyStatusNewPeer(lobby_id) ; - - return true ; -} - -ChatLobbyId DistributedChatService::createChatLobby(const std::string& lobby_name,const RsGxsId& lobby_identity,const std::string& lobby_topic,const std::set& invited_friends,ChatLobbyFlags lobby_flags) -{ -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Creating a new Chat lobby !!" << std::endl; -#endif - ChatLobbyId lobby_id ; - { - if (!rsIdentity->isOwnId(lobby_identity)) - { - RsErr() << __PRETTY_FUNCTION__ << " lobby_identity RsGxsId id must be own" << std::endl; - return 0; - } - - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - // create a unique id. - // - do { lobby_id = RSRandom::random_u64() ; } while(_chat_lobbys.find(lobby_id) != _chat_lobbys.end()) ; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " New (unique) ID: " << std::hex << lobby_id << std::dec << std::endl; -#endif - rstime_t now = time(NULL) ; - - ChatLobbyEntry entry ; - entry.lobby_flags = lobby_flags ; - entry.participating_friends.clear() ; - entry.gxs_id = lobby_identity ; // to be changed. For debug only!! - entry.lobby_id = lobby_id ; - entry.lobby_name = lobby_name ; - entry.lobby_topic = lobby_topic ; - entry.virtual_peer_id = makeVirtualPeerId(lobby_id) ; - entry.connexion_challenge_count = 0 ; - entry.last_activity = now ; - entry.last_connexion_challenge_time = now ; - entry.joined_lobby_packet_sent = false; - entry.last_keep_alive_packet_time = now ; - - _chat_lobbys[lobby_id] = entry ; - } - - for(std::set::const_iterator it(invited_friends.begin());it!=invited_friends.end();++it) - invitePeerToLobby(lobby_id,*it) ; - - RsServer::notify()->notifyListChange(NOTIFY_LIST_CHAT_LOBBY_LIST, NOTIFY_TYPE_ADD) ; - - triggerConfigSave(); - - return lobby_id ; -} - -void DistributedChatService::handleFriendUnsubscribeLobby(RsChatLobbyUnsubscribeItem *item) -{ - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - std::map::iterator it = _chat_lobbys.find(item->lobby_id) ; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Received unsubscribed to lobby " << std::hex << item->lobby_id << std::dec << ", from friend " << item->PeerId() << std::endl; -#endif - - if(it == _chat_lobbys.end()) - { - std::cerr << "Chat lobby " << std::hex << item->lobby_id << std::dec << " does not exist ! Can't unsubscribe friend!" << std::endl; - return ; - } - - for(std::set::iterator it2(it->second.participating_friends.begin());it2!=it->second.participating_friends.end();++it2) - if(*it2 == item->PeerId()) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " removing peer id " << item->PeerId() << " from participant list of lobby " << std::hex << item->lobby_id << std::dec << std::endl; -#endif - it->second.previously_known_peers.insert(*it2) ; - it->second.participating_friends.erase(it2) ; - break ; - } - } - - RsServer::notify()->notifyListChange(NOTIFY_LIST_CHAT_LOBBY_LIST, NOTIFY_TYPE_MOD) ; -} - -void DistributedChatService::unsubscribeChatLobby(const ChatLobbyId& id) -{ - // send AKN item - sendLobbyStatusPeerLeaving(id) ; - setLobbyAutoSubscribe(id, false); - - { - RS_STACK_MUTEX(mDistributedChatMtx); - - std::map::iterator it = _chat_lobbys.find(id) ; - - if(it == _chat_lobbys.end()) - { - std::cerr << "Chat lobby " << id << " does not exist ! Can't unsubscribe!" << std::endl; - return ; - } - - // send a lobby leaving packet to all friends - - for(std::set::const_iterator it2(it->second.participating_friends.begin());it2!=it->second.participating_friends.end();++it2) - { - RsChatLobbyUnsubscribeItem *item = new RsChatLobbyUnsubscribeItem ; - - item->lobby_id = id ; - item->PeerId(*it2) ; - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Sending unsubscribe item to friend " << *it2 << std::endl; -#endif - - sendChatItem(item) ; - } - - // remove history - - //mHistoryMgr->clear(it->second.virtual_peer_id); - - // remove lobby information - - _chat_lobbys.erase(it) ; - } - - triggerConfigSave(); // so that we save the subscribed lobbies - RsServer::notify()->notifyListChange(NOTIFY_LIST_CHAT_LOBBY_LIST, NOTIFY_TYPE_DEL) ; - - // done! -} -bool DistributedChatService::setDefaultIdentityForChatLobby(const RsGxsId& nick) -{ - if (nick.isNull()) - { - std::cerr << "Ignore empty nickname for chat lobby " << std::endl; - return false; - } - - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - _default_identity = nick; - } - - triggerConfigSave() ; - return true ; -} - -void DistributedChatService::getDefaultIdentityForChatLobby(RsGxsId& nick) -{ - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - nick = locked_getDefaultIdentity() ; -} - -RsGxsId DistributedChatService::locked_getDefaultIdentity() -{ - if(_default_identity.isNull() && rsIdentity!=NULL) - { - std::list own_ids ; - rsIdentity->getOwnIds(own_ids) ; - - if(!own_ids.empty()) - { - _default_identity = own_ids.front() ; - triggerConfigSave(); - } - } - return _default_identity ; -} - -bool DistributedChatService::getIdentityForChatLobby(const ChatLobbyId& lobby_id,RsGxsId& nick) -{ - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "getting nickname for chat lobby "<< std::hex << lobby_id << std::dec << std::endl; -#endif - std::map::iterator it = _chat_lobbys.find(lobby_id) ; - - if(it == _chat_lobbys.end()) - { - std::cerr << " (EE) lobby does not exist!!" << std::endl; - return false ; - } - - nick = it->second.gxs_id ; - return true ; -} - -bool DistributedChatService::setIdentityForChatLobby(const ChatLobbyId& lobby_id,const RsGxsId& nick) -{ - if (nick.isNull()) - { - std::cerr << "(EE) Ignore empty nickname for chat lobby " << nick << std::endl; - return false; - } - - // first check for change and send status peer changed nick name - bool changed = false; - std::map::iterator it; - - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Changing nickname for chat lobby " << std::hex << lobby_id << std::dec << " to " << nick << std::endl; -#endif - it = _chat_lobbys.find(lobby_id) ; - - if(it == _chat_lobbys.end()) - { - std::cerr << " (EE) lobby does not exist!!" << std::endl; - return false; - } - - if (!it->second.gxs_id.isNull() && it->second.gxs_id != nick) - changed = true; - } - - if (changed) - { - // Inform other peers of change the Nickname - { - RsIdentityDetails det1,det2 ; - - // Only send a nickname change event if the two Identities are not anonymous - - if(rsIdentity->getIdDetails(nick,det1) && rsIdentity->getIdDetails(it->second.gxs_id,det2) && (det1.mFlags & det2.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED)) - sendLobbyStatusPeerChangedNickname(lobby_id, nick.toStdString()) ; - } - - // set new nick name - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - it = _chat_lobbys.find(lobby_id) ; - - if(it == _chat_lobbys.end()) - { - std::cerr << " (EE) lobby does not exist!!" << std::endl; - return false; - } - - it->second.gxs_id = nick ; - } - - return true ; -} - -void DistributedChatService::setLobbyAutoSubscribe(const ChatLobbyId& lobby_id, const bool autoSubscribe) -{ - - if(autoSubscribe) - { - { - RS_STACK_MUTEX(mDistributedChatMtx); - _known_lobbies_flags[lobby_id] |= RS_CHAT_LOBBY_FLAGS_AUTO_SUBSCRIBE; - } - RsGxsId gxsId; - - if (getIdentityForChatLobby(lobby_id, gxsId)) - { - RS_STACK_MUTEX(mDistributedChatMtx); - _lobby_default_identity[lobby_id] = gxsId; - } - } - else - { - RS_STACK_MUTEX(mDistributedChatMtx); - _known_lobbies_flags[lobby_id] &= ~RS_CHAT_LOBBY_FLAGS_AUTO_SUBSCRIBE ; - _lobby_default_identity.erase(lobby_id); - } - - RsServer::notify()->notifyListChange(NOTIFY_LIST_CHAT_LOBBY_LIST, NOTIFY_TYPE_ADD) ; - triggerConfigSave(); -} - -bool DistributedChatService::getLobbyAutoSubscribe(const ChatLobbyId& lobby_id) -{ - if(_known_lobbies_flags.find(lobby_id) == _known_lobbies_flags.end()) // keep safe about default values form std::map - return false; - - return _known_lobbies_flags[lobby_id] & RS_CHAT_LOBBY_FLAGS_AUTO_SUBSCRIBE ; -} - -void DistributedChatService::cleanLobbyCaches() -{ -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Cleaning chat lobby caches." << std::endl; -#endif - - std::list keep_alive_lobby_ids ; - std::list changed_lobbies ; - std::list send_challenge_lobbies ; - std::list joined_lobby_ids ; - - { - RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - rstime_t now = time(NULL) ; - - for(std::map::iterator it = _chat_lobbys.begin();it!=_chat_lobbys.end();++it) - { - // 1 - remove old messages - // - for(std::map::iterator it2(it->second.msg_cache.begin());it2!=it->second.msg_cache.end();) - if(it2->second + MAX_KEEP_MSG_RECORD < now) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " removing old msg 0x" << std::hex << it2->first << ", time=" << std::dec << now - it2->second << " secs ago" << std::endl; -#endif - - std::map::iterator tmp(it2) ; - ++tmp ; - it->second.msg_cache.erase(it2) ; - it2 = tmp ; - } - else - ++it2 ; - - bool changed = false ; - - // 2 - remove inactive nicknames - // - for(std::map::iterator it2(it->second.gxs_ids.begin());it2!=it->second.gxs_ids.end();) - if(it2->second + MAX_KEEP_INACTIVE_NICKNAME < now) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " removing inactive nickname 0x" << std::hex << it2->first << ", time=" << std::dec << now - it2->second << " secs ago" << std::endl; -#endif - - std::map::iterator tmp(it2) ; - ++tmp ; - it->second.gxs_ids.erase(it2) ; - it2 = tmp ; - changed = true ; - } - else - ++it2 ; - - if(changed) - changed_lobbies.push_back(it->first) ; - - // 3 - send a joined_lobby packet if a participating friend is connected, we do that only once - // - if (!it->second.joined_lobby_packet_sent) - { - bool oneParticipatingFriendIsConnected = false; - for(std::set::const_iterator fit(it->second.participating_friends.begin());fit!=it->second.participating_friends.end();++fit) - { - if(mServControl->isPeerConnected(mServType, *fit)) - { - oneParticipatingFriendIsConnected = true; - break; - } - } - if (oneParticipatingFriendIsConnected) - { - joined_lobby_ids.push_back(it->first) ; - it->second.joined_lobby_packet_sent = true; - } - } - - // 4 - send lobby keep-alive packet - // - if(it->second.last_keep_alive_packet_time + MAX_DELAY_BETWEEN_LOBBY_KEEP_ALIVE < now) - { - keep_alive_lobby_ids.push_back(it->first) ; - it->second.last_keep_alive_packet_time = now ; - } - - // 5 - look at lobby activity and possibly send connection challenge - // - if(++it->second.connexion_challenge_count > CONNECTION_CHALLENGE_MAX_COUNT && now > it->second.last_connexion_challenge_time + CONNECTION_CHALLENGE_MIN_DELAY) - { - it->second.connexion_challenge_count = 0 ; - it->second.last_connexion_challenge_time = now ; - send_challenge_lobbies.push_back(it->first); - } - } - - // 2 - clean deprecated public chat lobby records - // - - for(std::map::iterator it(_visible_lobbies.begin());it!=_visible_lobbies.end();) - { - if(it->second.last_report_time + MAX_KEEP_PUBLIC_LOBBY_RECORD < now && _chat_lobbys.find(it->first)==_chat_lobbys.end()) // this lobby record is too late. - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << " removing old public lobby record 0x" << std::hex << it->first << ", time=" << std::dec << now - it->second.last_report_time << " secs ago" << std::endl; -#endif - std::map::iterator tmp(it) ; - ++tmp ; - _visible_lobbies.erase(it) ; - it = tmp ; - } - else - ++it ; - } - } - - // send keep alive - for(std::list::const_iterator it(keep_alive_lobby_ids.begin());it!=keep_alive_lobby_ids.end();++it) - sendLobbyStatusKeepAlive(*it) ; - - // update the gui - for(std::list::const_iterator it(changed_lobbies.begin());it!=changed_lobbies.end();++it) - RsServer::notify()->notifyChatLobbyEvent(*it,RS_CHAT_LOBBY_EVENT_KEEP_ALIVE,RsGxsId(),"") ; - - // send peer joined - for(std::list::const_iterator it(joined_lobby_ids.begin());it!=joined_lobby_ids.end();++it) - sendLobbyStatusNewPeer(*it) ; - - // send connection challenges - for(std::list::const_iterator it(send_challenge_lobbies.begin());it!=send_challenge_lobbies.end();++it) - sendConnectionChallenge(*it) ; -} - -void DistributedChatService::addToSaveList(std::list& list) const -{ - /* Save Lobby Auto Subscribe */ - for(std::map::const_iterator it=_known_lobbies_flags.begin(); it!=_known_lobbies_flags.end(); ++it) - { - RsChatLobbyConfigItem *clci = new RsChatLobbyConfigItem ; - clci->lobby_Id=it->first; - clci->flags=it->second.toUInt32(); - - list.push_back(clci) ; - } - - for(auto it(_chat_lobbys.begin());it!=_chat_lobbys.end();++it) - { - RsSubscribedChatLobbyConfigItem *scli = new RsSubscribedChatLobbyConfigItem; - scli->info = it->second; // copies the ChatLobbyInfo part only - list.push_back(scli); - } - - /* Save Default Nick Name */ - { - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; - RsTlvKeyValue kv; - kv.key = "DEFAULT_IDENTITY"; - kv.value = _default_identity.toStdString(); - vitem->tlvkvs.pairs.push_back(kv); - list.push_back(vitem); - } - - /* Save Default Nick Name by Lobby*/ - for(std::map::const_iterator it=_lobby_default_identity.begin(); it!=_lobby_default_identity.end(); ++it) - { - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; - ChatLobbyId cli = it->first; - RsGxsId gxsId = it->second; - - std::stringstream stream; - stream << std::setfill ('0') << std::setw(sizeof(ChatLobbyId)*2) - << std::hex << cli; - std::string strCli( stream.str() ); - - RsTlvKeyValue kv; - kv.key = "LOBBY_DEFAULT_IDENTITY:"+strCli; - kv.value = gxsId.toStdString(); - vitem->tlvkvs.pairs.push_back(kv); - list.push_back(vitem); - } - -} - -bool DistributedChatService::processLoadListItem(const RsItem *item) -{ - const RsConfigKeyValueSet *vitem = NULL; - const std::string strldID = "LOBBY_DEFAULT_IDENTITY:"; - - if(NULL != (vitem = dynamic_cast(item))) - for(std::list::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) - { - if( kit->key == "DEFAULT_IDENTITY" ) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Loaded config default nick name for distributed chat: " << kit->value << std::endl ; -#endif - if (!kit->value.empty()) - { - _default_identity = RsGxsId(kit->value) ; - if(_default_identity.isNull()) - std::cerr << "ERROR: default identity is malformed." << std::endl; - } - - return true; - } - - if( kit->key.compare(0, strldID.length(), strldID) == 0) - { -#ifdef DEBUG_CHAT_LOBBIES - std::cerr << "Loaded config lobby default nick name: " << kit->key << " " << kit->value << std::endl ; -#endif - - std::string strCli = kit->key.substr(strldID.length()); - std::stringstream stream; - stream << std::hex << strCli; - ChatLobbyId cli = 0; - stream >> cli; - - if (!kit->value.empty() && (cli != 0)) - { - RsGxsId gxsId(kit->value); - if (gxsId.isNull()) - std::cerr << "ERROR: lobby default identity is malformed." << std::endl; - else - _lobby_default_identity[cli] = gxsId ; - } - - return true; - } - } - - const RsChatLobbyConfigItem *clci = NULL ; - - if(NULL != (clci = dynamic_cast(item))) - { - _known_lobbies_flags[clci->lobby_Id] = ChatLobbyFlags(clci->flags) ; - return true ; - } - - if(_default_identity.isNull() && rsIdentity!=NULL) - { - std::list own_ids ; - rsIdentity->getOwnIds(own_ids) ; - - if(!own_ids.empty()) - _default_identity = own_ids.front() ; - } - - const RsSubscribedChatLobbyConfigItem *scli = dynamic_cast(item); - - if(scli != NULL) - { - if(_chat_lobbys.find(scli->info.lobby_id) != _chat_lobbys.end()) // do nothing if the lobby is already subscribed - return true; - - std::cerr << "Re-subscribing to chat lobby " << (void*)scli->info.lobby_id << ", flags = " << scli->info.lobby_flags << std::endl; - - rstime_t now = time(NULL); - - // Add the chat room into visible chat rooms - { - RS_STACK_MUTEX(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - - VisibleChatLobbyRecord& rec(_visible_lobbies[scli->info.lobby_id]) ; - - rec.lobby_id = scli->info.lobby_id ; - rec.lobby_name = scli->info.lobby_name ; - rec.lobby_topic = scli->info.lobby_topic ; - rec.participating_friends = scli->info.participating_friends; - rec.total_number_of_peers = 0; - rec.last_report_time = now ; - rec.lobby_flags = EXTRACT_PRIVACY_FLAGS(scli->info.lobby_flags) ; - - _known_lobbies_flags[scli->info.lobby_id] |= RS_CHAT_LOBBY_FLAGS_AUTO_SUBSCRIBE; - } - - // Add the chat room into subscribed chat rooms - - ChatLobbyEntry entry ; - (ChatLobbyInfo&)entry = scli->info; - - entry.virtual_peer_id = makeVirtualPeerId(entry.lobby_id) ; // not random, so we keep the same id at restart - entry.connexion_challenge_count = 0 ; - entry.last_activity = now ; - entry.last_connexion_challenge_time = now ; - entry.joined_lobby_packet_sent = false ; - entry.last_keep_alive_packet_time = now ; - - { - RS_STACK_MUTEX(mDistributedChatMtx); /********** STACK LOCKED MTX ******/ - _chat_lobbys[entry.lobby_id] = entry ; - } - - // make the UI aware of the existing chat room - - RsServer::notify()->notifyListChange(NOTIFY_LIST_CHAT_LOBBY_LIST, NOTIFY_TYPE_ADD) ; - - return true; - } - - return false ; -} - diff --git a/libretroshare/src/chat/distributedchat.h b/libretroshare/src/chat/distributedchat.h deleted file mode 100644 index e7b9ee33a..000000000 --- a/libretroshare/src/chat/distributedchat.h +++ /dev/null @@ -1,168 +0,0 @@ -/******************************************************************************* - * libretroshare/src/chat: distributedchat.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include - -typedef RsPeerId ChatLobbyVirtualPeerId ; - -struct RsItem; -class p3HistoryMgr ; -class p3IdService ; -class p3ServiceControl; -class RsChatLobbyItem ; -class RsChatLobbyListRequestItem ; -class RsChatLobbyListItem ; -class RsChatLobbyEventItem ; -class RsChatLobbyBouncingObject ; -class RsChatLobbyInviteItem_Deprecated ; // to be removed (deprecated since May 2017) -class RsChatLobbyInviteItem ; -class RsChatLobbyMsgItem ; -class RsChatLobbyConnectChallengeItem ; -class RsChatLobbyUnsubscribeItem ; - -class RsChatItem ; -class RsChatMsgItem ; -class RsGixs ; - -class DistributedChatService -{ - public: - DistributedChatService(uint32_t service_type,p3ServiceControl *sc,p3HistoryMgr *hm,RsGixs *is) ; - - virtual ~DistributedChatService() {} - - void flush() ; - - // Interface part to communicate with - // - bool getVirtualPeerId(const ChatLobbyId& lobby_id, RsPeerId& virtual_peer_id) ; - void getChatLobbyList(std::list& clids) ; - bool getChatLobbyInfo(const ChatLobbyId& id,ChatLobbyInfo& clinfo) ; - bool acceptLobbyInvite(const ChatLobbyId& id,const RsGxsId& identity) ; - bool denyLobbyInvite(const ChatLobbyId& id) ; - void getPendingChatLobbyInvites(std::list& invites) ; - void invitePeerToLobby(const ChatLobbyId&, const RsPeerId& peer_id,bool connexion_challenge = false) ; - void unsubscribeChatLobby(const ChatLobbyId& lobby_id) ; - bool setIdentityForChatLobby(const ChatLobbyId& lobby_id,const RsGxsId& nick) ; - bool getIdentityForChatLobby(const ChatLobbyId& lobby_id,RsGxsId& nick) ; - bool setDefaultIdentityForChatLobby(const RsGxsId& nick) ; - void getDefaultIdentityForChatLobby(RsGxsId& nick) ; - void setLobbyAutoSubscribe(const ChatLobbyId& lobby_id, const bool autoSubscribe); - bool getLobbyAutoSubscribe(const ChatLobbyId& lobby_id); - void sendLobbyStatusString(const ChatLobbyId& id,const std::string& status_string) ; - void sendLobbyStatusPeerLeaving(const ChatLobbyId& lobby_id) ; - - ChatLobbyId createChatLobby(const std::string& lobby_name,const RsGxsId& lobby_identity,const std::string& lobby_topic, const std::set& invited_friends,ChatLobbyFlags flags) ; - - void getListOfNearbyChatLobbies(std::vector& public_lobbies) ; - bool joinVisibleChatLobby(const ChatLobbyId& id, const RsGxsId &gxs_id) ; - - protected: - bool handleRecvItem(RsChatItem *) ; - - virtual void sendChatItem(RsChatItem *) =0 ; - virtual void locked_storeIncomingMsg(RsChatMsgItem *) =0 ; - virtual void triggerConfigSave() =0; - - void addToSaveList(std::list& list) const ; - bool processLoadListItem(const RsItem *item) ; - - void checkSizeAndSendLobbyMessage(RsChatItem *) ; - - bool sendLobbyChat(const ChatLobbyId &lobby_id, const std::string&) ; - bool handleRecvChatLobbyMsgItem(RsChatMsgItem *item) ; - - bool checkSignature(RsChatLobbyBouncingObject *obj,const RsPeerId& peer_id) ; - - private: - /// make some statistics about time shifts, to prevent various issues. - void addTimeShiftStatistics(int shift) ; - - void handleRecvChatLobbyListRequest(RsChatLobbyListRequestItem *item) ; - void handleRecvChatLobbyList(RsChatLobbyListItem *item) ; - void handleRecvChatLobbyEventItem(RsChatLobbyEventItem *item) ; - - - /// Checks that the lobby object is not flooding a lobby. - bool locked_bouncingObjectCheck(RsChatLobbyBouncingObject *obj,const RsPeerId& peer_id,uint32_t lobby_count) ; - - /// receive and handle chat lobby item - bool recvLobbyChat(RsChatLobbyMsgItem*,const RsPeerId& src_peer_id) ; - void handleRecvLobbyInvite_Deprecated(RsChatLobbyInviteItem_Deprecated*) ; // to be removed (deprecated since May 2017) - void handleRecvLobbyInvite(RsChatLobbyInviteItem*) ; - void checkAndRedirectMsgToLobby(RsChatMsgItem*) ; - void handleConnectionChallenge(RsChatLobbyConnectChallengeItem *item) ; - void sendConnectionChallenge(ChatLobbyId id) ; - void handleFriendUnsubscribeLobby(RsChatLobbyUnsubscribeItem*) ; - void cleanLobbyCaches() ; - bool bounceLobbyObject(RsChatLobbyBouncingObject *obj, const RsPeerId& peer_id) ; - - void sendLobbyStatusItem(const ChatLobbyId&, int type, const std::string& status_string) ; - void sendLobbyStatusPeerChangedNickname(const ChatLobbyId& lobby_id, const std::string& newnick) ; - - void sendLobbyStatusNewPeer(const ChatLobbyId& lobby_id) ; - void sendLobbyStatusKeepAlive(const ChatLobbyId&) ; - - bool locked_initLobbyBouncableObject(const ChatLobbyId& id,RsChatLobbyBouncingObject&) ; - void locked_printDebugInfo() const ; - RsGxsId locked_getDefaultIdentity(); - - static ChatLobbyVirtualPeerId makeVirtualPeerId(ChatLobbyId) ; - static uint64_t makeConnexionChallengeCode(const RsPeerId& peer_id,ChatLobbyId lobby_id,ChatLobbyMsgId msg_id) ; - - class ChatLobbyEntry: public ChatLobbyInfo - { - public: - std::map msg_cache ; - RsPeerId virtual_peer_id ; - int connexion_challenge_count ; - rstime_t last_connexion_challenge_time ; - bool joined_lobby_packet_sent; - rstime_t last_keep_alive_packet_time ; - std::set previously_known_peers ; - }; - - std::map _chat_lobbys ; - std::map _lobby_invites_queue ; - std::map _visible_lobbies ; - std::map _known_lobbies_flags ; // flags for all lobbies, including the ones that are not known. So we can't - std::map > _pendingPartialLobbyMessages ; // store them in _chat_lobbies (subscribed lobbies) nor _visible_lobbies. - // Known flags: - // RS_CHAT_LOBBY_FLAGS_AUTO_SUBSCRIBE - - float _time_shift_average ; - rstime_t last_lobby_challenge_time ; // prevents bruteforce attack - rstime_t last_visible_lobby_info_request_time ; // allows to ask for updates - bool _should_reset_lobby_counts ; - RsGxsId _default_identity; - std::map _lobby_default_identity; - - uint32_t mServType ; - RsMutex mDistributedChatMtx ; - - p3ServiceControl *mServControl; - p3HistoryMgr *mHistMgr; - RsGixs *mGixs ; -}; diff --git a/libretroshare/src/chat/p3chatservice.cc b/libretroshare/src/chat/p3chatservice.cc deleted file mode 100644 index 3fbbdaf75..000000000 --- a/libretroshare/src/chat/p3chatservice.cc +++ /dev/null @@ -1,1485 +0,0 @@ -/******************************************************************************* - * libretroshare/src/chat: chatservice.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include -#include -#include - -#include "util/rsdir.h" -#include "util/radix64.h" -#include "crypto/rsaes.h" -#include "util/rsrandom.h" -#include "util/rsstring.h" -#include "retroshare/rsiface.h" -#include "retroshare/rspeers.h" -#include "retroshare/rsstatus.h" -#include "pqi/pqibin.h" -#include "pqi/pqistore.h" -#include "pqi/p3linkmgr.h" -#include "pqi/p3historymgr.h" -#include "rsserver/p3face.h" -#include "services/p3idservice.h" -#include "gxstrans/p3gxstrans.h" - -#include "chat/p3chatservice.h" -#include "rsitems/rsconfigitems.h" - -/**** - * #define CHAT_DEBUG 1 - ****/ - -static const uint32_t MAX_MESSAGE_SECURITY_SIZE = 31000 ; // Max message size to forward other friends -static const uint32_t MAX_AVATAR_JPEG_SIZE = 32767; // Maximum size in bytes for an avatar. Too large packets - // don't transfer correctly and can kill the system. - // Images are 96x96, which makes approx. 27000 bytes uncompressed. - -p3ChatService::p3ChatService( p3ServiceControl *sc, p3IdService *pids, - p3LinkMgr *lm, p3HistoryMgr *historyMgr, - p3GxsTrans& gxsTransService ) : - DistributedChatService(getServiceInfo().mServiceType, sc, historyMgr,pids), - mChatMtx("p3ChatService"), mServiceCtrl(sc), mLinkMgr(lm), - mHistoryMgr(historyMgr), _own_avatar(NULL), - _serializer(new RsChatSerialiser()), - mDGMutex("p3ChatService distant id - gxs id map mutex"), - mGxsTransport(gxsTransService) -{ - addSerialType(_serializer); - mGxsTransport.registerGxsTransClient( GxsTransSubServices::P3_CHAT_SERVICE, - this ); -} - -RsServiceInfo p3ChatService::getServiceInfo() -{ return RsServiceInfo(RS_SERVICE_TYPE_CHAT, "chat", 1, 0, 1, 0); } - -int p3ChatService::tick() -{ - if(receivedItems()) receiveChatQueue(); - - DistributedChatService::flush(); - - return 0; -} - -/***************** Chat Stuff **********************/ - -void p3ChatService::sendPublicChat(const std::string &msg) -{ - /* go through all the peers */ - - std::set ids; - std::set::iterator it; - mServiceCtrl->getPeersConnected(getServiceInfo().mServiceType, ids); - - /* add in own id -> so get reflection */ - RsPeerId ownId = mServiceCtrl->getOwnId(); - ids.insert(ownId); - -#ifdef CHAT_DEBUG - std::cerr << "p3ChatService::sendChat()"; - std::cerr << std::endl; -#endif - - for(it = ids.begin(); it != ids.end(); ++it) - { - RsChatMsgItem *ci = new RsChatMsgItem(); - - ci->PeerId(*it); - ci->chatFlags = RS_CHAT_FLAG_PUBLIC; - ci->sendTime = time(NULL); - ci->recvTime = ci->sendTime; - ci->message = msg; - -#ifdef CHAT_DEBUG - std::cerr << "p3ChatService::sendChat() Item:"; - std::cerr << std::endl; - ci->print(std::cerr); - std::cerr << std::endl; -#endif - - if (*it == ownId) - { - //mHistoryMgr->addMessage(false, RsPeerId(), ownId, ci); - ChatMessage message; - initChatMessage(ci, message); - message.incoming = false; - message.online = true; - RsServer::notify()->notifyChatMessage(message); - mHistoryMgr->addMessage(message); - } - else - checkSizeAndSendMessage(ci); - } -} - - -class p3ChatService::AvatarInfo -{ - public: - AvatarInfo() - { - _image_size = 0 ; - _image_data = NULL ; - _peer_is_new = false ; // true when the peer has a new avatar - _own_is_new = false ; // true when I myself a new avatar to send to this peer. - } - - ~AvatarInfo() - { - free( _image_data ); - _image_data = NULL ; - _image_size = 0 ; - } - - AvatarInfo(const AvatarInfo& ai) - { - init(ai._image_data,ai._image_size) ; - } - - void init(const unsigned char *jpeg_data,int size) - { - if(size == 0) - { - _image_size = 0; - _image_data = nullptr; - } - else - { - _image_size = size ; - _image_data = (unsigned char*)rs_malloc(size) ; - memcpy(_image_data,jpeg_data,size) ; - } - } - AvatarInfo(const unsigned char *jpeg_data,int size) - { - init(jpeg_data,size) ; - } - - void toUnsignedChar(unsigned char *& data,uint32_t& size) const - { - if(_image_size == 0) - { - size = 0 ; - data = NULL ; - return ; - } - data = (unsigned char *)rs_malloc(_image_size) ; - size = _image_size ; - memcpy(data,_image_data,size*sizeof(unsigned char)) ; - } - - uint32_t _image_size ; - unsigned char *_image_data ; - int _peer_is_new ; // true when the peer has a new avatar - int _own_is_new ; // true when I myself a new avatar to send to this peer. -}; - -void p3ChatService::sendGroupChatStatusString(const std::string& status_string) -{ - std::set ids; - mServiceCtrl->getPeersConnected(getServiceInfo().mServiceType, ids); - -#ifdef CHAT_DEBUG - std::cerr << "p3ChatService::sendChat(): sending group chat status string: " << status_string << std::endl ; - std::cerr << std::endl; -#endif - - for(std::set::iterator it = ids.begin(); it != ids.end(); ++it) - { - RsChatStatusItem *cs = new RsChatStatusItem ; - - cs->status_string = status_string ; - cs->flags = RS_CHAT_FLAG_PUBLIC ; - - cs->PeerId(*it); - - sendItem(cs); - } -} - -void p3ChatService::sendStatusString( const ChatId& id, - const std::string& status_string ) -{ - if(id.isLobbyId()) sendLobbyStatusString(id.toLobbyId(),status_string); - else if(id.isBroadcast()) sendGroupChatStatusString(status_string); - else if(id.isPeerId() || id.isDistantChatId()) - { - RsPeerId vpid; - if(id.isDistantChatId()) vpid = RsPeerId(id.toDistantChatId()); - else vpid = id.toPeerId(); - - if(isOnline(vpid)) - { - RsChatStatusItem *cs = new RsChatStatusItem; - - cs->status_string = status_string; - cs->flags = RS_CHAT_FLAG_PRIVATE; - cs->PeerId(vpid); - -#ifdef CHAT_DEBUG - std::cerr << "sending chat status packet:" << std::endl; - cs->print(std::cerr); -#endif - sendChatItem(cs); - } - } - else - { - std::cerr << "p3ChatService::sendStatusString() Error: chat id of this " - << "type is not handled, is it empty?" << std::endl; - return; - } -} - -void p3ChatService::clearChatLobby(const ChatId& id) -{ - RsServer::notify()->notifyChatCleared(id); -} - -void p3ChatService::sendChatItem(RsChatItem *item) -{ - if(DistantChatService::handleOutgoingItem(item)) return; -#ifdef CHAT_DEBUG - std::cerr << "p3ChatService::sendChatItem(): sending to " << item->PeerId() - << ": interpreted as friend peer id." << std::endl; -#endif - sendItem(item); -} - -void p3ChatService::checkSizeAndSendMessage(RsChatMsgItem *msg) -{ - // We check the message item, and possibly split it into multiple messages, if the message is too big. - - static const uint32_t MAX_STRING_SIZE = 15000 ; - -#ifdef CHAT_DEBUG - std::cerr << "Sending message: size=" << msg->message.size() << ", sha1sum=" << RsDirUtil::sha1sum((uint8_t*)msg->message.c_str(),msg->message.size()) << std::endl; -#endif - - while(msg->message.size() > MAX_STRING_SIZE) - { - // chop off the first 15000 wchars - - RsChatMsgItem *item = new RsChatMsgItem(*msg) ; - - item->message = item->message.substr(0,MAX_STRING_SIZE) ; - msg->message = msg->message.substr(MAX_STRING_SIZE,msg->message.size()-MAX_STRING_SIZE) ; - - // Clear out any one time flags that should not be copied into multiple objects. This is - // a precaution, in case the receivign peer does not yet handle split messages transparently. - // - item->chatFlags &= (RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_PUBLIC | RS_CHAT_FLAG_LOBBY) ; - -#ifdef CHAT_DEBUG - std::cerr << "Creating slice of size " << item->message.size() << std::endl; -#endif - // Indicate that the message is to be continued. - // - item->chatFlags |= RS_CHAT_FLAG_PARTIAL_MESSAGE ; - sendChatItem(item) ; - } -#ifdef CHAT_DEBUG - std::cerr << "Creating slice of size " << msg->message.size() << std::endl; -#endif - sendChatItem(msg) ; -} - - -bool p3ChatService::isOnline(const RsPeerId& pid) -{ - // check if the id is a tunnel id or a peer id. - DistantChatPeerInfo dcpinfo; - if(getDistantChatStatus(DistantChatPeerId(pid),dcpinfo)) - return dcpinfo.status == RS_DISTANT_CHAT_STATUS_CAN_TALK; - else return mServiceCtrl->isPeerConnected(getServiceInfo().mServiceType, pid); -} - -bool p3ChatService::sendChat(ChatId destination, std::string msg) -{ - if(destination.isLobbyId()) - return DistributedChatService::sendLobbyChat(destination.toLobbyId(), msg); - else if(destination.isBroadcast()) - { - sendPublicChat(msg); - return true; - } - else if(destination.isPeerId()==false && destination.isDistantChatId()==false) - { - std::cerr << "p3ChatService::sendChat() Error: chat id type not handled. Is it empty?" << std::endl; - return false; - } - // destination is peer or distant -#ifdef CHAT_DEBUG - std::cerr << "p3ChatService::sendChat()" << std::endl; -#endif - - RsPeerId vpid; - if(destination.isDistantChatId()) - vpid = RsPeerId(destination.toDistantChatId()); // convert to virtual peer id - else - vpid = destination.toPeerId(); - - RsChatMsgItem *ci = new RsChatMsgItem(); - ci->PeerId(vpid); - ci->chatFlags = RS_CHAT_FLAG_PRIVATE; - ci->sendTime = time(NULL); - ci->recvTime = ci->sendTime; - ci->message = msg; - - ChatMessage message; - initChatMessage(ci, message); - message.incoming = false; - message.online = true; - - if(!isOnline(vpid) && !destination.isDistantChatId()) - { - message.online = false; - RsServer::notify()->notifyChatMessage(message); - - // use the history to load pending messages to the gui - // this is not very nice, because the user may think the message was send, while it is still in the queue - mHistoryMgr->addMessage(message); - - RsGxsTransId tId = RSRandom::random_u64(); - -#ifdef SUSPENDED_CODE - // this part of the code was formerly used to send the traffic over GxsTransport. The problem is that - // gxstunnel takes care of reaching the peer already, so GxsTransport would only be needed when the - // current peer is offline. So we need to fin a way to quickly push the items to friends when quitting RS. - - if(destination.isDistantChatId()) - { - RS_STACK_MUTEX(mDGMutex); - DIDEMap::const_iterator it = mDistantGxsMap.find(destination.toDistantChatId()); - if(it != mDistantGxsMap.end()) - { - const DistantEndpoints& de(it->second); - uint32_t sz = _serializer->size(ci); - std::vector data; data.resize(sz); - _serializer->serialise(ci, &data[0], &sz); - mGxsTransport.sendData(tId, GxsTransSubServices::P3_CHAT_SERVICE, - de.from, de.to, &data[0], sz); - } - else - std::cout << "p3ChatService::sendChat(...) can't find distant" - << "chat id in mDistantGxsMap this is unxpected!" - << std::endl; - } -#endif - - // peer is offline, add to outgoing list - { - RS_STACK_MUTEX(mChatMtx); - privateOutgoingMap.insert(outMP::value_type(tId, ci)); - } - - IndicateConfigChanged(); - return false; - } - - { - RS_STACK_MUTEX(mChatMtx); - std::map::iterator it = _avatars.find(vpid); - - if(it == _avatars.end()) - { - _avatars[vpid] = new AvatarInfo ; - it = _avatars.find(vpid) ; - } - if(it->second->_own_is_new) - { -#ifdef CHAT_DEBUG - std::cerr << "p3ChatService::sendChat: new avatar never sent to peer " << vpid << ". Setting flag to packet." << std::endl; -#endif - - ci->chatFlags |= RS_CHAT_FLAG_AVATAR_AVAILABLE ; - it->second->_own_is_new = false ; - } - } - -#ifdef CHAT_DEBUG - std::cerr << "Sending msg to (maybe virtual) peer " << vpid << ", flags = " << ci->chatFlags << std::endl ; - std::cerr << "p3ChatService::sendChat() Item:"; - std::cerr << std::endl; - ci->print(std::cerr); - std::cerr << std::endl; -#endif - - RsServer::notify()->notifyChatMessage(message); - - // cyril: history is temporarily disabled for distant chat, since we need to store the full tunnel ID, but then - // at loading time, the ID is not known so that chat window shows 00000000 as a peer. - - //if(!message.chat_id.isDistantChatId()) - mHistoryMgr->addMessage(message); - - checkSizeAndSendMessage(ci); - - // Check if custom state string has changed, in which case it should be sent to the peer. - bool should_send_state_string = false ; - { - RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it = _state_strings.find(vpid) ; - - if(it == _state_strings.end()) - { - _state_strings[vpid] = StateStringInfo() ; - it = _state_strings.find(vpid) ; - it->second._own_is_new = true ; - } - if(it->second._own_is_new) - { - should_send_state_string = true ; - it->second._own_is_new = false ; - } - } - - if(should_send_state_string) - { -#ifdef CHAT_DEBUG - std::cerr << "own status string is new for peer " << vpid << ": sending it." << std::endl ; -#endif - RsChatStatusItem *cs = makeOwnCustomStateStringItem() ; - cs->PeerId(vpid) ; - sendChatItem(cs) ; - } - - return true; -} - -// This method might take control over the memory, or modify it, possibly adding missing parts. -// This function looks weird because it cannot duplicate the message since it does not know -// what type of object it is and the duplicate method of lobby messages is reserved for -// ChatLobby bouncing objects. -// -// Returns false if the item shouldn't be used (and replaced to NULL) - -bool p3ChatService::locked_checkAndRebuildPartialMessage(RsChatMsgItem *& ci) -{ - // Check is the item is ending an incomplete item. - // - std::map::iterator it = _pendingPartialMessages.find(ci->PeerId()) ; - - bool ci_is_incomplete = ci->chatFlags & RS_CHAT_FLAG_PARTIAL_MESSAGE ; - - if(it != _pendingPartialMessages.end()) - { -#ifdef CHAT_DEBUG - std::cerr << "Pending message found. Appending it." << std::endl; -#endif - // Yes, there is. Append the item to ci. - - ci->message = it->second->message + ci->message ; - ci->chatFlags |= it->second->chatFlags ; - - // always remove existing partial. The compound message is in ci now. - - delete it->second ; - _pendingPartialMessages.erase(it) ; - } - - // now decide what to do: if ci is incomplete, store it and replace the pointer with NULL - // if complete, return it. - - if(ci_is_incomplete) - { -#ifdef CHAT_DEBUG - std::cerr << "Message is partial, storing for later." << std::endl; -#endif - // The item is a partial message. Push it, and wait for the rest. - // - _pendingPartialMessages[ci->PeerId()] = ci ; // cannot use duplicate() here - ci = NULL ; // takes memory ownership over ci - return false ; - } - else - { -#ifdef CHAT_DEBUG - std::cerr << "Message is complete, using it now. Size = " << ci->message.size() << ", hash=" << RsDirUtil::sha1sum((uint8_t*)ci->message.c_str(),ci->message.size()) << std::endl; -#endif - return true ; - } -} - - -void p3ChatService::receiveChatQueue() -{ - RsItem *item ; - - while(NULL != (item=recvItem())) - handleIncomingItem(item) ; -} - -class MsgCounter -{ - public: - MsgCounter() {} - - void clean(rstime_t max_time) - { - while(!recv_times.empty() && recv_times.front() < max_time) - recv_times.pop_front() ; - } - std::list recv_times ; -}; - -void p3ChatService::handleIncomingItem(RsItem *item) -{ -#ifdef CHAT_DEBUG - std::cerr << "p3ChatService::receiveChatQueue() Item:" << (void*)item - << std::endl ; -#endif - - // RsChatMsgItems needs dynamic_cast, since they have derived siblings. - RsChatMsgItem* ci = dynamic_cast(item); - if(ci) - { - handleRecvChatMsgItem(ci); - - /* +ci+ deletion is handled by handleRecvChatMsgItem ONLY in some - * specific cases, in case +ci+ has not been handled deleted it here */ - delete ci ; - - return; - } - - if(DistributedChatService::handleRecvItem(dynamic_cast(item))) - { - delete item; - return; - } - - switch(item->PacketSubType()) - { - case RS_PKT_SUBTYPE_CHAT_STATUS: - handleRecvChatStatusItem(dynamic_cast(item)); - break; - case RS_PKT_SUBTYPE_CHAT_AVATAR: - handleRecvChatAvatarItem(dynamic_cast(item)); - break; - default: - { - static int already = false; - if(!already) - { - std::cerr << "Unhandled item subtype " - << static_cast(item->PacketSubType()) - << " in p3ChatService: " << std::endl; - already = true; - } - } - } - delete item; -} - -void p3ChatService::handleRecvChatAvatarItem(RsChatAvatarItem *ca) -{ - receiveAvatarJpegData(ca) ; - -#ifdef CHAT_DEBUG - std::cerr << "Received avatar data for peer " << ca->PeerId() << ". Notifying." << std::endl ; -#endif - RsServer::notify()->notifyPeerHasNewAvatar(ca->PeerId().toStdString()) ; -} - -uint32_t p3ChatService::getMaxMessageSecuritySize(int type) -{ - switch (type) - { - case RS_CHAT_TYPE_LOBBY: - return MAX_MESSAGE_SECURITY_SIZE; - - case RS_CHAT_TYPE_PUBLIC: - case RS_CHAT_TYPE_PRIVATE: - case RS_CHAT_TYPE_DISTANT: - return 0; // unlimited - } - - std::cerr << "p3ChatService::getMaxMessageSecuritySize: Unknown chat type " << type << std::endl; - - return MAX_MESSAGE_SECURITY_SIZE; -} - -bool p3ChatService::checkForMessageSecurity(RsChatMsgItem *ci) -{ - // Remove too big messages - if (ci->chatFlags & RS_CHAT_FLAG_LOBBY) - { - uint32_t maxMessageSize = getMaxMessageSecuritySize(RS_CHAT_TYPE_LOBBY); - if (maxMessageSize > 0 && ci->message.length() > maxMessageSize) - { - std::ostringstream os; - os << getMaxMessageSecuritySize(RS_CHAT_TYPE_LOBBY); - - ci->message = "**** Security warning: Message bigger than "; - ci->message += os.str(); - ci->message += " characters, forwarded to you by "; - ci->message += rsPeers->getPeerName(ci->PeerId()); - ci->message += ", dropped. ****"; - return false; - } - } - - // The following code has been suggested, but is kept suspended since it is a bit too much restrictive. -#ifdef SUSPENDED - // Transform message to lowercase - std::wstring mes(ci->message); - std::transform( mes.begin(), mes.end(), mes.begin(), std::towlower); - - // Quick fix for svg attack and other nuisances (inline pictures) - if (mes.find(L"message = L"**** Security warning: Message contains an . ****"; - return false; - } - - // Remove messages with too many line breaks - size_t pos = 0; - int count_line_breaks = 0; - while ((pos = mes.find(L" 50) - { - ci->message = L"**** More than 50 line breaks, dropped. ****"; - return false; - } -#endif - - // https://en.wikipedia.org/wiki/Billion_laughs - // This should be done for all incoming HTML messages (also in forums - // etc.) so this should be a function in some other file. - - if (ci->message.find("message << std::endl; - std::cout << "**********" << std::endl; - std::cout << "********** entity attack by " << ci->PeerId().toStdString().c_str() << std::endl; - std::cout << "**********" << std::endl; - - ci->message = "**** This message (from peer id " + rsPeers->getPeerName(ci->PeerId()) + ") has been removed because it contains the string \" ā€¦ - - // Also check flags. Lobby msgs should have proper flags, but they can be - // corrupted by a friend before sending them that can result in e.g. lobby - // messages ending up in the broadcast channel, etc. - - uint32_t fl = ci->chatFlags & (RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_PUBLIC | RS_CHAT_FLAG_LOBBY) ; - -#ifdef CHAT_DEBUG - std::cerr << "Checking msg flags: " << std::hex << fl << std::endl; -#endif - - if(dynamic_cast(ci) != NULL) - { - if(fl != (RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_LOBBY)) - std::cerr << "Warning: received chat lobby message with iconsistent flags " << std::hex << fl << std::dec << " from friend peer " << ci->PeerId() << std::endl; - - ci->chatFlags &= ~RS_CHAT_FLAG_PUBLIC ; - } - else if(fl!=0 && !(fl == RS_CHAT_FLAG_PRIVATE || fl == RS_CHAT_FLAG_PUBLIC)) // The !=0 is normally not needed, but we keep it for - { // a while, for backward compatibility. It's not harmful. - std::cerr << "Warning: received chat lobby message with iconsistent flags " << std::hex << fl << std::dec << " from friend peer " << ci->PeerId() << std::endl; - - std::cerr << "This message will be dropped."<< std::endl; - return false ; - } - - return true ; -} - -bool p3ChatService::initiateDistantChatConnexion( const RsGxsId& to_gxs_id, - const RsGxsId& from_gxs_id, - DistantChatPeerId& pid, - uint32_t& error_code, - bool notify ) -{ - - if(to_gxs_id.isNull()) - { - RsErr() << __PRETTY_FUNCTION__ << " Destination RsGxsId is invalid" << std::endl; - return false; - } - if (from_gxs_id.isNull()) - { - RsErr() << __PRETTY_FUNCTION__ << " Origin RsGxsId is invalid" << std::endl; - return false; - } - if (!rsIdentity->isOwnId(from_gxs_id)) - { - RsErr() << __PRETTY_FUNCTION__ << " Origin RsGxsId id must be own" << std::endl; - return false; - } - - if(DistantChatService::initiateDistantChatConnexion( to_gxs_id, - from_gxs_id, pid, - error_code, notify )) - { - RS_STACK_MUTEX(mDGMutex); - DistantEndpoints ep; ep.from = from_gxs_id; ep.to = to_gxs_id; - mDistantGxsMap.insert(DIDEMap::value_type(pid, ep)); - return true; - } - return false; -} - -bool p3ChatService::receiveGxsTransMail( const RsGxsId& authorId, - const RsGxsId& recipientId, - const uint8_t* data, - uint32_t dataSize ) -{ - DistantChatPeerId pid; - uint32_t error_code; - if(initiateDistantChatConnexion( - authorId, recipientId, pid, error_code, false )) - { - RsChatMsgItem* item = static_cast( - _serializer->deserialise( - const_cast(data), &dataSize )); - RsPeerId rd(p3GxsTunnelService::makeGxsTunnelId(authorId, recipientId)); - item->PeerId(rd); - handleRecvChatMsgItem(item); - delete item; - return true; - } - - std::cerr << __PRETTY_FUNCTION__ << " (EE) failed initiating" - << " distant chat connection error: "<< error_code - << std::endl; - return false; -} - -bool p3ChatService::notifyGxsTransSendStatus(RsGxsTransId mailId, - GxsTransSendStatus status ) -{ - if ( status != GxsTransSendStatus::RECEIPT_RECEIVED ) return true; - - bool changed = false; - - { - RS_STACK_MUTEX(mChatMtx); - auto it = privateOutgoingMap.find(mailId); - if( it != privateOutgoingMap.end() ) - { - privateOutgoingMap.erase(it); - changed = true; - } - } - - if(changed) - { - RsServer::notify()->notifyListChange( - NOTIFY_LIST_PRIVATE_OUTGOING_CHAT, NOTIFY_TYPE_DEL ); - - IndicateConfigChanged(); - } - - return true; -} - -bool p3ChatService::handleRecvChatMsgItem(RsChatMsgItem *& ci) -{ - std::string name; - uint32_t popupChatFlag = RS_POPUP_CHAT; - - { - RS_STACK_MUTEX(mChatMtx); - - // we make sure this call does not take control over the memory - if(!locked_checkAndRebuildPartialMessage(ci)) return true; - /* message is a subpart of an existing message. - * So everything ok, but we need to return. */ - } - - // Check for security. This avoids bombing messages, and so on. - if(!checkForMessageSecurity(ci)) return false; - - /* If it's a lobby item, we need to bounce it and possibly check for timings - * etc. */ - if(!DistributedChatService::handleRecvChatLobbyMsgItem(ci)) return false; - -#ifdef CHAT_DEBUG - std::cerr << "p3ChatService::receiveChatQueue() Item:" << std::endl; - ci->print(std::cerr); - std::cerr << std::endl << "Got msg. Flags = " << ci->chatFlags << std::endl; -#endif - - // Now treat normal chat stuff such as avatar requests, except for chat lobbies. - - if( !(ci->chatFlags & RS_CHAT_FLAG_LOBBY)) - { - if(ci->chatFlags & RS_CHAT_FLAG_REQUESTS_AVATAR) // no msg here. Just an avatar request. - { - sendAvatarJpegData(ci->PeerId()) ; - return false ; - } - - // normal msg. Return it normally. - // Check if new avatar is available at peer's. If so, send a request to get the avatar. - - if((ci->chatFlags & RS_CHAT_FLAG_AVATAR_AVAILABLE) && !(ci->chatFlags & RS_CHAT_FLAG_LOBBY)) - { -#ifdef CHAT_DEBUG - std::cerr << "New avatar is available for peer " << ci->PeerId() << ", sending request" << std::endl ; -#endif - sendAvatarRequest(ci->PeerId()) ; - ci->chatFlags &= ~RS_CHAT_FLAG_AVATAR_AVAILABLE ; - } - - std::map::const_iterator it = _avatars.find(ci->PeerId()) ; - -#ifdef CHAT_DEBUG - std::cerr << "p3chatservice:: avatar requested from above. " << std::endl ; -#endif - // has avatar. Return it strait away. - // - if(it!=_avatars.end() && it->second->_peer_is_new) - { -#ifdef CHAT_DEBUG - std::cerr << "Avatar is new for peer. ending info above" << std::endl ; -#endif - ci->chatFlags |= RS_CHAT_FLAG_AVATAR_AVAILABLE ; - } - } - - std::string message = ci->message; - - if(!(ci->chatFlags & RS_CHAT_FLAG_LOBBY)) - { - if(ci->chatFlags & RS_CHAT_FLAG_PRIVATE) - RsServer::notify()->AddPopupMessage(popupChatFlag, ci->PeerId().toStdString(), name, message); /* notify private chat message */ - else - { -#ifdef RS_DIRECT_CHAT - /* notify public chat message */ - RsServer::notify()->AddPopupMessage( RS_POPUP_GROUPCHAT, ci->PeerId().toStdString(), "", message ); - //RsServer::notify()->AddFeedItem( RS_FEED_ITEM_CHAT_NEW, ci->PeerId().toStdString(), message, "" ); -#else // def RS_DIRECT_CHAT - /* Ignore deprecated direct node broadcast chat messages */ - return false; -#endif - } - } - - ci->recvTime = time(NULL); - - ChatMessage cm; - initChatMessage(ci, cm); - cm.incoming = true; - cm.online = true; - RsServer::notify()->notifyChatMessage(cm); - - mHistoryMgr->addMessage(cm); - - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mChatMessage = cm; - rsEvents->postEvent(ev); - } - - return true ; -} - -void p3ChatService::locked_storeIncomingMsg(RsChatMsgItem */*item*/) -{ -#ifdef REMOVE - privateIncomingList.push_back(item) ; -#endif -} - -void p3ChatService::handleRecvChatStatusItem(RsChatStatusItem *cs) -{ -#ifdef CHAT_DEBUG - std::cerr << "Received status string \"" << cs->status_string << "\"" << std::endl ; -#endif - - DistantChatPeerInfo dcpinfo; - - if(cs->flags & RS_CHAT_FLAG_REQUEST_CUSTOM_STATE) // no state here just a request. - sendCustomState(cs->PeerId()) ; - else if(cs->flags & RS_CHAT_FLAG_CUSTOM_STATE) // Check if new custom string is available at peer's. - { // If so, send a request to get the custom string. - receiveStateString(cs->PeerId(),cs->status_string) ; // store it - RsServer::notify()->notifyCustomState(cs->PeerId().toStdString(), cs->status_string) ; - } - else if(cs->flags & RS_CHAT_FLAG_CUSTOM_STATE_AVAILABLE) - { -#ifdef CHAT_DEBUG - std::cerr << "New custom state is available for peer " << cs->PeerId() << ", sending request" << std::endl ; -#endif - sendCustomStateRequest(cs->PeerId()) ; - } - else if(DistantChatService::getDistantChatStatus(DistantChatPeerId(cs->PeerId()), dcpinfo)) - { - RsServer::notify()->notifyChatStatus(ChatId(DistantChatPeerId(cs->PeerId())), cs->status_string) ; - } - else if(cs->flags & RS_CHAT_FLAG_PRIVATE) - { - RsServer::notify()->notifyChatStatus(ChatId(cs->PeerId()),cs->status_string) ; - } - else if(cs->flags & RS_CHAT_FLAG_PUBLIC) - { - ChatId id = ChatId::makeBroadcastId(); - id.broadcast_status_peer_id = cs->PeerId(); - RsServer::notify()->notifyChatStatus(id, cs->status_string) ; - } - - DistantChatService::handleRecvChatStatusItem(cs) ; -} - -void p3ChatService::initChatMessage(RsChatMsgItem *c, ChatMessage &m) -{ - m.chat_id = ChatId(c->PeerId()); - m.chatflags = 0; - m.sendTime = c->sendTime; - m.recvTime = c->recvTime; - m.msg = c->message; - - RsChatLobbyMsgItem *lobbyItem = dynamic_cast(c) ; - if(lobbyItem != NULL) - { - m.lobby_peer_gxs_id = lobbyItem->signature.keyId ; - m.chat_id = ChatId(lobbyItem->lobby_id); - return; - } - - DistantChatPeerInfo dcpinfo; - if(DistantChatService::getDistantChatStatus(DistantChatPeerId(c->PeerId()), dcpinfo)) - m.chat_id = ChatId(DistantChatPeerId(c->PeerId())); - - if (c -> chatFlags & RS_CHAT_FLAG_PRIVATE) - m.chatflags |= RS_CHAT_PRIVATE; - else - { - m.chat_id = ChatId::makeBroadcastId(); - m.broadcast_peer_id = c->PeerId(); - m.chatflags |= RS_CHAT_PUBLIC; - } -} - -void p3ChatService::setOwnCustomStateString(const std::string& s) -{ - std::set onlineList; - { - RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - -#ifdef CHAT_DEBUG - std::cerr << "p3chatservice: Setting own state string to new value : " << s << std::endl ; -#endif - _custom_status_string = s ; - - for(std::map::iterator it(_state_strings.begin());it!=_state_strings.end();++it) - it->second._own_is_new = true ; - - mServiceCtrl->getPeersConnected(getServiceInfo().mServiceType, onlineList); - } - - RsServer::notify()->notifyOwnStatusMessageChanged() ; - - // alert your online peers to your newly set status - std::set::iterator it(onlineList.begin()); - for(; it != onlineList.end(); ++it){ - - RsChatStatusItem *cs = new RsChatStatusItem(); - cs->flags = RS_CHAT_FLAG_CUSTOM_STATE_AVAILABLE; - cs->status_string = ""; - cs->PeerId(*it); - sendItem(cs); - } - - IndicateConfigChanged(); -} - -void p3ChatService::setOwnAvatarJpegData(const unsigned char *data,int size) -{ - { - RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ -#ifdef CHAT_DEBUG - std::cerr << "p3chatservice: Setting own avatar to new image." << std::endl ; -#endif - - if((uint32_t)size > MAX_AVATAR_JPEG_SIZE) - { - std::cerr << "Supplied avatar image is too big. Maximum size is " << MAX_AVATAR_JPEG_SIZE << ", supplied image has size " << size << std::endl; - return ; - } - if(_own_avatar != NULL) - delete _own_avatar ; - - _own_avatar = new AvatarInfo(data,size) ; - - // set the info that our avatar is new, for all peers - for(std::map::iterator it(_avatars.begin());it!=_avatars.end();++it) - it->second->_own_is_new = true ; - } - IndicateConfigChanged(); - - RsServer::notify()->notifyOwnAvatarChanged() ; - -#ifdef CHAT_DEBUG - std::cerr << "p3chatservice:setOwnAvatarJpegData() done." << std::endl ; -#endif - -} - -void p3ChatService::receiveStateString(const RsPeerId& id,const std::string& s) -{ - RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ -#ifdef CHAT_DEBUG - std::cerr << "p3chatservice: received custom state string for peer " << id << ". Storing it." << std::endl ; -#endif - - bool new_peer = (_state_strings.find(id) == _state_strings.end()) ; - - _state_strings[id]._custom_status_string = s ; - _state_strings[id]._peer_is_new = true ; - _state_strings[id]._own_is_new = new_peer ; -} - -void p3ChatService::receiveAvatarJpegData(RsChatAvatarItem *ci) -{ - RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ -#ifdef CHAT_DEBUG - std::cerr << "p3chatservice: received avatar jpeg data for peer " << ci->PeerId() << ". Storing it." << std::endl ; -#endif - - if(ci->image_size > MAX_AVATAR_JPEG_SIZE) - { - std::cerr << "Peer " << ci->PeerId()<< " is sending a jpeg image for avatar that exceeds the admitted size (size=" << ci->image_size << ", max=" << MAX_AVATAR_JPEG_SIZE << ")"<< std::endl; - return ; - } - bool new_peer = (_avatars.find(ci->PeerId()) == _avatars.end()) ; - - if (new_peer == false && _avatars[ci->PeerId()]) { - delete _avatars[ci->PeerId()]; - } - _avatars[ci->PeerId()] = new AvatarInfo(ci->image_data,ci->image_size) ; - _avatars[ci->PeerId()]->_peer_is_new = true ; - _avatars[ci->PeerId()]->_own_is_new = new_peer ; -} - -std::string p3ChatService::getOwnCustomStateString() -{ - RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - return _custom_status_string ; -} -void p3ChatService::getOwnAvatarJpegData(unsigned char *& data,int& size) -{ - // should be a Mutex here. - RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - - uint32_t s = 0 ; -#ifdef CHAT_DEBUG - std::cerr << "p3chatservice:: own avatar requested from above. " << std::endl ; -#endif - // has avatar. Return it strait away. - // - if(_own_avatar != NULL) - { - _own_avatar->toUnsignedChar(data,s) ; - size = s ; - } - else - { - data=NULL ; - size=0 ; - } -} - -std::string p3ChatService::getCustomStateString(const RsPeerId& peer_id) -{ - { - // should be a Mutex here. - RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it = _state_strings.find(peer_id) ; - - // has it. Return it strait away. - // - if(it!=_state_strings.end()) - { - it->second._peer_is_new = false ; - return it->second._custom_status_string ; - } - } - - sendCustomStateRequest(peer_id); - return std::string() ; -} - -void p3ChatService::getAvatarJpegData(const RsPeerId& peer_id,unsigned char *& data,int& size) -{ - { - // should be a Mutex here. - RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - - std::map::const_iterator it = _avatars.find(peer_id) ; - -#ifdef CHAT_DEBUG - std::cerr << "p3chatservice:: avatar for peer " << peer_id << " requested from above. " << std::endl ; -#endif - // has avatar. Return it straight away. - // - if(it!=_avatars.end()) - { - uint32_t s=0 ; - it->second->toUnsignedChar(data,s) ; - size = s ; - it->second->_peer_is_new = false ; -#ifdef CHAT_DEBUG - std::cerr << "Already has avatar. Returning it" << std::endl ; -#endif - return ; - } else { -#ifdef CHAT_DEBUG - std::cerr << "No avatar for this peer. Requesting it by sending request packet." << std::endl ; -#endif - } - } - - sendAvatarRequest(peer_id); -} - -void p3ChatService::sendAvatarRequest(const RsPeerId& peer_id) -{ - if(!isOnline(peer_id)) - return ; - - // Doesn't have avatar. Request it. - // - RsChatMsgItem *ci = new RsChatMsgItem(); - - ci->PeerId(peer_id); - ci->chatFlags = RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_REQUESTS_AVATAR ; - ci->sendTime = time(NULL); - ci->message.erase(); - -#ifdef CHAT_DEBUG - std::cerr << "p3ChatService::sending request for avatar, to peer " << peer_id << std::endl ; - std::cerr << std::endl; -#endif - - sendChatItem(ci); -} - -void p3ChatService::sendCustomStateRequest(const RsPeerId& peer_id){ - - if(!isOnline(peer_id)) - return ; - - RsChatStatusItem* cs = new RsChatStatusItem; - - cs->PeerId(peer_id); - cs->flags = RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_REQUEST_CUSTOM_STATE ; - cs->status_string.erase(); - -#ifdef CHAT_DEBUG - std::cerr << "p3ChatService::sending request for status, to peer " << peer_id << std::endl ; - std::cerr << std::endl; -#endif - - sendChatItem(cs); -} - -RsChatStatusItem *p3ChatService::makeOwnCustomStateStringItem() -{ - RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - RsChatStatusItem *ci = new RsChatStatusItem(); - - ci->flags = RS_CHAT_FLAG_CUSTOM_STATE ; - ci->status_string = _custom_status_string ; - - return ci ; -} - -RsChatAvatarItem *p3ChatService::makeOwnAvatarItem() -{ - RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ - RsChatAvatarItem *ci = new RsChatAvatarItem(); - - _own_avatar->toUnsignedChar(ci->image_data,ci->image_size) ; - - return ci ; -} - - -void p3ChatService::sendAvatarJpegData(const RsPeerId& peer_id) -{ -#ifdef CHAT_DEBUG - std::cerr << "p3chatservice: sending requested for peer " << peer_id << ", data=" << (void*)_own_avatar << std::endl ; -#endif - - if(_own_avatar != NULL) - { - RsChatAvatarItem *ci = makeOwnAvatarItem(); - ci->PeerId(peer_id); - - // take avatar, and embed it into a std::string. - // -#ifdef CHAT_DEBUG - std::cerr << "p3ChatService::sending avatar image to peer" << peer_id << ", image size = " << ci->image_size << std::endl ; - std::cerr << std::endl; -#endif - - sendChatItem(ci) ; - } - else { -#ifdef CHAT_DEBUG - std::cerr << "We have no avatar yet: Doing nothing" << std::endl ; -#endif - } -} - -void p3ChatService::sendCustomState(const RsPeerId& peer_id){ - -#ifdef CHAT_DEBUG -std::cerr << "p3chatservice: sending requested status string for peer " << peer_id << std::endl ; -#endif - - RsChatStatusItem *cs = makeOwnCustomStateStringItem(); - cs->PeerId(peer_id); - - sendChatItem(cs); -} - -bool p3ChatService::loadList(std::list& load) -{ - std::list ssl_peers; - mLinkMgr->getFriendList(ssl_peers); - - for(std::list::const_iterator it(load.begin());it!=load.end();++it) - { - if(PrivateOugoingMapItem* om=dynamic_cast(*it)) - { - RS_STACK_MUTEX(mChatMtx); - for( auto& pair : om->store ) - { - privateOutgoingMap.insert( - outMP::value_type(pair.first, - new RsChatMsgItem(pair.second)) ); - } - - delete om; continue; - } - - - RsChatAvatarItem *ai = NULL ; - - if(NULL != (ai = dynamic_cast(*it))) - { - RS_STACK_MUTEX(mChatMtx); - - if(ai->image_size <= MAX_AVATAR_JPEG_SIZE) - _own_avatar = new AvatarInfo(ai->image_data,ai->image_size) ; - else - std::cerr << "Dropping avatar image, because its size is " - << ai->image_size << ", and the maximum allowed size " - << "is " << MAX_AVATAR_JPEG_SIZE << std::endl; - - delete *it; - continue; - } - - RsChatStatusItem *mitem = NULL ; - - if(NULL != (mitem = dynamic_cast(*it))) - { - RS_STACK_MUTEX(mChatMtx); - - _custom_status_string = mitem->status_string ; - - delete *it; - continue; - } - - /* TODO: G10h4ck 2017/02/27 this block is kept for retrocompatibility, - * and will be used just first time, to load messages in the old format - * should be removed in the following RS version */ - if( RsPrivateChatMsgConfigItem *citem = - dynamic_cast(*it) ) - { - RS_STACK_MUTEX(mChatMtx); - - if ( citem->chatFlags & RS_CHAT_FLAG_PRIVATE ) - { - if ( std::find(ssl_peers.begin(), ssl_peers.end(), - citem->configPeerId) != ssl_peers.end() ) - { - RsChatMsgItem *ci = new RsChatMsgItem(); - citem->get(ci); - - if (citem->configFlags & RS_CHATMSG_CONFIGFLAG_INCOMING) - { - locked_storeIncomingMsg(ci); - } - else privateOutgoingMap.insert( - outMP::value_type(RSRandom::random_u64(), ci) ); - } - else { /* no friends */ } - } - else { /* ignore all other items */ } - - delete *it; - continue; - } - - DistributedChatService::processLoadListItem(*it) ; - DistantChatService::processLoadListItem(*it) ; - - // delete unknown items - delete *it; - } - - load.clear() ; - return true; -} - -bool p3ChatService::saveList(bool& cleanup, std::list& list) -{ - cleanup = true; - - /* now we create a pqistore, and stream all the msgs into it */ - - if(_own_avatar != NULL) - { - RsChatAvatarItem *ci = makeOwnAvatarItem() ; - ci->PeerId(mServiceCtrl->getOwnId()); - - list.push_back(ci) ; - } - - mChatMtx.lock(); /****** MUTEX LOCKED *******/ - - PrivateOugoingMapItem* om = new PrivateOugoingMapItem; - typedef std::map::value_type vT; - for( auto& pair : privateOutgoingMap ) - om->store.insert(vT(pair.first, *pair.second)); - list.push_back(om); - - - RsChatStatusItem *di = new RsChatStatusItem ; - di->status_string = _custom_status_string ; - di->flags = RS_CHAT_FLAG_CUSTOM_STATE ; - - list.push_back(di); - - DistributedChatService::addToSaveList(list) ; - DistantChatService::addToSaveList(list) ; - - return true; -} - -void p3ChatService::saveDone() -{ - /* unlock mutex */ - mChatMtx.unlock(); /****** MUTEX UNLOCKED *******/ -} - -RsSerialiser *p3ChatService::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser ; - rss->addSerialType(new RsChatSerialiser) ; - rss->addSerialType(new RsGeneralConfigSerialiser()); - - return rss ; -} - -/*************** pqiMonitor callback ***********************/ - -void p3ChatService::statusChange(const std::list &plist) -{ - for (auto it = plist.cbegin(); it != plist.cend(); ++it) - { - if (it->actions & RS_SERVICE_PEER_CONNECTED) - { - /* send the saved outgoing messages */ - bool changed = false; - - std::vector to_send; - - { - RS_STACK_MUTEX(mChatMtx); - - for( auto cit = privateOutgoingMap.begin(); - cit != privateOutgoingMap.end(); ) - { - RsChatMsgItem *c = cit->second; - if (c->PeerId() == it->id) - { - //mHistoryMgr->addMessage(false, c->PeerId(), ownId, c); - - to_send.push_back(c) ; - changed = true; - cit = privateOutgoingMap.erase(cit); - continue; - } - - ++cit; - } - } - - for(auto toIt = to_send.begin(); toIt != to_send.end(); ++toIt) - { - ChatMessage message; - initChatMessage(*toIt, message); - message.incoming = false; - message.online = true; - RsServer::notify()->notifyChatMessage(message); - - checkSizeAndSendMessage(*toIt); // delete item - } - - if (changed) - { - RsServer::notify()->notifyListChange( - NOTIFY_LIST_PRIVATE_OUTGOING_CHAT, NOTIFY_TYPE_DEL); - - IndicateConfigChanged(); - } - } - else if (it->actions & RS_SERVICE_PEER_REMOVED) - { - /* now handle remove */ - mHistoryMgr->clear(ChatId(it->id)); - - RS_STACK_MUTEX(mChatMtx); - for ( auto cit = privateOutgoingMap.begin(); - cit != privateOutgoingMap.end(); ) - { - RsChatMsgItem *c = cit->second; - if (c->PeerId() == it->id) cit = privateOutgoingMap.erase(cit); - else ++cit; - } - IndicateConfigChanged(); - } - } -} diff --git a/libretroshare/src/chat/p3chatservice.h b/libretroshare/src/chat/p3chatservice.h deleted file mode 100644 index bc4dd56b9..000000000 --- a/libretroshare/src/chat/p3chatservice.h +++ /dev/null @@ -1,305 +0,0 @@ -/******************************************************************************* - * libretroshare/src/chat: chatservice.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef SERVICE_CHAT_HEADER -#define SERVICE_CHAT_HEADER - -#include -#include -#include - -#include "rsitems/rsmsgitems.h" -#include "services/p3service.h" -#include "pqi/pqiservicemonitor.h" -#include "chat/distantchat.h" -#include "chat/distributedchat.h" -#include "retroshare/rsmsgs.h" -#include "gxstrans/p3gxstrans.h" -#include "util/rsdeprecate.h" - -class p3ServiceControl; -class p3LinkMgr; -class p3HistoryMgr; - -typedef RsPeerId ChatLobbyVirtualPeerId ; - -struct RsChatMessageEvent : RsEvent -{ - RsChatMessageEvent() : RsEvent(RsEventType::CHAT_MESSAGE) {} - ~RsChatMessageEvent() override = default; - - ///* @see RsEvent @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) override - { - RsEvent::serial_process(j, ctx); - - RS_SERIAL_PROCESS(mChatMessage); - } - - ChatMessage mChatMessage; -}; - -//!The basic Chat service. - /** - * - * Can be used to send and receive chats, immediate status (using notify), avatars, and custom status - * This service uses rsnotify (callbacks librs clients (e.g. rs-gui)) - * @see NotifyBase - */ -class p3ChatService : - public p3Service, public DistantChatService, public DistributedChatService, public p3Config, - public pqiServiceMonitor, GxsTransClient -{ -public: - p3ChatService(p3ServiceControl *cs, p3IdService *pids, p3LinkMgr *cm, - p3HistoryMgr *historyMgr, p3GxsTrans& gxsTransService ); - - virtual RsServiceInfo getServiceInfo(); - - /***** overloaded from p3Service *****/ - /*! - * This retrieves all chat msg items and also (important!) - * processes chat-status items that are in service item queue. chat msg item requests are also processed and not returned - * (important! also) notifications sent to notify base on receipt avatar, immediate status and custom status - * : notifyCustomState, notifyChatStatus, notifyPeerHasNewAvatar - * @see NotifyBase - */ - virtual int tick(); - - /*************** pqiMonitor callback ***********************/ - virtual void statusChange(const std::list &plist); - - /*! - * public chat sent to all peers - */ - void sendPublicChat(const std::string &msg); - - /********* RsMsgs ***********/ - /*! - * Send a chat message. - * @param destination where to send the chat message - * @param msg the message - * @see ChatId - */ - bool sendChat(ChatId destination, std::string msg); - - /*! - * chat is sent to specifc peer - * @param id peer to send chat msg to - */ - bool sendPrivateChat(const RsPeerId &id, const std::string &msg); - - /** - * can be used to send 'immediate' status msgs, these status updates are - * meant for immediate use by peer (not saved by rs) e.g currently used to - * update user when a peer 'is typing' during a chat */ - void sendStatusString( const ChatId& id, const std::string& status_str ); - - /** - * @brief clearChatLobby: Signal chat was cleared by GUI. - * @param id: Chat id cleared. - */ - virtual void clearChatLobby(const ChatId& id); - - /*! - * send to all peers online - *@see sendStatusString() - */ - void sendGroupChatStatusString(const std::string& status_str) ; - - /*! - * this retrieves custom status for a peers, generate a requests to the peer - * @param peer_id the id of the peer you want status string for - */ - std::string getCustomStateString(const RsPeerId& peer_id) ; - - /*! - * sets the client's custom status, generates 'status available' item sent to all online peers - */ - void setOwnCustomStateString(const std::string&) ; - - /*! - * @return client's custom string - */ - std::string getOwnCustomStateString() ; - - /*! gets the peer's avatar in jpeg format, if available. Null otherwise. Also asks the peer to send - * its avatar, if not already available. Creates a new unsigned char array. It's the caller's - * responsibility to delete this ones used. - */ - void getAvatarJpegData(const RsPeerId& peer_id,unsigned char *& data,int& size) ; - - /*! - * Sets the avatar data and size for client's account - * @param data is copied, so should be destroyed by the caller - */ - void setOwnAvatarJpegData(const unsigned char *data,int size) ; - - /*! - * Gets the avatar data for clients account - * data is in jpeg format - */ - void getOwnAvatarJpegData(unsigned char *& data,int& size) ; - - /*! - * Return the max message size for security forwarding - * @param type RS_CHAT_TYPE_... - * return 0 unlimited - */ - static uint32_t getMaxMessageSecuritySize(int type); - - /*! - * Checks message security, especially remove billion laughs attacks - */ - - static bool checkForMessageSecurity(RsChatMsgItem *) ; - - /*! - * @param clear private chat queue - */ - bool clearPrivateChatQueue(bool incoming, const RsPeerId &id); - - virtual bool initiateDistantChatConnexion( const RsGxsId& to_gxs_id, - const RsGxsId& from_gxs_id, - DistantChatPeerId &pid, - uint32_t& error_code, - bool notify = true ); - - /// @see GxsTransClient::receiveGxsTransMail(...) - virtual bool receiveGxsTransMail( const RsGxsId& authorId, - const RsGxsId& recipientId, - const uint8_t* data, uint32_t dataSize ); - - /// @see GxsTransClient::notifySendMailStatus(...) - virtual bool notifyGxsTransSendStatus( RsGxsTransId mailId, - GxsTransSendStatus status ); - - -protected: - /************* from p3Config *******************/ - virtual RsSerialiser *setupSerialiser() ; - - /*! - * chat msg items and custom status are saved - */ - virtual bool saveList(bool& cleanup, std::list&) ; - virtual void saveDone(); - virtual bool loadList(std::list& load) ; - - // accepts virtual peer id - bool isOnline(const RsPeerId &pid) ; - - /// This is to be used by subclasses/parents to call IndicateConfigChanged() - virtual void triggerConfigSave() { IndicateConfigChanged() ; } - - /// Same, for storing messages in incoming list - RS_DEPRECATED virtual void locked_storeIncomingMsg(RsChatMsgItem *) ; - -private: - RsMutex mChatMtx; - - class AvatarInfo ; - class StateStringInfo ; - - // Receive chat queue - void receiveChatQueue(); - void handleIncomingItem(RsItem *); // called by the former, and turtle handler for incoming encrypted items - - virtual void sendChatItem(RsChatItem *) ; - - void initChatMessage(RsChatMsgItem *c, ChatMessage& msg); - - /// Send avatar info to peer in jpeg format. - void sendAvatarJpegData(const RsPeerId& peer_id) ; - - /// Send custom state info to peer - void sendCustomState(const RsPeerId& peer_id); - - /// Receive the avatar in a chat item, with RS_CHAT_RECEIVE_AVATAR flag. - void receiveAvatarJpegData(RsChatAvatarItem *ci) ; // new method - void receiveStateString(const RsPeerId& id,const std::string& s) ; - - /// methods for handling various Chat items. - virtual bool handleRecvChatMsgItem(RsChatMsgItem *&item) ; // NULL-ifies the item if memory ownership is taken - - void handleRecvChatStatusItem(RsChatStatusItem *item) ; - void handleRecvChatAvatarItem(RsChatAvatarItem *item) ; - - /// Sends a request for an avatar to the peer of given id - void sendAvatarRequest(const RsPeerId& peer_id) ; - - /// Send a request for custom status string - void sendCustomStateRequest(const RsPeerId& peer_id); - - /// called as a proxy to sendItem(). Possibly splits item into multiple items of size lower than the maximum item size. - //void checkSizeAndSendMessage(RsChatLobbyMsgItem *item) ; - void checkSizeAndSendMessage(RsChatMsgItem *item) ; // keep for compatibility for a few weeks. - - /// Called when a RsChatMsgItem is received. The item may be collapsed with any waiting partial chat item from the same peer. - /// if so, the chat item will be turned to NULL - bool locked_checkAndRebuildPartialMessage(RsChatMsgItem *&) ; - - RsChatAvatarItem *makeOwnAvatarItem() ; - RsChatStatusItem *makeOwnCustomStateStringItem() ; - - p3ServiceControl *mServiceCtrl; - p3LinkMgr *mLinkMgr; - p3HistoryMgr *mHistoryMgr; - - /// messages waiting to be send when peer comes online - typedef std::map outMP; - outMP privateOutgoingMap; - - AvatarInfo *_own_avatar ; - std::map _avatars ; - std::map _pendingPartialMessages; - - std::string _custom_status_string ; - std::map _state_strings ; - - RsChatSerialiser *_serializer; - - struct DistantEndpoints { RsGxsId from; RsGxsId to; }; - typedef std::map DIDEMap; - DIDEMap mDistantGxsMap; - RsMutex mDGMutex; - - p3GxsTrans& mGxsTransport; -}; - -class p3ChatService::StateStringInfo -{ - public: - StateStringInfo() - { - _custom_status_string = "" ; // the custom status string of the peer - _peer_is_new = false ; // true when the peer has a new avatar - _own_is_new = false ; // true when I myself a new avatar to send to this peer. - } - - std::string _custom_status_string ; - int _peer_is_new ; // true when the peer has a new avatar - int _own_is_new ; // true when I myself a new avatar to send to this peer. -}; - -#endif // SERVICE_CHAT_HEADER - diff --git a/libretroshare/src/chat/rschatitems.cc b/libretroshare/src/chat/rschatitems.cc deleted file mode 100644 index 13d272c4e..000000000 --- a/libretroshare/src/chat/rschatitems.cc +++ /dev/null @@ -1,206 +0,0 @@ -/******************************************************************************* - * libretroshare/src/chat: rschatitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include -#include "retroshare/rsmsgs.h" -#include "util/rstime.h" -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstlvbase.h" - -#include "serialiser/rstypeserializer.h" - -#include "chat/rschatitems.h" - -//#define CHAT_DEBUG 1 - -//static const uint32_t RS_CHAT_SERIALIZER_FLAGS_NO_SIGNATURE = 0x0001; - -RsItem *RsChatSerialiser::create_item(uint16_t service_id,uint8_t item_sub_id) const -{ - if(service_id != RS_SERVICE_TYPE_CHAT) return NULL; - - switch(item_sub_id) - { - case RS_PKT_SUBTYPE_DEFAULT: return new RsChatMsgItem(); - case RS_PKT_SUBTYPE_PRIVATECHATMSG_CONFIG: return new RsPrivateChatMsgConfigItem(); - case RS_PKT_SUBTYPE_CHAT_STATUS: return new RsChatStatusItem(); - case RS_PKT_SUBTYPE_CHAT_AVATAR: return new RsChatAvatarItem(); - case RS_PKT_SUBTYPE_CHAT_LOBBY_SIGNED_MSG: return new RsChatLobbyMsgItem(); - case RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE: return new RsChatLobbyInviteItem(); - case RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE_DEPRECATED: return new RsChatLobbyInviteItem_Deprecated(); // to be removed (deprecated since May 2017) - case RS_PKT_SUBTYPE_CHAT_LOBBY_CHALLENGE: return new RsChatLobbyConnectChallengeItem(); - case RS_PKT_SUBTYPE_CHAT_LOBBY_UNSUBSCRIBE: return new RsChatLobbyUnsubscribeItem(); - case RS_PKT_SUBTYPE_CHAT_LOBBY_SIGNED_EVENT: return new RsChatLobbyEventItem(); - case RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_REQUEST: return new RsChatLobbyListRequestItem(); - case RS_PKT_SUBTYPE_CHAT_LOBBY_LIST: return new RsChatLobbyListItem(); - case RS_PKT_SUBTYPE_CHAT_LOBBY_CONFIG: return new RsChatLobbyConfigItem(); - case RS_PKT_SUBTYPE_SUBSCRIBED_CHAT_LOBBY_CONFIG: return new RsSubscribedChatLobbyConfigItem(); - case RS_PKT_SUBTYPE_OUTGOING_MAP: return new PrivateOugoingMapItem(); - default: - std::cerr << "Unknown packet type in chat!" << std::endl; - return NULL; - } -} - -void RsChatMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,chatFlags,"chatflags") ; - RsTypeSerializer::serial_process(j,ctx,sendTime,"sendTime") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,message,"message") ; -} - -/*************************************************************************/ - -void RsChatLobbyBouncingObject::serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,lobby_id,"lobby_id") ; - RsTypeSerializer::serial_process(j,ctx,msg_id ,"msg_id") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_NAME,nick,"nick") ; - - if(!(ctx.mFlags & RsSerializationFlags::SIGNATURE)) - RS_SERIAL_PROCESS(signature); -} - -void RsChatLobbyMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsChatMsgItem::serial_process(j,ctx) ; - RsTypeSerializer::serial_process(j,ctx,parent_msg_id,"parent_msg_id") ; - RsChatLobbyBouncingObject::serial_process(j,ctx) ; -} - -void RsChatLobbyListRequestItem::serial_process(RsGenericSerializer::SerializeJob /*j*/,RsGenericSerializer::SerializeContext& /*ctx*/) -{ - // nothing to do. This is an empty item. -} - -template<> void RsTypeSerializer::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx,VisibleChatLobbyInfo& info,const std::string& /*name*/) -{ - RsTypeSerializer::serial_process(j,ctx,info.id,"info.id") ; - - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_NAME,info.name, "info.name") ; - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_NAME,info.topic,"info.topic") ; - RsTypeSerializer::serial_process(j,ctx, info.count,"info.count") ; - RsTypeSerializer::serial_process (j,ctx, info.flags,"info.flags") ; -} - -void RsChatLobbyListItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,lobbies,"lobbies") ; -} - -void RsChatLobbyEventItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,event_type,"event_type") ; - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_NAME,string1,"string1") ; - RsTypeSerializer::serial_process(j,ctx,sendTime ,"sendTime") ; - - RsChatLobbyBouncingObject::serial_process(j,ctx) ; -} -void RsChatLobbyUnsubscribeItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,lobby_id,"lobby_id") ; -} - -void RsChatLobbyConnectChallengeItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,challenge_code,"challenge_code") ; -} - -// to be removed (deprecated since May 2017) -void RsChatLobbyInviteItem_Deprecated::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx, lobby_id, "lobby_id") ; - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_NAME,lobby_name, "lobby_name") ; - RsTypeSerializer::serial_process (j,ctx, lobby_flags,"lobby_flags") ; -} - -void RsChatLobbyInviteItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx, lobby_id, "lobby_id") ; - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_NAME,lobby_name, "lobby_name") ; - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_NAME,lobby_topic,"lobby_topic") ; - RsTypeSerializer::serial_process (j,ctx, lobby_flags,"lobby_flags") ; -} - -void RsPrivateChatMsgConfigItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - uint32_t x=0 ; - - RsTypeSerializer::serial_process(j,ctx, x, "place holder value") ; - RsTypeSerializer::serial_process (j,ctx, configPeerId,"configPeerId") ; - RsTypeSerializer::serial_process(j,ctx, chatFlags, "chatFlags") ; - RsTypeSerializer::serial_process(j,ctx, sendTime, "sendTime") ; - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_MSG,message, "message") ; - RsTypeSerializer::serial_process(j,ctx, recvTime, "recvTime") ; -} - -void RsChatStatusItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,flags,"flags") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,status_string,"status_string") ; -} - -void RsChatAvatarItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::TlvMemBlock_proxy b(image_data,image_size) ; - RsTypeSerializer::serial_process(j,ctx,b,"image data") ; -} - -void RsSubscribedChatLobbyConfigItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - info.serial_process(j,ctx); -} - -void RsChatLobbyConfigItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,lobby_Id,"lobby_Id") ; - RsTypeSerializer::serial_process(j,ctx,flags,"flags") ; -} - -/* set data from RsChatMsgItem to RsPrivateChatMsgConfigItem */ -void RsPrivateChatMsgConfigItem::set(RsChatMsgItem *ci, const RsPeerId& /*peerId*/, uint32_t confFlags) -{ - PeerId(ci->PeerId()); - configPeerId = ci->PeerId(); - chatFlags = ci->chatFlags; - configFlags = confFlags; - sendTime = ci->sendTime; - message = ci->message; - recvTime = ci->recvTime; -} - -/* get data from RsPrivateChatMsgConfigItem to RsChatMsgItem */ -void RsPrivateChatMsgConfigItem::get(RsChatMsgItem *ci) -{ - ci->PeerId(configPeerId); - ci->chatFlags = chatFlags; - //configFlags not used - ci->sendTime = sendTime; - ci->message = message; - ci->recvTime = recvTime; -} - - -void PrivateOugoingMapItem::serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ RS_SERIAL_PROCESS(store); } diff --git a/libretroshare/src/chat/rschatitems.h b/libretroshare/src/chat/rschatitems.h deleted file mode 100644 index aca3a411a..000000000 --- a/libretroshare/src/chat/rschatitems.h +++ /dev/null @@ -1,383 +0,0 @@ -/******************************************************************************* - * libretroshare/src/chat: rschatitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#pragma once - -#include "openssl/bn.h" -#include "retroshare/rstypes.h" -#include "serialiser/rsserializer.h" -#include "serialiser/rstlvkeys.h" -#include "rsitems/rsserviceids.h" -#include "rsitems/itempriorities.h" -#include "rsitems/rsitem.h" -#include "serialiser/rsserial.h" -#include "util/rsdeprecate.h" - -#include "serialiser/rstlvidset.h" -#include "serialiser/rstlvfileitem.h" -#include "retroshare/rsmsgs.h" - -/* chat Flags */ -const uint32_t RS_CHAT_FLAG_PRIVATE = 0x0001; -const uint32_t RS_CHAT_FLAG_REQUESTS_AVATAR = 0x0002; -const uint32_t RS_CHAT_FLAG_CONTAINS_AVATAR = 0x0004; -const uint32_t RS_CHAT_FLAG_AVATAR_AVAILABLE = 0x0008; -const uint32_t RS_CHAT_FLAG_CUSTOM_STATE = 0x0010; // used for transmitting peer status string -const uint32_t RS_CHAT_FLAG_PUBLIC = 0x0020; -const uint32_t RS_CHAT_FLAG_REQUEST_CUSTOM_STATE = 0x0040; -const uint32_t RS_CHAT_FLAG_CUSTOM_STATE_AVAILABLE = 0x0080; -const uint32_t RS_CHAT_FLAG_PARTIAL_MESSAGE = 0x0100; -const uint32_t RS_CHAT_FLAG_LOBBY = 0x0200; -const uint32_t RS_CHAT_FLAG_CLOSING_DISTANT_CONNECTION = 0x0400; -const uint32_t RS_CHAT_FLAG_ACK_DISTANT_CONNECTION = 0x0800; -const uint32_t RS_CHAT_FLAG_KEEP_ALIVE = 0x1000; -const uint32_t RS_CHAT_FLAG_CONNEXION_REFUSED = 0x2000; - -const uint32_t RS_CHATMSG_CONFIGFLAG_INCOMING = 0x0001; - -const uint8_t RS_PKT_SUBTYPE_CHAT_AVATAR = 0x03 ; -const uint8_t RS_PKT_SUBTYPE_CHAT_STATUS = 0x04 ; -const uint8_t RS_PKT_SUBTYPE_PRIVATECHATMSG_CONFIG = 0x05 ; -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_MSG_DEPRECATED = 0x06 ; // don't use ! Deprecated -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE_DEPREC = 0x07 ; // don't use ! Deprecated -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_ACCEPT = 0x08 ; -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_CHALLENGE = 0x09 ; -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_UNSUBSCRIBE = 0x0A ; -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_EVENT_DEPREC = 0x0B ; // don't use ! Deprecated -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_MSG = 0x0C ; // will be deprecated when only signed messages are accepted (02/2015) -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_REQUEST = 0x0D ; -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_deprecated = 0x0E ; // to be removed -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE_deprecated = 0x0F ; // to be removed -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_EVENT = 0x10 ; -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_deprecated2 = 0x11 ; // to be removed (deprecated since 02 Dec. 2012) -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_deprecated3 = 0x12 ; -const uint8_t RS_PKT_SUBTYPE_DISTANT_INVITE_CONFIG = 0x13 ; -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_CONFIG = 0x15 ; -const uint8_t RS_PKT_SUBTYPE_DISTANT_CHAT_DH_PUBLIC_KEY = 0x16 ; -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_SIGNED_MSG = 0x17 ; -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_SIGNED_EVENT = 0x18 ; -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_LIST = 0x19 ; - -RS_DEPRECATED_FOR(RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE) \ -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE_DEPRECATED = 0x1A ; // to be removed (deprecated since May 2017) - -const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE = 0x1B ; -const uint8_t RS_PKT_SUBTYPE_OUTGOING_MAP = 0x1C ; - -const uint8_t RS_PKT_SUBTYPE_SUBSCRIBED_CHAT_LOBBY_CONFIG = 0x1D ; - -typedef uint64_t ChatLobbyId ; -typedef uint64_t ChatLobbyMsgId ; -typedef std::string ChatLobbyNickName ; -typedef uint64_t DistantChatDHSessionId ; - -class RsChatItem: public RsItem -{ - public: - RsChatItem(uint8_t chat_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_CHAT,chat_subtype) - { - setPriorityLevel(QOS_PRIORITY_RS_CHAT_ITEM) ; - } - - virtual ~RsChatItem() {} - virtual void clear() {} -}; - -/*! - * For sending chat msgs - * @see p3ChatService - */ -class RsChatMsgItem: public RsChatItem -{ -public: - RsChatMsgItem() :RsChatItem(RS_PKT_SUBTYPE_DEFAULT) {} - RsChatMsgItem(uint8_t subtype) :RsChatItem(subtype) {} - - //RsChatMsgItem() {} - - virtual ~RsChatMsgItem() {} - - // derived from RsItem - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - virtual void clear() {} - - uint32_t chatFlags; - uint32_t sendTime; - std::string message; - - /* not serialised */ - uint32_t recvTime; -}; - -// This class contains the info to bounce an object throughout a lobby, while -// maintaining cache info to avoid duplicates. -// -class RsChatLobbyBouncingObject -{ -public: - ChatLobbyId lobby_id ; - ChatLobbyMsgId msg_id ; - ChatLobbyNickName nick ; // Nickname of sender - - RsTlvKeySignature signature ; - - virtual RsChatLobbyBouncingObject *duplicate() const = 0 ; - -protected: - // The functions below handle the serialisation of data that is specific to the bouncing object level. - // They are called by serial_size() and serialise() from children, but should not overload the serial_size() and - // serialise() methods, otherwise the wrong method will be called when serialising from this top level class. - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - virtual uint32_t PacketId() const= 0; -}; - -class RsChatLobbyMsgItem: public RsChatMsgItem, public RsChatLobbyBouncingObject -{ -public: - RsChatLobbyMsgItem() :RsChatMsgItem(RS_PKT_SUBTYPE_CHAT_LOBBY_SIGNED_MSG) {} - - virtual ~RsChatLobbyMsgItem() {} - virtual RsChatLobbyBouncingObject *duplicate() const { return new RsChatLobbyMsgItem(*this) ; } - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - ChatLobbyMsgId parent_msg_id ; // Used for threaded chat. - -protected: - virtual uint32_t PacketId() const { return RsChatMsgItem::PacketId() ; } -}; - -class RsChatLobbyEventItem: public RsChatItem, public RsChatLobbyBouncingObject -{ -public: - RsChatLobbyEventItem() :RsChatItem(RS_PKT_SUBTYPE_CHAT_LOBBY_SIGNED_EVENT) {} - - virtual ~RsChatLobbyEventItem() {} - virtual RsChatLobbyBouncingObject *duplicate() const { return new RsChatLobbyEventItem(*this) ; } - // - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - // members. - // - uint8_t event_type ; // used for defining the type of event. - std::string string1; // used for any string - uint32_t sendTime; // used to check for old looping messages - -protected: - virtual uint32_t PacketId() const { return RsChatItem::PacketId() ; } -}; - -class RsChatLobbyListRequestItem: public RsChatItem -{ - public: - RsChatLobbyListRequestItem() : RsChatItem(RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_REQUEST) {} - virtual ~RsChatLobbyListRequestItem() {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -struct VisibleChatLobbyInfo -{ - ChatLobbyId id ; - std::string name ; - std::string topic ; - uint32_t count ; - ChatLobbyFlags flags ; -}; - -class RsChatLobbyListItem: public RsChatItem -{ - public: - RsChatLobbyListItem() : RsChatItem(RS_PKT_SUBTYPE_CHAT_LOBBY_LIST) {} - virtual ~RsChatLobbyListItem() {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - std::vector lobbies ; -}; - -class RsChatLobbyUnsubscribeItem: public RsChatItem -{ - public: - RsChatLobbyUnsubscribeItem() :RsChatItem(RS_PKT_SUBTYPE_CHAT_LOBBY_UNSUBSCRIBE) {} - - virtual ~RsChatLobbyUnsubscribeItem() {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint64_t lobby_id ; -}; - -class RsChatLobbyConnectChallengeItem: public RsChatItem -{ - public: - RsChatLobbyConnectChallengeItem() :RsChatItem(RS_PKT_SUBTYPE_CHAT_LOBBY_CHALLENGE) {} - - virtual ~RsChatLobbyConnectChallengeItem() {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint64_t challenge_code ; -}; - -/// @deprecated since May 2017, to be removed -class RsChatLobbyInviteItem_Deprecated : public RsChatItem -{ - public: - RsChatLobbyInviteItem_Deprecated() :RsChatItem(RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE_DEPRECATED) {} - virtual ~RsChatLobbyInviteItem_Deprecated() {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - ChatLobbyId lobby_id ; - std::string lobby_name ; - std::string lobby_topic ; - ChatLobbyFlags lobby_flags ; -}; - -class RsChatLobbyInviteItem: public RsChatItem -{ - public: - RsChatLobbyInviteItem() :RsChatItem(RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE) {} - virtual ~RsChatLobbyInviteItem() {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - ChatLobbyId lobby_id ; - std::string lobby_name ; - std::string lobby_topic ; - ChatLobbyFlags lobby_flags ; -}; - -/*! - * For saving incoming and outgoing chat msgs - * @see p3ChatService - */ -struct RsPrivateChatMsgConfigItem : RsChatItem -{ - RsPrivateChatMsgConfigItem() : - RsChatItem(RS_PKT_SUBTYPE_PRIVATECHATMSG_CONFIG) {} - - virtual ~RsPrivateChatMsgConfigItem() {} - virtual void clear() {} - - virtual void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ); - - /** set data from RsChatMsgItem to RsPrivateChatMsgConfigItem */ - void set(RsChatMsgItem *ci, const RsPeerId &peerId, uint32_t confFlags); - /** get data from RsPrivateChatMsgConfigItem to RsChatMsgItem */ - void get(RsChatMsgItem *ci); - - RsPeerId configPeerId; - uint32_t chatFlags; - uint32_t configFlags; - uint32_t sendTime; - std::string message; - uint32_t recvTime; -}; - -class RsSubscribedChatLobbyConfigItem: public RsChatItem -{ -public: - RsSubscribedChatLobbyConfigItem() :RsChatItem(RS_PKT_SUBTYPE_SUBSCRIBED_CHAT_LOBBY_CONFIG) {} - virtual ~RsSubscribedChatLobbyConfigItem() {} - - virtual void clear() { RsChatItem::clear(); info.clear(); } - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - ChatLobbyInfo info; -}; - -class RsChatLobbyConfigItem: public RsChatItem -{ -public: - RsChatLobbyConfigItem() :RsChatItem(RS_PKT_SUBTYPE_CHAT_LOBBY_CONFIG) { lobby_Id = 0; } - - virtual ~RsChatLobbyConfigItem() {} - - virtual void clear() { lobby_Id = 0; } - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint64_t lobby_Id; - uint32_t flags ; -}; - -// This class contains activity info for the sending peer: active, idle, typing, etc. -// -class RsChatStatusItem: public RsChatItem -{ - public: - RsChatStatusItem() :RsChatItem(RS_PKT_SUBTYPE_CHAT_STATUS) {} - - virtual ~RsChatStatusItem() {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t flags ; - std::string status_string; -}; - -// This class contains avatar images in Qt format. -// -class RsChatAvatarItem: public RsChatItem -{ -public: - RsChatAvatarItem(): - RsChatItem(RS_PKT_SUBTYPE_CHAT_AVATAR), - image_size(0), image_data(nullptr) - { setPriorityLevel(QOS_PRIORITY_RS_CHAT_AVATAR_ITEM); } - - ~RsChatAvatarItem() override { free(image_data); } - - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override; - - uint32_t image_size; /// size of data in bytes - unsigned char* image_data ; /// image data -}; - - -struct PrivateOugoingMapItem : RsChatItem -{ - PrivateOugoingMapItem() : RsChatItem(RS_PKT_SUBTYPE_OUTGOING_MAP) {} - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ); - - std::map store; -}; - -struct RsChatSerialiser : RsServiceSerializer -{ - RsChatSerialiser(RsSerializationFlags flags = RsSerializationFlags::NONE): - RsServiceSerializer(RS_SERVICE_TYPE_CHAT, flags) {} - - virtual RsItem *create_item(uint16_t service_id,uint8_t item_sub_id) const; -}; - diff --git a/libretroshare/src/crypto/chacha20.cpp b/libretroshare/src/crypto/chacha20.cpp deleted file mode 100644 index ebda0ee3c..000000000 --- a/libretroshare/src/crypto/chacha20.cpp +++ /dev/null @@ -1,1421 +0,0 @@ -/******************************************************************************* - * libretroshare/src/crypto: chacha20.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2016 by Mr.Alice * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "crypto/chacha20.h" -#include "util/rsprint.h" -#include "util/rsrandom.h" -#include "util/rstime.h" - -#define rotl(x,n) { x = (x << n) | (x >> (-n & 31)) ;} - -//#define DEBUG_CHACHA20 - -#if OPENSSL_VERSION_NUMBER >= 0x010100000L && !defined(LIBRESSL_VERSION_NUMBER) - #define AEAD_chacha20_poly1305_openssl AEAD_chacha20_poly1305 -#else - #define AEAD_chacha20_poly1305_rs AEAD_chacha20_poly1305 -#endif - -namespace librs { -namespace crypto { - -/*! - * \brief The uint256_32 struct - * This structure represents 256bits integers, to be used for computing poly1305 authentication tags. - */ -struct uint256_32 -{ - uint32_t b[8] ; - - uint256_32() { memset(&b[0],0,8*sizeof(uint32_t)) ; } - - uint256_32(uint32_t b7,uint32_t b6,uint32_t b5,uint32_t b4,uint32_t b3,uint32_t b2,uint32_t b1,uint32_t b0) - { - b[0]=b0; b[1]=b1; b[2]=b2; b[3]=b3; - b[4]=b4; b[5]=b5; b[6]=b6; b[7]=b7; - } - - static uint256_32 random() - { - uint256_32 r ; - for(uint32_t i=0;i<8;++i) - r.b[i] = RSRandom::random_u32(); - - return r; - } - - // constant cost == - bool operator==(const uint256_32& u) - { - bool res = true ; - - if(b[0] != u.b[0]) res = false ; - if(b[1] != u.b[1]) res = false ; - if(b[2] != u.b[2]) res = false ; - if(b[3] != u.b[3]) res = false ; - if(b[4] != u.b[4]) res = false ; - if(b[5] != u.b[5]) res = false ; - if(b[6] != u.b[6]) res = false ; - if(b[7] != u.b[7]) res = false ; - - return res ; - } - - // Constant cost sum. - // - void operator +=(const uint256_32& u) - { - uint64_t v(0) ; - - v += (uint64_t)b[0] + (uint64_t)u.b[0] ; b[0] = (uint32_t)v ; v >>= 32; - v += (uint64_t)b[1] + (uint64_t)u.b[1] ; b[1] = (uint32_t)v ; v >>= 32; - v += (uint64_t)b[2] + (uint64_t)u.b[2] ; b[2] = (uint32_t)v ; v >>= 32; - v += (uint64_t)b[3] + (uint64_t)u.b[3] ; b[3] = (uint32_t)v ; v >>= 32; - v += (uint64_t)b[4] + (uint64_t)u.b[4] ; b[4] = (uint32_t)v ; v >>= 32; - v += (uint64_t)b[5] + (uint64_t)u.b[5] ; b[5] = (uint32_t)v ; v >>= 32; - v += (uint64_t)b[6] + (uint64_t)u.b[6] ; b[6] = (uint32_t)v ; v >>= 32; - v += (uint64_t)b[7] + (uint64_t)u.b[7] ; b[7] = (uint32_t)v ; - } - void operator -=(const uint256_32& u) - { - *this += ~u ; - ++*this ; - } - void operator++() - { - for(int i=0;i<8;++i) - if( ++b[i] ) - break ; - } - - bool operator<(const uint256_32& u) const - { - for(int i=7;i>=0;--i) - if(b[i] < u.b[i]) - return true ; - else - if(b[i] > u.b[i]) - return false ; - - return false ; - } - uint256_32 operator~() const - { - uint256_32 r(*this) ; - - r.b[0] = ~b[0] ; - r.b[1] = ~b[1] ; - r.b[2] = ~b[2] ; - r.b[3] = ~b[3] ; - r.b[4] = ~b[4] ; - r.b[5] = ~b[5] ; - r.b[6] = ~b[6] ; - r.b[7] = ~b[7] ; - - return r ; - } - - void poly1305clamp() - { - b[0] &= 0x0fffffff; - b[1] &= 0x0ffffffc; - b[2] &= 0x0ffffffc; - b[3] &= 0x0ffffffc; - } - // Constant cost product. - // - void operator *=(const uint256_32& u) - { - uint256_32 r ; - - for(int i=0;i<8;++i) - for(int j=0;j<8;++j) - if(i+j < 8) - { - uint64_t s = (uint64_t)u.b[j]*(uint64_t)b[i] ; - - uint256_32 partial ; - partial.b[i+j] = (s & 0xffffffff) ; - - if(i+j+1 < 8) - partial.b[i+j+1] = (s >> 32) ; - - r += partial; - } - *this = r; - } - - static void print(const uint256_32& s) - { - fprintf(stdout,"%08x %08x %08x %08x %08x %08x %08x %08x",(uint32_t)s.b[7],(uint32_t)s.b[6],(uint32_t)s.b[5],(uint32_t)s.b[4], - (uint32_t)s.b[3],(uint32_t)s.b[2],(uint32_t)s.b[1],(uint32_t)s.b[0]) ; - } - static int max_non_zero_of_height_bits(uint8_t s) - { - for(int i=7;i>=0;--i) - if((s & (1<=0;--c) - if(b[c] != 0) - { - if( (b[c] & 0xff000000) != 0) return (c<<5) + 3*8 + max_non_zero_of_height_bits(b[c] >> 24) ; - if( (b[c] & 0x00ff0000) != 0) return (c<<5) + 2*8 + max_non_zero_of_height_bits(b[c] >> 16) ; - if( (b[c] & 0x0000ff00) != 0) return (c<<5) + 1*8 + max_non_zero_of_height_bits(b[c] >> 8) ; - - return c*32 + 0*8 + max_non_zero_of_height_bits(b[c]) ; - } - return -1; - } - void lshift(uint32_t n) - { - uint32_t p = n >> 5; // n/32 - uint32_t u = n & 0x1f ; // n%32 - - if(p > 0) - for(int i=7;i>=0;--i) - b[i] = (i>=(int)p)?b[i-p]:0 ; - - uint32_t r = 0 ; - - if(u>0) - for(int i=0;i<8;++i) - { - uint32_t r1 = (b[i] >> (31-u+1)) ; - b[i] = (b[i] << u) & 0xffffffff; - b[i] += r ; - r = r1 ; - } - } - void lshift() - { - uint32_t r ; - uint32_t r1 ; - - r1 = (b[0] >> 31) ; b[0] <<= 1; r = r1 ; - r1 = (b[1] >> 31) ; b[1] <<= 1; b[1] += r ; r = r1 ; - r1 = (b[2] >> 31) ; b[2] <<= 1; b[2] += r ; r = r1 ; - r1 = (b[3] >> 31) ; b[3] <<= 1; b[3] += r ; r = r1 ; - r1 = (b[4] >> 31) ; b[4] <<= 1; b[4] += r ; r = r1 ; - r1 = (b[5] >> 31) ; b[5] <<= 1; b[5] += r ; r = r1 ; - r1 = (b[6] >> 31) ; b[6] <<= 1; b[6] += r ; r = r1 ; - b[7] <<= 1; b[7] += r ; - } - void rshift() - { - uint32_t r ; - uint32_t r1 ; - - r1 = b[7] & 0x1; b[7] >>= 1 ; r = r1 ; - r1 = b[6] & 0x1; b[6] >>= 1 ; if(r) b[6] += 0x80000000 ; r = r1 ; - r1 = b[5] & 0x1; b[5] >>= 1 ; if(r) b[5] += 0x80000000 ; r = r1 ; - r1 = b[4] & 0x1; b[4] >>= 1 ; if(r) b[4] += 0x80000000 ; r = r1 ; - r1 = b[3] & 0x1; b[3] >>= 1 ; if(r) b[3] += 0x80000000 ; r = r1 ; - r1 = b[2] & 0x1; b[2] >>= 1 ; if(r) b[2] += 0x80000000 ; r = r1 ; - r1 = b[1] & 0x1; b[1] >>= 1 ; if(r) b[1] += 0x80000000 ; r = r1 ; - b[0] >>= 1 ; if(r) b[0] += 0x80000000 ; - } -}; - -// Compute quotient and modulo of n by p where both n and p are 256bits integers. -// -static void quotient(const uint256_32& n,const uint256_32& p,uint256_32& q,uint256_32& r) -{ - // simple algorithm: add up multiples of u while keeping below *this. Once done, substract. - - r = n ; - q = uint256_32(0,0,0,0,0,0,0,0) ; - - int bmax = n.max_non_zero_bit() - p.max_non_zero_bit(); - - uint256_32 m(0,0,0,0,0,0,0,0) ; - uint256_32 d = p ; - - m.b[bmax/32] = (1u << (bmax%32)) ; // set m to be 2^bmax - - d.lshift(bmax); - - for(int b=bmax;b>=0;--b,d.rshift(),m.rshift()) - if(! (r < d)) - { - r -= d ; - q += m ; - } -} - -static void remainder(const uint256_32& n,const uint256_32& p,uint256_32& r) -{ - // simple algorithm: add up multiples of u while keeping below *this. Once done, substract. - - r = n ; - int bmax = n.max_non_zero_bit() - p.max_non_zero_bit(); - - uint256_32 d = p ; - d.lshift(bmax); - - for(int b=bmax;b>=0;--b,d.rshift()) - if(! (r < d)) - r -= d ; -} - -class chacha20_state -{ -public: - uint32_t c[16] ; - - chacha20_state(uint8_t key[32],uint32_t block_counter,uint8_t nounce[12]) - { - c[0] = 0x61707865 ; - c[1] = 0x3320646e ; - c[2] = 0x79622d32 ; - c[3] = 0x6b206574 ; - - c[ 4] = (uint32_t)key[0 ] + (((uint32_t)key[1 ])<<8) + (((uint32_t)key[2 ])<<16) + (((uint32_t)key[3 ])<<24); - c[ 5] = (uint32_t)key[4 ] + (((uint32_t)key[5 ])<<8) + (((uint32_t)key[6 ])<<16) + (((uint32_t)key[7 ])<<24); - c[ 6] = (uint32_t)key[8 ] + (((uint32_t)key[9 ])<<8) + (((uint32_t)key[10])<<16) + (((uint32_t)key[11])<<24); - c[ 7] = (uint32_t)key[12] + (((uint32_t)key[13])<<8) + (((uint32_t)key[14])<<16) + (((uint32_t)key[15])<<24); - c[ 8] = (uint32_t)key[16] + (((uint32_t)key[17])<<8) + (((uint32_t)key[18])<<16) + (((uint32_t)key[19])<<24); - c[ 9] = (uint32_t)key[20] + (((uint32_t)key[21])<<8) + (((uint32_t)key[22])<<16) + (((uint32_t)key[23])<<24); - c[10] = (uint32_t)key[24] + (((uint32_t)key[25])<<8) + (((uint32_t)key[26])<<16) + (((uint32_t)key[27])<<24); - c[11] = (uint32_t)key[28] + (((uint32_t)key[29])<<8) + (((uint32_t)key[30])<<16) + (((uint32_t)key[31])<<24); - - c[12] = block_counter ; - - c[13] = (uint32_t)nounce[0 ] + (((uint32_t)nounce[1 ])<<8) + (((uint32_t)nounce[2 ])<<16) + (((uint32_t)nounce[3 ])<<24); - c[14] = (uint32_t)nounce[4 ] + (((uint32_t)nounce[5 ])<<8) + (((uint32_t)nounce[6 ])<<16) + (((uint32_t)nounce[7 ])<<24); - c[15] = (uint32_t)nounce[8 ] + (((uint32_t)nounce[9 ])<<8) + (((uint32_t)nounce[10])<<16) + (((uint32_t)nounce[11])<<24); - } -}; - -static void quarter_round(uint32_t& a,uint32_t& b,uint32_t& c,uint32_t& d) -{ - a += b ; d ^= a; rotl(d,16) ; //d <<<=16 ; - c += d ; b ^= c; rotl(b,12) ; //b <<<=12 ; - a += b ; d ^= a; rotl(d,8) ; //d <<<=8 ; - c += d ; b ^= c; rotl(b,7) ; //b <<<=7 ; -} - -static void add(chacha20_state& s,const chacha20_state& t) { for(uint32_t i=0;i<16;++i) s.c[i] += t.c[i] ; } - -static void apply_20_rounds(chacha20_state& s) -{ - chacha20_state t(s) ; - - for(uint32_t i=0;i<10;++i) - { - quarter_round(s.c[ 0],s.c[ 4],s.c[ 8],s.c[12]) ; - quarter_round(s.c[ 1],s.c[ 5],s.c[ 9],s.c[13]) ; - quarter_round(s.c[ 2],s.c[ 6],s.c[10],s.c[14]) ; - quarter_round(s.c[ 3],s.c[ 7],s.c[11],s.c[15]) ; - quarter_round(s.c[ 0],s.c[ 5],s.c[10],s.c[15]) ; - quarter_round(s.c[ 1],s.c[ 6],s.c[11],s.c[12]) ; - quarter_round(s.c[ 2],s.c[ 7],s.c[ 8],s.c[13]) ; - quarter_round(s.c[ 3],s.c[ 4],s.c[ 9],s.c[14]) ; - } - - add(s,t) ; -} - -#ifdef DEBUG_CHACHA20 -static void print(const chacha20_state& s) -{ - fprintf(stdout,"%08x %08x %08x %08x\n",s.c[0 ],s.c[1 ],s.c[2 ],s.c[3 ]) ; - fprintf(stdout,"%08x %08x %08x %08x\n",s.c[4 ],s.c[5 ],s.c[6 ],s.c[7 ]) ; - fprintf(stdout,"%08x %08x %08x %08x\n",s.c[8 ],s.c[9 ],s.c[10],s.c[11]) ; - fprintf(stdout,"%08x %08x %08x %08x\n",s.c[12],s.c[13],s.c[14],s.c[15]) ; -} -#endif - -void chacha20_encrypt_rs(uint8_t key[32], uint32_t block_counter, uint8_t nonce[12], uint8_t *data, uint32_t size) -{ - for(uint32_t i=0;i> (8*(k%4))) & 0xff) ; - } -} - -#if OPENSSL_VERSION_NUMBER >= 0x010100000L && !defined(LIBRESSL_VERSION_NUMBER) -void chacha20_encrypt_openssl(uint8_t key[32], uint32_t block_counter, uint8_t nonce[12], uint8_t *data, uint32_t size) -{ - EVP_CIPHER_CTX *ctx; - - int len; - int tmp_len; - uint8_t tmp[size]; - uint8_t iv[16]; - - // create iv with nonce and block counter - memcpy(iv, &block_counter, 4); - memcpy(iv + 4, nonce, 12); - - /* Create and initialise the context */ - if(!(ctx = EVP_CIPHER_CTX_new())) return; - - /* Initialise the encryption operation. IMPORTANT - ensure you use a key - * and IV size appropriate for your cipher - * In this example we are using 256 bit AES (i.e. a 256 bit key). The - * IV size for *most* modes is the same as the block size. For AES this - * is 128 bits */ - if(1 != EVP_EncryptInit_ex(ctx, EVP_chacha20(), NULL, key, iv)) goto out; - - /* Provide the message to be encrypted, and obtain the encrypted output. - * EVP_EncryptUpdate can be called multiple times if necessary - */ - if(1 != EVP_EncryptUpdate(ctx, tmp, &len, data, size)) goto out; - tmp_len = len; - - /* Finalise the encryption. Further ciphertext bytes may be written at - * this stage. - */ - if(1 != EVP_EncryptFinal_ex(ctx, tmp + len, &len)) goto out; - tmp_len += len; - - memcpy(data, tmp, tmp_len); - -out: - /* Clean up */ - EVP_CIPHER_CTX_free(ctx); -} -#endif - -struct poly1305_state -{ - uint256_32 r ; - uint256_32 s ; - uint256_32 p ; - uint256_32 a ; -}; - -static void poly1305_init(poly1305_state& s,uint8_t key[32]) -{ - s.r = uint256_32( 0,0,0,0, - ((uint32_t)key[12] << 0) + ((uint32_t)key[13] << 8) + ((uint32_t)key[14] << 16) + ((uint32_t)key[15] << 24), - ((uint32_t)key[ 8] << 0) + ((uint32_t)key[ 9] << 8) + ((uint32_t)key[10] << 16) + ((uint32_t)key[11] << 24), - ((uint32_t)key[ 4] << 0) + ((uint32_t)key[ 5] << 8) + ((uint32_t)key[ 6] << 16) + ((uint32_t)key[ 7] << 24), - ((uint32_t)key[ 0] << 0) + ((uint32_t)key[ 1] << 8) + ((uint32_t)key[ 2] << 16) + ((uint32_t)key[ 3] << 24) - ); - - s.r.poly1305clamp(); - - s.s = uint256_32( 0,0,0,0, - ((uint32_t)key[28] << 0) + ((uint32_t)key[29] << 8) + ((uint32_t)key[30] << 16) + ((uint32_t)key[31] << 24), - ((uint32_t)key[24] << 0) + ((uint32_t)key[25] << 8) + ((uint32_t)key[26] << 16) + ((uint32_t)key[27] << 24), - ((uint32_t)key[20] << 0) + ((uint32_t)key[21] << 8) + ((uint32_t)key[22] << 16) + ((uint32_t)key[23] << 24), - ((uint32_t)key[16] << 0) + ((uint32_t)key[17] << 8) + ((uint32_t)key[18] << 16) + ((uint32_t)key[19] << 24) - ); - - s.p = uint256_32(0,0,0,0x3,0xffffffff,0xffffffff,0xffffffff,0xfffffffb) ; - s.a = uint256_32(0,0,0, 0, 0, 0, 0, 0) ; -} - -// Warning: each call will automatically *pad* the data to a multiple of 16 bytes. -// -static void poly1305_add(poly1305_state& s,uint8_t *message,uint32_t size,bool pad_to_16_bytes=false) -{ -#ifdef DEBUG_CHACHA20 - std::cerr << "Poly1305: digesting " << RsUtil::BinToHex(message,size) << std::endl; -#endif - - for(uint32_t i=0;i<(size+15)/16;++i) - { - uint256_32 block ; - uint32_t j; - - for(j=0;j<16 && i*16+j < size;++j) - block.b[j/4] += ((uint64_t)message[i*16+j]) << (8*(j & 0x3)) ; - - if(pad_to_16_bytes) - block.b[4] += 0x01 ; - else - block.b[j/4] += 0x01 << (8*(j& 0x3)); - - s.a += block ; - s.a *= s.r ; - - uint256_32 q,rst; - remainder(s.a,s.p,rst) ; - s.a = rst ; - } -} - -static void poly1305_finish(poly1305_state& s,uint8_t tag[16]) -{ - s.a += s.s ; - - tag[ 0] = (s.a.b[0] >> 0) & 0xff ; tag[ 1] = (s.a.b[0] >> 8) & 0xff ; tag[ 2] = (s.a.b[0] >>16) & 0xff ; tag[ 3] = (s.a.b[0] >>24) & 0xff ; - tag[ 4] = (s.a.b[1] >> 0) & 0xff ; tag[ 5] = (s.a.b[1] >> 8) & 0xff ; tag[ 6] = (s.a.b[1] >>16) & 0xff ; tag[ 7] = (s.a.b[1] >>24) & 0xff ; - tag[ 8] = (s.a.b[2] >> 0) & 0xff ; tag[ 9] = (s.a.b[2] >> 8) & 0xff ; tag[10] = (s.a.b[2] >>16) & 0xff ; tag[11] = (s.a.b[2] >>24) & 0xff ; - tag[12] = (s.a.b[3] >> 0) & 0xff ; tag[13] = (s.a.b[3] >> 8) & 0xff ; tag[14] = (s.a.b[3] >>16) & 0xff ; tag[15] = (s.a.b[3] >>24) & 0xff ; -} - -void poly1305_tag(uint8_t key[32],uint8_t *message,uint32_t size,uint8_t tag[16]) -{ - poly1305_state s; - - poly1305_init (s,key); - poly1305_add(s,message,size) ; - poly1305_finish(s,tag); -} - -static void poly1305_key_gen(uint8_t key[32], uint8_t nonce[12], uint8_t generated_key[32]) -{ - uint32_t counter = 0 ; - - chacha20_state s(key,counter,nonce); - apply_20_rounds(s) ; - - for(uint32_t k=0;k<8;++k) - for(uint32_t i=0;i<4;++i) - generated_key[k*4 + i] = (s.c[k] >> 8*i) & 0xff ; -} - -bool constant_time_memory_compare(const uint8_t *m1,const uint8_t *m2,uint32_t size) -{ - return !CRYPTO_memcmp(m1,m2,size) ; -} - -bool AEAD_chacha20_poly1305_rs(uint8_t key[32], uint8_t nonce[12],uint8_t *data,uint32_t data_size,uint8_t *aad,uint32_t aad_size,uint8_t tag[16],bool encrypt) -{ - // encrypt + tag. See RFC7539-2.8 - - uint8_t session_key[32]; - poly1305_key_gen(key,nonce,session_key); - - uint8_t lengths_vector[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } ; - - for(uint32_t i=0;i<4;++i) - { - lengths_vector[0+i] = ( aad_size >> (8*i)) & 0xff ; - lengths_vector[8+i] = (data_size >> (8*i)) & 0xff ; - } - - if(encrypt) - { - chacha20_encrypt_rs(key,1,nonce,data,data_size); - - poly1305_state pls ; - - poly1305_init(pls,session_key); - - poly1305_add(pls,aad,aad_size,true); // add and pad the aad - poly1305_add(pls,data,data_size,true); // add and pad the cipher text - poly1305_add(pls,lengths_vector,16,true); // add the lengths - - poly1305_finish(pls,tag); - return true ; - } - else - { - poly1305_state pls ; - uint8_t computed_tag[16]; - - poly1305_init(pls,session_key); - - poly1305_add(pls,aad,aad_size,true); // add and pad the aad - poly1305_add(pls,data,data_size,true); // add and pad the cipher text - poly1305_add(pls,lengths_vector,16,true); // add the lengths - - poly1305_finish(pls,computed_tag); - - // decrypt - - chacha20_encrypt_rs(key,1,nonce,data,data_size); - - return constant_time_memory_compare(tag,computed_tag,16) ; - } -} - -#if OPENSSL_VERSION_NUMBER >= 0x010100000L && !defined(LIBRESSL_VERSION_NUMBER) -#define errorOut {ret = false; goto out;} - -bool AEAD_chacha20_poly1305_openssl(uint8_t key[32], uint8_t nonce[12], uint8_t *data, uint32_t data_size, uint8_t *aad, uint32_t aad_size, uint8_t tag[16], bool encrypt_or_decrypt) -{ - EVP_CIPHER_CTX *ctx; - - bool ret = true; - int len; - const uint8_t tag_len = 16; - int tmp_len; - uint8_t tmp[data_size]; - - /* Create and initialise the context */ - if(!(ctx = EVP_CIPHER_CTX_new())) return false; - - if (encrypt_or_decrypt) { - /* Initialise the encryption operation. */ - if(1 != EVP_EncryptInit_ex(ctx, EVP_chacha20_poly1305(), NULL, NULL, NULL)) errorOut - - /* Initialise key and IV */ - if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce)) errorOut - - /* Provide any AAD data. This can be called zero or more times as - * required - */ - if(1 != EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_size)) errorOut - - /* Provide the message to be encrypted, and obtain the encrypted output. - * EVP_EncryptUpdate can be called multiple times if necessary - */ - if(1 != EVP_EncryptUpdate(ctx, tmp, &len, data, data_size)) errorOut - tmp_len = len; - - /* Finalise the encryption. Normally ciphertext bytes may be written at - * this stage, but this does not occur in GCM mode - */ - if(1 != EVP_EncryptFinal_ex(ctx, data + len, &len)) errorOut - tmp_len += len; - - /* Get the tag */ - if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, tag_len, tag)) errorOut - } else { - /* Initialise the decryption operation. */ - if(!EVP_DecryptInit_ex(ctx, EVP_chacha20_poly1305(), NULL, key, nonce)) errorOut - - /* Provide any AAD data. This can be called zero or more times as - * required - */ - if(!EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_size)) errorOut - - /* Provide the message to be decrypted, and obtain the plaintext output. - * EVP_DecryptUpdate can be called multiple times if necessary - */ - if(!EVP_DecryptUpdate(ctx, tmp, &len, data, data_size)) errorOut - tmp_len = len; - - /* Set expected tag value. Works in OpenSSL 1.0.1d and later */ - if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, tag)) errorOut - - /* Finalise the decryption. A positive return value indicates success, - * anything else is a failure - the plaintext is not trustworthy. - */ - if(EVP_DecryptFinal_ex(ctx, tmp + len, &len) > 0) { - /* Success */ - tmp_len += len; - ret = true; - } else { - /* Verify failed */ - errorOut - } - } - - memcpy(data, tmp, tmp_len); - -out: - /* Clean up */ - EVP_CIPHER_CTX_free(ctx); - return !!ret; -} - -#undef errorOut -#endif - -bool AEAD_chacha20_sha256(uint8_t key[32], uint8_t nonce[12],uint8_t *data,uint32_t data_size,uint8_t *aad,uint32_t aad_size,uint8_t tag[16],bool encrypt) -{ - // encrypt + tag. See RFC7539-2.8 - - if(encrypt) - { -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - chacha20_encrypt_rs(key,1,nonce,data,data_size); -#else - chacha20_encrypt_openssl(key, 1, nonce, data, data_size); -#endif - - uint8_t computed_tag[EVP_MAX_MD_SIZE]; - unsigned int md_size ; - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - HMAC_CTX hmac_ctx ; - HMAC_CTX_init(&hmac_ctx) ; - - HMAC_Init(&hmac_ctx,key,32,EVP_sha256()) ; - HMAC_Update(&hmac_ctx,aad,aad_size) ; - HMAC_Update(&hmac_ctx,data,data_size) ; - HMAC_Final(&hmac_ctx,computed_tag,&md_size) ; - - HMAC_CTX_cleanup(&hmac_ctx) ; -#else - HMAC_CTX *hmac_ctx = HMAC_CTX_new(); - - HMAC_Init_ex(hmac_ctx,key,32,EVP_sha256(),NULL) ; - HMAC_Update(hmac_ctx,aad,aad_size) ; - HMAC_Update(hmac_ctx,data,data_size) ; - HMAC_Final(hmac_ctx,computed_tag,&md_size) ; - - HMAC_CTX_free(hmac_ctx) ; - hmac_ctx=NULL; -#endif - - assert(md_size >= 16); - - memcpy(tag,computed_tag,16) ; - - return true ; - } - else - { - uint8_t computed_tag[EVP_MAX_MD_SIZE]; - unsigned int md_size ; - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - HMAC_CTX hmac_ctx ; - HMAC_CTX_init(&hmac_ctx) ; - - HMAC_Init(&hmac_ctx,key,32,EVP_sha256()) ; - HMAC_Update(&hmac_ctx,aad,aad_size) ; - HMAC_Update(&hmac_ctx,data,data_size) ; - HMAC_Final(&hmac_ctx,computed_tag,&md_size) ; - - HMAC_CTX_cleanup(&hmac_ctx) ; -#else - HMAC_CTX *hmac_ctx = HMAC_CTX_new(); - - HMAC_Init_ex(hmac_ctx,key,32,EVP_sha256(),NULL) ; - HMAC_Update(hmac_ctx,aad,aad_size) ; - HMAC_Update(hmac_ctx,data,data_size) ; - HMAC_Final(hmac_ctx,computed_tag,&md_size) ; - - HMAC_CTX_free(hmac_ctx) ; - hmac_ctx=NULL; -#endif - - // decrypt - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - chacha20_encrypt_rs(key,1,nonce,data,data_size); -#else - chacha20_encrypt_openssl(key, 1, nonce, data, data_size); -#endif - - return constant_time_memory_compare(tag,computed_tag,16) ; - } -} - - -bool perform_tests() -{ - // RFC7539 - 2.1.1 - - std::cerr << " quarter round " ; - - uint32_t a = 0x11111111 ; - uint32_t b = 0x01020304 ; - uint32_t c = 0x9b8d6f43 ; - uint32_t d = 0x01234567 ; - - quarter_round(a,b,c,d) ; - - if(!(a == 0xea2a92f4)) return false ; - if(!(b == 0xcb1cf8ce)) return false ; - if(!(c == 0x4581472e)) return false ; - if(!(d == 0x5881c4bb)) return false ; - - std::cerr << " OK" << std::endl; - - // RFC7539 - 2.3.2 - - std::cerr << " RFC7539 - 2.3.2 " ; - - uint8_t key[32] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b, \ - 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, \ - 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f } ; - uint8_t nounce[12] = { 0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x4a,0x00,0x00,0x00,0x00 } ; - - chacha20_state s(key,1,nounce) ; - -#ifdef DEBUG_CHACHA20 - print(s) ; -#endif - - apply_20_rounds(s) ; - -#ifdef DEBUG_CHACHA20 - fprintf(stdout,"\n") ; - - print(s) ; -#endif - - uint32_t check_vals[16] = { - 0xe4e7f110, 0x15593bd1, 0x1fdd0f50, 0xc47120a3, - 0xc7f4d1c7, 0x0368c033, 0x9aaa2204, 0x4e6cd4c3, - 0x466482d2, 0x09aa9f07, 0x05d7c214, 0xa2028bd9, - 0xd19c12b5, 0xb94e16de, 0xe883d0cb, 0x4e3c50a2 - }; - - for(uint32_t i=0;i<16;++i) - if(s.c[i] != check_vals[i]) - return false ; - - std::cerr << " OK" << std::endl; - - // RFC7539 - 2.4.2 - - std::cerr << " RFC7539 - 2.4.2 " ; - - uint8_t nounce2[12] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4a,0x00,0x00,0x00,0x00 } ; - - uint8_t plaintext[7*16+2] = { - 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, - 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, - 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, - 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, - 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, - 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, - 0x74, 0x2e - }; - - chacha20_encrypt_rs(key,1,nounce2,plaintext,7*16+2) ; - -#ifdef DEBUG_CHACHA20 - fprintf(stdout,"CipherText: \n") ; - - for(uint32_t k=0;k<7*16+2;++k) - { - fprintf(stdout,"%02x ",plaintext[k]) ; - - if( (k % 16) == 15) - fprintf(stdout,"\n") ; - } - fprintf(stdout,"\n") ; -#endif - - uint8_t check_cipher_text[7*16+2] = { - 0x6e, 0x2e, 0x35, 0x9a, 0x25, 0x68, 0xf9, 0x80, 0x41, 0xba, 0x07, 0x28, 0xdd, 0x0d, 0x69, 0x81, - 0xe9, 0x7e, 0x7a, 0xec, 0x1d, 0x43, 0x60, 0xc2, 0x0a, 0x27, 0xaf, 0xcc, 0xfd, 0x9f, 0xae, 0x0b, - 0xf9, 0x1b, 0x65, 0xc5, 0x52, 0x47, 0x33, 0xab, 0x8f, 0x59, 0x3d, 0xab, 0xcd, 0x62, 0xb3, 0x57, - 0x16, 0x39, 0xd6, 0x24, 0xe6, 0x51, 0x52, 0xab, 0x8f, 0x53, 0x0c, 0x35, 0x9f, 0x08, 0x61, 0xd8, - 0x07, 0xca, 0x0d, 0xbf, 0x50, 0x0d, 0x6a, 0x61, 0x56, 0xa3, 0x8e, 0x08, 0x8a, 0x22, 0xb6, 0x5e, - 0x52, 0xbc, 0x51, 0x4d, 0x16, 0xcc, 0xf8, 0x06, 0x81, 0x8c, 0xe9, 0x1a, 0xb7, 0x79, 0x37, 0x36, - 0x5a, 0xf9, 0x0b, 0xbf, 0x74, 0xa3, 0x5b, 0xe6, 0xb4, 0x0b, 0x8e, 0xed, 0xf2, 0x78, 0x5e, 0x42, - 0x87, 0x4d - }; - - for(uint32_t i=0;i<7*16+2;++i) - if(!(check_cipher_text[i] == plaintext[i] )) - return false; - - std::cerr << " OK" << std::endl; - - // operators - - { uint256_32 uu(0,0,0,0,0,0,0,0 ) ; ++uu ; if(!(uu == uint256_32(0,0,0,0,0,0,0,1))) return false ; } - { uint256_32 uu(0,0,0,0,0,0,0,0xffffffff) ; ++uu ; if(!(uu == uint256_32(0,0,0,0,0,0,1,0))) return false ; } - { uint256_32 uu(0,0,0,0,0,0,0,0) ; uu = ~uu;++uu ; if(!(uu == uint256_32(0,0,0,0,0,0,0,0))) return false ; } - - std::cerr << " operator++ on 256bits numbers OK" << std::endl; - - // sums/diffs of numbers - - for(uint32_t i=0;i<100;++i) - { - uint256_32 a = uint256_32::random() ; - uint256_32 b = uint256_32::random() ; -#ifdef DEBUG_CHACHA20 - fprintf(stdout,"Adding ") ; - uint256_32::print(a) ; - fprintf(stdout,"\n to ") ; - uint256_32::print(b) ; -#endif - - uint256_32 c(a) ; - if(!(c == a) ) - return false; - - c += b ; - -#ifdef DEBUG_CHACHA20 - fprintf(stdout,"\n found ") ; - uint256_32::print(c) ; -#endif - - c -= b ; - -#ifdef DEBUG_CHACHA20 - fprintf(stdout,"\n subst ") ; - uint256_32::print(c) ; - fprintf(stdout,"\n") ; -#endif - - if(!(a == a)) return false ; - if(!(c == a)) return false ; - - uint256_32 vv(0,0,0,0,0,0,0,1) ; - vv -= a ; - vv += a ; - - if(!(vv == uint256_32(0,0,0,0,0,0,0,1))) return false ; - - } - uint256_32 vv(0,0,0,0,0,0,0,0) ; - uint256_32 ww(0,0,0,0,0,0,0,1) ; - vv -= ww ; - if(!(vv == ~uint256_32(0,0,0,0,0,0,0,0))) return false; - - std::cerr << " Sums / diffs of 256bits numbers OK" << std::endl; - - // check that (a-b)*(c-d) = ac - bc - ad + bd - - for(uint32_t i=0;i<100;++i) - { - uint256_32 a = uint256_32::random(); - uint256_32 b = uint256_32::random(); - uint256_32 c = uint256_32::random(); - uint256_32 d = uint256_32::random(); - - uint256_32 amb(a) ; - amb -= b; - uint256_32 cmd(c) ; - cmd -= d; - uint256_32 ambtcmd(amb); - ambtcmd *= cmd ; - - uint256_32 atc(a) ; atc *= c ; - uint256_32 btc(b) ; btc *= c ; - uint256_32 atd(a) ; atd *= d ; - uint256_32 btd(b) ; btd *= d ; - - uint256_32 atcmbtcmatdpbtd(atc) ; - atcmbtcmatdpbtd -= btc ; - atcmbtcmatdpbtd -= atd ; - atcmbtcmatdpbtd += btd ; - - if(!(atcmbtcmatdpbtd == ambtcmd)) return false ; - } - std::cerr << " (a-b)*(c-d) == ac-bc-ad+bd on random OK" << std::endl; - - // shifts - - for(uint32_t i=0;i<100;++i) - { - uint256_32 x = uint256_32::random(); - uint256_32 y(x) ; - - uint32_t r = x.b[0] & 0x1 ; - x.rshift() ; - x.lshift() ; - - x.b[0] += r ; - - if(!(x == y) ) return false ; - } - std::cerr << " left/right shifting OK" << std::endl; - - // test modulo by computing modulo and recomputing the product. - - for(uint32_t i=0;i<100;++i) - { - uint256_32 q1(0,0,0,0,0,0,0,0),r1(0,0,0,0,0,0,0,0) ; - - uint256_32 n1 = uint256_32::random(); - uint256_32 p1 = uint256_32::random(); - - if(RSRandom::random_f32() < 0.2) - { - p1.b[7] = 0 ; - - if(RSRandom::random_f32() < 0.1) - p1.b[6] = 0 ; - } - - quotient(n1,p1,q1,r1) ; -#ifdef DEBUG_CHACHA20 - fprintf(stdout,"result: q=") ; uint256_32::print(q1) ; fprintf(stdout," r=") ; uint256_32::print(r1) ; fprintf(stdout,"\n") ; -#endif - - //uint256_32 res(q1) ; - q1 *= p1 ; - q1 += r1 ; - - if(!(q1 == n1)) return false ; - } - std::cerr << " Quotient/modulo on random numbers OK" << std::endl; - - // RFC7539 - 2.5 - // - { - uint8_t key[32] = { 0x85,0xd6,0xbe,0x78,0x57,0x55,0x6d,0x33,0x7f,0x44,0x52,0xfe,0x42,0xd5,0x06,0xa8,0x01,0x03,0x80,0x8a,0xfb,0x0d,0xb2,0xfd,0x4a,0xbf,0xf6,0xaf,0x41,0x49,0xf5,0x1b } ; - uint8_t tag[16] ; - std::string msg("Cryptographic Forum Research Group") ; - - poly1305_tag(key,(uint8_t*)msg.c_str(),msg.length(),tag) ; - - uint8_t test_tag[16] = { 0xa8,0x06,0x1d,0xc1,0x30,0x51,0x36,0xc6,0xc2,0x2b,0x8b,0xaf,0x0c,0x01,0x27,0xa9 }; - - if(!(constant_time_memory_compare(tag,test_tag,16))) return false ; - } - std::cerr << " RFC7539 - 2.5 OK" << std::endl; - - // RFC7539 - Poly1305 test vector #1 - // - { - uint8_t key[32] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; - uint8_t tag[16] ; - uint8_t text[64] ; - memset(text,0,64) ; - - poly1305_tag(key,text,64,tag) ; - - uint8_t test_tag[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; - - if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; - } - std::cerr << " RFC7539 poly1305 test vector #001 OK" << std::endl; - - // RFC7539 - Poly1305 test vector #2 - // - { - uint8_t key[32] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x36,0xe5,0xf6,0xb5,0xc5,0xe0,0x60,0x70,0xf0,0xef,0xca,0x96,0x22,0x7a,0x86,0x3e } ; - uint8_t tag[16] ; - - std::string msg("Any submission to the IETF intended by the Contributor for publication as all or part of an IETF Internet-Draft or RFC and any statement made within the context of an IETF activity is considered an \"IETF Contribution\". Such statements include oral statements in IETF sessions, as well as written and electronic communications made at any time or place, which are addressed to") ; - - poly1305_tag(key,(uint8_t*)msg.c_str(),msg.length(),tag) ; - - uint8_t test_tag[16] = { 0x36,0xe5,0xf6,0xb5,0xc5,0xe0,0x60,0x70,0xf0,0xef,0xca,0x96,0x22,0x7a,0x86,0x3e }; - - if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; - } - std::cerr << " RFC7539 poly1305 test vector #002 OK" << std::endl; - - // RFC7539 - Poly1305 test vector #3 - // - { - uint8_t key[32] = { 0x36,0xe5,0xf6,0xb5,0xc5,0xe0,0x60,0x70,0xf0,0xef,0xca,0x96,0x22,0x7a,0x86,0x3e, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; - uint8_t tag[16] ; - - std::string msg("Any submission to the IETF intended by the Contributor for publication as all or part of an IETF Internet-Draft or RFC and any statement made within the context of an IETF activity is considered an \"IETF Contribution\". Such statements include oral statements in IETF sessions, as well as written and electronic communications made at any time or place, which are addressed to") ; - - poly1305_tag(key,(uint8_t*)msg.c_str(),msg.length(),tag) ; - - uint8_t test_tag[16] = { 0xf3,0x47,0x7e,0x7c,0xd9,0x54,0x17,0xaf,0x89,0xa6,0xb8,0x79,0x4c,0x31,0x0c,0xf0 } ; - - if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; - } - std::cerr << " RFC7539 poly1305 test vector #003 OK" << std::endl; - - // RFC7539 - Poly1305 test vector #4 - // - { - uint8_t key[32] = { 0x1c ,0x92 ,0x40 ,0xa5 ,0xeb ,0x55 ,0xd3 ,0x8a ,0xf3 ,0x33 ,0x88 ,0x86 ,0x04 ,0xf6 ,0xb5 ,0xf0, - 0x47 ,0x39 ,0x17 ,0xc1 ,0x40 ,0x2b ,0x80 ,0x09 ,0x9d ,0xca ,0x5c ,0xbc ,0x20 ,0x70 ,0x75 ,0xc0 }; - uint8_t tag[16] ; - - std::string msg("'Twas brillig, and the slithy toves\nDid gyre and gimble in the wabe:\nAll mimsy were the borogoves,\nAnd the mome raths outgrabe.") ; - - poly1305_tag(key,(uint8_t*)msg.c_str(),msg.length(),tag) ; - - uint8_t test_tag[16] = { 0x45,0x41,0x66,0x9a,0x7e,0xaa,0xee,0x61,0xe7,0x08,0xdc,0x7c,0xbc,0xc5,0xeb,0x62 } ; - - if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; - } - std::cerr << " RFC7539 poly1305 test vector #004 OK" << std::endl; - - // RFC7539 - Poly1305 test vector #5 - // - { - uint8_t key[32] = { 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - uint8_t tag[16] ; - - uint8_t msg[] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }; - - poly1305_tag(key,msg,16,tag) ; - - uint8_t test_tag[16] = { 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; - - if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; - } - std::cerr << " RFC7539 poly1305 test vector #005 OK" << std::endl; - - // RFC7539 - Poly1305 test vector #6 - // - { - uint8_t key[32] = { 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }; - uint8_t tag[16] ; - - uint8_t msg[16] = { 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - - poly1305_tag(key,msg,16,tag) ; - - uint8_t test_tag[16] = { 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; - - if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; - } - std::cerr << " RFC7539 poly1305 test vector #006 OK" << std::endl; - - // RFC7539 - Poly1305 test vector #7 - // - { - uint8_t key[32] = { 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - uint8_t tag[16] ; - - uint8_t msg[48] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; - - poly1305_tag(key,msg,48,tag) ; - - uint8_t test_tag[16] = { 0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; - - if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; - } - std::cerr << " RFC7539 poly1305 test vector #007 OK" << std::endl; - - // RFC7539 - Poly1305 test vector #8 - // - { - uint8_t key[32] = { 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - uint8_t tag[16] ; - - uint8_t msg[48] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xfb,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe, - 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 } ; - - poly1305_tag(key,msg,48,tag) ; - - uint8_t test_tag[16] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; - - if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; - } - std::cerr << " RFC7539 poly1305 test vector #008 OK" << std::endl; - - // RFC7539 - Poly1305 test vector #9 - // - { - uint8_t key[32] = { 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - uint8_t tag[16] ; - - uint8_t msg[16] = { 0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff } ; - - poly1305_tag(key,msg,16,tag) ; - - uint8_t test_tag[16] = { 0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff } ; - - if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; - } - std::cerr << " RFC7539 poly1305 test vector #009 OK" << std::endl; - - // RFC7539 - Poly1305 test vector #10 - // - { - uint8_t key[32] = { 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - uint8_t tag[16] ; - - uint8_t msg[64] = { - 0xE3 ,0x35 ,0x94 ,0xD7 ,0x50 ,0x5E ,0x43 ,0xB9 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00, - 0x33 ,0x94 ,0xD7 ,0x50 ,0x5E ,0x43 ,0x79 ,0xCD ,0x01 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00, - 0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00, - 0x01 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 }; - - poly1305_tag(key,msg,64,tag) ; - - uint8_t test_tag[16] = { 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; - - if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; - } - std::cerr << " RFC7539 poly1305 test vector #010 OK" << std::endl; - - // RFC7539 - Poly1305 test vector #11 - // - { - uint8_t key[32] = { 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - uint8_t tag[16] ; - - uint8_t msg[48] = { - 0xE3 ,0x35 ,0x94 ,0xD7 ,0x50 ,0x5E ,0x43 ,0xB9 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00, - 0x33 ,0x94 ,0xD7 ,0x50 ,0x5E ,0x43 ,0x79 ,0xCD ,0x01 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00, - 0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 } ; - - poly1305_tag(key,msg,48,tag) ; - - uint8_t test_tag[16] = { 0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; - - if(!constant_time_memory_compare(tag,test_tag,16)) return false ; - } - std::cerr << " RFC7539 poly1305 test vector #011 OK" << std::endl; - - // RFC7539 - 2.6.2 - // - { - uint8_t key[32] = { 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, - 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f }; - - uint8_t session_key[32] ; - uint8_t test_session_key[32] = { 0x8a,0xd5,0xa0,0x8b,0x90,0x5f,0x81,0xcc,0x81,0x50,0x40,0x27,0x4a,0xb2,0x94,0x71, - 0xa8,0x33,0xb6,0x37,0xe3,0xfd,0x0d,0xa5,0x08,0xdb,0xb8,0xe2,0xfd,0xd1,0xa6,0x46 }; - - uint8_t nonce[12] = { 0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }; - - poly1305_key_gen(key,nonce,session_key) ; - - if(!constant_time_memory_compare(session_key,test_session_key,32)) return false ; - } - std::cerr << " RFC7539 - 2.6.2 OK" << std::endl; - - // RFC7539 - Poly1305 key generation. Test vector #1 - // - { - uint8_t key[32] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - - uint8_t nonce[12] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - uint8_t session_key[32] ; - uint8_t test_session_key[32] = { 0x76,0xb8,0xe0,0xad,0xa0,0xf1,0x3d,0x90,0x40,0x5d,0x6a,0xe5,0x53,0x86,0xbd,0x28, - 0xbd,0xd2,0x19,0xb8,0xa0,0x8d,0xed,0x1a,0xa8,0x36,0xef,0xcc,0x8b,0x77,0x0d,0xc7 }; - - poly1305_key_gen(key,nonce,session_key) ; - - if(!constant_time_memory_compare(session_key,test_session_key,32)) return false ; - } - std::cerr << " RFC7539 poly1305 key gen. TVec #1 OK" << std::endl; - - // RFC7539 - Poly1305 key generation. Test vector #2 - // - { - uint8_t key[32] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 }; - - uint8_t nonce[12] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02 }; - uint8_t session_key[32] ; - uint8_t test_session_key[32] = { 0xec,0xfa,0x25,0x4f,0x84,0x5f,0x64,0x74,0x73,0xd3,0xcb,0x14,0x0d,0xa9,0xe8,0x76, - 0x06,0xcb,0x33,0x06,0x6c,0x44,0x7b,0x87,0xbc,0x26,0x66,0xdd,0xe3,0xfb,0xb7,0x39 }; - - - - poly1305_key_gen(key,nonce,session_key) ; - - if(!constant_time_memory_compare(session_key,test_session_key,32)) return false ; - } - std::cerr << " RFC7539 poly1305 key gen. TVec #2 OK" << std::endl; - - // RFC7539 - Poly1305 key generation. Test vector #3 - // - { - uint8_t key[32] = { 0x1c,0x92,0x40,0xa5,0xeb,0x55,0xd3,0x8a,0xf3,0x33,0x88,0x86,0x04,0xf6,0xb5,0xf0, - 0x47,0x39,0x17,0xc1,0x40,0x2b,0x80,0x09,0x9d,0xca,0x5c,0xbc,0x20,0x70,0x75,0xc0 }; - - uint8_t nonce[12] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02 }; - uint8_t session_key[32] ; - uint8_t test_session_key[32] = { 0x96,0x5e,0x3b,0xc6,0xf9,0xec,0x7e,0xd9,0x56,0x08,0x08,0xf4,0xd2,0x29,0xf9,0x4b, - 0x13,0x7f,0xf2,0x75,0xca,0x9b,0x3f,0xcb,0xdd,0x59,0xde,0xaa,0xd2,0x33,0x10,0xae }; - - poly1305_key_gen(key,nonce,session_key) ; - - if(!constant_time_memory_compare(session_key,test_session_key,32)) return false ; - } - std::cerr << " RFC7539 poly1305 key gen. TVec #3 OK" << std::endl; - - // RFC7539 - 2.8.2 - // - { - uint8_t msg[7*16+2] = { - 0x4c,0x61,0x64,0x69,0x65,0x73,0x20,0x61,0x6e,0x64,0x20,0x47,0x65,0x6e,0x74,0x6c, - 0x65,0x6d,0x65,0x6e,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x63,0x6c,0x61,0x73, - 0x73,0x20,0x6f,0x66,0x20,0x27,0x39,0x39,0x3a,0x20,0x49,0x66,0x20,0x49,0x20,0x63, - 0x6f,0x75,0x6c,0x64,0x20,0x6f,0x66,0x66,0x65,0x72,0x20,0x79,0x6f,0x75,0x20,0x6f, - 0x6e,0x6c,0x79,0x20,0x6f,0x6e,0x65,0x20,0x74,0x69,0x70,0x20,0x66,0x6f,0x72,0x20, - 0x74,0x68,0x65,0x20,0x66,0x75,0x74,0x75,0x72,0x65,0x2c,0x20,0x73,0x75,0x6e,0x73, - 0x63,0x72,0x65,0x65,0x6e,0x20,0x77,0x6f,0x75,0x6c,0x64,0x20,0x62,0x65,0x20,0x69, - 0x74,0x2e } ; - - uint8_t test_msg[7*16+2] = { - 0xd3,0x1a,0x8d,0x34,0x64,0x8e,0x60,0xdb,0x7b,0x86,0xaf,0xbc,0x53,0xef,0x7e,0xc2, - 0xa4,0xad,0xed,0x51,0x29,0x6e,0x08,0xfe,0xa9,0xe2,0xb5,0xa7,0x36,0xee,0x62,0xd6, - 0x3d,0xbe,0xa4,0x5e,0x8c,0xa9,0x67,0x12,0x82,0xfa,0xfb,0x69,0xda,0x92,0x72,0x8b, - 0x1a,0x71,0xde,0x0a,0x9e,0x06,0x0b,0x29,0x05,0xd6,0xa5,0xb6,0x7e,0xcd,0x3b,0x36, - 0x92,0xdd,0xbd,0x7f,0x2d,0x77,0x8b,0x8c,0x98,0x03,0xae,0xe3,0x28,0x09,0x1b,0x58, - 0xfa,0xb3,0x24,0xe4,0xfa,0xd6,0x75,0x94,0x55,0x85,0x80,0x8b,0x48,0x31,0xd7,0xbc, - 0x3f,0xf4,0xde,0xf0,0x8e,0x4b,0x7a,0x9d,0xe5,0x76,0xd2,0x65,0x86,0xce,0xc6,0x4b, - 0x61,0x16 }; - - uint8_t aad[12] = { 0x50,0x51,0x52,0x53,0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7 }; - uint8_t nonce[12] = { 0x07,0x00,0x00,0x00,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47 }; - - uint8_t key[32] = { 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, - 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f }; - uint8_t tag[16] ; - uint8_t test_tag[16] = { 0x1a,0xe1,0x0b,0x59,0x4f,0x09,0xe2,0x6a,0x7e,0x90,0x2e,0xcb,0xd0,0x60,0x06,0x91 }; - - AEAD_chacha20_poly1305_rs(key,nonce,msg,7*16+2,aad,12,tag,true) ; - - if(!constant_time_memory_compare(msg,test_msg,7*16+2)) return false ; - if(!constant_time_memory_compare(tag,test_tag,16)) return false ; - - bool res = AEAD_chacha20_poly1305_rs(key,nonce,msg,7*16+2,aad,12,tag,false) ; - - if(!res) return false ; - } - std::cerr << " RFC7539 - 2.8.2 OK" << std::endl; - - - // RFC7539 - AEAD checking and decryption - // - { - uint8_t key[32] = { 0x1c,0x92,0x40,0xa5,0xeb,0x55,0xd3,0x8a,0xf3,0x33,0x88,0x86,0x04,0xf6,0xb5,0xf0, - 0x47,0x39,0x17,0xc1,0x40,0x2b,0x80,0x09,0x9d,0xca,0x5c,0xbc,0x20,0x70,0x75,0xc0 }; - - uint8_t nonce[12] = { 0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 }; - - uint8_t ciphertext[16*16 + 9] = { - 0x64,0xa0,0x86,0x15,0x75,0x86,0x1a,0xf4,0x60,0xf0,0x62,0xc7,0x9b,0xe6,0x43,0xbd, - 0x5e,0x80,0x5c,0xfd,0x34,0x5c,0xf3,0x89,0xf1,0x08,0x67,0x0a,0xc7,0x6c,0x8c,0xb2, - 0x4c,0x6c,0xfc,0x18,0x75,0x5d,0x43,0xee,0xa0,0x9e,0xe9,0x4e,0x38,0x2d,0x26,0xb0, - 0xbd,0xb7,0xb7,0x3c,0x32,0x1b,0x01,0x00,0xd4,0xf0,0x3b,0x7f,0x35,0x58,0x94,0xcf, - 0x33,0x2f,0x83,0x0e,0x71,0x0b,0x97,0xce,0x98,0xc8,0xa8,0x4a,0xbd,0x0b,0x94,0x81, - 0x14,0xad,0x17,0x6e,0x00,0x8d,0x33,0xbd,0x60,0xf9,0x82,0xb1,0xff,0x37,0xc8,0x55, - 0x97,0x97,0xa0,0x6e,0xf4,0xf0,0xef,0x61,0xc1,0x86,0x32,0x4e,0x2b,0x35,0x06,0x38, - 0x36,0x06,0x90,0x7b,0x6a,0x7c,0x02,0xb0,0xf9,0xf6,0x15,0x7b,0x53,0xc8,0x67,0xe4, - 0xb9,0x16,0x6c,0x76,0x7b,0x80,0x4d,0x46,0xa5,0x9b,0x52,0x16,0xcd,0xe7,0xa4,0xe9, - 0x90,0x40,0xc5,0xa4,0x04,0x33,0x22,0x5e,0xe2,0x82,0xa1,0xb0,0xa0,0x6c,0x52,0x3e, - 0xaf,0x45,0x34,0xd7,0xf8,0x3f,0xa1,0x15,0x5b,0x00,0x47,0x71,0x8c,0xbc,0x54,0x6a, - 0x0d,0x07,0x2b,0x04,0xb3,0x56,0x4e,0xea,0x1b,0x42,0x22,0x73,0xf5,0x48,0x27,0x1a, - 0x0b,0xb2,0x31,0x60,0x53,0xfa,0x76,0x99,0x19,0x55,0xeb,0xd6,0x31,0x59,0x43,0x4e, - 0xce,0xbb,0x4e,0x46,0x6d,0xae,0x5a,0x10,0x73,0xa6,0x72,0x76,0x27,0x09,0x7a,0x10, - 0x49,0xe6,0x17,0xd9,0x1d,0x36,0x10,0x94,0xfa,0x68,0xf0,0xff,0x77,0x98,0x71,0x30, - 0x30,0x5b,0xea,0xba,0x2e,0xda,0x04,0xdf,0x99,0x7b,0x71,0x4d,0x6c,0x6f,0x2c,0x29, - 0xa6,0xad,0x5c,0xb4,0x02,0x2b,0x02,0x70,0x9b }; - - uint8_t aad[12] = { 0xf3,0x33,0x88,0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x4e,0x91 }; - - uint8_t received_tag[16] = { 0xee,0xad,0x9d,0x67,0x89,0x0c,0xbb,0x22,0x39,0x23,0x36,0xfe,0xa1,0x85,0x1f,0x38 }; - - if(!AEAD_chacha20_poly1305_rs(key,nonce,ciphertext,16*16+9,aad,12,received_tag,false)) - return false ; - - uint8_t cleartext[16*16+9] = { - 0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x2d,0x44,0x72,0x61,0x66,0x74,0x73,0x20, - 0x61,0x72,0x65,0x20,0x64,0x72,0x61,0x66,0x74,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65, - 0x6e,0x74,0x73,0x20,0x76,0x61,0x6c,0x69,0x64,0x20,0x66,0x6f,0x72,0x20,0x61,0x20, - 0x6d,0x61,0x78,0x69,0x6d,0x75,0x6d,0x20,0x6f,0x66,0x20,0x73,0x69,0x78,0x20,0x6d, - 0x6f,0x6e,0x74,0x68,0x73,0x20,0x61,0x6e,0x64,0x20,0x6d,0x61,0x79,0x20,0x62,0x65, - 0x20,0x75,0x70,0x64,0x61,0x74,0x65,0x64,0x2c,0x20,0x72,0x65,0x70,0x6c,0x61,0x63, - 0x65,0x64,0x2c,0x20,0x6f,0x72,0x20,0x6f,0x62,0x73,0x6f,0x6c,0x65,0x74,0x65,0x64, - 0x20,0x62,0x79,0x20,0x6f,0x74,0x68,0x65,0x72,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65, - 0x6e,0x74,0x73,0x20,0x61,0x74,0x20,0x61,0x6e,0x79,0x20,0x74,0x69,0x6d,0x65,0x2e, - 0x20,0x49,0x74,0x20,0x69,0x73,0x20,0x69,0x6e,0x61,0x70,0x70,0x72,0x6f,0x70,0x72, - 0x69,0x61,0x74,0x65,0x20,0x74,0x6f,0x20,0x75,0x73,0x65,0x20,0x49,0x6e,0x74,0x65, - 0x72,0x6e,0x65,0x74,0x2d,0x44,0x72,0x61,0x66,0x74,0x73,0x20,0x61,0x73,0x20,0x72, - 0x65,0x66,0x65,0x72,0x65,0x6e,0x63,0x65,0x20,0x6d,0x61,0x74,0x65,0x72,0x69,0x61, - 0x6c,0x20,0x6f,0x72,0x20,0x74,0x6f,0x20,0x63,0x69,0x74,0x65,0x20,0x74,0x68,0x65, - 0x6d,0x20,0x6f,0x74,0x68,0x65,0x72,0x20,0x74,0x68,0x61,0x6e,0x20,0x61,0x73,0x20, - 0x2f,0xe2,0x80,0x9c,0x77,0x6f,0x72,0x6b,0x20,0x69,0x6e,0x20,0x70,0x72,0x6f,0x67, - 0x72,0x65,0x73,0x73,0x2e,0x2f,0xe2,0x80,0x9d } ; - - if(!constant_time_memory_compare(cleartext,ciphertext,16*16+9)) - return false ; - } - std::cerr << " RFC7539 AEAD test vector #1 OK" << std::endl; - - // bandwidth test - // - - { - uint32_t SIZE = 1*1024*1024 ; - uint8_t *ten_megabyte_data = (uint8_t*)malloc(SIZE) ; - - memset(ten_megabyte_data,0x37,SIZE) ; // put something. We dont really care here. - - uint8_t key[32] = { 0x1c,0x92,0x40,0xa5,0xeb,0x55,0xd3,0x8a,0xf3,0x33,0x88,0x86,0x04,0xf6,0xb5,0xf0, - 0x47,0x39,0x17,0xc1,0x40,0x2b,0x80,0x09,0x9d,0xca,0x5c,0xbc,0x20,0x70,0x75,0xc0 }; - - uint8_t nonce[12] = { 0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 }; - uint8_t aad[12] = { 0xf3,0x33,0x88,0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x4e,0x91 }; - - uint8_t received_tag[16] ; - - { - rstime::RsScopeTimer s("AEAD1") ; - chacha20_encrypt_rs(key, 1, nonce, ten_megabyte_data,SIZE) ; - - std::cerr << " Chacha20 encryption speed : " << SIZE / (1024.0*1024.0) / s.duration() << " MB/s" << std::endl; - } - { - rstime::RsScopeTimer s("AEAD2") ; - AEAD_chacha20_poly1305_rs(key,nonce,ten_megabyte_data,SIZE,aad,12,received_tag,true) ; - - std::cerr << " AEAD/poly1305 own encryption speed : " << SIZE / (1024.0*1024.0) / s.duration() << " MB/s" << std::endl; - } -#if OPENSSL_VERSION_NUMBER >= 0x010100000L && !defined(LIBRESSL_VERSION_NUMBER) - { - rstime::RsScopeTimer s("AEAD3") ; - AEAD_chacha20_poly1305_openssl(key,nonce,ten_megabyte_data,SIZE,aad,12,received_tag,true) ; - - std::cerr << " AEAD/poly1305 openssl encryption speed: " << SIZE / (1024.0*1024.0) / s.duration() << " MB/s" << std::endl; - } -#endif - { - rstime::RsScopeTimer s("AEAD4") ; - AEAD_chacha20_sha256(key,nonce,ten_megabyte_data,SIZE,aad,12,received_tag,true) ; - - std::cerr << " AEAD/sha256 encryption speed : " << SIZE / (1024.0*1024.0) / s.duration() << " MB/s" << std::endl; - } - - free(ten_megabyte_data) ; - } - - return true; -} - -} -} - - diff --git a/libretroshare/src/crypto/chacha20.h b/libretroshare/src/crypto/chacha20.h deleted file mode 100644 index 1b19a1402..000000000 --- a/libretroshare/src/crypto/chacha20.h +++ /dev/null @@ -1,113 +0,0 @@ -/******************************************************************************* - * libretroshare/src/crypto: chacha20.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2016 by Mr.Alice * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include - -namespace librs -{ - namespace crypto - { - /*! - * \brief chacha20_encrypt - * Performs in place encryption/decryption of the supplied data, using chacha20, using the supplied key and nonce. - * - * \param key secret encryption key. *Should never* be re-used. - * \param block_counter any integer. 0 is fine. - * \param nonce acts as an initialzation vector. /!\ it is extremely important to make sure that this nounce *is* everytime different. Using a purely random value is fine. - * \param data data that gets encrypted/decrypted in place - * \param size size of the data. - */ - void chacha20_encrypt(uint8_t key[32], uint32_t block_counter, uint8_t nonce[12], uint8_t *data, uint32_t size) ; - - /*! - * \brief poly1305_tag - * Computes an authentication tag for the supplied data, using the given secret key. - * \param key secret key. *Should not* be used multiple times. - * \param message message to generate a tag for - * \param size size of the message - * \param tag place where the tag is stored. - */ - - void poly1305_tag(uint8_t key[32],uint8_t *message,uint32_t size,uint8_t tag[16]); - - /*! - * \brief AEAD_chacha20_poly1305 - * Provides in-place authenticated encryption using the AEAD construction as described in RFC7539. - * The data is first encrypted in place then 16-padded and concatenated to its size, than concatenated to the - * 16-padded AAD (additional authenticated data) and its size, authenticated using poly1305. - * - * \param key key that is used to derive a one time secret key for poly1305 and that is also used to encrypt the data - * \param nonce nonce. *Should be unique* in order to make the chacha20 stream cipher unique. - * \param data data that is encrypted/decrypted in place. - * \param size size of the data - * \param aad additional authenticated data. Can be used to authenticate the nonce. - * \param aad_size - * \param tag generated poly1305 tag. - * \param encrypt true to encrypt, false to decrypt and check the tag. - * \return - * always true for encryption. - * authentication result for decryption. data is *always* xored to the cipher stream whatever the authentication result is. - */ - bool AEAD_chacha20_poly1305(uint8_t key[32], uint8_t nonce[12],uint8_t *data,uint32_t data_size,uint8_t *aad,uint32_t aad_size,uint8_t tag[16],bool encrypt_or_decrypt) ; - - /*! - * \brief AEAD_chacha20_sha256 - * Provides authenticated encryption using a simple construction that associates chacha20 encryption with HMAC authentication using - * the same 32 bytes key. The authenticated tag is the 16 first bytes of the sha256 HMAC. - * - * \param key encryption/authentication key - * \param nonce nonce. *Should be unique* in order to make chacha20 stream cipher unique. - * \param data data that is encrypted/decrypted in place - * \param data_size size of data to encrypt/authenticate - * \param aad additional authenticated data. Can be used to authenticate the nonce. - * \param aad_size - * \param tag 16 bytes authentication tag result - * \param encrypt true to encrypt, false to decrypt and check the tag. - * \return - * always true for encryption. - * authentication result for decryption. data is *always* xored to the cipher stream whatever the authentication result is. - */ - bool AEAD_chacha20_sha256(uint8_t key[32], uint8_t nonce[12],uint8_t *data,uint32_t data_size,uint8_t *aad,uint32_t aad_size,uint8_t tag[16],bool encrypt_or_decrypt) ; - - /*! - * \brief constant_time_memcmp - * Provides a constant time comparison of two memory chunks. Calls CRYPTO_memcmp. - * - * \param m1 memory block 1 - * \param m2 memory block 2 - * \param size common size of m1 and m2 - * \return - * false if the two chunks are different - * true if the two chunks are identical - */ - bool constant_time_memory_compare(const uint8_t *m1,const uint8_t *m2,uint32_t size) ; - - /*! - * \brief perform_tests - * Tests all methods in this class, using the tests supplied in RFC7539 - * \return - * true is all tests pass - */ - - bool perform_tests() ; - } -} diff --git a/libretroshare/src/crypto/hashstream.cc b/libretroshare/src/crypto/hashstream.cc deleted file mode 100644 index e1c39a60c..000000000 --- a/libretroshare/src/crypto/hashstream.cc +++ /dev/null @@ -1,105 +0,0 @@ -/******************************************************************************* - * libretroshare/src/crypto: hashstream.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 by Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "hashstream.h" - -#include -#include -#include -#include - -namespace librs -{ - namespace crypto - { - HashStream::HashStream(HashType t) - { - assert(t == SHA1) ; - - mdctx = EVP_MD_CTX_create(); - EVP_DigestInit_ex(mdctx,EVP_sha1(),NULL); - } - HashStream::~HashStream() - { - if(mdctx) - EVP_MD_CTX_destroy(mdctx) ; - } - - Sha1CheckSum HashStream::hash() - { - uint8_t h[EVP_MAX_MD_SIZE] ; - unsigned int len; - EVP_DigestFinal_ex(mdctx,h,&len) ; - - EVP_MD_CTX_destroy(mdctx) ; - mdctx=NULL ; - - return Sha1CheckSum(h); - } - template<> - HashStream& operator<<(HashStream& u,const std::pair& p) - { - EVP_DigestUpdate(u.mdctx,p.first,p.second) ; - return u; - } - template<> - HashStream& operator<<(HashStream& u,const std::string& s) - { - EVP_DigestUpdate(u.mdctx,s.c_str(),s.length()) ; - return u; - } - template<> - HashStream& operator<<(HashStream& u,const uint64_t& n) - { - unsigned char mem[8] ; - uint64_t s(n); - for(int i=0;i<8;++i) - { - mem[i] = (uint8_t)s; - s <<= 8 ; - } - - EVP_DigestUpdate(u.mdctx,mem,8); - return u; - } - template<> - HashStream& operator<<(HashStream& u,const uint32_t& n) - { - unsigned char mem[4] ; - uint64_t s(n); - for(int i=0;i<4;++i) - { - mem[i] = (uint8_t)s; - s <<= 8 ; - } - - EVP_DigestUpdate(u.mdctx,mem,4); - return u; - } - template<> - HashStream& operator<<(HashStream& u,const uint8_t& n) - { - EVP_DigestUpdate(u.mdctx,&n,1); - return u; - } - - } -} diff --git a/libretroshare/src/crypto/hashstream.h b/libretroshare/src/crypto/hashstream.h deleted file mode 100644 index b303b6509..000000000 --- a/libretroshare/src/crypto/hashstream.h +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************************* - * libretroshare/src/crypto: hashstream.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 by Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include - -namespace librs -{ - namespace crypto - { - // Forward declare the class - class HashStream; - // Forward declare the template operator - template HashStream& operator<<(HashStream& u, const T&); - - class HashStream - { - public: - enum HashType { UNKNOWN = 0x00, - SHA1 = 0x01 - }; - - HashStream(HashType t); - ~HashStream(); - - Sha1CheckSum hash() ; - - template friend HashStream& operator<<(HashStream& u, const T&) ; - - template - friend HashStream& operator<<(HashStream& u, const t_RsGenericIdType& r) - { - EVP_DigestUpdate(u.mdctx, r.toByteArray(), ID_SIZE_IN_BYTES); - return u; - } - private: - EVP_MD_CTX *mdctx ; - }; - } -} diff --git a/libretroshare/src/crypto/rsaes.cc b/libretroshare/src/crypto/rsaes.cc deleted file mode 100644 index d5ad2c7a0..000000000 --- a/libretroshare/src/crypto/rsaes.cc +++ /dev/null @@ -1,144 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsaes.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013-2013 Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include -#include -#include - -#include "rsaes.h" - -uint32_t RsAES::get_buffer_size(uint32_t n) -{ - return n + AES_BLOCK_SIZE ; -} - -bool RsAES::aes_crypt_8_16(const uint8_t *input_data,uint32_t input_data_length,uint8_t key_data[16],uint8_t salt[8],uint8_t *output_data,uint32_t& output_data_length) -{ - int nrounds = 5; - uint8_t key[32], iv[32]; - - /* - * Gen key & IV for AES 256 CBC mode. A SHA1 digest is used to hash the supplied key material. - * nrounds is the number of times the we hash the material. More rounds are more secure but - * slower. - */ - int i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), salt, key_data, 16, nrounds, key, iv); - - if (i != 32) - { - printf("Key size is %d bits - should be 256 bits\n", i); - return false ; - } - - EVP_CIPHER_CTX *e_ctx = EVP_CIPHER_CTX_new(); - EVP_EncryptInit_ex(e_ctx, EVP_aes_256_cbc(), NULL, key, iv); - - /* max ciphertext len for a n bytes of plaintext is n + AES_BLOCK_SIZE -1 bytes */ - int c_len = input_data_length + AES_BLOCK_SIZE ; - int f_len = 0; - - if(output_data_length < (uint32_t)c_len) - { - EVP_CIPHER_CTX_free(e_ctx) ; - return false ; - } - - /* update ciphertext, c_len is filled with the length of ciphertext generated, - *len is the size of plaintext in bytes */ - - if(!EVP_EncryptUpdate(e_ctx, output_data, &c_len, input_data, input_data_length)) - { - std::cerr << "RsAES: decryption failed at end. Check padding." << std::endl; - EVP_CIPHER_CTX_free(e_ctx) ; - return false ; - } - - /* update ciphertext with the final remaining bytes */ - if(!EVP_EncryptFinal_ex(e_ctx, output_data+c_len, &f_len)) - { - std::cerr << "RsAES: decryption failed at end. Check padding." << std::endl; - EVP_CIPHER_CTX_free(e_ctx) ; - return false ; - } - - output_data_length = c_len + f_len; - - EVP_CIPHER_CTX_free(e_ctx) ; - return true; -} - -bool RsAES::aes_decrypt_8_16(const uint8_t *input_data,uint32_t input_data_length,uint8_t key_data[16],uint8_t salt[8],uint8_t *output_data,uint32_t& output_data_length) -{ - int nrounds = 5; - uint8_t key[32], iv[32]; - - /* - * Gen key & IV for AES 256 CBC mode. A SHA1 digest is used to hash the supplied key material. - * nrounds is the number of times the we hash the material. More rounds are more secure but - * slower. - */ - int i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), salt, key_data, 16, nrounds, key, iv); - - if (i != 32) - { - printf("Key size is %d bits - should be 256 bits\n", i); - return false ; - } - - EVP_CIPHER_CTX *e_ctx = EVP_CIPHER_CTX_new(); - EVP_DecryptInit_ex(e_ctx, EVP_aes_256_cbc(), NULL, key, iv); - - /* max ciphertext len for a n bytes of plaintext is n + AES_BLOCK_SIZE -1 bytes */ - int c_len = input_data_length + AES_BLOCK_SIZE ; - int f_len = 0; - - if(output_data_length < (uint32_t)c_len) - { - EVP_CIPHER_CTX_free(e_ctx) ; - return false ; - } - - output_data_length = c_len ; - - /* update ciphertext, c_len is filled with the length of ciphertext generated, - *len is the size of plaintext in bytes */ - - if(! EVP_DecryptUpdate(e_ctx, output_data, &c_len, input_data, input_data_length)) - { - std::cerr << "RsAES: decryption failed." << std::endl; - EVP_CIPHER_CTX_free(e_ctx) ; - return false ; - } - - /* update ciphertext with the final remaining bytes */ - if(!EVP_DecryptFinal_ex(e_ctx, output_data+c_len, &f_len)) - { - std::cerr << "RsAES: decryption failed at end. Check padding." << std::endl; - EVP_CIPHER_CTX_free(e_ctx) ; - return false ; - } - - output_data_length = c_len + f_len; - - EVP_CIPHER_CTX_free(e_ctx) ; - return true; -} - diff --git a/libretroshare/src/crypto/rsaes.h b/libretroshare/src/crypto/rsaes.h deleted file mode 100644 index d4592793d..000000000 --- a/libretroshare/src/crypto/rsaes.h +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsaes.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013-2013 Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include - -class RsAES -{ - public: - // Crypt/decrypt data using a 16 bytes key and a 8 bytes salt. - // - // output_data allocation is left to the client. The size should be at least RsAES::get_buffer_size(input_data_length) - // - // Return value: - // true: encryption/decryption ok - // - // false: encryption/decryption went bad. Check buffer size. - // - static bool aes_crypt_8_16(const uint8_t *input_data,uint32_t input_data_length,uint8_t key[16],uint8_t salt[8],uint8_t *output_data,uint32_t& output_data_length) ; - static bool aes_decrypt_8_16(const uint8_t *input_data,uint32_t input_data_length,uint8_t key[16],uint8_t salt[8],uint8_t *output_data,uint32_t& output_data_length) ; - - // computes the safe buffer size to store encrypted/decrypted data for the given input stream size - // - static uint32_t get_buffer_size(uint32_t size) ; -}; - diff --git a/libretroshare/src/crypto/rscrypto.cpp b/libretroshare/src/crypto/rscrypto.cpp deleted file mode 100644 index 0a296673e..000000000 --- a/libretroshare/src/crypto/rscrypto.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/******************************************************************************* - * libretroshare/src/crypto: crypto.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include -#include -#include - -#include "rscrypto.h" -#include "util/rsrandom.h" - -//#define CRYPTO_DEBUG 1 - -namespace librs { -namespace crypto { - -#define RSCRYPTO_DEBUG() std::cerr << time(NULL) << " : RSCRYPTO : " << __FUNCTION__ << " : " -#define RSCRYPTO_ERROR() std::cerr << "(EE) RSCRYPTO ERROR : " - -static const uint32_t ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE = 12 ; -static const uint32_t ENCRYPTED_MEMORY_AUTHENTICATION_TAG_SIZE = 16 ; -static const uint32_t ENCRYPTED_MEMORY_HEADER_SIZE = 4 ; -static const uint32_t ENCRYPTED_MEMORY_EDATA_SIZE = 4 ; - -static const uint8_t ENCRYPTED_MEMORY_FORMAT_AEAD_CHACHA20_POLY1305 = 0x01 ; -static const uint8_t ENCRYPTED_MEMORY_FORMAT_AEAD_CHACHA20_SHA256 = 0x02 ; - -bool encryptAuthenticateData(const unsigned char *clear_data,uint32_t clear_data_size,uint8_t *encryption_master_key,unsigned char *& encrypted_data,uint32_t& encrypted_data_len) -{ - uint8_t initialization_vector[ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE] ; - - RSRandom::random_bytes(initialization_vector,ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE) ; - -#ifdef CRYPTO_DEBUG - RSCRYPTO_DEBUG() << "ftServer::Encrypting ft item." << std::endl; - RSCRYPTO_DEBUG() << " random nonce : " << RsUtil::BinToHex(initialization_vector,ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE) << std::endl; -#endif - - uint32_t item_serialized_size = clear_data_size;//RsGenericSerializer().size(clear_item) ; - uint32_t total_data_size = ENCRYPTED_MEMORY_HEADER_SIZE + ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_MEMORY_EDATA_SIZE + item_serialized_size + ENCRYPTED_MEMORY_AUTHENTICATION_TAG_SIZE ; - -#ifdef CRYPTO_DEBUG - RSCRYPTO_DEBUG() << " clear part size : " << size(clear_item) << std::endl; - RSCRYPTO_DEBUG() << " total item size : " << total_data_size << std::endl; -#endif - - encrypted_data = (unsigned char*)rs_malloc( total_data_size ) ; - encrypted_data_len = total_data_size ; - - if(encrypted_data == NULL) - return false ; - - uint8_t *edata = (uint8_t*)encrypted_data; - uint32_t edata_size = item_serialized_size; - uint32_t offset = 0; - - edata[0] = 0xae ; - edata[1] = 0xad ; - edata[2] = ENCRYPTED_MEMORY_FORMAT_AEAD_CHACHA20_SHA256 ; // means AEAD_chacha20_sha256 - edata[3] = 0x01 ; - - offset += ENCRYPTED_MEMORY_HEADER_SIZE; - uint32_t aad_offset = offset ; - uint32_t aad_size = ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_MEMORY_EDATA_SIZE ; - - memcpy(&edata[offset], initialization_vector, ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE) ; - offset += ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE ; - - edata[offset+0] = (edata_size >> 0) & 0xff ; - edata[offset+1] = (edata_size >> 8) & 0xff ; - edata[offset+2] = (edata_size >> 16) & 0xff ; - edata[offset+3] = (edata_size >> 24) & 0xff ; - - offset += ENCRYPTED_MEMORY_EDATA_SIZE ; - - memcpy(&edata[offset],clear_data,clear_data_size); - -#ifdef CRYPTO_DEBUG - RSCRYPTO_DEBUG() << " clear item : " << RsUtil::BinToHex(&edata[offset],std::min(50,(int)total_data_size-(int)offset)) << "(...)" << std::endl; -#endif - - uint32_t clear_item_offset = offset ; - offset += edata_size ; - - uint32_t authentication_tag_offset = offset ; - assert(ENCRYPTED_MEMORY_AUTHENTICATION_TAG_SIZE + offset == total_data_size) ; - - //uint8_t encryption_key[32] ; - //deriveEncryptionKey(hash,encryption_key) ; - - if(edata[2] == ENCRYPTED_MEMORY_FORMAT_AEAD_CHACHA20_POLY1305) - librs::crypto::AEAD_chacha20_poly1305(encryption_master_key,initialization_vector,&edata[clear_item_offset],edata_size, &edata[aad_offset],aad_size, &edata[authentication_tag_offset],true) ; - else if(edata[2] == ENCRYPTED_MEMORY_FORMAT_AEAD_CHACHA20_SHA256) - librs::crypto::AEAD_chacha20_sha256 (encryption_master_key,initialization_vector,&edata[clear_item_offset],edata_size, &edata[aad_offset],aad_size, &edata[authentication_tag_offset],true) ; - else - return false ; - -#ifdef CRYPTO_DEBUG - RSCRYPTO_DEBUG() << " encryption key : " << RsUtil::BinToHex(encryption_key,32) << std::endl; - RSCRYPTO_DEBUG() << " authen. tag : " << RsUtil::BinToHex(&edata[authentication_tag_offset],ENCRYPTED_MEMORY_AUTHENTICATION_TAG_SIZE) << std::endl; - RSCRYPTO_DEBUG() << " final item : " << RsUtil::BinToHex(&edata[0],std::min(50u,total_data_size)) << "(...)" << std::endl; -#endif - - return true ; -} - -// Decrypts the given item using aead-chacha20-poly1305 -bool decryptAuthenticateData(const unsigned char *encrypted_data,uint32_t encrypted_data_len,uint8_t *encryption_master_key, unsigned char *& decrypted_data, uint32_t& decrypted_data_size) -{ - //uint8_t encryption_key[32] ; - //deriveEncryptionKey(hash,encryption_key) ; - - uint8_t *edata = (uint8_t*)encrypted_data; - uint32_t offset = 0; - - if(encrypted_data_len < ENCRYPTED_MEMORY_HEADER_SIZE + ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_MEMORY_EDATA_SIZE) return false ; - - if(edata[0] != 0xae) return false ; - if(edata[1] != 0xad) return false ; - if(edata[2] != ENCRYPTED_MEMORY_FORMAT_AEAD_CHACHA20_POLY1305 && edata[2] != ENCRYPTED_MEMORY_FORMAT_AEAD_CHACHA20_SHA256) return false ; - if(edata[3] != 0x01) return false ; - - offset += ENCRYPTED_MEMORY_HEADER_SIZE ; - uint32_t aad_offset = offset ; - uint32_t aad_size = ENCRYPTED_MEMORY_EDATA_SIZE + ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE ; - - uint8_t *initialization_vector = &edata[offset] ; - -#ifdef CRYPTO_DEBUG - RSCRYPTO_DEBUG() << "ftServer::decrypting ft item." << std::endl; - RSCRYPTO_DEBUG() << " item data : " << RsUtil::BinToHex(edata,std::min(50u,encrypted_data_len) << "(...)" << std::endl; - RSCRYPTO_DEBUG() << " hash : " << hash << std::endl; - RSCRYPTO_DEBUG() << " encryption key : " << RsUtil::BinToHex(encryption_key,32) << std::endl; - RSCRYPTO_DEBUG() << " random nonce : " << RsUtil::BinToHex(initialization_vector,ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE) << std::endl; -#endif - - offset += ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE ; - - uint32_t edata_size = 0 ; - edata_size += ((uint32_t)edata[offset+0]) << 0 ; - edata_size += ((uint32_t)edata[offset+1]) << 8 ; - edata_size += ((uint32_t)edata[offset+2]) << 16 ; - edata_size += ((uint32_t)edata[offset+3]) << 24 ; - - if(edata_size + ENCRYPTED_MEMORY_EDATA_SIZE + ENCRYPTED_MEMORY_AUTHENTICATION_TAG_SIZE + ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_MEMORY_HEADER_SIZE != encrypted_data_len) - { - RSCRYPTO_ERROR() << " ERROR: encrypted data size is " << edata_size << ", should be " << encrypted_data_len - (ENCRYPTED_MEMORY_EDATA_SIZE + ENCRYPTED_MEMORY_AUTHENTICATION_TAG_SIZE + ENCRYPTED_MEMORY_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_MEMORY_HEADER_SIZE ) << std::endl; - return false ; - } - - offset += ENCRYPTED_MEMORY_EDATA_SIZE ; - uint32_t clear_item_offset = offset ; - - uint32_t authentication_tag_offset = offset + edata_size ; -#ifdef CRYPTO_DEBUG - RSCRYPTO_DEBUG() << " authen. tag : " << RsUtil::BinToHex(&edata[authentication_tag_offset],ENCRYPTED_MEMORY_AUTHENTICATION_TAG_SIZE) << std::endl; -#endif - - bool result ; - - if(edata[2] == ENCRYPTED_MEMORY_FORMAT_AEAD_CHACHA20_POLY1305) - result = librs::crypto::AEAD_chacha20_poly1305(encryption_master_key,initialization_vector,&edata[clear_item_offset],edata_size, &edata[aad_offset],aad_size, &edata[authentication_tag_offset],false) ; - else if(edata[2] == ENCRYPTED_MEMORY_FORMAT_AEAD_CHACHA20_SHA256) - result = librs::crypto::AEAD_chacha20_sha256 (encryption_master_key,initialization_vector,&edata[clear_item_offset],edata_size, &edata[aad_offset],aad_size, &edata[authentication_tag_offset],false) ; - else - return false ; - -#ifdef CRYPTO_DEBUG - RSCRYPTO_DEBUG() << " authen. result : " << result << std::endl; - RSCRYPTO_DEBUG() << " decrypted daya : " << RsUtil::BinToHex(&edata[clear_item_offset],std::min(50u,edata_size)) << "(...)" << std::endl; -#endif - - if(!result) - { - RSCRYPTO_ERROR() << "(EE) decryption/authentication went wrong." << std::endl; - return false ; - } - - decrypted_data_size = edata_size ; - decrypted_data = (unsigned char*)rs_malloc(edata_size) ; - - if(decrypted_data == NULL) - { - std::cerr << "Failed to allocate memory for decrypted data chunk of size " << edata_size << std::endl; - return false ; - } - memcpy(decrypted_data,&edata[clear_item_offset],edata_size) ; - - return true ; -} - -} -} - diff --git a/libretroshare/src/crypto/rscrypto.h b/libretroshare/src/crypto/rscrypto.h deleted file mode 100644 index 9666aed28..000000000 --- a/libretroshare/src/crypto/rscrypto.h +++ /dev/null @@ -1,59 +0,0 @@ - -/******************************************************************************* - * libretroshare/src/crypto: crypto.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "crypto/chacha20.h" - -namespace librs -{ -namespace crypto -{ -/*! - * \brief encryptAuthenticateData - Encrypts/decrypts data, using a autenticated construction + chacha20, based on a given 32 bytes master key. The actual encryption using a randomized key - based on a 96 bits IV. Input values are not touched (memory is not released). Memory ownership of outputs is left to the client. - * \param clear_data input data to encrypt - * \param clear_data_size length of input data - * \param encryption_master_key encryption master key of length 32 bytes. - * \param encrypted_data encrypted data, allocated using malloc - * \param encrypted_data_len length of encrypted data - * \return - * true if everything went well. - */ -bool encryptAuthenticateData(const unsigned char *clear_data,uint32_t clear_data_size,uint8_t *encryption_master_key,unsigned char *& encrypted_data,uint32_t& encrypted_data_size); - -/*! - * \brief decryptAuthenticateData - Encrypts/decrypts data, using a autenticated construction + chacha20, based on a given 32 bytes master key. The actual encryption using a randomized key - based on a 96 bits IV. Input values are not touched (memory is not released). Memory ownership of outputs is left to the client. - * \param encrypted_data input encrypted data - * \param encrypted_data_size input encrypted data length - * \param encryption_master_key encryption master key of length 32 bytes. - * \param decrypted_data decrypted data, allocated using malloc. - * \param decrypted_data_size length of allocated decrypted data. - * \return - * true if decryption + authentication are ok. - */ -bool decryptAuthenticateData(const unsigned char *encrypted_data,uint32_t encrypted_data_size, uint8_t* encryption_master_key, unsigned char *& decrypted_data,uint32_t& decrypted_data_size); -} -} - diff --git a/libretroshare/src/deep_search/channelsindex.cpp b/libretroshare/src/deep_search/channelsindex.cpp deleted file mode 100644 index cd1c374fc..000000000 --- a/libretroshare/src/deep_search/channelsindex.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/******************************************************************************* - * RetroShare full text indexing and search implementation based on Xapian * - * * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * Copyright (C) 2019 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License version 3 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "deep_search/channelsindex.hpp" -#include "deep_search/commonutils.hpp" - -uint32_t DeepChannelsIndex::search( - const std::string& queryStr, - std::vector& results, uint32_t maxResults ) -{ - results.clear(); - - std::unique_ptr dbPtr( - DeepSearch::openReadOnlyDatabase(dbPath()) ); - if(!dbPtr) return 0; - - Xapian::Database& db(*dbPtr); - - // Set up a QueryParser with a stemmer and suitable prefixes. - Xapian::QueryParser queryparser; - //queryparser.set_stemmer(Xapian::Stem("en")); - queryparser.set_stemming_strategy(queryparser.STEM_SOME); - // Start of prefix configuration. - //queryparser.add_prefix("title", "S"); - //queryparser.add_prefix("description", "XD"); - // End of prefix configuration. - - // And parse the query. - Xapian::Query query = queryparser.parse_query(queryStr); - - // Use an Enquire object on the database to run the query. - Xapian::Enquire enquire(db); - enquire.set_query(query); - - Xapian::MSet mset = enquire.get_mset( - 0, maxResults ? maxResults : db.get_doccount() ); - - for ( Xapian::MSetIterator m = mset.begin(); m != mset.end(); ++m ) - { - const Xapian::Document& doc = m.get_document(); - DeepChannelsSearchResult s; - s.mUrl = doc.get_value(URL_VALUENO); -#if XAPIAN_AT_LEAST(1,3,5) - s.mSnippet = mset.snippet(doc.get_data()); -#endif // XAPIAN_AT_LEAST(1,3,5) - results.push_back(s); - } - - return static_cast(results.size()); -} - -void DeepChannelsIndex::indexChannelGroup(const RsGxsChannelGroup& chan) -{ - std::unique_ptr dbPtr( - DeepSearch::openWritableDatabase( - dbPath(), Xapian::DB_CREATE_OR_OPEN ) ); - if(!dbPtr) return; - - Xapian::WritableDatabase& db(*dbPtr); - - // Set up a TermGenerator that we'll use in indexing. - Xapian::TermGenerator termgenerator; - //termgenerator.set_stemmer(Xapian::Stem("en")); - - // We make a document and tell the term generator to use this. - Xapian::Document doc; - termgenerator.set_document(doc); - - // Index each field with a suitable prefix. - termgenerator.index_text(chan.mMeta.mGroupName, 1, "G"); - termgenerator.index_text( - DeepSearch::timetToXapianDate(chan.mMeta.mPublishTs), 1, "D" ); - termgenerator.index_text(chan.mDescription, 1, "XD"); - - // Index fields without prefixes for general search. - termgenerator.index_text(chan.mMeta.mGroupName); - termgenerator.increase_termpos(); - termgenerator.index_text(chan.mDescription); - - RsUrl chanUrl; chanUrl - .setScheme("retroshare").setPath("/channel") - .setQueryKV("id", chan.mMeta.mGroupId.toStdString()); - const std::string idTerm("Q" + chanUrl.toString()); - - chanUrl.setQueryKV("publishTs", std::to_string(chan.mMeta.mPublishTs)); - chanUrl.setQueryKV("name", chan.mMeta.mGroupName); - if(!chan.mMeta.mAuthorId.isNull()) - chanUrl.setQueryKV("authorId", chan.mMeta.mAuthorId.toStdString()); - if(chan.mMeta.mSignFlags) - chanUrl.setQueryKV( "signFlags", - std::to_string(chan.mMeta.mSignFlags) ); - std::string rsLink(chanUrl.toString()); - - // store the RS link so we are able to retrive it on matching search - doc.add_value(URL_VALUENO, rsLink); - - // Store some fields for display purposes. - doc.set_data(chan.mMeta.mGroupName + "\n" + chan.mDescription); - - // We use the identifier to ensure each object ends up in the - // database only once no matter how many times we run the - // indexer. "Q" prefix is a Xapian convention for unique id term. - doc.add_boolean_term(idTerm); - db.replace_document(idTerm, doc); -} - -void DeepChannelsIndex::removeChannelFromIndex(RsGxsGroupId grpId) -{ - // "Q" prefix is a Xapian convention for unique id term. - RsUrl chanUrl; chanUrl - .setScheme("retroshare").setPath("/channel") - .setQueryKV("id", grpId.toStdString()); - std::string idTerm("Q" + chanUrl.toString()); - - std::unique_ptr dbPtr( - DeepSearch::openWritableDatabase( - dbPath(), Xapian::DB_CREATE_OR_OPEN ) ); - if(!dbPtr) return; - - Xapian::WritableDatabase& db(*dbPtr); - db.delete_document(idTerm); -} - -void DeepChannelsIndex::indexChannelPost(const RsGxsChannelPost& post) -{ - std::unique_ptr dbPtr( - DeepSearch::openWritableDatabase( - dbPath(), Xapian::DB_CREATE_OR_OPEN ) ); - if(!dbPtr) return; - - Xapian::WritableDatabase& db(*dbPtr); - - // Set up a TermGenerator that we'll use in indexing. - Xapian::TermGenerator termgenerator; - //termgenerator.set_stemmer(Xapian::Stem("en")); - - // We make a document and tell the term generator to use this. - Xapian::Document doc; - termgenerator.set_document(doc); - - // Index each field with a suitable prefix. - termgenerator.index_text(post.mMeta.mMsgName, 1, "S"); - termgenerator.index_text( - DeepSearch::timetToXapianDate(post.mMeta.mPublishTs), 1, "D" ); - - // TODO: we should strip out HTML tags instead of skipping indexing - // Avoid indexing HTML - bool isPlainMsg = - post.mMsg[0] != '<' || post.mMsg[post.mMsg.size() - 1] != '>'; - - if(isPlainMsg) - termgenerator.index_text(post.mMsg, 1, "XD"); - - // Index fields without prefixes for general search. - termgenerator.index_text(post.mMeta.mMsgName); - if(isPlainMsg) - { - termgenerator.increase_termpos(); - termgenerator.index_text(post.mMsg); - } - - for(const RsGxsFile& attachment : post.mFiles) - { - termgenerator.index_text(attachment.mName, 1, "F"); - - termgenerator.increase_termpos(); - termgenerator.index_text(attachment.mName); - } - - // We use the identifier to ensure each object ends up in the - // database only once no matter how many times we run the - // indexer. - RsUrl postUrl; postUrl - .setScheme("retroshare").setPath("/channel") - .setQueryKV("id", post.mMeta.mGroupId.toStdString()) - .setQueryKV("msgid", post.mMeta.mMsgId.toStdString()); - std::string idTerm("Q" + postUrl.toString()); - - postUrl.setQueryKV("publishTs", std::to_string(post.mMeta.mPublishTs)); - postUrl.setQueryKV("name", post.mMeta.mMsgName); - postUrl.setQueryKV("authorId", post.mMeta.mAuthorId.toStdString()); - std::string rsLink(postUrl.toString()); - - // store the RS link so we are able to retrive it on matching search - doc.add_value(URL_VALUENO, rsLink); - - // Store some fields for display purposes. - if(isPlainMsg) - doc.set_data(post.mMeta.mMsgName + "\n" + post.mMsg); - else doc.set_data(post.mMeta.mMsgName); - - doc.add_boolean_term(idTerm); - db.replace_document(idTerm, doc); -} - -void DeepChannelsIndex::removeChannelPostFromIndex( - RsGxsGroupId grpId, RsGxsMessageId msgId ) -{ - RsUrl postUrl; postUrl - .setScheme("retroshare").setPath("/channel") - .setQueryKV("id", grpId.toStdString()) - .setQueryKV("msgid", msgId.toStdString()); - // "Q" prefix is a Xapian convention for unique id term. - std::string idTerm("Q" + postUrl.toString()); - - std::unique_ptr dbPtr( - DeepSearch::openWritableDatabase( - dbPath(), Xapian::DB_CREATE_OR_OPEN ) ); - if(!dbPtr) return; - - Xapian::WritableDatabase& db(*dbPtr); - db.delete_document(idTerm); -} diff --git a/libretroshare/src/deep_search/channelsindex.hpp b/libretroshare/src/deep_search/channelsindex.hpp deleted file mode 100644 index 0a49629d9..000000000 --- a/libretroshare/src/deep_search/channelsindex.hpp +++ /dev/null @@ -1,77 +0,0 @@ -/******************************************************************************* - * RetroShare full text indexing and search implementation based on Xapian * - * * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * Copyright (C) 2019 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License version 3 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include - -#include "util/rstime.h" -#include "retroshare/rsgxschannels.h" -#include "retroshare/rsinit.h" -#include "util/rsurl.h" - -struct DeepChannelsSearchResult -{ - std::string mUrl; - double mWeight; - std::string mSnippet; -}; - -struct DeepChannelsIndex -{ - /** - * @brief Search indexed GXS groups and messages - * @param[in] maxResults maximum number of acceptable search results, 0 for - * no limits - * @return search results count - */ - static uint32_t search( const std::string& queryStr, - std::vector& results, - uint32_t maxResults = 100 ); - - static void indexChannelGroup(const RsGxsChannelGroup& chan); - - static void removeChannelFromIndex(RsGxsGroupId grpId); - - static void indexChannelPost(const RsGxsChannelPost& post); - - static void removeChannelPostFromIndex( - RsGxsGroupId grpId, RsGxsMessageId msgId ); - - static uint32_t indexFile(const std::string& path); - -private: - - enum : Xapian::valueno - { - /// Used to store retroshare url of indexed documents - URL_VALUENO, - - /// @see Xapian::BAD_VALUENO - BAD_VALUENO = Xapian::BAD_VALUENO - }; - - static const std::string& dbPath() - { - static const std::string dbDir = - RsAccounts::AccountDirectory() + "/deep_channels_xapian_db"; - return dbDir; - } -}; diff --git a/libretroshare/src/deep_search/commonutils.cpp b/libretroshare/src/deep_search/commonutils.cpp deleted file mode 100644 index e8e1e4b59..000000000 --- a/libretroshare/src/deep_search/commonutils.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/******************************************************************************* - * RetroShare full text indexing and search implementation based on Xapian * - * * - * Copyright (C) 2018-2021 Gioacchino Mazzurco * - * Copyright (C) 2019-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License version 3 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include -#include - -#include "deep_search/commonutils.hpp" -#include "util/stacktrace.h" -#include "util/rsthreads.h" -#include "util/rsdebuglevel0.h" - -#ifndef XAPIAN_AT_LEAST -/// Added in Xapian 1.4.2. -#define XAPIAN_AT_LEAST(A,B,C) \ - (XAPIAN_MAJOR_VERSION > (A) || \ - (XAPIAN_MAJOR_VERSION == (A) && \ - (XAPIAN_MINOR_VERSION > (B) || \ - (XAPIAN_MINOR_VERSION == (B) && XAPIAN_REVISION >= (C))))) -#endif - -namespace DeepSearch -{ -std::unique_ptr openReadOnlyDatabase( - const std::string& path, int flags ) -{ - try - { -#if XAPIAN_AT_LEAST(1,3,2) - std::unique_ptr dbPtr( - new Xapian::Database(path, flags) ); -#else - std::unique_ptr dbPtr(new Xapian::Database(path)); - if(flags) - { - RS_WARN( "Xapian DB flags: ", flags, " ignored due to old Xapian " - "library version: ", XAPIAN_VERSION, " < 1.3.2" ); - } -#endif - return dbPtr; - } - catch(Xapian::DatabaseOpeningError& e) - { - RsWarn() << __PRETTY_FUNCTION__ << " " << e.get_msg() - << ", probably nothing has been indexed yet." << std::endl; - } - catch(Xapian::DatabaseLockError&) - { - RsErr() << __PRETTY_FUNCTION__ << " Failed aquiring Xapian DB lock " - << path << std::endl; - print_stacktrace(); - } - catch(...) - { - RsErr() << __PRETTY_FUNCTION__ << " Xapian DB is apparently corrupted " - << "deleting it might help without causing any harm: " - << path << std::endl; - print_stacktrace(); - } - - return nullptr; -} - -std::string timetToXapianDate(const rstime_t& time) -{ - char date[] = "YYYYMMDD\0"; - time_t tTime = static_cast(time); - std::strftime(date, 9, "%Y%m%d", std::gmtime(&tTime)); - return date; -} - -StubbornWriteOpQueue::~StubbornWriteOpQueue() -{ - auto fErr = flush(0); - if(fErr) - { - RS_FATAL( "Flush failed on destruction ", mOpStore.size(), - " operations irreparably lost ", fErr ); - print_stacktrace(); - } -} - -void StubbornWriteOpQueue::push(write_op op) -{ - RS_DBG4(""); - - { - std::unique_lock lock(mQueueMutex); - mOpStore.push(op); - } - - flush(); -} - -std::error_condition StubbornWriteOpQueue::flush( - rstime_t acceptDelay, rstime_t callTS ) -{ - RS_DBG4(""); - - { - // Return without attempt to open the database if the queue is empty - std::unique_lock lock(mQueueMutex); - if(mOpStore.empty()) return std::error_condition(); - } - - std::unique_ptr dbPtr; - try - { - dbPtr = std::make_unique( - mDbPath, Xapian::DB_CREATE_OR_OPEN ); - } - catch(Xapian::DatabaseLockError) - { - if(acceptDelay) - { - rstime_t tNow = time(nullptr); - rstime_t maxRemaining = tNow - (callTS + acceptDelay); - if(maxRemaining > 0) - { - std::chrono::milliseconds interval( - std::max(rstime_t(50), maxRemaining*1000/5) ); - RS_DBG3( "Cannot acquire database write lock, retrying in:", - interval.count(), "ms" ); - RsThread::async([this, acceptDelay, callTS, interval]() - { - std::this_thread::sleep_for(interval); - flush(acceptDelay, callTS); - }); - return std::error_condition(); - } - else - { - RS_ERR(std::errc::timed_out, acceptDelay, callTS, tNow); - return std::errc::timed_out; - } - } - else return std::errc::resource_unavailable_try_again; - } - catch(...) - { - RS_ERR("Xapian DB ", mDbPath, " is apparently corrupted"); - print_stacktrace(); - return std::errc::io_error; - } - - std::unique_lock lock(mQueueMutex); - while(!mOpStore.empty()) - { - auto op = mOpStore.front(); mOpStore.pop(); - op(*dbPtr); - } - return std::error_condition(); -} - -std::string simpleTextHtmlExtract(const std::string& rsHtmlDoc) -{ - if(rsHtmlDoc.empty()) return rsHtmlDoc; - - const bool isPlainMsg = - rsHtmlDoc[0] != '<' || rsHtmlDoc[rsHtmlDoc.size() - 1] != '>'; - if(isPlainMsg) return rsHtmlDoc; - - auto oSize = rsHtmlDoc.size(); - auto bodyTagBegin(rsHtmlDoc.find("= oSize) return rsHtmlDoc; - - auto bodyTagEnd(rsHtmlDoc.find(">", bodyTagBegin)); - if(bodyTagEnd >= oSize) return rsHtmlDoc; - - std::string retVal(rsHtmlDoc.substr(bodyTagEnd+1)); - - // strip also CSS inside - oSize = retVal.size(); - auto styleTagBegin(retVal.find("", styleTagBegin)); - if(styleEnd < oSize) - retVal.erase(styleTagBegin, 8+styleEnd-styleTagBegin); - } - - std::string::size_type oPos; - std::string::size_type cPos; - int itCount = 0; - while((oPos = retVal.find("<")) < retVal.size()) - { - if((cPos = retVal.find(">")) <= retVal.size()) - retVal.erase(oPos, 1+cPos-oPos); - else break; - - // Avoid infinite loop with crafty input - if(itCount > 1000) - { - RS_WARN( "Breaking stripping loop due to max allowed iterations ", - "rsHtmlDoc: ", rsHtmlDoc, " retVal: ", retVal ); - break; - } - ++itCount; - } - - return retVal; -} - -} diff --git a/libretroshare/src/deep_search/commonutils.hpp b/libretroshare/src/deep_search/commonutils.hpp deleted file mode 100644 index 5f47c39bd..000000000 --- a/libretroshare/src/deep_search/commonutils.hpp +++ /dev/null @@ -1,69 +0,0 @@ -/******************************************************************************* - * RetroShare full text indexing and search implementation based on Xapian * - * * - * Copyright (C) 2018-2021 Gioacchino Mazzurco * - * Copyright (C) 2019-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License version 3 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include -#include - -#include "util/rstime.h" - -#ifndef XAPIAN_AT_LEAST -#define XAPIAN_AT_LEAST(A,B,C) (XAPIAN_MAJOR_VERSION > (A) || \ - (XAPIAN_MAJOR_VERSION == (A) && \ - (XAPIAN_MINOR_VERSION > (B) || \ - (XAPIAN_MINOR_VERSION == (B) && XAPIAN_REVISION >= (C))))) -#endif // ndef XAPIAN_AT_LEAST - -namespace DeepSearch -{ -typedef std::function write_op; - -std::unique_ptr openReadOnlyDatabase( - const std::string& path, int flags = 0 ); - -std::string timetToXapianDate(const rstime_t& time); - -std::string simpleTextHtmlExtract(const std::string& rsHtmlDoc); - -struct StubbornWriteOpQueue -{ - explicit StubbornWriteOpQueue(const std::string& dbPath): - mDbPath(dbPath) {} - - ~StubbornWriteOpQueue(); - - void push(write_op op); - - std::error_condition flush( - rstime_t acceptDelay = 20, rstime_t callTS = time(nullptr) ); - -private: - std::queue mOpStore; - rstime_t mLastFlush; - - std::mutex mQueueMutex; - - const std::string mDbPath; -}; - -} diff --git a/libretroshare/src/deep_search/filesflacindexer.hpp b/libretroshare/src/deep_search/filesflacindexer.hpp deleted file mode 100644 index dbdc62b99..000000000 --- a/libretroshare/src/deep_search/filesflacindexer.hpp +++ /dev/null @@ -1,156 +0,0 @@ -/******************************************************************************* - * RetroShare full text indexing and search implementation based on Xapian * - * * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * Copyright (C) 2019 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License version 3 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "deep_search/filesindex.hpp" -#include "util/rsdebug.h" - -#include -#include -#include -#include -#include - -struct RsDeepFlacFileIndexer -{ - RsDeepFlacFileIndexer() - { - DeepFilesIndex::registerIndexer(31, indexFlacFile); - } - - static uint32_t indexFlacFile( - const std::string& path, const std::string& /*name*/, - Xapian::TermGenerator& xTG, Xapian::Document& xDoc ) - { - Dbg3() << __PRETTY_FUNCTION__ << " " << path << std::endl; - - using FlacChain = FLAC::Metadata::Chain; - std::unique_ptr flacChain(new FlacChain); - - if(!flacChain->is_valid()) - { - RsErr() << __PRETTY_FUNCTION__ << " Failed creating FLAC Chain 1" - << std::endl; - return 1; - } - - if(!flacChain->read(path.c_str(), false)) - { - Dbg3() << __PRETTY_FUNCTION__ << " Failed to open the file as FLAC" - << std::endl; - - flacChain.reset(new FlacChain); - if(!flacChain->is_valid()) - { - RsErr() << __PRETTY_FUNCTION__ - << " Failed creating FLAC Chain 2" << std::endl; - return 1; - } - if(!flacChain->read(path.c_str(), true)) - { - Dbg3() << __PRETTY_FUNCTION__ - << " Failed to open the file as OggFLAC" - << std::endl; - return 0; - } - } - - unsigned validCommentsCnt = 0; - std::string docData = xDoc.get_data(); - - FLAC::Metadata::Iterator mdit; - mdit.init(*flacChain); - if(!mdit.is_valid()) return 1; - - do - { - ::FLAC__MetadataType mdt = mdit.get_block_type(); - if (mdt != FLAC__METADATA_TYPE_VORBIS_COMMENT) continue; - - Dbg2() << __PRETTY_FUNCTION__ << " Found Vorbis Comment Block" - << std::endl; - - std::unique_ptr proto(mdit.get_block()); - if(!proto) continue; - - const FLAC::Metadata::VorbisComment* vc = - dynamic_cast(proto.get()); - if(!vc || !vc->is_valid()) continue; - - unsigned numComments = vc->get_num_comments(); - for(unsigned i = 0; i < numComments; ++i) - { - FLAC::Metadata::VorbisComment::Entry entry = - vc->get_comment(i); - if(!entry.is_valid()) continue; - - std::string tagName( entry.get_field_name(), - entry.get_field_name_length() ); - - /* Vorbis tags should be uppercases but not all the softwares - * enforce it */ - for (auto& c: tagName) c = static_cast(toupper(c)); - - std::string tagValue( entry.get_field_value(), - entry.get_field_value_length() ); - - if(tagValue.empty()) continue; - - if(tagName == "ARTIST") - xTG.index_text(tagValue, 1, "A"); - else if (tagName == "DESCRIPTION") - xTG.index_text(tagValue, 1, "XD"); - else if (tagName == "TITLE") - xTG.index_text(tagValue, 1, "S"); - else if(tagName.find("COVERART") != tagName.npos) - continue; // Avoid polluting the index with binary data - else if (tagName.find("METADATA_BLOCK_PICTURE") != tagName.npos) - continue; // Avoid polluting the index with binary data - - // Index fields without prefixes for general search. - xTG.increase_termpos(); - std::string fullComment(tagName + "=" + tagValue); - xTG.index_text(fullComment); - docData += fullComment + "\n"; - - Dbg2() << __PRETTY_FUNCTION__ << " Indexed " << fullComment - << std::endl; - - ++validCommentsCnt; - } - } - while(mdit.next()); - - if(validCommentsCnt > 0) - { - Dbg1() << __PRETTY_FUNCTION__ << " Successfully indexed: " << path - << std::endl; - - xDoc.set_data(docData); - return 99; - } - - /* Altought the file appears to be a valid FLAC, no vorbis comment has - * been found so return less then 50 maybe it has tagged only with ID3 - * tags ? */ - return 30; - } - - RS_SET_CONTEXT_DEBUG_LEVEL(3) -}; diff --git a/libretroshare/src/deep_search/filesindex.cpp b/libretroshare/src/deep_search/filesindex.cpp deleted file mode 100644 index 9d5b09a72..000000000 --- a/libretroshare/src/deep_search/filesindex.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/******************************************************************************* - * RetroShare full text indexing and search implementation based on Xapian * - * * - * Copyright (C) 2018-2021 Gioacchino Mazzurco * - * Copyright (C) 2019-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License version 3 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - - -#include - -#include "deep_search/filesindex.hpp" -#include "deep_search/commonutils.hpp" -#include "util/rsdebuglevel1.h" -#include "retroshare/rsinit.h" -#include "retroshare/rsversion.h" - -/*static*/ std::multimap -DeepFilesIndex::indexersRegister = {}; - -std::error_condition DeepFilesIndex::indexFile( - const std::string& path, const std::string& name, - const RsFileHash& hash ) -{ - const std::string hashString = hash.toStdString(); - const std::string idTerm("Q" + hashString); - - auto db = DeepSearch::openReadOnlyDatabase(mDbPath); - if(db) - { - Xapian::Document oldDoc; - Xapian::PostingIterator pIt = db->postlist_begin(idTerm); - if( pIt != db->postlist_end(idTerm) ) - { - oldDoc = db->get_document(*pIt); - if( oldDoc.get_value(INDEXER_VERSION_VALUENO) == - RS_HUMAN_READABLE_VERSION && - std::stoull(oldDoc.get_value(INDEXERS_COUNT_VALUENO)) == - indexersRegister.size() ) - { - /* Looks like this file has already been indexed by this - * RetroShare exact version, so we can skip it. If the version - * was different it made sense to reindex it as better indexers - * might be available since last time it was indexed */ - RS_DBG3("skipping laready indexed file: ", hash, " ", name); - return std::error_condition(); - } - } - db.reset(); // Release DB read lock ASAP - } - - Xapian::Document doc; - - // Set up a TermGenerator that we'll use in indexing. - Xapian::TermGenerator termgenerator; - //termgenerator.set_stemmer(Xapian::Stem("en")); - termgenerator.set_document(doc); - - for(auto& indexerPair : indexersRegister) - if(indexerPair.second(path, name, termgenerator, doc) > 50) - break; - - doc.add_boolean_term(idTerm); - termgenerator.index_text(name, 1, "N"); - termgenerator.index_text(name); - doc.add_value(FILE_HASH_VALUENO, hashString); - doc.add_value(INDEXER_VERSION_VALUENO, RS_HUMAN_READABLE_VERSION); - doc.add_value( - INDEXERS_COUNT_VALUENO, - std::to_string(indexersRegister.size()) ); - - mWriteQueue.push([idTerm, doc](Xapian::WritableDatabase& db) - { db.replace_document(idTerm, doc); }); - - return std::error_condition(); -} - -std::error_condition DeepFilesIndex::removeFileFromIndex(const RsFileHash& hash) -{ - RS_DBG3(hash); - - mWriteQueue.push([hash](Xapian::WritableDatabase& db) - { db.delete_document("Q" + hash.toStdString()); }); - - return std::error_condition(); -} - -/*static*/ std::string DeepFilesIndex::dbDefaultPath() -{ return RsAccounts::AccountDirectory() + "/deep_files_index_xapian_db"; } - -/*static*/ bool DeepFilesIndex::registerIndexer( - int order, const DeepFilesIndex::IndexerFunType& indexerFun ) -{ - RS_DBG1(order); - - indexersRegister.insert(std::make_pair(order, indexerFun)); - return true; -} - -std::error_condition DeepFilesIndex::search( - const std::string& queryStr, - std::vector& results, uint32_t maxResults ) -{ - results.clear(); - - auto dbPtr = DeepSearch::openReadOnlyDatabase(mDbPath); - if(!dbPtr) return std::errc::bad_file_descriptor; - Xapian::Database& db(*dbPtr); - - // Set up a QueryParser with a stemmer and suitable prefixes. - Xapian::QueryParser queryparser; - //queryparser.set_stemmer(Xapian::Stem("en")); - queryparser.set_stemming_strategy(queryparser.STEM_SOME); - // Start of prefix configuration. - //queryparser.add_prefix("title", "S"); - //queryparser.add_prefix("description", "XD"); - // End of prefix configuration. - - // And parse the query. - Xapian::Query query = queryparser.parse_query(queryStr); - - // Use an Enquire object on the database to run the query. - Xapian::Enquire enquire(db); - enquire.set_query(query); - - Xapian::MSet mset = enquire.get_mset( - 0, maxResults ? maxResults : db.get_doccount() ); - - for ( Xapian::MSetIterator m = mset.begin(); m != mset.end(); ++m ) - { - const Xapian::Document& doc = m.get_document(); - DeepFilesSearchResult s; - s.mFileHash = RsFileHash(doc.get_value(FILE_HASH_VALUENO)); - s.mWeight = m.get_weight(); -#if XAPIAN_AT_LEAST(1,3,5) - s.mSnippet = mset.snippet(doc.get_data()); -#endif // XAPIAN_AT_LEAST(1,3,5) - results.push_back(s); - } - - return std::error_condition(); -} - - -#ifdef RS_DEEP_FILES_INDEX_OGG -# include "deep_search/filesoggindexer.hpp" -static RsDeepOggFileIndexer oggFileIndexer; -#endif // def RS_DEEP_FILES_INDEX_OGG - -#ifdef RS_DEEP_FILES_INDEX_FLAC -# include "deep_search/filesflacindexer.hpp" -static RsDeepFlacFileIndexer flacFileIndexer; -#endif // def RS_DEEP_FILES_INDEX_FLAC - -#ifdef RS_DEEP_FILES_INDEX_TAGLIB -# include "deep_search/filestaglibindexer.hpp" -static RsDeepTaglibFileIndexer taglibFileIndexer; -#endif // def RS_DEEP_FILES_INDEX_TAGLIB diff --git a/libretroshare/src/deep_search/filesindex.hpp b/libretroshare/src/deep_search/filesindex.hpp deleted file mode 100644 index b337bd072..000000000 --- a/libretroshare/src/deep_search/filesindex.hpp +++ /dev/null @@ -1,104 +0,0 @@ -/******************************************************************************* - * RetroShare full text indexing and search implementation based on Xapian * - * * - * Copyright (C) 2018-2021 Gioacchino Mazzurco * - * Copyright (C) 2019-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License version 3 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include "retroshare/rstypes.h" -#include "deep_search/commonutils.hpp" - -struct DeepFilesSearchResult -{ - DeepFilesSearchResult() : mWeight(0) {} - - RsFileHash mFileHash; - double mWeight; - std::string mSnippet; -}; - -class DeepFilesIndex -{ -public: - explicit DeepFilesIndex(const std::string& dbPath): - mDbPath(dbPath), mWriteQueue(dbPath) {} - - /** - * @brief Search indexed files - * @param[in] maxResults maximum number of acceptable search results, 0 for - * no limits - * @return search results count - */ - std::error_condition search( const std::string& queryStr, - std::vector& results, - uint32_t maxResults = 100 ); - - /** - * @return false if file could not be indexed because of error or - * unsupported type, true otherwise. - */ - std::error_condition indexFile( - const std::string& path, const std::string& name, - const RsFileHash& hash ); - - /** - * @brief Remove file entry from database - * @return false on error, true otherwise. - */ - std::error_condition removeFileFromIndex(const RsFileHash& hash); - - static std::string dbDefaultPath(); - - using IndexerFunType = std::function< - uint32_t( const std::string& path, const std::string& name, - Xapian::TermGenerator& xTG, Xapian::Document& xDoc ) >; - - static bool registerIndexer( - int order, const IndexerFunType& indexerFun ); - -private: - enum : Xapian::valueno - { - /// Used to store RsFileHash of indexed documents - FILE_HASH_VALUENO, - - /** Used to check if some file need reindex because was indexed with an - * older version of the indexer */ - INDEXER_VERSION_VALUENO, - - /** Used to check if some file need reindex because was indexed with an - * older version of the indexer */ - INDEXERS_COUNT_VALUENO, - - /// @see Xapian::BAD_VALUENO - BAD_VALUENO = Xapian::BAD_VALUENO - }; - - const std::string mDbPath; - - DeepSearch::StubbornWriteOpQueue mWriteQueue; - - /** Storage for indexers function by order */ - static std::multimap indexersRegister; -}; diff --git a/libretroshare/src/deep_search/filesoggindexer.hpp b/libretroshare/src/deep_search/filesoggindexer.hpp deleted file mode 100644 index 00c22ae66..000000000 --- a/libretroshare/src/deep_search/filesoggindexer.hpp +++ /dev/null @@ -1,97 +0,0 @@ -/******************************************************************************* - * RetroShare full text indexing and search implementation based on Xapian * - * * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * Copyright (C) 2019 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License version 3 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "deep_search/filesindex.hpp" -#include "util/rsdebug.h" - -#include -#include -#include -#include - -struct RsDeepOggFileIndexer -{ - RsDeepOggFileIndexer() - { - DeepFilesIndex::registerIndexer(30, indexOggFile); - } - - static uint32_t indexOggFile( - const std::string& path, const std::string& /*name*/, - Xapian::TermGenerator& xTG, Xapian::Document& xDoc ) - { - Dbg3() << __PRETTY_FUNCTION__ << " " << path << std::endl; - - OggVorbis_File vf; - int ret = ov_fopen(path.c_str(), &vf); - - if(ret == 0 && vf.vc) - { - vorbis_comment& vc = *vf.vc; - std::string docData = xDoc.get_data(); - for (int i = 0; i < vc.comments; ++i) - { - using szt = std::string::size_type; - std::string userComment( - vc.user_comments[i], - static_cast(vc.comment_lengths[i]) ); - - if(userComment.empty()) continue; - - szt equalPos = userComment.find('='); - if(equalPos == std::string::npos) continue; - - std::string tagName = userComment.substr(0, equalPos); - if(tagName.empty()) continue; - - std::string tagValue = userComment.substr(equalPos + 1); - if(tagValue.empty()) continue; - - /* Ogg tags should be uppercases but not all the softwares - * enforce it */ - for (auto& c: tagName) c = static_cast(toupper(c)); - - if(tagName == "ARTIST") - xTG.index_text(tagValue, 1, "A"); - else if (tagName == "DESCRIPTION") - xTG.index_text(tagValue, 1, "XD"); - else if (tagName == "TITLE") - xTG.index_text(tagValue, 1, "S"); - else if(tagName.find("COVERART") != tagName.npos) - continue; // Avoid polluting the index with binary data - else if (tagName.find("METADATA_BLOCK_PICTURE") != tagName.npos) - continue; // Avoid polluting the index with binary data - - // Index fields without prefixes for general search. - xTG.increase_termpos(); - xTG.index_text(userComment); - docData += userComment + "\n"; - } - xDoc.set_data(docData); - - ov_clear(&vf); - return 99; - } - - return 0; - } - - RS_SET_CONTEXT_DEBUG_LEVEL(1) -}; diff --git a/libretroshare/src/deep_search/filestaglibindexer.hpp b/libretroshare/src/deep_search/filestaglibindexer.hpp deleted file mode 100644 index 341e9af38..000000000 --- a/libretroshare/src/deep_search/filestaglibindexer.hpp +++ /dev/null @@ -1,103 +0,0 @@ -/******************************************************************************* - * RetroShare full text indexing and search implementation based on Xapian * - * * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * Copyright (C) 2019 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License version 3 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "deep_search/filesindex.hpp" -#include "util/rsdebug.h" - -#include -#include -#include -#include -#include -#include - -struct RsDeepTaglibFileIndexer -{ - RsDeepTaglibFileIndexer() - { - DeepFilesIndex::registerIndexer(40, indexFile); - } - - static uint32_t indexFile( - const std::string& path, const std::string& /*name*/, - Xapian::TermGenerator& xTG, Xapian::Document& xDoc ) - { - Dbg4() << __PRETTY_FUNCTION__ << " " << path << std::endl; - - TagLib::FileRef tFile(path.c_str()); - if(tFile.isNull()) return 0; - - const TagLib::Tag* tag = tFile.tag(); - if(!tag) return 0; - - TagLib::PropertyMap tMap = tag->properties(); - - unsigned validCommentsCnt = 0; - std::string docData = xDoc.get_data(); - for( TagLib::PropertyMap::ConstIterator mIt = tMap.begin(); - mIt != tMap.end(); ++mIt ) - { - if(mIt->first.isNull() || mIt->first.isEmpty()) continue; - std::string tagName(mIt->first.upper().to8Bit()); - - if(mIt->second.isEmpty()) continue; - std::string tagValue(mIt->second.toString(", ").to8Bit(true)); - if(tagValue.empty()) continue; - - if(tagName == "ARTIST") - xTG.index_text(tagValue, 1, "A"); - else if (tagName == "DESCRIPTION") - xTG.index_text(tagValue, 1, "XD"); - else if (tagName == "TITLE") - xTG.index_text(tagValue, 1, "S"); - else if(tagName.find("COVERART") != tagName.npos) - continue; // Avoid polluting the index with binary data - else if (tagName.find("METADATA_BLOCK_PICTURE") != tagName.npos) - continue; // Avoid polluting the index with binary data - - // Index fields without prefixes for general search. - xTG.increase_termpos(); - std::string fullComment(tagName + "=" + tagValue); - xTG.index_text(fullComment); - docData += fullComment + "\n"; - - Dbg2() << __PRETTY_FUNCTION__ << " Indexed " << tagName << "=\"" - << tagValue << '"' << std::endl; - - ++validCommentsCnt; - } - - if(validCommentsCnt > 0) - { - Dbg1() << __PRETTY_FUNCTION__ << " Successfully indexed: " << path - << std::endl; - - xDoc.set_data(docData); - return 99; - } - - /* Altought the file appears to be supported by taglib, no comments has - * been found so return less then 50 maybe another indexer is capable of - * extracting information */ - return 30; - } - - RS_SET_CONTEXT_DEBUG_LEVEL(3) -}; diff --git a/libretroshare/src/deep_search/forumsindex.cpp b/libretroshare/src/deep_search/forumsindex.cpp deleted file mode 100644 index a04f2ecac..000000000 --- a/libretroshare/src/deep_search/forumsindex.cpp +++ /dev/null @@ -1,210 +0,0 @@ -/******************************************************************************* - * RetroShare full text indexing and search implementation based on Xapian * - * * - * Copyright (C) 2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License version 3 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "deep_search/forumsindex.hpp" -#include "deep_search/commonutils.hpp" -#include "retroshare/rsinit.h" -#include "retroshare/rsgxsforums.h" -#include "util/rsdebuglevel4.h" - -std::error_condition DeepForumsIndex::search( - const std::string& queryStr, - std::vector& results, uint32_t maxResults ) -{ - results.clear(); - - std::unique_ptr dbPtr( - DeepSearch::openReadOnlyDatabase(mDbPath) ); - if(!dbPtr) return std::errc::bad_file_descriptor; - - Xapian::Database& db(*dbPtr); - - // Set up a QueryParser with a stemmer and suitable prefixes. - Xapian::QueryParser queryparser; - //queryparser.set_stemmer(Xapian::Stem("en")); - queryparser.set_stemming_strategy(queryparser.STEM_SOME); - // Start of prefix configuration. - //queryparser.add_prefix("title", "S"); - //queryparser.add_prefix("description", "XD"); - // End of prefix configuration. - - // And parse the query. - using XQP = Xapian::QueryParser; - Xapian::Query query = queryparser.parse_query( - queryStr, XQP::FLAG_WILDCARD | XQP::FLAG_DEFAULT ); - - // Use an Enquire object on the database to run the query. - Xapian::Enquire enquire(db); - enquire.set_query(query); - - Xapian::MSet mset = enquire.get_mset( - 0, maxResults ? maxResults : db.get_doccount() ); - - for( Xapian::MSetIterator m = mset.begin(); m != mset.end(); ++m ) - { - const Xapian::Document& doc = m.get_document(); - DeepForumsSearchResult s; - s.mUrl = doc.get_value(URL_VALUENO); -#if XAPIAN_AT_LEAST(1,3,5) - s.mSnippet = mset.snippet(doc.get_data()); -#endif // XAPIAN_AT_LEAST(1,3,5) - results.push_back(s); - } - - return std::error_condition(); -} - -/*static*/ std::string DeepForumsIndex::forumIndexId(const RsGxsGroupId& grpId) -{ - RsUrl forumIndexId(RsGxsForums::DEFAULT_FORUM_BASE_URL); - forumIndexId.setQueryKV( - RsGxsForums::FORUM_URL_ID_FIELD, grpId.toStdString() ); - return forumIndexId.toString(); -} - -/*static*/ std::string DeepForumsIndex::postIndexId( - const RsGxsGroupId& grpId, const RsGxsMessageId& msgId ) -{ - RsUrl postIndexId(RsGxsForums::DEFAULT_FORUM_BASE_URL); - postIndexId.setQueryKV(RsGxsForums::FORUM_URL_ID_FIELD, grpId.toStdString()); - postIndexId.setQueryKV(RsGxsForums::FORUM_URL_MSG_ID_FIELD, msgId.toStdString()); - return postIndexId.toString(); -} - -std::error_condition DeepForumsIndex::indexForumGroup( - const RsGxsForumGroup& forum ) -{ - // Set up a TermGenerator that we'll use in indexing. - Xapian::TermGenerator termgenerator; - //termgenerator.set_stemmer(Xapian::Stem("en")); - - // We make a document and tell the term generator to use this. - Xapian::Document doc; - termgenerator.set_document(doc); - - // Index each field with a suitable prefix. - termgenerator.index_text(forum.mMeta.mGroupName, 1, "G"); - termgenerator.index_text( - DeepSearch::timetToXapianDate(forum.mMeta.mPublishTs), 1, "D" ); - termgenerator.index_text(forum.mDescription, 1, "XD"); - - // Index fields without prefixes for general search. - termgenerator.index_text(forum.mMeta.mGroupName); - termgenerator.increase_termpos(); - termgenerator.index_text(forum.mDescription); - - // store the RS link so we are able to retrive it on matching search - const std::string rsLink(forumIndexId(forum.mMeta.mGroupId)); - doc.add_value(URL_VALUENO, rsLink); - - /* Store some fields for display purposes. Retrieved later to provide the - * matching snippet on search */ - doc.set_data(forum.mMeta.mGroupName + "\n" + forum.mDescription); - - /* We use the identifier to ensure each object ends up in the database only - * once no matter how many times we run the indexer. - * "Q" prefix is a Xapian convention for unique id term. */ - const std::string idTerm("Q" + rsLink); - doc.add_boolean_term(idTerm); - - mWriteQueue.push([idTerm, doc](Xapian::WritableDatabase& db) - { db.replace_document(idTerm, doc); } ); - - return std::error_condition(); -} - -std::error_condition DeepForumsIndex::removeForumFromIndex( - const RsGxsGroupId& grpId ) -{ - mWriteQueue.push([grpId](Xapian::WritableDatabase& db) - { db.delete_document("Q" + forumIndexId(grpId)); }); - - return std::error_condition(); -} - -std::error_condition DeepForumsIndex::indexForumPost(const RsGxsForumMsg& post) -{ - RS_DBG4(post); - - const auto& groupId = post.mMeta.mGroupId; - const auto& msgId = post.mMeta.mMsgId; - - if(groupId.isNull() || msgId.isNull()) - { - RS_ERR("Got post with invalid id ", post); - print_stacktrace(); - return std::errc::invalid_argument; - } - - // Set up a TermGenerator that we'll use in indexing. - Xapian::TermGenerator termgenerator; - //termgenerator.set_stemmer(Xapian::Stem("en")); - - // We make a document and tell the term generator to use this. - Xapian::Document doc; - termgenerator.set_document(doc); - - // Index each field with a suitable prefix. - termgenerator.index_text(post.mMeta.mMsgName, 1, "S"); - termgenerator.index_text( - DeepSearch::timetToXapianDate(post.mMeta.mPublishTs), 1, "D" ); - - // Avoid indexing RetroShare-gui HTML tags - const std::string cleanMsg = DeepSearch::simpleTextHtmlExtract(post.mMsg); - termgenerator.index_text(cleanMsg, 1, "XD" ); - - // Index fields without prefixes for general search. - termgenerator.index_text(post.mMeta.mMsgName); - - termgenerator.increase_termpos(); - termgenerator.index_text(cleanMsg); - // store the RS link so we are able to retrive it on matching search - const std::string rsLink(postIndexId(groupId, msgId)); - doc.add_value(URL_VALUENO, rsLink); - - // Store some fields for display purposes. - doc.set_data(post.mMeta.mMsgName + "\n" + cleanMsg); - - // We use the identifier to ensure each object ends up in the - // database only once no matter how many times we run the - // indexer. - const std::string idTerm("Q" + rsLink); - doc.add_boolean_term(idTerm); - - mWriteQueue.push( [idTerm, doc](Xapian::WritableDatabase& db) - { db.replace_document(idTerm, doc); } ); - - - return std::error_condition(); -} - -std::error_condition DeepForumsIndex::removeForumPostFromIndex( - RsGxsGroupId grpId, RsGxsMessageId msgId ) -{ - // "Q" prefix is a Xapian convention for unique id term. - std::string idTerm("Q" + postIndexId(grpId, msgId)); - mWriteQueue.push( [idTerm](Xapian::WritableDatabase& db) - { db.delete_document(idTerm); } ); - - return std::error_condition(); -} - -/*static*/ std::string DeepForumsIndex::dbDefaultPath() -{ return RsAccounts::AccountDirectory() + "/deep_forum_index_xapian_db"; } diff --git a/libretroshare/src/deep_search/forumsindex.hpp b/libretroshare/src/deep_search/forumsindex.hpp deleted file mode 100644 index 2955ce323..000000000 --- a/libretroshare/src/deep_search/forumsindex.hpp +++ /dev/null @@ -1,81 +0,0 @@ -/******************************************************************************* - * RetroShare full text indexing and search implementation based on Xapian * - * * - * Copyright (C) 2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License version 3 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include - -#include "util/rstime.h" -#include "retroshare/rsgxsforums.h" -#include "retroshare/rsevents.h" -#include "deep_search/commonutils.hpp" - -struct DeepForumsSearchResult -{ - std::string mUrl; - double mWeight; - std::string mSnippet; -}; - -struct DeepForumsIndex -{ - explicit DeepForumsIndex(const std::string& dbPath) : - mDbPath(dbPath), mWriteQueue(dbPath) {} - - /** - * @brief Search indexed GXS groups and messages - * @param[in] maxResults maximum number of acceptable search results, 0 for - * no limits - * @return search results count - */ - std::error_condition search( const std::string& queryStr, - std::vector& results, - uint32_t maxResults = 100 ); - - std::error_condition indexForumGroup(const RsGxsForumGroup& chan); - - std::error_condition removeForumFromIndex(const RsGxsGroupId& grpId); - - std::error_condition indexForumPost(const RsGxsForumMsg& post); - - std::error_condition removeForumPostFromIndex( - RsGxsGroupId grpId, RsGxsMessageId msgId ); - - static std::string dbDefaultPath(); - -private: - static std::string forumIndexId(const RsGxsGroupId& grpId); - static std::string postIndexId( - const RsGxsGroupId& grpId, const RsGxsMessageId& msgId ); - - enum : Xapian::valueno - { - /// Used to store retroshare url of indexed documents - URL_VALUENO, - - /// @see Xapian::BAD_VALUENO - BAD_VALUENO = Xapian::BAD_VALUENO - }; - - const std::string mDbPath; - - DeepSearch::StubbornWriteOpQueue mWriteQueue; -}; diff --git a/libretroshare/src/dht/connectstatebox.cc b/libretroshare/src/dht/connectstatebox.cc deleted file mode 100644 index c1a0c4ff2..000000000 --- a/libretroshare/src/dht/connectstatebox.cc +++ /dev/null @@ -1,1049 +0,0 @@ -/******************************************************************************* - * libretroshare/src/dht: connectstatebox.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "dht/connectstatebox.h" - -#include "util/rsrandom.h" -#include "util/rsstring.h" - -#include - -/** - * - * #define TESTING_PERIODS 1 - * #define DEBUG_CONNECTBOX 1 - * - **/ - - -/* Have made the PROXY Attempts + MAX_TIME much larger, - * have have potential for this to take a while. - */ - -#ifdef TESTING_PERIODS - #define FAILED_WAIT_TIME (1800) // 5 minutes. - #define TCP_WAIT_TIME (10) // 1/6 minutes. - #define DIRECT_MAX_WAIT_TIME (30) // 1/6 minutes. - #define PROXY_BASE_WAIT_TIME (10) // 30 // 1/6 minutes. - #define PROXY_MAX_WAIT_TIME (30) // 120 // 1/6 minutes. - #define RELAY_MAX_WAIT_TIME (30) // 1/6 minutes. - #define REVERSE_WAIT_TIME (30) // 1/2 minutes. - - #define MAX_DIRECT_ATTEMPTS (3) - #define MAX_PROXY_ATTEMPTS (3) - #define MAX_RELAY_ATTEMPTS (3) - - #define MAX_DIRECT_FAILED_ATTEMPTS (1) - #define MAX_PROXY_FAILED_ATTEMPTS (2) - #define MAX_RELAY_FAILED_ATTEMPTS (2) -#else - #define FAILED_WAIT_TIME (1800) // 30 minutes. - #define TCP_WAIT_TIME (60) // 1 minutes. - #define DIRECT_MAX_WAIT_TIME (60) // 1 minutes. - - #define PROXY_BASE_WAIT_TIME (30) // 1/2 minutes. - #define PROXY_MAX_WAIT_TIME (120) // 1 minutes. - - #define RELAY_MAX_WAIT_TIME (60) // 1 minutes. - #define REVERSE_WAIT_TIME (300) // 5 minutes. - - #define MAX_DIRECT_ATTEMPTS (5) - #define MAX_PROXY_ATTEMPTS (10) - #define MAX_RELAY_ATTEMPTS (5) - - #define MAX_DIRECT_FAILED_ATTEMPTS (3) - #define MAX_PROXY_FAILED_ATTEMPTS (3) - #define MAX_RELAY_FAILED_ATTEMPTS (3) - -#endif - -PeerConnectStateBox::PeerConnectStateBox() -{ - //mPeerId = id; - rstime_t now = time(NULL); - mState = CSB_START; - mNetState = CSB_NETSTATE_UNKNOWN; - mStateTS = now; - mNoAttempts = 0; - mNoFailedAttempts = 0; - mNextAttemptTS = now; - mAttemptLength = 0; - mProxyPortFlags = 0; - mProxyPortChoice = false; - mProxyPortTS = 0; - - -} - - -std::string NetStateAsString(uint32_t netstate) -{ - std::string str; - switch(netstate) - { - case CSB_NETSTATE_FORWARD: - str = "Forwarded"; - break; - - case CSB_NETSTATE_STABLENAT: - str = "StableNat"; - break; - - case CSB_NETSTATE_EXCLUSIVENAT: - str = "ExclusiveNat"; - break; - - case CSB_NETSTATE_FIREWALLED: - str = "Firewalled"; - break; - default: - str = "Unknown NetState"; - break; - } - return str; -} - -std::string StateAsString(uint32_t state) -{ - std::string str; - switch(state) - { - case CSB_START: - str = "Start:"; - break; - - case CSB_TCP_WAIT: - str = "TCP Wait:"; - break; - - case CSB_DIRECT_ATTEMPT: - str = "Direct Attempt:"; - break; - - case CSB_DIRECT_WAIT: - str = "Direct Wait:"; - break; - - case CSB_PROXY_ATTEMPT: - str = "Proxy Attempt:"; - break; - - case CSB_PROXY_WAIT: - str = "Proxy Wait:"; - break; - - case CSB_RELAY_ATTEMPT: - str = "Relay Attempt:"; - break; - - case CSB_RELAY_WAIT: - str = "Relay Wait:"; - break; - - case CSB_REVERSE_WAIT: - str = "Reverse Wait:"; - break; - - case CSB_FAILED_WAIT: - str = "Failed Wait:"; - break; - - case CSB_CONNECTED: - str = "Connected:"; - break; - - default: - str = "Unknown State:"; - break; - } - - return str; -} - - -std::string UpdateAsString(uint32_t update) -{ - std::string str; - switch(update) - { - case CSB_UPDATE_NONE: - str = "none"; - break; - - case CSB_UPDATE_CONNECTED: - str = "Connected"; - break; - - case CSB_UPDATE_DISCONNECTED: - str = "Disconnected"; - break; - - case CSB_UPDATE_AUTH_DENIED: - str = "Auth Denied"; - break; - - case CSB_UPDATE_FAILED_ATTEMPT: - str = "Failed Attempt:"; - break; - - case CSB_UPDATE_MODE_UNAVAILABLE: - str = "Mode Unavailable:"; - break; - - default: - str = "Unknown Update"; - break; - } - return str; -} - -void PeerConnectStateBox::errorMsg(std::ostream &out, std::string msg, uint32_t updateParam) -{ - out << "PeerConnectStateBox::ERROR " << msg; - out << " NetState: " << NetStateAsString(mNetState); - out << " State: " << StateAsString(mState); - out << " Update: " << UpdateAsString(updateParam); - out << " for peer: " << mPeerId; - out << std::endl; -} - - -void PeerConnectStateBox::stateMsg(std::ostream &out, std::string msg, uint32_t updateParam) -{ - out << "PeerConnectStateBox::MSG " << msg; - out << " NetState: " << NetStateAsString(mNetState); - out << " State: " << StateAsString(mState); - out << " Update: " << UpdateAsString(updateParam); - out << " for peer: " << mPeerId; - out << std::endl; -} - -std::string PeerConnectStateBox::connectState() const -{ - std::string str = StateAsString(mState); - rstime_t now = time(NULL); - std::string out; - rs_sprintf(out, "%s(%lu/%lu) for %ld secs", str.c_str(), mNoAttempts, mNoFailedAttempts, now - mStateTS); - if ( (mState == CSB_CONNECTED) || (mState == CSB_DIRECT_ATTEMPT) || - (mState == CSB_PROXY_ATTEMPT) || (mState == CSB_RELAY_ATTEMPT) || - (mState == CSB_FAILED_WAIT) ) - { - rs_sprintf_append(out, " Last Attempt: %ld", mAttemptLength); - } - else - { - rs_sprintf_append(out, " LA: %ld", mAttemptLength); - rs_sprintf_append(out, " NextAttempt: %ld", mNextAttemptTS - now); - } - - return out; -} - - -uint32_t convertNetStateToInternal(RsNetworkMode netmode, RsNatHoleMode nathole, RsNatTypeMode nattype) -{ - uint32_t connNet = CSB_NETSTATE_UNKNOWN; - - if (netmode == RsNetworkMode::EXTERNALIP) - { - connNet = CSB_NETSTATE_FORWARD; - } - else if ((nathole != RsNatHoleMode::UNKNOWN) && (nathole != RsNatHoleMode::NONE)) - { - connNet = CSB_NETSTATE_FORWARD; - } - else if (netmode == RsNetworkMode::BEHINDNAT) - { - if ((nattype == RsNatTypeMode::RESTRICTED_CONE) || - (nattype == RsNatTypeMode::FULL_CONE)) - { - connNet = CSB_NETSTATE_STABLENAT; - } - else if (nattype == RsNatTypeMode::DETERM_SYM) - { - connNet = CSB_NETSTATE_EXCLUSIVENAT; - } - else - { - connNet = CSB_NETSTATE_FIREWALLED; - } - } - return connNet; -} - -bool shouldUseProxyPortInternal(uint32_t netstate) -{ - if (netstate == CSB_NETSTATE_FORWARD) - { - return false; - } - return true; -} - -bool PeerConnectStateBox::shouldUseProxyPort(RsNetworkMode netmode, RsNatHoleMode nathole, RsNatTypeMode nattype) -{ - uint32_t netstate = convertNetStateToInternal(netmode, nathole, nattype); - return shouldUseProxyPortInternal(netstate); -} - -uint32_t PeerConnectStateBox::calcNetState(RsNetworkMode netmode, RsNatHoleMode nathole, RsNatTypeMode nattype) -{ - uint32_t netstate = convertNetStateToInternal(netmode, nathole, nattype); - return netstate; -} - - -uint32_t PeerConnectStateBox::connectCb(uint32_t cbtype, RsNetworkMode netmode, RsNatHoleMode nathole, RsNatTypeMode nattype) -{ - uint32_t netstate = convertNetStateToInternal(netmode, nathole, nattype); - -#ifdef DEBUG_CONNECTBOX - std::cerr << "PeerConnectStateBox::connectCb("; - if (cbtype == CSB_CONNECT_DIRECT) - { - std::cerr << "DIRECT"; - } - else - { - std::cerr << "UNREACHABLE"; - } - std::cerr << "," << NetStateAsString(netstate) << ")"; - std::cerr << std::endl; -#endif - - if (netstate != mNetState) - { -#ifdef DEBUG_CONNECTBOX - std::cerr << "PeerConnectStateBox::connectCb() WARNING Changing NetState from: "; - std::cerr << " from: " << NetStateAsString(mNetState); - std::cerr << " to: " << NetStateAsString(netstate); - std::cerr << " for peer: " << mPeerId; - std::cerr << std::endl; -#endif - - mNetState = netstate; - } - - if (cbtype == CSB_CONNECT_DIRECT) - { - return connectCb_direct(); - } - else - { - return connectCb_unreachable(); - } -} - - -uint32_t PeerConnectStateBox::connectCb_direct() -{ - uint32_t retval = 0; - rstime_t now = time(NULL); - - switch(mState) - { - - case CSB_DIRECT_ATTEMPT: - { - errorMsg(std::cerr, "mState == DIRECT_ATTEMPT", 0); - retval = CSB_ACTION_WAIT; - } - break; - - case CSB_PROXY_ATTEMPT: - { - errorMsg(std::cerr, "mState == PROXY_ATTEMPT", 0); - retval = CSB_ACTION_WAIT; - } - break; - - case CSB_RELAY_ATTEMPT: - { - errorMsg(std::cerr, "mState == RELAY_ATTEMPT", 0); - retval = CSB_ACTION_WAIT; - } - break; - - case CSB_FAILED_WAIT: - { - /* if too soon */ - //if (now - mStateTS < FAILED_WAIT_TIME) - if (mNextAttemptTS > now) - { - /* same state */ - retval = CSB_ACTION_WAIT; - break; - } - } /* FALLTHROUGH TO START CASE */ - /* fallthrough */ - default: - case CSB_REVERSE_WAIT: - case CSB_PROXY_WAIT: - case CSB_RELAY_WAIT: - { - if (mState != CSB_FAILED_WAIT) - { - /* ERROR */ - errorMsg(std::cerr, "mState != FAILED_WAIT", 0); - - } - - } /* FALLTHROUGH TO START CASE */ - /* fallthrough */ - case CSB_START: - { - /* starting up the connection */ - mState = CSB_TCP_WAIT; - retval = CSB_ACTION_TCP_CONN; - mStateTS = now; - mNoAttempts = 0; - mNoFailedAttempts = 0; - mNextAttemptTS = now + TCP_WAIT_TIME; - - } - break; - case CSB_TCP_WAIT: - { - /* if too soon */ - //if (now - mStateTS < TCP_WAIT_TIME) - if (mNextAttemptTS > now) - { - /* same state */ - retval = CSB_ACTION_WAIT; - } - else - { - /* try again */ - mState = CSB_DIRECT_ATTEMPT; - retval = CSB_ACTION_DIRECT_CONN | CSB_ACTION_DHT_PORT; - mStateTS = now; - mNoAttempts = 0; - mNoFailedAttempts = 0; - } - } - break; - - case CSB_DIRECT_WAIT: - { - /* if too soon */ - //if (now - mStateTS < DIRECT_WAIT_TIME) - if (mNextAttemptTS > now) - { - /* same state */ - retval = CSB_ACTION_WAIT; - } - else if ((mNoAttempts >= MAX_DIRECT_ATTEMPTS) || - (mNoFailedAttempts >= MAX_DIRECT_FAILED_ATTEMPTS)) - { - /* if too many attempts */ - /* no RELAY attempt => FAILED_WAIT */ - mState = CSB_FAILED_WAIT; - retval = CSB_ACTION_WAIT; - mStateTS = now; - mNoAttempts = 0; - mNoFailedAttempts = 0; - mNextAttemptTS = now + FAILED_WAIT_TIME; - } - else - { - /* try again */ - mState = CSB_DIRECT_ATTEMPT; - retval = CSB_ACTION_DIRECT_CONN | CSB_ACTION_DHT_PORT; - mStateTS = now; - mNoAttempts++; - } - } - break; - - case CSB_CONNECTED: - { - retval = CSB_ACTION_WAIT; - } - break; - } - - return retval; - -} - - -uint32_t PeerConnectStateBox::connectCb_unreachable() -{ - uint32_t retval = 0; - - uint32_t proxyPortMode = CSB_ACTION_PROXY_PORT; - if (!shouldUseProxyPortInternal(mNetState)) - { - proxyPortMode = CSB_ACTION_DHT_PORT; - } - - rstime_t now = time(NULL); - - switch(mState) - { - case CSB_DIRECT_ATTEMPT: - { - errorMsg(std::cerr, "mState == DIRECT_ATTEMPT", 0); - retval = CSB_ACTION_WAIT; - } - break; - - case CSB_PROXY_ATTEMPT: - { - errorMsg(std::cerr, "mState == PROXY_ATTEMPT", 0); - retval = CSB_ACTION_WAIT; - } - break; - - case CSB_RELAY_ATTEMPT: - { - errorMsg(std::cerr, "mState == RELAY_ATTEMPT", 0); - retval = CSB_ACTION_WAIT; - } - break; - - case CSB_FAILED_WAIT: - { - /* if too soon */ - //if (now - mStateTS < FAILED_WAIT_TIME) - if (mNextAttemptTS > now) - { - /* same state */ -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "too soon, no action", 0); -#endif - retval = CSB_ACTION_WAIT; - break; - } - } /* FALLTHROUGH TO START CASE */ - /* fallthrough */ - default: - case CSB_DIRECT_WAIT: - { - if (mState != CSB_FAILED_WAIT) - { - /* ERROR */ - errorMsg(std::cerr, "mState != FAILED_WAIT", 0); - - } - - } /* FALLTHROUGH TO START CASE */ - /* fallthrough */ - case CSB_START: - { - /* starting up the connection */ - mState = CSB_TCP_WAIT; - retval = CSB_ACTION_WAIT; /* NO POINT TRYING A TCP_CONN */ - mStateTS = now; - mNoAttempts = 0; - mNoFailedAttempts = 0; - mNextAttemptTS = now + TCP_WAIT_TIME; - - } - break; - case CSB_TCP_WAIT: - { - /* if too soon */ - if (mNextAttemptTS > now) - { - /* same state */ - retval = CSB_ACTION_WAIT; - } - else - { - /* starting up the connection */ - if (mState != CSB_NETSTATE_FIREWALLED) - { -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "not Firewalled => PROXY_ATTEMPT", 0); -#endif - mState = CSB_PROXY_ATTEMPT; - retval = CSB_ACTION_PROXY_CONN | proxyPortMode; - } - else - { -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "Firewalled => RELAY_ATTEMPT", 0); -#endif - mState = CSB_RELAY_ATTEMPT; - retval = CSB_ACTION_RELAY_CONN | CSB_ACTION_DHT_PORT; - - } - - mStateTS = now; - mNoAttempts = 0; - mNoFailedAttempts = 0; - } - - } - break; - case CSB_PROXY_WAIT: - { - /* if too soon */ - if (mNextAttemptTS > now) - { - /* same state */ -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "too soon, no action", 0); -#endif - retval = CSB_ACTION_WAIT; - } - else if ((mNoAttempts >= MAX_PROXY_ATTEMPTS) || - (mNoFailedAttempts >= MAX_PROXY_FAILED_ATTEMPTS)) - { - /* if too many attempts */ - /* switch to RELAY attempt */ -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "too many PROXY => RELAY_ATTEMPT", 0); -#endif - mState = CSB_RELAY_ATTEMPT; - retval = CSB_ACTION_RELAY_CONN | CSB_ACTION_DHT_PORT; - mStateTS = now; - mNoAttempts = 0; - mNoFailedAttempts = 0; - } - else - { - /* try again */ -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "PROXY_ATTEMPT try again", 0); -#endif - mState = CSB_PROXY_ATTEMPT; - retval = CSB_ACTION_PROXY_CONN | proxyPortMode; - mStateTS = now; - mNoAttempts++; - } - } - break; - - case CSB_REVERSE_WAIT: - { - /* if too soon */ - //if (now - mStateTS < REVERSE_WAIT_TIME) - if (mNextAttemptTS > now) - { - /* same state */ -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "too soon, no action", 0); -#endif - retval = CSB_ACTION_WAIT; - } - else - { -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "timeout => RELAY_ATTEMPT", 0); -#endif - /* switch to RELAY attempt */ - mState = CSB_RELAY_ATTEMPT; - retval = CSB_ACTION_RELAY_CONN | CSB_ACTION_DHT_PORT; - mStateTS = now; - mNoAttempts = 0; - mNoFailedAttempts = 0; - } - } - break; - - case CSB_RELAY_WAIT: - { - /* if too soon */ - if (mNextAttemptTS > now) - { - /* same state */ -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "too soon, no action", 0); -#endif - retval = CSB_ACTION_WAIT; - } - else if ((mNoAttempts >= MAX_RELAY_ATTEMPTS) || - (mNoFailedAttempts >= MAX_RELAY_FAILED_ATTEMPTS)) - { - /* if too many attempts */ - /* switch to RELAY attempt */ -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "too many RELAY => FAILED_WAIT", 0); -#endif - mState = CSB_FAILED_WAIT; - retval = CSB_ACTION_WAIT; - mStateTS = now; - mNoAttempts = 0; - mNoFailedAttempts = 0; - mNextAttemptTS = now + FAILED_WAIT_TIME; - } - else - { - /* try again */ -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "RELAY_ATTEMPT try again", 0); -#endif - mState = CSB_RELAY_ATTEMPT; - retval = CSB_ACTION_RELAY_CONN | CSB_ACTION_DHT_PORT; - mStateTS = now; - mNoAttempts++; - } - } - break; - - case CSB_CONNECTED: - { -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "connected => no action", 0); -#endif - retval = CSB_ACTION_WAIT; - } - break; - } - - return retval; -} - - - -uint32_t PeerConnectStateBox::updateCb(uint32_t update) -{ - /* The Error Callback doesn't trigger another connection. - * but can change the connection state - * - * Possible Errors: - * 1) AUTH DENIED. (fatal) - * 2) MODE UNAVILABLE - * 3) RETRY ATTEMPT - * 4) FAILED ATTEMPT - * 5) CONNECTION - * 6) DISCONNECTED. - * - * Fitting these into the states: - case CSB_START: - CONNECTION => CSB_CONNECTED - error if: AUTH DENIED, MODE UNAVAILABLE, FAILED ATTEMPT, RETRY ATTEMPT, DISCONNECTED - case CSB_CONNECTED: - CONNECTION => CSB_CONNECTED - DISCONNECTED => CSB_START - error if: AUTH DENIED, MODE UNAVAILABLE, FAILED ATTEMPT, RETRY ATTEMPT - - case CSB_FAILED_WAIT: - CONNECTION => CSB_CONNECTED - error if: AUTH DENIED, MODE UNAVAILABLE, FAILED ATTEMPT, RETRY ATTEMPT, DISCONNECTED - case CSB_REVERSE_WAIT: - CONNECTION => CSB_CONNECTED - error if: AUTH DENIED, MODE UNAVAILABLE, FAILED ATTEMPT, RETRY ATTEMPT, DISCONNECTED - case CSB_DIRECT_ATTEMPT: - CONNECTION => CSB_CONNECTED - AUTH DENIED => CSB_FAILED_WAIT - FAILED ATTEMPT => stay here. - RETRY ATTEMPT => stay here - MODE UNAVAILABLE - probably error => CSB_FAILED_WAIT - error if: MODE UNAVAILABLE, DISCONNECTED - - case CSB_PROXY_ATTEMPT: - CONNECTION => CSB_CONNECTED - AUTH DENIED => CSB_FAILED_WAIT - FAILED ATTEMPT => stay here. - RETRY ATTEMPT => stay here - MODE_UNAVAILABLE => CSB_REVERSE_WAIT | CSB_RELAY_ATTEMPT - error if: DISCONNECTED - - case CSB_RELAY_ATTEMPT: - CONNECTION => CSB_CONNECTED - AUTH DENIED => CSB_FAILED_WAIT - FAILED ATTEMPT => stay here. - RETRY ATTEMPT => stay here - MODE_UNAVAILABLE => CSB_FAILED_WAIT - error if: DISCONNECTED - - case CSB_DIRECT_WAIT: - CONNECTION => CSB_CONNECTED - error if: AUTH DENIED, MODE UNAVAILABLE, FAILED ATTEMPT, RETRY ATTEMPT, DISCONNECTED - case CSB_PROXY_WAIT: - CONNECTION => CSB_CONNECTED - error if: AUTH_DENIED, MODE UNAVAILABLE, FAILED ATTEMPT, RETRY ATTEMPT, DISCONNECTED - case CSB_RELAY_ATTEMPT: - CONNECTION => CSB_CONNECTED - error if: AUTH_DENIED, MODE UNAVAILABLE, FAILED ATTEMPT, RETRY ATTEMPT, DISCONNECTED - */ - - /* DO Connect / Disconnect Updates ... very specific! */ - rstime_t now = time(NULL); - switch(update) - { - case CSB_UPDATE_CONNECTED: - { - if ((mState == CSB_DIRECT_ATTEMPT) || (mState == CSB_PROXY_ATTEMPT) || (mState == CSB_RELAY_ATTEMPT)) - { - mAttemptLength = now - mStateTS; - } - else - { - mAttemptLength = 0; - } - -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "=> CONNECTED", update); -#endif - mState = CSB_CONNECTED; - mStateTS = now; - - return 0; - } - break; - case CSB_UPDATE_DISCONNECTED: - { - if (mState != CSB_CONNECTED) - { - /* ERROR, ignore (as already in disconnected state) */ - errorMsg(std::cerr, "mState != CSB_CONNECTED", update); - - } - else - { -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "=> START", update); -#endif - /* move to START state */ - mState = CSB_START; - mStateTS = now; - return 1; - } - - return 0; - } - break; - } - - - /* Now catch errors for feedback when we should be WAITING */ - switch(mState) - { - default: - case CSB_DIRECT_WAIT: - case CSB_PROXY_WAIT: - case CSB_RELAY_WAIT: - case CSB_REVERSE_WAIT: - case CSB_FAILED_WAIT: - case CSB_START: - case CSB_CONNECTED: /* impossible */ - { - /* ERROR */ - /* shouldn't receive anything here! */ - errorMsg(std::cerr, "shouldnt get anything", update); - - return 0; - } - break; - - case CSB_DIRECT_ATTEMPT: - case CSB_PROXY_ATTEMPT: - case CSB_RELAY_ATTEMPT: - { - /* OKAY */ - - } - break; - } - - - switch(update) - { - /* if AUTH_DENIED ... => FAILED_WAIT */ - case CSB_UPDATE_AUTH_DENIED: - { -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "=> FAILED WAIT", update); -#endif - mState = CSB_FAILED_WAIT; - mStateTS = now; - mAttemptLength = now - mStateTS; - mNextAttemptTS = now + FAILED_WAIT_TIME; - - return 1; - } - break; - /* if standard FAIL => stay where we are */ - case CSB_UPDATE_RETRY_ATTEMPT: - { -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "RETRY FAIL => switch to wait state", update); -#endif - mAttemptLength = now - mStateTS; - switch(mState) - { - case CSB_DIRECT_ATTEMPT: - mState = CSB_DIRECT_WAIT; - mStateTS = now; - mNextAttemptTS = now + RSRandom::random_u32() % DIRECT_MAX_WAIT_TIME; - break; - case CSB_PROXY_ATTEMPT: - mState = CSB_PROXY_WAIT; - mStateTS = now; - mNextAttemptTS = now + PROXY_BASE_WAIT_TIME + (RSRandom::random_u32() % (PROXY_MAX_WAIT_TIME - PROXY_BASE_WAIT_TIME)); - break; - case CSB_RELAY_ATTEMPT: - mState = CSB_RELAY_WAIT; - mStateTS = now; - mNextAttemptTS = now + RSRandom::random_u32() % RELAY_MAX_WAIT_TIME; - break; - default: -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "RETRY FAIL, but unusual state", update); -#endif - break; - } - - return 1; - } - /* if standard FAIL => stay where we are */ - case CSB_UPDATE_FAILED_ATTEMPT: - { -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "STANDARD FAIL => switch to wait state", update); -#endif - mNoFailedAttempts++; - mAttemptLength = now - mStateTS; - switch(mState) - { - case CSB_DIRECT_ATTEMPT: - mState = CSB_DIRECT_WAIT; - mStateTS = now; - mNextAttemptTS = now + RSRandom::random_u32() % DIRECT_MAX_WAIT_TIME; - break; - case CSB_PROXY_ATTEMPT: - mState = CSB_PROXY_WAIT; - mStateTS = now; - mNextAttemptTS = now + PROXY_BASE_WAIT_TIME + (RSRandom::random_u32() % (PROXY_MAX_WAIT_TIME - PROXY_BASE_WAIT_TIME)); - break; - case CSB_RELAY_ATTEMPT: - mState = CSB_RELAY_WAIT; - mStateTS = now; - mNextAttemptTS = now + RSRandom::random_u32() % RELAY_MAX_WAIT_TIME; - break; - default: -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "STANDARD FAIL, but unusual state", update); -#endif - break; - } - - return 1; - } - break; - - /* finally MODE_UNAVAILABLE */ - case CSB_UPDATE_MODE_UNAVAILABLE: - { - mAttemptLength = now - mStateTS; - if (mState == CSB_PROXY_ATTEMPT) - { - if (mNetState == CSB_NETSTATE_FORWARD) - { -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "as FORWARDED => REVERSE_WAIT", update); -#endif - mState = CSB_REVERSE_WAIT; - mStateTS = now; - mNextAttemptTS = now + REVERSE_WAIT_TIME; - } - else - { -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "as !FORWARDED => RELAY_ATTEMPT", update); -#endif - mState = CSB_RELAY_WAIT; - mNoAttempts = 0; - mStateTS = now; - mNextAttemptTS = now + RSRandom::random_u32() % RELAY_MAX_WAIT_TIME; - } - return 1; - } - else - { -#ifdef DEBUG_CONNECTBOX - stateMsg(std::cerr, "MODE UNAVAIL => FAILED_WAIT", update); -#endif - mState = CSB_FAILED_WAIT; - mStateTS = now; - mNextAttemptTS = now + FAILED_WAIT_TIME; - - if ((mState == CSB_DIRECT_ATTEMPT) - || (mState == CSB_PROXY_ATTEMPT)) - { - /* OKAY */ - return 1; - } - else - { - /* ERROR */ - errorMsg(std::cerr, "strange MODE", update); - - return 0; - } - } - } - break; - - default: - { - /* ERROR */ - errorMsg(std::cerr, "impossible default", update); - } - break; - } - - /* if we get here... ERROR */ - errorMsg(std::cerr, "if we get here => ERROR", update); - - - return 0; -} - - - - - - - - - - -bool PeerConnectStateBox::storeProxyPortChoice(uint32_t flags, bool useProxyPort) -{ - mProxyPortFlags = flags; - mProxyPortChoice = useProxyPort; - mProxyPortTS = time(NULL); - - return useProxyPort; -} - -bool PeerConnectStateBox::getProxyPortChoice() -{ -#ifdef DEBUG_CONNECTBOX - rstime_t now = time(NULL); - - std::cerr << "PeerConnectStateBox::getProxyPortChoice() Using ConnectLogic Info from: "; - std::cerr << now-mProxyPortTS << " ago. Flags: " << mProxyPortFlags; - std::cerr << " UseProxyPort? " << mProxyPortChoice; - std::cerr << std::endl; -#endif - - return mProxyPortChoice; -} - - - diff --git a/libretroshare/src/dht/connectstatebox.h b/libretroshare/src/dht/connectstatebox.h deleted file mode 100644 index 20c6fdb20..000000000 --- a/libretroshare/src/dht/connectstatebox.h +++ /dev/null @@ -1,122 +0,0 @@ -/******************************************************************************* - * libretroshare/src/dht: connectstatebox.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef CONNECT_STATUS_BOX_H -#define CONNECT_STATUS_BOX_H - -/* a connect state box */ - -#define CSB_START 1 -#define CSB_TCP_WAIT 2 -#define CSB_DIRECT_ATTEMPT 3 -#define CSB_DIRECT_WAIT 4 -#define CSB_PROXY_ATTEMPT 5 -#define CSB_PROXY_WAIT 6 -#define CSB_RELAY_ATTEMPT 7 -#define CSB_RELAY_WAIT 8 -#define CSB_REVERSE_WAIT 9 -#define CSB_FAILED_WAIT 10 -#define CSB_CONNECTED 11 - - -#define CSB_NETSTATE_UNKNOWN 0 -#define CSB_NETSTATE_FORWARD 1 -#define CSB_NETSTATE_STABLENAT 2 -#define CSB_NETSTATE_EXCLUSIVENAT 3 -#define CSB_NETSTATE_FIREWALLED 4 - -#define CSB_CONNECT_DIRECT 1 -#define CSB_CONNECT_UNREACHABLE 2 - -/* return values */ -#define CSB_ACTION_MASK_MODE 0x00ff -#define CSB_ACTION_MASK_PORT 0xff00 - -#define CSB_ACTION_WAIT 0x0001 -#define CSB_ACTION_TCP_CONN 0x0002 -#define CSB_ACTION_DIRECT_CONN 0x0004 -#define CSB_ACTION_PROXY_CONN 0x0008 -#define CSB_ACTION_RELAY_CONN 0x0010 - -#define CSB_ACTION_DHT_PORT 0x0100 -#define CSB_ACTION_PROXY_PORT 0x0200 - -/* update input */ -#define CSB_UPDATE_NONE 0x0000 -#define CSB_UPDATE_CONNECTED 0x0001 -#define CSB_UPDATE_DISCONNECTED 0x0002 -#define CSB_UPDATE_AUTH_DENIED 0x0003 -#define CSB_UPDATE_RETRY_ATTEMPT 0x0004 -#define CSB_UPDATE_FAILED_ATTEMPT 0x0005 -#define CSB_UPDATE_MODE_UNAVAILABLE 0x0006 - -#include -#include - -#include -#include "util/rstime.h" -#include - -#include - -class PeerConnectStateBox -{ - public: - PeerConnectStateBox(); - - uint32_t connectCb(uint32_t cbtype, RsNetworkMode netmode, RsNatHoleMode nathole, RsNatTypeMode nattype); - uint32_t updateCb(uint32_t updateType); - - bool shouldUseProxyPort(RsNetworkMode netmode, RsNatHoleMode nathole, RsNatTypeMode nattype); - - uint32_t calcNetState(RsNetworkMode netmode, RsNatHoleMode nathole, RsNatTypeMode nattype); - std::string connectState() const; - - std::string mPeerId; - - bool storeProxyPortChoice(uint32_t flags, bool useProxyPort); - bool getProxyPortChoice(); - - private: - - uint32_t connectCb_direct(); - uint32_t connectCb_unreachable(); - - void errorMsg(std::ostream &out, std::string msg, uint32_t updateParam); - void stateMsg(std::ostream &out, std::string msg, uint32_t updateParam); - - - uint32_t mState; - uint32_t mNetState; - rstime_t mStateTS; - uint32_t mNoAttempts; - uint32_t mNoFailedAttempts; - rstime_t mNextAttemptTS; - rstime_t mAttemptLength; - - // ProxyPort Storage. - uint32_t mProxyPortFlags; - bool mProxyPortChoice; - rstime_t mProxyPortTS; -}; - - -#endif diff --git a/libretroshare/src/dht/p3bitdht.cc b/libretroshare/src/dht/p3bitdht.cc deleted file mode 100644 index 9e4798066..000000000 --- a/libretroshare/src/dht/p3bitdht.cc +++ /dev/null @@ -1,460 +0,0 @@ -/******************************************************************************* - * libretroshare/src/dht: p3bitdht.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009-2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include - -#include "dht/p3bitdht.h" - -#include "bitdht/bdstddht.h" - -#include "tcponudp/udprelay.h" -#ifdef RS_USE_DHT_STUNNER -#include "tcponudp/udpstunner.h" -#endif // RS_USE_DHT_STUNNER - -#include "retroshare/rsbanlist.h" - -#include - - -/* This is a conversion callback class between pqi interface - * and the BitDht Interface. - * - */ - -/**** EXTERNAL INTERFACE DHT POINTER *****/ -RsDht *rsDht = NULL; - -class p3BdCallback: public BitDhtCallback -{ - public: - - p3BdCallback(p3BitDht *parent) - :mParent(parent) { return; } - -virtual int dhtNodeCallback(const bdId *id, uint32_t peerflags) -{ - return mParent->NodeCallback(id, peerflags); -} - -virtual int dhtPeerCallback(const bdId *id, uint32_t status) -{ - return mParent->PeerCallback(id, status); -} - -virtual int dhtValueCallback(const bdNodeId *id, std::string key, uint32_t status) -{ - return mParent->ValueCallback(id, key, status); -} - -virtual int dhtConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId *destId, - uint32_t mode, uint32_t point, uint32_t param, uint32_t cbtype, uint32_t errcode) -{ - return mParent->ConnectCallback(srcId, proxyId, destId, mode, point, param, cbtype, errcode); -} - -virtual int dhtInfoCallback(const bdId *id, uint32_t type, uint32_t flags, std::string info) -{ - return mParent->InfoCallback(id, type, flags, info); -} - - virtual int dhtIsBannedCallback(const sockaddr_in *addr, bool *isBanned) - { - if(!rsBanList) - { - *isBanned = true; // rsBanList is not enabled yet. For security, default to banned. - return 0; - } - - // check whether ip filtering is enabled - // if not return 0 to signal that no filter is available - if(!rsBanList->ipFilteringEnabled()) - return 0; - - // now check the filter - if(rsBanList->isAddressAccepted( - *reinterpret_cast(addr), - RSBANLIST_CHECKING_FLAGS_BLACKLIST )) - { - *isBanned = false; - } else { -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht dhtIsBannedCallback: peer is banned " << sockaddr_storage_tostring(*(const sockaddr_storage*)addr) << std::endl; -#endif - *isBanned = true; - } - - // return 1 to signal that a filter is available - return 1; - } - - private: - - p3BitDht *mParent; -}; - - -p3BitDht::p3BitDht(const RsPeerId& id, pqiConnectCb *cb, p3NetMgr *nm, - UdpStack *udpstack, std::string bootstrapfile, std::string bootstrapfilebak, const std::string& filteredipfile) - :p3Config(), pqiNetAssistConnect(id, cb), mNetMgr(nm), dhtMtx("p3BitDht") -{ -#ifdef RS_USE_DHT_STUNNER - mDhtStunner = NULL; - mProxyStunner = NULL; -#endif - mRelay = NULL; - - mPeerSharer = NULL; - - mRelayHandler = NULL; - - std::string dhtVersion = "RS51"; // should come from elsewhere! - mOwnRsId = id; - - mMinuteTS = 0; - -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::p3BitDht()" << std::endl; - std::cerr << "Using Id: " << id; - std::cerr << std::endl; - std::cerr << "Using Bootstrap File: " << bootstrapfile; - std::cerr << std::endl; - std::cerr << "Converting OwnId to bdNodeId...."; - std::cerr << std::endl; -#endif - - /* setup ownId */ - storeTranslation_locked(id); - lookupNodeId_locked(id, &mOwnDhtId); - - -#ifdef DEBUG_BITDHT - std::cerr << "Own NodeId: "; - bdStdPrintNodeId(std::cerr, &mOwnDhtId); - std::cerr << std::endl; -#endif - - /* standard dht behaviour */ - //bdDhtFunctions *stdfns = new bdStdDht(); - mDhtFns = new bdModDht(); - -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht() startup ... creating UdpBitDht"; - std::cerr << std::endl; -#endif - - /* create dht */ - mUdpBitDht = new UdpBitDht(udpstack, &mOwnDhtId, dhtVersion, bootstrapfile, bootstrapfilebak, filteredipfile,mDhtFns); - udpstack->addReceiver(mUdpBitDht); - - /* setup callback to here */ - p3BdCallback *bdcb = new p3BdCallback(this); - mUdpBitDht->addCallback(bdcb); - -#if 0 - /* enable all modes */ - /* Switched to only Proxy Mode - as Direct Connections can be unreliable - as they share the UDP with the DHT.... - * We'll get these working properly and then if necessary get Direct further tested. - */ - mUdpBitDht->ConnectionOptions( - // BITDHT_CONNECT_MODE_DIRECT | BITDHT_CONNECT_MODE_PROXY | BITDHT_CONNECT_MODE_RELAY, - //BITDHT_CONNECT_MODE_DIRECT | BITDHT_CONNECT_MODE_PROXY, - BITDHT_CONNECT_MODE_PROXY, - BITDHT_CONNECT_OPTION_AUTOPROXY); - -#endif - - setupRelayDefaults(); - - clearDataRates(); -} - -p3BitDht::~p3BitDht() -{ - //udpstack->removeReceiver(mUdpBitDht); - delete mUdpBitDht; -} - - -bool p3BitDht::getOwnDhtId(std::string &ownDhtId) -{ - bdStdPrintNodeId(ownDhtId, &(mOwnDhtId), false); - return true; -} - -#ifdef RS_USE_DHT_STUNNER -void p3BitDht::setupConnectBits(UdpStunner *dhtStunner, UdpStunner *proxyStunner, UdpRelayReceiver *relay) -{ - mDhtStunner = dhtStunner; - mProxyStunner = proxyStunner; - mRelay = relay; -} -#else // RS_USE_DHT_STUNNER -void p3BitDht::setupConnectBits(UdpRelayReceiver *relay) -{ - mRelay = relay; -} -#endif //RS_USE_DHT_STUNNER - -void p3BitDht::setupPeerSharer(pqiNetAssistPeerShare *sharer) -{ - mPeerSharer = sharer; -} - - /* Tweak the DHT Parameters */ -void p3BitDht::modifyNodesPerBucket(uint16_t count) -{ - bdModDht *modFns = (bdModDht *) mDhtFns; - modFns->setNodesPerBucket(count); -} - -/* Support for Outsourced Relay Handling */ - -void p3BitDht::installRelayHandler(p3BitDhtRelayHandler *handler) -{ - /* The Handler is mutex protected, as its installation can occur when the dht is already running */ - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - mRelayHandler = handler; -} - -UdpRelayReceiver *p3BitDht::getRelayReceiver() -{ - return mRelay; -} - - -void p3BitDht::start() -{ -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::start()"; - std::cerr << std::endl; -#endif - - mUdpBitDht->start(); /* starts up the bitdht thread */ - - /* dht switched on by config later. */ -} - - /* pqiNetAssist - external interface functions */ -void p3BitDht::enable(bool on) -{ -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::enable(" << on << ")"; - std::cerr << std::endl; -#endif - - if (on) - { - mUdpBitDht->startDht(); - } - else - { - mUdpBitDht->stopDht(); - } -} - -void p3BitDht::shutdown() /* blocking call */ -{ - mUdpBitDht->stopDht(); -} - - -void p3BitDht::restart() -{ - mUdpBitDht->stopDht(); - mUdpBitDht->startDht(); -} - -bool p3BitDht::getEnabled() -{ - return (mUdpBitDht->stateDht() != 0); -} - -bool p3BitDht::getActive() -{ - return (mUdpBitDht->stateDht() >= BITDHT_MGR_STATE_ACTIVE); -} - -bool p3BitDht::getNetworkStats(uint32_t &netsize, uint32_t &localnetsize) -{ - netsize = mUdpBitDht->statsNetworkSize(); - localnetsize = mUdpBitDht->statsBDVersionSize(); - return true; -} - -#if 0 - /* pqiNetAssistConnect - external interface functions */ - /* add / remove peers */ -bool p3BitDht::findPeer(std::string pid) -{ -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::findPeer(" << pid << ")"; - std::cerr << std::endl; -#endif - - /* convert id -> NodeId */ - if (!storeTranslation(pid)) - { - std::cerr << "p3BitDht::findPeer() Failed to storeTranslation"; - std::cerr << std::endl; - - /* error */ - return false; - } - - bdNodeId nid; - if (!lookupNodeId(pid, &nid)) - { - std::cerr << "p3BitDht::findPeer() Failed to lookupNodeId"; - std::cerr << std::endl; - - /* error */ - return false; - } - -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::findPeer() calling AddFindNode() with pid => NodeId: "; - bdStdPrintNodeId(std::cerr, &nid); - std::cerr << std::endl; -#endif - - /* add in peer */ - mUdpBitDht->addFindNode(&nid, BITDHT_QFLAGS_DO_IDLE); - - return true ; -} - -bool p3BitDht::dropPeer(std::string pid) -{ -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::dropPeer(" << pid << ")"; - std::cerr << std::endl; -#endif - - /* convert id -> NodeId */ - bdNodeId nid; - if (!lookupNodeId(pid, &nid)) - { - std::cerr << "p3BitDht::dropPeer() Failed to lookup NodeId"; - std::cerr << std::endl; - - /* error */ - return false; - } - -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::dropPeer() Translated to NodeId: "; - bdStdPrintNodeId(std::cerr, &nid); - std::cerr << std::endl; -#endif - - /* remove in peer */ - mUdpBitDht->removeFindNode(&nid); - - /* remove from translation */ - if (!removeTranslation(pid)) - { - std::cerr << "p3BitDht::dropPeer() Failed to removeTranslation"; - std::cerr << std::endl; - - /* error */ - return false; - } - - return true ; -} - -#endif - - - /* extract current peer status */ -bool p3BitDht::getPeerStatus(const RsPeerId& id, - struct sockaddr_storage &/*laddr*/, struct sockaddr_storage &/*raddr*/, - uint32_t &/*type*/, uint32_t &/*mode*/) -{ - /* remove unused parameter warnings */ - (void) id; - -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::getPeerStatus(" << id << ")"; - std::cerr << std::endl; -#endif - - return false; -} - -bool p3BitDht::getExternalInterface(struct sockaddr_storage &/*raddr*/, - uint32_t &/*mode*/) -{ - -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::getExternalInterface()"; - std::cerr << std::endl; -#endif - - - return false; -} - -bool p3BitDht::isAddressBanned(const sockaddr_storage &raddr) -{ - if(raddr.ss_family == AF_INET6) // the DHT does not handle INET6 addresses yet. - return false ; - - if(raddr.ss_family == AF_INET) - return mUdpBitDht->isAddressBanned((sockaddr_in&)raddr) ; - - return false ; -} - -void p3BitDht::getListOfBannedIps(std::list& ips) -{ - std::list lst ; - - mUdpBitDht->getListOfBannedIps(lst) ; - - for(std::list::const_iterator it(lst.begin());it!=lst.end();++it) - { - RsDhtFilteredPeer fp ; - fp.mAddr = (*it).mAddr ; - fp.mFilterFlags = (*it).mFilterFlags ; - fp.mFilterTS = (*it).mFilterTS ; - fp.mLastSeen = (*it).mLastSeen ; - ips.push_back(fp) ; - } -} - -bool p3BitDht::setAttachMode(bool on) -{ - -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::setAttachMode(" << on << ")"; - std::cerr << std::endl; -#endif - - return mUdpBitDht->setAttachMode(on); -} - - - - diff --git a/libretroshare/src/dht/p3bitdht.h b/libretroshare/src/dht/p3bitdht.h deleted file mode 100644 index 26cb43847..000000000 --- a/libretroshare/src/dht/p3bitdht.h +++ /dev/null @@ -1,398 +0,0 @@ -/******************************************************************************* - * libretroshare/src/dht: p3bitdht.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009-2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef MRK_P3_BITDHT_H -#define MRK_P3_BITDHT_H - -#include "pqi/pqiassist.h" -#include "pqi/p3cfgmgr.h" -#include "retroshare/rsdht.h" - -#include -#include -#include "pqi/pqinetwork.h" -#include "pqi/pqimonitor.h" -#include "util/rsthreads.h" - -#include "udp/udpstack.h" -#include "udp/udpbitdht.h" -#include "bitdht/bdiface.h" - -#include "dht/connectstatebox.h" - -class DhtPeerDetails -{ - public: - - DhtPeerDetails(); - - RsDhtPeerType mPeerType; - - bdId mDhtId; - RsPeerId mRsId; - - /* direct from the DHT! */ - RsDhtPeerDht mDhtState; - rstime_t mDhtUpdateTS; - - /* internal state */ - PeerConnectStateBox mConnectLogic; - - /* Actual Connection Status */ - RsDhtPeerConnectState mPeerConnectState; - std::string mPeerConnectMsg; - uint32_t mPeerConnectMode; - bdId mPeerConnectPeerId; - bdId mPeerConnectProxyId; - struct sockaddr_in mPeerConnectAddr; - uint32_t mPeerConnectPoint; - - rstime_t mPeerConnectUdpTS; - rstime_t mPeerConnectTS; - rstime_t mPeerConnectClosedTS; - - bool mExclusiveProxyLock; - - /* keeping the PeerCbMsg, as we will need it for debugging */ - /* don't think this data is ever used for decisions??? */ - - /* Connection Request Status */ - std::string mPeerReqStatusMsg; - RsDhtPeerRequest mPeerReqState; - uint32_t mPeerReqMode; - bdId mPeerReqProxyId; - rstime_t mPeerReqTS; - - /* Callback Info */ - std::string mPeerCbMsg; - uint32_t mPeerCbMode; - uint32_t mPeerCbPoint; - bdId mPeerCbProxyId; - bdId mPeerCbDestId; - rstime_t mPeerCbTS; - -}; - -#define PEERNET_ACTION_TYPE_CONNECT 1 -#define PEERNET_ACTION_TYPE_AUTHORISE 2 -#define PEERNET_ACTION_TYPE_START 3 -#define PEERNET_ACTION_TYPE_RESTARTREQ 4 -#define PEERNET_ACTION_TYPE_KILLREQ 5 -#define PEERNET_ACTION_TYPE_TCPATTEMPT 6 - -class PeerAction -{ - public: - - uint32_t mType; - bdId mSrcId; - bdId mProxyId; - bdId mDestId; - uint32_t mMode; - uint32_t mPoint; - uint32_t mAnswer; - uint32_t mDelayOrBandwidth; -}; - - - -/****** - * Adding the ability to install alternative Handler - * for monitoring/controlling Relay Connections outside of p3bitdht. - ***/ - -class p3BitDhtRelayHandler -{ - public: - - int (*mInstallRelay)(const bdId *srcId, const bdId *destId, uint32_t mode, uint32_t &bandwidth); - int (*mLogFailedConnection)(const bdId *srcId, const bdId *destId, uint32_t mode, uint32_t errcode); -}; - - - - -class UdpRelayReceiver; -#ifdef RS_USE_DHT_STUNNER -class UdpStunner; -#endif // RS_USE_DHT_STUNNER -class p3NetMgr; - -class p3BitDht: public p3Config, public pqiNetAssistConnect, public RsDht -{ -public: - p3BitDht(const RsPeerId& id, pqiConnectCb *cb, p3NetMgr *nm, - UdpStack *udpstack, std::string bootstrapfile, std::string bootstrapfilebak, const std::string &filteredipfile); - - - virtual ~p3BitDht(); - - - /*********************************************************************************************** - ********** External RsDHT Interface (defined in libretroshare/src/retroshare/rsdht.h) ********* -************************************************************************************************/ - - virtual uint32_t getNetState(uint32_t type); - virtual int getDhtPeers(int lvl, std::list &peers); - virtual int getNetPeerList(std::list &peerIds); - virtual int getNetPeerStatus(const RsPeerId& peerId, RsDhtNetPeer &status); - - virtual int getRelayEnds(std::list &relayEnds); - virtual int getRelayProxies(std::list &relayProxies); - - //virtual int getNetFailedPeer(std::string peerId, PeerStatus &status); - - virtual std::string getUdpAddressString(); - - virtual void getDhtRates(float &read, float &write); - virtual void getRelayRates(float &read, float &write, float &relay); - - virtual bool getOwnDhtId(std::string &ownDhtId); - - /*********************************************************************************************** - ********** External RsDHT Interface (defined in libretroshare/src/retroshare/rsdht.h) ********* -************************************************************************************************/ - -#ifdef RS_USE_DHT_STUNNER - void setupConnectBits(UdpStunner *dhtStunner, UdpStunner *proxyStunner, UdpRelayReceiver *relay); -#else // RS_USE_DHT_STUNNER - void setupConnectBits(UdpRelayReceiver *relay); -#endif // RS_USE_DHT_STUNNER - void setupPeerSharer(pqiNetAssistPeerShare *sharer); - void modifyNodesPerBucket(uint16_t count); - - void start(); /* starts up the bitdht thread */ - - /* pqiNetAssist - external interface functions */ - virtual int tick(); - virtual void enable(bool on); - virtual void shutdown(); /* blocking call */ - virtual void restart(); - - virtual bool getEnabled(); - virtual bool getActive(); - virtual bool getNetworkStats(uint32_t &netsize, uint32_t &localnetsize); - - /* pqiNetAssistConnect - external interface functions */ - - /* add / remove peers */ - virtual bool findPeer(const RsPeerId& id); - virtual bool dropPeer(const RsPeerId& id); - - virtual int addBadPeer(const struct sockaddr_storage &addr, uint32_t reason, uint32_t flags, uint32_t age); - virtual int addKnownPeer(const RsPeerId &pid, const struct sockaddr_storage &addr, uint32_t flags); - //virtual int addFriend(const std::string pid); - //virtual int addFriendOfFriend(const std::string pid); - //virtual int addOther(const std::string pid); - - /* feedback on success failure of Connections */ - virtual void ConnectionFeedback(const RsPeerId& pid, int state); - - /* extract current peer status */ - virtual bool getPeerStatus(const RsPeerId& id, - struct sockaddr_storage &laddr, struct sockaddr_storage &raddr, - uint32_t &type, uint32_t &mode); - - virtual bool getExternalInterface(struct sockaddr_storage &raddr, - uint32_t &mode); - - virtual bool isAddressBanned(const struct sockaddr_storage& raddr) ; - virtual void getListOfBannedIps(std::list &lst) ; - - virtual bool setAttachMode(bool on); - - - - /* notifyPeer/setExtInterface/Bootstrap/Stun - * hould all be removed from NetAssist? - */ - - - - /* pqiNetAssistConnect - external interface functions */ - - - /*********************************************************************************************** - ****************************** Connections (p3bitdht_peernet.cc) ****************************** -************************************************************************************************/ - /* Feedback from RS Upper Layers */ - //virtual void ConnectionFeedback(std::string pid, int state); - - /* Callback functions - from bitdht */ - int NodeCallback(const bdId *id, uint32_t peerflags); - int PeerCallback(const bdId *id, uint32_t status); - int ValueCallback(const bdNodeId *id, std::string key, uint32_t status); - int ConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId *destId, - uint32_t mode, uint32_t point, uint32_t param, uint32_t cbtype, uint32_t errcode); - int InfoCallback(const bdId *id, uint32_t type, uint32_t flags, std::string info); - - - int OnlinePeerCallback_locked(const bdId *id, uint32_t status, DhtPeerDetails *dpd); - int UnreachablePeerCallback_locked(const bdId *id, uint32_t status, DhtPeerDetails *dpd); - //int tick(); - int minuteTick(); - int doActions(); - int checkProxyAllowed(const bdId *srcId, const bdId *destId, int mode, uint32_t &bandwidth); - int checkConnectionAllowed(const bdId *peerId, int mode); - void initiateConnection(const bdId *srcId, const bdId *proxyId, const bdId *destId, uint32_t mode, uint32_t loc, uint32_t delayOrBandwidth); - int installRelayConnection(const bdId *srcId, const bdId *destId, uint32_t &bandwidth); - int removeRelayConnection(const bdId *srcId, const bdId *destId); - void monitorConnections(); - - void ConnectCallout(const RsPeerId &peerId, struct sockaddr_in addr, uint32_t connectMode); - - void ConnectCalloutTCPAttempt(const RsPeerId &peerId, struct sockaddr_in addr); - void ConnectCalloutDirectOrProxy(const RsPeerId &peerId, struct sockaddr_in raddr, uint32_t connectFlags, uint32_t delay); - void ConnectCalloutRelay(const RsPeerId &peerId, struct sockaddr_in srcaddr, - struct sockaddr_in proxyaddr, struct sockaddr_in destaddr, - uint32_t connectMode, uint32_t bandwidth); - - - void Feedback_Connected(const RsPeerId& pid); - void Feedback_ConnectionFailed(const RsPeerId& pid); - void Feedback_ConnectionClosed(const RsPeerId& pid); - - void UdpConnectionFailed_locked(DhtPeerDetails *dpd); - void ReleaseProxyExclusiveMode_locked(DhtPeerDetails *dpd, bool addrChgLikely); - - - /*** RELAY HANDLER CODE ***/ - void installRelayHandler(p3BitDhtRelayHandler *); - UdpRelayReceiver *getRelayReceiver(); - - int RelayHandler_InstallRelayConnection(const bdId *srcId, const bdId *destId, uint32_t mode, uint32_t &bandwidth); - int RelayHandler_LogFailedProxyAttempt(const bdId *srcId, const bdId *destId, uint32_t mode, uint32_t errcode); - - - - /*********************************************************************************************** - ******************** Relay Config Stuff (TEMP - MOSTLY, in p3bitdht_relay.cc) ***************** - ********** External RsDHT Interface (defined in libretroshare/src/retroshare/rsdht.h) ********* -************************************************************************************************/ - - // Interface for controlling Relays & DHT Relay Mode - virtual int getRelayServerList(std::list &ids); - virtual int addRelayServer(std::string ids); - virtual int removeRelayServer(std::string ids); - - virtual RsDhtRelayMode getRelayMode(); - virtual int setRelayMode(RsDhtRelayMode mode); - - virtual int getRelayAllowance(RsDhtRelayClass classIdx, uint32_t &count, uint32_t &bandwidth); - virtual int setRelayAllowance(RsDhtRelayClass classIdx, uint32_t count, uint32_t bandwidth); - -private: - - // Relay Handling Code / Variables (Mutex Protected). - int setupRelayDefaults(); - int pushRelayServers(); - - std::list mRelayServerList; - RsDhtRelayMode mRelayMode; - -protected: - /*****************************************************************/ - /*********************** p3config ******************************/ - /* Key Functions to be overloaded for Full Configuration */ - virtual RsSerialiser *setupSerialiser(); - virtual bool saveList(bool &cleanup, std::list&); - virtual void saveDone(); - virtual bool loadList(std::list& load); - /*****************************************************************/ - - // DATA RATES: Variables (Mutex Protected). -private: - - void updateDataRates(); - void clearDataRates(); - - float mRelayReadRate; - float mRelayWriteRate; - float mRelayRelayRate; - float mDhtReadRate; - float mDhtWriteRate; - - rstime_t mLastDataRateUpdate; - - - /*********************************************************************************************** - ************************** Internal Accounting (p3bitdht_peers.cc) **************************** -************************************************************************************************/ - -public: - - int removePeer(const RsPeerId& pid); - - // Can be used externally too. - int calculateNodeId(const RsPeerId& pid, bdNodeId *id); - int addKnownNode(const bdId *id, uint32_t flags); - -private: - - DhtPeerDetails *addInternalPeer_locked(const RsPeerId& pid, RsDhtPeerType type); - int removeInternalPeer_locked(const RsPeerId& pid); - DhtPeerDetails *findInternalDhtPeer_locked(const bdNodeId *id, RsDhtPeerType type); - DhtPeerDetails *findInternalRsPeer_locked(const RsPeerId &pid); - - bool havePeerTranslation_locked(const RsPeerId &pid); - int lookupNodeId_locked(const RsPeerId& pid, bdNodeId *id); - int lookupRsId_locked(const bdNodeId *id, RsPeerId &pid); - int storeTranslation_locked(const RsPeerId& pid); - int removeTranslation_locked(const RsPeerId& pid); - - UdpBitDht *mUdpBitDht; /* has own mutex, is static except for creation/destruction */ -#ifdef RS_USE_DHT_STUNNER - UdpStunner *mDhtStunner; - UdpStunner *mProxyStunner; -#endif // RS_USE_DHT_STUNNER - UdpRelayReceiver *mRelay; - - p3NetMgr *mNetMgr; - - pqiNetAssistPeerShare *mPeerSharer; - - bdDhtFunctions *mDhtFns; - - RsMutex dhtMtx; - - - p3BitDhtRelayHandler *mRelayHandler; - - RsPeerId mOwnRsId; - bdNodeId mOwnDhtId; - - rstime_t mMinuteTS; - - /* translation maps */ - std::map mTransToNodeId; - std::map mTransToRsId; - - std::map mPeers; - std::map mFailedPeers; - - /* Connection Action Queue */ - std::list mActions; - -}; - -#endif /* MRK_P3_BITDHT_H */ - diff --git a/libretroshare/src/dht/p3bitdht_interface.cc b/libretroshare/src/dht/p3bitdht_interface.cc deleted file mode 100644 index b31bbd03c..000000000 --- a/libretroshare/src/dht/p3bitdht_interface.cc +++ /dev/null @@ -1,387 +0,0 @@ -/******************************************************************************* - * libretroshare/src/dht: p3bitdht_interface.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009-2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "util/rsnet.h" -#include "dht/p3bitdht.h" - -#include "tcponudp/udprelay.h" -#include "tcponudp/udpstunner.h" -#include "bitdht/bdstddht.h" - - -void convertBdPeerToRsDhtPeer(RsDhtPeer &peer, const bdPeer &int_peer); -void convertDhtPeerDetailsToRsDhtNetPeer(RsDhtNetPeer &status, const DhtPeerDetails &details); -void convertUdpRelayEndtoRsDhtRelayEnd(RsDhtRelayEnd &end, const UdpRelayEnd &int_end); -void convertUdpRelayProxytoRsDhtRelayProxy(RsDhtRelayProxy &proxy, const UdpRelayProxy &int_proxy); - - -/*********************************************************************************************** - ********** External RsDHT Interface (defined in libretroshare/src/retroshare/rsdht.h) ********* -************************************************************************************************/ - -uint32_t p3BitDht::getNetState(uint32_t /*type*/) -{ - - return 1; -} - -int p3BitDht::getDhtPeers(int lvl, std::list &peers) -{ - /* this function we can actually implement! */ - bdBucket int_peers; - std::list::iterator it; - mUdpBitDht->getDhtBucket(lvl, int_peers); - - for(it = int_peers.entries.begin(); it != int_peers.entries.end(); ++it) - { - RsDhtPeer peer; - - convertBdPeerToRsDhtPeer(peer, *it); - peer.mBucket = lvl; - - peers.push_back(peer); - } - return (int_peers.entries.size() > 0); -} - -int p3BitDht::getNetPeerList(std::list &peerIds) -{ - RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ - std::map::iterator it; - for(it = mPeers.begin(); it != mPeers.end(); ++it) - { - peerIds.push_back(it->second.mRsId); - } - - return 1; -} - -int p3BitDht::getNetPeerStatus(const RsPeerId& peerId, RsDhtNetPeer &status) -{ - - RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ - - DhtPeerDetails *dpd = findInternalRsPeer_locked(peerId); - if (!dpd) - { - return 0; - } - - convertDhtPeerDetailsToRsDhtNetPeer(status, *dpd); - return 1; -} - - -int p3BitDht::getRelayEnds(std::list &relayEnds) -{ - /* no need for mutex as mRelayReceiver is protected */ - if (!mRelay) - { - return 0; - } - - std::list int_relayEnds; - std::list::iterator it; - mRelay->getRelayEnds(int_relayEnds); - - for(it = int_relayEnds.begin(); it != int_relayEnds.end(); ++it) - { - RsDhtRelayEnd end; - convertUdpRelayEndtoRsDhtRelayEnd(end, *it); - - relayEnds.push_back(end); - } - return 1; -} - - -int p3BitDht::getRelayProxies(std::list &relayProxies) -{ - /* no need for mutex as mRelayReceiver is protected */ - if (!mRelay) - { - return 0; - } - - std::list int_relayProxies; - std::list::iterator it; - mRelay->getRelayProxies(int_relayProxies); - - for(it = int_relayProxies.begin(); it != int_relayProxies.end(); ++it) - { - RsDhtRelayProxy proxy; - convertUdpRelayProxytoRsDhtRelayProxy(proxy, *it); - relayProxies.push_back(proxy); - } - return 1; -} - - -#if 0 -int p3BitDht::getNetFailedPeer(std::string peerId, PeerStatus &status) -{ - return 1; -} -#endif - -std::string p3BitDht::getUdpAddressString() -{ - std::string out; -#ifdef RS_USE_DHT_STUNNER - struct sockaddr_in extAddr; - uint8_t extStable; - - if (mDhtStunner->externalAddr(extAddr, extStable)) - { - rs_sprintf_append(out, " DhtExtAddr: %s:%u", rs_inet_ntoa(extAddr.sin_addr).c_str(), ntohs(extAddr.sin_port)); - - if (extStable) - { - out += " (Stable) "; - } - else - { - out += " (Unstable) "; - } - } - else - { - out += " DhtExtAddr: Unknown "; - } - if (mProxyStunner->externalAddr(extAddr, extStable)) - { - rs_sprintf_append(out, " ProxyExtAddr: %s:%u", rs_inet_ntoa(extAddr.sin_addr).c_str(), ntohs(extAddr.sin_port)); - - if (extStable) - { - out += " (Stable) "; - } - else - { - out += " (Unstable) "; - } - } - else - { - out += " ProxyExtAddr: Unknown "; - } -#else // RS_USE_DHT_STUNNER - // whitespaces taken from above - out = " DhtExtAddr: Unknown ProxyExtAddr: Unknown "; -#endif // RS_USE_DHT_STUNNER - return out; -} - -void p3BitDht::updateDataRates() -{ - uint32_t relayRead = 0; - uint32_t relayWrite = 0; - uint32_t relayRelay = 0; - uint32_t dhtRead = 0; - uint32_t dhtWrite = 0; - - mRelay->getDataTransferred(relayRead, relayWrite, relayRelay); - mUdpBitDht->getDataTransferred(dhtRead, dhtWrite); - - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - rstime_t now = time(NULL); - float period = now - mLastDataRateUpdate; - -#define RATE_FACTOR (0.75) - - mRelayReadRate *= RATE_FACTOR; - mRelayReadRate += (1.0 - RATE_FACTOR) * (relayRead / period); - - mRelayWriteRate *= RATE_FACTOR; - mRelayWriteRate += (1.0 - RATE_FACTOR) * (relayWrite / period); - - mRelayRelayRate *= RATE_FACTOR; - mRelayRelayRate += (1.0 - RATE_FACTOR) * (relayRelay / period); - - mDhtReadRate *= RATE_FACTOR; - mDhtReadRate += (1.0 - RATE_FACTOR) * (dhtRead / period); - - mDhtWriteRate *= RATE_FACTOR; - mDhtWriteRate += (1.0 - RATE_FACTOR) * (dhtWrite / period); - - mLastDataRateUpdate = now; - -} - -void p3BitDht::clearDataRates() -{ - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - mRelayReadRate = 0; - mRelayWriteRate = 0; - mRelayRelayRate = 0; - mDhtReadRate = 0; - mDhtWriteRate = 0; - - mLastDataRateUpdate = time(NULL); -} - - -/* in kB/s */ -void p3BitDht::getDhtRates(float &read, float &write) -{ - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - read = mDhtReadRate / 1024.0; - write = mDhtWriteRate / 1024.0; -} - -void p3BitDht::getRelayRates(float &read, float &write, float &relay) -{ - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - read = mRelayReadRate / 1024.0; - write = mRelayWriteRate / 1024.0; - relay = mRelayRelayRate / 1024.0; -} - - - -/*********************************************************************************************** - ********** External RsDHT Interface (defined in libretroshare/src/retroshare/rsdht.h) ********* -************************************************************************************************/ - -void convertBdPeerToRsDhtPeer(RsDhtPeer &peer, const bdPeer &int_peer) -{ - bdStdPrintNodeId(peer.mDhtId, &(int_peer.mPeerId.id), false); - - rs_sprintf(peer.mAddr, "%s:%u", rs_inet_ntoa(int_peer.mPeerId.addr.sin_addr).c_str(), ntohs(int_peer.mPeerId.addr.sin_port)); - - peer.mLastSendTime = int_peer.mLastSendTime; - peer.mLastRecvTime = int_peer.mLastRecvTime; - peer.mFoundTime = int_peer.mFoundTime; - peer.mPeerFlags = int_peer.mPeerFlags; - peer.mExtraFlags = int_peer.mExtraFlags; -} - - - -void convertDhtPeerDetailsToRsDhtNetPeer(RsDhtNetPeer &status, const DhtPeerDetails &details) -{ - bdStdPrintId(status.mDhtId, &(details.mDhtId), false); - - status.mRsId = details.mRsId; - - status.mPeerType = details.mPeerType; - - status.mDhtState = details.mDhtState; - - status.mConnectState = details.mConnectLogic.connectState(); - - status.mPeerReqState = details.mPeerReqState; - - status.mExclusiveProxyLock = details.mExclusiveProxyLock; - - status.mPeerConnectState = details.mPeerConnectState; - - switch(details.mPeerConnectMode) - { - default: - status.mPeerConnectMode = RsDhtTouMode::NONE; - break; - case BITDHT_CONNECT_MODE_DIRECT: - status.mPeerConnectMode = RsDhtTouMode::DIRECT; - break; - case BITDHT_CONNECT_MODE_PROXY: - status.mPeerConnectMode = RsDhtTouMode::PROXY; - break; - case BITDHT_CONNECT_MODE_RELAY: - status.mPeerConnectMode = RsDhtTouMode::RELAY; - break; - } - - //status.mPeerConnectProxyId = details.mPeerConnectProxyId; - bdStdPrintId(status.mPeerConnectProxyId, &(details.mPeerConnectProxyId), false); - - status.mCbPeerMsg = details.mPeerCbMsg; - - return; -} - -void convertUdpRelayEndtoRsDhtRelayEnd(RsDhtRelayEnd &end, const UdpRelayEnd &int_end) -{ - rs_sprintf(end.mLocalAddr, "%s:%u", rs_inet_ntoa(int_end.mLocalAddr.sin_addr).c_str(), ntohs(int_end.mLocalAddr.sin_port)); - rs_sprintf(end.mProxyAddr, "%s:%u", rs_inet_ntoa(int_end.mProxyAddr.sin_addr).c_str(), ntohs(int_end.mProxyAddr.sin_port)); - rs_sprintf(end.mRemoteAddr, "%s:%u", rs_inet_ntoa(int_end.mRemoteAddr.sin_addr).c_str(), ntohs(int_end.mRemoteAddr.sin_port)); - - end.mCreateTS = 0; - return; -} - -void convertUdpRelayProxytoRsDhtRelayProxy(RsDhtRelayProxy &proxy, const UdpRelayProxy &int_proxy) -{ - rs_sprintf(proxy.mSrcAddr, "%s:%u", rs_inet_ntoa(int_proxy.mAddrs.mSrcAddr.sin_addr).c_str(), ntohs(int_proxy.mAddrs.mSrcAddr.sin_port)); - rs_sprintf(proxy.mDestAddr, "%s:%u", rs_inet_ntoa(int_proxy.mAddrs.mDestAddr.sin_addr).c_str(), ntohs(int_proxy.mAddrs.mDestAddr.sin_port)); - - proxy.mBandwidth = int_proxy.mBandwidth; - proxy.mRelayClass = int_proxy.mRelayClass; - proxy.mLastTS = int_proxy.mLastTS; - proxy.mCreateTS = 0; - - //proxy.mDataSize = int_proxy.mDataSize; - //proxy.mLastBandwidthTS = int_proxy.mLastBandwidthTS; -} - -RsDhtPeer::RsDhtPeer() -{ - mBucket = 0; - - //std::string mDhtId; - mLastSendTime = 0; - mLastRecvTime = 0; - mFoundTime = 0; - mPeerFlags = 0; - mExtraFlags = 0; -} - - -RsDhtNetPeer::RsDhtNetPeer() -{ - return; -} - - -RsDhtRelayEnd::RsDhtRelayEnd() -{ - mCreateTS = 0; -} - - -RsDhtRelayProxy::RsDhtRelayProxy() -{ - mBandwidth = 0; - mRelayClass = 0; - mLastTS = 0; - mCreateTS = 0; - - //uint32_t mDataSize; - //rstime_t mLastBandwidthTS; - -} - - diff --git a/libretroshare/src/dht/p3bitdht_peernet.cc b/libretroshare/src/dht/p3bitdht_peernet.cc deleted file mode 100644 index a37678728..000000000 --- a/libretroshare/src/dht/p3bitdht_peernet.cc +++ /dev/null @@ -1,2533 +0,0 @@ -/******************************************************************************* - * libretroshare/src/dht: p3bitdht_peernet.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009-2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "dht/p3bitdht.h" - -#include -#include - - -#include "bitdht/bdiface.h" -#include "bitdht/bdstddht.h" -#include "bitdht/bdmanager.h" - -//#include "udp/udplayer.h" - -#include "util/rsnet.h" -#include "tcponudp/tou.h" -#include "tcponudp/udpstunner.h" -#include "tcponudp/udprelay.h" - -#include "pqi/p3netmgr.h" -#include "pqi/pqimonitor.h" - -#define PEERNET_CONNECT_TIMEOUT 180 // Should be BIGGER than Higher level (but okay if not!) - -#define MIN_DETERMINISTIC_SWITCH_PERIOD 60 - -/*** - * - * #define DEBUG_BITDHT_COMMON 1 // These are the things that are called regularly (annoying for debugging specifics) - * #define DEBUG_PEERNET 1 - * - **/ - - -/****************************************************************************************** - ************************************* Dht Callback *************************************** - ******************************************************************************************/ - -/**** dht NodeCallback **** - * - * - * In the old version, we used this to callback mConnCb->peerStatus() - * We might want to drop this, and concentrate on the connection stuff. - * - * -> if an new dht peer, then pass to Stunners. - * -> do we care if we know them? not really! - */ - -int p3BitDht::InfoCallback(const bdId *id, uint32_t /*type*/, uint32_t /*flags*/, std::string /*info*/) -{ - /* translate info */ - RsPeerId rsid; - struct sockaddr_in addr = id->addr; - int outtype = PNASS_TYPE_BADPEER; - int outreason = PNASS_REASON_UNKNOWN; - int outage = 0; - -#ifdef DEBUG_BITDHT_COMMON - std::cerr << "p3BitDht::InfoCallback() likely BAD_PEER: "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - { - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(id->id), RsDhtPeerType::ANY); - - if (dpd) - { - rsid = dpd->mRsId; - } - } - - if (mPeerSharer) - { - struct sockaddr_storage tmpaddr; - struct sockaddr_in *ap = (struct sockaddr_in *) &tmpaddr; - ap->sin_family = AF_INET; - ap->sin_addr = addr.sin_addr; - ap->sin_port = addr.sin_port; - - mPeerSharer->updatePeer(rsid, tmpaddr, outtype, outreason, outage); - } - -#ifdef RS_USE_DHT_STUNNER - /* call to the Stunners to drop the address as well */ - /* IDEALLY these addresses should all be filtered at UdpLayer level instead! */ - if (mDhtStunner) - { - mDhtStunner->dropStunPeer(addr); - } - if (mProxyStunner) - { - mProxyStunner->dropStunPeer(addr); - } -#endif // RS_USE_DHT_STUNNER - - return 1; -} - - - -/**** dht NodeCallback **** - * - * - * In the old version, we used this to callback mConnCb->peerStatus() - * We might want to drop this, and concentrate on the connection stuff. - * - * -> if an new dht peer, then pass to Stunners. - * -> do we care if we know them? not really! - */ - -int p3BitDht::NodeCallback(const bdId *id, uint32_t peerflags) -{ - // No need for Mutex, and Stunners are self protected. - - // These are the flags that will be returned by p3BitDht & RS peers with the new DHT. - // if (peerflags & BITDHT_PEER_STATUS_DHT_ENGINE_VERSION) // Change to this later... - if ((peerflags & BITDHT_PEER_STATUS_DHT_ENGINE) && - (peerflags & BITDHT_PEER_STATUS_DHT_APPL)) - { - - /* pass off to the Stunners - * but only if they need them. - * ideally don't pass to both peers... (XXX do later) - */ - - { - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - if (id->id == mOwnDhtId) - { -#ifdef DEBUG_BITDHT_COMMON - std::cerr << "p3BitDht::NodeCallback() Skipping own id"; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - return 1; - } - } - -#ifdef RS_USE_DHT_STUNNER - if ((mProxyStunner) && (mProxyStunner->needStunPeers())) - { -#ifdef DEBUG_BITDHT_COMMON - std::cerr << "p3BitDht::NodeCallback() Passing BitDHT Peer to DhtStunner: "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - mProxyStunner->addStunPeer(id->addr, NULL); - } - /* else */ // removed else until we have lots of peers. - - if ((mDhtStunner) && (mDhtStunner->needStunPeers())) - { -#ifdef DEBUG_BITDHT_COMMON - std::cerr << "p3BitDht::NodeCallback() Passing BitDHT Peer to DhtStunner: "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - mDhtStunner->addStunPeer(id->addr, NULL); - } -#endif // RS_USE_DHT_STUNNER - } - return 1; -} - -/**** dht PeerCallback **** - * - * - * In the old version, we used this to callback mConnCb->peerConnectRequest() - * we need to continue doing this, to maintain compatibility. - * - * -> update Dht Status, and trigger connect if ONLINE or UNREACHABLE - */ - - -int p3BitDht::PeerCallback(const bdId *id, uint32_t status) -{ - //std::string str; - //bdStdPrintNodeId(str, &(id->id)); - - //std::cerr << "p3BitDht::dhtPeerCallback()"; - //std::cerr << std::endl; - - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(id->id), RsDhtPeerType::FRIEND); - - if (!dpd) - { - /* ERROR */ - std::cerr << "p3BitDht::PeerCallback() ERROR Unknown Peer: "; - bdStdPrintId(std::cerr, id); - std::cerr << " status: " << status; - std::cerr << std::endl; - - return 0; - } - - sockaddr_clear(&(dpd->mDhtId.addr)); - - switch(status) - { - default: - dpd->mDhtState = RsDhtPeerDht::NOT_ACTIVE; - break; - - case BITDHT_MGR_QUERY_FAILURE: - dpd->mDhtState = RsDhtPeerDht::FAILURE; - break; - - case BITDHT_MGR_QUERY_PEER_OFFLINE: - dpd->mDhtState = RsDhtPeerDht::OFFLINE; - break; - - case BITDHT_MGR_QUERY_PEER_UNREACHABLE: - dpd->mDhtState = RsDhtPeerDht::UNREACHABLE; - dpd->mDhtId = *id; // set the IP:Port of the unreachable peer. - UnreachablePeerCallback_locked(id, status, dpd); - - break; - - case BITDHT_MGR_QUERY_PEER_ONLINE: - dpd->mDhtState = RsDhtPeerDht::ONLINE; - dpd->mDhtId = *id; // set the IP:Port of the Online peer. - OnlinePeerCallback_locked(id, status, dpd); - - break; - - } - - rstime_t now = time(NULL); - dpd->mDhtUpdateTS = now; - - return 1; -} - - - -int p3BitDht::OnlinePeerCallback_locked(const bdId *id, uint32_t /*status*/, DhtPeerDetails *dpd) -{ - /* remove unused parameter warnings */ - (void) id; - - if ((dpd->mPeerConnectState != RsDhtPeerConnectState::DISCONNECTED) || - (dpd->mPeerReqState == RsDhtPeerRequest::RUNNING)) - { - -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::OnlinePeerCallback_locked() WARNING Ignoring Callback: connection already underway: "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - - return 1; - } - - bool connectOk = true; - bool doTCPCallback = false; - - /* work out network state */ - uint32_t connectFlags = dpd->mConnectLogic.connectCb(CSB_CONNECT_DIRECT, - mNetMgr->getNetworkMode(), mNetMgr->getNatHoleMode(), mNetMgr->getNatTypeMode()); -// bool useProxyPort = (connectFlags & CSB_ACTION_PROXY_PORT); - - switch(connectFlags & CSB_ACTION_MASK_MODE) - { - default: - case CSB_ACTION_WAIT: - { - connectOk = false; - } - break; - case CSB_ACTION_TCP_CONN: - { - connectOk = false; - doTCPCallback = true; - } - break; - case CSB_ACTION_DIRECT_CONN: - { - - connectOk = true; - } - break; - case CSB_ACTION_PROXY_CONN: - { - /* ERROR */ - std::cerr << "dhtPeerCallback: ERROR ConnectLogic returned PROXY"; - std::cerr << std::endl; - connectOk = false; - } - break; - case CSB_ACTION_RELAY_CONN: - { - /* ERROR */ - std::cerr << "dhtPeerCallback: ERROR ConnectLogic returned RELAY"; - std::cerr << std::endl; - connectOk = false; - } - break; - } - - if (connectOk) - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtPeerCallback. Peer Online, triggering Direct Connection for: "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - - /* Push Back PeerAction */ - PeerAction ca; - ca.mType = PEERNET_ACTION_TYPE_CONNECT; - ca.mMode = BITDHT_CONNECT_MODE_DIRECT; - ca.mDestId = *id; - ca.mAnswer = BITDHT_CONNECT_ERROR_NONE; - - mActions.push_back(ca); - } - - /* might need to make this an ACTION - leave for now */ - if (doTCPCallback) - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtPeerCallback. Peer Online, triggering TCP Connection for: "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - - /* Push Back PeerAction */ - PeerAction ca; - ca.mType = PEERNET_ACTION_TYPE_TCPATTEMPT; - ca.mMode = BITDHT_CONNECT_MODE_DIRECT; - ca.mDestId = *id; - ca.mAnswer = BITDHT_CONNECT_ERROR_NONE; - - mActions.push_back(ca); - //ConnectCalloutTCPAttempt(dpd->mRsId, id->addr); - } - - return 1; -} - - - -int p3BitDht::UnreachablePeerCallback_locked(const bdId *id, uint32_t /*status*/, DhtPeerDetails *dpd) -{ - - if ((dpd->mPeerConnectState != RsDhtPeerConnectState::DISCONNECTED) || - (dpd->mPeerReqState == RsDhtPeerRequest::RUNNING)) - { - -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::UnreachablePeerCallback_locked() WARNING Ignoring Callback: connection already underway: "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - - return 1; - } - -#ifdef DEBUG_PEERNET - std::cerr << "dhtPeerCallback. Peer Unreachable, triggering Proxy | Relay Connection for: "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - - bool proxyOk = false; - bool connectOk = true; - - /* work out network state */ - uint32_t connectFlags = dpd->mConnectLogic.connectCb(CSB_CONNECT_UNREACHABLE, - mNetMgr->getNetworkMode(), mNetMgr->getNatHoleMode(), mNetMgr->getNatTypeMode()); - bool useProxyPort = (connectFlags & CSB_ACTION_PROXY_PORT); - - switch(connectFlags & CSB_ACTION_MASK_MODE) - { - default: - case CSB_ACTION_WAIT: - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtPeerCallback. Request to Wait ... so no Connection Attempt for "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - connectOk = false; - } - break; - case CSB_ACTION_DIRECT_CONN: - { - /* ERROR */ - std::cerr << "dhtPeerCallback: ERROR ConnectLogic returned DIRECT"; - std::cerr << std::endl; - - connectOk = false; - } - break; - case CSB_ACTION_PROXY_CONN: - { - proxyOk = true; - connectOk = true; - } - break; - case CSB_ACTION_RELAY_CONN: - { - proxyOk = false; - connectOk = true; - } - break; - } - - if (connectOk) - { - /* Push Back PeerAction */ - PeerAction ca; - ca.mType = PEERNET_ACTION_TYPE_CONNECT; - ca.mDestId = *id; - - dpd->mConnectLogic.storeProxyPortChoice(connectFlags, useProxyPort); - - if (proxyOk) - { - ca.mMode = BITDHT_CONNECT_MODE_PROXY; -#ifdef DEBUG_PEERNET - std::cerr << "dhtPeerCallback. Trying Proxy Connection."; - std::cerr << std::endl; -#endif - } - else - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtPeerCallback. Trying Relay Connection."; - std::cerr << std::endl; -#endif - ca.mMode = BITDHT_CONNECT_MODE_RELAY; - } - - ca.mAnswer = BITDHT_CONNECT_ERROR_NONE; - mActions.push_back(ca); - } - else - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtPeerCallback. Cancelled Connection Attempt for "; - bdStdPrintId(std::cerr, id); - std::cerr << std::endl; -#endif - } - - return 1; -} - - - -int p3BitDht::ValueCallback(const bdNodeId */*id*/, std::string /*key*/, uint32_t /*status*/) -{ - std::cerr << "p3BitDht::ValueCallback() ERROR Does nothing!"; - std::cerr << std::endl; - - return 1; -} - -int p3BitDht::ConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId *destId, - uint32_t mode, uint32_t point, uint32_t param, uint32_t cbtype, uint32_t errcode) -{ -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::ConnectCallback()"; - std::cerr << std::endl; - std::cerr << "srcId: "; - bdStdPrintId(std::cerr, srcId); - std::cerr << std::endl; - std::cerr << "proxyId: "; - bdStdPrintId(std::cerr, proxyId); - std::cerr << std::endl; - std::cerr << "destId: "; - bdStdPrintId(std::cerr, destId); - std::cerr << std::endl; - - std::cerr << " mode: " << mode; - std::cerr << " param: " << param; - std::cerr << " point: " << point; - std::cerr << " cbtype: " << cbtype; - std::cerr << std::endl; -#endif - - - /* we handle MID and START/END points differently... this is biggest difference. - * so handle first. - */ - - bdId peerId; - rstime_t now = time(NULL); - - switch(point) - { - default: - case BD_PROXY_CONNECTION_UNKNOWN_POINT: - { - std::cerr << "p3BitDht::dhtConnectCallback() ERROR UNKNOWN point, ignoring Callback"; - std::cerr << std::endl; - return 0; - } - case BD_PROXY_CONNECTION_START_POINT: - peerId = *destId; - break; - case BD_PROXY_CONNECTION_END_POINT: - peerId = *srcId; - break; - case BD_PROXY_CONNECTION_MID_POINT: - { - /* AS a mid point, we can receive.... AUTH,PENDING,PROXY,FAILED */ - - switch(cbtype) - { - case BITDHT_CONNECT_CB_AUTH: - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Proxy Connection Requested Between:"; - std::cerr << std::endl; - bdStdPrintId(std::cerr, srcId); - std::cerr << " and "; - bdStdPrintId(std::cerr, destId); - std::cerr << std::endl; -#endif - /* if there is an error code - then it is just to inform us of a failed attempt */ - if (errcode) - { - RelayHandler_LogFailedProxyAttempt(srcId, destId, mode, errcode); - /* END MID FAILED ATTEMPT */ - return 1; - } - - uint32_t bandwidth = 0; - - int connectionAllowed = BITDHT_CONNECT_ERROR_GENERIC; - if (checkProxyAllowed(srcId, destId, mode, bandwidth)) - { - connectionAllowed = BITDHT_CONNECT_ANSWER_OKAY; -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Connection Allowed"; - std::cerr << std::endl; -#endif - } - else - { - connectionAllowed = BITDHT_CONNECT_ERROR_AUTH_DENIED; -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Connection Denied"; - std::cerr << std::endl; -#endif - } - - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - /* Push Back PeerAction */ - PeerAction ca; - ca.mType = PEERNET_ACTION_TYPE_AUTHORISE; - ca.mMode = mode; - ca.mProxyId = *proxyId; - ca.mSrcId = *srcId; - ca.mDestId = *destId; - ca.mPoint = point; - ca.mAnswer = connectionAllowed; - ca.mDelayOrBandwidth = bandwidth; - - mActions.push_back(ca); - } - break; - case BITDHT_CONNECT_CB_PENDING: - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Proxy Connection Pending:"; - std::cerr << std::endl; - bdStdPrintId(std::cerr, srcId); - std::cerr << " and "; - bdStdPrintId(std::cerr, destId); - std::cerr << std::endl; -#endif - } - break; - case BITDHT_CONNECT_CB_PROXY: - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Proxy Connection Starting:"; - std::cerr << std::endl; - bdStdPrintId(std::cerr, srcId); - std::cerr << " and "; - bdStdPrintId(std::cerr, destId); - std::cerr << std::endl; -#endif - } - break; - case BITDHT_CONNECT_CB_FAILED: - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Proxy Connection Failed:"; - std::cerr << std::endl; - bdStdPrintId(std::cerr, srcId); - std::cerr << " and "; - bdStdPrintId(std::cerr, destId); - - std::cerr << " ErrorCode: " << errcode; - int errsrc = errcode & BITDHT_CONNECT_ERROR_MASK_SOURCE; - int errtype = errcode & BITDHT_CONNECT_ERROR_MASK_TYPE; - - std::cerr << " ErrorSrc: " << errsrc; - std::cerr << " ErrorType: " << errtype; - - std::cerr << std::endl; -#endif - - if (mode == BITDHT_CONNECT_MODE_RELAY) - { - removeRelayConnection(srcId, destId); - } - } - break; - default: - case BITDHT_CONNECT_CB_START: - { - std::cerr << "dhtConnectionCallback() ERROR unexpected Proxy ConnectionCallback:"; - std::cerr << std::endl; - bdStdPrintId(std::cerr, srcId); - std::cerr << " and "; - bdStdPrintId(std::cerr, destId); - std::cerr << std::endl; - } - break; - } - /* End the MID Point stuff */ - return 1; - } - } - - /* if we get here, we are an endpoint (peer specified in peerId) */ - - /* translate id into string for exclusive mode */ - std::string pid; - bdStdPrintNodeId(pid, &(peerId.id), false); - - switch(cbtype) - { - case BITDHT_CONNECT_CB_AUTH: - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Connection Requested By: "; - bdStdPrintId(std::cerr, &(peerId)); - std::cerr << std::endl; -#endif - - int connectionAllowed = BITDHT_CONNECT_ERROR_GENERIC; - if (checkConnectionAllowed(&(peerId), mode)) - { - connectionAllowed = BITDHT_CONNECT_ANSWER_OKAY; -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Connection Allowed"; - std::cerr << std::endl; -#endif - } - else - { - connectionAllowed = BITDHT_CONNECT_ERROR_AUTH_DENIED; -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Connection Denied"; - std::cerr << std::endl; -#endif - } - - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - /* Push Back PeerAction */ - PeerAction ca; - ca.mType = PEERNET_ACTION_TYPE_AUTHORISE; - ca.mProxyId = *proxyId; - ca.mSrcId = *srcId; - ca.mDestId = *destId; - ca.mDelayOrBandwidth = 0; - - /* Check Proxy ExtAddress Status (but only if connection is Allowed) */ - if ((connectionAllowed == BITDHT_CONNECT_ANSWER_OKAY) && - (mode == BITDHT_CONNECT_MODE_PROXY)) - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Checking Address for Proxy"; - std::cerr << std::endl; -#endif - - struct sockaddr_in extaddr; - sockaddr_clear(&extaddr); - - bool connectOk = false; - bool proxyPort = false; - bool exclusivePort = false; -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback(): Proxy... deciding which port to use."; - std::cerr << std::endl; -#endif - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(peerId.id), RsDhtPeerType::FRIEND); - if (dpd) - { - proxyPort = dpd->mConnectLogic.shouldUseProxyPort( - mNetMgr->getNetworkMode(), mNetMgr->getNatHoleMode(), mNetMgr->getNatTypeMode()); - - dpd->mConnectLogic.storeProxyPortChoice(0, proxyPort); - -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback: Setting ProxyPort: "; - std::cerr << " UseProxyPort? " << proxyPort; - std::cerr << std::endl; - - std::cerr << "dhtConnectionCallback: Checking ConnectLogic.NetState: "; - std::cerr << dpd->mConnectLogic.calcNetState(mNetMgr->getNetworkMode(), mNetMgr->getNatHoleMode(), mNetMgr->getNatTypeMode()); - std::cerr << std::endl; -#endif - - if (proxyPort) - { - exclusivePort = (CSB_NETSTATE_EXCLUSIVENAT == dpd->mConnectLogic.calcNetState( - mNetMgr->getNetworkMode(), mNetMgr->getNatHoleMode(), mNetMgr->getNatTypeMode())); - } - -#ifdef DEBUG_PEERNET - if (exclusivePort) std::cerr << "dhtConnectionCallback: we Require Exclusive Proxy Port for connection" << std::endl; - else std::cerr << "dhtConnectionCallback: Dont need Exclusive Proxy Port for connection" << std::endl; -#endif - - connectOk = true; - } - else - { - std::cerr << "PeerAction: Connect Proxy: ERROR Cannot find PeerStatus"; - std::cerr << std::endl; - } - -#ifdef RS_USE_DHT_STUNNER - uint8_t extStable = 0; - - UdpStunner *stunner = mProxyStunner; - if (!proxyPort) - { - stunner = mDhtStunner; - } - - if ((connectOk) && (stunner) && (stunner->externalAddr(extaddr, extStable))) - { - if (extStable) - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Proxy Connection Attempt to: "; - bdStdPrintId(std::cerr, &(peerId)); - std::cerr << " is Ok as we have Stable Own External Proxy Address"; - std::cerr << std::endl; -#endif - - if (point == BD_PROXY_CONNECTION_END_POINT) - { - ca.mDestId.addr = extaddr; - } - else - { - ca.mSrcId.addr = extaddr; - std::cerr << "dhtConnectionCallback() ERROR Proxy Auth as SrcId"; - std::cerr << std::endl; - } - - /* check if we require exclusive use of the proxy port */ - if (exclusivePort) - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback: Attempting to Grab ExclusiveLock of UdpStunner"; - std::cerr << std::endl; -#endif - - int stun_age = mProxyStunner->grabExclusiveMode(pid); - if (stun_age > 0) - { - int delay = 0; - if (stun_age < MIN_DETERMINISTIC_SWITCH_PERIOD) - { - delay = MIN_DETERMINISTIC_SWITCH_PERIOD - stun_age; - } - - /* great we got it! */ - ca.mDelayOrBandwidth = delay; - -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback: GotExclusiveLock With Delay: " << delay; - std::cerr << " for stable port"; - std::cerr << std::endl; -#endif - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(peerId.id), RsDhtPeerType::FRIEND); - if (dpd) - { - dpd->mExclusiveProxyLock = true; - -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback: Success at grabbing ExclusiveLock of UdpStunner"; - std::cerr << std::endl; -#endif - - } - else - { - std::cerr << "PeerAction: Connect Proxy: ERROR Cannot find PeerStatus"; - std::cerr << std::endl; - connectionAllowed = BITDHT_CONNECT_ERROR_TEMPUNAVAIL; - mProxyStunner->releaseExclusiveMode(pid,false); - } - } - else - { - /* failed to get exclusive mode - must wait */ - connectionAllowed = BITDHT_CONNECT_ERROR_TEMPUNAVAIL; - -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback: Failed to Grab ExclusiveLock, Returning TEMPUNAVAIL"; - std::cerr << std::endl; -#endif - } - } - - - } - else - { - if (exclusivePort) - { - connectionAllowed = BITDHT_CONNECT_ERROR_TEMPUNAVAIL; -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Proxy Connection"; - std::cerr << " is Discarded, as External Proxy Address is Not Stable! (EXCLUSIVE MODE)"; - std::cerr << std::endl; -#endif - } - else - { - connectionAllowed = BITDHT_CONNECT_ERROR_UNREACHABLE; -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Proxy Connection"; - std::cerr << " is Discarded, as Own External Proxy Address is Not Stable!"; - std::cerr << std::endl; -#endif - } - } - } - else - { - connectionAllowed = BITDHT_CONNECT_ERROR_TEMPUNAVAIL; -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() ERROR Proxy Connection "; - std::cerr << " is Discarded, as Failed to get Own External Proxy Address."; - std::cerr << std::endl; -#endif - } -#else // RS_USE_DHT_STUNNER - connectionAllowed = BITDHT_CONNECT_ERROR_TEMPUNAVAIL; - (void) connectOk; - (void) exclusivePort; -#endif // RS_USE_DHT_STUNNER - } - - ca.mMode = mode; - ca.mPoint = point; - ca.mAnswer = connectionAllowed; - - mActions.push_back(ca); - } - break; - - case BITDHT_CONNECT_CB_START: - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Connection Starting with: "; - bdStdPrintId(std::cerr, &(peerId)); - std::cerr << std::endl; -#endif - - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - /* Push Back PeerAction */ - PeerAction ca; - ca.mType = PEERNET_ACTION_TYPE_START; - ca.mMode = mode; - ca.mProxyId = *proxyId; - ca.mSrcId = *srcId; - ca.mDestId = *destId; - ca.mPoint = point; - ca.mDelayOrBandwidth = param; - ca.mAnswer = BITDHT_CONNECT_ERROR_NONE; - - mActions.push_back(ca); - - } - break; - - case BITDHT_CONNECT_CB_FAILED: - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Connection Attempt Failed with:"; - bdStdPrintId(std::cerr, &(peerId)); - std::cerr << std::endl; - - std::cerr << "dhtConnectionCallback() Proxy:"; - bdStdPrintId(std::cerr, proxyId); - std::cerr << std::endl; - - std::cerr << "dhtConnectionCallback() "; - std::cerr << " ErrorCode: " << errcode; - int errsrc = errcode & BITDHT_CONNECT_ERROR_MASK_SOURCE; - int errtype = errcode & BITDHT_CONNECT_ERROR_MASK_TYPE; - - std::cerr << " ErrorSrc: " << errsrc; - std::cerr << " ErrorType: " << errtype; - std::cerr << std::endl; -#endif - - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(peerId.id), RsDhtPeerType::FRIEND); - if (dpd) - { - dpd->mPeerCbMsg = "ERROR : "; - dpd->mPeerCbMsg += decodeConnectionError(errcode); - dpd->mPeerCbMode = mode; - dpd->mPeerCbPoint = point; - dpd->mPeerCbProxyId = *proxyId; - dpd->mPeerCbDestId = peerId; - dpd->mPeerCbTS = now; - } - else - { - std::cerr << "dhtConnectionCallback() "; - std::cerr << "ERROR Unknown Peer"; - std::cerr << std::endl; - } - } - break; - - case BITDHT_CONNECT_CB_REQUEST: - { -#ifdef DEBUG_PEERNET - std::cerr << "dhtConnectionCallback() Local Connection Request Feedback:"; - bdStdPrintId(std::cerr, &(peerId)); - std::cerr << std::endl; - - std::cerr << "dhtConnectionCallback() Proxy:"; - bdStdPrintId(std::cerr, proxyId); - std::cerr << std::endl; -#endif - - if (point != BD_PROXY_CONNECTION_START_POINT) - { - std::cerr << "dhtConnectionCallback() ERROR not START_POINT"; - std::cerr << std::endl; - return 0; - } - - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(peerId.id), RsDhtPeerType::FRIEND); - if (dpd) - { - if (errcode) - { - ReleaseProxyExclusiveMode_locked(dpd, false); - - dpd->mPeerReqStatusMsg = "STOPPED: "; - dpd->mPeerReqStatusMsg += decodeConnectionError(errcode); - dpd->mPeerReqState = RsDhtPeerRequest::STOPPED; - dpd->mPeerReqTS = now; - - int updatecode = CSB_UPDATE_FAILED_ATTEMPT; - int errtype = errcode & BITDHT_CONNECT_ERROR_MASK_TYPE; - switch(errtype) - { - /* fatal errors */ - case BITDHT_CONNECT_ERROR_AUTH_DENIED: - { - updatecode = CSB_UPDATE_AUTH_DENIED; - } - break; - - /* move on errors */ - case BITDHT_CONNECT_ERROR_UNREACHABLE: // sym NAT. - case BITDHT_CONNECT_ERROR_UNSUPPORTED: // mode unavailable. - { - updatecode = CSB_UPDATE_MODE_UNAVAILABLE; - } - break; - - - /* retry attempts */ - case BITDHT_CONNECT_ERROR_TEMPUNAVAIL: - case BITDHT_CONNECT_ERROR_DUPLICATE: - { - updatecode = CSB_UPDATE_RETRY_ATTEMPT; - } - break; - /* standard failed attempts */ - case BITDHT_CONNECT_ERROR_GENERIC: - case BITDHT_CONNECT_ERROR_PROTOCOL: - case BITDHT_CONNECT_ERROR_TIMEOUT: - case BITDHT_CONNECT_ERROR_NOADDRESS: - case BITDHT_CONNECT_ERROR_OVERLOADED: - /* CB_REQUEST errors */ - case BITDHT_CONNECT_ERROR_TOOMANYRETRY: - case BITDHT_CONNECT_ERROR_OUTOFPROXY: - { - updatecode = CSB_UPDATE_FAILED_ATTEMPT; - } - break; - - /* user cancelled ... no update */ - case BITDHT_CONNECT_ERROR_USER: - { - updatecode = CSB_UPDATE_NONE; - } - break; - } - if (updatecode) - { - dpd->mConnectLogic.updateCb(updatecode); - } - } - else // a new connection attempt. - { - dpd->mPeerReqStatusMsg = "Connect Attempt"; - dpd->mPeerReqState = RsDhtPeerRequest::RUNNING; - dpd->mPeerReqMode = mode; - dpd->mPeerReqProxyId = *proxyId; - dpd->mPeerReqTS = now; - - // This also is flagged into the instant Cb info. - dpd->mPeerCbMsg = "Local Connect Attempt"; - dpd->mPeerCbMode = mode; - dpd->mPeerCbPoint = point; - dpd->mPeerCbProxyId = *proxyId; - dpd->mPeerCbDestId = peerId; - dpd->mPeerCbTS = now; - } - } - else - { - std::cerr << "dhtConnectionCallback() ERROR Cannot find PeerStatus"; - std::cerr << std::endl; - } - } - break; - - default: - case BITDHT_CONNECT_CB_PENDING: - case BITDHT_CONNECT_CB_PROXY: - { - std::cerr << "dhtConnectionCallback() ERROR unexpected ConnectionCallback:"; - std::cerr << std::endl; - bdStdPrintId(std::cerr, srcId); - std::cerr << " and "; - bdStdPrintId(std::cerr, destId); - std::cerr << std::endl; - } - break; - } - return 1; -} - -/****************************************************************************************** - ******************************** Dht Actions / Monitoring ******************************** - ******************************************************************************************/ - - -/* tick stuff that isn't in its own thread */ - -int p3BitDht::tick() -{ - doActions(); - monitorConnections(); - - minuteTick(); - -#ifdef DEBUG_PEERNET_COMMON - time_t now = time(NULL); // Don't use rstime_t here or ctime break on windows - std::cerr << "p3BitDht::tick() TIME: " << ctime(&now) << std::endl; - std::cerr.flush(); -#endif - - return 1; -} - -#define MINUTE_IN_SECS 60 -#define TEN_IN_SECS 10 - -int p3BitDht::minuteTick() -{ - rstime_t now = time(NULL); - int deltaT = 0; - - { - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - deltaT = now-mMinuteTS; - } - - //if (deltaT > MINUTE_IN_SECS) - if (deltaT > TEN_IN_SECS) - { - mRelay->checkRelays(); - - updateDataRates(); - - /* temp - testing - print dht & relay traffic */ - float dhtRead, dhtWrite; - float relayRead, relayWrite, relayRelayed; - - getRelayRates(relayRead, relayWrite, relayRelayed); - getDhtRates(dhtRead, dhtWrite); - -#ifdef DEBUG_PEERNET_COMMON - double denom = deltaT; - - std::cerr << "p3BitDht::minuteTick() "; - std::cerr << "DhtRead: " << dhtRead / denom << " kB/s "; - std::cerr << "DhtWrite: " << dhtWrite / denom << " kB/s "; - std::cerr << std::endl; - - std::cerr << "p3BitDht::minuteTick() "; - std::cerr << "RelayRead: " << relayRead / denom << " kB/s "; - std::cerr << "RelayWrite: " << relayWrite / denom << " kB/s "; - std::cerr << "RelayRelayed: " << relayRelayed / denom << " kB/s "; - std::cerr << std::endl; -#endif - - - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - mMinuteTS = now; - } - return 1; -} - -int p3BitDht::doActions() -{ -#ifdef DEBUG_PEERNET_COMMON - std::cerr << "p3BitDht::doActions()" << std::endl; -#endif - - rstime_t now = time(NULL); - - while(mActions.size() > 0) - { - PeerAction action; - - { - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - if (mActions.size() < 1) - { - break; - } - - action = mActions.front(); - mActions.pop_front(); - } - - switch(action.mType) - { - case PEERNET_ACTION_TYPE_CONNECT: - { - /* connect attempt */ -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction. Connection Attempt to: "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " mode: " << action.mMode; - std::cerr << std::endl; -#endif - - bool doConnectionRequest = false; - bool connectionReqFailed = false; - bool grabbedExclusivePort = false; - - /* translate id into string for exclusive mode */ - std::string pid; - bdStdPrintNodeId(pid, &(action.mDestId.id), false); - - - // Parameters that will be used for the Connect Request. - struct sockaddr_in connAddr; // We zero this address. (DHT Layer handles most cases) - sockaddr_clear(&connAddr); - uint32_t connStart = 1; /* > 0 indicates GO (number indicates required startup delay) */ - uint32_t connDelay = 0; - - uint32_t failReason = CSB_UPDATE_MODE_UNAVAILABLE; - - if ((action.mMode == BITDHT_CONNECT_MODE_DIRECT) || - (action.mMode == BITDHT_CONNECT_MODE_RELAY)) - { - doConnectionRequest = true; - } - else if (action.mMode == BITDHT_CONNECT_MODE_PROXY) - { - struct sockaddr_in extaddr; - sockaddr_clear(&extaddr); - bool proxyPort = true; - bool exclusivePort = false; - bool connectOk = false; - -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction: Proxy... deciding which port to use."; - std::cerr << std::endl; -#endif - - { - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(action.mDestId.id), RsDhtPeerType::FRIEND); - if (dpd) - { - connectOk = true; - proxyPort = dpd->mConnectLogic.getProxyPortChoice(); - if (proxyPort) - { -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction: Using ProxyPort. Checking ConnectLogic.NetState: "; - std::cerr << dpd->mConnectLogic.calcNetState(mNetMgr->getNetworkMode(), - mNetMgr->getNatHoleMode(), mNetMgr->getNatTypeMode()); - std::cerr << std::endl; -#endif - - exclusivePort = (CSB_NETSTATE_EXCLUSIVENAT == dpd->mConnectLogic.calcNetState( - mNetMgr->getNetworkMode(), mNetMgr->getNatHoleMode(), mNetMgr->getNatTypeMode())); - - if (exclusivePort) - { -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction: NetState indicates Exclusive Mode"; - std::cerr << std::endl; -#endif - } - } - } - else - { - std::cerr << "PeerAction: Connect Proxy: ERROR Cannot find PeerStatus"; - std::cerr << std::endl; - } - } -#ifdef RS_USE_DHT_STUNNER - uint8_t extStable = 0; - - UdpStunner *stunner = mProxyStunner; - if (!proxyPort) - { - stunner = mDhtStunner; - } - - - - if ((connectOk) && (stunner) && (stunner->externalAddr(extaddr, extStable))) - { - if (extStable) - { -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction: Proxy Connection Attempt to: "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " is OkGo as we have Stable Own External Proxy Address"; - std::cerr << std::endl; -#endif - - /* check if we require exclusive use of the proxy port */ - if (exclusivePort) - { - int stun_age = mProxyStunner->grabExclusiveMode(pid); - if (stun_age > 0) - { - int delay = 0; - if (stun_age < MIN_DETERMINISTIC_SWITCH_PERIOD) - { - delay = MIN_DETERMINISTIC_SWITCH_PERIOD - stun_age; - } - -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction: Stunner has indicated a Delay of " << delay; - std::cerr << " to ensure a stable Port!"; - std::cerr << std::endl; -#endif - - /* great we got it! */ - connAddr = extaddr; - connDelay = delay; - doConnectionRequest = true; - grabbedExclusivePort = true; - } - else - { - /* failed to get exclusive mode - must wait */ - connectionReqFailed = true; - failReason = CSB_UPDATE_RETRY_ATTEMPT; - } - } - else - { - /* stable and non-exclusive - go for it */ - connAddr = extaddr; - connStart = 1; - doConnectionRequest = true; - } - } - else - { -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction: WARNING Proxy Connection Attempt to: "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " is Discarded, as Own External Proxy Address is Not Stable!"; - std::cerr << std::endl; -#endif - - connectionReqFailed = true; - if (exclusivePort) - { - failReason = CSB_UPDATE_RETRY_ATTEMPT; -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction: As Exclusive Mode, Port Will stabilise => RETRY"; - std::cerr << std::endl; -#endif - - } - else - { - failReason = CSB_UPDATE_MODE_UNAVAILABLE; -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction: Not Exclusive Mode, => MODE UNAVAILABLE"; - std::cerr << std::endl; -#endif - } - } - } - else - { -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction: ERROR Proxy Connection Attempt to: "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " is Discarded, as Failed to get Own External Proxy Address."; - std::cerr << std::endl; -#endif - - connectionReqFailed = true; - failReason = CSB_UPDATE_RETRY_ATTEMPT; - } -#else // RS_USE_DHT_STUNNER - connectionReqFailed = true; - failReason = CSB_UPDATE_RETRY_ATTEMPT; - (void) connectOk; -#endif //RS_USE_DHT_STUNNER - } - - if (doConnectionRequest) - { - if (mUdpBitDht->ConnectionRequest(&connAddr, &(action.mDestId.id), action.mMode, connDelay, connStart)) - { - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction: Connection Attempt to: "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " has gone ahead"; - std::cerr << std::endl; -#endif - - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(action.mDestId.id), RsDhtPeerType::FRIEND); - if (dpd) - { - dpd->mPeerReqStatusMsg = "Connect Request"; - dpd->mPeerReqState = RsDhtPeerRequest::RUNNING; - dpd->mPeerReqMode = action.mMode; - dpd->mPeerReqTS = now; - - if (grabbedExclusivePort) - { - dpd->mExclusiveProxyLock = true; - } - } - else - { - std::cerr << "PeerAction: Connect ERROR Cannot find PeerStatus"; - std::cerr << std::endl; - } - } - else - { - connectionReqFailed = true; - failReason = CSB_UPDATE_MODE_UNAVAILABLE; - } - } - - if (connectionReqFailed) - { -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction: Connection Attempt to: "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " is Discarded, as Mode is Unavailable"; - std::cerr << std::endl; -#endif - - //if (grabbedExclusivePort) - //{ - // mProxyStunner->releaseExclusiveMode(pid,false); - //} - - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(action.mDestId.id), RsDhtPeerType::FRIEND); - if (dpd) - { - dpd->mConnectLogic.updateCb(failReason); - - dpd->mPeerReqStatusMsg = "Req Mode Unavailable"; - dpd->mPeerReqState = RsDhtPeerRequest::STOPPED; - dpd->mPeerReqMode = action.mMode; - dpd->mPeerReqTS = now; - - if (grabbedExclusivePort) - { - ReleaseProxyExclusiveMode_locked(dpd, false); - } - } - else - { - std::cerr << "PeerAction: ERROR Connection Attempt to: "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " has no Internal Dht Peer!"; - std::cerr << std::endl; - - if (grabbedExclusivePort) - { - std::cerr << "PeerAction: ERROR ERROR, we grabd Exclusive Port to do this, trying emergency release"; - std::cerr << std::endl; -#ifdef RS_USE_DHT_STUNNER - mProxyStunner->releaseExclusiveMode(pid,false); -#endif // RS_USE_DHT_STUNNER - } - } - } - - } - break; - - case PEERNET_ACTION_TYPE_AUTHORISE: - { - /* connect attempt */ -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction. Authorise Connection between: "; - bdStdPrintId(std::cerr, &(action.mSrcId)); - std::cerr << " and "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " mode: " << action.mMode; - std::cerr << " delay/bandwidth: " << action.mDelayOrBandwidth; - std::cerr << std::endl; -#endif - - int delay = 0; - int bandwidth = 0; - if (action.mMode == BITDHT_CONNECT_MODE_RELAY) - { - bandwidth = action.mDelayOrBandwidth; - } - else - { - delay = action.mDelayOrBandwidth; - } - - mUdpBitDht->ConnectionAuth(&(action.mSrcId), &(action.mProxyId), &(action.mDestId), - action.mMode, action.mPoint, bandwidth, delay, action.mAnswer); - - // Only feedback to the gui if we are at END. - if (action.mPoint == BD_PROXY_CONNECTION_END_POINT) - { - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(action.mSrcId.id), RsDhtPeerType::ANY); - if (dpd) - { - if (action.mAnswer) - { - dpd->mPeerCbMsg = "WE DENIED AUTH: ERROR : "; - dpd->mPeerCbMsg += decodeConnectionError(action.mAnswer); - } - else - { - dpd->mPeerCbMsg = "We AUTHED"; - } - dpd->mPeerCbMode = action.mMode; - dpd->mPeerCbPoint = action.mPoint; - dpd->mPeerCbProxyId = action.mProxyId; - dpd->mPeerCbDestId = action.mSrcId; - dpd->mPeerCbTS = now; - } - // Not an error if AUTH_DENIED - cos we don't know them! (so won't be in peerList). - else if (action.mAnswer | BITDHT_CONNECT_ERROR_AUTH_DENIED) - { -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction Authorise Connection "; - std::cerr << "Denied Unknown Peer"; - std::cerr << std::endl; -#endif - } - else - { - std::cerr << "PeerAction Authorise Connection "; - std::cerr << "ERROR Unknown Peer & !DENIED ???"; - std::cerr << std::endl; - } - } - } - break; - - case PEERNET_ACTION_TYPE_START: - { - /* connect attempt */ -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction. Start Connection between: "; - bdStdPrintId(std::cerr, &(action.mSrcId)); - std::cerr << " and "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " mode: " << action.mMode; - std::cerr << " delay/bandwidth: " << action.mDelayOrBandwidth; - std::cerr << std::endl; -#endif - - initiateConnection(&(action.mSrcId), &(action.mProxyId), &(action.mDestId), - action.mMode, action.mPoint, action.mDelayOrBandwidth); - } - break; - - case PEERNET_ACTION_TYPE_RESTARTREQ: - { - /* connect attempt */ -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction. Restart Connection Attempt to: "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " mode: " << action.mMode; - std::cerr << std::endl; -#endif - - struct sockaddr_in laddr; - sockaddr_clear(&laddr); - uint32_t start = 1; - uint32_t delay = 0; - - mUdpBitDht->ConnectionRequest(&laddr, &(action.mDestId.id), action.mMode, delay, start); - } - break; - - case PEERNET_ACTION_TYPE_KILLREQ: - { - /* connect attempt */ -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction. Kill Connection Attempt to: "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " mode: " << action.mMode; - std::cerr << std::endl; -#endif - - struct sockaddr_in laddr; - sockaddr_clear(&laddr); - uint32_t start = 0; - uint32_t delay = 0; - - mUdpBitDht->ConnectionRequest(&laddr, &(action.mDestId.id), action.mMode, delay, start); - } - break; - - case PEERNET_ACTION_TYPE_TCPATTEMPT: - { - /* connect attempt */ -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction. TCP Connection Attempt to: "; - bdStdPrintId(std::cerr, &(action.mDestId)); - std::cerr << " mode: " << action.mMode; - std::cerr << std::endl; -#endif - - RsPeerId peerRsId; - bool foundPeerId = false; - { - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(action.mDestId.id), RsDhtPeerType::ANY); - if (dpd) - { - peerRsId = dpd->mRsId; - foundPeerId = true; -#ifdef DEBUG_PEERNET - std::cerr << "PeerAction. TCP Connection Attempt. DoingCallback for RsID: "; - std::cerr << peerRsId; - std::cerr << std::endl; -#endif - } - else - { - std::cerr << "PeerAction. TCP Connection Attempt. ERROR unknown peer"; - std::cerr << std::endl; - } - } - - if (foundPeerId) - { - ConnectCalloutTCPAttempt(peerRsId, action.mDestId.addr); - } - } - break; - } - } - return 1; -} - - - - - -/****************************** Connection Logic ***************************/ - -/* Proxies!. - * - * We can allow all PROXY connections, as it is just a couple of messages, - * however, we should be smart about how many RELAY connections are allowed. - * - * e.g. Allow 20 Relay connections. - * 15 for friends, 5 for randoms. - * - * Can also validate addresses with own secure connections. - */ - -int p3BitDht::checkProxyAllowed(const bdId *srcId, const bdId *destId, int mode, uint32_t &bandwidth) -{ -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::checkProxyAllowed()"; - std::cerr << std::endl; -#endif - - // Dont think that a mutex is required here! But might be so just lock to ensure that it is possible. - { - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - } - - if (mode == BITDHT_CONNECT_MODE_PROXY) - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::checkProxyAllowed() Allowing all PROXY connections, OKAY"; - std::cerr << std::endl; -#endif - - bandwidth = 0; // unlimited as p2p. - return 1; - //return CONNECTION_OKAY; - } - - if (mode != BITDHT_CONNECT_MODE_RELAY) - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::checkProxyAllowed() unknown Connect Mode DENIED"; - std::cerr << std::endl; -#endif - return 0; - } - - /* will install the Relay Here... so that we reserve the Relay Space for later. - * decide on relay bandwidth limitation as well - */ - if (RelayHandler_InstallRelayConnection(srcId, destId, mode, bandwidth)) - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::checkProxyAllowed() Successfully added Relay, Connection OKAY"; - std::cerr << std::endl; -#endif - - return 1; - // CONNECT_OKAY. - } - else - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::checkProxyAllowed() Failed to install Relay, Connection DENIED"; - std::cerr << std::endl; -#endif - - return 0; - //return CONNECT_MODE_OVERLOADED; - } - - return 0; - //return CONNECT_MODE_NOTAVAILABLE; - //return CONNECT_MODE_OVERLOADED; -} - - -int p3BitDht::checkConnectionAllowed(const bdId *peerId, int mode) -{ - (void) mode; - -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::checkConnectionAllowed() to: "; - bdStdPrintId(std::cerr,peerId); - std::cerr << " mode: " << mode; - std::cerr << std::endl; -#endif - - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - rstime_t now = time(NULL); - - /* check if they are in our friend list */ - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(peerId->id), RsDhtPeerType::FRIEND); - if (!dpd) - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::checkConnectionAllowed() Peer Not Friend, DENIED"; - std::cerr << std::endl; -#endif - - /* store as failed connection attempt */ - std::map::iterator it; - it = mFailedPeers.find(peerId->id); - if (it == mFailedPeers.end()) - { - mFailedPeers[peerId->id] = DhtPeerDetails(); - it = mFailedPeers.find(peerId->id); - } - - /* flag as failed */ - it->second.mDhtId = *peerId; - it->second.mDhtState = RsDhtPeerDht::NOT_ACTIVE; - it->second.mDhtUpdateTS = now; - - it->second.mPeerType = RsDhtPeerType::OTHER; - it->second.mPeerCbMsg = "Denied Non-Friend"; - - it->second.mPeerReqStatusMsg = "Denied Non-Friend"; - it->second.mPeerReqState = RsDhtPeerRequest::STOPPED; - it->second.mPeerReqTS = now; - it->second.mPeerReqMode = 0; - //it->second.mPeerProxyId; - it->second.mPeerReqTS = now; - - it->second.mPeerCbMsg = "Denied Non-Friend"; - - it->second.mPeerConnectMsg = "Denied Non-Friend"; - it->second.mPeerConnectState = RsDhtPeerConnectState::DISCONNECTED; - - - return 0; - //return NOT_FRIEND; - } - - /* are a friend */ - - if (dpd->mPeerConnectState == RsDhtPeerConnectState::CONNECTED) - { - std::cerr << "p3BitDht::checkConnectionAllowed() ERROR Peer Already Connected, DENIED"; - std::cerr << std::endl; - - // STATUS UPDATE DONE IN ACTION. - //it->second.mPeerStatusMsg = "2nd Connection Attempt!"; - //it->second.mPeerUpdateTS = now; - return 0; - //return ALREADY_CONNECTED; - } - - return 1; - //return CONNECTION_OKAY; -} - - - - - -/* So initiateConnection has to call out to other bits of RS. - * critical information is: - * Peer RsId, Peer Address, Connect Mode (includes Proxy/OrNot). - - * - * What do we need: ACTIVE / PASSIVE / UNSPEC - * + Min Delay Time, - */ - - -void p3BitDht::ConnectCalloutTCPAttempt(const RsPeerId &peerId, struct sockaddr_in raddrv4) -{ - struct sockaddr_storage raddr; - struct sockaddr_storage proxyaddr; - struct sockaddr_storage srcaddr; - - sockaddr_storage_clear(proxyaddr); - sockaddr_storage_clear(proxyaddr); - sockaddr_storage_clear(srcaddr); - - struct sockaddr_in *rap = (struct sockaddr_in *) &raddr; - //struct sockaddr_in *pap = (struct sockaddr_in *) &proxyaddr; - //struct sockaddr_in *sap = (struct sockaddr_in *) &srcaddr; - - // only one to translate - rap->sin_family = AF_INET; - rap->sin_addr = raddrv4.sin_addr; - rap->sin_port = raddrv4.sin_port; - - uint32_t source = RS_CB_DHT; - uint32_t connectFlags = RS_CB_FLAG_ORDER_UNSPEC | RS_CB_FLAG_MODE_TCP; - uint32_t delay = 0; - uint32_t bandwidth = 0; - - mConnCb->peerConnectRequest(peerId, raddr, proxyaddr, srcaddr, source, connectFlags, delay, bandwidth); -} - - -void p3BitDht::ConnectCalloutDirectOrProxy(const RsPeerId &peerId, struct sockaddr_in raddrv4, uint32_t connectFlags, uint32_t delay) -{ - struct sockaddr_storage raddr; - struct sockaddr_storage proxyaddr; - struct sockaddr_storage srcaddr; - - sockaddr_storage_clear(proxyaddr); - sockaddr_storage_clear(proxyaddr); - sockaddr_storage_clear(srcaddr); - - struct sockaddr_in *rap = (struct sockaddr_in *) &raddr; -// struct sockaddr_in *pap = (struct sockaddr_in *) &proxyaddr; -// struct sockaddr_in *sap = (struct sockaddr_in *) &srcaddr; - - // only one to translate - rap->sin_family = AF_INET; - rap->sin_addr = raddrv4.sin_addr; - rap->sin_port = raddrv4.sin_port; - - uint32_t source = RS_CB_DHT; - uint32_t bandwidth = 0; - - mConnCb->peerConnectRequest(peerId, raddr, proxyaddr, srcaddr, source, connectFlags, delay, bandwidth); -} - -void p3BitDht::ConnectCalloutRelay(const RsPeerId &peerId, - struct sockaddr_in srcaddrv4, struct sockaddr_in proxyaddrv4, struct sockaddr_in destaddrv4, - uint32_t connectFlags, uint32_t bandwidth) -{ - struct sockaddr_storage destaddr; - struct sockaddr_storage proxyaddr; - struct sockaddr_storage srcaddr; - - sockaddr_storage_clear(proxyaddr); - sockaddr_storage_clear(proxyaddr); - sockaddr_storage_clear(srcaddr); - - struct sockaddr_in *dap = (struct sockaddr_in *) &destaddr; - struct sockaddr_in *pap = (struct sockaddr_in *) &proxyaddr; - struct sockaddr_in *sap = (struct sockaddr_in *) &srcaddr; - - dap->sin_family = AF_INET; - dap->sin_addr = destaddrv4.sin_addr; - dap->sin_port = destaddrv4.sin_port; - - pap->sin_family = AF_INET; - pap->sin_addr = proxyaddrv4.sin_addr; - pap->sin_port = proxyaddrv4.sin_port; - - sap->sin_family = AF_INET; - sap->sin_addr = srcaddrv4.sin_addr; - sap->sin_port = srcaddrv4.sin_port; - - uint32_t source = RS_CB_DHT; - uint32_t delay = 0; - - mConnCb->peerConnectRequest(peerId, destaddr, proxyaddr, srcaddr, source, connectFlags, delay, bandwidth); -} - - - - -//virtual void peerConnectRequest(std::string id, struct sockaddr_in raddr, -// struct sockaddr_in proxyaddr, struct sockaddr_in srcaddr, -// uint32_t source, uint32_t flags, uint32_t delay, uint32_t bandwidth) = 0; - - -void p3BitDht::initiateConnection(const bdId *srcId, const bdId *proxyId, const bdId *destId, - uint32_t mode, uint32_t loc, uint32_t delayOrBandwidth) -{ -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::initiateConnection()"; - std::cerr << std::endl; - std::cerr << "\t srcId: "; - bdStdPrintId(std::cerr, srcId); - std::cerr << std::endl; - - std::cerr << "\t proxyId: "; - bdStdPrintId(std::cerr, proxyId); - std::cerr << std::endl; - - std::cerr << "\t destId: "; - bdStdPrintId(std::cerr, destId); - std::cerr << std::endl; - - std::cerr << "\t Mode: " << mode << " loc: " << loc; - std::cerr << std::endl; - std::cerr << "\t DelayOrBandwidth: " << delayOrBandwidth; - std::cerr << std::endl; -#endif - - bdId peerConnectId; - - uint32_t connectFlags = 0; - - uint32_t delay = 0; - uint32_t bandwidth = 0; - - /* determine who the actual destination is. - * as we always specify the remote address, this is all we need. - */ - if (loc == BD_PROXY_CONNECTION_START_POINT) - { - peerConnectId = *destId; - /* lowest is active */ - if (srcId < destId) - { - connectFlags |= RS_CB_FLAG_ORDER_ACTIVE; - } - else - { - connectFlags |= RS_CB_FLAG_ORDER_PASSIVE; - } - } - else if (loc == BD_PROXY_CONNECTION_END_POINT) - { - peerConnectId = *srcId; - /* lowest is active (we are now dest - in this case) */ - if (destId < srcId) - { - connectFlags |= RS_CB_FLAG_ORDER_ACTIVE; - } - else - { - connectFlags |= RS_CB_FLAG_ORDER_PASSIVE; - } - } - else - { - std::cerr << "p3BitDht::initiateConnection() ERROR, NOT either START or END"; - std::cerr << std::endl; - /* ERROR */ - return; - } - -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::initiateConnection() Connecting to "; - bdStdPrintId(std::cerr, &peerConnectId); - std::cerr << std::endl; -#endif - -// uint32_t touConnectMode = 0; - RsPeerId rsId; - - { - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&(peerConnectId.id), RsDhtPeerType::FRIEND); - /* grab a socket */ - if (!dpd) - { - std::cerr << "p3BitDht::initiateConnection() ERROR Peer not found"; - std::cerr << std::endl; - return; - } - - if (dpd->mPeerConnectState != RsDhtPeerConnectState::DISCONNECTED) - { - std::cerr << "p3BitDht::initiateConnection() ERROR Peer is not Disconnected"; - std::cerr << std::endl; - return; - } - - rsId = dpd->mRsId; - - /* start the connection */ - /* These Socket Modes must match the TOU Stack - or it breaks. */ - switch(mode) - { - default: - case BITDHT_CONNECT_MODE_DIRECT: -// touConnectMode = RsDhtTouMode::DIRECT; - connectFlags |= RS_CB_FLAG_MODE_UDP_DIRECT; - delay = delayOrBandwidth; - break; - - case BITDHT_CONNECT_MODE_PROXY: - { - bool useProxyPort = dpd->mConnectLogic.getProxyPortChoice(); - -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::initiateConnection() Peer Mode Proxy... deciding which port to use."; - std::cerr << " UseProxyPort? " << useProxyPort; - std::cerr << std::endl; -#endif - - delay = delayOrBandwidth; - if (useProxyPort) - { -// touConnectMode = RsDhtTouMode::PROXY; - connectFlags |= RS_CB_FLAG_MODE_UDP_PROXY; - } - else - { -// touConnectMode = RsDhtTouMode::DIRECT; - connectFlags |= RS_CB_FLAG_MODE_UDP_DIRECT; - } - - } - break; - - case BITDHT_CONNECT_MODE_RELAY: -// touConnectMode = RsDhtTouMode::RELAY; - connectFlags |= RS_CB_FLAG_MODE_UDP_RELAY; - bandwidth = delayOrBandwidth; - break; - } - - - dpd->mPeerConnectProxyId = *proxyId; - dpd->mPeerConnectPeerId = peerConnectId; - - - /* store results in Status */ - dpd->mPeerConnectMsg = "UDP started"; - dpd->mPeerConnectState = RsDhtPeerConnectState::UDP_STARTED; - dpd->mPeerConnectUdpTS = time(NULL); - dpd->mPeerConnectMode = mode; - dpd->mPeerConnectPoint = loc; - } - - /* finally we call out to start the connection (Outside of Mutex) */ - - if ((mode == BITDHT_CONNECT_MODE_DIRECT) || (mode == BITDHT_CONNECT_MODE_PROXY)) - { - ConnectCalloutDirectOrProxy(rsId, peerConnectId.addr, connectFlags, delay); - } - else if (mode == BITDHT_CONNECT_MODE_RELAY) - { - if (loc == BD_PROXY_CONNECTION_START_POINT) - { - ConnectCalloutRelay(rsId, srcId->addr, proxyId->addr, destId->addr, connectFlags, bandwidth); - } - else // END_POINT - { - /* reverse order connection call */ - ConnectCalloutRelay(rsId, destId->addr, proxyId->addr, srcId->addr, connectFlags, bandwidth); - } - } - - -} - - -int p3BitDht::installRelayConnection(const bdId *srcId, const bdId *destId, uint32_t &bandwidth) -{ - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - /* work out if either srcId or DestId is a friend */ - int relayClass = UDP_RELAY_CLASS_GENERAL; - -#ifdef DEBUG_PEERNET - RsPeerId strId1; - bdStdPrintNodeId(strId1, &(srcId->id), false); - - RsPeerId strId2; - bdStdPrintNodeId(strId2, &(destId->id), false); -#endif - - /* grab a socket */ - DhtPeerDetails *dpd_src = findInternalDhtPeer_locked(&(srcId->id), RsDhtPeerType::ANY); - DhtPeerDetails *dpd_dest = findInternalDhtPeer_locked(&(destId->id), RsDhtPeerType::ANY); - - if ((dpd_src) && (dpd_src->mPeerType == RsDhtPeerType::FRIEND)) - { - relayClass = UDP_RELAY_CLASS_FRIENDS; - } - else if ((dpd_dest) && (dpd_dest->mPeerType == RsDhtPeerType::FRIEND)) - { - relayClass = UDP_RELAY_CLASS_FRIENDS; - } - else if ((dpd_src) && (dpd_src->mPeerType == RsDhtPeerType::FOF)) - { - relayClass = UDP_RELAY_CLASS_FOF; - } - else if ((dpd_dest) && (dpd_dest->mPeerType == RsDhtPeerType::FOF)) - { - relayClass = UDP_RELAY_CLASS_FOF; - } - else - { - relayClass = UDP_RELAY_CLASS_GENERAL; - } - - /* will install the Relay Here... so that we reserve the Relay Space for later. */ - UdpRelayAddrSet relayAddrs(&(srcId->addr), &(destId->addr)); - if (mRelay->addUdpRelay(&relayAddrs, relayClass, bandwidth)) - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::installRelayConnection() Successfully added Relay, Connection OKAY"; - std::cerr << std::endl; -#endif - - return 1; - // CONNECT_OKAY. - } - else - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::installRelayConnection() Failed to install Relay, Connection DENIED"; - std::cerr << std::endl; -#endif - - return 0; - //return CONNECT_MODE_OVERLOADED; - } - return 0; -} - - -int p3BitDht::removeRelayConnection(const bdId *srcId, const bdId *destId) -{ - //RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - - UdpRelayAddrSet relayAddrs(&(srcId->addr), &(destId->addr)); - if (mRelay->removeUdpRelay(&relayAddrs)) - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::removeRelayConnection() Successfully removed Relay"; - std::cerr << std::endl; -#endif - - return 1; - } - else - { - std::cerr << "p3BitDht::removeRelayConnection() ERROR Failed to remove Relay"; - std::cerr << std::endl; - - return 0; - } -} - -/***************************************************** UDP Connections *****************************/ - - -void p3BitDht::monitorConnections() -{ - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - rstime_t now = time(NULL); - - std::map::iterator it; - - for(it = mPeers.begin(); it != mPeers.end(); ++it) - { - /* ignore ones which aren't friends */ - if (it->second.mPeerType != RsDhtPeerType::FRIEND) - { - continue; - } - - if (it->second.mPeerConnectState == RsDhtPeerConnectState::UDP_STARTED) - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::monitorConnections() Connection in progress to: "; - - bdStdPrintNodeId(std::cerr, &(it->second.mDhtId.id)); - std::cerr << std::endl; -#endif - - if (now - it->second.mPeerConnectUdpTS > PEERNET_CONNECT_TIMEOUT) - { - /* This CAN happen ;( */ -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::monitorConnections() WARNING InProgress Connection Failed: "; - bdStdPrintNodeId(std::cerr, &(it->second.mDhtId.id)); - std::cerr << std::endl; -#endif - - UdpConnectionFailed_locked(&(it->second)); - } - } - } -} - - - - -void p3BitDht::Feedback_Connected(const RsPeerId& pid) -{ - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - DhtPeerDetails *dpd = findInternalRsPeer_locked(pid); - - if (!dpd) - { - /* ERROR */ - std::cerr << "p3BitDht::Feedback_Connected() ERROR peer not found: " << pid; - std::cerr << std::endl; - - return; - } - - /* sanity checking */ - if (dpd->mPeerConnectState != RsDhtPeerConnectState::UDP_STARTED) - { - /* ERROR */ - std::cerr << "p3BitDht::Feedback_Connected() ERROR not in UDP_STARTED mode for: "; - bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); - std::cerr << std::endl; - - return; - } - -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::monitorConnections() InProgress Connection Now Active: "; - bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); - std::cerr << std::endl; -#endif - - /* switch state! */ - dpd->mPeerConnectState = RsDhtPeerConnectState::CONNECTED; - dpd->mPeerConnectTS = time(NULL); - - dpd->mConnectLogic.updateCb(CSB_UPDATE_CONNECTED); - - rs_sprintf(dpd->mPeerConnectMsg, "Connected in %ld secs", dpd->mPeerConnectTS - dpd->mPeerConnectUdpTS); - - // Remove the Connection Request. - if (dpd->mPeerReqState == RsDhtPeerRequest::RUNNING) - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::monitorConnections() Request Active, Stopping Request"; - std::cerr << std::endl; -#endif - - /* Push Back PeerAction */ - PeerAction ca; - ca.mType = PEERNET_ACTION_TYPE_KILLREQ; - ca.mMode = dpd->mPeerConnectMode; - //ca.mProxyId = *proxyId; - //ca.mSrcId = *srcId; - ca.mDestId = dpd->mPeerConnectPeerId; - //ca.mPoint = point; - ca.mAnswer = BITDHT_CONNECT_ERROR_NONE; - - mActions.push_back(ca); - - // What the Action should do... - //struct sockaddr_in tmpaddr; - //bdsockaddr_clear(&tmpaddr); - //int start = 0; - //mUdpBitDht->ConnectionRequest(&tmpaddr, &(it->second.mPeerConnectPeerId.id), it->second.mPeerConnectMode, start); - } - // only an error if we initiated the connection. - else if (dpd->mPeerConnectPoint == BD_PROXY_CONNECTION_START_POINT) - { - std::cerr << "p3BitDht::monitorConnections() ERROR Request not active, can't stop"; - std::cerr << std::endl; - } - - ReleaseProxyExclusiveMode_locked(dpd, true); -} - -void p3BitDht::Feedback_ConnectionFailed(const RsPeerId& pid) -{ - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - DhtPeerDetails *dpd = findInternalRsPeer_locked(pid); - - if (!dpd) - { - /* ERROR */ - std::cerr << "p3BitDht::Feedback_Connected() ERROR peer not found: " << pid; - std::cerr << std::endl; - - return; - } - -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::Feedback_ConnectionFailed() UDP Connection Failed: "; - bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); - std::cerr << std::endl; -#endif - - return UdpConnectionFailed_locked(dpd); -} - -void p3BitDht::Feedback_ConnectionClosed(const RsPeerId& pid) -{ - RsStackMutex stack(dhtMtx); /********** LOCKED MUTEX ***************/ - DhtPeerDetails *dpd = findInternalRsPeer_locked(pid); - - if (!dpd) - { - /* ERROR */ - std::cerr << "p3BitDht::Feedback_Connected() ERROR peer not found: " << pid; - std::cerr << std::endl; - - return; - } - -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::Feedback_ConnectionClosed() Active Connection Closed: "; - bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); - std::cerr << std::endl; -#endif - - return UdpConnectionFailed_locked(dpd); -} - - -void p3BitDht::UdpConnectionFailed_locked(DhtPeerDetails *dpd) -{ - if (dpd->mPeerConnectState == RsDhtPeerConnectState::UDP_STARTED) - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::UdpConnectionFailed_locked() UDP Connection Failed: "; - bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); - std::cerr << std::endl; -#endif - - /* shut it down */ - - /* ONLY need to update ConnectLogic - if it was our Attempt Running */ - if (dpd->mPeerReqState == RsDhtPeerRequest::RUNNING) - { - dpd->mConnectLogic.updateCb(CSB_UPDATE_FAILED_ATTEMPT); - } - dpd->mPeerConnectState = RsDhtPeerConnectState::DISCONNECTED; - dpd->mPeerConnectMsg = "UDP Failed"; - - } - else - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::UdpConnectionFailed_locked() Active Connection Closed: "; - bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); - std::cerr << std::endl; -#endif - - dpd->mConnectLogic.updateCb(CSB_UPDATE_DISCONNECTED); - - dpd->mPeerConnectState = RsDhtPeerConnectState::DISCONNECTED; - dpd->mPeerConnectClosedTS = time(NULL); - rs_sprintf(dpd->mPeerConnectMsg, "Closed, Alive for: %ld secs", dpd->mPeerConnectClosedTS - dpd->mPeerConnectTS); - } - - - - if (dpd->mPeerReqState == RsDhtPeerRequest::RUNNING) - { -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::UdpConnectionFailed_locked() "; - std::cerr << "Request Active (Paused)... Killing for next Attempt"; - std::cerr << std::endl; -#endif - - /* Push Back PeerAction */ - PeerAction ca; - ca.mType = PEERNET_ACTION_TYPE_KILLREQ; - ca.mMode = dpd->mPeerConnectMode; - //ca.mProxyId = *proxyId; - //ca.mSrcId = *srcId; - ca.mDestId = dpd->mPeerConnectPeerId; - //ca.mPoint = point; - ca.mAnswer = BITDHT_CONNECT_ERROR_NONE; - - mActions.push_back(ca); - } - // only an error if we initiated the connection. - else if (dpd->mPeerConnectPoint == BD_PROXY_CONNECTION_START_POINT) - { - std::cerr << "p3BitDht::UdpConnectionFailed_locked() "; - std::cerr << "ERROR Request not active, can't stop"; - std::cerr << std::endl; - } - - ReleaseProxyExclusiveMode_locked(dpd, true); -} - - - -void p3BitDht::ReleaseProxyExclusiveMode_locked(DhtPeerDetails *dpd, bool addrChgLikely) -{ -#ifdef DEBUG_BITDHT_COMMON - std::cerr << "p3BitDht::ReleaseProxyExclusiveMode_locked()"; - bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); - std::cerr << std::endl; -#endif - - /* translate id into string for exclusive mode */ - std::string pid; - bdStdPrintNodeId(pid, &(dpd->mDhtId.id), false); - - - if (dpd->mExclusiveProxyLock) - { -#ifdef RS_USE_DHT_STUNNER - if (mProxyStunner->releaseExclusiveMode(pid, addrChgLikely)) - { - dpd->mExclusiveProxyLock = false; - -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::ReleaseProxyExclusiveMode_locked() Lock released by Connection to peer: "; - bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); - std::cerr << std::endl; -#endif - } - else -#else // RS_USE_DHT_STUNNER - (void)addrChgLikely; -#endif // RS_USE_DHT_STUNNER - { - dpd->mExclusiveProxyLock = false; - - std::cerr << "p3BitDht::ReleaseProxyExclusiveMode_locked() ERROR ProxyStunner is not Locked"; - bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); - std::cerr << std::endl; - } - - } - else - { -#ifdef DEBUG_BITDHT_COMMON - std::cerr << "p3BitDht::ReleaseProxyExclusiveMode_locked() Don't Have a Lock"; - std::cerr << std::endl; -#endif - } - -} - - -void p3BitDht::ConnectionFeedback(const RsPeerId& pid, int mode) -{ -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::ConnectionFeedback() peer: " << pid; - std::cerr << " mode: " << mode; - std::cerr << std::endl; -#endif - - switch(mode) - { - case NETMGR_DHT_FEEDBACK_CONNECTED: -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::ConnectionFeedback() HAVE CONNECTED (tcp?/udp) to peer: " << pid; - std::cerr << std::endl; -#endif - - Feedback_Connected(pid); - break; - - case NETMGR_DHT_FEEDBACK_CONN_FAILED: -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::ConnectionFeedback() UDP CONNECTION FAILED to peer: " << pid; - std::cerr << std::endl; -#endif - Feedback_ConnectionFailed(pid); - break; - - case NETMGR_DHT_FEEDBACK_CONN_CLOSED: -#ifdef DEBUG_PEERNET - std::cerr << "p3BitDht::ConnectionFeedback() CONNECTION (tcp?/udp) CLOSED to peer: " << pid; - std::cerr << std::endl; -#endif - Feedback_ConnectionClosed(pid); - break; - } -} - - -/***** Check for a RelayHandler... and call its functions preferentially */ - -int p3BitDht::RelayHandler_LogFailedProxyAttempt(const bdId *srcId, const bdId *destId, uint32_t mode, uint32_t errcode) -{ - - { - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - if ((mRelayHandler) && (mRelayHandler->mLogFailedConnection)) - { - return mRelayHandler->mLogFailedConnection(srcId, destId, mode, errcode); - } - } - - /* NO standard handler */ - return 0; -} - - -int p3BitDht::RelayHandler_InstallRelayConnection(const bdId *srcId, const bdId *destId, - uint32_t mode, uint32_t &bandwidth) -{ - - { - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - if ((mRelayHandler) && (mRelayHandler->mInstallRelay)) - { - return mRelayHandler->mInstallRelay(srcId, destId, mode, bandwidth); - } - } - - /* standard handler */ - return installRelayConnection(srcId, destId, bandwidth); -} - - - - - diff --git a/libretroshare/src/dht/p3bitdht_peers.cc b/libretroshare/src/dht/p3bitdht_peers.cc deleted file mode 100644 index 013a9b47c..000000000 --- a/libretroshare/src/dht/p3bitdht_peers.cc +++ /dev/null @@ -1,752 +0,0 @@ -/******************************************************************************* - * libretroshare/src/dht: p3bitdht_peernet.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009-2010 by Robert Fernie. * - * Copyright (C) 2015-2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "dht/p3bitdht.h" - -#include "bitdht/bdstddht.h" - -#include "tcponudp/udprelay.h" -#include "tcponudp/udpstunner.h" - -#include - -/*** - * - * #define DEBUG_BITDHT 1 - * #define DEBUG_BITDHT_TRANSLATE 1 - * - **/ - -/****************************************************************************************** - ********************************* Existing Interface ************************************* - ******************************************************************************************/ - /* pqiNetAssistConnect - external interface functions */ - /* add / remove peers */ -/***** - * At the moment, findPeer, dropPeer are the only way that peer info enters the dht. - * This will obviously change, and we will have a list of Friends and FoF, - * but for now we need to expect that this function will add unknown pids. - * - */ -#define USE_OLD_DHT_INTERFACE 1 - - -bool p3BitDht::findPeer(const RsPeerId& pid) -{ -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::findPeer(" << pid << ")"; - std::cerr << std::endl; -#endif - bdNodeId nid; - - { - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - DhtPeerDetails *dpd = findInternalRsPeer_locked(pid); - if (!dpd) - { - dpd = addInternalPeer_locked(pid, RsDhtPeerType::FRIEND); - if (!dpd) - { - /* ERROR */ -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::findPeer() ERROR installing InternalPeer"; - std::cerr << std::endl; -#endif - return false; - } - - /* new entry... what do we need to set? */ - dpd->mDhtState = RsDhtPeerDht::SEARCHING; - -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::findPeer() Installed new DhtPeer with pid => NodeId: "; - bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); - std::cerr << std::endl; -#endif - } - else - { - /* old entry */ -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::findPeer() Reactivating DhtPeer with pid => NodeId: "; - bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); - std::cerr << std::endl; -#endif - - if (dpd->mDhtState != RsDhtPeerDht::NOT_ACTIVE) - { -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::findPeer() WARNING DhtState is Already Active!"; - bdStdPrintNodeId(std::cerr, &(dpd->mDhtId.id)); - std::cerr << std::endl; -#endif - } - else - { - /* flag as searching */ - dpd->mDhtState = RsDhtPeerDht::SEARCHING; -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::findPeer() Marking Old Peer as SEARCHING"; - std::cerr << std::endl; -#endif - } - - } - - nid = dpd->mDhtId.id; - -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::findPeer() calling AddFindNode() with pid => NodeId: "; - bdStdPrintNodeId(std::cerr, &nid); - std::cerr << std::endl; -#endif - - } - - /* add in peer */ - mUdpBitDht->addFindNode(&nid, BITDHT_QFLAGS_DO_IDLE | BITDHT_QFLAGS_UPDATES); - - return true ; -} - -bool p3BitDht::dropPeer(const RsPeerId& pid) -{ -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::dropPeer(" << pid << ")"; - std::cerr << std::endl; -#endif - - bdNodeId nid; - - { - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - DhtPeerDetails *dpd = findInternalRsPeer_locked(pid); - if (!dpd) - { -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::dropPeer(" << pid << ") HACK TO INCLUDE FRIEND AS NON-ACTIVE PEER"; - std::cerr << std::endl; -#endif - - //addFriend(pid); - dpd = addInternalPeer_locked(pid, RsDhtPeerType::FOF); - - return false; - } - - /* flag as searching */ - dpd->mDhtState = RsDhtPeerDht::NOT_ACTIVE; - - nid = dpd->mDhtId.id; - -#ifdef DEBUG_BITDHT - std::cerr << "p3BitDht::dropPeer() calling removeFindNode() with pid => NodeId: "; - bdStdPrintNodeId(std::cerr, &nid); - std::cerr << std::endl; -#endif - } - - /* remove in peer */ - mUdpBitDht->removeFindNode(&nid); - - /* not removing from translation */ - - return true ; -} - - -/****************************************************************************************** - ********************************* Basic Peer Details ************************************* - ******************************************************************************************/ - -int p3BitDht::addBadPeer( const sockaddr_storage &addr, uint32_t /*reason*/, - uint32_t /*flags*/, uint32_t /*age*/ ) -{ - //mUdpBitDht->updateKnownPeer(&id, 0, bdflags); - - sockaddr_in addrv4; - sockaddr_storage tmpaddr; - sockaddr_storage_copy(addr, tmpaddr); - if(!sockaddr_storage_ipv6_to_ipv4(tmpaddr)) - { - std::cerr << __PRETTY_FUNCTION__ << " Error: got non IPv4 address!" - << std::endl; - sockaddr_storage_dump(addr); - print_stacktrace(); - return -EINVAL; - } - - struct sockaddr_in *ap = (struct sockaddr_in *) &tmpaddr; - - // convert. - addrv4.sin_family = ap->sin_family; - addrv4.sin_addr = ap->sin_addr; - addrv4.sin_port = ap->sin_port; - -#ifdef RS_USE_DHT_STUNNER - if (mDhtStunner) - { - mDhtStunner->dropStunPeer(addrv4); - } - if (mProxyStunner) - { - mProxyStunner->dropStunPeer(addrv4); - } -#endif // RS_USE_DHT_STUNNER - return 1; -} - - -int p3BitDht::addKnownPeer( const RsPeerId &pid, - const sockaddr_storage &addr, uint32_t flags ) -{ - sockaddr_in addrv4; - sockaddr_clear(&addrv4); - - sockaddr_storage tmpaddr; - sockaddr_storage_copy(addr, tmpaddr); - if( !sockaddr_storage_isnull(addr) && - !sockaddr_storage_ipv6_to_ipv4(tmpaddr) ) - { - std::cerr << __PRETTY_FUNCTION__ << " Error: got non IPv4 address!" - << std::endl; - sockaddr_storage_dump(addr); - print_stacktrace(); - return -EINVAL; - } - - // convert. - struct sockaddr_in *ap = (struct sockaddr_in *) &tmpaddr; - addrv4.sin_family = ap->sin_family; - addrv4.sin_addr = ap->sin_addr; - addrv4.sin_port = ap->sin_port; - - RsDhtPeerType p3type = RsDhtPeerType::ANY; - int bdflags = 0; - bdId id; - bool isOwnId = false; - - switch(flags & NETASSIST_KNOWN_PEER_TYPE_MASK) - { - default: - return 0; - break; - case NETASSIST_KNOWN_PEER_WHITELIST: - p3type = RsDhtPeerType::OTHER; - bdflags = BITDHT_PEER_STATUS_DHT_WHITELIST; - - break; - case NETASSIST_KNOWN_PEER_FOF: - p3type = RsDhtPeerType::FOF; - bdflags = BITDHT_PEER_STATUS_DHT_FOF; - - break; - case NETASSIST_KNOWN_PEER_FRIEND: - p3type = RsDhtPeerType::FRIEND; - bdflags = BITDHT_PEER_STATUS_DHT_FRIEND; - - break; - case NETASSIST_KNOWN_PEER_RELAY: - p3type = RsDhtPeerType::OTHER; - bdflags = BITDHT_PEER_STATUS_DHT_RELAY_SERVER; - - break; - case NETASSIST_KNOWN_PEER_SELF: - p3type = RsDhtPeerType::OTHER; - bdflags = BITDHT_PEER_STATUS_DHT_SELF; - isOwnId = true; - - - break; - } - - if (flags & NETASSIST_KNOWN_PEER_ONLINE) - { - bdflags |= BD_FRIEND_ENTRY_ONLINE; - } - - if (!isOwnId) - { - RS_STACK_MUTEX(dhtMtx); - DhtPeerDetails *dpd = addInternalPeer_locked(pid, p3type); - - - if (bdflags & BD_FRIEND_ENTRY_ONLINE) - { - /* can we update the address? */ - //dpd->mDhtId.addr = addr; - } - - - id.id = dpd->mDhtId.id; - id.addr = addrv4; - } - else - { - // shouldn't use own id without mutex - but it is static! - id.id = mOwnDhtId; - id.addr = addrv4; - } - - mUdpBitDht->updateKnownPeer(&id, 0, bdflags); - - return 1; -} - - -/* Total duplicate of above function - can't be helped, should merge somehow */ -int p3BitDht::addKnownNode(const bdId *id, uint32_t flags) -{ - int bdflags = 0; - - switch(flags & NETASSIST_KNOWN_PEER_TYPE_MASK) - { - default: - return 0; - break; - case NETASSIST_KNOWN_PEER_WHITELIST: - bdflags = BITDHT_PEER_STATUS_DHT_WHITELIST; - - break; - case NETASSIST_KNOWN_PEER_FOF: - bdflags = BITDHT_PEER_STATUS_DHT_FOF; - - break; - case NETASSIST_KNOWN_PEER_FRIEND: - bdflags = BITDHT_PEER_STATUS_DHT_FRIEND; - - break; - case NETASSIST_KNOWN_PEER_RELAY: - bdflags = BITDHT_PEER_STATUS_DHT_RELAY_SERVER; - - break; - case NETASSIST_KNOWN_PEER_SELF: - bdflags = BITDHT_PEER_STATUS_DHT_SELF; - - break; - } - - if (flags & NETASSIST_KNOWN_PEER_ONLINE) - { - bdflags |= BD_FRIEND_ENTRY_ONLINE; - } - - mUdpBitDht->updateKnownPeer(id, 0, bdflags); - - return 1; -} - - - -#if 0 -int p3BitDht::addFriend(const std::string pid) -{ - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - return (NULL != addInternalPeer_locked(pid, RsDhtPeerType::FRIEND)); -} - - -int p3BitDht::addFriendOfFriend(const std::string pid) -{ - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - return (NULL != addInternalPeer_locked(pid, RsDhtPeerType::FOF)); -} - - -int p3BitDht::addOther(const std::string pid) -{ - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - return (NULL != addInternalPeer_locked(pid, RsDhtPeerType::OTHER)); -} -#endif - - -int p3BitDht::removePeer(const RsPeerId& pid) -{ - RsStackMutex stack(dhtMtx); /********* LOCKED *********/ - - return removeInternalPeer_locked(pid); -} - - -/****************************************************************************************** - ********************************* Basic Peer Details ************************************* - ******************************************************************************************/ - -DhtPeerDetails *p3BitDht::addInternalPeer_locked(const RsPeerId& pid, RsDhtPeerType type) -{ - /* create the data structure */ - if (!havePeerTranslation_locked(pid)) - { - storeTranslation_locked(pid); - } - - bdNodeId id; - if (!lookupNodeId_locked(pid, &id)) - { - return 0; - } - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&id, RsDhtPeerType::ANY); - if (!dpd) - { - DhtPeerDetails newdpd; - - newdpd.mDhtId.id = id; - newdpd.mRsId = pid; - newdpd.mDhtState = RsDhtPeerDht::NOT_ACTIVE; - newdpd.mPeerType = RsDhtPeerType::ANY; - - mPeers[id] = newdpd; - dpd = findInternalDhtPeer_locked(&id, RsDhtPeerType::ANY); - - if(dpd == NULL) - { - std::cerr << "(EE) inconsistency error in p3BitDht::addInternalPeer_locked() Cannot find peer that was just added." << std::endl; - return NULL; - } - } - - /* what do we need to reset? */ - dpd->mPeerType = type; - - return dpd; -} - - -int p3BitDht::removeInternalPeer_locked(const RsPeerId& pid) -{ - bdNodeId id; - if (!lookupNodeId_locked(pid, &id)) - { - return 0; - } - - std::map::iterator it = mPeers.find(id); - if (it == mPeers.end()) - { - return 0; - } - - mPeers.erase(it); - - // remove the translation? - removeTranslation_locked(pid); - - return 1; -} - - -/* indexed by bdNodeId, as this is the more used call interface */ -DhtPeerDetails *p3BitDht::findInternalDhtPeer_locked(const bdNodeId *id, RsDhtPeerType type) -{ - std::map::iterator it = mPeers.find(*id); - if (it == mPeers.end()) - { - return NULL; - } - if (type != RsDhtPeerType::ANY) - { - if (it->second.mPeerType != type) - { - return NULL; - } - } - return &(it->second); -} - - -/* interface to get with alt id */ -DhtPeerDetails *p3BitDht::findInternalRsPeer_locked(const RsPeerId &pid) -{ - /* create the data structure */ - if (!havePeerTranslation_locked(pid)) - { - return NULL; - } - - bdNodeId id; - if (!lookupNodeId_locked(pid, &id)) - { - return NULL; - } - - DhtPeerDetails *dpd = findInternalDhtPeer_locked(&id,RsDhtPeerType::ANY); - - return dpd; -} - - -/****************************************************************************************** - *************************** Fundamental Node Translation ********************************* - ******************************************************************************************/ - -bool p3BitDht::havePeerTranslation_locked(const RsPeerId &pid) -{ -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::havePeerTranslation_locked() for : " << pid; - std::cerr << std::endl; -#endif - - std::map::iterator it; - it = mTransToNodeId.find(pid); - if (it == mTransToNodeId.end()) - { -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::havePeerTranslation_locked() failed Missing translation"; - std::cerr << std::endl; -#endif - - return false; - } - -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::havePeerTranslation_locked() Found NodeId: "; - bdStdPrintNodeId(std::cerr, &(it->second)); - std::cerr << std::endl; -#endif - - return true; -} - - -int p3BitDht::lookupNodeId_locked(const RsPeerId& pid, bdNodeId *id) -{ -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::lookupNodeId_locked() for : " << pid; - std::cerr << std::endl; -#endif - - std::map::iterator it; - it = mTransToNodeId.find(pid); - if (it == mTransToNodeId.end()) - { -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::lookupNodeId_locked() failed"; - std::cerr << std::endl; -#endif - - return 0; - } - *id = it->second; - - -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::lookupNodeId_locked() Found NodeId: "; - bdStdPrintNodeId(std::cerr, id); - std::cerr << std::endl; -#endif - - return 1; -} - - -int p3BitDht::lookupRsId_locked(const bdNodeId *id, RsPeerId&pid) -{ -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::lookupRsId_locked() for : "; - bdStdPrintNodeId(std::cerr, id); - std::cerr << std::endl; -#endif - - std::map::iterator nit; - nit = mTransToRsId.find(*id); - if (nit == mTransToRsId.end()) - { -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::lookupRsId_locked() failed"; - std::cerr << std::endl; -#endif - - return 0; - } - pid = nit->second; - - -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::lookupRsId_locked() Found Matching RsId: " << pid; - std::cerr << std::endl; -#endif - - return 1; -} - -int p3BitDht::storeTranslation_locked(const RsPeerId& pid) -{ -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::storeTranslation_locked(" << pid << ")"; - std::cerr << std::endl; -#endif - - bdNodeId nid; - calculateNodeId(pid, &nid); - -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::storeTranslation_locked() Converts to NodeId: "; - bdStdPrintNodeId(std::cerr, &(nid)); - std::cerr << std::endl; -#endif - - mTransToNodeId[pid] = nid; - mTransToRsId[nid] = pid; - -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::storeTranslation_locked() Success"; - std::cerr << std::endl; -#endif - - return 1; -} - -int p3BitDht::removeTranslation_locked(const RsPeerId& pid) -{ - -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::removeTranslation_locked(" << pid << ")"; - std::cerr << std::endl; -#endif - - std::map::iterator it = mTransToNodeId.find(pid); - it = mTransToNodeId.find(pid); - if (it == mTransToNodeId.end()) - { - std::cerr << "p3BitDht::removeTranslation_locked() ERROR MISSING TransToNodeId"; - std::cerr << std::endl; - /* missing */ - return 0; - } - - bdNodeId nid = it->second; - -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::removeTranslation_locked() Found Translation: NodeId: "; - bdStdPrintNodeId(std::cerr, &(nid)); - std::cerr << std::endl; -#endif - - - std::map::iterator nit; - nit = mTransToRsId.find(nid); - if (nit == mTransToRsId.end()) - { - std::cerr << "p3BitDht::removeTranslation_locked() ERROR MISSING TransToRsId"; - std::cerr << std::endl; - /* inconsistent!!! */ - return 0; - } - - mTransToNodeId.erase(it); - mTransToRsId.erase(nit); - -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::removeTranslation_locked() SUCCESS"; - std::cerr << std::endl; -#endif - - return 1; -} - - -/* Adding a little bit of fixed text... - * This allows us to ensure that only compatible peers will find each other - */ - -const uint8_t RS_DHT_VERSION_LEN = 17; -const uint8_t rs_dht_version_data[RS_DHT_VERSION_LEN] = "RS_VERSION_0.5.1"; - -/******************** Conversion Functions **************************/ -int p3BitDht::calculateNodeId(const RsPeerId& pid, bdNodeId *id) -{ - /* generate node id from pid */ -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << "p3BitDht::calculateNodeId() " << pid; -#endif - - /* use a hash to make it impossible to reverse */ - - uint8_t sha_hash[SHA_DIGEST_LENGTH]; - memset(sha_hash,0,SHA_DIGEST_LENGTH*sizeof(uint8_t)) ; - SHA_CTX *sha_ctx = new SHA_CTX; - SHA1_Init(sha_ctx); - - SHA1_Update(sha_ctx, rs_dht_version_data, RS_DHT_VERSION_LEN); - SHA1_Update(sha_ctx, pid.toByteArray(), RsPeerId::SIZE_IN_BYTES); - SHA1_Final(sha_hash, sha_ctx); - - for(int i = 0; i < SHA_DIGEST_LENGTH && (i < BITDHT_KEY_LEN); i++) - { - id->data[i] = sha_hash[i]; - } - delete sha_ctx; - -#ifdef DEBUG_BITDHT_TRANSLATE - std::cerr << " => "; - bdStdPrintNodeId(std::cerr, id); - std::cerr << std::endl; -#endif - - return 1; -} - - -/******************** Conversion Functions **************************/ - -DhtPeerDetails::DhtPeerDetails() -{ - mDhtState = RsDhtPeerDht::NOT_ACTIVE; - - mDhtState = RsDhtPeerDht::SEARCHING; - mDhtUpdateTS = time(NULL); - - mPeerReqStatusMsg = "Just Added"; - mPeerReqState = RsDhtPeerRequest::STOPPED; - mPeerReqMode = 0; - //mPeerReqProxyId; - mPeerReqTS = time(NULL); - - mExclusiveProxyLock = false; - - mPeerCbMsg = "No CB Yet"; - mPeerCbMode = 0; - mPeerCbPoint = 0; - //mPeerCbProxyId = 0; - //mPeerCbDestId = 0; - mPeerCbTS = 0; - - mPeerConnectState = RsDhtPeerConnectState::DISCONNECTED; - mPeerConnectMsg = "Disconnected"; - mPeerConnectMode = 0; - //dpd->mPeerConnectProxyId; - mPeerConnectPoint = 0; - - mPeerConnectUdpTS = 0; - mPeerConnectTS = 0; - mPeerConnectClosedTS = 0; - - bdsockaddr_clear(&(mPeerConnectAddr)); -} - diff --git a/libretroshare/src/dht/p3bitdht_relay.cc b/libretroshare/src/dht/p3bitdht_relay.cc deleted file mode 100644 index 47099a2f1..000000000 --- a/libretroshare/src/dht/p3bitdht_relay.cc +++ /dev/null @@ -1,408 +0,0 @@ -/******************************************************************************* - * libretroshare/src/dht: p3bitdht_relay.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009-2011 by Robert Fernie. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ - -#include "util/rsnet.h" -#include "dht/p3bitdht.h" - -#include "tcponudp/udprelay.h" -#include "bitdht/bdstddht.h" - -#include "rsitems/rsconfigitems.h" - - -/*********************************************************************************************** - ********** External RsDHT Interface for Dht-Relay Control ************************************* -************************************************************************************************/ - -int p3BitDht::setupRelayDefaults() -{ - RsDhtRelayMode mode = RsDhtRelayMode::ENABLED | RsDhtRelayMode::OFF; - setRelayMode(mode); - - return 1; -} - - -/**** THIS IS A TEMPORARY HACK INTERFACE - UNTIL WE HAVE MORE SOFISTICATED SYSTEM - * NB: using bdNodeIds here, rather than SSL IDS. - *****/ - -int p3BitDht::getRelayServerList(std::list &ids) -{ - RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ - - ids = mRelayServerList; - - return 1; -} - -int p3BitDht::addRelayServer(std::string id) -{ - RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ - - std::list::iterator it; - it = std::find(mRelayServerList.begin(), mRelayServerList.end(), id); - if (it == mRelayServerList.end()) - { - mRelayServerList.push_back(id); - } - - IndicateConfigChanged(); - return 1; -} - -int p3BitDht::removeRelayServer(std::string id) -{ - - RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ - - std::list::iterator it; - it = std::find(mRelayServerList.begin(), mRelayServerList.end(), id); - if (it != mRelayServerList.end()) - { - mRelayServerList.erase(it); - } - - IndicateConfigChanged(); - return 1; -} - -int p3BitDht::pushRelayServers() -{ - std::list servers; - - { - RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ - - servers = mRelayServerList; - } - - std::list::iterator it; - for(it = servers.begin(); it != servers.end(); ++it) - { - /* push it to dht */ - uint32_t bdflags = BITDHT_PEER_STATUS_DHT_RELAY_SERVER; - bdId id; - bdStdLoadNodeId(&(id.id), *it); - - mUdpBitDht->updateKnownPeer(&id, 0, bdflags); - - } - return 1; -} - - -RsDhtRelayMode p3BitDht::getRelayMode() -{ - RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ - - return mRelayMode; -} - -int p3BitDht::setRelayMode(RsDhtRelayMode mode) -{ - std::cerr << "p3BitDht::setRelayMode(" << mode << ")"; - std::cerr << std::endl; - - if (!!(mode & RsDhtRelayMode::ENABLED)) - { - mUdpBitDht->ConnectionOptions( - BITDHT_CONNECT_MODE_DIRECT | BITDHT_CONNECT_MODE_PROXY | BITDHT_CONNECT_MODE_RELAY, - BITDHT_CONNECT_OPTION_AUTOPROXY); - } - else - { - mUdpBitDht->ConnectionOptions( - BITDHT_CONNECT_MODE_DIRECT | BITDHT_CONNECT_MODE_PROXY, - BITDHT_CONNECT_OPTION_AUTOPROXY); - } - - RsDhtRelayMode relaymode = mode & RsDhtRelayMode::MASK; - - switch(relaymode) - { - case RsDhtRelayMode::OFF: - mUdpBitDht->setDhtMode(BITDHT_MODE_RELAYSERVERS_IGNORED); - break; - case RsDhtRelayMode::ON: - pushRelayServers(); - mUdpBitDht->setDhtMode(BITDHT_MODE_RELAYSERVERS_FLAGGED); - break; - case RsDhtRelayMode::SERVER: - pushRelayServers(); - mUdpBitDht->setDhtMode(BITDHT_MODE_RELAYSERVERS_SERVER); - break; - case RsDhtRelayMode::ENABLED: - case RsDhtRelayMode::DISABLED: - case RsDhtRelayMode::MASK: - break; - } - - { - RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ - mRelayMode = mode; - } - - IndicateConfigChanged(); - - return 1; -} - -int p3BitDht::getRelayAllowance(RsDhtRelayClass classIdx, uint32_t &count, uint32_t &bandwidth) -{ - std::cerr << "p3BitDht::getRelayAllowance(" << static_cast::type>(classIdx) << "): "; - if ((classIdx >= RsDhtRelayClass::ALL) && (classIdx < RsDhtRelayClass::NUM_CLASS)) - { - count = mRelay->getRelayClassMax(static_cast::type>(classIdx)); - bandwidth = mRelay->getRelayClassBandwidth(static_cast::type>(classIdx)); - - std::cerr << " count: " << count << " bandwidth: " << bandwidth; - std::cerr << std::endl; - return 1; - } - std::cerr << " Invalid classIdx"; - std::cerr << std::endl; - - return 0; -} - -int p3BitDht::setRelayAllowance(RsDhtRelayClass classIdx, uint32_t count, uint32_t bandwidth) -{ - std::cerr << "p3BitDht::getRelayAllowance(" << static_cast::type>(classIdx) << ", "; - std::cerr << ", " << count << ", " << bandwidth << ")"; - std::cerr << std::endl; - - int retval = mRelay->setRelayClassMax(static_cast::type>(classIdx), count, bandwidth); - IndicateConfigChanged(); - - return retval; -} - - -/*********************************************************************************************** - ********** External RsDHT Interface for Dht-Relay Control ************************************* -************************************************************************************************/ - -/*****************************************************************/ -/*********************** p3config ******************************/ - /* Key Functions to be overloaded for Full Configuration */ -RsSerialiser *p3BitDht::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser ; - rss->addSerialType(new RsGeneralConfigSerialiser()); - return rss ; -} - - -bool p3BitDht::saveList(bool &cleanup, std::list &saveList) -{ - cleanup = true; - - std::cerr << "p3BitDht::saveList()"; - std::cerr << std::endl; - - - RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ - RsConfigKeyValueSet *config = new RsConfigKeyValueSet(); - - RsTlvKeyValue kv; - - /* Push Relay Class Stuff */ - int i; - for(i = 0; i < static_cast::type>(RsDhtRelayClass::NUM_CLASS); ++i) - { - rs_sprintf(kv.key, "RELAY_CLASS%d_COUNT", i); - rs_sprintf(kv.value, "%d", mRelay->getRelayClassMax(i)); - config->tlvkvs.pairs.push_back(kv); - - rs_sprintf(kv.key, "RELAY_CLASS%d_BANDWIDTH", i); - rs_sprintf(kv.value, "%d", mRelay->getRelayClassBandwidth(i)); - config->tlvkvs.pairs.push_back(kv); - } - - /* add RelayMode */ - { - kv.key = "RELAY_MODE"; - rs_sprintf(kv.value, "%lu", mRelayMode); - config->tlvkvs.pairs.push_back(kv); - } - - /* add Servers */ - std::list::iterator it; - for(i = 0, it = mRelayServerList.begin(); it != mRelayServerList.end(); ++it, ++i) - { - rs_sprintf(kv.key, "RELAY_SERVER%d", i); - kv.value = *it; - config->tlvkvs.pairs.push_back(kv); - } - - std::cerr << "BITDHT Save Item:"; - std::cerr << std::endl; - - config->print(std::cerr, 0); - - saveList.push_back(config); - - return true; -} - -void p3BitDht::saveDone() -{ - return; -} - -bool p3BitDht::loadList(std::list& load) -{ - std::cerr << "p3BitDht::loadList()"; - std::cerr << std::endl; - - if (load.empty() || (load.size() > 1)) - { - /* error */ - std::cerr << "p3BitDht::loadList() Error only expecting 1 item"; - std::cerr << std::endl; - - for(std::list::iterator it=load.begin();it!=load.end();++it) - delete *it ; - - load.clear() ; - return false; - } - RsItem *item = load.front(); - - RsConfigKeyValueSet *config = dynamic_cast(item); - - if (!config) - { - /* error */ - std::cerr << "p3BitDht::loadList() Error expecting item = config"; - std::cerr << std::endl; - delete item ; - return false; - } - - //std::cerr << "BITDHT Load Item:"; - //std::cerr << std::endl; - - //config->print(std::cerr, 0); - - std::list servers; - int peers[static_cast::type>(RsDhtRelayClass::NUM_CLASS)] = {0}; - int bandwidth[static_cast::type>(RsDhtRelayClass::NUM_CLASS)] = {0}; - - bool haveMode = false; - RsDhtRelayMode mode = RsDhtRelayMode::DISABLED; - - std::list::iterator it; - for(it = config->tlvkvs.pairs.begin(); it != config->tlvkvs.pairs.end(); ++it) - { - std::string key = it->key; - std::string value = it->value; - if (0 == strncmp(key.c_str(), "RELAY_SERVER", 12)) - { - /* add to RELAY_SERVER List */ - servers.push_back(value); - //std::cerr << "p3BitDht::loadList() Found Server: " << value; - //std::cerr << std::endl; - } - else if (0 == strncmp(key.c_str(), "RELAY_MODE", 10)) - { - mode = static_cast(atoi(value.c_str())); - haveMode = true; - - //std::cerr << "p3BitDht::loadList() Found Mode: " << mode; - //std::cerr << std::endl; - } - else if (0 == strncmp(key.c_str(), "RELAY_CLASS", 11)) - { - /* len check */ - if (key.length() < 14) - continue; - - int idx = 0; - uint32_t val = atoi(value.c_str()); - switch(key[11]) - { - default: - case '0': - idx = 0; - break; - case '1': - idx = 1; - break; - case '2': - idx = 2; - break; - case '3': - idx = 3; - break; - } - - if (key[13] == 'C') - { - //std::cerr << "p3BitDht::loadList() Found Count(" << idx << "): "; - //std::cerr << val; - //std::cerr << std::endl; - peers[idx] = val; - } - else - { - //std::cerr << "p3BitDht::loadList() Found Bandwidth(" << idx << "): "; - //std::cerr << val; - //std::cerr << std::endl; - bandwidth[idx] = val; - } - } - else - { - //std::cerr << "p3BitDht::loadList() Unknown Key:value: " << key; - //std::cerr << ":" << value; - //std::cerr << std::endl; - } - } - - - // Cleanup config. - delete config; - - { - RsStackMutex stack(dhtMtx); /*********** LOCKED **********/ - mRelayServerList = servers; - } - - int i; - for(i = 0; i < static_cast::type>(RsDhtRelayClass::NUM_CLASS); ++i) - { - mRelay->setRelayClassMax(i, peers[i], bandwidth[i]); - } - - if (haveMode) - { - setRelayMode(mode); - } - - load.clear() ; - return true; -} - -/*****************************************************************/ - diff --git a/libretroshare/src/dht/stunaddrassist.h b/libretroshare/src/dht/stunaddrassist.h deleted file mode 100644 index 195337b1a..000000000 --- a/libretroshare/src/dht/stunaddrassist.h +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************* - * libretroshare/src/dht: stunaddrassist.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Robert Fernie. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ - -#ifndef STUN_ADDR_ASSIST_H -#define STUN_ADDR_ASSIST_H - -#include "pqi/pqiassist.h" -#include "tcponudp/udpstunner.h" - -class stunAddrAssist: public pqiAddrAssist -{ - public: - - stunAddrAssist(UdpStunner *stunner) - { - mStunner = stunner; - } - -virtual bool getExternalAddr(struct sockaddr_storage &remote, uint8_t &stable) - { - // IPV4 ONLY. - struct sockaddr_in remotev4; - if (mStunner->externalAddr(remotev4, stable)) - { - sockaddr_storage_clear(remote); - struct sockaddr_in *addr = (struct sockaddr_in *) &remote; - addr->sin_family = AF_INET; - addr->sin_addr = remotev4.sin_addr; - addr->sin_port = remotev4.sin_port; - - return true; - } - return false; - } - -virtual int tick() - { - return mStunner->tick(); - } - -virtual void setRefreshPeriod(int32_t period) - { - return mStunner->setTargetStunPeriod(period); - } - - private: - - UdpStunner *mStunner; -}; - -#endif - diff --git a/libretroshare/src/file_sharing/README.txt b/libretroshare/src/file_sharing/README.txt deleted file mode 100644 index 947cf64be..000000000 --- a/libretroshare/src/file_sharing/README.txt +++ /dev/null @@ -1,215 +0,0 @@ -Design document for the new file list sharing system. -==================================================== - -Big picture ------------ - - p3SharesManager - Functionalities - * contains the list of shared files - - responds to search, requests for FileInfo - * responsible for sync-ing file lists between peers - - Level 3: interface with GUI - - regularly issue syncing requests in background - - automatically issue syncing requests as files are browsed - - Level 2: internal stuff - - examine syncing requests. Only get data - - Level 1: syncing system - - list of pending requests with priorities, sort them and handle response from friends - - Level 0: interface with friends - - serialisation/deserialisation of file list items - - FileIndex should support: - - O(log(n)) search for hash - - O(n) search for regular exp - - O(1) remove of file and directory - - Members - - list of file indexes - => map of - - - - Parent classes - - p3Service (sends and receives information about shared files) - - Notes: - - the same file should be able to be held by two different directories. Hash search will return a single hit. - - the previously existing PersonEntry had no field and was overloading DirEntry, with overwritten file names, hashes etc. Super bad! - -Directory storage file format ------------------------------ - * should be extensible (xml or binary format? Binary, because it's going to be encrypted anyway) - => works with binary fields - => - - [= version =] - [= peer id =] - [= num entries =] - [= some information =] - - [entry tag] [entry size] [Field ID 01] [field size v 01] [Field data 01] [Field ID 02] [field size v 02] [Field data 02] ... - [entry tag] [entry size] [Field ID 01] [field size v 01] [Field data 01] [Field ID 02] [field size v 02] [Field data 02] ... - [entry tag] [entry size] [Field ID 01] [field size v 01] [Field data 01] [Field ID 02] [field size v 02] [Field data 02] ... - ... - 2 1-5 v 2 1-5 v - * entry content - Tag | Content | Size - ----------------+--------------------------------------+------ - 01 | sha1 hash | 20 - 01 | sha1^2 hash | 20 - 02 | file name | < 512 - 03 | file size | 8 - 04 | dir name | < 512 - 05 | last modif time local | 4 - 06 | last modif time including sub-dirs | 4 - -Classes -------- - - p3ShareManager - - tick() - * handle pending syncing requests => sends items - * watch shared directories - => hash new files - => updates shared files - * - - - list of shared parent directories, with share flags - - FileIndex // should support hierarchical navigation, load/save - - - - LocalFileIndex: public FileIndex - - std::map // used for search - - FileInfo - - std::string name - - RsFileHash hash - - uint64_t size - - rstime_t Last modification time - - LocalFileInfo: public FileInfo - - rstime_t Last data access time - - uint64_t Total data uploaded - - uint32_t ShareFlags - - SharedDirectory - - parent groups - - group flags - -Best data structure for file index ----------------------------------- - - | Hash map map list - ----------------+-----------------+------------+-------------- - Adding | Constant | log(n) | O(n) - Hash search | Constant | log(n) | O(n) - Name/exp search | O(n) | O(n) | O(n) - Recursive browse| Constant | log(n) | O(n) - - Should we use the same struct for files and directories? - - Sol 1: - DirClass + PersonClass + FileEntry class - - each has pointers to elements list of the same type - - lists are handled for Files (all file entries), - - Directories are represented by the hash of the full path - - Sol 2: - Same class for all elements, in a single hash map. Each element is - defined by its type (Dir, Person, File) which all have a hash. - -Syncing between peers ---------------------- - -Generating sync events - * Client side - - for each directory, in breadth first order - - if directory has changed, or last update is old - => push a sync request - - store the peer's last up time. Compare with peer uptimes recursively. - - * Server side - - after a change, broadcast a "directory changed" packet to all connected friends - - * directoy updater - - crawl through directories - - compare TS of files, missing files, new files - - feed a queue of files to hash - - directory whatcher gets notified when files are hashed - - - a separate component hashes files (FileHashingProcess) - - DirectoryWatcher (watches a hierarchy) File List (stores a directory hierarchy) - | | - | | - | | - +-----------------------+------------------+ - | | - Shared File Service | - | | - | | - +----------- own file list -------+---------- Encrypted/compressed save to disk - | | | - +----------- friend file lists ---+ -Roadmap -------- - -[X] complete this file until a proper description of the whole thing is achieved. -[X] create a new directory and implement the .h for the basic functionality -[ ] look into existing code in ftServer for the integration, but don't change anything yet -[X] setup class hierarchy -[ ] merge hash cache into file lists. -[ ] new format for saving of FileIndex to make it locally encrypted, compact and extensible -[ ] create basic directory functionality with own files: re-hash, and store -[ ] display own files in GUI, with proper update and working sort - -TODO -==== - - [ ] directory handler - [ ] abstract functions to keep a directory and get updates to it. - [ ] hierarchical storage representation. - [ ] allow add/delete entries - [ ] auto-cleanup - - [ ] directory updater - [ ] abstract layer - [ ] crawls the directory and ask updates - - [ ] derive local directory updater - [ ] crawl local files, and asks updates to storage class - [ ] derive remote directory updater - [ ] crawl stored files, and request updates to storage class - - [ ] load/save of directory content. Should be extensible - [ ] p3FileLists with minimal functonality: no exchange. Only storage of own file lists - [ ] service (items) for p3FileLists - [ ] connect RemoteDirModel to new system - [ ] test GUI functions - [ ] test update between peers - - - - - - - - - - - - - - - - - - - - diff --git a/libretroshare/src/file_sharing/dir_hierarchy.cc b/libretroshare/src/file_sharing/dir_hierarchy.cc deleted file mode 100644 index 6504da96f..000000000 --- a/libretroshare/src/file_sharing/dir_hierarchy.cc +++ /dev/null @@ -1,1289 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: dir_hierarchy.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016 Mr.Alice * - * Copyright (C) 2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ -#include -#include - -#include "util/rstime.h" -#include "util/rsdir.h" -#include "util/rsprint.h" -#include "retroshare/rsexpr.h" -#include "dir_hierarchy.h" -#include "filelist_io.h" -#include "file_sharing_defaults.h" -#include "util/cxx17retrocompat.h" - -#ifdef RS_DEEP_FILES_INDEX -# include "deep_search/filesindex.hpp" -#endif // def RS_DEEP_FILES_INDEX - -//#define DEBUG_DIRECTORY_STORAGE 1 - -typedef FileListIO::read_error read_error; - -/******************************************************************************************************************/ -/* Internal File Hierarchy Storage */ -/******************************************************************************************************************/ - -template typename std::set::iterator erase_from_set(typename std::set& s,const typename std::set::iterator& it) -{ - typename std::set::iterator tmp(it); - ++tmp; - s.erase(it) ; - return tmp; -} - -// This class handles the file hierarchy -// A Mutex is used to ensure total coherence at this level. So only abstracted operations are allowed, -// so that the hierarchy stays completely coherent between calls. - -InternalFileHierarchyStorage::InternalFileHierarchyStorage() : mRoot(0) -{ - DirEntry *de = new DirEntry("") ; - - de->row=0; - de->parent_index=0; - de->dir_modtime=0; - de->dir_hash=RsFileHash() ; // null hash is root by convention. - - mNodes.push_back(de) ; - mDirHashes[de->dir_hash] = 0 ; - - mTotalSize = 0 ; - mTotalFiles = 0 ; -} - -bool InternalFileHierarchyStorage::getDirHashFromIndex( - const DirectoryStorage::EntryIndex& index, RsFileHash& hash ) const -{ - if(!checkIndex(index,FileStorageNode::TYPE_DIR)) - return false ; - - hash = static_cast(mNodes[index])->dir_hash ; - - return true; -} - -bool InternalFileHierarchyStorage::getIndexFromDirHash(const RsFileHash& hash,DirectoryStorage::EntryIndex& index) -{ - std::map::iterator it = mDirHashes.find(hash) ; - - if(it == mDirHashes.end()) - return false; - - index = it->second; - - /* make sure the hash actually points to some existing directory. If not, - * remove it. This is an opportunistic update of dir hashes: when we need - * them, we check them. */ - if( !checkIndex(index, FileStorageNode::TYPE_DIR) || - static_cast(mNodes[index])->dir_hash != hash ) - { - RS_INFO("removing non existing dir hash: ", hash, " from dir hash list"); - mDirHashes.erase(it); - return false; - } - return true; -} - -bool InternalFileHierarchyStorage::getIndexFromFileHash( - const RsFileHash& hash, DirectoryStorage::EntryIndex& index ) -{ - auto it = std::as_const(mFileHashes).find(hash); - if(it == mFileHashes.end()) return false; - - index = it->second; - - /* make sure the hash actually points to some existing file. If not, remove - * it. This is an opportunistic update of file hashes: when we need them, - * we check them. */ - if( !checkIndex(it->second, FileStorageNode::TYPE_FILE) || - static_cast(mNodes[index])->file_hash != hash ) - { - RS_INFO("removing non existing file hash: ", hash, " from file hash list"); - mFileHashes.erase(it); - return false; - } - - return true; -} - -bool InternalFileHierarchyStorage::getChildIndex(DirectoryStorage::EntryIndex e,int row,DirectoryStorage::EntryIndex& c) const -{ - if(!checkIndex(e,FileStorageNode::TYPE_DIR)) - return false ; - - const DirEntry& d = *static_cast(mNodes[e]) ; - - if((uint32_t)row < d.subdirs.size()) - { - c = d.subdirs[row] ; - return true ; - } - - if((uint32_t)row < d.subdirs.size() + d.subfiles.size()) - { - c = d.subfiles[row - (int)d.subdirs.size()] ; - return true ; - } - return false; -} - -int InternalFileHierarchyStorage::parentRow(DirectoryStorage::EntryIndex e) -{ - if(!checkIndex(e,FileStorageNode::TYPE_DIR | FileStorageNode::TYPE_FILE) || e==0) - return -1 ; - - return mNodes[mNodes[e]->parent_index]->row; -} - -// high level modification routines - -bool InternalFileHierarchyStorage::isIndexValid(DirectoryStorage::EntryIndex e) const -{ - return e < mNodes.size() && mNodes[e] != NULL ; -} - -bool InternalFileHierarchyStorage::updateSubDirectoryList( - const DirectoryStorage::EntryIndex& indx, - const std::set& subdirs, - const RsFileHash& random_hash_seed ) -{ - if(!checkIndex(indx,FileStorageNode::TYPE_DIR)) - return false; - - DirEntry& d(*static_cast(mNodes[indx])) ; - - std::set should_create(subdirs); - - for(uint32_t i=0;i(mNodes[d.subdirs[i]])->dir_name) == subdirs.end()) - { -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << "[directory storage] Removing subdirectory " << static_cast(mNodes[d.subdirs[i]])->dir_name << " with index " << d.subdirs[i] << std::endl; -#endif - - if( !removeDirectory(d.subdirs[i])) - i++ ; - } - else - { -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << "[directory storage] Keeping existing subdirectory " << static_cast(mNodes[d.subdirs[i]])->dir_name << " with index " << d.subdirs[i] << std::endl; -#endif - - should_create.erase(static_cast(mNodes[d.subdirs[i]])->dir_name) ; - ++i; - } - - for(std::set::const_iterator it(should_create.begin());it!=should_create.end();++it) - { -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << "[directory storage] adding new subdirectory " << it->first << " at index " << mNodes.size() << std::endl; -#endif - - DirEntry *de = new DirEntry(*it) ; - - de->row = mNodes.size(); - de->parent_index = indx; - de->dir_modtime = 0;// forces parsing.it->second; - de->dir_parent_path = RsDirUtil::makePath(d.dir_parent_path, d.dir_name) ; - de->dir_hash = createDirHash(de->dir_name,d.dir_hash,random_hash_seed) ; - - mDirHashes[de->dir_hash] = mNodes.size() ; - - d.subdirs.push_back(mNodes.size()) ; - mNodes.push_back(de) ; - } - - return true; -} - -RsFileHash InternalFileHierarchyStorage::createDirHash(const std::string& dir_name, const RsFileHash& dir_parent_hash, const RsFileHash& random_hash_salt) -{ - // What we need here: a unique identifier - // - that cannot be bruteforced to find the real directory name and path - // - that is used by friends to refer to a specific directory. - - // Option 1: compute H(some_secret_salt + dir_name + dir_parent_path) - // and keep the same salt so that we can re-create the hash - // - // Option 2: compute H(virtual_path). That only works at the level of LocalDirectoryStorage - // - // Option 3: just compute something random, but then we need to store it so as to not - // confuse friends when restarting. - - RsTemporaryMemory mem(dir_name.size() + 2*RsFileHash::SIZE_IN_BYTES) ; - - memcpy( mem, random_hash_salt.toByteArray(),RsFileHash::SIZE_IN_BYTES) ; - memcpy(&mem[ RsFileHash::SIZE_IN_BYTES], dir_parent_hash.toByteArray(),RsFileHash::SIZE_IN_BYTES) ; - memcpy(&mem[2*RsFileHash::SIZE_IN_BYTES],dir_name.c_str(), dir_name.size()) ; - - RsFileHash res = RsDirUtil::sha1sum( mem,mem.size() ) ; - -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << "Creating new dir hash for dir " << dir_name << ", parent dir hash=" << dir_parent_hash << " seed=[hidden]" << " result is " << res << std::endl; -#endif - - return res ; -} - -bool InternalFileHierarchyStorage::removeDirectory(DirectoryStorage::EntryIndex indx) // no reference here! Very important. Otherwise, the messign we do inside can change the value of indx!! -{ - // check that it's a directory - - if(!checkIndex(indx,FileStorageNode::TYPE_DIR)) - return false; - - if(indx == 0) - return nodeAccessError("checkIndex(): Cannot remove top level directory") ; - -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << "(--) Removing directory " << indx << std::endl; - print(); -#endif - // remove from parent - - DirEntry& d(*static_cast(mNodes[indx])) ; - DirEntry& parent_dir(*static_cast(mNodes[d.parent_index])); - - for(uint32_t i=0;i= mNodes.size() || mNodes[indx] == NULL) - return nodeAccessError("checkIndex(): Node does not exist") ; - - if(! (mNodes[indx]->type() & type)) - return nodeAccessError("checkIndex(): Node is of wrong type") ; - - return true; -} - -bool InternalFileHierarchyStorage::updateSubFilesList( - const DirectoryStorage::EntryIndex& indx, - const std::map& subfiles, - std::map& new_files ) -{ - if(!checkIndex(indx, FileStorageNode::TYPE_DIR)) - { - RS_ERR("indx: ", indx, std::errc::not_a_directory); - print_stacktrace(); - return false; - } - - DirEntry& d(*static_cast(mNodes[indx])) ; - new_files = subfiles ; - - // remove from new_files the ones that already exist and have a modf time that is not older. - - for(uint32_t i=0;i(mNodes[d.subfiles[i]])) ; - std::map::const_iterator it = subfiles.find(f.file_name) ; - - if(it == subfiles.end()) // file does not exist anymore => delete - { -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << "[directory storage] removing non existing file " << f.file_name << " at index " << d.subfiles[i] << std::endl; -#endif - - deleteFileNode(d.subfiles[i]) ; - - d.subfiles[i] = d.subfiles[d.subfiles.size()-1] ; - d.subfiles.pop_back(); - continue; - } - - // file is newer and/or has different size - if(it->second.modtime != f.file_modtime || it->second.size != f.file_size) - { - // hash needs recomputing - f.file_hash.clear(); - f.file_modtime = it->second.modtime; - f.file_size = it->second.size; - - mTotalSize -= f.file_size ; - mTotalSize += it->second.size ; - } - new_files.erase(f.file_name) ; - - ++i; - } - - for(std::map::const_iterator it(new_files.begin());it!=new_files.end();++it) - { -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << "[directory storage] adding new file " << it->first << " at index " << mNodes.size() << std::endl; -#endif - - d.subfiles.push_back(mNodes.size()) ; - mNodes.push_back(new FileEntry(it->first,it->second.size,it->second.modtime)); - mNodes.back()->row = mNodes.size()-1; - mNodes.back()->parent_index = indx; - - mTotalSize += it->second.size; - mTotalFiles += 1; - } - return true; -} -bool InternalFileHierarchyStorage::updateHash( - const DirectoryStorage::EntryIndex& file_index, const RsFileHash& hash ) -{ - if(!checkIndex(file_index, FileStorageNode::TYPE_FILE)) - { - RS_ERR( "Cannot update file at index ", file_index, - ". Not a valid index, or not a file." ); - print_stacktrace(); - return false; - } -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << "[directory storage] updating hash at index " << file_index << ", hash=" << hash << std::endl; -#endif - - RsFileHash& old_hash (static_cast(mNodes[file_index])->file_hash) ; - mFileHashes[hash] = file_index ; - - old_hash = hash ; - - return true; -} -bool InternalFileHierarchyStorage::updateFile(const DirectoryStorage::EntryIndex& file_index,const RsFileHash& hash, const std::string& fname,uint64_t size, const rstime_t modf_time) -{ - if(!checkIndex(file_index,FileStorageNode::TYPE_FILE)) - { - std::cerr << "[directory storage] (EE) cannot update file at index " << file_index << ". Not a valid index, or not a file." << std::endl; - return false; - } - - FileEntry& fe(*static_cast(mNodes[file_index])) ; - -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << "[directory storage] updating file entry at index " << file_index << ", name=" << fe.file_name << " size=" << fe.file_size << ", hash=" << fe.file_hash << std::endl; -#endif - if(mTotalSize >= fe.file_size) - mTotalSize -= fe.file_size; - - mTotalSize += size ; - - fe.file_hash = hash; - fe.file_size = size; - fe.file_modtime = modf_time; - fe.file_name = fname; - - if(!hash.isNull()) - mFileHashes[hash] = file_index ; - - return true; -} - -void InternalFileHierarchyStorage::deleteFileNode(uint32_t index) -{ - if(mNodes[index] != NULL) - { - FileEntry& fe(*static_cast(mNodes[index])) ; - -#ifdef RS_DEEP_FILES_INDEX - DeepFilesIndex tfi(DeepFilesIndex::dbDefaultPath()); - tfi.removeFileFromIndex(fe.file_hash); -#endif - - if(mTotalSize >= fe.file_size) - mTotalSize -= fe.file_size ; - - if(mTotalFiles > 0) - mTotalFiles -= 1; - - delete mNodes[index] ; - mFreeNodes.push_back(index) ; - mNodes[index] = NULL ; - } -} -void InternalFileHierarchyStorage::deleteNode(uint32_t index) -{ - if(mNodes[index] != NULL) - { - delete mNodes[index] ; - mFreeNodes.push_back(index) ; - mNodes[index] = NULL ; - } -} - -DirectoryStorage::EntryIndex InternalFileHierarchyStorage::allocateNewIndex() -{ - while(!mFreeNodes.empty()) - { - uint32_t index = mFreeNodes.front(); - mFreeNodes.pop_front(); - - if(mNodes[index] == NULL) - return DirectoryStorage::EntryIndex(index) ; - } - - mNodes.push_back(NULL) ; - return mNodes.size()-1 ; -} - -bool InternalFileHierarchyStorage::updateDirEntry( - const DirectoryStorage::EntryIndex& indx, const std::string& dir_name, - rstime_t most_recent_time, rstime_t dir_modtime, - const std::vector& subdirs_hash, - const std::vector& subfiles_array ) -{ - if(!checkIndex(indx,FileStorageNode::TYPE_DIR)) - { - RS_ERR( "cannot update dir at index ", indx, ". Not a valid index, or " - "not an existing dir." ); - return false; - } - - DirEntry& d(*static_cast(mNodes[indx])); - -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << "Updating dir entry: name=\"" << dir_name << "\", most_recent_time=" << most_recent_time << ", modtime=" << dir_modtime << std::endl; -#endif - - d.dir_most_recent_time = most_recent_time; - d.dir_modtime = dir_modtime; - d.dir_update_time = time(NULL); - d.dir_name = dir_name; - - std::map existing_subdirs ; - - for(uint32_t i=0;i(mNodes[d.subdirs[i]])->dir_hash] = d.subdirs[i] ; - - d.subdirs.clear(); - - // check that all subdirs already exist. If not, create. - for(uint32_t i=0;i::iterator it = existing_subdirs.find(subdirs_hash[i]) ; - DirectoryStorage::EntryIndex dir_index = 0; - - if(it != existing_subdirs.end() && mNodes[it->second] != NULL && mNodes[it->second]->type() == FileStorageNode::TYPE_DIR) - { - dir_index = it->second ; - -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << " already exists, at index " << dir_index << std::endl; -#endif - - existing_subdirs.erase(it) ; - } - else - { - dir_index = allocateNewIndex() ; - - DirEntry *de = new DirEntry("") ; - - mNodes[dir_index] = de ; - - de->dir_parent_path = RsDirUtil::makePath(d.dir_parent_path, dir_name) ; - de->dir_hash = subdirs_hash[i]; - - mDirHashes[subdirs_hash[i]] = dir_index ; - -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << " created, at new index " << dir_index << std::endl; -#endif - } - - d.subdirs.push_back(dir_index) ; - mDirHashes[subdirs_hash[i]] = dir_index ; - } - // remove subdirs that do not exist anymore - - for(std::map::const_iterator it = existing_subdirs.begin();it!=existing_subdirs.end();++it) - { -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << " removing existing subfile that is not in the dirctory anymore: name=" << it->first << " index=" << it->second << std::endl; -#endif - - if(!checkIndex(it->second,FileStorageNode::TYPE_DIR)) - { - std::cerr << "(EE) Cannot delete node of index " << it->second << " because it is not a file. Inconsistency error!" << std::endl; - continue ; - } - recursRemoveDirectory(it->second) ; - } - - // now update subfiles. This is more stricky because we need to not suppress hash duplicates - - std::map existing_subfiles ; - - for(uint32_t i=0;i(mNodes[d.subfiles[i]])->file_name] = d.subfiles[i] ; - - d.subfiles.clear(); - - for(uint32_t i=0;i::iterator it = existing_subfiles.find(subfiles_array[i].file_name) ; - const FileEntry& f(subfiles_array[i]) ; - DirectoryStorage::EntryIndex file_index ; - -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << " subfile name = " << subfiles_array[i].file_name << ": " ; -#endif - - if(it != existing_subfiles.end() && mNodes[it->second] != NULL && mNodes[it->second]->type() == FileStorageNode::TYPE_FILE) - { - file_index = it->second ; - -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << " already exists, at index " << file_index << std::endl; -#endif - - if(!updateFile(file_index,f.file_hash,f.file_name,f.file_size,f.file_modtime)) - std::cerr << "(EE) Cannot update file with index " << it->second <<" and hash " << f.file_hash << ". This is very weird. Entry should have just been created and therefore should exist. Skipping." << std::endl; - - existing_subfiles.erase(it) ; - } - else - { - file_index = allocateNewIndex() ; - - mNodes[file_index] = new FileEntry(f.file_name,f.file_size,f.file_modtime,f.file_hash) ; - mFileHashes[f.file_hash] = file_index ; - mTotalSize += f.file_size ; - mTotalFiles++; - -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << " created, at new index " << file_index << std::endl; -#endif - } - - d.subfiles.push_back(file_index) ; - } - // remove subfiles that do not exist anymore - - for(std::map::const_iterator it = existing_subfiles.begin();it!=existing_subfiles.end();++it) - { -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << " removing existing subfile that is not in the dirctory anymore: name=" << it->first << " index=" << it->second << std::endl; -#endif - - if(!checkIndex(it->second,FileStorageNode::TYPE_FILE)) - { - std::cerr << "(EE) Cannot delete node of index " << it->second << " because it is not a file. Inconsistency error!" << std::endl; - continue ; - } - deleteFileNode(it->second) ; - } - - // now update row and parent index for all subnodes - - uint32_t n=0; - for(uint32_t i=0;i(mNodes[d.subdirs[i]])->dir_update_time = 0 ; // force the update of the subdir. - - mNodes[d.subdirs[i]]->parent_index = indx ; - mNodes[d.subdirs[i]]->row = n++ ; - } - for(uint32_t i=0;iparent_index = indx ; - mNodes[d.subfiles[i]]->row = n++ ; - } - - - return true; -} - -void InternalFileHierarchyStorage::getStatistics(SharedDirStats& stats) const -{ - stats.total_number_of_files = mTotalFiles ; - stats.total_shared_size = mTotalSize ; -} - -bool InternalFileHierarchyStorage::getTS(const DirectoryStorage::EntryIndex& index,rstime_t& TS,rstime_t DirEntry::* m) const -{ - if(!checkIndex(index,FileStorageNode::TYPE_DIR)) - { - std::cerr << "[directory storage] (EE) cannot get TS for index " << index << ". Not a valid index or not a directory." << std::endl; - return false; - } - - DirEntry& d(*static_cast(mNodes[index])) ; - - TS = d.*m ; - - return true; -} - -bool InternalFileHierarchyStorage::setTS(const DirectoryStorage::EntryIndex& index,rstime_t& TS,rstime_t DirEntry::* m) -{ - if(!checkIndex(index,FileStorageNode::TYPE_DIR)) - { - std::cerr << "[directory storage] (EE) cannot get TS for index " << index << ". Not a valid index or not a directory." << std::endl; - return false; - } - - DirEntry& d(*static_cast(mNodes[index])) ; - - d.*m = TS; - - return true; -} - -// Do a complete recursive sweep of directory hierarchy and update cumulative size of directories - -uint64_t InternalFileHierarchyStorage::recursUpdateCumulatedSize(const DirectoryStorage::EntryIndex& dir_index) -{ - DirEntry& d(*static_cast(mNodes[dir_index])) ; - - uint64_t local_cumulative_size = 0; - - for(uint32_t i=0;i(mNodes[d.subfiles[i]])->file_size; - - for(uint32_t i=0;i(mNodes[dir_index])) ; - - rstime_t largest_modf_time = d.dir_modtime ; - unfinished_files_present = false ; - - for(uint32_t i=0;i(mNodes[d.subfiles[i]]) ; - - if(!f->file_hash.isNull()) - largest_modf_time = std::max(largest_modf_time, f->file_modtime) ; // only account for hashed files, since we never send unhashed files to friends. - else - unfinished_files_present = true ; - } - - for(uint32_t i=0;i 0) - largest_modf_time-- ; - - d.dir_most_recent_time = largest_modf_time ; - - return largest_modf_time ; -} - -// Low level stuff. Should normally not be used externally. - -const InternalFileHierarchyStorage::FileStorageNode *InternalFileHierarchyStorage::getNode(DirectoryStorage::EntryIndex indx) const -{ - if(checkIndex(indx,FileStorageNode::TYPE_FILE | FileStorageNode::TYPE_DIR)) - return mNodes[indx] ; - else - return NULL ; -} - -const InternalFileHierarchyStorage::DirEntry* -InternalFileHierarchyStorage::getDirEntry(DirectoryStorage::EntryIndex indx) const -{ - if(!checkIndex(indx,FileStorageNode::TYPE_DIR)) return nullptr; - return static_cast(mNodes[indx]); -} -const InternalFileHierarchyStorage::FileEntry* -InternalFileHierarchyStorage::getFileEntry(DirectoryStorage::EntryIndex indx) const -{ - if(!checkIndex(indx,FileStorageNode::TYPE_FILE)) - return NULL ; - - return static_cast(mNodes[indx]) ; -} -uint32_t InternalFileHierarchyStorage::getType(DirectoryStorage::EntryIndex indx) const -{ - if(checkIndex(indx,FileStorageNode::TYPE_FILE | FileStorageNode::TYPE_DIR)) - return mNodes[indx]->type() ; - else - return FileStorageNode::TYPE_UNKNOWN; -} - -DirectoryStorage::EntryIndex InternalFileHierarchyStorage::getSubFileIndex(DirectoryStorage::EntryIndex parent_index,uint32_t file_tab_index) -{ - if(!checkIndex(parent_index,FileStorageNode::TYPE_DIR)) - return DirectoryStorage::NO_INDEX; - - if(static_cast(mNodes[parent_index])->subfiles.size() <= file_tab_index) - return DirectoryStorage::NO_INDEX; - - return static_cast(mNodes[parent_index])->subfiles[file_tab_index]; -} -DirectoryStorage::EntryIndex InternalFileHierarchyStorage::getSubDirIndex(DirectoryStorage::EntryIndex parent_index,uint32_t dir_tab_index) -{ - if(!checkIndex(parent_index,FileStorageNode::TYPE_DIR)) - return DirectoryStorage::NO_INDEX; - - if(static_cast(mNodes[parent_index])->subdirs.size() <= dir_tab_index) - return DirectoryStorage::NO_INDEX; - - return static_cast(mNodes[parent_index])->subdirs[dir_tab_index]; -} - -bool InternalFileHierarchyStorage::searchHash(const RsFileHash& hash,DirectoryStorage::EntryIndex& result) -{ - return getIndexFromFileHash(hash,result); -} - -class DirectoryStorageExprFileEntry: public RsRegularExpression::ExpFileEntry -{ -public: - DirectoryStorageExprFileEntry( - const InternalFileHierarchyStorage::FileEntry& fe, - const InternalFileHierarchyStorage::DirEntry& parent ) : - mFe(fe), mDe(parent) {} - - inline virtual const std::string& file_name() const { return mFe.file_name ; } - inline virtual uint64_t file_size() const { return mFe.file_size ; } - inline virtual const RsFileHash& file_hash() const { return mFe.file_hash ; } - inline virtual rstime_t file_modtime() const { return mFe.file_modtime ; } - inline virtual std::string file_parent_path()const { return RsDirUtil::makePath(mDe.dir_parent_path, mDe.dir_name) ; } - inline virtual uint32_t file_popularity() const { NOT_IMPLEMENTED() ; return 0; } - -private: - const InternalFileHierarchyStorage::FileEntry& mFe ; - const InternalFileHierarchyStorage::DirEntry& mDe ; -}; - -int InternalFileHierarchyStorage::searchBoolExp( - RsRegularExpression::Expression* exp, - std::list& results ) const -{ - for(auto& it: std::as_const(mFileHashes)) - if(mNodes[it.second]) - if(exp->eval( - DirectoryStorageExprFileEntry( - *static_cast(mNodes[it.second]), - *static_cast(mNodes[mNodes[it.second]->parent_index]) - ) )) - results.push_back(it.second); - - return 0; -} - -int InternalFileHierarchyStorage::searchTerms( - const std::list& terms, - std::list& results ) const -{ - /* most entries are likely to be files, so we could do a linear search over - * the entries tab. Instead we go through the table of hashes.*/ - - for(auto& it : std::as_const(mFileHashes)) - { - // node may be null for some hash waiting to be deleted - if(mNodes[it.second]) - { - rs_view_ptr tFileEntry = - static_cast(mNodes[it.second]); - - /* Most file will just have file name stored, but single file shared - * without a shared dir will contain full path instead of just the - * name, so purify it to perform the search */ - std::string tFilename = tFileEntry->file_name; - if(tFileEntry->file_name.find("/") != std::string::npos) - { - std::string _tParentDir; - RsDirUtil::splitDirFromFile( - tFileEntry->file_name, _tParentDir, tFilename ); - } - - for(auto& termIt : std::as_const(terms)) - { - /* always ignore case */ - if(tFilename.end() != std::search( - tFilename.begin(), tFilename.end(), - termIt.begin(), termIt.end(), - RsRegularExpression::CompareCharIC() )) - { - results.push_back(it.second); - break; - } - } - } - } - return 0; -} - -bool InternalFileHierarchyStorage::check(std::string& error_string) // checks consistency of storage. -{ - // recurs go through all entries, check that all - - error_string = ""; - bool bDirOut = false; - bool bDirDouble = false; - bool bFileOut = false; - bool bFileDouble = false; - bool bOrphean = false; - - std::vector hits(mNodes.size(),0) ; // count hits of children. Should be 1 for all in the end. Otherwise there's an error. - hits[0] = 1 ; // because 0 is never the child of anyone - - mFreeNodes.clear(); - - for(uint32_t i=0;itype() == FileStorageNode::TYPE_DIR) - { - // stamp the kids - DirEntry& de = *static_cast(mNodes[i]) ; - - for(uint32_t j=0;j= mNodes.size()) - { - if(!bDirOut){ error_string += " - Node child dir out of tab!"; bDirOut = true;} - de.subdirs[j] = de.subdirs.back() ; - de.subdirs.pop_back(); - } - else if(hits[de.subdirs[j]] != 0) - { - if(!bDirDouble){ error_string += " - Double hit on a single node dir."; bDirDouble = true;} - de.subdirs[j] = de.subdirs.back() ; - de.subdirs.pop_back(); - } - else - { - hits[de.subdirs[j]] = 1; - ++j ; - } - } - for(uint32_t j=0;j= mNodes.size()) - { - if(!bFileOut){ error_string += " - Node child file out of tab!"; bFileOut = true;} - de.subfiles[j] = de.subfiles.back() ; - de.subfiles.pop_back(); - } - else if(hits[de.subfiles[j]] != 0) - { - if(!bFileDouble){ error_string += " - Double hit on a single node file."; bFileDouble = true;} - de.subfiles[j] = de.subfiles.back() ; - de.subfiles.pop_back(); - } - else - { - hits[de.subfiles[j]] = 1; - ++j ; - } - } - } - else if( mNodes[i] == NULL ) - mFreeNodes.push_back(i) ; - - for(uint32_t i=0;itype() == FileStorageNode::TYPE_DIR) - { - std::cerr << " Node " << i << ": type=" << mNodes[i]->type() << std::endl; - ++ndirs; - } - else if(mNodes[i]->type() == FileStorageNode::TYPE_FILE) - { - std::cerr << " Node " << i << ": type=" << mNodes[i]->type() << std::endl; - ++nfiles; - } - else - { - ++nunknown; - std::cerr << "(EE) Error: unknown type node found!" << std::endl; - } - - std::cerr << "Total nodes: " << mNodes.size() << " (" << nfiles << " files, " << ndirs << " dirs, " << nempty << " empty slots"; - if (nunknown > 0) std::cerr << ", " << nunknown << " unknown"; - std::cerr << ")" << std::endl; - - - recursPrint(0,DirectoryStorage::EntryIndex(0)); - - std::cerr << "Known dir hashes: " << std::endl; - for(std::map::const_iterator it(mDirHashes.begin());it!=mDirHashes.end();++it) - std::cerr << " " << it->first << " at index " << it->second << std::endl; - - std::cerr << "Known file hashes: " << std::endl; - for(std::map::const_iterator it(mFileHashes.begin());it!=mFileHashes.end();++it) - std::cerr << " " << it->first << " at index " << it->second << std::endl; -} -void InternalFileHierarchyStorage::recursPrint(int depth,DirectoryStorage::EntryIndex node) const -{ - std::string indent(2*depth,' '); - - if(mNodes[node] == NULL) - { - std::cerr << "EMPTY NODE !!" << std::endl; - return ; - } - DirEntry& d(*static_cast(mNodes[node])); - - std::cerr << indent << "dir hash=" << d.dir_hash << ". name:" << d.dir_name << ", parent_path:" << d.dir_parent_path << ", modf time: " << d.dir_modtime << ", recurs_last_modf_time: " << d.dir_most_recent_time << ", parent: " << d.parent_index << ", row: " << d.row << ", subdirs: " ; - - for(uint32_t i=0;i(mNodes[d.subfiles[i]])); - std::cerr << indent << " hash:" << f.file_hash << " ts:" << (uint64_t)f.file_modtime << " " << f.file_size << " " << f.file_name << ", parent: " << f.parent_index << ", row: " << f.row << std::endl; - } -} - -bool InternalFileHierarchyStorage::nodeAccessError(const std::string& s) -{ - RS_ERR(s); - print_stacktrace(); - return false; -} - -// Removes the given subdirectory from the parent node and all its pendign subdirs and files. - -bool InternalFileHierarchyStorage::recursRemoveDirectory(DirectoryStorage::EntryIndex dir) -{ - DirEntry& d(*static_cast(mNodes[dir])) ; - - RsFileHash hash = d.dir_hash ; - - for(uint32_t i=0;itype() == FileStorageNode::TYPE_FILE) - { - const FileEntry& fe(*static_cast(mNodes[i])) ; - - uint32_t file_section_offset = 0 ; - - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,file_section_offset,FILE_LIST_IO_TAG_PARENT_INDEX ,(uint32_t)fe.parent_index)) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,file_section_offset,FILE_LIST_IO_TAG_ROW ,(uint32_t)fe.row )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,file_section_offset,FILE_LIST_IO_TAG_ENTRY_INDEX ,(uint32_t)i )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,file_section_offset,FILE_LIST_IO_TAG_FILE_NAME ,fe.file_name )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,file_section_offset,FILE_LIST_IO_TAG_FILE_SIZE ,fe.file_size )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,file_section_offset,FILE_LIST_IO_TAG_FILE_SHA1_HASH,fe.file_hash )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,file_section_offset,FILE_LIST_IO_TAG_MODIF_TS ,(uint32_t)fe.file_modtime)) throw std::runtime_error("Write error") ; - - if(!FileListIO::writeField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_FILE_ENTRY,tmp_section_data,file_section_offset)) throw std::runtime_error("Write error") ; - } - else if(mNodes[i] != NULL && mNodes[i]->type() == FileStorageNode::TYPE_DIR) - { - const DirEntry& de(*static_cast(mNodes[i])) ; - - uint32_t dir_section_offset = 0 ; - - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_PARENT_INDEX ,(uint32_t)de.parent_index )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_ROW ,(uint32_t)de.row )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_ENTRY_INDEX ,(uint32_t)i )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_FILE_NAME ,de.dir_name )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_DIR_HASH ,de.dir_hash )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_FILE_SIZE ,de.dir_parent_path )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_MODIF_TS ,(uint32_t)de.dir_modtime )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_UPDATE_TS ,(uint32_t)de.dir_update_time )) throw std::runtime_error("Write error") ; - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_RECURS_MODIF_TS,(uint32_t)de.dir_most_recent_time )) throw std::runtime_error("Write error") ; - - if(!FileListIO::writeField(tmp_section_data,tmp_section_size,dir_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,(uint32_t)de.subdirs.size())) throw std::runtime_error("Write error") ; - - for(uint32_t j=0;j= mNodes.size()) - mNodes.resize(node_index+1,NULL) ; - - FileEntry *fe = new FileEntry(file_name,file_size,file_modtime,file_hash); - - fe->parent_index = parent_index ; - fe->row = row ; - - mNodes[node_index] = fe ; - mFileHashes[fe->file_hash] = node_index ; - - mTotalFiles++ ; - mTotalSize += file_size ; - } - else if(FileListIO::readField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_DIR_ENTRY,node_section_data,node_section_size)) - { - uint32_t node_index ; - std::string dir_name ; - std::string dir_parent_path ; - RsFileHash dir_hash ; - uint32_t dir_modtime ; - uint32_t dir_update_time ; - uint32_t dir_most_recent_time ; - uint32_t row ; - uint32_t parent_index ; - - if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_PARENT_INDEX ,parent_index )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_PARENT_INDEX ) ; - if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_ROW ,row )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_ROW ) ; - if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_ENTRY_INDEX ,node_index )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_ENTRY_INDEX ) ; - if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_FILE_NAME ,dir_name )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_FILE_NAME ) ; - if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_DIR_HASH ,dir_hash )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_DIR_HASH ) ; - if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_FILE_SIZE ,dir_parent_path )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_FILE_SIZE ) ; - if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_MODIF_TS ,dir_modtime )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_MODIF_TS ) ; - if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_UPDATE_TS ,dir_update_time )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_UPDATE_TS ) ; - if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RECURS_MODIF_TS,dir_most_recent_time )) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RECURS_MODIF_TS) ; - - if(node_index >= mNodes.size()) - mNodes.resize(node_index+1,NULL) ; - - DirEntry *de = new DirEntry(dir_name) ; - de->dir_name = dir_name ; - de->dir_parent_path = dir_parent_path ; - de->dir_hash = dir_hash ; - de->dir_modtime = dir_modtime ; - de->dir_update_time = dir_update_time ; - de->dir_most_recent_time = dir_most_recent_time ; - - de->parent_index = parent_index ; - de->row = row ; - - uint32_t n_subdirs = 0 ; - uint32_t n_subfiles = 0 ; - - if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,n_subdirs)) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER) ; - - for(uint32_t j=0;jsubdirs.push_back(di) ; - } - - if(!FileListIO::readField(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,n_subfiles)) throw read_error(node_section_data,node_section_size,node_section_offset,FILE_LIST_IO_TAG_RAW_NUMBER) ; - - for(uint32_t j=0;jsubfiles.push_back(fi) ; - } - mNodes[node_index] = de ; - mDirHashes[de->dir_hash] = node_index ; - } - else - throw read_error(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_FILE_ENTRY) ; - - free(node_section_data) ; - } - free(buffer) ; - - std::string err_str ; - - if(!check(err_str)) - std::cerr << "(EE) Error while loading file hierarchy " << fname << std::endl; - - recursUpdateCumulatedSize(mRoot); - - return true ; - } - catch(read_error& e) - { -#ifdef DEBUG_DIRECTORY_STORAGE - std::cerr << "Error while reading: " << e.what() << std::endl; -#endif - - if(buffer != NULL) - free(buffer) ; - return false; - } -} - diff --git a/libretroshare/src/file_sharing/dir_hierarchy.h b/libretroshare/src/file_sharing/dir_hierarchy.h deleted file mode 100644 index c6a28650b..000000000 --- a/libretroshare/src/file_sharing/dir_hierarchy.h +++ /dev/null @@ -1,199 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: dir_hierarchy.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2016 by Mr.Alice * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ -#pragma once - -#include -#include -#include - -#include "directory_storage.h" - -class InternalFileHierarchyStorage -{ -public: - class FileStorageNode - { - public: - static const uint32_t TYPE_UNKNOWN = 0x0000 ; - static const uint32_t TYPE_FILE = 0x0001 ; - static const uint32_t TYPE_DIR = 0x0002 ; - - virtual ~FileStorageNode() {} - virtual uint32_t type() const =0; - - DirectoryStorage::EntryIndex parent_index; - uint32_t row ; - }; - class FileEntry: public FileStorageNode - { - public: - FileEntry() : file_size(0), file_modtime(0) {} - FileEntry(const std::string& name,uint64_t size,rstime_t modtime) : file_name(name),file_size(size),file_modtime(modtime) {} - FileEntry(const std::string& name,uint64_t size,rstime_t modtime,const RsFileHash& hash) : file_name(name),file_size(size),file_modtime(modtime),file_hash(hash) {} - - virtual uint32_t type() const { return FileStorageNode::TYPE_FILE ; } - virtual ~FileEntry() {} - - // local stuff - std::string file_name ; - uint64_t file_size ; - rstime_t file_modtime; - RsFileHash file_hash ; - }; - - class DirEntry: public FileStorageNode - { - public: - explicit DirEntry(const std::string& name) : dir_name(name), dir_cumulated_size(0), dir_modtime(0),dir_most_recent_time(0),dir_update_time(0) {} - virtual ~DirEntry() {} - - virtual uint32_t type() const { return FileStorageNode::TYPE_DIR ; } - - // local stuff - std::string dir_name ; - std::string dir_parent_path ; - RsFileHash dir_hash ; - uint64_t dir_cumulated_size; - - std::vector subdirs ; - std::vector subfiles ; - - rstime_t dir_modtime; - rstime_t dir_most_recent_time;// recursive most recent modification time, including files and subdirs in the entire hierarchy below. - rstime_t dir_update_time; // last time the information was updated for that directory. Includes subdirs indexes and subfile info. - }; - - // class stuff - InternalFileHierarchyStorage() ; - - bool load(const std::string& fname) ; - bool save(const std::string& fname) ; - - int parentRow(DirectoryStorage::EntryIndex e); - bool isIndexValid(DirectoryStorage::EntryIndex e) const; - bool getChildIndex(DirectoryStorage::EntryIndex e,int row,DirectoryStorage::EntryIndex& c) const; - bool updateSubDirectoryList(const DirectoryStorage::EntryIndex& indx, const std::set& subdirs, const RsFileHash &random_hash_seed); - bool removeDirectory(DirectoryStorage::EntryIndex indx) ; - bool checkIndex(DirectoryStorage::EntryIndex indx,uint8_t type) const; - bool updateSubFilesList(const DirectoryStorage::EntryIndex& indx,const std::map& subfiles,std::map& new_files); - bool updateHash(const DirectoryStorage::EntryIndex& file_index,const RsFileHash& hash); - bool updateFile(const DirectoryStorage::EntryIndex& file_index,const RsFileHash& hash, const std::string& fname,uint64_t size, const rstime_t modf_time); - bool updateDirEntry(const DirectoryStorage::EntryIndex& indx, const std::string& dir_name, rstime_t most_recent_time, rstime_t dir_modtime, const std::vector &subdirs_hash, const std::vector &subfiles_array); - - // TS get/set functions. Take one of the class members as argument. - - bool getTS(const DirectoryStorage::EntryIndex& index,rstime_t& TS,rstime_t DirEntry::* ) const; - bool setTS(const DirectoryStorage::EntryIndex& index,rstime_t& TS,rstime_t DirEntry::* ) ; - - // Do a complete recursive sweep over sub-directories and files, and update the lst modf TS. This could be also performed by a cleanup method. - // Also keeps the high level statistics up to date. - - rstime_t recursUpdateLastModfTime(const DirectoryStorage::EntryIndex& dir_index, bool &unfinished_files_present); - - // Do a complete recursive sweep over sub-directories and files, and update the cumulative size. - - uint64_t recursUpdateCumulatedSize(const DirectoryStorage::EntryIndex& dir_index); - - // hash stuff - - bool getDirHashFromIndex(const DirectoryStorage::EntryIndex& index,RsFileHash& hash) const ; - bool getIndexFromDirHash(const RsFileHash& hash,DirectoryStorage::EntryIndex& index) ; - bool getIndexFromFileHash(const RsFileHash& hash,DirectoryStorage::EntryIndex& index) ; - - // file/dir access and modification - bool findSubDirectory(DirectoryStorage::EntryIndex e,const std::string& s) const ; // returns true when s is the name of a sub-directory in the given entry e - - uint32_t mRoot ; - std::list mFreeNodes ; // keeps a list of free nodes in order to make insert effcieint - std::vector mNodes;// uses pointers to keep information about valid/invalid objects. - - void compress() ; // use empty space in the vector, mostly due to deleted entries. This is a complicated operation, mostly due to - // all the indirections used. Nodes need to be moved, renamed, etc. The operation discards all file entries that - // are not referenced. - - friend class DirectoryStorage ; // only class that can use this. - friend class LocalDirectoryStorage ; // only class that can use this. - - // Low level stuff. Should normally not be used externally. - - const FileStorageNode *getNode(DirectoryStorage::EntryIndex indx) const; - const DirEntry *getDirEntry(DirectoryStorage::EntryIndex indx) const; - const FileEntry *getFileEntry(DirectoryStorage::EntryIndex indx) const; - uint32_t getType(DirectoryStorage::EntryIndex indx) const; - DirectoryStorage::EntryIndex getSubFileIndex(DirectoryStorage::EntryIndex parent_index,uint32_t file_tab_index); - DirectoryStorage::EntryIndex getSubDirIndex(DirectoryStorage::EntryIndex parent_index,uint32_t dir_tab_index); - - // search. SearchHash is logarithmic. The other two are linear. - - bool searchHash(const RsFileHash& hash, DirectoryStorage::EntryIndex &result); - int searchBoolExp(RsRegularExpression::Expression * exp, std::list &results) const ; - int searchTerms(const std::list& terms, std::list &results) const ; // does a logical OR between items of the list of terms - - bool check(std::string& error_string) ;// checks consistency of storage. - - void print() const; - - // gets statistics about share files - - void getStatistics(SharedDirStats& stats) const ; - -private: - void recursPrint(int depth,DirectoryStorage::EntryIndex node) const; - static bool nodeAccessError(const std::string& s); - static RsFileHash createDirHash(const std::string& dir_name, const RsFileHash &dir_parent_hash, const RsFileHash &random_hash_salt) ; - - // Allocates a new entry in mNodes, possible re-using an empty slot and returns its index. - - DirectoryStorage::EntryIndex allocateNewIndex(); - - // Deletes an existing entry in mNodes, and keeps record of the indices that get freed. - - void deleteNode(DirectoryStorage::EntryIndex); - void deleteFileNode(DirectoryStorage::EntryIndex); - - // Removes the given subdirectory from the parent node and all its pendign subdirs. Files are kept, and will go during the cleaning - // phase. That allows to keep file information when moving them around. - - bool recursRemoveDirectory(DirectoryStorage::EntryIndex dir); - - // Map of the hash of all files. The file hashes are the sha1sum of the file data. - // is used for fast search access for FT. - // Note: We should try something faster than std::map. hash_map?? - // Unlike directories, multiple files may have the same hash. So this cannot be used for anything else than FT. - - std::map mFileHashes ; - - // The directory hashes are the sha1sum of the - // full public path to the directory. - // The later is used by synchronisation items in order - // to avoid sending explicit EntryIndex values. - // This is kept separate from mFileHashes because the two are used - // in very different ways. - // - std::map mDirHashes ; - - // high level statistics on the full hierarchy. Should be kept up to date. - - uint32_t mTotalFiles ; - uint64_t mTotalSize ; -}; - diff --git a/libretroshare/src/file_sharing/directory_list.h b/libretroshare/src/file_sharing/directory_list.h deleted file mode 100644 index c643b6153..000000000 --- a/libretroshare/src/file_sharing/directory_list.h +++ /dev/null @@ -1,13 +0,0 @@ -// This class keeps a shared directory. It's quite the equivalent of the old "FileIndex" class -// The main difference is that it is -// - extensible -// - fast to search (at least for hashes). Should provide possibly multiple search handles for -// the same file, e.g. if connexion is encrypted. -// - abstracts the browsing in a same manner. -// -class SharedDirectoryList -{ - public: - - DirEntry mRoot ; -}; diff --git a/libretroshare/src/file_sharing/directory_storage.cc b/libretroshare/src/file_sharing/directory_storage.cc deleted file mode 100644 index 583ac5882..000000000 --- a/libretroshare/src/file_sharing/directory_storage.cc +++ /dev/null @@ -1,1082 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: directory_storage.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016 Mr.Alice * - * Copyright (C) 2018-2021 Gioacchino Mazzurco * - * Copyright (C) 2019-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ -#include - -#include "util/rstime.h" -#include "serialiser/rstlvbinary.h" -#include "retroshare/rspeers.h" -#include "util/rsdir.h" -#include "util/rsstring.h" -#include "file_sharing_defaults.h" -#include "directory_storage.h" -#include "dir_hierarchy.h" -#include "filelist_io.h" -#include "util/cxx17retrocompat.h" - -#ifdef RS_DEEP_FILES_INDEX -# include "deep_search/filesindex.hpp" -#endif // def RS_DEEP_FILES_INDEX - -//#define DEBUG_REMOTE_DIRECTORY_STORAGE 1 - -/******************************************************************************************************************/ -/* Iterators */ -/******************************************************************************************************************/ - -DirectoryStorage::DirIterator::DirIterator(DirectoryStorage *s,DirectoryStorage::EntryIndex i) -{ - mStorage = s->mFileHierarchy ; - mParentIndex = i; - mDirTabIndex = 0; -} - -DirectoryStorage::FileIterator::FileIterator(DirectoryStorage *s,DirectoryStorage::EntryIndex i) -{ - mStorage = s->mFileHierarchy ; - mParentIndex = i; - mFileTabIndex = 0; -} - -DirectoryStorage::DirIterator& DirectoryStorage::DirIterator::operator++() -{ - ++mDirTabIndex ; - - return *this; -} -DirectoryStorage::FileIterator& DirectoryStorage::FileIterator::operator++() -{ - ++mFileTabIndex ; - - return *this; -} -DirectoryStorage::EntryIndex DirectoryStorage::FileIterator::operator*() const -{ return mStorage->getSubFileIndex(mParentIndex, mFileTabIndex); } - -DirectoryStorage::EntryIndex DirectoryStorage::DirIterator::operator*() const -{ return mStorage->getSubDirIndex(mParentIndex, mDirTabIndex); } - -DirectoryStorage::FileIterator::operator bool() const { return **this != DirectoryStorage::NO_INDEX; } -DirectoryStorage::DirIterator ::operator bool() const { return **this != DirectoryStorage::NO_INDEX; } - -RsFileHash DirectoryStorage::FileIterator::hash() const { const InternalFileHierarchyStorage::FileEntry *f = mStorage->getFileEntry(**this) ; return f?(f->file_hash):RsFileHash(); } -uint64_t DirectoryStorage::FileIterator::size() const { const InternalFileHierarchyStorage::FileEntry *f = mStorage->getFileEntry(**this) ; return f?(f->file_size):0; } -std::string DirectoryStorage::FileIterator::name() const { const InternalFileHierarchyStorage::FileEntry *f = mStorage->getFileEntry(**this) ; return f?(f->file_name):std::string(); } -rstime_t DirectoryStorage::FileIterator::modtime() const { const InternalFileHierarchyStorage::FileEntry *f = mStorage->getFileEntry(**this) ; return f?(f->file_modtime):0; } - -std::string DirectoryStorage::DirIterator::name() const { const InternalFileHierarchyStorage::DirEntry *d = mStorage->getDirEntry(**this) ; return d?(d->dir_name):std::string(); } - -/******************************************************************************************************************/ -/* Directory Storage */ -/******************************************************************************************************************/ - -DirectoryStorage::DirectoryStorage(const RsPeerId &pid,const std::string& fname) - : mPeerId(pid), mDirStorageMtx("Directory storage "+pid.toStdString()),mLastSavedTime(0),mChanged(false),mFileName(fname) -{ - { - RS_STACK_MUTEX(mDirStorageMtx) ; - mFileHierarchy = new InternalFileHierarchyStorage(); - } - load(fname) ; -} - -DirectoryStorage::EntryIndex DirectoryStorage::root() const -{ - return EntryIndex(0) ; -} -int DirectoryStorage::parentRow(EntryIndex e) const -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - - return mFileHierarchy->parentRow(e) ; -} -bool DirectoryStorage::getChildIndex(EntryIndex e,int row,EntryIndex& c) const -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - - return mFileHierarchy->getChildIndex(e,row,c) ; -} - -uint32_t DirectoryStorage::getEntryType(const EntryIndex& indx) -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - - switch(mFileHierarchy->getType(indx)) - { - case InternalFileHierarchyStorage::FileStorageNode::TYPE_DIR: return DIR_TYPE_DIR ; - case InternalFileHierarchyStorage::FileStorageNode::TYPE_FILE: return DIR_TYPE_FILE ; - default: - return DIR_TYPE_UNKNOWN; - } -} - -bool DirectoryStorage::getDirectoryUpdateTime (EntryIndex index,rstime_t& update_TS) const { RS_STACK_MUTEX(mDirStorageMtx) ; return mFileHierarchy->getTS(index,update_TS,&InternalFileHierarchyStorage::DirEntry::dir_update_time ); } -bool DirectoryStorage::getDirectoryRecursModTime(EntryIndex index,rstime_t& rec_md_TS) const { RS_STACK_MUTEX(mDirStorageMtx) ; return mFileHierarchy->getTS(index,rec_md_TS,&InternalFileHierarchyStorage::DirEntry::dir_most_recent_time); } -bool DirectoryStorage::getDirectoryLocalModTime (EntryIndex index,rstime_t& loc_md_TS) const { RS_STACK_MUTEX(mDirStorageMtx) ; return mFileHierarchy->getTS(index,loc_md_TS,&InternalFileHierarchyStorage::DirEntry::dir_modtime ); } - -bool DirectoryStorage::setDirectoryUpdateTime (EntryIndex index,rstime_t update_TS) { RS_STACK_MUTEX(mDirStorageMtx) ; return mFileHierarchy->setTS(index,update_TS,&InternalFileHierarchyStorage::DirEntry::dir_update_time ); } -bool DirectoryStorage::setDirectoryRecursModTime(EntryIndex index,rstime_t rec_md_TS) { RS_STACK_MUTEX(mDirStorageMtx) ; return mFileHierarchy->setTS(index,rec_md_TS,&InternalFileHierarchyStorage::DirEntry::dir_most_recent_time); } -bool DirectoryStorage::setDirectoryLocalModTime (EntryIndex index,rstime_t loc_md_TS) { RS_STACK_MUTEX(mDirStorageMtx) ; return mFileHierarchy->setTS(index,loc_md_TS,&InternalFileHierarchyStorage::DirEntry::dir_modtime ); } - -bool DirectoryStorage::updateSubDirectoryList(const EntryIndex& indx, const std::set &subdirs, const RsFileHash& hash_salt) -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - bool res = mFileHierarchy->updateSubDirectoryList(indx,subdirs,hash_salt) ; - mChanged = true ; - return res ; -} -bool DirectoryStorage::updateSubFilesList( - const EntryIndex& indx, const std::map& subfiles, - std::map& new_files ) -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - bool res = mFileHierarchy->updateSubFilesList(indx,subfiles,new_files) ; - mChanged = true ; - return res ; -} -bool DirectoryStorage::removeDirectory(const EntryIndex& indx) -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - bool res = mFileHierarchy->removeDirectory(indx); - mChanged = true ; - - return res ; -} - -void DirectoryStorage::locked_check() -{ - std::string error ; - if(!mFileHierarchy->check(error)) - std::cerr << "Check error: " << error << std::endl; -} - -void DirectoryStorage::getStatistics(SharedDirStats& stats) -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - mFileHierarchy->getStatistics(stats); -} - -bool DirectoryStorage::load(const std::string& local_file_name) -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - mChanged = false ; - return mFileHierarchy->load(local_file_name); -} -void DirectoryStorage::save(const std::string& local_file_name) -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - mFileHierarchy->save(local_file_name); -} -void DirectoryStorage::print() -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - mFileHierarchy->print(); -} - -int DirectoryStorage::searchTerms( - const std::list& terms, - std::list& results ) const -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - return mFileHierarchy->searchTerms(terms,results); -} -int DirectoryStorage::searchBoolExp(RsRegularExpression::Expression * exp, std::list &results) const -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - return mFileHierarchy->searchBoolExp(exp,results); -} - -bool DirectoryStorage::extractData(const EntryIndex& indx,DirDetails& d) -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - - d.children.clear() ; - uint32_t type = mFileHierarchy->getType(indx) ; - - d.ref = (void*)(intptr_t)indx ; - - if (type == InternalFileHierarchyStorage::FileStorageNode::TYPE_DIR) /* has children --- fill */ - { - const InternalFileHierarchyStorage::DirEntry *dir_entry = mFileHierarchy->getDirEntry(indx) ; - - /* extract all the entries */ - - for(DirectoryStorage::DirIterator it(this,indx);it;++it) - { - DirStub stub; - stub.type = DIR_TYPE_DIR; - stub.name = it.name(); - stub.ref = (void*)(intptr_t)*it; // this is updated by the caller, who knows which friend we're dealing with - - d.children.push_back(stub); - } - - for(DirectoryStorage::FileIterator it(this,indx);it;++it) - { - DirStub stub; - stub.type = DIR_TYPE_FILE; - stub.name = it.name(); - stub.ref = (void*)(intptr_t)*it; - - d.children.push_back(stub); - } - - d.type = DIR_TYPE_DIR; - d.hash.clear() ; - d.size = dir_entry->dir_cumulated_size;//dir_entry->subdirs.size() + dir_entry->subfiles.size(); - d.max_mtime = dir_entry->dir_most_recent_time ; - d.mtime = dir_entry->dir_modtime ; - d.name = dir_entry->dir_name; - d.path = RsDirUtil::makePath(dir_entry->dir_parent_path, dir_entry->dir_name) ; - d.parent = (void*)(intptr_t)dir_entry->parent_index ; - - if(indx == 0) - { - d.type = DIR_TYPE_PERSON ; - d.name = mPeerId.toStdString(); - } - } - else if(type == InternalFileHierarchyStorage::FileStorageNode::TYPE_FILE) - { - const InternalFileHierarchyStorage::FileEntry *file_entry = mFileHierarchy->getFileEntry(indx) ; - - d.type = DIR_TYPE_FILE; - d.size = file_entry->file_size; - d.max_mtime = file_entry->file_modtime ; - d.name = file_entry->file_name; - d.hash = file_entry->file_hash; - d.mtime = file_entry->file_modtime; - d.parent = (void*)(intptr_t)file_entry->parent_index ; - - const InternalFileHierarchyStorage::DirEntry *parent_dir_entry = mFileHierarchy->getDirEntry(file_entry->parent_index); - - if(parent_dir_entry != NULL) - d.path = RsDirUtil::makePath(parent_dir_entry->dir_parent_path, parent_dir_entry->dir_name) ; - else - d.path = "" ; - } - else - return false; - - d.flags.clear() ; - - return true; -} - -bool DirectoryStorage::getDirHashFromIndex(const EntryIndex& index,RsFileHash& hash) const -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - return mFileHierarchy->getDirHashFromIndex(index,hash) ; -} -bool DirectoryStorage::getIndexFromDirHash(const RsFileHash& hash,EntryIndex& index) const -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - return mFileHierarchy->getIndexFromDirHash(hash,index) ; -} - -void DirectoryStorage::checkSave() -{ - rstime_t now = time(NULL); - - if(mChanged && mLastSavedTime + MIN_INTERVAL_BETWEEN_REMOTE_DIRECTORY_SAVE < now) - { - mFileHierarchy->recursUpdateCumulatedSize(mFileHierarchy->mRoot); - - { - RS_STACK_MUTEX(mDirStorageMtx) ; - locked_check(); - } - - save(mFileName); - - { - RS_STACK_MUTEX(mDirStorageMtx) ; - mLastSavedTime = now ; - mChanged = false ; - } - } -} -/******************************************************************************************************************/ -/* Local Directory Storage */ -/******************************************************************************************************************/ - -LocalDirectoryStorage::LocalDirectoryStorage(const std::string& fname,const RsPeerId& own_id) - : DirectoryStorage(own_id,fname) -{ - mTSChanged = false ; -} - -RsFileHash LocalDirectoryStorage::makeEncryptedHash(const RsFileHash& hash) -{ - return RsDirUtil::sha1sum(hash.toByteArray(),hash.SIZE_IN_BYTES); -} -bool LocalDirectoryStorage::locked_findRealHash(const RsFileHash& hash, RsFileHash& real_hash) const -{ - std::map::const_iterator it = mEncryptedHashes.find(hash) ; - - if(it == mEncryptedHashes.end()) - return false ; - - real_hash = it->second ; - return true ; -} - -int LocalDirectoryStorage::searchHash(const RsFileHash& hash, RsFileHash& real_hash, EntryIndex& result) const -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - - if(locked_findRealHash(hash,real_hash) && mFileHierarchy->searchHash(real_hash,result)) - return true ; - - if(mFileHierarchy->searchHash(hash,result)) - { - real_hash.clear(); - return true ; - } - return false ; -} - -void LocalDirectoryStorage::setSharedDirectoryList( - const std::list& lst ) -{ - std::set dirs_with_new_virtualname ; - bool dirs_with_changed_flags = false ; - - { - RS_STACK_MUTEX(mDirStorageMtx) ; - - // Chose virtual name if not supplied, and remove duplicates. - - std::set virtual_names ; // maps virtual to real name - std::list processed_list ; - - for(std::list::const_iterator it(lst.begin());it!= lst.end();++it) - { - int i=0; - std::string candidate_virtual_name = it->virtualname ; - - if(candidate_virtual_name.empty()) - candidate_virtual_name = RsDirUtil::getTopDir(it->filename); - - while(virtual_names.find(candidate_virtual_name) != virtual_names.end()) - rs_sprintf_append(candidate_virtual_name, "-%d", ++i); - - SharedDirInfo d(*it); - d.virtualname = candidate_virtual_name ; - processed_list.push_back(d) ; - - virtual_names.insert(candidate_virtual_name) ; - } - - /* now for each member of the processed list, check if it is an existing - * shared directory that has been changed. If so, we need to update the - * dir TS of that directory */ - - std::map new_dirs ; - - for(std::list::const_iterator it(processed_list.begin());it!=processed_list.end();++it) - { - std::map::iterator it2 = mLocalDirs.find(it->filename) ; - - if(it2 != mLocalDirs.end()) - { - if(it2->second.virtualname != it->virtualname) - dirs_with_new_virtualname.insert(it->filename) ; - - if(!SharedDirInfo::sameLists((*it).parent_groups,it2->second.parent_groups) || (*it).shareflags != it2->second.shareflags) - dirs_with_changed_flags = true ; - } - - new_dirs[it->filename] = *it; - } - - mLocalDirs = new_dirs ; - mTSChanged = true ; - } - - // now update the TS off-mutex. - - for(DirIterator dirit(this,root());dirit;++dirit) - if(dirs_with_new_virtualname.find(dirit.name()) != dirs_with_new_virtualname.end()) - { - std::cerr << "Updating TS of local dir \"" << dirit.name() << "\" with changed virtual name" << std::endl; - setDirectoryLocalModTime(*dirit,time(NULL)); - } - - if(dirs_with_changed_flags) - setDirectoryLocalModTime(0,time(NULL)) ; -} - -void LocalDirectoryStorage::getSharedDirectoryList(std::list& lst) -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - - lst.clear(); - - for(std::map::iterator it(mLocalDirs.begin());it!=mLocalDirs.end();++it) - lst.push_back(it->second) ; -} -void LocalDirectoryStorage::updateShareFlags(const SharedDirInfo& info) -{ - bool changed = false ; - - { - RS_STACK_MUTEX(mDirStorageMtx) ; - - std::map::iterator it = mLocalDirs.find(info.filename) ; - - if(it == mLocalDirs.end()) - { - std::cerr << "(EE) LocalDirectoryStorage::updateShareFlags: directory \"" << info.filename << "\" not found" << std::endl; - return ; - } - - // we compare the new info with the old one. If the two group lists have a different order, they will be seen as different. Not a big deal. We just - // want to make sure that if they are different, flags get updated. - - if(!SharedDirInfo::sameLists(it->second.parent_groups,info.parent_groups) || it->second.filename != info.filename || it->second.shareflags != info.shareflags || it->second.virtualname != info.virtualname) - { - it->second = info; - -#ifdef DEBUG_LOCAL_DIRECTORY_STORAGE - std::cerr << "Updating dir mod time because flags at level 0 have changed." << std::endl; -#endif - changed = true ; - } - } - - if(changed) - { - setDirectoryLocalModTime(0,time(NULL)) ; - mTSChanged = true ; - } -} - -bool LocalDirectoryStorage::convertSharedFilePath(const std::string& path, std::string& fullpath) -{ - std::string shpath = RsDirUtil::removeRootDir(path); - std::string basedir = RsDirUtil::getRootDir(path); - std::string realroot ; - { - RS_STACK_MUTEX(mDirStorageMtx) ; - realroot = locked_findRealRootFromVirtualFilename(basedir); - } - - if (realroot.empty()) - return false; - - /* construct full name */ - fullpath = realroot + "/"; - fullpath += shpath; - - return true; -} - -void LocalDirectoryStorage::notifyTSChanged() -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - mTSChanged = true ; -} -void LocalDirectoryStorage::updateTimeStamps() -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - - if(mTSChanged) - { -#ifdef DEBUG_LOCAL_DIRECTORY_STORAGE - std::cerr << "Updating recursive TS for local shared dirs..." << std::endl; -#endif - - bool unfinished_files_below ; - - rstime_t last_modf_time = mFileHierarchy->recursUpdateLastModfTime(EntryIndex(0),unfinished_files_below) ; - mTSChanged = false ; - -#ifdef DEBUG_LOCAL_DIRECTORY_STORAGE - std::cerr << "LocalDirectoryStorage: global last modf time is " << last_modf_time << " (which is " << time(NULL) - last_modf_time << " secs ago), unfinished files below=" << unfinished_files_below << std::endl; -#else - // remove unused variable warning - // variable is only used for debugging - (void)last_modf_time; -#endif - } -} - -bool LocalDirectoryStorage::updateHash( - const EntryIndex& index, const RsFileHash& hash, - bool update_internal_hierarchy ) -{ - bool ret = false; - - { - RS_STACK_MUTEX(mDirStorageMtx); - - mEncryptedHashes[makeEncryptedHash(hash)] = hash ; - mChanged = true ; - -#ifdef DEBUG_LOCAL_DIRECTORY_STORAGE - std::cerr << "Updating index of hash " << hash << " update_internal=" - << update_internal_hierarchy << std::endl; -#endif - - ret = (!update_internal_hierarchy) || - mFileHierarchy->updateHash(index, hash); - } // RS_STACK_MUTEX(mDirStorageMtx); - -#ifdef RS_DEEP_FILES_INDEX - FileInfo fInfo; - if( ret && getFileInfo(index, fInfo) && - fInfo.storage_permission_flags & DIR_FLAGS_ANONYMOUS_SEARCH ) - { - DeepFilesIndex dfi(DeepFilesIndex::dbDefaultPath()); - ret &= !dfi.indexFile(fInfo.path, fInfo.fname, hash); - } -#endif // def RS_DEEP_FILES_INDEX - - return ret; -} -std::string LocalDirectoryStorage::locked_findRealRootFromVirtualFilename(const std::string& virtual_rootdir) const -{ - /**** MUST ALREADY BE LOCKED ****/ - - std::map::const_iterator cit = mLocalDirs.find(virtual_rootdir) ; - - if (cit == mLocalDirs.end()) - { - std::cerr << "(EE) locked_findRealRootFromVirtualFilename() Invalid RootDir: " << virtual_rootdir << std::endl; - return std::string(); - } - return cit->second.filename; -} - -bool LocalDirectoryStorage::extractData(const EntryIndex& indx,DirDetails& d) -{ - bool res = DirectoryStorage::extractData(indx,d) ; - - if(!res) - return false; - - // here we should update the file sharing flags - - return getFileSharingPermissions(indx,d.flags,d.parent_groups) ; -} - -bool LocalDirectoryStorage::getFileInfo(DirectoryStorage::EntryIndex i,FileInfo& info) -{ - DirDetails d; - extractData(i,d) ; - - if(d.type != DIR_TYPE_FILE) - { - std::cerr << "(EE) LocalDirectoryStorage: asked for file info for index " << i << " which is not a file." << std::endl; - return false; - } - - info.storage_permission_flags = d.flags; // Combination of the four RS_DIR_FLAGS_*. Updated when the file is a local stored file. - info.parent_groups = d.parent_groups; - info.transfer_info_flags = TransferRequestFlags(); // various flags from RS_FILE_HINTS_* - info.path = d.path + "/" + d.name; - info.fname = d.name; - info.hash = d.hash; - info.size = d.size; - - // all this stuff below is not useful in this case. - - info.mId = 0; /* (GUI) Model Id -> unique number */ - info.ext.clear(); - info.avail = 0; /* how much we have */ - info.rank = 0; - info.age = 0; - info.queue_position =0; - info.searchId = 0; /* 0 if none */ - - /* Transfer Stuff */ - info.transfered = 0; - info.tfRate = 0; /* in kbytes */ - info.downloadStatus = FT_STATE_COMPLETE ; - //std::list peers; - - info.priority = SPEED_NORMAL; - info.lastTS = 0; - - return true; -} - -bool LocalDirectoryStorage::getFileSharingPermissions(const EntryIndex& indx,FileStorageFlags& flags,std::list& parent_groups) -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - return locked_getFileSharingPermissions(indx,flags,parent_groups) ; -} - -bool LocalDirectoryStorage::locked_getFileSharingPermissions( - const EntryIndex& indx, FileStorageFlags& flags, - std::list& parent_groups ) -{ - flags.clear(); - parent_groups.clear(); - - /* We got a request for root directory no need to do anything more after - * clearing outputs */ - if(!indx) return true; - - using FileStorageNode = InternalFileHierarchyStorage::FileStorageNode; - using EntryIndex = DirectoryStorage::EntryIndex; - - rs_view_ptr n = mFileHierarchy->getNode(indx); - if(!n) - { - RS_ERR("Node for index: ", indx, "not found"); - print_stacktrace(); - return false; - } - - // Climb down node tree up to root + 1 - EntryIndex curIndex = indx; - while (n->parent_index) - { - curIndex = n->parent_index; - n = mFileHierarchy->getNode(curIndex); - } - - // Retrieve base name - std::string tBaseName; - switch (n->type()) - { - // Handle single file shared case - case InternalFileHierarchyStorage::FileStorageNode::TYPE_FILE: - tBaseName = mFileHierarchy->getFileEntry(curIndex)->file_name; - break; - // Handle shared directory case - case InternalFileHierarchyStorage::FileStorageNode::TYPE_DIR: - tBaseName = mFileHierarchy->getDirEntry(curIndex)->dir_name; - break; - default: - RS_ERR("Got unhandled node type: ", n->type()); - print_stacktrace(); - return false; - } - - // Use base name to retrieve sharing permissions - if(!tBaseName.empty()) - { - auto it = std::as_const(mLocalDirs).find(tBaseName); - - if(it == mLocalDirs.end()) - { - RS_ERR( "base name \"", tBaseName, - "\" for index: ", indx, " not found in shared dir list." ); - print_stacktrace(); - return false; - } - - flags = it->second.shareflags; - parent_groups = it->second.parent_groups; - } - else - { - RS_ERR("base name for indx: ", indx, " is empty"); - print_stacktrace(); - return false; - } - - return true; -} - -std::string LocalDirectoryStorage::locked_getVirtualDirName(EntryIndex indx) const -{ - if(indx == 0) - return std::string() ; - - const InternalFileHierarchyStorage::DirEntry *dir = mFileHierarchy->getDirEntry(indx); - - if(dir->parent_index != 0) - return dir->dir_name ; - - std::map::const_iterator it = mLocalDirs.find(dir->dir_name) ; - - if(it == mLocalDirs.end()) - { - std::cerr << "(EE) Cannot find real name " << dir->dir_name << " at level 1 among shared dirs. Bug?" << std::endl; - return std::string() ; - } - - return it->second.virtualname ; -} -std::string LocalDirectoryStorage::locked_getVirtualPath(EntryIndex indx) const -{ - if(indx == 0) - return std::string() ; - - std::string res ; - const InternalFileHierarchyStorage::DirEntry *dir = mFileHierarchy->getDirEntry(indx); - - while(dir->parent_index != 0) - { - dir = mFileHierarchy->getDirEntry(dir->parent_index) ; - res += dir->dir_name + "/"+ res ; - } - - std::map::const_iterator it = mLocalDirs.find(dir->dir_name) ; - - if(it == mLocalDirs.end()) - { - std::cerr << "(EE) Cannot find real name " << dir->dir_name << " at level 1 among shared dirs. Bug?" << std::endl; - return std::string() ; - } - return it->second.virtualname + "/" + res; -} - -bool LocalDirectoryStorage::serialiseDirEntry( - const EntryIndex& indx, RsTlvBinaryData& bindata, - const RsPeerId& client_id ) -{ - RS_STACK_MUTEX(mDirStorageMtx); - - const InternalFileHierarchyStorage::DirEntry* dir = - mFileHierarchy->getDirEntry(indx); - -#ifdef DEBUG_LOCAL_DIRECTORY_STORAGE - std::cerr << "Serialising Dir entry " << std::hex << indx << " for client id " << client_id << std::endl; -#endif - - if(!dir) - { - RS_ERR("Cannot find entry ", indx); - return false; - } - - // compute list of allowed subdirs - std::vector allowed_subdirs; - FileStorageFlags node_flags; - std::list node_groups; - - /* for each subdir, compute the node flags and groups, then ask rsPeers to - * compute the mask that result from these flags for the particular peer - * supplied in parameter */ - - for(uint32_t i=0;isubdirs.size();++i) - if(indx != 0 || ( - locked_getFileSharingPermissions( - dir->subdirs[i], node_flags, node_groups ) && - ( rsPeers->computePeerPermissionFlags( - client_id, node_flags, node_groups ) & - RS_FILE_HINTS_BROWSABLE ) )) - { - RsFileHash hash; - if(!mFileHierarchy->getDirHashFromIndex(dir->subdirs[i],hash)) - { - RS_ERR( "Cannot get hash from subdir index: ", - dir->subdirs[i], ". Weird bug." ); - print_stacktrace(); - return false; - } - allowed_subdirs.push_back(hash); - -#ifdef DEBUG_LOCAL_DIRECTORY_STORAGE - std::cerr << " pushing subdir " << hash << ", array position=" << i << " indx=" << dir->subdirs[i] << std::endl; -#endif - } -#ifdef DEBUG_LOCAL_DIRECTORY_STORAGE - else - std::cerr << " not pushing subdir " << hash << ", array position=" << i << " indx=" << dir->subdirs[i] << ": permission denied for this peer." << std::endl; -#endif - - /* now count the files that do not have a null hash (meaning the hash has - * indeed been computed), also in case files are shared singularly (without - * a shared directory) so they are child of root check browsability - * permission */ - uint32_t allowed_subfiles = 0; - for(uint32_t i=0; isubfiles.size(); ++i) - { - const InternalFileHierarchyStorage::FileEntry* file = - mFileHierarchy->getFileEntry(dir->subfiles[i]); - if(file != nullptr && !file->file_hash.isNull() - && ( indx !=0 || ( - locked_getFileSharingPermissions( - dir->subfiles[i], node_flags, node_groups ) && - rsPeers->computePeerPermissionFlags( - client_id, node_flags, node_groups ) & - RS_FILE_HINTS_BROWSABLE ) )) - allowed_subfiles++; - } - - unsigned char* section_data = (unsigned char *) - rs_malloc(FL_BASE_TMP_SECTION_SIZE); - if(!section_data) return false; - - uint32_t section_size = FL_BASE_TMP_SECTION_SIZE; - uint32_t section_offset = 0; - - /* we need to send: - * - the name of the directory, its TS - * - the index entry for each subdir (the updte TS are exchanged at a - * higher level) - * - the file info for each subfile */ - - std::string virtual_dir_name = locked_getVirtualDirName(indx); - - /* Manual serialization AGAIN! This is terrible and should be ported to the - * new serialization system ASAP! */ - if(!FileListIO::writeField( - section_data, section_size, section_offset, - FILE_LIST_IO_TAG_DIR_NAME, virtual_dir_name )) - { free(section_data); return false; } - if(!FileListIO::writeField( - section_data, section_size, section_offset, - FILE_LIST_IO_TAG_RECURS_MODIF_TS, - (uint32_t)dir->dir_most_recent_time )) - { free(section_data); return false; } - if(!FileListIO::writeField( - section_data, section_size, section_offset, - FILE_LIST_IO_TAG_MODIF_TS, (uint32_t)dir->dir_modtime )) - { free(section_data); return false;} - - // serialise number of subdirs and number of subfiles - if(!FileListIO::writeField( - section_data, section_size, section_offset, - FILE_LIST_IO_TAG_RAW_NUMBER, (uint32_t)allowed_subdirs.size() )) - { free(section_data); return false; } - if(!FileListIO::writeField( - section_data, section_size, section_offset, - FILE_LIST_IO_TAG_RAW_NUMBER, (uint32_t)allowed_subfiles )) - { free(section_data); return false; } - - // serialise subdirs entry indexes - for(uint32_t i=0; isubfiles.size(); ++i) - { - uint32_t file_section_offset = 0; - - const InternalFileHierarchyStorage::FileEntry* file = - mFileHierarchy->getFileEntry(dir->subfiles[i]); - - if(file == nullptr || file->file_hash.isNull()) - { - RS_INFO( "skipping unhashed or Null file entry ", - dir->subfiles[i], " to get/send file info." ); - continue; - } - - if(indx == 0) - { - if(!locked_getFileSharingPermissions( - dir->subfiles[i], node_flags, node_groups )) - { - RS_ERR( "Failure getting sharing permission for single file: ", - dir->subfiles[i] ); - print_stacktrace(); - continue; - } - - if(!( rsPeers->computePeerPermissionFlags( - client_id, node_flags, node_groups ) & - RS_FILE_HINTS_BROWSABLE )) - { - RS_INFO( "Skipping single file shared without browse " - "permission" ); - continue; - } - } - - if(!FileListIO::writeField( - file_section_data, file_section_size, file_section_offset, - FILE_LIST_IO_TAG_FILE_NAME, file->file_name )) - { free(section_data); free(file_section_data); return false; } - if(!FileListIO::writeField( - file_section_data, file_section_size, file_section_offset, - FILE_LIST_IO_TAG_FILE_SIZE, file->file_size )) - { free(section_data); free(file_section_data); return false; } - if(!FileListIO::writeField( - file_section_data, file_section_size, file_section_offset, - FILE_LIST_IO_TAG_FILE_SHA1_HASH, file->file_hash )) - { free(section_data); free(file_section_data); return false; } - if(!FileListIO::writeField( - file_section_data, file_section_size, file_section_offset, - FILE_LIST_IO_TAG_MODIF_TS, (uint32_t)file->file_modtime )) - { free(section_data); free(file_section_data); return false; } - - // now write the whole string into a single section in the file - if(!FileListIO::writeField( - section_data, section_size, section_offset, - FILE_LIST_IO_TAG_REMOTE_FILE_ENTRY, - file_section_data, file_section_offset )) - { free(section_data); free(file_section_data); return false; } - -#ifdef DEBUG_LOCAL_DIRECTORY_STORAGE - std::cerr << " pushing subfile " << file->hash << ", array position=" << i << " indx=" << dir->subfiles[i] << std::endl; -#endif - } - free(file_section_data); - -#ifdef DEBUG_LOCAL_DIRECTORY_STORAGE - std::cerr << "Serialised dir entry to send for entry index " << (void*)(intptr_t)indx << ". Data size is " << section_size << " bytes" << std::endl; -#endif - - // Discards the possibly unused trailing bytes in the end of section_data - bindata.bin_data = realloc(section_data,section_offset); - bindata.bin_len = section_offset; - - return true; -} - - -/******************************************************************************************************************/ -/* Remote Directory Storage */ -/******************************************************************************************************************/ - -RemoteDirectoryStorage::RemoteDirectoryStorage(const RsPeerId& pid,const std::string& fname) - : DirectoryStorage(pid,fname) -{ - mLastSweepTime = time(NULL) - (RSRandom::random_u32() % DELAY_BETWEEN_REMOTE_DIRECTORIES_SWEEP) ; - - std::cerr << "Loaded remote directory for peer " << pid << ", inited last sweep time to " << time(NULL) - mLastSweepTime << " secs ago." << std::endl; -#ifdef DEBUG_REMOTE_DIRECTORY_STORAGE - mFileHierarchy->print(); -#endif -} - -bool RemoteDirectoryStorage::deserialiseUpdateDirEntry(const EntryIndex& indx,const RsTlvBinaryData& bindata) -{ - const unsigned char *section_data = (unsigned char*)bindata.bin_data ; - uint32_t section_size = bindata.bin_len ; - uint32_t section_offset=0 ; - -#ifdef DEBUG_REMOTE_DIRECTORY_STORAGE - std::cerr << "RemoteDirectoryStorage::deserialiseDirEntry(): deserialising directory content for friend " << peerId() << ", and directory " << indx << std::endl; -#endif - - std::string dir_name ; - uint32_t most_recent_time ,dir_modtime ; - - if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_DIR_NAME ,dir_name )) return false ; - if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_RECURS_MODIF_TS,most_recent_time)) return false ; - if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_MODIF_TS ,dir_modtime )) return false ; - -#ifdef DEBUG_REMOTE_DIRECTORY_STORAGE - std::cerr << " dir name : \"" << dir_name << "\"" << std::endl; - std::cerr << " most recent time : " << most_recent_time << std::endl; - std::cerr << " modification time : " << dir_modtime << std::endl; -#endif - - // serialise number of subdirs and number of subfiles - - uint32_t n_subdirs,n_subfiles ; - - if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,n_subdirs )) return false ; - if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_RAW_NUMBER,n_subfiles )) return false ; - -#ifdef DEBUG_REMOTE_DIRECTORY_STORAGE - std::cerr << " number of subdirs : " << n_subdirs << std::endl; - std::cerr << " number of files : " << n_subfiles << std::endl; -#endif - - // serialise subdirs entry indexes - - std::vector subdirs_hashes ; - RsFileHash subdir_hash ; - - for(uint32_t i=0;i subfiles_array ; - - // Pre-allocate file_section_data, so that read_field does not need to do it many times. - - unsigned char *file_section_data = (unsigned char *)rs_malloc(FL_BASE_TMP_SECTION_SIZE) ; - - if(!file_section_data) - return false ; - - uint32_t file_section_size = FL_BASE_TMP_SECTION_SIZE ; - - for(uint32_t i=0;iupdateDirEntry(indx,dir_name,most_recent_time,dir_modtime,subdirs_hashes,subfiles_array)) - { - std::cerr << "(EE) Cannot update dir entry with index " << indx << ": entry does not exist." << std::endl; - return false ; - } - - mChanged = true ; - - return true ; -} - -int RemoteDirectoryStorage::searchHash(const RsFileHash& hash, EntryIndex& result) const -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - - return mFileHierarchy->searchHash(hash,result); -} - - - diff --git a/libretroshare/src/file_sharing/directory_storage.h b/libretroshare/src/file_sharing/directory_storage.h deleted file mode 100644 index 670682be3..000000000 --- a/libretroshare/src/file_sharing/directory_storage.h +++ /dev/null @@ -1,318 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: directory_storage.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2016 by Mr.Alice * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ -#pragma once - -#include -#include -#include - -#include "retroshare/rsids.h" -#include "retroshare/rsfiles.h" -#include "util/rstime.h" - -#define NOT_IMPLEMENTED() { std::cerr << __PRETTY_FUNCTION__ << ": not yet implemented." << std::endl; } - -class RsTlvBinaryData ; -class InternalFileHierarchyStorage ; -class RsTlvBinaryData ; - -class DirectoryStorage -{ - public: - DirectoryStorage(const RsPeerId& pid, const std::string& fname) ; - virtual ~DirectoryStorage() {} - - typedef uint32_t EntryIndex ; - static const EntryIndex NO_INDEX = 0xffffffff; - - void save() const ; - - // These functions are to be used by file transfer and file search. - - virtual int searchTerms(const std::list& terms, std::list &results) const ; - virtual int searchBoolExp(RsRegularExpression::Expression * exp, std::list &results) const ; - - // gets/sets the various time stamps: - // - bool getDirectoryRecursModTime(EntryIndex index,rstime_t& recurs_max_modf_TS) const ; // last modification time, computed recursively over all subfiles and directories - bool getDirectoryLocalModTime (EntryIndex index,rstime_t& motime_TS) const ; // last modification time for that index only - bool getDirectoryUpdateTime (EntryIndex index,rstime_t& update_TS) const ; // last time the entry was updated. This is only used on the RemoteDirectoryStorage side. - - bool setDirectoryRecursModTime(EntryIndex index,rstime_t recurs_max_modf_TS) ; - bool setDirectoryLocalModTime (EntryIndex index,rstime_t modtime_TS) ; - bool setDirectoryUpdateTime (EntryIndex index,rstime_t update_TS) ; - - uint32_t getEntryType(const EntryIndex& indx) ; // WARNING: returns DIR_TYPE_*, not the internal directory storage stuff. - virtual bool extractData(const EntryIndex& indx,DirDetails& d); - - // This class allows to abstractly browse the stored directory hierarchy in a depth-first manner. - // It gives access to sub-files and sub-directories below. When using it, the client should make sure - // that the DirectoryStorage is properly locked, since the iterator cannot lock it. - // - class DirIterator - { - public: - DirIterator(const DirIterator& d) ; - DirIterator(DirectoryStorage *d,EntryIndex i) ; - - DirIterator& operator++() ; - EntryIndex operator*() const ; - - operator bool() const ; // used in for loops. Returns true when the iterator is valid. - - // info about the directory that is pointed by the iterator - - std::string name() const ; - rstime_t last_modif_time() const ; // last time a file in this directory or in the directories below has been modified. - rstime_t last_update_time() const ; // last time this directory was updated - private: - EntryIndex mParentIndex ; // index of the parent dir. - uint32_t mDirTabIndex ; // index in the vector of subdirs. - InternalFileHierarchyStorage *mStorage ; - - friend class DirectoryStorage ; - }; - class FileIterator - { - public: - explicit FileIterator(DirIterator& d); // crawls all files in specified directory - FileIterator(DirectoryStorage *d,EntryIndex e); // crawls all files in specified directory - - FileIterator& operator++() ; - EntryIndex operator*() const ; // current file entry - - operator bool() const ; // used in for loops. Returns true when the iterator is valid. - - // info about the file that is pointed by the iterator - - std::string name() const ; - uint64_t size() const ; - RsFileHash hash() const ; - rstime_t modtime() const ; - - private: - EntryIndex mParentIndex ; // index of the parent dir. - uint32_t mFileTabIndex ; // index in the vector of subdirs. - InternalFileHierarchyStorage *mStorage ; - }; - - struct FileTS - { - uint64_t size ; - rstime_t modtime; - }; - - EntryIndex root() const ; // returns the index of the root directory entry. This is generally 0. - const RsPeerId& peerId() const { return mPeerId ; } // peer ID of who owns that file list. - int parentRow(EntryIndex e) const ; // position of the current node, in the array of children at its parent node. Used by GUI for display. - bool getChildIndex(EntryIndex e,int row,EntryIndex& c) const; // returns the index of the children node at position "row" in the children nodes. Used by GUI for display. - - // Sets the subdirectory/subfiles list of entry indx the supplied one, possible adding and removing directories (resp.files). New directories are set empty with - // just a name and need to be updated later on. New files are returned in a list so that they can be sent to hash cache. - // - bool updateSubDirectoryList(const EntryIndex& indx, const std::set& subdirs, const RsFileHash &random_hash_salt) ; - bool updateSubFilesList(const EntryIndex& indx, const std::map &subfiles, std::map &new_files) ; - bool removeDirectory(const EntryIndex& indx) ; - - // Returns the hash of the directory at the given index and reverse. This hash is set as random the first time it is used (when updating directories). It will be - // used by the sync system to designate the directory without referring to index (index could be used to figure out the existance of hidden directories) - - bool getDirHashFromIndex(const EntryIndex& index,RsFileHash& hash) const ; // constant cost - bool getIndexFromDirHash(const RsFileHash& hash,EntryIndex& index) const ; // log cost. - - // gathers statistics from the internal directory structure - - void getStatistics(SharedDirStats& stats) ; - - void print(); - void cleanup(); - - /*! - * \brief checkSave - * Checks the time of last saving, last modification time, and saves if needed. - */ - void checkSave() ; - - const std::string& filename() const { return mFileName ; } - - protected: - bool load(const std::string& local_file_name) ; - void save(const std::string& local_file_name) ; - - private: - - // debug - void locked_check(); - - // storage of internal structure. Totally hidden from the outside. EntryIndex is simply the index of the entry in the vector. - - RsPeerId mPeerId; - - protected: - mutable RsMutex mDirStorageMtx ; - - InternalFileHierarchyStorage *mFileHierarchy ; - - rstime_t mLastSavedTime ; - bool mChanged ; - std::string mFileName; -}; - -class RemoteDirectoryStorage: public DirectoryStorage -{ -public: - RemoteDirectoryStorage(const RsPeerId& pid,const std::string& fname) ; - virtual ~RemoteDirectoryStorage() {} - - /*! - * \brief deserialiseDirEntry - * Loads a serialised directory content coming from a friend. The directory entry needs to exist already, - * as it is created when updating the parent. - * - * \param indx index of the directory to update - * \param bindata binary data to deserialise from - * \return false when the directory cannot be found. - */ - bool deserialiseUpdateDirEntry(const EntryIndex& indx,const RsTlvBinaryData& data) ; - - /*! - * \brief lastSweepTime - * returns the last time a sweep has been done over the directory in order to check update TS. - * \return - */ - rstime_t& lastSweepTime() { return mLastSweepTime ; } - - /*! - * \brief searchHash - * Looks into local database of shared files for the given hash. - * \param hash hash to look for - * \param results Entry index of the file that is found - * \return - * true is a file is found - * false otherwise. - */ - virtual int searchHash(const RsFileHash& hash, EntryIndex& results) const ; - -private: - rstime_t mLastSweepTime ; -}; - -class LocalDirectoryStorage: public DirectoryStorage -{ -public: - LocalDirectoryStorage(const std::string& fname,const RsPeerId& own_id); - virtual ~LocalDirectoryStorage() {} - - /*! - * \brief [gs]etSharedDirectoryList - * Gets/sets the list of shared directories. Each directory is supplied with a virtual name (the name the friends will see), and sharing flags/groups. - * \param lst - */ - void setSharedDirectoryList(const std::list& lst) ; - void getSharedDirectoryList(std::list& lst) ; - - void updateShareFlags(const SharedDirInfo& info) ; - bool convertSharedFilePath(const std::string& path_with_virtual_name,std::string& fullpath) ; - - virtual bool updateHash(const EntryIndex& index, const RsFileHash& hash, bool update_internal_hierarchy); - /*! - * \brief searchHash - * Looks into local database of shared files for the given hash. Also looks for files such that the hash of the hash - * matches the given hash, and returns the real hash. - * \param hash hash to look for - * \param real_hash hash such that H(real_hash) = hash, or null hash if not found. - * \param results Entry index of the file that is found - * \return - * true is a file is found - * false otherwise. - */ - virtual int searchHash(const RsFileHash& hash, RsFileHash &real_hash, EntryIndex &results) const ; - - /*! - * \brief updateTimeStamps - * Checks recursive TS and update the if needed. - */ - void updateTimeStamps(); - - /*! - * \brief notifyTSChanged - * Use this to force an update of the recursive TS, when calling updateTimeStamps(); - */ - void notifyTSChanged(); - /*! - * \brief getFileInfo Converts an index info a full file info structure. - * \param i index in the directory structure - * \param info structure to be filled in - * \return false if the file does not exist, or is a directory,... - */ - bool getFileInfo(DirectoryStorage::EntryIndex i,FileInfo& info) ; - - /*! - * \brief getFileSharingPermissions - * Computes the flags and parent groups for any index. - * \param indx index of the entry to compute the flags for - * \param flags computed flags - * \param parent_groups computed parent groups - * \return - * false if the index is not valid - * false otherwise - */ - bool getFileSharingPermissions(const EntryIndex& indx, FileStorageFlags &flags, std::list &parent_groups); - - virtual bool extractData(const EntryIndex& indx,DirDetails& d) ; - - /*! - * \brief serialiseDirEntry - * Produced a serialised directory content listing suitable for export to friends. - * - * \param indx index of the directory to serialise - * \param bindata binary data created by serialisation - * \param client_id Peer id to be serialised to. Depending on permissions, some subdirs can be removed. - * \return false when the directory cannot be found. - */ - bool serialiseDirEntry(const EntryIndex& indx, RsTlvBinaryData& bindata, const RsPeerId &client_id) ; - -private: - static RsFileHash makeEncryptedHash(const RsFileHash& hash); - bool locked_findRealHash(const RsFileHash& hash, RsFileHash& real_hash) const; - std::string locked_getVirtualPath(EntryIndex indx) const ; - std::string locked_getVirtualDirName(EntryIndex indx) const ; - - bool locked_getFileSharingPermissions(const EntryIndex& indx, FileStorageFlags &flags, std::list& parent_groups); - std::string locked_findRealRootFromVirtualFilename(const std::string& virtual_rootdir) const; - - std::map mLocalDirs ; // map is better for search. it->first=it->second.filename - std::map mEncryptedHashes; // map such that hash(it->second) = it->first - - bool mTSChanged ; -}; - - - - - - - - - - - diff --git a/libretroshare/src/file_sharing/directory_updater.cc b/libretroshare/src/file_sharing/directory_updater.cc deleted file mode 100644 index 7d6828712..000000000 --- a/libretroshare/src/file_sharing/directory_updater.cc +++ /dev/null @@ -1,474 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: directory_updater.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016 Mr.Alice * - * Copyright (C) 2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ - -#include "util/cxx17retrocompat.h" -#include "util/folderiterator.h" -#include "util/rstime.h" -#include "rsserver/p3face.h" -#include "directory_storage.h" -#include "directory_updater.h" -#include "file_sharing_defaults.h" -#include "util/rsdebuglevel3.h" - -//#define DEBUG_LOCAL_DIR_UPDATER 1 - -//=============================================================================================================// -// Local Directory Updater // -//=============================================================================================================// - -LocalDirectoryUpdater::LocalDirectoryUpdater(HashStorage *hc,LocalDirectoryStorage *lds) - : mHashCache(hc), mSharedDirectories(lds) - , mLastSweepTime(0), mLastTSUpdateTime(0) - , mDelayBetweenDirectoryUpdates(DELAY_BETWEEN_DIRECTORY_UPDATES) - , mIsEnabled(false), mFollowSymLinks(FOLLOW_SYMLINKS_DEFAULT) - , mIgnoreDuplicates(true) - /* Can be left to false, but setting it to true will force to re-hash any file that has been left unhashed in the last session.*/ - , mNeedsFullRecheck(true) - , mIsChecking(false), mForceUpdate(false), mIgnoreFlags (0), mMaxShareDepth(0) -{ -} - -bool LocalDirectoryUpdater::isEnabled() const -{ - return mIsEnabled ; -} -void LocalDirectoryUpdater::setEnabled(bool b) -{ - if(mIsEnabled == b) return; - if(!b) RsThread::askForStop(); - else if(!RsThread::isRunning()) start("fs dir updater"); - mIsEnabled = b ; -} - -void LocalDirectoryUpdater::threadTick() -{ - rstime_t now = time(NULL) ; - - if (mIsEnabled || mForceUpdate) - { - if(now > mDelayBetweenDirectoryUpdates + mLastSweepTime) - { - bool some_files_not_ready = false ; - - if(sweepSharedDirectories(some_files_not_ready)) - { - if(some_files_not_ready) - { - mNeedsFullRecheck = true ; - mLastSweepTime = now - mDelayBetweenDirectoryUpdates + 60 ; // retry 20 secs from now - - std::cerr << "(II) some files being modified. Will re-scan in 60 secs." << std::endl; - } - else - { - mNeedsFullRecheck = false ; - mLastSweepTime = now ; - } - - mSharedDirectories->notifyTSChanged(); - mForceUpdate = false ; - } - else - std::cerr << "(WW) sweepSharedDirectories() failed. Will do it again in a short time." << std::endl; - } - - if(now > DELAY_BETWEEN_LOCAL_DIRECTORIES_TS_UPDATE + mLastTSUpdateTime) - { - mSharedDirectories->updateTimeStamps() ; - mLastTSUpdateTime = now ; - } - } - - for(uint32_t i=0;i<10;++i) - { - rstime::rs_usleep(1*1000*1000); - - { - if(mForceUpdate) - break ; - } - } -} - -void LocalDirectoryUpdater::forceUpdate(bool add_safe_delay) -{ - mForceUpdate = true ; - mLastSweepTime = rstime_t(time(NULL)) - rstime_t(mDelayBetweenDirectoryUpdates) ; - - if(add_safe_delay) - mLastSweepTime += rstime_t(MIN_TIME_AFTER_LAST_MODIFICATION); - - if(mHashCache != NULL && mHashCache->hashingProcessPaused()) - mHashCache->togglePauseHashingProcess(); -} - -bool LocalDirectoryUpdater::sweepSharedDirectories(bool& some_files_not_ready) -{ - if(mHashSalt.isNull()) - { - RS_ERR("no salt value in LocalDirectoryUpdater"); - print_stacktrace(); - return false; - } - - mIsChecking = true; - - RsServer::notify()->notifyListPreChange(NOTIFY_LIST_DIRLIST_LOCAL, 0); - - /* recursive update algorithm works that way: - * - the external loop starts on the shared directory list and goes through - * sub-directories - * - at the same time, it updates the local list of shared directories. - * A single sweep is performed over the whole directory structure. - * - the information that is costly to compute (the hash) is stored - * externally into a separate structure. - * - doing so, changing directory names or moving files between directories - * does not cause a re-hash of the content. */ - std::list shared_directory_list; - mSharedDirectories->getSharedDirectoryList(shared_directory_list); - std::set sub_dir_list; - - /* Support also single files sharing as it make much more sense on some - * platforms like Android */ - std::map singleFilesMap; - - /* We re-check that each dir actually exists. It might have been removed - * from the disk. Accept also single files not just directories. */ - for(auto& realDir: std::as_const(shared_directory_list)) - { - const auto& fPath = realDir.filename; - if(RsDirUtil::checkDirectory(fPath)) - sub_dir_list.insert(fPath); - else if (RsDirUtil::fileExists(fPath)) - { - rstime_t lastWrite= RsDirUtil::lastWriteTime(fPath); - if(time(nullptr) >= lastWrite + MIN_TIME_AFTER_LAST_MODIFICATION) - { - uint64_t fSize = 0; - RsDirUtil::checkFile(fPath,fSize); - - singleFilesMap[fPath].modtime = lastWrite; - singleFilesMap[fPath].size = fSize; - } - else - { - some_files_not_ready = true; - RS_INFO( "file: \"", fPath, "\" is " - "probably being written to. Keep it for later"); - } - } - else RS_WARN( "Got non existent file \"", fPath, - "\" in shared directories list. Ignored." ); - } - - { - const auto tRoot = mSharedDirectories->root(); - std::map needsUpdate; - mSharedDirectories->updateSubFilesList( - tRoot, singleFilesMap, needsUpdate); - - for( DirectoryStorage::FileIterator storedSingleFilesIt( - mSharedDirectories, mSharedDirectories->root() ); - storedSingleFilesIt; ++storedSingleFilesIt ) - { - const auto& it = storedSingleFilesIt; - RsFileHash hash; - if( mHashCache->requestHash( - it.name(), it.size(), it.modtime(), hash, - this, *it ) ) - mSharedDirectories->updateHash(*it, hash, it.hash() != hash); - } - } - - /* make sure that entries in stored_dir_it are the same than paths in - * real_dir_it, and in the same order. */ - mSharedDirectories->updateSubDirectoryList( - mSharedDirectories->root(), sub_dir_list, mHashSalt ); - - // now for each of them, go recursively and match both files and dirs - std::set existing_dirs; - for( DirectoryStorage::DirIterator stored_dir_it( - mSharedDirectories, mSharedDirectories->root() ); - stored_dir_it; ++stored_dir_it ) - { - RS_DBG4("recursing into \"", stored_dir_it.name()); - - existing_dirs.insert(RsDirUtil::removeSymLinks(stored_dir_it.name())); - recursUpdateSharedDir( - stored_dir_it.name(), *stored_dir_it, - existing_dirs, 1, some_files_not_ready ); - /* here we need to use the list that was stored, instead of the shared - * dir list, because the two are not necessarily in the same order. */ - } - - RsServer::notify()->notifyListChange(NOTIFY_LIST_DIRLIST_LOCAL, 0); - mIsChecking = false; - - return true; -} - -void LocalDirectoryUpdater::recursUpdateSharedDir( - const std::string& cumulated_path, DirectoryStorage::EntryIndex indx, - std::set& existing_directories, uint32_t current_depth, - bool& some_files_not_ready ) -{ - RS_DBG4("parsing directory \"", cumulated_path, "\" index: ", indx); - - /* make sure list of subdirs is the same - * make sure list of subfiles is the same - * request all hashes to the hashcache */ - - // disallow symbolic links and files from the future. - librs::util::FolderIterator dirIt(cumulated_path, mFollowSymLinks, false); - - rstime_t dir_local_mod_time; - if(!mSharedDirectories->getDirectoryLocalModTime(indx,dir_local_mod_time)) - { - RS_ERR("Cannot get local mod time for dir index: ", indx); - print_stacktrace(); - return; - } - - rstime_t now = time(nullptr); - /* the > is because we may have changed the virtual name, and therefore the - * TS wont match. We only want to detect when the directory has changed on - * the disk */ - if(mNeedsFullRecheck || dirIt.dir_modtime() > dir_local_mod_time) - { - // collect subdirs and subfiles - std::map subfiles; - std::set subdirs; - - for( ; dirIt.isValid(); dirIt.next() ) - if(filterFile(dirIt.file_name())) - { - const auto fType = dirIt.file_type(); - switch(fType) - { - case librs::util::FolderIterator::TYPE_FILE: - if(now >= dirIt.file_modtime() + MIN_TIME_AFTER_LAST_MODIFICATION) - { - subfiles[dirIt.file_name()].modtime = dirIt.file_modtime(); - subfiles[dirIt.file_name()].size = dirIt.file_size(); - RS_DBG4("adding sub-file \"", dirIt.file_name(), "\""); - } - else - { - some_files_not_ready = true; - RS_INFO( "file: \"", dirIt.file_fullpath(), "\" is " - "probably being written to. Keep it for later"); - } - break; - case librs::util::FolderIterator::TYPE_DIR: - { - bool dir_is_accepted = true; - /* 64 is here as a safe limit, to make infinite loops - * impossible. - * TODO: Make it a visible constexpr in the header */ - if( (mMaxShareDepth > 0u && current_depth > mMaxShareDepth) - || (mMaxShareDepth == 0 && current_depth >= 64) ) - dir_is_accepted = false; - - if(dir_is_accepted && mFollowSymLinks && mIgnoreDuplicates) - { - std::string real_path = RsDirUtil::removeSymLinks( - cumulated_path + "/" + dirIt.file_name() ); - - if( existing_directories.end() != - existing_directories.find(real_path) ) - { - RS_WARN( "Directory: \"", cumulated_path, - "\" has real path: \"", real_path, - "\" which already belongs to another " - "shared directory. Ignoring" ); - dir_is_accepted = false; - } - else existing_directories.insert(real_path); - } - - if(dir_is_accepted) subdirs.insert(dirIt.file_name()); - - RS_DBG4("adding sub-dir \"", dirIt.file_name(), "\""); - - break; - } - default: - RS_ERR( "Got Dir entry of unknown type:", fType, - "with path \"", cumulated_path, "/", - dirIt.file_name(), "\"" ); - print_stacktrace(); - break; - } - } - - /* update folder modificatoin time, which is the only way to detect - * e.g. removed or renamed files. */ - mSharedDirectories->setDirectoryLocalModTime(indx,dirIt.dir_modtime()); - - // update file and dir lists for current directory. - mSharedDirectories->updateSubDirectoryList(indx,subdirs,mHashSalt); - - std::map new_files; - mSharedDirectories->updateSubFilesList(indx, subfiles, new_files); - - // now go through list of subfiles and request the hash to hashcache - for( DirectoryStorage::FileIterator dit(mSharedDirectories,indx); - dit; ++dit ) - { - /* ask about the hash. If not present, ask HashCache. - * If not present, or different, the callback will update it. */ - RsFileHash hash; - - /* mSharedDirectories does two things: store H(F), and - * compute H(H(F)), which is used in FT. - * The later is always needed. */ - - if( mHashCache->requestHash( - cumulated_path + "/" + dit.name(), - dit.size(), dit.modtime(), hash, this, *dit ) ) - mSharedDirectories->updateHash(*dit, hash, hash != dit.hash()); - } - } - - // go through the list of sub-dirs and recursively update - for( DirectoryStorage::DirIterator stored_dir_it(mSharedDirectories, indx); - stored_dir_it; ++stored_dir_it ) - recursUpdateSharedDir( cumulated_path + "/" + stored_dir_it.name(), - *stored_dir_it, existing_directories, - current_depth+1, some_files_not_ready ); -} - -bool LocalDirectoryUpdater::filterFile(const std::string& fname) const -{ - if(mIgnoreFlags & RS_FILE_SHARE_FLAGS_IGNORE_SUFFIXES) - for(auto it(mIgnoredSuffixes.begin());it!=mIgnoredSuffixes.end();++it) - if(fname.size() >= (*it).size() && fname.substr( fname.size() - (*it).size()) == *it) - { - std::cerr << "(II) ignoring file " << fname << ", because it matches suffix \"" << *it << "\"" << std::endl; - return false ; - } - - if(mIgnoreFlags & RS_FILE_SHARE_FLAGS_IGNORE_PREFIXES) - for(auto it(mIgnoredPrefixes.begin());it!=mIgnoredPrefixes.end();++it) - if(fname.size() >= (*it).size() && fname.substr( 0,(*it).size()) == *it) - { - std::cerr << "(II) ignoring file " << fname << ", because it matches prefix \"" << *it << "\"" << std::endl; - return false ; - } - - return true ; -} - -void LocalDirectoryUpdater::togglePauseHashingProcess() -{ - mHashCache->togglePauseHashingProcess() ; -} -bool LocalDirectoryUpdater::hashingProcessPaused() -{ - return mHashCache->hashingProcessPaused(); -} - -bool LocalDirectoryUpdater::inDirectoryCheck() const -{ - return mHashCache->isRunning(); -} - -void LocalDirectoryUpdater::hash_callback(uint32_t client_param, const std::string &/*name*/, const RsFileHash &hash, uint64_t /*size*/) -{ - if(!mSharedDirectories->updateHash(DirectoryStorage::EntryIndex(client_param),hash,true)) - std::cerr << "(EE) Cannot update file. Something's wrong." << std::endl; - - mSharedDirectories->notifyTSChanged() ; -} - -bool LocalDirectoryUpdater::hash_confirm(uint32_t client_param) -{ - return mSharedDirectories->getEntryType( - DirectoryStorage::EntryIndex(client_param) ) == DIR_TYPE_FILE; -} - -void LocalDirectoryUpdater::setFileWatchPeriod(int seconds) -{ - mDelayBetweenDirectoryUpdates = seconds ; -} -uint32_t LocalDirectoryUpdater::fileWatchPeriod() const -{ - return mDelayBetweenDirectoryUpdates ; -} - -void LocalDirectoryUpdater::setFollowSymLinks(bool b) -{ - if(b != mFollowSymLinks) - mNeedsFullRecheck = true ; - - mFollowSymLinks = b ; - - forceUpdate(false); -} - -bool LocalDirectoryUpdater::followSymLinks() const -{ - return mFollowSymLinks ; -} - -void LocalDirectoryUpdater::setIgnoreLists(const std::list& ignored_prefixes,const std::list& ignored_suffixes,uint32_t ignore_flags) -{ - mIgnoredPrefixes = ignored_prefixes ; - mIgnoredSuffixes = ignored_suffixes ; - mIgnoreFlags = ignore_flags; -} -bool LocalDirectoryUpdater::getIgnoreLists(std::list& ignored_prefixes,std::list& ignored_suffixes,uint32_t& ignore_flags) const -{ - ignored_prefixes = mIgnoredPrefixes; - ignored_suffixes = mIgnoredSuffixes; - ignore_flags = mIgnoreFlags ; - - return true; -} - -int LocalDirectoryUpdater::maxShareDepth() const -{ - return mMaxShareDepth ; -} - -void LocalDirectoryUpdater::setMaxShareDepth(uint32_t d) -{ - if(d != mMaxShareDepth) - mNeedsFullRecheck = true ; - - mMaxShareDepth = d ; -} - -bool LocalDirectoryUpdater::ignoreDuplicates() const -{ - return mIgnoreDuplicates; -} - -void LocalDirectoryUpdater::setIgnoreDuplicates(bool b) -{ - if(b != mIgnoreDuplicates) - mNeedsFullRecheck = true ; - - mIgnoreDuplicates = b ; -} diff --git a/libretroshare/src/file_sharing/directory_updater.h b/libretroshare/src/file_sharing/directory_updater.h deleted file mode 100644 index b7d72b3a9..000000000 --- a/libretroshare/src/file_sharing/directory_updater.h +++ /dev/null @@ -1,98 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: directory_updater.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2016 by Mr.Alice * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ - -// This class crawls the given directry hierarchy and updates it. It does so by calling the -// shared file list source. This source may be of two types: -// - local: directories are crawled n disk and files are hashed / requested from a cache -// - remote: directories are requested remotely to a providing client -// -#include "file_sharing/hash_cache.h" -#include "file_sharing/directory_storage.h" -#include "util/rstime.h" - -class LocalDirectoryUpdater: public HashStorageClient, public RsTickingThread -{ -public: - LocalDirectoryUpdater(HashStorage *hash_cache,LocalDirectoryStorage *lds) ; - virtual ~LocalDirectoryUpdater() {} - - void forceUpdate(bool add_safe_delay); - bool inDirectoryCheck() const ; - void togglePauseHashingProcess(); - bool hashingProcessPaused(); - - void setHashSalt(const RsFileHash& hash) { mHashSalt = hash; } - const RsFileHash& hashSalt() const { return mHashSalt; } - - void setFileWatchPeriod(int seconds) ; - uint32_t fileWatchPeriod() const ; - - void setFollowSymLinks(bool b) ; - bool followSymLinks() const ; - - void setEnabled(bool b) ; - bool isEnabled() const ; - - void setIgnoreLists(const std::list& ignored_prefixes,const std::list& ignored_suffixes,uint32_t ignore_flags) ; - bool getIgnoreLists(std::list& ignored_prefixes,std::list& ignored_suffixes,uint32_t& ignore_flags) const ; - - void setMaxShareDepth(uint32_t i) ; - int maxShareDepth() const; - - void setIgnoreDuplicates(bool b) ; - bool ignoreDuplicates() const; - -protected: - void threadTick() override; /// @see RsTickingThread - - virtual void hash_callback(uint32_t client_param, const std::string& name, const RsFileHash& hash, uint64_t size); - virtual bool hash_confirm(uint32_t client_param) ; - - void recursUpdateSharedDir(const std::string& cumulated_path, DirectoryStorage::EntryIndex indx, std::set& existing_directories, uint32_t current_depth,bool& files_not_ready); - bool sweepSharedDirectories(bool &some_files_not_ready); - -private: - bool filterFile(const std::string& fname) const ; // reponds true if the file passes the ignore lists test. - - HashStorage *mHashCache ; - LocalDirectoryStorage *mSharedDirectories ; - - RsFileHash mHashSalt ; - - rstime_t mLastSweepTime; - rstime_t mLastTSUpdateTime; - - uint32_t mDelayBetweenDirectoryUpdates; - bool mIsEnabled ; - bool mFollowSymLinks; - bool mIgnoreDuplicates; - bool mNeedsFullRecheck ; - bool mIsChecking ; - bool mForceUpdate ; - - uint32_t mIgnoreFlags ; - uint32_t mMaxShareDepth ; - - std::list mIgnoredPrefixes ; - std::list mIgnoredSuffixes ; -}; - diff --git a/libretroshare/src/file_sharing/file_sharing_defaults.h b/libretroshare/src/file_sharing/file_sharing_defaults.h deleted file mode 100644 index 92ff43947..000000000 --- a/libretroshare/src/file_sharing/file_sharing_defaults.h +++ /dev/null @@ -1,69 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: file_sharing_defaults.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2016 by Mr.Alice * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ -#pragma once - -static const uint32_t DELAY_BETWEEN_DIRECTORY_UPDATES = 600 ; // 10 minutes -static const uint32_t DELAY_BETWEEN_REMOTE_DIRECTORY_SYNC_REQ = 120 ; // 2 minutes -static const uint32_t DELAY_BETWEEN_LOCAL_DIRECTORIES_TS_UPDATE = 20 ; // 20 sec. But we only update for real if something has changed. -static const uint32_t DELAY_BETWEEN_REMOTE_DIRECTORIES_SWEEP = 60 ; // 60 sec. -static const uint32_t DELAY_BETWEEN_EXTRA_FILES_CACHE_UPDATES = 2 ; // 2 sec. - -static const uint32_t DELAY_BEFORE_DELETE_NON_EMPTY_REMOTE_DIR = 60*24*86400 ; // delete non empty remoe directories after 60 days of inactivity -static const uint32_t DELAY_BEFORE_DELETE_EMPTY_REMOTE_DIR = 5*24*86400 ; // delete empty remote directories after 5 days of inactivity - -static const std::string HASH_CACHE_DURATION_SS = "HASH_CACHE_DURATION" ; // key string to store hash remembering time -static const std::string WATCH_FILE_DURATION_SS = "WATCH_FILES_DELAY" ; // key to store delay before re-checking for new files -static const std::string WATCH_FILE_ENABLED_SS = "WATCH_FILES_ENABLED"; // key to store ON/OFF flags for file whatch -static const std::string TRUST_FRIEND_NODES_FOR_BANNED_FILES_SS = "TRUST_FRIEND_NODES_FOR_BANNED_FILES"; // should we trust friends for banned files or not -static const std::string FOLLOW_SYMLINKS_SS = "FOLLOW_SYMLINKS"; // dereference symbolic links, or just ignore them. -static const std::string IGNORE_DUPLICATES = "IGNORE_DUPLICATES"; // do not index files that are referenced multiple times because of links -static const std::string WATCH_HASH_SALT_SS = "WATCH_HASH_SALT"; // Salt that is used to hash directory names -static const std::string IGNORED_PREFIXES_SS = "IGNORED_PREFIXES"; // ignore file prefixes -static const std::string IGNORED_SUFFIXES_SS = "IGNORED_SUFFIXES"; // ignore file suffixes -static const std::string IGNORE_LIST_FLAGS_SS = "IGNORED_FLAGS"; // ignore file flags -static const std::string MAX_SHARE_DEPTH = "MAX_SHARE_DEPTH"; // maximum depth of shared directories - -static const std::string FILE_SHARING_DIR_NAME = "file_sharing" ; // hard-coded directory name to store friend file lists, hash cache, etc. -static const std::string HASH_CACHE_FILE_NAME = "hash_cache.bin" ; // hard-coded directory name to store encrypted hash cache. -static const std::string LOCAL_SHARED_DIRS_FILE_NAME = "local_dir_hierarchy.bin" ; // hard-coded directory name to store encrypted local dir hierarchy. - -static const uint32_t MIN_INTERVAL_BETWEEN_HASH_CACHE_SAVE = 20 ; // never save hash cache more often than every 20 secs. -static const uint32_t MIN_INTERVAL_BETWEEN_REMOTE_DIRECTORY_SAVE = 23 ; // never save remote directories more often than this -static const uint32_t MIN_TIME_AFTER_LAST_MODIFICATION = 10 ; // never hash a file that is just being modified, otherwise we end up with a corrupted hash - -static const uint32_t MAX_DIR_SYNC_RESPONSE_DATA_SIZE = 20000 ; // Maximum RsItem data size in bytes for serialised directory transmission -static const uint32_t DEFAULT_HASH_STORAGE_DURATION_DAYS = 30 ; // remember deleted/inaccessible files for 30 days - -static const uint32_t NB_FRIEND_INDEX_BITS_32BITS = 10 ; // Do not change this! -static const uint32_t NB_ENTRY_INDEX_BITS_32BITS = 22 ; // Do not change this! -static const uint32_t ENTRY_INDEX_BIT_MASK_32BITS = 0x003fffff ; // used for storing (EntryIndex,Friend) couples into a 32bits pointer. Depends on the two values just before. Dont change! - -static const uint64_t NB_FRIEND_INDEX_BITS_64BITS = 24 ; // Do not change this! -static const uint64_t NB_ENTRY_INDEX_BITS_64BITS = 40 ; // Do not change this! -static const uint64_t ENTRY_INDEX_BIT_MASK_64BITS = 0x0000000fffffffff ; // used for storing (EntryIndex,Friend) couples into a 32bits pointer. Depends on the two values just before. Dont change! - -static const uint32_t DELAY_BEFORE_DROP_REQUEST = 600; // every 10 min - -static const bool FOLLOW_SYMLINKS_DEFAULT = true; -static const bool TRUST_FRIEND_NODES_FOR_BANNED_FILES_DEFAULT = true; - -static const uint32_t FL_BASE_TMP_SECTION_SIZE = 4096 ; diff --git a/libretroshare/src/file_sharing/file_tree.cc b/libretroshare/src/file_sharing/file_tree.cc deleted file mode 100644 index d34dc166b..000000000 --- a/libretroshare/src/file_sharing/file_tree.cc +++ /dev/null @@ -1,378 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: file_tree.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2018 Retroshare Team * - * Copyright (C) 2020 Gioacchino Mazzurco * - * Copyright (C) 2020 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ -#include - -#include "util/radix64.h" -#include "util/rsbase64.h" -#include "util/rsdir.h" -#include "retroshare/rsfiles.h" -#include "file_sharing_defaults.h" -#include "filelist_io.h" -#include "serialiser/rstypeserializer.h" - -void RsFileTree::DirData::serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - RS_SERIAL_PROCESS(name); - RS_SERIAL_PROCESS(subdirs); - RS_SERIAL_PROCESS(subfiles); -} - -void RsFileTree::FileData::serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - RS_SERIAL_PROCESS(name); - RS_SERIAL_PROCESS(size); - RS_SERIAL_PROCESS(hash); -} - -/*static*/ std::tuple, std::error_condition> -RsFileTree::fromBase64(const std::string& base64) -{ - const auto failure = [](std::error_condition ec) - { return std::make_tuple(nullptr, ec); }; - - if(base64.empty()) return failure(std::errc::invalid_argument); - - std::error_condition ec; - std::vector mem; - if( (ec = RsBase64::decode(base64, mem)) ) return failure(ec); - - RsGenericSerializer::SerializeContext ctx( - mem.data(), static_cast(mem.size()), - RsSerializationFlags::INTEGER_VLQ ); - std::unique_ptr ft(new RsFileTree); - ft->serial_process( - RsGenericSerializer::SerializeJob::DESERIALIZE, ctx); - if(ctx.mOk) return std::make_tuple(std::move(ft), std::error_condition()); - - return failure(std::errc::invalid_argument); -} - -std::string RsFileTree::toBase64() const -{ - RsGenericSerializer::SerializeContext ctx; - ctx.mFlags = RsSerializationFlags::INTEGER_VLQ; - RsFileTree* ncThis = const_cast(this); - ncThis->serial_process( - RsGenericSerializer::SerializeJob::SIZE_ESTIMATE, ctx ); - - std::vector buf(ctx.mOffset); - ctx.mSize = ctx.mOffset; ctx.mOffset = 0; ctx.mData = buf.data(); - - ncThis->serial_process( - RsGenericSerializer::SerializeJob::SERIALIZE, ctx ); - std::string result; - RsBase64::encode(ctx.mData, ctx.mSize, result, false, true); - return result; -} - -std::string RsFileTree::toRadix64() const -{ - unsigned char* buff = nullptr; - uint32_t size = 0; - serialise(buff, size); - std::string res; - Radix64::encode(buff,size,res); - free(buff); - return res; -} - -std::unique_ptr RsFileTree::fromRadix64( - const std::string& radix64_string ) -{ - std::unique_ptr ft(new RsFileTree); - std::vector mem = Radix64::decode(radix64_string); - if(ft->deserialise(mem.data(), static_cast(mem.size()))) - return ft; - return nullptr; -} - -void RsFileTree::recurs_buildFileTree( - RsFileTree& ft, uint32_t index, const DirDetails& dd, bool remote, - bool remove_top_dirs ) -{ - RsDbg() << __PRETTY_FUNCTION__ << " index: " << index << std::endl; - if(ft.mDirs.size() <= index) - ft.mDirs.resize(index+1) ; - - if(remove_top_dirs) - ft.mDirs[index].name = RsDirUtil::getTopDir(dd.name) ; - else - ft.mDirs[index].name = dd.name ; - - ft.mDirs[index].subfiles.clear(); - ft.mDirs[index].subdirs.clear(); - - DirDetails dd2 ; - - FileSearchFlags flags = remote ? RS_FILE_HINTS_REMOTE : RS_FILE_HINTS_LOCAL; - - for(uint32_t i=0;iRequestDirDetails(dd.children[i].ref,dd2,flags)) - { - if(dd.children[i].type == DIR_TYPE_FILE) - { - FileData f ; - f.name = dd2.name ; - f.size = dd2.size ; - f.hash = dd2.hash ; - - ft.mDirs[index].subfiles.push_back(ft.mFiles.size()) ; - ft.mFiles.push_back(f) ; - - ft.mTotalFiles++ ; - ft.mTotalSize += f.size ; - } - else if(dd.children[i].type == DIR_TYPE_DIR) - { - ft.mDirs[index].subdirs.push_back(ft.mDirs.size()); - recurs_buildFileTree(ft,ft.mDirs.size(),dd2,remote,remove_top_dirs) ; - } - else - std::cerr << "(EE) Unsupported DirDetails type." << std::endl; - } - else - std::cerr << "(EE) Cannot request dir details for pointer " << dd.children[i].ref << std::endl; -} - -bool RsFileTree::getDirectoryContent( - std::string& name, std::vector& subdirs, - std::vector& subfiles, uint64_t index_p ) const -{ - // Avoid warnings on Android armv7 - using sz_t = std::vector::size_type; - sz_t index = static_cast(index_p); - - if(index >= mDirs.size()) return false; - - name = mDirs[index].name; - subdirs = mDirs[index].subdirs ; - - subfiles.clear() ; - for(sz_t i=0; i < mDirs[index].subfiles.size(); ++i) - subfiles.push_back(mFiles[static_cast(mDirs[index].subfiles[i])]); - - return true; -} - -std::unique_ptr RsFileTree::fromDirDetails( - const DirDetails& dd, bool remote ,bool remove_top_dirs ) -{ - std::unique_ptrft(new RsFileTree); - if(dd.type == DIR_TYPE_FILE) - { - FileData fd; - fd.name = dd.name; fd.hash = dd.hash; fd.size = dd.size; - ft->mFiles.push_back(fd); - ft->mTotalFiles = 1; - ft->mTotalSize = fd.size; - - DirData dd; - dd.name = "/"; - dd.subfiles.push_back(0); - ft->mDirs.push_back(dd); - } - else recurs_buildFileTree(*ft, 0, dd, remote, remove_top_dirs ); - return ft; -} - -typedef FileListIO::read_error read_error ; - -bool RsFileTree::deserialise(unsigned char *buffer,uint32_t buffer_size) -{ - uint32_t buffer_offset = 0 ; - - mTotalFiles = 0; - mTotalSize = 0; - - try - { - // Read some header - - uint32_t version,n_dirs,n_files ; - - if(!FileListIO::readField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_DIRECTORY_VERSION,version)) throw read_error(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_LOCAL_DIRECTORY_VERSION) ; - if(version != (uint32_t) FILE_LIST_IO_LOCAL_DIRECTORY_TREE_VERSION_0001) throw std::runtime_error("Wrong version number") ; - - if(!FileListIO::readField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_RAW_NUMBER,n_files)) throw read_error(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_RAW_NUMBER) ; - if(!FileListIO::readField(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_RAW_NUMBER,n_dirs)) throw read_error(buffer,buffer_size,buffer_offset,FILE_LIST_IO_TAG_RAW_NUMBER) ; - - // Write all file/dir entries - - mFiles.resize(n_files) ; - mDirs.resize(n_dirs) ; - - unsigned char *node_section_data = NULL ; - uint32_t node_section_size = 0 ; - - for(uint32_t i=0;i * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ -#include -#include "retroshare/rsids.h" -#include "pqi/authssl.h" -#include "util/rsdir.h" -#include "util/rsprint.h" -#include "serialiser/rsbaseserial.h" -#include "filelist_io.h" - -FileListIO::read_error::read_error(unsigned char *sec,uint32_t size,uint32_t offset,uint8_t expected_tag) -{ - std::ostringstream s ; - s << "At offset " << offset << "/" << size << ": expected section tag " << std::hex << (int)expected_tag << std::dec << " but got " << RsUtil::BinToHex(&sec[offset],std::min((int)size-(int)offset, 15)) << "..." << std::endl; - err_string = s.str(); -} - -template<> bool FileListIO::serialise(unsigned char *buff,uint32_t size,uint32_t& offset,const uint32_t & val) { return setRawUInt32(buff,size,&offset,val) ; } -template<> bool FileListIO::serialise(unsigned char *buff,uint32_t size,uint32_t& offset,const uint64_t & val) { return setRawUInt64(buff,size,&offset,val) ; } -template<> bool FileListIO::serialise(unsigned char *buff,uint32_t size,uint32_t& offset,const std::string & val) { return setRawString(buff,size,&offset,val) ; } -template<> bool FileListIO::serialise(unsigned char *buff,uint32_t size,uint32_t& offset,const Sha1CheckSum & val) { return val.serialise(buff,size,offset) ; } - -template<> bool FileListIO::deserialise(const unsigned char *buff,uint32_t size,uint32_t& offset,uint32_t & val) { return getRawUInt32(const_cast(buff),size,&offset,&val) ; } -template<> bool FileListIO::deserialise(const unsigned char *buff,uint32_t size,uint32_t& offset,uint64_t & val) { return getRawUInt64(const_cast(buff),size,&offset,&val) ; } -template<> bool FileListIO::deserialise(const unsigned char *buff,uint32_t size,uint32_t& offset,std::string & val) { return getRawString(const_cast(buff),size,&offset,val) ; } -template<> bool FileListIO::deserialise(const unsigned char *buff,uint32_t size,uint32_t& offset,Sha1CheckSum & val) { return val.deserialise(const_cast(buff),size,offset) ; } - -template<> uint32_t FileListIO::serial_size(const uint32_t & ) { return 4 ; } -template<> uint32_t FileListIO::serial_size(const uint64_t & ) { return 8 ; } -template<> uint32_t FileListIO::serial_size(const std::string & val) { return getRawStringSize(val) ; } -template<> uint32_t FileListIO::serial_size(const Sha1CheckSum & ) { return Sha1CheckSum::serial_size(); } - -bool FileListIO::writeField( unsigned char*&buff,uint32_t& buff_size,uint32_t& offset,uint8_t section_tag,const unsigned char * val,uint32_t size) -{ - if(!checkSectionSize(buff,buff_size,offset,size)) - return false; - - if(!writeSectionHeader(buff,buff_size,offset,section_tag,size)) - return false; - - memcpy(&buff[offset],val,size) ; - offset += size ; - - return true; -} - -bool FileListIO::readField (const unsigned char *buff,uint32_t buff_size,uint32_t& offset,uint8_t check_section_tag, unsigned char *& val,uint32_t& size) -{ - uint32_t local_size ; - - if(!readSectionHeader(buff,buff_size,offset,check_section_tag,local_size)) - return false; - - if(!checkSectionSize(val,size,0,local_size)) // allocate val if needed to handle local_size bytes. - return false; - - memcpy(val,&buff[offset],local_size); - offset += local_size ; - - return true ; -} - -bool FileListIO::write125Size(unsigned char *data,uint32_t data_size,uint32_t& offset,uint32_t S) -{ - if(S < 192) - { - if(offset+1 > data_size) - return false; - - data[offset++] = (uint8_t)S ; - return true; - } - else if(S < 8384) - { - if(offset+2 > data_size) - return false; - - data[offset+1] = (S - 192) & 0xff ; - data[offset ] = ((S - 192 - data[offset+1]) >> 8) + 192; - - offset += 2 ; - - return true; - } - else - { - if(offset+5 > data_size) - return false; - - data[offset++] = 0xff ; - data[offset++] = (uint8_t)((S >> 24) & 255) ; - data[offset++] = (uint8_t)((S >> 16) & 255) ; - data[offset++] = (uint8_t)((S >> 8) & 255) ; - data[offset++] = (uint8_t)((S ) & 255) ; - - return true ; - } -} - -bool FileListIO::read125Size(const unsigned char *data,uint32_t data_size,uint32_t& offset,uint32_t& S) -{ - if(offset + 1 >= data_size) return false; - - uint8_t b1 = data[offset++] ; - - if(b1 < 192) - { - S = b1; - return true ; - } - if(offset + 1 >= data_size) return false; - - uint8_t b2 = data[offset++] ; - - if(b1 < 224) - { - S = ((b1-192) << 8) + b2 + 192 ; - return true; - } - - if(b1 != 0xff) - return false; - - if(offset + 3 >= data_size) return false; - - uint8_t b3 = data[offset++]; - uint8_t b4 = data[offset++]; - uint8_t b5 = data[offset++]; - - S = (b2 << 24) | (b3 << 16) | (b4 << 8) | b5 ; - return true; -} - -bool FileListIO::saveEncryptedDataToFile(const std::string& fname,const unsigned char *data,uint32_t total_size) -{ - void *encryptedData = NULL ; - int encDataLen = 0 ; - - if(!AuthSSL::getAuthSSL()->encrypt( encryptedData, encDataLen, data,total_size, AuthSSL::getAuthSSL()->OwnId())) - { - std::cerr << "Cannot encrypt encrypted file. Something's wrong." << std::endl; - return false; - } - - FILE *F = fopen( (fname+".tmp").c_str(),"wb" ) ; - - if(!F) - { - std::cerr << "Cannot open encrypted file for writing: " << fname+".tmp" << std::endl; - - free(encryptedData); - return false; - } - if(fwrite(encryptedData,1,encDataLen,F) != (uint32_t)encDataLen) - { - std::cerr << "Could not write entire encrypted file. Out of disc space??" << std::endl; - fclose(F) ; - - free(encryptedData); - return false; - } - - fclose(F) ; - - RsDirUtil::renameFile(fname+".tmp",fname) ; -#ifdef FIM_DEBUG - std::cerr << "done." << std::endl ; -#endif - - free(encryptedData); - return true; -} - -bool FileListIO::loadEncryptedDataFromFile(const std::string& fname,unsigned char *& data,uint32_t& total_size) -{ - uint64_t file_size ; - - if(!RsDirUtil::checkFile( fname,file_size,true ) ) - { -#ifdef FIM_DEBUG - std::cerr << "Encrypted file " << fname << " not available or empty." << std::endl; -#endif - return false; - } - - // read the binary stream into memory. - // - RsTemporaryMemory buffer(file_size) ; - - if(buffer == NULL) - return false; - - FILE *F = fopen( fname.c_str(),"rb") ; - if (!F) - { - std::cerr << "Cannot open encrypted file, filename " << fname << std::endl; - return false; - } - if(fread(buffer,1,file_size,F) != file_size) - { - std::cerr << "Cannot read from file " + fname << ": something's wrong." << std::endl; - fclose(F) ; - return false; - } - fclose(F) ; - - // now decrypt - void *decrypted_data =NULL; - int decrypted_data_size =0; - - if(!AuthSSL::getAuthSSL()->decrypt(decrypted_data, decrypted_data_size, buffer, file_size)) - { - std::cerr << "Cannot decrypt encrypted file. Something's wrong." << std::endl; - return false; - } - - data = (unsigned char*)decrypted_data ; - total_size = decrypted_data_size ; - - return true; -} diff --git a/libretroshare/src/file_sharing/filelist_io.h b/libretroshare/src/file_sharing/filelist_io.h deleted file mode 100644 index 65863ffd0..000000000 --- a/libretroshare/src/file_sharing/filelist_io.h +++ /dev/null @@ -1,167 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: filelist_io.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 by Mr.Alice * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ -#pragma once - -#include -#include -#include - -#include "util/rsmemory.h" - -// This file implements load/save of various fields used for file lists and directory content. -// WARNING: the encoding is system-dependent, so this should *not* be used to exchange data between computers. - -static const uint32_t FILE_LIST_IO_LOCAL_DIRECTORY_STORAGE_VERSION_0001 = 0x00000001 ; -static const uint32_t FILE_LIST_IO_LOCAL_DIRECTORY_TREE_VERSION_0001 = 0x00010001 ; - -static const uint8_t FILE_LIST_IO_TAG_UNKNOWN = 0x00 ; -static const uint8_t FILE_LIST_IO_TAG_LOCAL_DIRECTORY_VERSION = 0x01 ; - -static const uint8_t FILE_LIST_IO_TAG_HASH_STORAGE_ENTRY = 0x10 ; -static const uint8_t FILE_LIST_IO_TAG_LOCAL_FILE_ENTRY = 0x11 ; -static const uint8_t FILE_LIST_IO_TAG_LOCAL_DIR_ENTRY = 0x12 ; -static const uint8_t FILE_LIST_IO_TAG_REMOTE_FILE_ENTRY = 0x13 ; - -static const uint8_t FILE_LIST_IO_TAG_FILE_SHA1_HASH = 0x20 ; -static const uint8_t FILE_LIST_IO_TAG_FILE_NAME = 0x21 ; -static const uint8_t FILE_LIST_IO_TAG_FILE_SIZE = 0x22 ; - -static const uint8_t FILE_LIST_IO_TAG_MODIF_TS = 0x30 ; -static const uint8_t FILE_LIST_IO_TAG_RECURS_MODIF_TS = 0x31 ; -static const uint8_t FILE_LIST_IO_TAG_UPDATE_TS = 0x32 ; - -static const uint8_t FILE_LIST_IO_TAG_ENTRY_INDEX = 0x40 ; -static const uint8_t FILE_LIST_IO_TAG_PARENT_INDEX = 0x41 ; - -static const uint8_t FILE_LIST_IO_TAG_DIR_HASH = 0x50 ; -static const uint8_t FILE_LIST_IO_TAG_DIR_NAME = 0x51 ; - -static const uint8_t FILE_LIST_IO_TAG_ROW = 0x60 ; -static const uint8_t FILE_LIST_IO_TAG_BINARY_DATA = 0x61 ; -static const uint8_t FILE_LIST_IO_TAG_RAW_NUMBER = 0x62 ; - -static const uint32_t SECTION_HEADER_MAX_SIZE = 6 ; // section tag (1 byte) + size (max = 5 bytes) - - -class FileListIO -{ -public: - template - static bool writeField(unsigned char *& buff,uint32_t& buff_size,uint32_t& offset,uint8_t section_tag,const T& val) - { - uint32_t s = serial_size(val) ; - - if(!checkSectionSize(buff,buff_size,offset,s)) - return false; - - if(!writeSectionHeader(buff,buff_size,offset,section_tag,s)) - return false; - - return serialise(buff,buff_size,offset,val) ; - } - - template - static bool readField(const unsigned char *buff,uint32_t buff_size,uint32_t& offset,uint8_t check_section_tag,T& val) - { - uint32_t section_size ; - - if(!readSectionHeader(buff,buff_size,offset,check_section_tag,section_size)) - return false; - - return deserialise(buff,buff_size,offset,val); - } - - class read_error - { - public: - read_error(unsigned char *sec,uint32_t size,uint32_t offset,uint8_t expected_tag); - read_error(const std::string& s) : err_string(s) {} - - const std::string& what() const { return err_string ; } - private: - std::string err_string ; - }; - - - static bool writeField( unsigned char*&buff,uint32_t& buff_size,uint32_t& offset,uint8_t section_tag,const unsigned char * val,uint32_t size) ; - static bool readField (const unsigned char *buff,uint32_t buff_size,uint32_t& offset,uint8_t check_section_tag, unsigned char *& val,uint32_t& size) ; - - template static bool serialise(unsigned char *buff,uint32_t size,uint32_t& offset,const T& val) ; - template static bool deserialise(const unsigned char *buff,uint32_t size,uint32_t& offset,T& val) ; - template static uint32_t serial_size(const T& val) ; - - static bool saveEncryptedDataToFile(const std::string& fname,const unsigned char *data,uint32_t total_size); - static bool loadEncryptedDataFromFile(const std::string& fname,unsigned char *& data,uint32_t& total_size); - -private: - static bool write125Size(unsigned char *data,uint32_t total_size,uint32_t& offset,uint32_t size) ; - static bool read125Size (const unsigned char *data,uint32_t total_size,uint32_t& offset,uint32_t& size) ; - - static bool checkSectionSize(unsigned char *& buff,uint32_t& buff_size,uint32_t offset,uint32_t S) - { - // This tests avoids an infinite loop when growing new size - - if(offset + S + SECTION_HEADER_MAX_SIZE > 0x8fffffff) - return false ; - - if(offset + S + SECTION_HEADER_MAX_SIZE > buff_size) - { - uint32_t new_size = (buff_size == 0)?512:buff_size ; - - while(new_size < offset + S + SECTION_HEADER_MAX_SIZE) - new_size <<= 1 ; - - buff = (unsigned char *)realloc(buff,new_size) ; - - if(!buff) - { - buff_size = 0 ; - return false ; - } - buff_size = new_size ; - } - return true ; - } - - static bool writeSectionHeader(unsigned char *& buff,uint32_t& buff_size,uint32_t& offset,uint8_t section_tag,uint32_t S) - { - buff[offset++] = section_tag ; - if(!write125Size(buff,buff_size,offset,S)) return false ; - - return true; - } - - static bool readSectionHeader(const unsigned char *& buff,uint32_t buff_size,uint32_t& offset,uint8_t check_section_tag,uint32_t& S) - { - if(offset + 1 > buff_size) - return false ; - - uint8_t section_tag = buff[offset] ; // we do the offset++ after, only if the header can be read. Doing so, we can make multiple read attempts. - - if(section_tag != check_section_tag) - return false; - - offset++ ; - - return read125Size(buff,buff_size,offset,S) ; - } -}; diff --git a/libretroshare/src/file_sharing/hash_cache.cc b/libretroshare/src/file_sharing/hash_cache.cc deleted file mode 100644 index 62924d70a..000000000 --- a/libretroshare/src/file_sharing/hash_cache.cc +++ /dev/null @@ -1,613 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: hash_cache.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 by Mr.Alice * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ -#include "util/rsdir.h" -#include "util/rsprint.h" -#include "util/rstime.h" -#include "rsserver/p3face.h" -#include "pqi/authssl.h" -#include "hash_cache.h" -#include "filelist_io.h" -#include "file_sharing_defaults.h" -#include "retroshare/rsinit.h" - -//#define HASHSTORAGE_DEBUG 1 - -static const uint32_t DEFAULT_INACTIVITY_SLEEP_TIME = 50*1000; -static const uint32_t MAX_INACTIVITY_SLEEP_TIME = 2*1000*1000; - -HashStorage::HashStorage(const std::string& save_file_name) - : mFilePath(save_file_name), mHashMtx("Hash Storage mutex") -{ - mInactivitySleepTime = DEFAULT_INACTIVITY_SLEEP_TIME; - mRunning = false ; - mLastSaveTime = 0 ; - mTotalSizeToHash = 0; - mTotalFilesToHash = 0; - mCurrentHashingSpeed = 0 ; - mMaxStorageDurationDays = DEFAULT_HASH_STORAGE_DURATION_DAYS ; - mHashingProcessPaused = false; - mHashedBytes = 0 ; - mHashingTime = 0 ; - - { - RS_STACK_MUTEX(mHashMtx) ; - - if(!locked_load()) - try_load_import_old_hash_cache(); - } -} - -void HashStorage::togglePauseHashingProcess() -{ - RS_STACK_MUTEX(mHashMtx) ; - mHashingProcessPaused = !mHashingProcessPaused ; -} -bool HashStorage::hashingProcessPaused() -{ - RS_STACK_MUTEX(mHashMtx) ; - return mHashingProcessPaused; -} - -static std::string friendlyUnit(uint64_t val) -{ - const std::string units[6] = {"B","KB","MB","GB","TB","PB"}; - char buf[50] ; - - double fact = 1.0 ; - - for(unsigned int i=0; i<6; ++i) - if(double(val)/fact < 1024.0) - { - sprintf(buf,"%2.2f",double(val)/fact) ; - return std::string(buf) + " " + units[i]; - } - else - fact *= 1024.0f ; - - sprintf(buf,"%2.2f",double(val)/fact*1024.0f) ; - return std::string(buf) + " TB"; -} - -void HashStorage::threadTick() -{ - FileHashJob job; - RsFileHash hash; - uint64_t size = 0; - - - { - bool empty ; - uint32_t st ; - - { - RS_STACK_MUTEX(mHashMtx) ; - - if(mChanged && mLastSaveTime + MIN_INTERVAL_BETWEEN_HASH_CACHE_SAVE < time(NULL)) - { - locked_save(); - mLastSaveTime = time(NULL) ; - mChanged = false ; - } - } - - { - RS_STACK_MUTEX(mHashMtx) ; - - empty = mFilesToHash.empty(); - st = mInactivitySleepTime ; - } - - // sleep off mutex! - if(empty) - { -#ifdef HASHSTORAGE_DEBUG - std::cerr << "nothing to hash. Sleeping for " << st << " us" << std::endl; -#endif - - rstime::rs_usleep(st); // when no files to hash, just wait for 2 secs. This avoids a dramatic loop. - - if(st > MAX_INACTIVITY_SLEEP_TIME) - { - RS_STACK_MUTEX(mHashMtx) ; - - mInactivitySleepTime = MAX_INACTIVITY_SLEEP_TIME; - - if(!mChanged) // otherwise it might prevent from saving the hash cache - { - stopHashThread(); - } - - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mEventCode = RsSharedDirectoriesEventCode::DIRECTORY_SWEEP_ENDED; - rsEvents->postEvent(ev); - } - //RsServer::notify()->notifyHashingInfo(NOTIFY_HASHTYPE_FINISH, "") ; - } - else - { - RS_STACK_MUTEX(mHashMtx) ; - mInactivitySleepTime = 2*st ; - } - - return ; - } - mInactivitySleepTime = DEFAULT_INACTIVITY_SLEEP_TIME; - - bool paused = false ; - { - RS_STACK_MUTEX(mHashMtx) ; - paused = mHashingProcessPaused ; - } - - if(paused) // we need to wait off mutex!! - { - rstime::rs_usleep(MAX_INACTIVITY_SLEEP_TIME) ; - std::cerr << "Hashing process currently paused." << std::endl; - return; - } - else - { - RS_STACK_MUTEX(mHashMtx) ; - - job = mFilesToHash.begin()->second ; - mFilesToHash.erase(mFilesToHash.begin()) ; - } - - if(job.client->hash_confirm(job.client_param)) - { -#ifdef HASHSTORAGE_DEBUG - std::cerr << "Hashing file " << job.full_path << "..." ; std::cerr.flush(); -#endif - - std::string tmpout; - - if(mCurrentHashingSpeed > 0) - rs_sprintf(tmpout, "%lu/%lu (%s - %d%%, %d MB/s) : %s", (unsigned long int)mHashCounter+1, (unsigned long int)mTotalFilesToHash, friendlyUnit(mTotalHashedSize).c_str(), int(mTotalHashedSize/double(mTotalSizeToHash)*100.0), mCurrentHashingSpeed,job.full_path.c_str()) ; - else - rs_sprintf(tmpout, "%lu/%lu (%s - %d%%) : %s", (unsigned long int)mHashCounter+1, (unsigned long int)mTotalFilesToHash, friendlyUnit(mTotalHashedSize).c_str(), int(mTotalHashedSize/double(mTotalSizeToHash)*100.0), job.full_path.c_str()) ; - - { - /* Emit deprecated event only for retrocompatibility - * TODO: create a proper event with structured data instead of a - * formatted string */ - auto ev = std::make_shared(); - ev->mEventCode = RsSharedDirectoriesEventCode::HASHING_FILE; - ev->mMessage = tmpout; - rsEvents->postEvent(ev); - } - - double seconds_origin = rstime::RsScopeTimer::currentTime() ; - - if(RsDirUtil::getFileHash(job.full_path, hash, size, this)) - { - // store the result - -#ifdef HASHSTORAGE_DEBUG - std::cerr << "done."<< std::endl; -#endif - - RS_STACK_MUTEX(mHashMtx) ; - HashStorageInfo& info(mFiles[job.real_path]); - - info.filename = job.real_path ; - info.size = size ; - info.modf_stamp = job.ts ; - info.time_stamp = time(NULL); - info.hash = hash; - - mChanged = true ; - mTotalHashedSize += size ; - } - else RS_ERR("Failure hashing file: ", job.full_path); - - mHashingTime += rstime::RsScopeTimer::currentTime() - seconds_origin ; - mHashedBytes += size ; - - if(mHashingTime > 3) - { - mCurrentHashingSpeed = (int)(mHashedBytes / mHashingTime ) / (1024*1024) ; - mHashingTime = 0 ; - mHashedBytes = 0 ; - } - - ++mHashCounter ; - } - } - - // call the client - if(!hash.isNull()) - job.client->hash_callback(job.client_param, job.full_path, hash, size); - - /* Notify we completed hashing a file */ - auto ev = std::make_shared(); - ev->mFilePath = job.full_path; - ev->mHashingSpeed = mCurrentHashingSpeed; - ev->mFileHash = hash; - rsEvents->postEvent(ev); -} - -bool HashStorage::requestHash(const std::string& full_path,uint64_t size,rstime_t mod_time,RsFileHash& known_hash,HashStorageClient *c,uint32_t client_param) -{ - // check if the hash is up to date w.r.t. cache. - -#ifdef HASHSTORAGE_DEBUG - std::cerr << "HASH Requested for file " << full_path << ": mod_time: " << mod_time << ", size: " << size << " :" ; -#endif - RS_STACK_MUTEX(mHashMtx) ; - - std::string real_path = RsDirUtil::removeSymLinks(full_path) ; - - rstime_t now = time(NULL) ; - std::map::iterator it = mFiles.find(real_path) ; - - // On windows we compare the time up to +/- 3600 seconds. This avoids re-hashing files in case of daylight saving change. - // - // See: - // https://support.microsoft.com/en-us/kb/190315 - // - if(it != mFiles.end() -#ifdef WINDOWS_SYS - && ( (uint64_t)mod_time == it->second.modf_stamp || (uint64_t)mod_time+3600 == it->second.modf_stamp ||(uint64_t)mod_time == it->second.modf_stamp+3600) -#else - && (uint64_t)mod_time == it->second.modf_stamp -#endif - && size == it->second.size) - { - it->second.time_stamp = now ; - -#ifdef WINDOWS_SYS - if(it->second.modf_stamp != (uint64_t)mod_time) - { - std::cerr << "(WW) detected a 1 hour shift in file modification time. This normally happens to many files at once, when daylight saving time shifts (file=\"" << full_path << "\")." << std::endl; - it->second.modf_stamp = (uint64_t)mod_time; - mChanged = true; - startHashThread(); - } -#endif - - known_hash = it->second.hash; -#ifdef HASHSTORAGE_DEBUG - std::cerr << "Found in cache." << std::endl ; -#endif - return true ; - } -#ifdef HASHSTORAGE_DEBUG - std::cerr << "Not in cache. Scheduling for re-hash." << std::endl ; -#endif - - // we need to schedule a re-hashing - - if(mFilesToHash.find(real_path) != mFilesToHash.end()) - return false ; - - FileHashJob job ; - - job.client = c ; - job.size = size ; - job.client_param = client_param ; - job.full_path = full_path ; - job.real_path = real_path ; - job.ts = mod_time ; - - // We store the files indexed by their real path, so that we allow to not re-hash files that are pointed multiple times through the directory links - // The client will be notified with the full path instead of the real path. - - mFilesToHash[real_path] = job; - - mTotalSizeToHash += size ; - ++mTotalFilesToHash; - - startHashThread(); - - return false; -} - -void HashStorage::startHashThread() -{ - if(!mRunning) - { - mRunning = true ; - std::cerr << "Starting hashing thread." << std::endl; - mHashCounter = 0; - mTotalHashedSize = 0; - - start("fs hash cache") ; - } -} - -void HashStorage::stopHashThread() -{ - if(mRunning) - { - RsInfo() << __PRETTY_FUNCTION__ << "Stopping hashing thread." - << std::endl; - - RsThread::askForStop(); - mRunning = false ; - mTotalSizeToHash = 0; - mTotalFilesToHash = 0; - } -} - -void HashStorage::clean() -{ - RS_STACK_MUTEX(mHashMtx) ; - - rstime_t now = time(NULL) ; - rstime_t duration = mMaxStorageDurationDays * 24 * 3600 ; // seconds - -#ifdef HASHSTORAGE_DEBUG - std::cerr << "Cleaning hash cache." << std::endl ; -#endif - - for(std::map::iterator it(mFiles.begin());it!=mFiles.end();) - if((uint64_t)(it->second.time_stamp + duration) < (uint64_t)now) - { -#ifdef HASHSTORAGE_DEBUG - std::cerr << " Entry too old: " << it->first << ", ts=" << it->second.time_stamp << std::endl ; -#endif - std::map::iterator tmp(it) ; - ++tmp ; - mFiles.erase(it) ; - it=tmp ; - mChanged = true ; - } - else - ++it ; - -#ifdef HASHSTORAGE_DEBUG - std::cerr << "Done." << std::endl; -#endif -} - -bool HashStorage::locked_load() -{ - unsigned char *data = NULL ; - uint32_t data_size=0; - - if(!FileListIO::loadEncryptedDataFromFile(mFilePath,data,data_size)) - { - std::cerr << "(EE) Cannot read hash cache." << std::endl; - return false; - } - uint32_t offset = 0 ; - HashStorageInfo info ; -#ifdef HASHSTORAGE_DEBUG - uint32_t n=0; -#endif - - while(offset < data_size) - if(readHashStorageInfo(data,data_size,offset,info)) - { -#ifdef HASHSTORAGE_DEBUG - std::cerr << info << std::endl; - ++n ; -#endif - mFiles[info.filename] = info ; - } - - free(data) ; -#ifdef HASHSTORAGE_DEBUG - std::cerr << n << " entries loaded." << std::endl ; -#endif - return true ; -} - -void HashStorage::locked_save() -{ -#ifdef HASHSTORAGE_DEBUG - std::cerr << "Saving Hash Cache to file " << mFilePath << "..." << std::endl ; -#endif - - unsigned char *data = NULL ; - uint32_t offset = 0 ; - uint32_t total_size = 0; - - for(std::map::const_iterator it(mFiles.begin());it!=mFiles.end();++it) - writeHashStorageInfo(data,total_size,offset,it->second) ; - - if(!FileListIO::saveEncryptedDataToFile(mFilePath,data,offset)) - { - std::cerr << "(EE) Cannot save hash cache data." << std::endl; - free(data) ; - return ; - } - - std::cerr << mFiles.size() << " entries saved in hash cache." << std::endl; - - free(data) ; -} - -bool HashStorage::readHashStorageInfo(const unsigned char *data,uint32_t total_size,uint32_t& offset,HashStorageInfo& info) const -{ - unsigned char *section_data = (unsigned char *)rs_malloc(FL_BASE_TMP_SECTION_SIZE) ; - - if(!section_data) - return false ; - - uint32_t section_size = FL_BASE_TMP_SECTION_SIZE; - uint32_t section_offset = 0; - - // This way, the entire section is either read or skipped. That avoids the risk of being stuck somewhere in the middle - // of a section because of some unknown field, etc. - - if(!FileListIO::readField(data,total_size,offset,FILE_LIST_IO_TAG_HASH_STORAGE_ENTRY,section_data,section_size)) - { - free(section_data); - return false; - } - - if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_FILE_NAME ,info.filename )) { free(section_data); return false ; } - if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_FILE_SIZE ,info.size )) { free(section_data); return false ; } - if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_UPDATE_TS ,info.time_stamp)) { free(section_data); return false ; } - if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_MODIF_TS ,info.modf_stamp)) { free(section_data); return false ; } - if(!FileListIO::readField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_FILE_SHA1_HASH,info.hash )) { free(section_data); return false ; } - - free(section_data); - return true; -} - -bool HashStorage::writeHashStorageInfo(unsigned char *& data,uint32_t& total_size,uint32_t& offset,const HashStorageInfo& info) const -{ - unsigned char *section_data = (unsigned char *)rs_malloc(FL_BASE_TMP_SECTION_SIZE) ; - - if(!section_data) - return false ; - - uint32_t section_offset = 0 ; - uint32_t section_size = FL_BASE_TMP_SECTION_SIZE; - - if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_FILE_NAME ,info.filename )) { free(section_data); return false ; } - if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_FILE_SIZE ,info.size )) { free(section_data); return false ; } - if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_UPDATE_TS ,info.time_stamp)) { free(section_data); return false ; } - if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_MODIF_TS ,info.modf_stamp)) { free(section_data); return false ; } - if(!FileListIO::writeField(section_data,section_size,section_offset,FILE_LIST_IO_TAG_FILE_SHA1_HASH,info.hash )) { free(section_data); return false ; } - - // now write the whole string into a single section in the file - - if(!FileListIO::writeField(data,total_size,offset,FILE_LIST_IO_TAG_HASH_STORAGE_ENTRY,section_data,section_offset)) return false ; -#ifdef HASHSTORAGE_DEBUG - std::cerr << "Writing hash storage section " << RsUtil::BinToHex(section_data,section_offset) << std::endl; - std::cerr << "Info.filename = " << info.filename << std::endl; -#endif - free(section_data) ; - - return true; -} - -std::ostream& operator<<(std::ostream& o,const HashStorage::HashStorageInfo& info) -{ - return o << info.hash << " " << info.modf_stamp << " " << info.size << " " << info.filename ; -} - -/********************************************************************************************************************************/ -/* 09/26/2016 */ -/* This method should be removed in a few months. It only helps importing the old hash cache in order to */ -/* spare the re-hashing of everything. If successful, it also renames the old hash cache into a new name so that */ -/* the file is not found at the next attempt. */ -/********************************************************************************************************************************/ -// -#include "rsserver/rsaccounts.h" -#include - -bool HashStorage::try_load_import_old_hash_cache() -{ - // compute file name - - std::string base_dir = RsAccounts::AccountDirectory(); - std::string old_cache_filename = base_dir + "/" + "file_cache.bin" ; - - // check for unencrypted - - std::istream *f = NULL ; - uint64_t file_size ; - - if(RsDirUtil::checkFile( old_cache_filename,file_size,false ) ) - { - std::cerr << "Encrypted hash cache file present. Reading it." << std::endl; - - // read the binary stream into memory. - // - RsTemporaryMemory buffer(file_size) ; - - if(buffer == NULL) - return false; - - FILE *F = fopen( old_cache_filename.c_str(),"rb") ; - if (!F) - { - std::cerr << "Cannot open file for reading encrypted file cache, filename " << old_cache_filename << std::endl; - return false; - } - if(fread(buffer,1,file_size,F) != file_size) - { - std::cerr << "Cannot read from file " << old_cache_filename << ": something's wrong." << std::endl; - fclose(F) ; - return false; - } - fclose(F) ; - - void *decrypted_data =NULL; - int decrypted_data_size =0; - - if(!AuthSSL::getAuthSSL()->decrypt(decrypted_data, decrypted_data_size, buffer, file_size)) - { - std::cerr << "Cannot decrypt encrypted file cache. Something's wrong." << std::endl; - return false; - } - std::string s((char *)decrypted_data,decrypted_data_size) ; - f = new std::istringstream(s) ; - - free(decrypted_data) ; - } - else - return false; - - std::streamsize max_line_size = 2000 ; // should be enough. Anyway, if we - // miss one entry, we just lose some - // cache itemsn but this is not too - // much of a problem. - char *buff = new char[max_line_size] ; - - std::cerr << "Importing hashCache from file " << old_cache_filename << std::endl ; - int n=0 ; - - std::map tmp_files ; // stored as (full_path, hash_info) - - while(!f->eof()) - { - HashStorageInfo info ; - - f->getline(buff,max_line_size,'\n') ; - info.filename = std::string(buff) ; - - f->getline(buff,max_line_size,'\n') ; //if(sscanf(buff,"%llu",&info.size) != 1) break ; - - info.size = 0 ; - sscanf(buff, RsDirUtil::scanf_string_for_uint(sizeof(info.size)), &info.size); - - f->getline(buff,max_line_size,'\n') ; if(sscanf(buff,RsDirUtil::scanf_string_for_uint(sizeof(info.time_stamp)),&info.time_stamp) != 1) { std::cerr << "Could not read one entry! Giving up." << std::endl; break ; } - f->getline(buff,max_line_size,'\n') ; if(sscanf(buff,RsDirUtil::scanf_string_for_uint(sizeof(info.modf_stamp)),&info.modf_stamp) != 1) { std::cerr << "Could not read one entry! Giving up." << std::endl; break ; } - f->getline(buff,max_line_size,'\n') ; info.hash = RsFileHash(std::string(buff)) ; - - std::cerr << " (" << info.filename << ", " << info.size << ", " << info.time_stamp << ", " << info.modf_stamp << ", " << info.hash << std::endl ; - ++n ; - - tmp_files[info.filename] = info ; - } - - delete[] buff ; - delete f ; - - std::cerr << "(II) Successfully imported hash cache from file " << old_cache_filename << " for a total of " << n << " entries." << std::endl; - std::cerr << "(II) This file is now obsolete, and will be renamed " << old_cache_filename + ".bak" << " in case you needed it. But you can safely remove it." << std::endl; - - RsDirUtil::renameFile(old_cache_filename,old_cache_filename+".bak") ; - - mFiles = tmp_files ; - locked_save() ; // this is called explicitly here because the ticking thread is not active. - - return true; -} -/********************************************************************************************************************************/ diff --git a/libretroshare/src/file_sharing/hash_cache.h b/libretroshare/src/file_sharing/hash_cache.h deleted file mode 100644 index 6fbb9ae5c..000000000 --- a/libretroshare/src/file_sharing/hash_cache.h +++ /dev/null @@ -1,149 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: hash_cache.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 by Mr.Alice * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ - - -#pragma once - -#include -#include "util/rsthreads.h" -#include "retroshare/rsfiles.h" -#include "util/rstime.h" - -/*! - * \brief The HashStorageClient class - * Used by clients of the hash cache for receiving hash results when done. This is asynchrone of course since hashing - * might be quite costly. - */ -class HashStorageClient -{ -public: - HashStorageClient() {} - virtual ~HashStorageClient() {} - - // the result of the hashing info is sent to this method - - virtual void hash_callback(uint32_t client_param, const std::string& name, const RsFileHash& hash, uint64_t size)=0; - - // this method is used to check that the client param is still valid just before hashing. This avoids hashing files - // that are still in queue while removed from shared lists. - - virtual bool hash_confirm(uint32_t client_param)=0 ; -}; - -class HashStorage: public RsTickingThread -{ -public: - explicit HashStorage(const std::string& save_file_name) ; - - /*! - * \brief requestHash Requests the hash for the given file, assuming size and mod_time are the same. - * - * \param full_path Full path to reach the file - * \param size Actual file size - * \param mod_time Actual file modification time - * \param known_hash Returned hash for the file. - * \param c Hash cache client to which the hash should be sent once calculated - * \param client_param Param to be passed to the client callback. Useful if the client needs a file ID. - * - * \return true if the supplied hash info is up to date. - */ - bool requestHash(const std::string& full_path, uint64_t size, rstime_t mod_time, RsFileHash& known_hash, HashStorageClient *c, uint32_t client_param) ; - - struct HashStorageInfo - { - std::string filename ; // full path of the file - uint64_t size ; - uint32_t time_stamp ; // last time the hash was tested/requested - uint32_t modf_stamp ; - RsFileHash hash ; - } ; - - // interaction with GUI, called from p3FileLists - void setRememberHashFilesDuration(uint32_t days) { mMaxStorageDurationDays = days ; } // duration for which the hash is kept even if the file is not shared anymore - uint32_t rememberHashFilesDuration() const { return mMaxStorageDurationDays ; } - void clear() { mFiles.clear(); mChanged=true; } // drop all known hashes. Not something to do, except if you want to rehash the entire database - bool empty() const { return mFiles.empty() ; } - void togglePauseHashingProcess() ; - bool hashingProcessPaused(); - - void threadTick() override; /// @see RsTickingThread - - friend std::ostream& operator<<(std::ostream& o,const HashStorageInfo& info) ; -private: - /*! - * \brief clean - * This function is responsible for removing old hashes, etc - */ - void clean() ; - - void startHashThread(); - void stopHashThread(); - - // loading/saving the entire hash database to a file - - void locked_save() ; - bool locked_load() ; - bool try_load_import_old_hash_cache(); - - bool readHashStorageInfo(const unsigned char *data,uint32_t total_size,uint32_t& offset,HashStorageInfo& info) const; - bool writeHashStorageInfo(unsigned char *& data,uint32_t& total_size,uint32_t& offset,const HashStorageInfo& info) const; - - // Local configuration and storage - - uint32_t mMaxStorageDurationDays ; // maximum duration of un-requested cache entries - std::map mFiles ; // stored as (full_path, hash_info) - std::string mFilePath ; // file where the hash database is stored - bool mChanged ; - bool mHashingProcessPaused ; - - struct FileHashJob - { - std::string full_path; // canonicalized file name (means: symlinks removed, loops removed, etc) - std::string real_path; // path supplied by the client. - uint64_t size ; - HashStorageClient *client; - uint32_t client_param ; - rstime_t ts; - }; - - // current work - - std::map mFilesToHash ; - - // thread/mutex stuff - - RsMutex mHashMtx ; - bool mRunning; - uint64_t mHashCounter; - uint32_t mInactivitySleepTime ; - uint64_t mTotalSizeToHash ; - uint64_t mTotalHashedSize ; - uint64_t mTotalFilesToHash ; - rstime_t mLastSaveTime ; - - // The following is used to estimate hashing speed. - - double mHashingTime ; - uint64_t mHashedBytes ; - uint32_t mCurrentHashingSpeed ; // in MB/s -}; - diff --git a/libretroshare/src/file_sharing/p3filelists.cc b/libretroshare/src/file_sharing/p3filelists.cc deleted file mode 100644 index 419196275..000000000 --- a/libretroshare/src/file_sharing/p3filelists.cc +++ /dev/null @@ -1,2331 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: p3filelists.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2018 Mr.Alice * - * Copyright (C) 2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ -#include "rsitems/rsserviceids.h" - -#include "file_sharing/p3filelists.h" -#include "file_sharing/directory_storage.h" -#include "file_sharing/directory_updater.h" -#include "file_sharing/rsfilelistitems.h" -#include "file_sharing/file_sharing_defaults.h" - -#include "retroshare/rsids.h" -#include "retroshare/rspeers.h" -#include "retroshare/rsinit.h" -#include "util/cxx17retrocompat.h" -#include "rsserver/p3face.h" - -#define P3FILELISTS_DEBUG() std::cerr << time(NULL) << " : FILE_LISTS : " << __FUNCTION__ << " : " -#define P3FILELISTS_ERROR() std::cerr << "***ERROR***" << " : FILE_LISTS : " << __FUNCTION__ << " : " - -//#define DEBUG_P3FILELISTS 1 -//#define DEBUG_CONTENT_FILTERING 1 -//#define DEBUG_FILE_HIERARCHY 1 - -static const uint32_t P3FILELISTS_UPDATE_FLAG_NOTHING_CHANGED = 0x0000 ; -static const uint32_t P3FILELISTS_UPDATE_FLAG_REMOTE_MAP_CHANGED = 0x0001 ; -static const uint32_t P3FILELISTS_UPDATE_FLAG_LOCAL_DIRS_CHANGED = 0x0002 ; -static const uint32_t P3FILELISTS_UPDATE_FLAG_REMOTE_DIRS_CHANGED = 0x0004 ; - -p3FileDatabase::p3FileDatabase(p3ServiceControl *mpeers) - : mServCtrl(mpeers), mFLSMtx("p3FileLists") -{ - // make sure the base directory exists - - std::string base_dir = RsAccounts::AccountDirectory(); - - if(base_dir.empty()) - throw std::runtime_error("Cannot create base directory to store/access file sharing files.") ; - - mFileSharingDir = base_dir + "/" + FILE_SHARING_DIR_NAME ; - - if(!RsDirUtil::checkCreateDirectory(mFileSharingDir)) - throw std::runtime_error("Cannot create base directory to store/access file sharing files.") ; - - // loads existing indexes for friends. Some might be already present here. - // - mRemoteDirectories.clear() ; // we should load them! - mOwnId = mpeers->getOwnId() ; - - mBannedFileListNeedsUpdate = false; - mLocalSharedDirs = new LocalDirectoryStorage(mFileSharingDir + "/" + LOCAL_SHARED_DIRS_FILE_NAME,mOwnId); - mHashCache = new HashStorage(mFileSharingDir + "/" + HASH_CACHE_FILE_NAME) ; - - mLocalDirWatcher = new LocalDirectoryUpdater(mHashCache,mLocalSharedDirs) ; - - mUpdateFlags = P3FILELISTS_UPDATE_FLAG_NOTHING_CHANGED ; - mLastRemoteDirSweepTS = 0 ; - mLastExtraFilesCacheUpdate = 0; - mLastCleanupTime = 0 ; - mLastDataRecvTS = 0 ; - mTrustFriendNodesForBannedFiles = TRUST_FRIEND_NODES_FOR_BANNED_FILES_DEFAULT; - mLastPrimaryBanListChangeTimeStamp = 0; - - // This is for the transmission of data - - addSerialType(new RsFileListsSerialiser()) ; -} - -void p3FileDatabase::setIgnoreLists(const std::list& ignored_prefixes,const std::list& ignored_suffixes, uint32_t ignore_flags) -{ - RS_STACK_MUTEX(mFLSMtx) ; - mLocalDirWatcher->setIgnoreLists(ignored_prefixes,ignored_suffixes,ignore_flags) ; - - IndicateConfigChanged(); -} -bool p3FileDatabase::getIgnoreLists(std::list& ignored_prefixes,std::list& ignored_suffixes, uint32_t& ignore_flags) -{ - RS_STACK_MUTEX(mFLSMtx) ; - return mLocalDirWatcher->getIgnoreLists(ignored_prefixes,ignored_suffixes,ignore_flags) ; -} - -RsSerialiser *p3FileDatabase::setupSerialiser() -{ - // This one is for saveList/loadList - - RsSerialiser *rss = new RsSerialiser ; - rss->addSerialType(new RsFileListsSerialiser()) ; - rss->addSerialType(new RsGeneralConfigSerialiser()); - rss->addSerialType(new RsFileConfigSerialiser()); - - return rss ; -} -void p3FileDatabase::setSharedDirectories(const std::list& shared_dirs) -{ - { - RS_STACK_MUTEX(mFLSMtx) ; - - mLocalSharedDirs->setSharedDirectoryList(shared_dirs) ; - mLocalDirWatcher->forceUpdate(false); - - } - - IndicateConfigChanged(); -} -void p3FileDatabase::getSharedDirectories(std::list& shared_dirs) -{ - RS_STACK_MUTEX(mFLSMtx) ; - mLocalSharedDirs->getSharedDirectoryList(shared_dirs) ; -} -void p3FileDatabase::updateShareFlags(const SharedDirInfo& info) -{ - { - RS_STACK_MUTEX(mFLSMtx) ; - mLocalSharedDirs->updateShareFlags(info) ; - } - - RsServer::notify()->notifyListChange(NOTIFY_LIST_DIRLIST_LOCAL, 0); - IndicateConfigChanged(); -} - -p3FileDatabase::~p3FileDatabase() -{ - RS_STACK_MUTEX(mFLSMtx) ; - - for(uint32_t i=0;iprint(); -#endif - last_print_time = now ; - } - -#warning mr-alice 2016-08-19: "This should be removed, but it's necessary atm for updating the GUI" - RsServer::notify()->notifyListChange(NOTIFY_LIST_DIRLIST_LOCAL, 0); - - checkSendBannedFilesInfo(); - } - - if(mUpdateFlags) - { - IndicateConfigChanged(); - - if(mUpdateFlags & P3FILELISTS_UPDATE_FLAG_LOCAL_DIRS_CHANGED) - RsServer::notify()->notifyListChange(NOTIFY_LIST_DIRLIST_LOCAL, 0); - - if(mUpdateFlags & P3FILELISTS_UPDATE_FLAG_REMOTE_DIRS_CHANGED) - RsServer::notify()->notifyListChange(NOTIFY_LIST_DIRLIST_FRIENDS, 0); - - mUpdateFlags = P3FILELISTS_UPDATE_FLAG_NOTHING_CHANGED ; - } - - if(mLastRemoteDirSweepTS + 5 < now) - { - RS_STACK_MUTEX(mFLSMtx) ; - - std::set online_peers ; - mServCtrl->getPeersConnected(getServiceInfo().mServiceType, online_peers) ; - - for(uint32_t i=0;ipeerId()) != online_peers.end() && mRemoteDirectories[i]->lastSweepTime() + DELAY_BETWEEN_REMOTE_DIRECTORIES_SWEEP < now) - { -#ifdef DEBUG_FILE_HIERARCHY - P3FILELISTS_DEBUG() << "Launching recurs sweep of friend directory " << mRemoteDirectories[i]->peerId() << ". Content currently is:" << std::endl; - mRemoteDirectories[i]->print(); -#endif - - locked_recursSweepRemoteDirectory(mRemoteDirectories[i],mRemoteDirectories[i]->root(),0) ; - mRemoteDirectories[i]->lastSweepTime() = now ; - } - - mRemoteDirectories[i]->checkSave() ; - } - - mLastRemoteDirSweepTS = now; - mLocalSharedDirs->checkSave() ; - - // This is a hack to make loaded directories show up in the GUI, because the GUI generally isn't ready at the time they are actually loaded up, - // so the first notify is ignored, and no other notify will happen next. We only do it if no data was received in the last 5 secs, in order to - // avoid syncing the GUI at every dir sync which kills performance. - - if(mLastDataRecvTS + 5 < now && mLastDataRecvTS + 20 > now) - RsServer::notify()->notifyListChange(NOTIFY_LIST_DIRLIST_FRIENDS, 0); // notify the GUI if the hierarchy has changed - } - - return 0; -} - -void p3FileDatabase::startThreads() -{ - RS_STACK_MUTEX(mFLSMtx) ; -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Starting directory watcher thread..." ; -#endif - mLocalDirWatcher->start("fs dir watcher"); -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Done." << std::endl; -#endif -} -void p3FileDatabase::stopThreads() -{ - RS_STACK_MUTEX(mFLSMtx) ; -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Stopping hash cache thread..." ; std::cerr.flush() ; -#endif - mHashCache->fullstop(); -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Done." << std::endl; - P3FILELISTS_DEBUG() << "Stopping directory watcher thread..." ; std::cerr.flush() ; -#endif - mLocalDirWatcher->fullstop(); -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Done." << std::endl; -#endif -} - -bool p3FileDatabase::saveList(bool &cleanup, std::list& sList) -{ -cleanup = true; - -#ifdef DEBUG_FILE_HIERARCHY - P3FILELISTS_DEBUG() << "Save list" << std::endl; -#endif - - /* get list of directories */ - std::list dirList; - { - RS_STACK_MUTEX(mFLSMtx) ; - mLocalSharedDirs->getSharedDirectoryList(dirList); - } - - { - RS_STACK_MUTEX(mFLSMtx) ; - for(std::list::iterator it = dirList.begin(); it != dirList.end(); ++it) - { - RsFileConfigItem *fi = new RsFileConfigItem(); - - fi->file.path = (*it).filename ; - fi->file.name = (*it).virtualname ; - fi->flags = (*it).shareflags.toUInt32() ; - - for(std::list::const_iterator it2( (*it).parent_groups.begin());it2!=(*it).parent_groups.end();++it2) - fi->parent_groups.ids.insert(*it2) ; - - sList.push_back(fi); - } - } - - { - RS_STACK_MUTEX(mFLSMtx) ; - - RsFileListsBannedHashesConfigItem *item = new RsFileListsBannedHashesConfigItem ; - - item->primary_banned_files_list = mPrimaryBanList; - sList.push_back(item) ; - } - - RsConfigKeyValueSet *rskv = new RsConfigKeyValueSet(); - - /* basic control parameters */ - { - RS_STACK_MUTEX(mFLSMtx) ; - std::string s ; - rs_sprintf(s, "%lu", mHashCache->rememberHashFilesDuration()) ; - - RsTlvKeyValue kv; - - kv.key = HASH_CACHE_DURATION_SS; - kv.value = s ; - - rskv->tlvkvs.pairs.push_back(kv); - } - - { - std::string s ; - rs_sprintf(s, "%d", watchPeriod()) ; - - RsTlvKeyValue kv; - - kv.key = WATCH_FILE_DURATION_SS; - kv.value = s ; - - rskv->tlvkvs.pairs.push_back(kv); - } - { - std::string s ; - rs_sprintf(s, "%d", maxShareDepth()) ; - - RsTlvKeyValue kv; - - kv.key = MAX_SHARE_DEPTH; - kv.value = s ; - - rskv->tlvkvs.pairs.push_back(kv); - } - { - RsTlvKeyValue kv; - - kv.key = FOLLOW_SYMLINKS_SS; - kv.value = followSymLinks()?"YES":"NO" ; - - rskv->tlvkvs.pairs.push_back(kv); - } - { - RsTlvKeyValue kv; - - kv.key = IGNORE_DUPLICATES; - kv.value = ignoreDuplicates()?"YES":"NO" ; - - rskv->tlvkvs.pairs.push_back(kv); - } - { - RsTlvKeyValue kv; - - kv.key = WATCH_FILE_ENABLED_SS; - kv.value = watchEnabled()?"YES":"NO" ; - - rskv->tlvkvs.pairs.push_back(kv); - } - { - RsTlvKeyValue kv; - - kv.key = TRUST_FRIEND_NODES_FOR_BANNED_FILES_SS; - kv.value = trustFriendNodesForBannedFiles()?"YES":"NO" ; - - rskv->tlvkvs.pairs.push_back(kv); - } - { - RsTlvKeyValue kv; - - kv.key = WATCH_HASH_SALT_SS; - kv.value = mLocalDirWatcher->hashSalt().toStdString(); - - rskv->tlvkvs.pairs.push_back(kv); - } - { - std::list prefix_list,suffix_list; - uint32_t flags ; - - mLocalDirWatcher->getIgnoreLists(prefix_list,suffix_list,flags) ; - - std::string prefix_string, suffix_string ; - - for(auto it(prefix_list.begin());it!=prefix_list.end();++it) prefix_string += *it + ";" ; - for(auto it(suffix_list.begin());it!=suffix_list.end();++it) suffix_string += *it + ";" ; - - RsTlvKeyValue kv; - - kv.key = IGNORED_PREFIXES_SS; kv.value = prefix_string; rskv->tlvkvs.pairs.push_back(kv); - kv.key = IGNORED_SUFFIXES_SS; kv.value = suffix_string; rskv->tlvkvs.pairs.push_back(kv); - - std::string s ; - rs_sprintf(s, "%lu", flags) ; - - kv.key = IGNORE_LIST_FLAGS_SS; kv.value = s; rskv->tlvkvs.pairs.push_back(kv); - } - - /* Add KeyValue to saveList */ - sList.push_back(rskv); - - return true; -} - -bool p3FileDatabase::loadList(std::list& load) -{ - /* for each item, check it exists .... - * - remove any that are dead (or flag?) - */ - static const FileStorageFlags PERMISSION_MASK = DIR_FLAGS_PERMISSIONS_MASK; - -#ifdef DEBUG_FILE_HIERARCHY - P3FILELISTS_DEBUG() << "Load list" << std::endl; -#endif - - std::list dirList; - std::list ignored_prefixes,ignored_suffixes ; - uint32_t ignore_flags = RS_FILE_SHARE_FLAGS_IGNORE_PREFIXES | RS_FILE_SHARE_FLAGS_IGNORE_SUFFIXES ; - uint32_t max_share_depth = 0; - - // OS-dependent default ignore lists -#ifdef WINDOWS_SYS - ignored_suffixes.push_back( ".bak" ); -#else - ignored_prefixes.push_back( "." ); - ignored_suffixes.push_back( "~" ); - ignored_suffixes.push_back( ".part" ); -#endif - - for(std::list::iterator it = load.begin(); it != load.end(); ++it) - { - RsConfigKeyValueSet *rskv ; - - if (NULL != (rskv = dynamic_cast(*it))) - { - /* make into map */ - //std::map configMap; - //std::map::const_iterator mit ; - - for(std::list::const_iterator kit = rskv->tlvkvs.pairs.begin(); kit != rskv->tlvkvs.pairs.end(); ++kit) - if (kit->key == HASH_CACHE_DURATION_SS) - { - uint32_t t=0 ; - if(sscanf(kit->value.c_str(),"%u",&t) == 1) - mHashCache->setRememberHashFilesDuration(t); - } - else if(kit->key == WATCH_FILE_DURATION_SS) - { - int t=0 ; - if(sscanf(kit->value.c_str(),"%d",&t) == 1) - setWatchPeriod(t); - } - else if(kit->key == FOLLOW_SYMLINKS_SS) - { - setFollowSymLinks(kit->value == "YES") ; - } - else if(kit->key == IGNORE_DUPLICATES) - { - setIgnoreDuplicates(kit->value == "YES") ; - } - else if(kit->key == WATCH_FILE_ENABLED_SS) - { - setWatchEnabled(kit->value == "YES") ; - } - else if(kit->key == TRUST_FRIEND_NODES_FOR_BANNED_FILES_SS) - { - setTrustFriendNodesForBannedFiles(kit->value == "YES") ; - } - else if(kit->key == WATCH_HASH_SALT_SS) - { - std::cerr << "Initing directory watcher with saved secret salt..." << std::endl; - mLocalDirWatcher->setHashSalt(RsFileHash(kit->value)) ; - } - else if(kit->key == IGNORED_PREFIXES_SS) - { - ignored_prefixes.clear(); - - std::string b ; - for(uint32_t i=0;ivalue.size();++i) - if(kit->value[i] == ';') - { - if(!b.empty()) // security! - ignored_prefixes.push_back(b) ; - - b.clear(); - } - else - b.push_back(kit->value[i]) ; - } - else if(kit->key == IGNORED_SUFFIXES_SS) - { - ignored_suffixes.clear(); - - std::string b ; - for(uint32_t i=0;ivalue.size();++i) - if(kit->value[i] == ';') - { - if(!b.empty()) // security! - ignored_suffixes.push_back(b) ; - b.clear(); - } - else - b.push_back(kit->value[i]) ; - } - else if(kit->key == IGNORE_LIST_FLAGS_SS) - { - int t=0 ; - if(sscanf(kit->value.c_str(),"%d",&t) == 1) - ignore_flags = (uint32_t)t ; - } - else if(kit->key == MAX_SHARE_DEPTH) - { - int t=0 ; - if(sscanf(kit->value.c_str(),"%d",&t) == 1) - max_share_depth = (uint32_t)t ; - } - - delete *it ; - continue ; - } - - RsFileConfigItem *fi = dynamic_cast(*it); - - if (fi) - { - /* ensure that it exists? */ - - SharedDirInfo info ; - info.filename = RsDirUtil::convertPathToUnix(fi->file.path); - info.virtualname = fi->file.name; - info.shareflags = FileStorageFlags(fi->flags) ; - info.shareflags &= PERMISSION_MASK ; - - for(std::set::const_iterator itt(fi->parent_groups.ids.begin());itt!=fi->parent_groups.ids.end();++itt) - info.parent_groups.push_back(*itt) ; - - dirList.push_back(info) ; - } - - RsFileListsBannedHashesConfigItem *fb = dynamic_cast(*it) ; - - if(fb) - { - mPrimaryBanList = fb->primary_banned_files_list ; - mBannedFileListNeedsUpdate = true; - mLastPrimaryBanListChangeTimeStamp = time(NULL); - } - - delete *it ; - } - - /* set directories */ - mLocalSharedDirs->setSharedDirectoryList(dirList); - mLocalDirWatcher->setIgnoreLists(ignored_prefixes,ignored_suffixes,ignore_flags) ; - mLocalDirWatcher->setMaxShareDepth(max_share_depth); - - load.clear() ; - - return true; -} - -void p3FileDatabase::cleanup() -{ - { - RS_STACK_MUTEX(mFLSMtx) ; -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "p3FileDatabase::cleanup()" << std::endl; -#endif - - // look through the list of friend directories. Remove those who are not our friends anymore. - // - std::set friend_set ; - { - std::list friend_lst ; - - rsPeers->getFriendList(friend_lst); - - for(std::list::const_iterator it(friend_lst.begin());it!=friend_lst.end();++it) - friend_set.insert(*it) ; - } - rstime_t now = time(NULL); - - for(uint32_t i=0;igetDirectoryRecursModTime(0,recurs_mod_time) ; - - rstime_t last_contact = 0 ; - RsPeerDetails pd ; - if(rsPeers->getPeerDetails(mRemoteDirectories[i]->peerId(),pd)) - last_contact = pd.lastConnect ; - - // We remove directories in the following situations: - // - the peer is not a friend - // - the dir list is non empty but the peer is offline since more than 60 days - // - the dir list is empty and the peer is ffline since more than 5 days - - bool should_remove = friend_set.find(mRemoteDirectories[i]->peerId()) == friend_set.end() - || (recurs_mod_time == 0 && last_contact + DELAY_BEFORE_DELETE_EMPTY_REMOTE_DIR < now ) - || (recurs_mod_time != 0 && last_contact + DELAY_BEFORE_DELETE_NON_EMPTY_REMOTE_DIR < now ); - - if(!should_remove) - continue ; - -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " removing file list of non friend " << mRemoteDirectories[i]->peerId() << std::endl; -#endif - - mUpdateFlags |= P3FILELISTS_UPDATE_FLAG_REMOTE_MAP_CHANGED ; - - friend_set.erase(mRemoteDirectories[i]->peerId()); - - mFriendIndexMap.erase(mRemoteDirectories[i]->peerId()); - - // also remove the existing file - - remove(mRemoteDirectories[i]->filename().c_str()) ; - - delete mRemoteDirectories[i]; - mRemoteDirectories[i] = NULL ; - - // now, in order to avoid empty seats, just move the last one here, and update indexes - - while(i < mRemoteDirectories.size() && mRemoteDirectories[i] == NULL) - { - mRemoteDirectories[i] = mRemoteDirectories.back(); - mRemoteDirectories.pop_back(); - } - - if(i < mRemoteDirectories.size() && mRemoteDirectories[i] != NULL) // this test is needed in the case we have deleted the last element - mFriendIndexMap[mRemoteDirectories[i]->peerId()] = i; - - mUpdateFlags |= P3FILELISTS_UPDATE_FLAG_REMOTE_DIRS_CHANGED ; - } - - // look through the remaining list of friends, which are the ones for which no remoteDirectoryStorage class has been allocated. - // - for(std::set::const_iterator it(friend_set.begin());it!=friend_set.end();++it) - { - // Check if a remote directory exists for that friend, possibly creating the index if the file does not but the friend is online. - - if(rsPeers->isOnline(*it) || RsDirUtil::fileExists(makeRemoteFileName(*it))) - locked_getFriendIndex(*it) ; - } - - // cancel existing requests for which the peer is offline - - std::set online_peers ; - mServCtrl->getPeersConnected(getServiceInfo().mServiceType, online_peers) ; - - for(std::map::iterator it = mPendingSyncRequests.begin();it!=mPendingSyncRequests.end();) - if(online_peers.find(it->second.peer_id) == online_peers.end() || it->second.request_TS + DELAY_BEFORE_DROP_REQUEST < now) - { -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " removing pending request " << std::hex << it->first << std::dec << " for peer " << it->second.peer_id << ", because peer is offline or request is too old." << std::endl; -#endif - std::map::iterator tmp(it); - ++tmp; - mPendingSyncRequests.erase(it) ; - it = tmp; - } - else - { -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " keeping request " << std::hex << it->first << std::dec << " for peer " << it->second.peer_id << std::endl; -#endif - ++it ; - } - - // This is needed at least here, because loadList() might never have been called, if there is no config file present. - - if(mLocalDirWatcher->hashSalt().isNull()) - { - std::cerr << "(WW) Initialising directory watcher salt to some random value " << std::endl; - mLocalDirWatcher->setHashSalt(RsFileHash::random()) ; - - IndicateConfigChanged(); - } - } -} - -std::string p3FileDatabase::makeRemoteFileName(const RsPeerId& pid) const -{ - return mFileSharingDir + "/" + "dirlist_"+pid.toStdString()+".bin" ; -} - -uint32_t p3FileDatabase::locked_getFriendIndex(const RsPeerId& pid) -{ - std::map::const_iterator it = mFriendIndexMap.find(pid) ; - - if(it == mFriendIndexMap.end()) - { - // allocate a new index for that friend, and tell that we should save. - uint32_t found = 0 ; - for(uint32_t i=0;isecond << std::endl; -#endif - } - - if(sizeof(void*)==4 && mRemoteDirectories.size() >= (1u << NB_FRIEND_INDEX_BITS_32BITS) ) - { - std::cerr << "(EE) FriendIndexTab is full. This is weird. Do you really have more than " << (1<= (1ull << NB_FRIEND_INDEX_BITS_64BITS) ) - { - std::cerr << "(EE) FriendIndexTab is full. This is weird. Do you really have more than " << (1<second) - { - mRemoteDirectories.resize(it->second+1,NULL) ; - mRemoteDirectories[it->second] = new RemoteDirectoryStorage(pid,makeRemoteFileName(pid)); - - mUpdateFlags |= P3FILELISTS_UPDATE_FLAG_REMOTE_DIRS_CHANGED ; - mUpdateFlags |= P3FILELISTS_UPDATE_FLAG_REMOTE_MAP_CHANGED ; - -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " adding missing remote dir entry for friend " << pid << ", with index " << it->second << std::endl; -#endif - } - - return it->second; - } -} - -template<> bool p3FileDatabase::convertPointerToEntryIndex<4>(const void *p, EntryIndex& e, uint32_t& friend_index) -{ - // trust me, I can do this ;-) - -#if defined(__GNUC__) && !defined(__clang__) -# pragma GCC diagnostic ignored "-Wstrict-aliasing" -#endif // defined(__GNUC__) && !defined(__clang__) - e = EntryIndex( *reinterpret_cast(&p) & ENTRY_INDEX_BIT_MASK_32BITS ) ; - friend_index = (*reinterpret_cast(&p)) >> NB_ENTRY_INDEX_BITS_32BITS ; -#if defined(__GNUC__) && !defined(__clang__) -# pragma GCC diagnostic pop -#endif // defined(__GNUC__) && !defined(__clang__) - - if(friend_index == 0) - { - std::cerr << "(EE) Cannot find friend index in pointer. Encoded value is zero!" << std::endl; - return false; - } - friend_index--; - - return true; -} -template<> bool p3FileDatabase::convertEntryIndexToPointer<4>(const EntryIndex& e, uint32_t fi, void *& p) -{ - // the pointer is formed the following way: - // - // [ 10 bits | 22 bits ] - // - // This means that the whoel software has the following build-in limitation: - // * 1023 friends - // * 4M shared files. - - uint32_t fe = (uint32_t)e ; - - if(fi+1 >= (1u<= (1u<< NB_ENTRY_INDEX_BITS_32BITS)) - { - P3FILELISTS_ERROR() << "(EE) cannot convert entry index " << e << " of friend with index " << fi << " to pointer." << std::endl; - return false ; - } - - p = reinterpret_cast( ( (1u+fi) << NB_ENTRY_INDEX_BITS_32BITS ) + (fe & ENTRY_INDEX_BIT_MASK_32BITS)) ; - - return true; -} -template<> bool p3FileDatabase::convertPointerToEntryIndex<8>(const void *p, EntryIndex& e, uint32_t& friend_index) -{ - // trust me, I can do this ;-) - -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic ignored "-Wstrict-aliasing" -#endif // defined(__GNUC__) && !defined(__clang__) - e = EntryIndex( *reinterpret_cast(&p) & ENTRY_INDEX_BIT_MASK_64BITS ) ; - friend_index = (*reinterpret_cast(&p)) >> NB_ENTRY_INDEX_BITS_64BITS ; -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif // defined(__GNUC__) && !defined(__clang__) - - if(friend_index == 0) - { - std::cerr << "(EE) Cannot find friend index in pointer. Encoded value is zero!" << std::endl; - return false; - } - friend_index--; - -#ifdef DEBUG_P3FILELISTS - std::cerr << "Generated index " << e <<" friend " << friend_index << " from pointer " << p << std::endl; -#endif - return true; -} -template<> bool p3FileDatabase::convertEntryIndexToPointer<8>(const EntryIndex& e, uint32_t fi, void *& p) -{ - // the pointer is formed the following way: - // - // [ 24 bits | 40 bits ] - // - // This means that the whoel software has the following build-in limitation: - // * 1.6M friends - // * 1T shared files. - - uint64_t fe = (uint64_t)e ; - - if(fi+1 >= (1ull<= (1ull<< NB_ENTRY_INDEX_BITS_64BITS)) - { - P3FILELISTS_ERROR() << "(EE) cannot convert entry index " << e << " of friend with index " << fi << " to pointer." << std::endl; - return false ; - } - - p = reinterpret_cast( ( (1ull+fi) << NB_ENTRY_INDEX_BITS_64BITS ) + (fe & ENTRY_INDEX_BIT_MASK_64BITS)) ; - -#ifdef DEBUG_P3FILELISTS - std::cerr << "Generated pointer " << p << " from friend " << fi << " and index " << e << std::endl; -#endif - - return true; -} -void p3FileDatabase::requestDirUpdate(void *ref) -{ - uint32_t fi; - DirectoryStorage::EntryIndex e ; - - convertPointerToEntryIndex(ref,e,fi); - - if(fi == 0) - return ; // not updating current directory (should we?) - -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Trying to force sync of entry ndex " << e << " to friend " << mRemoteDirectories[fi-1]->peerId() << std::endl; -#endif - - RS_STACK_MUTEX(mFLSMtx) ; - - if(locked_generateAndSendSyncRequest(mRemoteDirectories[fi-1],e)) - { -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " Succeed." << std::endl; -#endif - } -} - -// Finds the pointer to the sub-element #row under element ref. - -bool p3FileDatabase::findChildPointer( void *ref, int row, void *& result, - FileSearchFlags flags ) const -{ - if (ref == NULL) - { - if(flags & RS_FILE_HINTS_LOCAL) - { - if(row != 0 && row != 1) - return false ; - - convertEntryIndexToPointer(0,row,result); - - return true ; - } - else if((uint32_t)row < mRemoteDirectories.size()) - { - convertEntryIndexToPointer(mRemoteDirectories[row]->root(),row+1,result); - return true; - } - else - return false; - } - - uint32_t fi; - DirectoryStorage::EntryIndex e ; - - convertPointerToEntryIndex(ref,e,fi); - - // check consistency - if( (fi == 0 && !(flags & RS_FILE_HINTS_LOCAL)) || (fi > 1 && (flags & RS_FILE_HINTS_LOCAL))) - { - P3FILELISTS_ERROR() << "(EE) remote request on local index or local request on remote index. This should not happen." << std::endl; - return false ; - } - - if(fi==1 && (flags & RS_FILE_HINTS_LOCAL)) // extra list - { - convertEntryIndexToPointer(row+1,1,result); - return true; - } - DirectoryStorage *storage = (flags & RS_FILE_HINTS_LOCAL)? ((DirectoryStorage*)mLocalSharedDirs) : ((DirectoryStorage*)mRemoteDirectories[fi-1]); - - // Case where the index is the top of a single person. Can be us, or a friend. - - EntryIndex c = 0; - bool res = storage->getChildIndex(e,row,c); - - convertEntryIndexToPointer(c,fi,result) ; - - return res; -} - -// This function returns statistics about the entire directory - -int p3FileDatabase::getSharedDirStatistics(const RsPeerId& pid,SharedDirStats& stats) -{ - RS_STACK_MUTEX(mFLSMtx) ; - - if(pid == mOwnId) - { - mLocalSharedDirs->getStatistics(stats) ; - return true ; - } - else - { - uint32_t fi = locked_getFriendIndex(pid); - mRemoteDirectories[fi]->getStatistics(stats) ; - - return true ; - } -} - -bool p3FileDatabase::removeExtraFile(const RsFileHash& hash) -{ - bool ret = false; - { - RS_STACK_MUTEX(mFLSMtx) ; - - ret = mExtraFiles->removeExtraFile(hash); - mLastExtraFilesCacheUpdate = 0 ; // forced cache reload - } - - RsServer::notify()->notifyListChange(NOTIFY_LIST_DIRLIST_LOCAL, 0); - return ret; -} - -void p3FileDatabase::getExtraFilesDirDetails(void *ref,DirectoryStorage::EntryIndex e,DirDetails& d) const -{ - // update the cache of extra files if last requested too long ago - - rstime_t now = time(NULL); - - if(mLastExtraFilesCacheUpdate + DELAY_BETWEEN_EXTRA_FILES_CACHE_UPDATES <= now) - { - mExtraFiles->getExtraFileList(mExtraFilesCache); - mLastExtraFilesCacheUpdate = now; - } - - // - - if(e == 0) // "virtual extra files directory" => create a dir with as many child as they are extra files - { - d.parent = NULL ; - - d.prow = 0;//fi-1 ; - d.type = DIR_TYPE_PERSON; - d.hash.clear() ; - d.size = mExtraFilesCache.size(); - d.max_mtime = time(NULL); - d.mtime = time(NULL); - d.name = "[Extra List]"; - d.path = "/"; - d.ref = ref ; - - for(uint32_t i=0;i(i+1,1,stub.ref); // local shared files from extra list - - d.children.push_back(stub); - } - } - else // extra file. Just query the corresponding data from ftExtra - { - d.prow = 1;//fi-1 ; - d.type = DIR_TYPE_EXTRA_FILE; - - FileInfo& f(mExtraFilesCache[(int)e-1]) ; - - d.hash = f.hash; - d.size = f.size; - d.max_mtime = 0; // this is irrelevant - d.mtime = 0; // this is irrelevant - d.name = f.path; // so that the UI shows the complete path, since the parent directory is not really a directory. - d.path = f.path; - d.ref = ref ; - - convertEntryIndexToPointer(0,1,d.parent) ; - } - - d.flags = DIR_FLAGS_ANONYMOUS_DOWNLOAD ; - d.id = RsPeerId(); -} - -// This function converts a pointer into directory details, to be used by the AbstractItemModel for browsing the files. -int p3FileDatabase::RequestDirDetails( - void* ref, DirDetails& d, FileSearchFlags flags ) const -{ - RS_STACK_MUTEX(mFLSMtx); - - d.children.clear(); - - /* Case where the pointer is NULL, which means we're at the top of the list - * of shared directories for all friends (including us) or at the top of our - * own list of shared directories, depending on the flags. - * - * Friend index is used as follows: - * 0 : own id - * 1...n : other friends - * - * entry_index: starts at 0. - * - * The point is: we cannot use (0,0) because it encodes to NULL. No existing - * combination should encode to NULL. - * So we need to properly convert the friend index into 0 or into a friend - * tab index in mRemoteDirectories. - * - * We should also check the consistency between flags and the content of ref. - */ - - if (ref == nullptr) - { - d.ref = nullptr; - d.type = DIR_TYPE_ROOT; - d.parent = nullptr; - d.prow = -1; - d.name = "root"; - d.hash.clear() ; - d.path = ""; - d.mtime = 0; - d.flags.clear() ; - d.max_mtime = 0 ; - - if(flags & RS_FILE_HINTS_LOCAL) - { - void *p = nullptr; - - { - // root of own directories - convertEntryIndexToPointer(0, 0, p); - DirStub stub; - stub.type = DIR_TYPE_PERSON; - stub.name = mServCtrl->getOwnId().toStdString(); - stub.ref = p; - d.children.push_back(stub); - } - - if(mExtraFiles->size() > 0) - { - // local shared files from extra list - convertEntryIndexToPointer(0, 1, p); - DirStub stub; - // not totally exact, but used as a trick. - stub.type = DIR_TYPE_PERSON; - stub.name = "[Extra List]"; - stub.ref = p; - - d.children.push_back(stub); - } - - - } - else for(uint32_t i=0;i(mRemoteDirectories[i]->root(),i+1,p); - - DirStub stub; - stub.type = DIR_TYPE_PERSON; - stub.name = mRemoteDirectories[i]->peerId().toStdString(); - stub.ref = p; - d.children.push_back(stub); - } - - d.size = 0; // non documented - -#ifdef DEBUG_FILE_HIERARCHY - P3FILELISTS_DEBUG() << "ExtractData: ref=" << ref << ", flags=" << flags << " : returning this: " << std::endl; - P3FILELISTS_DEBUG() << d << std::endl; -#endif - - return true ; - } - - uint32_t fi; - DirectoryStorage::EntryIndex e; - - convertPointerToEntryIndex(ref,e,fi); - - // check consistency - if( (fi == 0 && !(flags & RS_FILE_HINTS_LOCAL)) || - (fi > 1 && (flags & RS_FILE_HINTS_LOCAL))) - { - RS_ERR("Remote request on local index or local request on remote index"); - return false; - } - - if((flags & RS_FILE_HINTS_LOCAL) && fi == 1) // extra list - { - getExtraFilesDirDetails(ref,e,d); - -#ifdef DEBUG_FILE_HIERARCHY - P3FILELISTS_DEBUG() << "ExtractData: ref=" << ref << ", flags=" << flags << " : returning this: " << std::endl; - P3FILELISTS_DEBUG() << d << std::endl; -#endif - return true; - } - - - DirectoryStorage* storage = - (flags & RS_FILE_HINTS_LOCAL) ? - ((DirectoryStorage*) mLocalSharedDirs) : - ((DirectoryStorage*) mRemoteDirectories[fi-1]); - - /* Case where the index is the top of a single person. - * Can be us, or a friend. */ - if(!storage || !storage->extractData(e,d)) - { - RS_WARN( "request on index; ", e, ", for directory ID:", - ( (!storage)? ("[NULL]") : (storage->peerId().toStdString()) ), - " failed" ); - return false; - } - - /* update indexes. This is a bit hacky, but does the job. The cast to - * intptr_t is the proper way to convert a pointer into an int. */ - convertEntryIndexToPointer((intptr_t)d.ref,fi,d.ref); - - for(uint32_t i=0; i( - (intptr_t) d.children[i].ref, fi, d.children[i].ref ); - - if(e == 0) // root - { - d.prow = 0;//fi-1 ; - d.parent = NULL ; - } - else - { - if(d.parent == 0) // child of root node - d.prow = (flags & RS_FILE_HINTS_LOCAL) ? 0 : (fi-1); - else - d.prow = storage->parentRow(e); - - convertEntryIndexToPointer((intptr_t)d.parent,fi,d.parent) ; - } - - d.id = storage->peerId(); - -#ifdef DEBUG_FILE_HIERARCHY - P3FILELISTS_DEBUG() << "ExtractData: ref=" << ref << ", flags=" << flags << " : returning this: " << std::endl; - P3FILELISTS_DEBUG() << d << std::endl; -#endif - - return true; -} - -uint32_t p3FileDatabase::getType(void *ref,FileSearchFlags flags) const -{ - RS_STACK_MUTEX(mFLSMtx) ; - - EntryIndex e ; - uint32_t fi; - - if(ref == NULL) - return DIR_TYPE_ROOT ; - - convertPointerToEntryIndex(ref,e,fi); - - if(e == 0) - return DIR_TYPE_PERSON ; - - if(flags & RS_FILE_HINTS_LOCAL) - { - if(fi == 0 && mLocalSharedDirs != NULL) - return mLocalSharedDirs->getEntryType(e) ; - - if(fi == 1) - return DIR_TYPE_EXTRA_FILE; - - P3FILELISTS_ERROR() << " Cannot determine type of entry " << ref << std::endl; - return DIR_TYPE_ROOT ;// some failure case. Should not happen - } - else - { - if(fi-1 < mRemoteDirectories.size() && mRemoteDirectories[fi-1]!=NULL) - return mRemoteDirectories[fi-1]->getEntryType(e) ; - - P3FILELISTS_ERROR() << " Cannot determine type of entry " << ref << std::endl; - return DIR_TYPE_ROOT ;// some failure case. Should not happen - } -} - -void p3FileDatabase::forceDirectoryCheck(bool add_safe_delay) // Force re-sweep the directories and see what's changed -{ - mLocalDirWatcher->forceUpdate(add_safe_delay); -} -void p3FileDatabase::togglePauseHashingProcess() -{ - RS_STACK_MUTEX(mFLSMtx) ; - mLocalDirWatcher->togglePauseHashingProcess(); -} -bool p3FileDatabase::hashingProcessPaused() -{ - RS_STACK_MUTEX(mFLSMtx) ; - return mLocalDirWatcher->hashingProcessPaused(); -} -bool p3FileDatabase::inDirectoryCheck() -{ - RS_STACK_MUTEX(mFLSMtx) ; - return mLocalDirWatcher->inDirectoryCheck(); -} -void p3FileDatabase::setFollowSymLinks(bool b) -{ - RS_STACK_MUTEX(mFLSMtx) ; - mLocalDirWatcher->setFollowSymLinks(b) ; - IndicateConfigChanged(); -} -bool p3FileDatabase::followSymLinks() const -{ - RS_STACK_MUTEX(mFLSMtx) ; - return mLocalDirWatcher->followSymLinks() ; -} -void p3FileDatabase::setIgnoreDuplicates(bool i) -{ - RS_STACK_MUTEX(mFLSMtx) ; - mLocalDirWatcher->setIgnoreDuplicates(i) ; - IndicateConfigChanged(); -} -bool p3FileDatabase::ignoreDuplicates() const -{ - RS_STACK_MUTEX(mFLSMtx) ; - return mLocalDirWatcher->ignoreDuplicates() ; -} -void p3FileDatabase::setMaxShareDepth(int i) -{ - RS_STACK_MUTEX(mFLSMtx) ; - mLocalDirWatcher->setMaxShareDepth(i) ; - IndicateConfigChanged(); -} -int p3FileDatabase::maxShareDepth() const -{ - RS_STACK_MUTEX(mFLSMtx) ; - return mLocalDirWatcher->maxShareDepth() ; -} -void p3FileDatabase::setWatchEnabled(bool b) -{ - RS_STACK_MUTEX(mFLSMtx) ; - mLocalDirWatcher->setEnabled(b) ; - IndicateConfigChanged(); -} -bool p3FileDatabase::watchEnabled() -{ - RS_STACK_MUTEX(mFLSMtx) ; - return mLocalDirWatcher->isEnabled() ; -} -void p3FileDatabase::setWatchPeriod(uint32_t seconds) -{ - RS_STACK_MUTEX(mFLSMtx) ; - - mLocalDirWatcher->setFileWatchPeriod(seconds); - IndicateConfigChanged(); -} -uint32_t p3FileDatabase::watchPeriod() -{ - RS_STACK_MUTEX(mFLSMtx) ; - return mLocalDirWatcher->fileWatchPeriod(); -} - -int p3FileDatabase::SearchKeywords( - const std::list& keywords, std::list& results, - FileSearchFlags flags, const RsPeerId& client_peer_id ) -{ - if(flags & RS_FILE_HINTS_LOCAL) - { - std::list firesults; - std::list pointers; - - { - RS_STACK_MUTEX(mFLSMtx) ; - - mLocalSharedDirs->searchTerms(keywords,firesults) ; - - for(auto& it: std::as_const(firesults)) - { - void *p = nullptr; - convertEntryIndexToPointer(it, 0, p); - pointers.push_back(p); - } - } - - filterResults(pointers, results, flags, client_peer_id); - } - - if(flags & RS_FILE_HINTS_REMOTE) - { - std::list pointers ; - - { - RS_STACK_MUTEX(mFLSMtx) ; - - for(uint32_t i=0;i local_results; - mRemoteDirectories[i]->searchTerms(keywords,local_results) ; - - for(std::list::iterator it(local_results.begin());it!=local_results.end();++it) - { - void *p=NULL; - convertEntryIndexToPointer(*it,i+1,p); - - pointers.push_back(p) ; - } - } - } - - for(auto it(pointers.begin());it!=pointers.end();++it) - { - DirDetails dd; - - if(!RequestDirDetails (*it,dd,RS_FILE_HINTS_REMOTE)) - continue ; - - results.push_back(dd); - } - } - - return !results.empty() ; -} - -int p3FileDatabase::SearchBoolExp(RsRegularExpression::Expression *exp, std::list& results,FileSearchFlags flags,const RsPeerId& client_peer_id) const -{ - if(flags & RS_FILE_HINTS_LOCAL) - { - std::list firesults; - std::list pointers; - { - RS_STACK_MUTEX(mFLSMtx) ; - - mLocalSharedDirs->searchBoolExp(exp,firesults) ; - - for(std::list::iterator it(firesults.begin());it!=firesults.end();++it) - { - void *p=NULL; - convertEntryIndexToPointer(*it,0,p); - pointers.push_back(p); - } - } - - filterResults(pointers,results,flags,client_peer_id) ; - } - - if(flags & RS_FILE_HINTS_REMOTE) - { - std::list pointers ; - { - RS_STACK_MUTEX(mFLSMtx) ; - - for(uint32_t i=0;i local_results; - mRemoteDirectories[i]->searchBoolExp(exp,local_results) ; - - for(std::list::iterator it(local_results.begin());it!=local_results.end();++it) - { - void *p=NULL; - convertEntryIndexToPointer(*it,i+1,p); - pointers.push_back(p) ; - } - } - } - - for(auto it(pointers.begin());it!=pointers.end();++it) - { - DirDetails dd; - - if(!RequestDirDetails (*it,dd,RS_FILE_HINTS_REMOTE)) - continue ; - - results.push_back(dd); - } - } - - return !results.empty() ; - -} - -bool p3FileDatabase::search( - const RsFileHash &hash, FileSearchFlags hintflags, FileInfo &info) const -{ - RS_STACK_MUTEX(mFLSMtx); - - if( (hintflags & RS_FILE_HINTS_EXTRA) && - mExtraFiles->search(hash, hintflags, info) ) - return true; - - if(hintflags & RS_FILE_HINTS_LOCAL) - { - RsFileHash real_hash ; - EntryIndex indx; - - if(mLocalSharedDirs->searchHash(hash,real_hash,indx)) - { - mLocalSharedDirs->getFileInfo(indx,info) ; - - if(!real_hash.isNull()) - { - info.hash = real_hash ; - info.transfer_info_flags |= RS_FILE_REQ_ENCRYPTED ; - } - - return true; - } - } - - if(hintflags & RS_FILE_HINTS_REMOTE) - { - EntryIndex indx; - bool found = false ; - - for(uint32_t i=0;isearchHash(hash,indx)) - { - TransferInfo ti ; - ti.peerId = mRemoteDirectories[i]->peerId(); - - info.hash = hash ; - info.peers.push_back(ti) ; - - found = true ; - } - - if(found) - return true; - } - return false; -} - -int p3FileDatabase::filterResults( - const std::list& firesults, std::list& results, - FileSearchFlags flags, const RsPeerId& peer_id ) const -{ - results.clear(); - - flags &= RS_FILE_HINTS_PERMISSION_MASK; // remove other flags. - - /* translate/filter results */ - - for(void* rit: std::as_const(firesults)) - { - DirDetails cdetails; - - if(!RequestDirDetails(rit, cdetails, RS_FILE_HINTS_LOCAL)) - { - RS_ERR("Cannot retrieve dir details for entry: ", rit); - print_stacktrace(); - continue ; - } - - RS_DBG( "Filtering candidate: ", rit, - ", name: ", cdetails.name, ", path: ", cdetails.path, - ", flags: ", cdetails.flags, ", peer: ", peer_id ); - - if(!peer_id.isNull()) - { - FileSearchFlags permission_flags = - rsPeers->computePeerPermissionFlags( - peer_id, cdetails.flags, cdetails.parent_groups ); - - if (cdetails.type == DIR_TYPE_FILE && ( permission_flags & flags )) - { - cdetails.id.clear(); - results.push_back(cdetails); -#ifdef DEBUG_P3FILELISTS - std::cerr << ": kept" << std::endl ; -#endif - } -#ifdef DEBUG_P3FILELISTS - else - std::cerr << ": discarded" << std::endl ; -#endif - } - else - results.push_back(cdetails); - } - - for(auto& res: results) - { - /* Most file will just have file name stored, but single file shared - * without a shared dir will contain full path instead of just the - * name, so purify it to perform the search */ - if(res.name.find("/") != std::string::npos ) - { - std::string _tDirPath; - RsDirUtil::splitDirFromFile(res.name, _tDirPath, res.name); - } - } - - return !results.empty(); -} - -bool p3FileDatabase::convertSharedFilePath(const std::string& path,std::string& fullpath) -{ - RS_STACK_MUTEX(mFLSMtx) ; - return mLocalSharedDirs->convertSharedFilePath(path,fullpath) ; -} - -//==============================================================================================================================// -// Update of remote directories // -//==============================================================================================================================// - -// Algorithm: -// -// Local dirs store the last modif time of the file, in local time -// - the max time is computed upward until the root of the hierarchy -// - because the hash is performed late, the last modf time upward is updated only when the hash is obtained. -// -// Remote dirs store -// 1 - recursive max modif time of the files/dir in the friend's time -// 2 - modif time of the files/dir in the friend's time -// 3 - update TS in the local time -// -// The update algorithm is the following: -// -// [Client side] -// - every 30 sec, send a sync packet for the root of the hierarchy containing the remote known max recurs TS. -// - crawl through all directories and if the update TS is 0, ask for sync too. -// - when a sync respnse is received: -// - if response is ACK, set the update time to now. Nothing changed. -// - if response is an update -// * locally update the subfiles -// * for all subdirs, set the local update time to 0 (so as to force a sync) -// -// [Server side] -// - when sync req is received, compare to local recurs TS, and send ACK or full update accordingly -// -// Directories are designated by their hash, instead of their index. This allows to hide the non shared directories -// behind a layer of abstraction, at the cost of a logarithmic search, which is acceptable as far as dir sync-ing between -// friends is concerned (We obviously could not do that for GUI display, which has a small and constant cost). - -void p3FileDatabase::tickRecv() -{ - RsItem *item ; - - while( NULL != (item = recvItem()) ) - { - switch(item->PacketSubType()) - { - case RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM: handleDirSyncRequest( dynamic_cast(item) ) ; break ; - case RS_PKT_SUBTYPE_FILELISTS_BANNED_HASHES_ITEM : handleBannedFilesInfo( dynamic_cast(item) ) ; break ; - case RS_PKT_SUBTYPE_FILELISTS_SYNC_RSP_ITEM: - { - RsFileListsSyncResponseItem *sitem = dynamic_cast(item); - handleDirSyncResponse(sitem) ; - item = sitem ; - } - break ; - default: - P3FILELISTS_ERROR() << "(EE) unhandled packet subtype " << item->PacketSubType() << " in " << __PRETTY_FUNCTION__ << std::endl; - } - - delete item ; - } -} - -void p3FileDatabase::tickSend() -{ - // go through the list of out requests and send them to the corresponding friends, if they are online. -} - -void p3FileDatabase::handleDirSyncRequest(RsFileListsSyncRequestItem *item) -{ - RsFileListsSyncResponseItem* ritem = new RsFileListsSyncResponseItem; - - // look at item TS. If local is newer, send the full directory content. - { - RS_STACK_MUTEX(mFLSMtx); - - RS_DBG( "Received directory sync request from peer ", item->PeerId(), - ". hash=", item->entry_hash, ", flags=", item->flags, - ", request id: ", item->request_id, ", last known TS: ", - item->last_known_recurs_modf_TS ); - - EntryIndex entry_index = DirectoryStorage::NO_INDEX; - if(!mLocalSharedDirs->getIndexFromDirHash(item->entry_hash,entry_index)) - { - RS_DBG("Cannot find entry index for hash ", item->entry_hash, - " cannot respond to sync request." ); - return; - } - - uint32_t entry_type = mLocalSharedDirs->getEntryType(entry_index); - ritem->PeerId(item->PeerId()); - ritem->request_id = item->request_id; - ritem->entry_hash = item->entry_hash; - - std::list node_groups; - FileStorageFlags node_flags; - - if(entry_type != DIR_TYPE_DIR) - { - RS_DBG( "Directory does not exist anymore, or is not a directory, " - "or permission denied. Answering with proper flags." ); - ritem->flags = RsFileListsItem::FLAGS_SYNC_RESPONSE | - RsFileListsItem::FLAGS_ENTRY_WAS_REMOVED; - } - else if( entry_index != 0 && - (!mLocalSharedDirs->getFileSharingPermissions( - entry_index, node_flags,node_groups ) || - !(rsPeers->computePeerPermissionFlags( - item->PeerId(), node_flags, node_groups ) & - RS_FILE_HINTS_BROWSABLE)) ) - { - RS_ERR("cannot get file permissions for entry index: ", entry_index, - ", or permission denied." ); - ritem->flags = RsFileListsItem::FLAGS_SYNC_RESPONSE | - RsFileListsItem::FLAGS_ENTRY_WAS_REMOVED; - } - else - { - rstime_t local_recurs_max_time; - mLocalSharedDirs->getDirectoryRecursModTime( - entry_index, local_recurs_max_time ); - - /* normally, should be "<", but since we provided the TS it should - * be equal, so != is more robust. */ - if(item->last_known_recurs_modf_TS != local_recurs_max_time) - { - RS_DBG( "Directory is more recent than what the friend knows. " - "Sending full dir content as response."); - - ritem->flags = RsFileListsItem::FLAGS_SYNC_RESPONSE | - RsFileListsItem::FLAGS_SYNC_DIR_CONTENT; - ritem->last_known_recurs_modf_TS = local_recurs_max_time; - - /* We supply the peer id, in order to possibly remove some - * subdirs, if entries are not allowed to be seen by this peer. - */ - mLocalSharedDirs->serialiseDirEntry( - entry_index, ritem->directory_content_data, - item->PeerId() ); - } - else - { - RS_DBG3( "Directory is up to date w.r.t. what the friend knows." - " Sending ACK." ); - - ritem->flags = RsFileListsItem::FLAGS_SYNC_RESPONSE | - RsFileListsItem::FLAGS_ENTRY_UP_TO_DATE; - ritem->last_known_recurs_modf_TS = local_recurs_max_time; - } - } - } - - // sends the response. - splitAndSendItem(ritem); -} - -void p3FileDatabase::splitAndSendItem(RsFileListsSyncResponseItem *ritem) -{ - ritem->checksum = RsDirUtil::sha1sum((uint8_t*)ritem->directory_content_data.bin_data,ritem->directory_content_data.bin_len); - - while(ritem->directory_content_data.bin_len > MAX_DIR_SYNC_RESPONSE_DATA_SIZE) - { -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Chopping off partial chunk of size " << MAX_DIR_SYNC_RESPONSE_DATA_SIZE << " from item data of size " << ritem->directory_content_data.bin_len << std::endl; -#endif - - ritem->flags |= RsFileListsItem::FLAGS_SYNC_PARTIAL ; - - RsFileListsSyncResponseItem *subitem = new RsFileListsSyncResponseItem() ; - - subitem->entry_hash = ritem->entry_hash; - subitem->flags = ritem->flags ; - subitem->last_known_recurs_modf_TS = ritem->last_known_recurs_modf_TS; - subitem->request_id = ritem->request_id; - subitem->checksum = ritem->checksum ; - - // copy a subpart of the data - subitem->directory_content_data.tlvtype = ritem->directory_content_data.tlvtype ; - subitem->directory_content_data.setBinData(ritem->directory_content_data.bin_data, MAX_DIR_SYNC_RESPONSE_DATA_SIZE) ; - - // update ritem to chop off the data that was sent. - memmove(ritem->directory_content_data.bin_data, &((unsigned char*)ritem->directory_content_data.bin_data)[MAX_DIR_SYNC_RESPONSE_DATA_SIZE], ritem->directory_content_data.bin_len - MAX_DIR_SYNC_RESPONSE_DATA_SIZE) ; - ritem->directory_content_data.bin_len -= MAX_DIR_SYNC_RESPONSE_DATA_SIZE ; - - // send - subitem->PeerId(ritem->PeerId()) ; - - sendItem(subitem) ; - - // fix up last chunk - if(ritem->directory_content_data.bin_len <= MAX_DIR_SYNC_RESPONSE_DATA_SIZE) - ritem->flags |= RsFileListsItem::FLAGS_SYNC_PARTIAL_END ; - } - - sendItem(ritem) ; -} - -// This function should not take memory ownership of ritem, so it makes copies. -// The item that is returned is either created (if different from ritem) or equal to ritem. - -RsFileListsSyncResponseItem *p3FileDatabase::recvAndRebuildItem(RsFileListsSyncResponseItem *ritem) -{ - if(!(ritem->flags & RsFileListsItem::FLAGS_SYNC_PARTIAL )) - return ritem ; - - // item is a partial item. Look first for a starting entry - -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Item from peer " << ritem->PeerId() << " is partial. Size = " << ritem->directory_content_data.bin_len << std::endl; -#endif - - RS_STACK_MUTEX(mFLSMtx) ; - - bool is_ending = (ritem->flags & RsFileListsItem::FLAGS_SYNC_PARTIAL_END); - std::map::iterator it = mPartialResponseItems.find(ritem->request_id) ; - - if(it == mPartialResponseItems.end()) - { - if(is_ending) - { - P3FILELISTS_ERROR() << "Impossible situation: partial item ended right away. Dropping..." << std::endl; - return NULL; - } -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Creating new item buffer" << std::endl; -#endif - - mPartialResponseItems[ritem->request_id] = new RsFileListsSyncResponseItem(*ritem) ; - return NULL ; - } - else if(it->second->checksum != ritem->checksum) - { - P3FILELISTS_ERROR() << "Impossible situation: partial items with different checksums. Dropping..." << std::endl; - mPartialResponseItems.erase(it); - return NULL; - } - - // collapse the item at the end of the existing partial item. Dont delete ritem as it will be by the caller. - - uint32_t old_len = it->second->directory_content_data.bin_len ; - uint32_t added = ritem->directory_content_data.bin_len; - - it->second->directory_content_data.bin_data = realloc(it->second->directory_content_data.bin_data,old_len + added) ; - memcpy(&((unsigned char*)it->second->directory_content_data.bin_data)[old_len],ritem->directory_content_data.bin_data,added); - it->second->directory_content_data.bin_len = old_len + added ; - -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Added new chunk of length " << added << ". New size is " << old_len + added << std::endl; -#endif - - // if finished, return the item - - if(is_ending) - { -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Item is complete. Returning it" << std::endl; -#endif - - RsFileListsSyncResponseItem *ret = it->second ; - mPartialResponseItems.erase(it) ; - - ret->flags &= ~RsFileListsItem::FLAGS_SYNC_PARTIAL_END ; - ret->flags &= ~RsFileListsItem::FLAGS_SYNC_PARTIAL ; - - return ret ; - } - else - return NULL ; -} - -// We employ a trick in this function: -// - if recvAndRebuildItem(item) returns the same item, it has not created memory, so the incoming item should be the one to -// delete, which is done by the caller in every case. -// - if it returns a different item, it means that the item has been created below when collapsing items, so we should delete both. -// to do so, we first delete the incoming item, and replace the pointer by the new created one. - -void p3FileDatabase::handleDirSyncResponse(RsFileListsSyncResponseItem*& sitem) -{ - RsFileListsSyncResponseItem *item = recvAndRebuildItem(sitem) ; - - if(!item) - return ; - - if(item != sitem) - { - delete sitem ; - sitem = item ; - } - - rstime_t now = time(NULL); - - // check the hash. If anything goes wrong (in the chunking for instance) the hash will not match - - if(RsDirUtil::sha1sum((uint8_t*)item->directory_content_data.bin_data,item->directory_content_data.bin_len) != item->checksum) - { - P3FILELISTS_ERROR() << "Checksum error in response item " << std::hex << item->request_id << std::dec << " . This is unexpected, and might be due to connection problems." << std::endl; - return ; - } - -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Handling sync response for directory with hash " << item->entry_hash << std::endl; -#endif - - EntryIndex entry_index = DirectoryStorage::NO_INDEX; - - // find the correct friend entry - - uint32_t fi = 0 ; - - { - RS_STACK_MUTEX(mFLSMtx) ; - fi = locked_getFriendIndex(item->PeerId()); - -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " friend index is " << fi ; -#endif - - // make sure we have a remote directory for that friend. - - if(!mRemoteDirectories[fi]->getIndexFromDirHash(item->entry_hash,entry_index)) - { - std::cerr << std::endl; - P3FILELISTS_ERROR() << " (EE) cannot find index from hash " << item->entry_hash << ". Dropping the response." << std::endl; - return ; - } -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " entry index is " << entry_index << " " ; -#endif - } - - if(item->flags & RsFileListsItem::FLAGS_ENTRY_WAS_REMOVED) - { - RS_STACK_MUTEX(mFLSMtx) ; -#ifdef DEBUG_P3FILELISTS - std::cerr << " removing directory with index " << entry_index << " because it does not exist." << std::endl; -#endif - mRemoteDirectories[fi]->removeDirectory(entry_index); - - mRemoteDirectories[fi]->print(); - } - else if(item->flags & RsFileListsItem::FLAGS_ENTRY_UP_TO_DATE) - { - RS_STACK_MUTEX(mFLSMtx) ; -#ifdef DEBUG_P3FILELISTS - std::cerr << " Directory is up to date. Setting local TS." << std::endl; -#endif - - mRemoteDirectories[fi]->setDirectoryUpdateTime(entry_index,now) ; - } - else if(item->flags & RsFileListsItem::FLAGS_SYNC_DIR_CONTENT) - { -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " Item contains directory data. Deserialising/Updating." << std::endl; -#endif - RS_STACK_MUTEX(mFLSMtx) ; - - if(mLastDataRecvTS + 1 < now) // avoid notifying the GUI too often as it kills performance. - { - RsServer::notify()->notifyListPreChange(NOTIFY_LIST_DIRLIST_FRIENDS, 0); // notify the GUI if the hierarchy has changed - mLastDataRecvTS = now; - } -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "Performing update of directory index " << std::hex << entry_index << std::dec << " from friend " << item->PeerId() << std::endl; -#endif - - if(mRemoteDirectories[fi]->deserialiseUpdateDirEntry(entry_index,item->directory_content_data)) - mRemoteDirectories[fi]->lastSweepTime() = now - DELAY_BETWEEN_REMOTE_DIRECTORIES_SWEEP + 10 ; // force re-sweep in 10 secs, so as to fasten updated - else - P3FILELISTS_ERROR() << "(EE) Cannot deserialise dir entry. ERROR. "<< std::endl; - -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " new content after update: " << std::endl; - mRemoteDirectories[fi]->print(); -#endif - } - - // remove the original request from pending list in the end. doing this here avoids that a new request is added while the previous response is not treated. - - { - RS_STACK_MUTEX(mFLSMtx) ; - - std::map::iterator it = mPendingSyncRequests.find(item->request_id) ; - - if(it == mPendingSyncRequests.end()) - { - P3FILELISTS_ERROR() << " request " << std::hex << item->request_id << std::dec << " cannot be found. ERROR!" << std::endl; - return ; - } - mPendingSyncRequests.erase(it) ; - } - - -} - -void p3FileDatabase::locked_recursSweepRemoteDirectory(RemoteDirectoryStorage *rds,DirectoryStorage::EntryIndex e,int depth) -{ - rstime_t now = time(NULL) ; - - //std::string indent(2*depth,' ') ; - - // if not up to date, request update, and return (content is not certified, so no need to recurs yet). - // if up to date, return, because TS is about the last modif TS below, so no need to recurs either. - - // get the info for this entry - -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << "currently at entry index " << e << std::endl; -#endif - - rstime_t local_update_TS; - - if(!rds->getDirectoryUpdateTime(e,local_update_TS)) - { - P3FILELISTS_ERROR() << " (EE) lockec_recursSweepRemoteDirectory(): cannot get update TS for directory with index " << e << ". This is a consistency bug." << std::endl; - return; - } - - // compare TS - - if((e == 0 && now > local_update_TS + DELAY_BETWEEN_REMOTE_DIRECTORY_SYNC_REQ) || local_update_TS == 0) // we need to compare local times only. We cannot compare local (now) with remote time. - if(locked_generateAndSendSyncRequest(rds,e)) - { -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " Asking for sync of directory " << e << " to peer " << rds->peerId() << " because it's " << (now - local_update_TS) << " secs old since last check." << std::endl; -#endif - } - - for(DirectoryStorage::DirIterator it(rds,e);it;++it) - locked_recursSweepRemoteDirectory(rds,*it,depth+1); -} - -p3FileDatabase::DirSyncRequestId p3FileDatabase::makeDirSyncReqId(const RsPeerId& peer_id,const RsFileHash& hash) -{ - static uint64_t random_bias = RSRandom::random_u64(); - - uint8_t mem[RsPeerId::SIZE_IN_BYTES + RsFileHash::SIZE_IN_BYTES]; - memcpy(mem,peer_id.toByteArray(),RsPeerId::SIZE_IN_BYTES) ; - memcpy(&mem[RsPeerId::SIZE_IN_BYTES],hash.toByteArray(),RsFileHash::SIZE_IN_BYTES) ; - - RsFileHash tmp = RsDirUtil::sha1sum(mem,RsPeerId::SIZE_IN_BYTES + RsFileHash::SIZE_IN_BYTES) ; - - // This is kind of arbitrary. The important thing is that the same ID needs to be generated every time for a given (peer_id,entry index) pair, in a way - // that cannot be brute-forced or reverse-engineered, which explains the random bias and the usage of the hash, that is itself random. - - uint64_t tmp2 ; - memcpy(&tmp2,tmp.toByteArray(),sizeof(uint64_t)); - - uint64_t r = random_bias ^ tmp2; - -#ifdef DEBUG_P3FILELISTS - std::cerr << "Creating ID " << std::hex << r << std::dec << " from peer id " << peer_id << " and hash " << hash << std::endl; -#endif - - return r ; -} - -bool p3FileDatabase::locked_generateAndSendSyncRequest(RemoteDirectoryStorage *rds,const DirectoryStorage::EntryIndex& e) -{ - RsFileHash entry_hash ; - rstime_t now = time(NULL) ; - - rstime_t max_known_recurs_modf_time ; - - if(!rds->getDirectoryRecursModTime(e,max_known_recurs_modf_time)) - { - P3FILELISTS_ERROR() << " (EE) cannot find recurs mod time for entry index " << e << ". This is very unexpected." << std::endl; - return false; - } - if(!rds->getDirHashFromIndex(e,entry_hash) ) - { - P3FILELISTS_ERROR() << " (EE) cannot find hash for entry index " << e << ". This is very unexpected." << std::endl; - return false; - } - - // check if a request already exists and is not too old either: no need to re-ask. - - DirSyncRequestId sync_req_id = makeDirSyncReqId(rds->peerId(),entry_hash) ; - - std::map::iterator it = mPendingSyncRequests.find(sync_req_id) ; - - if(it != mPendingSyncRequests.end()) - { -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " Not asking for sync of directory " << e << " to friend " << rds->peerId() << " because a recent pending request still exists." << std::endl; -#endif - return false ; - } - - RsFileListsSyncRequestItem *item = new RsFileListsSyncRequestItem ; - - item->entry_hash = entry_hash ; - item->flags = RsFileListsItem::FLAGS_SYNC_REQUEST ; - item->request_id = sync_req_id ; - item->last_known_recurs_modf_TS = max_known_recurs_modf_time ; - item->PeerId(rds->peerId()) ; - - DirSyncRequestData data ; - - data.request_TS = now ; - data.peer_id = item->PeerId(); - data.flags = item->flags; - -#ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " Pushing req " << std::hex << sync_req_id << std::dec << " in pending list with peer id " << data.peer_id << std::endl; -#endif - - mPendingSyncRequests[sync_req_id] = data ; - - sendItem(item) ; // at end! Because item is destroyed by the process. - - return true; -} - - -//=========================================================================================================================// -// Unwanted content filtering system // -//=========================================================================================================================// - -bool p3FileDatabase::banFile(const RsFileHash& real_file_hash, const std::string& filename, uint64_t file_size) -{ -#ifdef DEBUG_CONTENT_FILTERING - P3FILELISTS_DEBUG() << " setting file \"" << filename << "\" size=" << file_size << " hash=" << real_file_hash << " as banned." << std::endl; -#endif - { - RS_STACK_MUTEX(mFLSMtx) ; - BannedFileEntry& entry(mPrimaryBanList[real_file_hash]) ; // primary list (user controlled) of files banned from FT search and forwarding. map - - if(entry.mBanTimeStamp == 0) - { - entry.mFilename = filename ; - entry.mSize = file_size ; - entry.mBanTimeStamp = time(NULL); - - RsFileHash hash_of_hash ; - ftServer::encryptHash(real_file_hash,hash_of_hash) ; - - mBannedFileList.insert(real_file_hash) ; - mBannedFileList.insert(hash_of_hash) ; - - mLastPrimaryBanListChangeTimeStamp = time(NULL); - mBannedFileListNeedsUpdate = true ; - } - } - - IndicateConfigChanged(); - return true; -} -bool p3FileDatabase::unbanFile(const RsFileHash& real_file_hash) -{ -#ifdef DEBUG_CONTENT_FILTERING - P3FILELISTS_DEBUG() << " unbanning file with hash " << real_file_hash << std::endl; -#endif - { - RS_STACK_MUTEX(mFLSMtx) ; - mPrimaryBanList.erase(real_file_hash) ; - mLastPrimaryBanListChangeTimeStamp = time(NULL); - mBannedFileListNeedsUpdate = true ; - } - - IndicateConfigChanged(); - return true; -} - -bool p3FileDatabase::isFileBanned(const RsFileHash& hash) -{ - RS_STACK_MUTEX(mFLSMtx) ; - - if(mBannedFileList.empty()) // quick exit - return false ; - - RsFileHash hash_of_hash ; - ftServer::encryptHash(hash,hash_of_hash) ; - - bool res = mBannedFileList.find(hash) != mBannedFileList.end() || mBannedFileList.find(hash_of_hash) != mBannedFileList.end() ; - -#ifdef DEBUG_CONTENT_FILTERING - if(res) - P3FILELISTS_DEBUG() << " is file banned(" << hash << "): " << (res?"YES":"NO") << std::endl; -#endif - return res ; -} - -bool p3FileDatabase::getPrimaryBannedFilesList(std::map& banned_files) -{ - RS_STACK_MUTEX(mFLSMtx) ; - banned_files = mPrimaryBanList; - - return true ; -} - -bool p3FileDatabase::trustFriendNodesForBannedFiles() const -{ - RS_STACK_MUTEX(mFLSMtx) ; - return mTrustFriendNodesForBannedFiles; -} - -void p3FileDatabase::setTrustFriendNodesForBannedFiles(bool b) -{ - if(b != mTrustFriendNodesForBannedFiles) - { - IndicateConfigChanged(); - mBannedFileListNeedsUpdate = true; - } - - RS_STACK_MUTEX(mFLSMtx) ; - mTrustFriendNodesForBannedFiles = b; -} - -void p3FileDatabase::checkSendBannedFilesInfo() -{ - RS_STACK_MUTEX(mFLSMtx) ; - - // 1 - compare records to list of online friends, send own info of not already - -#ifdef DEBUG_CONTENT_FILTERING - P3FILELISTS_DEBUG() << " Checking banned files information: " << std::endl; -#endif - - rstime_t now = time(NULL); - std::list online_friends ; - rsPeers->getOnlineList(online_friends); - - std::set peers ; - for(auto it(online_friends.begin());it!=online_friends.end();++it) // convert to std::set for efficient search - peers.insert(*it) ; - - for(auto it(mPeerBannedFiles.begin());it!=mPeerBannedFiles.end();) - { - if(peers.find(it->first) == peers.end()) // friend not online, remove his record - { - it = mPeerBannedFiles.erase(it) ; -#ifdef DEBUG_CONTENT_FILTERING - P3FILELISTS_DEBUG() << " Peer " << it->first << " is offline: removign record." << std::endl; -#endif - continue; - } - - if(it->second.mLastSent < mLastPrimaryBanListChangeTimeStamp) // has ban info already been sent? If not do it. - { -#ifdef DEBUG_CONTENT_FILTERING - P3FILELISTS_DEBUG() << " Peer " << it->first << " is online and hasn't been sent since last change: sending..." << std::endl; -#endif - locked_sendBanInfo(it->first); - it->second.mLastSent = now; - } - - peers.erase(it->first); // friend has been handled -> remove from list - ++it; - } - - // 2 - add a new record for friends not already in the record map - - for(auto it(peers.begin());it!=peers.end();++it) - { - locked_sendBanInfo(*it); - mPeerBannedFiles[*it].mLastSent = now; -#ifdef DEBUG_CONTENT_FILTERING - P3FILELISTS_DEBUG() << " Peer " << *it << " is online and hasn't been sent info at all: sending..." << std::endl; -#endif - } - - // 3 - update list of banned hashes if it has changed somehow - - if(mBannedFileListNeedsUpdate) - { - mBannedFileList.clear(); - -#ifdef DEBUG_CONTENT_FILTERING - P3FILELISTS_DEBUG() << " Creating local banned file list: " << std::endl; -#endif - // Add all H(H(f)) from friends - - if(mTrustFriendNodesForBannedFiles) - for(auto it(mPeerBannedFiles.begin());it!=mPeerBannedFiles.end();++it) - for(auto it2(it->second.mBannedHashOfHash.begin());it2!=it->second.mBannedHashOfHash.end();++it2) - { - mBannedFileList.insert(*it2); - -#ifdef DEBUG_CONTENT_FILTERING - P3FILELISTS_DEBUG() << " from " << it->first << ": H(H(f)) = " << *it2 << std::endl; -#endif - } - - // Add H(f) and H(H(f)) from our primary list - - for(auto it(mPrimaryBanList.begin());it!=mPrimaryBanList.end();++it) - { - mBannedFileList.insert(it->first) ; - - RsFileHash hash_of_hash ; - ftServer::encryptHash(it->first,hash_of_hash) ; - - mBannedFileList.insert(hash_of_hash) ; - -#ifdef DEBUG_CONTENT_FILTERING - P3FILELISTS_DEBUG() << " primary: H(f) = " << it->first << ": H(H(f)) = " << hash_of_hash << std::endl; -#endif - } - - mBannedFileListNeedsUpdate = false ; - } - -#ifdef DEBUG_CONTENT_FILTERING - P3FILELISTS_DEBUG() << " Final list of locally banned hashes contains: " << mBannedFileList.size() << " elements." << std::endl; -#endif -} - -void p3FileDatabase::locked_sendBanInfo(const RsPeerId& peer) -{ - RsFileListsBannedHashesItem *item = new RsFileListsBannedHashesItem ; - uint32_t session_id = RSRandom::random_u32(); - - item->session_id = session_id ; - item->PeerId(peer); - - for(auto it(mPrimaryBanList.begin());it!=mPrimaryBanList.end();++it) - { - RsFileHash hash_of_hash ; - - ftServer::encryptHash(it->first,hash_of_hash) ; - - if(!item) - { - item = new RsFileListsBannedHashesItem ; - - item->PeerId(peer); - item->session_id = session_id ; - } - - item->encrypted_hashes.insert(hash_of_hash) ; - - if(item->encrypted_hashes.size() >= 200) - { - sendItem(item); - item = NULL ; - } - } - - if(item) - sendItem(item); -} - -void p3FileDatabase::handleBannedFilesInfo(RsFileListsBannedHashesItem *item) -{ - RS_STACK_MUTEX(mFLSMtx) ; - -#ifdef DEBUG_CONTENT_FILTERING - P3FILELISTS_DEBUG() << " received banned files info from peer " << item->PeerId() << ", session id = " << std::hex << item->session_id << std::dec << ": " << item->encrypted_hashes.size() << " files:" << std::endl; -#endif - // 1 - localize the friend in the banned file map - - PeerBannedFilesEntry& pbfe(mPeerBannedFiles[item->PeerId()]) ; - - if(pbfe.mSessionId != item->session_id) - pbfe.mBannedHashOfHash.clear(); - - pbfe.mSessionId = item->session_id ; - - // 2 - replace/update the list, depending on the session_id - - for(auto it(item->encrypted_hashes.begin());it!=item->encrypted_hashes.end();++it) - { - pbfe.mBannedHashOfHash.insert(*it); -#ifdef DEBUG_CONTENT_FILTERING - P3FILELISTS_DEBUG() << " added H(H(f)) = " << *it << std::endl; -#endif - } - - // 3 - tell the updater that the banned file list has changed - - mBannedFileListNeedsUpdate = true ; -} - diff --git a/libretroshare/src/file_sharing/p3filelists.h b/libretroshare/src/file_sharing/p3filelists.h deleted file mode 100644 index f9a97e47b..000000000 --- a/libretroshare/src/file_sharing/p3filelists.h +++ /dev/null @@ -1,301 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: p3filelists.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 by Mr.Alice * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ - -// -// This class is responsible for -// - maintaining a list of shared file hierarchies for each known friends -// - talking to the GUI -// - providing handles for the directory tree listing GUI -// - providing search handles for FT -// - keeping these lists up to date -// - sending our own file list to friends depending on the defined access rights -// - serving file search requests from other services such as file transfer -// -// p3FileList does the following micro-tasks: -// - tick the watchers -// - get incoming info from the service layer, which can be: -// - directory content request => the directory content is shared to the friend -// - directory content => the directory watcher is notified -// - keep two queues of update requests: -// - fast queue that is handled in highest priority. This one is used for e.g. updating while browsing. -// - slow queue that is handled slowly. Used in background update of shared directories. -// -// The list of local shared files is maintained by FileListWatcher. -// -// p3FileLists is organised as follows: -// -// p3FileDatabase -// | -// +---- HashStorage // Handles known hashes. Serves as a reference when new files are hashed. -// | -// +---- RemoteDirectoryStorage // Stores the list of shared files at friends -// | | -// | +---- InternalFileHierarchyStorage -// | -// +---- LocalDirectoryStorage // Stores the list of locally shared files -// | | -// | +---- InternalFileHierarchyStorage -// | -// +---- LocalDirectoryUpdater // Keeps the local lists up to date, by regularly crawling directories -// -#pragma once - -#include "ft/ftsearch.h" -#include "ft/ftextralist.h" -#include "retroshare/rsfiles.h" -#include "services/p3service.h" -#include "util/rstime.h" -#include "file_sharing/hash_cache.h" -#include "file_sharing/directory_storage.h" - -#include "pqi/p3cfgmgr.h" -#include "pqi/p3linkmgr.h" - -class RemoteDirectoryUpdater ; -class LocalDirectoryUpdater ; - -class RemoteDirectoryStorage ; -class LocalDirectoryStorage ; - -class RsFileListsSyncRequestItem ; -class RsFileListsSyncResponseItem ; -class RsFileListsBannedHashesItem ; - -class HashStorage ; - -struct PeerBannedFilesEntry -{ - std::set mBannedHashOfHash; - uint32_t mSessionId ; // used for when a friend sends multiple packets in separate items. - rstime_t mLastSent; -}; - -class p3FileDatabase: public p3Service, public p3Config, public ftSearch //, public RsSharedFileService -{ - public: - typedef DirectoryStorage::EntryIndex EntryIndex; // this should probably be defined elsewhere - - virtual RsServiceInfo getServiceInfo(); - - struct RsFileListSyncRequest - { - RsPeerId peerId ; - EntryIndex index ; - // [...] more to add here - }; - - explicit p3FileDatabase(p3ServiceControl *mpeers); - ~p3FileDatabase(); - - void setExtraList(ftExtraList *f) { mExtraFiles = f ; } - /*! - * \brief forceSyncWithPeers - * - * Forces the synchronisation of the database with connected peers. This is triggered when e.g. a new group of friend is created, or when - * a friend was added/removed from a group. - */ - void forceSyncWithPeers() { NOT_IMPLEMENTED() ; } - - // derived from p3Service - // - virtual int tick() ; - - // ftSearch - virtual bool search(const RsFileHash &hash, FileSearchFlags hintflags, FileInfo &info) const; - virtual int SearchKeywords(const std::list& keywords, std::list& results,FileSearchFlags flags,const RsPeerId& peer_id) ; - virtual int SearchBoolExp(RsRegularExpression::Expression *exp, std::list& results,FileSearchFlags flags,const RsPeerId& peer_id) const ; - - // Extra file list - virtual bool removeExtraFile(const RsFileHash& hash); - - // Interface for browsing dir hierarchy - // - - void stopThreads() ; - void startThreads() ; - - bool findChildPointer(void *ref, int row, void *& result, FileSearchFlags flags) const; - - // void * here is the type expected by the abstract model index from Qt. It gets turned into a DirectoryStorage::EntryIndex internally. - - void requestDirUpdate(void *ref) ; // triggers an update. Used when browsing. - int RequestDirDetails(void *, DirDetails&, FileSearchFlags) const ; - uint32_t getType(void *, FileSearchFlags flags) const ; - - // proxy method used by the web UI. Dont't delete! - int RequestDirDetails(const RsPeerId& uid, const std::string& path, DirDetails &details)const; - - // set/update shared directories - - void setSharedDirectories(const std::list& dirs); - void getSharedDirectories(std::list& dirs); - void updateShareFlags(const SharedDirInfo& info) ; - bool convertSharedFilePath(const std::string& path,std::string& fullpath); - - void setIgnoreLists(const std::list& ignored_prefixes,const std::list& ignored_suffixes, uint32_t ignore_flags) ; - bool getIgnoreLists(std::list& ignored_prefixes,std::list& ignored_suffixes, uint32_t& ignore_flags) ; - - void setIgnoreDuplicates(bool i) ; - bool ignoreDuplicates() const ; - - void setMaxShareDepth(int i) ; - int maxShareDepth() const ; - - bool banFile(const RsFileHash& real_file_hash, const std::string& filename, uint64_t file_size) ; - bool unbanFile(const RsFileHash& real_file_hash); - bool isFileBanned(const RsFileHash& hash) ; - bool getPrimaryBannedFilesList(std::map& banned_files) ; - bool trustFriendNodesForBannedFiles() const ; - void setTrustFriendNodesForBannedFiles(bool b) ; - - // computes/gathers statistics about shared directories - - int getSharedDirStatistics(const RsPeerId& pid,SharedDirStats& stats); - - // interface for hash caching - - void setWatchPeriod(uint32_t seconds); - uint32_t watchPeriod() ; - void setWatchEnabled(bool b) ; - bool watchEnabled() ; - - bool followSymLinks() const; - void setFollowSymLinks(bool b) ; - - // interfact for directory parsing - - void forceDirectoryCheck(bool add_safe_delay); // Force re-sweep the directories and see what's changed - bool inDirectoryCheck(); - void togglePauseHashingProcess(); - bool hashingProcessPaused(); - - protected: - void getExtraFilesDirDetails(void *ref,DirectoryStorage::EntryIndex e,DirDetails& d) const; - - int filterResults(const std::list& firesults,std::list& results,FileSearchFlags flags,const RsPeerId& peer_id) const; - std::string makeRemoteFileName(const RsPeerId& pid) const; - - // Derived from p3Config - // - virtual bool loadList(std::list& items); - virtual bool saveList(bool &cleanup, std::list&); - virtual RsSerialiser *setupSerialiser() ; - - void cleanup(); - void tickRecv(); - void tickSend(); - - void checkSendBannedFilesInfo(); - - private: - p3ServiceControl *mServCtrl ; - RsPeerId mOwnId ; - - typedef uint64_t DirSyncRequestId ; - - static DirSyncRequestId makeDirSyncReqId(const RsPeerId& peer_id, const RsFileHash &hash) ; - - // utility functions to send items with some maximum size. - - void splitAndSendItem(RsFileListsSyncResponseItem *ritem); - RsFileListsSyncResponseItem *recvAndRebuildItem(RsFileListsSyncResponseItem *ritem); - - /*! - * \brief generateAndSendSyncRequest - * \param rds Remote directory storage for the request - * \param e Entry index to update - * \return true if the request is correctly sent. - */ - bool locked_generateAndSendSyncRequest(RemoteDirectoryStorage *rds,const DirectoryStorage::EntryIndex& e); - - // File sync request queues. The fast one is used for online browsing when friends are connected. - // The slow one is used for background update of file lists. - // - std::map mFastRequestQueue ; - std::map mSlowRequestQueue ; - - // Directory storage hierarchies - // - // The remote one is the reference for the PeerId index below: - // RemoteDirectories[ getFriendIndex(pid) - 1] = RemoteDirectoryStorage(pid) - - std::vector mRemoteDirectories ; - LocalDirectoryStorage *mLocalSharedDirs ; - LocalDirectoryUpdater *mLocalDirWatcher ; - ftExtraList *mExtraFiles; - - // utility functions to make/get a pointer out of an (EntryIndex,PeerId) pair. This is further documented in the .cc - - template static bool convertEntryIndexToPointer(const EntryIndex &e, uint32_t friend_index, void *& p); - template static bool convertPointerToEntryIndex(const void *p, EntryIndex& e, uint32_t& friend_index) ; - - uint32_t locked_getFriendIndex(const RsPeerId& pid); - - void handleDirSyncRequest (RsFileListsSyncRequestItem *) ; - void handleDirSyncResponse (RsFileListsSyncResponseItem *&) ; - - std::map mFriendIndexMap ; - std::vector mFriendIndexTab; - - // Directory synchronization - // - struct DirSyncRequestData - { - RsPeerId peer_id ; - rstime_t request_TS ; - uint32_t flags ; - }; - - rstime_t mLastRemoteDirSweepTS ; // TS for friend list update - std::map mPendingSyncRequests ; // pending requests, waiting for an answer - std::map mPartialResponseItems; - - void locked_recursSweepRemoteDirectory(RemoteDirectoryStorage *rds, DirectoryStorage::EntryIndex e, int depth); - - // We use a shared file cache as well, to avoid re-hashing files with known modification TS and equal name. - // - HashStorage *mHashCache ; - - // Local flags and mutexes - - mutable RsMutex mFLSMtx ; - uint32_t mUpdateFlags ; - std::string mFileSharingDir ; - rstime_t mLastCleanupTime; - rstime_t mLastDataRecvTS ; - - // File filtering. Not explicitly related to shared files, but has its place here - // - - std::map mPrimaryBanList ; // primary list (user controlled) of files banned from FT search and forwarding. map - std::map mPeerBannedFiles ; // records of which files other peers ban, stored as H(H(f)) - std::set mBannedFileList ; // list of banned hashes. This include original hashs and H(H(f)) when coming from friends. - mutable std::vector mExtraFilesCache; // cache for extra files, to avoid requesting them too often. - mutable rstime_t mLastExtraFilesCacheUpdate ; - bool mTrustFriendNodesForBannedFiles ; - bool mBannedFileListNeedsUpdate; - rstime_t mLastPrimaryBanListChangeTimeStamp; - - void locked_sendBanInfo(const RsPeerId& pid); - void handleBannedFilesInfo(RsFileListsBannedHashesItem *item); -}; - diff --git a/libretroshare/src/file_sharing/rsfilelistitems.cc b/libretroshare/src/file_sharing/rsfilelistitems.cc deleted file mode 100644 index 4ac90af10..000000000 --- a/libretroshare/src/file_sharing/rsfilelistitems.cc +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: rsfilelistsitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 by Mr.Alice * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ -#include "serialiser/rsbaseserial.h" - -#include "serialiser/rstypeserializer.h" - -#include "file_sharing/rsfilelistitems.h" - -void RsFileListsSyncRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,entry_hash,"entry_hash") ; - RsTypeSerializer::serial_process(j,ctx,flags ,"flags") ; - RsTypeSerializer::serial_process(j,ctx,last_known_recurs_modf_TS,"last_known_recurs_modf_TS") ; - RsTypeSerializer::serial_process(j,ctx,request_id,"request_id") ; -} -void RsFileListsSyncResponseItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,entry_hash, "entry_hash") ; - RsTypeSerializer::serial_process (j,ctx,checksum, "checksum") ; - RsTypeSerializer::serial_process (j,ctx,flags, "flags") ; - RsTypeSerializer::serial_process (j,ctx,last_known_recurs_modf_TS,"last_known_recurs_modf_TS") ; - RsTypeSerializer::serial_process (j,ctx,request_id, "request_id") ; - RsTypeSerializer::serial_process(j,ctx,directory_content_data, "directory_content_data") ; -} -void RsFileListsBannedHashesItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,session_id ,"session_id") ; - RsTypeSerializer::serial_process(j,ctx,encrypted_hashes,"encrypted_hashes") ; -} -void RsFileListsBannedHashesConfigItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,primary_banned_files_list,"primary_banned_files_list") ; -} - -RsItem *RsFileListsSerialiser::create_item(uint16_t service,uint8_t type) const -{ - if(service != RS_SERVICE_TYPE_FILE_DATABASE) - return NULL ; - - switch(type) - { - case RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM: return new RsFileListsSyncRequestItem(); - case RS_PKT_SUBTYPE_FILELISTS_SYNC_RSP_ITEM: return new RsFileListsSyncResponseItem(); - case RS_PKT_SUBTYPE_FILELISTS_BANNED_HASHES_ITEM: return new RsFileListsBannedHashesItem(); - case RS_PKT_SUBTYPE_FILELISTS_BANNED_HASHES_CONFIG_ITEM: return new RsFileListsBannedHashesConfigItem(); - default: - return NULL ; - } -} -void RsFileListsSyncResponseItem::clear() -{ - directory_content_data.TlvClear(); -} diff --git a/libretroshare/src/file_sharing/rsfilelistitems.h b/libretroshare/src/file_sharing/rsfilelistitems.h deleted file mode 100644 index a8c84e18b..000000000 --- a/libretroshare/src/file_sharing/rsfilelistitems.h +++ /dev/null @@ -1,141 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: rsfilelistsitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 by Mr.Alice * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ -#pragma once - -#include -#include - -#include "rsitems/rsserviceids.h" -#include "rsitems/itempriorities.h" -#include "serialiser/rsserial.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvitem.h" -#include "serialiser/rstlvkeys.h" -#include "gxs/rsgxsdata.h" - -#include "serialiser/rsserializer.h" -#include "retroshare/rsfiles.h" - -const uint8_t RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM = 0x01; -const uint8_t RS_PKT_SUBTYPE_FILELISTS_SYNC_RSP_ITEM = 0x02; -const uint8_t RS_PKT_SUBTYPE_FILELISTS_CONFIG_ITEM = 0x03; -const uint8_t RS_PKT_SUBTYPE_FILELISTS_BANNED_HASHES_ITEM = 0x04; -const uint8_t RS_PKT_SUBTYPE_FILELISTS_BANNED_HASHES_CONFIG_ITEM = 0x05; - -/*! - * Base class for filelist sync items - */ -class RsFileListsItem : public RsItem -{ -public: - explicit RsFileListsItem(uint8_t subtype) - : RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_FILE_DATABASE, subtype) - { - setPriorityLevel(QOS_PRIORITY_RS_SLOW_SYNC_REQUEST); // this is the default. Someitems may be faster, on demand. - return; - } - virtual ~RsFileListsItem(){} - - virtual void clear() = 0; - - static const uint32_t FLAGS_SYNC_REQUEST = 0x0001 ; - static const uint32_t FLAGS_SYNC_RESPONSE = 0x0002 ; - static const uint32_t FLAGS_SYNC_DIR_CONTENT = 0x0004 ; - static const uint32_t FLAGS_ENTRY_UP_TO_DATE = 0x0008 ; - static const uint32_t FLAGS_ENTRY_WAS_REMOVED = 0x0010 ; - static const uint32_t FLAGS_SYNC_PARTIAL = 0x0020 ; - static const uint32_t FLAGS_SYNC_PARTIAL_END = 0x0040 ; -}; - -/*! - * Use to request synchronization on a specific directory. Also used to respond that the directory is up to date. - */ -class RsFileListsSyncRequestItem : public RsFileListsItem -{ -public: - - RsFileListsSyncRequestItem() : RsFileListsItem(RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM), flags(0), last_known_recurs_modf_TS(0), request_id(0) {} - - virtual void clear(){} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsFileHash entry_hash ; // hash of the directory to sync - uint32_t flags; // used to say that it's a request or a response, say that the directory has been removed, ask for further update, etc. - uint32_t last_known_recurs_modf_TS; // time of last modification, computed over all files+directories below. - uint64_t request_id; // use to determine if changes that have occured since last hash -}; - -class RsFileListsSyncResponseItem : public RsFileListsItem -{ -public: - - RsFileListsSyncResponseItem() : RsFileListsItem(RS_PKT_SUBTYPE_FILELISTS_SYNC_RSP_ITEM), flags(0), last_known_recurs_modf_TS(0), request_id(0) {} - - virtual void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsFileHash entry_hash ; // hash of the directory to sync - RsFileHash checksum ; // checksum of the bindary data, for checking - uint32_t flags; // is it a partial/final item (used for large items only) - uint32_t last_known_recurs_modf_TS; // time of last modification, computed over all files+directories below. - uint64_t request_id; // use to determine if changes that have occured since last hash - - RsTlvBinaryData directory_content_data ; // encoded binary data. This allows to vary the encoding format, in a way that is transparent to the serialiser. -}; - -class RsFileListsBannedHashesItem: public RsFileListsItem -{ -public: - RsFileListsBannedHashesItem() : RsFileListsItem(RS_PKT_SUBTYPE_FILELISTS_BANNED_HASHES_ITEM){} - - virtual void clear() { encrypted_hashes.clear(); } - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t session_id ; // used to allow to send in multiple parts. - std::set encrypted_hashes ;// hash of hash for each banned file. -}; - -class RsFileListsBannedHashesConfigItem: public RsFileListsItem -{ -public: - RsFileListsBannedHashesConfigItem() : RsFileListsItem(RS_PKT_SUBTYPE_FILELISTS_BANNED_HASHES_CONFIG_ITEM){} - - virtual void clear() { primary_banned_files_list.clear(); } - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - std::map primary_banned_files_list ; -}; - -class RsFileListsSerialiser : public RsServiceSerializer -{ -public: - - RsFileListsSerialiser() : RsServiceSerializer(RS_SERVICE_TYPE_FILE_DATABASE) {} - - virtual ~RsFileListsSerialiser() {} - - virtual RsItem *create_item(uint16_t service,uint8_t type) const ; -}; - - diff --git a/libretroshare/src/friend_server/fsclient.cc b/libretroshare/src/friend_server/fsclient.cc deleted file mode 100644 index 4104b0e6a..000000000 --- a/libretroshare/src/friend_server/fsclient.cc +++ /dev/null @@ -1,202 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: fsclient.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2021 by retroshare team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ - -#include "pqi/pqithreadstreamer.h" -#include "retroshare/rspeers.h" - -#include "fsclient.h" -#include "pqi/pqifdbin.h" -#include "pqi/pqiproxy.h" - -bool FsClient::requestFriends(const std::string& address,uint16_t port, - const std::string& proxy_address,uint16_t proxy_port, - uint32_t reqs,std::map& friend_certificates) -{ - // send our own certificate to publish and expects response frmo the server , decrypts it and reutnrs friend list - - RsFriendServerClientPublishItem *pitem = new RsFriendServerClientPublishItem(); - - pitem->n_requested_friends = reqs; - - std::string pgp_base64_string,pgp_base64_checksum,short_invite; - rsPeers->GetPGPBase64StringAndCheckSum(rsPeers->getGPGOwnId(),pgp_base64_string,pgp_base64_checksum); - - if(!rsPeers->getShortInvite(short_invite,RsPeerId(),RetroshareInviteFlags::RADIX_FORMAT | RetroshareInviteFlags::DNS)) - { - RsErr() << "Cannot request own short invite! Something's very wrong." ; - return false; - } - - pitem->pgp_public_key_b64 = pgp_base64_string; - pitem->short_invite = short_invite; - - std::list response; - sendItem(address,port,proxy_address,proxy_port,pitem,response); - - // now decode the response - - friend_certificates.clear(); - - for(auto item:response) - { - // auto *encrypted_response_item = dynamic_cast(item); - - // if(!encrypted_response_item) - // { - // delete item; - // continue; - // } - - // For now, also handle unencrypted response items. Will be disabled in production - - auto *response_item = dynamic_cast(item); - - if(response_item) - handleServerResponse(response_item); - - delete item; - } - return friend_certificates.size(); -} - -void FsClient::handleServerResponse(RsFriendServerServerResponseItem *item) -{ - std::cerr << "Received a response item from server: " << std::endl; - std::cerr << *item << std::endl; - - // for(const auto& it:response_item->friend_invites) - // friend_certificates.insert(it); -} - -bool FsClient::sendItem(const std::string& server_address,uint16_t server_port, - const std::string& proxy_address,uint16_t proxy_port, - RsItem *item,std::list& response) -{ - // open a connection - - RsDbg() << "Sending item to friend server at \"" << server_address << ":" << server_port << " through proxy " << proxy_address << ":" << proxy_port; - - int CreateSocket = 0; - char dataReceived[1024]; - struct sockaddr_in ipOfServer; - - memset(dataReceived, '0' ,sizeof(dataReceived)); - - if((CreateSocket = socket(AF_INET, SOCK_STREAM, 0))< 0) - { - printf("Socket not created \n"); - return 1; - } - - ipOfServer.sin_family = AF_INET; - ipOfServer.sin_port = htons(proxy_port); - ipOfServer.sin_addr.s_addr = inet_addr(proxy_address.c_str()); - - if(connect(CreateSocket, (struct sockaddr *)&ipOfServer, sizeof(ipOfServer))<0) - { - printf("Connection to proxy failed due to port and ip problems, or proxy is not available\n"); - return false; - } - - // Now connect to the proxy - - int ret=0; - pqiproxyconnection proxy; - proxy.setRemoteAddress(server_address); - proxy.setRemotePort(server_port); - - while(1 != (ret = proxy.proxy_negociate_connection(CreateSocket))) - if(ret < 0) - { - RsErr() << "FriendServer client: Connection problem to the proxy!" ; - return false; - } - else - std::this_thread::sleep_for(std::chrono::milliseconds(200)); - - // Serialise the item and send it. - - FsSerializer *fss = new FsSerializer; - RsSerialiser *rss = new RsSerialiser(); // deleted by ~pqistreamer() - rss->addSerialType(fss); - - RsFdBinInterface *bio = new RsFdBinInterface(CreateSocket,true); // deleted by ~pqistreamer() - - pqithreadstreamer p(this,rss,RsPeerId(),bio,BIN_FLAGS_READABLE | BIN_FLAGS_WRITEABLE | BIN_FLAGS_NO_CLOSE); - p.start(); - - uint32_t ss; - p.SendItem(item,ss); - - RsDbg() << "Item sent. Waiting for response..." ; - - // Now attempt to read and deserialize anything that comes back from that connexion until it gets closed by the server. - - while(true) - { - p.tick(); // ticks bio - - RsItem *item = GetItem(); -#ifdef DEBUG_FSCLIENT - RsDbg() << "Ticking for response..."; -#endif - if(item) - { - response.push_back(item); - std::cerr << "Got a response item: " << std::endl; - std::cerr << *item << std::endl; - - RsDbg() << "End of transmission. " ; - break; - } - else - std::this_thread::sleep_for(std::chrono::milliseconds(200)); - } - - RsDbg() << " Stopping/killing pqistreamer" ; - p.fullstop(); - - RsDbg() << " Closing socket." ; - close(CreateSocket); - CreateSocket=0; - - RsDbg() << " Exiting loop." ; - - return true; -} - -bool FsClient::RecvItem(RsItem *item) -{ - mIncomingItems.push_back(item); - return true; -} - -RsItem *FsClient::GetItem() -{ - if(mIncomingItems.empty()) - return nullptr; - - RsItem *item = mIncomingItems.front(); - mIncomingItems.pop_front(); - - return item; -} diff --git a/libretroshare/src/friend_server/fsclient.h b/libretroshare/src/friend_server/fsclient.h deleted file mode 100644 index b682a8bc4..000000000 --- a/libretroshare/src/friend_server/fsclient.h +++ /dev/null @@ -1,54 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: fsclient.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2021 by retroshare team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ - -#include -#include "fsitem.h" -#include "pqi/pqi_base.h" - -// This class runs a client connection to the friend server. It opens a socket at each connection. - -class FsClient: public PQInterface -{ -public: - FsClient() :PQInterface(RsPeerId()) {} - - bool requestFriends(const std::string& address, uint16_t port, - const std::string &proxy_address, uint16_t proxy_port, - uint32_t reqs, std::map& friend_certificates); - -protected: - // Implements PQInterface - - bool RecvItem(RsItem *item) override; - int SendItem(RsItem *) override { RsErr() << "FsClient::SendItem() called although it should not." ; return 0;} - RsItem *GetItem() override; - -private: - bool sendItem(const std::string &server_address, uint16_t server_port, - const std::string &proxy_address, uint16_t proxy_port, - RsItem *item, std::list &response); - - void handleServerResponse(RsFriendServerServerResponseItem *item); - - std::list mIncomingItems; -}; - diff --git a/libretroshare/src/friend_server/fsitem.h b/libretroshare/src/friend_server/fsitem.h deleted file mode 100644 index 95522b550..000000000 --- a/libretroshare/src/friend_server/fsitem.h +++ /dev/null @@ -1,185 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: fsitem.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2021 by retroshare team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ - -#pragma once - -#include "serialiser/rsserial.h" -#include "serialiser/rsserializer.h" - -#include "rsitems/rsitem.h" -#include "serialiser/rstlvbinary.h" -#include "rsitems/rsserviceids.h" -#include "rsitems/itempriorities.h" - -const uint8_t RS_PKT_SUBTYPE_FS_CLIENT_PUBLISH = 0x01 ; -const uint8_t RS_PKT_SUBTYPE_FS_CLIENT_REMOVE = 0x02 ; -const uint8_t RS_PKT_SUBTYPE_FS_SERVER_RESPONSE = 0x03 ; -const uint8_t RS_PKT_SUBTYPE_FS_SERVER_ENCRYPTED_RESPONSE = 0x04 ; -const uint8_t RS_PKT_SUBTYPE_FS_SERVER_STATUS = 0x05 ; - -class RsFriendServerItem: public RsItem -{ -public: - RsFriendServerItem(uint8_t item_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_FRIEND_SERVER,item_subtype) - { - setPriorityLevel(QOS_PRIORITY_DEFAULT) ; - } - virtual ~RsFriendServerItem() {} - virtual void clear() override {} -}; - -class RsFriendServerClientPublishItem: public RsFriendServerItem -{ -public: - RsFriendServerClientPublishItem() : RsFriendServerItem(RS_PKT_SUBTYPE_FS_CLIENT_PUBLISH) {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override - { - RS_SERIAL_PROCESS(n_requested_friends); - RS_SERIAL_PROCESS(short_invite); - RS_SERIAL_PROCESS(pgp_public_key_b64); - } - virtual void clear() override - { - pgp_public_key_b64.clear(); - short_invite.clear(); - n_requested_friends=0; - } - - // specific members for that item - - uint32_t n_requested_friends; - std::string short_invite; - std::string pgp_public_key_b64; -}; - -class RsFriendServerStatusItem: public RsFriendServerItem -{ -public: - RsFriendServerStatusItem() : RsFriendServerItem(RS_PKT_SUBTYPE_FS_SERVER_STATUS) {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override - { - RS_SERIAL_PROCESS(status); - } - - enum ConnectionStatus: uint8_t - { - UNKNOWN = 0x00, - END_OF_TRANSMISSION = 0x01 - }; - - // specific members for that item - - ConnectionStatus status; -}; - -class RsFriendServerClientRemoveItem: public RsFriendServerItem -{ -public: - RsFriendServerClientRemoveItem() : RsFriendServerItem(RS_PKT_SUBTYPE_FS_CLIENT_REMOVE) {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) - { - RS_SERIAL_PROCESS(peer_id); - RS_SERIAL_PROCESS(nonce); - } - - // Peer ID for the peer to remove. - - RsPeerId peer_id; - - // Nonce that was returned by the server after the last client request. Should match in order to proceed. This prevents - // a malicious actor from removing peers from the server. Since the nonce is sent through Tor tunnels, it cannot be known by - // anyone else than the client. - - uint64_t nonce; -}; - -class RsFriendServerEncryptedServerResponseItem: public RsFriendServerItem -{ -public: - RsFriendServerEncryptedServerResponseItem() : RsFriendServerItem(RS_PKT_SUBTYPE_FS_SERVER_ENCRYPTED_RESPONSE) {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override - { - RsTypeSerializer::RawMemoryWrapper prox(bin_data, bin_len); - RsTypeSerializer::serial_process(j, ctx, prox, "data"); - } - - virtual void clear() override - { - free(bin_data); - bin_len = 0; - bin_data = nullptr; - } - // - - void *bin_data; - uint32_t bin_len; -}; - -class RsFriendServerServerResponseItem: public RsFriendServerItem -{ -public: - RsFriendServerServerResponseItem() : RsFriendServerItem(RS_PKT_SUBTYPE_FS_SERVER_RESPONSE) {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override - { - RS_SERIAL_PROCESS(nonce); - RS_SERIAL_PROCESS(friend_invites); - } - - virtual void clear() override - { - friend_invites.clear(); - nonce = 0; - } - // specific members for that item - - uint64_t nonce; - std::map friend_invites; -}; - -struct FsSerializer : RsServiceSerializer -{ - FsSerializer(RsSerializationFlags flags = RsSerializationFlags::NONE): RsServiceSerializer(RS_SERVICE_TYPE_FRIEND_SERVER, flags) {} - - virtual RsItem *create_item(uint16_t service_id,uint8_t item_sub_id) const - { - if(service_id != static_cast(RsServiceType::FRIEND_SERVER)) - return nullptr; - - switch(item_sub_id) - { - case RS_PKT_SUBTYPE_FS_CLIENT_REMOVE: return new RsFriendServerClientRemoveItem(); - case RS_PKT_SUBTYPE_FS_CLIENT_PUBLISH: return new RsFriendServerClientPublishItem(); - case RS_PKT_SUBTYPE_FS_SERVER_RESPONSE: return new RsFriendServerServerResponseItem(); - case RS_PKT_SUBTYPE_FS_SERVER_STATUS: return new RsFriendServerStatusItem(); - case RS_PKT_SUBTYPE_FS_SERVER_ENCRYPTED_RESPONSE: return new RsFriendServerEncryptedServerResponseItem(); - default: - RsErr() << "Unknown subitem type " << item_sub_id << " in FsSerialiser" ; - return nullptr; - } - - } -}; diff --git a/libretroshare/src/friend_server/fsmanager.cc b/libretroshare/src/friend_server/fsmanager.cc deleted file mode 100644 index ff6571ef7..000000000 --- a/libretroshare/src/friend_server/fsmanager.cc +++ /dev/null @@ -1,123 +0,0 @@ -#include -#include "fsmanager.h" -#include "fsclient.h" - -RsFriendServer *rsFriendServer = nullptr; - -static const rstime_t MIN_DELAY_BETWEEN_FS_REQUESTS = 30; -static const rstime_t MAX_DELAY_BETWEEN_FS_REQUESTS = 3600; -static const uint32_t DEFAULT_FRIENDS_TO_REQUEST = 10; - -static const std::string DEFAULT_PROXY_ADDRESS = "127.0.0.1"; -static const uint16_t DEFAULT_FRIEND_SERVER_PORT = 2017; -static const uint16_t DEFAULT_PROXY_PORT = 9050; - -FriendServerManager::FriendServerManager() -{ - mLastFriendReqestCampain = 0; - mFriendsToRequest = DEFAULT_FRIENDS_TO_REQUEST; - - mProxyAddress = DEFAULT_PROXY_ADDRESS; - mProxyPort = DEFAULT_PROXY_PORT; - mServerPort = DEFAULT_FRIEND_SERVER_PORT; -} -void FriendServerManager::startServer() -{ - if(!isRunning()) - { - std::cerr << "Starting Friend Server Manager." << std::endl; - RsTickingThread::start() ; - } -} -void FriendServerManager::stopServer() -{ - if(isRunning() && !shouldStop()) - { - std::cerr << "Stopping Friend Server Manager." << std::endl; - RsTickingThread::askForStop() ; - } -} -void FriendServerManager::checkServerAddress_async(const std::string& addr,uint16_t, const std::function& callback) -{ -#warning TODO - std::this_thread::sleep_for(std::chrono::seconds(1)); - - callback(addr,true); -} - -void FriendServerManager::setServerAddress(const std::string& addr,uint16_t port) -{ - mServerAddress = addr; - mServerPort = port; -} -void FriendServerManager::setProxyAddress(const std::string& addr,uint16_t port) -{ - mProxyAddress = addr; - mProxyPort = port; -} -void FriendServerManager::setFriendsToRequest(uint32_t n) -{ - mFriendsToRequest = n; -} - -void FriendServerManager::threadTick() -{ - std::cerr << "Ticking FriendServerManager..." << std::endl; - std::this_thread::sleep_for(std::chrono::seconds(2)); - - if(mServerAddress.empty()) - { - RsErr() << "No friend server address has been setup. This is probably a bug."; - return; - } - // Check for requests. Compute how much to wait based on how many friends we have already - - std::vector friends; - rsPeers->getPgpFriendList(friends); - - // log-scale interpolation of the delay between two requests. - - if(mFriendsToRequest == 0 || mFriendsToRequest < friends.size()) - { - RsErr() << "No friends to request! This is unexpected. Returning." << std::endl; - return; - } - - // This formula makes RS wait much longuer between two requests to the server when the number of friends is close the - // wanted number - // Delay for 0 friends: 30 secs. - // Delay for 1 friends: 30 secs. - // Delay for 2 friends: 32 secs. - // Delay for 3 friends: 35 secs. - // Delay for 4 friends: 44 secs. - // Delay for 5 friends: 66 secs. - // Delay for 6 friends: 121 secs. - // Delay for 7 friends: 258 secs. - // Delay for 8 friends: 603 secs. - // Delay for 9 friends: 1466 secs. - - RsDbg() << friends.size() << " friends already, " << mFriendsToRequest << " friends to request"; - - double s = (friends.size() < mFriendsToRequest)? ( (mFriendsToRequest - friends.size())/(double)mFriendsToRequest) : 1.0; - rstime_t delay_for_request = MIN_DELAY_BETWEEN_FS_REQUESTS + (int)floor(exp(-1*s + log(MAX_DELAY_BETWEEN_FS_REQUESTS)*(1.0-s))); - - std::cerr << "Delay for " << friends.size() << " friends: " << delay_for_request << " secs." << std::endl; - - rstime_t now = time(nullptr); - - if(mLastFriendReqestCampain + delay_for_request < now) - { - mLastFriendReqestCampain = now; - - std::cerr << "Requesting new friends to friend server..." << std::endl; - - std::map friend_certificates; - FsClient().requestFriends(mServerAddress,mServerPort,mProxyAddress,mProxyPort,mFriendsToRequest,friend_certificates); // blocking call - - std::cerr << "Got the following list of friend certificates:" << std::endl; - - for(const auto& it:friend_certificates) - std::cerr << it.first << " : " << it.second << std::endl; - } -} - diff --git a/libretroshare/src/friend_server/fsmanager.h b/libretroshare/src/friend_server/fsmanager.h deleted file mode 100644 index 583a5febc..000000000 --- a/libretroshare/src/friend_server/fsmanager.h +++ /dev/null @@ -1,51 +0,0 @@ -#include - -#include "util/rsthreads.h" -#include "retroshare/rsfriendserver.h" -#include "retroshare/rspeers.h" - -struct FriendServerPeerInfo -{ - enum FriendServerPeerStatus: uint8_t - { - UNKNOWN = 0x00, - LOCALLY_ACCEPTED = 0x01, - HAS_ACCEPTED_ME = 0x02, - ALREADY_CONNECTED = 0x03 - }; - - uint32_t status ; - rstime_t received_TS; -}; - -class FriendServerManager: public RsFriendServer, public RsTickingThread -{ -public: - FriendServerManager(); - - virtual void startServer() override ; - virtual void stopServer() override ; - - virtual void checkServerAddress_async(const std::string& addr,uint16_t, const std::function& callback) override ; - virtual void setServerAddress(const std::string&,uint16_t) override ; - virtual void setProxyAddress(const std::string&,uint16_t) override ; - virtual void setFriendsToRequest(uint32_t) override ; - - virtual uint32_t friendsToRequest() override { return mFriendsToRequest ; } - virtual uint16_t friendsServerPort() override { return mServerPort ; } - virtual std::string friendsServerAddress() override { return mServerAddress ; } -protected: - virtual void threadTick() override; - -private: - uint32_t mFriendsToRequest; - rstime_t mLastFriendReqestCampain; - - // encode the current list of friends obtained through the friendserver and their status - - std::map mPeers; - std::string mServerAddress ; - uint16_t mServerPort; - std::string mProxyAddress ; - uint16_t mProxyPort; -}; diff --git a/libretroshare/src/ft/ftchunkmap.cc b/libretroshare/src/ft/ftchunkmap.cc deleted file mode 100644 index 8b0c60007..000000000 --- a/libretroshare/src/ft/ftchunkmap.cc +++ /dev/null @@ -1,708 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftchunkmap.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ - -/******** - * #define DEBUG_FTCHUNK 1 - *********/ - -#ifdef DEBUG_FTCHUNK -#include -#endif -#include -#include -#include "retroshare/rspeers.h" -#include "ftchunkmap.h" -#include "util/rstime.h" - -static const uint32_t SOURCE_CHUNK_MAP_UPDATE_PERIOD = 60 ; //! TTL for chunkmap info -static const uint32_t INACTIVE_CHUNK_TIME_LAPSE = 3600 ; //! TTL for an inactive chunk -static const uint32_t FT_CHUNKMAP_MAX_CHUNK_JUMP = 50 ; //! Maximum chunk jump in progressive DL mode -static const uint32_t FT_CHUNKMAP_MAX_SLICE_REASK_DELAY = 10 ; //! Maximum time to re-ask a slice to another peer at end of transfer - -std::ostream& operator<<(std::ostream& o,const ftChunk& c) -{ - return o << "\tChunk [" << c.offset << "] size: " << c.size << " ChunkId: " << c.id << " Age: " << time(NULL) - c.ts << ", owner: " << c.peer_id ; -} - -// Chunk: very bold implementation for now. We should compress the bits to have -// 32 of them per uint32_t value, of course! -// -Chunk::Chunk(uint64_t start,uint32_t size) - : _start(start),_offset(start),_end( (uint64_t)size + start ) -{ -} - -void Chunk::getSlice(uint32_t size_hint,ftChunk& chunk) -{ - // Take the current offset - chunk.offset = _offset ; - chunk.size = std::min(size_hint,(uint32_t)(_end-_offset)) ; - chunk.id = _offset ; - chunk.ts = time(NULL) ; - - // push the slice marker into currently handled slices. - _offset += chunk.size ; -} - -ChunkMap::ChunkMap(uint64_t s,bool availability) - : _file_size(s), - _chunk_size(CHUNKMAP_FIXED_CHUNK_SIZE), // 1MB chunks - _assume_availability(availability) -{ - uint64_t n = s/(uint64_t)_chunk_size ; - if(s% (uint64_t)_chunk_size != 0) - ++n ; - - _map.resize(n,FileChunksInfo::CHUNK_OUTSTANDING) ; - _strategy = FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE ; - _total_downloaded = 0 ; - _file_is_complete = false ; -#ifdef DEBUG_FTCHUNK - std::cerr << "*** ChunkMap::ChunkMap: starting new chunkmap:" << std::endl ; - std::cerr << " File size: " << s << std::endl ; - std::cerr << " Strategy: " << _strategy << std::endl ; - std::cerr << " ChunkSize: " << _chunk_size << std::endl ; - std::cerr << " Number of Chunks: " << n << std::endl ; - std::cerr << " Data: " ; - for(uint32_t i=0;i<_map.size();++i) - std::cerr << _map[i] ; - std::cerr << std::endl ; -#endif -} - -void ChunkMap::setAvailabilityMap(const CompressedChunkMap& map) -{ - // do some sanity check - // - - if( (((int)_map.size()-1)>>5) >= (int)map._map.size() ) - { - std::cerr << "ChunkMap::setPeerAvailabilityMap: Compressed chunkmap received is too small or corrupted." << std::endl; - return ; - } - - // copy the map - // - _file_is_complete = true ; - _total_downloaded = 0 ; - - for(uint32_t i=0;i<_map.size();++i) - if(map[i] > 0) - { - _map[i] = FileChunksInfo::CHUNK_DONE ; - _total_downloaded += sizeOfChunk(i) ; - } - else - { - _map[i] = FileChunksInfo::CHUNK_OUTSTANDING ; - _file_is_complete = false ; - } -} - -void ChunkMap::dataReceived(const ftChunk::OffsetInFile& cid) -{ - // 1 - find which chunk contains the received data. - // - - // trick: cid is the chunk offset. So we use it to get the chunk number. - int n = (uint64_t)cid/_chunk_size ; - - std::map::iterator itc(_slices_to_download.find(n)) ; - - if(itc == _slices_to_download.end()) - { - std::cerr << "!!! ChunkMap::dataReceived: error: ChunkId " << cid << " corresponds to chunk number " << n << ", which is not being downloaded!" << std::endl ; -#ifdef DEBUG_FTCHUNK - assert(false) ; -#endif - return ; - } - - std::map::iterator it(itc->second._slices.find(cid)) ; - - if(it == itc->second._slices.end()) - { - std::cerr << "!!! ChunkMap::dataReceived: chunk " << cid << " is not found in slice lst of chunk number " << n << std::endl ; -#ifdef DEBUG_FTCHUNK - assert(false) ; -#endif - return ; - } - - _total_downloaded += it->second.size ; - itc->second._remains -= it->second.size ; - itc->second._slices.erase(it) ; - itc->second._last_data_received = time(NULL) ; // update time stamp - -#ifdef DEBUG_FTCHUNK - std::cerr << "*** ChunkMap::dataReceived: received data chunk " << cid << " for chunk number " << n << ", local remains=" << itc->second._remains << ", total downloaded=" << _total_downloaded << ", remains=" << _file_size - _total_downloaded << std::endl ; -#endif - if(itc->second._remains == 0) // the chunk was completely downloaded - { -#ifdef DEBUG_FTCHUNK - std::cerr << "*** ChunkMap::dataReceived: Chunk is complete. Removing it." << std::endl ; -#endif - - _map[n] = FileChunksInfo::CHUNK_CHECKING ; - - if(n > 0 || _file_size > CHUNKMAP_FIXED_CHUNK_SIZE) // dont' put <1MB files into checking mode. This is useless. - _chunks_checking_queue.push_back(n) ; - else - _map[n] = FileChunksInfo::CHUNK_DONE ; - - _slices_to_download.erase(itc) ; - - updateTotalDownloaded() ; - } -} - -void ChunkMap::updateTotalDownloaded() -{ - _total_downloaded = 0 ; - _file_is_complete = true ; - - // First, round over chunk map to get the raw info. - // - for(uint32_t i=0;i<_map.size();++i) - switch(_map[i]) - { - case FileChunksInfo::CHUNK_CHECKING: _file_is_complete = false ; - /* fallthrough */ - case FileChunksInfo::CHUNK_DONE: _total_downloaded += sizeOfChunk(i) ; - break ; - default: - _file_is_complete = false ; - } - - // Then go through active chunks. - // - for(std::map::const_iterator itc(_slices_to_download.begin());itc!=_slices_to_download.end();++itc) - { - if(_map[itc->first] == FileChunksInfo::CHUNK_CHECKING) - _total_downloaded -= sizeOfChunk(itc->first) ; - - _total_downloaded += sizeOfChunk(itc->first) - itc->second._remains ; - - if(_file_is_complete) - std::cerr << "ChunkMap::updateTotalDownloaded(): ERROR: file still has pending slices but all chunks are marked as DONE !!" << std::endl; - } -} - -void ChunkMap::getChunksToCheck(std::vector& chunks_crc_to_ask) -{ - chunks_crc_to_ask.clear() ; - - for(uint32_t i=0;i<_chunks_checking_queue.size();) - { - chunks_crc_to_ask.push_back(_chunks_checking_queue[i]) ; - - // remove that chunk from the queue - - _chunks_checking_queue[i] = _chunks_checking_queue.back() ; - _chunks_checking_queue.pop_back() ; - } -} - -void ChunkMap::setChunkCheckingResult(uint32_t chunk_number,bool check_succeeded) -{ - // Find the chunk is the waiting queue. Remove it, and mark it as done. - // - if(_map[chunk_number] != FileChunksInfo::CHUNK_CHECKING) - { - std::cerr << "(EE) ChunkMap: asked to set checking result of chunk " << chunk_number<< " that is not marked as being checked!!" << std::endl; - return ; - } - - if(check_succeeded) - { - _map[chunk_number] = FileChunksInfo::CHUNK_DONE ; - - // We also check whether the file is complete or not. - - _file_is_complete = true ; - - for(uint32_t i=0;i<_map.size();++i) - if(_map[i] != FileChunksInfo::CHUNK_DONE) - { - _file_is_complete = false ; - break ; - } - } - else - { - _total_downloaded -= sizeOfChunk(chunk_number) ; // restore completion. - _map[chunk_number] = FileChunksInfo::CHUNK_OUTSTANDING ; - } -} - -bool ChunkMap::reAskPendingChunk( const RsPeerId& peer_id, - uint32_t /*size_hint*/, - uint64_t& offset, uint32_t& size) -{ - // make sure that we're at the end of the file. No need to be too greedy in the middle of it. - - for(uint32_t i=0;i<_map.size();++i) - if(_map[i] == FileChunksInfo::CHUNK_OUTSTANDING) - return false ; - - rstime_t now = time(NULL); - - for(std::map::iterator it(_slices_to_download.begin());it!=_slices_to_download.end();++it) - for(std::map::iterator it2(it->second._slices.begin());it2!=it->second._slices.end();++it2) - if(it2->second.request_time + FT_CHUNKMAP_MAX_SLICE_REASK_DELAY < now && it2->second.peers.end()==it2->second.peers.find(peer_id)) - { - offset = it2->first; - size = it2->second.size ; - -#ifdef DEBUG_FTCHUNK - std::cerr << "*** ChunkMap::reAskPendingChunk: re-asking slice (" << offset << ", " << size << ") to peer " << peer_id << std::endl; -#endif - - it2->second.request_time = now ; - it2->second.peers.insert(peer_id) ; - - return true ; - } - - return false ; -} - -// Warning: a chunk may be empty, but still being downloaded, so asking new slices from it -// will produce slices of size 0. This happens at the end of each chunk. -// --> I need to get slices from the next chunk, in such a case. -// --> solution: -// - have too chunks maps: -// 1 indexed by peer id to feed the getChunk method -// - chunks pushed when new chunks are needed -// - chunks removed when empty -// 1 indexed by chunk id to account for chunks being downloaded -// - chunks pushed when new chunks are needed -// - chunks removed when completely downloaded -// -bool ChunkMap::getDataChunk(const RsPeerId& peer_id,uint32_t size_hint,ftChunk& chunk,bool& source_chunk_map_needed) -{ -#ifdef DEBUG_FTCHUNK - std::cerr << "*** ChunkMap::getDataChunk: size_hint = " << size_hint << std::endl ; -#endif - // 1 - find if this peer already has an active chunk. - // - std::map::iterator it = _active_chunks_feed.find(peer_id) ; - std::map::iterator falsafe_it = _active_chunks_feed.end() ; - - if(it == _active_chunks_feed.end()) - { - SourceChunksInfo *sci = getSourceChunksInfo(peer_id) ; - - // 0 - Look into other pending chunks and slice from here. We only consider chunks with size smaller than - // the requested size, - // - for(std::map::iterator pit(_active_chunks_feed.begin());pit!=_active_chunks_feed.end();++pit) - { - uint32_t c = pit->second._start / _chunk_size ; - - if(!(sci->is_full || sci->cmap[c])) // check that the chunk is available for requested peer. - continue ; - - ChunkDownloadInfo& cdi(_slices_to_download[c]) ; - falsafe_it = pit ; // let's keep this one just in case. - - if(cdi._slices.rbegin() != cdi._slices.rend() && cdi._slices.rbegin()->second.size*0.7 <= (float)size_hint) - { - it = pit ; -#ifdef DEBUG_FTCHUNK - std::cerr << "*** ChunkMap::getDataChunk: Sharing slice " << pit->second._start << " of peer " << pit->first << " for peer " << peer_id << std::endl; -#endif - break ; - } -#ifdef DEBUG_FTCHUNK - else - std::cerr << "*** ChunkMap::getDataChunk: Not Sharing slice " << pit->second._start << " of peer " << pit->first << " for peer " << peer_id << ", because current peer is too slow" << std::endl; -#endif - } - - if(it == _active_chunks_feed.end()) // not found. Find a new chunk. - { - // 1 - select an available chunk id for this peer. - // - uint32_t c = getAvailableChunk(peer_id,source_chunk_map_needed) ; - - if(c >= _map.size()) - if(falsafe_it != _active_chunks_feed.end()) // no chunk available. Let's see if we can still take an active--faster--chunk. - { - it = falsafe_it ; -#ifdef DEBUG_FTCHUNK - std::cerr << "*** ChunkMap::getDataChunk: Using falsafe chunk " << it->second._start << " of peer " << it->first << " for peer " << peer_id << std::endl; -#endif - } - else - return false ; // no more availabel chunks, no falsafe case. - else - { - // 2 - add the chunk in the list of active chunks, and mark it as being downloaded - // - uint32_t soc = sizeOfChunk(c) ; - _active_chunks_feed[peer_id] = Chunk( c*(uint64_t)_chunk_size, soc ) ; - _map[c] = FileChunksInfo::CHUNK_ACTIVE ; - _slices_to_download[c]._remains = soc ; // init the list of slices to download - it = _active_chunks_feed.find(peer_id) ; -#ifdef DEBUG_FTCHUNK - std::cout << "*** ChunkMap::getDataChunk: Allocating new chunk " << c << " for peer " << peer_id << std::endl ; -#endif - } - } - } -#ifdef DEBUG_FTCHUNK - else - std::cout << "*** ChunkMap::getDataChunk: Re-using chunk " << it->second._start/_chunk_size << " for peer " << peer_id << std::endl ; -#endif - - // Get the first slice of the chunk, that is at most of length size - // - it->second.getSlice(size_hint,chunk) ; - _slices_to_download[chunk.offset/_chunk_size]._last_data_received = time(NULL) ; - - ChunkDownloadInfo::SliceRequestInfo& r(_slices_to_download[chunk.offset/_chunk_size]._slices[chunk.id]); - - r.size = chunk.size ; - r.request_time = time(NULL); - r.peers.insert(peer_id); - - chunk.peer_id = peer_id ; - -#ifdef DEBUG_FTCHUNK - std::cout << "*** ChunkMap::getDataChunk: returning slice " << chunk << " for peer " << it->first << std::endl ; -#endif - if(it->second.empty()) - _active_chunks_feed.erase(it) ; - - return true ; -} - -void ChunkMap::removeInactiveChunks(std::vector& to_remove) -{ - to_remove.clear() ; - rstime_t now = time(NULL) ; - - for(std::map::iterator it(_slices_to_download.begin());it!=_slices_to_download.end();) - if(now - it->second._last_data_received > (int)INACTIVE_CHUNK_TIME_LAPSE) - { -#ifdef DEBUG_FTCHUNK - std::cerr << "ChunkMap::removeInactiveChunks(): removing inactive chunk " << it->first << ", time lapse=" << now - it->second._last_data_received << std::endl ; -#endif - // First, remove all slices from this chunk - // - std::map::iterator tmp(it) ; - - for(std::map::const_iterator it2(it->second._slices.begin());it2!=it->second._slices.end();++it2) - to_remove.push_back(it2->first) ; - - _map[it->first] = FileChunksInfo::CHUNK_OUTSTANDING ; // reset the chunk - - _total_downloaded -= (sizeOfChunk(it->first) - it->second._remains) ; // restore completion. - - // Also remove the chunk from the chunk feed, to free the associated peer. - // - for(std::map::iterator it3=_active_chunks_feed.begin();it3!=_active_chunks_feed.end();) - if(it3->second._start == _chunk_size*uint64_t(it->first)) - { - std::map::iterator tmp3 = it3 ; - ++it3 ; - _active_chunks_feed.erase(tmp3) ; - } - else - ++it3 ; - - ++it ; - _slices_to_download.erase(tmp) ; - } - else - ++it ; -} - -bool ChunkMap::isChunkAvailable(uint64_t offset, uint32_t chunk_size) const -{ - return hasChunkState(offset, chunk_size, FileChunksInfo::CHUNK_DONE); -} - -bool ChunkMap::isChunkOutstanding(uint64_t offset, uint32_t chunk_size) const -{ - return hasChunkState(offset, chunk_size, FileChunksInfo::CHUNK_OUTSTANDING); -} - -bool ChunkMap::hasChunkState(uint64_t offset, uint32_t chunk_size, FileChunksInfo::ChunkState state) const -{ - uint32_t chunk_number_start = offset/(uint64_t)_chunk_size ; - uint32_t chunk_number_end = (offset+(uint64_t)chunk_size)/(uint64_t)_chunk_size ; - - if((offset+(uint64_t)chunk_size) % (uint64_t)_chunk_size != 0) - ++chunk_number_end ; - - // It's possible that chunk_number_start==chunk_number_end+1, but for this we need to have - // chunk_size=0, and offset%_chunk_size=0, so the response "true" is still valid. - // - for(uint32_t i=chunk_number_start;i::iterator it(_peers_chunks_availability.find(peer_id)) ; - - // Do we have a chunk map for this file source ? - // - if yes, we use it - // - if no, - // - if availability is assumed, let's build a plain chunkmap for it - // - otherwise, refuse the transfer, but still ask for the chunkmap - // - // We first test whether the source has a record of not. If not, we fill a new record. - // For availability sources we fill it plain, otherwise, we fill it blank. - // - if(it == _peers_chunks_availability.end()) - { - SourceChunksInfo& pchunks(_peers_chunks_availability[peer_id]) ; - - // Ok, we don't have the info, so two cases: - // - peer_id is a not a turtle peer, so he is considered having the full file source, so we init with a plain chunkmap - // - otherwise, a source map needs to be obtained, so we init with a blank chunkmap - // - if(_assume_availability) - { - pchunks.cmap._map.resize( CompressedChunkMap::getCompressedSize(_map.size()),~(uint32_t)0 ) ; - pchunks.TS = 0 ; - pchunks.is_full = true ; - } - else - { - pchunks.cmap._map.resize( CompressedChunkMap::getCompressedSize(_map.size()),0 ) ; - pchunks.TS = 0 ; - pchunks.is_full = false ; - } - - it = _peers_chunks_availability.find(peer_id) ; - } - return &(it->second) ; -} - -void ChunkMap::getSourcesList(uint32_t chunk_number,std::vector& sources) -{ - sources.clear() ; - - for(std::map::const_iterator it(_peers_chunks_availability.begin());it!=_peers_chunks_availability.end();++it) - if(it->second.cmap[chunk_number]) - sources.push_back(it->first) ; -} - -uint32_t ChunkMap::getAvailableChunk(const RsPeerId& peer_id,bool& map_is_too_old) -{ - // Quite simple strategy: Check for 1st availabe chunk for this peer starting from the given start location. - // - SourceChunksInfo *peer_chunks = getSourceChunksInfo(peer_id) ; - - // If the info is too old, we ask for a new one. When the map is full, we ask 10 times less, as it's probably not - // useful to get a new map that will also be full, but because we need to be careful not to mislead information, - // we still keep asking. - // - rstime_t now = time(NULL) ; - - if((!peer_chunks->is_full) && ((int)now - (int)peer_chunks->TS > (int)SOURCE_CHUNK_MAP_UPDATE_PERIOD)) - { - map_is_too_old = true ;// We will re-ask but not before some seconds. - peer_chunks->TS = now ; - } - else - map_is_too_old = false ;// the map is not too old - - uint32_t available_chunks = 0 ; - uint32_t available_chunks_before_max_dist = 0 ; - - for(unsigned int i=0;i<_map.size();++i) - if(_map[i] == FileChunksInfo::CHUNK_OUTSTANDING) - { - if(peer_chunks->is_full || peer_chunks->cmap[i]) - ++available_chunks ; - } - else - available_chunks_before_max_dist = available_chunks ; - - if(available_chunks > 0) - { - uint32_t chosen_chunk_number ; - - switch(_strategy) - { - case FileChunksInfo::CHUNK_STRATEGY_STREAMING: chosen_chunk_number = 0 ; - break ; - case FileChunksInfo::CHUNK_STRATEGY_RANDOM: chosen_chunk_number = rand() % available_chunks ; - break ; - case FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE: chosen_chunk_number = rand() % std::min(available_chunks, available_chunks_before_max_dist+FT_CHUNKMAP_MAX_CHUNK_JUMP) ; - break ; - default: - chosen_chunk_number = 0 ; - } - uint32_t j=0 ; - - for(uint32_t i=0;i<_map.size();++i) - if(_map[i] == FileChunksInfo::CHUNK_OUTSTANDING && (peer_chunks->is_full || peer_chunks->cmap[i])) - { - if(j == chosen_chunk_number) - { -#ifdef DEBUG_FTCHUNK - std::cerr << "ChunkMap::getAvailableChunk: returning chunk " << i << " for peer " << peer_id << std::endl; -#endif - return i ; - } - else - ++j ; - } - } - -#ifdef DEBUG_FTCHUNK - std::cout << "!!! ChunkMap::getAvailableChunk: No available chunk from peer " << peer_id << ": returning false" << std::endl ; -#endif - return _map.size() ; -} - -void ChunkMap::getChunksInfo(FileChunksInfo& info) const -{ - info.file_size = _file_size ; - info.chunk_size = _chunk_size ; - info.chunks = _map ; - info.strategy = _strategy ; - - info.active_chunks.clear() ; - - for(std::map::const_iterator it(_slices_to_download.begin());it!=_slices_to_download.end();++it) - info.active_chunks.push_back(std::pair(it->first,it->second._remains)) ; - - info.compressed_peer_availability_maps.clear() ; - - for(std::map::const_iterator it(_peers_chunks_availability.begin());it!=_peers_chunks_availability.end();++it) - info.compressed_peer_availability_maps[it->first] = it->second.cmap ; -} - -void ChunkMap::removeFileSource(const RsPeerId& peer_id) -{ - std::map::iterator it(_peers_chunks_availability.find(peer_id)) ; - - if(it == _peers_chunks_availability.end()) - return ; - - _peers_chunks_availability.erase(it) ; -} - -void ChunkMap::getAvailabilityMap(CompressedChunkMap& compressed_map) const -{ - compressed_map = CompressedChunkMap(_map) ; - -#ifdef DEBUG_FTCHUNK - std::cerr << "ChunkMap:: retrieved availability map of size " << _map.size() << ", chunk_size=" << _chunk_size << std::endl ; -#endif -} - -void ChunkMap::forceCheck() -{ - for(uint32_t i=0;i<_map.size();++i) - { - _map[i] = FileChunksInfo::CHUNK_CHECKING ; - _chunks_checking_queue.push_back(i) ; - } - - updateTotalDownloaded() ; -} - -uint32_t ChunkMap::getNumberOfChunks(uint64_t size) -{ - uint64_t n = size/(uint64_t)CHUNKMAP_FIXED_CHUNK_SIZE ; - - if(size % (uint64_t)CHUNKMAP_FIXED_CHUNK_SIZE != 0) - ++n ; - - uint32_t value = n & 0xffffffffull ; - - if((uint64_t)value != n) - { - std::cerr << "ERROR: number of chunks is a totally absurd value. File size is " << size << ", chunks are " << n << "!!" << std::endl ; - return 0 ; - } - return value ; -} - -void ChunkMap::buildPlainMap(uint64_t size, CompressedChunkMap& map) -{ - uint32_t n = getNumberOfChunks(size) ; - - map = CompressedChunkMap(n,~uint32_t(0)) ; -} - - diff --git a/libretroshare/src/ft/ftchunkmap.h b/libretroshare/src/ft/ftchunkmap.h deleted file mode 100644 index a9e7eb900..000000000 --- a/libretroshare/src/ft/ftchunkmap.h +++ /dev/null @@ -1,260 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftchunkmap.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ - -#pragma once - -#include -#include "retroshare/rstypes.h" - -// ftChunkMap: -// - handles chunk map over a complete file -// - mark down which chunk is being downloaded by which peer -// - allocate data ranges of any requested size for a given peer -// - continuing an existing chunk -// - allocating a new chunk -// -// Download mecanism: -// - ftFileCreator handles a list of active slices, and periodically resends requests every 20 sec. -// Slices have arbitrary size (less than a chunk), depending on the transfer rate. -// When receiving data, ftFileCreator shrinks its slices until they get complete. When a slice is finished, it -// notifies ftChunkMap that this slice is done. -// -// - ftChunkMap maintains two levels: -// - the chunk level (Chunks a 1MB long) with a map of who has which chunk and what locally is the state of -// each chunk -// - the slice level: each active chunk is cut into slices (basically a list of intervalls) being downloaded, and -// a remaining slice to cut off new candidates. When notified for a complete slice, ftChunkMap removed the -// corresponding acive slice. When asked a slice, ftChunkMap cuts out a slice from the remaining part of the chunk -// to download, sends the slice's coordinates and gives a unique slice id (such as the slice offset). - - -// This class handles a slice of a chunk of arbitrary uint32_t size, at the level of ftFileCreator - -class ftController ; - -class ftChunk -{ - public: - typedef uint64_t OffsetInFile ; - - ftChunk():offset(0), size(0), id(0), ts(0),ref_cnt(NULL) {} - - friend std::ostream& operator<<(std::ostream& o,const ftChunk& f) ; - - uint64_t offset; // current offset of the slice - uint64_t size; // size remaining to download - OffsetInFile id ; // id of the chunk. Equal to the starting offset of the chunk - rstime_t ts; // time of last data received - int *ref_cnt; // shared counter of number of sub-blocks. Used when a slice gets split. - RsPeerId peer_id ; -}; - -// This class handles a single fixed-sized chunk. Although each chunk is requested at once, -// it may be sent back into sub-chunks because of file transfer rate constraints. -// So the dataReceived function should be called to progressively complete the chunk, -// and the getChunk method should ask for a sub-chunk of a given size. -// -class Chunk -{ - public: - Chunk(): _start(0),_offset(0),_end(0) {} // only used in default std::map fillers - - Chunk(uint64_t start,uint32_t size) ; - - void getSlice(uint32_t size_hint,ftChunk& chunk) ; - - // Returns true when the chunk is complete - bool empty() const { return _offset == _end ; } - - // Array of intervalls of bytes to download. - // - uint64_t _start ; // const - uint64_t _offset ; // not const: handles the current offset within the chunk. - uint64_t _end ; // const -}; - -struct ChunkDownloadInfo -{ - public: - struct SliceRequestInfo - { - uint32_t size ; // size of the slice - rstime_t request_time ; // last request time - std::set peers ; // peers the slice was requested to. Normally only one, except at the end of the file. - }; - - std::map _slices ; - uint32_t _remains ; - rstime_t _last_data_received ; -}; - -class SourceChunksInfo -{ - public: - CompressedChunkMap cmap ; //! map of what the peer has/doens't have - rstime_t TS ; //! last update time for this info - bool is_full ; //! is the map full ? In such a case, re-asking for it is unnecessary. - - // Returns true if the offset is starting in a mapped chunk. - // - bool hasData(uint64_t offset,uint32_t fixed_chunk_size) const - { - if(is_full) - return true ; - - return cmap[offset / (uint64_t)fixed_chunk_size ] ; - } -}; - -class ChunkMap -{ - public: - static const uint32_t CHUNKMAP_FIXED_CHUNK_SIZE = 1024*1024 ; // 1 MB chunk - typedef uint32_t ChunkNumber ; - - /// Constructor. Decides what will be the size of chunks and how many there will be. - - ChunkMap(uint64_t file_size,bool assume_availability) ; - - /// destructor - virtual ~ChunkMap() {} - - /// Returns an slice of data to be asked to the peer within a chunk. - /// If a chunk is already been downloaded by this peer, take a slice at - /// the beginning of this chunk, or at least where it starts. - /// If not, randomly/streamly select a new chunk depending on the strategy. - /// adds an entry in the chunk_ids map, and sets up 1 interval for it. - /// the chunk should be available from the designated peer. - /// On return: - /// - source_chunk_map_needed = true if the source map should be asked - - virtual bool getDataChunk(const RsPeerId& peer_id,uint32_t size_hint,ftChunk& chunk,bool& source_chunk_map_needed) ; - - /// Returns an already pending slice that was being downloaded but hasn't arrived yet. This is mostly used at the end of the file - /// in order to re-ask pendign slices to active peers while slow peers take a lot of time to send their remaining slices. - /// - bool reAskPendingChunk(const RsPeerId& peer_id,uint32_t size_hint,uint64_t& offset,uint32_t& size); - - /// Notify received a slice of data. This needs to - /// - carve in the map of chunks what is received, what is not. - /// - tell which chunks are finished. For this, each interval must know what chunk number it has been attributed - /// when the interval is split in the middle, the number of intervals for the chunk is increased. If the interval is - /// completely covered by the data, the interval number is decreased. - - virtual void dataReceived(const ftChunk::OffsetInFile& c_id) ; - - /// Decides how chunks are selected. - /// STREAMING: the 1st chunk is always returned - /// RANDOM: a uniformly random chunk is selected among available chunks for the current source. - /// - - void setStrategy(FileChunksInfo::ChunkStrategy s) { _strategy = s ; } - FileChunksInfo::ChunkStrategy getStrategy() const { return _strategy ; } - - /// Properly fills an vector of fixed size chunks with availability or download state. - /// chunks is given with the proper number of chunks and we have to adapt to it. This can be used - /// to display square chunks in the gui or display a blue bar of availability by collapsing info from all peers. - /// The set method is not virtual because it has no reason to exist in the parent ftFileProvider - - virtual void getAvailabilityMap(CompressedChunkMap& cmap) const ; - void setAvailabilityMap(const CompressedChunkMap& cmap) ; - - /// Removes the source availability map. The map - void removeFileSource(const RsPeerId& peer_id) ; - - /// This function fills in a plain map for a file of the given size. This - /// is used to ensure that the chunk size will be consistent with the rest - /// of the code. - // - static void buildPlainMap(uint64_t size,CompressedChunkMap& map) ; - - /// Computes the number of chunks for the given file size. - static uint32_t getNumberOfChunks(uint64_t size) ; - - /// This function is used by the parent ftFileProvider to know whether the chunk can be sent or not. - bool isChunkAvailable(uint64_t offset, uint32_t chunk_size) const ; - - bool isChunkOutstanding(uint64_t offset, uint32_t chunk_size) const ; - - /// Remove active chunks that have not received any data for the last 60 seconds, and return - /// the list of slice numbers that should be canceled. - void removeInactiveChunks(std::vector& to_remove) ; - - /// Updates the peer's availablility map - // - void setPeerAvailabilityMap(const RsPeerId& peer_id,const CompressedChunkMap& peer_map) ; - - /// Returns a pointer to the availability chunk map of the given source, and possibly - /// allocates it if necessary. - // - SourceChunksInfo *getSourceChunksInfo(const RsPeerId& peer_id) ; - - /// Returns the total size of downloaded data in the file. - uint64_t getTotalReceived() const { return _total_downloaded ; } - - /// returns true is the file is complete - bool isComplete() const { return _file_is_complete ; } - - /// returns info about currently downloaded chunks - void getChunksInfo(FileChunksInfo& info) const ; - - /// input the result of the chunk hash checking - void setChunkCheckingResult(uint32_t chunk_number, bool succeed) ; - - /// returns the current list of chunks to ask for a CRC, and a proposed source for each - void getChunksToCheck(std::vector& chunks_to_ask) ; - - /// Get all available sources for this chunk - void getSourcesList(uint32_t chunk_number,std::vector& sources) ; - - /// sets all chunks to checking state - void forceCheck() ; - - /// Goes through all structures and computes the actual file completion. The true completion - /// gets lost when force checking the file. - void updateTotalDownloaded() ; - - protected: - /// handles what size the last chunk has. - uint32_t sizeOfChunk(uint32_t chunk_number) const ; - - /// Returns a chunk available for this peer_id, depending on the chunk strategy. - // - uint32_t getAvailableChunk(const RsPeerId& peer_id,bool& chunk_map_too_old) ; - - private: - bool hasChunkState(uint64_t offset, uint32_t chunk_size, FileChunksInfo::ChunkState state) const; - - uint64_t _file_size ; //! total size of the file in bytes. - uint32_t _chunk_size ; //! Size of chunks. Common to all chunks. - FileChunksInfo::ChunkStrategy _strategy ; //! how do we allocate new chunks - std::map _active_chunks_feed ; //! vector of chunks being downloaded. Exactly 1 chunk per peer. - std::map _slices_to_download ; //! list of (slice offset,slice size) currently being downloaded - std::vector _map ; //! vector of chunk state over the whole file - std::map _peers_chunks_availability ; //! what does each source peer have - uint64_t _total_downloaded ; //! completion for the file - bool _file_is_complete ; //! set to true when the file is complete. - bool _assume_availability ; //! true if all sources always have the complete file. - std::vector _chunks_checking_queue ; //! Queue of downloaded chunks to be checked. -}; - - diff --git a/libretroshare/src/ft/ftcontroller.cc b/libretroshare/src/ft/ftcontroller.cc deleted file mode 100644 index e14e1920f..000000000 --- a/libretroshare/src/ft/ftcontroller.cc +++ /dev/null @@ -1,2275 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftcontroller.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -/* - * ftController - * - * Top level download controller. - * - * inherits configuration (save downloading files) - * inherits pqiMonitor (knows which peers are online). - * inherits CacheTransfer (transfers cache files too) - * inherits RsThread (to control transfers) - * - */ - -#ifdef WINDOWS_SYS -#include "util/rsstring.h" -#endif -#include "util/rsdiscspace.h" -#include "util/rsmemory.h" -#include "util/rstime.h" -#include "util/cxx17retrocompat.h" -#include "ft/ftcontroller.h" - -#include "ft/ftfilecreator.h" -#include "ft/fttransfermodule.h" -#include "ft/ftsearch.h" -#include "ft/ftdatamultiplex.h" -#include "ft/ftextralist.h" -#include "ft/ftserver.h" - -#include "turtle/p3turtle.h" - -#include "util/rsdir.h" -#include "rsserver/p3face.h" - -#include "pqi/p3linkmgr.h" - -#include "retroshare/rsiface.h" -#include "retroshare/rspeers.h" - -#include "rsitems/rsconfigitems.h" -#include -#include /* for (u)sleep() */ -#include "util/rstime.h" - -/****** - * #define CONTROL_DEBUG 1 - * #define DEBUG_DWLQUEUE 1 - *****/ - -static const int32_t SAVE_TRANSFERS_DELAY = 301 ; // save transfer progress every 301 seconds. -static const int32_t INACTIVE_CHUNKS_CHECK_DELAY = 240 ; // time after which an inactive chunk is released -static const int32_t MAX_TIME_INACTIVE_REQUEUED = 120 ; // time after which an inactive ftFileControl is bt-queued - -static const int32_t FT_FILECONTROL_QUEUE_ADD_END = 0 ; -static const int32_t FT_FILECONTROL_MAX_UPLOAD_SLOTS_DEFAULT= 0 ; - -const uint32_t FT_CNTRL_STANDARD_RATE = 10 * 1024 * 1024; -const uint32_t FT_CNTRL_SLOW_RATE = 100 * 1024; - -ftFileControl::ftFileControl() - :mTransfer(NULL), mCreator(NULL), - mState(DOWNLOADING), mSize(0), mFlags(0), mCreateTime(0), mQueuePriority(0), mQueuePosition(0) -{ - return; -} - -ftFileControl::ftFileControl(const std::string& fname, const std::string& tmppath, const std::string& dest - , uint64_t size, const RsFileHash &hash, TransferRequestFlags flags - , ftFileCreator *fc, ftTransferModule *tm) - : mName(fname), mCurrentPath(tmppath), mDestination(dest) - , mTransfer(tm), mCreator(fc), mState(DOWNLOADING), mHash(hash) - , mSize(size), mFlags(flags), mCreateTime(0), mQueuePriority(0), mQueuePosition(0) -{} - -ftController::ftController(ftDataMultiplex *dm, p3ServiceControl *sc, uint32_t ftServiceId) - : p3Config(), - last_save_time(0), - last_clean_time(0), - mSearch(NULL), - mDataplex(dm), - mExtraList(NULL), - mTurtle(NULL), - mFtServer(NULL), - mServiceCtrl(sc), - mFtServiceType(ftServiceId), - mDefaultEncryptionPolicy(RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE), - mFilePermDirectDLPolicy(RS_FILE_PERM_DIRECT_DL_PER_USER), - cnt(0), - ctrlMutex("ftController"), - doneMutex("ftController"), - mFtActive(false), - mFtPendingDone(false), - mDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE), - _max_active_downloads(5), // default queue size - _max_uploads_per_friend(FT_FILECONTROL_MAX_UPLOAD_SLOTS_DEFAULT) -{ -} - -void ftController::setTurtleRouter(p3turtle *pt) { mTurtle = pt ; } -void ftController::setFtServer(ftServer *ft) { mFtServer = ft ; } - -void ftController::setFtSearchNExtra(ftSearch *search, ftExtraList *list) -{ - mSearch = search; - mExtraList = list; -} - -bool ftController::getFileDownloadChunksDetails(const RsFileHash& hash,FileChunksInfo& info) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - std::map::iterator it = mDownloads.find(hash) ; - - if(it != mDownloads.end()) - { - it->second->mCreator->getChunkMap(info) ; - //info.flags = it->second->mFlags ; - - return true ; - } - - it = mCompleted.find(hash) ; - - if(it != mCompleted.end()) - { - // This should rather be done as a static method of ChunkMap. - // - // We do this manually, because the file creator has already been destroyed. - // - info.file_size = it->second->mSize ; - info.strategy = mDefaultChunkStrategy ; - info.chunk_size = ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE ; - //info.flags = it->second->mFlags ; - uint32_t nb_chunks = it->second->mSize/ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE ; - if(it->second->mSize % ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE != 0) - ++nb_chunks ; - info.chunks.resize(nb_chunks,FileChunksInfo::CHUNK_DONE) ; - - return true ; - } - - return false ; -} - -void ftController::addFileSource(const RsFileHash& hash,const RsPeerId& peer_id) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - std::map::iterator it = mDownloads.find(hash); - -#ifdef CONTROL_DEBUG - std::cerr << "ftController: Adding source " << peer_id << " to current download hash=" << hash ; -#endif - if(it != mDownloads.end()) - { - it->second->mTransfer->addFileSource(peer_id); - setPeerState(it->second->mTransfer, peer_id, FT_CNTRL_STANDARD_RATE, mServiceCtrl->isPeerConnected(mFtServiceType, peer_id )); - -#ifdef CONTROL_DEBUG - std::cerr << "... added." << std::endl ; -#endif - return ; - } -#ifdef CONTROL_DEBUG - std::cerr << "... not added: hash not found." << std::endl ; -#endif -} -void ftController::removeFileSource(const RsFileHash& hash,const RsPeerId& peer_id) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - std::map::iterator it = mDownloads.find(hash); - -#ifdef CONTROL_DEBUG - std::cerr << "ftController: Adding source " << peer_id << " to current download hash=" << hash ; -#endif - if(it != mDownloads.end()) - { - it->second->mTransfer->removeFileSource(peer_id); - it->second->mCreator->removeFileSource(peer_id); - -#ifdef CONTROL_DEBUG - std::cerr << "... added." << std::endl ; -#endif - return ; - } -#ifdef CONTROL_DEBUG - std::cerr << "... not added: hash not found." << std::endl ; -#endif -} -void ftController::threadTick() -{ - /* check the queues */ - - //Waiting 1 sec before start - rstime::rs_usleep(1*1000*1000); // 1 sec - -#ifdef CONTROL_DEBUG - //std::cerr << "ftController::run()"; - //std::cerr << std::endl; -#endif - bool doPending = false; - { - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - doPending = (mFtActive) && (!mFtPendingDone); - } - - rstime_t now = time(NULL) ; - if(now > last_save_time + SAVE_TRANSFERS_DELAY) - { - IndicateConfigChanged() ; - last_save_time = now ; - } - - if(now > last_clean_time + INACTIVE_CHUNKS_CHECK_DELAY) - { - searchForDirectSources() ; - - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - for(std::map::iterator it(mDownloads.begin());it!=mDownloads.end();++it) - it->second->mCreator->removeInactiveChunks() ; - - last_clean_time = now ; - } - - if (doPending) - { - if (!handleAPendingRequest()) - { - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - mFtPendingDone = true; - } - } - - tickTransfers() ; - - { - std::list files_to_complete ; - - { - RsStackMutex stack2(doneMutex); - files_to_complete = mDone ; - mDone.clear(); - } - - for(std::list::iterator it(files_to_complete.begin()); it != files_to_complete.end(); ++it) - completeFile(*it); - } - - if(cnt++ % 10 == 0) - checkDownloadQueue() ; -} - -void ftController::searchForDirectSources() -{ -#ifdef CONTROL_DEBUG - std::cerr << "ftController::searchForDirectSources()" << std::endl; -#endif - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - if (!mSearch) - { -#ifdef CONTROL_DEBUG - std::cerr << " search module not available!" << std::endl; -#endif - return; - } - - for(std::map::iterator it(mDownloads.begin()); it != mDownloads.end(); ++it ) - if(it->second->mState != ftFileControl::QUEUED && it->second->mState != ftFileControl::PAUSED ) - { -#ifdef CONTROL_DEBUG - std::cerr << " file " << it->first << ":" << std::endl; -#endif - FileInfo info ; // Info needs to be re-allocated each time, to start with a clear list of peers (it's not cleared down there) - - if( mSearch->search(it->first, RS_FILE_HINTS_REMOTE | RS_FILE_HINTS_SPEC_ONLY, info) ) - for( std::vector::const_iterator pit = info.peers.begin(); pit != info.peers.end(); ++pit ) - { - bool bAllowDirectDL = false; - switch (mFilePermDirectDLPolicy) { - case RS_FILE_PERM_DIRECT_DL_YES: bAllowDirectDL = true; break; - case RS_FILE_PERM_DIRECT_DL_NO: bAllowDirectDL = false; break; - default:bAllowDirectDL = (rsPeers->servicePermissionFlags(pit->peerId) & RS_NODE_PERM_DIRECT_DL); break; - } - if( bAllowDirectDL ) - if( it->second->mTransfer->addFileSource(pit->peerId) ) /* if the sources don't exist already - add in */ - setPeerState( it->second->mTransfer, pit->peerId, FT_CNTRL_STANDARD_RATE, mServiceCtrl->isPeerConnected(mFtServiceType, pit->peerId) ); -#ifdef CONTROL_DEBUG - std::cerr << " found source " << pit->peerId << ", allowDirectDL=" << bAllowDirectDL << ". " << (bAllowDirectDL?"adding":"not adding") << std::endl; -#endif - } -#ifdef CONTROL_DEBUG - else - std::cerr << " search returned empty.: " << std::endl; -#endif - } -#ifdef CONTROL_DEBUG - else - std::cerr << " file " << it->first << ": state is " << it->second->mState << ": ignored." << std::endl; -#endif -} - -void ftController::tickTransfers() -{ - // 1 - sort modules into arrays according to priority - - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - -#ifdef CONTROL_DEBUG - // std::cerr << "ticking transfers." << std::endl ; -#endif - // Collect all non queued files. - // - for(std::map::iterator it(mDownloads.begin()); it != mDownloads.end(); ++it) - if(it->second->mState != ftFileControl::QUEUED && it->second->mState != ftFileControl::PAUSED) - it->second->mTransfer->tick() ; -} - -bool ftController::getPriority(const RsFileHash& hash,DwlSpeed& p) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - std::map::iterator it(mDownloads.find(hash)) ; - - if(it != mDownloads.end()) - { - p = it->second->mTransfer->downloadPriority() ; - return true ; - } - else - return false ; -} - -void ftController::setPriority(const RsFileHash& hash,DwlSpeed p) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - std::map::iterator it(mDownloads.find(hash)) ; - - if(it != mDownloads.end()) - it->second->mTransfer->setDownloadPriority(p) ; -} - -/* Called every 10 seconds or so */ -void ftController::checkDownloadQueue() -{ - // We do multiple things here: - // - // 0 - make sure all transfers have a consistent value for mDownloadQueue - // - // 1 - are there queued files ? - // - // YES - // 1.1 - check for inactive files (see below). - // - select one inactive file - // - close it temporarily - // - remove it from turtle handling - // - move the ftFileControl to queued list - // - set the queue priority to 1+largest in the queue. - // 1.2 - pop from the queue the 1st file to come (according to availability of sources, then priority) - // - enable turtle router handling for this hash - // - reset counters - // - set the file as waiting - // NO - // Do nothing, because no files are waiting. - // - // 2 - in FileRequest, if the max number of downloaded files is exceeded, put the - // file in the queue list, and don't enable the turtle router handling. - // - // Implementation: - // - locate a hash in the queue - // - move hashes in the queue up/down/top/bottom - // - now the place of each ftFileControl element in the queue to activate/desactive them - // - // So: - // - change mDownloads to be a std::map - // - sort the ftFileControl* into a std::vector - // - store the queue position of each ftFileControl* into its own structure (mQueuePosition member) - // - // We don't want the turtle router to keep openning tunnels for queued files, so we only base - // the notion of inactive on the fact that no traffic happens for the file within 5 mins. - // - // How do we detect inactive files? - // For a downld file: - no traffic for 5 min. - - RsStackMutex mtx(ctrlMutex) ; - -#ifdef DEBUG_DWLQUEUE - std::cerr << "Checking download queue." << std::endl ; -#endif - if(mDownloads.size() <= _max_active_downloads) - return ; - - std::vector inactive_transfers ; - std::vector transfers_with_online_sources ; - - std::set online_peers ; - mServiceCtrl->getPeersConnected(mFtServiceType,online_peers) ; - - // Check for inactive transfers, and queued transfers with online sources. - // - rstime_t now = time(NULL) ; - - for(std::map::const_iterator it(mDownloads.begin());it!=mDownloads.end() ;++it) - if( it->second->mState != ftFileControl::QUEUED && (it->second->mState == ftFileControl::PAUSED - || now > it->second->mTransfer->lastActvTimeStamp() + (rstime_t)MAX_TIME_INACTIVE_REQUEUED)) - { - inactive_transfers.push_back(it->second) ; - } - else if(it->second->mState == ftFileControl::QUEUED) - { - std::list srcs ; - it->second->mTransfer->getFileSources(srcs) ; - - for(std::list::const_iterator it2(srcs.begin());it2!=srcs.end();++it2) - if(online_peers.find(*it2) != online_peers.end()) - { - transfers_with_online_sources.push_back(it->second) ; - break ; - } - } - -#ifdef DEBUG_DWLQUEUE - std::cerr << "Identified " << inactive_transfers.size() << " inactive transfer, and " << transfers_with_online_sources.size() << " queued transfers with online sources." << std::endl; -#endif - - // first swap as many queued transfers with online sources with inactive transfers - uint32_t i=0; - - for(;imName << " at position " << inactive_transfers[i]->mQueuePosition << " with transfer at position " << transfers_with_online_sources[i]->mQueuePosition << " which has available sources." << std::endl; -#endif - inactive_transfers[i]->mTransfer->resetActvTimeStamp() ; // very important! - transfers_with_online_sources[i]->mTransfer->resetActvTimeStamp() ; // very important! - - locked_swapQueue(inactive_transfers[i]->mQueuePosition,transfers_with_online_sources[i]->mQueuePosition); - } - - // now if some inactive transfers remain, put them at the end of the queue. - - for(;imName << " at position " << inactive_transfers[i]->mQueuePosition << " moved to end of the queue. mState=" << inactive_transfers[i]->mState << ", time lapse=" << now - it->second->mCreator->lastActvTimeStamp() << std::endl ; -#endif - locked_bottomQueue(inactive_transfers[i]->mQueuePosition) ; -#ifdef DEBUG_DWLQUEUE - std::cerr << " new position: " << inactive_transfers[i]->mQueuePosition << std::endl ; - std::cerr << " new state: " << inactive_transfers[i]->mState << std::endl ; -#endif - inactive_transfers[i]->mTransfer->resetActvTimeStamp() ; // very important! - } - - // finally, do a full swab over the queue to make sure that the expected number of downloads is met. - - for(uint32_t i=0;i::iterator it(mDownloads.find(hash)) ; - - if(it == mDownloads.end()) - { - std::cerr << "ftController::moveInQueue: can't find hash " << hash << " in the download list." << std::endl ; - return ; - } - uint32_t pos = it->second->mQueuePosition ; - -#ifdef DEBUG_DWLQUEUE - std::cerr << "Moving file " << hash << ", pos=" << pos << " to new pos." << std::endl ; -#endif - switch(mv) - { - case QUEUE_TOP: locked_topQueue(pos) ; - break ; - - case QUEUE_BOTTOM: locked_bottomQueue(pos) ; - break ; - - case QUEUE_UP: if(pos > 0) - locked_swapQueue(pos,pos-1) ; - break ; - - case QUEUE_DOWN: if(pos < mDownloadQueue.size()-1) - locked_swapQueue(pos,pos+1) ; - break ; - default: - std::cerr << "ftController::moveInQueue: unknown move " << mv << std::endl ; - } -} - -void ftController::locked_topQueue(uint32_t pos) -{ - ftFileControl *tmp=mDownloadQueue[pos] ; - - for(int p=pos;p>0;--p) - { - mDownloadQueue[p]=mDownloadQueue[p-1] ; - locked_checkQueueElement(p) ; - } - mDownloadQueue[0]=tmp ; - - locked_checkQueueElement(0) ; -} -void ftController::locked_bottomQueue(uint32_t pos) -{ - ftFileControl *tmp=mDownloadQueue[pos] ; - - for(uint32_t p=pos;pmQueuePosition = pos ; - - if(pos < _max_active_downloads && mDownloadQueue[pos]->mState != ftFileControl::PAUSED) - { - if(mDownloadQueue[pos]->mState == ftFileControl::QUEUED) - mDownloadQueue[pos]->mTransfer->resetActvTimeStamp() ; - - mDownloadQueue[pos]->mState = ftFileControl::DOWNLOADING ; - - if(mDownloadQueue[pos]->mFlags & RS_FILE_REQ_ANONYMOUS_ROUTING) - mFtServer->activateTunnels(mDownloadQueue[pos]->mHash,mDefaultEncryptionPolicy,mDownloadQueue[pos]->mFlags,true); - } - - if(pos >= _max_active_downloads && mDownloadQueue[pos]->mState != ftFileControl::QUEUED && mDownloadQueue[pos]->mState != ftFileControl::PAUSED) - { - mDownloadQueue[pos]->mState = ftFileControl::QUEUED ; - mDownloadQueue[pos]->mCreator->closeFile() ; - - if(mDownloadQueue[pos]->mFlags & RS_FILE_REQ_ANONYMOUS_ROUTING) - mFtServer->activateTunnels(mDownloadQueue[pos]->mHash,mDefaultEncryptionPolicy,mDownloadQueue[pos]->mFlags,false); - } -} - -bool ftController::FlagFileComplete(const RsFileHash& hash) -{ - RsStackMutex stack2(doneMutex); - mDone.push_back(hash); - -#ifdef CONTROL_DEBUG - std::cerr << "ftController:FlagFileComplete(" << hash << ")"; - std::cerr << std::endl; -#endif - - return true; -} - -bool ftController::completeFile(const RsFileHash& hash) -{ - /* variables... so we can drop mutex later */ - std::string path; - std::string name; - uint64_t size = 0; - uint32_t period = 0; - TransferRequestFlags flags ; - TransferRequestFlags extraflags ; - - { - RS_STACK_MUTEX(ctrlMutex); - -#ifdef CONTROL_DEBUG - std::cerr << "ftController:completeFile(" << hash << ")"; - std::cerr << std::endl; -#endif - std::map::iterator it(mDownloads.find(hash)); - - if (it == mDownloads.end()) - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController:completeFile(" << hash << ")"; - std::cerr << " Not Found!"; - std::cerr << std::endl; -#endif - return false; - } - - /* check if finished */ - if (!(it->second)->mCreator->finished()) - { - /* not done! */ -#ifdef CONTROL_DEBUG - std::cerr << "ftController:completeFile(" << hash << ")"; - std::cerr << " Transfer Not Done"; - std::cerr << std::endl; - - std::cerr << "FileSize: "; - std::cerr << (it->second)->mCreator->getFileSize(); - std::cerr << " and Recvd: "; - std::cerr << (it->second)->mCreator->getRecvd(); -#endif - return false; - } - - - ftFileControl *fc = it->second; - - // (csoler) I've postponed this to the end of the block because deleting the - // element from the map calls the destructor of fc->mTransfer, which - // makes fc to point to nothing and causes random behavior/crashes. - // - // mDataplex->removeTransferModule(fc->mTransfer->hash()); - // - /* done - cleanup */ - - // (csoler) I'm copying this because "delete fc->mTransfer" deletes the hash string! - RsFileHash hash_to_suppress(fc->mTransfer->hash()); - - // This should be done that early, because once the file creator is - // deleted, it should not be accessed by the data multiplex anymore! - // - mDataplex->removeTransferModule(hash_to_suppress) ; - - if (fc->mTransfer) - { - delete fc->mTransfer; - fc->mTransfer = NULL; - } - - if (fc->mCreator) - { - fc->mCreator->closeFile() ; - delete fc->mCreator; - fc->mCreator = NULL; - } - - fc->mState = ftFileControl::COMPLETED; - - std::string dst_dir,src_dir,src_file,dst_file ; - - RsDirUtil::splitDirFromFile(fc->mCurrentPath,src_dir,src_file) ; - RsDirUtil::splitDirFromFile(fc->mDestination,dst_dir,dst_file) ; - - // We use this intermediate file in case the destination directory is not available, so as to not keep the partial file name. - std::string intermediate_file_name = RsDirUtil::makePath(src_dir, dst_file); - - // I don't know how the size can be zero, but believe me, this happens, - // and it causes an error on linux because then the file may not even exist. - // - if( fc->mSize == 0) - fc->mState = ftFileControl::ERROR_COMPLETION; - else - { - std::cerr << "CompleteFile(): renaming " << fc->mCurrentPath << " into " << fc->mDestination << std::endl; - std::cerr << "CompleteFile(): 1 - renaming " << fc->mCurrentPath << " info " << intermediate_file_name << std::endl; - - if(RsDirUtil::moveFile(fc->mCurrentPath,intermediate_file_name) ) - { - fc->mCurrentPath = intermediate_file_name ; - - std::cerr << "CompleteFile(): 2 - renaming/copying " << intermediate_file_name << " into " << fc->mDestination << std::endl; - - if(RsDirUtil::moveFile(intermediate_file_name,fc->mDestination) ) - fc->mCurrentPath = fc->mDestination; - else - fc->mState = ftFileControl::ERROR_COMPLETION; - } - else - fc->mState = ftFileControl::ERROR_COMPLETION; - } - - /* for extralist additions */ - path = fc->mDestination; - name = fc->mName; - //hash = fc->mHash; - size = fc->mSize; - period = 30 * 24 * 3600; /* 30 days */ - extraflags.clear() ; - -#ifdef CONTROL_DEBUG - std::cerr << "CompleteFile(): size = " << size << std::endl ; -#endif - - flags = fc->mFlags ; - - locked_queueRemove(it->second->mQueuePosition) ; - - /* switch map */ - mCompleted[fc->mHash] = fc; - - mDownloads.erase(it); - - if(flags & RS_FILE_REQ_ANONYMOUS_ROUTING) - mFtServer->activateTunnels(hash_to_suppress,mDefaultEncryptionPolicy,flags,false); - - } // UNLOCK: RS_STACK_MUTEX(ctrlMutex); - - - /******************** NO Mutex from Now ******************** - * cos Callback can end up back in this class. - ***********************************************************/ - - /* If it has a callback - do it now */ - - if(flags & RS_FILE_REQ_EXTRA)// | RS_FILE_HINTS_MEDIA)) - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController::completeFile() adding to ExtraList"; - std::cerr << std::endl; -#endif - - if(mExtraList) - mExtraList->addExtraFile(path, hash, size, period, extraflags); - } - else - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController::completeFile() No callback"; - std::cerr << std::endl; -#endif - } - - /* Notify GUI */ - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mHash = hash; - ev->mFileTransferEventCode = RsFileTransferEventCode::DOWNLOAD_COMPLETE; - rsEvents->postEvent(ev); - } - - rsFiles->ForceDirectoryCheck(true) ; - - IndicateConfigChanged(); /* completed transfer -> save */ - return true; -} - - /***************************************************************/ - /********************** Controller Access **********************/ - /***************************************************************/ - -bool ftController::activate() -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - mFtActive = true; - mFtPendingDone = false; - return true; -} - -bool ftController::isActiveAndNoPending() -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - return (mFtActive && mFtPendingDone); -} - -bool ftController::handleAPendingRequest() -{ - uint32_t nb_requests_handled = 0 ; - static const uint32_t MAX_SIMULTANEOUS_PENDING_REQUESTS = 100 ; - - while(!mPendingRequests.empty() && nb_requests_handled++ < MAX_SIMULTANEOUS_PENDING_REQUESTS) - { - ftPendingRequest req; - { - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - req = mPendingRequests.front(); - mPendingRequests.pop_front(); - } -#ifdef CONTROL_DEBUG - std::cerr << "Requesting pending hash " << req.mHash << std::endl ; -#endif - - FileRequest(req.mName, req.mHash, req.mSize, req.mDest, TransferRequestFlags(req.mFlags), req.mSrcIds, req.mState); - - { - // See whether there is a pendign chunk map recorded for this hash. - // - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - std::map::iterator it(mPendingChunkMaps.find(req.mHash)) ; - - if(it != mPendingChunkMaps.end()) - { - RsFileTransfer *rsft = it->second ; - std::map::iterator fit = mDownloads.find(rsft->file.hash); - - if((fit==mDownloads.end() || (fit->second)->mCreator == NULL)) - { - // This should never happen, because the last call to FileRequest must have created the fileCreator!! - // - std::cerr << "ftController::loadList(): Error: could not find hash " << rsft->file.hash << " in mDownloads list !" << std::endl ; - } - else - { -#ifdef CONTROL_DEBUG - std::cerr << "Hash " << req.mHash << " is in downloads" << std::endl ; - std::cerr << " setting chunk strategy to " << rsft->chunk_strategy << std::endl; -#endif - (fit->second)->mCreator->setAvailabilityMap(rsft->compressed_chunk_map) ; - (fit->second)->mCreator->setChunkStrategy((FileChunksInfo::ChunkStrategy)(rsft->chunk_strategy)) ; - (fit->second)->mState=rsft->state; - } - - delete rsft ; - mPendingChunkMaps.erase(it) ; - } -#ifdef CONTROL_DEBUG - else - std::cerr << "No pending chunkmap for hash " << req.mHash << std::endl ; -#endif - } - } - return !mPendingRequests.empty(); -} - -bool ftController::alreadyHaveFile(const RsFileHash& hash, FileInfo &info) -{ - // check for downloads - if (FileDetails(hash, info) && (info.downloadStatus == FT_STATE_COMPLETE)) - return true ; - - // check for file lists - if (!mSearch) return false; - if (mSearch->search(hash, RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_SPEC_ONLY, info)) - return true ; - - return false ; -} - -bool ftController::FileRequest( - const std::string& fname, const RsFileHash& hash, uint64_t size, - const std::string& dest, TransferRequestFlags flags, - const std::list &_srcIds, uint16_t state ) -{ - /* TODO: To support collections faithfully we need to be able to save - * the same file to multiple locations, both if already downloaded or - * incomplete */ - - std::list srcIds(_srcIds) ; - - /* check if we have the file */ - - FileInfo info; - if(alreadyHaveFile(hash, info)) - return false ; - - // the strategy for requesting encryption is the following: - // - // if policy is STRICT - // - disable clear, enforce encryption - // else - // - if not specified, use both - // - if(mDefaultEncryptionPolicy == RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT) - { - flags |= RS_FILE_REQ_ENCRYPTED ; - flags &= ~RS_FILE_REQ_UNENCRYPTED ; - } - else if(!(flags & ( RS_FILE_REQ_ENCRYPTED | RS_FILE_REQ_UNENCRYPTED ))) - { - flags |= RS_FILE_REQ_ENCRYPTED ; - flags |= RS_FILE_REQ_UNENCRYPTED ; - } - - if(size == 0) // we treat this special case because - { - /* if no destpath - send to download directory */ - std::string destination ; - - if (dest == "") - destination = mDownloadPath + "/" + fname; - else - destination = dest + "/" + fname; - - // create void file with the target name. - FILE *f = RsDirUtil::rs_fopen(destination.c_str(),"w") ; - if(!f) - RsErr() << __PRETTY_FUNCTION__ << " Could not write file " - << destination << std::endl; - else - fclose(f) ; - - return true ; - } - - // Bugs in the cache system can cause files with arbitrary size to be - // requested, causing a division by zero in ftChunkMap when size > 1MB * - // (2^32-1). I thus conservatively check for large size values. - // - if(size >= 1024ull*1024ull*((1ull << 32) - 1)) - { - RsErr() << __PRETTY_FUNCTION__ - << " unexpected size. This is probably a bug." - << " name = " << fname - << " flags = " << flags - << " dest = " << dest - << " size = " << size << std::endl; - return false; - } - - /* If file transfer is not enabled .... - * save request for later. This will also - * mean that we will have to copy local files, - * or have a callback which says: local file. - */ - - { - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - if (!mFtActive) - { - /* store in pending queue */ - ftPendingRequest req(fname, hash, size, dest, flags, srcIds,state); - mPendingRequests.push_back(req); - return true; - } - } - - /* remove the sources from the list, if they don't have clearance for direct - * transfer. This happens only for non cache files. */ - for(std::list::iterator it = srcIds.begin(); it != srcIds.end(); ) - { - bool bAllowDirectDL = false; - switch (mFilePermDirectDLPolicy) { - case RS_FILE_PERM_DIRECT_DL_YES: bAllowDirectDL = true; break; - case RS_FILE_PERM_DIRECT_DL_NO: bAllowDirectDL = false; break; - default:bAllowDirectDL = (rsPeers->servicePermissionFlags(*it) & RS_NODE_PERM_DIRECT_DL); break; - } - - if(!bAllowDirectDL) - { - std::list::iterator tmp(it); - ++tmp; - srcIds.erase(it); - it = tmp; - } - else - ++it; - } - - std::list::const_iterator it; - std::vector::const_iterator pit; - -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileRequest(" << fname << ","; - std::cerr << hash << "," << size << "," << dest << ","; - std::cerr << flags << ",<"; - - for(it = srcIds.begin(); it != srcIds.end(); ++it) - { - std::cerr << *it << ","; - } - std::cerr << ">)"; - std::cerr << std::endl; -#endif - - uint32_t rate = 0; - if (flags & RS_FILE_REQ_BACKGROUND) - rate = FT_CNTRL_SLOW_RATE; - else - rate = FT_CNTRL_STANDARD_RATE; - - /* First check if the file is already being downloaded.... - * This is important as some guis request duplicate files regularly. - */ - - { - RS_STACK_MUTEX(ctrlMutex); - - auto dit = std::as_const(mDownloads).find(hash); - if (dit != mDownloads.end()) - { - /* we already have it! */ - -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileRequest() Already Downloading File"; - std::cerr << std::endl; - std::cerr << "\tNo need to download"; - std::cerr << std::endl; -#endif - /* but we should add this peer - if they don't exist! - * (needed for channels). - */ - - for(it = srcIds.begin(); it != srcIds.end(); ++it) - { - bool bAllowDirectDL = false; - switch (mFilePermDirectDLPolicy) { - case RS_FILE_PERM_DIRECT_DL_YES: bAllowDirectDL = true; break; - case RS_FILE_PERM_DIRECT_DL_NO: bAllowDirectDL = false; break; - default:bAllowDirectDL = (rsPeers->servicePermissionFlags(*it) & RS_NODE_PERM_DIRECT_DL); break; - } - if(bAllowDirectDL) - { - uint32_t i, j; - if ((dit->second)->mTransfer->getPeerState(*it, i, j)) - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileRequest() Peer Existing"; - std::cerr << std::endl; -#endif - continue; /* already added peer */ - } - -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileRequest() Adding Peer: " << *it; - std::cerr << std::endl; -#endif - (dit->second)->mTransfer->addFileSource(*it); - setPeerState(dit->second->mTransfer, *it, rate, mServiceCtrl->isPeerConnected(mFtServiceType, *it)); - } - } - - if (srcIds.empty()) - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileRequest() WARNING: No Src Peers"; - std::cerr << std::endl; -#endif - } - - return true; - } - } // RS_STACK_MUTEX(ctrlMutex); unlocked - - - if(mSearch && !(flags & RS_FILE_REQ_NO_SEARCH)) - { - /* do a source search - for any extra sources */ - // add sources only in direct mode - // - if(/* (flags & RS_FILE_HINTS_BROWSABLE) && */ mSearch->search(hash, RS_FILE_HINTS_REMOTE | RS_FILE_HINTS_SPEC_ONLY, info)) - { - /* do something with results */ -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileRequest() Found Other Sources"; - std::cerr << std::endl; -#endif - - /* if the sources don't exist already - add in */ - for(pit = info.peers.begin(); pit != info.peers.end(); ++pit) - { -#ifdef CONTROL_DEBUG - std::cerr << "\tSource: " << pit->peerId; - std::cerr << std::endl; -#endif - // Because this is auto-add, we only add sources that we allow to DL from using direct transfers. - - bool bAllowDirectDL = false; - switch (mFilePermDirectDLPolicy) { - case RS_FILE_PERM_DIRECT_DL_YES: bAllowDirectDL = true; break; - case RS_FILE_PERM_DIRECT_DL_NO: bAllowDirectDL = false; break; - default:bAllowDirectDL = (rsPeers->servicePermissionFlags(pit->peerId) & RS_NODE_PERM_DIRECT_DL); break; - } - - if ((srcIds.end() == std::find( srcIds.begin(), srcIds.end(), pit->peerId)) && bAllowDirectDL) - { - srcIds.push_back(pit->peerId); - -#ifdef CONTROL_DEBUG - std::cerr << "\tAdding in: " << pit->peerId; - std::cerr << std::endl; -#endif - } - } - } - } - - /* add in new item for download */ - std::string savepath; - std::string destination; - - { - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - savepath = mPartialsPath + "/" + hash.toStdString(); - destination = dest + "/" + fname; - - /* if no destpath - send to download directory */ - if (dest == "") - destination = mDownloadPath + "/" + fname; - } /******* UNLOCKED ********/ - - // We check that flags are consistent. - - if(flags & RS_FILE_REQ_ANONYMOUS_ROUTING) - mFtServer->activateTunnels(hash,mDefaultEncryptionPolicy,flags,true); - - bool assume_availability = false; - - ftFileCreator *fc = new ftFileCreator(savepath, size, hash,assume_availability); - ftTransferModule *tm = new ftTransferModule(fc, mDataplex,this); - -#ifdef CONTROL_DEBUG - std::cerr << "Note: setting chunk strategy to " << mDefaultChunkStrategy <setChunkStrategy(mDefaultChunkStrategy) ; - - /* add into maps */ - ftFileControl *ftfc = new ftFileControl(fname, savepath, destination, size, hash, flags, fc, tm); - ftfc->mCreateTime = time(NULL); - - /* now add source peers (and their current state) */ - tm->setFileSources(srcIds); - - /* get current state for transfer module */ - for(it = srcIds.begin(); it != srcIds.end(); ++it) - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileRequest() adding peer: " << *it; - std::cerr << std::endl; -#endif - setPeerState(tm, *it, rate, mServiceCtrl->isPeerConnected(mFtServiceType, *it)); - } - - /* add structures into the accessible data. Needs to be locked */ - { - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - locked_addToQueue(ftfc, FT_FILECONTROL_QUEUE_ADD_END ) ; - -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileRequest() Created ftFileCreator @: " << fc; - std::cerr << std::endl; - std::cerr << "ftController::FileRequest() Created ftTransModule @: " << tm; - std::cerr << std::endl; - std::cerr << "ftController::FileRequest() Created ftFileControl." ; - std::cerr << std::endl; -#endif - - /* add to ClientModule */ - mDataplex->addTransferModule(tm, fc); - mDownloads[hash] = ftfc; - } - - IndicateConfigChanged(); /* completed transfer -> save */ - return true; -} - -bool ftController::setPeerState(ftTransferModule *tm, const RsPeerId& id, uint32_t maxrate, bool online) -{ - if (id == mServiceCtrl->getOwnId()) - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController::setPeerState() is Self"; - std::cerr << std::endl; -#endif - tm->setPeerState(id, PQIPEER_IDLE, maxrate); - } - else if (online || mTurtle->isOnline(id)) - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController::setPeerState()"; - std::cerr << " Peer is Online"; - std::cerr << std::endl; -#endif - tm->setPeerState(id, PQIPEER_IDLE, maxrate); - } - else - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController::setPeerState()"; - std::cerr << " Peer is Offline"; - std::cerr << std::endl; -#endif - tm->setPeerState(id, PQIPEER_NOT_ONLINE, maxrate); - } - return true; -} - - -bool ftController::setChunkStrategy(const RsFileHash& hash,FileChunksInfo::ChunkStrategy s) -{ - std::map::iterator mit=mDownloads.find(hash); - if (mit==mDownloads.end()) - { -#ifdef CONTROL_DEBUG - std::cerr<<"ftController::setChunkStrategy file is not found in mDownloads"<second->mCreator->setChunkStrategy(s) ; - return true ; -} - -bool ftController::FileCancel(const RsFileHash& hash) -{ - mFtServer->activateTunnels(hash,mDefaultEncryptionPolicy,TransferRequestFlags(0),false); - -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileCancel" << std::endl; -#endif - /*check if the file in the download map*/ - - { - RsStackMutex mtx(ctrlMutex) ; - - std::map::iterator mit=mDownloads.find(hash); - if (mit==mDownloads.end()) - { -#ifdef CONTROL_DEBUG - std::cerr<<"ftController::FileCancel file is not found in mDownloads"<second)->mCreator->finished()) - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController:FileCancel(" << hash << ")"; - std::cerr << " Transfer Already finished"; - std::cerr << std::endl; - - std::cerr << "FileSize: "; - std::cerr << (mit->second)->mCreator->getFileSize(); - std::cerr << " and Recvd: "; - std::cerr << (mit->second)->mCreator->getRecvd(); -#endif - return false; - } - - /*find the point to transfer module*/ - ftTransferModule* ft=(mit->second)->mTransfer; - ft->cancelTransfer(); - - ftFileControl *fc = mit->second; - mDataplex->removeTransferModule(fc->mTransfer->hash()); - - if (fc->mTransfer) - { - delete fc->mTransfer; - fc->mTransfer = NULL; - } - - if (fc->mCreator) - { - delete fc->mCreator; - fc->mCreator = NULL; - } - - /* delete the temporary file */ - if (0 == remove(fc->mCurrentPath.c_str())) - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileCancel() remove temporary file "; - std::cerr << fc->mCurrentPath; - std::cerr << std::endl; -#endif - } - else - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileCancel() fail to remove file "; - std::cerr << fc->mCurrentPath; - std::cerr << std::endl; -#endif - } - - locked_queueRemove(fc->mQueuePosition) ; - delete fc ; - mDownloads.erase(mit); - } - - IndicateConfigChanged(); /* completed transfer -> save */ - return true; -} - -bool ftController::FileControl(const RsFileHash& hash, uint32_t flags) -{ -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileControl(" << hash << ","; - std::cerr << flags << ")"<::iterator mit=mDownloads.find(hash); - if (mit==mDownloads.end()) - { -#ifdef CONTROL_DEBUG - std::cerr<<"ftController::FileControl file is not found in mDownloads"<second->mState = ftFileControl::PAUSED ; - std::cerr << "setting state to " << ftFileControl::PAUSED << std::endl ; - break; - - case RS_FILE_CTRL_START: - mit->second->mState = ftFileControl::DOWNLOADING ; - std::cerr << "setting state to " << ftFileControl::DOWNLOADING << std::endl ; - break; - - case RS_FILE_CTRL_FORCE_CHECK: - mit->second->mTransfer->forceCheck(); - std::cerr << "setting state to " << ftFileControl::CHECKING_HASH << std::endl ; - break; - - default: - return false; - } - IndicateConfigChanged() ; - - return true; -} - -bool ftController::FileClearCompleted() -{ -#ifdef CONTROL_DEBUG - std::cerr << "ftController::FileClearCompleted()" <second; - - mCompleted.clear(); - - IndicateConfigChanged(); - } - - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mFileTransferEventCode = RsFileTransferEventCode::COMPLETED_FILES_REMOVED; - rsEvents->postEvent(ev); - } - - return true; -} - - /* get Details of File Transfers */ -void ftController::FileDownloads(std::list &hashs) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - std::map::iterator it; - for(it = mDownloads.begin(); it != mDownloads.end(); ++it) - { - hashs.push_back(it->second->mHash); - } - for(it = mCompleted.begin(); it != mCompleted.end(); ++it) - { - hashs.push_back(it->second->mHash); - } -} - - - /* Directory Handling */ -bool ftController::setDownloadDirectory(std::string path) -{ -#ifdef CONTROL_DEBUG - std::cerr << "ftController::setDownloadDirectory(" << path << ")"; - std::cerr << std::endl; -#endif - /* check if it exists */ - if (RsDirUtil::checkCreateDirectory(path)) - { - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - mDownloadPath = RsDirUtil::convertPathToUnix(path); - - RsDiscSpace::setDownloadPath(mDownloadPath) ; -#ifdef CONTROL_DEBUG - std::cerr << "ftController::setDownloadDirectory() Okay!"; - std::cerr << std::endl; -#endif - IndicateConfigChanged(); - return true; - } - -#ifdef CONTROL_DEBUG - std::cerr << "ftController::setDownloadDirectory() Failed"; - std::cerr << std::endl; -#endif - return false; -} - -bool ftController::setPartialsDirectory(std::string path) -{ - - /* check it is not a subdir of download / shared directories (BAD) - TODO */ - { - RsStackMutex stack(ctrlMutex); - - path = RsDirUtil::convertPathToUnix(path); - - if (path.find(mDownloadPath) != std::string::npos) { - return false; - } - - if (rsFiles) { - std::list::iterator it; - std::list dirs; - rsFiles->getSharedDirectories(dirs); - for (it = dirs.begin(); it != dirs.end(); ++it) { - if (path.find((*it).filename) != std::string::npos) { - return false; - } - } - } - } - - /* check if it exists */ - - if (RsDirUtil::checkCreateDirectory(path)) - { - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - mPartialsPath = path; - - RsDiscSpace::setPartialsPath(path) ; - -#if 0 /*** FIX ME !!!**************/ - /* move all existing files! */ - std::map::iterator it; - for(it = mDownloads.begin(); it != mDownloads.end(); ++it) - { - (it->second).mCreator->changePartialDirectory(mPartialPath); - } -#endif - IndicateConfigChanged(); - return true; - } - - return false; -} - -std::string ftController::getDownloadDirectory() -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - return mDownloadPath; -} - -std::string ftController::getPartialsDirectory() -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - return mPartialsPath; -} - -bool ftController::FileServerCancel(const RsFileHash& hash) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - return mDataplex->deleteServer(hash); -} -bool ftController::setDestinationDirectory(const RsFileHash& hash,const std::string& dest_dir) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - std::map::iterator it = mDownloads.find(hash); - - if (it == mDownloads.end()) - return false; - - std::cerr << "(II) Changing destination of file " << it->second->mDestination << std::endl; - - it->second->mDestination = dest_dir + '/' + it->second->mName ; - - std::cerr << "(II) ...to " << it->second->mDestination << std::endl; - - return true ; -} -bool ftController::setDestinationName(const RsFileHash& hash,const std::string& dest_name) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - std::map::iterator it = mDownloads.find(hash); - - if (it == mDownloads.end()) - return false; - - std::cerr << "(II) Changing destination of file " << it->second->mDestination << std::endl; - - std::string dest_path ; - RsDirUtil::removeTopDir(it->second->mDestination, dest_path); /* remove fname */ - - it->second->mDestination = dest_path + '/' + dest_name ; - it->second->mName = dest_name ; - - std::cerr << "(II) ...to " << it->second->mDestination << std::endl; - - return true ; -} - -bool ftController::FileDetails(const RsFileHash &hash, FileInfo &info) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - bool completed = false; - std::map::iterator it = mDownloads.find(hash); - if (it == mDownloads.end()) - { - /* search completed files too */ - it = mCompleted.find(hash); - if (it == mCompleted.end()) - { - /* Note: mTransfer & mCreator - * are both NULL - */ - return false; - } - completed = true; - } - - /* extract details */ - info.hash = hash; - info.fname = it->second->mName; - info.storage_permission_flags.clear() ; - info.transfer_info_flags = it->second->mFlags ; - info.priority = SPEED_NORMAL ; - RsDirUtil::removeTopDir(it->second->mDestination, info.path); /* remove fname */ - info.queue_position = it->second->mQueuePosition ; - - if(it->second->mFlags & RS_FILE_REQ_ANONYMOUS_ROUTING) - info.storage_permission_flags |= DIR_FLAGS_ANONYMOUS_DOWNLOAD ; // file being downloaded anonymously are always anonymously available. - - /* get list of sources from transferModule */ - std::list peerIds; - std::list::iterator pit; - - if (!completed) - { - it->second->mTransfer->getFileSources(peerIds); - info.priority = it->second->mTransfer->downloadPriority() ; - info.lastTS = it->second->mCreator->lastRecvTimeStamp(); // last time the file was actually written - } - else - info.lastTS = 0; - - double totalRate = 0; - uint32_t tfRate = 0; - uint32_t state = 0; - - bool isDownloading = false; - bool isSuspended = false; - - info.peers.clear(); - - for(pit = peerIds.begin(); pit != peerIds.end(); ++pit) - { - if (it->second->mTransfer->getPeerState(*pit, state, tfRate)) - { - TransferInfo ti; - switch(state) - { - case PQIPEER_INIT: - ti.status = FT_STATE_OKAY; - break; - case PQIPEER_NOT_ONLINE: - ti.status = FT_STATE_WAITING; - break; - case PQIPEER_DOWNLOADING: - isDownloading = true; - ti.status = FT_STATE_DOWNLOADING; - break; - case PQIPEER_IDLE: - ti.status = FT_STATE_OKAY; - break; - default: - case PQIPEER_SUSPEND: - isSuspended = true; - ti.status = FT_STATE_FAILED; - break; - } - - ti.tfRate = tfRate / 1024.0; - ti.peerId = *pit; - info.peers.push_back(ti); - totalRate += tfRate / 1024.0; - } - } - - if ((completed) || ((it->second)->mCreator->finished())) - { - info.downloadStatus = FT_STATE_COMPLETE; - } - else if (isDownloading) - { - info.downloadStatus = FT_STATE_DOWNLOADING; - } - else if (isSuspended) - { - info.downloadStatus = FT_STATE_FAILED; - } - else - { - info.downloadStatus = FT_STATE_WAITING; - } - - if(it->second->mState == ftFileControl::QUEUED) - info.downloadStatus = FT_STATE_QUEUED ; - - if(it->second->mState == ftFileControl::PAUSED) - info.downloadStatus = FT_STATE_PAUSED ; - - if((!completed) && it->second->mTransfer->isCheckingHash()) - info.downloadStatus = FT_STATE_CHECKING_HASH ; - - info.tfRate = totalRate; - info.size = (it->second)->mSize; - - if (completed) - { - info.transfered = info.size; - info.avail = info.transfered; - } - else - { - info.transfered = (it->second)->mCreator->getRecvd(); - info.avail = info.transfered; - } - - return true; - - - -} - - - /***************************************************************/ - /********************** Controller Access **********************/ - /***************************************************************/ - - /* pqiMonitor callback: - * Used to tell TransferModules new available peers - */ -void ftController::statusChange(const std::list &plist) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - uint32_t rate = FT_CNTRL_STANDARD_RATE; - - /* add online to all downloads */ - std::map::iterator it; - std::list::const_iterator pit; - -#ifdef CONTROL_DEBUG - std::cerr << "ftController::statusChange()"; - std::cerr << std::endl; -#endif - - for(it = mDownloads.begin(); it != mDownloads.end(); ++it) - { -#ifdef CONTROL_DEBUG - std::cerr << "ftController::statusChange() Updating Hash:"; - std::cerr << it->first; - std::cerr << std::endl; -#endif - for(pit = plist.begin(); pit != plist.end(); ++pit) - { -#ifdef CONTROL_DEBUG - std::cerr << "Peer: " << pit->id; -#endif - if (pit->actions & RS_SERVICE_PEER_CONNECTED) - { -#ifdef CONTROL_DEBUG - std::cerr << " is Newly Connected!"; - std::cerr << std::endl; -#endif - setPeerState(it->second->mTransfer, pit->id, rate, true); - } - else if (pit->actions & RS_SERVICE_PEER_DISCONNECTED) - { -#ifdef CONTROL_DEBUG - std::cerr << " is Just disconnected!"; - std::cerr << std::endl; -#endif - setPeerState(it->second->mTransfer, pit->id, rate, false); - } - else // Added or Removed. - { -#ifdef CONTROL_DEBUG - std::cerr << " had something happen to it: "; - std::cerr << pit-> actions; - std::cerr << std::endl; -#endif - setPeerState(it->second->mTransfer, pit->id, rate, false); - } - } - - // Now also look at turtle virtual peers, for ongoing downloads only. - // - if(it->second->mState != ftFileControl::DOWNLOADING) - continue ; - - std::list vlist ; - std::list::const_iterator vit; - mTurtle->getSourceVirtualPeersList(it->first,vlist) ; - -#ifdef CONTROL_DEBUG - std::cerr << "vlist.size() = " << vlist.size() << std::endl; -#endif - - for(vit = vlist.begin(); vit != vlist.end(); ++vit) - { -#ifdef CONTROL_DEBUG - std::cerr << "Peer: " << vit->id; -#endif - if (vit->actions & RS_PEER_CONNECTED) - { -#ifdef CONTROL_DEBUG - std::cerr << " is Newly Connected!"; - std::cerr << std::endl; -#endif - setPeerState(it->second->mTransfer, vit->id, rate, true); - } - else if (vit->actions & RS_PEER_DISCONNECTED) - { -#ifdef CONTROL_DEBUG - std::cerr << " is Just disconnected!"; - std::cerr << std::endl; -#endif - setPeerState(it->second->mTransfer, vit->id, rate, false); - } - else - { -#ifdef CONTROL_DEBUG - std::cerr << " had something happen to it: "; - std::cerr << vit-> actions; - std::cerr << std::endl; -#endif - setPeerState(it->second->mTransfer, vit->id, rate, false); - } - } - } -} - -const std::string active_downloads_size_ss("MAX_ACTIVE_DOWNLOADS"); -const std::string download_dir_ss("DOWN_DIR"); -const std::string partial_dir_ss("PART_DIR"); -const std::string max_uploads_per_friend_ss("MAX_UPLOADS_PER_FRIEND"); -const std::string default_chunk_strategy_ss("DEFAULT_CHUNK_STRATEGY"); -const std::string free_space_limit_ss("FREE_SPACE_LIMIT"); -const std::string default_encryption_policy_ss("DEFAULT_ENCRYPTION_POLICY"); -const std::string file_perm_direct_dl_ss("FILE_PERM_DIRECT_DL"); - - - /* p3Config Interface */ -RsSerialiser *ftController::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser(); - - /* add in the types we need! */ - rss->addSerialType(new RsFileConfigSerialiser()); - rss->addSerialType(new RsGeneralConfigSerialiser()); - - return rss; -} - -bool ftController::saveList(bool &cleanup, std::list& saveData) -{ - - - /* it can delete them! */ - cleanup = true; - - /* create a key/value set for most of the parameters */ - std::map configMap; - std::map::iterator mit; - std::list::iterator it; - - /* basic control parameters */ - std::string s ; - rs_sprintf(s, "%lu", getQueueSize()) ; - configMap[active_downloads_size_ss] = s ; - configMap[download_dir_ss] = getDownloadDirectory(); - configMap[partial_dir_ss] = getPartialsDirectory(); - - switch(mDefaultChunkStrategy) - { - case FileChunksInfo::CHUNK_STRATEGY_STREAMING: configMap[default_chunk_strategy_ss] = "STREAMING" ; - break ; - case FileChunksInfo::CHUNK_STRATEGY_RANDOM: configMap[default_chunk_strategy_ss] = "RANDOM" ; - break ; - - default: - case FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE:configMap[default_chunk_strategy_ss] = "PROGRESSIVE" ; - break ; - } - - rs_sprintf(s,"%lu",_max_uploads_per_friend) ; - configMap[max_uploads_per_friend_ss] = s ; - - configMap[default_encryption_policy_ss] = (mDefaultEncryptionPolicy==RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE)?"PERMISSIVE":"STRICT" ; - - switch (mFilePermDirectDLPolicy) { - case RS_FILE_PERM_DIRECT_DL_YES: configMap[file_perm_direct_dl_ss] = "YES" ; - break; - case RS_FILE_PERM_DIRECT_DL_NO: configMap[file_perm_direct_dl_ss] = "NO" ; - break; - default: configMap[file_perm_direct_dl_ss] = "PER_USER" ; - break; - } - - rs_sprintf(s, "%lu", RsDiscSpace::freeSpaceLimit()); - configMap[free_space_limit_ss] = s ; - - RsConfigKeyValueSet *rskv = new RsConfigKeyValueSet(); - - /* Convert to TLV */ - for(mit = configMap.begin(); mit != configMap.end(); ++mit) - { - RsTlvKeyValue kv; - kv.key = mit->first; - kv.value = mit->second; - - rskv->tlvkvs.pairs.push_back(kv); - } - - /* Add KeyValue to saveList */ - saveData.push_back(rskv); - - /* get list of Downloads .... - * strip out Caches / ExtraList / Channels???? - * (anything with a callback?) - * - most systems will restart missing files. - */ - - - /* get Details of File Transfers */ - std::list hashs; - FileDownloads(hashs); - - for(it = hashs.begin(); it != hashs.end(); ++it) - { - /* stack mutex released each loop */ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - std::map::iterator fit = mDownloads.find(*it); - if (fit == mDownloads.end()) - continue; - - /* ignore cache files. As this is small files, better download them again from scratch at restart.*/ - - // Node: We still save finished transfers. This keeps transfers that are - // in checking mode. Finished or checked transfers will restart and - // immediately terminate/recheck at next startup. - // - // if ((fit->second)->mCreator->finished()) - // continue; - - /* make RsFileTransfer item for save list */ - RsFileTransfer *rft = new RsFileTransfer(); - - /* what data is important? */ - - rft->file.name = fit->second->mName; - rft->file.hash = fit->second->mHash; - rft->file.filesize = fit->second->mSize; - RsDirUtil::removeTopDir(fit->second->mDestination, rft->file.path); /* remove fname */ - rft->flags = fit->second->mFlags.toUInt32(); - rft->state = fit->second->mState; - - std::list lst ; - fit->second->mTransfer->getFileSources(lst); - - // Remove turtle peers from sources, as they are not supposed to survive a reboot of RS, since they are dynamic sources. - // Otherwize, such sources are unknown from the turtle router, at restart, and never get removed. - // - for(std::list::const_iterator it(lst.begin());it!=lst.end();++it) - if(!mTurtle->isTurtlePeer(*it)) - rft->allPeerIds.ids.insert(*it) ; - - rft->transferred = fit->second->mCreator->getRecvd(); - fit->second->mCreator->getAvailabilityMap(rft->compressed_chunk_map) ; - rft->chunk_strategy = fit->second->mCreator->getChunkStrategy() ; - - saveData.push_back(rft); - } - - { - /* Save pending list of downloads */ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - - std::list::iterator pit; - for (pit = mPendingRequests.begin(); pit != mPendingRequests.end(); ++pit) - { - /* make RsFileTransfer item for save list */ - RsFileTransfer *rft = NULL; - - std::map::iterator rit = mPendingChunkMaps.find(pit->mHash); - if (rit != mPendingChunkMaps.end()) { - /* use item from the not loaded pending list */ - rft = new RsFileTransfer(*(rit->second)); - } else { - rft = new RsFileTransfer(); - - /* what data is important? */ - - rft->file.name = pit->mName; - rft->file.hash = pit->mHash; - rft->file.filesize = pit->mSize; - RsDirUtil::removeTopDir(pit->mDest, rft->file.path); /* remove fname */ - rft->flags = pit->mFlags.toUInt32(); - rft->state = pit->mState; - - rft->allPeerIds.ids.clear() ; - for(std::list::const_iterator it(pit->mSrcIds.begin());it!=pit->mSrcIds.end();++it) - rft->allPeerIds.ids.insert( *it ) ; - } - - // Remove turtle peers from sources, as they are not supposed to survive a reboot of RS, since they are dynamic sources. - // Otherwize, such sources are unknown from the turtle router, at restart, and never get removed. We do that in post - // process since the rft object may have been created from mPendingChunkMaps - // - for(std::set::iterator sit(rft->allPeerIds.ids.begin());sit!=rft->allPeerIds.ids.end();) - if(mTurtle->isTurtlePeer(RsPeerId(*sit))) - { - std::set::iterator sittmp(sit) ; - ++sittmp ; - rft->allPeerIds.ids.erase(sit) ; - sit = sittmp ; - } - else - ++sit ; - - saveData.push_back(rft); - } - } - - /* list completed! */ - return true; -} - - -bool ftController::loadList(std::list& load) -{ - std::list::iterator it; - std::list::iterator kit; - RsConfigKeyValueSet *rskv; - RsFileTransfer *rsft; - -#ifdef CONTROL_DEBUG - std::cerr << "ftController::loadList() Item Count: " << load.size(); - std::cerr << std::endl; -#endif - - for(it = load.begin(); it != load.end(); ++it) - { - /* switch on type */ - if (NULL != (rskv = dynamic_cast(*it))) - { - /* make into map */ - std::map configMap; - for(kit = rskv->tlvkvs.pairs.begin(); - kit != rskv->tlvkvs.pairs.end(); ++kit) - { - configMap[kit->key] = kit->value; - } - - loadConfigMap(configMap); - - } - else if (NULL != (rsft = dynamic_cast(*it))) - { - /* This will get stored on a waiting list - until the - * config files are fully loaded - */ -#ifdef TO_REMOVE - (csoler) I removed this because RS_FILE_HINTS_NETWORK_WIDE is actually equal to RS_FILE_REQ_ENCRYPTED, so this test removed the encrypted flag when loading!! - // Compatibility with previous versions. - if(rsft->flags & RS_FILE_HINTS_NETWORK_WIDE.toUInt32()) - { - std::cerr << "Ensuring compatibility, replacing RS_FILE_HINTS_NETWORK_WIDE with RS_FILE_REQ_ANONYMOUS_ROUTING" << std::endl; - rsft->flags &= ~RS_FILE_HINTS_NETWORK_WIDE.toUInt32() ; - rsft->flags |= RS_FILE_REQ_ANONYMOUS_ROUTING.toUInt32() ; - } -#endif - -#ifdef CONTROL_DEBUG - std::cerr << "ftController::loadList(): requesting " << rsft->file.name << ", " << rsft->file.hash << ", " << rsft->file.filesize << std::endl ; -#endif - std::list src_lst ; - for(std::set::const_iterator it(rsft->allPeerIds.ids.begin());it!=rsft->allPeerIds.ids.end();++it) - src_lst.push_back(*it) ; - - FileRequest(rsft->file.name, rsft->file.hash, rsft->file.filesize, rsft->file.path, TransferRequestFlags(rsft->flags), src_lst, rsft->state); - - { - RsStackMutex mtx(ctrlMutex) ; - - std::map::iterator fit = mDownloads.find(rsft->file.hash); - - if((fit==mDownloads.end() || (fit->second)->mCreator == NULL)) - { - std::cerr << "ftController::loadList(): Error: could not find hash " << rsft->file.hash << " in mDownloads list !" << std::endl ; - std::cerr << "Storing the map in a wait list." << std::endl ; - - mPendingChunkMaps[rsft->file.hash] = rsft ; - - continue ; // i.e. don't delete the item! - } - else - { - (fit->second)->mCreator->setAvailabilityMap(rsft->compressed_chunk_map) ; - (fit->second)->mCreator->setChunkStrategy((FileChunksInfo::ChunkStrategy)(rsft->chunk_strategy)) ; - } - } - } - - /* cleanup */ - delete (*it); - } - load.clear() ; - return true; - -} - -bool ftController::loadConfigMap(std::map &configMap) -{ - std::map::iterator mit; - - //std::string str_true("true"); - //std::string empty(""); - //std::string dir = "notempty"; - - if (configMap.end() != (mit = configMap.find(download_dir_ss))) - setDownloadDirectory(mit->second); - - if (configMap.end() != (mit = configMap.find(active_downloads_size_ss))) - { - int n=5 ; - sscanf(mit->second.c_str(), "%d", &n); - std::cerr << "Note: loading active max downloads: " << n << std::endl; - setQueueSize(n); - } - if (configMap.end() != (mit = configMap.find(partial_dir_ss))) - { - setPartialsDirectory(mit->second); - } - - if (configMap.end() != (mit = configMap.find(default_encryption_policy_ss))) - { - if(mit->second == "STRICT") - { - mDefaultEncryptionPolicy = RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT ; - std::cerr << "Note: loading default value for encryption policy: STRICT" << std::endl; - } - else if(mit->second == "PERMISSIVE") - { - mDefaultEncryptionPolicy = RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE ; - std::cerr << "Note: loading default value for encryption policy: PERMISSIVE" << std::endl; - } - else - { - std::cerr << "(EE) encryption policy not recognized: \"" << mit->second << "\"" << std::endl; - mDefaultEncryptionPolicy = RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE ; - } - } - - if (configMap.end() != (mit = configMap.find(default_chunk_strategy_ss))) - { - if(mit->second == "STREAMING") - { - setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_STREAMING) ; - std::cerr << "Note: loading default value for chunk strategy: streaming" << std::endl; - } - else if(mit->second == "RANDOM") - { - setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_RANDOM) ; - std::cerr << "Note: loading default value for chunk strategy: random" << std::endl; - } - else if(mit->second == "PROGRESSIVE") - { - setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE) ; - std::cerr << "Note: loading default value for chunk strategy: progressive" << std::endl; - } - else - std::cerr << "**** ERROR ***: Unknown value for default chunk strategy in keymap." << std::endl ; - } - - if (configMap.end() != (mit = configMap.find(free_space_limit_ss))) - { - uint32_t size ; - if (sscanf(mit->second.c_str(), "%u", &size) == 1) { - std::cerr << "have read a size limit of " << size <<" MB" << std::endl ; - - RsDiscSpace::setFreeSpaceLimit(size) ; - } - } - if(configMap.end() != (mit = configMap.find(max_uploads_per_friend_ss))) - { - uint32_t n ; - if (sscanf(mit->second.c_str(), "%u", &n) == 1) { - std::cerr << "have read a max upload slots limit of " << n << std::endl ; - - _max_uploads_per_friend = n ; - } - } - - if(configMap.end() != (mit = configMap.find(file_perm_direct_dl_ss))) - { - if(mit->second == "YES") - { - mFilePermDirectDLPolicy = RS_FILE_PERM_DIRECT_DL_YES ; - std::cerr << "Note: loading default value for file permission direct download: YES" << std::endl; - } - else if(mit->second == "NO") - { - mFilePermDirectDLPolicy = RS_FILE_PERM_DIRECT_DL_NO ; - std::cerr << "Note: loading default value for file permission direct download: NO" << std::endl; - } - else if(mit->second == "PER_USER") - { - mFilePermDirectDLPolicy = RS_FILE_PERM_DIRECT_DL_PER_USER ; - std::cerr << "Note: loading default value for file permission direct download: PER_USER" << std::endl; - } - } - - return true; -} - -void ftController::setMaxUploadsPerFriend(uint32_t m) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - _max_uploads_per_friend = m ; - IndicateConfigChanged(); -} -uint32_t ftController::getMaxUploadsPerFriend() -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - return _max_uploads_per_friend ; -} -void ftController::setDefaultEncryptionPolicy(uint32_t p) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - mDefaultEncryptionPolicy = p ; - IndicateConfigChanged(); -} -uint32_t ftController::defaultEncryptionPolicy() -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - return mDefaultEncryptionPolicy ; -} - -void ftController::setFilePermDirectDL(uint32_t perm) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - if (mFilePermDirectDLPolicy != perm) - { - mFilePermDirectDLPolicy = perm; - IndicateConfigChanged(); - } -} -uint32_t ftController::filePermDirectDL() -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - return mFilePermDirectDLPolicy; -} - -void ftController::setFreeDiskSpaceLimit(uint32_t size_in_mb) -{ - RsDiscSpace::setFreeSpaceLimit(size_in_mb) ; - - IndicateConfigChanged() ; -} - - -uint32_t ftController::freeDiskSpaceLimit() const -{ - return RsDiscSpace::freeSpaceLimit() ; -} - -FileChunksInfo::ChunkStrategy ftController::defaultChunkStrategy() -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ - return mDefaultChunkStrategy ; -} -void ftController::setDefaultChunkStrategy(FileChunksInfo::ChunkStrategy S) -{ - RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ -#ifdef CONTROL_DEBUG - std::cerr << "Note: in frController: setting chunk strategy to " << S << std::endl ; -#endif - mDefaultChunkStrategy = S ; - IndicateConfigChanged() ; -} diff --git a/libretroshare/src/ft/ftcontroller.h b/libretroshare/src/ft/ftcontroller.h deleted file mode 100644 index 854a3e3a1..000000000 --- a/libretroshare/src/ft/ftcontroller.h +++ /dev/null @@ -1,274 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftcontroller.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef FT_CONTROLLER_HEADER -#define FT_CONTROLLER_HEADER - -/* - * ftController - * - * Top level download controller. - * - * inherits configuration (save downloading files) - * inherits pqiMonitor (knows which peers are online). - * inherits CacheTransfer (transfers cache files too) - * inherits RsThread (to control transfers) - * - */ - -class ftFileCreator; -class ftTransferModule; -class ftFileProvider; -class ftSearch; -class ftServer; -class ftExtraList; -class ftDataMultiplex; -class p3turtle ; -class p3ServiceControl; - -#include "util/rsthreads.h" -#include "pqi/pqiservicemonitor.h" -#include "pqi/p3cfgmgr.h" - -#include "retroshare/rsfiles.h" -#include "rsitems/rsconfigitems.h" - -#include - - -const uint32_t FC_TRANSFER_COMPLETE = 0x0001; - -class ftFileControl -{ - public: - - enum { DOWNLOADING = 0, - COMPLETED = 1, - ERROR_COMPLETION = 2, - QUEUED = 3, - PAUSED = 4, - CHECKING_HASH = 5 - }; - - ftFileControl(); - ftFileControl( const std::string& fname, const std::string& tmppath, const std::string& dest - , uint64_t size, const RsFileHash& hash, TransferRequestFlags flags - , ftFileCreator *fc, ftTransferModule *tm); - - std::string mName; - std::string mCurrentPath; /* current full path (including name) */ - std::string mDestination; /* final full path (including name) */ - ftTransferModule * mTransfer; - ftFileCreator * mCreator; - uint32_t mState; - RsFileHash mHash; - uint64_t mSize; - TransferRequestFlags mFlags; - rstime_t mCreateTime; - uint32_t mQueuePriority ; - uint32_t mQueuePosition ; -}; - -class ftPendingRequest -{ - public: - ftPendingRequest(const std::string& fname, const RsFileHash& hash, - uint64_t size, const std::string& dest, TransferRequestFlags flags, - const std::list &srcIds, uint16_t state) - : mName(fname), mHash(hash), mSize(size), - mDest(dest), mFlags(flags), mSrcIds(srcIds), mState(state) { return; } - - ftPendingRequest() : mSize(0), mFlags(0), mState(0) { return; } - - std::string mName; - RsFileHash mHash; - uint64_t mSize; - std::string mDest; - TransferRequestFlags mFlags; - std::list mSrcIds; - uint16_t mState; -}; - - -class ftController: - public RsTickingThread, public pqiServiceMonitor, public p3Config -{ -public: - - /* Setup */ - ftController(ftDataMultiplex *dm, p3ServiceControl *sc, uint32_t ftServiceId); - - void setFtSearchNExtra(ftSearch *, ftExtraList *); - void setTurtleRouter(p3turtle *) ; - void setFtServer(ftServer *) ; - bool activate(); - bool isActiveAndNoPending(); - - void threadTick() override; /// @see RsTickingThread - - /***************************************************************/ - /********************** Controller Access **********************/ - /***************************************************************/ - - bool FileRequest(const std::string& fname, const RsFileHash& hash, - uint64_t size, const std::string& dest, TransferRequestFlags flags, - const std::list &sourceIds, uint16_t state = ftFileControl::DOWNLOADING); - - /// Do we already have this file, either in download or in file lists ? - bool alreadyHaveFile(const RsFileHash& hash, FileInfo &info); - - bool setChunkStrategy(const RsFileHash& hash,FileChunksInfo::ChunkStrategy s); - void setDefaultChunkStrategy(FileChunksInfo::ChunkStrategy s); - void setDefaultEncryptionPolicy(uint32_t s); - FileChunksInfo::ChunkStrategy defaultChunkStrategy(); - uint32_t freeDiskSpaceLimit() const ; - void setFreeDiskSpaceLimit(uint32_t size_in_mb) ; - uint32_t defaultEncryptionPolicy(); - - void setMaxUploadsPerFriend(uint32_t m) ; - uint32_t getMaxUploadsPerFriend() ; - - void setFilePermDirectDL(uint32_t perm) ; - uint32_t filePermDirectDL() ; - - bool FileCancel(const RsFileHash& hash); - bool FileControl(const RsFileHash& hash, uint32_t flags); - bool FileClearCompleted(); - bool FlagFileComplete(const RsFileHash& hash); - bool getFileDownloadChunksDetails(const RsFileHash& hash,FileChunksInfo& info); - bool setDestinationName(const RsFileHash& hash,const std::string& dest_name) ; - bool setDestinationDirectory(const RsFileHash& hash,const std::string& dest_name) ; - bool FileServerCancel(const RsFileHash& hash); - - // Download speed - bool getPriority(const RsFileHash& hash,DwlSpeed& p); - void setPriority(const RsFileHash& hash,DwlSpeed p); - - // Action on queue position - // - void moveInQueue(const RsFileHash& hash,QueueMove mv) ; - void clearQueue() ; - void setQueueSize(uint32_t size) ; - uint32_t getQueueSize() ; - - /* get Details of File Transfers */ - void FileDownloads(std::list &hashs); - - /* Directory Handling */ - bool setDownloadDirectory(std::string path); - bool setPartialsDirectory(std::string path); - std::string getDownloadDirectory(); - std::string getPartialsDirectory(); - bool FileDetails(const RsFileHash &hash, FileInfo &info); - - /***************************************************************/ - /********************** Cache Transfer *************************/ - /***************************************************************/ - - /// Returns true is full source availability can be assumed for this peer. - /// - bool assumeAvailability(const RsPeerId& peer_id) const ; - - /* pqiMonitor callback (also provided mConnMgr pointer!) */ - virtual void statusChange(const std::list &plist); - - void addFileSource(const RsFileHash& hash,const RsPeerId& peer_id) ; - void removeFileSource(const RsFileHash& hash,const RsPeerId& peer_id) ; - - protected: - - void searchForDirectSources() ; - void tickTransfers() ; - - /***************************************************************/ - /********************** Controller Access **********************/ - /***************************************************************/ - - - /* p3Config Interface */ - virtual RsSerialiser *setupSerialiser(); - virtual bool saveList(bool &cleanup, std::list&); - virtual bool loadList(std::list& load); - bool loadConfigMap(std::map &configMap); - - private: - - /* RunTime Functions */ - void checkDownloadQueue(); // check the whole queue for inactive files - - void locked_addToQueue(ftFileControl*,int strategy) ;// insert this one into the queue - void locked_bottomQueue(uint32_t pos) ; // bottom queue file which is at this position - void locked_topQueue(uint32_t pos) ; // top queue file which is at this position - void locked_checkQueueElement(uint32_t pos) ; // check the state of this element in the queue - void locked_queueRemove(uint32_t pos) ; // delete this element from the queue - void locked_swapQueue(uint32_t pos1,uint32_t pos2) ; // swap position of the two elements - - bool completeFile(const RsFileHash& hash); - bool handleAPendingRequest(); - - bool setPeerState(ftTransferModule *tm, const RsPeerId& id, - uint32_t maxrate, bool online); - - rstime_t last_save_time ; - rstime_t last_clean_time ; - /* pointers to other components */ - - ftSearch *mSearch; - ftDataMultiplex *mDataplex; - ftExtraList *mExtraList; - p3turtle *mTurtle ; - ftServer *mFtServer ; - p3ServiceControl *mServiceCtrl; - uint32_t mFtServiceType; - uint32_t mDefaultEncryptionPolicy; - uint32_t mFilePermDirectDLPolicy; - - uint32_t cnt ; - RsMutex ctrlMutex; - - std::map mCompleted; - std::map mDownloads; - std::vector mDownloadQueue ; - - std::string mConfigPath; - std::string mDownloadPath; - std::string mPartialsPath; - - /**** SPEED QUEUES ****/ - - /* callback list (for File Completion) */ - RsMutex doneMutex; - std::list mDone; - - /* List to Pause File transfers until Caches are properly loaded */ - bool mFtActive; - bool mFtPendingDone; - std::list mPendingRequests; - std::map mPendingChunkMaps ; - - FileChunksInfo::ChunkStrategy mDefaultChunkStrategy ; - - uint32_t _max_active_downloads ; // maximum number of simultaneous downloads - uint32_t _max_uploads_per_friend ; // maximum number of uploads per friend. 0 means unlimited. -}; - -#endif diff --git a/libretroshare/src/ft/ftdata.h b/libretroshare/src/ft/ftdata.h deleted file mode 100644 index 349dae521..000000000 --- a/libretroshare/src/ft/ftdata.h +++ /dev/null @@ -1,94 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftdata.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef FT_DATA_INTERFACE_HEADER -#define FT_DATA_INTERFACE_HEADER - -/* - * ftData. - * - * Internal Interfaces for sending and receiving data. - * Most likely to be implemented by ftServer. - * Provided as an independent interface for testing purposes. - * - */ - -#include -#include - -#include - - /*************** SEND INTERFACE *******************/ - -class CompressedChunkMap ; - -class ftDataSend -{ - public: - virtual ~ftDataSend() { return; } - - /* Client Send */ - virtual bool sendDataRequest(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize) = 0; - - /* Server Send */ - virtual bool sendData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data) = 0; - - /// Send a chunkmap[request]. Because requests/chunkmaps can go both - //directions, but for different usages, we have this "is_client" flags, - //that gives the ultimate goal of the data. "is_client==true" means that - //the message is for a client (download) instead of a server. - // - virtual bool sendChunkMapRequest(const RsPeerId& peer_id,const RsFileHash& hash,bool is_client) = 0; - virtual bool sendChunkMap(const RsPeerId& peer_id,const RsFileHash& hash,const CompressedChunkMap& cmap,bool is_client) = 0; - - /// Send a request for a chunk crc map - virtual bool sendSingleChunkCRCRequest(const RsPeerId& peer_id,const RsFileHash& hash,uint32_t chunk_number) = 0; - /// Send a chunk crc map - virtual bool sendSingleChunkCRC(const RsPeerId& peer_id,const RsFileHash& hash,uint32_t chunk_number,const Sha1CheckSum& crc) = 0; -}; - - - - /*************** RECV INTERFACE *******************/ - -class ftDataRecv -{ - public: - virtual ~ftDataRecv() { return; } - - /* Client Recv */ - virtual bool recvData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data) = 0; - - /* Server Recv */ - virtual bool recvDataRequest(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize) = 0; - - /// Send a request for a chunk map - virtual bool recvChunkMapRequest(const RsPeerId& peer_id,const RsFileHash& hash,bool is_client) = 0; - - /// Send a chunk map - virtual bool recvChunkMap(const RsPeerId& peer_id,const RsFileHash& hash,const CompressedChunkMap& cmap,bool is_client) = 0; - - virtual bool recvSingleChunkCRCRequest(const RsPeerId& peer_id,const RsFileHash& hash,uint32_t chunk_id) = 0; - virtual bool recvSingleChunkCRC(const RsPeerId& peer_id,const RsFileHash& hash,uint32_t chunk_id,const Sha1CheckSum& sum) = 0; - -}; - -#endif diff --git a/libretroshare/src/ft/ftdatamultiplex.cc b/libretroshare/src/ft/ftdatamultiplex.cc deleted file mode 100644 index 24e2fe756..000000000 --- a/libretroshare/src/ft/ftdatamultiplex.cc +++ /dev/null @@ -1,1183 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftdatamultiplex.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -/* - * ftDataMultiplexModule. - * - * This multiplexes the data from PQInterface to the ftTransferModules. - */ - -#include "ft/ftdatamultiplex.h" -#include "ft/fttransfermodule.h" -#include "ft/ftfilecreator.h" -#include "ft/ftfileprovider.h" -#include "ft/ftsearch.h" -#include "util/rsdir.h" -#include "util/rsmemory.h" -#include "retroshare/rsturtle.h" -#include "util/rstime.h" -#include "rs_android/largefile_retrocompat.hpp" - - -/* For Thread Behaviour */ -const uint32_t DMULTIPLEX_MIN = 10; /* 10 msec sleep */ -const uint32_t DMULTIPLEX_MAX = 1000; /* 1 sec sleep */ -const double DMULTIPLEX_RELAX = 0.5; /* relax factor to calculate sleep time if not working in /libretroshare/src/util/rsthreads.cc */ - -static const uint32_t MAX_CHECKING_CHUNK_WAIT_DELAY = 120 ; //! TTL for an inactive chunk -const uint32_t MAX_SIMULTANEOUS_CRC_REQUESTS = 20 ; - -/****** - * #define MPLEX_DEBUG 1 - *****/ - -ftClient::ftClient(ftTransferModule *module, ftFileCreator *creator) - :mModule(module), mCreator(creator) -{ - return; -} - -const uint32_t FT_DATA = 0x0001; // data cuhnk to be stored -const uint32_t FT_DATA_REQ = 0x0002; // data request to be treated -const uint32_t FT_CLIENT_CHUNK_MAP_REQ = 0x0003; // chunk map request to be treated by client -const uint32_t FT_SERVER_CHUNK_MAP_REQ = 0x0004; // chunk map request to be treated by server -//const uint32_t FT_CRC32MAP_REQ = 0x0005; // crc32 map request to be treated by server -const uint32_t FT_CLIENT_CHUNK_CRC_REQ = 0x0006; // chunk sha1 crc request to be treated - -ftRequest::ftRequest(uint32_t type, const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunk, void *data) - :mType(type), mPeerId(peerId), mHash(hash), mSize(size), - mOffset(offset), mChunk(chunk), mData(data) -{ - return; -} - -ftDataMultiplex::ftDataMultiplex(const RsPeerId& ownId, ftDataSend *server, ftSearch *search) - :RsQueueThread(DMULTIPLEX_MIN, DMULTIPLEX_MAX, DMULTIPLEX_RELAX), dataMtx("ftDataMultiplex"), - mDataSend(server), mSearch(search), mOwnId(ownId) -{ - return; -} - -bool ftDataMultiplex::getFileData(const RsFileHash& hash, uint64_t offset, uint32_t& requested_size, uint8_t *data) -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - ftFileProvider* provider = 0; - - std::map::iterator cit; - std::map::iterator sit; - - // check if file is currently downloading - if (mClients.end() != (cit = mClients.find(hash))) - provider = (cit->second).mCreator; - - // else check if its already uploading - else if (mServers.end() != (sit = mServers.find(hash))) - provider = sit->second; - - // else create a new provider - else - { - FileInfo info; - FileSearchFlags hintflags = RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_SPEC_ONLY | RS_FILE_HINTS_NETWORK_WIDE; - if(mSearch->search(hash, hintflags, info)) - { - provider = new ftFileProvider(info.path, info.size, hash); - mServers[hash] = provider; - } - } - - if(!provider || ! provider->getFileData(mOwnId, offset, requested_size, data, true)) - { - requested_size = 0 ; - return false ; - } - return true ; -} - -bool ftDataMultiplex::addTransferModule(ftTransferModule *mod, ftFileCreator *f) -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - std::map::iterator it; - if (mClients.end() != (it = mClients.find(mod->hash()))) - { - /* error */ - return false; - } - mClients[mod->hash()] = ftClient(mod, f); - - return true; -} - -bool ftDataMultiplex::removeTransferModule(const RsFileHash& hash) -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - std::map::iterator it; - if (mClients.end() == (it = mClients.find(hash))) - { - /* error */ - return false; - } - mClients.erase(it); - - // This is very important to delete the hash from servers as well, because - // after removing the transfer module, ftController will delete the fileCreator. - // If the file creator is also a server in use, then it will cause a crash - // at the next server request. - // - // With the current action, the next server request will re-create the server as - // a ftFileProvider. - // - std::map::iterator sit = mServers.find(hash) ; - - if(sit != mServers.end()) - mServers.erase(sit); - - return true; -} - - -bool ftDataMultiplex::FileUploads(std::list &hashs) -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - std::map::iterator sit; - for(sit = mServers.begin(); sit != mServers.end(); ++sit) - { - hashs.push_back(sit->first); - } - return true; -} - -bool ftDataMultiplex::FileDownloads(std::list &hashs) -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - std::map::iterator cit; - for(cit = mClients.begin(); cit != mClients.end(); ++cit) - { - hashs.push_back(cit->first); - } - return true; -} - - -bool ftDataMultiplex::FileDetails(const RsFileHash &hash, FileSearchFlags hintsflag, FileInfo &info) -{ -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::FileDetails("; - std::cerr << hash << ", " << hintsflag << ")"; - std::cerr << std::endl; -#endif - - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - if(hintsflag & RS_FILE_HINTS_DOWNLOAD) - { - std::map::iterator cit; - if (mClients.end() != (cit = mClients.find(hash))) - { - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::FileDetails()"; - std::cerr << " Found ftFileCreator!"; - std::cerr << std::endl; -#endif - - //(cit->second).mModule->FileDetails(info); - (cit->second).mCreator->FileDetails(info); - return true; - } - } - - if(hintsflag & RS_FILE_HINTS_UPLOAD) - { - std::map::iterator sit; - sit = mServers.find(hash); - if (sit != mServers.end()) - { - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::FileDetails()"; - std::cerr << " Found ftFileProvider!"; - std::cerr << std::endl; -#endif - - (sit->second)->FileDetails(info); - return true; - } - } - - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::FileDetails()"; - std::cerr << " Found nothing"; - std::cerr << std::endl; -#endif - - return false; -} - - /* data interface */ - - /*************** SEND INTERFACE (calls ftDataSend) *******************/ - - /* Client Send */ -bool ftDataMultiplex::sendDataRequest(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize) -{ -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::sendDataRequest() Client Send"; - std::cerr << std::endl; -#endif - return mDataSend->sendDataRequest(peerId,hash,size,offset,chunksize); -} - - /* Server Send */ -bool ftDataMultiplex::sendData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data) -{ -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::sendData() Server Send"; - std::cerr << std::endl; -#endif - return mDataSend->sendData(peerId,hash,size,offset,chunksize,data); -} - - - /*************** RECV INTERFACE (provides ftDataRecv) ****************/ - - /* Client Recv */ -bool ftDataMultiplex::recvData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data) -{ -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::recvData() Client Recv"; - std::cerr << std::endl; -#endif - /* Store in Queue */ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - mRequestQueue.push_back(ftRequest(FT_DATA,peerId,hash,size,offset,chunksize,data)); - - return true; -} - - - /* Server Recv */ -bool ftDataMultiplex::recvDataRequest(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize) -{ -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::recvDataRequest() Server Recv"; - std::cerr << std::endl; -#endif - /* Store in Queue */ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - mRequestQueue.push_back( - ftRequest(FT_DATA_REQ,peerId,hash,size,offset,chunksize,NULL)); - - return true; -} - -bool ftDataMultiplex::recvChunkMapRequest(const RsPeerId& peerId, const RsFileHash& hash,bool is_client) -{ -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::recvChunkMapRequest() Server Recv"; - std::cerr << std::endl; -#endif - /* Store in Queue */ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - if(is_client) - mRequestQueue.push_back(ftRequest(FT_CLIENT_CHUNK_MAP_REQ,peerId,hash,0,0,0,NULL)); - else - mRequestQueue.push_back(ftRequest(FT_SERVER_CHUNK_MAP_REQ,peerId,hash,0,0,0,NULL)); - - return true; -} - -bool ftDataMultiplex::recvSingleChunkCRCRequest(const RsPeerId& peerId, const RsFileHash& hash,uint32_t chunk_number) -{ -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::recvChunkMapRequest() Server Recv"; - std::cerr << std::endl; -#endif - /* Store in Queue */ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - mRequestQueue.push_back(ftRequest(FT_CLIENT_CHUNK_CRC_REQ,peerId,hash,0,0,chunk_number,NULL)); - - return true; -} - -/*********** BACKGROUND THREAD OPERATIONS ***********/ -bool ftDataMultiplex::workQueued() -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - if (mRequestQueue.size() > 0) - { - return true; - } - - if (mSearchQueue.size() > 0) - { - return true; - } - - return false; -} - -bool ftDataMultiplex::doWork() -{ - bool doRequests = true; - - /* Handle All the current Requests */ - while(doRequests) - { - ftRequest req; - - { - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - if (mRequestQueue.empty()) - { - doRequests = false; - continue; - } - - req = mRequestQueue.front(); - mRequestQueue.pop_front(); - } - - /* MUTEX FREE */ - - switch(req.mType) - { - case FT_DATA: -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::doWork() Handling FT_DATA"; - std::cerr << std::endl; -#endif - handleRecvData(req.mPeerId, req.mHash, req.mSize, req.mOffset, req.mChunk, req.mData); - break; - - case FT_DATA_REQ: -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::doWork() Handling FT_DATA_REQ"; - std::cerr << std::endl; -#endif - handleRecvDataRequest(req.mPeerId, req.mHash, req.mSize, req.mOffset, req.mChunk); - break; - - case FT_CLIENT_CHUNK_MAP_REQ: -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::doWork() Handling FT_CLIENT_CHUNK_MAP_REQ"; - std::cerr << std::endl; -#endif - handleRecvClientChunkMapRequest(req.mPeerId,req.mHash) ; - break ; - - case FT_SERVER_CHUNK_MAP_REQ: -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::doWork() Handling FT_CLIENT_CHUNK_MAP_REQ"; - std::cerr << std::endl; -#endif - handleRecvServerChunkMapRequest(req.mPeerId,req.mHash) ; - break ; - - case FT_CLIENT_CHUNK_CRC_REQ: -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::doWork() Handling FT_CLIENT_CHUNK_CRC_REQ"; - std::cerr << std::endl; -#endif - handleRecvChunkCrcRequest(req.mPeerId,req.mHash,req.mChunk) ; - break ; - - default: -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::doWork() Ignoring UNKNOWN"; - std::cerr << std::endl; -#endif - break; - } - } - - /* Only Handle One Search Per Period.... - * Lower Priority - */ - ftRequest req; - - { - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - if (mSearchQueue.empty()) - { - /* Finished */ - return true; - } - - req = mSearchQueue.front(); - mSearchQueue.pop_front(); - } - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::doWork() Handling Search Request"; - std::cerr << std::endl; -#endif - if(handleSearchRequest(req.mPeerId, req.mHash)) - handleRecvDataRequest(req.mPeerId, req.mHash, req.mSize, req.mOffset, req.mChunk) ; - - - return true; -} - -bool ftDataMultiplex::recvSingleChunkCRC(const RsPeerId& peerId, const RsFileHash& hash,uint32_t chunk_number,const Sha1CheckSum& crc) -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::recvSingleChunkCrc() Received crc of file " << hash << ", from peer id " << peerId << ", chunk " << chunk_number << ", crc=" << crc.toStdString() << std::endl; -#else - (void) peerId; -#endif - // remove this chunk from the request list as well. - - Sha1CacheEntry& sha1cache(_cached_sha1maps[hash]) ; - std::map >::iterator it2(sha1cache._to_ask.find(chunk_number)) ; - - if(it2 != sha1cache._to_ask.end()) - sha1cache._to_ask.erase(it2) ; - - // update the cache: get size from the client. - - std::map::iterator it = mClients.find(hash); - - if(it == mClients.end()) - { - std::cerr << "ftDataMultiplex::recvSingleChunkCrc() ERROR: No matching Client for CRC. This is an error. " << hash << " !" << std::endl; - /* error */ - return false; - } - - // store in the cache as well - - if(sha1cache._map.size() == 0) - sha1cache._map = Sha1Map(it->second.mCreator->fileSize(),ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE) ; - - sha1cache._map.set(chunk_number,crc) ; - - sha1cache._received.push_back(chunk_number) ; - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::recvSingleChunkCrc() stored in cache. " << std::endl; -#endif - - return true ; -} - -bool ftDataMultiplex::dispatchReceivedChunkCheckSum() -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - uint32_t MAX_CHECKSUM_CHECK_PER_FILE = 25 ; - - for(std::map::iterator it(_cached_sha1maps.begin());it!=_cached_sha1maps.end();) - { - std::map::iterator itc = mClients.find(it->first); - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::dispatchReceivedChunkCheckSum(): treating hash " << it->first << std::endl; -#endif - - if(itc == mClients.end()) - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::dispatchReceivedChunkCheckSum() ERROR: No matching Client for hash. This is probably a late answer. Dropping the hash. Hash=" << it->first << std::endl; -#endif - - std::map::iterator tmp(it) ; - ++tmp ; - _cached_sha1maps.erase(it) ; - it = tmp ; - /* error */ - continue ; - } - ftFileCreator *client = itc->second.mCreator ; - - for(uint32_t n=0;nsecond._received.empty();++n) - { - int chunk_number = it->second._received.back() ; - - if(!it->second._map.isSet(chunk_number)) - std::cerr << "ftDataMultiplex::dispatchReceivedChunkCheckSum() ERROR: chunk " << chunk_number << " is supposed to be initialized but it was not received !!" << std::endl; - else - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::dispatchReceivedChunkCheckSum(): checking chunk " << chunk_number << " with hash " << it->second._map[chunk_number].toStdString() << std::endl; -#endif - client->verifyChunk(chunk_number,it->second._map[chunk_number]) ; - } - it->second._received.pop_back() ; - } - ++it ; - } - return true ; -} - -// A chunk map has arrived. It can be two different situations: -// - an uploader has sent his chunk map, so we need to store it in the corresponding ftFileProvider -// - a source for a download has sent his chunk map, so we need to send it to the corresponding ftFileCreator. -// -bool ftDataMultiplex::recvChunkMap(const RsPeerId& peerId, const RsFileHash& hash,const CompressedChunkMap& compressed_map,bool client) -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - if(client) // is the chunk map for a client, or for a server ? - { - std::map::iterator it = mClients.find(hash); - - if(it == mClients.end()) - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::recvChunkMap() ERROR: No matching Client for hash " << hash << " !"; - std::cerr << std::endl; -#endif - /* error */ - return false; - } - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::recvChunkMap() Passing map of file " << hash << ", to FT Module"; - std::cerr << std::endl; -#endif - - (it->second).mCreator->setSourceMap(peerId, compressed_map); - return true ; - } - else - { - std::map::iterator it = mServers.find(hash) ; - - if(it == mServers.end()) - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvChunkMap() ERROR: No matching file Provider for hash " << hash ; - std::cerr << std::endl; -#endif - return false; - } - - it->second->setClientMap(peerId, compressed_map); - return true ; - } - - return false; -} - -bool ftDataMultiplex::handleRecvClientChunkMapRequest(const RsPeerId& peerId, const RsFileHash& hash) -{ - CompressedChunkMap cmap ; - - { - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - std::map::iterator it = mClients.find(hash); - - if(it == mClients.end()) - { - // If we can't find the client, it's not a problem. Chunk maps from - // clients are not essential, as they are only used for display. -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvClientChunkMapRequest() ERROR: No matching Client for hash " << hash ; - std::cerr << ". Performing local search." << std::endl; -#endif - return false; - } - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvClientChunkMapRequest() Sending map of file " << hash << ", to peer " << peerId << std::endl; -#endif - - (it->second).mCreator->getAvailabilityMap(cmap); - } - - mDataSend->sendChunkMap(peerId,hash,cmap,false); - - return true ; -} - -bool ftDataMultiplex::handleRecvChunkCrcRequest(const RsPeerId& peerId, const RsFileHash& hash, uint32_t chunk_number) -{ - // look into the sha1sum cache - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvChunkMapReq() looking for chunk " << chunk_number << " for hash " << hash << std::endl; -#endif - - Sha1CheckSum crc ; - bool found = false ; - - { - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - Sha1CacheEntry& sha1cache(_cached_sha1maps[hash]) ; - sha1cache.last_activity = time(NULL) ; // update time_stamp - - if(sha1cache._map.size() > 0 && sha1cache._map.isSet(chunk_number)) - { - crc = sha1cache._map[chunk_number] ; - found = true ; - } - } - - if(found) - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvChunkMapReq() found in cache ! Sending " << crc.toStdString() << std::endl; -#endif - mDataSend->sendSingleChunkCRC(peerId,hash,chunk_number,crc); - return true ; - } - - std::map::iterator it ; - std::string filename ; - uint64_t filesize =0; - found = true ; - - // 1 - look into the list of servers.Not clients ! Clients dont' have verified data. - { - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - it = mServers.find(hash) ; - - if(it == mServers.end()) - found = false ; - } - - // 2 - if not found, create a server. - // - if(!found) - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvChunkMapReq() ERROR: No matching file Provider for hash " << hash ; - std::cerr << std::endl; -#endif - if(!handleSearchRequest(peerId,hash)) - return false ; - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvChunkMapReq() A new file Provider has been made up for hash " << hash ; - std::cerr << std::endl; -#endif - } - - { - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - it = mServers.find(hash) ; - - if(it == mServers.end()) // handleSearchRequest should have filled mServers[hash], but we have been off-mutex since, - { - std::cerr << "Could definitely not find a provider for file " << hash << ". Maybe the file does not exist?" << std::endl; - return false ; // so it's safer to check again. - } - else - { - filesize = it->second->fileSize() ; - filename = it->second->fileName() ; - } - } - -#ifdef MPLEX_DEBUG - std::cerr << "Computing Sha1 for chunk " << chunk_number<< " of file " << filename << ", hash=" << hash << ", size=" << filesize << std::endl; -#endif - - unsigned char *buf = new unsigned char[ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE] ; - FILE *fd = RsDirUtil::rs_fopen(filename.c_str(),"rb") ; - - if(fd == NULL) - { - std::cerr << "Cannot read file " << filename << ". Something's wrong!" << std::endl; - delete[] buf ; - return false ; - } - uint32_t len ; - if(fseeko64(fd,(uint64_t)chunk_number * (uint64_t)ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE,SEEK_SET)!=0 || 0==(len = fread(buf,1,ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE,fd))) - { - std::cerr << "Cannot fseek/read from file " << filename << " at position " << (uint64_t)chunk_number * (uint64_t)ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE << std::endl; - fclose(fd) ; - - delete[] buf ; - return false ; - } - fclose(fd) ; - - crc = RsDirUtil::sha1sum(buf,len) ; - delete[] buf ; - - // update cache - { - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - Sha1CacheEntry& sha1cache(_cached_sha1maps[hash]) ; - - if(sha1cache._map.size() == 0) - sha1cache._map = Sha1Map(filesize,ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE) ; - - sha1cache._map.set(chunk_number,crc) ; - } -#ifdef MPLEX_DEBUG - std::cerr << "Sending CRC of chunk " << chunk_number<< " of file " << filename << ", hash=" << hash << ", size=" << filesize << ", crc=" << crc.toStdString() << std::endl; -#endif - - mDataSend->sendSingleChunkCRC(peerId,hash,chunk_number,crc); - return true ; -} - -bool ftDataMultiplex::handleRecvServerChunkMapRequest(const RsPeerId& peerId, const RsFileHash& hash) -{ - CompressedChunkMap cmap ; - std::map::iterator it ; - bool found = true ; - - { - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - it = mServers.find(hash) ; - - if(it == mServers.end()) - found = false ; - } - - if(!found) - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvChunkMapReq() ERROR: No matching file Provider for hash " << hash ; - std::cerr << std::endl; -#endif - if(!handleSearchRequest(peerId,hash)) - return false ; - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvChunkMapReq() A new file Provider has been made up for hash " << hash ; - std::cerr << std::endl; -#endif - } - - { - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - it = mServers.find(hash) ; - - if(it == mServers.end()) // handleSearchRequest should have filled mServers[hash], but we have been off-mutex since, - { - std::cerr << "ftDataMultiplex::handleRecvChunkMapReq() : weird state: search request succeeded, but no server available!" << std::endl; - return false ; // so it's safer to check again. - } - else - it->second->getAvailabilityMap(cmap); - } - - mDataSend->sendChunkMap(peerId,hash,cmap,true); - - return true; -} - -bool ftDataMultiplex::handleRecvData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t /*size*/, uint64_t offset, uint32_t chunksize, void *data) -{ - ftTransferModule *transfer_module = NULL ; - - { - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - std::map::iterator it; - if (mClients.end() == (it = mClients.find(hash))) - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvData() ERROR: No matching Client!"; - std::cerr << std::endl; -#endif - /* error */ - return false; - } - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvData() Passing to Module"; - std::cerr << std::endl; -#endif - - transfer_module = (it->second).mModule ; - } - transfer_module->recvFileData(peerId, offset, chunksize, data); - - return true; -} - - - /* called by ftTransferModule */ -bool ftDataMultiplex::handleRecvDataRequest(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize) -{ - /**** Find Files *****/ - - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - std::map::iterator cit; - if (mOwnId == peerId) - { - /* own requests must be passed to Servers */ -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvData() OwnId, so skip Clients..."; - std::cerr << std::endl; -#endif - } - else if (mClients.end() != (cit = mClients.find(hash))) - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvData() Matched to a Client."; - std::cerr << std::endl; -#endif - locked_handleServerRequest((cit->second).mCreator, peerId, hash, size, offset, chunksize); - return true; - } - - std::map::iterator sit; - if (mServers.end() != (sit = mServers.find(hash))) - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvData() Matched to a Provider."; - std::cerr << std::endl; -#endif - locked_handleServerRequest(sit->second, peerId, hash, size, offset, chunksize); - return true; - } - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleRecvData() No Match... adding to Search Queue."; - std::cerr << std::endl; -#endif - - /* Add to Search Queue */ - mSearchQueue.push_back( ftRequest(FT_DATA_REQ, peerId, hash, size, offset, chunksize, NULL)); - - return true; -} - -bool ftDataMultiplex::locked_handleServerRequest(ftFileProvider *provider, const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, - uint64_t offset, uint32_t chunksize) -{ - if(chunksize > uint32_t(10*1024*1024)) - { - std::cerr << "Warning: peer " << peerId << " is asking a large chunk (s=" << chunksize << ") for hash " << hash << ", filesize=" << size << ". This is unexpected." << std::endl ; - return false ; - } - void *data = rs_malloc(chunksize); - - if(data == NULL) - return false ; - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::locked_handleServerRequest()"; - std::cerr << "\t peer: " << peerId << " hash: " << hash; - std::cerr << " size: " << size; - std::cerr << std::endl; - std::cerr << "\t offset: " << offset; - std::cerr << " chunksize: " << chunksize << " data: " << data; - std::cerr << std::endl; -#endif - - if (provider->getFileData(peerId,offset, chunksize, data)) - { - /* send data out */ - sendData(peerId, hash, size, offset, chunksize, data); - return true; - } -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::locked_handleServerRequest()"; - std::cerr << " FAILED"; - std::cerr << std::endl; -#endif - free(data); - - return false; -} - -bool ftDataMultiplex::getClientChunkMap(const RsFileHash& upload_hash,const RsPeerId& peerId,CompressedChunkMap& cmap) -{ - bool too_old = false; - { - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - std::map::iterator sit = mServers.find(upload_hash); - - if(mServers.end() == sit) - return false ; - - sit->second->getClientMap(peerId,cmap,too_old) ; - } - - // If the map is too old then we should ask an other map to the peer. - // - if(too_old) - sendChunkMapRequest(peerId,upload_hash,true); - - return true ; -} - -bool ftDataMultiplex::sendChunkMapRequest(const RsPeerId& peer_id,const RsFileHash& hash,bool is_client) -{ - return mDataSend->sendChunkMapRequest(peer_id,hash,is_client); -} -bool ftDataMultiplex::sendSingleChunkCRCRequests(const RsFileHash& hash, const std::vector& to_ask) -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - // Put all requested chunks in the request queue. - - Sha1CacheEntry& ce(_cached_sha1maps[hash]) ; - - for(uint32_t i=0;i& list(ce._to_ask[to_ask[i]]) ; - list.first = 0 ; // set last request time to 0 - } - return true ; -} - -void ftDataMultiplex::handlePendingCrcRequests() -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - rstime_t now = time(NULL) ; - uint32_t n=0 ; - - // Go through the list of currently handled hashes. For each of them, - // look for pending chunk crc requests. - // - if the last request is too old, re-ask: - // - ask the file creator about the possible sources for this chunk => returns a list of active sources - // - among active sources, pick the one that has the smallest request time stamp, in the request list. - // - // With this, only active sources are querried. - // - - for(std::map::iterator it(_cached_sha1maps.begin());it!=_cached_sha1maps.end();++it) - for(std::map >::iterator it2(it->second._to_ask.begin());it2!=it->second._to_ask.end();++it2) - if(it2->second.first + MAX_CHECKING_CHUNK_WAIT_DELAY < now) // is the last request old enough? - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handlePendingCrcRequests(): Requesting sources for chunk " << it2->first << ", hash " << it->first << std::endl; -#endif - // 0 - ask which sources can be used for this chunk - // - std::map::const_iterator it4(mClients.find(it->first)) ; - - if(it4 == mClients.end()) - continue ; - - std::vector sources ; - it4->second.mCreator->getSourcesList(it2->first,sources) ; - - // 1 - go through all sources. Take the oldest one. - // - - RsPeerId best_source ; - rstime_t oldest_timestamp = now ; - - for(uint32_t i=0;i::const_iterator it3(it2->second.second.find(sources[i])) ; - - if(it3 == it2->second.second.end()) // source not found. So this one is surely the oldest one to have been requested. - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handlePendingCrcRequests(): not found! So using it directly." << std::endl; -#endif - best_source = sources[i] ; - break ; - } - else if(it3->second <= oldest_timestamp) // do nothing, otherwise, ask again - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handlePendingCrcRequests(): not found! So using it directly." << std::endl; -#endif - best_source = sources[i] ; - oldest_timestamp = it3->second ; - } -#ifdef MPLEX_DEBUG - else - std::cerr << "ftDataMultiplex::handlePendingCrcRequests(): Source too recently used! So using it directly." << std::endl; -#endif - } - if(!best_source.isNull()) - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handlePendingCrcRequests(): Asking crc of chunk " << it2->first << " to peer " << best_source << " for hash " << it->first << std::endl; -#endif - // Use the source to ask the CRC. - // - // sendSingleChunkCRCRequest(peer_id, hash, chunk_id) - // - mDataSend->sendSingleChunkCRCRequest(best_source,it->first,it2->first); - it2->second.second[best_source] = now ; - it2->second.first = now ; - - if(++n > MAX_SIMULTANEOUS_CRC_REQUESTS) - return ; - } -#ifdef MPLEX_DEBUG - else - std::cerr << "ftDataMultiplex::handlePendingCrcRequests(): no source for chunk " << it2->first << std::endl; -#endif - } -} - -bool ftDataMultiplex::deleteServer(const RsFileHash& hash) -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - auto sit = mServers.find(hash); - - if(sit == mServers.end()) - return false; - - // We don't delete servers that are clients at the same time ! - if(dynamic_cast(sit->second) == NULL) - delete sit->second; - - mServers.erase(sit); - return true; -} - -void ftDataMultiplex::deleteUnusedServers() -{ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - //scan the uploads list in ftdatamultiplex and delete the items which time out - rstime_t now = time(NULL); - - for(std::map::iterator sit(mServers.begin());sit != mServers.end();) - if(sit->second->purgeOldPeers(now,10)) - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::deleteUnusedServers(): provider " << (void*)sit->second << " has no active peers. Removing. Now=" << now << std::endl ; -#endif - // We don't delete servers that are clients at the same time ! - if(dynamic_cast(sit->second) == NULL) - { -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::deleteUnusedServers(): deleting file provider " << (void*)sit->second << std::endl ; -#endif - delete sit->second; - } -#ifdef MPLEX_DEBUG - else - std::cerr << "ftDataMultiplex::deleteUnusedServers(): " << (void*)sit->second << " was not deleted because it's also a file creator." << std::endl ; -#endif - - std::map::iterator tmp(sit); - ++tmp ; - - mServers.erase(sit); - - sit = tmp ; - } - else - ++sit ; -} - -bool ftDataMultiplex::handleSearchRequest(const RsPeerId& peerId, const RsFileHash& hash) -{ -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleSearchRequest("; - std::cerr << peerId << ", " << hash << "...)"; - std::cerr << std::endl; -#endif - - /* - * Do Actual search - * Could be Cache File, Local or Extra - * (anywhere but remote really) - * - * the network wide and browsable flags are needed, otherwise results get filtered. - * For tunnel creation, the check of browsable/network wide flag is already done, so - * if we get a file download packet here, the source is already allowed to download it. - * That is why we don't call the search function with a peer id. - * - */ - - FileInfo info; - FileSearchFlags hintflags = RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_SPEC_ONLY ; - - if(rsTurtle->isTurtlePeer(peerId)) - hintflags |= RS_FILE_HINTS_NETWORK_WIDE ; - - if(mSearch->search(hash, hintflags, info)) - { - - /* setup a new provider */ - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - // We might already have a file provider, if two requests have got stacked in the request queue. So let's - // check that before. - -#ifdef MPLEX_DEBUG - std::cerr << "ftDataMultiplex::handleSearchRequest("; - std::cerr << " Found Local File, sharing..."; -#endif - std::map::const_iterator it = mServers.find(hash) ; - ftFileProvider *provider ; - - if(it == mServers.end()) - { - provider = new ftFileProvider(info.path, info.size, hash); - mServers[hash] = provider; -#ifdef MPLEX_DEBUG - std::cerr << " created new file provider " << (void*)provider << std::endl; -#endif - } - else - { -#ifdef MPLEX_DEBUG - std::cerr << " re-using existing file provider " << (void*)it->second << std::endl; -#endif - } - - return true; - } - // Now check wether the required file is actually being downloaded. In such a case, - // setup the file provider to be the file creator itself. Warning: this server should not - // be deleted when not used anymore. We need to restrict this to client peers that are - // not ourself, since the file transfer also handles the local cache traffic (this - // is something to be changed soon!!) - // - - if(peerId != mOwnId) - { - RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ - - std::map::const_iterator it(mClients.find(hash)) ; - - if(it != mClients.end()) - { - mServers[hash] = it->second.mCreator ; - return true; - } - } - - return false; -} - - - - - diff --git a/libretroshare/src/ft/ftdatamultiplex.h b/libretroshare/src/ft/ftdatamultiplex.h deleted file mode 100644 index 6b15e7617..000000000 --- a/libretroshare/src/ft/ftdatamultiplex.h +++ /dev/null @@ -1,192 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftdatamultiplex.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef FT_DATA_MULTIPLEX_HEADER -#define FT_DATA_MULTIPLEX_HEADER - -/* - * ftDataMultiplexModule. - * - * This multiplexes the data from PQInterface to the ftTransferModules. - */ - -class ftTransferModule; -class ftFileProvider; -class ftFileCreator; -class ftSearch; - -#include -#include -#include -#include - -#include "util/rsthreads.h" - -#include "ft/ftdata.h" -#include "retroshare/rsfiles.h" - - -class ftClient -{ - public: - - ftClient() :mModule(NULL), mCreator(NULL) { return; } - ftClient(ftTransferModule *module, ftFileCreator *creator); - - ftTransferModule *mModule; - ftFileCreator *mCreator; -}; - -class ftRequest -{ - public: - - ftRequest(uint32_t type, const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunk, void *data); - - ftRequest() - :mType(0), mSize(0), mOffset(0), mChunk(0), mData(NULL) { return; } - - uint32_t mType; - RsPeerId mPeerId; - RsFileHash mHash; - uint64_t mSize; - uint64_t mOffset; - uint32_t mChunk; - void *mData; -}; - -typedef std::map ChunkCheckSumSourceList ; - -class Sha1CacheEntry -{ - public: - Sha1Map _map ; // Map of available sha1 sums for every chunk. - rstime_t last_activity ; // This is used for removing unused entries. - std::vector _received ; // received chunk ids. To bedispatched. - std::map > _to_ask ; // Chunks to ask to sources. -}; - -class ftDataMultiplex: public ftDataRecv, public RsQueueThread -{ - - public: - - ftDataMultiplex(const RsPeerId& ownId, ftDataSend *server, ftSearch *search); - - /** - * @see RsFiles::getFileData - * - * data should be pre-allocated by the client with size sufficient gfor requested_size bytes. - * requested_size will be changed so as to contain the actual number of bytes copied from the file, - * in case where the full size wasn't available. - * False is returned if no data can be obtained from that file. - */ - bool getFileData(const RsFileHash& hash, uint64_t offset,uint32_t& requested_size, uint8_t *data); - - /* ftController Interface */ - bool addTransferModule(ftTransferModule *mod, ftFileCreator *f); - bool removeTransferModule(const RsFileHash& hash); - - /* data interface */ - /* get Details of File Transfers */ - bool FileUploads(std::list &hashs); - bool FileDownloads(std::list &hashs); - bool FileDetails(const RsFileHash &hash, FileSearchFlags hintsflag, FileInfo &info); - - void deleteUnusedServers() ; - bool deleteServer(const RsFileHash& hash); // deletes FtServers for the given hash. Used when removing an extra file from shares. - void handlePendingCrcRequests() ; - - /*************** SEND INTERFACE (calls ftDataSend) *******************/ - - /* Client Send */ - bool sendDataRequest(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize); - - /* Server Send */ - bool sendData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data); - - /* Server/client Send */ - bool sendChunkMapRequest(const RsPeerId& peerId, const RsFileHash& hash,bool is_client) ; - - - /* called from a separate thread */ - bool sendSingleChunkCRCRequests(const RsFileHash& hash, const std::vector& to_ask) ; - - bool dispatchReceivedChunkCheckSum() ; - - /*************** RECV INTERFACE (provides ftDataRecv) ****************/ - - /* Client Recv */ - virtual bool recvData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data); - /* Server Recv */ - virtual bool recvDataRequest(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize); - - /// Receive a request for a chunk map - virtual bool recvChunkMapRequest(const RsPeerId& peer_id,const RsFileHash& hash,bool is_client) ; - /// Receive a chunk map - virtual bool recvChunkMap(const RsPeerId& peer_id,const RsFileHash& hash,const CompressedChunkMap& cmap,bool is_client) ; - - virtual bool recvSingleChunkCRCRequest(const RsPeerId& peer_id,const RsFileHash& hash,uint32_t chunk_id) ; - virtual bool recvSingleChunkCRC(const RsPeerId& peer_id,const RsFileHash& hash,uint32_t chunk_id,const Sha1CheckSum& sum) ; - - // Returns the chunk map from the file uploading client. Also initiates a chunk map request if this - // map is too old. This supposes that the caller will ask again in a few seconds. - // - bool getClientChunkMap(const RsFileHash& upload_hash,const RsPeerId& peer_id,CompressedChunkMap& map) ; - - protected: - - /* Overloaded from RsQueueThread */ - virtual bool workQueued(); - virtual bool doWork(); - - private: - - /* Handling Job Queues */ - bool handleRecvData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data); - bool handleRecvDataRequest(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize); - bool handleSearchRequest(const RsPeerId& peerId, const RsFileHash& hash); - bool handleRecvClientChunkMapRequest(const RsPeerId& peerId, const RsFileHash& hash) ; - bool handleRecvServerChunkMapRequest(const RsPeerId& peerId, const RsFileHash& hash) ; - bool handleRecvChunkCrcRequest(const RsPeerId& peerId, const RsFileHash& hash,uint32_t chunk_id) ; - - /* We end up doing the actual server job here */ - bool locked_handleServerRequest(ftFileProvider *provider, const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize); - - RsMutex dataMtx; - - std::map mClients; - std::map mServers; - - std::list mRequestQueue; - std::list mSearchQueue; - - std::map _cached_sha1maps ; // one cache entry per file hash. Handled dynamically. - - ftDataSend *mDataSend; - ftSearch *mSearch; - RsPeerId mOwnId; - - friend class ftServer; -}; - -#endif diff --git a/libretroshare/src/ft/ftextralist.cc b/libretroshare/src/ft/ftextralist.cc deleted file mode 100644 index a68a5c7d1..000000000 --- a/libretroshare/src/ft/ftextralist.cc +++ /dev/null @@ -1,516 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftextralist.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2008 Robert Fernie * - * Copyright (C) 2018-2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include -#include - -#ifdef WINDOWS_SYS -#include "util/rswin.h" -#endif - -#include -#include -#include "ft/ftextralist.h" -#include "rsitems/rsconfigitems.h" -#include "util/rsdir.h" -#include "util/rstime.h" -#include -#include /* for (u)sleep() */ -#include "util/rstime.h" - -/****** - * #define DEBUG_ELIST 1 - *****/ - -ftExtraList::ftExtraList(): p3Config(), extMutex("p3Config"), mNextCleanupTS(0) -{} - -void ftExtraList::threadTick() -{ - bool haveFilesToHash = false; - rstime_t now = time(nullptr); - - { - RS_STACK_MUTEX(extMutex); - haveFilesToHash = !mToHash.empty(); - } - - if (haveFilesToHash) - { - hashAFile(); - std::this_thread::sleep_for(std::chrono::microseconds(10)); - } - else - { - if (mNextCleanupTS < now) - { - cleanupOldFiles(); - mNextCleanupTS = now + CLEANUP_PERIOD; - } - - std::this_thread::sleep_for(std::chrono::seconds(1)); - } -} - - - -void ftExtraList::hashAFile() -{ -#ifdef DEBUG_ELIST - std::cerr << "ftExtraList::hashAFile()"; - std::cerr << std::endl; -#endif - - /* extract entry from the queue */ - FileDetails details; - { - RS_STACK_MUTEX(extMutex); - if (mToHash.empty()) return; - details = mToHash.front(); - mToHash.pop(); - } - -#ifdef DEBUG_ELIST - std::cerr << "Hashing: " << details.info.path; - std::cerr << std::endl; -#endif - - if(RsDirUtil::hashFile( - details.info.path, details.info.fname, details.info.hash, - details.info.size )) - { - RS_STACK_MUTEX(extMutex); - - /* stick it in the available queue */ - mFiles[details.info.hash] = details; - mHashOfHash[makeEncryptedHash(details.info.hash)] = details.info.hash; - - /* add to the path->hash map */ - mHashedList[details.info.path] = details.info.hash; - - IndicateConfigChanged(); - - auto ev = std::make_shared(); - ev->mEventCode = RsSharedDirectoriesEventCode::EXTRA_LIST_FILE_ADDED; - rsEvents->postEvent(ev); - } -} - - /*** - * If the File is alreay Hashed, then just add it in. - **/ - -bool ftExtraList::addExtraFile(std::string path, const RsFileHash& hash, - uint64_t size, uint32_t period, TransferRequestFlags flags) -{ -#ifdef DEBUG_ELIST - std::cerr << "ftExtraList::addExtraFile() path: " << path; - std::cerr << " hash: " << hash; - std::cerr << " size: " << size; - std::cerr << " period: " << period; - std::cerr << " flags: " << flags; - - std::cerr << std::endl; -#endif - - RS_STACK_MUTEX(extMutex); - - FileDetails details; - - details.info.path = path; - details.info.fname = RsDirUtil::getTopDir(path); - details.info.hash = hash; - details.info.size = size; - details.info.age = time(NULL) + period; /* if time > this... cleanup */ - details.info.transfer_info_flags = flags ; - - /* stick it in the available queue */ - mFiles[details.info.hash] = details; - mHashOfHash[makeEncryptedHash(details.info.hash)] = details.info.hash ; - - IndicateConfigChanged(); - - return true; -} - -bool ftExtraList::removeExtraFile(const RsFileHash& hash) -{ - /* remove unused parameter warnings */ -#ifdef DEBUG_ELIST - std::cerr << "ftExtraList::removeExtraFile()"; - std::cerr << " hash: " << hash; - std::cerr << " flags: " << flags; - - std::cerr << std::endl; -#endif - - RS_STACK_MUTEX(extMutex); - - mHashOfHash.erase(makeEncryptedHash(hash)) ; - - std::map::iterator it; - it = mFiles.find(hash); - if (it == mFiles.end()) - { - return false; - } - - mFiles.erase(it); - - IndicateConfigChanged(); - - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mEventCode = RsSharedDirectoriesEventCode::EXTRA_LIST_FILE_REMOVED; - rsEvents->postEvent(ev); - } - return true; -} - -bool ftExtraList::moveExtraFile(std::string fname, const RsFileHash &hash, uint64_t /*size*/, - std::string destpath) -{ - RsStackMutex stack(extMutex); - - std::map::iterator it; - it = mFiles.find(hash); - if (it == mFiles.end()) - { - return false; - } - - std::string path = destpath + '/' + fname; - if (RsDirUtil::renameFile(it->second.info.path, path)) - { - /* rename */ - it->second.info.path = path; - it->second.info.fname = fname; - IndicateConfigChanged(); - } - - return true; -} - - - -bool ftExtraList::cleanupOldFiles() -{ -#ifdef DEBUG_ELIST - std::cerr << "ftExtraList::cleanupOldFiles()"; - std::cerr << std::endl; -#endif - - RS_STACK_MUTEX(extMutex); - - rstime_t now = time(NULL); - - std::list toRemove; - - for( std::map::iterator it = mFiles.begin(); it != mFiles.end(); ++it) /* check timestamps */ - if ((rstime_t)it->second.info.age < now) - toRemove.push_back(it->first); - - if (toRemove.size() > 0) - { - std::map::iterator it; - - /* remove items */ - for(std::list::iterator rit = toRemove.begin(); rit != toRemove.end(); ++rit) - { - if (mFiles.end() != (it = mFiles.find(*rit))) mFiles.erase(it); - mHashOfHash.erase(makeEncryptedHash(*rit)); - } - - IndicateConfigChanged(); - } - return true; -} - -bool ftExtraList::hashExtraFile( - std::string path, uint32_t period, TransferRequestFlags flags ) -{ - constexpr rstime_t max_int = std::numeric_limits::max(); - const rstime_t now = time(nullptr); - const rstime_t timeOut = now + period; - - if(timeOut > max_int) - { - /* Under the hood period is stored as int FileInfo::age so we do this - * check here to detect 2038 year problem - * https://en.wikipedia.org/wiki/Year_2038_problem */ - RsErr() << __PRETTY_FUNCTION__ << " period: " << period << " > " - << max_int - now << std::errc::value_too_large << std::endl; - return false; - } - - if(!RsDirUtil::fileExists(path)) - { - RsErr() << __PRETTY_FUNCTION__ << " path: " << path - << std::errc::no_such_file_or_directory << std::endl; - return false; - } - - if(RsDirUtil::checkDirectory(path)) - { - RsErr() << __PRETTY_FUNCTION__ << " path: " << path - << std::errc::is_a_directory << std::endl; - return false; - } - - FileDetails details(path, period, flags); - details.info.age = static_cast(timeOut); - - { - RS_STACK_MUTEX(extMutex); - mToHash.push(details); /* add into queue */ - } - - return true; -} - -bool ftExtraList::hashExtraFileDone(std::string path, FileInfo &info) -{ -#ifdef DEBUG_ELIST - std::cerr << "ftExtraList::hashExtraFileDone()"; - std::cerr << std::endl; -#endif - - RsFileHash hash; - { - /* Find in the path->hash map */ - RS_STACK_MUTEX(extMutex); - - std::map::iterator it; - if (mHashedList.end() == (it = mHashedList.find(path))) - { - return false; - } - hash = it->second; - } - return search(hash, FileSearchFlags(0), info); -} - - /*** - * Search Function - used by File Transfer - * - **/ -bool ftExtraList::search(const RsFileHash &hash, FileSearchFlags /*hintflags*/, FileInfo &info) const -{ -#ifdef DEBUG_ELIST - std::cerr << "ftExtraList::search() hash=" << hash ; -#endif - - /* find hash */ - std::map::const_iterator fit; - if (mFiles.end() == (fit = mFiles.find(hash))) - { -#ifdef DEBUG_ELIST - std::cerr << " not found in mFiles. Trying encrypted... " ; -#endif - // File not found. We try to look for encrypted hash. - - std::map::const_iterator hit = mHashOfHash.find(hash) ; - - if(hit == mHashOfHash.end()) - { -#ifdef DEBUG_ELIST - std::cerr << " not found." << std::endl; -#endif - return false; - } -#ifdef DEBUG_ELIST - std::cerr << " found! Reaching data..." ; -#endif - - fit = mFiles.find(hit->second) ; - - if(fit == mFiles.end()) // not found. This is an error. - { -#ifdef DEBUG_ELIST - std::cerr << " no data. Returning false." << std::endl; -#endif - return false ; - } - -#ifdef DEBUG_ELIST - std::cerr << " ok! Accepting encrypted transfer." << std::endl; -#endif - info = fit->second.info; - info.storage_permission_flags = FileStorageFlags(DIR_FLAGS_ANONYMOUS_DOWNLOAD) ; - info.transfer_info_flags |= RS_FILE_REQ_ENCRYPTED ; - } - else - { -#ifdef DEBUG_ELIST - std::cerr << " found! Accepting direct transfer" << std::endl; -#endif - info = fit->second.info; - - // Unencrypted file transfer: We only allow direct transfers. This is not exactly secure since another friend can - // swarm the file. But the hash being kept secret, there's no risk here. - // - info.storage_permission_flags = FileStorageFlags(DIR_FLAGS_BROWSABLE) ; - } - - if(info.transfer_info_flags & RS_FILE_REQ_ANONYMOUS_ROUTING) info.storage_permission_flags |= DIR_FLAGS_ANONYMOUS_DOWNLOAD ; - - return true; -} - -RsFileHash ftExtraList::makeEncryptedHash(const RsFileHash& hash) -{ - return RsDirUtil::sha1sum(hash.toByteArray(),hash.SIZE_IN_BYTES); -} - - /*** - * Configuration - store extra files. - * - **/ - -RsSerialiser *ftExtraList::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser(); - - /* add in the types we need! */ - rss->addSerialType(new RsFileConfigSerialiser()); - return rss; -} - -bool ftExtraList::saveList(bool &cleanup, std::list& sList) -{ - cleanup = true; - - /* called after each item is added */ - - /* create a list of fileitems with - * age used to specify its timeout. - */ - -#ifdef DEBUG_ELIST - std::cerr << "ftExtraList::saveList()"; - std::cerr << std::endl; -#endif - - RS_STACK_MUTEX(extMutex); - - - std::map::const_iterator it; - for(it = mFiles.begin(); it != mFiles.end(); ++it) - { - RsFileConfigItem *fi = new RsFileConfigItem(); - - fi->file.path = (it->second).info.path; - fi->file.name = (it->second).info.fname; - fi->file.hash = (it->second).info.hash; - fi->file.filesize = (it->second).info.size; - fi->file.age = (it->second).info.age; - fi->flags = (it->second).info.transfer_info_flags.toUInt32(); - - sList.push_back(fi); - } - - return true; -} - - -bool ftExtraList::loadList(std::list& load) -{ - /* for each item, check it exists .... - * - remove any that are dead (or flag?) - */ - -#ifdef DEBUG_ELIST - std::cerr << "ftExtraList::loadList()"; - std::cerr << std::endl; -#endif - - rstime_t ts = time(NULL); - - - std::list::iterator it; - for(it = load.begin(); it != load.end(); ++it) - { - - RsFileConfigItem *fi = dynamic_cast(*it); - if (!fi) - { - delete (*it); - continue; - } - - /* open file */ - FILE *fd = RsDirUtil::rs_fopen(fi->file.path.c_str(), "rb"); - if (fd == NULL) - { - delete (*it); - continue; - } - - fclose(fd); - fd = NULL ; - - if (ts > (rstime_t)fi->file.age) - { - /* too old */ - delete (*it); - continue ; - } - - /* add into system */ - FileDetails file; - - RS_STACK_MUTEX(extMutex); - - FileDetails details; - - details.info.path = fi->file.path; - details.info.fname = fi->file.name; - details.info.hash = fi->file.hash; - details.info.size = fi->file.filesize; - details.info.age = fi->file.age; /* time that we remove it. */ - details.info.transfer_info_flags = TransferRequestFlags(fi->flags); - - /* stick it in the available queue */ - mFiles[details.info.hash] = details; - mHashOfHash[makeEncryptedHash(details.info.hash)] = details.info.hash ; - - delete (*it); - - /* short sleep */ - rstime::rs_usleep(1000) ; - } - load.clear() ; - return true; -} - -void ftExtraList::getExtraFileList(std::vector& files) const -{ - RS_STACK_MUTEX(extMutex); - - files.clear(); - - for(auto it(mFiles.begin());it!=mFiles.end();++it) - files.push_back(it->second.info); -} diff --git a/libretroshare/src/ft/ftextralist.h b/libretroshare/src/ft/ftextralist.h deleted file mode 100644 index 7f96364b8..000000000 --- a/libretroshare/src/ft/ftextralist.h +++ /dev/null @@ -1,183 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftextralist.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2008 Robert Fernie * - * Copyright (C) 2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#pragma once - -/* - * ftFileExtraList - * - * This maintains a list of 'Extra Files' to share with peers. - * - * Files are added via: - * 1) For Files which have been hashed already: - * addExtraFile(std::string path, std::string hash, uint64_t size, uint32_t period, uint32_t flags); - * - * 2) For Files to be hashed: - * hashExtraFile(std::string path, uint32_t period, uint32_t flags); - * - * Results of Hashing can be retrieved via: - * hashExtraFileDone(std::string path, std::string &hash, uint64_t &size); - * - * Files can be searched for via: - * searchExtraFiles(std::string hash, ftFileDetail file); - * - * This Class is Mutexed protected, and has a thread in it which checks the files periodically. - * If a file is found to have changed... It is discarded from the list - and not updated. - * - * this thread is also used to hash added files. - * - * The list of extra files is stored using the configuration system. - * - */ - -#include -#include -#include - -#include "ft/ftsearch.h" -#include "util/rsthreads.h" -#include "retroshare/rsfiles.h" -#include "pqi/p3cfgmgr.h" -#include "util/rstime.h" - -class RS_DEPRECATED_FOR(FileInfo) FileDetails -{ - public: - FileDetails() - { - return; - } - - FileDetails(std::string path, uint32_t /*p*/, TransferRequestFlags f) - { - info.path = path; -// period = p; - info.transfer_info_flags = f; - } - - FileDetails(FileInfo &i, uint32_t /*p*/, TransferRequestFlags f) - { - info = i; - // period = p; - info.transfer_info_flags = f; - } - - FileInfo info; - -#if 0 /*** WHAT IS NEEDED ***/ - std::list sources; - std::string path; - std::string fname; - RsFileHash hash; - uint64_t size; -#endif - - //uint32_t start; - //uint32_t period; - //TransferRequestFlags flags; -}; - -const uint32_t FT_DETAILS_CLEANUP = 0x0100; /* remove when it expires */ -const uint32_t FT_DETAILS_LOCAL = 0x0001; -const uint32_t FT_DETAILS_REMOTE = 0x0002; - -const uint32_t CLEANUP_PERIOD = 600; /* 10 minutes */ - - -class ftExtraList: public RsTickingThread, public p3Config, public ftSearch -{ - -public: - - ftExtraList(); - - /*** - * If the File is alreay Hashed, then just add it in. - **/ - - bool addExtraFile(std::string path, const RsFileHash &hash, - uint64_t size, uint32_t period, TransferRequestFlags flags); - - bool removeExtraFile(const RsFileHash& hash); - bool moveExtraFile(std::string fname, const RsFileHash& hash, uint64_t size, - std::string destpath); - - - uint32_t size() const { return mFiles.size() ; } - - /*** - * Hash file, and add to the files, - * file is removed after period. - **/ - - /** - * Hash file, and add to the files, file is removed after period. - */ - bool hashExtraFile( - std::string path, uint32_t period, TransferRequestFlags flags ); - bool hashExtraFileDone(std::string path, FileInfo &info); - - /*** - * Search Function - used by File Transfer - * implementation of ftSearch. - * - **/ - virtual bool search(const RsFileHash &hash, FileSearchFlags hintflags, FileInfo &info) const; - - /*! - * \brief getExtraFileList - * Retrieves the list for display purposes - */ - void getExtraFileList(std::vector& files) const ; - - void threadTick() override; /// @see RsTickingThread - - /*** - * Configuration - store extra files. - * - **/ - -protected: - virtual RsSerialiser *setupSerialiser(); - virtual bool saveList(bool& cleanup, std::list&); - virtual bool loadList(std::list& load); - - static RsFileHash makeEncryptedHash(const RsFileHash& hash); - -private: - - /* Worker Functions */ - void hashAFile(); - bool cleanupOldFiles(); - - mutable RsMutex extMutex; - - std::queue mToHash; - - std::map mHashedList; /* path -> hash ( not saved ) */ - std::map mFiles; - std::map mHashOfHash; /* sha1(hash) map so as to answer requests to encrypted transfers */ - - rstime_t mNextCleanupTS; -}; diff --git a/libretroshare/src/ft/ftfilecreator.cc b/libretroshare/src/ft/ftfilecreator.cc deleted file mode 100644 index e38edc571..000000000 --- a/libretroshare/src/ft/ftfilecreator.cc +++ /dev/null @@ -1,765 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftfilecreator.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include -#include -#include - -#include "ftfilecreator.h" -#include "util/rstime.h" -#include "util/rsdiscspace.h" -#include "util/rsdir.h" -#include "rs_android/largefile_retrocompat.hpp" - -#ifdef WINDOWS_SYS -# include "util/rsstring.h" -# include "util/rswin.h" -#endif - -/******* - * #define FILE_DEBUG 1 - ******/ - -#define CHUNK_MAX_AGE 120 -#define MAX_FTCHUNKS_PER_PEER 20 - -/*********************************************************** -* -* ftFileCreator methods -* -***********************************************************/ - -ftFileCreator::ftFileCreator(const std::string& path, uint64_t size, const RsFileHash& hash,bool assume_availability) - : ftFileProvider(path,size,hash), chunkMap(size,assume_availability) -{ - /* - * FIXME any inits to do? - */ - -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator()"; - std::cerr << std::endl; - std::cerr << "\tpath: " << path; - std::cerr << std::endl; - std::cerr << "\tsize: " << size; - std::cerr << std::endl; - std::cerr << "\thash: " << hash; - std::cerr << std::endl; -#endif - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - rstime_t now = time(NULL) ; - _creation_time = now ; - - struct stat64 buf; - - // Initialise last recv time stamp to last modification time for the partial file. - // -#ifdef WINDOWS_SYS - std::wstring wfullname; - librs::util::ConvertUtf8ToUtf16(file_name, wfullname); - if ( 0 == _wstati64(wfullname.c_str(), &buf)) -#else - if ( 0 == stat64(file_name.c_str(), &buf)) -#endif - _last_recv_time_t = buf.st_mtime ; - else - _last_recv_time_t = now ; - -#ifdef FILE_DEBUG - std::cerr << "Inited last modification time for hash " << hash << " to " << _last_recv_time_t << std::endl; -#endif -} - -bool ftFileCreator::getFileData(const RsPeerId& peer_id,uint64_t offset, uint32_t &chunk_size, void *data, bool allow_unverified) -{ - // Only send the data if we actually have it. - // -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::getFileData(). Asked for offset=" << offset << ", size=" << chunk_size << std::endl ; -#endif - bool have_it = false ; - { - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - have_it = chunkMap.isChunkAvailable(offset, chunk_size) ; - -#define ENABLE_SLICES -#ifdef ENABLE_SLICES - // try if we have data from an incomplete or not veryfied chunk - if(!have_it && allow_unverified) - { - //std::map::iterator it; - have_it = true; - // this map contains chunks which are currently being downloaded - for(std::map::iterator it=mChunks.begin(); it!=mChunks.end(); ++it) - { - ftChunk chunk = it->second; - // begin of slice is in requested range - if(chunk.offset >= offset && chunk.offset < (offset+chunk_size)) - { - // reduce the requested size - chunk_size = chunk.offset - offset; - } - // end of slice is in requested range - if((chunk.offset+chunk.size) >= offset && (chunk.offset+chunk.size) < (offset+chunk_size)) - { - // can do nothing about this - have_it = false; - } - } - // check if the chunk was already started to download - // if not, we don't have it - if(chunkMap.isChunkOutstanding(offset, chunk_size)) - have_it = false; - } -#endif - } -#ifdef FILE_DEBUG - if(have_it) - std::cerr << "ftFileCreator::getFileData(). Have it" << std::endl ; - else - std::cerr << "ftFileCreator::getFileData(). Don't have it" << std::endl ; -#endif - - if(have_it) - return ftFileProvider::getFileData(peer_id,offset, chunk_size, data); - else - return false ; -} - -rstime_t ftFileCreator::creationTimeStamp() -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - return _creation_time ; -} -rstime_t ftFileCreator::lastRecvTimeStamp() -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - return _last_recv_time_t ; -} - -void ftFileCreator::closeFile() -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - if(fd != NULL) - { -#ifdef FILE_DEBUG - std::cerr << "CLOSED FILE " << (void*)fd << " (" << file_name << ")." << std::endl ; -#endif - fclose(fd) ; - } - - fd = NULL ; -} - -uint64_t ftFileCreator::getRecvd() -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - return chunkMap.getTotalReceived() ; -} - -bool ftFileCreator::addFileData(uint64_t offset, uint32_t chunk_size, void *data) -{ -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::addFileData("; - std::cerr << offset; - std::cerr << ", " << chunk_size; - std::cerr << ", " << data << ")"; - std::cerr << " this: " << this; - std::cerr << std::endl; -#endif - /* dodgey checking outside of mutex... much check again inside FileAttrs(). */ - /* Check File is open */ - - if(!RsDiscSpace::checkForDiscSpace(RS_PARTIALS_DIRECTORY)) - return false ; - - bool complete = false ; - { - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - if (fd == NULL) - if (!locked_initializeFileAttrs()) - return false; - - /* - * check its at the correct location - */ - if (offset + chunk_size > mSize) - { - chunk_size = mSize - offset; - std::cerr <<"Chunk Size greater than total file size, adjusting chunk size " << chunk_size << std::endl; - - } - - /* - * go to the offset of the file - */ - if (0 != fseeko64(this->fd, offset, SEEK_SET)) - { - std::cerr << "ftFileCreator::addFileData() Bad fseek at offset " << offset << ", fd=" << (void*)(this->fd) << ", size=" << mSize << ", errno=" << errno << std::endl; - return 0; - } - - if (1 != fwrite(data, chunk_size, 1, this->fd)) - { - std::cerr << "ftFileCreator::addFileData() Bad fwrite." << std::endl; - std::cerr << "ERRNO: " << errno << std::endl; - - return 0; - } - -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::addFileData() added Data..."; - std::cerr << std::endl; - std::cerr << " pos: " << offset; - std::cerr << std::endl; -#endif - /* - * Notify ftFileChunker about chunks received - */ - locked_notifyReceived(offset,chunk_size); - - complete = chunkMap.isComplete(); - } - if(complete) - { -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::addFileData() File is complete: closing" << std::endl ; -#endif - closeFile(); - } - - /* - * FIXME HANDLE COMPLETION HERE - Any better way? - */ - - return 1; -} - -void ftFileCreator::removeInactiveChunks() -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::removeInactiveChunks(): looking for old chunks." << std::endl ; -#endif - std::vector to_remove ; - - chunkMap.removeInactiveChunks(to_remove) ; - -#ifdef FILE_DEBUG - if(!to_remove.empty()) - std::cerr << "ftFileCreator::removeInactiveChunks(): removing slice ids: " ; -#endif - // This double loop looks costly, but it's called on very few chunks, and not often, so it's ok. - // - for(uint32_t i=0;i::iterator it(mChunks.begin());it!=mChunks.end();) - if(it->second.id == to_remove[i]) - { - std::map::iterator tmp(it) ; - ++it ; - if(--*tmp->second.ref_cnt == 0) - delete tmp->second.ref_cnt; - --mChunksPerPeer[tmp->second.peer_id].cnt ; - mChunks.erase(tmp) ; - } - else - ++it ; - } -#ifdef FILE_DEBUG - if(!to_remove.empty()) - std::cerr << std::endl ; -#endif -} - -void ftFileCreator::removeFileSource(const RsPeerId& peer_id) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator:: removign file source " << peer_id << " from chunkmap." << std::endl ; -#endif - chunkMap.removeFileSource(peer_id) ; -} - -int ftFileCreator::locked_initializeFileAttrs() -{ -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::initializeFileAttrs() Filename: " << file_name << " this: " << this << std::endl; -#endif - - /* - * check if the file exists - * cant use FileProviders verion because that opens readonly. - */ - - if (fd) - return 1; - - /* - * check if the file exists - */ - - { -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::initializeFileAttrs() trying (r+b) " << file_name << " this: " << this << std::endl; -#endif - } - - /* - * attempt to open file - */ - - fd = RsDirUtil::rs_fopen(file_name.c_str(), "r+b"); - - if (!fd) - { -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::initializeFileAttrs() Failed to open (r+b): "; - std::cerr << file_name << ", errno = " << errno << std::endl; - - std::cerr << "ftFileCreator::initializeFileAttrs() opening w+b"; - std::cerr << std::endl; -#endif - - /* try opening for write */ - fd = RsDirUtil::rs_fopen(file_name.c_str(), "w+b"); - if (!fd) - { - std::cerr << "ftFileCreator::initializeFileAttrs()"; - std::cerr << " Failed to open (w+b): "<< file_name << ", errno = " << errno << std::endl; - return 0; - } - } -#ifdef FILE_DEBUG - std::cerr << "OPENNED FILE " << (void*)fd << " (" << file_name << "), for r/w." << std::endl ; -#endif - - return 1; -} -ftFileCreator::~ftFileCreator() -{ -#ifdef FILE_DEBUG - std::cerr << "Deleting file creator for " << file_name << std::endl; -#endif - - // Note: The file is actually closed in the parent, that is always a ftFileProvider. - // - /* - * FIXME Any cleanups specific to filecreator? - */ -} - - -int ftFileCreator::locked_notifyReceived(uint64_t offset, uint32_t chunk_size) -{ - /* ALREADY LOCKED */ -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::locked_notifyReceived( " << offset; - std::cerr << ", " << chunk_size << " )"; - std::cerr << " this: " << this; - std::cerr << std::endl; -#endif - - /* find the chunk */ - std::map::iterator it = mChunks.find(offset); - ftChunk chunk ; - - if(it == mChunks.end()) - { - // Chunk is not found. Maybe that is because the packet is in the middle - // of an existing chunk. This case occurs whenever a packet is lost due - // to temporarily interrupted connection. In such a case we split the - // chunk. Any pending block will be re-asked to the source after 40 secs. - // -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::locked_notifyReceived(): Failed to match to existing chunk. A packet was probably dropped. Strategy is:" << std::endl; - std::cerr << " - find corresponding chunk, split it in two pieces and ask again the first part." << std::endl; - - locked_printChunkMap(); -#endif - bool found = false ; - - for(std::map::iterator it2=mChunks.begin();it2!=mChunks.end();++it2) - if( it2->second.offset < offset && it2->second.size+it2->second.offset >= chunk_size+offset) // found it if it started strictly after the beginning of the chunk and ends before its end. - { - it = it2 ; -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::locked_notifyReceived(): Chunk found: " << it->second.offset << " to " << it->second.offset + it->second.size << std::endl; -#endif - - // 1 - split the chunk into two parts. Re-ask the first part, and keep the second part - // as ongoing. - - ftChunk part1( it->second ); - part1.size = offset - it->second.offset ; // always > 0 - - chunk = it->second ; // saves the data, as it will be erased by next line - mChunks[part1.offset] = part1; - - chunk.offset = offset ; - chunk.size -= part1.size ; - - // 2 - we need to be extra careful: - // - the chunks will have the same id. That's potentially a problem for completing the slice - // we should keep a list of pending chunkIds, so as to only call chunkMap.dataReceived() when - // all parts are obtained. - // - new parts arriving in the second part cannot interfere since they should come in order. - - ++(*chunk.ref_cnt) ; - -#ifdef FILE_DEBUG - std::cerr << "Created two sub chunks. Ref_cnt = " << *chunk.ref_cnt << std::endl; - std::cerr << " chunk1: " << part1 << std::endl; - std::cerr << " chunk2: " << chunk << std::endl; -#endif - - found = true ; - break ; - } - - if(!found) - { -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::locked_notifyReceived(): failed to find an active slice for " << offset << "+" << chunk_size << ", hash = " << hash << ": dropping data." << std::endl; -#endif - return 0; /* ignoring */ - } - } - else - { - chunk = it->second; - mChunks.erase(it); - } - - if (chunk.size != chunk_size) - { - /* partial : shrink chunk */ - chunk.size -= chunk_size; - chunk.offset += chunk_size; - mChunks[chunk.offset] = chunk; - } - else if( --*chunk.ref_cnt == 0) // notify the chunkmap that the slice is finished, and decrement the number of chunks for this peer. - { -#ifdef FILE_DEBUG - std::cerr << "Chunk finished and ref cnt = " << *chunk.ref_cnt << ": deleting." << std::endl; -#endif - chunkMap.dataReceived(chunk.id) ; - --mChunksPerPeer[chunk.peer_id].cnt ; - delete chunk.ref_cnt ; // delete the counter - } -#ifdef FILE_DEBUG - else - std::cerr << "Chunk finished but ref cnt = " << *chunk.ref_cnt << ": not deleting." << std::endl; -#endif - - _last_recv_time_t = time(NULL) ; - - /* otherwise there is another earlier block to go - */ - - return 1; -} - -FileChunksInfo::ChunkStrategy ftFileCreator::getChunkStrategy() -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - return chunkMap.getStrategy() ; -} -void ftFileCreator::setChunkStrategy(FileChunksInfo::ChunkStrategy s) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - // Let's check, for safety. - if(s != FileChunksInfo::CHUNK_STRATEGY_STREAMING && s != FileChunksInfo::CHUNK_STRATEGY_RANDOM && s != FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE) - { - std::cerr << "ftFileCreator::ERROR: invalid chunk strategy " << s << "!" << " setting default value " << FileChunksInfo::CHUNK_STRATEGY_STREAMING << std::endl ; - s = FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE ; - } - -#ifdef FILE_DEBUG - std::cerr << "ftFileCtreator: setting chunk strategy to " << s << std::endl ; -#endif - chunkMap.setStrategy(s) ; -} - -/* Returns true if more to get - * But can return size = 0, if we are still waiting for the data. - */ - -bool ftFileCreator::getMissingChunk(const RsPeerId& peer_id,uint32_t size_hint,uint64_t &offset, uint32_t& size,bool& source_chunk_map_needed) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ -#ifdef FILE_DEBUG - std::cerr << "ffc::getMissingChunk(...,"<< size_hint << ")"; - std::cerr << " this: " << this; - std::cerr << std::endl; - locked_printChunkMap(); -#endif - source_chunk_map_needed = false ; - rstime_t now = time(NULL) ; - - // 0 - is there a faulting chunk that would need to be asked again ? - - for(std::map::iterator it(mChunks.begin());it!=mChunks.end();++it) - if(it->second.ts + CHUNK_MAX_AGE < now && chunkMap.getSourceChunksInfo(peer_id)->hasData(it->second.offset,ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE)) - { - offset = it->second.offset ; - size = it->second.size ; - it->second.ts = now ; - -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::getMissingChunk(): re-asking for chunk that wasn't received: " << offset << " + " << size << std::endl; -#endif - return true ; - } - - // 1 - is there an ongoing 1MB chunk for which we need to take a new slice? - // - uint32_t& chunks_for_this_peer(mChunksPerPeer[peer_id].cnt) ; - - if(chunks_for_this_peer >= MAX_FTCHUNKS_PER_PEER) - { -#ifdef FILE_DEBUG - std::cerr << "ffc::getMissingChunk() too many chunks for peer " << peer_id << " for hash " << hash << ". Count = " << chunks_for_this_peer << std::endl ; -#endif - return false ; - } - - /* else allocate a new chunk */ - - ftChunk chunk ; - - if(!chunkMap.getDataChunk(peer_id,size_hint,chunk,source_chunk_map_needed)) - { - // No chunks are available. We brutally re-ask an ongoing chunk to another peer. - - if(chunkMap.reAskPendingChunk(peer_id,size_hint,offset,size)) - return true ; - - return false ; - } - -#ifdef FILE_DEBUG - std::cerr << "ffc::getMissingChunk() Retrieved new chunk: " << chunk << std::endl ; -#endif - - chunk.ref_cnt = new int ; - *chunk.ref_cnt = 1 ; - mChunks[chunk.offset] = chunk ; - - offset = chunk.offset ; - // cppcheck-suppress unreadVariable - size = chunk.size ; - - ++chunks_for_this_peer ; // increase number of chunks for this peer. - - return true; /* cos more data to get */ -} - -void ftFileCreator::getChunkMap(FileChunksInfo& info) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - chunkMap.getChunksInfo(info) ; - - // add info pending requests, handled by ftFileCreator - // - info.pending_slices.clear(); - - for(std::map::iterator it = mChunks.begin();it!=mChunks.end();++it) - { - int n = it->second.id / info.chunk_size ; - - FileChunksInfo::SliceInfo si ; - si.start = it->second.offset - n*info.chunk_size ; - si.size = it->second.size ; - si.peer_id = it->second.peer_id ; - - info.pending_slices[n].push_back(si) ; - } -} - -bool ftFileCreator::locked_printChunkMap() -{ -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator::locked_printChunkMap()"; - std::cerr << " this: " << this; - std::cerr << std::endl; -#endif - - /* check start point */ - std::cerr << "\tOutstanding Chunks:"; - std::cerr << std::endl; - - std::map::iterator it; - - for(it = mChunks.begin(); it != mChunks.end(); ++it) - std::cerr << " " << it->second << std::endl ; - - std::cerr << "Active chunks per peer:" << std::endl ; - for(std::map::const_iterator it(mChunksPerPeer.begin());it!=mChunksPerPeer.end();++it) - std::cerr << " " << it->first << "\t: " << it->second.cnt << std::endl; - - return true; -} - -void ftFileCreator::setAvailabilityMap(const CompressedChunkMap& cmap) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - chunkMap.setAvailabilityMap(cmap) ; -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator: setting chunkmap for hash " << hash << ": " ; - - for(uint32_t i=0;iis_full ; -} - -void ftFileCreator::setSourceMap(const RsPeerId& peer_id,const CompressedChunkMap& compressed_map) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - -#ifdef FILE_DEBUG - std::cerr << "ftFileCreator:: Received source map for hash " << hash << " for source peer " << peer_id << std::endl; -#endif - // At this point, we should cancel all file chunks that are asked to the - // peer and which this peer actually doesn't possesses. Otherwise, the transfer may get stuck. - // This should be done by: - // - first setting the peer availability map - // - then asking the chunkmap which chunks are being downloaded, but actually shouldn't - // - cancelling them in the ftFileCreator, so that they can be re-asked later to another peer. - // - chunkMap.setPeerAvailabilityMap(peer_id,compressed_map) ; -} - -bool ftFileCreator::finished() -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - return chunkMap.isComplete() ; -} - -bool ftFileCreator::hashReceivedData(RsFileHash& hash) -{ -#ifdef FILE_DEBUG - std::cerr << "file creator asked for hashing received data " << file_name << std::endl; -#endif - - // csoler: No mutex here please ! - // - // This is a bit dangerous, but otherwise we might stuck the GUI for a - // long time. Therefore, we must pay attention not to call this function - // at a time file_name nor hash can be modified, which is easy. - // - if(!finished()) - { - std::cerr << "Transfer not finished !! This should not happen" << std::endl; - return false ; - } - - uint64_t tmpsize ; - return RsDirUtil::getFileHash(file_name,hash,tmpsize) ; -} - -void ftFileCreator::forceCheck() -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - chunkMap.forceCheck(); -} - -void ftFileCreator::getSourcesList(uint32_t chunk_num,std::vector& sources) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - chunkMap.getSourcesList(chunk_num,sources) ; -} - -void ftFileCreator::getChunksToCheck(std::vector& chunks_to_ask) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - chunkMap.getChunksToCheck(chunks_to_ask) ; -} - -bool ftFileCreator::verifyChunk(uint32_t chunk_number,const Sha1CheckSum& sum) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - if(!locked_initializeFileAttrs() ) - return false ; - - static const uint32_t chunk_size = ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE ; - unsigned char *buff = new unsigned char[chunk_size] ; - uint32_t len ; - - if(fseeko64(fd,(uint64_t)chunk_number * (uint64_t)chunk_size,SEEK_SET)==0 && (len = fread(buff,1,chunk_size,fd)) > 0) - { - Sha1CheckSum comp = RsDirUtil::sha1sum(buff,len) ; - - if(sum == comp) - chunkMap.setChunkCheckingResult(chunk_number,true) ; - else - { - std::cerr << "Sum mismatch for chunk " << chunk_number << std::endl; - std::cerr << " Computed hash = " << comp.toStdString() << std::endl; - std::cerr << " Reference hash = " << sum.toStdString() << std::endl; - - chunkMap.setChunkCheckingResult(chunk_number,false) ; - } - } - else - { - printf("Chunk verification: cannot fseek!\n") ; - chunkMap.setChunkCheckingResult(chunk_number,false) ; - } - - delete[] buff ; - return true ; -} - - - diff --git a/libretroshare/src/ft/ftfilecreator.h b/libretroshare/src/ft/ftfilecreator.h deleted file mode 100644 index 01a990414..000000000 --- a/libretroshare/src/ft/ftfilecreator.h +++ /dev/null @@ -1,151 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftfilecreator.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef FT_FILE_CREATOR_HEADER -#define FT_FILE_CREATOR_HEADER - -/* - * ftFileCreator - * - * TODO: Serialiser Load / Save. - * - */ -#include "ftfileprovider.h" -#include "ftchunkmap.h" -#include - -class ZeroInitCounter -{ - public: - ZeroInitCounter(): cnt(0) {} - uint32_t cnt ; -}; - -class ftFileCreator: public ftFileProvider -{ - public: - - ftFileCreator(const std::string& savepath, uint64_t size, const RsFileHash& hash,bool assume_availability); - - ~ftFileCreator(); - - /* overloaded from FileProvider */ - virtual bool getFileData(const RsPeerId& peer_id,uint64_t offset, uint32_t &chunk_size, void *data, bool allow_unverified = false); - bool finished() ; - uint64_t getRecvd(); - - /// (temporarily) close the file, to save file descriptors. - void closeFile() ; - - void getChunkMap(FileChunksInfo& info) ; - - void setChunkStrategy(FileChunksInfo::ChunkStrategy s) ; - FileChunksInfo::ChunkStrategy getChunkStrategy() ; - - // Computes a sha1sum of the partial file, to check that the data is overall consistent. - // This function is not mutexed. This is a bit dangerous, but otherwise we might stuck the GUI for a - // long time. Therefore, we must pay attention not to call this function - // at a time file_name nor hash can be modified, which is quite easy. - - bool hashReceivedData(RsFileHash& hash) ; - - // Sets all chunks to checking state - // - void forceCheck() ; - - bool verifyChunk(uint32_t, const Sha1CheckSum&) ; - - // Looks into the chunkmap for downloaded chunks that have not yet been certified. - // For each of them, returns the chunk number and a source peer to ask the CRC to. - // - void getChunksToCheck(std::vector& chunks_to_ask) ; - - /* - * creation functions for FileCreator - */ - - // Gets a new variable-sized chunk of size "size_hint" from the given peer id. The returned size, "size" is - // at most equal to size_hint. chunk_map_needed is set if - // - no chunkmap info is available. In such a case, the chunk info is irrelevant and false is returned. - // - the chunk info is too old. In tis case, true is returned, and the chunks info can be used. - // - bool getMissingChunk(const RsPeerId& peer_id,uint32_t size_hint,uint64_t& offset, uint32_t& size,bool& is_chunk_map_too_old); - - // Takes care of purging any inactive chunks. This should be called regularly, because some peers may disconnect - // and let inactive chunks not finished. - // - void removeInactiveChunks() ; - - // removes the designated file source from the chunkmap. - void removeFileSource(const RsPeerId& peer_id) ; - - // Get all available sources for this chunk - // - void getSourcesList(uint32_t chunk_number,std::vector& sources) ; - - // Returns resets the time stamp of the last data receive. - rstime_t lastRecvTimeStamp() ; - rstime_t creationTimeStamp() ; - - // actually store data in the file, and update chunks info - // - bool addFileData(uint64_t offset, uint32_t chunk_size, void *data); - - // Load/save the availability map for the file being downloaded, in a compact/compressed form. - // This is used for - // - loading and saving info about the current transfers - // - getting info about current chunks for the GUI - // - sending availability info to the peers for which we also are a source - // - virtual void getAvailabilityMap(CompressedChunkMap& cmap) ; - void setAvailabilityMap(const CompressedChunkMap& cmap) ; - - // This is called when receiving the availability map from a source peer, for the file being handled. - // - void setSourceMap(const RsPeerId& peer_id,const CompressedChunkMap& map) ; - - // Returns true id the given file source is complete. - // - bool sourceIsComplete(const RsPeerId& peer_id) ; - - protected: - - virtual int locked_initializeFileAttrs(); - - private: - - bool locked_printChunkMap(); - int locked_notifyReceived(uint64_t offset, uint32_t chunk_size); - /* - * structure to track missing chunks - */ - - std::map mChunks; - std::map mChunksPerPeer ; - - ChunkMap chunkMap ; - - rstime_t _last_recv_time_t ; /// last time stamp when data was received. Used for queue control. - rstime_t _creation_time ; /// time at which the file creator was created. Used to spot long-inactive transfers. -}; - -#endif // FT_FILE_CREATOR_HEADER diff --git a/libretroshare/src/ft/ftfileprovider.cc b/libretroshare/src/ft/ftfileprovider.cc deleted file mode 100644 index b789f9057..000000000 --- a/libretroshare/src/ft/ftfileprovider.cc +++ /dev/null @@ -1,360 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftfileprovider.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include -#include - -#include "ftfileprovider.h" -#include "ftchunkmap.h" -#include "util/rstime.h" -#include "util/rsdir.h" -#include "rs_android/largefile_retrocompat.hpp" - -#ifdef WINDOWS_SYS -# include "util/rswin.h" -#endif // WINDOWS_SYS - - -/******** -* #define DEBUG_FT_FILE_PROVIDER 1 -* #define DEBUG_TRANSFERS 1 // TO GET TIMESTAMPS of DATA READING -********/ - -#ifdef DEBUG_TRANSFERS - #include "util/rsprint.h" - #include -#endif - -static const rstime_t UPLOAD_CHUNK_MAPS_TIME = 20 ; // time to ask for a new chunkmap from uploaders in seconds. - -ftFileProvider::ftFileProvider(const std::string& path, uint64_t size, const RsFileHash& hash) - : mSize(size), hash(hash), file_name(path), fd(NULL), ftcMutex("ftFileProvider") -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - -#ifdef DEBUG_FT_FILE_PROVIDER - std::cout << "Creating file provider for " << hash << std::endl ; -#endif -} - -ftFileProvider::~ftFileProvider() -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ -#ifdef DEBUG_FT_FILE_PROVIDER - std::cout << "ftFileProvider::~ftFileProvider(): Destroying file provider for " << hash << std::endl ; -#endif - if (fd!=NULL) { - fclose(fd); - fd = NULL ; -#ifdef DEBUG_FT_FILE_PROVIDER - std::cout << "ftFileProvider::~ftFileProvider(): closed file: " << hash << std::endl ; -#endif - } -} - -bool ftFileProvider::fileOk() -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - return (fd != NULL); -} - -RsFileHash ftFileProvider::getHash() -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - return hash; -} - -uint64_t ftFileProvider::getFileSize() -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - return mSize; -} - -bool ftFileProvider::FileDetails(FileInfo &info) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - info.hash = hash; - info.size = mSize; - info.path = file_name; - info.fname = RsDirUtil::getTopDir(file_name); - - info.transfered = 0 ; // unused - info.lastTS = 0; - info.downloadStatus = FT_STATE_DOWNLOADING ; - - info.peers.clear() ; - float total_transfer_rate = 0.0f ; - - for(std::map::const_iterator it(uploading_peers.begin());it!=uploading_peers.end();++it) - { - TransferInfo inf ; - inf.peerId = it->first ; - inf.status = FT_STATE_DOWNLOADING ; - inf.name = info.fname ; - inf.transfered = it->second.req_loc ; - - inf.tfRate = it->second.transfer_rate/1024.0 ; - total_transfer_rate += it->second.transfer_rate ; - info.lastTS = std::max(info.lastTS,it->second.lastTS); - - info.peers.push_back(inf) ; - } - info.tfRate = total_transfer_rate/1024.0 ; - - /* Use req_loc / req_size to estimate data rate */ - - return true; -} - -bool ftFileProvider::purgeOldPeers(rstime_t now,uint32_t max_duration) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - -#ifdef DEBUG_FT_FILE_PROVIDER - std::cerr << "ftFileProvider::purgeOldPeers(): " << (void*)this << ": examining peers." << std::endl ; -#endif - bool ret = true ; - for(std::map::iterator it(uploading_peers.begin());it!=uploading_peers.end();) - if( (*it).second.lastTS+max_duration < (uint32_t)now) - { -#ifdef DEBUG_FT_FILE_PROVIDER - std::cerr << "ftFileProvider::purgeOldPeers(): " << (void*)this << ": peer " << it->first << " is too old. Removing." << std::endl ; -#endif - std::map::iterator tmp = it ; - ++tmp ; - uploading_peers.erase(it) ; - it=tmp ; - } - else - { -#ifdef DEBUG_FT_FILE_PROVIDER - std::cerr << "ftFileProvider::purgeOldPeers(): " << (void*)this << ": peer " << it->first << " will be kept." << std::endl ; -#endif - ret = false ; - ++it ; - } - return ret ; -} - -void ftFileProvider::getAvailabilityMap(CompressedChunkMap& cmap) -{ - // We are here because the file we deal with is complete. So we return a plain map. - // - ChunkMap::buildPlainMap(mSize,cmap) ; -} - - -bool ftFileProvider::getFileData(const RsPeerId& peer_id,uint64_t offset, uint32_t &chunk_size, void *data, bool /*allow_unverified*/) -{ - /* dodgey checking outside of mutex... - * much check again inside FileAttrs(). - */ - if (fd == NULL) - if (!initializeFileAttrs()) - return false; - - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - /* - * FIXME: Warning of comparison between unsigned and signed int? - */ - - if(offset >= mSize) - { - std::cerr << "ftFileProvider::getFileData(): request (" << offset << ") exceeds file size (" << mSize << "! " << std::endl; - return false ; - } - - uint32_t data_size = chunk_size; - uint64_t base_loc = offset; - - if (base_loc + data_size > mSize) - { - data_size = mSize - base_loc; - chunk_size = mSize - base_loc; - std::cerr <<"Chunk Size greater than total file size, adjusting chunk size " << data_size << std::endl; - } - - if(data_size > 0 && data != NULL) - { - /* - * seek for base_loc - */ - if(fseeko64(fd, base_loc, SEEK_SET) == -1) - { - #ifdef DEBUG_FT_FILE_PROVIDER - std::cerr << "ftFileProvider::getFileData() Failed to seek. Data_size=" << data_size << ", base_loc=" << base_loc << " !" << std::endl; - #endif - //free(data); No!! It's already freed upwards in ftDataMultiplex::locked_handleServerRequest() - return 0; - } - - // Data space allocated by caller. - //void *data = malloc(chunk_size); - - /* - * read the data - */ - - if (1 != fread(data, data_size, 1, fd)) - { - #ifdef DEBUG_FT_FILE_PROVIDER - std::cerr << "ftFileProvider::getFileData() Failed to get data. Data_size=" << data_size << ", base_loc=" << base_loc << " !" << std::endl; - #endif - //free(data); No!! It's already freed upwards in ftDataMultiplex::locked_handleServerRequest() - return 0; - } - - /* - * Update status of ftFileStatus to reflect last usage (for GUI display) - * We need to store. - * (a) Id, - * (b) Offset, - * (c) Size, - * (d) timestamp - */ - - // This creates the peer info, and updates it. - // - rstime_t now = time(NULL) ; - uploading_peers[peer_id].updateStatus(offset,data_size,now) ; - -#ifdef DEBUG_TRANSFERS - std::cerr << "ftFileProvider::getFileData() "; - std::cerr << " at " << RsUtil::AccurateTimeString(); - std::cerr << " hash: " << hash; - std::cerr << " for peerId: " << peer_id; - std::cerr << " offset: " << offset; - std::cerr << " chunkSize: " << chunk_size; - std::cerr << std::endl; -#endif - - } - else - { - std::cerr << "No data to read, or NULL buffer used" << std::endl; - return 0; - } - return 1; -} - -void ftFileProvider::PeerUploadInfo::updateStatus(uint64_t offset,uint32_t data_size,rstime_t now) -{ - lastTS = now ; - long int diff = (long int)now - (long int)lastTS_t ; // in bytes/s. Average over multiple samples - -#ifdef DEBUG_FT_FILE_PROVIDER - std::cout << "diff = " << diff << std::endl ; -#endif - - if(diff > 3) - { - transfer_rate = total_size / (float)diff ; -#ifdef DEBUG_FT_FILE_PROVIDER - std::cout << "updated TR = " << transfer_rate << ", total_size=" << total_size << std::endl ; -#endif - lastTS_t = now ; - total_size = 0 ; - } - - req_loc = offset; - req_size = data_size; - total_size += req_size ; -} - -void ftFileProvider::setClientMap(const RsPeerId& peer_id,const CompressedChunkMap& cmap) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - // Create by default. - uploading_peers[peer_id].client_chunk_map = cmap ; - uploading_peers[peer_id].client_chunk_map_stamp = time(NULL) ; -} - -void ftFileProvider::getClientMap(const RsPeerId& peer_id,CompressedChunkMap& cmap,bool& map_is_too_old) -{ - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - - PeerUploadInfo& pui(uploading_peers[peer_id]) ; - - rstime_t now = time(NULL) ; - - if(now - pui.client_chunk_map_stamp > UPLOAD_CHUNK_MAPS_TIME) - { - map_is_too_old = true ; - pui.client_chunk_map_stamp = now ; // to avoid re-asking before the TTL - } - else - map_is_too_old = false ; - - cmap = pui.client_chunk_map; -} - -int ftFileProvider::initializeFileAttrs() -{ -#ifdef DEBUG_FT_FILE_PROVIDER - std::cerr << "ftFileProvider::initializeFileAttrs() Filename: " << file_name << std::endl; -#endif - - RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ - if (fd) - return 1; - - /* - * check if the file exists - */ - - { -#ifdef DEBUG_FT_FILE_PROVIDER - std::cerr << "ftFileProvider::initializeFileAttrs() trying (r+b) " << std::endl; -#endif - } - - /* - * attempt to open file - */ - - fd = RsDirUtil::rs_fopen(file_name.c_str(), "r+b"); - if (!fd) - { - std::cerr << "ftFileProvider::initializeFileAttrs() Failed to open (r+b): "; - std::cerr << file_name << std::endl; - - /* try opening read only */ - fd = RsDirUtil::rs_fopen(file_name.c_str(), "rb"); - if (!fd) - { - std::cerr << "ftFileProvider::initializeFileAttrs() Failed to open (rb): "; - std::cerr << file_name << std::endl; - - /* try opening read only */ - return 0; - } - } -#ifdef DEBUG_FT_FILE_PROVIDER - std::cerr << "ftFileProvider:: openned file " << file_name << std::endl ; -#endif - - return 1; -} - - diff --git a/libretroshare/src/ft/ftfileprovider.h b/libretroshare/src/ft/ftfileprovider.h deleted file mode 100644 index 4ed0dbec9..000000000 --- a/libretroshare/src/ft/ftfileprovider.h +++ /dev/null @@ -1,118 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftfileprovider.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef FT_FILE_PROVIDER_HEADER -#define FT_FILE_PROVIDER_HEADER - -/* - * ftFileProvider. - * - */ -#include -#include -#include "util/rsthreads.h" -#include "retroshare/rsfiles.h" - -class ftFileProvider -{ - public: - ftFileProvider(const std::string& path, uint64_t size, const RsFileHash& hash); - virtual ~ftFileProvider(); - - /** - * read a block of data from the file - * @param peer_id for the uploading stats: to which peer the data will be send - * @param offset begin of the requested data range - * @param chunk_size how many bytes to read. Will be set to the number of valid bytes in data on return. - * @param data pointer to a buffer of size chunk_size. Contains the data on success. - * @param allow_unverified for ftFileCreator: set to true to return data from unverified chunks. Use it if you want data asap. - * @return true if data was read - */ - virtual bool getFileData(const RsPeerId& peer_id,uint64_t offset, uint32_t &chunk_size, void *data, bool allow_unverified = false); - virtual bool FileDetails(FileInfo &info); - RsFileHash getHash(); - uint64_t getFileSize(); - bool fileOk(); - - // Provides a client for the map of chunks actually present in the file. If the provider is also - // a file creator, because the file is actually being downloaded, then the map may be partially complete. - // Otherwize, a plain map is returned. - // - virtual void getAvailabilityMap(CompressedChunkMap& cmap) ; - - // a ftFileProvider feeds a distant peer. To display what the peers already has, we need to store/read this info. - void getClientMap(const RsPeerId& peer_id,CompressedChunkMap& cmap,bool& map_is_too_old) ; - void setClientMap(const RsPeerId& peer_id,const CompressedChunkMap& cmap) ; - - // Removes inactive peers from the client list. Returns true if all peers have been removed. - // - bool purgeOldPeers(rstime_t now,uint32_t max_duration) ; - - const RsFileHash& fileHash() const { return hash ; } - const std::string& fileName() const { return file_name ; } - uint64_t fileSize() const { return mSize ; } - protected: - virtual int initializeFileAttrs(); /* does for both */ - - uint64_t mSize; - RsFileHash hash; - std::string file_name; - FILE *fd; - - /* - * Structure to gather statistics FIXME: lastRequestor - figure out a - * way to get last requestor (peerID) - */ - class PeerUploadInfo - { - public: - PeerUploadInfo() - : req_loc(0),req_size(1), lastTS_t(0), lastTS(0),transfer_rate(0), total_size(0), client_chunk_map_stamp(0) {} - - void updateStatus(uint64_t offset,uint32_t data_size,rstime_t now) ; - - uint64_t req_loc; - uint32_t req_size; - rstime_t lastTS_t; // used for estimating transfer rate. - rstime_t lastTS; // last update time (for purging) - - // these two are used for speed estimation - float transfer_rate ; - uint32_t total_size ; - - // Info about what the downloading peer already has - CompressedChunkMap client_chunk_map ; - rstime_t client_chunk_map_stamp ; - }; - - // Contains statistics (speed, peer name, etc.) of all uploading peers for that file. - // - std::map uploading_peers ; - - /* - * Mutex Required for stuff below - */ - RsMutex ftcMutex; -}; - - -#endif // FT_FILE_PROVIDER_HEADER diff --git a/libretroshare/src/ft/ftfilesearch.cc b/libretroshare/src/ft/ftfilesearch.cc deleted file mode 100644 index c9571f9a8..000000000 --- a/libretroshare/src/ft/ftfilesearch.cc +++ /dev/null @@ -1,177 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftfilesearch.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "ft/ftfilesearch.h" - -const uint32_t MAX_SEARCHS = 24; /* lower 24 bits of hint */ - -//#define DEBUG_SEARCH 1 - -ftFileSearch::ftFileSearch() - :mSearchs(MAX_SEARCHS) -{ - uint32_t i; - for(i = 0; i < MAX_SEARCHS; i++) - { - mSearchs[i] = NULL; - } -} - -bool ftFileSearch::addSearchMode(ftSearch *search, FileSearchFlags hintflags) -{ - hintflags &= FileSearchFlags(0x000000ff); - -#ifdef DEBUG_SEARCH - std::cerr << "ftFileSearch::addSearchMode() : " << hintflags; - std::cerr << std::endl; -#endif - - uint32_t i; - for (i = 0; i < MAX_SEARCHS; i++) - { - uint32_t hints = hintflags.toUInt32() >> i; - if (hints & 0x0001) - { - /* has the flag */ - mSearchs[i] = search; - -#ifdef DEBUG_SEARCH - std::cerr << "ftFileSearch::addSearchMode() to slot "; - std::cerr << i; - std::cerr << std::endl; -#endif - - return true; - } - } - -#ifdef DEBUG_SEARCH - std::cerr << "ftFileSearch::addSearchMode() Failed"; - std::cerr << std::endl; -#endif - - return false; -} - -bool ftFileSearch::search(const RsFileHash &hash, FileSearchFlags hintflags, FileInfo &info) const -{ - uint32_t hints, i; - -#ifdef DEBUG_SEARCH - std::cerr << "ftFileSearch::search(" << hash ; - std::cerr << ", " << hintflags << ");"; - std::cerr << std::endl; -#endif - - for (i = 0; i < MAX_SEARCHS; i++) - { - hints = hintflags.toUInt32() >> i; - if (hints & 0x0001) - { - /* has the flag */ - ftSearch *search = mSearchs[i]; - if (search) - { -#ifdef DEBUG_SEARCH - std::cerr << "ftFileSearch::search() SLOT: "; - std::cerr << i; - std::cerr << std::endl; -#endif - if (search->search(hash, hintflags, info)) - { -#ifdef DEBUG_SEARCH - std::cerr << "ftFileSearch::search() SLOT: "; - std::cerr << i << " success!"; - std::cerr << std::endl; -#endif - return true; - } - else - { -#ifdef DEBUG_SEARCH - std::cerr << "ftFileSearch::search() SLOT: "; - std::cerr << i << " no luck"; - std::cerr << std::endl; -#endif - } - } - } - } - - /* if we haven't found it by now! - check if SPEC_ONLY flag is set */ - if (hintflags & RS_FILE_HINTS_SPEC_ONLY) - { -#ifdef DEBUG_SEARCH - std::cerr << "ftFileSearch::search() SPEC_ONLY: Failed"; - std::cerr << std::endl; -#endif - return false; - } - -#ifdef DEBUG_SEARCH - std::cerr << "ftFileSearch::search() Searching Others (no SPEC ONLY):"; - std::cerr << std::endl; -#endif - - /* if we don't have the SPEC_ONLY flag, - * we check through all the others - */ - for (i = 0; i < MAX_SEARCHS; i++) - { - hints = hintflags.toUInt32() >> i; - if (hints & 0x0001) - { - continue; - } - - /* has the flag */ - ftSearch *search = mSearchs[i]; - if (search) - { - -#ifdef DEBUG_SEARCH - std::cerr << "ftFileSearch::search() SLOT: " << i; - std::cerr << std::endl; -#endif - if (search->search(hash, hintflags, info)) - { -#ifdef DEBUG_SEARCH - std::cerr << "ftFileSearch::search() SLOT: "; - std::cerr << i << " success!"; - std::cerr << std::endl; -#endif - return true; - } - else - { -#ifdef DEBUG_SEARCH - std::cerr << "ftFileSearch::search() SLOT: "; - std::cerr << i << " no luck"; - std::cerr << std::endl; -#endif - } - - } - } - /* found nothing */ - return false; -} - diff --git a/libretroshare/src/ft/ftfilesearch.h b/libretroshare/src/ft/ftfilesearch.h deleted file mode 100644 index 46c11d33c..000000000 --- a/libretroshare/src/ft/ftfilesearch.h +++ /dev/null @@ -1,56 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftfilesearch.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef FT_FILE_SEARCH_HEADER -#define FT_FILE_SEARCH_HEADER - -/* - * ftFileSearch - * - * This is implements an array of ftSearch Interfaces. - * - */ - -#include - -#include "ft/ftsearch.h" - -class ftFileSearch: public ftSearch -{ - - public: - - ftFileSearch(); - -bool addSearchMode(ftSearch *search, FileSearchFlags hintflags); -virtual bool search(const RsFileHash &hash, FileSearchFlags hintflags, FileInfo &info) const; - - private: - - // should have a mutex to protect vector.... - // but not really necessary as it is const most of the time. - - std::vector mSearchs; -}; - - -#endif diff --git a/libretroshare/src/ft/ftsearch.h b/libretroshare/src/ft/ftsearch.h deleted file mode 100644 index 7906d275f..000000000 --- a/libretroshare/src/ft/ftsearch.h +++ /dev/null @@ -1,50 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftsearch.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef FT_SEARCH_HEADER -#define FT_SEARCH_HEADER - -/* - * ftSearch - * - * This is a generic search interface - used by ft* to find files. - * The derived class will search for Caches/Local/ExtraList/Remote entries. - * - */ - -#include "retroshare/rsfiles.h" // includes retroshare/rstypes.h too! - -class ftSearch -{ - - public: - ftSearch() { return; } - virtual ~ftSearch() { return; } - virtual bool search(const RsFileHash & /*hash*/, FileSearchFlags /*hintflags*/,const RsPeerId& /*peer_id*/, FileInfo & /*info*/) const - { - std::cerr << "Non overloaded search method called!!!" << std::endl; - return false; - } - virtual bool search(const RsFileHash &hash, FileSearchFlags hintflags, FileInfo &info) const = 0; - -}; - -#endif diff --git a/libretroshare/src/ft/ftserver.cc b/libretroshare/src/ft/ftserver.cc deleted file mode 100644 index 69f050a32..000000000 --- a/libretroshare/src/ft/ftserver.cc +++ /dev/null @@ -1,2371 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftserver.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2008 Robert Fernie * - * Copyright (C) 2018-2021 Gioacchino Mazzurco * - * Copyright (C) 2019-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include -#include -#include -#include - -#include "crypto/chacha20.h" -//const int ftserverzone = 29539; - -#include "file_sharing/p3filelists.h" -#include "ft/ftcontroller.h" -#include "ft/ftdatamultiplex.h" -//#include "ft/ftdwlqueue.h" -#include "ft/ftextralist.h" -#include "ft/ftfileprovider.h" -#include "ft/ftfilesearch.h" -#include "ft/ftserver.h" -#include "ft/ftturtlefiletransferitem.h" - -#include "pqi/p3linkmgr.h" -#include "pqi/p3notify.h" -#include "pqi/pqi.h" - -#include "retroshare/rstypes.h" -#include "retroshare/rspeers.h" -#include "retroshare/rsinit.h" -#include "util/cxx17retrocompat.h" -#include "rsitems/rsfiletransferitems.h" -#include "rsitems/rsserviceids.h" -#include "util/rsmemory.h" -#include "rsserver/p3face.h" -#include "turtle/p3turtle.h" -#include "util/rsurl.h" -#include "util/rsdebug.h" -#include "util/rsdir.h" -#include "util/rsprint.h" -#include "util/rstime.h" - -#ifdef RS_DEEP_FILES_INDEX -# include "deep_search/filesindex.hpp" -#endif // def RS_DEEP_FILES_INDEX - -/*** - * #define SERVER_DEBUG 1 - * #define SERVER_DEBUG_CACHE 1 - ***/ - -#define FTSERVER_DEBUG() std::cerr << time(NULL) << " : FILE_SERVER : " << __FUNCTION__ << " : " -#define FTSERVER_ERROR() std::cerr << "(EE) FILE_SERVER ERROR : " - -/*static*/ const RsFilesErrorCategory RsFilesErrorCategory::instance; - -/*static*/ const std::string RsFiles::DEFAULT_FILES_BASE_URL = - "retroshare:///files"; -/*static*/ const std::string RsFiles::FILES_URL_COUNT_FIELD = "filesCount"; -/*static*/ const std::string RsFiles::FILES_URL_DATA_FIELD = "filesData"; -// Use a 5 character word so there is no mistake it isn't base64 as 5%4=1 -/*static*/ const std::string RsFiles::FILES_URL_FAGMENT_FORWARD = "fragm"; -/*static*/ const std::string RsFiles::FILES_URL_NAME_FIELD = "filesName"; -/*static*/ const std::string RsFiles::FILES_URL_SIZE_FIELD = "filesSize"; - - -static const rstime_t FILE_TRANSFER_LOW_PRIORITY_TASKS_PERIOD = 5 ; // low priority tasks handling every 5 seconds -static const rstime_t FILE_TRANSFER_MAX_DELAY_BEFORE_DROP_USAGE_RECORD = 10 ; // keep usage records for 10 secs at most. - -#ifdef RS_DEEP_FILES_INDEX -TurtleFileInfoV2::TurtleFileInfoV2(const DeepFilesSearchResult& dRes) : - fHash(dRes.mFileHash), fWeight(static_cast(dRes.mWeight)), - fSnippet(dRes.mSnippet) -{ - FileInfo fInfo; - rsFiles->FileDetails(fHash, RS_FILE_HINTS_LOCAL, fInfo); - - fSize = fInfo.size; - fName = fInfo.fname; -} -#endif // def RS_DEEP_FILES_INDEX - -TurtleFileInfoV2::~TurtleFileInfoV2() = default; - -/* Setup */ -ftServer::ftServer(p3PeerMgr *pm, p3ServiceControl *sc): - p3Service(), - // should be FT, but this is for backward compatibility - RsServiceSerializer(RS_SERVICE_TYPE_TURTLE), - mPeerMgr(pm), mServiceCtrl(sc), - mFileDatabase(NULL), - mFtController(NULL), mFtExtra(NULL), - mFtDataplex(NULL), mFtSearch(NULL), srvMutex("ftServer"), - mSearchCallbacksMapMutex("ftServer callbacks map") -{ - addSerialType(new RsFileTransferSerialiser()) ; -} - -const std::string FILE_TRANSFER_APP_NAME = "ft"; -const uint16_t FILE_TRANSFER_APP_MAJOR_VERSION = 1; -const uint16_t FILE_TRANSFER_APP_MINOR_VERSION = 0; -const uint16_t FILE_TRANSFER_MIN_MAJOR_VERSION = 1; -const uint16_t FILE_TRANSFER_MIN_MINOR_VERSION = 0; - -RsServiceInfo ftServer::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_FILE_TRANSFER, - FILE_TRANSFER_APP_NAME, - FILE_TRANSFER_APP_MAJOR_VERSION, - FILE_TRANSFER_APP_MINOR_VERSION, - FILE_TRANSFER_MIN_MAJOR_VERSION, - FILE_TRANSFER_MIN_MINOR_VERSION); -} - - -void ftServer::setConfigDirectory(std::string path) -{ - mConfigPath = path; - - /* Must update the sub classes ... if they exist - * TODO. - */ - - std::string basecachedir = mConfigPath + "/cache"; - std::string localcachedir = mConfigPath + "/cache/local"; - std::string remotecachedir = mConfigPath + "/cache/remote"; - - RsDirUtil::checkCreateDirectory(basecachedir) ; - RsDirUtil::checkCreateDirectory(localcachedir) ; - RsDirUtil::checkCreateDirectory(remotecachedir) ; -} - -/* Control Interface */ - -/* add Config Items (Extra, Controller) */ -void ftServer::addConfigComponents(p3ConfigMgr */*mgr*/) -{ - /* NOT SURE ABOUT THIS ONE */ -} - -const RsPeerId& ftServer::OwnId() -{ - static RsPeerId null_id ; - - if (mServiceCtrl) - return mServiceCtrl->getOwnId(); - else - return null_id ; -} - -/* Final Setup (once everything is assigned) */ -void ftServer::SetupFtServer() -{ - - /* setup FiStore/Monitor */ - //std::string localcachedir = mConfigPath + "/cache/local"; - //std::string remotecachedir = mConfigPath + "/cache/remote"; - RsPeerId ownId = mServiceCtrl->getOwnId(); - - /* search/extras List */ - mFtExtra = new ftExtraList(); - mFtSearch = new ftFileSearch(); - - /* Transport */ - mFtDataplex = new ftDataMultiplex(ownId, this, mFtSearch); - - /* make Controller */ - mFtController = new ftController(mFtDataplex, mServiceCtrl, getServiceInfo().mServiceType); - mFtController -> setFtSearchNExtra(mFtSearch, mFtExtra); - - std::string emergencySaveDir = RsAccounts::AccountDirectory(); - std::string emergencyPartialsDir = RsAccounts::AccountDirectory(); - - if (emergencySaveDir != "") - { - emergencySaveDir += "/"; - emergencyPartialsDir += "/"; - } - emergencySaveDir += "Downloads"; - emergencyPartialsDir += "Partials"; - - mFtController->setDownloadDirectory(emergencySaveDir); - mFtController->setPartialsDirectory(emergencyPartialsDir); - - /* complete search setup */ - mFtSearch->addSearchMode(mFtExtra, RS_FILE_HINTS_EXTRA); - - mServiceCtrl->registerServiceMonitor(mFtController, getServiceInfo().mServiceType); - - return; -} - -void ftServer::connectToFileDatabase(p3FileDatabase *fdb) -{ - mFileDatabase = fdb ; - - mFtSearch->addSearchMode(fdb, RS_FILE_HINTS_LOCAL); // due to a bug in addSearchModule, modules can only be added one by one. Using | between flags wont work. - mFtSearch->addSearchMode(fdb, RS_FILE_HINTS_REMOTE); - - mFileDatabase->setExtraList(mFtExtra); -} -void ftServer::connectToTurtleRouter(p3turtle *fts) -{ - mTurtleRouter = fts ; - - mFtController->setTurtleRouter(fts) ; - mFtController->setFtServer(this) ; - - mTurtleRouter->registerTunnelService(this) ; -} - -void ftServer::StartupThreads() -{ - /* start up order - important for dependencies */ - - /* self contained threads */ - /* startup ExtraList Thread */ - mFtExtra->start("ft extra lst"); - - /* startup Monitor Thread */ - /* startup the FileMonitor (after cache load) */ - /* start it up */ - mFileDatabase->startThreads(); - - /* Controller thread */ - mFtController->start("ft ctrl"); - - /* Dataplex */ - mFtDataplex->start("ft dataplex"); -} - -void ftServer::StopThreads() -{ - /* stop Dataplex */ - mFtDataplex->fullstop(); - - /* stop Controller thread */ - mFtController->fullstop(); - - /* self contained threads */ - /* stop ExtraList Thread */ - mFtExtra->fullstop(); - - delete (mFtDataplex); - mFtDataplex = nullptr; - - delete (mFtController); - mFtController = nullptr; - - delete (mFtExtra); - mFtExtra = nullptr; - - /* stop Monitor Thread */ - mFileDatabase->stopThreads(); - delete mFileDatabase; - mFileDatabase = nullptr; -} - -/***************************************************************/ -/********************** RsFiles Interface **********************/ -/***************************************************************/ - -/***************************************************************/ -/********************** Controller Access **********************/ -/***************************************************************/ - -bool ftServer::ResumeTransfers() -{ - mFtController->activate(); - - return true; -} - -bool ftServer::getFileData(const RsFileHash& hash, uint64_t offset, uint32_t& requested_size,uint8_t *data) -{ - return mFtDataplex->getFileData(hash, offset, requested_size,data); -} - -bool ftServer::alreadyHaveFile(const RsFileHash& hash, FileInfo &info) -{ - return mFileDatabase->search( - hash, RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL, info ); -} - -bool ftServer::FileRequest( - const std::string& fname, const RsFileHash& hash, uint64_t size, - const std::string& dest, TransferRequestFlags flags, - const std::list& srcIds ) -{ -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "Requesting " << fname << std::endl ; -#endif - - if(!mFtController->FileRequest(fname, hash, size, dest, flags, srcIds)) - return false ; - - return true ; -} - -std::error_condition ftServer::requestFiles( - const RsFileTree& collection, const std::string& destPath, - const std::vector& srcIds, FileRequestFlags flags ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto dirsCount = collection.mDirs.size(); - const auto filesCount = collection.mFiles.size(); - - Dbg2() << fname << " dirsCount: " << dirsCount - << " filesCount: " << filesCount << std::endl; - - if(!dirsCount) - { - RsErr() << fname << " Directories list empty in collection " - << std::endl; - return std::errc::not_a_directory; - } - - if(!filesCount) - { - RsErr() << fname << " Files list empty in collection " << std::endl; - return std::errc::invalid_argument; - } - - if(filesCount != collection.mTotalFiles) - { - RsErr() << fname << " Files count mismatch" << std::endl; - return std::errc::invalid_argument; - } - - std::string basePath = destPath.empty() ? getDownloadDirectory() : destPath; - // Track how many time a directory have been explored - std::vector dirsSeenCnt(dirsCount, 0); - // - using StackEntry = std::tuple; - std::deque dStack = { std::make_tuple(0, basePath) }; - - const auto exploreDir = [&](const StackEntry& se)-> std::error_condition - { - uint64_t dirHandle; std::string parentPath; - std::tie(dirHandle, parentPath) = se; - - const auto& dirData = collection.mDirs[dirHandle]; - auto& seenTimes = dirsSeenCnt[dirHandle]; - std::string dirPath = RsDirUtil::makePath(parentPath, dirData.name); - - /* This check is not perfect but is cheap and interrupt loop exploration - * before it becomes pathological */ - if(seenTimes++ > dirsCount) - { - RsErr() << fname << " loop detected! dir: " - << dirHandle << " \"" << dirPath - << "\" explored too many times" << std::endl; - return std::errc::too_many_symbolic_link_levels; - } - - for(auto fHandle: dirData.subfiles) - { - if(fHandle >= filesCount) return std::errc::argument_out_of_domain; - - const RsFileTree::FileData& fData = collection.mFiles[fHandle]; - - bool fr = - FileRequest( fData.name, fData.hash, fData.size, - dirPath, - TransferRequestFlags::fromEFT(flags), - std::list(srcIds.begin(), srcIds.end()) ); - - Dbg2() << fname << " requested: " << fr << " " - << fData.hash << " -> " << dirPath << std::endl; - } - - for(auto dHandle: dirData.subdirs) - dStack.push_back(std::make_tuple(dHandle, dirPath)); - - return std::error_condition(); - }; - - while(!dStack.empty()) - { - if(std::error_condition ec = exploreDir(dStack.front())) return ec; - dStack.pop_front(); - } - - return std::error_condition(); -} - -bool ftServer::activateTunnels(const RsFileHash& hash,uint32_t encryption_policy,TransferRequestFlags flags,bool onoff) -{ - RsFileHash hash_of_hash ; - - encryptHash(hash,hash_of_hash) ; - mEncryptedHashes.insert(std::make_pair(hash_of_hash,hash)) ; - - if(onoff) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "Activating tunnels for hash " << hash << std::endl; -#endif - if(flags & RS_FILE_REQ_ENCRYPTED) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << " flags require end-to-end encryption. Requesting hash of hash " << hash_of_hash << std::endl; -#endif - mTurtleRouter->monitorTunnels(hash_of_hash,this,true) ; - } - if((flags & RS_FILE_REQ_UNENCRYPTED) && (encryption_policy != RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT)) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << " flags require no end-to-end encryption. Requesting hash " << hash << std::endl; -#endif - mTurtleRouter->monitorTunnels(hash,this,true) ; - } - } - else - { - mTurtleRouter->stopMonitoringTunnels(hash_of_hash); - mTurtleRouter->stopMonitoringTunnels(hash); - } - return true ; -} - -bool ftServer::setDestinationDirectory(const RsFileHash& hash,const std::string& directory) -{ - return mFtController->setDestinationDirectory(hash,directory); -} -bool ftServer::setDestinationName(const RsFileHash& hash,const std::string& name) -{ - return mFtController->setDestinationName(hash,name); -} - -bool ftServer::setChunkStrategy(const RsFileHash& hash,FileChunksInfo::ChunkStrategy s) -{ - return mFtController->setChunkStrategy(hash,s); -} -void ftServer::setDefaultChunkStrategy(FileChunksInfo::ChunkStrategy s) -{ - mFtController->setDefaultChunkStrategy(s) ; -} -FileChunksInfo::ChunkStrategy ftServer::defaultChunkStrategy() -{ - return mFtController->defaultChunkStrategy() ; -} - -uint32_t ftServer::freeDiskSpaceLimit()const -{ - return mFtController->freeDiskSpaceLimit() ; -} -void ftServer::setFreeDiskSpaceLimit(uint32_t s) -{ - mFtController->setFreeDiskSpaceLimit(s) ; -} - -void ftServer::setDefaultEncryptionPolicy(uint32_t s) -{ - mFtController->setDefaultEncryptionPolicy(s) ; -} -uint32_t ftServer::defaultEncryptionPolicy() -{ - return mFtController->defaultEncryptionPolicy() ; -} - -void ftServer::setMaxUploadSlotsPerFriend(uint32_t n) -{ - mFtController->setMaxUploadsPerFriend(n) ; -} -uint32_t ftServer::getMaxUploadSlotsPerFriend() -{ - return mFtController->getMaxUploadsPerFriend() ; -} - -void ftServer::setFilePermDirectDL(uint32_t perm) -{ - mFtController->setFilePermDirectDL(perm); -} -uint32_t ftServer::filePermDirectDL() -{ - return mFtController->filePermDirectDL() ; -} - -bool ftServer::FileCancel(const RsFileHash& hash) -{ - // Remove from both queue and ftController, by default. - // - mFtController->FileCancel(hash); - - return true ; -} - -bool ftServer::FileControl(const RsFileHash& hash, uint32_t flags) -{ - return mFtController->FileControl(hash, flags); -} - -bool ftServer::FileClearCompleted() -{ - return mFtController->FileClearCompleted(); -} -void ftServer::setQueueSize(uint32_t s) -{ - mFtController->setQueueSize(s) ; -} -uint32_t ftServer::getQueueSize() -{ - return mFtController->getQueueSize() ; -} -/* Control of Downloads Priority. */ -bool ftServer::changeQueuePosition(const RsFileHash& hash, QueueMove mv) -{ - mFtController->moveInQueue(hash,mv) ; - return true ; -} -bool ftServer::changeDownloadSpeed(const RsFileHash& hash, int speed) -{ - mFtController->setPriority(hash, (DwlSpeed)speed); - return true ; -} -bool ftServer::getDownloadSpeed(const RsFileHash& hash, int & speed) -{ - DwlSpeed _speed; - int ret = mFtController->getPriority(hash, _speed); - if (ret) - speed = _speed; - - return ret; -} -bool ftServer::clearDownload(const RsFileHash& /*hash*/) -{ - return true ; -} - -bool ftServer::FileDownloadChunksDetails(const RsFileHash& hash,FileChunksInfo& info) -{ - return mFtController->getFileDownloadChunksDetails(hash,info); -} - -void ftServer::requestDirUpdate(void *ref) -{ - mFileDatabase->requestDirUpdate(ref) ; -} - -/* Directory Handling */ -bool ftServer::setDownloadDirectory(const std::string& path) -{ - return mFtController->setDownloadDirectory(path); -} - -std::string ftServer::getDownloadDirectory() -{ - return mFtController->getDownloadDirectory(); -} - -bool ftServer::setPartialsDirectory(const std::string& path) -{ - return mFtController->setPartialsDirectory(path); -} - -std::string ftServer::getPartialsDirectory() -{ - return mFtController->getPartialsDirectory(); -} - -/***************************************************************/ -/************************* Other Access ************************/ -/***************************************************************/ - -bool ftServer::copyFile(const std::string& source, const std::string& dest) -{ - return RsDirUtil::copyFile(source, dest); -} - -void ftServer::FileDownloads(std::list &hashs) -{ - mFtController->FileDownloads(hashs); -} - -bool ftServer::FileUploadChunksDetails(const RsFileHash& hash,const RsPeerId& peer_id,CompressedChunkMap& cmap) -{ - return mFtDataplex->getClientChunkMap(hash,peer_id,cmap); -} - -bool ftServer::FileUploads(std::list &hashs) -{ - return mFtDataplex->FileUploads(hashs); -} - -bool ftServer::FileDetails(const RsFileHash &hash, FileSearchFlags hintflags, FileInfo &info) -{ - if (hintflags & RS_FILE_HINTS_DOWNLOAD) - if(mFtController->FileDetails(hash, info)) - return true ; - - if(hintflags & RS_FILE_HINTS_UPLOAD) - if(mFtDataplex->FileDetails(hash, hintflags, info)) - { - // We also check if the file is a DL as well. In such a case we use - // the DL as the file name, to replace the hash. If the file is a cache - // file, we skip the call to fileDetails() for efficiency reasons. - // - FileInfo info2 ; - if(mFtController->FileDetails(hash, info2)) - info.fname = info2.fname ; - - return true ; - } - - if(hintflags & ~(RS_FILE_HINTS_UPLOAD | RS_FILE_HINTS_DOWNLOAD)) - if(mFtSearch->search(hash, hintflags, info)) - return true ; - - return false; -} - -RsItem *ftServer::create_item(uint16_t service, uint8_t item_type) const -{ -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "p3turtle: deserialising packet: " << std::endl ; -#endif - - RsServiceType serviceType = static_cast(service); - switch (serviceType) - { - /* This one is here for retro-compatibility as turtle routing and file - * trasfer services were just one service before turle service was - * generalized */ - case RsServiceType::TURTLE: break; - case RsServiceType::FILE_TRANSFER: break; - default: - RsErr() << __PRETTY_FUNCTION__ << " Wrong service type: " << service - << std::endl; - return nullptr; - } - - try - { - switch(item_type) - { - case RS_TURTLE_SUBTYPE_FILE_REQUEST : return new RsTurtleFileRequestItem(); - case RS_TURTLE_SUBTYPE_FILE_DATA : return new RsTurtleFileDataItem(); - case RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST : return new RsTurtleFileMapRequestItem(); - case RS_TURTLE_SUBTYPE_FILE_MAP : return new RsTurtleFileMapItem(); - case RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST : return new RsTurtleChunkCrcRequestItem(); - case RS_TURTLE_SUBTYPE_CHUNK_CRC : return new RsTurtleChunkCrcItem(); - case static_cast(RsFileItemType::FILE_SEARCH_REQUEST): - return new RsFileSearchRequestItem(); - case static_cast(RsFileItemType::FILE_SEARCH_RESULT): - return new RsFileSearchResultItem(); - default: - return nullptr; - } - } - catch(std::exception& e) - { - FTSERVER_ERROR() << "(EE) deserialisation error in " << __PRETTY_FUNCTION__ << ": " << e.what() << std::endl; - - return nullptr; - } -} - -bool ftServer::isEncryptedSource(const RsPeerId& virtual_peer_id) -{ - RS_STACK_MUTEX(srvMutex) ; - - return mEncryptedPeerIds.find(virtual_peer_id) != mEncryptedPeerIds.end(); -} - -void ftServer::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir) -{ -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "adding virtual peer. Direction=" << dir << ", hash=" << hash << ", vpid=" << virtual_peer_id << std::endl; -#endif - RsFileHash real_hash ; - - { - if(findRealHash(hash,real_hash)) - { - RS_STACK_MUTEX(srvMutex) ; - mEncryptedPeerIds[virtual_peer_id] = hash ; - } - else - real_hash = hash; - } - - if(dir == RsTurtleGenericTunnelItem::DIRECTION_SERVER) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << " direction is SERVER. Adding file source for end-to-end encrypted tunnel for real hash " << real_hash << ", virtual peer id = " << virtual_peer_id << std::endl; -#endif - mFtController->addFileSource(real_hash,virtual_peer_id) ; - } -} - -void ftServer::removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) -{ - RsFileHash real_hash ; - if(findRealHash(hash,real_hash)) - mFtController->removeFileSource(real_hash,virtual_peer_id) ; - else - mFtController->removeFileSource(hash,virtual_peer_id) ; - - RS_STACK_MUTEX(srvMutex) ; - mEncryptedPeerIds.erase(virtual_peer_id) ; -} - -bool ftServer::handleTunnelRequest(const RsFileHash& hash,const RsPeerId& peer_id) -{ - FileInfo info ; - RsFileHash real_hash ; - bool found = false ; - - if(FileDetails(hash, RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_SPEC_ONLY, info)) - { - if(info.transfer_info_flags & RS_FILE_REQ_ENCRYPTED) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "handleTunnelRequest: openning encrypted FT tunnel for H(H(F))=" << hash << " and H(F)=" << info.hash << std::endl; -#endif - - RS_STACK_MUTEX(srvMutex) ; - mEncryptedHashes[hash] = info.hash; - - real_hash = info.hash ; - } - else - real_hash = hash ; - - found = true ; - } - else // try to see if we're already swarming the file - { - { - RS_STACK_MUTEX(srvMutex) ; - std::map::const_iterator it = mEncryptedHashes.find(hash) ; - - if(it != mEncryptedHashes.end()) - real_hash = it->second ; - else - real_hash = hash ; - } - - if(FileDetails(real_hash,RS_FILE_HINTS_DOWNLOAD,info)) - { - // This file is currently being downloaded. Let's look if we already have a chunk or not. If not, no need to - // share the file! - - FileChunksInfo info2 ; - if(rsFiles->FileDownloadChunksDetails(real_hash, info2)) - for(uint32_t i=0;idefaultEncryptionPolicy() == RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT && hash == real_hash) - { -#ifdef SERVER_DEBUG - std::cerr << "(WW) rejecting file transfer for hash " << hash << " because the hash is not encrypted and encryption policy requires it." << std::endl; -#endif - return false ; - } - -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer: performing local hash search for hash " << hash << std::endl; - - if(found) - { - FTSERVER_DEBUG() << "Found hash: " << std::endl; - FTSERVER_DEBUG() << " hash = " << real_hash << std::endl; - FTSERVER_DEBUG() << " peer = " << peer_id << std::endl; - FTSERVER_DEBUG() << " flags = " << info.storage_permission_flags << std::endl; - FTSERVER_DEBUG() << " groups= " ; - for(std::list::const_iterator it(info.parent_groups.begin());it!=info.parent_groups.end();++it) - FTSERVER_DEBUG() << (*it) << ", " ; - FTSERVER_DEBUG() << std::endl; - FTSERVER_DEBUG() << " clear = " << rsPeers->computePeerPermissionFlags(peer_id,info.storage_permission_flags,info.parent_groups) << std::endl; - } -#endif - - // The call to computeHashPeerClearance() return a combination of RS_FILE_HINTS_NETWORK_WIDE and RS_FILE_HINTS_BROWSABLE - // This is an additional computation cost, but the way it's written here, it's only called when res is true. - // - found = found && (RS_FILE_HINTS_NETWORK_WIDE & rsPeers->computePeerPermissionFlags(peer_id,info.storage_permission_flags,info.parent_groups)) ; - - return found ; -} - -/***************************************************************/ -/******************* ExtraFileList Access **********************/ -/***************************************************************/ - -bool ftServer::ExtraFileAdd(std::string fname, const RsFileHash& hash, uint64_t size, uint32_t period, TransferRequestFlags flags) -{ - return mFtExtra->addExtraFile(fname, hash, size, period, flags); -} - -bool ftServer::ExtraFileRemove(const RsFileHash& hash) -{ - mFtController->FileServerCancel(hash); - return mFileDatabase->removeExtraFile(hash); -} - -bool ftServer::ExtraFileHash( std::string localpath, rstime_t period, TransferRequestFlags flags ) -{ - constexpr rstime_t uintmax = std::numeric_limits::max(); - if(period > uintmax) - { - RsErr() << __PRETTY_FUNCTION__ << " period: " << period << " > " - << uintmax << std::errc::value_too_large << std::endl; - return false; - } - - return mFtExtra->hashExtraFile( - localpath, static_cast(period), flags ); -} - -bool ftServer::ExtraFileStatus(std::string localpath, FileInfo &info) -{ - return mFtExtra->hashExtraFileDone(localpath, info); -} - -bool ftServer::ExtraFileMove(std::string fname, const RsFileHash& hash, uint64_t size, std::string destpath) -{ - return mFtExtra->moveExtraFile(fname, hash, size, destpath); -} - -/***************************************************************/ -/******************** Directory Listing ************************/ -/***************************************************************/ - -bool ftServer::findChildPointer(void *ref, int row, void *& result, FileSearchFlags flags) -{ - return mFileDatabase->findChildPointer(ref,row,result,flags) ; -} - -bool ftServer::requestDirDetails( - DirDetails &details, uint64_t handle, FileSearchFlags flags ) -{ return RequestDirDetails(reinterpret_cast(handle), details, flags); } - -int ftServer::RequestDirDetails(void *ref, DirDetails &details, FileSearchFlags flags) -{ - return mFileDatabase->RequestDirDetails(ref,details,flags) ; -} - -uint32_t ftServer::getType(void *ref, FileSearchFlags flags) -{ - return mFileDatabase->getType(ref,flags) ; -} -/***************************************************************/ -/******************** Search Interface *************************/ -/***************************************************************/ - -int ftServer::SearchKeywords(std::list keywords, std::list &results,FileSearchFlags flags) -{ - return mFileDatabase->SearchKeywords(keywords, results,flags,RsPeerId()); -} -int ftServer::SearchKeywords( - std::list keywords, std::list &results, - FileSearchFlags flags, const RsPeerId& peer_id ) -{ - return mFileDatabase->SearchKeywords(keywords, results, flags, peer_id); -} - -int ftServer::SearchBoolExp(RsRegularExpression::Expression * exp, std::list &results,FileSearchFlags flags) -{ - return mFileDatabase->SearchBoolExp(exp, results,flags,RsPeerId()); -} -int ftServer::SearchBoolExp(RsRegularExpression::Expression * exp, std::list &results,FileSearchFlags flags,const RsPeerId& peer_id) -{ - return mFileDatabase->SearchBoolExp(exp,results,flags,peer_id) ; -} -int ftServer::getSharedDirStatistics(const RsPeerId& pid, SharedDirStats& stats) -{ - return mFileDatabase->getSharedDirStatistics(pid,stats) ; -} - -/***************************************************************/ -/*************** Local Shared Dir Interface ********************/ -/***************************************************************/ - -bool ftServer::ConvertSharedFilePath(std::string path, std::string &fullpath) -{ - return mFileDatabase->convertSharedFilePath(path, fullpath); -} - -void ftServer::updateSinceGroupPermissionsChanged() -{ - mFileDatabase->forceSyncWithPeers(); -} -void ftServer::ForceDirectoryCheck(bool add_safe_delay) -{ - mFileDatabase->forceDirectoryCheck(add_safe_delay); - return; -} - -bool ftServer::InDirectoryCheck() -{ - return mFileDatabase->inDirectoryCheck(); -} - -bool ftServer::getSharedDirectories(std::list &dirs) -{ - mFileDatabase->getSharedDirectories(dirs); - return true; -} - -bool ftServer::setSharedDirectories(const std::list& dirs) -{ - mFileDatabase->setSharedDirectories(dirs); - return true; -} - -bool ftServer::addSharedDirectory(const SharedDirInfo& dir) -{ - SharedDirInfo _dir = dir; - _dir.filename = RsDirUtil::convertPathToUnix(_dir.filename); - - std::list dirList; - mFileDatabase->getSharedDirectories(dirList); - - // check that the directory is not already in the list. - for(std::list::const_iterator it(dirList.begin());it!=dirList.end();++it) - if((*it).filename == _dir.filename) - return false ; - - // ok then, add the shared directory. - dirList.push_back(_dir); - - mFileDatabase->setSharedDirectories(dirList); - return true; -} - -bool ftServer::updateShareFlags(const SharedDirInfo& info) -{ - mFileDatabase->updateShareFlags(info); - - return true ; -} - -bool ftServer::removeSharedDirectory(std::string dir) -{ - dir = RsDirUtil::convertPathToUnix(dir); - - std::list dirList; - std::list::iterator it; - -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::removeSharedDirectory(" << dir << ")" << std::endl; -#endif - - mFileDatabase->getSharedDirectories(dirList); - -#ifdef SERVER_DEBUG - for(it = dirList.begin(); it != dirList.end(); ++it) - FTSERVER_DEBUG() << " existing: " << (*it).filename << std::endl; -#endif - - for(it = dirList.begin();it!=dirList.end() && (*it).filename != dir;++it) ; - - if(it == dirList.end()) - { - FTSERVER_ERROR() << "(EE) ftServer::removeSharedDirectory(): Cannot Find Directory... Fail" << std::endl; - return false; - } - - -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << " Updating Directories" << std::endl; -#endif - - dirList.erase(it); - mFileDatabase->setSharedDirectories(dirList); - - return true; -} - -bool ftServer::getIgnoreLists(std::list& ignored_prefixes, std::list& ignored_suffixes,uint32_t& ignore_flags) -{ - return mFileDatabase->getIgnoreLists(ignored_prefixes,ignored_suffixes,ignore_flags) ; -} -void ftServer::setIgnoreLists(const std::list& ignored_prefixes, const std::list& ignored_suffixes, uint32_t ignore_flags) -{ - mFileDatabase->setIgnoreLists(ignored_prefixes,ignored_suffixes,ignore_flags) ; -} - -bool ftServer::watchEnabled() { return mFileDatabase->watchEnabled() ; } -int ftServer::watchPeriod() const { return mFileDatabase->watchPeriod()/60 ; } -bool ftServer::followSymLinks() const { return mFileDatabase->followSymLinks() ; } -bool ftServer::ignoreDuplicates() { return mFileDatabase->ignoreDuplicates() ; } -int ftServer::maxShareDepth() const { return mFileDatabase->maxShareDepth() ; } - -void ftServer::setWatchEnabled(bool b) { mFileDatabase->setWatchEnabled(b) ; } -void ftServer::setWatchPeriod(int minutes) { mFileDatabase->setWatchPeriod(minutes*60) ; } -void ftServer::setFollowSymLinks(bool b) { mFileDatabase->setFollowSymLinks(b) ; } -void ftServer::setIgnoreDuplicates(bool ignore) { mFileDatabase->setIgnoreDuplicates(ignore); } -void ftServer::setMaxShareDepth(int depth) { mFileDatabase->setMaxShareDepth(depth) ; } - -void ftServer::togglePauseHashingProcess() { mFileDatabase->togglePauseHashingProcess() ; } -bool ftServer::hashingProcessPaused() { return mFileDatabase->hashingProcessPaused() ; } - -bool ftServer::getShareDownloadDirectory() -{ - std::list dirList; - mFileDatabase->getSharedDirectories(dirList); - - std::string dir = mFtController->getDownloadDirectory(); - - // check if the download directory is in the list. - for (std::list::const_iterator it(dirList.begin()); it != dirList.end(); ++it) - if ((*it).filename == dir) - return true; - - return false; -} - -bool ftServer::shareDownloadDirectory(bool share) -{ - if (share) - { - /* Share */ - SharedDirInfo inf ; - inf.filename = mFtController->getDownloadDirectory(); - inf.shareflags = DIR_FLAGS_ANONYMOUS_DOWNLOAD ; - - return addSharedDirectory(inf); - } - else - { - /* Unshare */ - std::string dir = mFtController->getDownloadDirectory(); - return removeSharedDirectory(dir); - } -} - -/***************************************************************/ -/****************** End of RsFiles Interface *******************/ -/***************************************************************/ - -//bool ftServer::loadConfigMap(std::map &/*configMap*/) -//{ -// return true; -//} - -/***************************************************************/ -/********************** Data Flow **********************/ -/***************************************************************/ - -bool ftServer::sendTurtleItem(const RsPeerId& peerId,const RsFileHash& hash,RsTurtleGenericTunnelItem *item) -{ - // we cannot look in the encrypted hash map, since the same hash--on this side of the FT--can be used with both - // encrypted and unencrypted peers ids. So the information comes from the virtual peer Id. - - RsFileHash encrypted_hash; - - if(findEncryptedHash(peerId,encrypted_hash)) - { - // we encrypt the item - -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "Sending turtle item to peer ID " << peerId << " using encrypted tunnel." << std::endl; -#endif - - RsTurtleGenericDataItem *encrypted_item ; - - if(!encryptItem(item, hash, encrypted_item)) - return false ; - - encrypted_item->setPriorityLevel(item->priority_level()); - - delete item ; - - mTurtleRouter->sendTurtleData(peerId,encrypted_item) ; - } - else - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "Sending turtle item to peer ID " << peerId << " using non uncrypted tunnel." << std::endl; -#endif - mTurtleRouter->sendTurtleData(peerId,item) ; - } - - return true ; -} - -/* Client Send */ -bool ftServer::sendDataRequest(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize) -{ -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::sendDataRequest() to peer " << peerId << " for hash " << hash << ", offset=" << offset << ", chunk size="<< chunksize << std::endl; -#endif - if(mTurtleRouter->isTurtlePeer(peerId)) - { - RsTurtleFileRequestItem *item = new RsTurtleFileRequestItem ; - - item->chunk_offset = offset ; - item->chunk_size = chunksize ; - - sendTurtleItem(peerId,hash,item) ; - } - else - { - /* create a packet */ - /* push to networking part */ - RsFileTransferDataRequestItem *rfi = new RsFileTransferDataRequestItem(); - - /* id */ - rfi->PeerId(peerId); - - /* file info */ - rfi->file.filesize = size; - rfi->file.hash = hash; /* ftr->hash; */ - - /* offsets */ - rfi->fileoffset = offset; /* ftr->offset; */ - rfi->chunksize = chunksize; /* ftr->chunk; */ - - sendItem(rfi); - } - - return true; -} - -bool ftServer::sendChunkMapRequest(const RsPeerId& peerId,const RsFileHash& hash,bool is_client) -{ -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::sendChunkMapRequest() to peer " << peerId << " for hash " << hash << std::endl; -#endif - if(mTurtleRouter->isTurtlePeer(peerId)) - { - RsTurtleFileMapRequestItem *item = new RsTurtleFileMapRequestItem ; - sendTurtleItem(peerId,hash,item) ; - } - else - { - /* create a packet */ - /* push to networking part */ - RsFileTransferChunkMapRequestItem *rfi = new RsFileTransferChunkMapRequestItem(); - - /* id */ - rfi->PeerId(peerId); - - /* file info */ - rfi->hash = hash; /* ftr->hash; */ - rfi->is_client = is_client ; - - sendItem(rfi); - } - - return true ; -} - -bool ftServer::sendChunkMap(const RsPeerId& peerId,const RsFileHash& hash,const CompressedChunkMap& map,bool is_client) -{ -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::sendChunkMap() to peer " << peerId << " for hash " << hash << std::endl; -#endif - if(mTurtleRouter->isTurtlePeer(peerId)) - { - RsTurtleFileMapItem *item = new RsTurtleFileMapItem ; - item->compressed_map = map ; - sendTurtleItem(peerId,hash,item) ; - } - else - { - /* create a packet */ - /* push to networking part */ - RsFileTransferChunkMapItem *rfi = new RsFileTransferChunkMapItem(); - - /* id */ - rfi->PeerId(peerId); - - /* file info */ - rfi->hash = hash; /* ftr->hash; */ - rfi->is_client = is_client; /* ftr->hash; */ - rfi->compressed_map = map; /* ftr->hash; */ - - sendItem(rfi); - } - - return true ; -} - -bool ftServer::sendSingleChunkCRCRequest(const RsPeerId& peerId,const RsFileHash& hash,uint32_t chunk_number) -{ -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::sendSingleCRCRequest() to peer " << peerId << " for hash " << hash << ", chunk number=" << chunk_number << std::endl; -#endif - if(mTurtleRouter->isTurtlePeer(peerId)) - { - RsTurtleChunkCrcRequestItem *item = new RsTurtleChunkCrcRequestItem; - item->chunk_number = chunk_number ; - - sendTurtleItem(peerId,hash,item) ; - } - else - { - /* create a packet */ - /* push to networking part */ - RsFileTransferSingleChunkCrcRequestItem *rfi = new RsFileTransferSingleChunkCrcRequestItem(); - - /* id */ - rfi->PeerId(peerId); - - /* file info */ - rfi->hash = hash; /* ftr->hash; */ - rfi->chunk_number = chunk_number ; - - sendItem(rfi); - } - - return true ; -} - -bool ftServer::sendSingleChunkCRC(const RsPeerId& peerId,const RsFileHash& hash,uint32_t chunk_number,const Sha1CheckSum& crc) -{ -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::sendSingleCRC() to peer " << peerId << " for hash " << hash << ", chunk number=" << chunk_number << std::endl; -#endif - if(mTurtleRouter->isTurtlePeer(peerId)) - { - RsTurtleChunkCrcItem *item = new RsTurtleChunkCrcItem; - item->chunk_number = chunk_number ; - item->check_sum = crc ; - - sendTurtleItem(peerId,hash,item) ; - } - else - { - /* create a packet */ - /* push to networking part */ - RsFileTransferSingleChunkCrcItem *rfi = new RsFileTransferSingleChunkCrcItem(); - - /* id */ - rfi->PeerId(peerId); - - /* file info */ - rfi->hash = hash; /* ftr->hash; */ - rfi->check_sum = crc; - rfi->chunk_number = chunk_number; - - sendItem(rfi); - } - - return true ; -} - -/* Server Send */ -bool ftServer::sendData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t baseoffset, uint32_t chunksize, void *data) -{ - /* create a packet */ - /* push to networking part */ - uint32_t tosend = chunksize; - uint64_t offset = 0; - uint32_t chunk; - -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::sendData() to " << peerId << ", hash: " << hash << " offset: " << baseoffset << " chunk: " << chunksize << " data: " << data << std::endl; -#endif - - while(tosend > 0) - { - //static const uint32_t MAX_FT_CHUNK = 32 * 1024; /* 32K */ - //static const uint32_t MAX_FT_CHUNK = 16 * 1024; /* 16K */ - // - static const uint32_t MAX_FT_CHUNK = 8 * 1024; /* 16K */ - - /* workout size */ - chunk = MAX_FT_CHUNK; - if (chunk > tosend) - { - chunk = tosend; - } - - /******** New Serialiser Type *******/ - - if(mTurtleRouter->isTurtlePeer(peerId)) - { - RsTurtleFileDataItem *item = new RsTurtleFileDataItem ; - - item->chunk_offset = offset+baseoffset ; - item->chunk_size = chunk; - item->chunk_data = rs_malloc(chunk) ; - - if(item->chunk_data == NULL) - { - delete item; - return false; - } - memcpy(item->chunk_data,&(((uint8_t *) data)[offset]),chunk) ; - - sendTurtleItem(peerId,hash,item) ; - } - else - { - RsFileTransferDataItem *rfd = new RsFileTransferDataItem(); - - /* set id */ - rfd->PeerId(peerId); - - /* file info */ - rfd->fd.file.filesize = size; - rfd->fd.file.hash = hash; - rfd->fd.file.name = ""; /* blank other data */ - rfd->fd.file.path = ""; - rfd->fd.file.pop = 0; - rfd->fd.file.age = 0; - - rfd->fd.file_offset = baseoffset + offset; - - /* file data */ - rfd->fd.binData.setBinData( &(((uint8_t *) data)[offset]), chunk); - - sendItem(rfd); - - /* print the data pointer */ -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::sendData() Packet: " << " offset: " << rfd->fd.file_offset << " chunk: " << chunk << " len: " << rfd->fd.binData.bin_len << " data: " << rfd->fd.binData.bin_data << std::endl; -#endif - } - - offset += chunk; - tosend -= chunk; - } - - /* clean up data */ - free(data); - - return true; -} - -// Encrypts the given item using aead-chacha20-poly1305 -// -// The format is the following -// -// [encryption format] [random initialization vector] [encrypted data size] [encrypted data] [authentication tag] -// 4 bytes 12 bytes 4 bytes variable 16 bytes -// -// +-------------------- authenticated data part ----------------------+ -// -// -// Encryption format: -// ae ad 01 01 : encryption using AEAD, format 01 (authed with Poly1305 ), version 01 -// ae ad 02 01 : encryption using AEAD, format 02 (authed with HMAC Sha256), version 01 -// -// - -void ftServer::deriveEncryptionKey(const RsFileHash& hash, uint8_t *key) -{ - // The encryption key is simply the 256 hash of the - SHA256_CTX sha_ctx ; - - if(SHA256_DIGEST_LENGTH != 32) - throw std::runtime_error("Warning: can't compute Sha1Sum with sum size != 32") ; - - SHA256_Init(&sha_ctx); - SHA256_Update(&sha_ctx, hash.toByteArray(), hash.SIZE_IN_BYTES); - SHA256_Final (key, &sha_ctx); -} - -#ifdef USE_NEW_METHOD -static const uint32_t ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE = 12 ; -static const uint32_t ENCRYPTED_FT_AUTHENTICATION_TAG_SIZE = 16 ; -static const uint32_t ENCRYPTED_FT_HEADER_SIZE = 4 ; -static const uint32_t ENCRYPTED_FT_EDATA_SIZE = 4 ; - -static const uint8_t ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_POLY1305 = 0x01 ; -static const uint8_t ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_SHA256 = 0x02 ; -#endif //USE_NEW_METHOD - -bool ftServer::encryptItem(RsTurtleGenericTunnelItem *clear_item,const RsFileHash& hash,RsTurtleGenericDataItem *& encrypted_item) -{ -#ifndef USE_NEW_METHOD - uint32_t item_serialized_size = size(clear_item) ; - - RsTemporaryMemory data(item_serialized_size) ; - - if(data == NULL) - return false ; - - serialise(clear_item, data, &item_serialized_size); - - uint8_t encryption_key[32] ; - deriveEncryptionKey(hash,encryption_key) ; - - return p3turtle::encryptData(data,item_serialized_size,encryption_key,encrypted_item) ; -#else - uint8_t initialization_vector[ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE] ; - - RSRandom::random_bytes(initialization_vector,ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE) ; - -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::Encrypting ft item." << std::endl; - FTSERVER_DEBUG() << " random nonce : " << RsUtil::BinToHex(initialization_vector,ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE) << std::endl; -#endif - - uint32_t item_serialized_size = size(clear_item) ; - uint32_t total_data_size = ENCRYPTED_FT_HEADER_SIZE + ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_FT_EDATA_SIZE + item_serialized_size + ENCRYPTED_FT_AUTHENTICATION_TAG_SIZE ; - -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << " clear part size : " << size(clear_item) << std::endl; - FTSERVER_DEBUG() << " total item size : " << total_data_size << std::endl; -#endif - - encrypted_item = new RsTurtleGenericDataItem ; - encrypted_item->data_bytes = rs_malloc( total_data_size ) ; - encrypted_item->data_size = total_data_size ; - - if(encrypted_item->data_bytes == NULL) - return false ; - - uint8_t *edata = (uint8_t*)encrypted_item->data_bytes ; - uint32_t edata_size = item_serialized_size; - uint32_t offset = 0; - - edata[0] = 0xae ; - edata[1] = 0xad ; - edata[2] = ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_SHA256 ; // means AEAD_chacha20_sha256 - edata[3] = 0x01 ; - - offset += ENCRYPTED_FT_HEADER_SIZE; - uint32_t aad_offset = offset ; - uint32_t aad_size = ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_FT_EDATA_SIZE ; - - memcpy(&edata[offset], initialization_vector, ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE) ; - offset += ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE ; - - edata[offset+0] = (edata_size >> 0) & 0xff ; - edata[offset+1] = (edata_size >> 8) & 0xff ; - edata[offset+2] = (edata_size >> 16) & 0xff ; - edata[offset+3] = (edata_size >> 24) & 0xff ; - - offset += ENCRYPTED_FT_EDATA_SIZE ; - - uint32_t ser_size = (uint32_t)((int)total_data_size - (int)offset); - - serialise(clear_item,&edata[offset], &ser_size); - -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << " clear item : " << RsUtil::BinToHex(&edata[offset],std::min(50,(int)total_data_size-(int)offset)) << "(...)" << std::endl; -#endif - - uint32_t clear_item_offset = offset ; - offset += edata_size ; - - uint32_t authentication_tag_offset = offset ; - assert(ENCRYPTED_FT_AUTHENTICATION_TAG_SIZE + offset == total_data_size) ; - - uint8_t encryption_key[32] ; - deriveEncryptionKey(hash,encryption_key) ; - - if(edata[2] == ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_POLY1305) - librs::crypto::AEAD_chacha20_poly1305(encryption_key,initialization_vector,&edata[clear_item_offset],edata_size, &edata[aad_offset],aad_size, &edata[authentication_tag_offset],true) ; - else if(edata[2] == ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_SHA256) - librs::crypto::AEAD_chacha20_sha256 (encryption_key,initialization_vector,&edata[clear_item_offset],edata_size, &edata[aad_offset],aad_size, &edata[authentication_tag_offset],true) ; - else - return false ; - -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << " encryption key : " << RsUtil::BinToHex(encryption_key,32) << std::endl; - FTSERVER_DEBUG() << " authen. tag : " << RsUtil::BinToHex(&edata[authentication_tag_offset],ENCRYPTED_FT_AUTHENTICATION_TAG_SIZE) << std::endl; - FTSERVER_DEBUG() << " final item : " << RsUtil::BinToHex(&edata[0],std::min(50u,total_data_size)) << "(...)" << std::endl; -#endif - - return true ; -#endif -} - -// Decrypts the given item using aead-chacha20-poly1305 - -bool ftServer::decryptItem(const RsTurtleGenericDataItem *encrypted_item,const RsFileHash& hash,RsTurtleGenericTunnelItem *& decrypted_item) -{ -#ifndef USE_NEW_METHOD - unsigned char *data = NULL ; - uint32_t data_size = 0 ; - - uint8_t encryption_key[32] ; - deriveEncryptionKey(hash,encryption_key) ; - - if(!p3turtle::decryptItem(encrypted_item,encryption_key,data,data_size)) - { - FTSERVER_ERROR() << "Cannot decrypt data!" << std::endl; - - if(data) - free(data) ; - return false ; - } - decrypted_item = dynamic_cast(deserialise(data,&data_size)) ; - free(data); - - return (decrypted_item != NULL); - -#else - uint8_t encryption_key[32] ; - deriveEncryptionKey(hash,encryption_key) ; - - uint8_t *edata = (uint8_t*)encrypted_item->data_bytes ; - uint32_t offset = 0; - - if(encrypted_item->data_size < ENCRYPTED_FT_HEADER_SIZE + ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_FT_EDATA_SIZE) return false ; - - if(edata[0] != 0xae) return false ; - if(edata[1] != 0xad) return false ; - if(edata[2] != ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_POLY1305 && edata[2] != ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_SHA256) return false ; - if(edata[3] != 0x01) return false ; - - offset += ENCRYPTED_FT_HEADER_SIZE ; - uint32_t aad_offset = offset ; - uint32_t aad_size = ENCRYPTED_FT_EDATA_SIZE + ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE ; - - uint8_t *initialization_vector = &edata[offset] ; - -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::decrypting ft item." << std::endl; - FTSERVER_DEBUG() << " item data : " << RsUtil::BinToHex(edata,std::min(50u,encrypted_item->data_size)) << "(...)" << std::endl; - FTSERVER_DEBUG() << " hash : " << hash << std::endl; - FTSERVER_DEBUG() << " encryption key : " << RsUtil::BinToHex(encryption_key,32) << std::endl; - FTSERVER_DEBUG() << " random nonce : " << RsUtil::BinToHex(initialization_vector,ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE) << std::endl; -#endif - - offset += ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE ; - - uint32_t edata_size = 0 ; - edata_size += ((uint32_t)edata[offset+0]) << 0 ; - edata_size += ((uint32_t)edata[offset+1]) << 8 ; - edata_size += ((uint32_t)edata[offset+2]) << 16 ; - edata_size += ((uint32_t)edata[offset+3]) << 24 ; - - if(edata_size + ENCRYPTED_FT_EDATA_SIZE + ENCRYPTED_FT_AUTHENTICATION_TAG_SIZE + ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_FT_HEADER_SIZE != encrypted_item->data_size) - { - FTSERVER_ERROR() << " ERROR: encrypted data size is " << edata_size << ", should be " << encrypted_item->data_size - (ENCRYPTED_FT_EDATA_SIZE + ENCRYPTED_FT_AUTHENTICATION_TAG_SIZE + ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_FT_HEADER_SIZE ) << std::endl; - return false ; - } - - offset += ENCRYPTED_FT_EDATA_SIZE ; - uint32_t clear_item_offset = offset ; - - uint32_t authentication_tag_offset = offset + edata_size ; -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << " authen. tag : " << RsUtil::BinToHex(&edata[authentication_tag_offset],ENCRYPTED_FT_AUTHENTICATION_TAG_SIZE) << std::endl; -#endif - - bool result ; - - if(edata[2] == ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_POLY1305) - result = librs::crypto::AEAD_chacha20_poly1305(encryption_key,initialization_vector,&edata[clear_item_offset],edata_size, &edata[aad_offset],aad_size, &edata[authentication_tag_offset],false) ; - else if(edata[2] == ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_SHA256) - result = librs::crypto::AEAD_chacha20_sha256 (encryption_key,initialization_vector,&edata[clear_item_offset],edata_size, &edata[aad_offset],aad_size, &edata[authentication_tag_offset],false) ; - else - return false ; - -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << " authen. result : " << result << std::endl; - FTSERVER_DEBUG() << " decrypted daya : " << RsUtil::BinToHex(&edata[clear_item_offset],std::min(50u,edata_size)) << "(...)" << std::endl; -#endif - - if(!result) - { - FTSERVER_ERROR() << "(EE) decryption/authentication went wrong." << std::endl; - return false ; - } - - decrypted_item = dynamic_cast(deserialise(&edata[clear_item_offset],&edata_size)) ; - - if(decrypted_item == NULL) - return false ; - - return true ; -#endif -} - -bool ftServer::encryptHash(const RsFileHash& hash, RsFileHash& hash_of_hash) -{ - hash_of_hash = RsDirUtil::sha1sum(hash.toByteArray(),hash.SIZE_IN_BYTES); - return true ; -} - -bool ftServer::findEncryptedHash(const RsPeerId& virtual_peer_id, RsFileHash& encrypted_hash) -{ - RS_STACK_MUTEX(srvMutex); - - std::map::const_iterator it = mEncryptedPeerIds.find(virtual_peer_id) ; - - if(it != mEncryptedPeerIds.end()) - { - encrypted_hash = it->second ; - return true ; - } - else - return false ; -} - -bool ftServer::findRealHash(const RsFileHash& hash, RsFileHash& real_hash) -{ - RS_STACK_MUTEX(srvMutex); - std::map::const_iterator it = mEncryptedHashes.find(hash) ; - - if(it != mEncryptedHashes.end()) - { - real_hash = it->second ; - return true ; - } - else - return false ; -} - -TurtleSearchRequestId ftServer::turtleSearch(const std::string& string_to_match) -{ - return mTurtleRouter->turtleSearch(string_to_match) ; -} -TurtleSearchRequestId ftServer::turtleSearch(const RsRegularExpression::LinearizedExpression& expr) -{ - return mTurtleRouter->turtleSearch(expr) ; -} - -#warning we should do this here, but for now it is done by turtle router. -// // Dont delete the item. The client (p3turtle) is doing it after calling this. -// // -// void ftServer::receiveSearchResult(RsTurtleSearchResultItem *item) -// { -// RsTurtleFTSearchResultItem *ft_sr = dynamic_cast(item) ; -// -// if(ft_sr == NULL) -// { -// FTSERVER_ERROR() << "(EE) ftServer::receiveSearchResult(): item cannot be cast to a RsTurtleFTSearchResultItem" << std::endl; -// return ; -// } -// -// RsServer::notify()->notifyTurtleSearchResult(ft_sr->request_id,ft_sr->result) ; -// } - -// Dont delete the item. The client (p3turtle) is doing it after calling this. -// -void ftServer::receiveTurtleData(const RsTurtleGenericTunnelItem *i, - const RsFileHash& hash, - const RsPeerId& virtual_peer_id, - RsTurtleGenericTunnelItem::Direction direction) -{ - if(i->PacketSubType() == RS_TURTLE_SUBTYPE_GENERIC_DATA) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "Received encrypted data item. Trying to decrypt" << std::endl; -#endif - - RsFileHash real_hash ; - - if(!findRealHash(hash,real_hash)) - { - FTSERVER_ERROR() << "(EE) Cannot find real hash for encrypted data item with H(H(F))=" << hash << ". This is unexpected." << std::endl; - return ; - } - - RsTurtleGenericTunnelItem *decrypted_item ; - if(!decryptItem(dynamic_cast(i),real_hash,decrypted_item)) - { - FTSERVER_ERROR() << "(EE) decryption error." << std::endl; - return ; - } - - receiveTurtleData(decrypted_item, real_hash, virtual_peer_id,direction) ; - - delete decrypted_item ; - return ; - } - - switch(i->PacketSubType()) - { - case RS_TURTLE_SUBTYPE_FILE_REQUEST: - { - const RsTurtleFileRequestItem *item = dynamic_cast(i) ; - if (item) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::receiveTurtleData(): received file data request for " << hash << " from peer " << virtual_peer_id << std::endl; -#endif - getMultiplexer()->recvDataRequest(virtual_peer_id,hash,0,item->chunk_offset,item->chunk_size) ; - } - } - break ; - - case RS_TURTLE_SUBTYPE_FILE_DATA : - { - const RsTurtleFileDataItem *item = dynamic_cast(i) ; - if (item) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::receiveTurtleData(): received file data for " << hash << " from peer " << virtual_peer_id << std::endl; -#endif - getMultiplexer()->recvData(virtual_peer_id,hash,0,item->chunk_offset,item->chunk_size,item->chunk_data) ; - - const_cast(item)->chunk_data = NULL ; // this prevents deletion in the destructor of RsFileDataItem, because data will be deleted - // down _ft_server->getMultiplexer()->recvData()...in ftTransferModule::recvFileData - } - } - break ; - - case RS_TURTLE_SUBTYPE_FILE_MAP : - { - const RsTurtleFileMapItem *item = dynamic_cast(i) ; - if (item) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::receiveTurtleData(): received chunk map for hash " << hash << " from peer " << virtual_peer_id << std::endl; -#endif - getMultiplexer()->recvChunkMap(virtual_peer_id,hash,item->compressed_map,direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ; - } - } - break ; - - case RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST: - { - //RsTurtleFileMapRequestItem *item = dynamic_cast(i) ; -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::receiveTurtleData(): received chunkmap request for hash " << hash << " from peer " << virtual_peer_id << std::endl; -#endif - getMultiplexer()->recvChunkMapRequest(virtual_peer_id,hash,direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ; - } - break ; - - case RS_TURTLE_SUBTYPE_CHUNK_CRC : - { - const RsTurtleChunkCrcItem *item = dynamic_cast(i) ; - if (item) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::receiveTurtleData(): received single chunk CRC for hash " << hash << " from peer " << virtual_peer_id << std::endl; -#endif - getMultiplexer()->recvSingleChunkCRC(virtual_peer_id,hash,item->chunk_number,item->check_sum) ; - } - } - break ; - - case RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST: - { - const RsTurtleChunkCrcRequestItem *item = dynamic_cast(i) ; - if (item) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::receiveTurtleData(): received single chunk CRC request for hash " << hash << " from peer " << virtual_peer_id << std::endl; -#endif - getMultiplexer()->recvSingleChunkCRCRequest(virtual_peer_id,hash,item->chunk_number) ; - } - } - break ; - default: - FTSERVER_ERROR() << "WARNING: Unknown packet type received: sub_id=" << reinterpret_cast(i->PacketSubType()) << ". Is somebody trying to poison you ?" << std::endl ; - } -} - -/* NB: The rsCore lock must be activated before calling this. - * This Lock should be moved lower into the system... - * most likely destination is in ftServer. - */ -int ftServer::tick() -{ - bool moreToTick = false ; - - if(handleIncoming()) - moreToTick = true; - - static rstime_t last_law_priority_tasks_handling_time = 0 ; - rstime_t now = time(NULL) ; - - if(last_law_priority_tasks_handling_time + FILE_TRANSFER_LOW_PRIORITY_TASKS_PERIOD < now) - { - last_law_priority_tasks_handling_time = now ; - - mFtDataplex->deleteUnusedServers() ; - mFtDataplex->handlePendingCrcRequests() ; - mFtDataplex->dispatchReceivedChunkCheckSum() ; - cleanTimedOutSearches(); - } - - return moreToTick; -} - -bool ftServer::checkUploadLimit(const RsPeerId& pid,const RsFileHash& hash) -{ - // No need for this extra cost if the value means "unlimited" - -#ifdef SERVER_DEBUG - std::cerr << "Checking upload limit for friend " << pid << " and hash " << hash << ": " ; -#endif - - uint32_t max_ups = mFtController->getMaxUploadsPerFriend() ; - - RS_STACK_MUTEX(srvMutex) ; - - if(max_ups == 0) - { -#ifdef SERVER_DEBUG - std::cerr << " no limit! returning true." << std::endl; -#endif - return true ; - } -#ifdef SERVER_DEBUG - std::cerr << " max=" << max_ups ; -#endif - - // Find the latest records for this pid. - - std::map& tmap(mUploadLimitMap[pid]) ; - std::map::iterator it ; - - rstime_t now = time(NULL) ; - - // If the limit has been decresed, we arbitrarily drop some ongoing slots. - - while(tmap.size() > max_ups) - tmap.erase(tmap.begin()) ; - - // Look in the upload record map. If it's not full, directly allocate a slot. If full, re-use an existing slot if a file is already cited. - - if(tmap.size() < max_ups || (tmap.size()==max_ups && tmap.end() != (it = tmap.find(hash)))) - { -#ifdef SERVER_DEBUG - std::cerr << " allocated slot for this hash => true" << std::endl; -#endif - - tmap[hash] = now ; - return true ; - } - - // There's no room in the used slots, but maybe some of them are not used anymore, in which case we remove them, which freeze a slot. - uint32_t cleaned = 0 ; - - for(it = tmap.begin();it!=tmap.end() && cleaned<2;) - if(it->second + FILE_TRANSFER_MAX_DELAY_BEFORE_DROP_USAGE_RECORD < now) - { - std::map::iterator tmp(it) ; - ++tmp; - tmap.erase(it) ; - it = tmp; - ++cleaned ; - } - else - ++it ; - - if(cleaned > 0) - { -#ifdef SERVER_DEBUG - std::cerr << " cleaned up " << cleaned << " old hashes => true" << std::endl; -#endif - tmap[hash] = now ; - return true ; - } - -#ifdef SERVER_DEBUG - std::cerr << " no slot for this hash => false" << std::endl; -#endif - return false ; -} - -int ftServer::handleIncoming() -{ - // now File Input. - int nhandled = 0 ; - - RsItem *item = NULL ; - - while(NULL != (item = recvItem())) - { - nhandled++ ; - - switch(item->PacketSubType()) - { - case RS_PKT_SUBTYPE_FT_DATA_REQUEST: - { - RsFileTransferDataRequestItem *f = dynamic_cast(item) ; - - if (f && checkUploadLimit(f->PeerId(),f->file.hash)) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::handleIncoming: received data request for hash " << f->file.hash << ", offset=" << f->fileoffset << ", chunk size=" << f->chunksize << std::endl; -#endif - mFtDataplex->recvDataRequest(f->PeerId(), f->file.hash, f->file.filesize, f->fileoffset, f->chunksize); - } - } - break ; - - case RS_PKT_SUBTYPE_FT_DATA: - { - RsFileTransferDataItem *f = dynamic_cast(item) ; - if (f) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::handleIncoming: received data for hash " << f->fd.file.hash << ", offset=" << f->fd.file_offset << ", chunk size=" << f->fd.binData.bin_len << std::endl; -#endif - mFtDataplex->recvData(f->PeerId(), f->fd.file.hash, f->fd.file.filesize, f->fd.file_offset, f->fd.binData.bin_len, f->fd.binData.bin_data); - - /* we've stolen the data part -> so blank before delete - */ - f->fd.binData.TlvShallowClear(); - } - } - break ; - - case RS_PKT_SUBTYPE_FT_CHUNK_MAP_REQUEST: - { - RsFileTransferChunkMapRequestItem *f = dynamic_cast(item) ; - if (f) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::handleIncoming: received chunkmap request for hash " << f->hash << ", client=" << f->is_client << std::endl; -#endif - mFtDataplex->recvChunkMapRequest(f->PeerId(), f->hash,f->is_client) ; - } - } - break ; - - case RS_PKT_SUBTYPE_FT_CHUNK_MAP: - { - RsFileTransferChunkMapItem *f = dynamic_cast(item) ; - if (f) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::handleIncoming: received chunkmap for hash " << f->hash << ", client=" << f->is_client << /*", map=" << f->compressed_map <<*/ std::endl; -#endif - mFtDataplex->recvChunkMap(f->PeerId(), f->hash,f->compressed_map,f->is_client) ; - } - } - break ; - - case RS_PKT_SUBTYPE_FT_CHUNK_CRC_REQUEST: - { - RsFileTransferSingleChunkCrcRequestItem *f = dynamic_cast(item) ; - if (f) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::handleIncoming: received single chunk crc req for hash " << f->hash << ", chunk number=" << f->chunk_number << std::endl; -#endif - mFtDataplex->recvSingleChunkCRCRequest(f->PeerId(), f->hash,f->chunk_number) ; - } - } - break ; - - case RS_PKT_SUBTYPE_FT_CHUNK_CRC: - { - RsFileTransferSingleChunkCrcItem *f = dynamic_cast(item) ; - if (f) - { -#ifdef SERVER_DEBUG - FTSERVER_DEBUG() << "ftServer::handleIncoming: received single chunk crc req for hash " << f->hash << ", chunk number=" << f->chunk_number << ", checksum = " << f->check_sum << std::endl; -#endif - mFtDataplex->recvSingleChunkCRC(f->PeerId(), f->hash,f->chunk_number,f->check_sum); - } - } - break ; - } - - delete item ; - } - - return nhandled; -} - -/********************************** - ********************************** - ********************************** - *********************************/ - -void ftServer::ftReceiveSearchResult(RsTurtleFTSearchResultItem *item) -{ - bool hasCallback = false; - - { - RS_STACK_MUTEX(mSearchCallbacksMapMutex); - auto cbpt = mSearchCallbacksMap.find(item->request_id); - if(cbpt != mSearchCallbacksMap.end()) - { - hasCallback = true; - - std::vector cRes; - for(auto& res: std::as_const(item->result)) - cRes.push_back(TurtleFileInfoV2(res)); - - cbpt->second.first(cRes); - } - } // end RS_STACK_MUTEX(mSearchCallbacksMapMutex); - - if(!hasCallback) - RsServer::notify()->notifyTurtleSearchResult( - item->PeerId(), item->request_id, item->result ); -} - -bool ftServer::receiveSearchRequest( - unsigned char* searchRequestData, uint32_t searchRequestDataLen, - unsigned char*& searchResultData, uint32_t& searchResultDataLen, - uint32_t& maxAllowsHits ) -{ -#ifdef RS_DEEP_FILES_INDEX - std::unique_ptr recvItem( - RsServiceSerializer::deserialise( - searchRequestData, &searchRequestDataLen ) ); - - if(!recvItem) - { - RsWarn() << __PRETTY_FUNCTION__ << " Search request deserialization " - << "failed" << std::endl; - return false; - } - - std::unique_ptr sReqItPtr( - dynamic_cast(recvItem.get()) ); - if(!sReqItPtr) - { - RsWarn() << __PRETTY_FUNCTION__ << " Received an invalid search request" - << " " << *recvItem << std::endl; - return false; - } - recvItem.release(); - - RsFileSearchRequestItem& searchReq(*sReqItPtr); - - std::vector dRes; - DeepFilesIndex dfi(DeepFilesIndex::dbDefaultPath()); - if(!dfi.search(searchReq.queryString, dRes, maxAllowsHits)) - { - RsFileSearchResultItem resIt; - - for(const auto& dMatch : dRes) - resIt.mResults.push_back(TurtleFileInfoV2(dMatch)); - - searchResultDataLen = RsServiceSerializer::size(&resIt); - searchResultData = static_cast(malloc(searchResultDataLen)); - return RsServiceSerializer::serialise( - &resIt, searchResultData, &searchResultDataLen ); - } -#else - (void) searchRequestData; - (void) searchRequestDataLen; - (void) maxAllowsHits; -#endif // def RS_DEEP_FILES_INDEX - - searchResultData = nullptr; - searchResultDataLen = 0; - return false; -} - -void ftServer::receiveSearchResult( - TurtleSearchRequestId requestId, unsigned char* searchResultData, - uint32_t searchResultDataLen ) -{ - if(!searchResultData || !searchResultDataLen) - { - RsWarn() << __PRETTY_FUNCTION__ << " got null paramethers " - << "searchResultData: " << static_cast(searchResultData) - << " searchResultDataLen: " << searchResultDataLen - << " seems someone else in the network have a buggy RetroShare" - << " implementation" << std::endl; - return; - } - - RS_STACK_MUTEX(mSearchCallbacksMapMutex); - auto cbpt = mSearchCallbacksMap.find(requestId); - if(cbpt != mSearchCallbacksMap.end()) - { - RsItem* recvItem = RsServiceSerializer::deserialise( - searchResultData, &searchResultDataLen ); - - if(!recvItem) - { - RsWarn() << __PRETTY_FUNCTION__ << " Search result deserialization " - << "failed" << std::endl; - return; - } - - std::unique_ptr resItPtr( - dynamic_cast(recvItem) ); - - if(!resItPtr) - { - RsWarn() << __PRETTY_FUNCTION__ << " Received invalid search result" - << std::endl; - delete recvItem; - return; - } - - cbpt->second.first(resItPtr->mResults); - } -} - -/***************************** CONFIG ****************************/ - -bool ftServer::addConfiguration(p3ConfigMgr *cfgmgr) -{ - /* add all the subbits to config mgr */ - cfgmgr->addConfiguration("ft_database.cfg" , mFileDatabase); - cfgmgr->addConfiguration("ft_extra.cfg" , mFtExtra ); - cfgmgr->addConfiguration("ft_transfers.cfg", mFtController); - - return true; -} - -#ifdef RS_DEEP_FILES_INDEX -static std::vector xapianQueryKeywords = -{ - " AND ", " OR ", " NOT ", " XOR ", " +", " -", " ( ", " ) ", " NEAR ", - " ADJ ", " \"", "\" " -}; -#endif - -bool ftServer::turtleSearchRequest( - const std::string& matchString, - const std::function& results)>& multiCallback, - rstime_t maxWait ) -{ - if(matchString.empty()) - { - RsWarn() << __PRETTY_FUNCTION__ << " match string can't be empty!" - << std::endl; - return false; - } - -#ifdef RS_DEEP_FILES_INDEX - RsFileSearchRequestItem sItem; - sItem.queryString = matchString; - - uint32_t iSize = RsServiceSerializer::size(&sItem); - uint8_t* iBuf = static_cast(malloc(iSize)); - RsServiceSerializer::serialise(&sItem, iBuf, &iSize); - - Dbg3() << __PRETTY_FUNCTION__ << " sending search request:" << sItem - << std::endl; - - TurtleRequestId xsId = mTurtleRouter->turtleSearch(iBuf, iSize, this); - - { RS_STACK_MUTEX(mSearchCallbacksMapMutex); - mSearchCallbacksMap.emplace( - xsId, - std::make_pair( - multiCallback, - std::chrono::system_clock::now() + - std::chrono::seconds(maxWait) ) ); - } // RS_STACK_MUTEX(mSearchCallbacksMapMutex); - - /* Trick to keep receiving more or less usable results from old peers */ - std::string strippedQuery = matchString; - for(const std::string& xKeyword : xapianQueryKeywords) - { - std::string::size_type pos = std::string::npos; - while( (pos = strippedQuery.find(xKeyword)) != std::string::npos ) - strippedQuery.replace(pos, xKeyword.length(), " "); - } - - Dbg3() << __PRETTY_FUNCTION__ << " sending stripped query for " - << "retro-compatibility: " << strippedQuery << std::endl; - - TurtleRequestId sId = mTurtleRouter->turtleSearch(strippedQuery); -#else // def RS_DEEP_FILES_INDEX - TurtleRequestId sId = mTurtleRouter->turtleSearch(matchString); -#endif // def RS_DEEP_FILES_INDEX - - { - RS_STACK_MUTEX(mSearchCallbacksMapMutex); - mSearchCallbacksMap.emplace( - sId, - std::make_pair( - multiCallback, - std::chrono::system_clock::now() + - std::chrono::seconds(maxWait) ) ); - } - - return true; -} - -void ftServer::cleanTimedOutSearches() -{ - RS_STACK_MUTEX(mSearchCallbacksMapMutex); - auto now = std::chrono::system_clock::now(); - for( auto cbpt = mSearchCallbacksMap.begin(); - cbpt != mSearchCallbacksMap.end(); ) - if(cbpt->second.second <= now) - cbpt = mSearchCallbacksMap.erase(cbpt); - else ++cbpt; -} - -// Offensive content file filtering - -int ftServer::banFile(const RsFileHash& real_file_hash, const std::string& filename, uint64_t file_size) -{ - return mFileDatabase->banFile(real_file_hash,filename,file_size) ; -} -int ftServer::unbanFile(const RsFileHash& real_file_hash) -{ - return mFileDatabase->unbanFile(real_file_hash) ; -} -bool ftServer::getPrimaryBannedFilesList(std::map& banned_files) -{ - return mFileDatabase->getPrimaryBannedFilesList(banned_files) ; -} - -bool ftServer::isHashBanned(const RsFileHash& hash) -{ - return mFileDatabase->isFileBanned(hash); -} - -RsFileItem::~RsFileItem() = default; - -RsFileItem::RsFileItem(RsFileItemType subtype) : - RsItem( RS_PKT_VERSION_SERVICE, - static_cast(RsServiceType::FILE_TRANSFER), - static_cast(subtype) ) {} - -void RsFileSearchRequestItem::clear() { queryString.clear(); } - -void RsFileSearchResultItem::clear() { mResults.clear(); } - - -std::error_condition RsFilesErrorCategory::default_error_condition(int ev) -const noexcept -{ - switch(static_cast(ev)) - { - case RsFilesErrorNum::FILES_HANDLE_NOT_FOUND: - return std::errc::invalid_argument; - default: - return std::error_condition(ev, *this); - } -} - -std::error_condition ftServer::dirDetailsToLink( - std::string& link, - const DirDetails& dirDetails, bool fragSneak, const std::string& baseUrl ) -{ - std::unique_ptr tFileTree = - RsFileTree::fromDirDetails(dirDetails, false); - if(!tFileTree) return std::errc::invalid_argument; - - link = tFileTree->toBase64(); - - if(!baseUrl.empty()) - { - RsUrl tUrl(baseUrl); - tUrl.setQueryKV(FILES_URL_COUNT_FIELD, - std::to_string(tFileTree->mTotalFiles) ) - .setQueryKV(FILES_URL_NAME_FIELD, dirDetails.name) - .setQueryKV( FILES_URL_SIZE_FIELD, - std::to_string(tFileTree->mTotalSize) ); - if(fragSneak) - tUrl.setQueryKV(FILES_URL_DATA_FIELD, FILES_URL_FAGMENT_FORWARD) - .setFragment(link); - else tUrl.setQueryKV(FILES_URL_DATA_FIELD, link); - link = tUrl.toString(); - } - - return std::error_condition(); -} - -std::error_condition ftServer::exportCollectionLink( - std::string& link, uint64_t handle, bool fragSneak, - const std::string& baseUrl ) -{ - DirDetails tDirDet; - if(!requestDirDetails(tDirDet, handle)) - return RsFilesErrorNum::FILES_HANDLE_NOT_FOUND; - - return dirDetailsToLink(link, tDirDet, fragSneak, baseUrl); -} - -/// @see RsFiles -std::error_condition ftServer::exportFileLink( - std::string& link, const RsFileHash& fileHash, uint64_t fileSize, - const std::string& fileName, bool fragSneak, const std::string& baseUrl ) -{ - if(fileHash.isNull() || !fileSize || fileName.empty()) - return std::errc::invalid_argument; - - DirDetails tDirDet; - tDirDet.type = DIR_TYPE_FILE; - tDirDet.name = fileName; - tDirDet.hash = fileHash; - tDirDet.size = fileSize; - - return dirDetailsToLink(link, tDirDet, fragSneak, baseUrl); -} - -std::error_condition ftServer::parseFilesLink( - const std::string& link, RsFileTree& collection ) -{ - RsUrl tUrl(link); - - { - /* Handle retrocompatibility with old stile single file links - * retroshare://file?name=$FILE_NAME&size=$FILE_SIZE&hash=$FILE_HASH - */ - if( tUrl.scheme() == "retroshare" && tUrl.host() == "file" - && tUrl.hasQueryK("name") && !tUrl.getQueryV("name")->empty() - && tUrl.hasQueryK("size") && !tUrl.getQueryV("size")->empty() - && tUrl.hasQueryK("hash") && !tUrl.getQueryV("hash")->empty() ) - { - DirDetails dt; - dt.type = DIR_TYPE_FILE; - dt.hash = RsFileHash(*tUrl.getQueryV("hash")); - dt.name = *tUrl.getQueryV("name"); - try - { - dt.size = std::stoull(*tUrl.getQueryV("size")); - std::unique_ptr ft; - if( !dt.hash.isNull() && - (ft = RsFileTree::fromDirDetails(dt, true)) ) - { - collection = *ft; - return std::error_condition(); - } - } - catch (...) {} - } - } - - { - /* Handle retrocompatibility with old stile collection links - * retroshare://collection?name=$NAME&size=$SIZE&radix=$RADIX&files=$COUNT - */ - if( tUrl.scheme() == "retroshare" && tUrl.host() == "collection" - && tUrl.hasQueryK("name") && !tUrl.getQueryV("name")->empty() - && tUrl.hasQueryK("size") && !tUrl.getQueryV("size")->empty() - && tUrl.hasQueryK("radix") && !tUrl.getQueryV("radix")->empty() - && tUrl.hasQueryK("files") && !tUrl.getQueryV("files")->empty() ) - { - try - { - // Don't need the values just check they are valid numbers - std::stoull(*tUrl.getQueryV("size")); - std::stoull(*tUrl.getQueryV("files")); - - auto ft = RsFileTree::fromRadix64(*tUrl.getQueryV("radix")); - if(ft) - { - collection = *ft; - return std::error_condition(); - } - } - catch (...) {} - } - } - - // Finaly handle the new files link format - rs_view_ptr radixPtr = - tUrl.getQueryV(FILES_URL_DATA_FIELD); - if(!radixPtr) radixPtr = &link; - else if(*radixPtr == FILES_URL_FAGMENT_FORWARD) radixPtr = &tUrl.fragment(); - - std::unique_ptr tft; std::error_condition ec; - std::tie(tft, ec) = RsFileTree::fromBase64(*radixPtr); - if(tft) collection = *tft; - return ec; -} diff --git a/libretroshare/src/ft/ftserver.h b/libretroshare/src/ft/ftserver.h deleted file mode 100644 index f6cc4b44c..000000000 --- a/libretroshare/src/ft/ftserver.h +++ /dev/null @@ -1,439 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftserver.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef FT_SERVER_HEADER -#define FT_SERVER_HEADER - -/* - * ftServer. - * - * Top level File Transfer interface. - * (replaces old filedexserver) - * - * sets up the whole File Transfer class structure. - * sets up the File Indexing side of cache system too. - * - * provides rsFiles interface for external control. - * - */ - -#include -#include -#include -#include -#include - -#include "ft/ftdata.h" -#include "turtle/turtleclientservice.h" -#include "services/p3service.h" -#include "retroshare/rsfiles.h" -#include "rsitems/rsitem.h" -#include "serialiser/rsserial.h" -#include "pqi/pqi.h" -#include "pqi/p3cfgmgr.h" - -class p3ConnectMgr; -class p3FileDatabase; - -class ftFiStore; -class ftFiMonitor; - -class ftController; -class ftExtraList; -class ftFileSearch; - -class ftDataMultiplex; -class p3turtle; - -class p3PeerMgr; -class p3ServiceControl; -class p3FileDatabase; - -enum class RsFileItemType : uint8_t -{ - NONE = 0x00, /// Only to detect ununitialized - FILE_SEARCH_REQUEST = 0x57, - FILE_SEARCH_RESULT = 0x58 -}; - -struct RsFileItem : RsItem -{ - ~RsFileItem() override; - -protected: - RsFileItem(RsFileItemType subtype); -}; - -struct RsFileSearchRequestItem : RsFileItem -{ - RsFileSearchRequestItem() : RsFileItem(RsFileItemType::FILE_SEARCH_REQUEST) - { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_SEARCH_REQUEST); } - - std::string queryString; - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { RS_SERIAL_PROCESS(queryString); } - - void clear() override; -}; - -struct RsFileSearchResultItem : RsFileItem -{ - RsFileSearchResultItem() : RsFileItem(RsFileItemType::FILE_SEARCH_RESULT) - { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_SEARCH_RESULT); } - - std::vector mResults; - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { RS_SERIAL_PROCESS(mResults); } - - void clear() override; -}; - - -class ftServer : - public p3Service, public RsFiles, public ftDataSend, - public RsTurtleClientService, public RsServiceSerializer -{ - -public: - - /***************************************************************/ - /******************** Setup ************************************/ - /***************************************************************/ - - ftServer(p3PeerMgr *peerMgr, p3ServiceControl *serviceCtrl); - virtual RsServiceInfo getServiceInfo(); - - /* Assign important variables */ - void setConfigDirectory(std::string path); - - /* add Config Items (Extra, Controller) */ - void addConfigComponents(p3ConfigMgr *mgr); - - const RsPeerId& OwnId(); - - /* Final Setup (once everything is assigned) */ - void SetupFtServer() ; - virtual void connectToTurtleRouter(p3turtle *p) ; - virtual void connectToFileDatabase(p3FileDatabase *b); - - // Implements RsTurtleClientService - // - - uint16_t serviceId() const { return RS_SERVICE_TYPE_FILE_TRANSFER ; } - virtual bool handleTunnelRequest(const RsFileHash& hash,const RsPeerId& peer_id) ; - virtual void receiveTurtleData(const RsTurtleGenericTunnelItem *item,const RsFileHash& hash,const RsPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction) ; - - /// We keep this for retro-compatibility @see RsTurtleClientService - virtual void ftReceiveSearchResult(RsTurtleFTSearchResultItem *item); - - /// @see RsTurtleClientService - bool receiveSearchRequest( - unsigned char* searchRequestData, uint32_t searchRequestDataLen, - unsigned char*& search_result_data, uint32_t& searchResultDataLen, - uint32_t& maxAllowsHits ) override; - - /// @see RsTurtleClientService - void receiveSearchResult( - TurtleSearchRequestId requestId, unsigned char* searchResultData, - uint32_t searchResultDataLen ) override; - - virtual RsItem *create_item(uint16_t service,uint8_t item_type) const ; - virtual RsServiceSerializer *serializer() { return this ; } - - void addVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&,RsTurtleGenericTunnelItem::Direction dir) ; - void removeVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&) ; - - /***************************************************************/ - /*************** Control Interface *****************************/ - /************** (Implements RsFiles) ***************************/ - /***************************************************************/ - - void StartupThreads(); - void StopThreads(); - - // member access - - ftDataMultiplex *getMultiplexer() const { return mFtDataplex ; } - ftController *getController() const { return mFtController ; } - - /** - * @see RsFiles::getFileData - */ - bool getFileData(const RsFileHash& hash, uint64_t offset, uint32_t& requested_size,uint8_t *data); - - /*** - * Control of Downloads - ***/ - virtual bool alreadyHaveFile(const RsFileHash& hash, FileInfo &info); - virtual bool FileRequest(const std::string& fname, const RsFileHash& hash, uint64_t size, const std::string& dest, TransferRequestFlags flags, const std::list& srcIds); - virtual bool FileCancel(const RsFileHash& hash); - virtual bool FileControl(const RsFileHash& hash, uint32_t flags); - virtual bool FileClearCompleted(); - virtual bool setDestinationDirectory(const RsFileHash& hash,const std::string& new_path) ; - virtual bool setDestinationName(const RsFileHash& hash,const std::string& new_name) ; - virtual bool setChunkStrategy(const RsFileHash& hash,FileChunksInfo::ChunkStrategy s) ; - virtual void setDefaultChunkStrategy(FileChunksInfo::ChunkStrategy) ; - virtual FileChunksInfo::ChunkStrategy defaultChunkStrategy() ; - virtual uint32_t freeDiskSpaceLimit() const ; - virtual void setFreeDiskSpaceLimit(uint32_t size_in_mb) ; - virtual void setDefaultEncryptionPolicy(uint32_t policy) ; // RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT/PERMISSIVE - virtual uint32_t defaultEncryptionPolicy() ; - virtual void setMaxUploadSlotsPerFriend(uint32_t n) ; - virtual uint32_t getMaxUploadSlotsPerFriend() ; - virtual void setFilePermDirectDL(uint32_t perm) ; - virtual uint32_t filePermDirectDL() ; - - /// @see RsFiles - std::error_condition requestFiles( - const RsFileTree& collection, - const std::string& destPath = "", - const std::vector& srcIds = std::vector(), - FileRequestFlags flags = FileRequestFlags::ANONYMOUS_ROUTING - ) override; - - /// @see RsFiles - bool turtleSearchRequest( - const std::string& matchString, - const std::function& results)>& multiCallback, - rstime_t maxWait = 300 ) override; - - virtual TurtleSearchRequestId turtleSearch(const std::string& string_to_match) ; - virtual TurtleSearchRequestId turtleSearch(const RsRegularExpression::LinearizedExpression& expr) ; - - /// @see RsFiles - std::error_condition exportCollectionLink( - std::string& link, uint64_t handle, bool fragSneak = false, - const std::string& baseUrl = RsFiles::DEFAULT_FILES_BASE_URL - ) override; - - /// @see RsFiles - std::error_condition exportFileLink( - std::string& link, const RsFileHash& fileHash, uint64_t fileSize, - const std::string& fileName, bool fragSneak = false, - const std::string& baseUrl = RsFiles::DEFAULT_FILES_BASE_URL - ) override; - - /// @see RsFiles - std::error_condition parseFilesLink( - const std::string& link, RsFileTree& collection ) override; - - /*** - * Control of Downloads Priority. - ***/ - virtual uint32_t getQueueSize() ; - virtual void setQueueSize(uint32_t s) ; - virtual bool changeQueuePosition(const RsFileHash& hash, QueueMove queue_mv); - virtual bool changeDownloadSpeed(const RsFileHash& hash, int speed); - virtual bool getDownloadSpeed(const RsFileHash& hash, int & speed); - virtual bool clearDownload(const RsFileHash& hash); - //virtual void getDwlDetails(std::list & details); - - /*** - * Download/Upload Details - ***/ - virtual void FileDownloads(std::list &hashs); - virtual bool FileUploads(std::list &hashs); - virtual bool FileDetails(const RsFileHash &hash, FileSearchFlags hintflags, FileInfo &info); - virtual bool FileDownloadChunksDetails(const RsFileHash& hash,FileChunksInfo& info) ; - virtual bool FileUploadChunksDetails(const RsFileHash& hash,const RsPeerId& peer_id,CompressedChunkMap& map) ; - virtual bool isEncryptedSource(const RsPeerId& virtual_peer_id) ; - - - /*** - * Extra List Access - ***/ - virtual bool ExtraFileAdd(std::string fname, const RsFileHash& hash, uint64_t size, uint32_t period, TransferRequestFlags flags); - virtual bool ExtraFileRemove(const RsFileHash& hash); - virtual bool ExtraFileHash(std::string localpath, rstime_t period, TransferRequestFlags flags); - virtual bool ExtraFileStatus(std::string localpath, FileInfo &info); - virtual bool ExtraFileMove(std::string fname, const RsFileHash& hash, uint64_t size, std::string destpath); - - - /*** - * Directory Listing / Search Interface - ***/ - virtual int RequestDirDetails(void *ref, DirDetails &details, FileSearchFlags flags); - - /// @see RsFiles::RequestDirDetails - virtual bool requestDirDetails( - DirDetails &details, uint64_t handle = 0, - FileSearchFlags flags = RS_FILE_HINTS_LOCAL ); - - virtual bool findChildPointer(void *ref, int row, void *& result, FileSearchFlags flags) ; - virtual uint32_t getType(void *ref,FileSearchFlags flags) ; - - virtual int SearchKeywords(std::list keywords, std::list &results,FileSearchFlags flags); - virtual int SearchKeywords(std::list keywords, std::list &results,FileSearchFlags flags,const RsPeerId& peer_id); - virtual int SearchBoolExp(RsRegularExpression::Expression * exp, std::list &results,FileSearchFlags flags); - virtual int SearchBoolExp(RsRegularExpression::Expression * exp, std::list &results,FileSearchFlags flags,const RsPeerId& peer_id); - virtual int getSharedDirStatistics(const RsPeerId& pid, SharedDirStats& stats) ; - - virtual int banFile(const RsFileHash& real_file_hash, const std::string& filename, uint64_t file_size) ; - virtual int unbanFile(const RsFileHash& real_file_hash); - virtual bool getPrimaryBannedFilesList(std::map& banned_files) ; - virtual bool isHashBanned(const RsFileHash& hash); - - /*** - * Utility Functions - ***/ - virtual bool ConvertSharedFilePath(std::string path, std::string &fullpath); - virtual void ForceDirectoryCheck(bool add_safe_delay); - virtual void updateSinceGroupPermissionsChanged() ; - virtual bool InDirectoryCheck(); - virtual bool copyFile(const std::string& source, const std::string& dest); - - /*** - * Directory Handling - ***/ - virtual void requestDirUpdate(void *ref) ; // triggers the update of the given reference. Used when browsing. - virtual bool setDownloadDirectory(const std::string& path); - virtual bool setPartialsDirectory(const std::string& path); - virtual std::string getDownloadDirectory(); - virtual std::string getPartialsDirectory(); - - virtual bool getSharedDirectories(std::list &dirs); - virtual bool setSharedDirectories(const std::list &dirs); - virtual bool addSharedDirectory(const SharedDirInfo& dir); - virtual bool updateShareFlags(const SharedDirInfo& dir); // updates the flags. The directory should already exist ! - virtual bool removeSharedDirectory(std::string dir); - - virtual bool getIgnoreLists(std::list& ignored_prefixes, std::list& ignored_suffixes, uint32_t& ignore_flags) ; - virtual void setIgnoreLists(const std::list& ignored_prefixes, const std::list& ignored_suffixes,uint32_t ignore_flags) ; - - virtual bool getShareDownloadDirectory(); - virtual bool shareDownloadDirectory(bool share); - - virtual void setWatchPeriod(int minutes) ; - virtual int watchPeriod() const ; - virtual void setWatchEnabled(bool b) ; - virtual bool watchEnabled() ; - virtual bool followSymLinks() const; - virtual void setFollowSymLinks(bool b); - virtual void togglePauseHashingProcess(); - virtual bool hashingProcessPaused(); - - virtual void setMaxShareDepth(int depth) ; - virtual int maxShareDepth() const; - - virtual bool ignoreDuplicates() ; - virtual void setIgnoreDuplicates(bool ignore) ; - - static bool encryptHash(const RsFileHash& hash, RsFileHash& hash_of_hash); - - /***************************************************************/ - /*************** Data Transfer Interface ***********************/ - /***************************************************************/ -public: - virtual bool activateTunnels(const RsFileHash& hash,uint32_t default_encryption_policy,TransferRequestFlags flags,bool onoff); - - virtual bool sendData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data); - virtual bool sendDataRequest(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize); - virtual bool sendChunkMapRequest(const RsPeerId& peer_id,const RsFileHash& hash,bool is_client) ; - virtual bool sendChunkMap(const RsPeerId& peer_id,const RsFileHash& hash,const CompressedChunkMap& cmap,bool is_client) ; - virtual bool sendSingleChunkCRCRequest(const RsPeerId& peer_id,const RsFileHash& hash,uint32_t chunk_number) ; - virtual bool sendSingleChunkCRC(const RsPeerId& peer_id,const RsFileHash& hash,uint32_t chunk_number,const Sha1CheckSum& crc) ; - - static void deriveEncryptionKey(const RsFileHash& hash, uint8_t *key); - - bool encryptItem(RsTurtleGenericTunnelItem *clear_item,const RsFileHash& hash,RsTurtleGenericDataItem *& encrypted_item); - bool decryptItem(const RsTurtleGenericDataItem *encrypted_item, const RsFileHash& hash, RsTurtleGenericTunnelItem *&decrypted_item); - - /*************** Internal Transfer Fns *************************/ - virtual int tick(); - - /* Configuration */ - bool addConfiguration(p3ConfigMgr *cfgmgr); - bool ResumeTransfers(); - - /*************************** p3 Config Overload ********************/ - -protected: - int handleIncoming() ; - bool handleCacheData() ; - - /*! - * \brief sendTurtleItem - * Sends the given item into a turtle tunnel, possibly encrypting it if the type of tunnel requires it, which is known from the hash itself. - * \param peerId Peer id to send to (this is a virtual peer id from turtle service) - * \param hash hash of the file. If the item needs to be encrypted - * \param item item to send. - * \return - * true if everything goes right - */ - bool sendTurtleItem(const RsPeerId& peerId,const RsFileHash& hash,RsTurtleGenericTunnelItem *item); - - // fnds out what is the real hash of encrypted hash hash - bool findRealHash(const RsFileHash& hash, RsFileHash& real_hash); - bool findEncryptedHash(const RsPeerId& virtual_peer_id, RsFileHash& encrypted_hash); - - bool checkUploadLimit(const RsPeerId& pid,const RsFileHash& hash); - - std::error_condition dirDetailsToLink( - std::string& link, - const DirDetails& dirDetails, bool fragSneak, - const std::string& baseUrl ); - -private: - - /* no need for Mutex protection - - * as each component is protected independently. - */ - p3PeerMgr *mPeerMgr; - p3ServiceControl *mServiceCtrl; - p3FileDatabase *mFileDatabase ; - ftController *mFtController; - ftExtraList *mFtExtra; - ftDataMultiplex *mFtDataplex; - p3turtle *mTurtleRouter ; - ftFileSearch *mFtSearch; - - RsMutex srvMutex; - std::string mConfigPath; - std::string mDownloadPath; - std::string mPartialsPath; - - std::map mEncryptedHashes ; // This map is such that sha1(it->second) = it->first - std::map mEncryptedPeerIds ; // This map holds the hash to be used with each peer id - std::map > mUploadLimitMap ; - - /** Store search callbacks with timeout*/ - std::map< - TurtleRequestId, - std::pair< - std::function& results)>, - std::chrono::system_clock::time_point > - > mSearchCallbacksMap; - RsMutex mSearchCallbacksMapMutex; - - /// Cleanup mSearchCallbacksMap - void cleanTimedOutSearches(); - - RS_SET_CONTEXT_DEBUG_LEVEL(1) -}; - - - -#endif diff --git a/libretroshare/src/ft/fttransfermodule.cc b/libretroshare/src/ft/fttransfermodule.cc deleted file mode 100644 index 8c6ae1f08..000000000 --- a/libretroshare/src/ft/fttransfermodule.cc +++ /dev/null @@ -1,923 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: fttransfermodule.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -/****** - * #define FT_DEBUG 1 - *****/ - -#include "util/rstime.h" - -#include "retroshare/rsturtle.h" -#include "fttransfermodule.h" - -/************************************************************************* - * Notes on file transfer strategy. - * Care must be taken not to overload pipe. best way is to time requests. - * and according adjust data rate. - * - * each peer gets a 'max_rate' which is decided on the type of transfer. - * - trickle ... - * - stream ... - * - max ... - * - * Each peer is independently managed. - * - * via the functions: - * - */ - -const double FT_TM_MAX_PEER_RATE = 100 * 1024 * 1024; /* 100MB/s */ -const uint32_t FT_TM_MAX_RESETS = 5; -const uint32_t FT_TM_MINIMUM_CHUNK = 1024; /* ie 1Kb / sec */ -const uint32_t FT_TM_DEFAULT_TRANSFER_RATE = 20*1024; /* ie 20 Kb/sec */ -const uint32_t FT_TM_RESTART_DOWNLOAD = 20; /* 20 seconds */ -const uint32_t FT_TM_DOWNLOAD_TIMEOUT = 10; /* 10 seconds */ - -const double FT_TM_RATE_INCREASE_SLOWER = 0.05 ; -const double FT_TM_RATE_INCREASE_AVERAGE = 0.3 ; -const double FT_TM_RATE_INCREASE_FASTER = 1.0 ; - -#define FT_TM_FLAG_DOWNLOADING 0 -#define FT_TM_FLAG_CANCELED 1 -#define FT_TM_FLAG_COMPLETE 2 -#define FT_TM_FLAG_CHECKING 3 -#define FT_TM_FLAG_CHUNK_CRC 4 - -peerInfo::peerInfo(const RsPeerId& peerId_in) - :peerId(peerId_in),state(PQIPEER_NOT_ONLINE),desiredRate(FT_TM_DEFAULT_TRANSFER_RATE),actualRate(FT_TM_DEFAULT_TRANSFER_RATE), - lastTS(0), - recvTS(0), lastTransfers(0), nResets(0), - rtt(0), rttActive(false), rttStart(0), rttOffset(0), - mRateIncrease(1) - { - } -// peerInfo(const RsPeerId& peerId_in,uint32_t state_in,uint32_t maxRate_in): -// peerId(peerId_in),state(state_in),desiredRate(maxRate_in),actualRate(0), -// lastTS(0), -// recvTS(0), lastTransfers(0), nResets(0), -// rtt(0), rttActive(false), rttStart(0), rttOffset(0), -// mRateIncrease(1) -// { -// return; -// } -ftTransferModule::ftTransferModule(ftFileCreator *fc, ftDataMultiplex *dm, ftController *c) - :mFileCreator(fc), mMultiplexor(dm), mFtController(c), tfMtx("ftTransferModule"), mFlag(FT_TM_FLAG_DOWNLOADING),mPriority(SPEED_NORMAL) -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - - mHash = mFileCreator->getHash(); - mSize = mFileCreator->getFileSize(); - mFileStatus.hash = mHash; - - _hash_thread = NULL ; - - // Dummy for Testing (should be handled independantly for - // each peer. - //mChunkSize = 10000; - desiredRate = FT_TM_MAX_PEER_RATE; /* 1MB/s ??? */ - actualRate = 0; - - _last_activity_time_stamp = time(NULL) ; -} - -ftTransferModule::~ftTransferModule() -{ - // Prevents deletion while called from another thread. - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ -} - - -bool ftTransferModule::setFileSources(const std::list& peerIds) -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - - mFileSources.clear(); - -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::setFileSources()"; - std::cerr << " List of peers: " ; -#endif - - std::list::const_iterator it; - for(it = peerIds.begin(); it != peerIds.end(); ++it) - { - -#ifdef FT_DEBUG - std::cerr << " \t" << *it; -#endif - - peerInfo pInfo(*it); - mFileSources.insert(std::pair(*it,pInfo)); - } - -#ifdef FT_DEBUG - std::cerr << std::endl; -#endif - - return true; -} - -bool ftTransferModule::getFileSources(std::list &peerIds) -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - std::map::iterator it; - for(it = mFileSources.begin(); it != mFileSources.end(); ++it) - { - peerIds.push_back(it->first); - } - return true; -} - -bool ftTransferModule::addFileSource(const RsPeerId& peerId) -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - std::map::iterator mit; - mit = mFileSources.find(peerId); - - if (mit == mFileSources.end()) - { - /* add in new source */ - peerInfo pInfo(peerId); - mFileSources.insert(std::pair(peerId,pInfo)); - //mit = mFileSources.find(peerId); - - mMultiplexor->sendChunkMapRequest(peerId, mHash,false) ; -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::addFileSource()"; - std::cerr << " adding peer: " << peerId << " to sourceList"; - std::cerr << std::endl; -#endif - return true ; - - } - else - { -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::addFileSource()"; - std::cerr << " peer: " << peerId << " already there"; - std::cerr << std::endl; -#endif - return false; - } -} - -bool ftTransferModule::removeFileSource(const RsPeerId& peerId) -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - std::map::iterator mit; - mit = mFileSources.find(peerId); - - if (mit != mFileSources.end()) - { - /* add in new source */ - mFileSources.erase(mit) ; -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::addFileSource(): removing peer: " << peerId << " from sourceList" << std::endl; -#endif - } -#ifdef FT_DEBUG - else - std::cerr << "ftTransferModule::addFileSource(): Should remove peer: " << peerId << ", but it's not in the source list. " << std::endl; -#endif - - return true; -} - -bool ftTransferModule::setPeerState(const RsPeerId& peerId,uint32_t state,uint32_t maxRate) -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::setPeerState()"; - std::cerr << " peerId: " << peerId; - std::cerr << " state: " << state; - std::cerr << " maxRate: " << maxRate << std::endl; -#endif - - std::map::iterator mit; - mit = mFileSources.find(peerId); - - if (mit == mFileSources.end()) - { - /* add in new source */ - -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::setPeerState()"; - std::cerr << " adding new peer to sourceList"; - std::cerr << std::endl; -#endif - return false; - } - - (mit->second).state=state; - (mit->second).desiredRate=maxRate; - // Start it off at zero.... - // (mit->second).actualRate=maxRate; /* should give big kick in right direction */ - - std::list::iterator it; - it = std::find(mOnlinePeers.begin(), mOnlinePeers.end(), peerId); - - if (state!=PQIPEER_NOT_ONLINE) - { - //change to online, add peerId in online peer list - if (it==mOnlinePeers.end()) mOnlinePeers.push_back(peerId); - } - else - { - //change to offline, remove peerId in online peer list - if (it!=mOnlinePeers.end()) mOnlinePeers.erase(it); - } - - return true; -} - - -bool ftTransferModule::getPeerState(const RsPeerId& peerId,uint32_t &state,uint32_t &tfRate) -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - std::map::iterator mit; - mit = mFileSources.find(peerId); - - if (mit == mFileSources.end()) return false; - - state = (mit->second).state; - tfRate = (uint32_t) (mit->second).actualRate; - -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::getPeerState()"; - std::cerr << " peerId: " << peerId; - std::cerr << " state: " << state; - std::cerr << " tfRate: " << tfRate << std::endl; -#endif - return true; -} - -uint32_t ftTransferModule::getDataRate(const RsPeerId& peerId) -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - std::map::iterator mit; - mit = mFileSources.find(peerId); - if (mit == mFileSources.end()) - { -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::getDataRate()"; - std::cerr << " peerId: " << peerId; - std::cerr << " peer not exist in file sources " << std::endl; -#endif - return 0; - } - else - return (uint32_t) (mit->second).actualRate; -} -void ftTransferModule::resetActvTimeStamp() -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - _last_activity_time_stamp = time(NULL); -} -rstime_t ftTransferModule::lastActvTimeStamp() -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - return _last_activity_time_stamp ; -} - - //interface to client module -bool ftTransferModule::recvFileData(const RsPeerId& peerId, uint64_t offset, uint32_t chunk_size, void *data) -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::recvFileData()"; - std::cerr << " peerId: " << peerId; - std::cerr << " offset: " << offset; - std::cerr << " chunksize: " << chunk_size; - std::cerr << " data: " << data; - std::cerr << std::endl; -#endif - - bool ok = false; - - std::map::iterator mit; - mit = mFileSources.find(peerId); - - if (mit == mFileSources.end()) - { -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::recvFileData()"; - std::cerr << " peer not found in sources"; - std::cerr << std::endl; -#endif - return false; - } - ok = locked_recvPeerData(mit->second, offset, chunk_size, data); - - locked_storeData(offset, chunk_size, data); - - _last_activity_time_stamp = time(NULL) ; - - free(data) ; - return ok; -} - -void ftTransferModule::locked_requestData(const RsPeerId& peerId, uint64_t offset, uint32_t chunk_size) -{ -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::requestData()"; - std::cerr << " peerId: " << peerId; - std::cerr << " hash: " << mHash; - std::cerr << " size: " << mSize; - std::cerr << " offset: " << offset; - std::cerr << " chunk_size: " << chunk_size; - std::cerr << std::endl; -#endif - - mMultiplexor->sendDataRequest(peerId, mHash, mSize, offset,chunk_size); -} - -bool ftTransferModule::locked_getChunk(const RsPeerId& peer_id,uint32_t size_hint,uint64_t &offset, uint32_t &chunk_size) -{ -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::locked_getChunk()"; - std::cerr << " hash: " << mHash; - std::cerr << " size: " << mSize; - std::cerr << " offset: " << offset; - std::cerr << " size_hint: " << size_hint; - std::cerr << " chunk_size: " << chunk_size; - std::cerr << std::endl; -#endif - - bool source_peer_map_needed ; - - bool val = mFileCreator->getMissingChunk(peer_id,size_hint,offset, chunk_size,source_peer_map_needed); - - if(source_peer_map_needed) - mMultiplexor->sendChunkMapRequest(peer_id, mHash,false) ; - -#ifdef FT_DEBUG - if (val) - { - std::cerr << "ftTransferModule::locked_getChunk()"; - std::cerr << " Answer: Chunk Available"; - std::cerr << " hash: " << mHash; - std::cerr << " size: " << mSize; - std::cerr << " offset: " << offset; - std::cerr << " chunk_size: " << chunk_size; - std::cerr << " peer map needed = " << source_peer_map_needed << std::endl ; - std::cerr << std::endl; - } - else - { - std::cerr << "ftTransferModule::locked_getChunk()"; - std::cerr << " Answer: No Chunk Available"; - std::cerr << " peer map needed = " << source_peer_map_needed << std::endl ; - std::cerr << std::endl; - } -#endif - - return val; -} - -bool ftTransferModule::locked_storeData(uint64_t offset, uint32_t chunk_size,void *data) -{ -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::storeData()"; - std::cerr << " hash: " << mHash; - std::cerr << " size: " << mSize; - std::cerr << " offset: " << offset; - std::cerr << " chunk_size: " << chunk_size; - std::cerr << std::endl; -#endif - - return mFileCreator -> addFileData(offset, chunk_size, data); -} - -bool ftTransferModule::queryInactive() -{ - /* NB: Not sure about this lock... might cause deadlock. - */ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::queryInactive()" << std::endl; -#endif - - if (mFileStatus.stat == ftFileStatus::PQIFILE_INIT) - mFileStatus.stat = ftFileStatus::PQIFILE_DOWNLOADING; - - if (mFileStatus.stat != ftFileStatus::PQIFILE_DOWNLOADING) - { - if (mFileStatus.stat == ftFileStatus::PQIFILE_FAIL_CANCEL) - mFlag = FT_TM_FLAG_COMPLETE; //file canceled by user - return false; - } - - if (mFileStatus.stat == ftFileStatus::PQIFILE_CHECKING) - return false ; - - std::map::iterator mit; - for(mit = mFileSources.begin(); mit != mFileSources.end(); ++mit) - { - locked_tickPeerTransfer(mit->second); - } - if(mFileCreator->finished()) // transfer is complete - { - mFileStatus.stat = ftFileStatus::PQIFILE_CHECKING ; - mFlag = FT_TM_FLAG_CHECKING; - } - else - { - // request for CRCs to ask - std::vector chunks_to_ask ; - -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::queryInactive() : getting chunks to check." << std::endl; -#endif - - mFileCreator->getChunksToCheck(chunks_to_ask) ; -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::queryInactive() : got " << chunks_to_ask.size() << " chunks." << std::endl; -#endif - - mMultiplexor->sendSingleChunkCRCRequests(mHash,chunks_to_ask); - } - - return true; -} - -bool ftTransferModule::cancelTransfer() -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - mFileStatus.stat=ftFileStatus::PQIFILE_FAIL_CANCEL; - - return 1; -} - -bool ftTransferModule::cancelFileTransferUpward() -{ - if (mFtController) - mFtController->FileCancel(mHash); - return true; -} -bool ftTransferModule::completeFileTransfer() -{ -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::completeFileTransfer()"; - std::cerr << std::endl; -#endif - if (mFtController) - mFtController->FlagFileComplete(mHash); - return true; -} - -int ftTransferModule::tick() -{ - queryInactive(); -#ifdef FT_DEBUG - { - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - - std::cerr << "ftTransferModule::tick()"; - std::cerr << " mFlag: " << mFlag; - std::cerr << " mHash: " << mHash; - std::cerr << " mSize: " << mSize; - std::cerr << std::endl; - - std::cerr << "Peers: "; - std::map::iterator it; - for(it = mFileSources.begin(); it != mFileSources.end(); ++it) - { - std::cerr << " " << it->first; - } - std::cerr << std::endl; - - - } -#endif - - uint32_t flags = 0; - { - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - flags = mFlag; - } - - switch (flags) - { - case FT_TM_FLAG_DOWNLOADING: //file transfer not complete - adjustSpeed(); - break; - case FT_TM_FLAG_COMPLETE: //file transfer complete - completeFileTransfer(); - break; - case FT_TM_FLAG_CANCELED: //file transfer canceled - break; - case FT_TM_FLAG_CHECKING: // Check if file hash matches the hashed data - checkFile() ; - break ; - default: - break; - } - - return 0; -} - -bool ftTransferModule::isCheckingHash() -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ -#ifdef FT_DEBUG - std::cerr << "isCheckingHash(): mFlag=" << mFlag << std::endl; -#endif - return mFlag == FT_TM_FLAG_CHECKING || mFlag == FT_TM_FLAG_CHUNK_CRC; -} - -class HashThread: public RsThread -{ - public: - explicit HashThread(ftFileCreator *m) - : _hashThreadMtx("HashThread"), _m(m),_finished(false),_hash("") {} - - virtual void run() - { -#ifdef FT_DEBUG - std::cerr << "hash thread is running for file " << std::endl; -#endif - RsFileHash tmphash ; - _m->hashReceivedData(tmphash) ; - - RsStackMutex stack(_hashThreadMtx) ; - _hash = tmphash ; - _finished = true ; - } - RsFileHash hash() - { - RsStackMutex stack(_hashThreadMtx) ; - return _hash ; - } - bool finished() - { - RsStackMutex stack(_hashThreadMtx) ; - return _finished ; - } - private: - RsMutex _hashThreadMtx ; - ftFileCreator *_m ; - bool _finished ; - RsFileHash _hash ; -}; - -bool ftTransferModule::checkFile() -{ - { - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::checkFile(): checking File " << mHash << std::endl ; -#endif - - // if we don't have a hashing thread, create one. - - if(_hash_thread == NULL) - { - // Note: using new is really important to avoid copy and write errors in the thread. - // - _hash_thread = new HashThread(mFileCreator) ; - _hash_thread->start("ft hash") ; -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::checkFile(): launched hashing thread for file " << mHash << std::endl ; -#endif - return false ; - } - - if(!_hash_thread->finished()) - { -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::checkFile(): file " << mHash << " is being hashed.?" << std::endl ; -#endif - return false ; - } - - RsFileHash check_hash( _hash_thread->hash() ) ; - - delete _hash_thread ; - _hash_thread = NULL ; - - if(check_hash == mHash) - { - mFlag = FT_TM_FLAG_COMPLETE ; // Transfer is complete. -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::checkFile(): hash finished. File verification complete ! Setting mFlag to 1" << std::endl ; -#endif - return true ; - } - } - - - forceCheck() ; - return false ; -} - -void ftTransferModule::forceCheck() -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::forceCheck(): setting flags to force check." << std::endl ; -#endif - - mFileCreator->forceCheck() ; - mFlag = FT_TM_FLAG_DOWNLOADING ; // Ask for CRC map. - mFileStatus.stat = ftFileStatus::PQIFILE_DOWNLOADING; -} - -void ftTransferModule::adjustSpeed() -{ - RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ - - std::map::iterator mit; - - - actualRate = 0; - for(mit = mFileSources.begin(); mit != mFileSources.end(); ++mit) - { -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::adjustSpeed()"; - std::cerr << "Peer: " << mit->first; - std::cerr << " Desired Rate: " << (mit->second).desiredRate; - std::cerr << " Actual Rate: " << (mit->second).actualRate; - std::cerr << std::endl; -#endif - actualRate += mit->second.actualRate; - } - -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::adjustSpeed() Totals:"; - std::cerr << "Desired Rate: " << desiredRate << " Actual Rate: " << actualRate; - std::cerr << std::endl; -#endif - - return; -} - - -/******************************************************************************* - * Actual Peer Transfer Management Code. - * - * request very tick, at rate - * - * - **/ - - -/* NOTEs on this function... - * 1) This is the critical function for deciding the rate at which ft takes place. - * 2) Some of the peers might not have the file... care must be taken avoid deadlock. - * - * Eg. A edge case which fails badly. - * Small 1K file (one chunk), with 3 sources (A,B,C). A doesn't have file. - * (a) request data from A. B & C pause cos no more data needed. - * (b) all timeout, chunk reset... then back to request again (a) and repeat. - * (c) all timeout x 5 and are disabled.... no transfer, while B&C had it all the time. - * - * To solve this we might need random waiting periods, so each peer can - * be tried. - * - * - */ - -bool ftTransferModule::locked_tickPeerTransfer(peerInfo &info) -{ - /* how long has it been? */ - rstime_t ts = time(NULL); - - int ageRecv = ts - info.recvTS; - int ageReq = ts - info.lastTS; - - /* if offline - ignore */ - if(info.state == PQIPEER_SUSPEND) - return false; - - if (ageReq > (int) (FT_TM_RESTART_DOWNLOAD * (info.nResets + 1))) - { - // The succession of ifs, makes the process continue every 6 * FT_TM_RESTART_DOWNLOAD * FT_TM_MAX_RESETS seconds - // on average, which is one attempt every 600 seconds in the least, which corresponds to once every 10 minutes in - // average. - // - if (info.nResets > 1) /* 3rd timeout */ - { - /* 90% chance of return false... - * will mean variations in which peer - * starts first. hopefully stop deadlocks. - */ - if (rand() % 12 != 0) - return false; - } - - info.state = PQIPEER_DOWNLOADING; - info.recvTS = ts; /* reset to activate */ - info.nResets = std::min(FT_TM_MAX_RESETS,info.nResets + 1); - ageRecv = 0; - } - - if (ageRecv > (int) FT_TM_DOWNLOAD_TIMEOUT) - { - info.state = PQIPEER_IDLE; - return false; - } -#ifdef FT_DEBUG - std::cerr << "locked_tickPeerTransfer() actual rate (before): " << info.actualRate << ", lastTransfers=" << info.lastTransfers << std::endl ; - std::cerr << mHash<< " - actual rate: " << info.actualRate << " lastTransfers=" << info.lastTransfers << ". AgeReq = " << ageReq << std::endl; -#endif - /* update rate */ - - if( (info.lastTransfers > 0 && ageReq > 0) || ageReq > 2) - { - info.actualRate = info.actualRate * 0.75 + 0.25 * info.lastTransfers / (float)ageReq; - info.lastTransfers = 0; - info.lastTS = ts; - } - - /**************** - * NOTE: If we continually increase the request rate thus: ... - * uint32_t next_req = info.actualRate * 1.25; - * - * then we will achieve max data rate, but we will fill up - * peers out queue and/or network buffers..... - * - * we must therefore monitor the RTT to tell us if this is happening. - */ - - /* emergency shutdown if we are stuck in x 1.25 mode - * probably not needed - */ - -// csoler: I commented this out because that tends to make some sources -// get stuck into minimal 128 B/s rate, when multiple sources are competiting into the -// same limited bandwidth. I don't think this emergency shutdown is necessary anyway. -// -// if ((info.rttActive) && (ts - info.rttStart > FT_TM_SLOW_RTT)) -// { -// if (info.mRateIncrease > 0) -// { -//#ifdef FT_DEBUG -// std::cerr << "!!! - Emergency shutdown because rttActive is true, and age is " << ts - info.rttStart << std::endl ; -//#endif -// info.mRateIncrease = 0; -// info.rttActive = false ; // I've added this to avoid being stuck when rttActive is true -// } -// } - - /* request at more than current rate */ - uint32_t next_req = info.actualRate * (1.0 + info.mRateIncrease); -#ifdef FT_DEBUG - std::cerr << "locked_tickPeerTransfer() actual rate (after): " << actualRate - << " info.desiredRate=" << info.desiredRate - << " info.actualRate=" << info.actualRate - << ", next_req=" << next_req ; - - std::cerr << std::endl; -#endif - - if (next_req > info.desiredRate * 1.1) - { - next_req = info.desiredRate * 1.1; -#ifdef FT_DEBUG - std::cerr << "locked_tickPeerTransfer() Reached MaxRate: next_req: " << next_req; - std::cerr << std::endl; -#endif - } - - - if (next_req > FT_TM_MAX_PEER_RATE) - { - next_req = FT_TM_MAX_PEER_RATE; -#ifdef FT_DEBUG - std::cerr << "locked_tickPeerTransfer() Reached AbsMaxRate: next_req: " << next_req; - std::cerr << std::endl; -#endif - } - - - if (next_req < FT_TM_MINIMUM_CHUNK) - { - next_req = FT_TM_MINIMUM_CHUNK; -#ifdef FT_DEBUG - std::cerr << "locked_tickPeerTransfer() small chunk: next_req: " << next_req; - std::cerr << std::endl; -#endif - } - -#ifdef FT_DEBUG - std::cerr << "locked_tickPeerTransfer() desired next_req: " << next_req; - std::cerr << std::endl; -#endif - - /* do request */ - uint64_t req_offset = 0; - uint32_t req_size =0 ; - - // Loop over multiple calls to the file creator: for some reasons the file creator might not be able to - // give a plain chunk of the requested size (size hint larger than the fixed chunk size, priority given to - // an old pending chunk, etc). - // - while(next_req > 0 && locked_getChunk(info.peerId,next_req,req_offset,req_size)) - if(req_size > 0) - { - info.state = PQIPEER_DOWNLOADING; - locked_requestData(info.peerId,req_offset,req_size); - - /* start next rtt measurement */ - if (!info.rttActive) - { - info.rttStart = ts; - info.rttActive = true; - info.rttOffset = req_offset + req_size; - } - next_req -= std::min(req_size,next_req) ; - } - else - { - std::cerr << "transfermodule::Waiting for available data"; - std::cerr << std::endl; - break ; - } - - return true; -} - - - - //interface to client module -bool ftTransferModule::locked_recvPeerData(peerInfo &info, uint64_t offset, uint32_t chunk_size, void *) -{ -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::locked_recvPeerData()"; - std::cerr << " peerId: " << info.peerId; - std::cerr << " rttOffset: " << info.rttOffset; - std::cerr << " lastTransfers: " << info.lastTransfers; - std::cerr << " offset: " << offset; - std::cerr << " chunksize: " << chunk_size; - std::cerr << std::endl; -#endif - - rstime_t ts = time(NULL); - info.recvTS = ts; - info.nResets = 0; - info.state = PQIPEER_DOWNLOADING; - info.lastTransfers += chunk_size; - - if ((info.rttActive) && (info.rttOffset == offset + chunk_size)) - { - /* update tip */ - int32_t rtt = time(NULL) - info.rttStart; - - /* - * FT_TM_FAST_RTT = 1 sec. mRateIncrease = 1.00 - * FT_TM_SLOW_RTT =20 sec. mRateIncrease = 0 - * 11 sec. mRateIncrease = -0.25 - * if it is slower than this allow fast data increase. - * initial guess - linear with rtt. - * change if this leads to wild oscillations - * - */ - -// info.mRateIncrease = (FT_TM_SLOW_RTT - rtt) * -// (FT_TM_MAX_INCREASE / (FT_TM_SLOW_RTT - FT_TM_FAST_RTT)); -// -// if (info.mRateIncrease > FT_TM_MAX_INCREASE) -// info.mRateIncrease = FT_TM_MAX_INCREASE; -// -// if (info.mRateIncrease < FT_TM_MIN_INCREASE) -// info.mRateIncrease = FT_TM_MIN_INCREASE; - - switch(mPriority) - { - case SPEED_LOW : info.mRateIncrease = FT_TM_RATE_INCREASE_SLOWER ; break ; - case SPEED_NORMAL : info.mRateIncrease = FT_TM_RATE_INCREASE_AVERAGE; break ; - case SPEED_HIGH : info.mRateIncrease = FT_TM_RATE_INCREASE_FASTER ; break ; - } - info.rtt = rtt; - info.rttActive = false; - -#ifdef FT_DEBUG - std::cerr << "ftTransferModule::locked_recvPeerData()"; - std::cerr << "Updated Rate based on RTT: " << rtt; - std::cerr << " Rate increase: " << 1.0+info.mRateIncrease; - std::cerr << std::endl; -#endif - - } - return true; -} - diff --git a/libretroshare/src/ft/fttransfermodule.h b/libretroshare/src/ft/fttransfermodule.h deleted file mode 100644 index 29766dbad..000000000 --- a/libretroshare/src/ft/fttransfermodule.h +++ /dev/null @@ -1,189 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: fttransfermodule.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef FT_TRANSFER_MODULE_HEADER -#define FT_TRANSFER_MODULE_HEADER - -/* - * FUNCTION DESCRIPTION - * - * Each Transfer Module is paired up with a single File Creator, and responsible for the transfer of one file. - * The Transfer Module is responsible for sending requests to peers at the correct data rates, and storing the returned data - * in a FileCreator. - * There are multiple Transfer Modules in the File Transfer system. Their requests are multiplexed through the Client Module. * The Transfer Module contains all the algorithms for sensible Data Requests. - * It must be able to cope with varying data rates and dropped peers without flooding the system with too many requests. - * - */ - -#include -#include -#include - -#include "ft/ftfilecreator.h" -#include "ft/ftdatamultiplex.h" -#include "ft/ftcontroller.h" - -#include "util/rsthreads.h" - -const uint32_t PQIPEER_INIT = 0x0000; -const uint32_t PQIPEER_NOT_ONLINE = 0x0001; -const uint32_t PQIPEER_DOWNLOADING = 0x0002; -const uint32_t PQIPEER_IDLE = 0x0004; -const uint32_t PQIPEER_SUSPEND = 0x0010; - -class HashThread ; - -class peerInfo -{ -public: - explicit peerInfo(const RsPeerId& peerId_in); - -// peerInfo(const RsPeerId& peerId_in,uint32_t state_in,uint32_t maxRate_in): -// peerId(peerId_in),state(state_in),desiredRate(maxRate_in),actualRate(0), -// lastTS(0), -// recvTS(0), lastTransfers(0), nResets(0), -// rtt(0), rttActive(false), rttStart(0), rttOffset(0), -// mRateIncrease(1) -// { -// return; -// } - RsPeerId peerId; - uint32_t state; - double desiredRate; /* speed at which the data should be requested */ - double actualRate; /* actual speed at which the data is received */ - - rstime_t lastTS; /* last Request */ - rstime_t recvTS; /* last Recv */ - uint32_t lastTransfers; /* data recvd in last second */ - uint32_t nResets; /* count to disable non-existant files */ - - uint32_t rtt; /* last rtt */ - bool rttActive; /* have we initialised an rtt measurement */ - rstime_t rttStart; /* ts of request */ - uint64_t rttOffset; /* end of request */ - float mRateIncrease; /* current rate increase factor */ -}; - -class ftFileStatus -{ -public: - enum Status { - PQIFILE_INIT, - PQIFILE_NOT_ONLINE, - PQIFILE_DOWNLOADING, - PQIFILE_COMPLETE, - PQIFILE_CHECKING, - PQIFILE_FAIL, - PQIFILE_FAIL_CANCEL, - PQIFILE_FAIL_NOT_AVAIL, - PQIFILE_FAIL_NOT_OPEN, - PQIFILE_FAIL_NOT_SEEK, - PQIFILE_FAIL_NOT_WRITE, - PQIFILE_FAIL_NOT_READ, - PQIFILE_FAIL_BAD_PATH - }; - - ftFileStatus():hash(""),stat(PQIFILE_INIT) {} - explicit ftFileStatus(const RsFileHash& hash_in):hash(hash_in),stat(PQIFILE_INIT) {} - - RsFileHash hash; - Status stat; -}; - -class ftTransferModule -{ -public: - ftTransferModule(ftFileCreator *fc, ftDataMultiplex *dm, ftController *c); - ~ftTransferModule(); - - //interface to download controller - bool setFileSources(const std::list& peerIds); - bool addFileSource(const RsPeerId& peerId); - bool removeFileSource(const RsPeerId& peerId); - bool setPeerState(const RsPeerId& peerId,uint32_t state,uint32_t maxRate); //state = ONLINE/OFFLINE - bool getFileSources(std::list &peerIds); - bool getPeerState(const RsPeerId& peerId,uint32_t &state,uint32_t &tfRate); - uint32_t getDataRate(const RsPeerId& peerId); - bool cancelTransfer(); - bool cancelFileTransferUpward(); - bool completeFileTransfer(); - bool isCheckingHash() ; - void forceCheck() ; - - //interface to multiplex module - bool recvFileData(const RsPeerId& peerId, uint64_t offset, uint32_t chunk_size, void *data); - void locked_requestData(const RsPeerId& peerId, uint64_t offset, uint32_t chunk_size); - - //interface to file creator - bool locked_getChunk(const RsPeerId& peer_id,uint32_t size_hint,uint64_t &offset, uint32_t &chunk_size); - bool locked_storeData(uint64_t offset, uint32_t chunk_size, void *data); - - int tick(); - - const RsFileHash& hash() const { return mHash; } - uint64_t size() const { return mSize; } - - //internal used functions - bool queryInactive(); - void adjustSpeed(); - - DwlSpeed downloadPriority() const { return mPriority ; } - void setDownloadPriority(DwlSpeed p) { mPriority =p ; } - - // read/reset the last time the transfer module was active (either wrote data, or was solicitaded by clients) - rstime_t lastActvTimeStamp() ; - void resetActvTimeStamp() ; - -private: - - bool locked_tickPeerTransfer(peerInfo &info); - bool locked_recvPeerData(peerInfo &info, uint64_t offset, - uint32_t chunk_size, void *data); - - bool checkFile() ; - bool checkCRC() ; - - /* These have independent Mutexes / are const locally (no Mutex protection)*/ - ftFileCreator *mFileCreator; - ftDataMultiplex *mMultiplexor; - ftController *mFtController; - - RsFileHash mHash; - uint64_t mSize; - - RsMutex tfMtx; /* below is mutex protected */ - - std::list mOnlinePeers; - std::map mFileSources; - - uint16_t mFlag; //2:file canceled, 1:transfer complete, 0: not complete, 3: checking hash, 4: checking chunks - double desiredRate; - double actualRate; - - rstime_t _last_activity_time_stamp ; - - ftFileStatus mFileStatus; //used for pause/resume file transfer - - HashThread *_hash_thread ; - DwlSpeed mPriority ; // transfer speed priority -}; - -#endif //FT_TRANSFER_MODULE_HEADER diff --git a/libretroshare/src/ft/ftturtlefiletransferitem.cc b/libretroshare/src/ft/ftturtlefiletransferitem.cc deleted file mode 100644 index 14150e42d..000000000 --- a/libretroshare/src/ft/ftturtlefiletransferitem.cc +++ /dev/null @@ -1,70 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftturtlefiletransferitem.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include -#include - -#include -#include -#include - -#include - -void RsTurtleFileMapRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,tunnel_id,"tunnel_id") ; - RsTypeSerializer::serial_process(j,ctx,direction,"direction") ; -} - -void RsTurtleFileMapItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,tunnel_id,"tunnel_id") ; - RsTypeSerializer::serial_process(j,ctx,direction,"direction") ; - RsTypeSerializer::serial_process (j,ctx,compressed_map._map,"map") ; -} -void RsTurtleChunkCrcRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,tunnel_id,"tunnel_id") ; - RsTypeSerializer::serial_process(j,ctx,chunk_number,"chunk_number") ; -} -void RsTurtleChunkCrcItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,tunnel_id,"tunnel_id") ; - RsTypeSerializer::serial_process(j,ctx,chunk_number,"chunk_number") ; - RsTypeSerializer::serial_process (j,ctx,check_sum,"check_sum") ; -} - -void RsTurtleFileRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,tunnel_id,"tunnel_id") ; - RsTypeSerializer::serial_process(j,ctx,chunk_offset,"chunk_offset") ; - RsTypeSerializer::serial_process(j,ctx,chunk_size,"chunk_size") ; -} -void RsTurtleFileDataItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,tunnel_id,"tunnel_id") ; - RsTypeSerializer::serial_process(j,ctx,chunk_offset,"chunk_offset") ; - - RsTypeSerializer::TlvMemBlock_proxy prox(chunk_data,chunk_size) ; - - RsTypeSerializer::serial_process(j,ctx,prox,"chunk_data") ; -} - diff --git a/libretroshare/src/ft/ftturtlefiletransferitem.h b/libretroshare/src/ft/ftturtlefiletransferitem.h deleted file mode 100644 index 6bbc24aef..000000000 --- a/libretroshare/src/ft/ftturtlefiletransferitem.h +++ /dev/null @@ -1,122 +0,0 @@ -/******************************************************************************* - * libretroshare/src/ft: ftturtlefiletransferitem.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include -#include - -/***********************************************************************************/ -/* Turtle File Transfer item classes */ -/***********************************************************************************/ - -class RsTurtleFileRequestItem: public RsTurtleGenericTunnelItem -{ - public: - RsTurtleFileRequestItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_REQUEST), chunk_offset(0), chunk_size(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_REQUEST);} - - virtual bool shouldStampTunnel() const { return false ; } - virtual Direction travelingDirection() const { return DIRECTION_SERVER ; } - - uint64_t chunk_offset ; - uint32_t chunk_size ; - - void clear() {} - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -class RsTurtleFileDataItem: public RsTurtleGenericTunnelItem -{ - public: - RsTurtleFileDataItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_DATA), chunk_offset(0), chunk_size(0), chunk_data(NULL) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_DATA) ;} - ~RsTurtleFileDataItem() { clear() ; } - - virtual bool shouldStampTunnel() const { return true ; } - virtual Direction travelingDirection() const { return DIRECTION_CLIENT ; } - - void clear() - { - free(chunk_data); - chunk_data = NULL ; - chunk_size = 0 ; - chunk_offset = 0 ; - } - - uint64_t chunk_offset ; // offset in the file - uint32_t chunk_size ; // size of the file chunk - void *chunk_data ; // actual data. - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -class RsTurtleFileMapRequestItem: public RsTurtleGenericTunnelItem -{ - public: - RsTurtleFileMapRequestItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_MAP_REQUEST) ;} - - virtual bool shouldStampTunnel() const { return false ; } - - void clear() {} - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -class RsTurtleFileMapItem: public RsTurtleGenericTunnelItem -{ - public: - RsTurtleFileMapItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_MAP) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_MAP) ;} - - virtual bool shouldStampTunnel() const { return false ; } - - CompressedChunkMap compressed_map ; // Map info for the file in compressed format. Each *bit* in the array uint's says "I have" or "I don't have" - // by default, we suppose the peer has all the chunks. This info will thus be and-ed - // with the default file map for this source. - - void clear() { compressed_map._map.clear() ;} - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -class RsTurtleChunkCrcRequestItem: public RsTurtleGenericTunnelItem -{ - public: - RsTurtleChunkCrcRequestItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST), chunk_number(0) { setPriorityLevel(QOS_PRIORITY_RS_CHUNK_CRC_REQUEST);} - - virtual bool shouldStampTunnel() const { return false ; } - virtual Direction travelingDirection() const { return DIRECTION_SERVER ; } - - uint32_t chunk_number ; // id of the chunk to CRC. - - void clear() {} - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -class RsTurtleChunkCrcItem: public RsTurtleGenericTunnelItem -{ - public: - RsTurtleChunkCrcItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_CHUNK_CRC), chunk_number(0) { setPriorityLevel(QOS_PRIORITY_RS_CHUNK_CRC);} - - virtual bool shouldStampTunnel() const { return true ; } - virtual Direction travelingDirection() const { return DIRECTION_CLIENT ; } - - uint32_t chunk_number ; - Sha1CheckSum check_sum ; - - void clear() { check_sum.clear() ;} - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; diff --git a/libretroshare/src/gossipdiscovery/gossipdiscoveryitems.cc b/libretroshare/src/gossipdiscovery/gossipdiscoveryitems.cc deleted file mode 100644 index 6f66684c9..000000000 --- a/libretroshare/src/gossipdiscovery/gossipdiscoveryitems.cc +++ /dev/null @@ -1,155 +0,0 @@ -/******************************************************************************* - * Gossip discovery service items * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2007-2008 Robert Fernie * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "gossipdiscovery/gossipdiscoveryitems.h" -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstypeserializer.h" -#include "serialiser/rsserializable.h" - -#include - -RsItem *RsDiscSerialiser::create_item( - uint16_t service, uint8_t item_subtype ) const -{ - if(service != RS_SERVICE_TYPE_DISC) return nullptr; - - switch(static_cast(item_subtype)) - { - case RsGossipDiscoveryItemType::PGP_LIST: return new RsDiscPgpListItem(); - case RsGossipDiscoveryItemType::PGP_CERT_BINARY: return new RsDiscPgpKeyItem(); - case RsGossipDiscoveryItemType::PGP_CERT: return new RsDiscPgpCertItem(); // deprecated, hanlde to suppress "unkown item" warning - case RsGossipDiscoveryItemType::CONTACT: return new RsDiscContactItem(); - case RsGossipDiscoveryItemType::IDENTITY_LIST: return new RsDiscIdentityListItem(); - default: - return nullptr; - } - - return nullptr; -} - -/*************************************************************************/ - -void RsDiscPgpListItem::clear() -{ - mode = RsGossipDiscoveryPgpListMode::NONE; - pgpIdSet.TlvClear(); -} - -void RsDiscPgpListItem::serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - RS_SERIAL_PROCESS(mode); - RS_SERIAL_PROCESS(pgpIdSet); -} - -void RsDiscPgpKeyItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,pgpKeyId,"pgpKeyId") ; - - RsTypeSerializer::TlvMemBlock_proxy prox(bin_data,bin_len) ; - RsTypeSerializer::serial_process(j,ctx,prox,"keyData") ; -} - -void RsDiscPgpKeyItem::clear() -{ - pgpKeyId.clear(); - free(bin_data); - bin_data = nullptr; - bin_len = 0; -} - -void RsDiscContactItem::clear() -{ - pgpId.clear(); - sslId.clear(); - - location.clear(); - version.clear(); - - netMode = 0; - vs_disc = 0; - vs_dht = 0; - lastContact = 0; - - isHidden = false; - hiddenAddr.clear(); - hiddenPort = 0; - - localAddrV4.TlvClear(); - extAddrV4.TlvClear(); - localAddrV6.TlvClear(); - extAddrV6.TlvClear(); - - - dyndns.clear(); - - localAddrList.TlvClear(); - extAddrList.TlvClear(); -} - -void RsDiscContactItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,pgpId,"pgpId"); - RsTypeSerializer::serial_process (j,ctx,sslId,"sslId"); - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_LOCATION,location,"location"); - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_VERSION,version,"version"); - RsTypeSerializer::serial_process(j,ctx,netMode,"netMode"); - RsTypeSerializer::serial_process(j,ctx,vs_disc,"vs_disc"); - RsTypeSerializer::serial_process(j,ctx,vs_dht,"vs_dht"); - RsTypeSerializer::serial_process(j,ctx,lastContact,"lastContact"); - - // This is a hack. Normally we should have to different item types, in order to avoid this nonesense. - - if(j == RsGenericSerializer::DESERIALIZE) - isHidden = ( GetTlvType( &(((uint8_t *) ctx.mData)[ctx.mOffset]) )==TLV_TYPE_STR_DOMADDR); - - if(isHidden) - { - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_DOMADDR,hiddenAddr,"hiddenAddr"); - RsTypeSerializer::serial_process(j,ctx,hiddenPort,"hiddenPort"); - } - else - { - RsTypeSerializer::serial_process(j,ctx,localAddrV4,"localAddrV4"); - RsTypeSerializer::serial_process(j,ctx, extAddrV4,"extAddrV4"); - RsTypeSerializer::serial_process(j,ctx,localAddrV6,"localAddrV6"); - RsTypeSerializer::serial_process(j,ctx, extAddrV6,"extAddrV6"); - RsTypeSerializer::serial_process(j,ctx,currentConnectAddress,"currentConnectAddress"); - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_DYNDNS,dyndns,"dyndns"); - RsTypeSerializer::serial_process (j,ctx,localAddrList,"localAddrList"); - RsTypeSerializer::serial_process (j,ctx, extAddrList,"extAddrList"); - } -} - -void RsDiscIdentityListItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RS_SERIAL_PROCESS(ownIdentityList); -} - -RsDiscItem::RsDiscItem(RsGossipDiscoveryItemType subtype) - : RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_DISC, static_cast(subtype) ) -{ -} - -RsDiscItem::~RsDiscItem() {} diff --git a/libretroshare/src/gossipdiscovery/gossipdiscoveryitems.h b/libretroshare/src/gossipdiscovery/gossipdiscoveryitems.h deleted file mode 100644 index b77074e37..000000000 --- a/libretroshare/src/gossipdiscovery/gossipdiscoveryitems.h +++ /dev/null @@ -1,196 +0,0 @@ -/******************************************************************************* - * Gossip discovery service items * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2008 Robert Fernie * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include "serialiser/rsserial.h" -#include "serialiser/rstlvidset.h" -#include "serialiser/rstlvaddrs.h" -#include "serialiser/rstlvbinary.h" -#include "rsitems/rsserviceids.h" -#include "rsitems/rsitem.h" -#include "rsitems/itempriorities.h" - -#include "serialiser/rsserializer.h" - -enum class RsGossipDiscoveryItemType : uint8_t -{ - PGP_LIST = 0x1, - PGP_CERT = 0x2, // deprecated - CONTACT = 0x5, - IDENTITY_LIST = 0x6, - PGP_CERT_BINARY = 0x9, -}; - -class RsDiscItem: public RsItem -{ -protected: - RsDiscItem(RsGossipDiscoveryItemType subtype); - -public: - RsDiscItem() = delete; - virtual ~RsDiscItem(); -}; - -/** - * This enum is underlined by uint32_t for historical reasons. - * We are conscious that uint32_t is an overkill for so few possible values but, - * changing here it at this point would break binary serialized item - * retro-compatibility. - */ -enum class RsGossipDiscoveryPgpListMode : uint32_t -{ - NONE = 0x0, - FRIENDS = 0x1, - GETCERT = 0x2 -}; - -class RsDiscPgpListItem: public RsDiscItem -{ -public: - - RsDiscPgpListItem() : RsDiscItem(RsGossipDiscoveryItemType::PGP_LIST) - { setPriorityLevel(QOS_PRIORITY_RS_DISC_PGP_LIST); } - - void clear() override; - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override; - - RsGossipDiscoveryPgpListMode mode; - RsTlvPgpIdSet pgpIdSet; -}; - -class RsDiscPgpKeyItem: public RsDiscItem -{ -public: - - RsDiscPgpKeyItem() : - RsDiscItem(RsGossipDiscoveryItemType::PGP_CERT_BINARY), - bin_data(nullptr), bin_len(0) - { setPriorityLevel(QOS_PRIORITY_RS_DISC_PGP_CERT); } - - ~RsDiscPgpKeyItem() override { free(bin_data); } - void clear() override; - - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override; - - /// duplicate information for practical reasons - RsPgpId pgpKeyId; - - unsigned char* bin_data; - uint32_t bin_len; -}; - -class RS_DEPRECATED_FOR(RsDiscPgpKeyItem) RsDiscPgpCertItem: public RsDiscItem -{ -public: - RsDiscPgpCertItem() : RsDiscItem(RsGossipDiscoveryItemType::PGP_CERT) - { setPriorityLevel(QOS_PRIORITY_RS_DISC_PGP_CERT); } - - void clear() override - { - pgpId.clear(); - pgpCert.clear(); - } - void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx) override - { - RsTypeSerializer::serial_process(j,ctx,pgpId,"pgpId") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_PGPCERT,pgpCert,"pgpCert") ; - } - - RsPgpId pgpId; - std::string pgpCert; -}; - -class RsDiscContactItem: public RsDiscItem -{ -public: - - RsDiscContactItem() : RsDiscItem(RsGossipDiscoveryItemType::CONTACT) - { setPriorityLevel(QOS_PRIORITY_RS_DISC_CONTACT); } - - void clear() override; - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override; - - RsPgpId pgpId; - RsPeerId sslId; - - // COMMON - std::string location; - std::string version; - - uint32_t netMode; /* Mandatory */ - uint16_t vs_disc; /* Mandatory */ - uint16_t vs_dht; /* Mandatory */ - uint32_t lastContact; - - bool isHidden; /* not serialised */ - - // HIDDEN. - std::string hiddenAddr; - uint16_t hiddenPort; - - // STANDARD. - - RsTlvIpAddress currentConnectAddress ; // used to check! - - RsTlvIpAddress localAddrV4; /* Mandatory */ - RsTlvIpAddress extAddrV4; /* Mandatory */ - - RsTlvIpAddress localAddrV6; /* Mandatory */ - RsTlvIpAddress extAddrV6; /* Mandatory */ - - std::string dyndns; - - RsTlvIpAddrSet localAddrList; - RsTlvIpAddrSet extAddrList; -}; - -class RsDiscIdentityListItem: public RsDiscItem -{ -public: - - RsDiscIdentityListItem() : - RsDiscItem(RsGossipDiscoveryItemType::IDENTITY_LIST) - { setPriorityLevel(QOS_PRIORITY_RS_DISC_CONTACT); } - - void clear() override { ownIdentityList.clear(); } - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override; - - std::list ownIdentityList; -}; - -class RsDiscSerialiser: public RsServiceSerializer -{ -public: - RsDiscSerialiser() :RsServiceSerializer(RS_SERVICE_TYPE_DISC) {} - virtual ~RsDiscSerialiser() {} - - RsItem* create_item(uint16_t service, uint8_t item_subtype) const; -}; diff --git a/libretroshare/src/gossipdiscovery/p3gossipdiscovery.cc b/libretroshare/src/gossipdiscovery/p3gossipdiscovery.cc deleted file mode 100644 index 948fa3ccc..000000000 --- a/libretroshare/src/gossipdiscovery/p3gossipdiscovery.cc +++ /dev/null @@ -1,1366 +0,0 @@ -/******************************************************************************* - * RetroShare gossip discovery service implementation * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2013 Robert Fernie * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "gossipdiscovery/p3gossipdiscovery.h" -#include "pqi/p3peermgr.h" -#include "retroshare/rsversion.h" -#include "retroshare/rsiface.h" -#include "rsserver/p3face.h" -#include "util/rsdebug.h" -#include "retroshare/rspeers.h" - -/**** - * #define P3DISC_DEBUG 1 - ****/ - -/*extern*/ std::shared_ptr rsGossipDiscovery(nullptr); - -static bool populateContactInfo( const peerState &detail, - RsDiscContactItem *pkt, - bool include_ip_information ) -{ - pkt->clear(); - - pkt->pgpId = detail.gpg_id; - pkt->sslId = detail.id; - pkt->location = detail.location; - pkt->version = ""; - pkt->netMode = detail.netMode; - pkt->vs_disc = detail.vs_disc; - pkt->vs_dht = detail.vs_dht; - - pkt->lastContact = time(nullptr); - - if (detail.hiddenNode) - { - pkt->isHidden = true; - pkt->hiddenAddr = detail.hiddenDomain; - pkt->hiddenPort = detail.hiddenPort; - } - else - { - pkt->isHidden = false; - - if(include_ip_information) - { - pkt->localAddrV4.addr = detail.localaddr; - pkt->extAddrV4.addr = detail.serveraddr; - sockaddr_storage_clear(pkt->localAddrV6.addr); - sockaddr_storage_clear(pkt->extAddrV6.addr); - - pkt->dyndns = detail.dyndns; - detail.ipAddrs.mLocal.loadTlv(pkt->localAddrList); - detail.ipAddrs.mExt.loadTlv(pkt->extAddrList); - } - else - { - sockaddr_storage_clear(pkt->localAddrV6.addr); - sockaddr_storage_clear(pkt->extAddrV6.addr); - sockaddr_storage_clear(pkt->localAddrV4.addr); - sockaddr_storage_clear(pkt->extAddrV4.addr); - } - } - - return true; -} - -void DiscPgpInfo::mergeFriendList(const std::set &friends) -{ - std::set::const_iterator it; - for(it = friends.begin(); it != friends.end(); ++it) - { - mFriendSet.insert(*it); - } -} - - -p3discovery2::p3discovery2( - p3PeerMgr* peerMgr, p3LinkMgr* linkMgr, p3NetMgr* netMgr, - p3ServiceControl* sc, RsGixs* gixs ) : - p3Service(), mRsEventsHandle(0), mPeerMgr(peerMgr), mLinkMgr(linkMgr), - mNetMgr(netMgr), mServiceCtrl(sc), mGixs(gixs), mDiscMtx("p3discovery2"), - mLastPgpUpdate(0) -{ - Dbg3() << __PRETTY_FUNCTION__ << std::endl; - - RS_STACK_MUTEX(mDiscMtx); - addSerialType(new RsDiscSerialiser()); - - // Add self into PGP FriendList. - mFriendList[AuthPGP::getPgpOwnId()] = DiscPgpInfo(); -} - - -const std::string DISCOVERY_APP_NAME = "disc"; -const uint16_t DISCOVERY_APP_MAJOR_VERSION = 1; -const uint16_t DISCOVERY_APP_MINOR_VERSION = 0; -const uint16_t DISCOVERY_MIN_MAJOR_VERSION = 1; -const uint16_t DISCOVERY_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3discovery2::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_DISC, - DISCOVERY_APP_NAME, - DISCOVERY_APP_MAJOR_VERSION, - DISCOVERY_APP_MINOR_VERSION, - DISCOVERY_MIN_MAJOR_VERSION, - DISCOVERY_MIN_MINOR_VERSION); -} - -p3discovery2::~p3discovery2() -{ rsEvents->unregisterEventsHandler(mRsEventsHandle); } - -void p3discovery2::addFriend(const RsPeerId &sslId) -{ - RsPgpId pgpId = getPGPId(sslId); - - RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it; - it = mFriendList.find(pgpId); - if (it == mFriendList.end()) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::addFriend() adding pgp entry: " << pgpId; - std::cerr << std::endl; -#endif - - mFriendList[pgpId] = DiscPgpInfo(); - - it = mFriendList.find(pgpId); - } - - - /* now add RsPeerId */ - - std::map::iterator sit; - sit = it->second.mSslIds.find(sslId); - if (sit == it->second.mSslIds.end()) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::addFriend() adding ssl entry: " << sslId; - std::cerr << std::endl; -#endif - - it->second.mSslIds[sslId] = DiscSslInfo(); - sit = it->second.mSslIds.find(sslId); - } - - /* update Settings from peerMgr */ - peerState detail; - if (mPeerMgr->getFriendNetStatus(sit->first, detail)) - { - sit->second.mDiscStatus = detail.vs_disc; - } - else - { - sit->second.mDiscStatus = RS_VS_DISC_OFF; - } -} - -void p3discovery2::removeFriend(const RsPeerId &sslId) -{ - RsPgpId pgpId = getPGPId(sslId); - - RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it; - it = mFriendList.find(pgpId); - if (it == mFriendList.end()) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::removeFriend() missing pgp entry: " << pgpId; - std::cerr << std::endl; -#endif - return; - } - - std::map::iterator sit; - sit = it->second.mSslIds.find(sslId); - if (sit == it->second.mSslIds.end()) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::addFriend() missing ssl entry: " << sslId; - std::cerr << std::endl; -#endif - return; - } - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::addFriend() removing ssl entry: " << sslId; - std::cerr << std::endl; -#endif - it->second.mSslIds.erase(sit); - - if (it->second.mSslIds.empty()) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::addFriend() pgpId now has no sslIds"; - std::cerr << std::endl; -#endif - /* pgp peer without any ssl entries -> check if they are still a real friend */ - if (!(AuthPGP::isPGPAccepted(pgpId))) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::addFriend() pgpId is no longer a friend, removing"; - std::cerr << std::endl; -#endif - mFriendList.erase(it); - } - } -} - -RsPgpId p3discovery2::getPGPId(const RsPeerId &id) -{ - RsPgpId pgpId; - mPeerMgr->getGpgId(id, pgpId); - return pgpId; -} - -int p3discovery2::tick() -{ - return handleIncoming(); -} - -int p3discovery2::handleIncoming() -{ - RsItem* item = nullptr; - - int nhandled = 0; - // While messages read - while(nullptr != (item = recvItem())) - { - RsDiscPgpListItem* pgplist = nullptr; - RsDiscPgpKeyItem* pgpkey = nullptr; - RsDiscPgpCertItem* pgpcert = nullptr; // deprecated, hanlde for retro compability - RsDiscContactItem* contact = nullptr; - RsDiscIdentityListItem* gxsidlst = nullptr; - - ++nhandled; - - Dbg4() << __PRETTY_FUNCTION__ << " Received item: " << *item << std::endl; - - if((contact = dynamic_cast(item)) != nullptr) - { - if (item->PeerId() == contact->sslId) - recvOwnContactInfo(item->PeerId(), contact); - else - processContactInfo(item->PeerId(), contact); - } - else if( (gxsidlst = dynamic_cast(item)) != nullptr ) - recvIdentityList(item->PeerId(),gxsidlst->ownIdentityList); - else if((pgpkey = dynamic_cast(item)) != nullptr) - recvPGPCertificate(item->PeerId(), pgpkey); - else if((pgpcert = dynamic_cast(item)) != nullptr) - RsWarn() << "Received a deprecated RsDiscPgpCertItem. Will not be handled." << std::endl; // nothing to do. - else if((pgplist = dynamic_cast(item)) != nullptr) - { - if (pgplist->mode == RsGossipDiscoveryPgpListMode::FRIENDS) - processPGPList(pgplist->PeerId(), pgplist); - else if (pgplist->mode == RsGossipDiscoveryPgpListMode::GETCERT) - recvPGPCertificateRequest(pgplist->PeerId(), pgplist); - } - else - { - RsWarn() << __PRETTY_FUNCTION__ << " Received unknown item type " << (int)item->PacketSubType() << "! " << std::endl ; - RsWarn() << item << std::endl; - } - - delete item; - } - - return nhandled; -} - -void p3discovery2::sendOwnContactInfo(const RsPeerId &sslid) -{ - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::sendOwnContactInfo()"; - std::cerr << std::endl; -#endif - peerState detail; - if (mPeerMgr->getOwnNetStatus(detail)) - { - RsDiscContactItem *pkt = new RsDiscContactItem(); - - /* Cyril: we dont send our own IP to an hidden node. It will not use it - * anyway. Furthermore, a Tor node is not supposed to have any mean to send the IPs of his friend nodes - * to other nodes. This would be a very serious security risk. */ - - populateContactInfo(detail, pkt, !rsPeers->isHiddenNode(sslid)); - - /* G10h4ck: sending IP information also to hidden nodes has proven very - * helpful in the usecase of non hidden nodes, that share a common - * hidden trusted node, to discover each other IP. - * Advanced/corner case non hidden node users that want to hide their - * IP to a specific hidden ~trusted~ node can do it through the - * permission matrix. Disabling this instead will make life more - * difficult for average user, that moreover whould have no way to - * revert an hardcoded policy. */ - - pkt->version = RS_HUMAN_READABLE_VERSION; - pkt->PeerId(sslid); - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::sendOwnContactInfo() sending:" << std::endl; - pkt -> print(std::cerr); - std::cerr << std::endl; -#endif - sendItem(pkt); - - RsDiscIdentityListItem *pkt2 = new RsDiscIdentityListItem(); - - rsIdentity->getOwnIds(pkt2->ownIdentityList,true); - pkt2->PeerId(sslid) ; - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::sendOwnContactInfo() sending own signed identity list:" << std::endl; - for(auto it(pkt2->ownIdentityList.begin());it!=pkt2->ownIdentityList.end();++it) - std::cerr << " identity: " << (*it).toStdString() << std::endl; -#endif - sendItem(pkt2); - } -} - -void p3discovery2::recvOwnContactInfo(const RsPeerId &fromId, const RsDiscContactItem *item) -{ -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::recvOwnContactInfo()"; - std::cerr << std::endl; - - std::cerr << "Info sent by the peer itself -> updating self info:" << std::endl; - std::cerr << " -> vs_disc : " << item->vs_disc << std::endl; - std::cerr << " -> vs_dht : " << item->vs_dht << std::endl; - std::cerr << " -> network mode : " << item->netMode << std::endl; - std::cerr << " -> location : " << item->location << std::endl; - std::cerr << std::endl; -#endif - // Check that the "own" ID sent corresponds to the one we think it should be. - // Some of these checks may look superfluous but it's better to risk to check twice than not check at all. - - // was obtained using a short invite. , and that the friend is marked as "ignore PGP validation" because it - RsPeerDetails det ; - if(!rsPeers->getPeerDetails(fromId,det)) - { - RsErr() << "(EE) Cannot obtain details from " << fromId << " who is supposed to be a friend! Dropping the info." << std::endl; - return; - } - if(det.gpg_id != item->pgpId) - { - RsErr() << "(EE) peer " << fromId << " sent own details with PGP key ID " << item->pgpId << " which does not match the known key id " << det.gpg_id << ". Dropping the info." << std::endl; - return; - } - - // Peer Own Info replaces the existing info, because the - // peer is the primary source of his own IPs, except for hidden nodes - // that normally send nothing. We still ignore it as a double security. - - mPeerMgr->setNetworkMode(fromId, item->netMode); - mPeerMgr->setLocation(fromId, item->location); - mPeerMgr->setVisState(fromId, item->vs_disc, item->vs_dht); - - if(!mPeerMgr->isHiddenNode(fromId)) - { - if(!det.localAddr.empty()) - { - if(sockaddr_storage_isValidNet(item->localAddrV4.addr)) - mPeerMgr->setLocalAddress(fromId,item->localAddrV4.addr); - else if(sockaddr_storage_isValidNet(item->localAddrV6.addr)) - mPeerMgr->setLocalAddress(fromId,item->localAddrV6.addr); - } - - if(!det.extAddr.empty()) - { - if(sockaddr_storage_isValidNet(item->extAddrV4.addr)) - mPeerMgr->setExtAddress(fromId,item->extAddrV4.addr); - else if(sockaddr_storage_isValidNet(item->extAddrV6.addr)) - mPeerMgr->setExtAddress(fromId,item->extAddrV6.addr); - } - } - - setPeerVersion(fromId, item->version); - - // Hidden nodes do not need IP information. So that information is dropped. - // However, that doesn't mean hidden nodes do not know that information. Normally - // normal nodes should not send it, but old nodes still do. - - if(!mPeerMgr->isHiddenNode(rsPeers->getOwnId())) - updatePeerAddresses(item); - - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mGossipDiscoveryEventType = RsGossipDiscoveryEventType::FRIEND_PEER_INFO_RECEIVED; - ev->mFromId = fromId; - ev->mAboutId = item->sslId; - rsEvents->postEvent(ev); - } - - // if the peer is not validated, we stop the exchange here - - if(det.skip_pgp_signature_validation) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::recvOwnContactInfo() missing PGP key " << item->pgpId << " from short invite friend " << fromId << ". Requesting it." << std::endl; -#endif - requestPGPCertificate(det.gpg_id, fromId); - return; - } - - // This information will be sent out to online peers, at the receipt of their PGPList. - // It is important that PGPList is received after the OwnContactItem. - // This should happen, but is not enforced by the protocol. - - // Start peer list exchange, if discovery is enabled - - peerState ps; - mPeerMgr->getOwnNetStatus(ps); - - if(ps.vs_disc != RS_VS_DISC_OFF) - sendPGPList(fromId); - - // Update mDiscStatus. - RS_STACK_MUTEX(mDiscMtx); - - RsPgpId pgpId = getPGPId(fromId); - std::map::iterator it = mFriendList.find(pgpId); - if (it != mFriendList.end()) - { - std::map::iterator sit = it->second.mSslIds.find(fromId); - if (sit != it->second.mSslIds.end()) - { - sit->second.mDiscStatus = item->vs_disc; -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::recvOwnContactInfo()"; - std::cerr << "updating mDiscStatus to: " << sit->second.mDiscStatus; - std::cerr << std::endl; -#endif - } - else - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::recvOwnContactInfo()"; - std::cerr << " ERROR missing SSL Entry: " << fromId; - std::cerr << std::endl; -#endif - } - } -} - -void p3discovery2::recvIdentityList(const RsPeerId& pid,const std::list& ids) -{ - std::list peers; - peers.push_back(pid); - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::recvIdentityList(): from peer " << pid << ": " << ids.size() << " identities" << std::endl; -#endif - - RsIdentityUsage use_info(RsServiceType::GOSSIP_DISCOVERY,RsIdentityUsage::IDENTITY_NEW_FROM_DISCOVERY); - - for(auto it(ids.begin());it!=ids.end();++it) - { -#ifdef P3DISC_DEBUG - std::cerr << " identity: " << (*it).toStdString() << std::endl; -#endif - mGixs->requestKey(*it,peers,use_info) ; - } -} - -void p3discovery2::updatePeerAddresses(const RsDiscContactItem *item) -{ - if (item->isHidden) - mPeerMgr->setHiddenDomainPort(item->sslId, item->hiddenAddr, - item->hiddenPort); - else - { - mPeerMgr->setDynDNS(item->sslId, item->dyndns); - updatePeerAddressList(item); - } -} - -void p3discovery2::updatePeerAddressList(const RsDiscContactItem *item) -{ - if (item->isHidden) - { - } - else if(!mPeerMgr->isHiddenNode(rsPeers->getOwnId())) - { - /* Cyril: we don't store IP addresses if we're a hidden node. - * Normally they should not be sent to us, except for old peers. */ - /* G10h4ck: sending IP information also to hidden nodes has proven very - * helpful in the usecase of non hidden nodes, that share a common - * hidden trusted node, to discover each other IP. - * Advanced/corner case non hidden node users that want to hide their - * IP to a specific hidden ~trusted~ node can do it through the - * permission matrix. Disabling this instead will make life more - * difficult for average user, that moreover whould have no way to - * revert an hardcoded policy. */ - pqiIpAddrSet addrsFromPeer; - addrsFromPeer.mLocal.extractFromTlv(item->localAddrList); - addrsFromPeer.mExt.extractFromTlv(item->extAddrList); - -#ifdef P3DISC_DEBUG - std::cerr << "Setting address list to peer " << item->sslId - << ", to be:" << std::endl ; - - std::string addrstr; - addrsFromPeer.printAddrs(addrstr); - std::cerr << addrstr; - std::cerr << std::endl; -#endif - mPeerMgr->updateAddressList(item->sslId, addrsFromPeer); - } -} - -// Starts the Discovery process. -// should only be called it DISC2_STATUS_NOT_HIDDEN(OwnInfo.status). -void p3discovery2::sendPGPList(const RsPeerId &toId) -{ - updatePgpFriendList(); - - RS_STACK_MUTEX(mDiscMtx); - - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::sendPGPList() to " << toId << std::endl; -#endif - - RsDiscPgpListItem *pkt = new RsDiscPgpListItem(); - - pkt->mode = RsGossipDiscoveryPgpListMode::FRIENDS; - - for(auto it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - // Check every friend, and only send his PGP key if the friend tells that he wants discovery. Because this action over profiles depends on a node information, - // we check each node of a given progile and only send the profile key if at least one node allows it. - - for(auto it2(it->second.mSslIds.begin());it2!=it->second.mSslIds.end();++it2) - if(it2->second.mDiscStatus != RS_VS_DISC_OFF) - { - pkt->pgpIdSet.ids.insert(it->first); - break; - } - } - - pkt->PeerId(toId); - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::sendPGPList() sending:" << std::endl; - pkt->print(std::cerr); - std::cerr << std::endl; -#endif - - sendItem(pkt); -} - -void p3discovery2::updatePgpFriendList() -{ -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::updatePgpFriendList()"; - std::cerr << std::endl; -#endif - - RS_STACK_MUTEX(mDiscMtx); - -#define PGP_MAX_UPDATE_PERIOD 300 - - if (time(NULL) < mLastPgpUpdate + PGP_MAX_UPDATE_PERIOD ) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::updatePgpFriendList() Already uptodate"; - std::cerr << std::endl; -#endif - return; - } - - mLastPgpUpdate = time(NULL); - - std::list pgpList; - std::set pgpSet; - - std::set::iterator sit; - std::list::iterator lit; - std::map::iterator it; - - RsPgpId ownPgpId = AuthPGP::getPgpOwnId(); - AuthPGP::getPgpAcceptedList(pgpList); - pgpList.push_back(ownPgpId); - - // convert to set for ordering. - for(lit = pgpList.begin(); lit != pgpList.end(); ++lit) - { - pgpSet.insert(*lit); - } - - std::list pgpToAdd; - std::list pgpToRemove; - - - sit = pgpSet.begin(); - it = mFriendList.begin(); - while (sit != pgpSet.end() && it != mFriendList.end()) - { - if (*sit < it->first) - { - /* to add */ - pgpToAdd.push_back(*sit); - ++sit; - } - else if (it->first < *sit) - { - /* to remove */ - pgpToRemove.push_back(it->first); - ++it; - } - else - { - /* same - okay */ - ++sit; - ++it; - } - } - - /* more to add? */ - for(; sit != pgpSet.end(); ++sit) - { - pgpToAdd.push_back(*sit); - } - - for(; it != mFriendList.end(); ++it) - { - /* more to remove */ - pgpToRemove.push_back(it->first); - } - - for(lit = pgpToRemove.begin(); lit != pgpToRemove.end(); ++lit) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::updatePgpFriendList() Removing pgpId: " << *lit; - std::cerr << std::endl; -#endif - - it = mFriendList.find(*lit); - mFriendList.erase(it); - } - - for(lit = pgpToAdd.begin(); lit != pgpToAdd.end(); ++lit) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::updatePgpFriendList() Adding pgpId: " << *lit; - std::cerr << std::endl; -#endif - - mFriendList[*lit] = DiscPgpInfo(); - } - - /* finally install the pgpList on our own entry */ - DiscPgpInfo &ownInfo = mFriendList[ownPgpId]; - ownInfo.mergeFriendList(pgpSet); - -} - -void p3discovery2::processPGPList(const RsPeerId &fromId, const RsDiscPgpListItem *item) -{ - RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::processPGPList() from " << fromId; - std::cerr << std::endl; -#endif - - RsPgpId fromPgpId = getPGPId(fromId); - auto it = mFriendList.find(fromPgpId); - if (it == mFriendList.end()) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::processPGPList() is not friend: " << fromId; - std::cerr << std::endl; -#endif - - // cleanup. - return; - } - - bool requestUnknownPgpCerts = true; - peerState pstate; - mPeerMgr->getOwnNetStatus(pstate); - if (pstate.vs_disc != RS_VS_DISC_FULL) - requestUnknownPgpCerts = false; - - uint32_t linkType = mLinkMgr->getLinkType(fromId); - if ((linkType & RS_NET_CONN_SPEED_TRICKLE) || - (linkType & RS_NET_CONN_SPEED_LOW)) - { - std::cerr << "p3discovery2::processPGPList() Not requesting Certificates from: " << fromId; - std::cerr << " (low bandwidth)" << std::endl; - requestUnknownPgpCerts = false; - } - - if (requestUnknownPgpCerts) - { - std::set::const_iterator fit; - for(fit = item->pgpIdSet.ids.begin(); fit != item->pgpIdSet.ids.end(); ++fit) - { - if (!AuthPGP::isPGPId(*fit)) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::processPGPList() requesting certificate for PgpId: " << *fit; - std::cerr << " from SslId: " << fromId; - std::cerr << std::endl; -#endif - requestPGPCertificate(*fit, fromId); - } - } - } - - it->second.mergeFriendList(item->pgpIdSet.ids); - updatePeers_locked(fromId); -} - - -/* - * -> Update Other Peers about B. - * -> Update B about Other Peers. - */ -void p3discovery2::updatePeers_locked(const RsPeerId &aboutId) -{ - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::updatePeers_locked() about " << aboutId; - std::cerr << std::endl; -#endif - - RsPgpId aboutPgpId = getPGPId(aboutId); - - auto ait = mFriendList.find(aboutPgpId); - if (ait == mFriendList.end()) - { - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::updatePeers_locked() PgpId is not a friend: " << aboutPgpId; - std::cerr << std::endl; -#endif - return; - } - - std::set mutualFriends; - std::set onlineFriends; - - const std::set &friendSet = ait->second.mFriendSet; - - for(auto fit = friendSet.begin(); fit != friendSet.end(); ++fit) - { - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::updatePeer_locked() checking their friend: " << *fit; - std::cerr << std::endl; -#endif - - auto ffit = mFriendList.find(*fit); - - if (ffit == mFriendList.end()) - { - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::updatePeer_locked() Ignoring not our friend"; - std::cerr << std::endl; -#endif - // Not our friend, or we have no Locations (SSL) for this RsPgpId (same difference) - continue; - } - - if (ffit->second.mFriendSet.find(aboutPgpId) != ffit->second.mFriendSet.end()) - { - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::updatePeer_locked() Adding as Mutual Friend"; - std::cerr << std::endl; -#endif - mutualFriends.insert(*fit); - - for(auto mit = ffit->second.mSslIds.begin(); mit != ffit->second.mSslIds.end(); ++mit) - { - RsPeerId sslid = mit->first; - if (mServiceCtrl->isPeerConnected(getServiceInfo().mServiceType, sslid)) - { - // TODO IGNORE if sslid == aboutId, or sslid == ownId. -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::updatePeer_locked() Adding Online RsPeerId: " << sslid; - std::cerr << std::endl; -#endif - onlineFriends.insert(sslid); - } - } - } - } - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::updatePeer_locked() Updating " << aboutId << " about Mutual Friends"; - std::cerr << std::endl; -#endif - // update aboutId about Other Peers. - for(auto fit = mutualFriends.begin(); fit != mutualFriends.end(); ++fit) - sendContactInfo_locked(*fit, aboutId); - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::updatePeer_locked() Updating Online Peers about " << aboutId; - std::cerr << std::endl; -#endif - // update Other Peers about aboutPgpId. - for(auto sit = onlineFriends.begin(); sit != onlineFriends.end(); ++sit) - { - // This could be more efficient, and only be specific about aboutId. - // but we'll leave it like this for the moment. - sendContactInfo_locked(aboutPgpId, *sit); - } -} - -void p3discovery2::sendContactInfo_locked(const RsPgpId &aboutId, const RsPeerId &toId) -{ -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::sendContactInfo_locked() aboutPGPId: " << aboutId << " toId: " << toId; - std::cerr << std::endl; -#endif - std::map::const_iterator it; - it = mFriendList.find(aboutId); - if (it == mFriendList.end()) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::sendContactInfo_locked() ERROR aboutId is not a friend"; - std::cerr << std::endl; -#endif - return; - } - - std::map::const_iterator sit; - for(sit = it->second.mSslIds.begin(); sit != it->second.mSslIds.end(); ++sit) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::sendContactInfo_locked() related sslId: " << sit->first; - std::cerr << std::endl; -#endif - - if (sit->first == rsPeers->getOwnId()) - { - // sending info of toId to himself will be used by toId to check that the IP it is connected as is the same - // as its external IP. -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::processContactInfo() not sending info on self"; - std::cerr << std::endl; -#endif - continue; - } - - if (sit->second.mDiscStatus != RS_VS_DISC_OFF) - { - peerState detail; - peerConnectState detail2; - - if (mPeerMgr->getFriendNetStatus(sit->first, detail)) - { - RsDiscContactItem *pkt = new RsDiscContactItem(); - populateContactInfo(detail, pkt,!mPeerMgr->isHiddenNode(toId));// never send IPs to an hidden node. The node will not use them anyway. - pkt->PeerId(toId); - - // send to each peer its own connection address. - - if(sit->first == toId && mLinkMgr->getFriendNetStatus(sit->first,detail2)) - pkt->currentConnectAddress.addr = detail2.connectaddr; - else - sockaddr_storage_clear(pkt->currentConnectAddress.addr) ; - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::sendContactInfo_locked() Sending"; - std::cerr << std::endl; - pkt->print(std::cerr); - std::cerr << std::endl; -#endif - sendItem(pkt); - } - else - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::sendContactInfo_locked() No Net Status"; - std::cerr << std::endl; -#endif - } - } - else - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::sendContactInfo_locked() RsPeerId Hidden"; - std::cerr << std::endl; -#endif - } - } -} - -void p3discovery2::processContactInfo(const RsPeerId &fromId, const RsDiscContactItem *item) -{ - (void) fromId; // remove unused parameter warnings, debug only - - RS_STACK_MUTEX(mDiscMtx); - - // This case is the node fromId sending information about ourselves to us. There's one good use of this: - // read the IP information the friend knows about us, and use it to extimate our external address. - - if (item->sslId == rsPeers->getOwnId()) - { - if(sockaddr_storage_isExternalNet(item->currentConnectAddress.addr)) - mPeerMgr->addCandidateForOwnExternalAddress(item->PeerId(), item->currentConnectAddress.addr); - - return; - } - - auto it = mFriendList.find(item->pgpId); // is this the PGP id one of our friends? - - if (it == mFriendList.end()) // no it's not. - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::processContactInfo(" << fromId << ") RsPgpId: "; - std::cerr << item->pgpId << " Not Friend."; - std::cerr << std::endl; - std::cerr << "p3discovery2::processContactInfo(" << fromId << ") THIS SHOULD NEVER HAPPEN!"; - std::cerr << std::endl; -#endif - - /* THESE ARE OUR FRIEND OF FRIENDS ... pass this information along to - * NetMgr & DHT... - * as we can track FOF and use them as potential Proxies / Relays - */ - - if (!item->isHidden) - { - /* add into NetMgr and non-search, so we can detect connect attempts */ - mNetMgr->netAssistFriend(item->sslId,false); - - /* inform NetMgr that we know this peer */ - mNetMgr->netAssistKnownPeer(item->sslId, item->extAddrV4.addr, NETASSIST_KNOWN_PEER_FOF | NETASSIST_KNOWN_PEER_OFFLINE); - } - return; - } - - // The peer the discovery info is about is a friend. We gather the nodes for that profile into the local structure and notify p3peerMgr. - - if(!rsPeers->isGPGAccepted(item->pgpId)) // this is an additional check, because the friendship previously depends on the local cache. We need - return ; // fresh information here. - - bool should_notify_discovery = false; - - DiscSslInfo& sslInfo(it->second.mSslIds[item->sslId]); // This line inserts the entry while not removing already existing data - // do not remove it! - if (!mPeerMgr->isFriend(item->sslId)) - { - should_notify_discovery = true; - - // Add with no disc by default. If friend already exists, it will do nothing - // NO DISC is important - otherwise, we'll just enter a nasty loop, - // where every addition triggers requests, then they are cleaned up, and readded... - - // This way we get their addresses, but don't advertise them until we get a - // connection. -#ifdef P3DISC_DEBUG - std::cerr << "--> Adding to friends list " << item->sslId << " - " << item->pgpId << std::endl; -#endif - // We pass RS_NODE_PERM_ALL because the PGP id is already a friend, so we should keep the existing - // permission flags. Therefore the mask needs to be 0xffff. - - // set last seen to RS_PEER_OFFLINE_NO_DISC minus 1 so that it won't be shared with other friends - // until a first connection is established - - // This code is a bit dangerous: we add a friend without the insurance that the PGP key that will validate this friend actually has - // the supplied PGP id. Of course, because it comes from a friend, we should trust that friend. Anyway, it is important that - // when connecting the handshake is always doen w.r.t. the known PGP key, and not the one that is indicated in the certificate issuer field. - - mPeerMgr->addFriend( item->sslId, item->pgpId, item->netMode, - RS_VS_DISC_OFF, RS_VS_DHT_FULL, - time(NULL) - RS_PEER_OFFLINE_NO_DISC - 1, - RS_NODE_PERM_ALL ); - - updatePeerAddresses(item); - } - updatePeerAddressList(item); - - RsServer::notify()->notifyListChange(NOTIFY_LIST_NEIGHBOURS, NOTIFY_TYPE_MOD); - - if(should_notify_discovery) - { - RsServer::notify()->notifyDiscInfoChanged(); - - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mGossipDiscoveryEventType = RsGossipDiscoveryEventType::FRIEND_PEER_INFO_RECEIVED; - ev->mFromId = fromId; - ev->mAboutId = item->sslId; - rsEvents->postEvent(ev); - } - } -} - -/* we explictly request certificates, instead of getting them all the time - */ -void p3discovery2::requestPGPCertificate(const RsPgpId &aboutId, const RsPeerId &toId) -{ -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::requestPGPCertificate() aboutId: " << aboutId << " to: " << toId; - std::cerr << std::endl; -#endif - - RsDiscPgpListItem *pkt = new RsDiscPgpListItem(); - - pkt->mode = RsGossipDiscoveryPgpListMode::GETCERT; - pkt->pgpIdSet.ids.insert(aboutId); - pkt->PeerId(toId); - -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::requestPGPCertificate() sending:" << std::endl; - pkt->print(std::cerr); - std::cerr << std::endl; -#endif - - sendItem(pkt); -} - -void p3discovery2::recvPGPCertificateRequest( const RsPeerId& fromId, const RsDiscPgpListItem* item ) -{ -#ifdef P3DISC_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " from " << fromId << std::endl; -#endif - peerState ps; - mPeerMgr->getOwnNetStatus(ps); - - if(ps.vs_disc == RS_VS_DISC_OFF) - { - std::cerr << "(WW) refusing PGP certificate request from " << fromId << " because discovery is OFF" << std::endl; - return; - } - - RsPgpId ownPgpId = AuthPGP::getPgpOwnId(); - for(const RsPgpId& pgpId : item->pgpIdSet.ids) - if (pgpId == ownPgpId) - sendPGPCertificate(pgpId, fromId); - else if(ps.vs_disc != RS_VS_DISC_OFF && AuthPGP::isPGPAccepted(pgpId)) - sendPGPCertificate(pgpId, fromId); - else - std::cerr << "(WW) not sending certificate " << pgpId << " asked by friend " << fromId << " because this either this cert is not a friend, or discovery is off" << std::endl; -} - - -void p3discovery2::sendPGPCertificate(const RsPgpId &aboutId, const RsPeerId &toId) -{ - RsDiscPgpKeyItem *pgp_key_item = new RsDiscPgpKeyItem; - - pgp_key_item->PeerId(toId); - pgp_key_item->pgpKeyId = aboutId; - unsigned char *bin_data; - size_t bin_len; - - if(!AuthPGP::exportPublicKey(aboutId,bin_data,bin_len,false,true)) - { - std::cerr << "(EE) cannot export public key " << aboutId << " requested by peer " << toId << std::endl; - return ; - } - - pgp_key_item->bin_data = bin_data; - pgp_key_item->bin_len = bin_len; - - sendItem(pgp_key_item); -} - -void p3discovery2::recvPGPCertificate(const RsPeerId& fromId, RsDiscPgpKeyItem* item ) -{ - // 1 - check that the cert structure is valid. - - RsPgpId cert_pgp_id; - std::string cert_name; - std::list cert_signers; - - if(!AuthPGP::getPgpDetailsFromBinaryBlock( (unsigned char*)item->bin_data,item->bin_len, cert_pgp_id, cert_name, cert_signers )) - { - std::cerr << "(EE) cannot parse own PGP key sent by " << fromId << std::endl; - return; - } - - if(cert_pgp_id != item->pgpKeyId) - { - std::cerr << "(EE) received a PGP key from " << fromId << " which ID (" << cert_pgp_id << ") is different from the one anounced in the packet (" << item->pgpKeyId << ")!" << std::endl; - return; - } - - // 2 - check if the peer who is sending us a cert is already validated - - RsPeerDetails det; - if(!rsPeers->getPeerDetails(fromId,det)) - { - std::cerr << "(EE) cannot get peer details from friend " << fromId << ": this is very wrong!"<< std::endl; - return; - } - - // We treat own pgp keys right away when they are sent by a friend for which we dont have it. This way we can keep the skip_pgg_signature_validation consistent - - if(det.skip_pgp_signature_validation) - { -#ifdef P3DISC_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " Received own full certificate from short-invite friend " << fromId << std::endl; -#endif - // do some extra checks. Dont remove them. They cost nothing as compared to what they could avoid. - - if(item->pgpKeyId != det.gpg_id) - { - std::cerr << "(EE) received a PGP key with ID " << item->pgpKeyId << " from non validated peer " << fromId << ", which should only be allowed to send his own key " << det.gpg_id << std::endl; - return; - } - } - RsPgpId tmp_pgp_id; - std::string error_string; - -#ifdef P3DISC_DEBUG - std::cerr << __PRETTY_FUNCTION__ << "Received PGP key " << cert_pgp_id << " from from friend " << fromId << ". Adding to keyring." << std::endl; -#endif - // now that will add the key *and* set the skip_signature_validation flag at once - rsPeers->loadPgpKeyFromBinaryData((unsigned char*)item->bin_data,item->bin_len, tmp_pgp_id,error_string); // no error should occur at this point because we called loadDetailsFromStringCert() already - - // Make sure we allow connections after the key is added. This is not the case otherwise. We only do that if the peer is non validated peer, since - // otherwise the connection should already be accepted. This only happens when the short invite peer sends its own PGP key. - - if(det.skip_pgp_signature_validation) - AuthPGP::AllowConnection(det.gpg_id,true); -} - - /************* from pqiServiceMonitor *******************/ -void p3discovery2::statusChange(const std::list &plist) -{ -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::statusChange()" << std::endl; -#endif - - std::list::const_iterator pit; - for(pit = plist.begin(); pit != plist.end(); ++pit) - { - if (pit->actions & RS_SERVICE_PEER_CONNECTED) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::statusChange() Starting Disc with: " << pit->id << std::endl; -#endif - sendOwnContactInfo(pit->id); - } - else if (pit->actions & RS_SERVICE_PEER_DISCONNECTED) - { - std::cerr << "p3discovery2::statusChange() Disconnected: " << pit->id << std::endl; - } - - if (pit->actions & RS_SERVICE_PEER_NEW) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::statusChange() Adding Friend: " << pit->id << std::endl; -#endif - addFriend(pit->id); - } - else if (pit->actions & RS_SERVICE_PEER_REMOVED) - { -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::statusChange() Removing Friend: " << pit->id << std::endl; -#endif - removeFriend(pit->id); - } - } -#ifdef P3DISC_DEBUG - std::cerr << "p3discovery2::statusChange() finished." << std::endl; -#endif - return; -} - - - /*************************************************************************************/ - /* Extracting Network Graph Details */ - /*************************************************************************************/ -bool p3discovery2::getDiscFriends(const RsPeerId& id, std::list &proxyIds) -{ - // This is treated appart, because otherwise we don't receive any disc info about us - if(id == rsPeers->getOwnId()) // SSL id - return rsPeers->getFriendList(proxyIds) ; - - RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ - - std::map::const_iterator it; - RsPgpId pgp_id = getPGPId(id); - - it = mFriendList.find(pgp_id); - if (it == mFriendList.end()) - { - // ERROR. - return false; - } - - // For each of their friends that we know, grab that set of RsPeerId. - const std::set &friendSet = it->second.mFriendSet; - std::set::const_iterator fit; - for(fit = friendSet.begin(); fit != friendSet.end(); ++fit) - { - it = mFriendList.find(*fit); - if (it == mFriendList.end()) - { - continue; - } - - std::map::const_iterator sit; - for(sit = it->second.mSslIds.begin(); - sit != it->second.mSslIds.end(); ++sit) - { - proxyIds.push_back(sit->first); - } - } - return true; - -} - -bool p3discovery2::getWaitingDiscCount(size_t &sendCount, size_t &recvCount) -{ - RS_STACK_MUTEX(mDiscMtx); - sendCount = 0;//mPendingDiscPgpCertOutList.size(); - recvCount = 0;//mPendingDiscPgpCertInList.size(); - - return true; -} - -bool p3discovery2::getDiscPgpFriends(const RsPgpId &pgp_id, std::list &proxyPgpIds) -{ - /* find id -> and extract the neighbour_of ids */ - - if(pgp_id == rsPeers->getGPGOwnId()) // SSL id // This is treated appart, because otherwise we don't receive any disc info about us - return rsPeers->getGPGAcceptedList(proxyPgpIds) ; - - RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ - - std::map::const_iterator it; - it = mFriendList.find(pgp_id); - if (it == mFriendList.end()) - { - // ERROR. - return false; - } - - std::set::const_iterator fit; - for(fit = it->second.mFriendSet.begin(); fit != it->second.mFriendSet.end(); ++fit) - { - proxyPgpIds.push_back(*fit); - } - return true; -} - -bool p3discovery2::getPeerVersion(const RsPeerId &peerId, std::string &version) -{ - RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ - - std::map::const_iterator it; - it = mLocationMap.find(peerId); - if (it == mLocationMap.end()) - { - // MISSING. - return false; - } - - version = it->second.mVersion; - return true; -} - -bool p3discovery2::setPeerVersion(const RsPeerId &peerId, const std::string &version) -{ - RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it; - it = mLocationMap.find(peerId); - if (it == mLocationMap.end()) - { - mLocationMap[peerId] = DiscPeerInfo(); - it = mLocationMap.find(peerId); - } - - it->second.mVersion = version; - return true; -} - - -/*************************************************************************************/ -/* AuthGPGService */ -/*************************************************************************************/ -// AuthGPGOperation *p3discovery2::getGPGOperation() -// { -// { -// RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ -// -// /* process disc reply in list */ -// if (!mPendingDiscPgpCertInList.empty()) { -// RsDiscPgpCertItem *item = mPendingDiscPgpCertInList.front(); -// mPendingDiscPgpCertInList.pop_front(); -// -// return new AuthGPGOperationLoadOrSave(true, item->pgpId, item->pgpCert, item); -// } -// } -// -// return NULL; -// } - -// void p3discovery2::setGPGOperation(AuthGPGOperation *operation) -// { -// AuthGPGOperationLoadOrSave *loadOrSave = dynamic_cast(operation); -// if (loadOrSave) -// { -// RsDiscPgpCertItem *item = (RsDiscPgpCertItem *) loadOrSave->m_userdata; -// if (!item) -// { -// return; -// } -// -// if (loadOrSave->m_load) -// { -// -// #ifdef P3DISC_DEBUG -// std::cerr << "p3discovery2::setGPGOperation() Loaded Cert" << std::endl; -// item->print(std::cerr, 5); -// std::cerr << std::endl; -// #endif -// // It has already been processed by PGP. -// delete item; -// } -// else -// { -// // Attaching Certificate. -// item->pgpCert = loadOrSave->m_certGpg; -// -// #ifdef P3DISC_DEBUG -// std::cerr << "p3discovery2::setGPGOperation() Sending Message:" << std::endl; -// item->print(std::cerr, 5); -// #endif -// -// // Send off message -// sendItem(item); -// } -// return; -// } -// -// /* ignore other operations */ -// } diff --git a/libretroshare/src/gossipdiscovery/p3gossipdiscovery.h b/libretroshare/src/gossipdiscovery/p3gossipdiscovery.h deleted file mode 100644 index 95773df69..000000000 --- a/libretroshare/src/gossipdiscovery/p3gossipdiscovery.h +++ /dev/null @@ -1,222 +0,0 @@ -/******************************************************************************* - * RetroShare gossip discovery service implementation * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2013 Robert Fernie * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -// -// p3GossipDiscovery is reponsible for facilitating the circulation of public keys between friend nodes. -// -// The service locally holds a cache that stores: -// * the list of friend profiles, in each of which the list of locations with their own discovery flag (which means whether they allow discovery or not) -// * the list of friend nodes, with their version number -// -// Data flow -// ========= -// -// statusChange(std::list&) // called by pqiMonitor when peers are added,removed, or recently connected -// | -// +---- sendOwnContactInfo(RsPeerId) // [On connection] sends own PgpId, discovery flag, list of own signed GxsIds -// | | -// | +---->[to friend] -// | -// +---- locally add/remove cache info // [New/Removed friend] updates the list of friends, along with their own discovery flag -// -// tick() -// | -// +------ handleIncoming() -// | -// +-- recvOwnContactInfo(RsPeerId) // update location, IP addresses of a peer. -// | | -// | +------(if the peer has short_invite flag) -// | | | -// | | +---------requestPGPKey()->[to friend] // requests the full PGP public key, so as to be -// | | // able to validate connections. -// | | -// | +------(if disc != RS_VS_DISC_OFF) -// | | -// | +---------sendPgpList()->[to friend] // sends own list of friend profiles for which at least one location -// | // accepts discovery -// +-- processContactInfo(item->PeerId(), contact); -// | | -// | +------ addFriend() // called on nodes signed by the PGP key mentionned in the disc info -// | | -// | +------ update local discovery info -// | -// +-- recvIdentityList(Gxs Identity List) -// | | -// | +------ mGixs->requestKey(*it,peers,use_info) ; // requestKey() takes care of requesting the GxsIds that are missing -// | -// +-- recvPGPCertificate(item->PeerId(), pgpkey); -// | | -// | +------(if peer has short invite flag) -// | | -// | +--------- add key to keyring, accept connections and notify peerMgr -// | -// +-- processPGPList(pgplist->PeerId(), pgplist); // list of PGP keys of a friend, received from himself -// | | -// | +------ requestPgpCertificate() // request missing keys only -// | | -// | +------ updatePeers_locked(fromId) -// | | -// | +--------- sendContactInfo_locked(from,to) // sends IP information about mutual friends to the origin of the info -// | | -// | +--------- sendContactInfo_locked(to,from) // sends IP information origin to online mutual friends -// | -// +-- recvPGPCertificateRequest(pgplist->PeerId(), pgplist); -// | -// +------ sendPGPCertificate() // only sends the ones we are friend with, and only send own cert -// // if discovery is off -// -// Notes: -// * Tor nodes never send their own IP, and normal nodes never send their IP to Tor nodes either. -// A Tor node may accidentally know the IP of a normal node when it adds its certificate. However, the IP is dropped and not saved in this case. -// Generally speaking, no IP information should leave or transit through a Tor node. -// -// * the decision to call recvOwnContactInfo() or processContactInfo() depends on whether the item's peer id is the one the info is about. This is -// a bit unsafe. We should probably have to different items here especially if the information is not exactly the same. -// -#include - -#include "retroshare/rsgossipdiscovery.h" -#include "pqi/p3peermgr.h" -#include "pqi/p3linkmgr.h" -#include "pqi/p3netmgr.h" -#include "pqi/pqiservicemonitor.h" -#include "gossipdiscovery/gossipdiscoveryitems.h" -#include "services/p3service.h" -#include "pqi/authgpg.h" -#include "gxs/rsgixs.h" - -class p3ServiceControl; - -struct DiscSslInfo -{ - DiscSslInfo() : mDiscStatus(RS_VS_DISC_OFF) {} // default is to not allow discovery, until the peer tells about it - uint16_t mDiscStatus; -}; - -struct DiscPeerInfo -{ - DiscPeerInfo() {} - - std::string mVersion; -}; - -struct DiscPgpInfo -{ - DiscPgpInfo() {} - - void mergeFriendList(const std::set &friends); - - std::set mFriendSet; - std::map mSslIds; -}; - - -class p3discovery2 : - public RsGossipDiscovery, public p3Service, public pqiServiceMonitor - //public AuthGPGService -{ -public: - - p3discovery2( p3PeerMgr* peerMgr, p3LinkMgr* linkMgr, p3NetMgr* netMgr, - p3ServiceControl* sc, RsGixs* gixs ); - virtual ~p3discovery2(); - -virtual RsServiceInfo getServiceInfo(); - - /************* from pqiServiceMonitor *******************/ - virtual void statusChange(const std::list &plist); - /************* from pqiServiceMonitor *******************/ - - int tick(); - - /* external interface */ - bool getDiscFriends(const RsPeerId &id, std::list &friends); - bool getDiscPgpFriends(const RsPgpId &pgpid, std::list &gpg_friends); - bool getPeerVersion(const RsPeerId &id, std::string &version); - bool getWaitingDiscCount(size_t &sendCount, size_t &recvCount); - - /************* from AuthGPService ****************/ - // virtual AuthGPGOperation *getGPGOperation(); - // virtual void setGPGOperation(AuthGPGOperation *operation); - - -private: - - RsPgpId getPGPId(const RsPeerId &id); - - int handleIncoming(); - void updatePgpFriendList(); - - void addFriend(const RsPeerId &sslId); - void removeFriend(const RsPeerId &sslId); - - void updatePeerAddresses(const RsDiscContactItem *item); - void updatePeerAddressList(const RsDiscContactItem *item); - - void sendOwnContactInfo(const RsPeerId &sslid); - void recvOwnContactInfo(const RsPeerId &fromId, const RsDiscContactItem *item); - - void sendPGPList(const RsPeerId &toId); - void processPGPList(const RsPeerId &fromId, const RsDiscPgpListItem *item); - - void processContactInfo(const RsPeerId &fromId, const RsDiscContactItem *info); - - // send/recv information - - void requestPGPCertificate(const RsPgpId &aboutId, const RsPeerId &toId); - void recvPGPCertificateRequest(const RsPeerId& fromId, const RsDiscPgpListItem* item ); - void sendPGPCertificate(const RsPgpId &aboutId, const RsPeerId &toId); - void recvPGPCertificate(const RsPeerId &fromId, RsDiscPgpKeyItem *item); - void recvIdentityList(const RsPeerId& pid,const std::list& ids); - - bool setPeerVersion(const RsPeerId &peerId, const std::string &version); - - void rsEventsHandler(const RsEvent& event); - RsEventsHandlerId_t mRsEventsHandle; - - p3PeerMgr *mPeerMgr; - p3LinkMgr *mLinkMgr; - p3NetMgr *mNetMgr; - p3ServiceControl *mServiceCtrl; - RsGixs* mGixs; - - /* data */ - RsMutex mDiscMtx; - - void updatePeers_locked(const RsPeerId &aboutId); - void sendContactInfo_locked(const RsPgpId &aboutId, const RsPeerId &toId); - - rstime_t mLastPgpUpdate; - - std::map mFriendList; - std::map mLocationMap; - -// This was used to async the receiving of PGP keys, mainly because PGPHandler cross-checks all signatures, so receiving these keys in large loads can be costly -// Because discovery is not running in the main thread, there's no reason to re-async this into another process (e.g. AuthGPG) -// -// std::list mPendingDiscPgpCertInList; - -protected: - RS_SET_CONTEXT_DEBUG_LEVEL(1) -}; diff --git a/libretroshare/src/grouter/groutercache.h b/libretroshare/src/grouter/groutercache.h deleted file mode 100644 index cfaa847b8..000000000 --- a/libretroshare/src/grouter/groutercache.h +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************* - * libretroshare/src/grouter: groutercache.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include "retroshare/rsflags.h" -#include "rsgrouter.h" - -#define FLAGS_TAG_GROUTER_CACHE 0x22948eb1 - -typedef t_RsFlags32 GRouterCacheInfoFlags ; -typedef uint64_t GRouterMessageId ; - -const uint32_t GROUTER_CACHE_INFO_FLAGS_WAITING_ACK = 0x0001 ; - -class GRouterMessageDataItem -{ - public: - uint8_t *data_bytes ; // data to be sent - uint32_t data_size ; // size of the data - GRouterMessageId message_id ; - GRouterKeyId destination ; - - private: - // Make this class non copiable to avoid memory issues - // - GRouterMessageDataItem& operator=(const GRouterMessageDataItem&) ; - GRouterMessageDataItem(const GRouterMessageDataItem&) ; -}; - -class GRouterCacheInfo -{ - public: - GRouterCacheInfoFlags flags ; - rstime_t last_activity ; -}; - -class GRouterCache -{ - public: - // Stored transitting messages - // - std::list _pending_messages ; - - // Cache of which message is pending, waiting for an ACK, etc. - // - std::map _cache_info ; - - // debug stuff - // - void debugDump() ; -}; - diff --git a/libretroshare/src/grouter/grouterclientservice.h b/libretroshare/src/grouter/grouterclientservice.h deleted file mode 100644 index 394f8421a..000000000 --- a/libretroshare/src/grouter/grouterclientservice.h +++ /dev/null @@ -1,80 +0,0 @@ -/******************************************************************************* - * libretroshare/src/grouter: grouterclientservice.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -// This class is the parent class for any service that will use the global router to distribute its packets. -// Typical representative clients include: -// -// p3msgservice: sends distant messages and advertise messaging keys -// -#pragma once - -#include -#include -#include - -struct RsItem; - -static const uint32_t GROUTER_CLIENT_SERVICE_DATA_STATUS_UNKNOWN = 0x0000 ; // unused. -static const uint32_t GROUTER_CLIENT_SERVICE_DATA_STATUS_RECEIVED = 0x0001 ; // sent when data has been received and a receipt is available. -static const uint32_t GROUTER_CLIENT_SERVICE_DATA_STATUS_FAILED = 0x0002 ; // sent if the global router cannot send after a while - -class GRouterClientService -{ -public: - // This method is called by the turtle router to send data that comes out of a turtle tunnel. - // The turtle router stays responsible for the memory management of data. Most of the time the - // data chunk is a serialized item to be de-serialized by the client service. - // - // Parameters: - // item : global router item. Handled by the client service. - // destination_key : key that is associated with this item. Can be useful for the client. - // - // GRouter stays owner of the item, so the client should not delete it! - // - virtual void receiveGRouterData(const RsGxsId& destination_key,const RsGxsId& /*signing_key*/, GRouterServiceId &/*client_id*/, uint8_t */*data*/, uint32_t /*data_size*/) - { - std::cerr << "!!!!!! Received Data from global router, but the client service is not handling it !!!!!!!!!!" << std::endl ; - std::cerr << " destination key_id = " << destination_key.toStdString() << std::endl; - } - - // This method is called by the global router when a message has been received, or cannot be sent, etc. - // - virtual void notifyDataStatus(const GRouterMsgPropagationId& received_id,const RsGxsId& signer_id,uint32_t data_status) - { - std::cerr << "!!!!!! Received Data status from global router, but the client service is not handling it !!!!!!!!!!" << std::endl ; - std::cerr << " message ID = " << received_id << std::endl; - std::cerr << " data status = " << data_status << std::endl; - std::cerr << " signer ID = " << signer_id << std::endl; - } - - // This function is mandatory. It should do two things: - // 1 - keep a pointer to the global router, so as to be able to send data (e.g. copy pt into a local variable) - // 2 - call pt->registerTunnelService(this), so that the TR knows that service and can send back information to it. - // - virtual void connectToGlobalRouter(p3GRouter *pt) = 0 ; - - // should be derived to determine wether the client accepts data from this peer or not. If not, the data is dropped. - - virtual bool acceptDataFromPeer(const RsGxsId& gxs_id) =0; -}; - - diff --git a/libretroshare/src/grouter/grouteritems.cc b/libretroshare/src/grouter/grouteritems.cc deleted file mode 100644 index 10c91b222..000000000 --- a/libretroshare/src/grouter/grouteritems.cc +++ /dev/null @@ -1,269 +0,0 @@ -/******************************************************************************* - * libretroshare/src/grouter: grouteritems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "util/rsprint.h" -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstlvbase.h" -#include "grouteritems.h" - -#include "serialiser/rstypeserializer.h" - -/**********************************************************************************************/ -/* SERIALISER STUFF */ -/**********************************************************************************************/ - -RsItem *RsGRouterSerialiser::create_item(uint16_t service_id,uint8_t subtype) const -{ - if(RS_SERVICE_TYPE_GROUTER != service_id) - return NULL; /* wrong type */ - - switch(subtype) - { - case RS_PKT_SUBTYPE_GROUTER_DATA: return new RsGRouterGenericDataItem (); - case RS_PKT_SUBTYPE_GROUTER_TRANSACTION_CHUNK: return new RsGRouterTransactionChunkItem(); - case RS_PKT_SUBTYPE_GROUTER_TRANSACTION_ACKN: return new RsGRouterTransactionAcknItem (); - case RS_PKT_SUBTYPE_GROUTER_SIGNED_RECEIPT: return new RsGRouterSignedReceiptItem (); - case RS_PKT_SUBTYPE_GROUTER_MATRIX_CLUES: return new RsGRouterMatrixCluesItem (); - case RS_PKT_SUBTYPE_GROUTER_MATRIX_TRACK: return new RsGRouterMatrixTrackItem (); - case RS_PKT_SUBTYPE_GROUTER_FRIENDS_LIST: return new RsGRouterMatrixFriendListItem(); - case RS_PKT_SUBTYPE_GROUTER_ROUTING_INFO: return new RsGRouterRoutingInfoItem (); - - default: - return NULL; - } -} - -void RsGRouterTransactionChunkItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,propagation_id,"propagation_id") ; - RsTypeSerializer::serial_process(j,ctx,chunk_start ,"chunk_start") ; - RsTypeSerializer::serial_process(j,ctx,chunk_size ,"chunk_size") ; - RsTypeSerializer::serial_process(j,ctx,total_size ,"total_size") ; - - // Hack for backward compatibility (the chunk size is not directly next to the chunk data) - - if(j == RsGenericSerializer::DESERIALIZE) - { - if(chunk_size > ctx.mSize || ctx.mOffset > ctx.mSize - chunk_size) // better than if(chunk_size + offset > size) - { - std::cerr << __PRETTY_FUNCTION__ << ": Cannot read beyond item size. Serialisation error!" << std::endl; - ctx.mOk = false ; - return ; - } - if( NULL == (chunk_data = (uint8_t*)rs_malloc(chunk_size))) - { - ctx.mOk = false ; - return ; - } - - memcpy(chunk_data,&((uint8_t*)ctx.mData)[ctx.mOffset],chunk_size) ; - ctx.mOffset += chunk_size ; - } - else if(j== RsGenericSerializer::SERIALIZE) - { - memcpy(&((uint8_t*)ctx.mData)[ctx.mOffset],chunk_data,chunk_size) ; - ctx.mOffset += chunk_size ; - } - else if(j== RsGenericSerializer::SIZE_ESTIMATE) - ctx.mOffset += chunk_size ; - else - std::cerr << " [Binary data] " << ", length=" << chunk_size << " data=" << RsUtil::BinToHex((uint8_t*)chunk_data,std::min(50u,chunk_size)) << ((chunk_size>50)?"...":"") << std::endl; - -} -void RsGRouterTransactionAcknItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,propagation_id,"propagation_id") ; -} - -void RsGRouterGenericDataItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,routing_id,"routing_id") ; - RsTypeSerializer::serial_process (j,ctx,destination_key,"destination_key") ; - RsTypeSerializer::serial_process(j,ctx,service_id,"service_id") ; - - RsTypeSerializer::RawMemoryWrapper prox(data_bytes, data_size); - RsTypeSerializer::serial_process(j, ctx, prox, "data"); - - if(!!(ctx.mFlags & RsSerializationFlags::SIGNATURE)) return; - - RsTypeSerializer::serial_process(j,ctx,signature,"signature") ; - RsTypeSerializer::serial_process(j,ctx,duplication_factor,"duplication_factor") ; - RS_SERIAL_PROCESS(flags); - - if(j == RsGenericSerializer::DESERIALIZE) // make sure the duplication factor is not altered by friends. In the worst case, the item will duplicate a bit more. - { - if(duplication_factor < 1) - { - duplication_factor = 1 ; - std::cerr << "(II) correcting GRouter item duplication factor from 0 to 1, to ensure backward compat." << std::endl; - } - if(duplication_factor > GROUTER_MAX_DUPLICATION_FACTOR) - { - std::cerr << "(WW) correcting GRouter item duplication factor of " << duplication_factor << ". This is very unexpected." << std::endl; - duplication_factor = GROUTER_MAX_DUPLICATION_FACTOR ; - } - } -} - -void RsGRouterSignedReceiptItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,routing_id,"routing_id") ; - RS_SERIAL_PROCESS(flags); - RsTypeSerializer::serial_process (j,ctx,destination_key,"destination_key") ; - RsTypeSerializer::serial_process (j,ctx,service_id,"service_id") ; - RsTypeSerializer::serial_process (j,ctx,data_hash,"data_hash") ; - - if(!!(ctx.mFlags & RsSerializationFlags::SIGNATURE)) return; - - RsTypeSerializer::serial_process(j,ctx,signature,"signature") ; -} - -void RsGRouterRoutingInfoItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,peerId,"peerId") ; - RsTypeSerializer::serial_process(j,ctx,data_status,"data_status") ; - RsTypeSerializer::serial_process(j,ctx,tunnel_status,"tunnel_status") ; - RsTypeSerializer::serial_process (j,ctx,received_time_TS,"received_time_TS") ; - RsTypeSerializer::serial_process (j,ctx,last_sent_TS,"last_sent_TS") ; - - RsTypeSerializer::serial_process (j,ctx,last_tunnel_request_TS,"last_tunnel_request_TS") ; - RsTypeSerializer::serial_process(j,ctx,sending_attempts,"sending_attempts") ; - - RsTypeSerializer::serial_process(j,ctx,client_id,"client_id") ; - RsTypeSerializer::serial_process (j,ctx,item_hash,"item_hash") ; - RsTypeSerializer::serial_process (j,ctx,tunnel_hash,"tunnel_hash") ; - RsTypeSerializer::serial_process(j,ctx,routing_flags,"routing_flags") ; - - RsTypeSerializer::serial_process(j,ctx,incoming_routes,"incoming_routes") ; - - // Hack for backward compatibility. Normally we should need a single commandline to serialise/deserialise a single item here. - // But the full item is serialised, so we need the header. - - if(j == RsGenericSerializer::DESERIALIZE) - { - data_item = new RsGRouterGenericDataItem() ; - - ctx.mOffset += 8 ; - data_item->serial_process(j,ctx) ; - - if(ctx.mOffset < ctx.mSize) - { - receipt_item = new RsGRouterSignedReceiptItem(); - - ctx.mOffset += 8 ; - receipt_item->serial_process(j,ctx) ; - } - else - receipt_item = NULL ; - } - else if(j == RsGenericSerializer::SERIALIZE) - { - uint32_t remaining_size = ctx.mSize - ctx.mOffset; - ctx.mOk = ctx.mOk && RsGRouterSerialiser().serialise(data_item,ctx.mData,&remaining_size) ; - ctx.mOffset += RsGRouterSerialiser().size(data_item) ; - - if(receipt_item != NULL) - { - remaining_size = ctx.mSize - ctx.mOffset; - ctx.mOk = ctx.mOk && RsGRouterSerialiser().serialise(receipt_item,ctx.mData,&remaining_size); - ctx.mOffset += RsGRouterSerialiser().size(receipt_item) ; - } - } - else if(j == RsGenericSerializer::PRINT) - { - std::cerr << " [Serialized data] " << std::endl; - - if(receipt_item != NULL) - std::cerr << " [Receipt item ]" << std::endl; - } - else if(j == RsGenericSerializer::SIZE_ESTIMATE) - { - ctx.mOffset += RsGRouterSerialiser().size(data_item) ; - - if(receipt_item != NULL) - ctx.mOffset += RsGRouterSerialiser().size(receipt_item) ; - } -} - -void RsGRouterMatrixFriendListItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,reverse_friend_indices,"reverse_friend_indices") ; -} - -void RsGRouterMatrixTrackItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,provider_id,"provider_id") ; - RsTypeSerializer::serial_process(j,ctx,message_id,"message_id") ; - RsTypeSerializer::serial_process(j,ctx,time_stamp,"time_stamp") ; -} - -void RsGRouterMatrixCluesItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,destination_key,"destination_key") ; - RsTypeSerializer::serial_process(j,ctx,clues,"clues") ; -} - -template<> void RsTypeSerializer::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx,RoutingMatrixHitEntry& s,const std::string& name) -{ - RsTypeSerializer::serial_process(j,ctx,s.friend_id,name+":friend_id") ; - RsTypeSerializer::serial_process (j,ctx,s.weight,name+":weight") ; - RsTypeSerializer::serial_process (j,ctx,s.time_stamp,name+":time_stamp") ; -} - -RsGRouterGenericDataItem *RsGRouterGenericDataItem::duplicate() const -{ - RsGRouterGenericDataItem *item = new RsGRouterGenericDataItem ; - - // copy all members - - *item = *this ; - - // then duplicate the memory chunk - - if(data_size > 0) - { - item->data_bytes = (uint8_t*)rs_malloc(data_size) ; - - if(item->data_bytes == NULL) - { - delete item ; - return NULL ; - } - memcpy(item->data_bytes,data_bytes,data_size) ; - } - else - item->data_bytes = NULL ; - - return item ; -} - -RsGRouterSignedReceiptItem *RsGRouterSignedReceiptItem::duplicate() const -{ - RsGRouterSignedReceiptItem *item = new RsGRouterSignedReceiptItem ; - - // copy all members - - *item = *this ; - - return item ; -} - -RsGRouterAbstractMsgItem::~RsGRouterAbstractMsgItem() = default; diff --git a/libretroshare/src/grouter/grouteritems.h b/libretroshare/src/grouter/grouteritems.h deleted file mode 100644 index 0a12cb3f0..000000000 --- a/libretroshare/src/grouter/grouteritems.h +++ /dev/null @@ -1,296 +0,0 @@ -/******************************************************************************* - * libretroshare/src/grouter: grouteritems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include "util/rsmemory.h" - -#include "serialiser/rsserial.h" -#include "serialiser/rstlvkeys.h" -#include "rsitems/rsserviceids.h" -#include "retroshare/rstypes.h" -#include "retroshare/rsflags.h" -#include "retroshare/rsgrouter.h" -#include "groutermatrix.h" - -const uint8_t RS_PKT_SUBTYPE_GROUTER_PUBLISH_KEY = 0x01 ; // used to publish a key -const uint8_t RS_PKT_SUBTYPE_GROUTER_ACK_deprecated = 0x03 ; // don't use! -const uint8_t RS_PKT_SUBTYPE_GROUTER_SIGNED_RECEIPT_deprecated = 0x04 ; // don't use! -const uint8_t RS_PKT_SUBTYPE_GROUTER_DATA_deprecated = 0x05 ; // don't use! -const uint8_t RS_PKT_SUBTYPE_GROUTER_DATA_deprecated2 = 0x06 ; // don't use! -const uint8_t RS_PKT_SUBTYPE_GROUTER_DATA = 0x07 ; // used to send data to a destination (Signed by source) -const uint8_t RS_PKT_SUBTYPE_GROUTER_SIGNED_RECEIPT = 0x08 ; // long-distance acknowledgement of data received -const uint8_t RS_PKT_SUBTYPE_GROUTER_TRANSACTION_CHUNK = 0x10 ; // chunk of data. Used internally. -const uint8_t RS_PKT_SUBTYPE_GROUTER_TRANSACTION_ACKN = 0x11 ; // acknowledge for finished transaction. Not necessary, but increases fiability. -const uint8_t RS_PKT_SUBTYPE_GROUTER_MATRIX_CLUES = 0x80 ; // item to save matrix clues -const uint8_t RS_PKT_SUBTYPE_GROUTER_FRIENDS_LIST = 0x82 ; // item to save friend lists -const uint8_t RS_PKT_SUBTYPE_GROUTER_ROUTING_INFO = 0x93 ; // -const uint8_t RS_PKT_SUBTYPE_GROUTER_MATRIX_TRACK = 0x94 ; // item to save matrix track info - -const uint8_t QOS_PRIORITY_RS_GROUTER = 4 ; // relevant for items that travel through friends - - -/***********************************************************************************/ -/* Basic GRouter Item Class */ -/***********************************************************************************/ - -class RsGRouterItem: public RsItem -{ - public: - explicit RsGRouterItem(uint8_t grouter_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_GROUTER,grouter_subtype) {} - - virtual ~RsGRouterItem() {} - - virtual void clear() = 0 ; -}; - -/***********************************************************************************/ -/* Helper base classes */ -/***********************************************************************************/ - -class RsGRouterNonCopyableObject -{ - public: - RsGRouterNonCopyableObject() {} - protected: - RsGRouterNonCopyableObject(const RsGRouterNonCopyableObject&) {} - RsGRouterNonCopyableObject operator=(const RsGRouterNonCopyableObject&) { return *this ;} -}; - -/***********************************************************************************/ -/* Specific packets */ -/***********************************************************************************/ - -// This abstract item class encapsulates 2 types of signed items. All have signature, destination key -// and routing ID. Sub-items are responsible for providing the serialised data to be signed for -// both signing and checking. - -enum class RsGRouterItemFlags : uint32_t -{ - NONE = 0x0, - ENCRYPTED = 0x1, - SERVICE_UNKNOWN = 0x2 -}; -RS_REGISTER_ENUM_FLAGS_TYPE(RsGRouterItemFlags) - -struct RsGRouterAbstractMsgItem: RsGRouterItem -{ - explicit RsGRouterAbstractMsgItem(uint8_t pkt_subtype): - RsGRouterItem(pkt_subtype), flags(RsGRouterItemFlags::NONE) {} - - GRouterMsgPropagationId routing_id ; - GRouterKeyId destination_key ; - GRouterServiceId service_id ; - RsTlvKeySignature signature ; // signs mid+destination_key+state - - /// packet was delivered, not delivered, bounced, etc - RsGRouterItemFlags flags; - - ~RsGRouterAbstractMsgItem(); -}; - -class RsGRouterGenericDataItem: - public RsGRouterAbstractMsgItem, public RsGRouterNonCopyableObject -{ -public: - RsGRouterGenericDataItem(): - RsGRouterAbstractMsgItem(RS_PKT_SUBTYPE_GROUTER_DATA), - data_size(0), data_bytes(nullptr), duplication_factor(0) - { setPriorityLevel(QOS_PRIORITY_RS_GROUTER); } - - virtual ~RsGRouterGenericDataItem() { clear(); } - virtual void clear() - { - free(data_bytes); - data_bytes = nullptr; - } - - virtual void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ); - - RsGRouterGenericDataItem *duplicate() const; - - /// packet data - uint32_t data_size; - uint8_t* data_bytes; - - /** number of duplicates allowed. Should be capped at each de-serialise - * operation! */ - uint32_t duplication_factor; -}; - -class RsGRouterSignedReceiptItem: public RsGRouterAbstractMsgItem -{ - public: - RsGRouterSignedReceiptItem() : RsGRouterAbstractMsgItem(RS_PKT_SUBTYPE_GROUTER_SIGNED_RECEIPT) { setPriorityLevel(QOS_PRIORITY_RS_GROUTER) ; } - virtual ~RsGRouterSignedReceiptItem() {} - - virtual void clear() {} - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsGRouterSignedReceiptItem *duplicate() const ; - - // packet data - // - Sha1CheckSum data_hash ; // avoids an attacker to re-use a given signed receipt. This is the hash of the enceypted data. -}; - -// Low-level data items - -class RsGRouterTransactionItem: public RsGRouterItem -{ - public: - explicit RsGRouterTransactionItem(uint8_t pkt_subtype) : RsGRouterItem(pkt_subtype) {} - - virtual ~RsGRouterTransactionItem() {} - - virtual void clear() =0; - - virtual RsGRouterTransactionItem *duplicate() const = 0 ; -}; - -class RsGRouterTransactionChunkItem: public RsGRouterTransactionItem, public RsGRouterNonCopyableObject -{ -public: - RsGRouterTransactionChunkItem() : RsGRouterTransactionItem(RS_PKT_SUBTYPE_GROUTER_TRANSACTION_CHUNK), chunk_start(0), chunk_size(0), total_size(0), chunk_data(NULL) { setPriorityLevel(QOS_PRIORITY_RS_GROUTER) ; } - - virtual ~RsGRouterTransactionChunkItem() { free(chunk_data) ; } - - virtual void clear() {} - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - virtual RsGRouterTransactionItem *duplicate() const - { - RsGRouterTransactionChunkItem *item = new RsGRouterTransactionChunkItem ; - *item = *this ; // copy all fields - item->chunk_data = (uint8_t*)rs_malloc(chunk_size) ; // deep copy memory chunk - - if(item->chunk_data == NULL) - return NULL ; - - memcpy(item->chunk_data,chunk_data,chunk_size) ; - return item ; - } - - GRouterMsgPropagationId propagation_id ; - uint32_t chunk_start ; - uint32_t chunk_size ; - uint32_t total_size ; - uint8_t *chunk_data ; -}; -class RsGRouterTransactionAcknItem: public RsGRouterTransactionItem -{ -public: - RsGRouterTransactionAcknItem() : RsGRouterTransactionItem(RS_PKT_SUBTYPE_GROUTER_TRANSACTION_ACKN) { setPriorityLevel(QOS_PRIORITY_RS_GROUTER) ; } - virtual ~RsGRouterTransactionAcknItem() {} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - virtual void clear() {} - - virtual RsGRouterTransactionItem *duplicate() const { return new RsGRouterTransactionAcknItem(*this) ; } - - GRouterMsgPropagationId propagation_id ; -}; - -// Items for saving the routing matrix information. - -class RsGRouterMatrixCluesItem: public RsGRouterItem -{ - public: - RsGRouterMatrixCluesItem() : RsGRouterItem(RS_PKT_SUBTYPE_GROUTER_MATRIX_CLUES) - { setPriorityLevel(0) ; } // this item is never sent through the network - - virtual void clear() {} - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - // packet data - // - GRouterKeyId destination_key ; - std::list clues ; -}; - -class RsGRouterMatrixTrackItem: public RsGRouterItem -{ - public: - RsGRouterMatrixTrackItem() : RsGRouterItem(RS_PKT_SUBTYPE_GROUTER_MATRIX_TRACK), time_stamp(0) - { setPriorityLevel(0) ; } // this item is never sent through the network - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - virtual void clear() {} - - // packet data - // - RsGxsMessageId message_id ; - RsPeerId provider_id ; - rstime_t time_stamp ; -}; -class RsGRouterMatrixFriendListItem: public RsGRouterItem -{ - public: - RsGRouterMatrixFriendListItem() : RsGRouterItem(RS_PKT_SUBTYPE_GROUTER_FRIENDS_LIST) - { setPriorityLevel(0) ; } // this item is never sent through the network - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - virtual void clear() {} - - // packet data - // - std::vector reverse_friend_indices ; -}; - -class RsGRouterRoutingInfoItem: public RsGRouterItem, public GRouterRoutingInfo, public RsGRouterNonCopyableObject -{ - public: - RsGRouterRoutingInfoItem() : RsGRouterItem(RS_PKT_SUBTYPE_GROUTER_ROUTING_INFO) - { setPriorityLevel(0) ; } // this item is never sent through the network - - virtual ~RsGRouterRoutingInfoItem() { clear() ; } - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - virtual void clear() - { - if(data_item != NULL) delete data_item ; - if(receipt_item != NULL) delete receipt_item ; - - data_item = NULL ; - receipt_item = NULL ; - } -}; - -/***********************************************************************************/ -/* Serialisation */ -/***********************************************************************************/ - -class RsGRouterSerialiser: public RsServiceSerializer -{ -public: - explicit RsGRouterSerialiser( - RsSerializationFlags flags = RsSerializationFlags::NONE ): - RsServiceSerializer(RS_SERVICE_TYPE_GROUTER, flags) {} - - virtual RsItem *create_item(uint16_t service,uint8_t subtype) const ; -}; - - diff --git a/libretroshare/src/grouter/groutermatrix.cc b/libretroshare/src/grouter/groutermatrix.cc deleted file mode 100644 index b210f619e..000000000 --- a/libretroshare/src/grouter/groutermatrix.cc +++ /dev/null @@ -1,379 +0,0 @@ -/******************************************************************************* - * libretroshare/src/grouter: groutermatrix.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "groutertypes.h" -#include "groutermatrix.h" -#include "grouteritems.h" - -//#define ROUTING_MATRIX_DEBUG - -GRouterMatrix::GRouterMatrix() -{ - _proba_need_updating = true ; -} - -bool GRouterMatrix::addTrackingInfo(const RsGxsMessageId& mid,const RsPeerId& source_friend) -{ - rstime_t now = time(NULL) ; - - RoutingTrackEntry rte ; - - rte.friend_id = source_friend ; - rte.time_stamp = now ; - - _tracking_clues[mid] = rte ; -#ifdef ROUTING_MATRIX_DEBUG - std::cerr << "GRouterMatrix::addTrackingInfo(): Added clue mid=" << mid << ", from " << source_friend << " ID=" << source_friend << std::endl; -#endif - return true ; -} - -bool GRouterMatrix::cleanUp() -{ - // remove all tracking entries that have become too old. - -#ifdef ROUTING_MATRIX_DEBUG - std::cerr << "GRouterMatrix::cleanup()" << std::endl; -#endif - rstime_t now = time(NULL) ; - - for(std::map::iterator it(_tracking_clues.begin());it!=_tracking_clues.end();) - if(it->second.time_stamp + RS_GROUTER_MAX_KEEP_TRACKING_CLUES < now) - { -#ifdef ROUTING_MATRIX_DEBUG - std::cerr << " removing old entry msgId=" << it->first << ", from id " << it->second.friend_id << ", obtained " << (now - it->second.time_stamp) << " secs ago." << std::endl; -#endif - std::map::iterator tmp(it) ; - ++tmp ; - _tracking_clues.erase(it) ; - it=tmp ; - } - else - ++it ; - - return true ; -} - -bool GRouterMatrix::addRoutingClue(const GRouterKeyId& key_id,const RsPeerId& source_friend,float weight) -{ - // 1 - get the friend index. - // - uint32_t fid = getFriendId(source_friend) ; - - // 2 - get the Key map, and add the routing clue. - // - rstime_t now = time(NULL) ; - - RoutingMatrixHitEntry rc ; - rc.weight = weight ; - rc.time_stamp = now ; - rc.friend_id = fid ; - - std::list& lst( _routing_clues[key_id] ) ; - - // Prevent flooding. Happens in two scenarii: - // 1 - a user restarts RS very often => keys get republished for some reason - // 2 - a user intentionnaly floods a key - // - // Solution is to look for all recorded events, and not add any new event if an event came from the same friend - // too close in the past. Going through the list is not costly since it is bounded to RS_GROUTER_MATRIX_MAX_HIT_ENTRIES elemts. - - for(std::list::const_iterator mit(lst.begin());mit!=lst.end();++mit) - if((*mit).friend_id == fid && (*mit).time_stamp + RS_GROUTER_MATRIX_MIN_TIME_BETWEEN_HITS > now) - { -#ifdef ROUTING_MATRIX_DEBUG - std::cerr << "GRouterMatrix::addRoutingClue(): too many clues for key " << key_id.toStdString() << " from friend " << source_friend << " in a small interval of " << now - lst.front().time_stamp << " seconds. Flooding?" << std::endl; -#endif - return false ; - } - - lst.push_front(rc) ; // create it if necessary - - // Remove older elements - // - uint32_t sz = lst.size() ; // O(n)! - - for(uint32_t i=RS_GROUTER_MATRIX_MAX_HIT_ENTRIES;i::const_iterator it = _friend_indices.find(source_friend) ; - - if(it == _friend_indices.end()) - return _reverse_friend_indices.size() ; - else - return it->second ; -} -uint32_t GRouterMatrix::getFriendId(const RsPeerId& source_friend) -{ - std::map::const_iterator it = _friend_indices.find(source_friend) ; - - if(it == _friend_indices.end()) - { - // add a new friend - - uint32_t new_id = _reverse_friend_indices.size() ; - _reverse_friend_indices.push_back(source_friend) ; - _friend_indices[source_friend] = new_id ; - - return new_id ; - } - else - return it->second ; -} - -void GRouterMatrix::getListOfKnownKeys(std::vector& key_ids) const -{ - key_ids.clear() ; - - for(std::map >::const_iterator it(_time_combined_hits.begin());it!=_time_combined_hits.end();++it) - key_ids.push_back(it->first) ; -} - -bool GRouterMatrix::getTrackingInfo(const RsGxsMessageId& mid, RsPeerId &source_friend) -{ - std::map::const_iterator it = _tracking_clues.find(mid) ; - - if(it == _tracking_clues.end()) - return false ; - - source_friend = it->second.friend_id; - - return true ; -} - -void GRouterMatrix::debugDump() const -{ - std::cerr << " Proba needs up: " << _proba_need_updating << std::endl; - std::cerr << " Known keys: " << _time_combined_hits.size() << std::endl; - std::cerr << " Routing events: " << std::endl; - rstime_t now = time(NULL) ; - - for(std::map >::const_iterator it(_routing_clues.begin());it!=_routing_clues.end();++it) - { - std::cerr << " " << it->first.toStdString() << " : " ; - for(std::list::const_iterator it2(it->second.begin());it2!=it->second.end();++it2) - std::cerr << now - (*it2).time_stamp << " (" << (*it2).friend_id << "," << (*it2).weight << ") " ; - - std::cerr << std::endl; - } - std::cerr << " Routing values: " << std::endl; - - for(std::map >::const_iterator it(_time_combined_hits.begin());it!=_time_combined_hits.end();++it) - { - std::cerr << " " << it->first.toStdString() << " : " ; - - for(uint32_t i=0;isecond.size();++i) - std::cerr << it->second[i] << " " ; - std::cerr << std::endl; - } - std::cerr << " Tracking clues: " << std::endl; - - for(std::map::const_iterator it(_tracking_clues.begin());it!=_tracking_clues.end();++it) - std::cerr << " " << it->first << ": from " << it->second.friend_id << " " << now - it->second.time_stamp << " secs ago." << std::endl; -} - -bool GRouterMatrix::computeRoutingProbabilities(const GRouterKeyId& key_id, const std::vector& friends, std::vector& probas, float& maximum) const -{ - // Routing probabilities are computed according to routing clues - // - // For a given key, each friend has a known set of routing clues (rstime_t, weight) - // We combine these to compute a static weight for each friend/key pair. - // This is performed in updateRoutingProbabilities() - // - // Then for a given list of online friends, the weights are computed into probabilities, - // that always sum up to 1. - // -#ifdef ROUTING_MATRIX_DEBUG - if(_proba_need_updating) - std::cerr << "GRouterMatrix::computeRoutingProbabilities(): matrix is not up to date. Not a real problem, but still..." << std::endl; -#endif - - probas.resize(friends.size(),0.0f) ; - float total = 0.0f ; - - std::map >::const_iterator it2 = _time_combined_hits.find(key_id) ; - - if(it2 == _time_combined_hits.end()) - { - // The key is not known. In this case, we return a zero probability for all peers. - // - float p = 0.0f;//1.0f / friends.size() ; - - probas.clear() ; - probas.resize(friends.size(),p) ; - -#ifdef ROUTING_MATRIX_DEBUG - std::cerr << "GRouterMatrix::computeRoutingProbabilities(): key id " << key_id.toStdString() << " does not exist! Returning uniform probabilities." << std::endl; -#endif - return false ; - } - const std::vector& w(it2->second) ; - maximum = 0.0f ; - - for(uint32_t i=0;i= w.size()) - probas[i] = 0.0f ; - else - { - probas[i] = w[findex] ; - total += w[findex] ; - - if(maximum < w[findex]) - maximum = w[findex] ; - } - } - - if(total > 0.0f) - for(uint32_t i=0;i >::const_iterator it(_routing_clues.begin());it!=_routing_clues.end();++it) - { -#ifdef ROUTING_MATRIX_DEBUG - std::cerr << " " << it->first.toStdString() << " : " ; -#endif - - std::vector& v(_time_combined_hits[it->first]) ; - v.clear() ; - v.resize(_friend_indices.size(),0.0f) ; - - for(std::list::const_iterator it2(it->second.begin());it2!=it->second.end();++it2) - { - // Half life period is 7 days. - - float time_difference_in_days = 1 + (now - (*it2).time_stamp ) / (7*86400.0f) ; - v[(*it2).friend_id] += (*it2).weight / (time_difference_in_days*time_difference_in_days) ; - } - } -#ifdef ROUTING_MATRIX_DEBUG - std::cerr << " done." << std::endl; -#endif - - _proba_need_updating = false ; - return true ; -} - -bool GRouterMatrix::saveList(std::list& items) -{ -#ifdef ROUTING_MATRIX_DEBUG - std::cerr << " GRoutingMatrix::saveList()" << std::endl; -#endif - - RsGRouterMatrixFriendListItem *item = new RsGRouterMatrixFriendListItem ; - - item->reverse_friend_indices = _reverse_friend_indices ; - items.push_back(item) ; - - for(std::map >::const_iterator it(_routing_clues.begin());it!=_routing_clues.end();++it) - { - RsGRouterMatrixCluesItem *item = new RsGRouterMatrixCluesItem ; - - item->destination_key = it->first ; - item->clues = it->second ; - - items.push_back(item) ; - } - - for(std::map::const_iterator it(_tracking_clues.begin());it!=_tracking_clues.end();++it) - { - RsGRouterMatrixTrackItem *item = new RsGRouterMatrixTrackItem ; - - item->provider_id = it->second.friend_id ; - item->time_stamp = it->second.time_stamp ; - item->message_id = it->first ; - - items.push_back(item) ; - } - - return true ; -} -bool GRouterMatrix::loadList(std::list& items) -{ - RsGRouterMatrixFriendListItem *itm1 = NULL ; - RsGRouterMatrixCluesItem *itm2 = NULL ; - RsGRouterMatrixTrackItem *itm3 = NULL ; - -#ifdef ROUTING_MATRIX_DEBUG - std::cerr << " GRoutingMatrix::loadList()" << std::endl; -#endif - - for(std::list::const_iterator it(items.begin());it!=items.end();++it) - { - if(NULL != (itm3 = dynamic_cast(*it))) - { -#ifdef ROUTING_MATRIX_DEBUG - std::cerr << " initing tracking clues." << std::endl; -#endif - RoutingTrackEntry rte ; - rte.friend_id = itm3->provider_id ; - rte.time_stamp = itm3->time_stamp ; - - _tracking_clues[itm3->message_id] = rte; - } - if(NULL != (itm2 = dynamic_cast(*it))) - { -#ifdef ROUTING_MATRIX_DEBUG - std::cerr << " initing routing clues." << std::endl; -#endif - - _routing_clues[itm2->destination_key] = itm2->clues ; - _proba_need_updating = true ; // notifies to re-compute all the info. - } - if(NULL != (itm1 = dynamic_cast(*it))) - { - _reverse_friend_indices = itm1->reverse_friend_indices ; - _friend_indices.clear() ; - - for(uint32_t i=0;i<_reverse_friend_indices.size();++i) - _friend_indices[_reverse_friend_indices[i]] = i ; - - _proba_need_updating = true ; // notifies to re-compute all the info. - } - } - - return true ; -} - diff --git a/libretroshare/src/grouter/groutermatrix.h b/libretroshare/src/grouter/groutermatrix.h deleted file mode 100644 index 7630b798d..000000000 --- a/libretroshare/src/grouter/groutermatrix.h +++ /dev/null @@ -1,105 +0,0 @@ -/******************************************************************************* - * libretroshare/src/grouter: groutermatrix.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#pragma once - -#include - -#include "pgp/rscertificate.h" -#include "retroshare/rsgrouter.h" -#include "groutertypes.h" - -struct RsItem; - -// The routing matrix records the event clues received from each friend -// -struct RoutingMatrixHitEntry -{ - uint32_t friend_id ; // not the full key. Gets too big otherwise! - float weight ; - rstime_t time_stamp ; -}; - -struct RoutingTrackEntry -{ - RsPeerId friend_id ; // not the full key. Gets too big otherwise! - rstime_t time_stamp ; -}; - -class GRouterMatrix -{ - public: - GRouterMatrix() ; - - // Computes the routing probabilities for this id for the given list of friends. - // the computation accounts for the time at which the info was received and the - // weight of each routing hit record. - // - bool computeRoutingProbabilities(const GRouterKeyId& id, const std::vector& friends, std::vector& probas, float &maximum) const ; - - // Update routing probabilities for each key, accounting for all received events, but without - // activity information - // - bool updateRoutingProbabilities() ; - - // Record one routing clue. The events can possibly be merged in time buckets. - // - bool addRoutingClue(const GRouterKeyId& id,const RsPeerId& source_friend,float weight) ; - bool addTrackingInfo(const RsGxsMessageId& id,const RsPeerId& source_friend) ; - - bool saveList(std::list& items) ; - bool loadList(std::list& items) ; - - bool cleanUp() ; - - // Dump info in terminal. - // - void debugDump() const ; - void getListOfKnownKeys(std::vector& key_ids) const ; - - bool getTrackingInfo(const RsGxsMessageId& id,RsPeerId& source_friend); - private: - // returns the friend id, possibly creating a new id. - // - uint32_t getFriendId(const RsPeerId& id) ; - - // returns the friend id. If not exist, returns _reverse_friend_indices.size() - // - uint32_t getFriendId_const(const RsPeerId& id) const; - - // List of events received and computed routing probabilities - // - std::map > _routing_clues ; // received routing clues. Should be saved. - std::map > _time_combined_hits ; // hit matrix after time-convolution filter - std::map _tracking_clues ; // who provided the most recent messages - - // This is used to avoid re-computing probas when new events have been received. - // - bool _proba_need_updating ; - - // Routing weights. These are the result of a time convolution of the routing clues and weights - // recorded in _routing_clues. - // - std::map _friend_indices ; // index for each friend to lookup in the routing matrix Not saved. - std::vector _reverse_friend_indices ;// SSLid corresponding to each friend index. Saved. -}; - diff --git a/libretroshare/src/grouter/groutertypes.h b/libretroshare/src/grouter/groutertypes.h deleted file mode 100644 index 23efdbed6..000000000 --- a/libretroshare/src/grouter/groutertypes.h +++ /dev/null @@ -1,135 +0,0 @@ -/******************************************************************************* - * libretroshare/src/grouter: groutertypes.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include "util/rstime.h" -#include -#include "pgp/rscertificate.h" -#include "turtle/p3turtle.h" -#include "retroshare/rsgrouter.h" - -class RsGRouterGenericDataItem ; -class RsGRouterSignedReceiptItem ; - -static const uint16_t GROUTER_CLIENT_ID_MESSAGES = 0x1001 ; - -static const uint32_t RS_GROUTER_MATRIX_MAX_HIT_ENTRIES = 10 ; // max number of clues to store -static const uint32_t RS_GROUTER_MATRIX_MIN_TIME_BETWEEN_HITS = 60 ; // can be set to up to half the publish time interval. Prevents flooding routes. -static const uint32_t RS_GROUTER_MIN_CONFIG_SAVE_PERIOD = 61 ; // at most save config every 10 seconds -static const uint32_t RS_GROUTER_MAX_KEEP_TRACKING_CLUES = 86400*10 ; // max time for which we keep record of tracking info: 10 days. - -static const float RS_GROUTER_BASE_WEIGHT_ROUTED_MSG = 1.0f ; // base contribution of routed message clue to routing matrix -static const float RS_GROUTER_BASE_WEIGHT_GXS_PACKET = 0.1f ; // base contribution of GXS message to routing matrix -static const float RS_GROUTER_PROBABILITY_THRESHOLD_FOR_RANDOM_ROUTING = 0.01f ; // routing probability under which the routage is performed randomly -static const float RS_GROUTER_PROBABILITY_THRESHOLD_BEST_PEERS_SELECT = 0.5f ; // min ratio of forward proba with respect to best peer. - -static const uint32_t MAX_TUNNEL_WAIT_TIME = 60 ; // wait for 60 seconds at most for a tunnel response. -static const uint32_t MAX_TUNNEL_UNMANAGED_TIME = 600 ; // min time before retry tunnels for that msg. -static const uint32_t MAX_DELAY_FOR_RESEND = 2*86400+300 ; // re-send if held for more than 2 days (cache store period) plus security delay. -static const uint32_t MAX_DESTINATION_KEEP_TIME = 20*86400 ; // keep for 20 days in destination cache to avoid re- -static const uint32_t MAX_RECEIPT_KEEP_TIME = 20*86400 ; // keep for 20 days in destination cache to avoid re- -static const uint32_t TUNNEL_OK_WAIT_TIME = 2 ; // wait for 2 seconds after last tunnel ok, so that we have a complete set of tunnels. -static const uint32_t MAX_GROUTER_DATA_SIZE = 2*1024*1024 ; // 2MB size limit. This is of course arbitrary. -static const uint32_t MAX_TRANSACTION_ACK_WAITING_TIME = 60 ; // wait for at most 60 secs for a ACK. If not restart the transaction. -static const uint32_t DIRECT_FRIEND_TRY_DELAY = 20 ; // wait for 20 secs if no friends available, then try tunnels. -static const uint32_t MAX_INACTIVE_DATA_PIPE_DELAY = 300 ; // clean inactive data pipes for more than 5 mins -static const uint32_t GROUTER_MAX_DUPLICATION_FACTOR = 10 ; // max number of duplicates for a given message to keep in the network -static const uint32_t GROUTER_MAX_BRANCHING_FACTOR = 3 ; // max number of branches, for locally forwarding items - -static const rstime_t RS_GROUTER_DEBUG_OUTPUT_PERIOD = 10 ; // Output everything -static const rstime_t RS_GROUTER_AUTOWASH_PERIOD = 10 ; // Autowash every minute. Not a costly operation. -static const rstime_t RS_GROUTER_MATRIX_UPDATE_PERIOD = 60*10 ; // Check for key advertising every 10 minutes -static const uint32_t GROUTER_ITEM_MAX_CACHE_KEEP_TIME = 2*86400 ; // Cached items are kept for 48 hours at most. - -static const uint32_t RS_GROUTER_DATA_STATUS_UNKNOWN = 0x0000 ; // unknown. Unused. -static const uint32_t RS_GROUTER_DATA_STATUS_PENDING = 0x0001 ; // item is pending. Should be sent asap. -static const uint32_t RS_GROUTER_DATA_STATUS_SENT = 0x0002 ; // item is sent to tunnel or friend. No need to keep sending. -static const uint32_t RS_GROUTER_DATA_STATUS_RECEIPT_OK = 0x0003 ; // item is at destination. -static const uint32_t RS_GROUTER_DATA_STATUS_ONGOING = 0x0004 ; // transaction is ongoing. -static const uint32_t RS_GROUTER_DATA_STATUS_DONE = 0x0005 ; // receipt item has been forward to all routes. We can remove the item. - -static const uint32_t RS_GROUTER_SENDING_STATUS_TUNNEL = 0x0001 ; // item was sent in a tunnel -static const uint32_t RS_GROUTER_SENDING_STATUS_FRIEND = 0x0002 ; // item was sent to a friend - -static const uint32_t RS_GROUTER_TUNNEL_STATUS_UNMANAGED = 0x0000 ; // no tunnel requested atm -static const uint32_t RS_GROUTER_TUNNEL_STATUS_PENDING = 0x0001 ; // tunnel requested to turtle -static const uint32_t RS_GROUTER_TUNNEL_STATUS_READY = 0x0002 ; // tunnel is ready but we're still waiting for various confirmations - -class FriendTrialRecord -{ - public: - RsPeerId friend_id ; // id of the friend - rstime_t time_stamp ; // time of the last tried - float probability ; // probability at which the item was selected - uint32_t nb_friends ; // number of friends at the time of sending the item - - bool serialise(void *data,uint32_t& offset,uint32_t size) const ; - bool deserialise(void *data,uint32_t& offset,uint32_t size) ; -}; - -class GRouterRoutingInfo -{ - // There's no destructor to this class, because the memory is managed elsewhere, which - // ovoids lots of duplications if the class is copied. -public: - GRouterRoutingInfo() - : data_status(0) - , tunnel_status(0) - , received_time_TS(0) - , last_sent_TS(0) - , last_tunnel_request_TS(0) - , sending_attempts(0) - , routing_flags(0) - , data_item(NULL) - , receipt_item(NULL) - , data_transaction_TS(0) // this is not serialised. - {} - - uint32_t data_status ; // pending, waiting, etc. - uint32_t tunnel_status ; // status of tunnel handling. - - rstime_t received_time_TS ; // time at which the item was originally received - rstime_t last_sent_TS ; // last time the item was sent - rstime_t last_tunnel_request_TS ; // last time tunnels have been asked for this item. - uint32_t sending_attempts ; // number of times tunnels have been asked for this peer without success - - GRouterServiceId client_id ; // service ID of the client. Only valid when origin==OwnId - TurtleFileHash tunnel_hash ; // tunnel hash to be used for this item - uint32_t routing_flags ; - - RsGRouterGenericDataItem *data_item ; - RsGRouterSignedReceiptItem *receipt_item ; - - RsTlvPeerIdSet incoming_routes ; - Sha1CheckSum item_hash ; // used to check re-existance, consistency, etc. - - // non serialised data - - rstime_t data_transaction_TS ; - - static const uint32_t ROUTING_FLAGS_ALLOW_TUNNELS = 0x0001; - static const uint32_t ROUTING_FLAGS_ALLOW_FRIENDS = 0x0002; - static const uint32_t ROUTING_FLAGS_IS_ORIGIN = 0x0004; - static const uint32_t ROUTING_FLAGS_IS_DESTINATION = 0x0008; -}; - diff --git a/libretroshare/src/grouter/p3grouter.cc b/libretroshare/src/grouter/p3grouter.cc deleted file mode 100644 index 1c3f56515..000000000 --- a/libretroshare/src/grouter/p3grouter.cc +++ /dev/null @@ -1,2522 +0,0 @@ -/******************************************************************************* - * libretroshare/src/grouter: p3grouter.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -//////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Decentralized routing -// ===================== -// -// Main idea: Each peer holds a local routing table, a matrix with probabilities that each friend -// is a correct path for a given key ID. -// -// The routing tables are updated as messages go back and forth. Successful -// interactions feed the routing table with information of where to route the -// packets. -// -// The routing is kept probabilistic, meaning that the optimal route is not -// always chosen, but the randomness helps updating the routing probabilities. -// -// Services that might use the router (All services really...) -// - Messenger -// - sends/receives messages to distant peers -// - Channels, forums, posted, etc. -// - send messages to the origin of the channel/forum/posted -// -// Decentralized routing algorithm: -// - message passing -// - upward: -// * Forward msg to friends according to probabilities. -// * If all equal, send to all friends (or a rando subset of them). -// * keep the local routing info in a cache that is saved (Which peer issued the msg) -// - which probability was used to chose this friend (will be useful -// to compute the routing contribution if the msg is ACK-ed) -// -// Two probabilities are computed: -// - routing probabilities among connected friends -// * this is computed by the routing matrix -// - branching factor N -// * depends on the depth of the items. Currently branching is 3 at origin and 1 elsewhere. -// * depends on the distribution of probabilities (min and max) -// -// Once computed, -// - the item is forwarded randomly to N peers drawn from the list of connected peers with the given probabilities. -// - the depth of the item is incremented randomly -// -// - downward: look into routing cache. If info not present, drop the item. -// Forward item into stored direction. -// -// - routing probability computation: count number of times a reliable info is obtained from -// which direction for which identity -// * the count is a floating point number, since weights can be assigned to each info -// (especially for importance sampling) -// * init: all friends have equal count of 0 (or 1, well, we'll have to make this right). -// * We use importance sampling, meaning that when peer relays a msg from ID: -// count[ID, peer] += 1.0 / importance -// -// ... where importance was the probability of chosing peer for the -// route upward. -// -// * probability of forward is proportional to count. -// -// - routing cache -// * this cache stores messages IDs (like turtle router) but is saved on disk -// * it is used to remember where to send back responses to messages, and -// with what probability the route was chosen. -// * cache items have a TTL and the cache is cleaned regularly. -// -// - routing matrix -// * the structure is fed by other services, when they receive key IDs. -// * stores for each identity the count of how many times each peer gave reliable info for that ID. -// That information should be enough to route packets in the correct direction. -// * saved to disk. -// * all contributions should have a time stamp. Regularly, the oldest contributions are removed. -// -// - Routed packets: we use a common packet type for all services: -// -// We need two abstract item types: -// -// * Data packet -// - packet unique ID (sha1, or uint64_t) -// - destination ID (for Dn packets, the destination is the source!) -// - packet type: Id request, Message, etc. -// - packet service ID (Can be messenging, channels, etc). -// - packet data (void* + size_t) -// - flags (such as ACK or response required, and packet direction) -// - routed directions and probabilities -// * ACK packet. -// - packet unique ID (the id of the corresponding data) -// - flags (reason for ACK. Could be data delivered, or error, too far, etc) -// -// - Data storage packets -// * We need storage packets for the matrix states. -// * General routing options info? -// -// - Main difficulties: -// * have a good re-try strategy if a msg does not arrive. -// * handle peer availability. In forward mode: easy. In backward mode: -// difficult. We should wait, and send back the packet if possible. -// * robustness -// * security: avoid flooding, and message alteration. -// -// Data pipeline -// ============= -// -// sendData() -// | -// +--> encrypt/sign ---> store in _pending_messages -// -// receiveTurtleData() -// | -// +-------------------------------------------------+ -// tick() | -// | | -// +--> HandleLowLevelServiceItems() | -// | | | -// | +--> handleLowLevelServiceItem(item) <------------+ -// | | -// | +--> handleIncomingTransactionAckItem() -// | | -// | +--> handleIncomingTransactionChunkItem() -// | | -// | +---> addDataChunk() -// | | -// | +---> push item to _incoming_items list -// | -// +--> handleIncoming() -// | | -// | +---> handleIncomingReceiptItem(GRouterSignedReceiptItem*) -// | | | -// | +---> handleIncomingDataItem(GRouterDataItem*) | -// | | | -// | +----------------------------+ -// | | -// | | -// | [for US?] --------------------+-----> verifySignedData() -// | | | -// | +-----> notifyClient() -// | | | -// | | +-----> send Receipt item ---+ -// | | | -// | +----> Store In _pending_messages | -// | | -// +--> routePendingObjects() | -// | | | -// | +--> locked_collectAvailablePeers()/locked_collectAvailableTunnels() | -// | | | -// | +--> sliceDataItem() | -// | | | -// | +--> locked_sendTransactionData() <-----------------------------------------------+ -// | | -// | +--> mTurtle->sendTurtleData(virtual_pid,turtle_item) / sendItem() -// | -// +--> handleTunnels() -// | | -// | +---> mTurtle->stopMonitoringTunnels(hash) ; -// | +---> mTurtle->monitoringTunnels(hash) ; -// | -// +--> autoWash() -// -//////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include -#include - -#include "util/rsrandom.h" -#include "util/rsprint.h" -#include "util/rsmemory.h" -#include "rsitems/rsconfigitems.h" -#include "services/p3idservice.h" -#include "turtle/p3turtle.h" -#include "gxs/rsgixs.h" -#include "retroshare/rspeers.h" -#include "util/cxx17retrocompat.h" -#include "p3grouter.h" -#include "grouteritems.h" -#include "groutertypes.h" -#include "grouterclientservice.h" - -/**********************/ -//#define GROUTER_DEBUG -/**********************/ - -const std::string p3GRouter::SERVICE_INFO_APP_NAME = "Global Router" ; - -p3GRouter::p3GRouter(p3ServiceControl *sc, RsGixs *is) : - p3Service(), p3Config(), mServiceControl(sc), mTurtle(nullptr), mGixs(is), - grMtx("GRouter"), _changed(false), _debug_enabled(true), - _last_autowash_time(0), _last_matrix_update_time(0), - _last_debug_output_time(0), _last_config_changed(0), - _random_salt(RsRandom::random_u64()), - mMissingKeyQueueMtx("GRouterMissingKeyQueue") -{ addSerialType(new RsGRouterSerialiser()); } - -int p3GRouter::tick() -{ - rstime_t now = time(nullptr); - - // Sort incoming service data - // - handleLowLevelServiceItems() ; - - // Handle high level global router data - // - handleIncoming() ; - - // Take each item in the list of pending messages and receipts. If the destination peer is available - // or if the tunnel is available, the item will be sent there. - // - routePendingObjects() ; - - // clean things up. Remove unused requests, old stuff etc. - - autoWash() ; - - // Go through the list of active tunnel requests and pending objects to ask for new tunnels - // or close existing tunnel requests. - // - handleTunnels() ; - - /* Handle items in mMissingKeyQueue */ - if(now > mMissingKeyQueueCheckLastCheck + mMissingKeyQueueCheckEvery) - { - mMissingKeyQueueCheckLastCheck = now; - - RS_STACK_MUTEX(mMissingKeyQueueMtx); - for(auto it = mMissingKeyQueue.begin(); it != mMissingKeyQueue.end();) - { - const RsGxsId& senderId = it->first->signature.keyId; - if(rsIdentity->isKnownId(senderId)) - { - Dbg2() << __PRETTY_FUNCTION__ << " got key: " << senderId - << " for item pending validation, calling item handler" - << std::endl; - - handleIncomingItem(it->first.get()); - it = mMissingKeyQueue.erase(it); - } - else - { - Dbg3() << __PRETTY_FUNCTION__ << " requesting missing key: " - << senderId << " to validate pending item" << std::endl; - - /* At this point the network status may have varied a lot since - * we received the item, so we don't even know if the peer who - * forwarded the item is still online, moreover the fact that - * after specific request we haven't got the key yet suggests it - * is not a good route toward the key, so request it to all - * available peers */ - rsIdentity->requestIdentity(senderId); - ++it; - } - } - } - - // Update routing matrix - // - if(now > _last_matrix_update_time + RS_GROUTER_MATRIX_UPDATE_PERIOD) - { - RsStackMutex mtx(grMtx) ; - - _last_matrix_update_time = now ; - _routing_matrix.updateRoutingProbabilities() ; // This should be locked. - _routing_matrix.cleanUp() ; // This should be locked. - } - -#ifdef GROUTER_DEBUG - // Debug dump everything - // - if(now > _last_debug_output_time + RS_GROUTER_DEBUG_OUTPUT_PERIOD) - { - _last_debug_output_time = now ; - if(_debug_enabled) - debugDump() ; - } -#endif - - // If content has changed, save config, at most every RS_GROUTER_MIN_CONFIG_SAVE_PERIOD seconds appart - // Otherwise, always save at least every RS_GROUTER_MAX_CONFIG_SAVE_PERIOD seconds - // - if(_changed && now > _last_config_changed + RS_GROUTER_MIN_CONFIG_SAVE_PERIOD) - { -#ifdef GROUTER_DEBUG - grouter_debug() << "p3GRouter::tick(): triggering config save." << std::endl; -#endif - - _changed = false ; - _last_config_changed = now ; - IndicateConfigChanged() ; - } - - return 0 ; -} - -RsSerialiser *p3GRouter::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser ; - - rss->addSerialType(new RsGRouterSerialiser) ; - rss->addSerialType(new RsGeneralConfigSerialiser()); - - return rss ; -} - -bool p3GRouter::registerKey(const RsGxsId& authentication_key,const GRouterServiceId& client_id,const std::string& description) -{ - RS_STACK_MUTEX(grMtx) ; - - if(_registered_services.find(client_id) == _registered_services.end()) - { - std::cerr << __PRETTY_FUNCTION__ << ": unable to register key " << authentication_key << " for client id " << client_id << ": client id is not known." << std::endl; - return false ; - } - - GRouterPublishedKeyInfo info ; - info.service_id = client_id ; - info.authentication_key = authentication_key ; - info.description_string = description.substr(0,20); - - Sha1CheckSum hash = makeTunnelHash(authentication_key,client_id) ; - - _owned_key_ids[hash] = info ; -#ifdef GROUTER_DEBUG - grouter_debug() << "Registered the following key: " << std::endl; - grouter_debug() << " Auth GXS Id : " << authentication_key << std::endl; - grouter_debug() << " Client id : " << std::hex << client_id << std::dec << std::endl; - grouter_debug() << " Description : " << info.description_string << std::endl; - grouter_debug() << " Hash : " << hash << std::endl; -#endif - - return true ; -} -bool p3GRouter::unregisterKey(const RsGxsId& key_id,const GRouterServiceId& sid) -{ - RS_STACK_MUTEX(grMtx) ; - - Sha1CheckSum hash = makeTunnelHash(key_id,sid) ; - - const auto it = _owned_key_ids.find(hash); - if(it == _owned_key_ids.end()) - { - RsErr() << __PRETTY_FUNCTION__ << " key " << key_id << " not found." - << std::endl; - return false; - } - -#ifdef GROUTER_DEBUG - grouter_debug() << "p3GRouter::unregistered the following key: " << std::endl; - grouter_debug() << " Key id : " << key_id.toStdString() << std::endl; - grouter_debug() << " Client id : " << std::hex << it->second.service_id << std::dec << std::endl; - grouter_debug() << " Description : " << it->second.description_string << std::endl; -#endif - - _owned_key_ids.erase(it) ; - - return true ; -} -//===========================================================================================================================// -// Service data handling // -//===========================================================================================================================// - -void p3GRouter::handleLowLevelServiceItems() -{ - // While messages read - // - RsItem *item = NULL; - - while(NULL != (item = recvItem())) - { - RsGRouterTransactionItem *gtitem = dynamic_cast(item); - if (gtitem) - { - handleLowLevelServiceItem(gtitem) ; - } - else - { - delete(item); - } - } -} - -void p3GRouter::handleLowLevelServiceItem(RsGRouterTransactionItem *item) -{ - switch(item->PacketSubType()) - { - case RS_PKT_SUBTYPE_GROUTER_TRANSACTION_ACKN: - { - RsGRouterTransactionAcknItem *trans_ack_item = dynamic_cast(item); - if (trans_ack_item) - { - handleLowLevelTransactionAckItem(trans_ack_item) ; - } - break ; - } - case RS_PKT_SUBTYPE_GROUTER_TRANSACTION_CHUNK: - { - RsGRouterTransactionChunkItem *chunk_item = dynamic_cast(item); - if (chunk_item) - { - handleLowLevelTransactionChunkItem(chunk_item) ; - } - break ; - } - default: - std::cerr << "p3GRouter::handleIncoming: Unknown packet subtype " << item->PacketSubType() << std::endl ; - } - delete item; -} - -//===========================================================================================================================// -// Turtle management // -//===========================================================================================================================// - -bool p3GRouter::handleTunnelRequest(const RsFileHash& hash,const RsPeerId& /*peer_id*/) -{ - // tunnel request is answered according to the following rules: - // - we are the destination => always accept - // - we know the destination and have RCPT items to send back => always accept - // - we know the destination and have a route (according to matrix) => accept with high probability - // - we don't know the destination => accept with very low probability - - if(_owned_key_ids.find(hash) == _owned_key_ids.end()) - return false ; - -#ifdef GROUTER_DEBUG - std::cerr << "p3GRouter::handleTunnelRequest(). Got req for hash " << hash << ", responding OK" << std::endl; -#endif - return true ; -} - -void p3GRouter::handleLowLevelTransactionChunkItem(RsGRouterTransactionChunkItem *chunk_item) -{ -#ifdef GROUTER_DEBUG - std::cerr << " item is a transaction item." << std::endl; -#endif - - RsPeerId pid = chunk_item->PeerId() ; - - RsGRouterAbstractMsgItem *generic_item = NULL; - { - RS_STACK_MUTEX(grMtx) ; - - generic_item = _incoming_data_pipes[pid].addDataChunk(dynamic_cast(chunk_item->duplicate())) ;// addDataChunk takes ownership over chunk_item - } - - // send to client off-mutex - - if(generic_item == NULL) - return ; - - generic_item->PeerId(pid) ; - -#ifdef GROUTER_DEBUG - std::cerr << " transaction is finished. Passing newly created item to client." << std::endl; - std::cerr << " sending a ACK item" << std::endl; -#endif - - RsGRouterTransactionAcknItem ackn_item ; - ackn_item.propagation_id = generic_item->routing_id ; - locked_sendTransactionData(pid,ackn_item) ; - - { - RS_STACK_MUTEX(grMtx) ; - _incoming_items.push_back(generic_item) ; - } -} - -void p3GRouter::handleLowLevelTransactionAckItem(RsGRouterTransactionAcknItem *trans_ack_item) -{ -#ifdef GROUTER_DEBUG - std::cerr << " item is a transaction ACK." << std::endl; -#endif - RS_STACK_MUTEX(grMtx) ; - - std::map::iterator it=_pending_messages.find(trans_ack_item->propagation_id) ; - - if(it != _pending_messages.end() && it->second.data_status == RS_GROUTER_DATA_STATUS_ONGOING) - { - it->second.data_status = RS_GROUTER_DATA_STATUS_SENT; - it->second.last_sent_TS = time(NULL) ; -#ifdef GROUTER_DEBUG - std::cerr << " setting new status as sent/awaiting receipt." << std::endl; -#endif - } -#ifdef GROUTER_DEBUG - else - std::cerr << " Note: no routing ID corresponds to this ACK item. This probably corresponds to a signed receipt" << std::endl; -#endif -} - -void p3GRouter::receiveTurtleData(const RsTurtleGenericTunnelItem *gitem, const RsFileHash & hash, const RsPeerId &virtual_peer_id, RsTurtleGenericTunnelItem::Direction direction) -{ -#ifdef GROUTER_DEBUG - std::cerr << "p3GRouter::receiveTurtleData() " << std::endl; - std::cerr << " Received data for hash : " << hash << std::endl; - std::cerr << " Virtual peer id : " << virtual_peer_id << std::endl; - std::cerr << " Direction : " << direction << std::endl; -#else - (void) hash; - (void) direction; -#endif - - // turtle data is received. - // This function - // - possibly packs multi-item blocks back together - // - converts it into a grouter generic item (by deserialising it) - - const RsTurtleGenericDataItem *item = dynamic_cast(gitem) ; - - if(item == NULL) - { - std::cerr << " ERROR: item is not a data item. That is an error." << std::endl; - return ; - } -#ifdef GROUTER_DEBUG - std::cerr << " data size : " << item->data_size << std::endl; - std::cerr << " data bytes : " << RsDirUtil::sha1sum((unsigned char*)item->data_bytes,item->data_size) << std::endl; -#endif - - // Items come out of the pipe in order. We need to recover all chunks before we de-serialise the content and have it handled by handleIncoming() - - uint32_t size = item->data_size ; - RsItem *itm = RsGRouterSerialiser().deserialise(item->data_bytes,&size); - -if(itm == NULL) -{ - std::cerr << "(EE) p3GRouter::receiveTurtleData(): cannot de-serialise data. Somthing wrong in the format. Item data (size="<< item->data_size << "): " << RsUtil::BinToHex((char*)item->data_bytes,item->data_size) << std::endl; - return ; -} - - itm->PeerId(virtual_peer_id) ; - - // At this point we can have either a transaction chunk, or a transaction ACK. - // We handle them both here - - RsGRouterTransactionChunkItem *chunk_item = dynamic_cast(itm) ; - RsGRouterTransactionAcknItem *trans_ack_item = NULL; - - if(chunk_item != NULL) - handleLowLevelTransactionChunkItem(chunk_item) ; - else if(NULL != (trans_ack_item = dynamic_cast(itm))) - handleLowLevelTransactionAckItem(trans_ack_item) ; - else - { - std::cerr << " ERROR: cannot deserialise turtle item." << std::endl; - if(itm) - delete itm ; - } -} - -void GRouterTunnelInfo::removeVirtualPeer(const TurtleVirtualPeerId& vpid) -{ - std::set::iterator it = virtual_peers.find(vpid) ; - - if(it == virtual_peers.end()) - { - std::cerr << " ERROR: removing a virtual peer that does not exist. This is an error!" << std::endl; - return ; - } - - virtual_peers.erase(it) ; -} -void GRouterTunnelInfo::addVirtualPeer(const TurtleVirtualPeerId& vpid) -{ - if(virtual_peers.find(vpid) != virtual_peers.end()) - std::cerr << " ERROR: adding a virtual peer that already exist. This is an error!" << std::endl; - - virtual_peers.insert(vpid) ; - - rstime_t now = time(NULL) ; - - if(first_tunnel_ok_TS == 0) first_tunnel_ok_TS = now ; - last_tunnel_ok_TS = now ; -} - -RsGRouterAbstractMsgItem *GRouterDataInfo::addDataChunk(RsGRouterTransactionChunkItem *chunk) -{ - last_activity_TS = time(NULL) ; - - // perform some checking - - if(chunk->total_size > MAX_GROUTER_DATA_SIZE + 10000 || chunk->chunk_size > chunk->total_size || chunk->chunk_start >= chunk->total_size) - { - std::cerr << " ERROR: chunk size is unconsistent, or too large: size=" << chunk->chunk_size << ", start=" << chunk->chunk_start << ", total size=" << chunk->total_size << ". Chunk will be dropped. Data pipe will be reset." << std::endl; - clear() ; - delete chunk ; - return NULL ; - } - - // now add that chunk. - - if(incoming_data_buffer == NULL) - { - if(chunk->chunk_start != 0) - { - std::cerr << " ERROR: chunk numbering is wrong. First chunk is not starting at 0. Dropping." << std::endl; - delete chunk; - return NULL; - } - incoming_data_buffer = chunk ; - } - else - { - if(incoming_data_buffer->chunk_size != chunk->chunk_start || incoming_data_buffer->total_size != chunk->total_size) - { - std::cerr << " ERROR: chunk numbering is wrong. Dropping." << std::endl; - delete chunk ; - delete incoming_data_buffer ; - incoming_data_buffer = NULL ; - return NULL; - } - incoming_data_buffer->chunk_data = (uint8_t*)realloc((uint8_t*)incoming_data_buffer->chunk_data,incoming_data_buffer->chunk_size + chunk->chunk_size) ; - memcpy(&incoming_data_buffer->chunk_data[incoming_data_buffer->chunk_size],chunk->chunk_data,chunk->chunk_size) ; - incoming_data_buffer->chunk_size += chunk->chunk_size ; - - delete chunk ; - } - - // if finished, return it. - - if(incoming_data_buffer->total_size == incoming_data_buffer->chunk_size) - { - RsItem *data_item = RsGRouterSerialiser().deserialise(incoming_data_buffer->chunk_data,&incoming_data_buffer->chunk_size) ; - - delete incoming_data_buffer; - incoming_data_buffer = NULL ; - - return dynamic_cast(data_item) ; - } - else - return NULL ; -} - -void p3GRouter::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir) -{ - RS_STACK_MUTEX(grMtx) ; - - // Server side tunnels. This is incoming data. Nothing to do. - -#ifdef GROUTER_DEBUG - std::cerr << "p3GRouter::addVirtualPeer(). Received vpid " << virtual_peer_id << " for hash " << hash << ", direction=" << dir << std::endl; - std::cerr << " direction = " << dir << std::endl; -#endif - - // client side. We set the tunnel flags to READY. - - if(dir == RsTurtleGenericTunnelItem::DIRECTION_SERVER) - { - bool found = false ; - - // linear search. Bad, but not really a problem. New virtual peers come quite rarely. - for(std::map::iterator it(_pending_messages.begin());it!=_pending_messages.end();++it) - if(it->second.tunnel_hash == hash) - { -#ifdef GROUTER_DEBUG - std::cerr << " setting tunnel state to READY." << std::endl; -#endif - it->second.tunnel_status = RS_GROUTER_TUNNEL_STATUS_READY ; - found = true ; - - // don't break here, because we might send multiple items though the same tunnel. - } - - if(!found) - { - std::cerr << " ERROR: cannot find corresponding pending message." << std::endl; - return ; - } - } - if(dir == RsTurtleGenericTunnelItem::DIRECTION_CLIENT) - { - } - -#ifdef GROUTER_DEBUG - std::cerr << " adding VPID." << std::endl; -#endif - - _tunnels[hash].addVirtualPeer(virtual_peer_id) ; - -} - -void p3GRouter::removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) -{ - RS_STACK_MUTEX(grMtx) ; - -#ifdef GROUTER_DEBUG - std::cerr << "p3GRouter::removeVirtualPeer(). Removing vpid " << virtual_peer_id << " for hash " << hash << std::endl; - std::cerr << " removing VPID." << std::endl; -#endif - - // make sure the VPID exists. - - std::map::iterator it = _tunnels.find(hash) ; - - if(it == _tunnels.end()) - { - std::cerr << " no virtual peers at all for this hash: " << hash << "! This is a consistency error." << std::endl; - return ; - } - it->second.removeVirtualPeer(virtual_peer_id) ; - -#ifdef GROUTER_DEBUG - std::cerr << " setting tunnel status in pending message." << std::endl; -#endif - - for(std::map::iterator it2(_pending_messages.begin());it2!=_pending_messages.end();++it2) - if(it2->second.tunnel_hash == hash && it->second.virtual_peers.empty()) - it2->second.tunnel_status = RS_GROUTER_TUNNEL_STATUS_PENDING ; - - if(it->second.virtual_peers.empty()) - { -#ifdef GROUTER_DEBUG - std::cerr << " last virtual peer removed. Also deleting hash entry." << std::endl; -#endif - _tunnels.erase(it) ; - } - -} - -void p3GRouter::connectToTurtleRouter(p3turtle *pt) -{ - mTurtle = pt ; - pt->registerTunnelService(this) ; -} - -//===========================================================================================================================// -// Tunnel management // -//===========================================================================================================================// - -class item_comparator_001 -{ -public: - template - bool operator()(const std::pair& p1,const std::pair& p2) const - { - return p1.first < p2.first ; - } -}; - -void p3GRouter::handleTunnels() -{ - // This function is responsible for asking for tunnels, and removing requests from the turtle router. - // To remove the unnecessary TR activity generated by multiple peers trying to send the same message, - // only peers which haven't passed on any data to direct friends, or for which the best friends are not online - // will be allowed to monitor tunnels. - - // Go through the list of pending messages - // - if tunnels are pending for too long => remove from turtle - // - if item is waiting for too long => tunnels are waitin - - // We need a priority queue of items to handle, starting from the most ancient items, with a delay that varies with - // how much time they have been waiting. When a turtle slot it freed, we take the next item in the queue and - // activate tunnel handling for it. - - // possible pending message status: - // - RS_GROUTER_PENDING_MSG_STATUS_TUNNEL_READY : tunnel is ready. Waiting a few seconds to be used (this is to allow multiple tunnels to come). - // - RS_GROUTER_PENDING_MSG_STATUS_TUNNEL_PENDING : tunnel was asked. - // - RS_GROUTER_PENDING_MSG_STATUS_TUNNEL_UNMANAGED: not tunnel managed at the moment. - - // 1 - make a priority list of messages to ask tunnels for - - // Compute the priority of pending messages, according to the number of attempts and how far in the past they have been tried for the last time. - // Delay after which a message is re-sent, depending on the number of attempts already made. - - RS_STACK_MUTEX(grMtx) ; - -#ifdef GROUTER_DEBUG - if(!_pending_messages.empty()) - { - grouter_debug() << "p3GRouter::handleTunnels()" << std::endl; - grouter_debug() << " building priority list of items to send..." << std::endl; - } -#endif - - rstime_t now = time(NULL) ; - std::vector > priority_list ; - - for(std::map::iterator it=_pending_messages.begin();it!=_pending_messages.end();++it) - { -#ifdef GROUTER_DEBUG - grouter_debug() << " " << std::hex << it->first << std::dec - << ", data_status=" << it->second.data_status << ", tunnel_status=" << it->second.tunnel_status - << ", last received: "<< now - it->second.received_time_TS << " (secs ago)" - << ", last TR: "<< now - it->second.last_tunnel_request_TS << " (secs ago)" - << ", last sent: " << now - it->second.last_sent_TS << " (secs ago) "<< std::endl; -#endif - - if(it->second.data_status == RS_GROUTER_DATA_STATUS_PENDING && (it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_TUNNELS)) - { - if(it->second.tunnel_status == RS_GROUTER_TUNNEL_STATUS_UNMANAGED && it->second.last_tunnel_request_TS + MAX_TUNNEL_UNMANAGED_TIME < now) - { - uint32_t item_delay = now - it->second.last_tunnel_request_TS ; - int item_priority = item_delay ; - -#ifdef GROUTER_DEBUG - grouter_debug() << " delay=" << item_delay << " attempts=" << it->second.sending_attempts << ", priority=" << item_priority << std::endl; -#endif - - if(item_priority > 0) - priority_list.push_back(std::make_pair(item_priority,&it->second)) ; - } - else if(it->second.tunnel_status == RS_GROUTER_TUNNEL_STATUS_PENDING && it->second.last_tunnel_request_TS + MAX_TUNNEL_WAIT_TIME < now) - { - mTurtle->stopMonitoringTunnels(it->second.tunnel_hash) ; - - it->second.tunnel_status = RS_GROUTER_TUNNEL_STATUS_UNMANAGED ; - -#ifdef GROUTER_DEBUG - grouter_debug() << " stopping tunnels for this message." << std::endl; ; -#endif - } -#ifdef GROUTER_DEBUG - else if(it->second.tunnel_status == RS_GROUTER_TUNNEL_STATUS_READY) - grouter_debug() << " tunnel is available. " << std::endl; - else - grouter_debug() << " doing nothing." << std::endl; - - grouter_debug() << std::endl; -#endif - } - else - { -#ifdef GROUTER_DEBUG - std::cerr << " closing pending tunnels." << std::endl; -#endif - mTurtle->stopMonitoringTunnels(it->second.tunnel_hash) ; - - it->second.tunnel_status = RS_GROUTER_TUNNEL_STATUS_UNMANAGED ; - } - - // also check that all tunnels are actually active, to remove any old dead tunnels - // - // if(it->second.tunnel_status == RS_GROUTER_TUNNEL_STATUS_READY) - // { - // std::map::iterator it2 = _tunnels.find(it->second.tunnel_hash) ; - // - // if(it2 == _tunnels.end() || it2->second.virtual_peers.empty()) ; - // { - // std::cerr << " re-setting tunnel status to PENDING, as no tunnels are actually present." << std::endl; - // it->second.tunnel_status = RS_GROUTER_TUNNEL_STATUS_PENDING ; - // } - // } - } -#ifdef GROUTER_DEBUG - if(!priority_list.empty()) - grouter_debug() << " sorting..." << std::endl; -#endif - - - std::sort(priority_list.begin(),priority_list.end(),item_comparator_001()) ; - - // take tunnels from item priority list, and enable tunnel handling, while respecting max number of active tunnels limit - - for(uint32_t i=0;ifirst << " with duplication factor = " << itpid->second << std::endl; -#endif - // delete temporary items - - for(std::list::const_iterator cit=chunks.begin();cit!=chunks.end();++cit) - delete *cit; - } - - data_item->duplication_factor = saved_duplication_factor ; -} - -void p3GRouter::routePendingObjects() -{ - // Go throught he list of pending messages. For those with a peer ready, send the message to that peer. - // The peer might be: - // - a virtual peer id that actually is a tunnel - // - a real friend node - // Tunnels and friends will used whenever available. Of course this might cause a message to arrive multiple times, but we - // don't really care since the GR takes care of duplicates already. - // - // Which tunnels are available is handled by handleTunnels() - // - - rstime_t now = time(NULL) ; - - RS_STACK_MUTEX(grMtx) ; -#ifdef GROUTER_DEBUG - if(!_pending_messages.empty()) - std::cerr << "p3GRouter::routePendingObjects()" << std::endl; -#endif - bool pending_messages_changed = false ; - - for(std::map::iterator it=_pending_messages.begin();it!=_pending_messages.end();++it) - { -#ifdef GROUTER_DEBUG - std::cerr << " message " << std::hex << it->first << std::dec << std::endl; -#endif - if(it->second.data_status == RS_GROUTER_DATA_STATUS_PENDING) - { - // Look for tunnels and friends where to send the data. Send to both. - - std::map peers_and_duplication_factors ; - - if(it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_TUNNELS) - locked_collectAvailableTunnels(it->second.tunnel_hash,it->second.data_item->duplication_factor,peers_and_duplication_factors); - - if(!peers_and_duplication_factors.empty()) - { -#ifdef GROUTER_DEBUG - std::cerr << " tunnels available! sending!" << std::endl; -#endif - locked_sendToPeers(it->second.data_item,peers_and_duplication_factors) ; - - // change item state in waiting list - - it->second.data_status = RS_GROUTER_DATA_STATUS_ONGOING ; - it->second.data_transaction_TS = now ; - - pending_messages_changed = true ; - continue ; // no need to seek for friend asynced routes since tunnels directly go to the final destination! - } - - if(it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_FRIENDS) - locked_collectAvailableFriends(it->second.data_item->destination_key,it->second.incoming_routes.ids,it->second.data_item->duplication_factor,peers_and_duplication_factors); - - if(!peers_and_duplication_factors.empty()) - { -#ifdef GROUTER_DEBUG - std::cerr << " friends available! sending!" << std::endl; -#endif - locked_sendToPeers(it->second.data_item,peers_and_duplication_factors) ; - - // change item state in waiting list - - it->second.data_status = RS_GROUTER_DATA_STATUS_ONGOING ; - it->second.data_transaction_TS = now ; - - pending_messages_changed = true ; - } - else - { -#ifdef GROUTER_DEBUG - std::cerr << " no direct friends available" << std::endl; -#endif - - if(it->second.received_time_TS + DIRECT_FRIEND_TRY_DELAY < now && !(it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_TUNNELS)) - { -#ifdef GROUTER_DEBUG - std::cerr << " enabling tunnels for this message." << std::endl; -#endif - it->second.routing_flags |= GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_TUNNELS ; - } - } - - } - else if(it->second.data_status == RS_GROUTER_DATA_STATUS_ONGOING && now > MAX_TRANSACTION_ACK_WAITING_TIME + it->second.data_transaction_TS) - { -#ifdef GROUTER_DEBUG - std::cerr << " waited too long for this transation. Switching back to PENDING." << std::endl; -#endif - - it->second.data_status = RS_GROUTER_DATA_STATUS_PENDING ; - } - else if(it->second.data_status == RS_GROUTER_DATA_STATUS_SENT) - { - if( (it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_IS_ORIGIN) && it->second.last_sent_TS + MAX_DELAY_FOR_RESEND < now) - { -#ifdef GROUTER_DEBUG - std::cerr << " item was not received. Re-setting status to PENDING" << std::endl; -#endif - it->second.data_status = RS_GROUTER_DATA_STATUS_PENDING ; - } - else - { -#ifdef GROUTER_DEBUG - std::cerr << " item was sent. Desactivating tunnels." << std::endl; -#endif - it->second.routing_flags &= ~GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_TUNNELS ; - } - } - - // We treat this case apart, so as to make sure that receipt items are always forwarded wen possible even if the data_status - // is not set correctly. - - if(it->second.receipt_item != NULL && !it->second.incoming_routes.ids.empty()) - { - // send the receipt through all incoming routes, as soon as it gets delivered. - -#ifdef GROUTER_DEBUG - std::cerr << " receipt should be sent back. Trying all incoming routes..." << std::endl; -#endif - - std::list chunks ; - - for(std::set::iterator it2=it->second.incoming_routes.ids.begin();it2!=it->second.incoming_routes.ids.end();) - if(mServiceControl->isPeerConnected(getServiceInfo().mServiceType,*it2) || mTurtle->isTurtlePeer(*it2)) - { -#ifdef GROUTER_DEBUG - std::cerr << " sending receipt back to " << *it2 << " which is online." << std::endl; -#endif - if(chunks.empty()) - sliceDataItem(it->second.receipt_item,chunks) ; - - for(std::list::const_iterator it3(chunks.begin());it3!=chunks.end();++it3) - locked_sendTransactionData(*it2,*(*it3) ) ; - - // then remove from the set. - std::set::iterator it2tmp = it2 ; - ++it2tmp ; - it->second.incoming_routes.ids.erase(it2) ; - it2 = it2tmp ; - - pending_messages_changed = true ; - } - else - ++it2 ; - - for(std::list::const_iterator cit=chunks.begin();cit!=chunks.end();++cit) - delete *cit; - - // Because signed receipts are small items, we take the bet that if the item could be sent, then it was received. - // otherwise, we should mark that incomng route as being handled, wait for the ACK and deal with it by updating - // it->second.data_status at that time. - - if(it->second.incoming_routes.ids.empty()) - it->second.data_status = RS_GROUTER_DATA_STATUS_DONE ; - } - } - - if(pending_messages_changed) - IndicateConfigChanged() ; -} - -void p3GRouter::locked_collectAvailableFriends(const GRouterKeyId& gxs_id,const std::set& incoming_routes,uint32_t duplication_factor, std::map& friend_peers_and_duplication_factors) -{ - // Old strategy was the following: - // if origin - // send to multiple neighbors : best and random - // else - // send to a single "best" neighbor (determined by threshold over routing probability), - - // New strategy is: - // - // Characteristics of the distribution to look at: - // * who's online, who's not - // * all values quite equal - // * single value well above others - // * largest value is small - // Algorithm: - // - // 0 - encode duplicate factor in routed item and allow at most N duplicates - // - when forwarding to N peers, split the duplication factor into N bins, each being proportional to the forwarding probability. - // Example for N=3 and D=10: - // - // p Calculation Final bin - // - // +-0.21--> 0.21*10=2.1 --> 2 0.1 below - // | - // 10 ----+-0.45--> 0.45*10=4.5 --> 4.6-> 5 0.4 above - // | - // +-0.34--> 0.34*10=3.4 --> 3.0-> 3 0 - // - // - // 1 - get routing probabilities p_i for all peers as well as the maximum proba p before normalization. - // - // Set N = min(3,item->duplication_factor) // max number of friends to route to - // - // if p < threshold // That means the routage info is too old => Fallback to random routing. - // Select N random online friends and forward to them. - // else - // Let p_i be the probabilities of all peers - // Select all online peers for which p_i >= 0.5*p. - // if !empty - // Update duplication factors according to probabilities and number of peers - // Route to these peers - // else - // Keep the item - // - -#ifdef GROUTER_DEBUG - std::cerr << "locked_getAvailableFriends()" << std::endl; - std::cerr << " looking for friends for item to ID " << gxs_id << " duplication factor = " << duplication_factor << std::endl; - std::cerr << " retrieving online friends and all friends lists." << std::endl; -#endif - std::set online_ids ; - std::list all_ids ; - - rsPeers->getFriendList(all_ids) ; - mServiceControl->getPeersConnected(getServiceInfo().mServiceType,online_ids) ; - - std::vector tmp_peers; - - for(std::list::const_iterator it(all_ids.begin());it!=all_ids.end();++it) - tmp_peers.push_back(*it) ; - - std::vector probas; - float maximum = 1.0; - float max_probability = 0.0; - - _routing_matrix.computeRoutingProbabilities(gxs_id, tmp_peers, probas, maximum) ; - -#ifdef GROUTER_DEBUG - std::cerr << " initial routing probabilities (maximum=" << maximum << ")" << std::endl; - for(uint32_t i=0;i using uniform random routing." << std::endl; -#endif - } - else - { - for(uint32_t i=0;i giving up." << std::endl; -#endif - return ; - } - - // now select the N best peers -#ifdef GROUTER_DEBUG - std::cerr << " Remaining peers and routing probabilities:" << std::endl; - for(uint32_t i=0;i > mypairs ; - - for(uint32_t i=0;i 0 && max_count > 0) - { - for(int i=mypairs.size()-1,n=0;i>=0 && n=0 && n=0 && nsecond.last_tunnel_ok_TS + TUNNEL_OK_WAIT_TIME > now) - { -#ifdef GROUTER_DEBUG - std::cerr << ". Still waiting delay (stabilisation)." << std::endl; -#endif - return ; - } - - // for now, just take one. But in the future, we will need some policy to temporarily store objects at proxy peers, etc. - -#ifdef GROUTER_DEBUG - std::cerr << " " << vpit->second.virtual_peers.size() << " virtual peers available. " << std::endl; -#endif - TurtleVirtualPeerId vpid = *(vpit->second.virtual_peers.begin()) ; - - tunnel_peers_and_duplication_factors[vpid] = total_duplication ; -} - -bool p3GRouter::locked_sendTransactionData(const RsPeerId& pid,const RsGRouterTransactionItem& trans_item) -{ - if(mTurtle->isTurtlePeer(pid)) - { -#ifdef GROUTER_DEBUG - std::cerr << " sending to tunnel vpid " << pid << std::endl; -#endif - uint32_t turtle_data_size = RsGRouterSerialiser().size(const_cast(&trans_item)) ; - uint8_t *turtle_data = (uint8_t*)rs_malloc(turtle_data_size) ; - - if(turtle_data == NULL) - return false ; - - if(!RsGRouterSerialiser().serialise(const_cast(&trans_item),turtle_data,&turtle_data_size)) - { - std::cerr << " ERROR: cannot serialise RsGRouterTransactionChunkItem." << std::endl; - - free(turtle_data) ; - return false ; - } - - RsTurtleGenericDataItem *turtle_item = new RsTurtleGenericDataItem ; - - turtle_item->data_size = turtle_data_size ; - turtle_item->data_bytes = turtle_data ; - -#ifdef GROUTER_DEBUG - std::cerr << " sending to vpid " << pid << std::endl; -#endif - mTurtle->sendTurtleData(pid,turtle_item) ; - - return true ; - } - else - { -#ifdef GROUTER_DEBUG - std::cerr << " sending to pid " << pid << std::endl; -#endif - RsGRouterTransactionItem *item_copy = trans_item.duplicate() ; - item_copy->PeerId(pid) ; - - sendItem(item_copy) ; - - return true ; - } -} - -void p3GRouter::autoWash() -{ - bool items_deleted = false ; - rstime_t now = time(nullptr); - - std::map > failed_msgs ; - - { - RS_STACK_MUTEX(grMtx) ; - - for(std::map::iterator it=_pending_messages.begin();it!=_pending_messages.end();) - { - bool delete_entry = false ; - - if(it->second.data_status == RS_GROUTER_DATA_STATUS_DONE ) - { - if(!(it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_IS_DESTINATION) || it->second.received_time_TS + MAX_DESTINATION_KEEP_TIME < now) // is the item too old for cache - delete_entry = true ; - } - else if(it->second.data_status == RS_GROUTER_DATA_STATUS_RECEIPT_OK ) - { - if(it->second.received_time_TS + MAX_RECEIPT_KEEP_TIME < now) // is the item too old for cache - delete_entry = true ; - } - else - if(it->second.received_time_TS + GROUTER_ITEM_MAX_CACHE_KEEP_TIME < now) - delete_entry = true ; - - if(delete_entry) - { -#ifdef GROUTER_DEBUG - grouter_debug() << " Removing cached item " << std::hex << it->first << std::dec << std::endl; -#endif - //GRouterClientService *client = NULL ; - //GRouterServiceId service_id = 0; - - if( it->second.data_status != RS_GROUTER_DATA_STATUS_DONE ) - { - GRouterClientService *client = NULL; - - if(locked_getLocallyRegisteredClientFromServiceId(it->second.client_id,client)) - failed_msgs[it->first] = std::make_pair(client,it->second.data_item->signature.keyId) ; - else - std::cerr << " ERROR: client id " << it->second.client_id << " not registered. Consistency error." << std::endl; - } - - delete it->second.data_item ; - - if(it->second.receipt_item != NULL) - delete it->second.receipt_item ; - - std::map::iterator tmp(it) ; - ++tmp ; - _pending_messages.erase(it) ; - it = tmp ; - - items_deleted = true ; - } - else - ++it ; - } - - // also check all existing tunnels - - for(std::map::iterator it = _tunnels.begin();it!=_tunnels.end();++it) - { - std::list vpids_to_remove ; - for(std::set::iterator it2 = it->second.virtual_peers.begin();it2!=it->second.virtual_peers.end();++it2) - if(!mTurtle->isTurtlePeer(*it2)) - { - vpids_to_remove.push_back(*it2) ; -#ifdef GROUTER_DEBUG - std::cerr << " " << *it2 << " is not an active tunnel for hash " << it->first << ". Removing virtual peer id." << std::endl; -#endif - } - - for(std::list::const_iterator it2=vpids_to_remove.begin();it2!=vpids_to_remove.end();++it2) - it->second.removeVirtualPeer(*it2) ; - } - - - // Also clean incoming data pipes - - for(std::map::iterator it(_incoming_data_pipes.begin());it!=_incoming_data_pipes.end();) - if(it->second.last_activity_TS + MAX_INACTIVE_DATA_PIPE_DELAY < now) - { -#ifdef GROUTER_DEBUG - std::cerr << " removing data pipe for peer " << it->first << " which is too old." << std::endl; -#endif - std::map::iterator ittmp = it ; - ++ittmp ; - it->second.clear() ; - _incoming_data_pipes.erase(it) ; - it = ittmp ; - } - else - ++it ; - - /* Cleanup timed out items in mMissingKeyQueue */ - mMissingKeyQueueMtx.lock(); - while( mMissingKeyQueue.begin() != mMissingKeyQueue.end() && - mMissingKeyQueue.front().second <= now ) - { - RsWarn() << __PRETTY_FUNCTION__ << " Deleting timed out item from " - << "unknown RsGxsId: " - << mMissingKeyQueue.front().first->signature.keyId - << std::endl; - mMissingKeyQueue.pop_front(); - } - mMissingKeyQueueMtx.unlock(); - } - // Look into pending items. - - for(std::map >::const_iterator it(failed_msgs.begin());it!=failed_msgs.end();++it) - { -#ifdef GROUTER_DEBUG - std::cerr << " notifying client for message id " << std::hex << it->first << " state = FAILED" << std::endl; -#endif - it->second.first->notifyDataStatus(it->first,it->second.second ,GROUTER_CLIENT_SERVICE_DATA_STATUS_FAILED) ; - } - - if(items_deleted) - _changed = true ; -} - -bool p3GRouter::sliceDataItem(RsGRouterAbstractMsgItem *item,std::list& chunks) -{ - try - { - // Split the item into chunks. This function ensures that chunks in the list are valid. Memory ownership is left to the - // calling client. In case of error, all allocated memory is deleted. - -#ifdef GROUTER_DEBUG - std::cerr << "p3GRouter::sliceDataItem()" << std::endl; - std::cerr << "item dump before send:" << std::endl; - item->print(std::cerr, 2) ; -#endif - - uint32_t size = RsGRouterSerialiser().size(item); - - RsTemporaryMemory data(size) ; // data will be freed on return, whatever the route taken. - - if(data == NULL) - { - std::cerr << " ERROR: cannot allocate memory. Size=" << size << std::endl; - throw ; - } - - if(!RsGRouterSerialiser().serialise(item,data,&size)) - { - std::cerr << " ERROR: cannot serialise." << std::endl; - throw ; - } - - uint32_t offset = 0 ; - static const uint32_t CHUNK_SIZE = 15000 ; - - while(offset < size) - { - uint32_t chunk_size = std::min(size - offset, CHUNK_SIZE) ; - - RsGRouterTransactionChunkItem *chunk_item = new RsGRouterTransactionChunkItem ; - - chunk_item->propagation_id = item->routing_id ; - chunk_item->total_size = size; - chunk_item->chunk_start= offset; - chunk_item->chunk_size = chunk_size ; - chunk_item->chunk_data = (uint8_t*)rs_malloc(chunk_size) ; -#ifdef GROUTER_DEBUG - std::cerr << " preparing to send a chunk [" << offset << " -> " << offset + chunk_size << " / " << size << "]" << std::endl; -#endif - - if(chunk_item->chunk_data == NULL) - { - delete chunk_item; - throw ; - } - memcpy(chunk_item->chunk_data,&data[offset],chunk_size) ; - - offset += chunk_size ; - - chunks.push_back(chunk_item) ; - } - - return true ; - } - catch(...) - { - for(std::list::const_iterator it(chunks.begin());it!=chunks.end();++it) - delete *it ; - - chunks.clear() ; - - return false ; - } -} - -void p3GRouter::handleIncoming() -{ - while(!_incoming_items.empty()) - { - RsGRouterAbstractMsgItem *item = _incoming_items.front() ; - _incoming_items.pop_front() ; - - handleIncomingItem(item); - delete item ; - } -} - -void p3GRouter::handleIncomingItem(const RsGRouterAbstractMsgItem *item) -{ - const RsGRouterGenericDataItem *generic_data_item ; - const RsGRouterSignedReceiptItem *receipt_item ; - - if(NULL != (generic_data_item = dynamic_cast(item))) - handleIncomingDataItem(generic_data_item) ; - else if(NULL != (receipt_item = dynamic_cast(item))) - handleIncomingReceiptItem(receipt_item) ; - else - std::cerr << "Item has unknown type (not data nor signed receipt). Dropping!" << std::endl; -} - -void p3GRouter::handleIncomingReceiptItem(const RsGRouterSignedReceiptItem *receipt_item) -{ - bool changed = false ; -#ifdef GROUTER_DEBUG - std::cerr << "Handling incoming signed receipt item." << std::endl; - std::cerr << "Item content:" << std::endl; - const_cast(receipt_item)->print(std::cerr,2) ; -#endif - RsGxsId signer_id ; - - // Because we don't do proxy-transmission yet, the client needs to be notified. Otherwise, we will need to - // first check if we're a proxy or not. We also remove the message from the global router sending list. - // in the proxy case, we should only store the receipt. - - GRouterClientService *client_service = NULL; - GRouterMsgPropagationId mid = 0 ; - - { - RS_STACK_MUTEX (grMtx) ; - - std::map::iterator it=_pending_messages.find(receipt_item->routing_id) ; - if(it == _pending_messages.end()) - { - std::cerr << " ERROR: no routing ID corresponds to this message. Inconsistency!" << std::endl; - return ; - } - signer_id = it->second.data_item->signature.keyId ; - - // check hash. - - if(receipt_item->data_hash != it->second.item_hash) - { - std::cerr << " checking receipt hash : FAILED. Receipt is dropped." << std::endl; - return ; - } -#ifdef GROUTER_DEBUG - else - std::cerr << " checking receipt hash : OK" << std::endl; -#endif - // check signature. The policy if the following: - // if we're the destination: - // signature should check and signing key should be available // always ensures the receipt is valid - // else - // if key is available, signature should check // early protects against frodulent receipts that we can check - - uint32_t error_status ; - - if(! verifySignedDataItem(receipt_item,RsIdentityUsage::GLOBAL_ROUTER_SIGNATURE_CHECK,error_status)) - if( (it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_IS_ORIGIN) || (error_status != RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE)) - { - std::cerr << " checking receipt signature : FAILED. Receipt is dropped. Error status=" << error_status << std::endl; - return ; - } -#ifdef GROUTER_DEBUG - std::cerr << " checking receipt signature : OK. " << std::endl; - std::cerr << " removing messsage from cache." << std::endl; -#endif - - if(it->second.routing_flags & GRouterRoutingInfo::ROUTING_FLAGS_IS_ORIGIN) - { -#ifdef GROUTER_DEBUG - std::cerr << " message is at origin. Setting message transmission to DONE" << std::endl; -#endif - it->second.data_status = RS_GROUTER_DATA_STATUS_DONE; - - if(locked_getLocallyRegisteredClientFromServiceId(it->second.client_id,client_service)) - mid = it->first ; - else - { - mid = 0 ; - std::cerr << " ERROR: cannot retrieve service ID for message " << std::hex << it->first << std::dec << std::endl; - } - } - else - { -#ifdef GROUTER_DEBUG - std::cerr << " message is not at origin. Setting message transmission to RECEIPT_OK" << std::endl; -#endif - it->second.data_status = RS_GROUTER_DATA_STATUS_RECEIPT_OK; - it->second.receipt_item = receipt_item->duplicate() ; - } - - changed = true ; - } - - if(mid != 0) - { -#ifdef GROUTER_DEBUG - std::cerr << " notifying client " << (void*)client_service << " that msg " << std::hex << mid << std::dec << " was received." << std::endl; -#endif - client_service->notifyDataStatus(mid, signer_id, GROUTER_CLIENT_SERVICE_DATA_STATUS_RECEIVED) ; - } - - // also note the incoming route in the routing matrix - - if(!mTurtle->isTurtlePeer(receipt_item->PeerId())) - { -#ifdef GROUTER_DEBUG - std::cerr << " receipt item comes from a direct friend. Marking route in routing matrix." << std::endl; -#endif - addRoutingClue(receipt_item->signature.keyId,receipt_item->PeerId()) ; - } - - if(changed) - IndicateConfigChanged() ; -} - -Sha1CheckSum p3GRouter::computeDataItemHash(const RsGRouterGenericDataItem *data_item) -{ - RsGRouterSerialiser signature_serializer( - RsSerializationFlags::SIGNATURE | - RsSerializationFlags::SKIP_HEADER ); - - uint32_t signed_data_size = signature_serializer.size(const_cast(data_item)); - uint32_t total_size = signed_data_size + data_item->signature.TlvSize() ; - RsTemporaryMemory mem(total_size) ; - - uint32_t offset = 0 ; - uint32_t tmp_size = total_size ; - signature_serializer.serialise(const_cast(data_item),mem,&tmp_size) ; - if(tmp_size != signed_data_size) - std::cerr << "(EE) Some error occured in p3GRouter::computeDataItemHash(). Mismatched offset/data size" << std::endl; - - offset += tmp_size ; - - data_item->signature.SetTlv(mem, total_size,&offset) ; - - if(offset != total_size) - std::cerr << "(EE) Some error occured in p3GRouter::computeDataItemHash(). Mismatched offset/data size" << std::endl; - - return RsDirUtil::sha1sum(mem,total_size) ; -} - -void p3GRouter::handleIncomingDataItem(const RsGRouterGenericDataItem *data_item) -{ -#ifdef GROUTER_DEBUG - std::cerr << "Handling incoming data item. " << std::endl; - std::cerr << "Item content:" << std::endl; - const_cast(data_item)->print(std::cerr,2) ; -#endif - - // we find 3 things: - // A - is the item for us ? - // B - signature and hash check ? - // C - item is already known ? - - // Store the item? if !C - // Send a receipt? if A && B - // Notify client? if A && !C - // - GRouterClientService *clientService = NULL ; - GRouterServiceId service_id = data_item->service_id ; - RsGRouterSignedReceiptItem *receipt_item = NULL ; - - Sha1CheckSum item_hash = computeDataItemHash(data_item) ; - - bool item_is_already_known = false ; - bool cache_has_changed = false ; - bool item_is_for_us = _owned_key_ids.find( makeTunnelHash(data_item->destination_key,service_id) ) != _owned_key_ids.end() ; - - // A - Find client and service ID from destination key. -#ifdef GROUTER_DEBUG - std::cerr << " step A: find if the item is for us or not, and whether it's aready in cache or not." << std::endl; -#endif - { - RS_STACK_MUTEX(grMtx) ; - - // also check wether this item is for us or not - -#ifdef GROUTER_DEBUG - std::cerr << " item is " << (item_is_for_us?"":"not") << " for us." << std::endl; -#endif - auto it = _pending_messages.find(data_item->routing_id) ; - - if(it != _pending_messages.end()) - { - if(it->second.item_hash != item_hash) - { -#ifdef GROUTER_DEBUG - std::cerr << " ERROR: item is already known but data hash does not match. Dropping that item." << std::endl; -#endif - return ; - } - item_is_already_known = true ; - receipt_item = it->second.receipt_item ; -#ifdef GROUTER_DEBUG - std::cerr << " item is already in cache." << std::endl; -#endif - } -#ifdef GROUTER_DEBUG - else - std::cerr << " item is new." << std::endl; -#endif - } - - if(!item_is_already_known) - { - uint32_t error_status ; - - if(!verifySignedDataItem(data_item,RsIdentityUsage::GLOBAL_ROUTER_SIGNATURE_CHECK,error_status)) // we should get proper flags out of this - { - switch(error_status) - { - case RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE: - { - RS_STACK_MUTEX(mMissingKeyQueueMtx); - - rstime_t timeout = time(nullptr) + mMissingKeyQueueEntryTimeout; - RsGxsId authorId = data_item->signature.keyId; - mMissingKeyQueue.push_back( std::make_pair(std::unique_ptr(data_item->duplicate()), timeout) ); - - /* Do not request the missing key here to the peer which forwarded the item as verifySignedDataItem(...) does it already */ - - RsInfo() << __PRETTY_FUNCTION__ << " Received a message from unknown RsGxsId: " << authorId <<". Cannot verify signature yet, storing in mMissingKeyQueue for later processing. Timeout: " << timeout << std::endl; - return; - } - default: - RsWarn() << __PRETTY_FUNCTION__ << " item signature verification FAILED with: " << error_status << ", Dropping!" << std::endl; - return; - } - } -#ifdef GROUTER_DEBUG - else - std::cerr << " verifying item signature: CHECKED!" ; -#endif - } - - // At this point, if item is already known, it is guarrantied to be identical to the stored item. - // If the item is for us, and not already known, check the signature and hash, and generate a signed receipt - - if(item_is_for_us && !item_is_already_known) - { - // Check that we actually have a registered service ready to accept this item. If not, drop it. - - { - RS_STACK_MUTEX(grMtx) ; - auto its = _registered_services.find(service_id) ; - - if(its != _registered_services.end()) - clientService = its->second ; - } - -#ifdef GROUTER_DEBUG - std::cerr << " step B: item is for us and is new, so make sure it's authentic and create a receipt" << std::endl; -#endif - // No we need to send a signed receipt to the sender. - - receipt_item = new RsGRouterSignedReceiptItem; - receipt_item->data_hash = item_hash ; - receipt_item->service_id = data_item->service_id ; - receipt_item->routing_id = data_item->routing_id ; - receipt_item->destination_key = data_item->signature.keyId ; - receipt_item->flags = RsGRouterItemFlags::NONE ; - - if(!clientService) - { - receipt_item->flags = RsGRouterItemFlags::SERVICE_UNKNOWN; - RsWarn() << __PRETTY_FUNCTION__ << " got a message from: " << data_item->signature.keyId << " for an unkown service: " << data_item->service_id << " is your RetroShare version updated?" << std::endl; - } - -#ifdef GROUTER_DEBUG - std::cerr << " preparing signed receipt." << std::endl; -#endif - - if(!signDataItem(receipt_item,data_item->destination_key)) - { - std::cerr << " signing: FAILED. Receipt dropped. ERROR. Packet dropped as well." << std::endl; - return ; - } -#ifdef GROUTER_DEBUG - std::cerr << " signing: OK." << std::endl; -#endif - } -#ifdef GROUTER_DEBUG - else - std::cerr << " step B: skipped, since item is not for us, or already known." << std::endl; -#endif - - // now store the item in _pending_messages whether it is for us or not (if the item is for us, this prevents receiving multiple - // copies of the message) -#ifdef GROUTER_DEBUG - std::cerr << " step C: store the item is cache." << std::endl; -#endif - { - RS_STACK_MUTEX(grMtx) ; - - GRouterRoutingInfo& info(_pending_messages[data_item->routing_id]) ; - - if(info.data_item == NULL) // item is not for us - { -#ifdef GROUTER_DEBUG - std::cerr << " item is new. Storing it." << std::endl; -#endif - - info.data_item = data_item->duplicate() ; - info.receipt_item = receipt_item ; // inited before, or NULL. - info.tunnel_status = RS_GROUTER_TUNNEL_STATUS_UNMANAGED ; - info.last_sent_TS = 0 ; - info.client_id = data_item->service_id ; - info.item_hash = item_hash ; - info.last_tunnel_request_TS = 0 ; - info.sending_attempts = 0 ; - info.received_time_TS = time(NULL) ; - info.tunnel_hash = makeTunnelHash(data_item->destination_key,data_item->service_id) ; - - if(item_is_for_us) - { - // don't store if item is for us. No need to take that much memory. - - free(info.data_item->data_bytes) ; - info.data_item->data_size = 0 ; - info.data_item->data_bytes = NULL ; - - info.routing_flags = GRouterRoutingInfo::ROUTING_FLAGS_IS_DESTINATION | GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_FRIENDS ; - info.data_status = RS_GROUTER_DATA_STATUS_RECEIPT_OK ; - } - else - { - info.routing_flags = GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_FRIENDS ; // don't allow tunnels just yet - info.data_status = RS_GROUTER_DATA_STATUS_PENDING ; - } - } -#ifdef GROUTER_DEBUG - else - std::cerr << " item is already in cache." << std::endl; - - std::cerr << " storing incoming route from " << data_item->PeerId() << std::endl; -#endif - info.incoming_routes.ids.insert(data_item->PeerId()) ; - cache_has_changed = true ; - } - - // if the item is for us and is not already known, notify the client. - - if(clientService && !item_is_already_known) - { - // compute the hash before decryption. - -#ifdef GROUTER_DEBUG - std::cerr << " step D: item is for us and is new: decrypting and notifying client." << std::endl; -#endif - RsGRouterGenericDataItem *decrypted_item = data_item->duplicate() ; - - if(!decryptDataItem(decrypted_item)) - { - std::cerr << " decrypting item : FAILED! Item cannot be passed to the client." << std::endl; - delete decrypted_item ; - - return ; - } -#ifdef GROUTER_DEBUG - else - std::cerr << " decrypting item : OK!" << std::endl; - - std::cerr << " notyfying client." << std::endl; -#endif - if(clientService->acceptDataFromPeer(decrypted_item->signature.keyId)) - { - clientService->receiveGRouterData(decrypted_item->destination_key,decrypted_item->signature.keyId,service_id,decrypted_item->data_bytes,decrypted_item->data_size); - - decrypted_item->data_bytes = NULL ; - decrypted_item->data_size = 0 ; - } - - delete decrypted_item ; - } -#ifdef GROUTER_DEBUG - else - std::cerr << " step D: item is not for us or not new: skipping this step." << std::endl; -#endif - - if(cache_has_changed) - IndicateConfigChanged() ; -} - -bool p3GRouter::locked_getLocallyRegisteredClientFromServiceId(const GRouterServiceId& service_id,GRouterClientService *& client) -{ - client = NULL ; - - std::map::const_iterator its = _registered_services.find(service_id) ; - - if(its == _registered_services.end()) - { - std::cerr << " ERROR: client id " << service_id << " not registered. Consistency error." << std::endl; - return false; - } - - client = its->second ; - - return true ; -} - -void p3GRouter::addRoutingClue(const RsGxsId& id, const RsPeerId& peer_id) -{ - RS_STACK_MUTEX(grMtx) ; -#ifdef GROUTER_DEBUG - grouter_debug() << "Received new routing clue for key " << id << " from peer " << peer_id << std::endl; -#endif - _routing_matrix.addRoutingClue(id,peer_id,RS_GROUTER_BASE_WEIGHT_GXS_PACKET) ; - _changed = true ; -} - -bool p3GRouter::registerClientService(const GRouterServiceId& id,GRouterClientService *service) -{ - RS_STACK_MUTEX(grMtx) ; - _registered_services[id] = service ; - return true ; -} - -bool p3GRouter::encryptDataItem(RsGRouterGenericDataItem *item,const RsGxsId& destination_key) -{ - assert(!(item->flags & RsGRouterItemFlags::ENCRYPTED)); - -#ifdef GROUTER_DEBUG - std::cerr << " Encrypting data for key " << destination_key << std::endl; - std::cerr << " Decrypted size = " << item->data_size << std::endl; -#endif - - uint8_t *encrypted_data =NULL; - uint32_t encrypted_size =0; - uint32_t error_status ; - - if(!mGixs->encryptData( item->data_bytes, item->data_size, encrypted_data, - encrypted_size, destination_key, error_status, - true )) - { - std::cerr << "(EE) Cannot encrypt: " ; - if(error_status == RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE) std::cerr << " key not available for ID = " << destination_key << std::endl; - if(error_status == RsGixs::RS_GIXS_ERROR_UNKNOWN ) std::cerr << " unknown error for ID = " << destination_key << std::endl; - - return false ; - } - - free(item->data_bytes) ; - item->data_bytes = encrypted_data ; - item->data_size = encrypted_size ; - item->flags |= RsGRouterItemFlags::ENCRYPTED; - -#ifdef GROUTER_DEBUG - std::cerr << " Encrypted size = " << encrypted_size << std::endl; - std::cerr << " First bytes of encrypted data: " << RsUtil::BinToHex((const char *)encrypted_data,std::min(encrypted_size,30u)) << "..."<< std::endl; - std::cerr << " Encrypted data hash = " << RsDirUtil::sha1sum((const uint8_t *)encrypted_data,encrypted_size) << std::endl; -#endif -return true ; -} -bool p3GRouter::decryptDataItem(RsGRouterGenericDataItem *item) -{ - assert(!!(item->flags & RsGRouterItemFlags::ENCRYPTED)); - -#ifdef GROUTER_DEBUG - std::cerr << " decrypting data for key " << item->destination_key << std::endl; - std::cerr << " encrypted size = " << item->data_size << std::endl; -#endif - - uint8_t *decrypted_data =NULL; - uint32_t decrypted_size =0; - uint32_t error_status ; - - if(!mGixs->decryptData( item->data_bytes, item->data_size, decrypted_data, - decrypted_size, item->destination_key, error_status, - true )) - { - if(error_status == RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE) - std::cerr << "(EE) Cannot decrypt incoming message. Key " << item->destination_key << " unknown." << std::endl; - else - std::cerr << "(EE) Cannot decrypt incoming message. Unknown error. " << std::endl; - - return false ; - } - - free(item->data_bytes) ; - item->data_bytes = decrypted_data ; - item->data_size = decrypted_size ; - item->flags &= ~RsGRouterItemFlags::ENCRYPTED; - - return true ; -} - -bool p3GRouter::signDataItem(RsGRouterAbstractMsgItem *item,const RsGxsId& signing_id) -{ - try - { -//#ifdef GROUTER_DEBUG - std::cerr << "p3GRouter::signDataItem()" << std::endl; - std::cerr << " Key ID = " << signing_id << std::endl; - std::cerr << " Getting key material..." << std::endl; -//#endif - RsGRouterSerialiser signature_serializer( - RsSerializationFlags::SIGNATURE | - RsSerializationFlags::SKIP_HEADER ); - uint32_t data_size = signature_serializer.size(item) ; - RsTemporaryMemory data(data_size) ; - - if(data == NULL) - throw std::runtime_error("Cannot allocate memory for signing data.") ; - - if(!signature_serializer.serialise(item,data,&data_size)) - throw std::runtime_error("Cannot serialise signed data.") ; - - uint32_t error_status ; - - std::cerr << "GRouter::signing data" << std::endl; - std::cerr << " size: " << data_size << std::endl; - std::cerr << " data: " << RsUtil::BinToHex(data,data_size) << std::endl; - - if(!mGixs->signData(data,data_size,signing_id,item->signature,error_status)) - throw std::runtime_error("Cannot sign for id " + signing_id.toStdString() + ". Signature call failed.") ; - -//#ifdef GROUTER_DEBUG - std::cerr << "Created signature for data hash: " << RsDirUtil::sha1sum(data,data_size) << " and key id=" << signing_id << std::endl; -//#endif - // Check signature - RsIdentityUsage::UsageCode info = RsIdentityUsage::GLOBAL_ROUTER_SIGNATURE_CREATION; - uint32_t error; - - if(verifySignedDataItem(item,info,error)) - std::cerr << "Signature checks." << std::endl; - else - { - std::cerr << "(EE) Cannot verify own signed item. Something's wrong." << std::endl; - return false ; - } - - return true ; - } - catch(std::exception& e) - { - std::cerr << " signing failed. Error: " << e.what() << std::endl; - - item->signature.TlvClear() ; - return false ; - } -} -bool p3GRouter::verifySignedDataItem(const RsGRouterAbstractMsgItem *item,const RsIdentityUsage::UsageCode& info,uint32_t& error_status) -{ - try - { - if( rsReputations->overallReputationLevel(item->signature.keyId) == - RsReputationLevel::LOCALLY_NEGATIVE ) - { - RsWarn() << __PRETTY_FUNCTION__ << " received global router " - << "message from banned identity " << item->signature.keyId - << ". Rejecting the message." << std::endl; - return false; - } - - RsGRouterSerialiser signature_serializer( - RsSerializationFlags::SIGNATURE | - RsSerializationFlags::SKIP_HEADER ); - - uint32_t data_size = signature_serializer.size(const_cast(item)); // the const cast shouldn't be necessary if size() took a const. - RsTemporaryMemory data(data_size); - - if(data == NULL) - throw std::runtime_error("Cannot allocate data.") ; - - if(!signature_serializer.serialise(const_cast(item),data,&data_size)) - throw std::runtime_error("Cannot serialise signed data."); - - RsIdentityUsage use(RsServiceType::GROUTER,info); - - if(!mGixs->validateData( data, data_size, item->signature, true, use, error_status )) - { - switch(error_status) - { - case RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE: - { - std::list peer_ids; - peer_ids.push_back(item->PeerId()); - - RsWarn() << __PRETTY_FUNCTION__ << " Key for GXS Id " << item->signature.keyId << " is not available. Cannot verify. Asking key to peer " << item->PeerId() << std::endl; - mGixs->requestKey(item->signature.keyId,peer_ids,use); - } - break; - case RsGixs::RS_GIXS_ERROR_SIGNATURE_MISMATCH: - RsWarn() << __PRETTY_FUNCTION__ << " Signature mismatch. " << "Spoofing/Corrupted/MITM?." << std::endl; - break; - default: - RsErr() << __PRETTY_FUNCTION__ << " Signature verification failed on GRouter message. Unknown error status: " << error_status << std::endl; - break; - } - return false; - } - - return true; - } - catch(std::exception& e) - { - RsErr() << __PRETTY_FUNCTION__ << " Failed. Error: " << e.what() << std::endl; - return false ; - } -} - -bool p3GRouter::cancel(GRouterMsgPropagationId mid) -{ - { - RS_STACK_MUTEX(grMtx) ; - -#ifdef GROUTER_DEBUG - std::cerr << "p3GRouter::cancel(). Canceling message ID " << mid << std::endl; -#endif - - std::map::iterator it = _pending_messages.find(mid) ; - - if(it == _pending_messages.end()) - { - std::cerr << " ERROR: message ID is unknown." << std::endl; - return false ; - } - - delete it->second.data_item ; - if(it->second.receipt_item) - delete it->second.receipt_item; - - _pending_messages.erase(it) ; - } - - IndicateConfigChanged() ; - - return true ; -} - -bool p3GRouter::sendData( const RsGxsId& destination, const GRouterServiceId& client_id, const uint8_t* data, uint32_t data_size, const RsGxsId& signing_id, GRouterMsgPropagationId&propagation_id ) -{ -// std::cerr << "GRouter currently disabled." << std::endl; -// return false; - - if(data_size > MAX_GROUTER_DATA_SIZE) - { - std::cerr << "GRouter max size limit exceeded (size=" << data_size << ", max=" << MAX_GROUTER_DATA_SIZE << "). Please send a smaller object!" << std::endl; - return false ; - } - - // Make sure we have a unique id (at least locally). There's little chances that an id of the same value is out there anyway. - // - { - RsStackMutex mtx(grMtx) ; - do { propagation_id = RSRandom::random_u64(); } while(_pending_messages.find(propagation_id) != _pending_messages.end()) ; - } - - // create the signed data item - - RsGRouterGenericDataItem *data_item = new RsGRouterGenericDataItem ; - - data_item->data_bytes = (uint8_t*)rs_malloc(data_size) ; - - if(data_item->data_bytes == NULL) - return false ; - - memcpy(data_item->data_bytes,data,data_size) ; - - data_item->data_size = data_size ; - data_item->routing_id = propagation_id ; - data_item->duplication_factor = GROUTER_MAX_DUPLICATION_FACTOR ; - data_item->service_id = client_id ; - data_item->destination_key = destination ; - data_item->flags = RsGRouterItemFlags::NONE ; // this is unused for now. - - // First, encrypt. - - if(!encryptDataItem(data_item,destination)) - { - std::cerr << "Cannot encrypt data item. Some error occured!" << std::endl; - delete data_item; - return false; - } - - // Then, sign the encrypted data, so that the signature can be checked by non priviledged users. - - if(!signDataItem(data_item,signing_id)) - { - std::cerr << "Cannot sign data item. Some error occured!" << std::endl; - delete data_item; - return false; - } - - // Verify the signature. If that fails, there's a bug somewhere!! - uint32_t error_status; - - if(!verifySignedDataItem(data_item,RsIdentityUsage::GLOBAL_ROUTER_SIGNATURE_CREATION,error_status)) - { - std::cerr << "Cannot verify data item that was just signed. Some error occured!" << std::endl; - delete data_item; - return false; - } - // push the item into pending messages. - // - GRouterRoutingInfo info ; - - rstime_t now = time(NULL) ; - - info.data_item = data_item ; - info.receipt_item = NULL ; - info.data_status = RS_GROUTER_DATA_STATUS_PENDING ; - info.tunnel_status = RS_GROUTER_TUNNEL_STATUS_UNMANAGED ; - info.last_sent_TS = 0 ; - info.client_id = client_id ; - info.last_tunnel_request_TS = 0 ; - info.item_hash = computeDataItemHash(data_item) ; - info.sending_attempts = 0 ; - info.routing_flags = GRouterRoutingInfo::ROUTING_FLAGS_IS_ORIGIN | GRouterRoutingInfo::ROUTING_FLAGS_ALLOW_FRIENDS ;// don't allow tunnels just yet - info.received_time_TS = now ; - info.tunnel_hash = makeTunnelHash(destination,client_id) ; - -#ifdef GROUTER_DEBUG - grouter_debug() << "p3GRouter::sendGRouterData(): pushing the following item in the msg pending list:" << std::endl; - grouter_debug() << " routing id = " << std::hex << propagation_id << std::dec << std::endl; - grouter_debug() << " data_item.size = " << info.data_item->data_size << std::endl; - grouter_debug() << " data_item.byte = " << RsDirUtil::sha1sum(info.data_item->data_bytes,info.data_item->data_size) << std::endl; - grouter_debug() << " destination = " << data_item->destination_key << std::endl; - grouter_debug() << " signed by key = " << data_item->signature.keyId << std::endl; - grouter_debug() << " data status = " << info.data_status << std::endl; - grouter_debug() << " tunnel status = " << info.tunnel_status << std::endl; - grouter_debug() << " sending attempt= " << info.sending_attempts << std::endl; - grouter_debug() << " duplicate fact = " << info.data_item->duplication_factor << std::endl; - grouter_debug() << " recv time = " << info.received_time_TS << std::endl; - grouter_debug() << " client id = " << std::hex << data_item->service_id << std::dec << std::endl; - grouter_debug() << " tunnel hash = " << info.tunnel_hash << std::endl; - grouter_debug() << " item hash = " << info.item_hash << std::endl; - grouter_debug() << " routing flags = " << info.routing_flags << std::endl; -#endif - - { - RS_STACK_MUTEX(grMtx) ; - _pending_messages[propagation_id] = info ; - } - IndicateConfigChanged() ; - -return true ; -} - -Sha1CheckSum p3GRouter::makeTunnelHash(const RsGxsId& destination,const GRouterServiceId& client) -{ - static_assert( RsGxsId::SIZE_IN_BYTES == 16, - "This function breaks if RsGxsId size changes" ); - static_assert( Sha1CheckSum::SIZE_IN_BYTES == 20, - "This function breaks if Sha1CheckSum size changes" ); - static_assert( sizeof(client) == 4, - "This function breaks if client service id size changes" ); - - uint8_t bytes[20] ; - memcpy(bytes,destination.toByteArray(),16) ; - bytes[16] = 0 ; - bytes[17] = 0 ; - bytes[18] = (client >> 8) & 0xff ; - bytes[19] = client & 0xff ; - - return RsDirUtil::sha1sum(bytes,20) ; -} -bool p3GRouter::loadList(std::list& items) -{ - { - RS_STACK_MUTEX(grMtx) ; - -#ifdef GROUTER_DEBUG - grouter_debug() << "p3GRouter::loadList() : " << std::endl; -#endif - - _routing_matrix.loadList(items) ; - -#ifdef GROUTER_DEBUG - // remove all existing objects. - // - grouter_debug() << " removing all existing items (" << _pending_messages.size() << " items to delete)." << std::endl; -#endif - - if(!_pending_messages.empty()) - std::cerr << " WARNING: pending msg list is not empty. List will be cleared." << std::endl; - - // clear the existing list. - // - for(std::map::iterator it(_pending_messages.begin());it!=_pending_messages.end();++it) - delete it->second.data_item ; - - _pending_messages.clear() ; - - for(std::list::const_iterator it(items.begin());it!=items.end();++it) - { - RsGRouterRoutingInfoItem *itm1 = NULL ; - - if(NULL != (itm1 = dynamic_cast(*it))) - { - // clean data state - itm1->tunnel_status = RS_GROUTER_TUNNEL_STATUS_UNMANAGED ; - - _pending_messages[itm1->data_item->routing_id] = *itm1 ; - - itm1->data_item = NULL ; // prevents deletion. - itm1->receipt_item = NULL ; // prevents deletion. - } - - delete *it ; - } - } -#ifdef GROUTER_DEBUG - debugDump(); -#endif - items.clear() ; - return true ; -} -bool p3GRouter::saveList(bool& cleanup,std::list& items) -{ - // We save - // - the routing clues - // - the pending items - - cleanup = true ; // the client should delete the items. - -#ifdef GROUTER_DEBUG - grouter_debug() << "p3GRouter::saveList()..." << std::endl; - grouter_debug() << " saving routing clues." << std::endl; -#endif - - RS_STACK_MUTEX(grMtx) ; - - _routing_matrix.saveList(items) ; - -#ifdef GROUTER_DEBUG - grouter_debug() << " saving pending items." << std::endl; -#endif - - for(std::map::const_iterator it(_pending_messages.begin());it!=_pending_messages.end();++it) - { - RsGRouterRoutingInfoItem *item = new RsGRouterRoutingInfoItem ; - -#warning: Cppcheck(cstyleCast): C-style pointer casting - // cppcheck-suppress cstyleCast - *(GRouterRoutingInfo*)item = it->second ; // copy all members - - item->data_item = it->second.data_item->duplicate() ; // deep copy, because we call delete on the object, and the item might be removed before we handle it in the client. - if(it->second.receipt_item != NULL) - item->receipt_item = it->second.receipt_item->duplicate() ; - - items.push_back(item) ; - } - - return true ; -} - -bool p3GRouter::getRoutingMatrixInfo(RsGRouter::GRouterRoutingMatrixInfo& info) -{ - RS_STACK_MUTEX(grMtx) ; - - info.per_friend_probabilities.clear() ; - info.friend_ids.clear() ; - info.published_keys.clear() ; - - std::list ids ; - //mServiceControl->getPeersConnected(getServiceInfo().mServiceType,ids) ; - rsPeers->getFriendList(ids) ; - - info.published_keys = _owned_key_ids ; - - for(std::list::const_iterator it(ids.begin());it!=ids.end();++it) - info.friend_ids.push_back(*it) ; - - std::vector known_keys ; - std::vector probas ; - float maximum= 0.0f; - _routing_matrix.getListOfKnownKeys(known_keys) ; - - for(uint32_t i=0;i& infos) -{ - RS_STACK_MUTEX(grMtx) ; - - infos.clear() ; - - for(std::map::const_iterator it(_pending_messages.begin());it!=_pending_messages.end();++it) - { - GRouterRoutingCacheInfo cinfo ; - - cinfo.mid = it->first ; - cinfo.local_origin = it->second.incoming_routes.ids ; - cinfo.destination = it->second.data_item->destination_key ; - cinfo.duplication_factor = it->second.data_item->duplication_factor ; - cinfo.routing_time = it->second.received_time_TS ; - cinfo.last_tunnel_attempt_time = it->second.last_tunnel_request_TS ; - cinfo.last_sent_time = it->second.last_sent_TS ; - cinfo.receipt_available = (it->second.receipt_item != NULL); - cinfo.data_status = it->second.data_status ; - cinfo.tunnel_status = it->second.tunnel_status ; - cinfo.data_size = it->second.data_item->data_size ; - cinfo.item_hash = it->second.item_hash; - - infos.push_back(cinfo) ; - } - return true ; -} - -// Dump everything -// -void p3GRouter::debugDump() -{ - RS_STACK_MUTEX(grMtx) ; - - rstime_t now = time(NULL) ; - - grouter_debug() << "Full dump of Global Router state: " << std::endl; - grouter_debug() << " Owned keys : " << std::endl; - - for(std::map::const_iterator it(_owned_key_ids.begin());it!=_owned_key_ids.end();++it) - { - grouter_debug() << " Hash : " << it->first << std::endl; - grouter_debug() << " Key : " << it->second.authentication_key << std::endl; - grouter_debug() << " Service id : " << std::hex << it->second.service_id << std::dec << std::endl; - grouter_debug() << " Description : " << it->second.description_string << std::endl; - } - - grouter_debug() << " Registered services: " << std::endl; - - for(std::map::const_iterator it(_registered_services.begin() );it!=_registered_services.end();++it) - grouter_debug() << " " << std::hex << it->first << " " << std::dec << (void*)it->second << std::endl; - - grouter_debug() << " Data items: " << std::endl; - - static const std::string statusString[6] = { "Unkn","Pend","Sent","Receipt OK","Ongoing","Done" }; - - for(std::map::iterator it(_pending_messages.begin());it!=_pending_messages.end();++it) - { - grouter_debug() << " Msg id: " << std::hex << it->first << std::dec ; - grouter_debug() << " data hash: " << it->second.item_hash ; - grouter_debug() << " client: " << std::hex << it->second.client_id << std::dec; - grouter_debug() << " Flags: " << std::hex << it->second.routing_flags << std::dec; - grouter_debug() << " Dest: " << it->second.data_item->destination_key ; - grouter_debug() << " Recd: " << now - it->second.received_time_TS << " secs ago."; - grouter_debug() << " Sent: " << now - it->second.last_sent_TS << " secs ago."; - grouter_debug() << " Trans. TS: " << now - it->second.data_transaction_TS << " secs ago." ; - grouter_debug() << " Data Status: " << statusString[it->second.data_status] ; - grouter_debug() << " Tunl Status: " << statusString[it->second.tunnel_status] ; - grouter_debug() << " Receipt ok: " << (it->second.receipt_item != NULL) ; - grouter_debug() << " Dup: " << it->second.data_item->duplication_factor << std::endl; - } - - grouter_debug() << " Tunnels: " << std::endl; - - for(std::map::const_iterator it(_tunnels.begin());it!=_tunnels.end();++it) - { - grouter_debug() << " hash: " << it->first << ", first received: " << now - it->second.last_tunnel_ok_TS << " (secs ago), last received: " << now - it->second.last_tunnel_ok_TS << std::endl; - - for(std::set::const_iterator it2 = it->second.virtual_peers.begin();it2!=it->second.virtual_peers.end();++it2) - grouter_debug() << " " << (*it2) << std::endl; - } - - grouter_debug() << " Incoming data pipes: " << std::endl; - - for(std::map::const_iterator it(_incoming_data_pipes.begin());it!=_incoming_data_pipes.end();++it) - if(it->second.incoming_data_buffer != NULL) - grouter_debug() << " " << it->first << ": offset=" << it->second.incoming_data_buffer->chunk_start << " size=" << it->second.incoming_data_buffer->chunk_size << " over " << it->second.incoming_data_buffer->total_size << std::endl; - else - grouter_debug() << " " << it->first << " empty." << std::endl; - - grouter_debug() << " Routing matrix: " << std::endl; - - // if(_debug_enabled) - // _routing_matrix.debugDump() ; -} - - - - diff --git a/libretroshare/src/grouter/p3grouter.h b/libretroshare/src/grouter/p3grouter.h deleted file mode 100644 index 236c8b7a5..000000000 --- a/libretroshare/src/grouter/p3grouter.h +++ /dev/null @@ -1,374 +0,0 @@ -/******************************************************************************* - * libretroshare/src/grouter: p3grouter.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include - -#include "retroshare/rsgrouter.h" -#include "retroshare/rstypes.h" -#include "retroshare/rstypes.h" -#include "retroshare/rsidentity.h" - -#include "turtle/turtleclientservice.h" -#include "services/p3service.h" -#include "pqi/p3cfgmgr.h" -#include "util/rsdebug.h" -#include "groutertypes.h" -#include "groutermatrix.h" -#include "grouteritems.h" - -// To be put in pqi/p3cfgmgr.h -static const uint32_t CONFIG_TYPE_GROUTER = 0x0016 ; - -class p3LinkMgr ; -class p3turtle ; -class RsGixs ; -class RsGRouterItem ; -class RsGRouterGenericDataItem ; -class RsGRouterSignedReceiptItem ; -class RsGRouterAbstractMsgItem ; -class RsGRouterTransactionItem ; -class RsGRouterTransactionAcknItem ; - -// This class is responsible for accepting data chunks and merging them into a final object. When the object is -// complete, it is de-serialised and returned as a RsGRouterGenericDataItem*. - -class GRouterTunnelInfo -{ -public: - GRouterTunnelInfo() :first_tunnel_ok_TS(0), last_tunnel_ok_TS(0) {} - - // These two methods handle the memory management of buffers for each virtual peers. - - void addVirtualPeer(const TurtleVirtualPeerId& vpid) ; - void removeVirtualPeer(const TurtleVirtualPeerId& vpid) ; - - std::set virtual_peers ; - - rstime_t first_tunnel_ok_TS ; // timestamp when 1st tunnel was received. - rstime_t last_tunnel_ok_TS ; // timestamp when last tunnel was received. -}; -class GRouterDataInfo -{ - // ! This class does not have a copy constructor that duplicates the incoming data buffer. This is on purpose! -public: - GRouterDataInfo() : last_activity_TS(0) - { - incoming_data_buffer = NULL ; - } - - void clear() { if(incoming_data_buffer!=NULL) delete incoming_data_buffer ; incoming_data_buffer = NULL ;} - - // These two methods handle the memory management of buffers for each virtual peers. - - RsGRouterAbstractMsgItem *addDataChunk(RsGRouterTransactionChunkItem *chunk_item) ; - RsGRouterTransactionChunkItem *incoming_data_buffer ; - - rstime_t last_activity_TS ; -}; - -class p3GRouter: public RsGRouter, public RsTurtleClientService, public p3Service, public p3Config -{ -public: - p3GRouter(p3ServiceControl *sc,RsGixs *is) ; - - //===================================================// - // Router clients business // - //===================================================// - - // This method allows to associate client ids (that are saved to disk) to client objects deriving - // from GRouterClientService. The various services are responsible for regstering themselves to the - // global router, with consistent ids. The services are stored in a map, and arriving objects are - // passed on the correct service depending on the client id of the key they are reaching. - // - virtual bool registerClientService(const GRouterServiceId& id,GRouterClientService *service) ; - - // Use this method to register/unregister a key that the global router will - // forward in the network, so that is can be a possible destination for - // global messages. - // - // auth_id : The GXS key that will be used to sign the data Receipts. - // contact_key : The key that is used to open tunnels - // desc_str : Any fixed length string (< 20 characters) to descript the address in words. - // client_id : Id of the client service to send the traffic to. - // The client ID should match the ID that has been registered using the previous method. - // - // Unregistering a key might not have an instantaneous effect, so the client is responsible for - // discarding traffic that might later come for this key. - // - virtual bool registerKey(const RsGxsId& authentication_id, const GRouterServiceId& client_id,const std::string& description_string) ; - virtual bool unregisterKey(const RsGxsId &key_id, const GRouterServiceId &sid) ; - - //===================================================// - // Routing clue collection methods // - //===================================================// - - virtual void addRoutingClue( - const RsGxsId& id, const RsPeerId& peer_id) override; - - //===================================================// - // Client/server request services // - //===================================================// - - // Sends an item to the given destination. The router takes ownership of - // the memory. That means item_data will be erase on return. The returned id should be - // remembered by the client, so that he knows when the data has been received. - // The client id is supplied so that the client can be notified when the data has been received. - // Data is not modified by the global router. - // - virtual bool sendData(const RsGxsId& destination, const GRouterServiceId& client_id, const uint8_t *data, uint32_t data_size, const RsGxsId& signing_id, GRouterMsgPropagationId& id) ; - - // Cancels a given sending order. If called too late, the message might already have left. But this will remove the item from the - // re-try list. - virtual bool cancel(GRouterMsgPropagationId mid) ; - - //===================================================// - // Interface with RsGRouter // - //===================================================// - - // debug info from routing matrix - // - list of known key ids - // - list of clues/time_stamp for each key. - // - real time routing probabilities - // - virtual bool getRoutingMatrixInfo(GRouterRoutingMatrixInfo& info) ; - - // debug info from routing cache - // - Cache Items - // * which message ids - // * directions - // * timestamp - // * message type - // - Cache state (memory size, etc) - // - virtual bool getRoutingCacheInfo(std::vector& info) ; - - //===================================================// - // Derived from p3Service // - //===================================================// - - virtual RsServiceInfo getServiceInfo() - { - return RsServiceInfo(RS_SERVICE_TYPE_GROUTER, - SERVICE_INFO_APP_NAME, - SERVICE_INFO_APP_MAJOR_VERSION, - SERVICE_INFO_APP_MINOR_VERSION, - SERVICE_INFO_MIN_MAJOR_VERSION, - SERVICE_INFO_MIN_MINOR_VERSION) ; - } - - virtual void setDebugEnabled(bool b) { _debug_enabled = b ; } - - virtual void connectToTurtleRouter(p3turtle *pt) ; - -protected: - //===================================================// - // Routing method handling // - //===================================================// - - // Calls - // - packet handling methods - // - matrix updates - // - virtual int tick() ; - - static const std::string SERVICE_INFO_APP_NAME ; - static const uint16_t SERVICE_INFO_APP_MAJOR_VERSION = 1; - static const uint16_t SERVICE_INFO_APP_MINOR_VERSION = 0; - static const uint16_t SERVICE_INFO_MIN_MAJOR_VERSION = 1; - static const uint16_t SERVICE_INFO_MIN_MINOR_VERSION = 0; - - //===================================================// - // Interaction with turtle router // - //===================================================// - - uint16_t serviceId() const { return RS_SERVICE_TYPE_GROUTER; } - virtual bool handleTunnelRequest(const RsFileHash& /*hash*/,const RsPeerId& /*peer_id*/) ; - virtual void receiveTurtleData(const RsTurtleGenericTunnelItem */*item*/,const RsFileHash& /*hash*/,const RsPeerId& /*virtual_peer_id*/,RsTurtleGenericTunnelItem::Direction /*direction*/); - virtual void addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir) ; - virtual void removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) ; - -private: - //===================================================// - // Low level item sorting // - //===================================================// - - void handleLowLevelServiceItems() ; - void handleLowLevelServiceItem(RsGRouterTransactionItem*) ; - void handleLowLevelTransactionChunkItem(RsGRouterTransactionChunkItem *chunk_item); - void handleLowLevelTransactionAckItem(RsGRouterTransactionAcknItem*) ; - - static Sha1CheckSum computeDataItemHash(const RsGRouterGenericDataItem *data_item); - - std::ostream& grouter_debug() const - { - static std::ostream null(0); - return _debug_enabled?(std::cerr):null; - } - - void routePendingObjects() ; - void handleTunnels() ; - void autoWash() ; - - //===================================================// - // High level item sorting // - //===================================================// - - void handleIncoming() ; - - void handleIncomingItem(const RsGRouterAbstractMsgItem *item); - void handleIncomingReceiptItem(const RsGRouterSignedReceiptItem *receipt_item) ; - void handleIncomingDataItem(const RsGRouterGenericDataItem *data_item) ; - - bool locked_getLocallyRegisteredClientFromServiceId(const GRouterServiceId& service_id,GRouterClientService *& client); - - // utility functions - // - static float computeMatrixContribution(float base,uint32_t time_shift,float probability) ; - static bool sliceDataItem(RsGRouterAbstractMsgItem *,std::list& chunks) ; - - uint32_t computeRandomDistanceIncrement(const RsPeerId& pid,const GRouterKeyId& destination_id) ; - - // signs an item with the given key. - bool signDataItem(RsGRouterAbstractMsgItem *item,const RsGxsId& id) ; - bool verifySignedDataItem(const RsGRouterAbstractMsgItem *item, const RsIdentityUsage::UsageCode &info, uint32_t &error_status) ; - bool encryptDataItem(RsGRouterGenericDataItem *item,const RsGxsId& destination_key) ; - bool decryptDataItem(RsGRouterGenericDataItem *item) ; - - static Sha1CheckSum makeTunnelHash(const RsGxsId& destination,const GRouterServiceId& client); - - //bool locked_getGxsIdAndClientId(const TurtleFileHash &sum,RsGxsId& gxs_id,GRouterServiceId& client_id); - bool locked_sendTransactionData(const RsPeerId& pid,const RsGRouterTransactionItem& item); - - void locked_collectAvailableFriends(const GRouterKeyId &gxs_id, const std::set& incoming_routes,uint32_t duplication_factor, std::map &friend_peers_and_duplication_factors); - void locked_collectAvailableTunnels(const TurtleFileHash& hash, uint32_t total_duplication, std::map &tunnel_peers_and_duplication_factors); - void locked_sendToPeers(RsGRouterGenericDataItem *data_item, const std::map &peers_and_duplication_factors); - - //===================================================// - // p3Config methods // - //===================================================// - - // Load/save the routing info, the pending items in transit, and the config variables. - // - virtual bool loadList(std::list& items) ; - virtual bool saveList(bool& cleanup,std::list& items) ; - - virtual RsSerialiser *setupSerialiser() ; - - //===================================================// - // Debug methods // - //===================================================// - - // Prints the internal state of the router, for debug purpose. - // - void debugDump() ; - - //===================================================// - // Internal queues/variables // - //===================================================// - - // Stores the routing info - // - list of known key ids - // - list of clues/time_stamp for each key. - // - real time routing probabilities - // - GRouterMatrix _routing_matrix ; - - // Stores the keys which identify the router's node. For each key, a structure holds: - // - the client service - // - flags - // - usage time stamps - // - std::map _owned_key_ids ; - - // Registered services. These are known to the different peers with a common id, - // so it's important to keep consistency here. This map is volatile, and re-created at each startup of - // the software, when newly created services register themselves. - - std::map _registered_services ; - - // Stores the routing events. - // - ongoing requests, waiting for return ACK - // - pending items - // Both a stored in 2 different lists, to allow a more efficient handling. - // - std::map _pending_messages;// pending messages - - // Stores virtual peers that appear/disappear as the result of the turtle router client - // - std::map _tunnels ; - - // Stores incoming data from any peers (virtual and real) into chunks that get aggregated until finished. - // - std::map _incoming_data_pipes ; - - // Queue of incoming items. Might be receipts or data. Should always be empty (not a storage place) - std::list _incoming_items ; - - // Data handling methods - // - //void handleRecvDataItem(RsGRouterGenericDataItem *item); - //void handleRecvReceiptItem(RsGRouterReceiptItem *item); - - // Pointers to other RS objects - // - p3ServiceControl *mServiceControl ; - p3turtle *mTurtle ; - RsGixs *mGixs ; - //p3LinkMgr *mLinkMgr ; - - // Multi-thread protection mutex. - // - RsMutex grMtx ; - - // config update/save variables - bool _changed ; - bool _debug_enabled ; - - rstime_t _last_autowash_time ; - rstime_t _last_matrix_update_time ; - rstime_t _last_debug_output_time ; - rstime_t _last_config_changed ; - - uint64_t _random_salt ; - - /** Temporarly store items that could not have been verified yet due to - * missing author key, attempt to handle them once in a while. - * The items are discarded if after mMissingKeyQueueEntryTimeout the key - * hasn't been received yet, and are not saved on RetroShare stopping. */ - std::list< std::pair< - std::unique_ptr, rstime_t > > mMissingKeyQueue; - RsMutex mMissingKeyQueueMtx; /// protect mMissingKeyQueue - - /// @see mMissingKeyQueue - static constexpr rstime_t mMissingKeyQueueEntryTimeout = 600; - - /// @see mMissingKeyQueue - static constexpr rstime_t mMissingKeyQueueCheckEvery = 30; - - /// @see mMissingKeyQueue - rstime_t mMissingKeyQueueCheckLastCheck = 0; - - RS_SET_CONTEXT_DEBUG_LEVEL(2) -}; diff --git a/libretroshare/src/gxs/UseCases.txt b/libretroshare/src/gxs/UseCases.txt deleted file mode 100644 index 4ca721633..000000000 --- a/libretroshare/src/gxs/UseCases.txt +++ /dev/null @@ -1,341 +0,0 @@ - -These are some example usages of the GxsService... -All of these must be provided by the basic system. - -chris: -Please not all request* functions have a receive pair if not noted below - - -1) Forums ------------------------------------- -1.1) Display of subscribed forums. Service must provide: - 1.1.1) list of subscribed Groups. - ---------------- - int requestSubscribedGrps(); - - Component: - RsGnp::requestGroups() - - - ---------------- - 1.1.2) list of messages for each Group. - ---------------- - int requestGrpMsgs(std::list&); - ---------------- - - 1.1.3) details of group by group Id. - ---------------- - int requestGrp(std::list& grpIds); - ---------------- - - 1.1.4) details of messages by message Id. - ---------------- - int requestMsgs(std::list& msgs); - ---------------- - - 1.1.5) newest version of each message - - ---------------- - 1.1.4 : not intitialising RsGxsMsgId::version default to returning - newest version of message - ---------------- - - 1.1.6) status of message (read / unread). - - ---------------- - returned with msg data - int flagMsgRead(const RsGxsMsgId& msgId, bool read) - - ---------------- - - 1.1.7) access to Identity associated with Group and Messages - - ---------------- - returned with message - ---------------- - - 1.1.8) updates when new groups arrive. - - ---------------- - virtual void notifyGroupChanged(std::list grpId) = 0 - ---------------- - - 1.1.9) updates when new messages arrive. - ---------------- - virtual void notifyMsgChanged(std::list msgId) = 0 - ---------------- - - 1.1.10) updates when groups / messages change. - - ---------------- - 1.1.8 and 1.1.9 - ---------------- - - 1.1.11) Search forums for Keywords. - - ---------------- - int requestLocalSearch(RsGxsSearch* term); - ---------------- - - 1.1.12) Access new (time restricted) messages. - ---------------- - ? explain - ---------------- - -1.2) Creation of new material. - 1.2.1) ability to create Groups. - - ---------------- - int pushGrp(std::set& grp, std::string& profileName); - int pushGrp(std::set& grp, RsIdentityExchangeService::IdentityType type, const std::set& peers, - const std::string& pseudonymName = ""); - - ---------------- - - 1.2.2) ability to create Messages. - - void pushMsg(std::set& msg); - -1.3) Deletion of forums and posts. - 1.3.1) discard forum (can't do this currently). - ---------------- - done automatically by GDService based on cutoff - ---------------- - - 1.3.2) delete post. - ---------------- - // post is removed from system and note made in db not to syn it - // this is cleaned from db post expires - // very likely to also propagate to friends - int requestDeleteMsg(const RsGxsMsgId& msgId); - int requestDeleteGrp(const RsGxsGrpId& grpId); - ---------------- - - 1.3.3) discard old posts. - ---------------- - done automatically by GDService based on cutoff - ---------------- - -1.4) Control of Forums - - 1.4.1) Storage Period of subscribed forums - - ---------------- - void setSubscribedGroupDiscardAge(uint32_t length); - ---------------- - - 1.4.2) Storage Period of unsubscribed forums. - - ---------------- - void setUnsubscribedGrpDiscardAge(uint32_t length); - ---------------- - - 1.4.3) transfer unsubscribed forums and posts (yes/no) - - ---------------- - don't think I want this, definitely default false - int GXService::allUnsubscribedTransfer(bool) - ---------------- - - 1.4.4) modify forums we own. - - ---------------- - int GXService::updateGroup(multimap) - ---------------- - - ---------------- - int GXService::updateMsg(multimap) - ---------------- - - 1.4.5) modify read status. - - ---------------- - int flagMsgRead(const RsGxsMsgId& msgId, bool read) ; - ---------------- - 1.4.6) Subscribe to forums - - ---------------- - int requestSubscribeToGrp(const RsGxsGrpId& grpId, bool subscribe); - ---------------- - -1.5) Finding other forums. - 1.5.1) Listing of other forums. - int GXService::requestGroupList(); - void receiveGroupList(token, list); //call back - 1.5.2) ability to temporarily get forum messages. - ? Explain - 1.5.3) search remote forums for keywords. - ---------------- - // service will have to provide own search module (can RsGDService can - // service remote search requests concurrent with GXS) - // module return message and groups (msgs can be marked compile time as not // searchable - int requestRemoteSearch(RsGxsSearch* term, uint32_t hops); - - ---------------- - 1.5.4) optional download of friends forums. - ---------------- - int requestPeersGrps(const std::string& sslId); - ---------------- - - -2) Channels ------------------------------------- -2.1) Mostly like Forums, additional functionality. - 2.1.1) Download files associated with Post. - - ---------------- - ? Explain, This should not be part of interface, this is feature specific - ---------------- - -2.2) Comments - 2.2.1) Write a comment. - ---------------- - see 1.2.2. RsGxsMsg with required indirection data members - to associate with message the comment is being made on - ---------------- - - 2.2.2) Reject (downgrade) bad comment. - ---------------- - user needs to verify publisher sent downgrage message - bool RsGxis::bool verify(const KeyRef& keyref, unsigned char* data, uint32_t dataLen, std::string& signature); - - ---------------- - - 2.2.3) Control Comments: Allow / Disallow, Pseudo / Authed Comments. - ---------------- - bool RsGxis::bool sign(const KeyRef& keyref, unsigned char* data, uint32_t dataLen, std::string& signature); - - ---------------- - - -3) Wiki ------------------------------------- -3.1) Editing functionality - 3.1.1) Access to Latest Version. - - ---------------- - Pls see 1.1.7 - ---------------- - - 3.1.2) Access to Version History. (including who edited). - - ---------------- - // need to include std::map as top level RsGxsMsg - ---------------- - - 3.2) Controlling Editing Rights. - - ---------------- - Pls see 1.1.7 - ---------------- - - - 3.2.1) Rejecting an Edit. - - ---------------- - using 1.2.2 publisher can send messages with private key signature that he does not accept edit 'x' - bool GXIService verify(Identity, data, dataLen, signature) - ---------------- - - 3.2.2) Changing Edit Rights. -using 1.2.2, publisher sends new publish key under old private key signature, and user uses - -3.3) Searching for Wikis. - 3.3.1) Search for keyword. - ---------------- - see 1.5.3 - ---------------- - - 3.3.2) Search for hashtag. - ---------------- - ? Explain, anything different from keyword - see 1.5.3 - ---------------- - - - 3.3.3) Search for pattern? - ---------------- - Bit more detail on search type - RsGxsSearch{ int searchType; const int PATTERN_TYPE, TERM_TYPE; ....} - - ---------------- - - -4) Wire (Twitter) ------------------------------------- -4.1) Following Friends. - 4.1.1) Adding Person. - - ---------------- - See 1.4.6 - ---------------- - - -4.2) Search The Wire. - 4.2.1) Search for friends. - 4.2.2) Search for hash tags. - 4.2.3) Search for keywords. - 4.2.4) Search for Retweets. - 4.2.5) Search for replies. - ---------------- - for 4.2.* see 3.3.1 - ---------------- - -5) PhotoShare. ------------------------------------- -5.1) Controlling Access. - 5.1.1) Friends Only. - - ---------------- - GXService::setShareGroup(grpId, group=RsGroups::GROUP_FRIENDS) - ---------------- - - 5.1.2) Groups Only. - - ---------------- - 5.1.1 - ---------------- - - 5.1.3) Everyone. - ---------------- - 5.1.1 GXService::setShareGroup(grpId, group=RsGroups::GROUP_ALL) - ---------------- - - 5.1.4) Deleting Photographs. - - ---------------- - 1.3.2 - ---------------- - - 5.1.4) Deleting Album. - ---------------- - 1.3.2 - ---------------- - -6) Acadeeb ------------------------------------- -6.1) Review Article. - 6.1.1) Write Review/Rate. - ---------------- - see 1.2.2 for sending message - ---------------- - - 6.1.2) Recommend Article. - ---------------- - see 1.2.2 for sending message - ---------------- - 6.1.3) Get Rating of Article. - ---------------- - See 3.2.1 and 2.2.2 - ---------------- - - -6.2) Submit Review of Article - 6.2.1) stuff. - 6.2.2) stuff. - - -7) Tracker. ------------------------------------- -7.1) Tracker Stuff. - diff --git a/libretroshare/src/gxs/gxssecurity.cc b/libretroshare/src/gxs/gxssecurity.cc deleted file mode 100644 index 6798ee29c..000000000 --- a/libretroshare/src/gxs/gxssecurity.cc +++ /dev/null @@ -1,1191 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: gxssecurity.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008-2010 by Robert Fernie * - * 2011-2012 Christopher Evi-Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "gxssecurity.h" -#include "pqi/authgpg.h" -#include "util/rsdir.h" -#include "util/rsmemory.h" -//#include "retroshare/rspeers.h" - -/**** - * #define GXS_SECURITY_DEBUG 1 - ***/ - -static const uint32_t MULTI_ENCRYPTION_FORMAT_v001_HEADER = 0xFACE; -static const uint32_t MULTI_ENCRYPTION_FORMAT_v001_HEADER_SIZE = 2 ; -static const uint32_t MULTI_ENCRYPTION_FORMAT_v001_NUMBER_OF_KEYS_SIZE = 2 ; -static const uint32_t MULTI_ENCRYPTION_FORMAT_v001_ENCRYPTED_KEY_SIZE = 256 ; - -static RsGxsId getRsaKeyFingerprint_old_insecure_method(RSA *pubkey) -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - int lenn = BN_num_bytes(pubkey -> n); - - RsTemporaryMemory tmp(lenn) ; - BN_bn2bin(pubkey -> n, tmp); -#else - const BIGNUM *nn=NULL,*ee=NULL ; - RSA_get0_key(pubkey,&nn,&ee,NULL) ; - - int lenn = BN_num_bytes(nn); - - RsTemporaryMemory tmp(lenn) ; - BN_bn2bin(nn, tmp); -#endif - - // Copy first CERTSIGNLEN bytes from the hash of the public modulus and exponent - // We should not be using strings here, but a real ID. To be done later. - - assert(lenn >= CERTSIGNLEN) ; - - return RsGxsId((unsigned char*)tmp) ; -} -static RsGxsId getRsaKeyFingerprint(RSA *pubkey) -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - int lenn = BN_num_bytes(pubkey -> n); - int lene = BN_num_bytes(pubkey -> e); - - RsTemporaryMemory tmp(lenn+lene) ; - - BN_bn2bin(pubkey -> n, tmp); - BN_bn2bin(pubkey -> e, &tmp[lenn]); -#else - const BIGNUM *nn=NULL,*ee=NULL ; - RSA_get0_key(pubkey,&nn,&ee,NULL) ; - - int lenn = BN_num_bytes(nn); - int lene = BN_num_bytes(ee); - - RsTemporaryMemory tmp(lenn+lene) ; - - BN_bn2bin(nn, tmp); - BN_bn2bin(ee, &tmp[lenn]); -#endif - - Sha1CheckSum s = RsDirUtil::sha1sum(tmp,lenn+lene) ; - - // Copy first CERTSIGNLEN bytes from the hash of the public modulus and exponent - // We should not be using strings here, but a real ID. To be done later. - - assert(Sha1CheckSum::SIZE_IN_BYTES >= CERTSIGNLEN) ; - - return RsGxsId(s.toStdString().substr(0,2*CERTSIGNLEN)); -} - -static RSA *extractPrivateKey(const RsTlvPrivateRSAKey& key) -{ - assert(key.keyFlags & RSTLV_KEY_TYPE_FULL) ; - - const unsigned char *keyptr = (const unsigned char *) key.keyData.bin_data; - long keylen = key.keyData.bin_len; - - /* extract admin key */ - RSA *rsakey = d2i_RSAPrivateKey(NULL, &(keyptr), keylen); - - return rsakey; -} - -static RSA *extractPublicKey(const RsTlvPublicRSAKey& key) -{ - assert(!(key.keyFlags & RSTLV_KEY_TYPE_FULL)) ; - - const unsigned char *keyptr = (const unsigned char *) key.keyData.bin_data; - long keylen = key.keyData.bin_len; - - /* extract admin key */ - RSA *rsakey = d2i_RSAPublicKey(NULL, &(keyptr), keylen); - - return rsakey; -} -static void setRSAPublicKeyData(RsTlvPublicRSAKey& key, RSA *rsa_pub) -{ - assert(!(key.keyFlags & RSTLV_KEY_TYPE_FULL)) ; - unsigned char *data = NULL ; // this works for OpenSSL > 0.9.7 - int reqspace = i2d_RSAPublicKey(rsa_pub, &data); - - key.keyData.setBinData(data, reqspace); - key.keyId = getRsaKeyFingerprint(rsa_pub); - - free(data) ; -} - -static void setRSAPrivateKeyData(RsTlvPrivateRSAKey& key, RSA *rsa_priv) -{ - assert(key.keyFlags & RSTLV_KEY_TYPE_FULL) ; - - unsigned char *data = NULL ; // this works for OpenSSL > 0.9.7 - int reqspace = i2d_RSAPrivateKey(rsa_priv, &data); - - key.keyData.setBinData(data, reqspace); - key.keyId = getRsaKeyFingerprint(rsa_priv); - - free(data) ; -} -bool GxsSecurity::checkFingerprint(const RsTlvPublicRSAKey& key) -{ - RSA *rsa_pub = ::extractPublicKey(key) ; - bool res = (key.keyId == getRsaKeyFingerprint(rsa_pub)) ; - RSA_free(rsa_pub) ; - return res ; -} - -bool GxsSecurity::checkPrivateKey(const RsTlvPrivateRSAKey& key) -{ -#ifdef GXS_SECURITY_DEBUG - std::cerr << "Checking private key " << key.keyId << " ..." << std::endl; -#endif - - if( (key.keyFlags & RSTLV_KEY_TYPE_MASK) != RSTLV_KEY_TYPE_FULL) - { - std::cerr << "(WW) GxsSecurity::checkPrivateKey(): private key has wrong flags " << std::hex << (key.keyFlags & RSTLV_KEY_TYPE_MASK) << std::dec << ". This is unexpected." << std::endl; - return false ; - } - RSA *rsa_prv = ::extractPrivateKey(key) ; - - if(rsa_prv == NULL) - { - std::cerr << "(WW) GxsSecurity::checkPrivateKey(): no private key can be extracted from key ID " << key.keyId << ". Key is corrupted?" << std::endl; - return false ; - } - RSA *rsa_pub = RSAPublicKey_dup(rsa_prv); - RSA_free(rsa_prv) ; - - if(rsa_pub == NULL) - { - std::cerr << "(WW) GxsSecurity::checkPrivateKey(): no public key can be extracted from key ID " << key.keyId << ". Key is corrupted?" << std::endl; - return false ; - } - RsGxsId recomputed_key_id = getRsaKeyFingerprint(rsa_pub) ; - - if(recomputed_key_id != key.keyId) - { - if(key.keyId == getRsaKeyFingerprint_old_insecure_method(rsa_pub)) - { -#ifdef GXS_SECURITY_DEBUG - std::cerr << "(WW) fingerprint of key " << key.keyId << " was derived using old---insecure---format. It can be faked easily. You should get rid of this key!" << std::endl; -#endif - RSA_free(rsa_pub) ; - - // The policy is to *accept* these private keys, but the public key that corresponds will be rejected anyway, as it can easily be faked. - return true ; - } - else - { - std::cerr << "(WW) GxsSecurity::checkPrivateKey(): key " << key.keyId << " has wrong fingerprint " << recomputed_key_id << std::endl; - - RSA_free(rsa_pub) ; - return false ; - } - } - - RSA_free(rsa_pub) ; - return true ; -} - -bool GxsSecurity::checkPublicKey(const RsTlvPublicRSAKey &key) -{ -#ifdef GXS_SECURITY_DEBUG - std::cerr << "Checking public key " << key.keyId << " ..." << std::endl; -#endif - - if( (key.keyFlags & RSTLV_KEY_TYPE_MASK) != RSTLV_KEY_TYPE_PUBLIC_ONLY) - { - std::cerr << "(WW) GxsSecurity::checkPublicKey(): public key has wrong flags " << std::hex << (key.keyFlags & RSTLV_KEY_TYPE_MASK) << std::dec << ". This is unexpected." << std::endl; - return false ; - } - - // try to extract private key - const unsigned char *keyptr = (const unsigned char *) key.keyData.bin_data; - long keylen = key.keyData.bin_len; - RSA *rsa_prv = d2i_RSAPrivateKey(NULL, &(keyptr), keylen); - - if(rsa_prv != NULL) - { - std::cerr << "(SS) GxsSecurity::checkPublicKey(): public key with ID " << key.keyId << " actually is a Private key!!!" << std::endl; - RSA_free(rsa_prv) ; - return false ; - } - - RSA *rsa_pub = ::extractPublicKey(key) ; - - if(rsa_pub == NULL) - { - std::cerr << "(WW) GxsSecurity::checkPublicKey(): no public key can be extracted from key ID " << key.keyId << ". Key is corrupted?" << std::endl; - return false ; - } - RsGxsId recomputed_key_id = getRsaKeyFingerprint(rsa_pub) ; - - if(recomputed_key_id != key.keyId) - { - if(key.keyId == getRsaKeyFingerprint_old_insecure_method(rsa_pub)) - { -#ifdef GXS_SECURITY_DEBUG - std::cerr << "(WW) fingerprint was derived using old---insecure---format. It can be faked easily." << std::endl; -#endif - RSA_free(rsa_pub) ; - - // The policy is to accept these public keys, but warn the owner, since they might be fake keys. They will be soon rejected here, by replacing - // the return value by false. - return true ; - } - else - std::cerr << "(WW) GxsSecurity::checkPublicKey(): key " << key.keyId << " has wrong fingerprint " << recomputed_key_id << "! Key will be discarded." << std::endl; - - RSA_free(rsa_pub) ; - return false ; - } - - RSA_free(rsa_pub) ; - return true ; -} - -bool GxsSecurity::generateKeyPair(RsTlvPublicRSAKey& public_key,RsTlvPrivateRSAKey& private_key) -{ - // admin keys - BIGNUM *ebn = BN_new(); - BN_set_word(ebn, 65537); - RSA *rsa = RSA_new(); - RSA_generate_key_ex(rsa, 2048, ebn, NULL); - RSA *rsa_pub = RSAPublicKey_dup(rsa); - - BN_clear_free(ebn) ; - - public_key.keyFlags = RSTLV_KEY_TYPE_PUBLIC_ONLY ; - private_key.keyFlags = RSTLV_KEY_TYPE_FULL ; - - setRSAPublicKeyData(public_key, rsa_pub); - setRSAPrivateKeyData(private_key, rsa); - - public_key.startTS = time(NULL); - public_key.endTS = public_key.startTS + 60 * 60 * 24 * 365 * 5; /* approx 5 years */ - - private_key.startTS = public_key.startTS; - private_key.endTS = 0; /* no end */ - - // clean up - RSA_free(rsa); - RSA_free(rsa_pub); - - if(!(private_key.checkKey() && public_key.checkKey())) - { - std::cerr << "(EE) ERROR while generating keys. Something inconsistent in flags. This is probably a bad sign!" << std::endl; - return false ; - } - - return true ; -} - -bool GxsSecurity::extractPublicKey(const RsTlvPrivateRSAKey &private_key, RsTlvPublicRSAKey &public_key) -{ - public_key.TlvClear() ; - - if(!(private_key.keyFlags & RSTLV_KEY_TYPE_FULL)) - return false ; - - RSA *rsaPrivKey = extractPrivateKey(private_key); - - if(!rsaPrivKey) - return false ; - - RSA *rsaPubKey = RSAPublicKey_dup(rsaPrivKey); - RSA_free(rsaPrivKey); - - if(!rsaPubKey) - return false ; - - setRSAPublicKeyData(public_key, rsaPubKey); - RSA_free(rsaPubKey); - - public_key.keyFlags = private_key.keyFlags & (RSTLV_KEY_DISTRIB_MASK) ; // keep the distrib flags - public_key.keyFlags |= RSTLV_KEY_TYPE_PUBLIC_ONLY; - public_key.startTS = private_key.startTS ; - public_key.endTS = public_key.startTS + 60 * 60 * 24 * 365 * 5; /* approx 5 years */ - - // This code fixes a problem of old RSA keys where the fingerprint wasn't computed using SHA1(n,e) but - // using the first bytes of n (ouuuuch!). Still, these keys are valid and should produce a correct - // fingerprint. So we replace the public key fingerprint (that is normally recomputed) with the FP of - // the private key. - - if(public_key.keyId != private_key.keyId) - { - std::cerr << std::endl; - std::cerr << "WARNING: GXS ID key pair " << private_key.keyId << " has inconsistent fingerprint. This is an old key " << std::endl; - std::cerr << " that is unsecure (can be faked easily). You should delete it!" << std::endl; - std::cerr << std::endl; - - public_key.keyId = private_key.keyId ; - } - - return true ; -} - -bool GxsSecurity::getSignature(const char *data, uint32_t data_len, const RsTlvPrivateRSAKey &privKey, RsTlvKeySignature& sign) -{ - RSA* rsa_priv = extractPrivateKey(privKey); - - if(!rsa_priv) - { - std::cerr << "GxsSecurity::getSignature(): Cannot create signature. Keydata is incomplete." << std::endl; - return false ; - } - EVP_PKEY *key_priv = EVP_PKEY_new(); - EVP_PKEY_assign_RSA(key_priv, rsa_priv); - - /* calc and check signature */ - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - bool ok = EVP_SignInit(mdctx, EVP_sha1()) == 1; - ok &= EVP_SignUpdate(mdctx, data, data_len) == 1; - - unsigned int siglen = EVP_PKEY_size(key_priv); - unsigned char sigbuf[siglen] ; - memset(sigbuf,0,siglen) ; - ok &= EVP_SignFinal(mdctx, sigbuf, &siglen, key_priv) == 1; - - // clean up - EVP_MD_CTX_destroy(mdctx); - EVP_PKEY_free(key_priv); - - sign.signData.setBinData(sigbuf, siglen); - sign.keyId = RsGxsId(privKey.keyId); - - return ok; -} - -bool GxsSecurity::validateSignature(const char *data, uint32_t data_len, const RsTlvPublicRSAKey &key, const RsTlvKeySignature& signature) -{ - assert(!(key.keyFlags & RSTLV_KEY_TYPE_FULL)) ; - - RSA *rsakey = ::extractPublicKey(key) ; - - if(!rsakey) - { - std::cerr << "GxsSecurity::validateSignature(): Cannot validate signature. Keydata is incomplete." << std::endl; - key.print(std::cerr,0) ; - return false ; - } - EVP_PKEY *signKey = EVP_PKEY_new(); - EVP_PKEY_assign_RSA(signKey, rsakey); - - /* calc and check signature */ - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - - EVP_VerifyInit(mdctx, EVP_sha1()); - EVP_VerifyUpdate(mdctx, data, data_len); - - int signOk = EVP_VerifyFinal(mdctx, (unsigned char*)signature.signData.bin_data, signature.signData.bin_len, signKey); - - /* clean up */ - EVP_PKEY_free(signKey); - EVP_MD_CTX_destroy(mdctx); - - return signOk; -} - -bool GxsSecurity::validateNxsMsg(const RsNxsMsg& msg, const RsTlvKeySignature& sign, const RsTlvPublicRSAKey& key) -{ - #ifdef GXS_SECURITY_DEBUG - std::cerr << "GxsSecurity::validateNxsMsg()"; - std::cerr << std::endl; - std::cerr << "RsNxsMsg :"; - std::cerr << std::endl; - const_cast(&msg)->print(std::cerr, 10); - std::cerr << std::endl; - #endif - - RsGxsMsgMetaData& msgMeta = *(msg.metaData); - - // /********************* check signature *******************/ - - /* check signature timeperiod */ - if(msgMeta.mPublishTs < key.startTS) - { - RsWarn() << __PRETTY_FUNCTION__ << " GxsSecurity::validateNxsMsg() TS out of range for key " << msgMeta.mAuthorId - << " The signed message has an inconsistent msg publish time of " << msgMeta.mPublishTs - << " whereas the signing key was created later at TS " << key.startTS - << ". Validation rejected for security. If you see this, something irregular is going on." << std::endl; - return false; - } - - if(key.endTS != 0 && msgMeta.mPublishTs > key.endTS) - { - RsWarn() << __PRETTY_FUNCTION__ << " GxsSecurity::validateNxsMsg() TS out of range for key " << msgMeta.mAuthorId - << " usage is limited to TS=[" << key.startTS << "," << key.endTS << "] and msg publish time is " << msgMeta.mPublishTs - << " The validation still passes, but that key should be renewed." << std::endl; - - // no return here. We still proceed checking the signature. - } - - /* decode key */ - const unsigned char *keyptr = (const unsigned char *) key.keyData.bin_data; - long keylen = key.keyData.bin_len; - unsigned int siglen = sign.signData.bin_len; - unsigned char *sigbuf = (unsigned char *) sign.signData.bin_data; - - #ifdef DISTRIB_DEBUG - std::cerr << "GxsSecurity::validateNxsMsg() Decode Key"; - std::cerr << " keylen: " << keylen << " siglen: " << siglen; - std::cerr << std::endl; - #endif - - /* extract admin key */ - - RSA *rsakey = (key.keyFlags & RSTLV_KEY_TYPE_FULL)? (d2i_RSAPrivateKey(NULL, &(keyptr), keylen)) : (d2i_RSAPublicKey(NULL, &(keyptr), keylen)); - - if (!rsakey) - { - #ifdef GXS_SECURITY_DEBUG - std::cerr << "GxsSecurity::validateNxsMsg()"; - std::cerr << " Invalid RSA Key"; - std::cerr << std::endl; - - key.print(std::cerr, 10); - #endif - } - - - RsTlvKeySignatureSet signSet = msgMeta.signSet; - msgMeta.signSet.TlvClear(); - - RsGxsMessageId msgId = msgMeta.mMsgId, origMsgId = msgMeta.mOrigMsgId; - - if(msgMeta.mOrigMsgId == msgMeta.mMsgId) // message is not versionned, then the signature was made with mOrigMsgId==NULL - msgMeta.mOrigMsgId.clear(); - - msgMeta.mMsgId.clear(); - - int signOk = 0 ; - - { - EVP_PKEY *signKey = EVP_PKEY_new(); - EVP_PKEY_assign_RSA(signKey, rsakey); - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - - uint32_t metaDataLen = msgMeta.serial_size(); - uint32_t allMsgDataLen = metaDataLen + msg.msg.bin_len; - - RsTemporaryMemory metaData(metaDataLen) ; - RsTemporaryMemory allMsgData(allMsgDataLen) ; - - if(!metaData || !allMsgData) - return false ; - - msgMeta.serialise(metaData, &metaDataLen); - - // copy msg data and meta in allmsgData buffer - memcpy(allMsgData, msg.msg.bin_data, msg.msg.bin_len); - memcpy(allMsgData+(msg.msg.bin_len), metaData, metaDataLen); - - /* calc and check signature */ - - EVP_VerifyInit(mdctx, EVP_sha1()); - EVP_VerifyUpdate(mdctx, allMsgData, allMsgDataLen); - - signOk = EVP_VerifyFinal(mdctx, sigbuf, siglen, signKey); - - /* clean up */ - EVP_PKEY_free(signKey); - EVP_MD_CTX_destroy(mdctx); - } - - msgMeta.mOrigMsgId = origMsgId; - msgMeta.mMsgId = msgId; - msgMeta.signSet = signSet; - - if (signOk == 1) - { - #ifdef GXS_SECURITY_DEBUG - std::cerr << "GxsSecurity::validateNxsMsg() Signature OK"; - std::cerr << std::endl; - #endif - return true; - } - - #ifdef GXS_SECURITY_DEBUG - std::cerr << "GxsSecurity::validateNxsMsg() Signature invalid"; - std::cerr << std::endl; - #endif - - return false; -} - -bool GxsSecurity::encrypt(uint8_t *& out, uint32_t &outlen, const uint8_t *in, uint32_t inlen, const RsTlvPublicRSAKey& key) -{ -#ifdef DISTRIB_DEBUG - std::cerr << "GxsSecurity::encrypt() " << std::endl; -#endif - // Encrypts (in,inlen) into (out,outlen) using the given RSA public key. - // The format of the encrypted data is: - // - // [--- Encrypted session key length ---|--- Encrypted session key ---|--- IV ---|---- Encrypted data ---] - // - - out = NULL ; - - RSA *tmpkey = ::extractPublicKey(key) ; - RSA *rsa_publish_pub = RSAPublicKey_dup(tmpkey) ; - RSA_free(tmpkey) ; - - EVP_PKEY *public_key = NULL; - - //RSA* rsa_publish = EVP_PKEY_get1_RSA(privateKey); - //rsa_publish_pub = RSAPublicKey_dup(rsa_publish); - - - if(rsa_publish_pub != NULL) - { - public_key = EVP_PKEY_new(); - EVP_PKEY_assign_RSA(public_key, rsa_publish_pub); - } - else - { -#ifdef DISTRIB_DEBUG - std::cerr << "GxsSecurity(): Could not generate publish key " << grpId - << std::endl; -#endif - return false; - } - - EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - int eklen, net_ekl; - unsigned char *ek; - unsigned char iv[EVP_MAX_IV_LENGTH]; - int out_currOffset = 0; - int out_offset = 0; - - int max_evp_key_size = EVP_PKEY_size(public_key); - ek = (unsigned char*)rs_malloc(max_evp_key_size); - - if(ek == NULL) - return false ; - - const EVP_CIPHER *cipher = EVP_aes_128_cbc(); - int cipher_block_size = EVP_CIPHER_block_size(cipher); - int size_net_ekl = sizeof(net_ekl); - - int max_outlen = inlen + cipher_block_size + EVP_MAX_IV_LENGTH + max_evp_key_size + size_net_ekl; - - // intialize context and send store encrypted cipher in ek - if(!EVP_SealInit(ctx, EVP_aes_128_cbc(), &ek, &eklen, iv, &public_key, 1)) return false; - - EVP_PKEY_free(public_key) ; - - // now assign memory to out accounting for data, and cipher block size, key length, and key length val - out = (uint8_t*)rs_malloc(inlen + cipher_block_size + size_net_ekl + eklen + EVP_MAX_IV_LENGTH) ; - - if (out == NULL) - return false; - - net_ekl = htonl(eklen); - memcpy((unsigned char*)out + out_offset, &net_ekl, size_net_ekl); - out_offset += size_net_ekl; - - memcpy((unsigned char*)out + out_offset, ek, eklen); - out_offset += eklen; - - memcpy((unsigned char*)out + out_offset, iv, EVP_MAX_IV_LENGTH); - out_offset += EVP_MAX_IV_LENGTH; - - // now encrypt actual data - if(!EVP_SealUpdate(ctx, (unsigned char*) out + out_offset, &out_currOffset, (unsigned char*) in, inlen)) - { - free(out) ; - out = NULL ; - return false; - } - - // move along to partial block space - out_offset += out_currOffset; - - // add padding - if(!EVP_SealFinal(ctx, (unsigned char*) out + out_offset, &out_currOffset)) - { - free(out) ; - out = NULL ; - return false; - } - - // move to end - out_offset += out_currOffset; - - // make sure offset has not gone passed valid memory bounds - if(out_offset > max_outlen) - { - free(out) ; - out = NULL ; - return false; - } - - // free encrypted key data - free(ek); - - EVP_CIPHER_CTX_free(ctx); - - outlen = out_offset; - return true; -} - -bool GxsSecurity::encrypt(uint8_t *& out, uint32_t &outlen, const uint8_t *in, uint32_t inlen, const std::vector &keys) -{ -#ifdef DISTRIB_DEBUG - std::cerr << "GxsSecurity::encrypt() " << std::endl; -#endif - // Encrypts (in,inlen) into (out,outlen) using the given RSA public key. - // The format of the encrypted data is: - // - // [--- ID ---|--- number of encrypted keys---| n * (--- Encrypted session keys ---) |--- IV ---|---- Encrypted data ---] - // 2 bytes 2 byte = n 256 bytes EVP_MAX_IV_LENGTH Rest of packet - // - - out = NULL ; - EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - std::vector public_keys(keys.size(),NULL); - - try - { - if(keys.empty()) - throw std::runtime_error("EVP_SealInit will not be called with 0 keys. GxsSecurity::encrypt() was called with an empty set of destination keys!") ; - - for(uint32_t i=0;i ek(keys.size(),NULL) ; - std::vector eklen(keys.size(),0) ; - - for(uint32_t i=0;i> 8) & 0xff ; - - // number of keys - - out[out_offset++] = keys.size() & 0xff ; - out[out_offset++] = (keys.size() >> 8) & 0xff ; - - // encrypted keys, each preceeded with its length - - for(uint32_t i=0;i max_outlen) - throw std::runtime_error("Memory used by encryption exceeds allocated memory block") ; - - // free encrypted key data - - for(uint32_t i=0;i 512 || eklen+in_offset > (int)inlen) - { - std::cerr << "Error while deserialising encryption key length: eklen = " << std::dec << eklen << ". Giving up decryption." << std::endl; - free(ek); - return false; - } - - memcpy(ek, (unsigned char*)in + in_offset, eklen); - in_offset += eklen; - - memcpy(iv, (unsigned char*)in + in_offset, EVP_MAX_IV_LENGTH); - in_offset += EVP_MAX_IV_LENGTH; - - const EVP_CIPHER* cipher = EVP_aes_128_cbc(); - - if(!EVP_OpenInit(ctx, cipher, ek, eklen, iv, privateKey)) - { - std::cerr << "(EE) Cannot decrypt data. Most likely reason: private GXS key is missing." << std::endl; - return false; - } - EVP_PKEY_free(privateKey) ; - - if(inlen < (uint32_t)in_offset) - { - std::cerr << "Severe error in " << __PRETTY_FUNCTION__ << ": cannot encrypt. " << std::endl; - return false ; - } - out = (uint8_t*)rs_malloc(inlen - in_offset); - - if(out == NULL) - return false; - - if(!EVP_OpenUpdate(ctx, (unsigned char*) out, &out_currOffset, (unsigned char*)in + in_offset, inlen - in_offset)) - { - free(out) ; - out = NULL ; - return false; - } - - outlen = out_currOffset; - - if(!EVP_OpenFinal(ctx, (unsigned char*)out + out_currOffset, &out_currOffset)) - { - free(out) ; - out = NULL ; - return false; - } - - outlen += out_currOffset; - free(ek); - - EVP_CIPHER_CTX_free(ctx); - return true; -} - -bool GxsSecurity::decrypt(uint8_t *& out, uint32_t & outlen, const uint8_t *in, uint32_t inlen, const std::vector &keys) -{ - // Decrypts (in,inlen) into (out,outlen) using one of the given RSA public keys, trying them all in a row. - // The format of the encrypted data is: - // - // [--- ID ---|--- number of encrypted keys---| n * (--- Encrypted session keys ---) |--- IV ---|---- Encrypted data ---] - // 2 bytes 2 byte = n 256 bytes EVP_MAX_IV_LENGTH Rest of packet - // - // This method can be used to decrypt multi-encrypted data, if passing he correct encrypted key block (corresponding to the given key) - -#ifdef DISTRIB_DEBUG - std::cerr << "GxsSecurity::decrypt() " << std::endl; -#endif - EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - - try - { - out = NULL ; - - // check that the input block has a valid format. - - uint32_t offset = 0 ; - uint16_t format_id = in[offset] + (in[offset+1] << 8) ; - - if(format_id != MULTI_ENCRYPTION_FORMAT_v001_HEADER) - { - std::cerr << "Unrecognised format in encrypted block. Header id = " << std::hex << format_id << std::dec << std::endl; - throw std::runtime_error("Unrecognised format in encrypted block.") ; - } - offset += MULTI_ENCRYPTION_FORMAT_v001_HEADER_SIZE; - - // read number of encrypted keys - - uint32_t number_of_keys = in[offset] + (in[offset+1] << 8) ; - offset += MULTI_ENCRYPTION_FORMAT_v001_NUMBER_OF_KEYS_SIZE; - - // reach the actual data offset - - uint32_t encrypted_keys_offset = offset ; - uint32_t encrypted_block_size = 0 ; - - uint32_t IV_offset = offset + number_of_keys * MULTI_ENCRYPTION_FORMAT_v001_ENCRYPTED_KEY_SIZE ; - uint32_t encrypted_block_offset = IV_offset + EVP_MAX_IV_LENGTH ; - - // read IV offset - - if(encrypted_block_offset >= inlen) - throw std::runtime_error("Offset error") ; - - encrypted_block_size = inlen - encrypted_block_offset ; -#ifdef GXS_SECURITY_DEBUG - std::cerr << " number of keys in envelop: " << number_of_keys << std::endl; - std::cerr << " IV offset : " << IV_offset << std::endl; - std::cerr << " encrypted block offset : " << encrypted_block_offset << std::endl; - std::cerr << " encrypted block size : " << encrypted_block_size << std::endl; -#endif - - // decrypt - - bool succeed = false; - - for(uint32_t j=0;j(&grp)->print(std::cerr, 10); - std::cerr << std::endl; -#endif - - RsGxsGrpMetaData& grpMeta = *(grp.metaData); - - /********************* check signature *******************/ - - /* check signature timeperiod */ - if (grpMeta.mPublishTs < key.startTS) - { - RsWarn() << __PRETTY_FUNCTION__ << " GxsSecurity::validateNxsGrp() TS out of range for admin/publish key of group " << grpMeta.mGroupId - << " The signed group has an inconsistent creation/modification time of " << grpMeta.mPublishTs - << " whereas the key was created later at TS " << key.startTS - << ". Validation rejected for security. If you see this, something irregular is going on." << std::endl; - return false; - } - if (key.endTS != 0 && grpMeta.mPublishTs > key.endTS) - { - RsWarn() << __PRETTY_FUNCTION__ << " GxsSecurity::validateNxsMsg() TS out of range for admin/publish key for group " << grpMeta.mGroupId - << " usage is limited to TS=[" << key.startTS << "," << key.endTS << "] and msg publish time is " << grpMeta.mPublishTs - << " The validation still passes, but that key should be renewed." << std::endl; - - // no return. Still proceed checking signature. - } - - /* decode key */ - const unsigned char *keyptr = (const unsigned char *) key.keyData.bin_data; - long keylen = key.keyData.bin_len; - unsigned int siglen = sign.signData.bin_len; - unsigned char *sigbuf = (unsigned char *) sign.signData.bin_data; - -#ifdef DISTRIB_DEBUG - std::cerr << "GxsSecurity::validateNxsMsg() Decode Key"; - std::cerr << " keylen: " << keylen << " siglen: " << siglen; - std::cerr << std::endl; -#endif - - /* extract admin key */ - RSA *rsakey = d2i_RSAPublicKey(NULL, &(keyptr), keylen); - - if (!rsakey) - { -#ifdef GXS_SECURITY_DEBUG - std::cerr << "GxsSecurity::validateNxsGrp()"; - std::cerr << " Invalid RSA Key"; - std::cerr << std::endl; - - key.print(std::cerr, 10); -#endif - } - - std::vector api_versions_to_check ; - api_versions_to_check.push_back(RS_GXS_GRP_META_DATA_VERSION_ID_0002) ; // put newest first, for debug info purpose - api_versions_to_check.push_back(RS_GXS_GRP_META_DATA_VERSION_ID_0001) ; - - RsTlvKeySignatureSet signSet = grpMeta.signSet; - grpMeta.signSet.TlvClear(); - - int signOk =0; - EVP_PKEY *signKey = EVP_PKEY_new(); - EVP_PKEY_assign_RSA(signKey, rsakey); - - - for(uint32_t i=0;i0) - std::cerr << "(WW) Checking group signature with old api version " << i+1 << " : tag " << std::hex << api_versions_to_check[i] << std::dec << " result: " << signOk << std::endl; -#endif - } - - /* clean up */ - EVP_PKEY_free(signKey); - - // restore data - - grpMeta.signSet = signSet; - - if (signOk == 1) - { -#ifdef GXS_SECURITY_DEBUG - std::cerr << "GxsSecurity::validateNxsGrp() Signature OK"; - std::cerr << std::endl; -#endif - return true; - } - -#ifdef GXS_SECURITY_DEBUG - std::cerr << "GxsSecurity::validateNxsGrp() Signature invalid"; - std::cerr << std::endl; -#endif - - return false; -} - -void GxsSecurity::createPublicKeysFromPrivateKeys(RsTlvSecurityKeySet& keyset) -{ - for( std::map::const_iterator it = keyset.private_keys.begin(); it != keyset.private_keys.end() ; ++it) - if(keyset.public_keys.find(it->second.keyId) == keyset.public_keys.end()) - { - RsTlvPublicRSAKey pub_key ; - - if(!extractPublicKey(it->second,pub_key)) - { - std::cerr << "(EE) ERROR when trying to generate public key from private key for ID " << it->second.keyId << ". This is probably a bug with security implications." << std::endl; - continue ; - } - - keyset.public_keys[it->second.keyId] = pub_key ; - - std::cerr << "(II) Generated missing public key for ID " << it->second.keyId << " from private key." << std::endl; - } -} diff --git a/libretroshare/src/gxs/gxssecurity.h b/libretroshare/src/gxs/gxssecurity.h deleted file mode 100644 index 7b607c916..000000000 --- a/libretroshare/src/gxs/gxssecurity.h +++ /dev/null @@ -1,138 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: gxssecurity.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008-2010 by Robert Fernie * - * 2011-2012 Christopher Evi-Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef GXSSECURITY_H -#define GXSSECURITY_H - -#include "serialiser/rstlvkeys.h" - -#include "rsitems/rsnxsitems.h" - -#include -#include - - -/*! - * This contains functionality for performing basic security operations needed - * in RsGenExchange operations. - * Also has routine for creating security objects around msgs and groups - * TODO: Those functions doesn't do param checking! - */ -class GxsSecurity -{ - public: - /*! - * Extracts a public key from a private key. - */ - static bool extractPublicKey(const RsTlvPrivateRSAKey& private_key,RsTlvPublicRSAKey& public_key) ; - - /*! - * Generates a public/private RSA keypair. To be used for all GXS purposes. - * @param RsTlvSecurityKey public RSA key - * @param RsTlvSecurityKey private RSA key - * @return true if the generate was successful, false otherwise. - */ - static bool generateKeyPair(RsTlvPublicRSAKey &public_key, RsTlvPrivateRSAKey &private_key) ; - - /*! - * Encrypts data using envelope encryption (taken from open ssl's evp_sealinit ) - * only full publish key holders can encrypt data for given group - *@param out - *@param outlen - *@param in - *@param inlen - */ - static bool encrypt(uint8_t *&out, uint32_t &outlen, const uint8_t *in, uint32_t inlen, const RsTlvPublicRSAKey& key) ; - static bool encrypt(uint8_t *&out, uint32_t &outlen, const uint8_t *in, uint32_t inlen, const std::vector& keys) ; - - /** - * Decrypts data using evelope decryption (taken from open ssl's evp_sealinit ) - * only full publish key holders can decrypt data for a group - * @param out where decrypted data is written to - * @param outlen - * @param in - * @param inlen - * @return false if encryption failed - */ - static bool decrypt(uint8_t *&out, uint32_t &outlen, const uint8_t *in, uint32_t inlen, const RsTlvPrivateRSAKey& key) ; - static bool decrypt(uint8_t *& out, uint32_t & outlen, const uint8_t *in, uint32_t inlen, const std::vector& keys); - - /*! - * uses grp signature to check if group has been - * tampered with - * @param newGrp the Nxs group to be validated - * @param sign the signature to validdate against - * @param key the public key to use to check signature - * @return true if group valid false otherwise - */ - static bool validateNxsGrp(const RsNxsGrp& grp, const RsTlvKeySignature& sign, const RsTlvPublicRSAKey& key); - - /*! - * Validate a msg's signature using the given public key - * @param msg the Nxs message to be validated - * @param sign the signature to validdate against - * @param key the public key to use to check signature - * @return false if verfication of signature is not passed - */ - static bool validateNxsMsg(const RsNxsMsg& msg, const RsTlvKeySignature& sign, const RsTlvPublicRSAKey &key); - - - /*! - * @param data data to be signed - * @param data_len length of data to be signed - * @param privKey private key to used to make signature - * @param sign the signature is stored here - * @return false if signature creation failed, true is signature created - */ - static bool getSignature(const char *data, uint32_t data_len, const RsTlvPrivateRSAKey& privKey, RsTlvKeySignature& sign); - - /*! - * @param data data that has been signed - * @param data_len length of signed data - * @param privKey public key to used to check signature - * @param sign Signature for the data - * @return true if signature checks - */ - static bool validateSignature(const char *data, uint32_t data_len, const RsTlvPublicRSAKey& pubKey, const RsTlvKeySignature& sign); - - /*! - * Checks that the public key has correct fingerprint and correct flags. - * @brief checkPublicKey - * @param key - * @return false if the key is invalid. - */ - - static bool checkPublicKey(const RsTlvPublicRSAKey &key); - static bool checkPrivateKey(const RsTlvPrivateRSAKey &key); - static bool checkFingerprint(const RsTlvPublicRSAKey& key); // helper function to only check the fingerprint - - /*! - * Adds possibly missing public keys when private keys are present. - * - * \brief createPublicKeysForPrivateKeys - * \param set set of keys to consider - * \return - */ - static void createPublicKeysFromPrivateKeys(RsTlvSecurityKeySet& set) ; -}; - -#endif // GXSSECURITY_H diff --git a/libretroshare/src/gxs/gxstokenqueue.cc b/libretroshare/src/gxs/gxstokenqueue.cc deleted file mode 100644 index 227ea33fc..000000000 --- a/libretroshare/src/gxs/gxstokenqueue.cc +++ /dev/null @@ -1,95 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: gxstokenqueue.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "gxs/gxstokenqueue.h" - -/******* - * #define GXS_DEBUG 1 - ******/ - -bool GxsTokenQueue::queueRequest(uint32_t token, uint32_t req_type) -{ - RS_STACK_MUTEX(mQueueMtx); - mQueue.push_back(GxsTokenQueueItem(token, req_type)); - return true; -} - - -void GxsTokenQueue::checkRequests() -{ - { - RS_STACK_MUTEX(mQueueMtx); - if (mQueue.empty()) return; - } - - // Must check all, and move to a different list - for reentrant / good mutex behaviour. - std::list toload; - std::list::iterator it; - bool stuffToLoad = false; - - { - RS_STACK_MUTEX(mQueueMtx); - for(it = mQueue.begin(); it != mQueue.end();) - { - uint32_t token = it->mToken; - it->mStatus = mGenExchange->getTokenService()->requestStatus(token); - - if ( it->mStatus == RsTokenService::COMPLETE - || it->mStatus == RsTokenService::CANCELLED ) - { - toload.push_back(*it); - it = mQueue.erase(it); - stuffToLoad = true; - -#ifdef GXS_DEBUG - std::cerr << "GxsTokenQueue::checkRequests() token: " << token - << " Complete" << std::endl; -#endif - ++it; - } - else if (it->mStatus == RsTokenService::FAILED) - { - // maybe we should do alternative callback? - std::cerr << __PRETTY_FUNCTION__ << " ERROR Request Failed! " - << " token: " << token << std::endl; - - it = mQueue.erase(it); - } - else - { -#ifdef GXS_DEBUG - std::cerr << "GxsTokenQueue::checkRequests() token: " << token - << " is unfinished, status: " << status << std::endl; -#endif - ++it; - } - } - } // RS_STACK_MUTEX(mQueueMtx) END - - if (stuffToLoad) - { - for(it = toload.begin(); it != toload.end(); ++it) - { - handleResponse(it->mToken, it->mReqType, it->mStatus); - } - } -} - diff --git a/libretroshare/src/gxs/gxstokenqueue.h b/libretroshare/src/gxs/gxstokenqueue.h deleted file mode 100644 index e4445c44a..000000000 --- a/libretroshare/src/gxs/gxstokenqueue.h +++ /dev/null @@ -1,70 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: gxstokenqueue.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef R_GXS_TOKEN_QUEUE_H -#define R_GXS_TOKEN_QUEUE_H - -#include "gxs/rsgenexchange.h" -#include "retroshare/rsservicecontrol.h" -#include "util/rsthreads.h" - - -struct GxsTokenQueueItem -{ -public: - - GxsTokenQueueItem(const uint32_t token, const uint32_t req_type) : - mToken(token), mReqType(req_type), mStatus(RsTokenService::PENDING) {} - - GxsTokenQueueItem(): mToken(0), mReqType(0), mStatus(RsTokenService::PENDING) {} - - uint32_t mToken; - uint32_t mReqType; - RsTokenService::GxsRequestStatus mStatus; -}; - - -/** - * A little helper class, to manage callbacks from requests - */ -class GxsTokenQueue -{ -public: - explicit GxsTokenQueue(RsGenExchange *gxs) : - mGenExchange(gxs), mQueueMtx("GxsTokenQueueMtx") {} - - bool queueRequest(uint32_t token, uint32_t req_type); - void checkRequests(); /// must be called by - -protected: - - /// This must be overloaded to complete the functionality. - virtual void handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) = 0; - -private: - RsGenExchange *mGenExchange; - RsMutex mQueueMtx; - std::list mQueue; -}; - - -#endif //R_GXS_TOKEN_QUEUE_H diff --git a/libretroshare/src/gxs/rsdataservice.cc b/libretroshare/src/gxs/rsdataservice.cc deleted file mode 100644 index b0415a9f6..000000000 --- a/libretroshare/src/gxs/rsdataservice.cc +++ /dev/null @@ -1,1780 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: gxsdataservice.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Evi-Parker Christopher * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -/***** - * #define RS_DATA_SERVICE_DEBUG 1 - * #define RS_DATA_SERVICE_DEBUG_TIME 1 - * #define RS_DATA_SERVICE_DEBUG_CACHE 1 - ****/ - -#include -#include -#include - -#ifdef RS_DATA_SERVICE_DEBUG_TIME -#include -#endif - -#include "rsdataservice.h" -#include "retroshare/rsgxsflags.h" -#include "util/rsstring.h" - -#define MSG_TABLE_NAME std::string("MESSAGES") -#define GRP_TABLE_NAME std::string("GROUPS") -#define DATABASE_RELEASE_TABLE_NAME std::string("DATABASE_RELEASE") - -#define GRP_LAST_POST_UPDATE_TRIGGER std::string("LAST_POST_UPDATE") - -#define MSG_INDEX_GRPID std::string("INDEX_MESSAGES_GRPID") - -// generic -#define KEY_NXS_DATA std::string("nxsData") -#define KEY_NXS_DATA_LEN std::string("nxsDataLen") -#define KEY_NXS_IDENTITY std::string("identity") -#define KEY_GRP_ID std::string("grpId") -#define KEY_ORIG_GRP_ID std::string("origGrpId") -#define KEY_PARENT_GRP_ID std::string("parentGrpId") -#define KEY_SIGN_SET std::string("signSet") -#define KEY_TIME_STAMP std::string("timeStamp") -#define KEY_NXS_FLAGS std::string("flags") -#define KEY_NXS_META std::string("meta") -#define KEY_NXS_SERV_STRING std::string("serv_str") -#define KEY_NXS_HASH std::string("hash") -#define KEY_RECV_TS std::string("recv_time_stamp") - -// remove later -#define KEY_NXS_FILE_OLD std::string("nxsFile") -#define KEY_NXS_FILE_OFFSET_OLD std::string("fileOffset") -#define KEY_NXS_FILE_LEN_OLD std::string("nxsFileLen") - -// grp table columns -#define KEY_KEY_SET std::string("keySet") -#define KEY_GRP_NAME std::string("grpName") -#define KEY_GRP_SIGN_FLAGS std::string("signFlags") -#define KEY_GRP_CIRCLE_ID std::string("circleId") -#define KEY_GRP_CIRCLE_TYPE std::string("circleType") -#define KEY_GRP_INTERNAL_CIRCLE std::string("internalCircle") -#define KEY_GRP_ORIGINATOR std::string("originator") -#define KEY_GRP_AUTHEN_FLAGS std::string("authenFlags") - -// grp local -#define KEY_GRP_SUBCR_FLAG std::string("subscribeFlag") -#define KEY_GRP_POP std::string("popularity") -#define KEY_MSG_COUNT std::string("msgCount") -#define KEY_GRP_STATUS std::string("grpStatus") -#define KEY_GRP_LAST_POST std::string("lastPost") -#define KEY_GRP_REP_CUTOFF std::string("rep_cutoff") - -// msg table columns -#define KEY_MSG_ID std::string("msgId") -#define KEY_ORIG_MSG_ID std::string("origMsgId") -#define KEY_MSG_PARENT_ID std::string("parentId") -#define KEY_MSG_THREAD_ID std::string("threadId") -#define KEY_MSG_NAME std::string("msgName") - -// msg local -#define KEY_MSG_STATUS std::string("msgStatus") -#define KEY_CHILD_TS std::string("childTs") - -// database release columns -#define KEY_DATABASE_RELEASE_ID std::string("id") -#define KEY_DATABASE_RELEASE_ID_VALUE 1 -#define KEY_DATABASE_RELEASE std::string("release") - -const std::string RsGeneralDataService::GRP_META_SERV_STRING = KEY_NXS_SERV_STRING; -const std::string RsGeneralDataService::GRP_META_STATUS = KEY_GRP_STATUS; -const std::string RsGeneralDataService::GRP_META_SUBSCRIBE_FLAG = KEY_GRP_SUBCR_FLAG; -const std::string RsGeneralDataService::GRP_META_CUTOFF_LEVEL = KEY_GRP_REP_CUTOFF; - -const std::string RsGeneralDataService::MSG_META_SERV_STRING = KEY_NXS_SERV_STRING; -const std::string RsGeneralDataService::MSG_META_STATUS = KEY_MSG_STATUS; - -const uint32_t RsGeneralDataService::GXS_MAX_ITEM_SIZE = 1572864; // 1.5 Mbytes - -static int addColumn(std::list &list, const std::string &attribute) -{ - list.push_back(attribute); - return list.size() - 1; -} - -RsDataService::RsDataService(const std::string &serviceDir, const std::string &dbName, uint16_t serviceType, - RsGxsSearchModule * /* mod */, const std::string& key) - : RsGeneralDataService(), mDbMutex("RsDataService"), mServiceDir(serviceDir), mDbName(dbName), mDbPath(mServiceDir + "/" + dbName), mServType(serviceType), mDb(NULL) -{ - bool isNewDatabase = !RsDirUtil::fileExists(mDbPath); - - mDb = new RetroDb(mDbPath, RetroDb::OPEN_READWRITE_CREATE, key); - mUseCache = true; - - initialise(isNewDatabase); - - // for retrieving msg meta - mColMsgMeta_GrpId = addColumn(mMsgMetaColumns, KEY_GRP_ID); - mColMsgMeta_TimeStamp = addColumn(mMsgMetaColumns, KEY_TIME_STAMP); - mColMsgMeta_NxsFlags = addColumn(mMsgMetaColumns, KEY_NXS_FLAGS); - mColMsgMeta_SignSet = addColumn(mMsgMetaColumns, KEY_SIGN_SET); - mColMsgMeta_NxsIdentity = addColumn(mMsgMetaColumns, KEY_NXS_IDENTITY); - mColMsgMeta_NxsHash = addColumn(mMsgMetaColumns, KEY_NXS_HASH); - mColMsgMeta_MsgId = addColumn(mMsgMetaColumns, KEY_MSG_ID); - mColMsgMeta_OrigMsgId = addColumn(mMsgMetaColumns, KEY_ORIG_MSG_ID); - mColMsgMeta_MsgStatus = addColumn(mMsgMetaColumns, KEY_MSG_STATUS); - mColMsgMeta_ChildTs = addColumn(mMsgMetaColumns, KEY_CHILD_TS); - mColMsgMeta_MsgParentId = addColumn(mMsgMetaColumns, KEY_MSG_PARENT_ID); - mColMsgMeta_MsgThreadId = addColumn(mMsgMetaColumns, KEY_MSG_THREAD_ID); - mColMsgMeta_Name = addColumn(mMsgMetaColumns, KEY_MSG_NAME); - mColMsgMeta_NxsServString = addColumn(mMsgMetaColumns, KEY_NXS_SERV_STRING); - mColMsgMeta_RecvTs = addColumn(mMsgMetaColumns, KEY_RECV_TS); - mColMsgMeta_NxsDataLen = addColumn(mMsgMetaColumns, KEY_NXS_DATA_LEN); - - // for retrieving actual data - mColMsg_GrpId = addColumn(mMsgColumns, KEY_GRP_ID); - mColMsg_NxsData = addColumn(mMsgColumns, KEY_NXS_DATA); - mColMsg_MetaData = addColumn(mMsgColumns, KEY_NXS_META); - mColMsg_MsgId = addColumn(mMsgColumns, KEY_MSG_ID); - - // for retrieving msg data with meta - mMsgColumnsWithMeta = mMsgColumns; - mColMsg_WithMetaOffset = mMsgColumnsWithMeta.size(); - mMsgColumnsWithMeta.insert(mMsgColumnsWithMeta.end(), mMsgMetaColumns.begin(), mMsgMetaColumns.end()); - - // for retrieving grp meta data - mColGrpMeta_GrpId = addColumn(mGrpMetaColumns, KEY_GRP_ID); - mColGrpMeta_TimeStamp = addColumn(mGrpMetaColumns, KEY_TIME_STAMP); - mColGrpMeta_NxsFlags = addColumn(mGrpMetaColumns, KEY_NXS_FLAGS); -// mColGrpMeta_SignSet = addColumn(mGrpMetaColumns, KEY_SIGN_SET); - mColGrpMeta_NxsIdentity = addColumn(mGrpMetaColumns, KEY_NXS_IDENTITY); - mColGrpMeta_NxsHash = addColumn(mGrpMetaColumns, KEY_NXS_HASH); - mColGrpMeta_KeySet = addColumn(mGrpMetaColumns, KEY_KEY_SET); - mColGrpMeta_SubscrFlag = addColumn(mGrpMetaColumns, KEY_GRP_SUBCR_FLAG); - mColGrpMeta_Pop = addColumn(mGrpMetaColumns, KEY_GRP_POP); - mColGrpMeta_MsgCount = addColumn(mGrpMetaColumns, KEY_MSG_COUNT); - mColGrpMeta_Status = addColumn(mGrpMetaColumns, KEY_GRP_STATUS); - mColGrpMeta_Name = addColumn(mGrpMetaColumns, KEY_GRP_NAME); - mColGrpMeta_LastPost = addColumn(mGrpMetaColumns, KEY_GRP_LAST_POST); - mColGrpMeta_OrigGrpId = addColumn(mGrpMetaColumns, KEY_ORIG_GRP_ID); - mColGrpMeta_ServString = addColumn(mGrpMetaColumns, KEY_NXS_SERV_STRING); - mColGrpMeta_SignFlags = addColumn(mGrpMetaColumns, KEY_GRP_SIGN_FLAGS); - mColGrpMeta_CircleId = addColumn(mGrpMetaColumns, KEY_GRP_CIRCLE_ID); - mColGrpMeta_CircleType = addColumn(mGrpMetaColumns, KEY_GRP_CIRCLE_TYPE); - mColGrpMeta_InternCircle = addColumn(mGrpMetaColumns, KEY_GRP_INTERNAL_CIRCLE); - mColGrpMeta_Originator = addColumn(mGrpMetaColumns, KEY_GRP_ORIGINATOR); - mColGrpMeta_AuthenFlags = addColumn(mGrpMetaColumns, KEY_GRP_AUTHEN_FLAGS); - mColGrpMeta_ParentGrpId = addColumn(mGrpMetaColumns, KEY_PARENT_GRP_ID); - mColGrpMeta_RecvTs = addColumn(mGrpMetaColumns, KEY_RECV_TS); - mColGrpMeta_RepCutoff = addColumn(mGrpMetaColumns, KEY_GRP_REP_CUTOFF); - mColGrpMeta_NxsDataLen = addColumn(mGrpMetaColumns, KEY_NXS_DATA_LEN); - - // for retrieving actual grp data - mColGrp_GrpId = addColumn(mGrpColumns, KEY_GRP_ID); - mColGrp_NxsData = addColumn(mGrpColumns, KEY_NXS_DATA); - mColGrp_MetaData = addColumn(mGrpColumns, KEY_NXS_META); - - // for retrieving grp data with meta - mGrpColumnsWithMeta = mGrpColumns; - mColGrp_WithMetaOffset = mGrpColumnsWithMeta.size(); - mGrpColumnsWithMeta.insert(mGrpColumnsWithMeta.end(), mGrpMetaColumns.begin(), mGrpMetaColumns.end()); - - // Group id columns - mColGrpId_GrpId = addColumn(mGrpIdColumn, KEY_GRP_ID); - - // Msg id columns - mColMsgId_MsgId = addColumn(mMsgIdColumn, KEY_MSG_ID); -} - -RsDataService::~RsDataService(){ - -#ifdef RS_DATA_SERVICE_DEBUG - std::cerr << "RsDataService::~RsDataService()"; - std::cerr << std::endl; -#endif - - mDb->closeDb(); - delete mDb; -} - -static bool moveDataFromFileToDatabase(RetroDb *db, const std::string serviceDir, const std::string &tableName, const std::string &keyId, std::list &files) -{ - bool ok = true; - - // Move message data - std::list columns; - columns.push_back(keyId); - columns.push_back(KEY_NXS_FILE_OLD); - columns.push_back(KEY_NXS_FILE_OFFSET_OLD); - columns.push_back(KEY_NXS_FILE_LEN_OLD); - - RetroCursor* c = db->sqlQuery(tableName, columns, "", ""); - - if (c) - { - bool valid = c->moveToFirst(); - - while (ok && valid){ - std::string dataFile; - c->getString(1, dataFile); - - if (!dataFile.empty()) { - bool fileOk = true; - - // first try to find the file in the service dir - if (RsDirUtil::fileExists(serviceDir + "/" + dataFile)) { - dataFile.insert(0, serviceDir + "/"); - } else if (RsDirUtil::fileExists(dataFile)) { - // use old way for backward compatibility - //TODO: can be removed later - } else { - fileOk = false; - - std::cerr << "moveDataFromFileToDatabase() cannot find file " << dataFile; - std::cerr << std::endl; - } - - if (fileOk) { - std::string id; - c->getString(0, id); - - uint32_t offset = c->getInt32(2); - uint32_t data_len = c->getInt32(3); - - char* data = new char[data_len]; - std::ifstream istrm(dataFile.c_str(), std::ios::binary); - istrm.seekg(offset, std::ios::beg); - istrm.read(data, data_len); - istrm.close(); - - ContentValue cv; - // insert new columns - cv.put(KEY_NXS_DATA, data_len, data); - cv.put(KEY_NXS_DATA_LEN, (int32_t) data_len); - // clear old columns - cv.put(KEY_NXS_FILE_OLD, ""); - cv.put(KEY_NXS_FILE_OFFSET_OLD, 0); - cv.put(KEY_NXS_FILE_LEN_OLD, 0); - - ok = db->sqlUpdate(tableName, keyId + "='" + id + "'", cv); - delete[] data; - - if (std::find(files.begin(), files.end(), dataFile) == files.end()) { - files.push_back(dataFile); - } - } - } - - valid = c->moveToNext(); - } - - delete c; - } - - return ok; -} - -void RsDataService::initialise(bool isNewDatabase) -{ - const int databaseRelease = 1; - int currentDatabaseRelease = 0; - bool ok = true; - - RsStackMutex stack(mDbMutex); - - // initialise database - - if (isNewDatabase || !mDb->tableExists(DATABASE_RELEASE_TABLE_NAME)) { - // create table for database release - mDb->execSQL("CREATE TABLE " + DATABASE_RELEASE_TABLE_NAME + "(" + - KEY_DATABASE_RELEASE_ID + " INT PRIMARY KEY," + - KEY_DATABASE_RELEASE + " INT);"); - } - - if (isNewDatabase) { - // create table for msg data - mDb->execSQL("CREATE TABLE " + MSG_TABLE_NAME + "(" + - KEY_MSG_ID + " TEXT PRIMARY KEY," + - KEY_GRP_ID + " TEXT," + - KEY_NXS_FLAGS + " INT," + - KEY_ORIG_MSG_ID + " TEXT," + - KEY_TIME_STAMP + " INT," + - KEY_NXS_IDENTITY + " TEXT," + - KEY_SIGN_SET + " BLOB," + - KEY_NXS_DATA + " BLOB,"+ - KEY_NXS_DATA_LEN + " INT," + - KEY_MSG_STATUS + " INT," + - KEY_CHILD_TS + " INT," + - KEY_NXS_META + " BLOB," + - KEY_MSG_THREAD_ID + " TEXT," + - KEY_MSG_PARENT_ID + " TEXT,"+ - KEY_MSG_NAME + " TEXT," + - KEY_NXS_SERV_STRING + " TEXT," + - KEY_NXS_HASH + " TEXT," + - KEY_RECV_TS + " INT);"); - - // create table for grp data - mDb->execSQL("CREATE TABLE " + GRP_TABLE_NAME + "(" + - KEY_GRP_ID + " TEXT PRIMARY KEY," + - KEY_TIME_STAMP + " INT," + - KEY_NXS_DATA + " BLOB," + - KEY_NXS_DATA_LEN + " INT," + - KEY_KEY_SET + " BLOB," + - KEY_NXS_META + " BLOB," + - KEY_GRP_NAME + " TEXT," + - KEY_GRP_LAST_POST + " INT," + - KEY_GRP_POP + " INT," + - KEY_MSG_COUNT + " INT," + - KEY_GRP_SUBCR_FLAG + " INT," + - KEY_GRP_STATUS + " INT," + - KEY_NXS_IDENTITY + " TEXT," + - KEY_ORIG_GRP_ID + " TEXT," + - KEY_NXS_SERV_STRING + " TEXT," + - KEY_NXS_FLAGS + " INT," + - KEY_GRP_AUTHEN_FLAGS + " INT," + - KEY_GRP_SIGN_FLAGS + " INT," + - KEY_GRP_CIRCLE_ID + " TEXT," + - KEY_GRP_CIRCLE_TYPE + " INT," + - KEY_GRP_INTERNAL_CIRCLE + " TEXT," + - KEY_GRP_ORIGINATOR + " TEXT," + - KEY_NXS_HASH + " TEXT," + - KEY_RECV_TS + " INT," + - KEY_PARENT_GRP_ID + " TEXT," + - KEY_GRP_REP_CUTOFF + " INT," + - KEY_SIGN_SET + " BLOB);"); - - mDb->execSQL("CREATE TRIGGER " + GRP_LAST_POST_UPDATE_TRIGGER + - " INSERT ON " + MSG_TABLE_NAME + - std::string(" BEGIN ") + - " UPDATE " + GRP_TABLE_NAME + " SET " + KEY_GRP_LAST_POST + "= new." - + KEY_RECV_TS + " WHERE " + KEY_GRP_ID + "=new." + KEY_GRP_ID + ";" - + std::string("END;")); - - mDb->execSQL("CREATE INDEX " + MSG_INDEX_GRPID + " ON " + MSG_TABLE_NAME + "(" + KEY_GRP_ID + ");"); - - // Insert release, no need to upgrade - ContentValue cv; - cv.put(KEY_DATABASE_RELEASE_ID, KEY_DATABASE_RELEASE_ID_VALUE); - cv.put(KEY_DATABASE_RELEASE, databaseRelease); - mDb->sqlInsert(DATABASE_RELEASE_TABLE_NAME, "", cv); - - currentDatabaseRelease = databaseRelease; - } else { - // check release - - { - // try to select the release - std::list columns; - columns.push_back(KEY_DATABASE_RELEASE); - - std::string where; - rs_sprintf(where, "%s=%d", KEY_DATABASE_RELEASE_ID.c_str(), KEY_DATABASE_RELEASE_ID_VALUE); - - RetroCursor* c = mDb->sqlQuery(DATABASE_RELEASE_TABLE_NAME, columns, where, ""); - if (c) { - ok = c->moveToFirst(); - - if (ok) { - currentDatabaseRelease = c->getInt32(0); - } - delete c; - - if (!ok) { - // No record found ... insert the record - ContentValue cv; - cv.put(KEY_DATABASE_RELEASE_ID, KEY_DATABASE_RELEASE_ID_VALUE); - cv.put(KEY_DATABASE_RELEASE, currentDatabaseRelease); - ok = mDb->sqlInsert(DATABASE_RELEASE_TABLE_NAME, "", cv); - } - } else { - ok = false; - } - } - - // Release 1 - int newRelease = 1; - if (ok && currentDatabaseRelease < newRelease) { - // Update database - std::list files; - - ok = startReleaseUpdate(newRelease); - - // Move data in files into database - ok = ok && mDb->execSQL("ALTER TABLE " + GRP_TABLE_NAME + " ADD COLUMN " + KEY_NXS_DATA + " BLOB;"); - ok = ok && mDb->execSQL("ALTER TABLE " + GRP_TABLE_NAME + " ADD COLUMN " + KEY_NXS_DATA_LEN + " INT;"); - ok = ok && mDb->execSQL("ALTER TABLE " + MSG_TABLE_NAME + " ADD COLUMN " + KEY_NXS_DATA + " BLOB;"); - ok = ok && mDb->execSQL("ALTER TABLE " + MSG_TABLE_NAME + " ADD COLUMN " + KEY_NXS_DATA_LEN + " INT;"); - - ok = ok && moveDataFromFileToDatabase(mDb, mServiceDir, GRP_TABLE_NAME, KEY_GRP_ID, files); - ok = ok && moveDataFromFileToDatabase(mDb, mServiceDir, MSG_TABLE_NAME, KEY_MSG_ID, files); - -// SQLite doesn't support DROP COLUMN -// ok = ok && mDb->execSQL("ALTER TABLE " + GRP_TABLE_NAME + " DROP COLUMN " + KEY_NXS_FILE_OLD + ";"); -// ok = ok && mDb->execSQL("ALTER TABLE " + GRP_TABLE_NAME + " DROP COLUMN " + KEY_NXS_FILE_OFFSET_OLD + ";"); -// ok = ok && mDb->execSQL("ALTER TABLE " + GRP_TABLE_NAME + " DROP COLUMN " + KEY_NXS_FILE_LEN_OLD + ";"); -// ok = ok && mDb->execSQL("ALTER TABLE " + MSG_TABLE_NAME + " DROP COLUMN " + KEY_NXS_FILE_OLD + ";"); -// ok = ok && mDb->execSQL("ALTER TABLE " + MSG_TABLE_NAME + " DROP COLUMN " + KEY_NXS_FILE_OFFSET_OLD + ";"); -// ok = ok && mDb->execSQL("ALTER TABLE " + MSG_TABLE_NAME + " DROP COLUMN " + KEY_NXS_FILE_LEN_OLD + ";"); - - ok = finishReleaseUpdate(newRelease, ok); - if (ok) { - // Remove transfered files - std::list::const_iterator file; - for (file = files.begin(); file != files.end(); ++file) { - remove(file->c_str()); - } - currentDatabaseRelease = newRelease; - } - } - } - - if (ok) { - std::cerr << "Database " << mDbName << " release " << currentDatabaseRelease << " successfully initialised." << std::endl; - } else { - std::cerr << "Database " << mDbName << " initialisation failed." << std::endl; - } -} - -bool RsDataService::startReleaseUpdate(int release) -{ - // Update database - std::cerr << "Database " << mDbName << " update to release " << release << "." << std::endl; - - return mDb->beginTransaction(); -} - -bool RsDataService::finishReleaseUpdate(int release, bool result) -{ - if (result) { - std::string where; - rs_sprintf(where, "%s=%d", KEY_DATABASE_RELEASE_ID.c_str(), KEY_DATABASE_RELEASE_ID_VALUE); - - ContentValue cv; - cv.put(KEY_DATABASE_RELEASE, release); - result = mDb->sqlUpdate(DATABASE_RELEASE_TABLE_NAME, where, cv); - } - - if (result) { - result = mDb->commitTransaction(); - } else { - result = mDb->rollbackTransaction(); - } - - if (result) { - std::cerr << "Database " << mDbName << " successfully updated to release " << release << "." << std::endl; - } else { - std::cerr << "Database " << mDbName << " update to release " << release << "failed." << std::endl; - } - - return result; -} - -std::shared_ptr RsDataService::locked_getGrpMeta(RetroCursor& c, int colOffset) -{ -#ifdef RS_DATA_SERVICE_DEBUG - std::cerr << "RsDataService::locked_getGrpMeta()" << std::endl; -#endif - - bool ok = true; - - // for extracting raw data - uint32_t offset = 0; - char* data = NULL; - uint32_t data_len = 0; - - // grpId - std::string tempId; - c.getString(mColGrpMeta_GrpId + colOffset, tempId); - - std::shared_ptr grpMeta ; - RsGxsGroupId grpId(tempId) ; - - if(grpId.isNull()) // not in the DB! - return nullptr; - - if(mUseCache) - grpMeta = mGrpMetaDataCache.getOrCreateMeta(grpId); - else - grpMeta = std::make_shared(); - - if(!grpMeta->mGroupId.isNull()) // the grpMeta is already initialized because it comes from the cache - return grpMeta; - - grpMeta->mGroupId = RsGxsGroupId(tempId); - c.getString(mColGrpMeta_NxsIdentity + colOffset, tempId); - grpMeta->mAuthorId = RsGxsId(tempId); - - c.getString(mColGrpMeta_Name + colOffset, grpMeta->mGroupName); - c.getString(mColGrpMeta_OrigGrpId + colOffset, tempId); - grpMeta->mOrigGrpId = RsGxsGroupId(tempId); - c.getString(mColGrpMeta_ServString + colOffset, grpMeta->mServiceString); - std::string temp; - c.getString(mColGrpMeta_NxsHash + colOffset, temp); - grpMeta->mHash = RsFileHash(temp); - grpMeta->mReputationCutOff = c.getInt32(mColGrpMeta_RepCutoff + colOffset); - grpMeta->mSignFlags = c.getInt32(mColGrpMeta_SignFlags + colOffset); - - grpMeta->mPublishTs = c.getInt32(mColGrpMeta_TimeStamp + colOffset); - grpMeta->mGroupFlags = c.getInt32(mColGrpMeta_NxsFlags + colOffset); - grpMeta->mGrpSize = c.getInt32(mColGrpMeta_NxsDataLen + colOffset); - - offset = 0; data = NULL; data_len = 0; - data = (char*)c.getData(mColGrpMeta_KeySet + colOffset, data_len); - - if(data) - ok &= grpMeta->keys.GetTlv(data, data_len, &offset); - else - grpMeta->keys.TlvClear() ; - - // local meta - grpMeta->mSubscribeFlags = c.getInt32(mColGrpMeta_SubscrFlag + colOffset); - grpMeta->mPop = c.getInt32(mColGrpMeta_Pop + colOffset); - grpMeta->mVisibleMsgCount = c.getInt32(mColGrpMeta_MsgCount + colOffset); - grpMeta->mLastPost = c.getInt32(mColGrpMeta_LastPost + colOffset); - grpMeta->mGroupStatus = c.getInt32(mColGrpMeta_Status + colOffset); - - c.getString(mColGrpMeta_CircleId + colOffset, tempId); - grpMeta->mCircleId = RsGxsCircleId(tempId); - grpMeta->mCircleType = c.getInt32(mColGrpMeta_CircleType + colOffset); - c.getString(mColGrpMeta_InternCircle + colOffset, tempId); - grpMeta->mInternalCircle = RsGxsCircleId(tempId); - - std::string s ; c.getString(mColGrpMeta_Originator + colOffset, s) ; - grpMeta->mOriginator = RsPeerId(s); - grpMeta->mAuthenFlags = c.getInt32(mColGrpMeta_AuthenFlags + colOffset); - grpMeta->mRecvTS = c.getInt32(mColGrpMeta_RecvTs + colOffset); - - - c.getString(mColGrpMeta_ParentGrpId, tempId); - grpMeta->mParentGrpId = RsGxsGroupId(tempId); - - // make sure that flags and keys are actually consistent - - bool have_private_admin_key = false ; - bool have_private_publish_key = false ; - - for(auto mit = grpMeta->keys.private_keys.begin(); mit != grpMeta->keys.private_keys.end();++mit) - { - if(mit->second.keyFlags == (RSTLV_KEY_DISTRIB_PUBLISH | RSTLV_KEY_TYPE_FULL)) have_private_publish_key = true ; - if(mit->second.keyFlags == (RSTLV_KEY_DISTRIB_ADMIN | RSTLV_KEY_TYPE_FULL)) have_private_admin_key = true ; - } - - if(have_private_admin_key && !(grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN)) - { - std::cerr << "(WW) inconsistency in group " << grpMeta->mGroupId << ": group does not have flag ADMIN but an admin key was found. Updating the flags." << std::endl; - grpMeta->mSubscribeFlags |= GXS_SERV::GROUP_SUBSCRIBE_ADMIN; - } - if(!have_private_admin_key && (grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN)) - { - std::cerr << "(WW) inconsistency in group " << grpMeta->mGroupId << ": group has flag ADMIN but no admin key found. Updating the flags." << std::endl; - grpMeta->mSubscribeFlags &= ~GXS_SERV::GROUP_SUBSCRIBE_ADMIN; - } - if(have_private_publish_key && !(grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_PUBLISH)) - { - std::cerr << "(WW) inconsistency in group " << grpMeta->mGroupId << ": group does not have flag PUBLISH but an admin key was found. Updating the flags." << std::endl; - grpMeta->mSubscribeFlags |= GXS_SERV::GROUP_SUBSCRIBE_PUBLISH; - } - if(!have_private_publish_key && (grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_PUBLISH)) - { - std::cerr << "(WW) inconsistency in group " << grpMeta->mGroupId << ": group has flag PUBLISH but no admin key found. Updating the flags." << std::endl; - grpMeta->mSubscribeFlags &= ~GXS_SERV::GROUP_SUBSCRIBE_PUBLISH; - } - - if(ok) - return grpMeta; - else - return NULL; -} - -RsNxsGrp* RsDataService::locked_getGroup(RetroCursor &c) -{ - /*! - * grpId, pub admin and pub publish key - * necessary for successful group - */ - RsNxsGrp* grp = new RsNxsGrp(mServType); - bool ok = true; - - // for manipulating raw data - uint32_t offset = 0; - char* data = NULL; - uint32_t data_len = 0; - - // grpId - c.getStringT(mColGrp_GrpId, grp->grpId); - ok &= !grp->grpId.isNull(); - - offset = 0; data_len = 0; - if(ok){ - - data = (char*)c.getData(mColGrp_MetaData, data_len); - if(data) - grp->meta.GetTlv(data, data_len, &offset); - } - - /* now retrieve grp data */ - offset = 0; data_len = 0; - if(ok){ - data = (char*)c.getData(mColGrp_NxsData, data_len); - if(data) - ok &= grp->grp.GetTlv(data, data_len, &offset); - } - - if(ok) - return grp; - else - delete grp; - - return NULL; -} - -std::shared_ptr RsDataService::locked_getMsgMeta(RetroCursor &c, int colOffset) -{ - bool ok = true; - uint32_t data_len = 0, - offset = 0; - char* data = NULL; - - RsGxsGroupId group_id; - RsGxsMessageId msg_id; - - std::string gId; - c.getString(mColMsgMeta_GrpId + colOffset, gId); - group_id = RsGxsGroupId(gId); - std::string temp; - c.getString(mColMsgMeta_MsgId + colOffset, temp); - msg_id = RsGxsMessageId(temp); - - // without these, a msg is meaningless - if(group_id.isNull() || msg_id.isNull()) - return nullptr; - - std::shared_ptr msgMeta; - - if(mUseCache) - msgMeta = mMsgMetaDataCache[group_id].getOrCreateMeta(msg_id); - else - msgMeta = std::make_shared(); - - if(!msgMeta->mGroupId.isNull()) // we cannot do that because the cursor needs to advance. Is there a method to skip some data in the db? - return msgMeta; - - msgMeta->mGroupId = group_id; - msgMeta->mMsgId = msg_id; - - c.getString(mColMsgMeta_OrigMsgId + colOffset, temp); - msgMeta->mOrigMsgId = RsGxsMessageId(temp); - c.getString(mColMsgMeta_NxsIdentity + colOffset, temp); - msgMeta->mAuthorId = RsGxsId(temp); - c.getString(mColMsgMeta_Name + colOffset, msgMeta->mMsgName); - c.getString(mColMsgMeta_NxsServString + colOffset, msgMeta->mServiceString); - - c.getString(mColMsgMeta_NxsHash + colOffset, temp); - msgMeta->mHash = RsFileHash(temp); - msgMeta->recvTS = c.getInt32(mColMsgMeta_RecvTs + colOffset); - offset = 0; - data = (char*)c.getData(mColMsgMeta_SignSet + colOffset, data_len); - msgMeta->signSet.GetTlv(data, data_len, &offset); - msgMeta->mMsgSize = c.getInt32(mColMsgMeta_NxsDataLen + colOffset); - - msgMeta->mMsgFlags = c.getInt32(mColMsgMeta_NxsFlags + colOffset); - msgMeta->mPublishTs = c.getInt32(mColMsgMeta_TimeStamp + colOffset); - - offset = 0; data_len = 0; - - // thread and parent id - c.getString(mColMsgMeta_MsgThreadId + colOffset, temp); - msgMeta->mThreadId = RsGxsMessageId(temp); - c.getString(mColMsgMeta_MsgParentId + colOffset, temp); - msgMeta->mParentId = RsGxsMessageId(temp); - - // local meta - msgMeta->mMsgStatus = c.getInt32(mColMsgMeta_MsgStatus + colOffset); - msgMeta->mChildTs = c.getInt32(mColMsgMeta_ChildTs + colOffset); - - if(ok) - return msgMeta; - - return nullptr; -} - - - -RsNxsMsg* RsDataService::locked_getMessage(RetroCursor &c) -{ - - RsNxsMsg* msg = new RsNxsMsg(mServType); - - bool ok = true; - uint32_t data_len = 0, - offset = 0; - char* data = NULL; - c.getStringT(mColMsg_GrpId, msg->grpId); - std::string temp; - c.getString(mColMsg_MsgId, temp); - msg->msgId = RsGxsMessageId(temp); - - ok &= (!msg->grpId.isNull()) && (!msg->msgId.isNull()); - - offset = 0; data_len = 0; - if(ok){ - - data = (char*)c.getData(mColMsg_MetaData, data_len); - if(data) - msg->meta.GetTlv(data, data_len, &offset); - } - - /* now retrieve msg data */ - offset = 0; data_len = 0; - if(ok){ - data = (char*)c.getData(mColMsg_NxsData, data_len); - if(data) - ok &= msg->msg.GetTlv(data, data_len, &offset); - } - - if(ok) - return msg; - - delete msg; - return nullptr; -} - -int RsDataService::storeMessage(const std::list& msg) -{ - - RsStackMutex stack(mDbMutex); - - // start a transaction - mDb->beginTransaction(); - - for(std::list::const_iterator mit = msg.begin(); mit != msg.end(); ++mit) - { - RsNxsMsg* msgPtr = *mit; - RsGxsMsgMetaData* msgMetaPtr = msgPtr->metaData; - - assert(msgMetaPtr != NULL); - -#ifdef RS_DATA_SERVICE_DEBUG - std::cerr << "RsDataService::storeMessage() "; - std::cerr << " GroupId: " << msgMetaPtr->mGroupId.toStdString(); - std::cerr << " MessageId: " << msgMetaPtr->mMsgId.toStdString(); - std::cerr << std::endl; -#endif - - // skip msg item if size if greater than - if(!validSize(msgPtr)) - { - std::cerr << "RsDataService::storeMessage() ERROR invalid size"; - std::cerr << std::endl; - continue; - } - - ContentValue cv; - - uint32_t dataLen = msgPtr->msg.TlvSize(); - char msgData[dataLen]; - uint32_t offset = 0; - msgPtr->msg.SetTlv(msgData, dataLen, &offset); - cv.put(KEY_NXS_DATA, dataLen, msgData); - - cv.put(KEY_NXS_DATA_LEN, (int32_t)dataLen); - cv.put(KEY_MSG_ID, msgMetaPtr->mMsgId.toStdString()); - cv.put(KEY_GRP_ID, msgMetaPtr->mGroupId.toStdString()); - cv.put(KEY_NXS_SERV_STRING, msgMetaPtr->mServiceString); - cv.put(KEY_NXS_HASH, msgMetaPtr->mHash.toStdString()); - cv.put(KEY_RECV_TS, (int32_t)msgMetaPtr->recvTS); - - - char signSetData[msgMetaPtr->signSet.TlvSize()]; - offset = 0; - msgMetaPtr->signSet.SetTlv(signSetData, msgMetaPtr->signSet.TlvSize(), &offset); - cv.put(KEY_SIGN_SET, msgMetaPtr->signSet.TlvSize(), signSetData); - cv.put(KEY_NXS_IDENTITY, msgMetaPtr->mAuthorId.toStdString()); - - - cv.put(KEY_NXS_FLAGS, (int32_t) msgMetaPtr->mMsgFlags); - cv.put(KEY_TIME_STAMP, (int32_t) msgMetaPtr->mPublishTs); - - offset = 0; - char metaData[msgPtr->meta.TlvSize()]; - msgPtr->meta.SetTlv(metaData, msgPtr->meta.TlvSize(), &offset); - cv.put(KEY_NXS_META, msgPtr->meta.TlvSize(), metaData); - - cv.put(KEY_MSG_PARENT_ID, msgMetaPtr->mParentId.toStdString()); - cv.put(KEY_MSG_THREAD_ID, msgMetaPtr->mThreadId.toStdString()); - cv.put(KEY_ORIG_MSG_ID, msgMetaPtr->mOrigMsgId.toStdString()); - cv.put(KEY_MSG_NAME, msgMetaPtr->mMsgName); - - // now local meta - cv.put(KEY_MSG_STATUS, (int32_t)msgMetaPtr->mMsgStatus); - cv.put(KEY_CHILD_TS, (int32_t)msgMetaPtr->mChildTs); - - if (!mDb->sqlInsert(MSG_TABLE_NAME, "", cv)) - { - std::cerr << "RsDataService::storeMessage() sqlInsert Failed"; - std::cerr << std::endl; - std::cerr << "\t For GroupId: " << msgMetaPtr->mGroupId.toStdString(); - std::cerr << std::endl; - std::cerr << "\t & MessageId: " << msgMetaPtr->mMsgId.toStdString(); - std::cerr << std::endl; - } - - // This is needed so that mLastPost is correctly updated in the group meta when it is re-loaded. - - if(mUseCache) - mMsgMetaDataCache[msgMetaPtr->mGroupId].updateMeta(msgMetaPtr->mMsgId,*msgMetaPtr); - - delete *mit; - } - - // finish transaction - bool ret = mDb->commitTransaction(); - - return ret; -} - -bool RsDataService::validSize(RsNxsMsg* msg) const -{ - if((msg->msg.TlvSize() + msg->meta.TlvSize()) <= GXS_MAX_ITEM_SIZE) return true; - - return false; -} - - -int RsDataService::storeGroup(const std::list& grp) -{ - - RsStackMutex stack(mDbMutex); - - // begin transaction - mDb->beginTransaction(); - - for(std::list::const_iterator sit = grp.begin();sit != grp.end(); ++sit) - { - RsNxsGrp* grpPtr = *sit; - RsGxsGrpMetaData* grpMetaPtr = grpPtr->metaData; - - assert(grpMetaPtr != NULL); - - // if data is larger than max item size do not add - if(!validSize(grpPtr)) continue; - -#ifdef RS_DATA_SERVICE_DEBUG - std::cerr << "RsDataService::storeGroup() GrpId: " << grpPtr->grpId.toStdString(); - std::cerr << " CircleType: " << (uint32_t) grpMetaPtr->mCircleType; - std::cerr << " CircleId: " << grpMetaPtr->mCircleId.toStdString(); - std::cerr << std::endl; -#endif - - /*! - * STORE data, data len, - * grpId, flags, publish time stamp, identity, - * id signature, admin signatue, key set, last posting ts - * and meta data - **/ - ContentValue cv; - - uint32_t dataLen = grpPtr->grp.TlvSize(); - char grpData[dataLen]; - uint32_t offset = 0; - grpPtr->grp.SetTlv(grpData, dataLen, &offset); - cv.put(KEY_NXS_DATA, dataLen, grpData); - - cv.put(KEY_NXS_DATA_LEN, (int32_t) dataLen); - cv.put(KEY_GRP_ID, grpPtr->grpId.toStdString()); - cv.put(KEY_GRP_NAME, grpMetaPtr->mGroupName); - cv.put(KEY_ORIG_GRP_ID, grpMetaPtr->mOrigGrpId.toStdString()); - cv.put(KEY_NXS_SERV_STRING, grpMetaPtr->mServiceString); - cv.put(KEY_NXS_FLAGS, (int32_t)grpMetaPtr->mGroupFlags); - cv.put(KEY_TIME_STAMP, (int32_t)grpMetaPtr->mPublishTs); - cv.put(KEY_GRP_SIGN_FLAGS, (int32_t)grpMetaPtr->mSignFlags); - cv.put(KEY_GRP_CIRCLE_ID, grpMetaPtr->mCircleId.toStdString()); - cv.put(KEY_GRP_CIRCLE_TYPE, (int32_t)grpMetaPtr->mCircleType); - cv.put(KEY_GRP_INTERNAL_CIRCLE, grpMetaPtr->mInternalCircle.toStdString()); - cv.put(KEY_GRP_ORIGINATOR, grpMetaPtr->mOriginator.toStdString()); - cv.put(KEY_GRP_AUTHEN_FLAGS, (int32_t)grpMetaPtr->mAuthenFlags); - cv.put(KEY_PARENT_GRP_ID, grpMetaPtr->mParentGrpId.toStdString()); - cv.put(KEY_NXS_HASH, grpMetaPtr->mHash.toStdString()); - cv.put(KEY_RECV_TS, (int32_t)grpMetaPtr->mRecvTS); - cv.put(KEY_GRP_REP_CUTOFF, (int32_t)grpMetaPtr->mReputationCutOff); - cv.put(KEY_NXS_IDENTITY, grpMetaPtr->mAuthorId.toStdString()); - - offset = 0; - char keySetData[grpMetaPtr->keys.TlvSize()]; - grpMetaPtr->keys.SetTlv(keySetData, grpMetaPtr->keys.TlvSize(), &offset); - cv.put(KEY_KEY_SET, grpMetaPtr->keys.TlvSize(), keySetData); - - offset = 0; - char metaData[grpPtr->meta.TlvSize()]; - grpPtr->meta.SetTlv(metaData, grpPtr->meta.TlvSize(), &offset); - cv.put(KEY_NXS_META, grpPtr->meta.TlvSize(), metaData); - - // local meta data - cv.put(KEY_GRP_SUBCR_FLAG, (int32_t)grpMetaPtr->mSubscribeFlags); - cv.put(KEY_GRP_POP, (int32_t)grpMetaPtr->mPop); - cv.put(KEY_MSG_COUNT, (int32_t)grpMetaPtr->mVisibleMsgCount); - cv.put(KEY_GRP_STATUS, (int32_t)grpMetaPtr->mGroupStatus); - cv.put(KEY_GRP_LAST_POST, (int32_t)grpMetaPtr->mLastPost); - - mGrpMetaDataCache.updateMeta(grpMetaPtr->mGroupId,*grpMetaPtr); - - if (!mDb->sqlInsert(GRP_TABLE_NAME, "", cv)) - { - std::cerr << "RsDataService::storeGroup() sqlInsert Failed"; - std::cerr << std::endl; - std::cerr << "\t For GroupId: " << grpMetaPtr->mGroupId.toStdString(); - std::cerr << std::endl; - } - - delete *sit; - } - // finish transaction - bool ret = mDb->commitTransaction(); - - return ret; -} - -int RsDataService::updateGroup(const std::list &grp) -{ - - RsStackMutex stack(mDbMutex); - - // begin transaction - mDb->beginTransaction(); - - for( std::list::const_iterator sit = grp.begin(); sit != grp.end(); ++sit) - { - - RsNxsGrp* grpPtr = *sit; - RsGxsGrpMetaData* grpMetaPtr = grpPtr->metaData; - - assert(grpMetaPtr != NULL); - - // if data is larger than max item size do not add - if(!validSize(grpPtr)) continue; - - /*! - * STORE data, data len, - * grpId, flags, publish time stamp, identity, - * id signature, admin signatue, key set, last posting ts - * and meta data - **/ - ContentValue cv; - uint32_t dataLen = grpPtr->grp.TlvSize(); - char grpData[dataLen]; - uint32_t offset = 0; - grpPtr->grp.SetTlv(grpData, dataLen, &offset); - cv.put(KEY_NXS_DATA, dataLen, grpData); - - cv.put(KEY_NXS_DATA_LEN, (int32_t) dataLen); - cv.put(KEY_GRP_ID, grpPtr->grpId.toStdString()); - cv.put(KEY_GRP_NAME, grpMetaPtr->mGroupName); - cv.put(KEY_ORIG_GRP_ID, grpMetaPtr->mOrigGrpId.toStdString()); - cv.put(KEY_NXS_SERV_STRING, grpMetaPtr->mServiceString); - cv.put(KEY_NXS_FLAGS, (int32_t)grpMetaPtr->mGroupFlags); - cv.put(KEY_TIME_STAMP, (int32_t)grpMetaPtr->mPublishTs); - cv.put(KEY_GRP_SIGN_FLAGS, (int32_t)grpMetaPtr->mSignFlags); - cv.put(KEY_GRP_CIRCLE_ID, grpMetaPtr->mCircleId.toStdString()); - cv.put(KEY_GRP_CIRCLE_TYPE, (int32_t)grpMetaPtr->mCircleType); - cv.put(KEY_GRP_INTERNAL_CIRCLE, grpMetaPtr->mInternalCircle.toStdString()); - cv.put(KEY_GRP_ORIGINATOR, grpMetaPtr->mOriginator.toStdString()); - cv.put(KEY_GRP_AUTHEN_FLAGS, (int32_t)grpMetaPtr->mAuthenFlags); - cv.put(KEY_NXS_HASH, grpMetaPtr->mHash.toStdString()); - cv.put(KEY_RECV_TS, (int32_t)grpMetaPtr->mRecvTS); - cv.put(KEY_NXS_IDENTITY, grpMetaPtr->mAuthorId.toStdString()); - - offset = 0; - char keySetData[grpMetaPtr->keys.TlvSize()]; - grpMetaPtr->keys.SetTlv(keySetData, grpMetaPtr->keys.TlvSize(), &offset); - cv.put(KEY_KEY_SET, grpMetaPtr->keys.TlvSize(), keySetData); - - offset = 0; - char metaData[grpPtr->meta.TlvSize()]; - grpPtr->meta.SetTlv(metaData, grpPtr->meta.TlvSize(), &offset); - cv.put(KEY_NXS_META, grpPtr->meta.TlvSize(), metaData); - - // local meta data - cv.put(KEY_GRP_SUBCR_FLAG, (int32_t)grpMetaPtr->mSubscribeFlags); - cv.put(KEY_GRP_POP, (int32_t)grpMetaPtr->mPop); - cv.put(KEY_MSG_COUNT, (int32_t)grpMetaPtr->mVisibleMsgCount); - cv.put(KEY_GRP_STATUS, (int32_t)grpMetaPtr->mGroupStatus); - cv.put(KEY_GRP_LAST_POST, (int32_t)grpMetaPtr->mLastPost); - - mDb->sqlUpdate(GRP_TABLE_NAME, "grpId='" + grpPtr->grpId.toStdString() + "'", cv); - - mGrpMetaDataCache.updateMeta(grpMetaPtr->mGroupId,*grpMetaPtr); - - delete *sit; - } - // finish transaction - bool ret = mDb->commitTransaction(); - - return ret; -} - -int RsDataService::updateGroupKeys(const RsGxsGroupId& grpId,const RsTlvSecurityKeySet& keys,uint32_t subscribe_flags) -{ - RsStackMutex stack(mDbMutex); - - // begin transaction - mDb->beginTransaction(); - - /*! - * STORE key set - **/ - - ContentValue cv; - //cv.put(KEY_NXS_FLAGS, (int32_t)grpMetaPtr->mGroupFlags); ? - - uint32_t offset = 0; - char keySetData[keys.TlvSize()]; - keys.SetTlv(keySetData, keys.TlvSize(), &offset); - cv.put(KEY_KEY_SET, keys.TlvSize(), keySetData); - cv.put(KEY_GRP_SUBCR_FLAG, (int32_t)subscribe_flags); - - mDb->sqlUpdate(GRP_TABLE_NAME, "grpId='" + grpId.toStdString() + "'", cv); - - // finish transaction - bool res = mDb->commitTransaction(); - - mGrpMetaDataCache.clear(grpId); - mGrpMetaDataCache.setCacheUpToDate(false); // this is needed because clear() doesn't do it (on purpose) - - return res; -} - -bool RsDataService::validSize(RsNxsGrp* grp) const -{ - if((grp->grp.TlvSize() + grp->meta.TlvSize()) <= GXS_MAX_ITEM_SIZE) return true; - return false; -} - -int RsDataService::retrieveNxsGrps(std::map &grp, bool withMeta) -{ -#ifdef RS_DATA_SERVICE_DEBUG_TIME - rstime::RsScopeTimer timer(""); - int resultCount = 0; - int requestedGroups = grp.size(); -#endif - - if(grp.empty()) - { - RsStackMutex stack(mDbMutex); - RetroCursor* c = mDb->sqlQuery(GRP_TABLE_NAME, withMeta ? mGrpColumnsWithMeta : mGrpColumns, "", ""); - - if(c) - { - std::vector grps; - - locked_retrieveGroups(c, grps, withMeta ? mColGrp_WithMetaOffset : 0); - std::vector::iterator vit = grps.begin(); - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - resultCount = grps.size(); -#endif - - for(; vit != grps.end(); ++vit) - { - grp[(*vit)->grpId] = *vit; - } - - delete c; - } - - } - else - { - RsStackMutex stack(mDbMutex); - std::map::iterator mit = grp.begin(); - - std::list toRemove; - - for(; mit != grp.end(); ++mit) - { - const RsGxsGroupId& grpId = mit->first; - RetroCursor* c = mDb->sqlQuery(GRP_TABLE_NAME, withMeta ? mGrpColumnsWithMeta : mGrpColumns, "grpId='" + grpId.toStdString() + "'", ""); - - if(c) - { - std::vector grps; - locked_retrieveGroups(c, grps, withMeta ? mColGrp_WithMetaOffset : 0); - - if(!grps.empty()) - { - RsNxsGrp* ng = grps.front(); - grp[ng->grpId] = ng; - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - ++resultCount; -#endif - }else{ - toRemove.push_back(grpId); - } - - delete c; - } - } - - std::list::iterator grpIdIt; - for (grpIdIt = toRemove.begin(); grpIdIt != toRemove.end(); ++grpIdIt) - { - grp.erase(*grpIdIt); - } - } - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - std::cerr << "RsDataService::retrieveNxsGrps() " << mDbName << ", Requests: " << requestedGroups << ", Results: " << resultCount << ", Time: " << timer.duration() << std::endl; -#endif - - return 1; -} - -void RsDataService::locked_retrieveGroups(RetroCursor* c, std::vector& grps, int metaOffset) -{ - if(c){ - bool valid = c->moveToFirst(); - - while(valid){ - RsNxsGrp* g = locked_getGroup(*c); - - // only add the latest grp info - if(g) - { - if (metaOffset) - g->metaData = new RsGxsGrpMetaData(*locked_getGrpMeta(*c, metaOffset)); - else - g->metaData = nullptr; - - grps.push_back(g); - } - valid = c->moveToNext(); - } - } -} - -int RsDataService::retrieveNxsMsgs(const GxsMsgReq &reqIds, GxsMsgResult &msg, bool withMeta) -{ -#ifdef RS_DATA_SERVICE_DEBUG_TIME - rstime::RsScopeTimer timer(""); - int resultCount = 0; -#endif - - for(auto mit = reqIds.begin(); mit != reqIds.end(); ++mit) - { - - const RsGxsGroupId& grpId = mit->first; - - // if vector empty then request all messages - const std::set& msgIdV = mit->second; - std::vector msgSet; - - if(msgIdV.empty()) - { - RS_STACK_MUTEX(mDbMutex); - - RetroCursor* c = mDb->sqlQuery(MSG_TABLE_NAME, withMeta ? mMsgColumnsWithMeta : mMsgColumns, KEY_GRP_ID+ "='" + grpId.toStdString() + "'", ""); - - if(c) - locked_retrieveMessages(c, msgSet, withMeta ? mColMsg_WithMetaOffset : 0); - - delete c; - } - else - { - RS_STACK_MUTEX(mDbMutex); - - // request each grp - for( std::set::const_iterator sit = msgIdV.begin(); - sit!=msgIdV.end();++sit ) - { - const RsGxsMessageId& msgId = *sit; - - RetroCursor* c = mDb->sqlQuery(MSG_TABLE_NAME, withMeta ? mMsgColumnsWithMeta : mMsgColumns, KEY_GRP_ID+ "='" + grpId.toStdString() - + "' AND " + KEY_MSG_ID + "='" + msgId.toStdString() + "'", ""); - - if(c) - { - locked_retrieveMessages(c, msgSet, withMeta ? mColMsg_WithMetaOffset : 0); - } - - delete c; - } - } - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - resultCount += msgSet.size(); -#endif - - msg[grpId] = msgSet; - - msgSet.clear(); - } - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - std::cerr << "RsDataService::retrieveNxsMsgs() " << mDbName << ", Requests: " << reqIds.size() << ", Results: " << resultCount << ", Time: " << timer.duration() << std::endl; -#endif - - return 1; -} - -void RsDataService::locked_retrieveMessages(RetroCursor *c, std::vector &msgs, int metaOffset) -{ - bool valid = c->moveToFirst(); - while(valid){ - RsNxsMsg* m = locked_getMessage(*c); - - if(m){ - if (metaOffset) - m->metaData = new RsGxsMsgMetaData(*locked_getMsgMeta(*c, metaOffset)); - else - m->metaData = nullptr; - - msgs.push_back(m); - } - - valid = c->moveToNext(); - } - return; -} - -int RsDataService::retrieveGxsMsgMetaData(const GxsMsgReq& reqIds, GxsMsgMetaResult& msgMeta) -{ - RsStackMutex stack(mDbMutex); - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - rstime::RsScopeTimer timer(""); - int resultCount = 0; -#endif - - for(auto mit(reqIds.begin()); mit != reqIds.end(); ++mit) - { - - const RsGxsGroupId& grpId = mit->first; - const std::set& msgIdV = mit->second; - - // if vector empty then request all messages - - // The pointer here is a trick to not initialize a new cache entry when cache is disabled, while keeping the unique variable all along. - t_MetaDataCache *cache(mUseCache? (&mMsgMetaDataCache[grpId]) : nullptr); - - if(msgIdV.empty()) - { - if(mUseCache && cache->isCacheUpToDate()) - cache->getFullMetaList(msgMeta[grpId]); - else - { - RetroCursor* c = mDb->sqlQuery(MSG_TABLE_NAME, mMsgMetaColumns, KEY_GRP_ID+ "='" + grpId.toStdString() + "'", ""); - - if (c) - { - locked_retrieveMsgMetaList(c, msgMeta[grpId]); - - if(mUseCache) - cache->setCacheUpToDate(true); - } - delete c; - } -#ifdef RS_DATA_SERVICE_DEBUG_CACHE - std::cerr << mDbName << ": Retrieving (all) Msg metadata grpId=" << grpId << ", " << std::dec << metaSet.size() << " messages" << std::endl; -#endif - } - else - { - // request each msg meta - auto& metaSet(msgMeta[grpId]); - - for(auto sit(msgIdV.begin()); sit!=msgIdV.end(); ++sit) - { - const RsGxsMessageId& msgId = *sit; - - auto meta = mUseCache?cache->getMeta(msgId): (std::shared_ptr()); - - if(meta) - metaSet.push_back(meta); - else - { - RetroCursor* c = mDb->sqlQuery(MSG_TABLE_NAME, mMsgMetaColumns, KEY_GRP_ID+ "='" + grpId.toStdString() + "' AND " + KEY_MSG_ID + "='" + msgId.toStdString() + "'", ""); - - c->moveToFirst(); - auto meta = locked_getMsgMeta(*c, 0); - - if(meta) - { - metaSet.push_back(meta); - - if(mUseCache) - mMsgMetaDataCache[grpId].updateMeta(msgId,meta); - } - - delete c; - } - } -#ifdef RS_DATA_SERVICE_DEBUG_CACHE - std::cerr << mDbName << ": Retrieving Msg metadata grpId=" << grpId << ", " << std::dec << metaSet.size() << " messages" << std::endl; -#endif - } - } - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - if(mDbName==std::string("gxsforums_db")) - std::cerr << "RsDataService::retrieveGxsMsgMetaData() " << mDbName << ", Requests: " << reqIds.size() << ", Results: " << resultCount << ", Time: " << timer.duration() << std::endl; -#endif - - return 1; -} - -void RsDataService::locked_retrieveGrpMetaList(RetroCursor *c, std::map >& grpMeta) -{ - if(!c) - { - RsErr() << __PRETTY_FUNCTION__ << ": attempt to retrieve Group Meta data from the DB with null cursor!" << std::endl; - return; - } - - bool valid = c->moveToFirst(); - - while(valid) - { - auto m = locked_getGrpMeta(*c, 0); - - if(m != nullptr) - grpMeta[m->mGroupId] = m; - - valid = c->moveToNext(); - } -} - -void RsDataService::locked_retrieveMsgMetaList(RetroCursor *c, std::vector >& msgMeta) -{ - if(!c) - { - RsErr() << __PRETTY_FUNCTION__ << ": attempt to retrieve Msg Meta data from the DB with null cursor!" << std::endl; - return; - } - - bool valid = c->moveToFirst(); - while(valid) - { - auto m = locked_getMsgMeta(*c, 0); - - if(m != nullptr) - msgMeta.push_back(m); - - valid = c->moveToNext(); - } -} - -int RsDataService::retrieveGxsGrpMetaData(std::map >& grp) -{ -#ifdef RS_DATA_SERVICE_DEBUG - std::cerr << "RsDataService::retrieveGxsGrpMetaData()"; - std::cerr << std::endl; -#endif - - RS_STACK_MUTEX(mDbMutex); - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - rstime::RsScopeTimer timer(""); - int resultCount = 0; - int requestedGroups = grp.size(); -#endif - - if(grp.empty()) - { - if(mUseCache && mGrpMetaDataCache.isCacheUpToDate()) // grab all the stash from the cache, so as to avoid decryption costs. - { -#ifdef RS_DATA_SERVICE_DEBUG_CACHE - std::cerr << (void*)this << ": RsDataService::retrieveGxsGrpMetaData() retrieving all from cache!" << std::endl; -#endif - - mGrpMetaDataCache.getFullMetaList(grp) ; - } - else - { -#ifdef RS_DATA_SERVICE_DEBUG - std::cerr << "RsDataService::retrieveGxsGrpMetaData() retrieving all" << std::endl; -#endif - // clear the cache - - RetroCursor* c = mDb->sqlQuery(GRP_TABLE_NAME, mGrpMetaColumns, "", ""); - - if(c) - { - locked_retrieveGrpMetaList(c,grp); - - if(mUseCache) - mGrpMetaDataCache.setCacheUpToDate(true); - } - delete c; -#ifdef RS_DATA_SERVICE_DEBUG_TIME - resultCount += grp.size(); -#endif - - } - } - else - { - for(auto mit(grp.begin()); mit != grp.end(); ++mit) - { - auto meta = mUseCache?mGrpMetaDataCache.getMeta(mit->first): (std::shared_ptr()) ; - - if(meta) - mit->second = meta; - else - { -#ifdef RS_DATA_SERVICE_DEBUG_CACHE - std::cerr << mDbName << ": Retrieving Grp metadata grpId=" << mit->first ; -#endif - - const RsGxsGroupId& grpId = mit->first; - RetroCursor* c = mDb->sqlQuery(GRP_TABLE_NAME, mGrpMetaColumns, "grpId='" + grpId.toStdString() + "'", ""); - - c->moveToFirst(); - - auto meta = locked_getGrpMeta(*c, 0); - - if(meta) - { - mit->second = meta; - - if(mUseCache) - mGrpMetaDataCache.updateMeta(grpId,meta); - } - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - ++resultCount; -#endif - - delete c; - -#ifdef RS_DATA_SERVICE_DEBUG_CACHE - else - std::cerr << ". not found!" << std::endl; -#endif - } - } - - } - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - std::cerr << "RsDataService::retrieveGxsGrpMetaData() " << mDbName << ", Requests: " << requestedGroups << ", Results: " << resultCount << ", Time: " << timer.duration() << std::endl; -#endif - - /* Remove not found entries as stated in the documentation */ - for(auto i = grp.begin(); i != grp.end();) - if(!i->second) i = grp.erase(i); - else ++i; - - return 1; -} - -int RsDataService::resetDataStore() -{ - -#ifdef RS_DATA_SERVICE_DEBUG - std::cerr << "resetDataStore() " << std::endl; -#endif - - { - RsStackMutex stack(mDbMutex); - - mDb->execSQL("DROP INDEX " + MSG_INDEX_GRPID); - mDb->execSQL("DROP TABLE " + DATABASE_RELEASE_TABLE_NAME); - mDb->execSQL("DROP TABLE " + MSG_TABLE_NAME); - mDb->execSQL("DROP TABLE " + GRP_TABLE_NAME); - mDb->execSQL("DROP TRIGGER " + GRP_LAST_POST_UPDATE_TRIGGER); - } - - // recreate database - initialise(true); - - return 1; -} - -int RsDataService::updateGroupMetaData(const GrpLocMetaData& meta) -{ -#ifdef RS_DATA_SERVICE_DEBUG_CACHE - std::cerr << (void*)this << ": Updating Grp Meta data: grpId = " << meta.grpId << std::endl; -#endif - - RsStackMutex stack(mDbMutex); - const RsGxsGroupId& grpId = meta.grpId; - -#ifdef RS_DATA_SERVICE_DEBUG_CACHE - std::cerr << (void*)this << ": erasing old entry from cache." << std::endl; -#endif - - if( mDb->sqlUpdate(GRP_TABLE_NAME, KEY_GRP_ID+ "='" + grpId.toStdString() + "'", meta.val)) - { - // If we use the cache, update the meta data immediately. - - if(mUseCache) - { - RetroCursor* c = mDb->sqlQuery(GRP_TABLE_NAME, mGrpMetaColumns, "grpId='" + grpId.toStdString() + "'", ""); - - c->moveToFirst(); - - // temporarily disable the cache so that we get the value from the DB itself. - mUseCache=false; - auto meta = locked_getGrpMeta(*c, 0); - mUseCache=true; - - if(meta) - mGrpMetaDataCache.updateMeta(grpId,meta); - - delete c; - } - - return 1; - } - return 0; -} - -int RsDataService::updateMessageMetaData(const MsgLocMetaData& metaData) -{ -#ifdef RS_DATA_SERVICE_DEBUG_CACHE - std::cerr << (void*)this << ": Updating Msg Meta data: grpId = " << metaData.msgId.first << " msgId = " << metaData.msgId.second << std::endl; -#endif - - RsStackMutex stack(mDbMutex); - const RsGxsGroupId& grpId = metaData.msgId.first; - const RsGxsMessageId& msgId = metaData.msgId.second; - - if(mDb->sqlUpdate(MSG_TABLE_NAME, KEY_GRP_ID+ "='" + grpId.toStdString() + "' AND " + KEY_MSG_ID + "='" + msgId.toStdString() + "'", metaData.val) ) - { - // If we use the cache, update the meta data immediately. - - if(mUseCache) - { - RetroCursor* c = mDb->sqlQuery(MSG_TABLE_NAME, mMsgMetaColumns, KEY_GRP_ID+ "='" + grpId.toStdString() + "' AND " + KEY_MSG_ID + "='" + msgId.toStdString() + "'", ""); - - c->moveToFirst(); - - // temporarily disable the cache so that we get the value from the DB itself. - mUseCache=false; - auto meta = locked_getMsgMeta(*c, 0); - mUseCache=true; - - if(meta) - mMsgMetaDataCache[grpId].updateMeta(msgId,meta); - - delete c; - } - - return 1; - } - return 0; -} - -int RsDataService::removeMsgs(const GxsMsgReq& msgIds) -{ - RsStackMutex stack(mDbMutex); - - GxsMsgReq::const_iterator mit = msgIds.begin(); - - for(; mit != msgIds.end(); ++mit) - { - const std::set& msgIdV = mit->second; - const RsGxsGroupId& grpId = mit->first; - - // delete messages - GxsMsgReq msgsToDelete; - msgsToDelete[grpId] = msgIdV; - locked_removeMessageEntries(msgsToDelete); - } - - return 1; -} - -int RsDataService::removeGroups(const std::vector &grpIds) -{ - - RsStackMutex stack(mDbMutex); - - locked_removeGroupEntries(grpIds); - - return 1; -} - -int RsDataService::retrieveGroupIds(std::vector &grpIds) -{ - RsStackMutex stack(mDbMutex); - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - rstime::RsScopeTimer timer(""); - int resultCount = 0; -#endif - - RetroCursor* c = mDb->sqlQuery(GRP_TABLE_NAME, mGrpIdColumn, "", ""); - - if(c) - { - bool valid = c->moveToFirst(); - - while(valid) - { - std::string grpId; - c->getString(mColGrpId_GrpId, grpId); - grpIds.push_back(RsGxsGroupId(grpId)); - valid = c->moveToNext(); - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - ++resultCount; -#endif - } - delete c; - }else - { - return 0; - } - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - std::cerr << "RsDataService::retrieveGroupIds() " << mDbName << ", Results: " << resultCount << ", Time: " << timer.duration() << std::endl; -#endif - - return 1; -} - -int RsDataService::retrieveMsgIds(const RsGxsGroupId& grpId, RsGxsMessageId::std_set& msgIds) -{ -#ifdef RS_DATA_SERVICE_DEBUG_TIME - rstime::RsScopeTimer timer(""); - int resultCount = 0; -#endif - - RetroCursor* c = mDb->sqlQuery(MSG_TABLE_NAME, mMsgIdColumn, KEY_GRP_ID+ "='" + grpId.toStdString() + "'", ""); - - if(c) - { - bool valid = c->moveToFirst(); - - while(valid) - { - std::string msgId; - c->getString(mColMsgId_MsgId, msgId); - - if(c->columnCount() != 1) - std::cerr << "(EE) ********* not retrieving all columns!!" << std::endl; - - msgIds.insert(RsGxsMessageId(msgId)); - valid = c->moveToNext(); - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - ++resultCount; -#endif - } - delete c; - }else - { - return 0; - } - -#ifdef RS_DATA_SERVICE_DEBUG_TIME - std::cerr << "RsDataService::retrieveNxsGrps() " << mDbName << ", Results: " << resultCount << ", Time: " << timer.duration() << std::endl; -#endif - - return 1; - -} - -bool RsDataService::locked_removeMessageEntries(const GxsMsgReq& msgIds) -{ - // start a transaction - bool ret = mDb->beginTransaction(); - - GxsMsgReq::const_iterator mit = msgIds.begin(); - - for(; mit != msgIds.end(); ++mit) - { - const RsGxsGroupId& grpId = mit->first; - const std::set& msgsV = mit->second; - auto& cache(mMsgMetaDataCache[grpId]); - - for(auto& msgId:msgsV) - { - mDb->sqlDelete(MSG_TABLE_NAME, KEY_GRP_ID+ "='" + grpId.toStdString() + "' AND " + KEY_MSG_ID + "='" + msgId.toStdString() + "'", ""); - - cache.clear(msgId); - } - } - - ret &= mDb->commitTransaction(); - - return ret; -} - -bool RsDataService::locked_removeGroupEntries(const std::vector& grpIds) -{ - // start a transaction - bool ret = mDb->beginTransaction(); - - for(auto grpId:grpIds) - { - mDb->sqlDelete(GRP_TABLE_NAME, KEY_GRP_ID+ "='" + grpId.toStdString() + "'", ""); - - // also remove the group meta from cache. - mGrpMetaDataCache.clear(grpId) ; - } - - ret &= mDb->commitTransaction(); - return ret; -} - -uint32_t RsDataService::cacheSize() const { - return 0; -} - -int RsDataService::setCacheSize(uint32_t /* size */) -{ - return 0; -} - -void RsDataService::debug_printCacheSize() -{ - RS_STACK_MUTEX(mDbMutex); - - uint32_t nb_items; - uint64_t total_size; - - mGrpMetaDataCache.debug_computeSize(nb_items, total_size); - - RsDbg() << "[CACHE] Cache size: " << std::endl; - RsDbg() << "[CACHE] Groups: " << " total: " << nb_items << ", size: " << total_size << std::endl; - - nb_items = 0; - total_size = 0; - - for(auto& it:mMsgMetaDataCache) - { - uint32_t tmp_nb_items; - uint64_t tmp_total_size; - - it.second.debug_computeSize(tmp_nb_items, tmp_total_size); - - nb_items += tmp_nb_items; - total_size += tmp_total_size; - } - RsDbg() << "[CACHE] Msgs: " << " total: " << nb_items << ", size: " << total_size << std::endl; -} - - - - - - - - diff --git a/libretroshare/src/gxs/rsdataservice.h b/libretroshare/src/gxs/rsdataservice.h deleted file mode 100644 index e9554f04f..000000000 --- a/libretroshare/src/gxs/rsdataservice.h +++ /dev/null @@ -1,459 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: gxsdataservice.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2012 by Evi-Parker Christopher * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RSDATASERVICE_H -#define RSDATASERVICE_H - -#include "gxs/rsgds.h" -#include "util/retrodb.h" - -class MsgUpdate -{ -public: - - //MsgUpdate(){} - //MsgUpdate(const MsgUpdate& ){}//hier mĆ¼sste ein echter constructor sein - RsGxsMessageId msgId; - ContentValue cv; -}; - -template class t_MetaDataCache -{ -public: - t_MetaDataCache() - : mCache_ContainsAllMetas(false) - {} - virtual ~t_MetaDataCache() = default; - - bool isCacheUpToDate() const { return mCache_ContainsAllMetas ; } - void setCacheUpToDate(bool b) { mCache_ContainsAllMetas = b; } - - void getFullMetaList(std::map >& mp) const { mp = mMetas ; } - void getFullMetaList(std::vector >& mp) const { for(auto& m:mMetas) mp.push_back(m.second) ; } - - std::shared_ptr getMeta(const ID& id) - { - auto itt = mMetas.find(id); - - if(itt != mMetas.end()) - return itt->second ; - else - return nullptr; - } - - std::shared_ptr getOrCreateMeta(const ID& id) - { - auto it = mMetas.find(id) ; - - if(it != mMetas.end()) - { -#ifdef RS_DATA_SERVICE_DEBUG - RsDbg() << __PRETTY_FUNCTION__ << ": getting group meta " << grpId << " from cache." << std::endl; -#endif - return it->second ; - } - else - { -#ifdef RS_DATA_SERVICE_DEBUG - RsDbg() << __PRETTY_FUNCTION__ << ": group meta " << grpId << " not in cache. Loading it from DB..." << std::endl; -#endif - return (mMetas[id] = std::make_shared()); - } - } - - void updateMeta(const ID& id,const MetaDataClass& meta) - { - mMetas[id] = std::make_shared(meta); // create a new shared_ptr to possibly replace the previous one - } - - void updateMeta(const ID& id,const std::shared_ptr& meta) - { - mMetas[id] = meta; // create a new shared_ptr to possibly replace the previous one - } - - void clear(const ID& id) - { - auto it = mMetas.find(id) ; - - // We dont actually delete the item, because it might be used by a calling client. - // In this case, the memory will not be used for long, so we keep it into a list for a safe amount - // of time and delete it later. Using smart pointers here would be more elegant, but that would need - // to be implemented thread safe, which is difficult in this case. - - if(it != mMetas.end()) - { -#ifdef RS_DATA_SERVICE_DEBUG - std::cerr << "(II) moving database cache entry " << (void*)(*it).second << " to dead list." << std::endl; -#endif - - mMetas.erase(it) ; - - // No need to modify mCache_ContainsAllMetas since, assuming that the cache always contains - // all possible elements from the DB, clearing one from the cache means that it is also deleted from the db, so - // the property is preserved. - } - } - - void debug_computeSize(uint32_t& nb_items, uint64_t& total_size) const - { - nb_items = mMetas.size(); - total_size = 0; - - for(auto it:mMetas) total_size += it.second->serial_size(); - } -private: - std::map > mMetas; - - static const uint32_t CACHE_ENTRY_GRACE_PERIOD = 600 ; // Unused items are deleted 10 minutes after last usage. - - bool mCache_ContainsAllMetas ; -}; - -class RsDataService : public RsGeneralDataService -{ -public: - - RsDataService(const std::string& serviceDir, const std::string& dbName, uint16_t serviceType, - RsGxsSearchModule* mod = NULL, const std::string& key = ""); - virtual ~RsDataService(); - - /*! - * Retrieves all msgs - * @param reqIds requested msg ids (grpId,msgId), leave msg list empty to get all msgs for the grp - * @param msg result of msg retrieval - * @param withMeta true will also retrieve metadata - * @return error code - */ - int retrieveNxsMsgs(const GxsMsgReq& reqIds, GxsMsgResult& msg, bool withMeta = false) override; - - /*! - * Retrieves groups, if empty, retrieves all grps, if map is not empty - * only retrieve entries, if entry cannot be found, it is removed from map - * @param grp retrieved groups - * @param withMeta this initialise the metaData member of the nxsgroups retrieved - * @return error code - */ - int retrieveNxsGrps(std::map& grp, bool withMeta) override; - - /*! - * Retrieves meta data of all groups stored (most current versions only) - * @param grp output group meta data - * @return error code - */ - int retrieveGxsGrpMetaData(std::map > &grp) override; - - /*! - * Retrieves meta data of all groups stored (most current versions only) - * @param grpIds grpIds for which to retrieve meta data - * @param msgMeta meta data result as map of grpIds to array of metadata for that grpId - * @return error code - */ - int retrieveGxsMsgMetaData(const GxsMsgReq& reqIds, GxsMsgMetaResult& msgMeta) override; - - /*! - * remove msgs in data store - * @param grpId group Id of message to be removed - * @param msgIds ids of messages to be removed - * @return error code - */ - int removeMsgs(const GxsMsgReq& msgIds) override; - - /*! - * remove groups in data store listed in grpIds param - * @param grpIds ids of groups to be removed - * @return error code - */ - int removeGroups(const std::vector& grpIds) override; - - /*! - * Retrieves all group ids in store - * @param grpIds all grpids in store is inserted into this vector - * @return error code - */ - int retrieveGroupIds(std::vector &grpIds) override; - - /*! - * Retrives all msg ids in store - * @param grpId groupId of message ids to retrieve - * @param msgId msgsids retrieved - * @return error code - */ - int retrieveMsgIds(const RsGxsGroupId& grpId, RsGxsMessageId::std_set& msgId) override; - - /*! - * @return the cache size set for this RsGeneralDataService in bytes - */ - uint32_t cacheSize() const override; - - /*! - * \brief serviceType - * \return - * The service type for the current data service. - */ - virtual uint16_t serviceType() const override { return mServType; } - - /*! - * @param size size of cache to set in bytes - */ - int setCacheSize(uint32_t size) override; - - /*! - * Stores a list of signed messages into data store - * @param msg map of message and decoded meta data information - * @return error code - */ - int storeMessage(const std::list& msg) override; - - /*! - * Stores a list of groups in data store - * @param grp map of group and decoded meta data - * @return error code - */ - int storeGroup(const std::list& grp) override; - - /*! - * Updates group entries in Db - * @param grp map of group and decoded meta data - * @return error code - */ - int updateGroup(const std::list& grsp) override; - - /*! - * @param metaData The meta data item to update - * @return error code - */ - int updateMessageMetaData(const MsgLocMetaData& metaData) override; - - /*! - * @param metaData The meta data item to update - * @return error code - */ - int updateGroupMetaData(const GrpLocMetaData &meta) override; - - /*! - * Completely clear out data stored in - * and returns this to a state - * as it was when first constructed - * @return error code - */ - int resetDataStore() override; - - bool validSize(RsNxsMsg* msg) const override; - bool validSize(RsNxsGrp* grp) const override; - - /*! - * Convenience function used to only update group keys. This is used when sending - * publish keys between peers. - * @return SQL error code - */ - - int updateGroupKeys(const RsGxsGroupId& grpId,const RsTlvSecurityKeySet& keys, uint32_t subscribe_flags) override; - - void debug_printCacheSize() ; - -private: - - /*! - * Retrieves all the msg results from a cursor - * @param c cursor to result set - * @param msgs messages retrieved from cursor are stored here - */ - void locked_retrieveMessages(RetroCursor* c, std::vector& msgs, int metaOffset); - - /*! - * Retrieves all the grp results from a cursor - * @param c cursor to result set - * @param grps groups retrieved from cursor are stored here - * @param withMeta this initialise the metaData member of the nxsgroups retrieved - */ - void locked_retrieveGroups(RetroCursor* c, std::vector& grps, int metaOffset); - - /*! - * Retrieves all the msg meta results from a cursor - * @param c cursor to result set - * @param msgMeta message metadata retrieved from cursor are stored here - */ - void locked_retrieveMsgMetaList(RetroCursor* c, std::vector > &msgMeta); - - /*! - * Retrieves all the grp meta results from a cursor - * @param c cursor to result set - * @param grpMeta group metadata retrieved from cursor are stored here - */ - void locked_retrieveGrpMetaList(RetroCursor *c, std::map > &grpMeta); - - /*! - * extracts a msg meta item from a cursor at its - * current position - */ - std::shared_ptr locked_getMsgMeta(RetroCursor& c, int colOffset); - - /*! - * extracts a grp meta item from a cursor at its - * current position - */ - std::shared_ptr locked_getGrpMeta(RetroCursor& c, int colOffset); - - /*! - * extracts a msg item from a cursor at its - * current position - */ - RsNxsMsg* locked_getMessage(RetroCursor& c); - - /*! - * extracts a grp item from a cursor at its - * current position - */ - RsNxsGrp* locked_getGroup(RetroCursor& c); - - /*! - * Creates an sql database and its associated file - * also creates the message and groups table - * @param isNewDatabase is new database - */ - void initialise(bool isNewDatabase); - - /*! - * Remove entries for data base - * @param msgIds - */ - bool locked_removeMessageEntries(const GxsMsgReq& msgIds); - bool locked_removeGroupEntries(const std::vector& grpIds); - -private: - /*! - * Start release update - * @param release - * @return true/false - */ - bool startReleaseUpdate(int release); - - /*! - * Finish release update - * @param release - * @param result - * @return true/false - */ - bool finishReleaseUpdate(int release, bool result); - -private: - - RsMutex mDbMutex; - - std::list mMsgColumns; - std::list mMsgMetaColumns; - std::list mMsgColumnsWithMeta; - std::list mMsgIdColumn; - - std::list mGrpColumns; - std::list mGrpMetaColumns; - std::list mGrpColumnsWithMeta; - std::list mGrpIdColumn; - - // Message meta column - int mColMsgMeta_GrpId; - int mColMsgMeta_TimeStamp; - int mColMsgMeta_NxsFlags; - int mColMsgMeta_SignSet; - int mColMsgMeta_NxsIdentity; - int mColMsgMeta_NxsHash; - int mColMsgMeta_MsgId; - int mColMsgMeta_OrigMsgId; - int mColMsgMeta_MsgStatus; - int mColMsgMeta_ChildTs; - int mColMsgMeta_MsgParentId; - int mColMsgMeta_MsgThreadId; - int mColMsgMeta_Name; - int mColMsgMeta_NxsServString; - int mColMsgMeta_RecvTs; - int mColMsgMeta_NxsDataLen; - - // Message columns - int mColMsg_GrpId; - int mColMsg_NxsData; - int mColMsg_MetaData; - int mColMsg_MsgId; - - // Message columns with meta - int mColMsg_WithMetaOffset; - - // Group meta columns - int mColGrpMeta_GrpId; - int mColGrpMeta_TimeStamp; - int mColGrpMeta_NxsFlags; -// int mColGrpMeta_SignSet; - int mColGrpMeta_NxsIdentity; - int mColGrpMeta_NxsHash; - int mColGrpMeta_KeySet; - int mColGrpMeta_SubscrFlag; - int mColGrpMeta_Pop; - int mColGrpMeta_MsgCount; - int mColGrpMeta_Status; - int mColGrpMeta_Name; - int mColGrpMeta_LastPost; - int mColGrpMeta_OrigGrpId; - int mColGrpMeta_ServString; - int mColGrpMeta_SignFlags; - int mColGrpMeta_CircleId; - int mColGrpMeta_CircleType; - int mColGrpMeta_InternCircle; - int mColGrpMeta_Originator; - int mColGrpMeta_AuthenFlags; - int mColGrpMeta_ParentGrpId; - int mColGrpMeta_RecvTs; - int mColGrpMeta_RepCutoff; - int mColGrpMeta_NxsDataLen; - - // Group columns - int mColGrp_GrpId; - int mColGrp_NxsData; - int mColGrp_MetaData; - - // Group columns with meta - int mColGrp_WithMetaOffset; - - // Group id columns - int mColGrpId_GrpId; - - // Msg id columns - int mColMsgId_MsgId; - - std::string mServiceDir; - std::string mDbName; - std::string mDbPath; - uint16_t mServType; - - RetroDb* mDb; - - // used to store metadata instead of reading it from the database. - // The boolean variable below is also used to force re-reading when - // the entre list of grp metadata is requested (which happens quite often) - - void locked_clearGrpMetaCache(const RsGxsGroupId& gid); - void locked_updateGrpMetaCache(const RsGxsGrpMetaData& meta); - - t_MetaDataCache mGrpMetaDataCache; - std::map > mMsgMetaDataCache; - - bool mUseCache; -}; - -#endif // RSDATASERVICE_H diff --git a/libretroshare/src/gxs/rsgds.h b/libretroshare/src/gxs/rsgds.h deleted file mode 100644 index f4a3b0229..000000000 --- a/libretroshare/src/gxs/rsgds.h +++ /dev/null @@ -1,278 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgds.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Robert Fernie, Evi-Parker Christopher * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#pragma once - -#include -#include -#include - -#include "inttypes.h" - -#include "rsitems/rsgxsitems.h" -#include "rsitems/rsnxsitems.h" -#include "gxs/rsgxsdata.h" -#include "rsgxs.h" -#include "rsgxsutil.h" -#include "util/contentvalue.h" - -class RsGxsSearchModule { - -public: - - virtual ~RsGxsSearchModule(); - - -}; - -/*! - * This allows modification of local - * meta data items of a message - */ -struct MsgLocMetaData { - MsgLocMetaData() = default; - MsgLocMetaData(const MsgLocMetaData& meta): msgId(meta.msgId), val(meta.val) {} - - RsGxsGrpMsgIdPair msgId; - ContentValue val; -}; - -/*! - * This allows modification of local - * meta data items of a group - */ -struct GrpLocMetaData { - GrpLocMetaData() = default; - GrpLocMetaData(const GrpLocMetaData& meta): grpId(meta.grpId), val(meta.val) {} - - RsGxsGroupId grpId; - ContentValue val; -}; - -/*! - * This is used to query network statistics for a given group. This is useful - * to e.g. show group popularity, or number of visible messages for unsubscribed - * group. - */ -struct RsGroupNetworkStats -{ - RsGroupNetworkStats() : - mSuppliers(0), mMaxVisibleCount(0), mGrpAutoSync(false), - mAllowMsgSync(false), mLastGroupModificationTS(0) {} - - uint32_t mSuppliers; - uint32_t mMaxVisibleCount; - bool mGrpAutoSync; - bool mAllowMsgSync; - rstime_t mLastGroupModificationTS; -}; - -typedef std::map > NxsMsgDataResult; -typedef std::map > NxsMsgRelatedDataResult; -typedef std::map > GxsMsgResult; // - -/*! - * The main role of GDS is the preparation and handing out of messages requested from - * RsGeneralExchangeService and RsGeneralExchangeService - * It is important to note that no actual messages are passed by this interface as its is expected - * architecturally to pass messages to the service via a call back - * - * It also acts as a layer between RsGeneralStorageService and its parent RsGeneralExchangeService - * thus allowing for non-blocking requests, etc. - * It also provides caching ability - * - * - * Caching feature: - * - A cache index should be maintained which is faster than normal message request - * - This should allow fast retrieval of message based on grp id or msg id - * - * Identity Exchange Service: - * - As this is the point where data is accessed by both the GNP and GXS the identities - * used to decrypt, encrypt and verify is handle here. - * - * Please note all function are blocking. - */ -class RsGeneralDataService -{ - -public: - - static const uint32_t GXS_MAX_ITEM_SIZE; - - static const std::string MSG_META_SERV_STRING; - static const std::string MSG_META_STATUS; - - static const std::string GRP_META_SUBSCRIBE_FLAG; - static const std::string GRP_META_STATUS; - static const std::string GRP_META_SERV_STRING; - static const std::string GRP_META_CUTOFF_LEVEL; - -public: - - typedef std::map GrpStoreMap; - typedef std::map MsgStoreMap; - - RsGeneralDataService(){} - virtual ~RsGeneralDataService(){} - - /*! - * Retrieves all msgs - * @param reqIds requested msg ids (grpId,msgId), leave msg list empty to get all msgs for the grp - * @param msg result of msg retrieval - * @param cache whether to store results of this retrieval in memory for faster later retrieval - * @param strictFilter if true do not request any message if reqIds is empty - * @return error code - */ - virtual int retrieveNxsMsgs( const GxsMsgReq& reqIds, GxsMsgResult& msg, bool withMeta = false ) = 0; - - /*! - * Retrieves all groups stored. Caller owns the memory and is supposed to delete the RsNxsGrp pointers after use. - * @param grp retrieved groups - * @param withMeta if true the meta handle of nxs grps is intitialised - * @param cache whether to store retrieval in mem for faster later retrieval - * @return error code - */ - virtual int retrieveNxsGrps(std::map& grp, bool withMeta) = 0; - - /*! - * Retrieves meta data of all groups stored (most current versions only) - * Memory is owned by the service, not the caller. Therefore the pointers in the temporary map - * shouldn't be destroyed. - * - * @param grp if null grpIds entries are made, only meta for those grpId are retrieved \n - * , if grpId is failed to be retrieved it will be erased from map - * @return error code - */ - virtual int retrieveGxsGrpMetaData(std::map >& grp) = 0; - - /*! - * Retrieves meta data of all groups stored (most current versions only) - * @param grpIds grpIds for which to retrieve meta data - * @param msgMeta meta data result as map of grpIds to array of metadata for that grpId - * @return error code - */ - virtual int retrieveGxsMsgMetaData(const GxsMsgReq& msgIds, GxsMsgMetaResult& msgMeta) = 0; - - /*! - * remove msgs in data store listed in msgIds param - * @param msgIds ids of messages to be removed - * @return error code - */ - virtual int removeMsgs(const GxsMsgReq& msgIds) = 0; - - /*! - * remove groups in data store listed in grpIds param - * @param grpIds ids of groups to be removed - * @return error code - */ - virtual int removeGroups(const std::vector& grpIds) = 0; - - /*! - * Retrieves all group ids in store - * @param grpIds all grpids in store is inserted into this vector - * @return error code - */ - virtual int retrieveGroupIds(std::vector& grpIds) = 0; - - /*! - * Retrives all msg ids in store - * @param grpId groupId of message ids to retrieve - * @param msgId msgsids retrieved - * @return error code - */ - virtual int retrieveMsgIds(const RsGxsGroupId& grpId, RsGxsMessageId::std_set& msgId) = 0; - - /*! - * @return the cache size set for this RsGeneralDataService in bytes - */ - virtual uint32_t cacheSize() const = 0; - - /*! - * \brief serviceType - * \return - * The service type for the current data service. - */ - virtual uint16_t serviceType() const = 0 ; - - /*! - * @param size size of cache to set in bytes - */ - virtual int setCacheSize(uint32_t size) = 0; - - /*! - * Stores a list of signed messages into data store - * @param msg map of message and decoded meta data information - * @return error code - */ - virtual int storeMessage(const std::list& msgs) = 0; - - /*! - * Stores a list of groups in data store - * @param grp map of group and decoded meta data - * @return error code - */ - virtual int storeGroup(const std::list& grsp) = 0; - - - /*! - * Updates group entries in Db - * @param grp map of group and decoded meta data - * @return error code - */ - virtual int updateGroup(const std::list& grsp) = 0; - - /*! - * @param metaData - */ - virtual int updateMessageMetaData(const MsgLocMetaData& metaData) = 0; - - /*! - * @param metaData - */ - virtual int updateGroupMetaData(const GrpLocMetaData& meta) = 0; - - virtual int updateGroupKeys(const RsGxsGroupId& grpId,const RsTlvSecurityKeySet& keys,uint32_t subscribed_flags) = 0 ; - - /*! - * Completely clear out data stored in - * and returns this to a state - * as it was when first constructed - */ - virtual int resetDataStore() = 0; - - /*! - * Use to determine if message isn't over the storage - * limit for a single message item - * @param msg the message to check size validity - * @return whether the size of of msg is valid - */ - virtual bool validSize(RsNxsMsg* msg) const = 0 ; - - /*! - * Use to determine if group isn't over the storage limit - * for a single group item - * @param grp the group to check size validity - * @return whether the size of grp is valid for storage - */ - virtual bool validSize(RsNxsGrp* grp) const = 0 ; - -}; diff --git a/libretroshare/src/gxs/rsgenexchange.cc b/libretroshare/src/gxs/rsgenexchange.cc deleted file mode 100644 index 3979cf270..000000000 --- a/libretroshare/src/gxs/rsgenexchange.cc +++ /dev/null @@ -1,3718 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgenexchange.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Christopher Evi-Parker * - * Copyright (C) 2019-2021 Gioacchino Mazzurco * - * Copyright (C) 2019-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include -#include - -#include "pqi/pqihash.h" -#include "rsgenexchange.h" -#include "gxssecurity.h" -#include "util/contentvalue.h" -#include "util/rsprint.h" -#include "util/rstime.h" -#include "retroshare/rsgxsflags.h" -#include "retroshare/rsgxscircles.h" -#include "retroshare/rsgrouter.h" -#include "retroshare/rsidentity.h" -#include "retroshare/rspeers.h" -#include "rsitems/rsnxsitems.h" -#include "rsgixs.h" -#include "rsgxsutil.h" -#include "rsserver/p3face.h" -#include "retroshare/rsevents.h" -#include "util/radix64.h" -#include "util/cxx17retrocompat.h" - -#define PUB_GRP_MASK 0x000f -#define RESTR_GRP_MASK 0x00f0 -#define PRIV_GRP_MASK 0x0f00 -#define GRP_OPTIONS_MASK 0xf000 - -#define PUB_GRP_OFFSET 0 -#define RESTR_GRP_OFFSET 8 -#define PRIV_GRP_OFFSET 16 -#define GRP_OPTIONS_OFFSET 24 - -// Authentication key indices. Used to store them in a map -// these where originally flags, but used as indexes. Still, we need -// to keep their old values to ensure backward compatibility. - -static const uint32_t INDEX_AUTHEN_IDENTITY = 0x00000010; // identity -static const uint32_t INDEX_AUTHEN_PUBLISH = 0x00000020; // publish key -static const uint32_t INDEX_AUTHEN_ADMIN = 0x00000040; // admin key - -static const uint32_t MSG_CLEANUP_PERIOD = 60*59; // 59 minutes -static const uint32_t INTEGRITY_CHECK_PERIOD = 60*31; // 31 minutes - -#define GXS_MASK "GXS_MASK_HACK" - -/* - * #define GEN_EXCH_DEBUG 1 - */ - -#if defined(GEN_EXCH_DEBUG) -static const uint32_t service_to_print = RS_SERVICE_GXS_TYPE_FORUMS;// use this to allow to this service id only, or 0 for all services - // warning. Numbers should be SERVICE IDS (see serialiser/rsserviceids.h. E.g. 0x0215 for forums) -class nullstream: public std::ostream {}; - -// static std::string nice_time_stamp(rstime_t now,rstime_t TS) -// { -// if(TS == 0) -// return "Never" ; -// else -// { -// std::ostringstream s; -// s << now - TS << " secs ago" ; -// return s.str() ; -// } -// } - -static std::ostream& gxsgenexchangedebug(uint32_t service_type) -{ - static nullstream null ; - - if (service_to_print==0 || service_type == 0 || (service_type == service_to_print)) - return std::cerr << time(NULL) << ":RSGENEXCHANGE service " << std::hex << service_type << std::dec << ": " ; - else - return null ; -} - -#define GXSGENEXCHANGEDEBUG gxsgenexchangedebug(serviceType()) - -#endif - -// Data flow in RsGenExchange -// -// publishGroup() -// | -// +--- stores in mGrpsToPublish -// -// updateGroup() -// | -// +--- stores in mGroupUpdatePublish -// -// tick() -// | -// +--- processRecvdData(); -// | | -// | +-- processRecvdGroups(); -// | | | -// | | +---- mGroupPendingValidate -// | | | -// | | +---- acceptance => validateGrp() => check existance => store in mGroupUpdates -// | | | -// | | +--- validateNxsGrp() -// | | -// | +-- processRecvdMessages(); -// | | -// | +-- performUpdateValidation(); // validates group updates in mGroupUpdates received from friends -// | | -// | +---- mGroupUpdates => updateValid() => store new groups -// | | | -// | | +--- stamp keys, check admin keys are the same, validateNxsGrp() -// | | | -// | +---- stores RsGxsGroupChange in mNotifications +--- data signature check -// | -// +--- publishGrps(); // creates signatures and data for locally created groups -// | | -// | +-- reads mGrpsToPublish, creates the group, clears mGrpsToPublish -// | | -// | +--- generateGroupKeys() -// | | -// | +--- serviceCreateGroup() -// | | -// | +--- createGroup() -// | | -// | +--- createGroupSignatures() -// | -// +--- processGroupUpdatePublish(); // goes through list of group updates to perform locally -// | | -// | +-- reads/deletes mGroupUpdatePublish, stores in mGrpsToPublish -// | -// +--- processGrpMetaChanges(); -// | | -// | +-- updates mNotifications, calls mDataAccess -// | -// +--- processGroupDelete(); -// | -// +--- publishMsgs(); -// | -// +--- processMsgMetaChanges(); -// | | -// | +-- updates mNotifications, calls mDataAccess -// | -// +--- processMessageDelete(); -// | -// +--- mDataAccess->processRequests(); -// | -// +--- processRoutingClues() ; -// - -RsGenExchange::RsGenExchange( - RsGeneralDataService* gds, RsNetworkExchangeService* ns, - RsSerialType* serviceSerialiser, uint16_t servType, RsGixs* gixs, - uint32_t authenPolicy ) : - mGenMtx("GenExchange"), - mDataStore(gds), - mNetService(ns), - mSerialiser(serviceSerialiser), - mServType(servType), - mGixs(gixs), - mAuthenPolicy(authenPolicy), - mCleaning(false), - mLastClean((int)time(NULL) - (int)(RSRandom::random_u32() % MSG_CLEANUP_PERIOD)), // this helps unsynchronising the checks for the different services - mChecking(false), - mCheckStarted(false), - mLastCheck((int)time(NULL) - (int)(RSRandom::random_u32() % INTEGRITY_CHECK_PERIOD) + 120), // this helps unsynchronising the checks for the different services, with 2 min security to avoid checking right away before statistics come up. - mIntegrityCheck(NULL), - SIGN_MAX_WAITING_TIME(60), - SIGN_FAIL(0), - SIGN_SUCCESS(1), - SIGN_FAIL_TRY_LATER(2), - VALIDATE_FAIL(0), - VALIDATE_SUCCESS(1), - VALIDATE_FAIL_TRY_LATER(2), - VALIDATE_MAX_WAITING_TIME(60) -{ - mDataAccess = new RsGxsDataAccess(gds); -} - -void RsGenExchange::setNetworkExchangeService(RsNetworkExchangeService *ns) -{ - if(mNetService != NULL) - std::cerr << "(EE) Cannot override existing network exchange service. Make sure it has been deleted otherwise." << std::endl; - else - mNetService = ns ; -} - -RsGenExchange::~RsGenExchange() -{ - // need to destruct in a certain order (bad thing, TODO: put down instance ownership rules!) - delete mNetService; - - delete mDataAccess; - mDataAccess = NULL; - - delete mDataStore; - mDataStore = NULL; - - for(uint32_t i=0;igetGroupServerUpdateTS(gid,grp_server_update_TS,msg_server_update_TS) ; -} - -void RsGenExchange::threadTick() -{ - static const double timeDelta = 0.1; // slow tick in sec - - tick(); - rstime::rs_usleep((int) (timeDelta * 1000 *1000)); // timeDelta sec -} - -void RsGenExchange::tick() -{ - // Meta Changes should happen first. - // This is important, as services want to change Meta, then get results. - // Services shouldn't rely on this ordering - but some do. - processGrpMetaChanges(); - processMsgMetaChanges(); - - mDataAccess->processRequests(); - - publishGrps(); - - publishMsgs(); - - processGroupUpdatePublish(); - - processGroupDelete(); - processMessageDelete(); - - processRecvdData(); - - processRoutingClues() ; - - { - std::vector mNotifications_copy; - - // make a non-deep copy of mNotifications so that it can be passed off-mutex to notifyChanged() - // that will delete it. The potential high cost of notifyChanges() makes it preferable to call off-mutex. - { - RS_STACK_MUTEX(mGenMtx); - if(!mNotifications.empty()) - { - mNotifications_copy = mNotifications; - mNotifications.clear(); - } - } - - // Calling notifyChanges() calls back RsGxsIfaceHelper::receiveChanges() that deletes the pointers in the array - // and the array itself. This is pretty bad and we should normally delete the changes here. - - if(!mNotifications_copy.empty()) - notifyChanges(mNotifications_copy); - } - - // implemented service tick function - service_tick(); - - rstime_t now = time(NULL); - - // Cleanup unused data. This is only needed when auto-synchronization is needed, which is not the case - // of identities. This is why idendities do their own cleaning. - now = time(NULL); - - if( (mNetService && (mNetService->msgAutoSync() || mNetService->grpAutoSync())) && (mLastClean + MSG_CLEANUP_PERIOD < now) ) - { - GxsMsgReq msgs_to_delete; - std::vector grps_to_delete; - - RsGxsCleanUp(mDataStore,this,1).clean(mNextGroupToCheck,grps_to_delete,msgs_to_delete); // no need to lock here, because all access below (RsGenExchange, RsDataStore) are properly mutexed - - uint32_t token1=0; - deleteMsgs(token1,msgs_to_delete); - - for(auto& grpId: grps_to_delete) - { - uint32_t token2=0; - deleteGroup(token2,grpId); - } - - RS_STACK_MUTEX(mGenMtx) ; - mLastClean = now; - } - - if(mChecking || (mLastCheck + INTEGRITY_CHECK_PERIOD < now)) - { - mLastCheck = time(NULL); - - { - RS_STACK_MUTEX(mGenMtx) ; - - if(!mIntegrityCheck) - { - mIntegrityCheck = new RsGxsIntegrityCheck( mDataStore, this, - *mSerialiser, mGixs); - std::string thisName = typeid(*this).name(); - mChecking = mIntegrityCheck->start("gxs IC4 "+thisName); - } - } - - if(mIntegrityCheck->isDone() || !mChecking) - { - std::vector grpIds; - GxsMsgReq msgIds; - - { - RS_STACK_MUTEX(mGenMtx) ; - mIntegrityCheck->getDeletedIds(grpIds, msgIds); - } - - if(!msgIds.empty()) - { - uint32_t token1=0; - deleteMsgs(token1,msgIds); - } - - if(!grpIds.empty()) - for(auto& grpId: grpIds) - { - uint32_t token2=0; - deleteGroup(token2,grpId); - } - - { - RS_STACK_MUTEX(mGenMtx) ; - delete mIntegrityCheck; - mIntegrityCheck = NULL; - mChecking = false; - } - } - } -} - -bool RsGenExchange::messagePublicationTest(const RsGxsMsgMetaData& meta) -{ - if(!mNetService) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "(EE) No network service in service " << std::hex << serviceType() << std::dec << ": cannot read message storage time." << std::endl; -#endif - return false ; - } - - uint32_t st = mNetService->getKeepAge(meta.mGroupId); - - rstime_t storageTimeLimit = meta.mPublishTs + st; - - return meta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_KEEP_FOREVER || st == 0 || storageTimeLimit >= time(NULL); -} - -bool RsGenExchange::acknowledgeTokenMsg(const uint32_t& token, RsGxsGrpMsgIdPair& msgId) -{ - RS_STACK_MUTEX(mGenMtx) ; - -#ifdef GEN_EXCH_DEBUG - GXSGENEXCHANGEDEBUG << "RsGenExchange::acknowledgeTokenMsg(). token=" << token << std::endl; -#endif - std::map::iterator mit = mMsgNotify.find(token); - - if(mit == mMsgNotify.end()) - { -#ifdef GEN_EXCH_DEBUG - GXSGENEXCHANGEDEBUG << " no notification found for this token." << std::endl; -#endif - return false; - } - - - msgId = mit->second; - - // no dump token as client has ackowledged its completion - mDataAccess->disposeOfPublicToken(token); - mMsgNotify.erase(mit); - -#ifdef GEN_EXCH_DEBUG - GXSGENEXCHANGEDEBUG << " found grpId=" << msgId.first <<", msgId=" << msgId.second << " disposing token from mDataAccess" << std::endl; -#endif - return true; -} - - - -bool RsGenExchange::acknowledgeTokenGrp(const uint32_t& token, RsGxsGroupId& grpId) -{ - RS_STACK_MUTEX(mGenMtx) ; - -#ifdef GEN_EXCH_DEBUG - GXSGENEXCHANGEDEBUG << "RsGenExchange::acknowledgeTokenGrp(). token=" << token << std::endl; -#endif - std::map::iterator mit = mGrpNotify.find(token); - - if(mit == mGrpNotify.end()) - { -#ifdef GEN_EXCH_DEBUG - GXSGENEXCHANGEDEBUG << " no notification found for this token." << std::endl; -#endif - return false; - } - - grpId = mit->second; - - // no dump token as client has ackowledged its completion - mDataAccess->disposeOfPublicToken(token); - mGrpNotify.erase(mit); - -#ifdef GEN_EXCH_DEBUG - GXSGENEXCHANGEDEBUG << " found grpId=" << grpId << ". Disposing token from mDataAccess" << std::endl; -#endif - return true; -} - -void RsGenExchange::generateGroupKeys(RsTlvSecurityKeySet& keySet, bool genPublishKeys) -{ - /* create Keys */ - RsTlvPublicRSAKey pubAdminKey ; - RsTlvPrivateRSAKey privAdminKey; - - GxsSecurity::generateKeyPair(pubAdminKey,privAdminKey) ; - - // for now all public - pubAdminKey.keyFlags |= RSTLV_KEY_DISTRIB_ADMIN ; - privAdminKey.keyFlags |= RSTLV_KEY_DISTRIB_ADMIN ; - - keySet.public_keys[pubAdminKey.keyId] = pubAdminKey; - keySet.private_keys[privAdminKey.keyId] = privAdminKey; - - if(genPublishKeys) - { - /* set publish keys */ - RsTlvPublicRSAKey pubPublishKey ; - RsTlvPrivateRSAKey privPublishKey; - - GxsSecurity::generateKeyPair(pubPublishKey,privPublishKey) ; - - // for now all public - pubPublishKey.keyFlags |= RSTLV_KEY_DISTRIB_PUBLISH ; - privPublishKey.keyFlags |= RSTLV_KEY_DISTRIB_PUBLISH ; - - keySet.public_keys[pubPublishKey.keyId] = pubPublishKey; - keySet.private_keys[privPublishKey.keyId] = privPublishKey; - } -} - -uint8_t RsGenExchange::createGroup(RsNxsGrp *grp, RsTlvSecurityKeySet& keySet) -{ -#ifdef GEN_EXCH_DEBUG - GXSGENEXCHANGEDEBUG << "RsGenExchange::createGroup()"<< std::endl; -#endif - - RsGxsGrpMetaData* meta = grp->metaData; - - /* add public admin and publish keys to grp */ - - // find private admin key - RsTlvPrivateRSAKey privAdminKey; - bool privKeyFound = false; // private admin key - - for( std::map::iterator mit = keySet.private_keys.begin(); mit != keySet.private_keys.end(); ++mit) - { - RsTlvPrivateRSAKey& key = mit->second; - - if((key.keyFlags & RSTLV_KEY_DISTRIB_ADMIN) && (key.keyFlags & RSTLV_KEY_TYPE_FULL)) - { - privAdminKey = key; - privKeyFound = true; - break ; - } - } - - if(!privKeyFound) - { - std::cerr << "RsGenExchange::createGroup() Missing private ADMIN Key" << std::endl; - - return false; - } - - // only public keys are included to be transported. The 2nd line below is very important. - - meta->keys = keySet; - meta->keys.private_keys.clear() ; - - // group is self signing - // for the creation of group signature - // only public admin and publish keys are present in meta - uint32_t metaDataLen = meta->serial_size(RS_GXS_GRP_META_DATA_CURRENT_API_VERSION); - uint32_t allGrpDataLen = metaDataLen + grp->grp.bin_len; - - char* metaData = new char[metaDataLen]; - char* allGrpData = new char[allGrpDataLen]; // msgData + metaData - - meta->serialise(metaData, metaDataLen,RS_GXS_GRP_META_DATA_CURRENT_API_VERSION); - - // copy msg data and meta in allMsgData buffer - memcpy(allGrpData, grp->grp.bin_data, grp->grp.bin_len); - memcpy(allGrpData+(grp->grp.bin_len), metaData, metaDataLen); - - RsTlvKeySignature adminSign; - bool ok = GxsSecurity::getSignature(allGrpData, allGrpDataLen, privAdminKey, adminSign); - - // add admin sign to grpMeta - meta->signSet.keySignSet[INDEX_AUTHEN_ADMIN] = adminSign; - - RsTlvBinaryData grpData(mServType); - grpData.setBinData(allGrpData, allGrpDataLen); - - uint8_t ret = createGroupSignatures(meta->signSet, grpData, *(grp->metaData)); - - // clean up - delete[] allGrpData; - delete[] metaData; - - if (!ok) - { - std::cerr << "RsGenExchange::createGroup() ERROR !okay (getSignature error)" << std::endl; - return CREATE_FAIL; - } - - if(ret == SIGN_FAIL) - { - return CREATE_FAIL; - }else if(ret == SIGN_FAIL_TRY_LATER) - { - return CREATE_FAIL_TRY_LATER; - }else if(ret == SIGN_SUCCESS) - { - return CREATE_SUCCESS; - }else{ - return CREATE_FAIL; - } -} - -int RsGenExchange::createGroupSignatures(RsTlvKeySignatureSet& signSet, RsTlvBinaryData& grpData, - RsGxsGrpMetaData& grpMeta) -{ - bool needIdentitySign = false; - int id_ret; - - uint8_t author_flag = GXS_SERV::GRP_OPTION_AUTHEN_AUTHOR_SIGN; - - PrivacyBitPos pos = GRP_OPTION_BITS; - - // Check required permissions, and allow them to sign it - if they want too - as well! - if ((!grpMeta.mAuthorId.isNull()) || checkAuthenFlag(pos, author_flag)) - { - needIdentitySign = true; -#ifdef GEN_EXCH_DEBUG - GXSGENEXCHANGEDEBUG << "Needs Identity sign! (Service Flags)"<< std::endl; -#endif - } - - if (needIdentitySign) - { - if(grpMeta.mAuthorId.isNull()) - { - std::cerr << "RsGenExchange::createGroupSignatures() "; - std::cerr << "Group signature is required by service, but the author id is null." << std::endl; - id_ret = SIGN_FAIL; - } - else if(mGixs) - { - bool haveKey = mGixs->havePrivateKey(grpMeta.mAuthorId); - - if(haveKey) - { - RsTlvPrivateRSAKey authorKey; - mGixs->getPrivateKey(grpMeta.mAuthorId, authorKey); - RsTlvKeySignature sign; - - if(GxsSecurity::getSignature((char*)grpData.bin_data, grpData.bin_len, authorKey, sign)) - { - id_ret = SIGN_SUCCESS; - mGixs->timeStampKey(grpMeta.mAuthorId,RsIdentityUsage(RsServiceType(mServType),RsIdentityUsage::GROUP_AUTHOR_SIGNATURE_CREATION,grpMeta.mGroupId)) ; - signSet.keySignSet[INDEX_AUTHEN_IDENTITY] = sign; - } - else - id_ret = SIGN_FAIL; - } - else - { - mGixs->requestPrivateKey(grpMeta.mAuthorId); - -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::createGroupSignatures(): "; - std::cerr << " ERROR AUTHOR KEY: " << grpMeta.mAuthorId - << " is not Cached / available for Message Signing\n"; - std::cerr << "RsGenExchange::createGroupSignatures(): Requestiong AUTHOR KEY"; - std::cerr << std::endl; -#endif - - id_ret = SIGN_FAIL_TRY_LATER; - } - } - else - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::createGroupSignatures()"; - std::cerr << "Gixs not enabled while request identity signature validation!" << std::endl; -#endif - id_ret = SIGN_FAIL; - } - } - else - { - id_ret = SIGN_SUCCESS; - } - - return id_ret; -} - -int RsGenExchange::createMsgSignatures(RsTlvKeySignatureSet& signSet, RsTlvBinaryData& msgData, - const RsGxsMsgMetaData& msgMeta, const RsGxsGrpMetaData& grpMeta) -{ - bool needPublishSign = false, needIdentitySign = false; - uint32_t grpFlag = grpMeta.mGroupFlags; - - bool publishSignSuccess = false; - -#ifdef GEN_EXCH_DEBUG - GXSGENEXCHANGEDEBUG << "RsGenExchange::createMsgSignatures() for Msg.mMsgName: " << msgMeta.mMsgName<< std::endl; -#endif - - - // publish signature is determined by whether group is public or not - // for private group signature is not needed as it needs decrypting with - // the private publish key anyways - - // restricted is a special case which heeds whether publish sign needs to be checked or not - // one may or may not want - - uint8_t author_flag = GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN; - uint8_t publish_flag = GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN; - - if(!msgMeta.mParentId.isNull()) - { - // Child Message. - author_flag = GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; - publish_flag = GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN; - } - - PrivacyBitPos pos = PUBLIC_GRP_BITS; - if (grpFlag & GXS_SERV::FLAG_PRIVACY_RESTRICTED) - { - pos = RESTRICTED_GRP_BITS; - } - else if (grpFlag & GXS_SERV::FLAG_PRIVACY_PRIVATE) - { - pos = PRIVATE_GRP_BITS; - } - - needIdentitySign = false; - needPublishSign = false; - if (checkAuthenFlag(pos, publish_flag)) - { - needPublishSign = true; -#ifdef GEN_EXCH_DEBUG - GXSGENEXCHANGEDEBUG << "Needs Publish sign! (Service Flags)"<< std::endl; -#endif - } - - // Check required permissions, and allow them to sign it - if they want too - as well! - if (checkAuthenFlag(pos, author_flag)) - { - needIdentitySign = true; -#ifdef GEN_EXCH_DEBUG - GXSGENEXCHANGEDEBUG << "Needs Identity sign! (Service Flags)"<< std::endl; -#endif - } - - if (!msgMeta.mAuthorId.isNull()) - { - needIdentitySign = true; -#ifdef GEN_EXCH_DEBUG - GXSGENEXCHANGEDEBUG << "Needs Identity sign! (AuthorId Exists)"<< std::endl; -#endif - } - - if(needPublishSign) - { - // public and shared is publish key - const RsTlvSecurityKeySet& keys = grpMeta.keys; - const RsTlvPrivateRSAKey *publishKey; - - std::map::const_iterator mit = keys.private_keys.begin(), mit_end = keys.private_keys.end(); - bool publish_key_found = false; - - for(; mit != mit_end; ++mit) - { - - publish_key_found = mit->second.keyFlags == (RSTLV_KEY_DISTRIB_PUBLISH | RSTLV_KEY_TYPE_FULL); - if(publish_key_found) - break; - } - - if (publish_key_found) - { - // private publish key - publishKey = &(mit->second); - - RsTlvKeySignature publishSign = signSet.keySignSet[INDEX_AUTHEN_PUBLISH]; - - publishSignSuccess = GxsSecurity::getSignature((char*)msgData.bin_data, msgData.bin_len, *publishKey, publishSign); - - //place signature in msg meta - signSet.keySignSet[INDEX_AUTHEN_PUBLISH] = publishSign; - }else - { - std::cerr << "RsGenExchange::createMsgSignatures()"; - std::cerr << " ERROR Cannot find PUBLISH KEY for Message Signing!"; - std::cerr << " ERROR Publish Sign failed!"; - std::cerr << std::endl; - } - - } - else // publish sign not needed so set as successful - { - publishSignSuccess = true; - } - - int id_ret; - - if (needIdentitySign) - { - if(mGixs) - { - bool haveKey = mGixs->havePrivateKey(msgMeta.mAuthorId); - - if(haveKey) - { - RsTlvPrivateRSAKey authorKey; - mGixs->getPrivateKey(msgMeta.mAuthorId, authorKey); - RsTlvKeySignature sign; - - if(GxsSecurity::getSignature((char*)msgData.bin_data, msgData.bin_len, authorKey, sign)) - { - id_ret = SIGN_SUCCESS; - mGixs->timeStampKey(msgMeta.mAuthorId,RsIdentityUsage(RsServiceType(mServType),RsIdentityUsage::MESSAGE_AUTHOR_SIGNATURE_CREATION,msgMeta.mGroupId,msgMeta.mMsgId,msgMeta.mParentId,msgMeta.mThreadId)) ; - signSet.keySignSet[INDEX_AUTHEN_IDENTITY] = sign; - } - else - id_ret = SIGN_FAIL; - } - else - { - mGixs->requestPrivateKey(msgMeta.mAuthorId); - -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::createMsgSignatures(): "; - std::cerr << " ERROR AUTHOR KEY: " << msgMeta.mAuthorId - << " is not Cached / available for Message Signing\n"; - std::cerr << "RsGenExchange::createMsgSignatures(): Requestiong AUTHOR KEY"; - std::cerr << std::endl; -#endif - - id_ret = SIGN_FAIL_TRY_LATER; - } - } - else - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::createMsgSignatures()"; - std::cerr << "Gixs not enabled while request identity signature validation!" << std::endl; -#endif - id_ret = SIGN_FAIL; - } - } - else - { - id_ret = SIGN_SUCCESS; - } - - if(publishSignSuccess) - { - return id_ret; - } - else - { - return SIGN_FAIL; - } -} - -int RsGenExchange::createMessage(RsNxsMsg* msg) -{ - const RsGxsGroupId& id = msg->grpId; - -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::createMessage() " << std::endl; -#endif - RsGxsGrpMetaTemporaryMap metaMap ; - metaMap[id] = std::make_shared(); - mDataStore->retrieveGxsGrpMetaData(metaMap); - - RsGxsMsgMetaData &meta = *(msg->metaData); - - int ret_val; - - if(!metaMap[id]) - { - return CREATE_FAIL; - } - else - { - // get publish key - const auto& grpMeta = metaMap[id]; - - uint32_t metaDataLen = meta.serial_size(); - uint32_t allMsgDataLen = metaDataLen + msg->msg.bin_len; - - RsTemporaryMemory metaData(metaDataLen); - RsTemporaryMemory allMsgData(allMsgDataLen); - - meta.serialise(metaData, &metaDataLen); - - // copy msg data and meta in allmsgData buffer - memcpy(allMsgData, msg->msg.bin_data, msg->msg.bin_len); - memcpy(allMsgData+(msg->msg.bin_len), metaData, metaDataLen); - - RsTlvBinaryData msgData(0); - - msgData.setBinData(allMsgData, allMsgDataLen); - - // create signatures - ret_val = createMsgSignatures(meta.signSet, msgData, meta, *grpMeta); - - - // get hash of msg data to create msg id - pqihash hash; - hash.addData(allMsgData, allMsgDataLen); - RsFileHash hashId; - hash.Complete(hashId); - msg->msgId = RsGxsMessageId(hashId); - - // assign msg id to msg meta - msg->metaData->mMsgId = msg->msgId; - } - - if(ret_val == SIGN_FAIL) - return CREATE_FAIL; - else if(ret_val == SIGN_FAIL_TRY_LATER) - return CREATE_FAIL_TRY_LATER; - else if(ret_val == SIGN_SUCCESS) - return CREATE_SUCCESS; - else - { - std::cerr << "Unknown return value from signature attempt!"; - return CREATE_FAIL; - } -} - -int RsGenExchange::validateMsg(RsNxsMsg *msg, const uint32_t& grpFlag, const uint32_t& /*signFlag*/, RsTlvSecurityKeySet& grpKeySet) -{ - bool needIdentitySign = false; - bool needPublishSign = false; - bool publishValidate = true, idValidate = true; - - uint8_t author_flag = GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN; - uint8_t publish_flag = GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN; - - if(!msg->metaData->mParentId.isNull()) - { - // Child Message. - author_flag = GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; - publish_flag = GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN; - } - - PrivacyBitPos pos = PUBLIC_GRP_BITS; - if (grpFlag & GXS_SERV::FLAG_PRIVACY_RESTRICTED) - { - pos = RESTRICTED_GRP_BITS; - } - else if (grpFlag & GXS_SERV::FLAG_PRIVACY_PRIVATE) - { - pos = PRIVATE_GRP_BITS; - } - - if (checkAuthenFlag(pos, publish_flag)) - needPublishSign = true; - - // Check required permissions, if they have signed it anyway - we need to validate it. - if ((checkAuthenFlag(pos, author_flag)) || (!msg->metaData->mAuthorId.isNull())) - needIdentitySign = true; - -#ifdef GEN_EXCH_DEBUG - std::cerr << "Validate message: msgId=" << msg->msgId << ", grpId=" << msg->grpId << " grpFlags=" << std::hex << grpFlag << std::dec - << ". Need publish=" << needPublishSign << ", needIdentitySign=" << needIdentitySign ; -#endif - - RsGxsMsgMetaData& metaData = *(msg->metaData); - - if(needPublishSign) - { - RsTlvKeySignature sign = metaData.signSet.keySignSet[INDEX_AUTHEN_PUBLISH]; - - std::map& keys = grpKeySet.public_keys; - std::map::iterator mit = keys.begin(); - - RsGxsId keyId; - for(; mit != keys.end() ; ++mit) - { - RsTlvPublicRSAKey& key = mit->second; - - if(key.keyFlags & RSTLV_KEY_DISTRIB_PUBLIC_deprecated) - { - keyId = key.keyId; - std::cerr << "WARNING: old style publish key with flags " << key.keyFlags << std::endl; - std::cerr << " this cannot be fixed, but RS will deal with it." << std::endl; - break ; - } - if(key.keyFlags & RSTLV_KEY_DISTRIB_PUBLISH) // we might have the private key, but we still should be able to check the signature - { - keyId = key.keyId; - break; - } - } - - if(!keyId.isNull()) - { - RsTlvPublicRSAKey& key = keys[keyId]; - publishValidate &= GxsSecurity::validateNxsMsg(*msg, sign, key); - } - else - { - std::cerr << "(EE) public publish key not found in group that require publish key validation. This should not happen! msgId=" << metaData.mMsgId << ", grpId=" << metaData.mGroupId << std::endl; - std::cerr << "(EE) public keys available for this group are: " << std::endl; - - for(std::map::const_iterator it(grpKeySet.public_keys.begin());it!=grpKeySet.public_keys.end();++it) - std::cerr << "(EE) " << it->first << std::endl; - - std::cerr << "(EE) private keys available for this group are: " << std::endl; - - for(std::map::const_iterator it(grpKeySet.private_keys.begin());it!=grpKeySet.private_keys.end();++it) - std::cerr << "(EE) " << it->first << std::endl; - - publishValidate = false; - } - } - else - { - publishValidate = true; - } - - - - if(needIdentitySign) - { - if(mGixs) - { - bool haveKey = mGixs->haveKey(metaData.mAuthorId); - - if(haveKey) - { - - RsTlvPublicRSAKey authorKey; - bool auth_key_fetched = mGixs->getKey(metaData.mAuthorId, authorKey) ; - - if (auth_key_fetched) - { - RsTlvKeySignature sign = metaData.signSet.keySignSet[INDEX_AUTHEN_IDENTITY]; - idValidate &= GxsSecurity::validateNxsMsg(*msg, sign, authorKey); - mGixs->timeStampKey(metaData.mAuthorId,RsIdentityUsage(RsServiceType(mServType),RsIdentityUsage::MESSAGE_AUTHOR_SIGNATURE_VALIDATION, - metaData.mGroupId, - metaData.mMsgId, - metaData.mParentId, - metaData.mThreadId)) ; - } - else - { - std::cerr << "RsGenExchange::validateMsg()"; - std::cerr << " ERROR Cannot Retrieve AUTHOR KEY for Message Validation"; - std::cerr << std::endl; - idValidate = false; - } - - if(idValidate) - { - // get key data and check that the key is actually PGP-linked. If not, reject the post. - - RsIdentityDetails details ; - - if(!mGixs->getIdDetails(metaData.mAuthorId,details)) - { - // the key cannot ke reached, although it's in cache. Weird situation. - std::cerr << "RsGenExchange::validateMsg(): cannot get key data for ID=" << metaData.mAuthorId << ", although it's supposed to be already in cache. Cannot validate." << std::endl; - idValidate = false ; - } - else - { - - // now check reputation of the message author. The reputation will need to be at least as high as this value for the msg to validate. - // At validation step, we accept all messages, except the ones signed by locally rejected identities. - - if( details.mReputation.mOverallReputationLevel == - RsReputationLevel::LOCALLY_NEGATIVE ) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::validateMsg(): message from " << metaData.mAuthorId << ", rejected because reputation level (" << static_cast(details.mReputation.mOverallReputationLevel) <<") indicate that you banned this ID." << std::endl; -#endif - idValidate = false ; - } - } - - } - } - else - { - std::list peers; - peers.push_back(msg->PeerId()); - mGixs->requestKey(metaData.mAuthorId, peers, RsIdentityUsage((RsServiceType)serviceType(), - RsIdentityUsage::MESSAGE_AUTHOR_SIGNATURE_VALIDATION, - metaData.mGroupId, - metaData.mMsgId, - metaData.mParentId, - metaData.mThreadId)); - -#ifdef GEN_EXCH_DEBUG - std::cerr << ", Key missing. Retry later." << std::endl; -#endif - return VALIDATE_FAIL_TRY_LATER; - } - } - else - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "Gixs not enabled while request identity signature validation!" << std::endl; -#endif - idValidate = false; - } - } - else - { - idValidate = true; - } - -#ifdef GEN_EXCH_DEBUG - std::cerr << ", publish val=" << publishValidate << ", idValidate=" << idValidate << ". Result=" << (publishValidate && idValidate) << std::endl; -#endif - - if(publishValidate && idValidate) - return VALIDATE_SUCCESS; - else - return VALIDATE_FAIL; - -} - -int RsGenExchange::validateGrp(RsNxsGrp* grp) -{ - bool needIdentitySign = false, idValidate = false; - RsGxsGrpMetaData& metaData = *(grp->metaData); - - uint8_t author_flag = GXS_SERV::GRP_OPTION_AUTHEN_AUTHOR_SIGN; - - PrivacyBitPos pos = GRP_OPTION_BITS; - -#ifdef GEN_EXCH_DEBUG - std::cerr << "Validating group " << grp->grpId << ", authorId = " << metaData.mAuthorId << std::endl; -#endif - // Check required permissions, and allow them to sign it - if they want too - as well! - if ((!metaData.mAuthorId.isNull()) || checkAuthenFlag(pos, author_flag)) - { - needIdentitySign = true; -#ifdef GEN_EXCH_DEBUG - std::cerr << " Needs Identity sign! (Service Flags). Identity signing key is " << metaData.mAuthorId << std::endl; -#endif - } - - if(needIdentitySign) - { - if(mGixs) - { - bool haveKey = mGixs->haveKey(metaData.mAuthorId); - - if(haveKey) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << " have ID key in cache: yes" << std::endl; -#endif - - RsTlvPublicRSAKey authorKey; - bool auth_key_fetched = mGixs->getKey(metaData.mAuthorId, authorKey) ; - - if (auth_key_fetched) - { - - RsTlvKeySignature sign = metaData.signSet.keySignSet[INDEX_AUTHEN_IDENTITY]; - idValidate = GxsSecurity::validateNxsGrp(*grp, sign, authorKey); - -#ifdef GEN_EXCH_DEBUG - std::cerr << " key ID validation result: " << idValidate << std::endl; -#endif - mGixs->timeStampKey(metaData.mAuthorId,RsIdentityUsage(RsServiceType(mServType),RsIdentityUsage::GROUP_AUTHOR_SIGNATURE_VALIDATION,metaData.mGroupId)); - } - else - { - std::cerr << "RsGenExchange::validateGrp()"; - std::cerr << " ERROR Cannot Retrieve AUTHOR KEY for Group Sign Validation"; - std::cerr << std::endl; - idValidate = false; - } - - }else - { -#ifdef GEN_EXCH_DEBUG - std::cerr << " have key in cache: no. Return VALIDATE_LATER" << std::endl; - std::cerr << " requesting key " << metaData.mAuthorId << " to origin peer " << grp->PeerId() << std::endl; -#endif - std::list peers; - peers.push_back(grp->PeerId()); - mGixs->requestKey(metaData.mAuthorId, peers,RsIdentityUsage(RsServiceType(mServType),RsIdentityUsage::GROUP_AUTHOR_SIGNATURE_VALIDATION,metaData.mGroupId)); - return VALIDATE_FAIL_TRY_LATER; - } - } - else - { -#ifdef GEN_EXCH_DEBUG - std::cerr << " (EE) Gixs not enabled while request identity signature validation!" << std::endl; -#endif - idValidate = false; - } - } - else - { - idValidate = true; - } - - if(idValidate) - return VALIDATE_SUCCESS; - else - return VALIDATE_FAIL; - -} - -bool RsGenExchange::checkAuthenFlag(const PrivacyBitPos& pos, const uint8_t& flag) const -{ -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::checkMsgAuthenFlag(pos: " << pos << " flag: "; - std::cerr << (int) flag << " mAuthenPolicy: " << mAuthenPolicy << ")"; - std::cerr << std::endl; -#endif - - switch(pos) - { - case PUBLIC_GRP_BITS: - return mAuthenPolicy & flag; - break; - case RESTRICTED_GRP_BITS: - return flag & (mAuthenPolicy >> RESTR_GRP_OFFSET); - break; - case PRIVATE_GRP_BITS: - return flag & (mAuthenPolicy >> PRIV_GRP_OFFSET); - break; - case GRP_OPTION_BITS: - return flag & (mAuthenPolicy >> GRP_OPTIONS_OFFSET); - break; - default: - std::cerr << "pos option not recognised"; - return false; - } -} - -#ifdef TO_REMOVE -static void addMessageChanged(std::map > &msgs, const std::map > &msgChanged) -{ - if (msgs.empty()) { - msgs = msgChanged; - } else { - for (auto mapIt = msgChanged.begin(); mapIt != msgChanged.end(); ++mapIt) - { - const RsGxsGroupId &grpId = mapIt->first; - const std::set &srcMsgIds = mapIt->second; - std::set &destMsgIds = msgs[grpId]; - - for (auto msgIt = srcMsgIds.begin(); msgIt != srcMsgIds.end(); ++msgIt) - destMsgIds.insert(*msgIt) ; - } - } -} - -void RsGenExchange::receiveChanges(std::vector& changes) -{ - std::cerr << "*********************************** RsGenExchange::receiveChanges()" << std::endl; -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::receiveChanges()" << std::endl; -#endif - std::unique_ptr evt(new RsGxsChanges); - evt->mServiceType = static_cast(mServType); - - RsGxsChanges& out = *evt; - out.mService = getTokenService(); - - // collect all changes in one GxsChanges object - std::vector::iterator vit = changes.begin(); - for(; vit != changes.end(); ++vit) - { - RsGxsNotify* n = *vit; - RsGxsGroupChange* gc; - RsGxsMsgChange* mc; - RsGxsDistantSearchResultChange *gt; - - if((mc = dynamic_cast(n)) != nullptr) - { - if (mc->metaChange()) - addMessageChanged(out.mMsgsMeta, mc->msgChangeMap); - else - addMessageChanged(out.mMsgs, mc->msgChangeMap); - } - else if((gc = dynamic_cast(n)) != nullptr) - { - if(gc->metaChange()) - out.mGrpsMeta.splice(out.mGrpsMeta.end(), gc->mGrpIdList); - else - out.mGrps.splice(out.mGrps.end(), gc->mGrpIdList); - } - else if(( gt = dynamic_cast(n) ) != nullptr) - out.mDistantSearchReqs.push_back(gt->mRequestId); - else - RsErr() << __PRETTY_FUNCTION__ << " Unknown changes type!" << std::endl; - delete n; - } - changes.clear() ; - - if(rsEvents) rsEvents->postEvent(std::move(evt)); -} -#endif - -bool RsGenExchange::subscribeToGroup(uint32_t& token, const RsGxsGroupId& grpId, bool subscribe) -{ - if(subscribe) - setGroupSubscribeFlags(token, grpId, GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED, - (GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED | GXS_SERV::GROUP_SUBSCRIBE_NOT_SUBSCRIBED)); - else - setGroupSubscribeFlags(token, grpId, GXS_SERV::GROUP_SUBSCRIBE_NOT_SUBSCRIBED, - (GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED | GXS_SERV::GROUP_SUBSCRIBE_NOT_SUBSCRIBED)); - - if(mNetService) mNetService->subscribeStatusChanged(grpId,subscribe); -#ifdef GEN_EXCH_DEBUG - else - std::cerr << "(EE) No mNetService in RsGenExchange for service 0x" << std::hex << mServType << std::dec << std::endl; -#endif - - return true; -} - -bool RsGenExchange::getGroupStatistic(const uint32_t& token, GxsGroupStatistic& stats) -{ - return mDataAccess->getGroupStatistic(token, stats); -} - -bool RsGenExchange::getServiceStatistic(const uint32_t& token, GxsServiceStatistic& stats) -{ - return mDataAccess->getServiceStatistic(token, stats); -} - -bool RsGenExchange::getGroupList(const uint32_t &token, std::list &groupIds) -{ - return mDataAccess->getGroupList(token, groupIds); - -} - -bool RsGenExchange::getMsgList(const uint32_t &token, - GxsMsgIdResult &msgIds) -{ - return mDataAccess->getMsgIdList(token, msgIds); -} - -bool RsGenExchange::getMsgRelatedList(const uint32_t &token, MsgRelatedIdResult &msgIds) -{ - return mDataAccess->getMsgRelatedList(token, msgIds); -} -bool RsGenExchange::getPublishedMsgMeta(const uint32_t& token,RsMsgMetaData& meta) -{ - auto it = mPublishedMsgs.find(token); - - if(it == mPublishedMsgs.end()) - return false ; - - meta = it->second; - return true; -} -bool RsGenExchange::getPublishedGroupMeta(const uint32_t& token,RsGroupMetaData& meta) -{ - auto it = mPublishedGrps.find(token); - - if(it == mPublishedGrps.end()) - return false ; - - meta = it->second; - return true; -} - -bool RsGenExchange::getGroupMeta(const uint32_t &token, std::list &groupInfo) -{ - std::list > metaL; - bool ok = mDataAccess->getGroupSummary(token, metaL); - - for( auto lit = metaL.begin(); lit != metaL.end(); ++lit) - { - const RsGxsGrpMetaData& gMeta = *(*lit); - - RsGroupMetaData m(gMeta); - RsGroupNetworkStats sts ; - - if(mNetService != NULL && mNetService->getGroupNetworkStats(gMeta.mGroupId,sts)) - { - m.mPop = sts.mSuppliers ; - m.mVisibleMsgCount = sts.mMaxVisibleCount ; - - if((!(IS_GROUP_SUBSCRIBED(gMeta.mSubscribeFlags))) || gMeta.mLastPost == 0) - m.mLastPost = sts.mLastGroupModificationTS ; - } - else - { - m.mPop= 0 ; - m.mVisibleMsgCount = 0 ; - } - - // We could save this in the net service, but it's a bit more than that since some services have - // specific usage footprints for their groups. - - m.mLastSeen = (IS_GROUP_SUBSCRIBED(gMeta.mSubscribeFlags)) ? time(nullptr) : service_getLastGroupSeenTs(gMeta.mGroupId); - -#ifdef GEN_EXCH_DEBUG - std::cerr << "Group: " << gMeta.mGroupId << " name \"" << gMeta.mGroupName << "\" last seen=" << m.mLastSeen << " now=" << time(nullptr) << std::endl; -#endif - - groupInfo.push_back(m); - } - - return ok; -} - -bool RsGenExchange::getMsgMeta(const uint32_t &token, - GxsMsgMetaMap &msgInfo) -{ -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::getMsgMeta(): retrieving meta data for token " << token << std::endl; -#endif - //std::list metaL; - GxsMsgMetaResult result; - bool ok = mDataAccess->getMsgSummary(token, result); - - for(auto mit=result.begin(); mit != result.end(); ++mit) - { - auto& metaV = mit->second; - - std::vector& msgInfoV = msgInfo[mit->first]; - - RsMsgMetaData meta; - for(auto vit=metaV.begin(); vit != metaV.end(); ++vit) - msgInfoV.push_back(RsMsgMetaData(*(*vit))); - } - - return ok; -} - -bool RsGenExchange::getMsgRelatedMeta(const uint32_t &token, GxsMsgRelatedMetaMap &msgMeta) -{ - MsgRelatedMetaResult result; - bool ok = mDataAccess->getMsgRelatedSummary(token, result); - - MsgRelatedMetaResult::iterator mit = result.begin(); - - for(; mit != result.end(); ++mit) - { - auto& metaV = mit->second; - - std::vector& msgInfoV = msgMeta[mit->first]; - - for(auto vit=metaV.begin(); vit != metaV.end(); ++vit) - msgInfoV.push_back(RsMsgMetaData(*(*vit))); - } - - return ok; -} - -bool RsGenExchange::getSerializedGroupData(uint32_t token, RsGxsGroupId& id, - unsigned char *& data, - uint32_t& size) -{ - RS_STACK_MUTEX(mGenMtx) ; - - std::list nxsGrps; - - if(!mDataAccess->getGroupData(token, nxsGrps)) - return false ; - - if(nxsGrps.size() != 1) - { - std::cerr << "(EE) getSerializedGroupData() got multiple groups in single request. This is unexpected." << std::endl; - - for(std::list::const_iterator it(nxsGrps.begin());it!=nxsGrps.end();++it) - delete *it ; - - return false ; - } - RsNxsGrp *nxs_grp = *(nxsGrps.begin()); - - size = RsNxsSerialiser(mServType).size(nxs_grp); - id = nxs_grp->metaData->mGroupId ; - - if(size > 1024*1024 || NULL==(data = (unsigned char *)rs_malloc(size))) - { - std::cerr << "(EE) getSerializedGroupData() cannot allocate mem chunk of size " << size << ". Too big, or no room." << std::endl; - delete nxs_grp ; - return false ; - } - - return RsNxsSerialiser(mServType).serialise(nxs_grp,data,&size) ; -} - -bool RsGenExchange::retrieveNxsIdentity(const RsGxsGroupId& group_id,RsNxsGrp *& identity_grp) -{ - RS_STACK_MUTEX(mGenMtx) ; - - std::map grp; - grp[group_id]=nullptr; - std::map::const_iterator grp_it; - - if(! mDataStore->retrieveNxsGrps(grp, true) || grp.end()==(grp_it=grp.find(group_id)) || !grp_it->second) - { - std::cerr << "(EE) Cannot retrieve group data for group " << group_id << " in service " << mServType << std::endl; - return false; - } - - identity_grp = grp_it->second; - return true; -} - -bool RsGenExchange::deserializeGroupData(unsigned char *data, uint32_t size, - RsGxsGroupId* gId /*= nullptr*/) -{ - RS_STACK_MUTEX(mGenMtx) ; - - RsItem *item = RsNxsSerialiser(mServType).deserialise(data, &size); - - RsNxsGrp *nxs_grp = dynamic_cast(item); - - if(item == NULL) - { - std::cerr << "(EE) RsGenExchange::deserializeGroupData(): cannot " - << "deserialise this data. Something's wrong." << std::endl; - delete item; - return false; - } - - if(mGrpPendingValidate.find(nxs_grp->grpId) != mGrpPendingValidate.end()) - { - std::cerr << "(WW) Group " << nxs_grp->grpId << " is already pending validation. Not adding again." << std::endl; - return true; - } - - if(gId) - *gId = nxs_grp->grpId; - - mGrpPendingValidate.insert(std::make_pair(nxs_grp->grpId, GxsPendingItem(nxs_grp, nxs_grp->grpId,time(NULL)))); - - return true; -} - -bool RsGenExchange::getGroupData(const uint32_t &token, std::vector& grpItem) -{ - std::list nxsGrps; - bool ok = mDataAccess->getGroupData(token, nxsGrps); - - std::list::iterator lit = nxsGrps.begin(); -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::getGroupData() RsNxsGrp::len: " << nxsGrps.size(); - std::cerr << std::endl; -#endif - - if(ok) - { - for(; lit != nxsGrps.end(); ++lit) - { - RsTlvBinaryData& data = (*lit)->grp; - RsItem* item = NULL; - - if(data.bin_len != 0) - item = mSerialiser->deserialise(data.bin_data, &data.bin_len); - - if(item) - { - RsGxsGrpItem* gItem = dynamic_cast(item); - if (gItem) - { - gItem->meta = *((*lit)->metaData); - - RsGroupNetworkStats sts ; - if(mNetService && mNetService->getGroupNetworkStats(gItem->meta.mGroupId,sts)) - { - gItem->meta.mPop = sts.mSuppliers; - gItem->meta.mVisibleMsgCount = sts.mMaxVisibleCount; - - // When the group is not subscribed, the last post value is not updated, because there's no message stored. As a consequence, - // we rely on network statistics to give this value, but it is not as accurate as if it was locally computed, because of blocked - // posts, friends not available, sync delays, etc. Similarly if the group has just been subscribed, the last post info is probably - // uninitialised, so we will it too. - - if((!(IS_GROUP_SUBSCRIBED(gItem->meta.mSubscribeFlags))) || gItem->meta.mLastPost == 0) - gItem->meta.mLastPost = sts.mLastGroupModificationTS ; - - } - else - { - gItem->meta.mPop = 0; - gItem->meta.mVisibleMsgCount = 0; - } - - // We could save this in the net service, but it's a bit more than that since some services have - // specific usage footprints for their groups. - - gItem->meta.mLastSeen = (IS_GROUP_SUBSCRIBED(gItem->meta.mSubscribeFlags)) ? time(nullptr) : service_getLastGroupSeenTs(gItem->meta.mGroupId); - -#ifdef GEN_EXCH_DEBUG - std::cerr << "Group: " << gItem->meta.mGroupId << " name \"" << gItem->meta.mGroupName << "\" last seen=" << gItem->meta.mLastSeen << " now=" << time(nullptr) << std::endl; -#endif - - // Also check the group privacy flags. A while ago, it as possible to publish a group without privacy flags. Now it is not possible anymore. - // As a consequence, it's important to supply a correct value in this flag before the data can be edited/updated. - - if((gItem->meta.mGroupFlags & GXS_SERV::FLAG_PRIVACY_MASK) == 0) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "(WW) getGroupData(): mGroupFlags for group " << gItem->meta.mGroupId << " has incorrect value " << std::hex << gItem->meta.mGroupFlags << std::dec << ". Setting value to GXS_SERV::FLAG_PRIVACY_PUBLIC." << std::endl; -#endif - gItem->meta.mGroupFlags |= GXS_SERV::FLAG_PRIVACY_PUBLIC; - } - - grpItem.push_back(gItem); - } - else - { - std::cerr << "RsGenExchange::getGroupData() deserialisation/dynamic_cast ERROR"; - std::cerr << std::endl; - delete item; - } - } - else if(data.bin_len > 0) - //std::cerr << "(EE) RsGenExchange::getGroupData() Item type is probably not handled. Data is: " << RsUtil::BinToHex((unsigned char*)data.bin_data,std::min(50u,data.bin_len)) << ((data.bin_len>50)?"...":"") << std::endl; - std::cerr << "(EE) RsGenExchange::getGroupData() Item type is probably not handled. Data is: " << RsUtil::BinToHex((unsigned char*)data.bin_data,data.bin_len) << std::endl; - - delete *lit; - } - } - return ok; -} - -bool RsGenExchange::getMsgData(uint32_t token, GxsMsgDataMap &msgItems) -{ - RS_STACK_MUTEX(mGenMtx) ; - NxsMsgDataResult msgResult; - bool ok = mDataAccess->getMsgData(token, msgResult); - - if(ok) - { - NxsMsgDataResult::iterator mit = msgResult.begin(); - for(; mit != msgResult.end(); ++mit) - { - const RsGxsGroupId& grpId = mit->first; - std::vector& gxsMsgItems = msgItems[grpId]; - std::vector& nxsMsgsV = mit->second; - std::vector::iterator vit = nxsMsgsV.begin(); - for(; vit != nxsMsgsV.end(); ++vit) - { - RsNxsMsg*& msg = *vit; - RsItem* item = NULL; - - if(msg->msg.bin_len != 0) - item = mSerialiser->deserialise(msg->msg.bin_data, &msg->msg.bin_len); - - if (item) - { - RsGxsMsgItem* mItem = dynamic_cast(item); - if (mItem) - { - mItem->meta = *((*vit)->metaData); // get meta info from nxs msg - gxsMsgItems.push_back(mItem); - } - else - { - std::cerr << "RsGenExchange::getMsgData() deserialisation/dynamic_cast ERROR"; - std::cerr << std::endl; - delete item; - } - } - else - { - std::cerr << "RsGenExchange::getMsgData() deserialisation ERROR"; - std::cerr << std::endl; - } - delete msg; - } - } - } - return ok; -} - -bool RsGenExchange::getMsgRelatedData( uint32_t token, - GxsMsgRelatedDataMap &msgItems ) -{ - RS_STACK_MUTEX(mGenMtx) ; - NxsMsgRelatedDataResult msgResult; - bool ok = mDataAccess->getMsgRelatedData(token, msgResult); - - if(ok) - { - NxsMsgRelatedDataResult::iterator mit = msgResult.begin(); - for(; mit != msgResult.end(); ++mit) - { - const RsGxsGrpMsgIdPair& msgId = mit->first; - std::vector &gxsMsgItems = msgItems[msgId]; - std::vector& nxsMsgsV = mit->second; - - for(auto vit=nxsMsgsV.begin(); vit != nxsMsgsV.end(); ++vit) - { - RsNxsMsg*& msg = *vit; - RsItem* item = NULL; - - if(msg->msg.bin_len != 0) - item = mSerialiser->deserialise(msg->msg.bin_data, - &msg->msg.bin_len); - if (item) - { - RsGxsMsgItem* mItem = dynamic_cast(item); - - if (mItem) - { - mItem->meta = *((*vit)->metaData); // get meta info from nxs msg - gxsMsgItems.push_back(mItem); - } - else - { - std::cerr << "RsGenExchange::getMsgRelatedData() deserialisation/dynamic_cast ERROR"; - std::cerr << std::endl; - delete item; - } - } - else - { - std::cerr << "RsGenExchange::getMsgRelatedData() deserialisation ERROR"; - std::cerr << std::endl; - } - - delete msg; - } - } - } - return ok; -} - -RsTokenService* RsGenExchange::getTokenService() -{ - return mDataAccess; -} - - -bool RsGenExchange::setAuthenPolicyFlag(const uint8_t &msgFlag, uint32_t& authenFlag, const PrivacyBitPos &pos) -{ - uint32_t temp = 0; - temp = msgFlag; - - switch(pos) - { - case PUBLIC_GRP_BITS: - authenFlag &= ~PUB_GRP_MASK; - authenFlag |= temp; - break; - case RESTRICTED_GRP_BITS: - authenFlag &= ~RESTR_GRP_MASK; - authenFlag |= (temp << RESTR_GRP_OFFSET); - break; - case PRIVATE_GRP_BITS: - authenFlag &= ~PRIV_GRP_MASK; - authenFlag |= (temp << PRIV_GRP_OFFSET); - break; - case GRP_OPTION_BITS: - authenFlag &= ~GRP_OPTIONS_MASK; - authenFlag |= (temp << GRP_OPTIONS_OFFSET); - break; - default: - std::cerr << "pos option not recognised"; - return false; - } - return true; -} - -void RsGenExchange::receiveNewGroups(const std::vector &groups) -{ - RS_STACK_MUTEX(mGenMtx) ; - - auto vit = groups.begin(); - - // store these for tick() to pick them up - for(; vit != groups.end(); ++vit) - { - RsNxsGrp* grp = *vit; - NxsGrpPendValidVect::iterator received = mGrpPendingValidate.find(grp->grpId); - - // drop group if you already have them - // TODO: move this to nxs layer to save bandwidth - if(received == mGrpPendingValidate.end()) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::notifyNewGroups() Received GrpId: " << grp->grpId; - std::cerr << std::endl; -#endif - - mGrpPendingValidate.insert(std::make_pair(grp->grpId, GxsPendingItem(grp, grp->grpId,time(NULL)))); - } - else - { - delete grp; - } - } - -} - - -void RsGenExchange::receiveNewMessages(const std::vector& messages) -{ - RS_STACK_MUTEX(mGenMtx) ; - - // store these for tick() to pick them up - - for(uint32_t i=0;imsgId) ; - - // if we have msg already just delete it - if(it == mMsgPendingValidate.end()) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::notifyNewMessages() Received Msg: "; - std::cerr << " GrpId: " << msg->grpId; - std::cerr << " MsgId: " << msg->msgId; - std::cerr << std::endl; -#endif - RsGxsGrpMsgIdPair id; - id.first = msg->grpId; - id.second = msg->msgId; - - mMsgPendingValidate.insert(std::make_pair(msg->msgId,GxsPendingItem(msg, id,time(NULL)))); - } - else - { -#ifdef GEN_EXCH_DEBUG - std::cerr << " message is already in pending validation list. dropping." << std::endl; -#endif - delete msg; - } - } -} - -void RsGenExchange::receiveDistantSearchResults(TurtleRequestId id,const RsGxsGroupId &/*grpId*/) -{ - std::cerr << __PRETTY_FUNCTION__ << " received result for request " << std::hex << id << std::dec << ": this method should be overloaded in the client service, but it is not. This is a bug!" << std::endl; -} - -void RsGenExchange::notifyReceivePublishKey(const RsGxsGroupId &grpId) -{ - RS_STACK_MUTEX(mGenMtx); - - RsGxsGroupChange* gc = new RsGxsGroupChange(RsGxsNotify::TYPE_RECEIVED_PUBLISHKEY,grpId, true); - mNotifications.push_back(gc); -} - -void RsGenExchange::notifyChangedGroupSyncParams(const RsGxsGroupId &grpId) -{ - RS_STACK_MUTEX(mGenMtx); - - RsGxsGroupChange* gc = new RsGxsGroupChange(RsGxsNotify::TYPE_GROUP_SYNC_PARAMETERS_UPDATED,grpId, false); - - mNotifications.push_back(gc); -} -void RsGenExchange::notifyChangedGroupStats(const RsGxsGroupId &grpId) -{ - RS_STACK_MUTEX(mGenMtx); - - RsGxsGroupChange* gc = new RsGxsGroupChange(RsGxsNotify::TYPE_STATISTICS_CHANGED,grpId, false); - - mNotifications.push_back(gc); -} - -bool RsGenExchange::checkGroupMetaConsistency(const RsGroupMetaData& meta) -{ - std::cerr << "Checking group consistency:" << std::endl; - - if(meta.mGroupName.empty()) - { - std::cerr << "(EE) cannot create a group with no name." << std::endl; - return false; - } - - uint32_t gf = meta.mGroupFlags & GXS_SERV::FLAG_PRIVACY_MASK ; - - if(gf != GXS_SERV::FLAG_PRIVACY_PUBLIC && gf != GXS_SERV::FLAG_PRIVACY_RESTRICTED && gf != GXS_SERV::FLAG_PRIVACY_PRIVATE) - { - std::cerr << "(EE) mGroupFlags has incorrect value " << std::hex << meta.mGroupFlags << std::dec << ". A value among GXS_SERV::FLAG_PRIVACY_{PUBLIC,RESTRICTED,PRIVATE} is expected." << std::endl; - return false ; - } - - if(meta.mCircleType < GXS_CIRCLE_TYPE_PUBLIC || meta.mCircleType > GXS_CIRCLE_TYPE_YOUR_EYES_ONLY) - { - std::cerr << "(EE) mCircleType has incorrect value " << std::hex << meta.mCircleType << std::dec << ". A single value among GXS_CIRCLE_TYPE_{PUBLIC,EXTERNAL,YOUR_FRIENDS_ONLY,LOCAL,EXT_SELF,YOUR_EYES_ONLY} is expected." << std::endl; - return false ; - } - - if(meta.mCircleType == GXS_CIRCLE_TYPE_EXTERNAL) - { - if(!meta.mInternalCircle.isNull()) - { - std::cerr << "(EE) Group circle type is EXTERNAL, but an internal circle ID " << meta.mInternalCircle << " was supplied. This is an error." << std::endl; - return false ; - } - if(meta.mCircleId.isNull()) - { - std::cerr << "(EE) Group circle type is EXTERNAL, but no external circle ID was supplied. meta.mCircleId is indeed empty. This is an error." << std::endl; - return false ; - } - } - - if(meta.mCircleType == GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY) - { - if(!meta.mCircleId.isNull()) - { - std::cerr << "(EE) Group circle type is YOUR_FRIENDS_ONLY, but an external circle ID " << meta.mCircleId << " was supplied. This is an error." << std::endl; - return false ; - } - if(meta.mInternalCircle.isNull()) - { - std::cerr << "(EE) Group circle type is YOUR_FRIENDS_ONLY, but no internal circle ID was supplied. meta.mInternalCircle is indeed empty. This is an error." << std::endl; - return false ; - } - } - - if(meta.mCircleType == GXS_CIRCLE_TYPE_EXT_SELF) - { - if(!meta.mCircleId.isNull()) - { - std::cerr << "(EE) Group circle type is EXT_SELF, but an external circle ID " << meta.mCircleId << " was supplied. This is an error." << std::endl; - return false ; - } - if(!meta.mInternalCircle.isNull()) - { - std::cerr << "(EE) Group circle type is EXT_SELF, but an internal circle ID " << meta.mInternalCircle << " was supplied. This is an error." << std::endl; - return false ; - } - } - - std::cerr << "Group is clean." << std::endl; - return true ; -} - -void RsGenExchange::publishGroup(uint32_t& token, RsGxsGrpItem *grpItem) -{ - if(!checkGroupMetaConsistency(grpItem->meta)) - { - std::cerr << "(EE) Cannot publish group. Some information was not supplied." << std::endl; - return ; - } - - RS_STACK_MUTEX(mGenMtx) ; - token = mDataAccess->generatePublicToken(); - GxsGrpPendingSign ggps(grpItem, token); - mGrpsToPublish.push_back(ggps); - -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::publishGroup() token: " << token; - std::cerr << std::endl; -#endif - -} - - -void RsGenExchange::updateGroup(uint32_t& token, RsGxsGrpItem* grpItem) -{ - if(!checkGroupMetaConsistency(grpItem->meta)) - { - std::cerr << "(EE) Cannot update group. Some information was not supplied." << std::endl; - delete grpItem; - return ; - } - - RS_STACK_MUTEX(mGenMtx) ; - token = mDataAccess->generatePublicToken(); - mGroupUpdatePublish.push_back(GroupUpdatePublish(grpItem, token)); - -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::updateGroup() token: " << token; - std::cerr << std::endl; -#endif -} - -void RsGenExchange::deleteGroup(uint32_t& token, const RsGxsGroupId& grpId) -{ - RS_STACK_MUTEX(mGenMtx) ; - token = mDataAccess->generatePublicToken(); - mGroupDeletePublish.push_back(GroupDeletePublish(grpId, token)); - -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::deleteGroup() token: " << token; - std::cerr << std::endl; -#endif -} -void RsGenExchange::deleteMsgs(uint32_t& token, const GxsMsgReq& msgs) -{ - RS_STACK_MUTEX(mGenMtx) ; - - token = mDataAccess->generatePublicToken(); - mMsgDeletePublish.push_back(MsgDeletePublish(msgs, token)); - - // This code below will suspend any requests of the deleted messages for 24 hrs. This of course only works - // if all friend nodes consistently delete the messages in the mean time. - - if(mNetService != NULL) - for(GxsMsgReq::const_iterator it(msgs.begin());it!=msgs.end();++it) - for(auto it2(it->second.begin());it2!=it->second.end();++it2) - mNetService->rejectMessage(*it2); -} - -void RsGenExchange::publishMsg(uint32_t& token, RsGxsMsgItem *msgItem) -{ - RS_STACK_MUTEX(mGenMtx) ; - token = mDataAccess->generatePublicToken(); - mMsgsToPublish.insert(std::make_pair(token, msgItem)); - -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::publishMsg() token: " << token; - std::cerr << std::endl; -#endif - -} - -uint32_t RsGenExchange::getDefaultSyncPeriod() -{ - RS_STACK_MUTEX(mGenMtx) ; - - if(mNetService != NULL) - return mNetService->getDefaultSyncAge(); - else - { - std::cerr << "(EE) No network service available. Cannot get default sync period. " << std::endl; - return 0; - } -} - -RsReputationLevel RsGenExchange::minReputationForForwardingMessages( - uint32_t group_sign_flags, uint32_t identity_sign_flags ) -{ - return RsNetworkExchangeService::minReputationForForwardingMessages(group_sign_flags,identity_sign_flags); -} -uint32_t RsGenExchange::getSyncPeriod(const RsGxsGroupId& grpId) -{ - RS_STACK_MUTEX(mGenMtx) ; - - if(mNetService != NULL) - return mNetService->getSyncAge(grpId); - else - return RS_GXS_DEFAULT_MSG_REQ_PERIOD; -} - -bool RsGenExchange::getGroupNetworkStats(const RsGxsGroupId& grpId,RsGroupNetworkStats& stats) -{ - return (!mNetService) || mNetService->getGroupNetworkStats(grpId,stats) ; -} - -void RsGenExchange::setSyncPeriod(const RsGxsGroupId& grpId,uint32_t age_in_secs) -{ - if(mNetService != NULL) - return mNetService->setSyncAge(grpId,age_in_secs) ; - else - std::cerr << "(EE) No network service available. Cannot set storage period. " << std::endl; -} - -uint32_t RsGenExchange::getStoragePeriod(const RsGxsGroupId& grpId) -{ - RS_STACK_MUTEX(mGenMtx) ; - - if(!mNetService) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "(EE) No network service in service " << std::hex << serviceType() << std::dec << ": cannot read message storage time. Returning infinity." << std::endl; -#endif - return false ; - } - return mNetService->getKeepAge(grpId) ; -} -void RsGenExchange::setStoragePeriod(const RsGxsGroupId& grpId,uint32_t age_in_secs) -{ - if(mNetService != NULL) - return mNetService->setKeepAge(grpId,age_in_secs) ; - else - std::cerr << "(EE) No network service available. Cannot set storage period. " << std::endl; -} - -void RsGenExchange::setGroupSubscribeFlags(uint32_t& token, const RsGxsGroupId& grpId, const uint32_t& flag, const uint32_t& mask) -{ - /* TODO APPLY MASK TO FLAGS */ - RS_STACK_MUTEX(mGenMtx) ; - token = mDataAccess->generatePublicToken(); - - GrpLocMetaData g; - g.grpId = grpId; - g.val.put(RsGeneralDataService::GRP_META_SUBSCRIBE_FLAG, (int32_t)flag); - g.val.put(RsGeneralDataService::GRP_META_SUBSCRIBE_FLAG+GXS_MASK, (int32_t)mask); // HACK, need to perform mask operation in a non-blocking location - mGrpLocMetaMap.insert(std::make_pair(token, g)); -} - -void RsGenExchange::setGroupStatusFlags(uint32_t& token, const RsGxsGroupId& grpId, const uint32_t& status, const uint32_t& mask) -{ - /* TODO APPLY MASK TO FLAGS */ - RS_STACK_MUTEX(mGenMtx) ; - token = mDataAccess->generatePublicToken(); - - GrpLocMetaData g; - g.grpId = grpId; - g.val.put(RsGeneralDataService::GRP_META_STATUS, (int32_t)status); - g.val.put(RsGeneralDataService::GRP_META_STATUS+GXS_MASK, (int32_t)mask); // HACK, need to perform mask operation in a non-blocking location - mGrpLocMetaMap.insert(std::make_pair(token, g)); -} - - -void RsGenExchange::setGroupServiceString(uint32_t& token, const RsGxsGroupId& grpId, const std::string& servString) -{ - RS_STACK_MUTEX(mGenMtx); - token = mDataAccess->generatePublicToken(); - - GrpLocMetaData g; - g.grpId = grpId; - g.val.put(RsGeneralDataService::GRP_META_SERV_STRING, servString); - mGrpLocMetaMap.insert(std::make_pair(token, g)); -} - -void RsGenExchange::setMsgStatusFlags(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, const uint32_t& status, const uint32_t& mask) -{ - /* TODO APPLY MASK TO FLAGS */ - RS_STACK_MUTEX(mGenMtx) ; - token = mDataAccess->generatePublicToken(); - - MsgLocMetaData m; - m.val.put(RsGeneralDataService::MSG_META_STATUS, (int32_t)status); - m.val.put(RsGeneralDataService::MSG_META_STATUS+GXS_MASK, (int32_t)mask); // HACK, need to perform mask operation in a non-blocking location - m.msgId = msgId; - mMsgLocMetaMap.insert(std::make_pair(token, m)); -} - -void RsGenExchange::setMsgServiceString(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, const std::string& servString ) -{ - RS_STACK_MUTEX(mGenMtx) ; - token = mDataAccess->generatePublicToken(); - - MsgLocMetaData m; - m.val.put(RsGeneralDataService::MSG_META_SERV_STRING, servString); - m.msgId = msgId; - mMsgLocMetaMap.insert(std::make_pair(token, m)); -} - -void RsGenExchange::processMsgMetaChanges() -{ - std::map metaMap; - - { - RS_STACK_MUTEX(mGenMtx); - if (mMsgLocMetaMap.empty()) - { - return; - } - metaMap = mMsgLocMetaMap; - mMsgLocMetaMap.clear(); - } - - GxsMsgReq msgIds; - - std::map::iterator mit; - for (mit = metaMap.begin(); mit != metaMap.end(); ++mit) - { - MsgLocMetaData& m = mit->second; - - int32_t value, mask; - bool ok = true; - bool changed = false; - - // for meta flag changes get flag to apply mask - if(m.val.getAsInt32(RsGeneralDataService::MSG_META_STATUS, value)) - { - ok = false; - if(m.val.getAsInt32(RsGeneralDataService::MSG_META_STATUS+GXS_MASK, mask)) - { - GxsMsgReq req; - std::set msgIdV; - msgIdV.insert(m.msgId.second); - req.insert(std::make_pair(m.msgId.first, msgIdV)); - GxsMsgMetaResult result; - mDataStore->retrieveGxsMsgMetaData(req, result); - GxsMsgMetaResult::iterator mit = result.find(m.msgId.first); - - if(mit != result.end()) - { - const auto& msgMetaV = mit->second; - - if(!msgMetaV.empty()) - { - const auto& meta = *(msgMetaV.begin()); - value = (meta->mMsgStatus & ~mask) | (mask & value); - changed = (static_cast(meta->mMsgStatus) != value); - m.val.put(RsGeneralDataService::MSG_META_STATUS, value); - ok = true; - } - } - m.val.removeKeyValue(RsGeneralDataService::MSG_META_STATUS+GXS_MASK); - } - } - - ok &= mDataStore->updateMessageMetaData(m) == 1; - uint32_t token = mit->first; - - if(ok) - { - mDataAccess->updatePublicRequestStatus(token, RsTokenService::COMPLETE); - if (changed) - { - msgIds[m.msgId.first].insert(m.msgId.second); - } - } - else - { - mDataAccess->updatePublicRequestStatus(token, RsTokenService::FAILED); - } - - { - RS_STACK_MUTEX(mGenMtx); - mMsgNotify.insert(std::make_pair(token, m.msgId)); - } - } - - if (!msgIds.empty()) - { - RS_STACK_MUTEX(mGenMtx); - - for(auto it(msgIds.begin());it!=msgIds.end();++it) - for(auto& msg_id:it->second) - mNotifications.push_back(new RsGxsMsgChange(RsGxsNotify::TYPE_PROCESSED, it->first, msg_id, false)); - } -} - -void RsGenExchange::processGrpMetaChanges() -{ - std::map metaMap; - - { - RS_STACK_MUTEX(mGenMtx); - if (mGrpLocMetaMap.empty()) - { - return; - } - metaMap = mGrpLocMetaMap; - mGrpLocMetaMap.clear(); - } - - std::list grpChanged; - - std::map::iterator mit; - for (mit = metaMap.begin(); mit != metaMap.end(); ++mit) - { - GrpLocMetaData& g = mit->second; - uint32_t token = mit->first; - -#ifdef GEN_EXCH_DEBUG - RsDbg() << " Processing GrpMetaChange for token " << token << std::endl; -#endif - // process mask - bool ok = processGrpMask(g.grpId, g.val); - - ok = ok && (mDataStore->updateGroupMetaData(g) == 1); - - if(ok) - { - mDataAccess->updatePublicRequestStatus(token, RsTokenService::COMPLETE); - grpChanged.push_back(g.grpId); - } - else - { - mDataAccess->updatePublicRequestStatus(token, RsTokenService::FAILED); - } - - { - RS_STACK_MUTEX(mGenMtx); - mGrpNotify.insert(std::make_pair(token, g.grpId)); -#ifdef GEN_EXCH_DEBUG - RsDbg() << " Processing GrpMetaChange Adding token " << token << " to mGrpNotify" << std::endl; -#endif - } - } - - for(auto& groupId:grpChanged) - { - RS_STACK_MUTEX(mGenMtx); - - mNotifications.push_back(new RsGxsGroupChange(RsGxsNotify::TYPE_PROCESSED,groupId, true)); - } -} - -bool RsGenExchange::processGrpMask(const RsGxsGroupId& grpId, ContentValue &grpCv) -{ - // first find out which mask is involved - int32_t value, mask, currValue; - std::string key; - std::shared_ptr grpMeta; - bool ok = false; - - RsGxsGrpMetaTemporaryMap grpMetaMap; - grpMetaMap[grpId] = std::make_shared(); - - mDataStore->retrieveGxsGrpMetaData(grpMetaMap); - auto mit = grpMetaMap.find(grpId); - - if(mit != grpMetaMap.end()) - { - grpMeta = mit->second; - - if (!grpMeta) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::processGrpMask() Ignore update for not existing grp id " << grpId.toStdString(); - std::cerr << std::endl; -#endif - return false; - } - ok = true; - } - - if(grpCv.getAsInt32(RsGeneralDataService::GRP_META_STATUS, value) && grpMeta) - { - key = RsGeneralDataService::GRP_META_STATUS; - currValue = grpMeta->mGroupStatus; - } - else if(grpCv.getAsInt32(RsGeneralDataService::GRP_META_SUBSCRIBE_FLAG, value) && grpMeta) - { - key = RsGeneralDataService::GRP_META_SUBSCRIBE_FLAG; - currValue = grpMeta->mSubscribeFlags; - } - else - return !(grpCv.empty()); - - ok &= grpCv.getAsInt32(key+GXS_MASK, mask); - - // remove mask entry so it doesn't affect actual entry - grpCv.removeKeyValue(key+GXS_MASK); - - // apply mask to current value - value = (currValue & ~mask) | (value & mask); - - grpCv.put(key, value); - - return ok; -} - -void RsGenExchange::publishMsgs() -{ - bool atLeastOneMessageCreatedSuccessfully = false; - - RS_STACK_MUTEX(mGenMtx); - - rstime_t now = time(NULL); - - // stick back msgs pending signature - typedef std::map > PendSignMap; - - PendSignMap::iterator sign_it = mMsgPendingSign.begin(); - - for(; sign_it != mMsgPendingSign.end(); ++sign_it) - { - GxsPendingItem& item = sign_it->second; - mMsgsToPublish.insert(std::make_pair(sign_it->first, item.mItem)); - } - - std::map > msgChangeMap; - std::map::iterator mit = mMsgsToPublish.begin(); - - for(; mit != mMsgsToPublish.end(); ++mit) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::publishMsgs() Publishing a Message"; - std::cerr << std::endl; -#endif - - RsGxsMsgItem* msgItem = mit->second; - uint32_t token = mit->first; - - uint32_t size = mSerialiser->size(msgItem); - - if(size > RsSerialiser::MAX_SERIAL_SIZE) - { - std::cerr << "Trying to publish a GXS message larger than the accepted maximal size of " << RsSerialiser::MAX_SERIAL_SIZE << " bytes. This is a bug." << std::endl; - mDataAccess->updatePublicRequestStatus(token, RsTokenService::FAILED); - delete msgItem; - - continue; - } - RsTemporaryMemory mData(size); - - // for fatal sign creation - bool createOk = false; - - // if sign requests to try later - bool tryLater = false; - - bool serialOk = mSerialiser->serialise(msgItem, mData, &size); - - if(serialOk) - { - RsNxsMsg* msg = new RsNxsMsg(mServType); - msg->grpId = msgItem->meta.mGroupId; - - msg->msg.setBinData(mData, size); - - // now create meta - msg->metaData = new RsGxsMsgMetaData(); - *(msg->metaData) = msgItem->meta; - - // assign time stamp - msg->metaData->mPublishTs = time(NULL); - - // now intialise msg (sign it) - uint8_t createReturn = createMessage(msg); - - if(createReturn == CREATE_FAIL) - { - createOk = false; - } - else if(createReturn == CREATE_FAIL_TRY_LATER) - { - PendSignMap::iterator pit = mMsgPendingSign.find(token); - tryLater = true; - - // add to queue of messages waiting for a successful - // sign attempt - if(pit == mMsgPendingSign.end()) - { - GxsPendingItem gsi(msgItem, token,time(NULL)); - mMsgPendingSign.insert(std::make_pair(token, gsi)); - } - else - { - // remove from attempts queue if over sign - // attempts limit - if(pit->second.mFirstTryTS + SIGN_MAX_WAITING_TIME < now) - { - std::cerr << "Pending signature grp=" << pit->second.mItem->meta.mGroupId << ", msg=" << pit->second.mItem->meta.mMsgId << ", has exceeded validation time limit. The author's key can probably not be obtained. This is unexpected." << std::endl; - - mMsgPendingSign.erase(token); - tryLater = false; - } - } - - createOk = false; - } - else if(createReturn == CREATE_SUCCESS) - { - createOk = true; - - // erase from queue if it exists - mMsgPendingSign.erase(token); - } - else // unknown return, just fail - createOk = false; - - - - RsGxsMessageId msgId; - RsGxsGroupId grpId = msgItem->meta.mGroupId; - - bool validSize = false; - - // check message not over single msg storage limit - if(createOk) - validSize = mDataStore->validSize(msg); - - if(createOk && validSize) - { - // empty orig msg id means this is the original - // msg. - // (csoler) Why are we doing this??? - - if(msg->metaData->mOrigMsgId.isNull()) - { - msg->metaData->mOrigMsgId = msg->metaData->mMsgId; - } - - // now serialise meta data - size = msg->metaData->serial_size(); - - { - RsTemporaryMemory metaDataBuff(size); - - bool s = msg->metaData->serialise(metaDataBuff, &size); - s &= msg->meta.setBinData(metaDataBuff, size); - if (!s) - std::cerr << "(WW) Can't serialise or set bin data" << std::endl; - } - - msg->metaData->mMsgStatus = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - msgId = msg->msgId; - grpId = msg->grpId; - msg->metaData->recvTS = time(NULL); - - // FIXTESTS global variable rsPeers not available in unittests! - - if(rsPeers) - mRoutingClues[msg->metaData->mAuthorId].insert(rsPeers->getOwnId()) ; - - computeHash(msg->msg, msg->metaData->mHash); // (csoler) weird choice: hash should also depend on metadata. Fortunately, msg signature - // signs the holw thing (msg + meta) - - mPublishedMsgs[token] = *msg->metaData; - - RsGxsMsgItem *msg_item = dynamic_cast(mSerialiser->deserialise(msg->msg.bin_data,&msg->msg.bin_len)) ; - - if(!msg_item) - { - delete msg; - mDataAccess->updatePublicRequestStatus(mit->first, RsTokenService::FAILED); - - std::cerr << "RsGenExchange::publishMsgs() failed to publish msg, probably because of data size limits. bin_len=" << msg->msg.bin_len << std::endl; - continue; // next mit - } - msg_item->meta = *msg->metaData; - - mDataAccess->addMsgData(msg); // msg is deleted by addMsgData() - - msgChangeMap[grpId].push_back(msg_item); - - if(mNetService != NULL) - mNetService->stampMsgServerUpdateTS(grpId) ; - - // add to published to allow acknowledgement - mMsgNotify.insert(std::make_pair(mit->first, std::make_pair(grpId, msgId))); - mDataAccess->updatePublicRequestStatus(mit->first, RsTokenService::COMPLETE); - - atLeastOneMessageCreatedSuccessfully = true; - } - else - { - // delete msg if create msg not ok - delete msg; - - if(!tryLater) - mDataAccess->updatePublicRequestStatus(mit->first, RsTokenService::FAILED); - - std::cerr << "RsGenExchange::publishMsgs() failed to publish msg " << std::endl; - } - } - else - { - std::cerr << "RsGenExchange::publishMsgs() failed to serialise msg " << std::endl; - } - - if(!tryLater) - delete msgItem; - } - - // clear msg item map as we're done publishing them and all - // entries are invalid - mMsgsToPublish.clear(); - - for(auto it(msgChangeMap.begin());it!=msgChangeMap.end();++it) - for(auto& msg_item: it->second) - { - RsGxsMsgChange* ch = new RsGxsMsgChange(RsGxsNotify::TYPE_PUBLISHED,msg_item->meta.mGroupId, msg_item->meta.mMsgId, false); - ch->mNewMsgItem = msg_item; - - mNotifications.push_back(ch); - } - - if(atLeastOneMessageCreatedSuccessfully) mNetService->requestPull(); -} - -RsGenExchange::ServiceCreate_Return RsGenExchange::service_CreateGroup(RsGxsGrpItem* /* grpItem */, - RsTlvSecurityKeySet& /* keySet */) -{ -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::service_CreateGroup(): Does nothing" - << std::endl; -#endif - return SERVICE_CREATE_SUCCESS; -} - - -#define PENDING_SIGN_TIMEOUT 10 // 5 seconds - - -void RsGenExchange::processGroupUpdatePublish() -{ - RS_STACK_MUTEX(mGenMtx) ; - - // get keys for group update publish - - // first build meta request map for groups to be updated - RsGxsGrpMetaTemporaryMap grpMeta; - - for(auto vit = mGroupUpdatePublish.begin(); vit != mGroupUpdatePublish.end(); ++vit) - { - GroupUpdatePublish& gup = *vit; - const RsGxsGroupId& groupId = gup.grpItem->meta.mGroupId; - grpMeta.insert(std::make_pair(groupId, std::make_shared())); - } - - if(grpMeta.empty()) - return; - - mDataStore->retrieveGxsGrpMetaData(grpMeta); - - // now - for(auto vit = mGroupUpdatePublish.begin(); vit != mGroupUpdatePublish.end(); ++vit) - { - GroupUpdatePublish& gup = *vit; - const RsGxsGroupId& groupId = gup.grpItem->meta.mGroupId; - auto mit = grpMeta.find(groupId); - - std::shared_ptr meta; - - if(mit == grpMeta.end() || mit->second == nullptr) - { - std::cerr << "Error! could not find meta of old group to update!" << std::endl; - mDataAccess->updatePublicRequestStatus(gup.mToken, RsTokenService::FAILED); - delete gup.grpItem; - continue; - } - else - meta = mit->second; - - //gup.grpItem->meta = *meta; - GxsGrpPendingSign ggps(gup.grpItem, gup.mToken); - - if(checkKeys(meta->keys)) - { - ggps.mKeys = meta->keys; - - GxsSecurity::createPublicKeysFromPrivateKeys(ggps.mKeys) ; - - ggps.mHaveKeys = true; - ggps.mStartTS = time(NULL); - ggps.mLastAttemptTS = 0; - ggps.mIsUpdate = true; - ggps.mToken = gup.mToken; - mGrpsToPublish.push_back(ggps); - } - else - { - std::cerr << "(EE) publish group fails because RS cannot find the private publish and author keys" << std::endl; - - delete gup.grpItem; - mDataAccess->updatePublicRequestStatus(gup.mToken, RsTokenService::FAILED); - } - } - - mGroupUpdatePublish.clear(); -} - - -void RsGenExchange::processRoutingClues() -{ - RS_STACK_MUTEX(mGenMtx) ; - - for(std::map >::const_iterator it = mRoutingClues.begin();it!=mRoutingClues.end();++it) - for(std::set::const_iterator it2(it->second.begin());it2!=it->second.end();++it2) - rsGRouter->addRoutingClue(GRouterKeyId(it->first),(*it2) ) ; - - mRoutingClues.clear() ; -} - -void RsGenExchange::processGroupDelete() -{ - RS_STACK_MUTEX(mGenMtx); - - // get keys for group delete publish - typedef std::pair GrpNote; - std::map toNotify; - - for( auto vit = mGroupDeletePublish.begin();vit != mGroupDeletePublish.end(); ++vit) - { - std::vector gprIds; - gprIds.push_back(vit->mGroupId); - mDataStore->removeGroups(gprIds); - toNotify.insert(std::make_pair( vit->mToken, GrpNote(true, vit->mGroupId))); - } - - std::list grpDeleted; - for(auto mit=toNotify.begin(); mit != toNotify.end(); ++mit) - { - GrpNote& note = mit->second; - RsTokenService::GxsRequestStatus status = - note.first ? RsTokenService::COMPLETE - : RsTokenService::FAILED; - - mDataAccess->updatePublicRequestStatus(mit->first, status); - mDataAccess->disposeOfPublicToken(mit->first); - - if(note.first) - grpDeleted.push_back(note.second); - } - - for(auto& groupId:grpDeleted) - { - RsGxsGroupChange* gc = new RsGxsGroupChange(RsGxsNotify::TYPE_GROUP_DELETED, groupId,false); - mNotifications.push_back(gc); - } - - mGroupDeletePublish.clear(); -} - -void RsGenExchange::processMessageDelete() -{ - RS_STACK_MUTEX(mGenMtx) ; - - struct MsgNote { - MsgNote(bool s,const GxsMsgReq& mid) : state(s),msgIds(mid){} - - bool state; - GxsMsgReq msgIds; - }; - std::map toNotify; - - for( auto vit = mMsgDeletePublish.begin(); vit != mMsgDeletePublish.end(); ++vit) - { - uint32_t token = (*vit).mToken; - bool res = mDataStore->removeMsgs( (*vit).mMsgs ); - -#ifdef GEN_EXCH_DEBUG - for(auto mit: (*vit).mMsgs) - { - std::cerr << "Attempt to delete messages: token=" << token << std::endl; - for(const auto& msg:mit.second) - std::cerr << " grpId=" << mit.first << ", msgId=" << msg << std::endl; - std::cerr << " Result: " << res << std::endl; - } -#endif - toNotify.insert(std::make_pair(token, MsgNote(res,(*vit).mMsgs))); - } - - std::list msgDeleted; - - for(auto mit = toNotify.begin(); mit != toNotify.end(); ++mit) - { - MsgNote& note = mit->second; - RsTokenService::GxsRequestStatus status = - note.state ? RsTokenService::COMPLETE - : RsTokenService::FAILED; - - mDataAccess->updatePublicRequestStatus(mit->first, status); - mDataAccess->disposeOfPublicToken(mit->first); - - if(note.state) - msgDeleted.push_back(note.msgIds); - } - - /* Three nested for looks like a performance bomb, but as Cyril says here - * https://github.com/RetroShare/RetroShare/pull/2218#pullrequestreview-565194022 - * this should actually not explode at all because it is just one message at - * time that get notified */ - for(const auto& msd : mMsgDeletePublish) - for(auto& msgMap : msd.mMsgs) - for(auto& msgId : msgMap.second) - mNotifications.push_back( - new RsGxsMsgDeletedChange(msgMap.first, msgId) ); - - mMsgDeletePublish.clear(); -} - -bool RsGenExchange::checkKeys(const RsTlvSecurityKeySet& keySet) -{ - - typedef std::map keyMap; - const keyMap& allKeys = keySet.private_keys; - keyMap::const_iterator cit = allKeys.begin(); - - bool adminFound = false, publishFound = false; - for(; cit != allKeys.end(); ++cit) - { - const RsTlvPrivateRSAKey& key = cit->second; - if(key.keyFlags & RSTLV_KEY_TYPE_FULL) // this one is not useful. Just a security. - { - if(key.keyFlags & RSTLV_KEY_DISTRIB_ADMIN) - adminFound = true; - - if(key.keyFlags & RSTLV_KEY_DISTRIB_PUBLISH) - publishFound = true; - - } - else if(key.keyFlags & RSTLV_KEY_TYPE_PUBLIC_ONLY) // this one is not useful. Just a security. - { - std::cerr << "(EE) found a public only key in the private key list" << std::endl; - return false ; - } - } - - // user must have both private and public parts of publish and admin keys - return adminFound && publishFound; -} - -void RsGenExchange::publishGrps() -{ - bool atLeastOneGroupCreatedSuccessfully = false; - std::list groups_to_subscribe; - - { - RS_STACK_MUTEX(mGenMtx) ; - NxsGrpSignPendVect::iterator vit = mGrpsToPublish.begin(); - - typedef struct _GrpNote { - - _GrpNote(bool success,bool is_update,const RsGxsGroupId& gid) : mSuccess(success),mIsUpdate(is_update),mGroupId(gid){} - - bool mSuccess; - bool mIsUpdate; - RsGxsGroupId mGroupId; - - } GrpNote; - - std::map toNotify; // used to notify about token processing if success or fails because of timeout - - while( vit != mGrpsToPublish.end() ) - { - GxsGrpPendingSign& ggps = *vit; - - /* do intial checks to see if this entry has expired */ - rstime_t now = time(NULL) ; - uint32_t token = ggps.mToken; - - - if(now > (ggps.mStartTS + PENDING_SIGN_TIMEOUT) ) - { - // timed out - toNotify.insert(std::make_pair( token, GrpNote(false,ggps.mIsUpdate, RsGxsGroupId()))); - delete ggps.mItem; - vit = mGrpsToPublish.erase(vit); - - continue; - } - - RsGxsGroupId grpId; - RsNxsGrp* grp = new RsNxsGrp(mServType); - RsGxsGrpItem* grpItem = ggps.mItem; - - RsTlvSecurityKeySet fullKeySet; - - if(!(ggps.mHaveKeys)) - { - generateGroupKeys(fullKeySet, true); - ggps.mHaveKeys = true; - ggps.mKeys = fullKeySet; - } - else - { - // We should just merge the keys instead of overwriting them, because the update may not contain private parts. - - fullKeySet = ggps.mKeys; - } - - // find private admin key - RsTlvPrivateRSAKey privAdminKey; - bool privKeyFound = false; - for(std::map::iterator mit_keys = fullKeySet.private_keys.begin(); mit_keys != fullKeySet.private_keys.end(); ++mit_keys) - { - RsTlvPrivateRSAKey& key = mit_keys->second; - - if(key.keyFlags == (RSTLV_KEY_DISTRIB_ADMIN | RSTLV_KEY_TYPE_FULL)) - { - privAdminKey = key; - privKeyFound = true; - } - } - - uint8_t create = CREATE_FAIL; - - if(privKeyFound) - { - // get group id from private admin key id - grpItem->meta.mGroupId = grp->grpId = RsGxsGroupId(privAdminKey.keyId); - - ServiceCreate_Return ret = service_CreateGroup(grpItem, fullKeySet); - - bool serialOk = false, servCreateOk; - - if(ret == SERVICE_CREATE_SUCCESS) - { - uint32_t size = mSerialiser->size(grpItem); - char *gData = new char[size]; - serialOk = mSerialiser->serialise(grpItem, gData, &size); - grp->grp.setBinData(gData, size); - delete[] gData; - servCreateOk = true; - - }else - { - servCreateOk = false; - } - - if(serialOk && servCreateOk) - { - grp->metaData = new RsGxsGrpMetaData(); - grpItem->meta.mPublishTs = time(NULL); - *(grp->metaData) = grpItem->meta; - - // TODO: change when publish key optimisation added (public groups don't have publish key - grp->metaData->mSubscribeFlags = GXS_SERV::GROUP_SUBSCRIBE_ADMIN | GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED - | GXS_SERV::GROUP_SUBSCRIBE_PUBLISH; - - create = createGroup(grp, fullKeySet); - -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::publishGrps() "; - std::cerr << " GrpId: " << grp->grpId; - std::cerr << " CircleType: " << (uint32_t) grp->metaData->mCircleType; - std::cerr << " CircleId: " << grp->metaData->mCircleId.toStdString(); - std::cerr << std::endl; -#endif - - if(create == CREATE_SUCCESS) - { - // Here we need to make sure that no private keys are included. This is very important since private keys - // can be used to modify the group. Normally the private key set is whiped out by createGroup, but - - grp->metaData->keys.private_keys.clear() ; - - uint32_t mdSize = grp->metaData->serial_size(RS_GXS_GRP_META_DATA_CURRENT_API_VERSION); - - { - RsTemporaryMemory metaData(mdSize); - serialOk = grp->metaData->serialise(metaData, mdSize,RS_GXS_GRP_META_DATA_CURRENT_API_VERSION); -#warning csoler: TODO: grp->meta should be renamed grp->public_meta ! - grp->meta.setBinData(metaData, mdSize); - } - mPublishedGrps[ggps.mToken] = *grp->metaData ; // save the connexion between the token and the created metadata, without private keys - - // Place back private keys for publisher and database storage - grp->metaData->keys.private_keys = fullKeySet.private_keys; - - if(mDataStore->validSize(grp) && serialOk) - { - grpId = grp->grpId; - computeHash(grp->grp, grp->metaData->mHash); - grp->metaData->mRecvTS = time(NULL); - - // Also push in notifications. We do it here when we still have pointers on the old and new groups - - RsGxsGroupChange *c = new RsGxsGroupChange(ggps.mIsUpdate?RsGxsNotify::TYPE_UPDATED:RsGxsNotify::TYPE_PUBLISHED, grpId,false); - - c->mNewGroupItem = dynamic_cast(mSerialiser->deserialise(grp->grp.bin_data,&grp->grp.bin_len)); - c->mNewGroupItem->meta = *grp->metaData; // grp will be deleted because mDataStore will destroy it on update - - if(ggps.mIsUpdate) - { - RsNxsGrpDataTemporaryMap oldGrpDatas; - oldGrpDatas.insert(std::make_pair(grpId, (RsNxsGrp*)NULL)); - - if(mDataStore->retrieveNxsGrps(oldGrpDatas,true) && oldGrpDatas.size() == 1) - { - auto oldGrp = oldGrpDatas[grpId]; - c->mOldGroupItem = dynamic_cast(mSerialiser->deserialise(oldGrp->grp.bin_data,&oldGrp->grp.bin_len)); - c->mOldGroupItem->meta = *oldGrp->metaData; - } - } - - mNotifications.push_back(c); - - // now store (and incidently delete grp) - - if(ggps.mIsUpdate) - mDataAccess->updateGroupData(grp); - else - mDataAccess->addGroupData(grp); - - groups_to_subscribe.push_back(grpId) ; - } - else - { - create = CREATE_FAIL; - } - } - } - else if(ret == SERVICE_CREATE_FAIL_TRY_LATER) - { - // if the service is not ready yet, reset the start timestamp to give the service more time - // the service should have it's own timeout mechanism - // services should return SERVICE_CREATE_FAIL if the action timed out - // at the moment this is only important for the idservice: - // the idservice may ask the user for a password, and the user needs time - ggps.mStartTS = now; - create = CREATE_FAIL_TRY_LATER; - } - else if(ret == SERVICE_CREATE_FAIL) - create = CREATE_FAIL; - } - else - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::publishGrps() Could not find private publish keys " << std::endl; -#endif - create = CREATE_FAIL; - } - - if(create == CREATE_FAIL) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::publishGrps() failed to publish grp " << std::endl; -#endif - delete grp; - delete grpItem; - vit = mGrpsToPublish.erase(vit); - toNotify.insert(std::make_pair(token, GrpNote(false, ggps.mIsUpdate,grpId))); - - } - else if(create == CREATE_FAIL_TRY_LATER) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::publishGrps() failed grp, trying again " << std::endl; -#endif - delete grp; - ggps.mLastAttemptTS = time(NULL); - ++vit; - } - else if(create == CREATE_SUCCESS) - { - delete grpItem; - vit = mGrpsToPublish.erase(vit); - -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::publishGrps() ok -> pushing to notifies" - << std::endl; -#endif - - // add to published to allow acknowledgement - toNotify.insert(std::make_pair(token, GrpNote(true,ggps.mIsUpdate,grpId))); - - atLeastOneGroupCreatedSuccessfully = true; - } - } - - // toNotify contains the token and the group update/creation info. We parse it to - // - notify that group creation/update for a specific token was - - for(auto mit=toNotify.begin(); mit != toNotify.end(); ++mit) - { - GrpNote& note = mit->second; - RsTokenService::GxsRequestStatus status = note.mSuccess ? RsTokenService::COMPLETE : RsTokenService::FAILED; - - mGrpNotify.insert(std::make_pair(mit->first, note.mGroupId)); // always notify - mDataAccess->updatePublicRequestStatus(mit->first, status); // update the token request with the given status - } - } - - // This is done off-mutex to avoid possible cross deadlocks with the net service. - - if(mNetService != nullptr) - { - for(auto& grpId : std::as_const(groups_to_subscribe)) - mNetService->subscribeStatusChanged(grpId, true); - - if(atLeastOneGroupCreatedSuccessfully) - mNetService->requestPull(); - } -} - -uint32_t RsGenExchange::generatePublicToken() -{ - uint32_t token = mDataAccess->generatePublicToken(); -#ifdef GEN_EXCH_DEBUG - std::cerr << "New token generated: " << token << " in RsGenExchange::generatePublicToken()" << std::endl; -#endif - return token; -} - -bool RsGenExchange::updatePublicRequestStatus( - uint32_t token, RsTokenService::GxsRequestStatus status ) -{ - return mDataAccess->updatePublicRequestStatus(token, status); -} - -bool RsGenExchange::disposeOfPublicToken(const uint32_t &token) -{ - return mDataAccess->disposeOfPublicToken(token); -} - -RsGeneralDataService* RsGenExchange::getDataStore() -{ - return mDataStore; -} - -bool RsGenExchange::getGroupKeys(const RsGxsGroupId &grpId, RsTlvSecurityKeySet &keySet) -{ - if(grpId.isNull()) - return false; - - RS_STACK_MUTEX(mGenMtx) ; - - RsGxsGrpMetaTemporaryMap grpMeta; - grpMeta[grpId] = std::make_shared(); - mDataStore->retrieveGxsGrpMetaData(grpMeta); - - if(grpMeta.empty()) - return false; - - const auto& meta = grpMeta[grpId]; - - if(meta == NULL) - return false; - - keySet = meta->keys; - GxsSecurity::createPublicKeysFromPrivateKeys(keySet) ; - - return true; -} - -void RsGenExchange::shareGroupPublishKey(const RsGxsGroupId& grpId,const std::set& peers) -{ - if(grpId.isNull()) - return ; - - mNetService->sharePublishKey(grpId,peers) ; -} - -void RsGenExchange::processRecvdData() -{ - processRecvdGroups(); - - processRecvdMessages(); - - performUpdateValidation(); - -} - - -void RsGenExchange::computeHash(const RsTlvBinaryData& data, RsFileHash& hash) -{ - pqihash pHash; - pHash.addData(data.bin_data, data.bin_len); - pHash.Complete(hash); -} - -void RsGenExchange::processRecvdMessages() -{ - std::list messages_to_reject ; - - { - RS_STACK_MUTEX(mGenMtx) ; - - rstime_t now = time(NULL); - - if(mMsgPendingValidate.empty()) - return ; -#ifdef GEN_EXCH_DEBUG - else - std::cerr << "processing received messages" << std::endl; -#endif - // 1 - First, make sure items metadata is deserialised, clean old failed items, and collect the groups Ids we have to check - - RsGxsGrpMetaTemporaryMap grpMetas; - - for(NxsMsgPendingVect::iterator pend_it = mMsgPendingValidate.begin();pend_it != mMsgPendingValidate.end();) - { - GxsPendingItem& gpsi = pend_it->second; - RsNxsMsg *msg = gpsi.mItem ; - - if(msg->metaData == NULL) - { - RsGxsMsgMetaData* meta = new RsGxsMsgMetaData(); - - if(msg->meta.bin_len != 0 && meta->deserialise(msg->meta.bin_data, &(msg->meta.bin_len))) - msg->metaData = meta; - else - delete meta; - } - - bool accept_new_msg = msg->metaData != NULL && acceptNewMessage(msg->metaData,msg->msg.bin_len); - - if(!accept_new_msg) - messages_to_reject.push_back(msg->metaData->mMsgId); // This prevents reloading the message again at next sync. - - if(!accept_new_msg || gpsi.mFirstTryTS + VALIDATE_MAX_WAITING_TIME < now) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "Pending validation grp=" << gpsi.mId.first << ", msg=" << gpsi.mId.second << ", has exceeded validation time limit. The author's key can probably not be obtained. This is unexpected." << std::endl; -#endif - - delete gpsi.mItem; - pend_it = mMsgPendingValidate.erase(pend_it); - } - else - { - grpMetas.insert(std::make_pair(pend_it->second.mItem->grpId, std::make_shared())); - ++pend_it; - } - } - - // 2 - Retrieve the metadata for the associated groups. The test is here to avoid the default behavior to - // retrieve all groups when the list is empty - - if(!grpMetas.empty()) - mDataStore->retrieveGxsGrpMetaData(grpMetas); - - GxsMsgReq msgIds; - std::list msgs_to_store; - -#ifdef GEN_EXCH_DEBUG - std::cerr << " updating received messages:" << std::endl; -#endif - - // 3 - Validate each message - - for(NxsMsgPendingVect::iterator pend_it = mMsgPendingValidate.begin();pend_it != mMsgPendingValidate.end();) - { - RsNxsMsg* msg = pend_it->second.mItem; - - // (cyril) Normally we should discard posts that are older than the sync request. But that causes a problem because - // RsGxsNetService requests posts to sync by chunks of 20. So if the 20 are discarded, they will be re-synced next time, and the sync process - // will indefinitly loop on the same 20 posts. Since the posts are there already, keeping them is the least problematique way to fix this problem. - // - // uint32_t max_sync_age = ( mNetService != NULL)?( mNetService->getSyncAge(msg->metaData->mGroupId)):RS_GXS_DEFAULT_MSG_REQ_PERIOD; - // - // if(max_sync_age != 0 && msg->metaData->mPublishTs + max_sync_age < time(NULL)) - // { - // std::cerr << "(WW) not validating message " << msg->metaData->mMsgId << " in group " << msg->metaData->mGroupId << " because it is older than synchronisation limit. This message was probably sent by a friend node that does not accept sync limits already." << std::endl; - // ok = false ; - // } - -#ifdef GEN_EXCH_DEBUG - std::cerr << " deserialised info: grp id=" << msg->grpId << ", msg id=" << msg->msgId ; -#endif - auto mit = grpMetas.find(msg->grpId); - -#ifdef GEN_EXCH_DEBUG - std::cerr << " msg info : grp id=" << msg->grpId << ", msg id=" << msg->msgId << std::endl; -#endif - // validate msg - - if(mit == grpMetas.end()) - { - std::cerr << "RsGenExchange::processRecvdMessages(): impossible situation: grp meta " << msg->grpId << " not available." << std::endl; - ++pend_it ; - continue ; - } - - const auto& grpMeta = mit->second; - RsTlvSecurityKeySet keys = grpMeta->keys ; - - GxsSecurity::createPublicKeysFromPrivateKeys(keys); // make sure we have the public keys that correspond to the private ones, as it happens. Most of the time this call does nothing. - - int validateReturn = validateMsg(msg, grpMeta->mGroupFlags, grpMeta->mSignFlags, keys); - -#ifdef GEN_EXCH_DEBUG - std::cerr << " grpMeta.mSignFlags: " << std::hex << grpMeta->mSignFlags << std::dec << std::endl; - std::cerr << " grpMeta.mAuthFlags: " << std::hex << grpMeta->mAuthenFlags << std::dec << std::endl; - std::cerr << " message validation result: " << (int)validateReturn << std::endl; -#endif - - if(validateReturn == VALIDATE_SUCCESS) - { - msg->metaData->mMsgStatus = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED | GXS_SERV::GXS_MSG_STATUS_GUI_NEW | GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; - msgs_to_store.push_back(msg); - - msgIds[msg->grpId].insert(msg->msgId); - // std::vector &msgv = msgIds[msg->grpId]; - // if (std::find(msgv.begin(), msgv.end(), msg->msgId) == msgv.end()) - // msgv.push_back(msg->msgId); - - computeHash(msg->msg, msg->metaData->mHash); - msg->metaData->recvTS = time(NULL); - -#ifdef GEN_EXCH_DEBUG - std::cerr << " new status flags: " << msg->metaData->mMsgStatus << std::endl; - std::cerr << " computed hash: " << msg->metaData->mHash << std::endl; - std::cerr << "Message received. Identity=" << msg->metaData->mAuthorId << ", from peer " << msg->PeerId() << std::endl; -#endif - - if(!msg->metaData->mAuthorId.isNull()) - mRoutingClues[msg->metaData->mAuthorId].insert(msg->PeerId()) ; - } - else if(validateReturn == VALIDATE_FAIL) - { - // In this case, we notify the network exchange service not to DL the message again, at least not yet. - -#ifdef GEN_EXCH_DEBUG - std::cerr << "Validation failed for message id " - << "msg->grpId: " << msg->grpId << ", msgId: " << msg->msgId << std::endl; -#endif - messages_to_reject.push_back(msg->msgId) ; - delete msg ; - } - else if(validateReturn == VALIDATE_FAIL_TRY_LATER) - { - ++pend_it ; - continue; - } - - // Remove the entry from mMsgPendingValidate, but do not delete msg since it's either pushed into msg_to_store or deleted in the FAIL case! - - NxsMsgPendingVect::iterator tmp = pend_it ; - ++tmp ; - mMsgPendingValidate.erase(pend_it) ; - pend_it = tmp ; - } - - if(!msgIds.empty()) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << " removing existing and old messages from incoming list." << std::endl; -#endif - removeDeleteExistingMessages(msgs_to_store, msgIds); - -#ifdef GEN_EXCH_DEBUG - std::cerr << " storing remaining messages" << std::endl; -#endif - - for(auto& nxs_msg: msgs_to_store) - { - RsGxsMsgItem *item = dynamic_cast(mSerialiser->deserialise(nxs_msg->msg.bin_data,&nxs_msg->msg.bin_len)); - - if(!item) - continue; - - item->meta = *nxs_msg->metaData; - - RsGxsMsgChange* c = new RsGxsMsgChange(RsGxsNotify::TYPE_RECEIVED_NEW, item->meta.mGroupId, item->meta.mMsgId,false); - c->mNewMsgItem = item; - - mNotifications.push_back(c); - } - - mDataStore->storeMessage(msgs_to_store); // All items will be destroyed later on, since msgs_to_store is a temporary map - } - } - - // Done off-mutex to avoid cross deadlocks in the netservice that might call the RsGenExchange as an observer.. - - if(mNetService != NULL) - for(std::list::const_iterator it(messages_to_reject.begin());it!=messages_to_reject.end();++it) - mNetService->rejectMessage(*it) ; -} - -bool RsGenExchange::acceptNewGroup(const RsGxsGrpMetaData* /*grpMeta*/ ) { return true; } -bool RsGenExchange::acceptNewMessage(const RsGxsMsgMetaData* /*grpMeta*/,uint32_t /*size*/ ) { return true; } - -void RsGenExchange::processRecvdGroups() -{ - RS_STACK_MUTEX(mGenMtx) ; - - if(mGrpPendingValidate.empty()) - return; - -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::Processing received groups" << std::endl; -#endif - std::list grpIds; - std::list grps_to_store; - - // 1 - retrieve the existing groups so as to check what's not new - std::vector existingGrpIds; - mDataStore->retrieveGroupIds(existingGrpIds); - - // 2 - go through each and every new group data and validate the signatures. - - for(NxsGrpPendValidVect::iterator vit = mGrpPendingValidate.begin(); vit != mGrpPendingValidate.end();) - { - GxsPendingItem& gpsi = vit->second; - RsNxsGrp* grp = gpsi.mItem; - - if(grp->metaData == NULL) - { - RsGxsGrpMetaData* meta = new RsGxsGrpMetaData(); - - if(grp->meta.bin_len != 0 && meta->deserialise(grp->meta.bin_data, grp->meta.bin_len)) - grp->metaData = meta ; - else - delete meta ; - } -#ifdef GEN_EXCH_DEBUG - std::cerr << " processing validation for group " << grp->metaData->mGroupId << ", original attempt time: " << time(NULL) - gpsi.mFirstTryTS << " seconds ago" << std::endl; -#endif - - // early deletion of group from the pending list if it's malformed, not accepted, or has been tried unsuccessfully for too long - - if(grp->metaData == NULL || !acceptNewGroup(grp->metaData) || gpsi.mFirstTryTS + VALIDATE_MAX_WAITING_TIME < time(NULL)) - { - NxsGrpPendValidVect::iterator tmp(vit) ; - ++tmp ; - delete grp ; - mGrpPendingValidate.erase(vit) ; - vit = tmp ; - continue; - } - - // group signature validation - - uint8_t ret = validateGrp(grp); - - if(ret == VALIDATE_SUCCESS) - { - grp->metaData->mGroupStatus = GXS_SERV::GXS_GRP_STATUS_UNPROCESSED | GXS_SERV::GXS_GRP_STATUS_UNREAD; - - computeHash(grp->grp, grp->metaData->mHash); - - // group has been validated. Let's notify the global router for the clue - - if(!grp->metaData->mAuthorId.isNull()) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "Group routage info: Identity=" << grp->metaData->mAuthorId << " from " << grp->PeerId() << std::endl; -#endif - mRoutingClues[grp->metaData->mAuthorId].insert(grp->PeerId()) ; - } - - // This has been moved here (as opposed to inside part for new groups below) because it is used to update the server TS when updates - // of grp metadata arrive. - - grp->metaData->mRecvTS = time(NULL); - - // now check if group already exists - - if(std::find(existingGrpIds.begin(), existingGrpIds.end(), grp->grpId) == existingGrpIds.end()) - { - grp->metaData->mOriginator = grp->PeerId(); - grp->metaData->mSubscribeFlags = GXS_SERV::GROUP_SUBSCRIBE_NOT_SUBSCRIBED; - - grps_to_store.push_back(grp); - grpIds.push_back(grp->grpId); - } - else - { - GroupUpdate update; - update.newGrp = grp; - mGroupUpdates.push_back(update); - } - } - else if(ret == VALIDATE_FAIL) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << " failed to validate incoming meta, grpId: " << grp->grpId << ": wrong signature" << std::endl; -#endif - delete grp; - } - else if(ret == VALIDATE_FAIL_TRY_LATER) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << " failed to validate incoming grp, trying again later. grpId: " << grp->grpId << std::endl; -#endif - ++vit ; - continue; - } - - // Erase entry from the list - - NxsGrpPendValidVect::iterator tmp(vit) ; - ++tmp ; - mGrpPendingValidate.erase(vit) ; - vit = tmp ; - } - - if(!grps_to_store.empty()) - { - for(auto Grp:grps_to_store) - { - RsGxsGroupChange* c = new RsGxsGroupChange(RsGxsNotify::TYPE_RECEIVED_NEW, Grp->grpId, false); - - c->mNewGroupItem = dynamic_cast(mSerialiser->deserialise(Grp->grp.bin_data,&Grp->grp.bin_len)); - - mNotifications.push_back(c); - } - - mDataStore->storeGroup(grps_to_store); // deletes the data after storing it. -#ifdef GEN_EXCH_DEBUG - std::cerr << " adding the following grp ids to notification: " << std::endl; - for(std::list::const_iterator it(grpIds.begin());it!=grpIds.end();++it) - std::cerr << " " << *it << std::endl; -#endif - } -} - -void RsGenExchange::performUpdateValidation() -{ - RS_STACK_MUTEX(mGenMtx) ; - - if(mGroupUpdates.empty()) - return; - -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::performUpdateValidation() " << std::endl; -#endif - - RsNxsGrpDataTemporaryMap grpDatas; - - for(auto vit(mGroupUpdates.begin()); vit != mGroupUpdates.end(); ++vit) - grpDatas.insert(std::make_pair(vit->newGrp->grpId, (RsNxsGrp*)NULL)); - - if(grpDatas.empty() || !mDataStore->retrieveNxsGrps(grpDatas,true)) - { - if(grpDatas.empty()) - RsErr() << __PRETTY_FUNCTION__ << " Validation of multiple group updates failed: no group in list!" << std::endl; - else - RsErr() << __PRETTY_FUNCTION__ << " Validation of multiple group updates failed: cannot retrieve froup data for these groups!" << std::endl; - - return; - } - -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::performUpdateValidation() " << std::endl; -#endif - std::list grps; // dont use RsNxsGrpDataTemporaryList because updateGrps will delete the groups - - for(auto vit(mGroupUpdates.begin()); vit != mGroupUpdates.end(); ++vit) - { - GroupUpdate& gu = *vit; - - auto mit = grpDatas.find(gu.newGrp->grpId); - - if(mit == grpDatas.end()) - { - RsErr() << __PRETTY_FUNCTION__ << " Validation of group update failed for group " << gu.newGrp->grpId << " because previous grp version cannot be found." << std::endl; - continue; - } - RsGxsGrpMetaData *oldGrpMeta(mit->second->metaData); - RsNxsGrp *oldGrp(mit->second); - - if(updateValid(*oldGrpMeta, *gu.newGrp)) - { - if(gu.newGrp->metaData->mCircleType == GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY) - gu.newGrp->metaData->mOriginator = gu.newGrp->PeerId(); - - // Keep subscriptionflag to what it was. This avoids clearing off the flag when updates to group meta information - // is received. - - gu.newGrp->metaData->mSubscribeFlags = oldGrpMeta->mSubscribeFlags ; - - // Also keep private keys if present - - if(!gu.newGrp->metaData->keys.private_keys.empty()) - std::cerr << "(EE) performUpdateValidation() group " <metaData->mGroupId << " has been received with private keys. This is very unexpected!" << std::endl; - else - gu.newGrp->metaData->keys.private_keys = oldGrpMeta->keys.private_keys ; - - // Now prepare notification of the client - - RsGxsGroupChange *c = new RsGxsGroupChange(RsGxsNotify::TYPE_UPDATED,gu.newGrp->metaData->mGroupId,false); - - c->mNewGroupItem = dynamic_cast(mSerialiser->deserialise(gu.newGrp->grp.bin_data,&gu.newGrp->grp.bin_len)); - c->mNewGroupItem->meta = *gu.newGrp->metaData; // gu.newGrp will be deleted because mDataStore will destroy it on update - - c->mOldGroupItem = dynamic_cast(mSerialiser->deserialise(oldGrp->grp.bin_data,&oldGrp->grp.bin_len)); - c->mOldGroupItem->meta = *oldGrpMeta; // no need to delete mit->second, as it will be deleted automatically in the temporary map - - mNotifications.push_back(c); - - // finally, add the group to the list to send to mDataStore - - grps.push_back(gu.newGrp); - } - else - { - delete gu.newGrp; // delete here because mDataStore will not take care of this one. no need to delete mit->second, as it will be deleted automatically in the temporary map - gu.newGrp = NULL ; - } - } - - mDataStore->updateGroup(grps); - -#ifdef GEN_EXCH_DEBUG - std::cerr << " adding the following grp ids to notification: " << std::endl; -#endif - - // cleanup - - mGroupUpdates.clear(); -} - -bool RsGenExchange::updateValid(const RsGxsGrpMetaData& oldGrpMeta, const RsNxsGrp& newGrp) const -{ - std::map& signSet = newGrp.metaData->signSet.keySignSet; - std::map::iterator mit = signSet.find(INDEX_AUTHEN_ADMIN); - - if(mit == signSet.end()) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::updateValid() new admin sign not found! " << std::endl; - std::cerr << "RsGenExchange::updateValid() grpId: " << oldGrpMeta.mGroupId << std::endl; -#endif - - return false; - } - - RsTlvKeySignature adminSign = mit->second; - RsTlvSecurityKeySet old_keys = oldGrpMeta.keys ; - - GxsSecurity::createPublicKeysFromPrivateKeys(old_keys); // make sure we have the public keys that correspond to the private ones, as it happens. Most of the time this call does nothing. - - std::map& keys = old_keys.public_keys; - std::map::iterator keyMit = keys.find(RsGxsId(oldGrpMeta.mGroupId)); - - if(keyMit == keys.end()) - { -#ifdef GEN_EXCH_DEBUG - std::cerr << "RsGenExchange::updateValid() admin key not found! " << std::endl; -#endif - return false; - } - - // also check this is the latest published group - bool latest = newGrp.metaData->mPublishTs > oldGrpMeta.mPublishTs; - - mGixs->timeStampKey(newGrp.metaData->mAuthorId, RsIdentityUsage(RsServiceType(mServType),RsIdentityUsage::GROUP_ADMIN_SIGNATURE_CREATION, oldGrpMeta.mGroupId)) ; - - return GxsSecurity::validateNxsGrp(newGrp, adminSign, keyMit->second) && latest; -} - -void RsGenExchange::setGroupReputationCutOff(uint32_t& token, const RsGxsGroupId& grpId, int CutOff) -{ - RS_STACK_MUTEX(mGenMtx) ; - token = mDataAccess->generatePublicToken(); - - GrpLocMetaData g; - g.grpId = grpId; - g.val.put(RsGeneralDataService::GRP_META_CUTOFF_LEVEL, (int32_t)CutOff); - mGrpLocMetaMap.insert(std::make_pair(token, g)); -} - -void RsGenExchange::removeDeleteExistingMessages( std::list& msgs, GxsMsgReq& msgIdsNotify) -{ - // first get grp ids of messages to be stored - - RsGxsGroupId::std_set mGrpIdsUnique; - - for(std::list::const_iterator cit = msgs.begin(); cit != msgs.end(); ++cit) - mGrpIdsUnique.insert((*cit)->metaData->mGroupId); - - //RsGxsGroupId::std_list grpIds(mGrpIdsUnique.begin(), mGrpIdsUnique.end()); - //RsGxsGroupId::std_list::const_iterator it = grpIds.begin(); - typedef std::map MsgIdReq; - MsgIdReq msgIdReq; - - // now get a list of all msgs ids for each group - for(RsGxsGroupId::std_set::const_iterator it(mGrpIdsUnique.begin()); it != mGrpIdsUnique.end(); ++it) - { - mDataStore->retrieveMsgIds(*it, msgIdReq[*it]); - -#ifdef GEN_EXCH_DEBUG - const std::set& vec(msgIdReq[*it]) ; - std::cerr << " retrieved " << vec.size() << " message ids for group " << *it << std::endl; - - for(auto it2(vec.begin());it2!=vec.end();++it2) - std::cerr << " " << *it2 << std::endl; -#endif - } - - // now for each msg to be stored that exist in the retrieved msg/grp "index" delete and erase from map - for(std::list::iterator cit2 = msgs.begin(); cit2 != msgs.end();) - { - const RsGxsMessageId::std_set& msgIds = msgIdReq[(*cit2)->metaData->mGroupId]; - -#ifdef GEN_EXCH_DEBUG - std::cerr << " grpid=" << (*cit2)->grpId << ", msgid=" << (*cit2)->msgId ; -#endif - - // Avoid storing messages that are already in the database, as well as messages that are too old (or generally do not pass the database storage test) - // - if(msgIds.find((*cit2)->metaData->mMsgId) != msgIds.end() || !messagePublicationTest( *(*cit2)->metaData)) - { - // msg exist in retrieved index. We should use a std::set here instead of a vector. - - RsGxsMessageId::std_set& notifyIds = msgIdsNotify[ (*cit2)->metaData->mGroupId]; - RsGxsMessageId::std_set::iterator it2 = notifyIds.find((*cit2)->metaData->mMsgId); - - if(it2 != notifyIds.end()) - { - notifyIds.erase(it2); - if (notifyIds.empty()) - { - msgIdsNotify.erase( (*cit2)->metaData->mGroupId); - } - } -#ifdef GEN_EXCH_DEBUG - std::cerr << " discarding " << (*cit2)->msgId << std::endl; -#endif - - delete *cit2; - cit2 = msgs.erase(cit2); - } - else - ++cit2; - } -} - -DistantSearchGroupStatus RsGenExchange::getDistantSearchStatus(const RsGxsGroupId& group_id) -{ - return mNetService->getDistantSearchStatus(group_id) ; -} -void RsGenExchange::turtleGroupRequest(const RsGxsGroupId& group_id) -{ - mNetService->turtleGroupRequest(group_id) ; -} -void RsGenExchange::turtleSearchRequest(const std::string& match_string) -{ - mNetService->turtleSearchRequest(match_string) ; -} - -bool RsGenExchange::localSearch( const std::string& matchString, - std::list& results ) -{ - return mNetService->search(matchString, results); -} - -bool RsGenExchange::exportGroupBase64( - std::string& radix, const RsGxsGroupId& groupId, std::string& errMsg ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - errMsg = err; - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(groupId.isNull()) return failure("groupId cannot be null"); - - // We have no blocking API here, so we need to make a blocking request manually. - const std::list groupIds({groupId}); - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - uint32_t token; - mDataAccess->requestGroupInfo( token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds); - - // provide a sync response: actually wait for the token. - std::chrono::milliseconds maxWait = std::chrono::milliseconds(10000); - std::chrono::milliseconds checkEvery = std::chrono::milliseconds(100); - - auto timeout = std::chrono::steady_clock::now() + maxWait; // wait for 10 secs at most - auto st = mDataAccess->requestStatus(token); - - while( !(st == RsTokenService::FAILED || st >= RsTokenService::COMPLETE) && std::chrono::steady_clock::now() < timeout ) - { - std::this_thread::sleep_for(checkEvery); - st = mDataAccess->requestStatus(token); - } - if(st != RsTokenService::COMPLETE) - return failure( "waitToken(...) failed with: " + std::to_string(st) ); - - uint8_t* buf = nullptr; - uint32_t size; - RsGxsGroupId grpId; - - if(!getSerializedGroupData(token, grpId, buf, size)) - return failure("failed retrieving GXS data"); - - Radix64::encode(buf, static_cast(size), radix); - free(buf); - - return true; -} - -bool RsGenExchange::importGroupBase64( - const std::string& radix, RsGxsGroupId& groupId, - std::string& errMsg ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - errMsg = err; - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(radix.empty()) return failure("radix is empty"); - - std::vector mem = Radix64::decode(radix); - if(mem.empty()) return failure("radix seems corrupted"); - - // On success this also import the group as pending validation - if(!deserializeGroupData( - mem.data(), static_cast(mem.size()), - reinterpret_cast(&groupId) )) - return failure("failed deserializing group"); - - return true; -} - -RsGxsChanges::RsGxsChanges() : - RsEvent(RsEventType::GXS_CHANGES), mServiceType(RsServiceType::NONE), - mService(nullptr) {} - -RsGxsIface::~RsGxsIface() = default; -RsGxsGroupSummary::~RsGxsGroupSummary() = default; diff --git a/libretroshare/src/gxs/rsgenexchange.h b/libretroshare/src/gxs/rsgenexchange.h deleted file mode 100644 index 1bb8bbde6..000000000 --- a/libretroshare/src/gxs/rsgenexchange.h +++ /dev/null @@ -1,1015 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgenexchange.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie, Evi-Parker Christopher * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RSGENEXCHANGE_H -#define RSGENEXCHANGE_H - -#include -#include "util/rstime.h" - -#include "rsgxs.h" -#include "rsgds.h" -#include "rsnxs.h" -#include "retroshare/rsgxsiface.h" -#include "rsgxsdataaccess.h" -#include "rsnxsobserver.h" -#include "retroshare/rsgxsservice.h" -#include "rsitems/rsnxsitems.h" -#include "gxs/rsgxsnotify.h" -#include "rsgxsutil.h" - -template -class GxsPendingItem -{ -public: - GxsPendingItem(GxsItem item, Identity id,rstime_t ts) : - mItem(item), mId(id), mFirstTryTS(ts) - {} - - bool operator==(const Identity& id) - { - return this->mId == id; - } - - GxsItem mItem; - Identity mId; - rstime_t mFirstTryTS; -}; - -class GxsGrpPendingSign -{ -public: - - GxsGrpPendingSign(RsGxsGrpItem* item, uint32_t token): mLastAttemptTS(0), mStartTS(time(NULL)), mToken(token), - mItem(item), mHaveKeys(false), mIsUpdate(false) - {} - - rstime_t mLastAttemptTS, mStartTS; - uint32_t mToken; - RsGxsGrpItem* mItem; - bool mHaveKeys; // mKeys->first == true if key present - bool mIsUpdate; - RsTlvSecurityKeySet mKeys; -}; - -typedef std::map > GxsMsgDataMap; -typedef std::map GxsGroupDataMap; -typedef std::map > GxsMsgRelatedDataMap; - -/*! - * This should form the parent class to \n - * all gxs services. This provides access to service's msg/grp data \n - * management/publishing/sync features - * - * Features: \n - * a. Data Access: \n - * Provided by handle to RsTokenService. This ensure consistency \n - * of requests and hiearchy of groups -> then messages which are \n - * sectioned by group ids. \n - * The one caveat is that redemption of tokens are done through \n - * the backend of this class \n - * b. Publishing: \n - * Methods are provided to publish msg and group items and also make \n - * changes to meta information of both item types \n - * c. Sync/Notification: \n - * Also notifications are made here on receipt of new data from \n - * connected peers - */ - -class RsGixs; - -class RsGenExchange : public RsNxsObserver, public RsTickingThread, - public RsGxsIface -{ -public: - - /// used by class derived for RsGenExchange to indicate if service create passed or not - enum ServiceCreate_Return { SERVICE_CREATE_SUCCESS, SERVICE_CREATE_FAIL, SERVICE_CREATE_FAIL_TRY_LATER } ; - - /*! - * Constructs a RsGenExchange object, the owner ship of gds, ns, and serviceserialiser passes \n - * onto the constructed object - * @param gds Data service needed to act as store of message - * @param ns Network service needed to synchronise data with rs peers - * @param serviceSerialiser The users service needs this \n - * in order for gen exchange to deal with its data types - * @param mServType This should be service type used by the serialiser - * @param gixs This is used for verification of msgs and groups received by Gen Exchange using identities. - * @param authenPolicy This determines the authentication used for verfying authorship of msgs and groups - */ - RsGenExchange( - RsGeneralDataService* gds, RsNetworkExchangeService* ns, - RsSerialType* serviceSerialiser, uint16_t mServType, RsGixs* gixs, - uint32_t authenPolicy ); - - virtual ~RsGenExchange(); - - // Convention that this is implemented here. - // and passes to network service. - virtual RsServiceInfo getServiceInfo() = 0; - - void setNetworkExchangeService(RsNetworkExchangeService *ns) ; - - /** S: Observer implementation **/ - - /*! - * @param messages messages are deleted after function returns - */ - virtual void receiveNewMessages(const std::vector &messages) override; - - /*! - * @param groups groups are deleted after function returns - */ - virtual void receiveNewGroups(const std::vector &groups) override; - - /*! - * @param grpId group id - */ - virtual void notifyReceivePublishKey(const RsGxsGroupId &grpId) override; - - virtual void notifyChangedGroupSyncParams(const RsGxsGroupId &grpId) override; - /*! - * \brief notifyReceiveDistantSearchResults - * Should be called when new search results arrive. - * \param grpId - */ - virtual void receiveDistantSearchResults(TurtleRequestId id,const RsGxsGroupId &grpId) override; - /*! - * @param grpId group id - */ - virtual void notifyChangedGroupStats(const RsGxsGroupId &grpId) override; - - /** E: Observer implementation **/ - - /*! - * This is called by Gxs service runner - * periodically, use to implement non - * blocking calls - */ - void tick(); - - /*! - * Any backgroup processing needed by - */ - virtual void service_tick() = 0; - - /*! - * - * @return handle to token service handle for making - * request to this gxs service - */ - RsTokenService* getTokenService(); - - void threadTick() override; /// @see RsTickingThread - - /*! - * Policy bit pattern portion - */ - enum PrivacyBitPos { PUBLIC_GRP_BITS, RESTRICTED_GRP_BITS, PRIVATE_GRP_BITS, GRP_OPTION_BITS } ; - - /*! - * Convenience function for setting bit patterns of the individual privacy level authentication - * policy and group options - * @param flag the bit pattern (and policy) set for the privacy policy - * @param authenFlag Only the policy portion chosen will be modified with 'flag', - * the origianl flags in the indicated bit position (pos) are over-written - * @param pos The policy bit portion to modify - * @see PrivacyBitPos - */ - static bool setAuthenPolicyFlag(const uint8_t& flag, uint32_t& authenFlag, const PrivacyBitPos& pos); - -public: - - /** data access functions **/ - - /*! - * Retrieve group list for a given token - * @param token - * @param groupIds - * @return false if token cannot be redeemed, if false you may have tried to redeem when not ready - */ - bool getGroupList(const uint32_t &token, std::list &groupIds); - - /*! - * Retrieve msg list for a given token sectioned by group Ids - * @param token token to be redeemed - * @param msgIds a map of grpId -> msgList (vector) - * @return false if could not redeem token - */ - bool getMsgList(const uint32_t &token, GxsMsgIdResult &msgIds); - - /*! - * Retrieve msg list for a given token for message related info - * @param token token to be redeemed - * @param msgIds a map of RsGxsGrpMsgIdPair -> msgList (vector) - * @return false if could not redeem token - */ - bool getMsgRelatedList(const uint32_t &token, MsgRelatedIdResult& msgIds)override; - - - /*! - * retrieve group meta data associated to a request token - * @param token - * @param groupInfo - * @return false if could not redeem token - */ - bool getGroupMeta(const uint32_t &token, std::list& groupInfo)override; - - /*! - * retrieves message meta data associated to a request token - * @param token token to be redeemed - * @param msgInfo the meta data to be retrieved for token store here - */ - bool getMsgMeta(const uint32_t &token, GxsMsgMetaMap &msgInfo)override; - - /*! - * Retrieve msg meta for a given token for message related info - * @param token token to be redeemed - * @param msgIds a map of RsGxsGrpMsgIdPair -> msgList (vector) - * @return false if could not redeem token - */ - bool getMsgRelatedMeta(const uint32_t &token, GxsMsgRelatedMetaMap& msgMeta)override; - - /*! - * Retrieves the meta data of a newly created group. The meta is kept in cache for the current session. - * \param token token that was used to create the group - * \param meta meta data for this group - * \return false if the group is not yet created. - */ - bool getPublishedGroupMeta(const uint32_t& token,RsGroupMetaData& meta); - - /*! - * Retrieves the meta data of a newly created post. The meta is kept in cache for the current session. - * \param token token that was used to create the post - * \param meta meta data for this post - * \return false if the group is not yet created. - */ - bool getPublishedMsgMeta(const uint32_t& token,RsMsgMetaData& meta); - -#ifdef TO_REMOVE - /*! - * Gxs services should call this for automatic handling of - * changes, send - * @param changes - */ - virtual void receiveChanges(std::vector& changes); -#endif - - /*! - * \brief acceptNewGroup - * Early checks if the group can be accepted. This is mainly used to check wether the group is banned for some reasons. - * Returns true unless derived in GXS services. - * - * \param grpMeta Group metadata to check - * \return - */ - virtual bool acceptNewGroup(const RsGxsGrpMetaData *grpMeta) ; - - /*! - * \brief acceptNewMessage - * Early checks if the message can be accepted. This is mainly used to check wether the group is for instance overloaded and the service wants - * to put limitations to it. - * Returns true unless derived in GXS services. - * - * \param grpMeta Group metadata to check - * \return - */ - virtual bool acceptNewMessage(const RsGxsMsgMetaData *msgMeta, uint32_t size) ; - - bool subscribeToGroup(uint32_t& token, const RsGxsGroupId& grpId, bool subscribe) override; - - /*! - * Gets service statistic for a given services - * @param token value to to retrieve requested stats - * @param stats the status - * @return true if token exists false otherwise - */ - bool getServiceStatistic(const uint32_t& token, GxsServiceStatistic& stats) override; - - /*! - * Get group statistic - * @param token to be redeemed - * @param stats the stats associated to token requ - * @return true if token is false otherwise - */ - bool getGroupStatistic(const uint32_t& token, GxsGroupStatistic& stats) override; - - /*! - * \brief turtleGroupRequest - * Issues a browadcast group request using the turtle router generic search system. The request is obviously asynchroneous and will be - * handled in RsGenExchange when received. - * \param group_id - */ - void turtleGroupRequest(const RsGxsGroupId& group_id); - void turtleSearchRequest(const std::string& match_string); - - /*! - * \brief getDistantSearchStatus - * Returns the status of ongoing search: unknown (probably not even searched), known as a search result, - * data request ongoing and data available - */ - DistantSearchGroupStatus getDistantSearchStatus(const RsGxsGroupId& group_id) ; - - /** - * @brief Search local groups. Blocking API. - * @param matchString string to look for in the search - * @param results storage for results - * @return false on error, true otherwise - */ - bool localSearch( const std::string& matchString, - std::list& results ); - - /// @see RsGxsIface - bool exportGroupBase64( - std::string& radix, const RsGxsGroupId& groupId, - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - /// @see RsGxsIface - bool importGroupBase64( - const std::string& radix, - RsGxsGroupId& groupId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId), - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - -protected: - - bool messagePublicationTest(const RsGxsMsgMetaData&) ; - /*! - * retrieves group data associated to a request token - * @param token token to be redeemed for grpitem retrieval - * @param grpItem the items to be retrieved for token are stored here - */ - bool getGroupData(const uint32_t &token, std::vector& grpItem); - - /*! - * \brief getSerializedGroupData - * Retrieves the complete group data serialized into a chunk of memory. This can be useful to - * transfer a full group from one machine to another. - * - * \param token token previously obtained from cache request - * \param data memory chunk allocated (using malloc) - * \param size size of the memory chunk. - * \return - */ - - bool getSerializedGroupData(uint32_t token, RsGxsGroupId &id, - unsigned char *& data, uint32_t& size); - bool deserializeGroupData(unsigned char *data, uint32_t size, - RsGxsGroupId* gId = nullptr); - - /*! - * \brief retrieveNxsIdentity - * Sync version of the previous method. Might take some time, so should be used carefully. - */ - bool retrieveNxsIdentity(const RsGxsGroupId& group_id,RsNxsGrp *& identity_grp); - - template - bool getGroupDataT(const uint32_t &token, std::vector& grpItem) - { - std::vector items; - bool ok = getGroupData(token, items); - std::vector::iterator vit = items.begin(); - - for(; vit != items.end(); ++vit) - { - RsGxsGrpItem* gi = *vit; - - GrpType* item = dynamic_cast(gi); - - if(item) - { - grpItem.push_back(item); - } - else - { -#ifdef GXS_DEBUG - std::cerr << "\nRsGenExchange::getGroupDataT(): Wrong type!\n"; -#endif - delete gi; - } - } - - return ok; - } - -public: - - /*! - * retrieves message data associated to a request token - * @param token token to be redeemed for message item retrieval - * @param msgItems - */ - bool getMsgData(uint32_t token, GxsMsgDataMap& msgItems); - - template - bool getMsgDataT( uint32_t token, std::map >& msgItems) - { - GxsMsgDataMap msgData; - bool ok = getMsgData(token, msgData); - - GxsMsgDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - const RsGxsGroupId& grpId = mit->first; - std::vector& mv = mit->second; - std::vector::iterator vit = mv.begin(); - for(; vit != mv.end(); ++vit) - { - RsGxsMsgItem* mi = *vit; - MsgType* mt = dynamic_cast(mi); - - if(mt != NULL) - { - msgItems[grpId].push_back(mt); - } - else - { - std::cerr << "RsGenExchange::getMsgDataT(): bad cast to msg type" << std::endl; - delete mi; - } - } - } - - return ok; - } - - /*! - * retrieves message related data associated to a request token - * @param token token to be redeemed for message item retrieval - * @param msgItems - */ - bool getMsgRelatedData(uint32_t token, GxsMsgRelatedDataMap& msgItems); - -protected: - - /*! - * Convenience template function for retrieve - * msg related data from - * @param GxsMsgType This represent derived msg class type of the service (i.e. msg type that derives from RsGxsMsgItem - * @param MsgType Represents the final type the core data is converted to - * @param token token to be redeemed - */ - template - bool getMsgRelatedDataT(const uint32_t &token, std::map > &msgItems) - { - - RsStackMutex stack(mGenMtx); - NxsMsgRelatedDataResult msgResult; - bool ok = mDataAccess->getMsgRelatedData(token, msgResult); - NxsMsgRelatedDataResult::iterator mit = msgResult.begin(); - - if(ok) - { - for(; mit != msgResult.end(); ++mit) - { - std::vector gxsMsgItems; - const RsGxsGrpMsgIdPair& msgId = mit->first; - std::vector& nxsMsgsV = mit->second; - std::vector::iterator vit - = nxsMsgsV.begin(); - for(; vit != nxsMsgsV.end(); ++vit) - { - RsNxsMsg*& msg = *vit; - RsItem* item = NULL; - - if(msg->msg.bin_len != 0) - item = mSerialiser->deserialise(msg->msg.bin_data, - &msg->msg.bin_len); - - GxsMsgType* mItem = NULL; - - if(item) - mItem = dynamic_cast(item); - - if(mItem == NULL) - { - delete msg; - continue; - } - - mItem->meta = *((*vit)->metaData); // get meta info from nxs msg - // GxsMsgType m = (*mItem); // doesn't work! don't know why, even with overloading done. - MsgType theServMsg = (MsgType)*mItem; - gxsMsgItems.push_back(theServMsg); - delete msg; - } - msgItems[msgId] = gxsMsgItems; - } - } - return ok; - } - -public: - /*! - * Generate a new token, the status of the token can be queried from request - * status feature. - * @attention the token space is shared with RsGenExchange backend. - * @return Generated token - */ - uint32_t generatePublicToken(); - - /*! - * Updates the status of associate token - * @warning the token space is shared with RsGenExchange backend, so do not - * modify tokens except does you have created by calling generatePublicToken() - * @param token - * @param status - * @return false if token could not be found, true if token disposed of - */ - bool updatePublicRequestStatus( - uint32_t token, RsTokenService::GxsRequestStatus status); - - /*! - * This gets rid of a publicly issued token - * @param token - * @return false if token could not found, true if token is disposed of - */ - bool disposeOfPublicToken(const uint32_t &token); - -protected: - /*! - * This gives access to the data store which hold msgs and groups - * for the service - * @return Data store for retrieving msgs and groups - */ - RsGeneralDataService* getDataStore(); - - /*! - * Retrieve keys for a given group, \n - * call is blocking retrieval from underlying db - * @warning under normal circumstance a service should not need this - * @param grpId the id of the group to retrieve keys for - * @param keys set to the retrieved keys - * @return false if group does not exist or grpId is empty - */ - bool getGroupKeys(const RsGxsGroupId& grpId, RsTlvSecurityKeySet& keySet); - -public: - - /*! - * This allows the client service to acknowledge that their msgs has \n - * been created/modified and retrieve the create/modified msg ids - * @param token the token related to modification/create request - * @param msgIds map of grpid->msgIds of message created/modified - * @return true if token exists false otherwise - */ - bool acknowledgeTokenMsg(const uint32_t& token, RsGxsGrpMsgIdPair& msgId); - - /*! - * This allows the client service to acknowledge that their grps has \n - * been created/modified and retrieve the create/modified grp ids - * @param token the token related to modification/create request - * @param grpId ids of created/modified group - * @return true if token exists false otherwise - */ - bool acknowledgeTokenGrp(const uint32_t& token, RsGxsGroupId& grpId); - -protected: - - /** Modifications **/ - - /*! - * Enables publication of a group item \n - * This will induce a related change message \n - * Ownership of item passes to this rsgenexchange \n - * @param token - * @param grpItem - */ - void publishGroup(uint32_t& token, RsGxsGrpItem* grpItem); - - /*! - * Updates an existing group item \n - * This will induce a related change message \n - * Ownership of item passes to this rsgenexchange \n - * @param token - * @param grpItem - */ - void updateGroup(uint32_t& token, RsGxsGrpItem* grpItem); - - /*! - * Deletes an existing group item \n - * This will induce a related change message \n - * Ownership of item passes to this rsgenexchange \n - * @param token - * @param grpItem - */ - void deleteGroup(uint32_t& token, const RsGxsGroupId &grpId); - -public: - /*! - * Enables publication of a message item \n - * Setting mOrigMsgId meta member to blank \n - * leads to this msg being an original msg \n - * if mOrigMsgId is not blank the msgId then this msg is \n - * considered a versioned msg \n - * Ownership of item passes to this rsgenexchange - * @param token - * @param msgItem - */ - void publishMsg(uint32_t& token, RsGxsMsgItem* msgItem); - - /*! - * Deletes the messages \n - * This will induce a related change message \n - * @param token - * @param msgs - */ - void deleteMsgs(uint32_t& token, const GxsMsgReq& msgs); - -protected: - /*! - * This represents the group before its signature is calculated - * Reimplement this function if you need to access keys to further extend - * security of your group items using keyset properties - * Derived service should return one of three ServiceCreate_Return enum values below - * @warning do not modify keySet! - * @param grp The group which is stored by GXS prior - * service can make specific modifications need - * in particular access to its keys and meta - * @param keySet this is the key set used to define the group - * contains private and public admin and publish keys - * (use key flags to distinguish) - * @return SERVICE_CREATE_SUCCESS, SERVICE_CREATE_FAIL, SERVICE_FAIL_TRY_LATER - */ - virtual ServiceCreate_Return service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet); - - /*! - * \brief service_checkIfGroupIsStillUsed - * Re-implement this function to help GXS cleaning, by telling that some particular group - * is not used anymore. This usually depends on subscription, the fact that friend nodes send - * some info or not, and particular cleaning strategy of each service. - * Besides, groups in some services are used by other services (e.g. identities, circles, are used in - * forums and so on), so deciding on a group usage can only be left to the specific service it is used in. - * \return - * true if the group is still used, false otherwise, meaning that the group can be deleted. Default is - * that the group is always in use. - */ - virtual bool service_checkIfGroupIsStillUsed(const RsGxsGrpMetaData& /* meta */) { return true; } // see RsGenExchange - - /*! - * \brief service_getLastGroupSeenTs - * \return - * returns the last time a friend sent information (statistics) about this group. That practically means when the - * group was still being subscribed by at least one friend. This is used by service_checkIfGroupIsStillUsed() to - * help getting rid of dead groups. - */ - virtual rstime_t service_getLastGroupSeenTs(const RsGxsGroupId&) { return 0; } -public: - - /*! - * sets the group subscribe flag - * @param token this is set to token value associated to this request - * @param grpId Id of group whose subscribe file will be changed - * @param status - * @param mask - */ - void setGroupSubscribeFlags(uint32_t& token, const RsGxsGroupId& grpId, const uint32_t& status, const uint32_t& mask); - - /*! - * sets the group subscribe flag - * @param token this is set to token value associated to this request - * @param grpId Id of group whose subscribe file will be changed - * @param status - * @param mask - */ - void setGroupStatusFlags(uint32_t& token, const RsGxsGroupId& grpId, const uint32_t& status, const uint32_t& mask); - - /*! - * sets the group service string - * @param token this is set to token value associated to this request - * @param grpId Id of group whose subscribe file will be changed - * @param servString - */ - void setGroupServiceString(uint32_t& token, const RsGxsGroupId& grpId, const std::string& servString); - - /*! - * - * @param token value set to be redeemed with acknowledgement - * @param grpId group id for cutoff value to be set - * @param CutOff The cut off value to set - */ - void setGroupReputationCutOff(uint32_t& token, const RsGxsGroupId& grpId, int CutOff); - - /*! - * - * @param token value set to be redeemed with acknowledgement - * @param grpId group id of the group to update - * @param CutOff The cut off value to set - */ - void updateGroupLastMsgTimeStamp(uint32_t& token, const RsGxsGroupId& grpId); - - /*! - * sets the msg status flag - * @param token this is set to token value associated to this request - * @param grpId Id of group whose subscribe file will be changed - * @param status - * @param mask Mask to apply to status flag - */ - void setMsgStatusFlags(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, const uint32_t& status, const uint32_t& mask); - - /*! - * sets the message service string - * @param token this is set to token value associated to this request - * @param msgId Id of message whose service string will be changed - * @param servString The service string to set msg to - */ - void setMsgServiceString(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, const std::string& servString ); - - /*! - * sets the message service string - */ - - void shareGroupPublishKey(const RsGxsGroupId& grpId,const std::set& peers) ; - - /*! - * Returns the local TS of the group as known by the network service. - * This is useful to allow various network services to sync their update TS - * when needed. Typical use case is forums and circles. - * @param gid GroupId the TS is which is requested - */ - bool getGroupServerUpdateTS(const RsGxsGroupId& gid,rstime_t& grp_server_update_TS,rstime_t& msg_server_update_TS) ; - - /*! - * \brief getDefaultStoragePeriod. All times in seconds. - * \return - */ - virtual uint32_t getDefaultStoragePeriod() override{ return mNetService->getDefaultKeepAge() ; } - - virtual uint32_t getStoragePeriod(const RsGxsGroupId& grpId) override; - virtual void setStoragePeriod(const RsGxsGroupId& grpId,uint32_t age_in_secs) override; - - virtual uint32_t getDefaultSyncPeriod()override; - virtual uint32_t getSyncPeriod(const RsGxsGroupId& grpId) override; - virtual void setSyncPeriod(const RsGxsGroupId& grpId,uint32_t age_in_secs) override; - virtual bool getGroupNetworkStats(const RsGxsGroupId& grpId,RsGroupNetworkStats& stats); - - uint16_t serviceType() const override { return mServType ; } - uint32_t serviceFullType() const { return RsServiceInfo::RsServiceInfoUIn16ToFullServiceId(mServType); } - - virtual RsReputationLevel minReputationForForwardingMessages( - uint32_t group_sign_flags, uint32_t identity_flags )override; -protected: - - /** Notifications **/ - - /*! - * This confirms this class as an abstract one that \n - * should not be instantiated \n - * The deriving class should implement this function \n - * as it is called by the backend GXS system to \n - * update client of changes which should \n - * instigate client to retrieve new content from the system - * Note! For newly received message and groups, bit 0xf00 is set to - * GXS_SERV::GXS_MSG_STATUS_UNPROCESSED and GXS_SERV::GXS_MSG_STATUS_UNREAD - * @param changes the changes that have occured to data held by this service - */ - virtual void notifyChanges(std::vector& changes) = 0; - -private: - - void processRecvdData(); - - void processRecvdMessages(); - - void processRecvdGroups(); - - void publishGrps(); - - void processGroupUpdatePublish(); - - void processGroupDelete(); - void processMessageDelete(); - void processRoutingClues(); - - void publishMsgs(); - - bool checkGroupMetaConsistency(const RsGroupMetaData& meta); - - /*! - * processes msg local meta changes - */ - void processMsgMetaChanges(); - - /*! - * Processes group local meta changes - */ - void processGrpMetaChanges(); - - /*! - * Convenience function for properly applying masks for status and subscribe flag - * of a group. - * @warning mask entry is removed from grpCv - */ - bool processGrpMask(const RsGxsGroupId& grpId, ContentValue& grpCv); - - /*! - * This completes the creation of an instance on RsNxsGrp - * by assigning it a groupId and signature via SHA1 and EVP_sign respectively \n - * @param grp Nxs group to create - * @return CREATE_SUCCESS for success, CREATE_FAIL for fail, - * CREATE_FAIL_TRY_LATER for Id sign key not avail (but requested) - */ - uint8_t createGroup(RsNxsGrp* grp, RsTlvSecurityKeySet& keySet); - -protected: - /*! - * This completes the creation of an instance on RsNxsMsg - * by assigning it a groupId and signature via SHA1 and EVP_sign respectively - * What signatures are calculated are based on the authentication policy - * of the service - * @param msg the Nxs message to create - * @return CREATE_SUCCESS for success, CREATE_FAIL for fail, - * CREATE_FAIL_TRY_LATER for Id sign key not avail (but requested) - */ - int createMessage(RsNxsMsg* msg); - - RsNetworkExchangeService *netService() const { return mNetService ; } - -private: - /*! - * convenience function to create sign - * @param signSet signatures are stored here - * @param msgData message data to be signed - * @param grpMeta the meta data for group the message belongs to - * @return SIGN_SUCCESS for success, SIGN_FAIL for fail, - * SIGN_FAIL_TRY_LATER for Id sign key not avail (but requested), try later - */ - int createMsgSignatures(RsTlvKeySignatureSet& signSet, RsTlvBinaryData& msgData, - const RsGxsMsgMetaData& msgMeta, const RsGxsGrpMetaData& grpMeta); - - /*! - * convenience function to create sign for groups - * @param signSet signatures are stored here - * @param grpData group data to be signed - * @param grpMeta the meta data for group to be signed - * @return SIGN_SUCCESS for success, SIGN_FAIL for fail, - * SIGN_FAIL_TRY_LATER for Id sign key not avail (but requested), try later - */ - int createGroupSignatures(RsTlvKeySignatureSet& signSet, RsTlvBinaryData& grpData, - RsGxsGrpMetaData& grpMeta); - - /*! - * check meta change is legal - * @return false if meta change is not legal - */ - bool locked_validateGrpMetaChange(GrpLocMetaData&); - - /*! - * Generate a set of keys that can define a GXS group - * @param privatekeySet contains private generated keys - * @param publickeySet contains public generated keys (counterpart of private) - * @param genPublicKeys should publish key pair also be generated - */ - void generateGroupKeys(RsTlvSecurityKeySet& keySet, bool genPublishKeys); - - /*! - * Attempts to validate msg signatures - * @param msg message to be validated - * @param grpFlag the distribution flag for the group the message belongs to - * @param grpFlag the signature flag for the group the message belongs to - * @param grpKeySet the key set user has for the message's group - * @return VALIDATE_SUCCESS for success, VALIDATE_FAIL for fail, - * VALIDATE_ID_SIGN_NOT_AVAIL for Id sign key not avail (but requested) - */ - int validateMsg(RsNxsMsg* msg, const uint32_t& grpFlag, const uint32_t &signFlag, RsTlvSecurityKeySet& grpKeySet); - - /*! - * Attempts to validate group signatures - * @param grp group to be validated - * @return VALIDATE_SUCCESS for success, VALIDATE_FAIL for fail, - * VALIDATE_ID_SIGN_NOT_AVAIL for Id sign key not avail (but requested) - */ - int validateGrp(RsNxsGrp* grp); - - /*! - * Checks flag against a given privacy bit block - * @param pos Determines 8 bit wide privacy block to check - * @param flag the flag to and(&) against - * @param the result of the (bit-block & flag) - */ - bool checkAuthenFlag(const PrivacyBitPos& pos, const uint8_t& flag) const; - - void groupShareKeys(std::list peers); - - static void computeHash(const RsTlvBinaryData& data, RsFileHash& hash); - - /*! - * Checks validation of recently received groups to be - * updated (and updates them, a bit of a misnomer) - */ - void performUpdateValidation(); - - /*! - * Checks if the update is valid (i.e. the new admin signature is by the old admin key) - * @param oldGrp the old group to be updated (must have meta data member initialised) - * @param newGrp the new group that updates the old group (must have meta data member initialised) - * @return - */ - bool updateValid(const RsGxsGrpMetaData& oldGrp, const RsNxsGrp& newGrp) const; - - /*! - * convenience function for checking private publish and admin keys are present - * @param keySet The keys set to split into a private and public set - * @return false, if private admin and publish keys cannot be found, true otherwise - */ - bool checkKeys(const RsTlvSecurityKeySet& keySet); - - /*! - * Message and notification map passed to method - * are cleansed of msgs and ids that already exist in database - * @param msgs messages to be filtered - * @param msgIdsNotify message notification map to be filtered - */ - void removeDeleteExistingMessages(std::list& msgs, GxsMsgReq& msgIdsNotify); - - RsMutex mGenMtx; - RsGxsDataAccess* mDataAccess; - RsGeneralDataService* mDataStore; - RsNetworkExchangeService *mNetService; - RsSerialType *mSerialiser; - /// service type - uint16_t mServType; - RsGixs* mGixs; - - std::vector mReceivedMsgs; - - typedef std::map > NxsGrpPendValidVect; - NxsGrpPendValidVect mGrpPendingValidate; - - std::vector mGrpsToPublish; - typedef std::vector NxsGrpSignPendVect; - - std::map mPublishedGrps ; // keeps track of which group was created using which token - std::map mPublishedMsgs ; // keeps track of which message was created using which token - - std::map mMsgsToPublish; - - std::map mMsgNotify; - std::map mGrpNotify; - - // for loc meta changes - std::map mGrpLocMetaMap; - std::map mMsgLocMetaMap; - - std::vector mNotifications; - - - - /// authentication policy - uint32_t mAuthenPolicy; - - std::map > mMsgPendingSign; - - typedef std::map > NxsMsgPendingVect; - NxsMsgPendingVect mMsgPendingValidate; - - bool mCleaning; - rstime_t mLastClean; - - bool mChecking, mCheckStarted; - rstime_t mLastCheck; - RsGxsIntegrityCheck* mIntegrityCheck; - RsGxsGroupId mNextGroupToCheck ; - -protected: - enum CreateStatus { CREATE_FAIL, CREATE_SUCCESS, CREATE_FAIL_TRY_LATER }; - const uint8_t SIGN_MAX_WAITING_TIME; - // TODO: cleanup this should be an enum! - const uint8_t SIGN_FAIL, SIGN_SUCCESS, SIGN_FAIL_TRY_LATER; - const uint8_t VALIDATE_FAIL, VALIDATE_SUCCESS, VALIDATE_FAIL_TRY_LATER, VALIDATE_MAX_WAITING_TIME; - -private: - - std::vector mGroupUpdates, mPeersGroupUpdate; - - std::vector mGroupUpdatePublish; - std::vector mGroupDeletePublish; - std::vector mMsgDeletePublish; - - std::map > mRoutingClues ; - - friend class RsGxsCleanUp; -}; - -#endif // RSGENEXCHANGE_H diff --git a/libretroshare/src/gxs/rsgixs.h b/libretroshare/src/gxs/rsgixs.h deleted file mode 100644 index 955aea673..000000000 --- a/libretroshare/src/gxs/rsgixs.h +++ /dev/null @@ -1,248 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgixs.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Robert Fernie, Evi-Parker Christopher * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RSGIXS_H -#define RSGIXS_H - -#include "gxs/rsgxs.h" -#include "gxs/rsgenexchange.h" - -#include "retroshare/rsgxscircles.h" - -#include "serialiser/rstlvkeys.h" -#include "retroshare/rsids.h" -/*! - * GIXP: General Identity Exchange Service. - * - * As we're always running into troubles with GPG signatures... we are going to - * create a layer of RSA Keys for the following properties: - * - * 1) RSA Keys can be Anonymous, Self-Signed with Pseudonym, Signed by GPG Key. - * To clarify: - * a. This forms a layer of keys stay between GPG and pub/priv publish key ? - * b. Difference between anonymous and pseudonym keys? - * - Anonymous cannot be signed? - * - - * c. To some extent this determines security model of RsGeneralExchangeService - - * - Anonymous & Pseudonym Keys will be shared network-wide (Hop by Hop). - - GPG signed Keys will only be shared if we can validate the signature - (providing similar behaviour to existing GPG Keys). - - GPG signed Keys can optionally be marked for Network-wide sharing. - * 2) These keys can be used anywhere, specifically in the protocols described below. - * 3) These keys can be used to sign, encrypt, verify & decrypt - * 4) Keys will never need to be directly accessed - stored in this class. - * a. I guess can work solely through Id - * b. Use Case: Receivve a message, has a key id, request - * 5) They will be cached locally and exchanged p2p, by pull request. - * 6) This class will use the generalised packet storage for efficient caching & loading. - * 7) Data will be stored encrypted. - */ - - -/****** - * More notes. The ideas above have been crystalised somewhat. - * - * The Identity service will now serve two roles: - * 1) validating msgs. - * 2) reputation of identity. - * - * The identity will be equivalent to a Group Definition. - * and the reputation contained in the group's messages. - * - * - * Group - * MetaData: - * Public Key - * Signatures. (Admin & optional GPG). - * RealData: - * Nickname. - * GPGHash - * - * The GPGHash will allow people to identify the real gpg user behind the identity. - * We must make sure that the Hash input has enough entropy that it cannot be brute-forced (e.g. like password hashes). - * - * The Identity service only has to provide hooks to access the Keys for each group. - * All the key definitions are exactly the same as for GroupMetaData. - * - * The Interface is split into three parts. - * 1) Internal interface used by GXS to verify signatures. - * 2) Internal interface used by GXS to help decide if we get a message or not. - * 3) External interface to access nicknames, generate new identities etc. - * - * The actual implementation will cache frequently used keys and nicknames, - * as these will be used very frequently. - *****/ - -/* Identity Interface for GXS Message Verification. - */ -class RsGixs -{ -public: - // TODO: cleanup this should be an enum! - static const uint32_t RS_GIXS_ERROR_NO_ERROR = 0x0000 ; - static const uint32_t RS_GIXS_ERROR_UNKNOWN = 0x0001 ; - static const uint32_t RS_GIXS_ERROR_KEY_NOT_AVAILABLE = 0x0002 ; - static const uint32_t RS_GIXS_ERROR_SIGNATURE_MISMATCH = 0x0003 ; - - /* Performs/validate a signature with the given key ID. The key must be available, otherwise the signature error - * will report it. Each time a key is used to validate a signature, its usage timestamp is updated. - * - * If force_load is true, the key will be forced loaded from the cache. If not, uncached keys will return - * with error_status=RS_GIXS_SIGNATURE_ERROR_KEY_NOT_AVAILABLE, but will likely be cached on the next call. - */ - - virtual bool signData(const uint8_t *data,uint32_t data_size,const RsGxsId& signer_id,RsTlvKeySignature& signature,uint32_t& signing_error) = 0 ; - virtual bool validateData(const uint8_t *data,uint32_t data_size,const RsTlvKeySignature& signature,bool force_load,const RsIdentityUsage& info,uint32_t& signing_error) = 0 ; - - virtual bool encryptData( const uint8_t *clear_data, - uint32_t clear_data_size, - uint8_t *& encrypted_data, - uint32_t& encrypted_data_size, - const RsGxsId& encryption_key_id, - uint32_t& encryption_error, bool force_load) = 0 ; - virtual bool decryptData( const uint8_t *encrypted_data, - uint32_t encrypted_data_size, - uint8_t *& clear_data, uint32_t& clear_data_size, - const RsGxsId& encryption_key_id, - uint32_t& encryption_error, bool force_load) = 0 ; - - virtual bool getOwnIds(std::list &ownIds, bool signed_only = false)=0; - virtual bool isOwnId(const RsGxsId& key_id) = 0 ; - - virtual void timeStampKey(const RsGxsId& key_id,const RsIdentityUsage& reason) = 0 ; - - // Key related interface - used for validating msgs and groups. - /*! - * Use to query a whether given key is available by its key reference - * @param keyref the keyref of key that is being checked for - * @return true if available, false otherwise - */ - virtual bool haveKey(const RsGxsId &id) = 0; - - /*! - * Use to query whether private key member of the given key reference is available - * @param keyref the KeyRef of the key being checked for - * @return true if private key is held here, false otherwise - */ - virtual bool havePrivateKey(const RsGxsId &id) = 0; - - // The fetchKey has an optional peerList.. this is people that had the msg with the signature. - // These same people should have the identity - so we ask them first. - /*! - * Use to request a given key reference - * @param keyref the KeyRef of the key being requested - * @return will - */ - virtual bool requestKey(const RsGxsId &id, const std::list &peers,const RsIdentityUsage& info) = 0; - virtual bool requestPrivateKey(const RsGxsId &id) = 0; - - /*! - * \brief receiveNewIdentity - * Receives a new identity. This is a facility offerred to RsGxsNetService when identities are sent/received by turtle tunnels - */ - virtual bool receiveNewIdentity(RsNxsGrp *identity_grp)=0; - virtual bool retrieveNxsIdentity(const RsGxsId& group_id,RsNxsGrp *& identity_grp)=0; - - /*! - * Retrieves a key identity - * @param keyref - * @return a pointer to a valid profile if successful, otherwise NULL - * - */ - virtual bool getKey(const RsGxsId &id, RsTlvPublicRSAKey& key) = 0; - virtual bool getPrivateKey(const RsGxsId &id, RsTlvPrivateRSAKey& key) = 0; // For signing outgoing messages. - virtual bool getIdDetails(const RsGxsId& id, RsIdentityDetails& details) = 0 ; // Proxy function so that we get p3Identity info from Gxs - - virtual ~RsGixs(); -}; - -class GixsReputation -{ -public: - GixsReputation() :reputation_level(0) {} - - RsGxsId id; - uint32_t reputation_level ; -}; - -struct RsGixsReputation -{ - virtual RsReputationLevel overallReputationLevel( - const RsGxsId& id, uint32_t* identity_flags = nullptr ) = 0; - virtual ~RsGixsReputation(){} -}; - -/*** This Class pulls all the GXS Interfaces together ****/ - -struct RsGxsIdExchange : RsGenExchange, RsGixs -{ - RsGxsIdExchange( - RsGeneralDataService* gds, RsNetworkExchangeService* ns, - RsSerialType* serviceSerialiser, uint16_t mServType, - uint32_t authenPolicy ) - : RsGenExchange( - gds, ns, serviceSerialiser, mServType, this, authenPolicy ) {} -}; - - - - -/* For Circles Too */ - -class RsGcxs -{ - public: - virtual ~RsGcxs(){} - - /* GXS Interface - for working out who can receive */ - virtual bool isLoaded(const RsGxsCircleId &circleId) = 0; - virtual bool loadCircle(const RsGxsCircleId &circleId) = 0; - - virtual int canSend(const RsGxsCircleId &circleId, const RsPgpId &id,bool& should_encrypt) = 0; - virtual int canReceive(const RsGxsCircleId &circleId, const RsPgpId &id) = 0; - - virtual bool recipients(const RsGxsCircleId &circleId, std::list& friendlist) = 0; - virtual bool recipients(const RsGxsCircleId &circleId, const RsGxsGroupId& destination_group, std::list& idlist) = 0; - - virtual bool isRecipient(const RsGxsCircleId &circleId, const RsGxsGroupId& destination_group, const RsGxsId& id) = 0; - - virtual bool getLocalCircleServerUpdateTS(const RsGxsCircleId& gid,rstime_t& grp_server_update_TS,rstime_t& msg_server_update_TS) =0; -}; - - - -class RsGxsCircleExchange: public RsGenExchange, public RsGcxs -{ -public: - RsGxsCircleExchange(RsGeneralDataService* gds, RsNetworkExchangeService* ns, RsSerialType* serviceSerialiser, - uint16_t mServType, RsGixs* gixs, uint32_t authenPolicy) - :RsGenExchange(gds,ns,serviceSerialiser,mServType, gixs, authenPolicy) { return; } - virtual ~RsGxsCircleExchange() { return; } - - virtual bool getLocalCircleServerUpdateTS(const RsGxsCircleId& gid,rstime_t& grp_server_update_TS,rstime_t& msg_server_update_TS) - { - return RsGenExchange::getGroupServerUpdateTS(RsGxsGroupId(gid),grp_server_update_TS,msg_server_update_TS) ; - } -}; - - -#endif // RSGIXS_H diff --git a/libretroshare/src/gxs/rsgroups.h b/libretroshare/src/gxs/rsgroups.h deleted file mode 100644 index 5a24ac826..000000000 --- a/libretroshare/src/gxs/rsgroups.h +++ /dev/null @@ -1,151 +0,0 @@ -// -// This is a first attempt at managing groups and group permissions -// in libretroshare. -// -// Rules: -// 1 - Groups are handled GPG-wise, and not SSLId wise, but we need to provide functions -// for SSLIds since that's what peers are represented by. -// -// 2 - A peer can be in different groups. That will be useful for e.g. file sharing. -// -// 3 - Global permissions always prevail over permissions given at the group level. For -// instance for discovery between two peers that belong to groups G1 and G2: -// -// | Global discovery flag ON | Global disc flag OFF | -// --------------------+--------------------------+----------------------+ -// Group disc(G1,G2)=1 | Allow | Don't allow | -// Group disc(G1,G2)=0 | Don't allow | Don't allow | -// -// 4 - Binary group permissions are OR-ed between pairs of groups. If peers (A,B) can be matched to -// two different pairs of groups, the flags are combined with an OR. -// -// libretroshare side -// ================== -// We need a matrix for binary group flags, i.e. flags for pair of groups, for: -// -// Turtle traffic: -// * does the turtle traffic can go from peers of a group to another -// * default: yes -// -// Discovery: -// * does the turtle traffic can go from peers of a group to another -// * default: yes. Overriden by discovery status in config. -// -// Public chat lobby advertisement: -// * public lobby coming from peers of a group go to peers of another group -// * default: yes -// -// Relay connexions: -// * allow relay connexions between people of group A and group B. -// -// General Exchange Services: -// * Allow data exchanged from one peers of one group to peers of another group -// -// We need per-group permission flags for: -// -// File download permission: -// * each shared directory belongs to a list of groups -// * each shared directory has a set of DL flags (browsable B,network wide N) for groups and for global. -// * files are listed with unix-like permissions style: -// ---- : file can't be transfered at all. -// bn-- : file is browsable and turtle-able by friends of its groups only. -// b-b- : file is browsable by everybody -// --b- : file is browsable by everybody that does not belong to its groups (can be useful to isolate people in a group) -// -n-- : file is turtle-able by people that belong to its groups only. -// bnbn : file is always accessible in any ways. That's what file sharing is about. Should be the default ;-) -// -// We need to propose some pre-initialized settings to the user, so that he won't have to bother with flags, but we -// need to allow precisely tweaking them as well: -// Directory is -// - Accessible for this group only (allow select a group) -// - Fully shared anonymously -// - [...] -// -// If the shared directory has no groups, than the first two flags are meaningless. -// -// GUI side -// ======== -// - we need a tab in config to manage groups and group flag permission matrix -// - when sharing a directory, the user can act on permissions: setting which groups a -// directory belongs to. -// -// Classes for groups. To be displatched in rstypes.h ? -// - -#pragma once - -typedef RsPeerId SSLId ; -typedef RsPgpId GPGId ; -typedef uint64_t RsGroupId ; - -class RsPeerGroupInfo -{ - public: - RsGroupId group_id ; // Id of the group, should be random and unique in the RS session. - std::string group_name ; // user-defined name of the group ("parents", "friends", etc) - std::set elements ; // people in the group. GPG-wise. -}; - -class GroupFlagsMatrix -{ - public: - // flags - - static const uint32_t GROUP_MATRIX_FLAG_DISCOVERY = 0x1 ; - static const uint32_t GROUP_MATRIX_FLAG_TURTLE = 0x2 ; - static const uint32_t GROUP_MATRIX_FLAG_PUBLIC_LOBBY = 0x4 ; - static const uint32_t GROUP_MATRIX_FLAG_RELAY = 0x8 ; - - // returns/set all flags for a given pair of groups. Used by the - // GUI to draw/modify group flags. - // - uint32_t getGroupFlags(RsGroupId grp1,RsGroupId grp2) const ; - void setGroupFlags(uint32_t flags,RsGroupId grp1,RsGroupId grp2) const ; - - // Returns a given flag for two people in particular. Used by services to - // know what to do or not do. - // - bool groupPermission(uint32_t group_flag,GPGId peer_1,GPGId peer2) const ; - - private: - std::vector _flags ; // vector of size number_of_groups^2 - std::map _group_entries ; // index to read the flags vector. -}; - -// Interface class for Groups. Should go in libretroshare/stc/retroshare/rsgroups.h -// - -class RsGroupManagement -{ - public: - // Group handling - - // Returns false is the group does not exist. Otherwise, fills the GroupInfo struct. - // - virtual bool getGroupInfo(const RsGroupId& id,RsPeerGroupInfo& info) = 0 ; - - // Adds a friend to a group. - virtual bool getGroupInfo(const RsGroupId& id,RsPeerGroupInfo& info) = 0 ; - - // Group permission handling - // - virtual bool allow_TwoPeers_TurtleTraffic (const SSLId& p1,const SSLId& p2) = 0 ; - virtual bool allow_TwoPeers_Discovery (const SSLId& p1,const SSLId& p2) = 0 ; - virtual bool allow_TwoPeers_LobbyAdvertisement(const SSLId& p1,const SSLId& p2) = 0 ; - virtual bool allow_TwoPeers_GeneralExchangeService(const SSLId& p1,const SSLId& p2) = 0 ; - // [...] -}; - -class p3GroupManagement: public RsGroupManagement, public p3Config -{ - public: - // [...] - - private: - std::map _groups ; -}; - -// This is the entry point for external interface. -// -extern RsGroupManagement *rsGroups ; - diff --git a/libretroshare/src/gxs/rsgxs.h b/libretroshare/src/gxs/rsgxs.h deleted file mode 100644 index 696f317ae..000000000 --- a/libretroshare/src/gxs/rsgxs.h +++ /dev/null @@ -1,41 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxs.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 Christopher Evi-Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RSGXS_H -#define RSGXS_H - -#include "gxs/rsgxsdata.h" - -#include -#include - -/* data types used throughout Gxs from netservice to genexchange */ - -typedef std::map > > GxsMsgMetaResult; -typedef std::map > > MsgRelatedMetaResult; - -// Default values that are used throughout GXS code - -static const uint32_t RS_GXS_DEFAULT_MSG_STORE_PERIOD = 86400 * 372 ; // 1 year. Default time for which messages are keps in the database. -static const uint32_t RS_GXS_DEFAULT_MSG_SEND_PERIOD = 86400 * 30 * 1 ; // one month. Default delay after which we don't send messages -static const uint32_t RS_GXS_DEFAULT_MSG_REQ_PERIOD = 86400 * 30 * 1 ; // one month. Default Delay after which we don't request messages - -#endif // RSGXS_H diff --git a/libretroshare/src/gxs/rsgxsdata.cc b/libretroshare/src/gxs/rsgxsdata.cc deleted file mode 100644 index b83096575..000000000 --- a/libretroshare/src/gxs/rsgxsdata.cc +++ /dev/null @@ -1,360 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsdata.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Christopher Evi-Parker, Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "rsgxsdata.h" -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstlvbase.h" - -RsGxsGrpMetaData::RsGxsGrpMetaData() -{ - clear(); -} - -uint32_t RsGxsGrpMetaData::serial_size(uint32_t api_version) const -{ - uint32_t s = 8; // header size - - s += mGroupId.serial_size(); - s += mOrigGrpId.serial_size(); - s += mParentGrpId.serial_size(); - s += GetTlvStringSize(mGroupName); - s += 4; // mGroupFlags - s += 4; // mPublishTs - s += 4; // mCircleType - s += 4; // mAuthenFlag - s += mAuthorId.serial_size(); - s += GetTlvStringSize(mServiceString); - s += mCircleId.serial_size(); - s += signSet.TlvSize(); - s += keys.TlvSize(); - - if(api_version == RS_GXS_GRP_META_DATA_VERSION_ID_0002) - s += 4; // mSignFlag - else if(api_version != RS_GXS_GRP_META_DATA_VERSION_ID_0001) - std::cerr << "(EE) wrong/unknown API version " << api_version << " requested in RsGxsGrpMetaData::serial_size()" << std::endl; - - return s; -} - -void RsGxsGrpMetaData::clear(){ - - mGroupId.clear(); - mOrigGrpId.clear(); - mGroupName.clear(); - mGroupFlags = 0; - mPublishTs = 0; - mSignFlags = 0; - mAuthorId.clear(); - - mCircleId.clear(); - mCircleType = 0; - - signSet.TlvClear(); - keys.TlvClear(); - - mServiceString.clear(); - mAuthenFlags = 0; - mParentGrpId.clear(); - - mSubscribeFlags = 0; - - mPop = 0; - mVisibleMsgCount = 0; - mGroupStatus = 0; - mLastPost = 0; - mReputationCutOff = 0; - mGrpSize = 0 ; - - mGroupStatus = 0 ; - mRecvTS = 0; - - mOriginator.clear(); - mInternalCircle.clear(); - mHash.clear() ; -} - -bool RsGxsGrpMetaData::serialise(void *data, uint32_t &pktsize,uint32_t api_version) -{ - uint32_t tlvsize = serial_size(api_version) ; - uint32_t offset = 0; - - if (pktsize < tlvsize) - return false; /* not enough space */ - - pktsize = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, api_version, tlvsize); - -#ifdef GXS_DEBUG - std::cerr << "RsGxsGrpMetaData serialise()" << std::endl; - std::cerr << "RsGxsGrpMetaData serialise(): Header: " << ok << std::endl; - std::cerr << "RsGxsGrpMetaData serialise(): Size: " << tlvsize << std::endl; -#endif - - /* skip header */ - offset += 8; - - ok &= mGroupId.serialise(data, tlvsize, offset); - ok &= mOrigGrpId.serialise(data, tlvsize, offset); - ok &= mParentGrpId.serialise(data, tlvsize, offset); - ok &= SetTlvString(data, tlvsize, &offset, 0, mGroupName); - ok &= setRawUInt32(data, tlvsize, &offset, mGroupFlags); - ok &= setRawUInt32(data, tlvsize, &offset, mPublishTs); - ok &= setRawUInt32(data, tlvsize, &offset, mCircleType); - ok &= setRawUInt32(data, tlvsize, &offset, mAuthenFlags); - ok &= mAuthorId.serialise(data, tlvsize, offset); - ok &= SetTlvString(data, tlvsize, &offset, 0, mServiceString); - ok &= mCircleId.serialise(data, tlvsize, offset); - - ok &= signSet.SetTlv(data, tlvsize, &offset); - ok &= keys.SetTlv(data, tlvsize, &offset); - - if(api_version == RS_GXS_GRP_META_DATA_VERSION_ID_0002) - ok &= setRawUInt32(data, tlvsize, &offset, mSignFlags); // new in API v2. Was previously missing. Kept in the end for backward compatibility - - return ok; -} - -bool RsGxsGrpMetaData::deserialise(void *data, uint32_t &pktsize) -{ - - uint32_t offset = 8; // skip the header - uint32_t rssize = getRsItemSize(data); - - bool ok = true ; - - ok &= rssize == pktsize; - - if(!ok) return false; - - ok &= mGroupId.deserialise(data, pktsize, offset); - ok &= mOrigGrpId.deserialise(data, pktsize, offset); - ok &= mParentGrpId.deserialise(data, pktsize, offset); - ok &= GetTlvString(data, pktsize, &offset, 0, mGroupName); - ok &= getRawUInt32(data, pktsize, &offset, &mGroupFlags); - ok &= getRawUInt32(data, pktsize, &offset, &mPublishTs); - ok &= getRawUInt32(data, pktsize, &offset, &mCircleType); - ok &= getRawUInt32(data, pktsize, &offset, &mAuthenFlags); - - - ok &= mAuthorId.deserialise(data, pktsize, offset); - ok &= GetTlvString(data, pktsize, &offset, 0, mServiceString); - ok &= mCircleId.deserialise(data, pktsize, offset); - ok &= signSet.GetTlv(data, pktsize, &offset); - ok &= keys.GetTlv(data, pktsize, &offset); - - switch(getRsItemId(data)) - { - case RS_GXS_GRP_META_DATA_VERSION_ID_0002: ok &= getRawUInt32(data, pktsize, &offset, &mSignFlags); // current API - break ; - - case RS_GXS_GRP_META_DATA_VERSION_ID_0001: mSignFlags = 0; // old API. Do not leave this uninitialised! - break ; - - default: - std::cerr << "(EE) RsGxsGrpMetaData::deserialise(): ERROR: unknown API version " << std::hex << getRsItemId(data) << std::dec << std::endl; - } - - if(offset != pktsize) - { - std::cerr << "(EE) RsGxsGrpMetaData::deserialise(): ERROR: unmatched size " << offset << ", expected: " << pktsize << std::dec << std::endl; - return false ; - } -#ifdef DROP_NON_CANONICAL_ITEMS - if(mGroupName.length() > RsGxsGrpMetaData::MAX_ALLOWED_STRING_SIZE) - { - std::cerr << "WARNING: Deserialised group with mGroupName.length() = " << mGroupName.length() << ". This is not allowed. This item will be dropped." << std::endl; - return false ; - } - if(mServiceString.length() > RsGxsGrpMetaData::MAX_ALLOWED_STRING_SIZE) - { - std::cerr << "WARNING: Deserialised group with mServiceString.length() = " << mGroupName.length() << ". This is not allowed. This item will be dropped." << std::endl; - return false ; - } -#endif - - return ok; -} - -RsGxsMsgMetaData::RsGxsMsgMetaData(){ - clear(); - //std::cout << "\nrefcount++ : " << ++refcount << std::endl; - return; -} - -RsGxsMsgMetaData::~RsGxsMsgMetaData(){ - //std::cout << "\nrefcount-- : " << --refcount << std::endl; - return; -} - -uint32_t RsGxsMsgMetaData::serial_size() const -{ - - uint32_t s = 8; // header size - - s += mGroupId.serial_size(); - s += mMsgId.serial_size(); - s += mThreadId.serial_size(); - s += mParentId.serial_size(); - s += mOrigMsgId.serial_size(); - s += mAuthorId.serial_size(); - - s += signSet.TlvSize(); - s += GetTlvStringSize(mMsgName); - s += 4; // mPublishTS - s += 4; // mMsgFlags - - return s; -} - -void RsGxsMsgMetaData::clear() -{ - mGroupId.clear(); - mMsgId.clear(); - mThreadId.clear(); - mParentId.clear(); - mOrigMsgId.clear(); - mAuthorId.clear(); - - signSet.TlvClear(); - mMsgName.clear(); - mPublishTs = 0; - mMsgFlags = 0; - - mServiceString.clear(); - mMsgStatus = 0; - mMsgSize = 0; - mChildTs = 0; - recvTS = 0; - mHash.clear(); - validated = false; -} - -bool RsGxsMsgMetaData::serialise(void *data, uint32_t *size) -{ - uint32_t tlvsize = serial_size() ; - uint32_t offset = 0; - - if (*size < tlvsize) - return false; /* not enough space */ - - *size = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, RS_GXS_MSG_META_DATA_VERSION_ID_0002, tlvsize); - -#ifdef GXS_DEBUG - std::cerr << "RsGxsGrpMetaData serialise()" << std::endl; - std::cerr << "RsGxsGrpMetaData serialise(): Header: " << ok << std::endl; - std::cerr << "RsGxsGrpMetaData serialise(): Size: " << tlvsize << std::endl; -#endif - - /* skip header */ - offset += 8; - - ok &= mGroupId.serialise(data, *size, offset); - ok &= mMsgId.serialise(data, *size, offset); - ok &= mThreadId.serialise(data, *size, offset); - ok &= mParentId.serialise(data, *size, offset); - ok &= mOrigMsgId.serialise(data, *size, offset); - ok &= mAuthorId.serialise(data, *size, offset); - - ok &= signSet.SetTlv(data, *size, &offset); - ok &= SetTlvString(data, *size, &offset, 0, mMsgName); - ok &= setRawUInt32(data, *size, &offset, mPublishTs); - ok &= setRawUInt32(data, *size, &offset, mMsgFlags); - - return ok; -} - - -bool RsGxsMsgMetaData::deserialise(void *data, uint32_t *size) -{ - uint32_t offset = 8; // skip the header - uint32_t rssize = getRsItemSize(data); - - bool ok = true ; - - ok &= rssize == *size; - - if(!ok) return false; - - ok &= mGroupId.deserialise(data, *size, offset); - ok &= mMsgId.deserialise(data, *size, offset); - ok &= mThreadId.deserialise(data, *size, offset); - ok &= mParentId.deserialise(data, *size, offset); - ok &= mOrigMsgId.deserialise(data, *size, offset); - ok &= mAuthorId.deserialise(data, *size, offset); - - ok &= signSet.GetTlv(data, *size, &offset); - ok &= GetTlvString(data, *size, &offset, 0, mMsgName); - uint32_t t=0; - ok &= getRawUInt32(data, *size, &offset, &t); - mPublishTs = t; - ok &= getRawUInt32(data, *size, &offset, &mMsgFlags); - - return ok; -} - -void RsGxsGrpMetaData::operator =(const RsGroupMetaData& rMeta) -{ - this->mAuthorId = rMeta.mAuthorId; - this->mGroupFlags = rMeta.mGroupFlags; - this->mGroupId = rMeta.mGroupId; - this->mGroupStatus = rMeta.mGroupStatus ; - this->mLastPost = rMeta.mLastPost; - this->mVisibleMsgCount = rMeta.mVisibleMsgCount ; - this->mPop = rMeta.mPop; - this->mPublishTs = rMeta.mPublishTs; - this->mSubscribeFlags = rMeta.mSubscribeFlags; - this->mGroupName = rMeta.mGroupName; - this->mServiceString = rMeta.mServiceString; - this->mSignFlags = rMeta.mSignFlags; - this->mCircleId = rMeta.mCircleId; - this->mCircleType = rMeta.mCircleType; - this->mInternalCircle = rMeta.mInternalCircle; - this->mOriginator = rMeta.mOriginator; - this->mAuthenFlags = rMeta.mAuthenFlags; - //std::cout << "rMeta.mParentGrpId= " <mParentGrpId = rMeta.mParentGrpId; -} - -void RsGxsMsgMetaData::operator =(const RsMsgMetaData& rMeta) -{ - this->mAuthorId = rMeta.mAuthorId; - this->mChildTs = rMeta.mChildTs ; - this->mGroupId = rMeta.mGroupId; - this->mMsgFlags = rMeta.mMsgFlags ; - this->mMsgId = rMeta.mMsgId ; - this->mMsgName = rMeta.mMsgName; - this->mMsgStatus = rMeta.mMsgStatus; - this->mOrigMsgId = rMeta.mOrigMsgId; - this->mParentId = rMeta.mParentId ; - this->mPublishTs = rMeta.mPublishTs ; - this->mThreadId = rMeta.mThreadId; - this->mServiceString = rMeta.mServiceString; -} - - diff --git a/libretroshare/src/gxs/rsgxsdata.h b/libretroshare/src/gxs/rsgxsdata.h deleted file mode 100644 index acc0c71d8..000000000 --- a/libretroshare/src/gxs/rsgxsdata.h +++ /dev/null @@ -1,130 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsdata.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Christopher Evi-Parker, Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RSGXSMETA_H -#define RSGXSMETA_H - -#include - -#include "retroshare/rstypes.h" -#include "serialiser/rstlvkeys.h" -#include "util/rstime.h" -#include "rsitems/rsgxsitems.h" - -struct RsGroupMetaData; -struct RsMsgMetaData; - -static const uint32_t RS_GXS_GRP_META_DATA_VERSION_ID_0001 = 0x0000 ; // change this, and keep old values if the content changes -static const uint32_t RS_GXS_GRP_META_DATA_VERSION_ID_0002 = 0xaf01 ; // current API - -static const uint32_t RS_GXS_MSG_META_DATA_VERSION_ID_0002 = 0x0000 ; // current API - -static const uint32_t RS_GXS_GRP_META_DATA_CURRENT_API_VERSION = RS_GXS_GRP_META_DATA_VERSION_ID_0002; - -class RsGxsGrpMetaData -{ -public: - static const int MAX_ALLOWED_STRING_SIZE = 50 ; - - RsGxsGrpMetaData(); - bool deserialise(void *data, uint32_t &pktsize); - bool serialise(void* data, uint32_t &pktsize, uint32_t api_version); - uint32_t serial_size(uint32_t api_version) const; - uint32_t serial_size() const { return serial_size(RS_GXS_GRP_META_DATA_CURRENT_API_VERSION); } - void clear(); - void operator =(const RsGroupMetaData& rMeta); - - //Sort data in same order than serialiser and deserializer - RsGxsGroupId mGroupId; - RsGxsGroupId mOrigGrpId; - RsGxsGroupId mParentGrpId; - std::string mGroupName; - uint32_t mGroupFlags; // GXS_SERV::FLAG_PRIVACY_RESTRICTED | GXS_SERV::FLAG_PRIVACY_PRIVATE | GXS_SERV::FLAG_PRIVACY_PUBLIC - uint32_t mPublishTs; - uint32_t mCircleType; - uint32_t mAuthenFlags; - RsGxsId mAuthorId; - std::string mServiceString; - RsGxsCircleId mCircleId; - RsTlvKeySignatureSet signSet; - RsTlvSecurityKeySet keys; - - uint32_t mSignFlags; - - // BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG. - - uint32_t mSubscribeFlags; - - uint32_t mPop; // Number of friends who subscribed - uint32_t mVisibleMsgCount; // Max number of messages reported by a single friend (used for unsubscribed groups) - uint32_t mLastPost; // Time stamp of last post (not yet filled) - uint32_t mReputationCutOff; - uint32_t mGrpSize; - - uint32_t mGroupStatus; - uint32_t mRecvTS; - RsPeerId mOriginator; - RsGxsCircleId mInternalCircle; - RsFileHash mHash; -}; - - -class RsGxsMsgMetaData -{ -public: - - explicit RsGxsMsgMetaData(); - ~RsGxsMsgMetaData(); - bool deserialise(void *data, uint32_t *size); - bool serialise(void* data, uint32_t *size); - uint32_t serial_size() const; - void clear(); - void operator =(const RsMsgMetaData& rMeta); - - //Sort data in same order than serialiser and deserializer - RsGxsGroupId mGroupId; - RsGxsMessageId mMsgId; - RsGxsMessageId mThreadId; - RsGxsMessageId mParentId; - RsGxsMessageId mOrigMsgId; - RsGxsId mAuthorId; - - RsTlvKeySignatureSet signSet; - std::string mMsgName; - rstime_t mPublishTs; - uint32_t mMsgFlags; // used by some services (e.g. by forums to store message moderation flags) - - // BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG. - // normally READ / UNREAD flags. LOCAL Data. - - std::string mServiceString; - uint32_t mMsgStatus; - uint32_t mMsgSize; - rstime_t mChildTs; - uint32_t recvTS; - RsFileHash mHash; - bool validated; -}; - - - - -#endif // RSGXSMETA_H diff --git a/libretroshare/src/gxs/rsgxsdataaccess.cc b/libretroshare/src/gxs/rsgxsdataaccess.cc deleted file mode 100644 index a14248d4f..000000000 --- a/libretroshare/src/gxs/rsgxsdataaccess.cc +++ /dev/null @@ -1,1973 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsdataaccess.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2013 by Christopher Evi-Parker, Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "util/rstime.h" - -#include "rsgxsutil.h" -#include "rsgxsdataaccess.h" -#include "retroshare/rsgxsflags.h" - -/*********** - * #define DATA_DEBUG 1 - **********/ - -// Debug system to allow to print only for some services (group, Peer, etc) - -#if defined(DATA_DEBUG) -static const uint32_t service_to_print = RS_SERVICE_GXS_TYPE_FORUMS;// use this to allow to this service id only, or 0 for all services - // warning. Numbers should be SERVICE IDS (see serialiser/rsserviceids.h. E.g. 0x0215 for forums) - -class nullstream: public std::ostream {}; - -static std::string nice_time_stamp(rstime_t now,rstime_t TS) -{ - if(TS == 0) - return "Never" ; - else - { - std::ostringstream s; - s << now - TS << " secs ago" ; - return s.str() ; - } -} - -static std::ostream& gxsdatadebug(uint32_t service_type) -{ - static nullstream null ; - - if (service_to_print==0 || service_type == 0 || (service_type == service_to_print)) - return std::cerr << time(NULL) << ":GXSDATASERVICE: " ; - else - return null ; -} - -#define GXSDATADEBUG gxsdatadebug(mDataStore->serviceType()) - -static const std::vector tokenStatusString( { - std::string("FAILED"), - std::string("PENDING"), - std::string("PARTIAL"), - std::string("COMPLETE"), - std::string("DONE"), - std::string("CANCELLED"), - }); - -#endif - -bool operator<(const std::pair& p1,const std::pair& p2) -{ - return p1.second->Options.mPriority <= p2.second->Options.mPriority ; // <= so that new elements with same priority are inserted before -} - -RsGxsDataAccess::RsGxsDataAccess(RsGeneralDataService* ds) : - mDataStore(ds), mDataMutex("RsGxsDataAccess"), mNextToken(0) {} - - -RsGxsDataAccess::~RsGxsDataAccess() -{ - for(auto& it:mRequestQueue) - delete it.second; -} -bool RsGxsDataAccess::requestGroupInfo( uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds ) -{ - if(groupIds.empty()) - { - std::cerr << __PRETTY_FUNCTION__ << " (WW) Group Id list is empty!" << std::endl; - return false; - } - - GxsRequest* req = nullptr; - uint32_t reqType = opts.mReqType; - - if(reqType & GXS_REQUEST_TYPE_GROUP_META) - { - GroupMetaReq* gmr = new GroupMetaReq(); - gmr->mGroupIds = groupIds; - req = gmr; - } - else if(reqType & GXS_REQUEST_TYPE_GROUP_DATA) - { - GroupDataReq* gdr = new GroupDataReq(); - gdr->mGroupIds = groupIds; - req = gdr; - } - else if(reqType & GXS_REQUEST_TYPE_GROUP_IDS) - { - GroupIdReq* gir = new GroupIdReq(); - gir->mGroupIds = groupIds; - req = gir; - } - else if(reqType & GXS_REQUEST_TYPE_GROUP_SERIALIZED_DATA) - { - GroupSerializedDataReq* gir = new GroupSerializedDataReq(); - gir->mGroupIds = groupIds; - req = gir; - } - - if(!req) - { - RsErr() << __PRETTY_FUNCTION__ << " request type not recognised, " << "reqType: " << reqType << std::endl; - return false; - } - - generateToken(token); - -#ifdef DATA_DEBUG - GXSDATADEBUG << "RsGxsDataAccess::requestGroupInfo() gets token: " << token << std::endl; -#endif - - setReq(req, token, ansType, opts); - storeRequest(req); - - return true; -} - -bool RsGxsDataAccess::requestGroupInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts) -{ - - GxsRequest* req = nullptr; - uint32_t reqType = opts.mReqType; - - if(reqType & GXS_REQUEST_TYPE_GROUP_META) - req = new GroupMetaReq(); - else if(reqType & GXS_REQUEST_TYPE_GROUP_DATA) - req = new GroupDataReq(); - else if(reqType & GXS_REQUEST_TYPE_GROUP_IDS) - req = new GroupIdReq(); - else if(reqType & GXS_REQUEST_TYPE_GROUP_SERIALIZED_DATA) - req = new GroupSerializedDataReq(); - else - { - RsErr() << "RsGxsDataAccess::requestGroupInfo() request type not recognised, type " << reqType << std::endl; - return false; - } - - generateToken(token); -#ifdef DATA_DEBUG - GXSDATADEBUG << "RsGxsDataAccess::requestGroupInfo() gets Token: " << token << std::endl; -#endif - - setReq(req, token, ansType, opts); - storeRequest(req); - - return true; -} - -void RsGxsDataAccess::generateToken(uint32_t &token) -{ - RS_STACK_MUTEX(mDataMutex); - token = mNextToken++; -} - - -bool RsGxsDataAccess::requestMsgInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const GxsMsgReq &msgIds) -{ - - GxsRequest* req = nullptr; - uint32_t reqType = opts.mReqType; - - // remove all empty grpId entries - GxsMsgReq::const_iterator mit = msgIds.begin(); - std::vector toRemove; - - for(; mit != msgIds.end(); ++mit) - { - if(mit->second.empty()) - toRemove.push_back(mit->first); - } - - std::vector::const_iterator vit = toRemove.begin(); - - GxsMsgReq filteredMsgIds = msgIds; - - for(; vit != toRemove.end(); ++vit) - filteredMsgIds.erase(*vit); - - if(reqType & GXS_REQUEST_TYPE_MSG_META) - { - MsgMetaReq* mmr = new MsgMetaReq(); - mmr->mMsgIds = filteredMsgIds; - req = mmr; - - }else if(reqType & GXS_REQUEST_TYPE_MSG_DATA) - { - MsgDataReq* mdr = new MsgDataReq(); - mdr->mMsgIds = filteredMsgIds; - req = mdr; - - }else if(reqType & GXS_REQUEST_TYPE_MSG_IDS) - { - MsgIdReq* mir = new MsgIdReq(); - mir->mMsgIds = filteredMsgIds; - req = mir; - - } - - if(req == nullptr) - { - RsErr() << "RsGxsDataAccess::requestMsgInfo() request type not recognised, type " << reqType << std::endl; - return false; - }else - { - generateToken(token); -#ifdef DATA_DEBUG - GXSDATADEBUG << "RsGxsDataAccess::requestMsgInfo() gets Token: " << token << std::endl; -#endif - } - - setReq(req, token, ansType, opts); - storeRequest(req); - return true; -} - -bool RsGxsDataAccess::requestMsgInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list& grpIds) -{ - GxsRequest* req = nullptr; - uint32_t reqType = opts.mReqType; - - std::list::const_iterator lit = grpIds.begin(); - - if(reqType & GXS_REQUEST_TYPE_MSG_META) - { - MsgMetaReq* mmr = new MsgMetaReq(); - - for(; lit != grpIds.end(); ++lit) - mmr->mMsgIds[*lit] = std::set(); - - req = mmr; - } - else if(reqType & GXS_REQUEST_TYPE_MSG_DATA) - { - MsgDataReq* mdr = new MsgDataReq(); - - for(; lit != grpIds.end(); ++lit) - mdr->mMsgIds[*lit] = std::set(); - - req = mdr; - } - else if(reqType & GXS_REQUEST_TYPE_MSG_IDS) - { - MsgIdReq* mir = new MsgIdReq(); - - for(; lit != grpIds.end(); ++lit) - mir->mMsgIds[*lit] = std::set(); - - req = mir; - } - - if(req == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " request type not recognised, type " << reqType << std::endl; - return false; - }else - { - generateToken(token); -#ifdef DATA_DEBUG - GXSDATADEBUG << __PRETTY_FUNCTION__ << " gets Token: " << token << std::endl; -#endif - } - - setReq(req, token, ansType, opts); - storeRequest(req); - return true; -} - - -void RsGxsDataAccess::requestServiceStatistic(uint32_t& token,const RsTokReqOptions& opts) -{ - ServiceStatisticRequest* req = new ServiceStatisticRequest(); - - generateToken(token); - - if(opts.mReqType != GXS_REQUEST_TYPE_SERVICE_STATS) - { - RsErr() << "Expected opts.mReqType to be GXS_REQUEST_TYPE_SERVICE_STATS requestServiceStatistic()" << std::endl; - return; - } - - setReq(req, token, 0, opts); - storeRequest(req); -} - -void RsGxsDataAccess::requestGroupStatistic(uint32_t& token, const RsGxsGroupId& grpId,const RsTokReqOptions& opts) -{ - GroupStatisticRequest* req = new GroupStatisticRequest(); - req->mGrpId = grpId; - - if(opts.mReqType != GXS_REQUEST_TYPE_GROUP_STATS) - { - RsErr() << "Expected opts.mReqType to be GXS_REQUEST_TYPE_SERVICE_STATS requestServiceStatistic()" << std::endl; - return; - } - - generateToken(token); - - setReq(req, token,0, opts); - storeRequest(req); -} - -bool RsGxsDataAccess::requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::vector &msgIds) -{ - - MsgRelatedInfoReq* req = new MsgRelatedInfoReq(); - req->mMsgIds = msgIds; - - generateToken(token); - - setReq(req, token, ansType, opts); - storeRequest(req); - - return true; -} - - -void RsGxsDataAccess::setReq(GxsRequest* req, uint32_t token, uint32_t ansType, const RsTokReqOptions& opts) const -{ - req->token = token; - req->clientAnswerType = ansType; - req->Options = opts; - return; -} -void RsGxsDataAccess::storeRequest(GxsRequest* req) -{ - RS_STACK_MUTEX(mDataMutex); - req->status = PENDING; - req->reqTime = time(nullptr); - - mRequestQueue.insert(std::make_pair(req->token,req)); - mPublicToken[req->token] = PENDING; - -#ifdef DATA_DEBUG - GXSDATADEBUG << "Stored request token=" << req->token << " priority = " << static_cast(req->Options.mPriority) << " Current request Queue is:" ; - for(auto it(mRequestQueue.begin());it!=mRequestQueue.end();++it) - GXSDATADEBUG << it->first << " (p=" << static_cast(req->Options.mPriority) << ") "; - GXSDATADEBUG << std::endl; - GXSDATADEBUG << "PublicToken size: " << mPublicToken.size() << " Completed requests waiting for client: " << mCompletedRequests.size() << std::endl; -#endif -} - -RsTokenService::GxsRequestStatus RsGxsDataAccess::requestStatus(uint32_t token) -{ - RsTokenService::GxsRequestStatus status; - uint32_t reqtype; - uint32_t anstype; - rstime_t ts; - - if (!checkRequestStatus(token, status, reqtype, anstype, ts)) - return RsTokenService::FAILED; - - return status; -} - -bool RsGxsDataAccess::cancelRequest(const uint32_t& token) -{ - RsStackMutex stack(mDataMutex); /****** LOCKED *****/ - - GxsRequest* req = locked_retrieveCompletedRequest(token); - if (!req) - { - return false; - } - - req->status = CANCELLED; - - return true; -} - -bool RsGxsDataAccess::clearRequest(const uint32_t& token) -{ - RS_STACK_MUTEX(mDataMutex); - return locked_clearRequest(token); -} - -bool RsGxsDataAccess::locked_clearRequest(const uint32_t& token) -{ - auto it = mCompletedRequests.find(token); - - if(it == mCompletedRequests.end()) - return false; - - delete it->second; - mCompletedRequests.erase(it); - - auto it2 = mPublicToken.find(token); - if(it2 != mPublicToken.end()) - mPublicToken.erase(it2); - -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": Removing public token " << token << ". Completed tokens: " << mCompletedRequests.size() << " Size of mPublicToken: " << mPublicToken.size() << std::endl; -#endif - return true; -} - -bool RsGxsDataAccess::getGroupSummary(const uint32_t& token, std::list >& groupInfo) -{ - RS_STACK_MUTEX(mDataMutex); - - GxsRequest* req = locked_retrieveCompletedRequest(token); - - if(req == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " Unable to retrieve group summary" << std::endl; - return false; - } - - GroupMetaReq* gmreq = dynamic_cast(req); - - if(gmreq) - { - groupInfo = gmreq->mGroupMetaData; - gmreq->mGroupMetaData.clear(); - } - else - { - RsErr() << __PRETTY_FUNCTION__ << " Req found, failed cast" << std::endl; - return false; - } - locked_clearRequest(token); - - return true; -} - -bool RsGxsDataAccess::getGroupData(const uint32_t& token, std::list& grpData) -{ - RS_STACK_MUTEX(mDataMutex); - - GxsRequest* req = locked_retrieveCompletedRequest(token); - - if(req == nullptr) - { - RsErr() << "RsGxsDataAccess::getGroupData() Unable to retrieve group data" << std::endl; - return false; - } - - GroupDataReq* gmreq = dynamic_cast(req); - GroupSerializedDataReq* gsreq = dynamic_cast(req); - - if(gsreq) - { - grpData.swap(gsreq->mGroupData); - gsreq->mGroupData.clear(); - } - else if(gmreq) - { - grpData.swap(gmreq->mGroupData); - gmreq->mGroupData.clear(); - } - else - { - RsErr() << __PRETTY_FUNCTION__ << " Req found, failed cast req->reqType: " << req->reqType << std::endl; - return false; - } - locked_clearRequest(token); - - return true; -} - -bool RsGxsDataAccess::getMsgData(const uint32_t& token, NxsMsgDataResult& msgData) -{ - - RsStackMutex stack(mDataMutex); - - GxsRequest* req = locked_retrieveCompletedRequest(token); - - if(req == nullptr) - { - - RsErr() << __PRETTY_FUNCTION__ << " Unable to retrieve group data" << std::endl; - return false; - } - - MsgDataReq* mdreq = dynamic_cast(req); - - if(mdreq) - { - msgData.swap(mdreq->mMsgData); - mdreq->mMsgData.clear(); - } - else - { - RsErr() << "RsGxsDataAccess::getMsgData() Req found, failed caste" << std::endl; - return false; - } - locked_clearRequest(token); - - return true; -} - -bool RsGxsDataAccess::getMsgRelatedData(const uint32_t& token, NxsMsgRelatedDataResult& msgData) -{ - - RsStackMutex stack(mDataMutex); - - GxsRequest* req = locked_retrieveCompletedRequest(token); - - if(req == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " Unable to retrieve group data" << std::endl; - return false; - } - MsgRelatedInfoReq* mrireq = dynamic_cast(req); - - if(req->Options.mReqType != GXS_REQUEST_TYPE_MSG_RELATED_DATA) - return false; - - if(mrireq) - { - msgData.swap(mrireq->mMsgDataResult); - mrireq->mMsgDataResult.clear(); - } - else - { - RsErr() << __PRETTY_FUNCTION__ << " Req found, failed caste" << std::endl; - return false; - } - - locked_clearRequest(token); - - return true; -} - -bool RsGxsDataAccess::getMsgSummary(const uint32_t& token, GxsMsgMetaResult& msgInfo) -{ - - RsStackMutex stack(mDataMutex); - - GxsRequest* req = locked_retrieveCompletedRequest(token); - - if(req == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " Unable to retrieve group data" << std::endl; - return false; - } - MsgMetaReq* mmreq = dynamic_cast(req); - - if(mmreq) - { - msgInfo.swap(mmreq->mMsgMetaData); - mmreq->mMsgMetaData.clear(); - } - else - { - RsErr() << " Req found, failed caste" << std::endl; - return false; - } - locked_clearRequest(token); - return true; -} - -bool RsGxsDataAccess::getMsgRelatedSummary(const uint32_t &token, MsgRelatedMetaResult &msgMeta) -{ - RsStackMutex stack(mDataMutex); - - GxsRequest* req = locked_retrieveCompletedRequest(token); - - if(req == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " Unable to retrieve message summary" << std::endl; - return false; - } - if(req->Options.mReqType != GXS_REQUEST_TYPE_MSG_RELATED_META) - return false; - - MsgRelatedInfoReq* mrireq = dynamic_cast(req); - - if(mrireq) - { - msgMeta.swap(mrireq->mMsgMetaResult); - mrireq->mMsgMetaResult.clear(); - } - else - { - RsErr() << __PRETTY_FUNCTION__ << " Req found, failed caste" << std::endl; - return false; - } - locked_clearRequest(token); - return true; -} - - -bool RsGxsDataAccess::getMsgRelatedList(const uint32_t &token, MsgRelatedIdResult &msgIds) -{ - RsStackMutex stack(mDataMutex); - - GxsRequest* req = locked_retrieveCompletedRequest(token); - - if(req == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " Unable to retrieve message data" << std::endl; - return false; - } - if(req->Options.mReqType != GXS_REQUEST_TYPE_MSG_RELATED_IDS) - return false; - - MsgRelatedInfoReq* mrireq = dynamic_cast(req); - - if(mrireq) - { - msgIds.swap(mrireq->mMsgIdResult); - mrireq->mMsgIdResult.clear(); - } - else - { - RsErr() << __PRETTY_FUNCTION__ << " Req found, failed caste" << std::endl; - return false; - } - locked_clearRequest(token); - return true; -} - -bool RsGxsDataAccess::getMsgIdList(const uint32_t& token, GxsMsgIdResult& msgIds) -{ - RsStackMutex stack(mDataMutex); - - GxsRequest* req = locked_retrieveCompletedRequest(token); - - if(req == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " Unable to retrieve msg Ids" << std::endl; - return false; - } - MsgIdReq* mireq = dynamic_cast(req); - - if(mireq) - { - msgIds.swap(mireq->mMsgIdResult); - mireq->mMsgIdResult.clear(); - } - else - { - RsErr() << __PRETTY_FUNCTION__ << " Req found, failed cast" << std::endl; - return false; - } - locked_clearRequest(token); - return true; -} - -bool RsGxsDataAccess::getGroupList(const uint32_t& token, std::list& groupIds) -{ - RsStackMutex stack(mDataMutex); - - GxsRequest* req = locked_retrieveCompletedRequest(token); - - if(req == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " Unable to retrieve group Ids, Request does not exist" << std::endl; - return false; - } - GroupIdReq* gireq = dynamic_cast(req); - - if(gireq) - { - groupIds.swap(gireq->mGroupIdResult); - gireq->mGroupIdResult.clear(); - } - else - { - RsErr() << __PRETTY_FUNCTION__ << " Req found, failed caste" << std::endl; - return false; - } - locked_clearRequest(token); - return true; -} - -bool RsGxsDataAccess::getGroupStatistic(const uint32_t &token, GxsGroupStatistic &grpStatistic) -{ - RsStackMutex stack(mDataMutex); - - GxsRequest* req = locked_retrieveCompletedRequest(token); - - if(req == nullptr) - { - RsErr() << "RsGxsDataAccess::getGroupStatistic() Unable to retrieve grp stats" << std::endl; - return false; - } - GroupStatisticRequest* gsreq = dynamic_cast(req); - - if(gsreq) - grpStatistic = gsreq->mGroupStatistic; - else - { - RsErr() << __PRETTY_FUNCTION__ << " Req found, failed caste" << std::endl; - return false; - } - locked_clearRequest(token); - return true; -} - -bool RsGxsDataAccess::getServiceStatistic(const uint32_t &token, GxsServiceStatistic &servStatistic) -{ - RsStackMutex stack(mDataMutex); - - GxsRequest* req = locked_retrieveCompletedRequest(token); - - if(req == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " Unable to retrieve service stats" << std::endl; - return false; - } - ServiceStatisticRequest* ssreq = dynamic_cast(req); - - if(ssreq) - servStatistic = ssreq->mServiceStatistic; - else - { - RsErr() << __PRETTY_FUNCTION__ << " Req found, failed caste" << std::endl; - return false; - } - locked_clearRequest(token); - return true; -} -GxsRequest* RsGxsDataAccess::locked_retrieveCompletedRequest(const uint32_t& token) -{ - auto it = mCompletedRequests.find(token) ; - - if(it == mCompletedRequests.end()) - return nullptr; - - return it->second; -} - -#define MAX_REQUEST_AGE 120 // 2 minutes - -void RsGxsDataAccess::processRequests() -{ - // process requests - - while (!mRequestQueue.empty()) - { -#ifdef DATA_DEBUG - dumpTokenQueues(); -#endif - // Extract the first elements from the request queue. cleanup all other elements marked at terminated. - - GxsRequest* req = nullptr; - { - RsStackMutex stack(mDataMutex); /******* LOCKED *******/ - rstime_t now = time(nullptr); // this is ok while in the loop below - - while(!mRequestQueue.empty() && req == nullptr) - { - if(now > mRequestQueue.begin()->second->reqTime + MAX_REQUEST_AGE) - { - mPublicToken[mRequestQueue.begin()->second->token] = CANCELLED; - delete mRequestQueue.begin()->second; - mRequestQueue.erase(mRequestQueue.begin()); - continue; - } - - switch( mRequestQueue.begin()->second->status ) - { - case PARTIAL: - RsErr() << "Found partial request in mRequestQueue. This is a bug." << std::endl; // fallthrough - case COMPLETE: - case DONE: - case FAILED: - case CANCELLED: -#ifdef DATA_DEBUG - GXSDATADEBUG << " Service " << std::hex << mDataStore->serviceType() << std::dec << ": request " << mRequestQueue.begin()->second->token << ": status = " << mRequestQueue.begin()->second->status << ": removing from the RequestQueue" << std::endl; -#endif - delete mRequestQueue.begin()->second; - mRequestQueue.erase(mRequestQueue.begin()); - continue; - break; - case PENDING: - req = mRequestQueue.begin()->second; - req->status = PARTIAL; - mRequestQueue.erase(mRequestQueue.begin()); // remove it right away from the waiting queue. - break; - } - - } - } // END OF MUTEX. - - if (!req) - break; - - GroupMetaReq* gmr; - GroupDataReq* gdr; - GroupIdReq* gir; - - MsgMetaReq* mmr; - MsgDataReq* mdr; - MsgIdReq* mir; - MsgRelatedInfoReq* mri; - GroupStatisticRequest* gsr; - GroupSerializedDataReq* grr; - ServiceStatisticRequest* ssr; - -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": Processing request: " << req->token << " Status: " << req->status << " ReqType: " << req->reqType << " Age: " << time(nullptr) - req->reqTime << std::endl; -#endif - - /* PROCESS REQUEST! */ - bool ok = false; - - if((gmr = dynamic_cast(req)) != nullptr) - { - ok = getGroupSummary(gmr); - } - else if((gdr = dynamic_cast(req)) != nullptr) - { - ok = getGroupData(gdr); - } - else if((gir = dynamic_cast(req)) != nullptr) - { - ok = getGroupList(gir); - } - else if((mmr = dynamic_cast(req)) != nullptr) - { - ok = getMsgSummary(mmr); - } - else if((mdr = dynamic_cast(req)) != nullptr) - { - ok = getMsgData(mdr); - } - else if((mir = dynamic_cast(req)) != nullptr) - { - ok = getMsgIdList(mir); - } - else if((mri = dynamic_cast(req)) != nullptr) - { - ok = getMsgRelatedInfo(mri); - } - else if((gsr = dynamic_cast(req)) != nullptr) - { - ok = getGroupStatistic(gsr); - } - else if((ssr = dynamic_cast(req)) != nullptr) - { - ok = getServiceStatistic(ssr); - } - else if((grr = dynamic_cast(req)) != nullptr) - { - ok = getGroupSerializedData(grr); - } - else - RsErr() << __PRETTY_FUNCTION__ << " Failed to process request, token: " << req->token << std::endl; - - // We cannot easily remove the request here because the queue may have more elements now and mRequestQueue.begin() is not necessarily the same element. - // but we mark it as COMPLETE/FAILED so that it will be removed in the next loop. - { - RsStackMutex stack(mDataMutex); /******* LOCKED *******/ - - if(ok) - { - // When the request is complete, we move it to the complete list, so that the caller can easily retrieve the request data - -#ifdef DATA_DEBUG - GXSDATADEBUG << " Service " << std::hex << mDataStore->serviceType() << std::dec << ": Request completed successfully. Marking as COMPLETE." << std::endl; -#endif - req->status = COMPLETE ; - mCompletedRequests[req->token] = req; - mPublicToken[req->token] = COMPLETE; - } - else - { - mPublicToken[req->token] = FAILED; - delete req;//req belongs to no one now -#ifdef DATA_DEBUG - GXSDATADEBUG << " Service " << std::hex << mDataStore->serviceType() << std::dec << ": Request failed. Marking as FAILED." << std::endl; -#endif - } - } // END OF MUTEX. - - } -} - - - -bool RsGxsDataAccess::getGroupSerializedData(GroupSerializedDataReq* req) -{ - std::map grpData; - std::list grpIdsOut; - - getGroupList(req->mGroupIds, req->Options, grpIdsOut); - - if(grpIdsOut.empty()) - return true; - - - for(std::list::iterator lit = grpIdsOut.begin();lit != grpIdsOut.end();++lit) - grpData[*lit] = nullptr; - - bool ok = mDataStore->retrieveNxsGrps(grpData, true); - req->mGroupData.clear(); - - std::map::iterator mit = grpData.begin(); - - for(; mit != grpData.end(); ++mit) - req->mGroupData.push_back(mit->second) ; - - return ok; -} -bool RsGxsDataAccess::getGroupData(GroupDataReq* req) -{ - std::map grpData; - std::list grpIdsOut; - - getGroupList(req->mGroupIds, req->Options, grpIdsOut); - - if(grpIdsOut.empty()) - return true; - - std::list::iterator lit = grpIdsOut.begin(), - lit_end = grpIdsOut.end(); - - for(; lit != lit_end; ++lit) - { - grpData[*lit] = nullptr; - } - - bool ok = mDataStore->retrieveNxsGrps(grpData, true); - - std::map::iterator mit = grpData.begin(); - for(; mit != grpData.end(); ++mit) - req->mGroupData.push_back(mit->second); - - return ok; -} - -bool RsGxsDataAccess::getGroupSummary(GroupMetaReq* req) -{ - - RsGxsGrpMetaTemporaryMap grpMeta; - std::list grpIdsOut; - - getGroupList(req->mGroupIds, req->Options, grpIdsOut); - - if(grpIdsOut.empty()) - return true; - - for(auto lit = grpIdsOut.begin();lit != grpIdsOut.end(); ++lit) - grpMeta[*lit] = nullptr; - - mDataStore->retrieveGxsGrpMetaData(grpMeta); - - for(auto mit = grpMeta.begin(); mit != grpMeta.end(); ++mit) - req->mGroupMetaData.push_back(mit->second); - - return true; -} - -bool RsGxsDataAccess::getGroupList(GroupIdReq* req) -{ - return getGroupList(req->mGroupIds, req->Options, req->mGroupIdResult); -} - -bool RsGxsDataAccess::getGroupList(const std::list& grpIdsIn, const RsTokReqOptions& opts, std::list& grpIdsOut) -{ - RsGxsGrpMetaTemporaryMap grpMeta; - - for(auto lit = grpIdsIn.begin(); lit != grpIdsIn.end(); ++lit) - grpMeta[*lit] = nullptr; - - mDataStore->retrieveGxsGrpMetaData(grpMeta); - - for(auto mit = grpMeta.begin() ; mit != grpMeta.end(); ++mit) - grpIdsOut.push_back(mit->first); - - filterGrpList(grpIdsOut, opts, grpMeta); - - return true; -} - -bool RsGxsDataAccess::getMsgData(MsgDataReq* req) -{ - GxsMsgReq msgIdOut; - - const RsTokReqOptions& opts(req->Options); - - // filter based on options - getMsgIdList(req->mMsgIds, opts, msgIdOut); - - // If the list is empty because of filtering do not retrieve from DB - if((opts.mMsgFlagMask || opts.mStatusMask) && msgIdOut.empty()) - return true; - - mDataStore->retrieveNxsMsgs(msgIdOut, req->mMsgData, true); - return true; -} - - -bool RsGxsDataAccess::getMsgSummary(MsgMetaReq* req) -{ - GxsMsgReq msgIdOut; - - const RsTokReqOptions& opts(req->Options); - - // filter based on options - getMsgMetaDataList(req->mMsgIds, opts, req->mMsgMetaData); - -// // If the list is empty because of filtering do not retrieve from DB -// if((opts.mMsgFlagMask || opts.mStatusMask) && msgIdOut.empty()) -// return true; -// -// mDataStore->retrieveGxsMsgMetaData(msgIdOut, req->mMsgMetaData); - - return true; -} - -bool RsGxsDataAccess::getMsgMetaDataList( const GxsMsgReq& msgIds, const RsTokReqOptions& opts, GxsMsgMetaResult& result ) -{ - // First get all message metas, then filter out the ones we want to keep. - result.clear(); - mDataStore->retrieveGxsMsgMetaData(msgIds, result); - - /* CASEs this handles. - * Input is groupList + Flags. - * 1) No Flags => All Messages in those Groups. - * - */ -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": RsGxsDataAccess::getMsgList()" << std::endl; -#endif - - bool onlyOrigMsgs = false; - bool onlyLatestMsgs = false; - bool onlyThreadHeadMsgs = false; - - // Can only choose one of these two. - if (opts.mOptions & RS_TOKREQOPT_MSG_ORIGMSG) - { -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": RsGxsDataAccess::getMsgList() MSG_ORIGMSG" << std::endl; -#endif - onlyOrigMsgs = true; - } - else if (opts.mOptions & RS_TOKREQOPT_MSG_LATEST) - { -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": RsGxsDataAccess::getMsgList() MSG_LATEST" << std::endl; -#endif - onlyLatestMsgs = true; - } - - if (opts.mOptions & RS_TOKREQOPT_MSG_THREAD) - { -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": RsGxsDataAccess::getMsgList() MSG_THREAD" << std::endl; -#endif - onlyThreadHeadMsgs = true; - } - - GxsMsgMetaResult::iterator meta_it; - - for(meta_it = result.begin(); meta_it != result.end(); ++meta_it) - { - //const RsGxsGroupId& grpId = meta_it->first; - - //auto& filter( metaFilter[grpId] ); // does the initialization of metaFilter[grpId] and avoids further O(log(n)) calls - - auto& metaV = meta_it->second; - - if (onlyLatestMsgs) // if we only consider latest messages, we need to first filter out messages with "children" - { - // The strategy is the following: for each msg we only know its direct ancestor. So we build a map to be able to find for a given message - // which messages derive from it. - // Then when this map is fuly build, we follow this map and every message that has no direct follow up will be kept. - // Because msgs are stored in a std::vector we build a map to convert each vector to its position in metaV. - - std::vector keep(metaV.size(),true); // this vector will tell wether we keep or not a given Meta - std::map index_in_metaV; // holds the index of each group Id in metaV - - for(uint32_t i=0;imMsgId] = i; - - // Now loop once over message Metas and see if they have a parent. If yes, then mark the parent to be discarded. - - for(uint32_t i=0;imOrigMsgId.isNull() && metaV[i]->mOrigMsgId != metaV[i]->mMsgId) // this one is a follow up - { - auto it = index_in_metaV.find(metaV[i]->mOrigMsgId); - - if(it != index_in_metaV.end()) - keep[it->second] = false; - else - std::cerr << "Found a msg that has a parent that is not locally known. Not an error anyway." << std::endl; - - } - - // Finally we just discard the messages for which the keep flag has been set to false. - - for(uint32_t i=0;i TS. - std::map > origMsgTs; - - for(uint32_t i=0;imParentId.isNull())) - { - delete msgMeta; - metaV[i] = nullptr; - continue; - } - - auto oit = origMsgTs.find(msgMeta->mOrigMsgId); - - bool addMsg = false; - if (oit != origMsgTs.end()) - { - if(oit->second.second > msgMeta->mPublishTs) - { -#ifdef DATA_DEBUG - std::cerr << "RsGxsDataAccess::getMsgList() Found New OrigMsgId: "; - std::cerr << msgMeta->mOrigMsgId; - std::cerr << " MsgId: " << msgMeta->mMsgId; - std::cerr << " TS: " << msgMeta->mPublishTs; - std::cerr << std::endl; -#endif - origMsgTs[msgMeta->mOrigMsgId] = std::make_pair(msgMeta->mMsgId, msgMeta->mPublishTs); // add as latest. (overwriting if necessary) - } - } - else - { - delete msgMeta; - metaV[i] = nullptr; - continue; - } - - - } - - // Add the discovered Latest Msgs. - for(auto oit = origMsgTs.begin(); oit != origMsgTs.end(); ++oit) - { - msgIdsOut[grpId].insert(oit->second.first); - } -#endif - - for(uint32_t i=0;imParentId.isNull()) - { - //delete msgMeta; - metaV[i] = nullptr; - continue; - } - - if (onlyOrigMsgs && !msgMeta->mOrigMsgId.isNull() && msgMeta->mMsgId != msgMeta->mOrigMsgId) - { - //delete msgMeta; - metaV[i] = nullptr; - continue; - } - } - } - - // collapse results while keeping the order, eliminating empty slots - - for(auto it(result.begin());it!=result.end();++it) - { - uint32_t j=0; // j is the end of the cleaned-up tab, at the first available place - - for(uint32_t i=0;isecond.size();++i) // i is the index in the tab possibly containing nullptr's - if(it->second[i] != nullptr) - { - it->second[j] = it->second[i]; // move the pointer to the first available place - ++j; - } - - it->second.resize(j); // normally all pointers have been moved forward so there is nothing to delete here. - } - - // filterMsgIdList(msgIdsOut, opts, metaFilter); // this call is absurd: we already have in metaFilter the content we want. - - //metaFilter.clear(); - - // delete meta data - //cleanseMsgMetaMap(result); - - return true; -} - -bool RsGxsDataAccess::getMsgIdList( const GxsMsgReq& msgIds, const RsTokReqOptions& opts, GxsMsgReq& msgIdsOut ) -{ - GxsMsgMetaResult result; - - getMsgMetaDataList( msgIds, opts, result ); - - // extract MessageIds - - msgIdsOut.clear(); - - for(auto it(result.begin());it!=result.end();++it) - { - auto& id_set(msgIdsOut[it->first]); - - for(uint32_t i=0;isecond.size();++i) - id_set.insert(it->second[i]->mMsgId); - } - - // delete meta data - //cleanseMsgMetaMap(result); - - return true; -} - -bool RsGxsDataAccess::getMsgRelatedInfo(MsgRelatedInfoReq *req) -{ - /* CASEs this handles. - * Input is msgList + Flags. - * 1) No Flags => return nothing - */ -#ifdef DATA_DEBUG - GXSDATADEBUG << "RsGxsDataAccess::getMsgRelatedList()" << std::endl; -#endif - - const RsTokReqOptions& opts = req->Options; - - bool onlyLatestMsgs = false; - bool onlyAllVersions = false; - bool onlyChildMsgs = false; - bool onlyThreadMsgs = false; - - if (opts.mOptions & RS_TOKREQOPT_MSG_LATEST) - { -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": RsGxsDataAccess::getMsgRelatedList() MSG_LATEST" << std::endl; -#endif - onlyLatestMsgs = true; - } - else if (opts.mOptions & RS_TOKREQOPT_MSG_VERSIONS) - { -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": RsGxsDataAccess::getMsgRelatedList() MSG_VERSIONS" << std::endl; -#endif - onlyAllVersions = true; - } - - if (opts.mOptions & RS_TOKREQOPT_MSG_PARENT) - { -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": RsGxsDataAccess::getMsgRelatedList() MSG_PARENTS" << std::endl; -#endif - onlyChildMsgs = true; - } - - if (opts.mOptions & RS_TOKREQOPT_MSG_THREAD) - { -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": RsGxsDataAccess::getMsgRelatedList() MSG_THREAD" << std::endl; -#endif - onlyThreadMsgs = true; - } - - if(onlyAllVersions && onlyChildMsgs) - { - RS_ERR("Incompatible FLAGS (VERSIONS & PARENT)"); - return false; - } - - if(onlyAllVersions && onlyThreadMsgs) - { - RS_ERR("Incompatible FLAGS (VERSIONS & THREAD)"); - return false; - } - - if((!onlyLatestMsgs) && onlyChildMsgs) - { - RS_ERR("Incompatible FLAGS (!LATEST & PARENT)"); - return false; - } - - if((!onlyLatestMsgs) && onlyThreadMsgs) - { - RS_ERR("Incompatible FLAGS (!LATEST & THREAD)"); - return false; - } - - if(onlyChildMsgs && onlyThreadMsgs) - { - RS_ERR("Incompatible FLAGS (PARENT & THREAD)"); - return false; - } - - if( (!onlyLatestMsgs) && (!onlyAllVersions) && (!onlyChildMsgs) && - (!onlyThreadMsgs) ) - { - RS_WARN("NO FLAGS -> SIMPLY RETURN nothing"); - return true; - } - - for(auto vit_msgIds(req->mMsgIds.begin()); vit_msgIds != req->mMsgIds.end(); ++vit_msgIds) - { - MsgMetaFilter filterMap; - - - const RsGxsGrpMsgIdPair& grpMsgIdPair = *vit_msgIds; - - // get meta data for all in group - GxsMsgMetaResult result; - GxsMsgReq msgIds; - msgIds.insert(std::make_pair(grpMsgIdPair.first, std::set())); - mDataStore->retrieveGxsMsgMetaData(msgIds, result); - auto& metaV = result[grpMsgIdPair.first]; - - // msg id to relate to - const RsGxsMessageId& msgId = grpMsgIdPair.second; - const RsGxsGroupId& grpId = grpMsgIdPair.first; - - std::set outMsgIds; - - std::shared_ptr origMeta; - - for(auto vit_meta = metaV.begin(); vit_meta != metaV.end(); ++vit_meta) - if(msgId == (*vit_meta)->mMsgId) - { - origMeta = *vit_meta; - break; - } - - if(!origMeta) - { - RS_ERR("Cannot find meta of msgId: ", msgId, " to relate to"); - return false; - } - - const RsGxsMessageId& origMsgId = origMeta->mOrigMsgId; - auto& metaMap = filterMap[grpId]; - - if (onlyLatestMsgs) - { - if (onlyChildMsgs || onlyThreadMsgs) - { - // RUN THROUGH ALL MSGS... in map origId -> TS. - std::map > origMsgTs; - std::map >::iterator oit; - - for(auto vit_meta = metaV.begin(); vit_meta != metaV.end(); ++vit_meta) - { - auto meta = *vit_meta; - - // skip msgs that aren't children. - if (onlyChildMsgs) - { - if (meta->mParentId != origMsgId) - { - continue; - } - } - else /* onlyThreadMsgs */ - { - if (meta->mThreadId != msgId) - { - continue; - } - } - - - oit = origMsgTs.find(meta->mOrigMsgId); - - bool addMsg = false; - if (oit == origMsgTs.end()) - { -#ifdef DATA_DEBUG - GXSDATADEBUG << "RsGxsDataAccess::getMsgRelatedList() Found New OrigMsgId: " - << meta->mOrigMsgId - << " MsgId: " << meta->mMsgId - << " TS: " << meta->mPublishTs - << std::endl; -#endif - - addMsg = true; - } - // check timestamps. - else if (oit->second.second < meta->mPublishTs) - { -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": RsGxsDataAccess::getMsgRelatedList() Found Later Msg. OrigMsgId: " - << meta->mOrigMsgId - << " MsgId: " << meta->mMsgId - << " TS: " << meta->mPublishTs - << std::endl; -#endif - - addMsg = true; - } - - if (addMsg) - { - // add as latest. (overwriting if necessary) - origMsgTs[meta->mOrigMsgId] = std::make_pair(meta->mMsgId, meta->mPublishTs); - metaMap.insert(std::make_pair(meta->mMsgId, meta)); - } - } - - // Add the discovered Latest Msgs. - for(oit = origMsgTs.begin(); oit != origMsgTs.end(); ++oit) - { - outMsgIds.insert(oit->second.first); - } - } - else - { - - /* first guess is potentially better than Orig (can't be worse!) */ - rstime_t latestTs = 0; - RsGxsMessageId latestMsgId; - std::shared_ptr latestMeta; - - for(auto vit_meta = metaV.begin(); vit_meta != metaV.end(); ++vit_meta) - if ((*vit_meta)->mOrigMsgId == origMsgId) - { - if ((*vit_meta)->mPublishTs > latestTs) - { - latestTs = (*vit_meta)->mPublishTs; - latestMsgId = (*vit_meta)->mMsgId; - latestMeta = (*vit_meta); - } - } - - outMsgIds.insert(latestMsgId); - metaMap.insert(std::make_pair(latestMsgId, latestMeta)); - } - } - else if (onlyAllVersions) - { - for(auto vit_meta = metaV.begin(); vit_meta != metaV.end(); ++vit_meta) - if ((*vit_meta)->mOrigMsgId == origMsgId) - { - outMsgIds.insert((*vit_meta)->mMsgId); - metaMap.insert(std::make_pair((*vit_meta)->mMsgId, (*vit_meta))); - } - } - - GxsMsgIdResult filteredOutMsgIds; - filteredOutMsgIds[grpId] = outMsgIds; - filterMsgIdList(filteredOutMsgIds, opts, filterMap); - - if(!filteredOutMsgIds[grpId].empty()) - { - if(req->Options.mReqType == GXS_REQUEST_TYPE_MSG_RELATED_IDS) - { - req->mMsgIdResult[grpMsgIdPair] = filteredOutMsgIds[grpId]; - } - else if(req->Options.mReqType == GXS_REQUEST_TYPE_MSG_RELATED_META) - { - GxsMsgMetaResult metaResult; - mDataStore->retrieveGxsMsgMetaData(filteredOutMsgIds, metaResult); - req->mMsgMetaResult[grpMsgIdPair] = metaResult[grpId]; - } - else if(req->Options.mReqType == GXS_REQUEST_TYPE_MSG_RELATED_DATA) - { - GxsMsgResult msgResult; - mDataStore->retrieveNxsMsgs(filteredOutMsgIds, msgResult, true); - req->mMsgDataResult[grpMsgIdPair] = msgResult[grpId]; - } - } - - outMsgIds.clear(); - filteredOutMsgIds.clear(); - } - return true; -} - -bool RsGxsDataAccess::getGroupStatistic(GroupStatisticRequest *req) -{ - // filter based on options - GxsMsgIdResult metaReq; - metaReq[req->mGrpId] = std::set(); - GxsMsgMetaResult metaResult; - mDataStore->retrieveGxsMsgMetaData(metaReq, metaResult); - - const auto& msgMetaV_it = metaResult.find(req->mGrpId); - - if(msgMetaV_it == metaResult.end()) - return false; - - const auto& msgMetaV(msgMetaV_it->second); - - req->mGroupStatistic.mGrpId = req->mGrpId; - req->mGroupStatistic.mNumMsgs = msgMetaV.size(); - req->mGroupStatistic.mTotalSizeOfMsgs = 0; - req->mGroupStatistic.mNumThreadMsgsNew = 0; - req->mGroupStatistic.mNumThreadMsgsUnread = 0; - req->mGroupStatistic.mNumChildMsgsNew = 0; - req->mGroupStatistic.mNumChildMsgsUnread = 0; - - std::set obsolete_msgs ; // stored message ids that are referred to as older versions of an existing message - - for(uint32_t i = 0; i < msgMetaV.size(); ++i) - if(!msgMetaV[i]->mOrigMsgId.isNull() && msgMetaV[i]->mOrigMsgId!=msgMetaV[i]->mMsgId) - obsolete_msgs.insert(msgMetaV[i]->mOrigMsgId); - - for(uint32_t i = 0; i < msgMetaV.size(); ++i) - { - const auto& m = msgMetaV[i]; - req->mGroupStatistic.mTotalSizeOfMsgs += m->mMsgSize + m->serial_size(); - - if(obsolete_msgs.find(m->mMsgId) != obsolete_msgs.end()) // skip obsolete messages. - continue; - - if (IS_MSG_NEW(m->mMsgStatus)) - { - if (m->mParentId.isNull()) - ++req->mGroupStatistic.mNumThreadMsgsNew; - else - ++req->mGroupStatistic.mNumChildMsgsNew; - } - if (IS_MSG_UNREAD(m->mMsgStatus)) - { - if (m->mParentId.isNull()) - ++req->mGroupStatistic.mNumThreadMsgsUnread; - else - ++req->mGroupStatistic.mNumChildMsgsUnread; - } - } - - return true; -} - -// potentially very expensive! -bool RsGxsDataAccess::getServiceStatistic(ServiceStatisticRequest *req) -{ - RsGxsGrpMetaTemporaryMap grpMeta ; - - mDataStore->retrieveGxsGrpMetaData(grpMeta); - - req->mServiceStatistic.mNumGrps = grpMeta.size(); - req->mServiceStatistic.mNumMsgs = 0; - req->mServiceStatistic.mSizeOfGrps = 0; - req->mServiceStatistic.mSizeOfMsgs = 0; - req->mServiceStatistic.mNumGrpsSubscribed = 0; - req->mServiceStatistic.mNumThreadMsgsNew = 0; - req->mServiceStatistic.mNumThreadMsgsUnread = 0; - req->mServiceStatistic.mNumChildMsgsNew = 0; - req->mServiceStatistic.mNumChildMsgsUnread = 0; - - for(auto mit = grpMeta.begin(); mit != grpMeta.end(); ++mit) - { - const auto& m = mit->second; - req->mServiceStatistic.mSizeOfGrps += m->mGrpSize + m->serial_size(RS_GXS_GRP_META_DATA_CURRENT_API_VERSION); - - if (IS_GROUP_SUBSCRIBED(m->mSubscribeFlags)) - { - ++req->mServiceStatistic.mNumGrpsSubscribed; - - GroupStatisticRequest gr; - gr.mGrpId = m->mGroupId; - getGroupStatistic(&gr); - - req->mServiceStatistic.mNumMsgs += gr.mGroupStatistic.mNumMsgs; - req->mServiceStatistic.mSizeOfMsgs += gr.mGroupStatistic.mTotalSizeOfMsgs; - req->mServiceStatistic.mNumThreadMsgsNew += gr.mGroupStatistic.mNumThreadMsgsNew; - req->mServiceStatistic.mNumThreadMsgsUnread += gr.mGroupStatistic.mNumThreadMsgsUnread; - req->mServiceStatistic.mNumChildMsgsNew += gr.mGroupStatistic.mNumChildMsgsNew; - req->mServiceStatistic.mNumChildMsgsUnread += gr.mGroupStatistic.mNumChildMsgsUnread; - } - } - - req->mServiceStatistic.mSizeStore = req->mServiceStatistic.mSizeOfGrps + req->mServiceStatistic.mSizeOfMsgs; - - return true; -} - -bool RsGxsDataAccess::getMsgIdList(MsgIdReq* req) -{ - - GxsMsgMetaResult result; - mDataStore->retrieveGxsMsgMetaData(req->mMsgIds, result); - - for(auto mit = result.begin(); mit != result.end(); ++mit) - { - const RsGxsGroupId grpId = mit->first; - auto& metaV = mit->second; - - for(auto vit=metaV.begin(); vit != metaV.end(); ++vit) - req->mMsgIdResult[grpId].insert((*vit)->mMsgId); - } - - GxsMsgReq msgIdOut; - - // filter based on options - getMsgIdList(req->mMsgIdResult, req->Options, msgIdOut); - req->mMsgIdResult = msgIdOut; - - return true; -} - -void RsGxsDataAccess::filterMsgIdList( GxsMsgIdResult& resultsMap, const RsTokReqOptions& opts, const MsgMetaFilter& msgMetas ) const -{ - for( GxsMsgIdResult::iterator grpIt = resultsMap.begin(); grpIt != resultsMap.end(); ++grpIt ) - { - const RsGxsGroupId& groupId(grpIt->first); - std::set& msgsIdSet(grpIt->second); - - MsgMetaFilter::const_iterator cit = msgMetas.find(groupId); - if(cit == msgMetas.end()) continue; -#ifdef DATA_DEBUG - GXSDATADEBUG << __PRETTY_FUNCTION__ << " " << msgsIdSet.size() - << " for group: " << groupId << " before filtering" - << std::endl; -#endif - - for( std::set::iterator msgIdIt = msgsIdSet.begin(); msgIdIt != msgsIdSet.end(); ) - { - const RsGxsMessageId& msgId(*msgIdIt); - const auto& msgsMetaMap = cit->second; - - bool keep = false; - auto msgsMetaMapIt = msgsMetaMap.find(msgId); - - if( msgsMetaMapIt != msgsMetaMap.end() ) - keep = checkMsgFilter(opts, msgsMetaMapIt->second); - - if(keep) - ++msgIdIt; - else - msgIdIt = msgsIdSet.erase(msgIdIt); - } - -#ifdef DATA_DEBUG - GXSDATADEBUG << __PRETTY_FUNCTION__ << " " << msgsIdSet.size() - << " for group: " << groupId << " after filtering" - << std::endl; -#endif - } -} - -void RsGxsDataAccess::filterGrpList(std::list &grpIds, const RsTokReqOptions &opts, const GrpMetaFilter& meta) const -{ - for(auto lit = grpIds.begin(); lit != grpIds.end(); ) - { - auto cit = meta.find(*lit); - - bool keep = false; - - if(cit != meta.end()) - keep = checkGrpFilter(opts, cit->second); - - if(keep) - ++lit; - else - lit = grpIds.erase(lit); - } -} - - -bool RsGxsDataAccess::checkRequestStatus( uint32_t token, GxsRequestStatus& status, uint32_t& reqtype, uint32_t& anstype, rstime_t& ts ) -{ - RS_STACK_MUTEX(mDataMutex); - - GxsRequest* req = locked_retrieveCompletedRequest(token); - -#ifdef DATA_DEBUG - GXSDATADEBUG << "CheckRequestStatus: token=" << token << std::endl ; -#endif - - if(req != nullptr) - { - anstype = req->clientAnswerType; - reqtype = req->reqType; - status = COMPLETE; - ts = req->reqTime; -#ifdef DATA_DEBUG - GXSDATADEBUG << " Returning status = COMPLETE" << std::endl; -#endif - return true; - } - - auto it = mPublicToken.find(token); - - if(it != mPublicToken.end()) - { - status = it->second; -#ifdef DATA_DEBUG - GXSDATADEBUG << " Returning status = " << status << std::endl; -#endif - return true; - } - - status = FAILED; -#ifdef DATA_DEBUG - GXSDATADEBUG << " Token not found. Returning FAILED" << std::endl; -#endif - return false; -} - -bool RsGxsDataAccess::addGroupData(RsNxsGrp* grp) { - - RsStackMutex stack(mDataMutex); - - std::list grpM; - grpM.push_back(grp); - return mDataStore->storeGroup(grpM); -} - -bool RsGxsDataAccess::updateGroupData(RsNxsGrp* grp) { - - RsStackMutex stack(mDataMutex); - - std::list grpM; - grpM.push_back(grp); - return mDataStore->updateGroup(grpM); -} - -bool RsGxsDataAccess::getGroupData(const RsGxsGroupId& grpId, RsNxsGrp *& grp_data) -{ - RsStackMutex stack(mDataMutex); - - std::map grps ; - - grps[grpId] = nullptr ; - - if(mDataStore->retrieveNxsGrps(grps, false)) // the false here is very important: it removes the private key parts. - { - grp_data = grps.begin()->second; - return true; - } - else - return false ; -} - -bool RsGxsDataAccess::addMsgData(RsNxsMsg* msg) { - - RsStackMutex stack(mDataMutex); - - std::list msgM; - msgM.push_back(msg); - return mDataStore->storeMessage(msgM); -} - - - -void RsGxsDataAccess::tokenList(std::list& tokens) -{ - - RsStackMutex stack(mDataMutex); - - for(auto& it:mRequestQueue) - tokens.push_back(it.second->token); - - for(auto& it:mCompletedRequests) - tokens.push_back(it.first); -} - -bool RsGxsDataAccess::locked_updateRequestStatus( uint32_t token, RsTokenService::GxsRequestStatus status ) -{ - GxsRequest* req = locked_retrieveCompletedRequest(token); - - if(req) req->status = status; - else return false; - - return true; -} - -uint32_t RsGxsDataAccess::generatePublicToken() -{ - uint32_t token; - generateToken(token); - - { - RS_STACK_MUTEX(mDataMutex); - mPublicToken[token] = PENDING ; -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": Adding new public token " << token << " in PENDING state. Completed tokens: " << mCompletedRequests.size() << " Size of mPublicToken: " << mPublicToken.size() << std::endl; - if(mDataStore->serviceType() == 0x218 && token==19) - print_stacktrace(); -#endif - } - - return token; -} - - - -bool RsGxsDataAccess::updatePublicRequestStatus( uint32_t token, RsTokenService::GxsRequestStatus status ) -{ - RS_STACK_MUTEX(mDataMutex); - - auto mit = mPublicToken.find(token); - - if(mit != mPublicToken.end()) - { - mit->second = status; -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": updating public token " << token << " to state " << tokenStatusString[status] << std::endl; -#endif - return true; - } - else - return false; -} - - - -bool RsGxsDataAccess::disposeOfPublicToken(uint32_t token) -{ - RS_STACK_MUTEX(mDataMutex); - auto mit = mPublicToken.find(token); - if(mit != mPublicToken.end()) - { - mPublicToken.erase(mit); -#ifdef DATA_DEBUG - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": Deleting public token " << token << ". Completed tokens: " << mCompletedRequests.size() << " Size of mPublicToken: " << mPublicToken.size() << std::endl; -#endif - return true; - } - else - return false; -} - -#ifdef DATA_DEBUG -void RsGxsDataAccess::dumpTokenQueues() -{ - RS_STACK_MUTEX(mDataMutex); - - GXSDATADEBUG << "Service " << std::hex << mDataStore->serviceType() << std::dec << ": dumping token list."<< std::endl; - - for(auto tokenpair:mPublicToken) - GXSDATADEBUG << " Public Token " << tokenpair.first << " : " << tokenStatusString[tokenpair.second] << std::endl; - - for(auto tokenpair:mCompletedRequests) - GXSDATADEBUG << " Completed Tokens: " << tokenpair.first << std::endl; - - for(auto tokenpair:mRequestQueue) - GXSDATADEBUG << " RequestQueue: " << tokenpair.first << " status " << tokenStatusString[tokenpair.second->status] << std::endl; - - GXSDATADEBUG << std::endl; -} -#endif - -bool RsGxsDataAccess::checkGrpFilter(const RsTokReqOptions &opts, const std::shared_ptr& meta) const -{ - - bool subscribeMatch = false; - - if(opts.mSubscribeMask) - { - // Exact Flags match required. - if ((opts.mSubscribeMask & opts.mSubscribeFilter) == (opts.mSubscribeMask & meta->mSubscribeFlags)) - { - subscribeMatch = true; - } - } - else - { - subscribeMatch = true; - } - - return subscribeMatch; -} -bool RsGxsDataAccess::checkMsgFilter(const RsTokReqOptions& opts, const std::shared_ptr &meta ) const -{ - if (opts.mStatusMask) - { - // Exact Flags match required. - if ( (opts.mStatusMask & opts.mStatusFilter) == - (opts.mStatusMask & meta->mMsgStatus) ) - { -#ifdef DATA_DEBUG - GXSDATADEBUG << __PRETTY_FUNCTION__ - << " Continue checking Msg as StatusMatches: " - << " Mask: " << opts.mStatusMask - << " StatusFilter: " << opts.mStatusFilter - << " MsgStatus: " << meta->mMsgStatus - << " MsgId: " << meta->mMsgId << std::endl; -#endif - } - else - { -#ifdef DATA_DEBUG - GXSDATADEBUG << __PRETTY_FUNCTION__ - << " Dropping Msg due to !StatusMatch " - << " Mask: " << opts.mStatusMask - << " StatusFilter: " << opts.mStatusFilter - << " MsgStatus: " << meta->mMsgStatus - << " MsgId: " << meta->mMsgId << std::endl; -#endif - - return false; - } - } - else - { -#ifdef DATA_DEBUG - GXSDATADEBUG << __PRETTY_FUNCTION__ - << " Status check not requested" - << " mStatusMask: " << opts.mStatusMask - << " MsgId: " << meta->mMsgId << std::endl; -#endif - } - - if(opts.mMsgFlagMask) - { - // Exact Flags match required. - if ( (opts.mMsgFlagMask & opts.mMsgFlagFilter) == - (opts.mMsgFlagMask & meta->mMsgFlags) ) - { -#ifdef DATA_DEBUG - GXSDATADEBUG << __PRETTY_FUNCTION__ - << " Accepting Msg as FlagMatches: " - << " Mask: " << opts.mMsgFlagMask - << " FlagFilter: " << opts.mMsgFlagFilter - << " MsgFlag: " << meta->mMsgFlags - << " MsgId: " << meta->mMsgId << std::endl; -#endif - } - else - { -#ifdef DATA_DEBUG - GXSDATADEBUG << __PRETTY_FUNCTION__ - << " Dropping Msg due to !FlagMatch " - << " Mask: " << opts.mMsgFlagMask - << " FlagFilter: " << opts.mMsgFlagFilter - << " MsgFlag: " << meta->mMsgFlags - << " MsgId: " << meta->mMsgId << std::endl; -#endif - - return false; - } - } - else - { -#ifdef DATA_DEBUG - GXSDATADEBUG << __PRETTY_FUNCTION__ - << " Flags check not requested" - << " mMsgFlagMask: " << opts.mMsgFlagMask - << " MsgId: " << meta->mMsgId << std::endl; -#endif - } - - return true; -} - -GxsGroupStatistic::~GxsGroupStatistic() = default; -GxsServiceStatistic::~GxsServiceStatistic() = default; diff --git a/libretroshare/src/gxs/rsgxsdataaccess.h b/libretroshare/src/gxs/rsgxsdataaccess.h deleted file mode 100644 index cf5c729bd..000000000 --- a/libretroshare/src/gxs/rsgxsdataaccess.h +++ /dev/null @@ -1,519 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsdataaccess.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Christopher Evi-Parker, Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RSGXSDATAACCESS_H -#define RSGXSDATAACCESS_H - -#include -#include "retroshare/rstokenservice.h" -#include "rsgxsrequesttypes.h" -#include "rsgds.h" - - -typedef std::map< RsGxsGroupId, std::map > > MsgMetaFilter; -typedef std::map< RsGxsGroupId, std::shared_ptr > GrpMetaFilter; - -bool operator<(const std::pair& p1,const std::pair& p2); - -class RsGxsDataAccess : public RsTokenService -{ -public: - explicit RsGxsDataAccess(RsGeneralDataService* ds); - virtual ~RsGxsDataAccess() ; - -public: - - /** S: RsTokenService - * TODO: cleanup - * In the following methods @param uint32_t ansType is of no use, it is - * deprecated and should be removed as soon as possible as it is cause of - * many confusions, instead use const RsTokReqOptions::mReqType &opts to - * specify the kind of data you are interested in. - * Most of the methods use const uint32_t &token as param type change it to - * uint32_t - */ - - /*! - * Use this to request group related information - * @param token The token returned for the request, store this value to pool for request completion - * @param ansType @deprecated unused @see S: RsTokenService notice - * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - * @param groupIds group id to request info for - * @return - */ - bool requestGroupInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds) override; - - /*! - * Use this to request all group related info - * @param token The token returned for the request, store this value to pool for request completion - * @param ansType @deprecated unused @see S: RsTokenService notice - * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - * @return - */ - bool requestGroupInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts) override; - - /*! - * Use this to get msg information (id, meta, or data), store token value to poll for request completion - * @param token The token returned for the request - * @param ansType @deprecated unused @see S: RsTokenService notice - * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - * @param groupIds The ids of the groups to get, second entry of map empty to query for all msgs - * @return true if request successful false otherwise - */ - bool requestMsgInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const GxsMsgReq& msgIds) override; - - /*! - * Use this to get message information (id, meta, or data), store token value to poll for request completion - * @param token The token returned for the request - * @param ansType @deprecated unused @see S: RsTokenService notice - * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - * @param groupIds The ids of the groups to get, this retrieve all the msgs info for each grpId in list, if group Id list is empty \n - * all messages for all groups are retrieved - * @return true if request successful false otherwise - */ - bool requestMsgInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list& grpIds) override; - - /*! - * For requesting msgs related to a given msg id within a group - * @param token The token returned for the request - * @param ansType @deprecated unused @see S: RsTokenService notice - * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - * @param groupIds The ids of the groups to get, second entry of map empty to query for all msgs - * @return true if request successful false otherwise - */ - bool requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::vector &msgIds) override; - - /*! - * This request statistics on amount of data held - * number of groups - * number of groups subscribed - * number of messages - * size of db store - * total size of messages - * total size of groups - * @param token - * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - */ - void requestServiceStatistic(uint32_t& token, const RsTokReqOptions &opts) override; - - /*! - * To request statistic on a group - * @param token set to value to be redeemed to get statistic - * @param grpId the id of the group - * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - */ - void requestGroupStatistic(uint32_t& token, const RsGxsGroupId& grpId, const RsTokReqOptions &opts) override; - - /* Poll */ - GxsRequestStatus requestStatus(uint32_t token); - - /* Cancel Request */ - bool cancelRequest(const uint32_t &token); - - - /** E: RsTokenService **/ - -public: - - /*! - * This adds a groups to the gxs data base, this is a blocking call \n - * If function returns successfully DataAccess can be queried for grp - * @param grp the group to add, responsibility grp passed lies with callee - * @return false if group cound not be added - */ - bool addGroupData(RsNxsGrp* grp); - - /*! - * This updates a groups in the gxs data base, this is a blocking call \n - * If function returns successfully DataAccess can be queried for grp - * @param grp the group to add, responsibility grp passed lies with callee - * @return false if group cound not be added - */ - bool updateGroupData(RsNxsGrp* grp); - - /*! - * This adds a group to the gxs data base, this is a blocking call \n - * Responsibility for msg still lies with callee \n - * If function returns successfully DataAccess can be queried for msg - * @param msg the msg to add - * @return false if msg could not be added, true otherwise - */ - bool addMsgData(RsNxsMsg* msg); - - /*! - * This retrieves a group from the gxs data base, this is a blocking call \n - * @param grp the group to add, memory ownership passed to the callee - * @return false if group cound not be retrieved - */ - bool getGroupData(const RsGxsGroupId& grpId,RsNxsGrp *& grp_data); - - -public: - - - - /*! - * This must be called periodically to progress requests - */ - void processRequests(); - - /*! - * @param token - * @param grpStatistic - * @return false if token cannot be redeemed - */ - bool getGroupStatistic(const uint32_t &token, GxsGroupStatistic& grpStatistic); - - /*! - * @param token - * @param servStatistic - * @return false if token cannot be redeemed - */ - bool getServiceStatistic(const uint32_t &token, GxsServiceStatistic& servStatistic); - - - /*! - * Retrieve group list for a given token - * @param token request token to be redeemed - * @param groupIds - * @param msgIds - * @return false if token cannot be redeemed, if false you may have tried to redeem when not ready - */ - bool getGroupList(const uint32_t &token, std::list &groupIds); - - /*! - * - * @param token request token to be redeemed - * @param msgIds - */ - bool getMsgIdList(const uint32_t &token, GxsMsgIdResult &msgIds); - - - /*! - * Retrieve msg list for a given token for message related info - * @param token token to be redeemed - * @param msgIds a map of RsGxsGrpMsgIdPair -> msgList (vector) - * @return false if could not redeem token - */ - bool getMsgRelatedList(const uint32_t &token, MsgRelatedIdResult& msgIds); - - - /*! - * @param token request token to be redeemed - * @param groupInfo - */ - bool getGroupSummary(const uint32_t &token, std::list > &groupInfo); - - /*! - * - * @param token request token to be redeemed - * @param msgInfo - */ - bool getMsgSummary(const uint32_t &token, GxsMsgMetaResult &msgInfo); - - - /*! - * Retrieve msg meta for a given token for message related info - * @param token token to be redeemed - * @param msgIds a map of RsGxsGrpMsgIdPair -> msgList (vector) - * @return false if could not redeem token - */ - bool getMsgRelatedSummary(const uint32_t &token, MsgRelatedMetaResult& msgMeta); - - /*! - * - * @param token request token to be redeemed - * @param grpData - */ - bool getGroupData(const uint32_t &token, std::list& grpData); - - /*! - * - * @param token request token to be redeemed - * @param msgData - * @return false if data cannot be found for token - */ - bool getMsgData(const uint32_t &token, NxsMsgDataResult& msgData); - - /*! - * - * @param token request token to be redeemed - * @param msgData - * @return false if data cannot be found for token - */ - bool getMsgRelatedData(const uint32_t &token, NxsMsgRelatedDataResult& msgData); - -private: - - /** helper functions to implement token service **/ - - /*! - * Assigns a token value to passed integer - * @param token is assigned a unique token value - */ - void generateToken(uint32_t &token); - - /*! - * - * @param token the value of the token for the request object handle wanted - * @return the request associated to this token - */ - GxsRequest* locked_retrieveCompletedRequest(const uint32_t& token); - - /*! - * Add a gxs request to queue - * @param req gxs request to add - */ - void storeRequest(GxsRequest* req); - - /*! - * convenience function to setting members of request - * @param req - * @param token - * @param ansType - * @param opts - */ - void setReq(GxsRequest* req, uint32_t token, uint32_t ansType, const RsTokReqOptions& opts) const; - - /*! - * Remove request for request queue - * Request is deleted - * @param token the token associated to the request - * @return true if token successfully cleared, false if token does not exist - */ - bool clearRequest(const uint32_t &token); - - /*! - * Updates the status flag of a request - * @param token the token value of the request to set - * @param status the status to set - * @return - */ - bool locked_updateRequestStatus(uint32_t token, GxsRequestStatus status); - - /*! - * Use to query the status and other values of a given token - * @param token the toke of the request to check for - * @param status set to current status of request - * @param reqtype set to request type of request - * @param anstype set to to anstype of request - * @param ts time stamp - * @return false if token does not exist, true otherwise - */ - bool checkRequestStatus( uint32_t token, GxsRequestStatus &status, - uint32_t &reqtype, uint32_t &anstype, rstime_t &ts); - - // special ones for testing (not in final design) - /*! - * Get list of active tokens of this token service - * @param tokens sets to list of token contained in this tokenservice - */ - void tokenList(std::list &tokens); - - // /*! - // * Convenience function to delete the ids - // * @param filter the meta filter to clean - // */ - // void cleanseMsgMetaMap(GxsMsgMetaResult& result); - -public: - - /*! - * Assigns a token value to passed integer - * The status of the token can still be queried from request status feature - * @param token is assigned a unique token value - */ - uint32_t generatePublicToken(); - - /*! - * Updates the status of associate token - * @param token - * @param status - * @return false if token could not be found, true if token disposed of - */ - bool updatePublicRequestStatus(uint32_t token, GxsRequestStatus status); - - /*! - * This gets rid of a publicly issued token - * @param token - * @return false if token could not found, true if token disposed of - */ - bool disposeOfPublicToken(uint32_t token); - -private: - - /* These perform the actual blocking retrieval of data */ - - /*! - * Attempts to retrieve group id list from data store - * @param req - * @return false if unsuccessful, true otherwise - */ - bool getGroupList(GroupIdReq* req); - - /*! - * convenience function for filtering grpIds - * @param grpIdsIn The ids to filter with opts - * @param opts the filter options - * @param grpIdsOut grpIdsIn filtered with opts - */ - bool getGroupList(const std::list& grpIdsIn, const RsTokReqOptions& opts, std::list& grpIdsOut); - - /*! - * Attempts to retrieve msg id list from data store - * Computationally/CPU-Bandwidth expensive - * @param req - * @return false if unsuccessful, true otherwise - */ - bool getMsgIdList(MsgIdReq* req); - - /*! - * Attempts to retrieve msg Meta list from data store - * Computationally/CPU-Bandwidth expensive - * - * @param msgIds List of message Ids for the Message Metas to retrieve - * @param opts GxsRequest options - * @param result Map of Meta information for messages - * - */ - bool getMsgMetaDataList( const GxsMsgReq& msgIds, const RsTokReqOptions& opts, GxsMsgMetaResult& result ); - - /*! - * Attempts to retrieve group meta data from data store - * @param req - * @return false if unsuccessful, true otherwise - */ - bool getGroupSummary(GroupMetaReq* req); - - /*! - * Attempts to retrieve msg meta data from data store - * @param req - * @return false if unsuccessful, true otherwise - */ - bool getMsgSummary(MsgMetaReq* req); - - /*! - * Attempts to retrieve group data from data store - * @param req The request specifying data to retrieve - * @return false if unsuccessful, true otherwise - */ - bool getGroupData(GroupDataReq* req); - - /*! - * Attempts to retrieve message data from data store - * @param req The request specifying data to retrieve - * @return false if unsuccessful, true otherwise - */ - bool getMsgData(MsgDataReq* req); - - - /*! - * Attempts to retrieve messages related to msgIds of associated equest - * @param req Request object to satisfy - * @return false if data cannot be found for token - */ - bool getMsgRelatedInfo(MsgRelatedInfoReq* req); - - - /*! - * - * Attempts to retrieve group statistic - * @param req Request object to satisfy - */ - bool getGroupStatistic(GroupStatisticRequest* req); - - /*! - * - * Attempts to retrieve group data in serialized format - * @param req Request object to satisfy - */ - bool getGroupSerializedData(GroupSerializedDataReq* req); - - /*! - * - * Attempts to service statistic - * @param req request object to satisfy - */ - bool getServiceStatistic(ServiceStatisticRequest* req); - - /*! - * This filter msgs based of options supplied (at the moment just status masks) - * @param msgIds The msgsIds to filter - * @param opts the request options set by user - * @param meta The accompanying meta information for msg, ids - */ - void filterMsgIdList(GxsMsgIdResult& msgIds, const RsTokReqOptions& opts, const MsgMetaFilter& meta) const; - - /*! - * This filter msgs based of options supplied (at the moment just status masks) - * @param grpIds The group ids to filter - * @param opts the request options containing mask set by user - * @param meta The accompanying meta information for group ids - */ - void filterGrpList(std::list& msgIds, const RsTokReqOptions& opts, const GrpMetaFilter& meta) const; - - - /*! - * This applies the options to the meta to find out if the given message satisfies - * them - * @param opts options containing filters to check - * @param meta meta containing currently defined options for msg - * @return true if msg meta passes all options - */ - bool checkMsgFilter(const RsTokReqOptions& opts, const std::shared_ptr& meta) const; - - /*! - * This applies the options to the meta to find out if the given group satisfies - * them - * @param opts options containing filters to check - * @param meta meta containing currently defined options for group - * @return true if group meta passes all options - */ - bool checkGrpFilter(const RsTokReqOptions& opts, const std::shared_ptr &meta) const; - - - /*! - * This is a filter method which applies the request options to the list of ids - * requested - * @param msgIds the msg ids for filter to be applied to - * @param opts the options used to parameterise the id filter - * @param msgIdsOut the left overs ids after filter is applied to msgIds - */ - bool getMsgIdList(const GxsMsgReq& msgIds, const RsTokReqOptions& opts, GxsMsgReq& msgIdsOut); - - void dumpTokenQueues(); -private: - bool locked_clearRequest(const uint32_t &token); - - RsGeneralDataService* mDataStore; - - RsMutex mDataMutex; /* protecting below */ - - uint32_t mNextToken; - std::map mPublicToken; - - std::set > mRequestQueue; - std::map mCompletedRequests; - - bool mUseMetaCache; -}; - -#endif // RSGXSDATAACCESS_H diff --git a/libretroshare/src/gxs/rsgxsnetservice.cc b/libretroshare/src/gxs/rsgxsnetservice.cc deleted file mode 100644 index 163bd4ef9..000000000 --- a/libretroshare/src/gxs/rsgxsnetservice.cc +++ /dev/null @@ -1,5645 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsnetservice.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Christopher Evi-Parker * - * Copyright (C) 2018-2021 Gioacchino Mazzurco * - * Copyright (C) 2019-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -// -// RsNxsItem -// | -// +-- RsNxsSyncGrp send req for group list, with time stamp of what we have -// +-- RsNxsSyncMsg -// +-- RsNxsGroupPublishKeyItem -// +-- RsNxsSyncGrpItem send individual grp info with time stamps, authors, etc. -// -// -// tick() -// | -// +----------- sharePublishKeys() -// | -// +----------- checkUpdatesFromPeers() -// | | -// | +--if AutoSync--- send global UpdateTS of each peer to itself => the peer knows the last -// | | time current peer has received an updated from himself -// | | type=RsNxsSyncGrp -// | | role: advise to request grp list for mServType -// | | -// | +--Retrive all grp Id + meta -// | -// | For each peer -// | For each grp to request -// | send RsNxsSyncMsg(ServiceType, grpId, updateTS) -// | | -// | (Only send if rand() < sendingProb()) +---comes from mClientMsgUpdateMap -// | -// +----------- recvNxsItemQueue() -// | -// +------ handleRecvPublishKeys(auto*) -// | -// | -// | -// +------ handleRecvSyncGroup( RsNxsSyncGrp*) -// | - parse all subscribed groups. For each, send a RsNxsSyncGrpItem with publish TS -// | - pack into a single RsNxsTransac item -// | | -// | +---- canSendGrpId(peer, grpMeta, toVet) // determines if put in vetting list -// | | | // or sent right away -// | | +--CIRCLES_TYPE_LOCAL------- false -// | | +--CIRCLES_TYPE_PUBLIC------ true -// | | +--CIRCLES_TYPE_EXTERNAL---- mCircles->canSend(circleId, getPgpId(peerId)) -// | | +--CIRCLES_TYPE_YOUR_EYES--- internal circle stuff -// | | -// | +---- store in mPendingCircleVet ou directement locked_pushGrpRespFromList() -// | -// +------ handleRecvSyncMessage( RsNxsSyncMsg*) -// - parse msgs from group -// - send all msg IDs for this group -// | -// +---- canSendMsgIds(msgMeta, grpMeta, peer) -// | | -// | +--CIRCLES_TYPE_LOCAL------- false -// | +--CIRCLES_TYPE_PUBLIC------ true -// | +--CIRCLES_TYPE_EXTERNAL---- mCircles->canSend(circleId, getPgpId(peerId)) -// | +--CIRCLES_TYPE_YOUR_EYES--- internal circle stuff -// | -// +---- store in mPendingCircleVet ou directement locked_pushGrpRespFromList() -// data_tick() -// | -// +----------- updateServerSyncTS() -// | - retrieve all group meta data -// | - updates mServerMsgUpdateMap[grpId]=grp->mLastPostTS for all grps -// | - updates mGrpServerUpdateItem to max of all received TS -// | -// +----------- processTransactions() -// | -// +----------- processCompletedTransactions() -// | | -// | +------ locked_processCompletedIncomingTrans() -// | | | -// | | +-------- locked_genReqMsgTransaction() // request messages based on list -// | | | -// | | +-------- locked_genReqGrpTransaction() // request groups based on list -// | | | -// | | +-------- locked_genSendMsgsTransaction() // send msg list -// | | | -// | | +-------- locked_genSendGrpsTransaction() // send group list -// | | -// | +------ locked_processCompletedOutgoingTrans() -// | -// +----------- processExplicitGroupRequests() -// | - parse mExplicitRequest and for each element (containing a grpId list), -// | send the group ID (?!?!) -// | -// +----------- runVetting() -// | -// +--------- sort items from mPendingResp -// | | -// | +------ locked_createTransactionFromPending(GrpRespPending / MsgRespPending) -// | | // takes accepted transaction and adds them to the list of active trans -// | -// +--------- sort items from mPendingCircleVetting -// | -// +------ locked_createTransactionFromPending(GrpCircleIdsRequestVetting / MsgCircleIdsRequestVetting) -// // takes accepted transaction and adds them to the list of active trans -// -// Objects for time stamps -// ======================= -// -// mClientGrpUpdateMap: map< RsPeerId, TimeStamp > Time stamp of last modification of group data for that peer (in peer's clock time!) -// (Set at server side to be mGrpServerUpdateItem->grpUpdateTS) -// -// Only updated in processCompletedIncomingTransaction() from Grp list transaction. -// Used in checkUpdatesFromPeers() sending in RsNxsSyncGrp once to all peers: peer will send data if -// has something new. All time comparisons are in the friends' clock time. -// -// mClientMsgUpdateMap: map< RsPeerId, map > -// -// Last msg list modification time sent by that peer Id -// Updated in processCompletedIncomingTransaction() from Grp list trans. -// Used in checkUpdatesFromPeers() sending in RsNxsSyncGrp once to all peers. -// Set at server to be mServerMsgUpdateMap[grpId]->msgUpdateTS -// -// mGrpServerUpdateItem: TimeStamp Last group local modification timestamp over all groups -// -// mServerMsgUpdateMap: map< GrpId, TimeStamp > Timestamp local modification for each group (i.e. time of most recent msg / metadata update) -// -// -// Group update algorithm -// ====================== -// -// CLient Server -// ====== ====== -// -// tick() tick() -// | | -// +---- checkUpdatesFromPeers() +-- recvNxsItemQueue() -// | | -// +---------------- Send global UpdateTS of each peer to itself => the peer knows +---------> +------ handleRecvSyncGroup( RsNxsSyncGrp*) -// | the last msg sent (stored in mClientGrpUpdateMap[peer_id]), | | - parse all subscribed groups. For each, send a RsNxsSyncGrpItem with publish TS -// | type=RsNxsSyncGrp | | - pack into a single RsNxsTransac item -// | role: advise to request grp list for mServType -------------------+ | -// | +--> +------ handleRecvSyncMessage( RsNxsSyncMsg*) -// +---------------- Retrieve all grp Id + meta | - parse msgs from group -// | | - send all msg IDs for this group -// +-- For each peer | -// For each grp to request | -// send RsNxsSyncMsg(ServiceType, grpId, updateTS) | -// | | -// (Only send if rand() < sendingProb()) +---comes from mClientMsgUpdateMap -----+ -// -// Suggestions -// =========== -// * handleRecvSyncGroup should use mit->second.mLastPost to limit the sending of already known data -// X * apparently mServerMsgUpdateMap is initially empty -> by default clients will always want to receive the data. -// => new peers will always send data for each group until they get an update for that group. -// X * check that there is a timestamp for unsubscribed items, otherwise we always send TS=0 and we always get them!! (in 346) -// -// -> there is not. mClientMsgUpdateMap is updated when msgs are received. -// -> 1842: leaves before asking for msg content. -// -// Proposed changes: -// - for unsubsribed groups, mClientMsgUpdateMap[peerid][grpId]=now when the group list is received => wont be asked again -// - when we subscribe, we reset the time stamp. -// -// Better change: -// - each peer sends last -// -// * the last TS method is not perfect: do new peers always receive old messages? -// -// * there's double information between mServerMsgUpdateMap first element (groupId) and second->grpId -// * processExplicitGroupRequests() seems to send the group list that it was asked for without further information. How is that useful??? -// -// * grps without messages will never be stamped because stamp happens in genReqMsgTransaction, after checking msgListL.empty() -// Problem: without msg, we cannot know the grpId!! -// -// * mClientMsgUpdateMap[peerid][grpId] is only updated when new msgs are received. Up to date groups will keep asking for lists! -// -// Distant sync -// ============ -// -// Distant sync uses tunnels to sync subscribed GXS groups that are not supplied by friends. Peers can subscribe to a GXS group using a RS link -// which GXS uses to request updates through tunnels. -// * The whole exchange should be kept private and anonymous between the two distant peers, so we use the same trick than for FT: encrypt the data using the group ID. -// * The same node shouldn't be known as a common server for different GXS groups -// -// GXS net service: -// * talks to virtual peers, treated like normal peers -// * virtual peers only depend on the server ID, not on tunnel ID, and be kept constant accross time so that ClientGroupUpdateMap is kept consistent -// * does not use tunnels if friends can already supply the data (??) This causes issues with "islands". -// -// Tunnels: -// * a specific service named GxsSyncTunnelService handles the creation/management of sync tunnels: -// * tunnel data need to be encrypted. -// -// bool manageTunnels(const RsGxsGroupId&) ; // start managing tunnels for this group -// bool releaseTunnels(const RsGxsGroupId&) ; // stop managing tunnels for this group -// bool sendData(const unsigned char *data,uint32_t size,const RsPeerId& virtual_peer) ; // send data to this virtual peer -// bool getVirtualPeers(const RsGxsGroupId&, std::list& peers) ; // returns the virtual peers for this group -// -// Proposed protocol: -// * request tunnels based on H(GroupId) -// * encrypt tunnel data using chacha20+HMAC-SHA256 using AEAD( GroupId, 96bits IV, tunnel ID ) (similar to what FT does) -// * when tunnel is established, exchange virtual peer names: vpid = H( GroupID | Random bias ) -// * when vpid is known, notify the client (GXS net service) which can use the virtual peer to sync -// -// * only use a single tunnel per virtual peer ID -// -// Client ------------------ TR(H(GroupId)) --------------> Server -// -// Client <-------------------- T OK ---------------------- Server -// -// [Encrypted traffic using H(GroupId, 96bits IV, tunnel ID)] -// -// Client <--------- VPID = H( Random IV | GroupId ) ------ Server -// | | -// +--------------> Mark the virtual peer active <-----------+ -// -// Unsolved problems: -// * if we want to preserve anonymity, we cannot prevent GXS from duplicating the data from virtual/real peers that actually are the same peers. -// * ultimately we should only use tunnels to sync GXS. The mix between tunnels and real peers is not a problem but will cause unnecessary traffic. -// -// Notes: -// * given that GXS only talks to peers once every 2 mins, it's likely that keep-alive packets will be needed - - -#include -#include -#include -#include -#include - -#include "rsgxsnetservice.h" -#include "gxssecurity.h" -#include "retroshare/rsconfig.h" -#include "retroshare/rsgxsflags.h" -#include "retroshare/rsgxscircles.h" -#include "retroshare/rspeers.h" -#include "pgp/pgpauxutils.h" -#include "crypto/rscrypto.h" -#include "util/rsdir.h" -#include "util/rstime.h" -#include "util/rsmemory.h" -#include "util/stacktrace.h" -#include "util/rsdebug.h" -#include "util/cxx17retrocompat.h" - -/*** - * Use the following defines to debug: - NXS_NET_DEBUG_0 shows group update high level information - NXS_NET_DEBUG_1 shows group update low level info (including transaction details) - NXS_NET_DEBUG_2 bandwidth information - NXS_NET_DEBUG_3 publish key exchange - NXS_NET_DEBUG_4 vetting - NXS_NET_DEBUG_5 summary of transactions (useful to just know what comes in/out) - NXS_NET_DEBUG_6 group sync statistics (e.g. number of posts at nighbour nodes, etc) - NXS_NET_DEBUG_7 encryption/decryption of transactions - NXS_NET_DEBUG_8 gxs distant sync - NXS_NET_DEBUG_9 gxs distant search - - ***/ -//#define NXS_NET_DEBUG_0 1 -//#define NXS_NET_DEBUG_1 1 -//#define NXS_NET_DEBUG_2 1 -//#define NXS_NET_DEBUG_3 1 -//#define NXS_NET_DEBUG_4 1 -//#define NXS_NET_DEBUG_5 1 -//#define NXS_NET_DEBUG_6 1 -//#define NXS_NET_DEBUG_7 1 -//#define NXS_NET_DEBUG_8 1 -//#define NXS_NET_DEBUG_9 1 - -//#define NXS_FRAG - -// The constant below have a direct influence on how fast forums/channels/posted/identity groups propagate and on the overloading of queues: -// -// Channels/forums will update at a rate of SYNC_PERIOD*MAX_REQLIST_SIZE/60 messages per minute. -// A large TRANSAC_TIMEOUT helps large transactions to finish before anything happens (e.g. disconnexion) or when the server has low upload bandwidth, -// but also uses more memory. -// A small value for MAX_REQLIST_SIZE is likely to help messages to propagate in a chaotic network, but will also slow them down. -// A small SYNC_PERIOD fasten message propagation, but is likely to overload the server side of transactions (e.g. overload outqueues). -// -//static const uint32_t GIXS_CUT_OFF = 0; -static const uint32_t SYNC_PERIOD = 60; -static const uint32_t MAX_REQLIST_SIZE = 20; // No more than 20 items per msg request list => creates smaller transactions that are less likely to be cancelled. -static const uint32_t TRANSAC_TIMEOUT = 2000; // In seconds. Has been increased to avoid epidemic transaction cancelling due to overloaded outqueues. -#ifdef TO_REMOVE -static const uint32_t SECURITY_DELAY_TO_FORCE_CLIENT_REUPDATE = 3600; // force re-update if there happens to be a large delay between our server side TS and the client side TS of friends -#endif -static const uint32_t REJECTED_MESSAGE_RETRY_DELAY = 24*3600; // re-try rejected messages every 24hrs. Most of the time this is because the peer's reputation has changed. -static const uint32_t GROUP_STATS_UPDATE_DELAY = 240; // update unsubscribed group statistics every 3 mins -static const uint32_t GROUP_STATS_UPDATE_NB_PEERS = 2; // number of peers to which the group stats are asked -static const uint32_t MAX_ALLOWED_GXS_MESSAGE_SIZE = 199000; // 200,000 bytes including signature and headers -static const uint32_t MIN_DELAY_BETWEEN_GROUP_SEARCH = 40; // dont search same group more than every 40 secs. -static const uint32_t SAFETY_DELAY_FOR_UNSUCCESSFUL_UPDATE = 0; // avoid re-sending the same msg list to a peer who asks twice for the same update in less than this time - -static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN = 0x00 ; -static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_NO_ERROR = 0x01 ; -static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_CIRCLE_ERROR = 0x02 ; -static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_ENCRYPTION_ERROR = 0x03 ; -static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_SERIALISATION_ERROR = 0x04 ; -static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_GXS_KEY_MISSING = 0x05 ; - -// Debug system to allow to print only for some IDs (group, Peer, etc) - -#if defined(NXS_NET_DEBUG_0) || defined(NXS_NET_DEBUG_1) || defined(NXS_NET_DEBUG_2) || defined(NXS_NET_DEBUG_3) \ - || defined(NXS_NET_DEBUG_4) || defined(NXS_NET_DEBUG_5) || defined(NXS_NET_DEBUG_6) || defined(NXS_NET_DEBUG_7) \ - || defined(NXS_NET_DEBUG_8) || defined(NXS_NET_DEBUG_9) - -static const RsPeerId peer_to_print = RsPeerId();//std::string("a97fef0e2dc82ddb19200fb30f9ac575")) ; -static const RsGxsGroupId group_id_to_print = RsGxsGroupId();//std::string("66052380f5d1d0c5992e2b55dc402ce6")) ; // use this to allow to this group id only, or "" for all IDs -static const uint32_t service_to_print = RS_SERVICE_GXS_TYPE_CHANNELS; // use this to allow to this service id only, or 0 for all services - // warning. Numbers should be SERVICE IDS (see serialiser/rsserviceids.h. E.g. 0x0215 for forums) - -class nullstream: public std::ostream {}; - -static std::string nice_time_stamp(rstime_t now,rstime_t TS) -{ - if(TS == 0) - return "Never" ; - else - { - std::ostringstream s; - s << now - TS << " secs ago" ; - return s.str() ; - } -} - -static std::ostream& gxsnetdebug(const RsPeerId& peer_id,const RsGxsGroupId& grp_id,uint32_t service_type) -{ - static nullstream null ; - - if((peer_to_print.isNull() || peer_id.isNull() || peer_id == peer_to_print) - && (group_id_to_print.isNull() || grp_id.isNull() || grp_id == group_id_to_print) - && (service_to_print==0 || service_type == 0 || ((service_type >> 8)&0xffff) == service_to_print)) - return std::cerr << time(NULL) << ":GXSNETSERVICE: " ; - else - return null ; -} - -#define GXSNETDEBUG___ gxsnetdebug(RsPeerId(),RsGxsGroupId(),mServiceInfo.mServiceType) -#define GXSNETDEBUG_P_(peer_id ) gxsnetdebug(peer_id ,RsGxsGroupId(),mServiceInfo.mServiceType) -#define GXSNETDEBUG__G( group_id) gxsnetdebug(RsPeerId(),group_id ,mServiceInfo.mServiceType) -#define GXSNETDEBUG_PG(peer_id,group_id) gxsnetdebug(peer_id ,group_id ,mServiceInfo.mServiceType) - -#endif - -const uint32_t RsGxsNetService::FRAGMENT_SIZE = 150000; - -RsGxsNetService::RsGxsNetService(uint16_t servType, RsGeneralDataService *gds, - RsNxsNetMgr *netMgr, RsNxsObserver *nxsObs, - const RsServiceInfo serviceInfo, - RsGixsReputation* reputations, RsGcxs* circles, RsGixs *gixs, - PgpAuxUtils *pgpUtils, RsGxsNetTunnelService *mGxsNT, - bool grpAutoSync, bool msgAutoSync, bool distSync, uint32_t default_store_period, uint32_t default_sync_period) - : p3ThreadedService(), p3Config(), mTransactionN(0), - mObserver(nxsObs), mDataStore(gds), - mServType(servType), mTransactionTimeOut(TRANSAC_TIMEOUT), - mNetMgr(netMgr), mNxsMutex("RsGxsNetService"), - mSyncTs(0), mLastKeyPublishTs(0), - mLastCleanRejectedMessages(0), mSYNC_PERIOD(SYNC_PERIOD), - mCircles(circles), mGixs(gixs), - mReputations(reputations), mPgpUtils(pgpUtils), mGxsNetTunnel(mGxsNT), - mGrpAutoSync(grpAutoSync), mAllowMsgSync(msgAutoSync),mAllowDistSync(distSync), - mServiceInfo(serviceInfo), mDefaultMsgStorePeriod(default_store_period), - mDefaultMsgSyncPeriod(default_sync_period) -{ - addSerialType(new RsNxsSerialiser(mServType)); - mOwnId = mNetMgr->getOwnId(); - mUpdateCounter = 0; - - mLastCacheReloadTS = 0; - - // check the consistency - - if(mDefaultMsgStorePeriod > 0 && mDefaultMsgSyncPeriod > mDefaultMsgStorePeriod) - { - std::cerr << "(WW) in GXS service \"" << getServiceInfo().mServiceName << "\": too large message sync period will be set to message store period." << std::endl; - mDefaultMsgSyncPeriod = mDefaultMsgStorePeriod ; - } -} - -void RsGxsNetService::getItemNames(std::map& names) const -{ - names.clear(); - - names[RS_PKT_SUBTYPE_NXS_SYNC_GRP_REQ_ITEM ] = "Group Sync Request" ; - names[RS_PKT_SUBTYPE_NXS_SYNC_GRP_ITEM ] = "Group Sync" ; - names[RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS_ITEM ] = "Group Stats" ; - names[RS_PKT_SUBTYPE_NXS_GRP_ITEM ] = "Group Data" ; - names[RS_PKT_SUBTYPE_NXS_ENCRYPTED_DATA_ITEM ] = "Encrypted data" ; - names[RS_PKT_SUBTYPE_NXS_SESSION_KEY_ITEM ] = "Session Key" ; - names[RS_PKT_SUBTYPE_NXS_SYNC_MSG_ITEM ] = "Message Sync" ; - names[RS_PKT_SUBTYPE_NXS_SYNC_MSG_REQ_ITEM ] = "Message Sync Request" ; - names[RS_PKT_SUBTYPE_NXS_MSG_ITEM ] = "Message Data" ; - names[RS_PKT_SUBTYPE_NXS_TRANSAC_ITEM ] = "Transaction" ; - names[RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY_ITEM ] = "Publish key" ; -} - -RsGxsNetService::~RsGxsNetService() -{ - RS_STACK_MUTEX(mNxsMutex) ; - - for(TransactionsPeerMap::iterator it = mTransactions.begin();it!=mTransactions.end();++it) - { - for(TransactionIdMap::iterator it2 = it->second.begin();it2!=it->second.end();++it2) - delete it2->second ; - - it->second.clear() ; - } - mTransactions.clear() ; - - mClientGrpUpdateMap.clear() ; - mServerMsgUpdateMap.clear() ; -} - - -int RsGxsNetService::tick() -{ - // always check for new items arriving - // from peers - recvNxsItemQueue(); - - bool should_notify = false; - - { - RS_STACK_MUTEX(mNxsMutex) ; - - should_notify = should_notify || !mNewGroupsToNotify.empty() ; - should_notify = should_notify || !mNewMessagesToNotify.empty() ; - should_notify = should_notify || !mNewPublishKeysToNotify.empty() ; - should_notify = should_notify || !mNewStatsToNotify.empty() ; - should_notify = should_notify || !mNewGrpSyncParamsToNotify.empty() ; - } - - if(should_notify) - processObserverNotifications() ; - - rstime_t now = time(NULL); - rstime_t elapsed = mSYNC_PERIOD + mSyncTs; - - if((elapsed) < now) - { - checkUpdatesFromPeers(); - syncGrpStatistics(); - checkDistantSyncState(); - - mSyncTs = now; - } - - if(now > 10 + mLastKeyPublishTs) - { - sharePublishKeysPending() ; - - mLastKeyPublishTs = now ; - } - - if(now > 3600 + mLastCleanRejectedMessages) - { - mLastCleanRejectedMessages = now ; - cleanRejectedMessages() ; - } - return 1; -} - -void RsGxsNetService::processObserverNotifications() -{ -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG___ << "Processing observer notification." << std::endl; -#endif - - // Observer notifycation should never be done explicitly within a Mutex-protected region, because of the risk - // of causing a cross-deadlock between the observer (RsGxsGenExchange) and the network layer (RsGxsNetService). - - std::vector grps_copy ; - std::vector msgs_copy ; - std::set stat_copy ; - std::set keys_copy,grpss_copy ; - - { - RS_STACK_MUTEX(mNxsMutex) ; - - grps_copy = mNewGroupsToNotify ; - msgs_copy = mNewMessagesToNotify ; - stat_copy = mNewStatsToNotify ; - keys_copy = mNewPublishKeysToNotify ; - grpss_copy = mNewGrpSyncParamsToNotify ; - - mNewGroupsToNotify.clear() ; - mNewMessagesToNotify.clear() ; - mNewStatsToNotify.clear() ; - mNewPublishKeysToNotify.clear() ; - mNewGrpSyncParamsToNotify.clear() ; - } - - if(!grps_copy.empty()) mObserver->receiveNewGroups (grps_copy); - if(!msgs_copy.empty()) mObserver->receiveNewMessages(msgs_copy); - - for(std::set::const_iterator it(keys_copy.begin());it!=keys_copy.end();++it) - mObserver->notifyReceivePublishKey(*it); - - for(std::set::const_iterator it(stat_copy.begin());it!=stat_copy.end();++it) - mObserver->notifyChangedGroupStats(*it); - - for(std::set::const_iterator it(grpss_copy.begin());it!=grpss_copy.end();++it) - mObserver->notifyChangedGroupSyncParams(*it); -} - -void RsGxsNetService::rejectMessage(const RsGxsMessageId& msg_id) -{ - RS_STACK_MUTEX(mNxsMutex) ; - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG___ << "adding message " << msg_id << " to rejection list for 24hrs." << std::endl; -#endif - mRejectedMessages[msg_id] = time(NULL) ; -} -void RsGxsNetService::cleanRejectedMessages() -{ - RS_STACK_MUTEX(mNxsMutex) ; - rstime_t now = time(NULL) ; - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG___ << "Cleaning rejected messages." << std::endl; -#endif - - for(std::map::iterator it(mRejectedMessages.begin());it!=mRejectedMessages.end();) - if(it->second + REJECTED_MESSAGE_RETRY_DELAY < now) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG___ << " message id " << it->first << " should be re-tried. removing from list..." << std::endl; -#endif - - std::map::iterator tmp = it ; - ++tmp ; - mRejectedMessages.erase(it) ; - it=tmp ; - } - else - ++it ; -} - -RsGxsGroupId RsGxsNetService::hashGrpId(const RsGxsGroupId& gid,const RsPeerId& pid) -{ - static const uint32_t SIZE = RsGxsGroupId::SIZE_IN_BYTES + RsPeerId::SIZE_IN_BYTES ; - unsigned char tmpmem[SIZE]; - uint32_t offset = 0 ; - - pid.serialise(tmpmem,SIZE,offset) ; - gid.serialise(tmpmem,SIZE,offset) ; - - assert(RsGxsGroupId::SIZE_IN_BYTES <= Sha1CheckSum::SIZE_IN_BYTES) ; - - return RsGxsGroupId( RsDirUtil::sha1sum(tmpmem,SIZE).toByteArray() ); -} - -std::error_condition RsGxsNetService::checkUpdatesFromPeers( - std::set peers ) -{ -#ifdef NXS_NET_DEBUG_0 - RS_DBG("this=", (void*)this, ". serviceInfo=", mServiceInfo); -#endif - - /* If specific peers are passed as paramether ask only to them */ - if(peers.empty()) - { - mNetMgr->getOnlineList(mServiceInfo.mServiceType, peers); - - if(mAllowDistSync && mGxsNetTunnel != nullptr) - { - /* Grab all online virtual peers of distant tunnels for the current - * service. */ - - std::list vpids ; - mGxsNetTunnel->getVirtualPeers(vpids); - - for(auto it(vpids.begin());it!=vpids.end();++it) - peers.insert(RsPeerId(*it)) ; - } - } - - // Still empty? Reports there are no available peers - if (peers.empty()) return std::errc::network_down; - - - RS_STACK_MUTEX(mNxsMutex); - - // for now just grps - for(auto sit = peers.begin(); sit != peers.end(); ++sit) - { - const RsPeerId peerId = *sit; - - ClientGrpMap::const_iterator cit = mClientGrpUpdateMap.find(peerId); - uint32_t updateTS = 0; - - if(cit != mClientGrpUpdateMap.end()) - { - const RsGxsGrpUpdate *gui = &cit->second; - updateTS = gui->grpUpdateTS; - } - RsNxsSyncGrpReqItem *grp = new RsNxsSyncGrpReqItem(mServType); - grp->clear(); - grp->PeerId(*sit); - grp->updateTS = updateTS; - -#ifdef NXS_NET_DEBUG_5 - GXSNETDEBUG_P_(*sit) << "Service "<< std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " sending global group TS of peer id: " << *sit << " ts=" << nice_time_stamp(time(NULL),updateTS) << " (secs ago) to himself" << std::endl; -#endif - generic_sendItem(grp); - } - - if(!mAllowMsgSync) return std::error_condition(); - -#ifndef GXS_DISABLE_SYNC_MSGS - - RsGxsGrpMetaTemporaryMap grpMeta; - - mDataStore->retrieveGxsGrpMetaData(grpMeta); - - RsGxsGrpMetaTemporaryMap toRequest; - - for(RsGxsGrpMetaTemporaryMap::iterator mit = grpMeta.begin(); mit != grpMeta.end(); ++mit) - { - const auto& meta = mit->second; - - // This was commented out because we want to know how many messages are available for unsubscribed groups. - - if(meta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED ) - { - toRequest.insert(std::make_pair(mit->first, meta)); - mit->second = NULL ; // avoids destruction ;-) - } - } - - // Synchronise group msg for groups which we're subscribed to - // For each peer and each group, we send to the peer the time stamp of the most - // recent modification the peer has sent. If the peer has more recent messages he will send them, because its latest - // modifications will be more recent. This ensures that we always compare timestamps all taken in the same - // computer (the peer's computer in this case) - - for(auto sit = peers.begin(); sit != peers.end(); ++sit) - { - const RsPeerId& peerId = *sit; - - // now see if you have an updateTS so optimise whether you need - // to get a new list of peer data - const RsGxsMsgUpdate *mui = NULL; - - ClientMsgMap::const_iterator cit = mClientMsgUpdateMap.find(peerId); - - if(cit != mClientMsgUpdateMap.end()) - mui = &cit->second; - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(peerId) << " syncing messages with peer " << peerId << std::endl; -#endif - - RsGxsGrpMetaTemporaryMap::const_iterator mmit = toRequest.begin(); - for(; mmit != toRequest.end(); ++mmit) - { - const auto& meta = mmit->second; - const RsGxsGroupId& grpId = mmit->first; - RsGxsCircleId encrypt_to_this_circle_id ; - - if(!checkCanRecvMsgFromPeer(peerId, *meta,encrypt_to_this_circle_id)) - continue; - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(peerId,grpId) << " peer can send messages for group " << grpId ; - if(!encrypt_to_this_circle_id.isNull()) - GXSNETDEBUG_PG(peerId,grpId) << " request should be encrypted for circle ID " << encrypt_to_this_circle_id << std::endl; - else - GXSNETDEBUG_PG(peerId,grpId) << " request should be sent in clear." << std::endl; - -#endif - // On default, the info has never been received so the TS is 0, meaning the peer has sent that it had no information. - - uint32_t updateTS = 0; - - if(mui) - { - std::map::const_iterator cit2 = mui->msgUpdateInfos.find(grpId); - - if(cit2 != mui->msgUpdateInfos.end()) - updateTS = cit2->second.time_stamp; - } - - // get sync params for this group - - RsNxsSyncMsgReqItem* msg = new RsNxsSyncMsgReqItem(mServType); - - msg->clear(); - msg->PeerId(peerId); - msg->updateTS = updateTS; - - int req_delay = (int)locked_getGrpConfig(grpId).msg_req_delay ; - int keep_delay = (int)locked_getGrpConfig(grpId).msg_keep_delay ; - - // If we store for less than we request, we request less, otherwise the posts will be deleted after being obtained. - - if(keep_delay > 0 && req_delay > 0 && keep_delay < req_delay) - req_delay = keep_delay ; - - // The last post will be set to TS 0 if the req delay is 0, which means "Indefinitly" - - if(req_delay > 0) - msg->createdSinceTS = std::max(0,(int)time(NULL) - req_delay); - else - msg->createdSinceTS = 0 ; - - if(encrypt_to_this_circle_id.isNull()) - msg->grpId = grpId; - else - { - msg->grpId = hashGrpId(grpId,mNetMgr->getOwnId()) ; - msg->flag |= RsNxsSyncMsgReqItem::FLAG_USE_HASHED_GROUP_ID ; - } - -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_PG(*sit,grpId) << " Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " sending message TS of peer id: " << *sit << " ts=" << nice_time_stamp(time(NULL),updateTS) << " (secs ago) for group " << grpId << " to himself - in clear " << std::endl; -#endif - generic_sendItem(msg); - -#ifdef NXS_NET_DEBUG_5 - GXSNETDEBUG_PG(*sit,grpId) << "Service "<< std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " sending global message TS of peer id: " << *sit << " ts=" << nice_time_stamp(time(NULL),updateTS) << " (secs ago) for group " << grpId << " to himself" << std::endl; -#endif - } - } - -#endif // ndef GXS_DISABLE_SYNC_MSGS - - return std::error_condition(); -} - -void RsGxsNetService::generic_sendItem(rs_owner_ptr si) -{ - // check if the item is to be sent to a distant peer or not - - RsGxsGroupId tmp_grpId; - - if(mAllowDistSync && mGxsNetTunnel != NULL && mGxsNetTunnel->isDistantPeer( static_cast(si->PeerId()),tmp_grpId)) - { - RsNxsSerialiser ser(mServType); - - uint32_t size = ser.size(si); - unsigned char *mem = (unsigned char *)rs_malloc(size) ; - - if(!mem) - return ; - -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG_P_(si->PeerId()) << "Sending RsGxsNetTunnelService Item:" << (void*)si << " of type: " << std::hex << si->PacketId() << std::dec - << " transaction " << si->transactionNumber << " to virtual peer " << si->PeerId() << std::endl ; -#endif - ser.serialise(si,mem,&size) ; - - mGxsNetTunnel->sendTunnelData(mServType,mem,size,static_cast(si->PeerId())); - delete si; - } - else - sendItem(si) ; -} - -void RsGxsNetService::checkDistantSyncState() -{ - if(!mAllowDistSync || mGxsNetTunnel==NULL || !mGrpAutoSync) - return ; - - RsGxsGrpMetaTemporaryMap grpMeta; - mDataStore->retrieveGxsGrpMetaData(grpMeta); - - // Go through group statistics and groups without information are re-requested to random peers selected - // among the ones who provided the group info. - -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___<< "Checking distant sync for all groups." << std::endl; -#endif - // get the list of online peers - - std::set online_peers; - mNetMgr->getOnlineList(mServiceInfo.mServiceType , online_peers); - - RS_STACK_MUTEX(mNxsMutex) ; - - for(auto it(grpMeta.begin());it!=grpMeta.end();++it) - if(it->second->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) // we only consider subscribed groups here. - { -#warning (cyril) We might need to also remove peers for recently unsubscribed groups - const RsGxsGroupId& grpId(it->first); - const RsGxsGrpConfig& rec = locked_getGrpConfig(grpId) ; - -#ifdef NXS_NET_DEBUG_6 - GXSNETDEBUG__G(it->first) << " group " << grpId; -#endif - bool at_least_one_friend_is_supplier = false ; - - for(auto it2(rec.suppliers.ids.begin());it2!=rec.suppliers.ids.end() && !at_least_one_friend_is_supplier;++it2) - if(online_peers.find(*it2) != online_peers.end()) // check that the peer is online - at_least_one_friend_is_supplier = true ; - - // That strategy is likely to create islands of friends connected to each other. There's no real way - // to decide what to do here, except maybe checking the last message TS remotely vs. locally. - - if(at_least_one_friend_is_supplier) - { - mGxsNetTunnel->releaseDistantPeers(mServType,grpId); -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___<< " Group " << grpId << ": suppliers among friends. Releasing peers." << std::endl; -#endif - } - else - { - mGxsNetTunnel->requestDistantPeers(mServType,grpId); -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___<< " Group " << grpId << ": no suppliers among friends. Requesting peers." << std::endl; -#endif - } - } -} - -void RsGxsNetService::syncGrpStatistics() -{ - RS_STACK_MUTEX(mNxsMutex) ; - -#ifdef NXS_NET_DEBUG_6 - GXSNETDEBUG___<< "Sync-ing group statistics." << std::endl; -#endif - RsGxsGrpMetaTemporaryMap grpMeta; - - mDataStore->retrieveGxsGrpMetaData(grpMeta); - - std::set online_peers; - mNetMgr->getOnlineList(mServiceInfo.mServiceType, online_peers); - - if(mAllowDistSync && mGxsNetTunnel != NULL) - { - // Grab all online virtual peers of distant tunnels for the current service. - - std::list vpids ; - mGxsNetTunnel->getVirtualPeers(vpids); - - for(auto it(vpids.begin());it!=vpids.end();++it) - online_peers.insert(RsPeerId(*it)) ; - } - - // Go through group statistics and groups without information are re-requested to random peers selected - // among the ones who provided the group info. - - rstime_t now = time(NULL) ; - - for(auto it(grpMeta.begin());it!=grpMeta.end();++it) - { - const RsGxsGrpConfig& rec = locked_getGrpConfig(it->first) ; - -#ifdef NXS_NET_DEBUG_6 - GXSNETDEBUG__G(it->first) << " group " << it->first ; -#endif - - if(rec.statistics_update_TS + GROUP_STATS_UPDATE_DELAY < now && rec.suppliers.ids.size() > 0) - { -#ifdef NXS_NET_DEBUG_6 - GXSNETDEBUG__G(it->first) << " needs update. Randomly asking to some friends" << std::endl; -#endif - // randomly select GROUP_STATS_UPDATE_NB_PEERS friends among the suppliers of this group - - uint32_t n = RSRandom::random_u32() % rec.suppliers.ids.size() ; - - std::set::const_iterator rit = rec.suppliers.ids.begin(); - for(uint32_t i=0;ifirst) << " asking friend " << peer_id << " for an update of stats for group " << it->first << std::endl; -#endif - - RsNxsSyncGrpStatsItem *grs = new RsNxsSyncGrpStatsItem(mServType) ; - - grs->request_type = RsNxsSyncGrpStatsItem::GROUP_INFO_TYPE_REQUEST ; - - grs->grpId = it->first ; - grs->PeerId(peer_id) ; - - generic_sendItem(grs) ; - } - } - } -#ifdef NXS_NET_DEBUG_6 - else - GXSNETDEBUG__G(it->first) << " up to date." << std::endl; -#endif - } -} - -void RsGxsNetService::handleRecvSyncGrpStatistics(RsNxsSyncGrpStatsItem *grs) -{ - if(grs->request_type == RsNxsSyncGrpStatsItem::GROUP_INFO_TYPE_REQUEST) - { -#ifdef NXS_NET_DEBUG_6 - GXSNETDEBUG_PG(grs->PeerId(),grs->grpId) << "Received Grp update stats Request for group " << grs->grpId << " from friend " << grs->PeerId() << std::endl; -#endif - RsGxsGrpMetaTemporaryMap grpMetas; - grpMetas[grs->grpId] = NULL; - - mDataStore->retrieveGxsGrpMetaData(grpMetas); - - const auto& grpMeta = grpMetas[grs->grpId]; - - if(grpMeta == NULL) - { -#ifdef NXS_NET_DEBUG_6 - GXSNETDEBUG_PG(grs->PeerId(),grs->grpId) << " Group is unknown. Not reponding." << std::endl; -#endif - return ; - } - - // check if we're subscribed or not - - if(! (grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED )) - { -#ifdef NXS_NET_DEBUG_6 - GXSNETDEBUG_PG(grs->PeerId(),grs->grpId) << " Group is not subscribed. Not reponding." << std::endl; -#endif - return ; - } - - // now count available messages - - GxsMsgReq reqIds; - reqIds[grs->grpId] = std::set(); - GxsMsgMetaResult result; - -#ifdef NXS_NET_DEBUG_6 - GXSNETDEBUG_PG(grs->PeerId(),grs->grpId) << " retrieving message information." << std::endl; -#endif - mDataStore->retrieveGxsMsgMetaData(reqIds, result); - - const auto& vec(result[grs->grpId]) ; - - if(vec.empty()) // that means we don't have any, or there isn't any, but since the default is always 0, no need to send. - return ; - - RsNxsSyncGrpStatsItem *grs_resp = new RsNxsSyncGrpStatsItem(mServType) ; - grs_resp->request_type = RsNxsSyncGrpStatsItem::GROUP_INFO_TYPE_RESPONSE ; - grs_resp->number_of_posts = vec.size(); - grs_resp->grpId = grs->grpId; - grs_resp->PeerId(grs->PeerId()) ; - - grs_resp->last_post_TS = grpMeta->mPublishTs ; // This is not zero, and necessarily older than any message in the group up to clock precision. - // This allows us to use 0 as "uninitialized" proof. If the group meta has been changed, this time - // will be more recent than some messages. This shouldn't be a problem, since this value can only - // be used to discard groups that are not used. - - for(uint32_t i=0;ilast_post_TS < vec[i]->mPublishTs) - grs_resp->last_post_TS = vec[i]->mPublishTs; - -#ifdef NXS_NET_DEBUG_6 - GXSNETDEBUG_PG(grs->PeerId(),grs->grpId) << " sending back statistics item with " << vec.size() << " elements." << std::endl; -#endif - - generic_sendItem(grs_resp) ; - } - else if(grs->request_type == RsNxsSyncGrpStatsItem::GROUP_INFO_TYPE_RESPONSE) - { -#ifdef NXS_NET_DEBUG_6 - GXSNETDEBUG_PG(grs->PeerId(),grs->grpId) << "Received Grp update stats item from peer " << grs->PeerId() << " for group " << grs->grpId << ", reporting " << grs->number_of_posts << " posts." << std::endl; -#endif - RS_STACK_MUTEX(mNxsMutex) ; - - RsGxsGrpConfig& rec(locked_getGrpConfig(grs->grpId)) ; - - uint32_t old_count = rec.max_visible_count ; - uint32_t old_suppliers_count = rec.suppliers.ids.size() ; - - rec.suppliers.ids.insert(grs->PeerId()) ; - rec.max_visible_count = std::max(rec.max_visible_count,grs->number_of_posts) ; - rec.statistics_update_TS = time(NULL) ; - rec.last_group_modification_TS = grs->last_post_TS; - - if (old_count != rec.max_visible_count || old_suppliers_count != rec.suppliers.ids.size()) - mNewStatsToNotify.insert(grs->grpId) ; - } - else - std::cerr << "(EE) RsGxsNetService::handleRecvSyncGrpStatistics(): unknown item type " << grs->request_type << " found. This is a bug." << std::endl; -} - -// This function is useful when we need to force a new sync of messages from all friends when e.g. the delay for sync gets changed. -// Normally, when subscribing to a group (not needed when unsubscribing), we should also call this method. - -void RsGxsNetService::locked_resetClientTS(const RsGxsGroupId& grpId) -{ -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG__G(grpId) << "Resetting client TS for grp " << grpId << std::endl; -#endif - - for(ClientMsgMap::iterator it(mClientMsgUpdateMap.begin());it!=mClientMsgUpdateMap.end();++it) - it->second.msgUpdateInfos.erase(grpId) ; -} - -void RsGxsNetService::subscribeStatusChanged( - const RsGxsGroupId& grpId, bool subscribed ) -{ - if(!subscribed) return; - - // When we subscribe, we reset the time stamps, so that the entire group list - // gets requested once again, for a proper update. - - RS_STACK_MUTEX(mNxsMutex); - -#ifdef NXS_NET_DEBUG_0 - RS_DBG( "Changing subscribe status for grp", grpId, " to ", subscribed, - ": reseting all server msg time stamps for this group, and " - "server global TS." ); -#endif - - RsGxsServerMsgUpdate& item(mServerMsgUpdateMap[grpId]); - item.msgUpdateTS = static_cast(time(nullptr)); - - /* We also update mGrpServerUpdateItem so as to trigger a new grp list - * exchange with friends (friends will send their known ClientTS which - * will be lower than our own grpUpdateTS, triggering our sending of the - * new subscribed grp list. */ - mGrpServerUpdate.grpUpdateTS = static_cast(time(nullptr)); - - locked_resetClientTS(grpId); -} - -bool RsGxsNetService::fragmentMsg(RsNxsMsg& msg, MsgFragments& msgFragments) const -{ - // first determine how many fragments - uint32_t msgSize = msg.msg.TlvSize(); - uint32_t dataLeft = msgSize; - uint8_t nFragments = ceil(float(msgSize)/FRAGMENT_SIZE); - - RsTemporaryMemory buffer(FRAGMENT_SIZE); - int currPos = 0; - - - for(uint8_t i=0; i < nFragments; ++i) - { - RsNxsMsg* msgFrag = new RsNxsMsg(mServType); - msgFrag->grpId = msg.grpId; - msgFrag->msgId = msg.msgId; - msgFrag->meta = msg.meta; - msgFrag->transactionNumber = msg.transactionNumber; - msgFrag->pos = i; - msgFrag->PeerId(msg.PeerId()); - msgFrag->count = nFragments; - uint32_t fragSize = std::min(dataLeft, FRAGMENT_SIZE); - - memcpy(buffer, ((char*)msg.msg.bin_data) + currPos, fragSize); - msgFrag->msg.setBinData(buffer, fragSize); - - currPos += fragSize; - dataLeft -= fragSize; - msgFragments.push_back(msgFrag); - } - - return true; -} - -bool RsGxsNetService::fragmentGrp(RsNxsGrp& grp, GrpFragments& grpFragments) const -{ - // first determine how many fragments - uint32_t grpSize = grp.grp.TlvSize(); - uint32_t dataLeft = grpSize; - uint8_t nFragments = ceil(float(grpSize)/FRAGMENT_SIZE); - char buffer[FRAGMENT_SIZE]; - int currPos = 0; - - - for(uint8_t i=0; i < nFragments; ++i) - { - RsNxsGrp* grpFrag = new RsNxsGrp(mServType); - grpFrag->grpId = grp.grpId; - grpFrag->meta = grp.meta; - grpFrag->pos = i; - grpFrag->count = nFragments; - uint32_t fragSize = std::min(dataLeft, FRAGMENT_SIZE); - - memcpy(buffer, ((char*)grp.grp.bin_data) + currPos, fragSize); - grpFrag->grp.setBinData(buffer, fragSize); - - currPos += fragSize; - dataLeft -= fragSize; - grpFragments.push_back(grpFrag); - } - - return true; -} - -RsNxsMsg* RsGxsNetService::deFragmentMsg(MsgFragments& msgFragments) const -{ - if(msgFragments.empty()) return NULL; - - // if there is only one fragment with a count 1 or less then - // the fragment is the msg - if(msgFragments.size() == 1) - { - RsNxsMsg* m = msgFragments.front(); - - if(m->count > 1) // normally mcount should be exactly 1, but if not initialised (old versions) it's going to be 0 - { - // delete everything - std::cerr << "(WW) Cannot deFragment message set. m->count=" << m->count << ", but msgFragments.size()=" << msgFragments.size() << ". Incomplete? Dropping all." << std::endl; - - for(uint32_t i=0;imsg.bin_len; - - RsTemporaryMemory data(datSize) ; - - if(!data) - { - for(uint32_t i=0;imsg.bin_data, msg->msg.bin_len); - currPos += msg->msg.bin_len; - } - - RsNxsMsg* msg = new RsNxsMsg(mServType); - const RsNxsMsg& m = *(*(msgFragments.begin())); - msg->msg.setBinData(data, datSize); - msg->msgId = m.msgId; - msg->grpId = m.grpId; - msg->transactionNumber = m.transactionNumber; - msg->meta = m.meta; - - // now clean! - for(uint32_t i=0;igrp.bin_len; - - char* data = new char[datSize]; - uint32_t currPos = 0; - - for(mit = grpFragments.begin(); mit != grpFragments.end(); ++mit) - { - RsNxsGrp* grp = *mit; - memcpy(data + (currPos), grp->grp.bin_data, grp->grp.bin_len); - currPos += grp->grp.bin_len; - } - - RsNxsGrp* grp = new RsNxsGrp(mServType); - const RsNxsGrp& g = *(*(grpFragments.begin())); - grp->grp.setBinData(data, datSize); - grp->grpId = g.grpId; - grp->transactionNumber = g.transactionNumber; - grp->meta = g.meta; - - delete[] data; - - return grp; -} - -struct GrpFragCollate -{ - RsGxsGroupId mGrpId; - GrpFragCollate(const RsGxsGroupId& grpId) : mGrpId(grpId){ } - bool operator()(RsNxsGrp* grp) { return grp->grpId == mGrpId;} -}; - -void RsGxsNetService::locked_createTransactionFromPending( MsgRespPending* msgPend) -{ -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(msgPend->mPeerId) << "locked_createTransactionFromPending()" << std::endl; -#endif - MsgAuthorV::const_iterator cit = msgPend->mMsgAuthV.begin(); - std::list reqList; - uint32_t transN = locked_getTransactionId(); - for(; cit != msgPend->mMsgAuthV.end(); ++cit) - { - const MsgAuthEntry& entry = *cit; - - if(entry.mPassedVetting) - { - RsNxsSyncMsgItem* msgItem = new RsNxsSyncMsgItem(mServType); - msgItem->grpId = entry.mGrpId; - msgItem->msgId = entry.mMsgId; - msgItem->authorId = entry.mAuthorId; - msgItem->flag = RsNxsSyncMsgItem::FLAG_REQUEST; - msgItem->transactionNumber = transN; - msgItem->PeerId(msgPend->mPeerId); - reqList.push_back(msgItem); - } -#ifdef NXS_NET_DEBUG_1 - else - GXSNETDEBUG_PG(msgPend->mPeerId,entry.mGrpId) << " entry failed vetting: grpId=" << entry.mGrpId << ", msgId=" << entry.mMsgId << ", peerId=" << msgPend->mPeerId << std::endl; -#endif - } - - if(!reqList.empty()) - locked_pushMsgTransactionFromList(reqList, msgPend->mPeerId, transN) ; -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(msgPend->mPeerId) << " added " << reqList.size() << " items to transaction." << std::endl; -#endif -} - -void RsGxsNetService::locked_createTransactionFromPending(GrpRespPending* grpPend) -{ -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(grpPend->mPeerId) << "locked_createTransactionFromPending() from peer " << grpPend->mPeerId << std::endl; -#endif - GrpAuthorV::const_iterator cit = grpPend->mGrpAuthV.begin(); - std::list reqList; - uint32_t transN = locked_getTransactionId(); - for(; cit != grpPend->mGrpAuthV.end(); ++cit) - { - const GrpAuthEntry& entry = *cit; - - if(entry.mPassedVetting) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(grpPend->mPeerId,entry.mGrpId) << " entry Group Id: " << entry.mGrpId << " PASSED" << std::endl; -#endif - RsNxsSyncGrpItem* msgItem = new RsNxsSyncGrpItem(mServType); - msgItem->grpId = entry.mGrpId; - msgItem->authorId = entry.mAuthorId; - msgItem->flag = RsNxsSyncMsgItem::FLAG_REQUEST; - msgItem->transactionNumber = transN; - msgItem->PeerId(grpPend->mPeerId); - reqList.push_back(msgItem); - } -#ifdef NXS_NET_DEBUG_1 - else - GXSNETDEBUG_PG(grpPend->mPeerId,entry.mGrpId) << " entry failed vetting: grpId=" << entry.mGrpId << ", peerId=" << grpPend->mPeerId << std::endl; -#endif - } - - if(!reqList.empty()) - locked_pushGrpTransactionFromList(reqList, grpPend->mPeerId, transN); -} - - -bool RsGxsNetService::locked_createTransactionFromPending(GrpCircleIdRequestVetting* grpPend) -{ -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(grpPend->mPeerId) << "locked_createTransactionFromPending(GrpCircleIdReq)" << std::endl; -#endif - std::vector::iterator cit = grpPend->mGrpCircleV.begin(); - uint32_t transN = locked_getTransactionId(); - std::list itemL; - for(; cit != grpPend->mGrpCircleV.end(); ++cit) - { - const GrpIdCircleVet& entry = *cit; - - if(entry.mCleared) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(grpPend->mPeerId,entry.mGroupId) << " Group Id: " << entry.mGroupId << " PASSED" << std::endl; -#endif - RsNxsSyncGrpItem* gItem = new RsNxsSyncGrpItem(mServType); - gItem->flag = RsNxsSyncGrpItem::FLAG_RESPONSE; - gItem->grpId = entry.mGroupId; - gItem->publishTs = 0; - gItem->PeerId(grpPend->mPeerId); - gItem->transactionNumber = transN; - gItem->authorId = entry.mAuthorId; - // why it authorId not set here??? - - if(entry.mShouldEncrypt) - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_PG(grpPend->mPeerId,entry.mGroupId) << " item for this grpId should be encrypted." << std::endl; -#endif - RsNxsItem *encrypted_item = NULL ; - uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ; - - if(encryptSingleNxsItem(gItem, entry.mCircleId, entry.mGroupId,encrypted_item,status)) - { - itemL.push_back(encrypted_item) ; - delete gItem ; - } -#ifdef NXS_NET_DEBUG_7 - else - GXSNETDEBUG_PG(grpPend->mPeerId,entry.mGroupId) << " Could not encrypt item for grpId " << entry.mGroupId << " for circle " << entry.mCircleId << ". Will try later. Adding to vetting list." << std::endl; -#endif - } - else - itemL.push_back(gItem); - } -#ifdef NXS_NET_DEBUG_1 - else - GXSNETDEBUG_PG(grpPend->mPeerId,entry.mGroupId) << " Group Id: " << entry.mGroupId << " FAILED" << std::endl; -#endif - } - - if(!itemL.empty()) - locked_pushGrpRespFromList(itemL, grpPend->mPeerId, transN); - - return true ; -} - -bool RsGxsNetService::locked_createTransactionFromPending(MsgCircleIdsRequestVetting* msgPend) -{ - std::vector::iterator vit = msgPend->mMsgs.begin(); - std::list itemL; - - uint32_t transN = locked_getTransactionId(); - RsGxsGroupId grp_id ; - - for(; vit != msgPend->mMsgs.end(); ++vit) - { - MsgIdCircleVet& mic = *vit; - RsNxsSyncMsgItem* mItem = new RsNxsSyncMsgItem(mServType); - mItem->flag = RsNxsSyncGrpItem::FLAG_RESPONSE; - mItem->grpId = msgPend->mGrpId; - mItem->msgId = mic.mMsgId; - mItem->authorId = mic.mAuthorId; - mItem->PeerId(msgPend->mPeerId); - mItem->transactionNumber = transN; - - grp_id = msgPend->mGrpId ; - - if(msgPend->mShouldEncrypt) - { - RsNxsItem *encrypted_item = NULL ; - uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ; - - if(encryptSingleNxsItem(mItem,msgPend->mCircleId,msgPend->mGrpId,encrypted_item,status)) - { - itemL.push_back(encrypted_item) ; - delete mItem ; - } - else - { - std::cerr << "(EE) cannot encrypt Msg ids in circle-restriced response to grp " << msgPend->mGrpId << " for circle " << msgPend->mCircleId << std::endl; - return false ; - } - } - else - itemL.push_back(mItem); - } - - if(!itemL.empty()) - locked_pushMsgRespFromList(itemL, msgPend->mPeerId,grp_id, transN); - - return true ; -} - -/*bool RsGxsNetService::locked_canReceive(const RsGxsGrpMetaData * const grpMeta - , const RsPeerId& peerId ) -{ - - double timeDelta = 0.2; - - if(grpMeta->mCircleType == GXS_CIRCLE_TYPE_EXTERNAL) { - int i=0; - mCircles->loadCircle(grpMeta->mCircleId); - - // check 5 times at most - // spin for 1 second at most - while(i < 5) { - - if(mCircles->isLoaded(grpMeta->mCircleId)) { - const RsPgpId& pgpId = mPgpUtils->getPGPId(peerId); - return mCircles->canSend(grpMeta->mCircleId, pgpId); - }//if(mCircles->isLoaded(grpMeta->mCircleId)) - - usleep((int) (timeDelta * 1000 * 1000));// timeDelta sec - i++; - }//while(i < 5) - - } else {//if(grpMeta->mCircleType == GXS_CIRCLE_TYPE_EXTERNAL) - return true; - }//else (grpMeta->mCircleType == GXS_CIRCLE_TYPE_EXTERNAL) - - return false; -}*/ - -void RsGxsNetService::collateGrpFragments(GrpFragments fragments, - std::map& partFragments) const -{ - // get all unique grpIds; - GrpFragments::iterator vit = fragments.begin(); - std::set grpIds; - - for(; vit != fragments.end(); ++vit) - grpIds.insert( (*vit)->grpId ); - - std::set::iterator sit = grpIds.begin(); - - for(; sit != grpIds.end(); ++sit) - { - const RsGxsGroupId& grpId = *sit; - GrpFragments::iterator bound = std::partition( - fragments.begin(), fragments.end(), - GrpFragCollate(grpId)); - - // something will always be found for a group id - for(vit = fragments.begin(); vit != bound; ) - { - partFragments[grpId].push_back(*vit); - vit = fragments.erase(vit); - } - - GrpFragments& f = partFragments[grpId]; - RsNxsGrp* grp = *(f.begin()); - - // if counts of fragments is incorrect remove - // from coalescion - if(grp->count != f.size()) - { - GrpFragments::iterator vit2 = f.begin(); - - for(; vit2 != f.end(); ++vit2) - delete *vit2; - - partFragments.erase(grpId); - } - } - - fragments.clear(); -} - -struct MsgFragCollate -{ - RsGxsMessageId mMsgId; - MsgFragCollate(const RsGxsMessageId& msgId) : mMsgId(msgId){ } - bool operator()(RsNxsMsg* msg) { return msg->msgId == mMsgId;} -}; - -void RsGxsNetService::collateMsgFragments(MsgFragments& fragments, std::map& partFragments) const -{ - // get all unique message Ids; - MsgFragments::iterator vit = fragments.begin(); - std::set msgIds; - - for(; vit != fragments.end(); ++vit) - msgIds.insert( (*vit)->msgId ); - - - std::set::iterator sit = msgIds.begin(); - - for(; sit != msgIds.end(); ++sit) - { - const RsGxsMessageId& msgId = *sit; - MsgFragments::iterator bound = std::partition( - fragments.begin(), fragments.end(), - MsgFragCollate(msgId)); - - // something will always be found for a group id - for(vit = fragments.begin(); vit != bound; ++vit ) - { - partFragments[msgId].push_back(*vit); - } - - fragments.erase(fragments.begin(), bound); - MsgFragments& f = partFragments[msgId]; - RsNxsMsg* msg = *(f.begin()); - - // if counts of fragments is incorrect remove - // from coalescion - if(msg->count != f.size()) - { - MsgFragments::iterator vit2 = f.begin(); - - for(; vit2 != f.end(); ++vit2) - delete *vit2; - - partFragments.erase(msgId); - } - } - - fragments.clear(); -} - -class StoreHere -{ -public: - - StoreHere(RsGxsNetService::ClientGrpMap& cgm, RsGxsNetService::ClientMsgMap& cmm, RsGxsNetService::ServerMsgMap& smm,RsGxsNetService::GrpConfigMap& gcm, RsGxsServerGrpUpdate& sgm) - : mClientGrpMap(cgm), mClientMsgMap(cmm), mServerMsgMap(smm), mGrpConfigMap(gcm), mServerGrpUpdate(sgm) - {} - - template void check_store(ID_type id,UpdateMap& map,ItemClass& item) - { - if(!id.isNull()) - map.insert(std::make_pair(id,item)) ; - else - std::cerr << "(EE) loaded a null ID for class type " << typeid(map).name() << std::endl; - } - - void operator() (RsItem* item) - { - RsGxsMsgUpdateItem *mui; - RsGxsGrpUpdateItem *gui; - RsGxsServerGrpUpdateItem *gsui; - RsGxsServerMsgUpdateItem *msui; - RsGxsGrpConfigItem *mgci; - - if((mui = dynamic_cast(item)) != NULL) - check_store(mui->peerID,mClientMsgMap,*mui); - else if((mgci = dynamic_cast(item)) != NULL) - check_store(mgci->grpId,mGrpConfigMap, *mgci); - else if((gui = dynamic_cast(item)) != NULL) - check_store(gui->peerID,mClientGrpMap, *gui); - else if((msui = dynamic_cast(item)) != NULL) - check_store(msui->grpId,mServerMsgMap, *msui); - else if((gsui = dynamic_cast(item)) != NULL) - mServerGrpUpdate = *gsui; - else - std::cerr << "Type not expected!" << std::endl; - - delete item ; - } - -private: - - RsGxsNetService::ClientGrpMap& mClientGrpMap; - RsGxsNetService::ClientMsgMap& mClientMsgMap; - RsGxsNetService::ServerMsgMap& mServerMsgMap; - RsGxsNetService::GrpConfigMap& mGrpConfigMap; - - RsGxsServerGrpUpdate& mServerGrpUpdate; -}; - -bool RsGxsNetService::loadList(std::list &load) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - // The delete is done in StoreHere, if necessary - - std::for_each(load.begin(), load.end(), StoreHere(mClientGrpUpdateMap, mClientMsgUpdateMap, mServerMsgUpdateMap, mServerGrpConfigMap, mGrpServerUpdate)); - rstime_t now = time(NULL); - - // We reset group statistics here. This is the best place since we know at this point which are all unsubscribed groups. - - for(GrpConfigMap::iterator it(mServerGrpConfigMap.begin());it!=mServerGrpConfigMap.end();++it) - { - // At each reload, we reset the count of visible messages. It will be rapidely restored to its real value from friends. - - it->second.max_visible_count = 0; // std::max(it2->second.message_count,gnsr.max_visible_count) ; - - // the update time stamp is randomised so as not to ask all friends at once about group statistics. - - it->second.statistics_update_TS = now - GROUP_STATS_UPDATE_DELAY + (RSRandom::random_u32()%(GROUP_STATS_UPDATE_DELAY/10)) ; - - // Similarly, we remove all suppliers. - // Actual suppliers will come back automatically. - - it->second.suppliers.ids.clear() ; - - // also make sure that values stored for keep and req delays correspond to the canonical values - - locked_checkDelay(it->second.msg_req_delay); - locked_checkDelay(it->second.msg_keep_delay); - } - - return true; -} - -void RsGxsNetService::locked_checkDelay(uint32_t& time_in_secs) -{ - if(time_in_secs < 1 * 86400) { time_in_secs = 0 ; return ; } - if(time_in_secs <= 10 * 86400) { time_in_secs = 5 * 86400; return ; } - if(time_in_secs <= 20 * 86400) { time_in_secs = 15 * 86400; return ; } - if(time_in_secs <= 60 * 86400) { time_in_secs = 30 * 86400; return ; } - if(time_in_secs <= 120 * 86400) { time_in_secs = 90 * 86400; return ; } - if(time_in_secs <= 250 * 86400) { time_in_secs = 180 * 86400; return ; } - time_in_secs = 365 * 86400; -} - -#include - -template -struct get_second : public std::unary_function -{ - get_second(uint16_t serv_type,typename UpdateMap::key_type ItemClass::*member): mServType(serv_type),ID_member(member) {} - - RsItem* operator()(const typename UpdateMap::value_type& value) const - { - ItemClass *item = new ItemClass(value.second,mServType); - (*item).*ID_member = value.first ; - return item ; - } - - uint16_t mServType ; - typename UpdateMap::key_type ItemClass::*ID_member ; -}; - - -bool RsGxsNetService::saveList(bool& cleanup, std::list& save) -{ - RS_STACK_MUTEX(mNxsMutex) ; - -#ifdef NXS_NET_DEBUG_0 - std::cerr << "RsGxsNetService::saveList()..." << std::endl; -#endif - - // hardcore templates - std::transform(mClientGrpUpdateMap.begin(), mClientGrpUpdateMap.end(), std::back_inserter(save), get_second(mServType,&RsGxsGrpUpdateItem::peerID)); - std::transform(mClientMsgUpdateMap.begin(), mClientMsgUpdateMap.end(), std::back_inserter(save), get_second(mServType,&RsGxsMsgUpdateItem::peerID)); - std::transform(mServerMsgUpdateMap.begin(), mServerMsgUpdateMap.end(), std::back_inserter(save), get_second(mServType,&RsGxsServerMsgUpdateItem::grpId)); - std::transform(mServerGrpConfigMap.begin(), mServerGrpConfigMap.end(), std::back_inserter(save), get_second(mServType,&RsGxsGrpConfigItem::grpId)); - - RsGxsServerGrpUpdateItem *it = new RsGxsServerGrpUpdateItem(mGrpServerUpdate,mServType) ; - - save.push_back(it); - - cleanup = true; - return true; -} - -RsSerialiser *RsGxsNetService::setupSerialiser() -{ - - RsSerialiser *rss = new RsSerialiser; - rss->addSerialType(new RsGxsUpdateSerialiser(mServType)); - - return rss; -} - -RsItem *RsGxsNetService::generic_recvItem() -{ - { - RsItem *item ; - - if(NULL != (item=recvItem())) - return item ; - } - - unsigned char *data = NULL ; - uint32_t size = 0 ; - RsGxsNetTunnelVirtualPeerId virtual_peer_id ; - - while(mAllowDistSync && mGxsNetTunnel!=NULL && mGxsNetTunnel->receiveTunnelData(mServType,data,size,virtual_peer_id)) - { - RsNxsItem *item = dynamic_cast(RsNxsSerialiser(mServType).deserialise(data,&size)) ; - item->PeerId(virtual_peer_id) ; - - free(data) ; - - if(!item) - continue ; - -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG_P_(item->PeerId()) << "Received RsGxsNetTunnelService Item:" << (void*)item << " of type: " << std::hex << item->PacketId() << std::dec - << " transaction " << item->transactionNumber << " from virtual peer " << item->PeerId() << std::endl ; -#endif - return item ; - } - - return NULL ; -} - -void RsGxsNetService::recvNxsItemQueue() -{ - RsItem* item; - - while(nullptr != (item=generic_recvItem())) - { -#ifdef NXS_NET_DEBUG_1 - RS_DBG( "Received RsGxsNetService Item: ", (void*)item, " type=", - item->PacketId() ); -#endif - /* Handle pull request and other new items here to not mess with all the - * old nested code and items hell */ - // RsNxsItem needs dynamic_cast, since they have derived siblings. - // - RsNxsItem *ni = dynamic_cast(item) ; - if(ni != NULL) - { - // a live transaction has a non zero value - if(ni->transactionNumber != 0) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(item->PeerId()) << " recvNxsItemQueue() handlingTransaction, transN " << ni->transactionNumber << std::endl; -#endif - - if(!handleTransaction(ni)) - delete ni; - - continue; - } - - // Check whether the item is encrypted. If so, try to decrypt it, and replace ni with the decrypted item.. - - bool item_was_encrypted = false ; - - if(ni->PacketSubType() == RS_PKT_SUBTYPE_NXS_ENCRYPTED_DATA_ITEM) - { - RsNxsItem *decrypted_item ; - - if(decryptSingleNxsItem(dynamic_cast(ni),decrypted_item)) - { - item = ni = decrypted_item ; - item_was_encrypted = true ; -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(item->PeerId()) << " decrypted item " << std::endl; -#endif - } -#ifdef NXS_NET_DEBUG_7 - else - GXSNETDEBUG_P_(item->PeerId()) << " (EE) Could not decrypt incoming encrypted NXS item. Probably a friend subscribed to a circle-restricted group." << std::endl; -#endif - } - - switch(ni->PacketSubType()) - { - case RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS_ITEM: handleRecvSyncGrpStatistics (dynamic_cast(ni)) ; break ; - case RS_PKT_SUBTYPE_NXS_SYNC_GRP_REQ_ITEM: handleRecvSyncGroup (dynamic_cast(ni)) ; break ; - case RS_PKT_SUBTYPE_NXS_SYNC_MSG_REQ_ITEM: handleRecvSyncMessage (dynamic_cast(ni),item_was_encrypted) ; break ; - case RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY_ITEM: handleRecvPublishKeys (dynamic_cast(ni)) ; break ; - case RS_PKT_SUBTYPE_NXS_SYNC_PULL_REQUEST_ITEM: handlePullRequest (dynamic_cast(ni)) ; break ; - - default: - if(ni->PacketSubType() != RS_PKT_SUBTYPE_NXS_ENCRYPTED_DATA_ITEM) - { - std::cerr << "Unhandled item subtype " << (uint32_t) ni->PacketSubType() << " in RsGxsNetService: " << std::endl ; break ; - } - } - delete item ; - } - else - { - std::cerr << "Not a RsNxsItem, deleting!" << std::endl; - delete(item); - } - } -} - - -bool RsGxsNetService::handleTransaction(RsNxsItem* item) -{ -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(item->PeerId()) << "handleTransaction(RsNxsItem) number=" << item->transactionNumber << std::endl; -#endif - - /*! - * This attempts to handle a transaction - * It first checks if this transaction id already exists - * If it does then check this not a initiating transactions - */ - - RS_STACK_MUTEX(mNxsMutex) ; - - const RsPeerId& peer = item->PeerId(); - - RsNxsTransacItem* transItem = dynamic_cast(item); - - // if this is a RsNxsTransac item process - if(transItem) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(item->PeerId()) << " this is a RsNxsTransac item. callign process." << std::endl; -#endif - return locked_processTransac(transItem); - } - - - // then this must be transaction content to be consumed - // first check peer exist for transaction - bool peerTransExists = mTransactions.find(peer) != mTransactions.end(); - - // then check transaction exists - - NxsTransaction* tr = NULL; - uint32_t transN = item->transactionNumber; - - if(peerTransExists) - { - TransactionIdMap& transMap = mTransactions[peer]; - - if(transMap.find(transN) != transMap.end()) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(item->PeerId()) << " Consuming Transaction content, transN: " << item->transactionNumber << std::endl; - GXSNETDEBUG_P_(item->PeerId()) << " Consuming Transaction content, from Peer: " << item->PeerId() << std::endl; -#endif - - tr = transMap[transN]; - tr->mItems.push_back(item); - - return true; - } - } - - return false; -} - -bool RsGxsNetService::locked_processTransac(RsNxsTransacItem *item) -{ - - /*! - * To process the transaction item - * It can either be initiating a transaction - * or ending one that already exists - * - * For initiating an incoming transaction the peer - * and transaction item need not exists - * as the peer will be added and transaction number - * added thereafter - * - * For commencing/starting an outgoing transaction - * the transaction must exist already - * - * For ending a transaction the - */ - - RsPeerId peer; - - // for outgoing transaction use own id - if(item->transactFlag & (RsNxsTransacItem::FLAG_BEGIN_P2 | RsNxsTransacItem::FLAG_END_SUCCESS)) - peer = mOwnId; - else - peer = item->PeerId(); - - uint32_t transN = item->transactionNumber; - item->timestamp = time(NULL); // register time received - NxsTransaction* tr = NULL; - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peer) << "locked_processTransac() " << std::endl; - GXSNETDEBUG_P_(peer) << " Received transaction item: " << transN << std::endl; - GXSNETDEBUG_P_(peer) << " With peer: " << item->PeerId() << std::endl; - GXSNETDEBUG_P_(peer) << " trans type: " << item->transactFlag << std::endl; -#endif - - bool peerTrExists = mTransactions.find(peer) != mTransactions.end(); - bool transExists = false; - - if(peerTrExists) - { - TransactionIdMap& transMap = mTransactions[peer]; - // record whether transaction exists already - transExists = transMap.find(transN) != transMap.end(); - } - - // initiating an incoming transaction - if(item->transactFlag & RsNxsTransacItem::FLAG_BEGIN_P1) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peer) << " initiating Incoming transaction." << std::endl; -#endif - - if(transExists) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peer) << " transaction already exist! ERROR" << std::endl; -#endif - return false; // should not happen! - } - - // create a transaction if the peer does not exist - if(!peerTrExists) - mTransactions[peer] = TransactionIdMap(); - - TransactionIdMap& transMap = mTransactions[peer]; - - - // create new transaction - tr = new NxsTransaction(); - transMap[transN] = tr; - tr->mTransaction = item; - tr->mTimeOut = item->timestamp + mTransactionTimeOut; -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peer) << " Setting timeout of " << mTransactionTimeOut << " secs, which is " << tr->mTimeOut - time(NULL) << " secs from now." << std::endl; -#endif - - // note state as receiving, commencement item - // is sent on next run() loop - tr->mFlag = NxsTransaction::FLAG_STATE_STARTING; - return true; - // commencement item for outgoing transaction - } - else if(item->transactFlag & RsNxsTransacItem::FLAG_BEGIN_P2) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peer) << " initiating outgoign transaction." << std::endl; -#endif - // transaction must exist - if(!peerTrExists || !transExists) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peer) << " transaction does not exist. Cancelling!" << std::endl; -#endif - - return false; - } - - - // alter state so transaction content is sent on - // next run() loop - TransactionIdMap& transMap = mTransactions[mOwnId]; - NxsTransaction* tr = transMap[transN]; - tr->mFlag = NxsTransaction::FLAG_STATE_SENDING; - delete item; - return true; - // end transac item for outgoing transaction - } - else if(item->transactFlag & RsNxsTransacItem::FLAG_END_SUCCESS) - { - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peer) << " marking this transaction succeed" << std::endl; -#endif - // transaction does not exist - if(!peerTrExists || !transExists) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peer) << " transaction does not exist. Cancelling!" << std::endl; -#endif - return false; - } - - // alter state so that transaction is removed - // on next run() loop - TransactionIdMap& transMap = mTransactions[mOwnId]; - NxsTransaction* tr = transMap[transN]; - tr->mFlag = NxsTransaction::FLAG_STATE_COMPLETED; - delete item; - return true; - } - else - return false; -} - -void RsGxsNetService::threadTick() -{ - static const double timeDelta = 0.5; - - //Start waiting as nothing to do in runup - rstime::rs_usleep((int) (timeDelta * 1000 * 1000)); // timeDelta sec - - if(mUpdateCounter >= 120) // 60 seconds - { - updateServerSyncTS(); -#ifdef TO_REMOVE - updateClientSyncTS(); -#endif - mUpdateCounter = 1; - } - else - mUpdateCounter++; - - if(mUpdateCounter % 20 == 0) // dump the full shit every 20 secs - debugDump() ; - - // process active transactions - processTransactions(); - - // process completed transactions - processCompletedTransactions(); - - // vetting of id and circle info - runVetting(); - - processExplicitGroupRequests(); -} - -void RsGxsNetService::debugDump() -{ -#ifdef NXS_NET_DEBUG_0 - RS_STACK_MUTEX(mNxsMutex) ; - //rstime_t now = time(NULL) ; - - GXSNETDEBUG___<< "RsGxsNetService::debugDump():" << std::endl; - - RsGxsGrpMetaTemporaryMap grpMetas; - - if(!group_id_to_print.isNull()) - grpMetas[group_id_to_print] = NULL ; - - mDataStore->retrieveGxsGrpMetaData(grpMetas); - - GXSNETDEBUG___<< " mGrpServerUpdateItem time stamp: " << nice_time_stamp(time(NULL) , mGrpServerUpdate.grpUpdateTS) << " (is the last local modification time over all groups of this service)" << std::endl; - - GXSNETDEBUG___<< " mServerMsgUpdateMap: (is for each subscribed group, the last local modification time)" << std::endl; - - for(ServerMsgMap::const_iterator it(mServerMsgUpdateMap.begin());it!=mServerMsgUpdateMap.end();++it) - { - RsGxsGrpMetaTemporaryMap::const_iterator it2 = grpMetas.find(it->first) ; - auto grpMeta = (it2 != grpMetas.end())? it2->second : (std::shared_ptr()) ; - std::string subscribe_string = (grpMeta==NULL)?"Unknown" : ((grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED)?" Subscribed":" NOT Subscribed") ; - - GXSNETDEBUG__G(it->first) << " Grp:" << it->first << " last local modification (secs ago): " << nice_time_stamp(time(NULL),it->second.msgUpdateTS) << ", " << subscribe_string << std::endl; - } - - GXSNETDEBUG___<< " mClientGrpUpdateMap: (is for each friend, last modif time of group meta data at that friend, all groups included, sent by the friend himself)" << std::endl; - - for(std::map::const_iterator it(mClientGrpUpdateMap.begin());it!=mClientGrpUpdateMap.end();++it) - GXSNETDEBUG_P_(it->first) << " From peer: " << it->first << " - last updated at peer (secs ago): " << nice_time_stamp(time(NULL),it->second.grpUpdateTS) << std::endl; - - GXSNETDEBUG___<< " mClientMsgUpdateMap: (is for each friend, the modif time for each group (e.g. last message received), sent by the friend himself)" << std::endl; - - for(std::map::const_iterator it(mClientMsgUpdateMap.begin());it!=mClientMsgUpdateMap.end();++it) - { - GXSNETDEBUG_P_(it->first) << " From peer: " << it->first << std::endl; - - for(std::map::const_iterator it2(it->second.msgUpdateInfos.begin());it2!=it->second.msgUpdateInfos.end();++it2) - GXSNETDEBUG_PG(it->first,it2->first) << " group " << it2->first << " - last updated at peer (secs ago): " << nice_time_stamp(time(NULL),it2->second.time_stamp) << ". Message count=" << it2->second.message_count << std::endl; - } - - GXSNETDEBUG___<< " List of rejected message ids: " << std::dec << mRejectedMessages.size() << std::endl; -#endif -} - -#ifdef TO_REMOVE -// This method is normally not needed, but we use it to correct possible inconsistencies in the updte time stamps -// on the client side. - -void RsGxsNetService::updateClientSyncTS() -{ - RS_STACK_MUTEX(mNxsMutex) ; - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG___<< "updateClientSyncTS(): checking last modification time stamps of local data w.r.t. client's modification times" << std::endl; -#endif - - if(mGrpServerUpdateItem == NULL) - mGrpServerUpdateItem = new RsGxsServerGrpUpdateItem(mServType); - - for(ClientGrpMap::iterator it = mClientGrpUpdateMap.begin();it!=mClientGrpUpdateMap.end();++it) - if(it->second->grpUpdateTS > SECURITY_DELAY_TO_FORCE_CLIENT_REUPDATE + mGrpServerUpdateItem->grpUpdateTS) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(it->first) << " last global client GRP modification time known for peer (" << nice_time_stamp(time(NULL),it->second->grpUpdateTS) << " is quite more recent than our own server modification time (" << nice_time_stamp(time(NULL),mGrpServerUpdateItem->grpUpdateTS) << ". Forcing update! " << std::endl; -#endif - it->second->grpUpdateTS = 0 ; - } - - for(ClientMsgMap::iterator it = mClientMsgUpdateMap.begin();it!=mClientMsgUpdateMap.end();++it) - for(std::map::iterator it2 = it->second->msgUpdateInfos.begin();it2!=it->second->msgUpdateInfos.end();++it2) - { - std::map::const_iterator mmit = mServerMsgUpdateMap.find(it2->first) ; - - if(mmit != mServerMsgUpdateMap.end() && it2->second.time_stamp > SECURITY_DELAY_TO_FORCE_CLIENT_REUPDATE + mmit->second->msgUpdateTS) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(it->first,it2->first) << " last group msg modification time known for peer (" << nice_time_stamp(time(NULL),it2->second.time_stamp) << " and group " << it2->first << " is quite more recent than our own server modification time (" << nice_time_stamp(time(NULL),mmit->second->msgUpdateTS) << ". Forcing update! " << std::endl; -#endif - it2->second.time_stamp = 0 ; - } - } -} -#endif - -void RsGxsNetService::updateServerSyncTS() -{ - RsGxsGrpMetaTemporaryMap gxsMap; - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG___<< "updateServerSyncTS(): updating last modification time stamp of local data." << std::endl; -#endif - - { - RS_STACK_MUTEX(mNxsMutex) ; - // retrieve all grps and update TS - mDataStore->retrieveGxsGrpMetaData(gxsMap); - - // (cyril) This code was previously removed because it sounded inconsistent: the list of grps normally does not need to be updated when - // new posts arrive. The two (grp list and msg list) are handled independently. Still, when group meta data updates are received, - // the server TS needs to be updated, because it is the only way to propagate the changes. So we update it to the publish time stamp, - // if needed. - - // as a grp list server also note this is the latest item you have - // then remove from mServerMsgUpdateMap, all items that are not in the group list! - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG___ << " cleaning server map of groups with no data:" << std::endl; -#endif - - for(ServerMsgMap::iterator it(mServerMsgUpdateMap.begin());it!=mServerMsgUpdateMap.end();) - if(gxsMap.find(it->first) == gxsMap.end()) - { - // not found! Removing server update info for this group - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG__G(it->first) << " removing server update info for group " << it->first << std::endl; -#endif - ServerMsgMap::iterator tmp(it) ; - ++tmp ; - mServerMsgUpdateMap.erase(it) ; - it = tmp ; - } - else - ++it; - } - -#ifdef NXS_NET_DEBUG_0 - if(gxsMap.empty()) - GXSNETDEBUG___<< " database seems to be empty. The modification timestamp will be reset." << std::endl; -#endif - // finally, update timestamps. - bool change = false; - - for(auto mit = gxsMap.begin();mit != gxsMap.end(); ++mit) - { - // Check if the group is subscribed and restricted to a circle. If the circle has changed, update the - // global TS to reflect that change to clients who may be able to see/subscribe to that particular group. - - if( (mit->second->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) && !mit->second->mCircleId.isNull()) - { - // ask to the GxsNetService of circles what the server TS is for that circle. If more recent, we update the serverTS of the - // local group - - rstime_t circle_group_server_ts ; - rstime_t circle_msg_server_ts ; - - // This call needs to be off-mutex, because of self-restricted circles. - // Normally we should update as a function of MsgServerUpdateTS and the mRecvTS of the circle, not the global grpServerTS. - // But grpServerTS is easier to get since it does not require a db access. So we trade the real call for this cheap and conservative call. - - if(mCircles->getLocalCircleServerUpdateTS(mit->second->mCircleId,circle_group_server_ts,circle_msg_server_ts)) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG__G(mit->first) << " Group " << mit->first << " is conditionned to circle " << mit->second->mCircleId << ". local Grp TS=" << time(NULL) - mGrpServerUpdate.grpUpdateTS << " secs ago, circle grp server update TS=" << time(NULL) - circle_group_server_ts << " secs ago"; -#endif - // We use a max here between grp and msg TS because membership is driven by invite list (grp data) crossed with - // membership requests messages (msg data). - - auto circle_membership_ts = std::max(circle_group_server_ts,circle_msg_server_ts); - - if(circle_membership_ts > mGrpServerUpdate.grpUpdateTS) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG__G(mit->first) << " - Updating local Grp Server update TS to follow changes in circles." << std::endl; -#endif - - RS_STACK_MUTEX(mNxsMutex) ; - mGrpServerUpdate.grpUpdateTS = circle_membership_ts ; - } -#ifdef NXS_NET_DEBUG_0 - else - GXSNETDEBUG__G(mit->first) << " - Nothing to do." << std::endl; -#endif - } - else - std::cerr << "(EE) Cannot retrieve attached circle TS" << std::endl; - } - - RS_STACK_MUTEX(mNxsMutex) ; - - const auto& grpMeta = mit->second; -#ifdef TO_REMOVE - // That accounts for modification of the meta data. - - if(mGrpServerUpdateItem->grpUpdateTS < grpMeta->mPublishTs) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG__G(grpId) << " publish time stamp of group " << grpId << " has changed to " << time(NULL)-grpMeta->mPublishTs << " secs ago. updating!" << std::endl; -#endif - mGrpServerUpdateItem->grpUpdateTS = grpMeta->mPublishTs; - } -#endif - - // I keep the creation, but the data is not used yet. -#warning csoler 2016-12-12: Disabled this, but do we need it? - // RsGxsServerMsgUpdate& msui(mServerMsgUpdateMap[grpId]) ; - - // (cyril) I'm removing this, because the msgUpdateTS is updated when new messages are received by calling locked_stampMsgServerUpdateTS(). - // mLastPost is actually updated somewhere when loading group meta data. It's not clear yet whether it is set to the latest publish time (wrong) - // or the latest receive time (right). The former would cause problems because it would need to compare times coming from different (potentially async-ed) - // machines. - // - // if(grpMeta->mLastPost > msui->msgUpdateTS ) - // { - // change = true; - // msui->msgUpdateTS = grpMeta->mLastPost; -#ifdef NXS_NET_DEBUG_0 - // GXSNETDEBUG__G(grpId) << " updated msgUpdateTS to last post = " << time(NULL) - grpMeta->mLastPost << " secs ago for group "<< grpId << std::endl; -#endif - // } - - // This is needed for group metadata updates to actually propagate: only a new grpUpdateTS will trigger the exchange of groups mPublishTs which - // will then be compared and pssibly trigger a MetaData transmission. mRecvTS is upated when creating, receiving for the first time, or receiving - // an update, all in rsgenexchange.cc, after group/update validation. It is therefore a local TS, that can be compared to grpUpdateTS (same machine). - - if(mGrpServerUpdate.grpUpdateTS < grpMeta->mRecvTS) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG__G(grpMeta->mGroupId) << " updated msgUpdateTS to last RecvTS = " << time(NULL) - grpMeta->mRecvTS << " secs ago for group "<< grpMeta->mGroupId << ". This is probably because an update has been received." << std::endl; -#endif - mGrpServerUpdate.grpUpdateTS = grpMeta->mRecvTS; - change = true; - } - } - - // actual change in config settings, then save configuration - if(change) - IndicateConfigChanged(); -} - -bool RsGxsNetService::locked_checkTransacTimedOut(NxsTransaction* tr) -{ - return tr->mTimeOut < ((uint32_t) time(NULL)); -} - -void RsGxsNetService::processTransactions() -{ - RS_STACK_MUTEX(mNxsMutex) ; - - for(TransactionsPeerMap::iterator mit = mTransactions.begin();mit != mTransactions.end(); ++mit) - { -#ifdef NXS_NET_DEBUG_1 - if(!mit->second.empty()) - GXSNETDEBUG_P_(mit->first) << "processTransactions from/to peer " << mit->first << std::endl; -#endif - - TransactionIdMap& transMap = mit->second; - TransactionIdMap::iterator mmit = transMap.begin(), mmit_end = transMap.end(); - - if(mmit == mmit_end) // no waiting transactions for this peer - continue ; - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first) << " peerId=" << mit->first << std::endl; -#endif - // transaction to be removed - std::list toRemove; - - /*! - * Transactions owned by peer - */ - if(mit->first == mOwnId) - { - for(; mmit != mmit_end; ++mmit) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first) << " type: outgoing " << std::endl; - GXSNETDEBUG_P_(mit->first) << " transN = " << mmit->second->mTransaction->transactionNumber << std::endl; -#endif - NxsTransaction* tr = mmit->second; - uint16_t flag = tr->mFlag; - std::list::iterator lit, lit_end; - uint32_t transN = tr->mTransaction->transactionNumber; - - // first check transaction has not expired - if(locked_checkTransacTimedOut(tr)) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first) << " timeout! " << std::endl; - GXSNETDEBUG_P_(mit->first) << std::dec ; - int total_transaction_time = (int)time(NULL) - (tr->mTimeOut - mTransactionTimeOut) ; - GXSNETDEBUG_P_(mit->first) << " Outgoing Transaction has failed, tranN: " << transN << ", Peer: " << mit->first ; - GXSNETDEBUG_P_(mit->first) << ", age: " << total_transaction_time << ", nItems=" << tr->mTransaction->nItems << ". tr->mTimeOut = " << tr->mTimeOut << ", now = " << (uint32_t) time(NULL) << std::endl; -#endif - - tr->mFlag = NxsTransaction::FLAG_STATE_FAILED; - toRemove.push_back(transN); - mComplTransactions.push_back(tr); - continue; - } -#ifdef NXS_NET_DEBUG_1 - else - GXSNETDEBUG_P_(mit->first) << " still on time." << std::endl; -#endif - - // send items requested - if(flag & NxsTransaction::FLAG_STATE_SENDING) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first)<< " Sending Transaction content, transN: " << transN << " with peer: " << tr->mTransaction->PeerId() << std::endl; -#endif - lit = tr->mItems.begin(); - lit_end = tr->mItems.end(); - - for(; lit != lit_end; ++lit){ - generic_sendItem(*lit); - } - - tr->mItems.clear(); // clear so they don't get deleted in trans cleaning - tr->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; - - } - else if(flag & NxsTransaction::FLAG_STATE_WAITING_CONFIRM) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first)<< " Waiting confirm! returning." << std::endl; -#endif - continue; - - } - else if(flag & NxsTransaction::FLAG_STATE_COMPLETED) - { - -#ifdef NXS_NET_DEBUG_1 - int total_transaction_time = (int)time(NULL) - (tr->mTimeOut - mTransactionTimeOut) ; - - GXSNETDEBUG_P_(mit->first)<< " Outgoing completed " << tr->mTransaction->nItems << " items transaction in " << total_transaction_time << " seconds." << std::endl; -#endif - // move to completed transactions - toRemove.push_back(transN); - mComplTransactions.push_back(tr); - }else{ - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first)<< " Unknown flag for active transaction, transN: " << transN << ", Peer: " << mit->first<< std::endl; -#endif - - toRemove.push_back(transN); - tr->mFlag = NxsTransaction::FLAG_STATE_FAILED; - mComplTransactions.push_back(tr); - } - } - - }else{ - - /*! - * Essentially these are incoming transactions - * Several states are dealth with - * Receiving: waiting to receive items from peer's transaction - * and checking if all have been received - * Completed: remove transaction from active and tell peer - * involved in transaction - * Starting: this is a new transaction and need to teell peer - * involved in transaction - */ - - for(; mmit != mmit_end; ++mmit){ - - NxsTransaction* tr = mmit->second; - uint16_t flag = tr->mFlag; - uint32_t transN = tr->mTransaction->transactionNumber; - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first) << " type: incoming " << std::endl; - GXSNETDEBUG_P_(mit->first) << " transN = " << mmit->second->mTransaction->transactionNumber << std::endl; -#endif - // first check transaction has not expired - if(locked_checkTransacTimedOut(tr)) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first) << " timeout!" << std::endl; - GXSNETDEBUG_P_(mit->first) << std::dec ; - int total_transaction_time = (int)time(NULL) - (tr->mTimeOut - mTransactionTimeOut) ; - GXSNETDEBUG_P_(mit->first) << " Incoming Transaction has failed, tranN: " << transN << ", Peer: " << mit->first ; - GXSNETDEBUG_P_(mit->first) << ", age: " << total_transaction_time << ", nItems=" << tr->mTransaction->nItems << ". tr->mTimeOut = " << tr->mTimeOut << ", now = " << (uint32_t) time(NULL) << std::endl; -#endif - - tr->mFlag = NxsTransaction::FLAG_STATE_FAILED; - toRemove.push_back(transN); - mComplTransactions.push_back(tr); - continue; - } - - if(flag & NxsTransaction::FLAG_STATE_RECEIVING) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first) << " received " << tr->mItems.size() << " item over a total of " << tr->mTransaction->nItems << std::endl; -#endif - - // if the number it item received equal that indicated - // then transaction is marked as completed - // to be moved to complete transations - // check if done - if(tr->mItems.size() == tr->mTransaction->nItems) - { - tr->mFlag = NxsTransaction::FLAG_STATE_COMPLETED; -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first) << " completed!" << std::endl; -#endif - } - - }else if(flag & NxsTransaction::FLAG_STATE_COMPLETED) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first) << " transaction is completed!" << std::endl; - GXSNETDEBUG_P_(mit->first) << " sending success!" << std::endl; -#endif - - // send completion msg - RsNxsTransacItem* trans = new RsNxsTransacItem(mServType); - trans->clear(); - trans->transactFlag = RsNxsTransacItem::FLAG_END_SUCCESS; - trans->transactionNumber = transN; - trans->PeerId(tr->mTransaction->PeerId()); - generic_sendItem(trans); - - // move to completed transactions - - // Try to decrypt the items that need to be decrypted. This function returns true if the transaction is not encrypted. - - if(processTransactionForDecryption(tr)) - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " successfully decrypted/processed transaction " << transN << ". Adding to completed list." << std::endl; -#endif - mComplTransactions.push_back(tr); - - // transaction processing done - // for this id, add to removal list - toRemove.push_back(mmit->first); -#ifdef NXS_NET_DEBUG_1 - int total_transaction_time = (int)time(NULL) - (tr->mTimeOut - mTransactionTimeOut) ; - GXSNETDEBUG_P_(mit->first) << " incoming completed " << tr->mTransaction->nItems << " items transaction in " << total_transaction_time << " seconds." << std::endl; -#endif - } - else - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " no decryption occurred because of unloaded keys. Will retry later. TransN=" << transN << std::endl; -#endif - } - - - } - else if(flag & NxsTransaction::FLAG_STATE_STARTING) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first) << " transaction is starting!" << std::endl; - GXSNETDEBUG_P_(mit->first) << " setting state to Receiving" << std::endl; -#endif - // send item to tell peer your are ready to start - RsNxsTransacItem* trans = new RsNxsTransacItem(mServType); - trans->clear(); - trans->transactFlag = RsNxsTransacItem::FLAG_BEGIN_P2 | - (tr->mTransaction->transactFlag & RsNxsTransacItem::FLAG_TYPE_MASK); - trans->transactionNumber = transN; - trans->PeerId(tr->mTransaction->PeerId()); - generic_sendItem(trans); - tr->mFlag = NxsTransaction::FLAG_STATE_RECEIVING; - - } - else{ -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(mit->first) << " transaction is in unknown state. ERROR!" << std::endl; - GXSNETDEBUG_P_(mit->first) << " transaction FAILS!" << std::endl; -#endif - - std::cerr << " Unknown flag for active transaction, transN: " << transN << ", Peer: " << mit->first << std::endl; - toRemove.push_back(mmit->first); - mComplTransactions.push_back(tr); - tr->mFlag = NxsTransaction::FLAG_STATE_FAILED; // flag as a failed transaction - } - } - } - - std::list::iterator lit = toRemove.begin(); - - for(; lit != toRemove.end(); ++lit) - { - transMap.erase(*lit); - } - - } -} - -bool RsGxsNetService::getGroupNetworkStats(const RsGxsGroupId& gid,RsGroupNetworkStats& stats) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - GrpConfigMap::const_iterator it ( mServerGrpConfigMap.find(gid) ); - - if(it == mServerGrpConfigMap.end()) - return false ; - - stats.mSuppliers = it->second.suppliers.ids.size(); - stats.mMaxVisibleCount = it->second.max_visible_count ; - stats.mAllowMsgSync = mAllowMsgSync ; - stats.mGrpAutoSync = mGrpAutoSync ; - stats.mLastGroupModificationTS = it->second.last_group_modification_TS ; - - return true ; -} - -void RsGxsNetService::processCompletedTransactions() -{ - RS_STACK_MUTEX(mNxsMutex) ; - /*! - * Depending on transaction we may have to respond to peer - * responsible for transaction - */ - while(mComplTransactions.size()>0) - { - - NxsTransaction* tr = mComplTransactions.front(); - - bool outgoing = tr->mTransaction->PeerId() == mOwnId; - - if(outgoing){ - locked_processCompletedOutgoingTrans(tr); - }else{ - locked_processCompletedIncomingTrans(tr); - } - - - delete tr; - mComplTransactions.pop_front(); - } -} - -void RsGxsNetService::locked_processCompletedIncomingTrans(NxsTransaction* tr) -{ - uint16_t flag = tr->mTransaction->transactFlag; - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << "Processing complete Incoming transaction with " << tr->mTransaction->nItems << " items." << std::endl; - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " flags = " << flag << std::endl; - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " peerId= " << tr->mTransaction->PeerId() << std::endl; -#endif - if(tr->mFlag & NxsTransaction::FLAG_STATE_COMPLETED) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " transaction has completed." << std::endl; -#endif - // for a completed list response transaction - // one needs generate requests from this - if(flag & RsNxsTransacItem::FLAG_TYPE_MSG_LIST_RESP) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " type = msg list response." << std::endl; - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " => generate msg request based on it." << std::endl; -#endif - // generate request based on a peers response - locked_genReqMsgTransaction(tr); - - }else if(flag & RsNxsTransacItem::FLAG_TYPE_GRP_LIST_RESP) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " type = grp list response." << std::endl; - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " => generate group transaction request based on it." << std::endl; -#endif - locked_genReqGrpTransaction(tr); - } - // you've finished receiving request information now gen - else if(flag & RsNxsTransacItem::FLAG_TYPE_MSG_LIST_REQ) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " type = msg list request." << std::endl; - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " => generate msg list based on it." << std::endl; -#endif - locked_genSendMsgsTransaction(tr); - } - else if(flag & RsNxsTransacItem::FLAG_TYPE_GRP_LIST_REQ) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " type = grp list request." << std::endl; - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " => generate grp list based on it." << std::endl; -#endif - locked_genSendGrpsTransaction(tr); - } - else if(flag & RsNxsTransacItem::FLAG_TYPE_GRPS) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " type = groups." << std::endl; -#endif - std::vector grps; - - while(tr->mItems.size() != 0) - { - RsNxsGrp* grp = dynamic_cast(tr->mItems.front()); - - if(grp) - { - tr->mItems.pop_front(); - grps.push_back(grp); -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grp->grpId) << " adding new group " << grp->grpId << " to incoming list!" << std::endl; -#endif - } - else - std::cerr << " /!\\ item did not caste to grp" << std::endl; - } - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " ...and notifying observer " << std::endl; -#endif -#ifdef NXS_NET_DEBUG_5 - GXSNETDEBUG_P_ (tr->mTransaction->PeerId()) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - Received new groups meta data from peer " << tr->mTransaction->PeerId() << std::endl; - for(uint32_t i=0;imTransaction->PeerId(),grps[i]->grpId) ; -#endif - // notify listener of grps - for(uint32_t i=0;imTransaction->PeerId(); - uint32_t updateTS = tr->mTransaction->updateTS; - -#ifdef NXS_NET_DEBUG_0 - ClientGrpMap::iterator it = mClientGrpUpdateMap.find(peerFrom); -#endif - - RsGxsGrpUpdate& item(mClientGrpUpdateMap[peerFrom]) ; - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " and updating mClientGrpUpdateMap for peer " << peerFrom << " of new time stamp " << nice_time_stamp(time(NULL),updateTS) << std::endl; -#endif - - item.grpUpdateTS = updateTS; - - IndicateConfigChanged(); - } - else if(flag & RsNxsTransacItem::FLAG_TYPE_MSGS) - { - - std::vector msgs; -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " type = msgs." << std::endl; -#endif - RsGxsGroupId grpId; - //rstime_t now = time(NULL) ; - - while(tr->mItems.size() > 0) - { - RsNxsMsg* msg = dynamic_cast(tr->mItems.front()); - if(msg) - { - if(grpId.isNull()) - grpId = msg->grpId; - - tr->mItems.pop_front(); - - msgs.push_back(msg); -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),msg->grpId) << " pushing grpId="<< msg->grpId << ", msgsId=" << msg->msgId << " to list of incoming messages" << std::endl; -#endif - } - else - std::cerr << "RsGxsNetService::processCompletedTransactions(): item did not caste to msg" << std::endl; - } - -//#warning We need here to queue all incoming items into a list where the vetting will be checked -//#warning in order to avoid someone without the proper rights to post in a group protected with an external circle - -#ifdef NXS_FRAG - // (cyril) This code does not work. Since we do not really need message fragmenting, I won't fix it. - - std::map collatedMsgs; - collateMsgFragments(msgs, collatedMsgs); // this destroys msgs whatsoever and recovers memory when needed - - msgs.clear(); - - std::map::iterator mit = collatedMsgs.begin(); - for(; mit != collatedMsgs.end(); ++mit) - { - MsgFragments& f = mit->second; - RsNxsMsg* msg = deFragmentMsg(f); - - if(msg) - msgs.push_back(msg); - } - collatedMsgs.clear(); -#endif -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grpId) << " ...and notifying observer of " << msgs.size() << " new messages." << std::endl; -#endif -#ifdef NXS_NET_DEBUG_5 - GXSNETDEBUG_PG (tr->mTransaction->PeerId(),grpId) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - Received new messages from peer " << tr->mTransaction->PeerId() << " for group " << grpId << std::endl; - for(uint32_t i=0;imTransaction->PeerId(),grpId) << " " << msgs[i]->msgId << std::endl ; -#endif - // notify listener of msgs - for(uint32_t i=0;imTransaction, grpId); - - // also update server sync TS, since we need to send the new message list to friends for comparison - locked_stampMsgServerUpdateTS(grpId); - } - } - else if(tr->mFlag == NxsTransaction::FLAG_STATE_FAILED) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " transaction has failed. Wasting it." << std::endl; -#endif - // don't do anything transaction will simply be cleaned - } - return; -} - -void RsGxsNetService::locked_doMsgUpdateWork(const RsNxsTransacItem *nxsTrans, const RsGxsGroupId &grpId) -{ -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(nxsTrans->PeerId(),grpId) << "updating MsgUpdate time stamps for peerId=" << nxsTrans->PeerId() << ", grpId=" << grpId << std::endl; -#endif - // firts check if peer exists - const RsPeerId& peerFrom = nxsTrans->PeerId(); - - if(peerFrom.isNull()) - { - std::cerr << "(EE) update from null peer!" << std::endl; - print_stacktrace() ; - } - - RsGxsMsgUpdate& mui(mClientMsgUpdateMap[peerFrom]) ; - - // now update the peer's entry for this grp id - - if(mPartialMsgUpdates[peerFrom].find(grpId) != mPartialMsgUpdates[peerFrom].end()) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(nxsTrans->PeerId(),grpId) << " this is a partial update. Not using new time stamp." << std::endl; -#endif - } - else - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(nxsTrans->PeerId(),grpId) << " this is a full update. Updating time stamp." << std::endl; -#endif - mui.msgUpdateInfos[grpId].time_stamp = nxsTrans->updateTS; - IndicateConfigChanged(); - } -} - -void RsGxsNetService::locked_processCompletedOutgoingTrans(NxsTransaction* tr) -{ - uint16_t flag = tr->mTransaction->transactFlag; - -#ifdef NXS_NET_DEBUG_0 - RsNxsTransacItem *nxsTrans = tr->mTransaction; - GXSNETDEBUG_P_(nxsTrans->PeerId()) << "locked_processCompletedOutgoingTrans(): tr->flags = " << flag << std::endl; -#endif - - if(tr->mFlag & NxsTransaction::FLAG_STATE_COMPLETED) - { - // for a completed list response transaction - // one needs generate requests from this - if(flag & RsNxsTransacItem::FLAG_TYPE_MSG_LIST_RESP) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(nxsTrans->PeerId())<< " complete Sending Msg List Response, transN: " << tr->mTransaction->transactionNumber << std::endl; -#endif - }else if(flag & RsNxsTransacItem::FLAG_TYPE_GRP_LIST_RESP) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(nxsTrans->PeerId())<< " complete Sending Grp Response, transN: " << tr->mTransaction->transactionNumber << std::endl; -#endif - } - // you've finished sending a request so don't do anything - else if( (flag & RsNxsTransacItem::FLAG_TYPE_MSG_LIST_REQ) || - (flag & RsNxsTransacItem::FLAG_TYPE_GRP_LIST_REQ) ) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(nxsTrans->PeerId())<< " complete Sending Msg/Grp Request, transN: " << tr->mTransaction->transactionNumber << std::endl; -#endif - - }else if(flag & RsNxsTransacItem::FLAG_TYPE_GRPS) - { - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(nxsTrans->PeerId())<< " complete Sending Grp Data, transN: " << tr->mTransaction->transactionNumber << std::endl; -#endif - - }else if(flag & RsNxsTransacItem::FLAG_TYPE_MSGS) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(nxsTrans->PeerId())<< " complete Sending Msg Data, transN: " << tr->mTransaction->transactionNumber << std::endl; -#endif - } - }else if(tr->mFlag == NxsTransaction::FLAG_STATE_FAILED){ -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(nxsTrans->PeerId())<< " Failed transaction! transN: " << tr->mTransaction->transactionNumber << std::endl; -#endif - }else{ - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(nxsTrans->PeerId())<< " Serious error unrecognised trans Flag! transN: " << tr->mTransaction->transactionNumber << std::endl; -#endif - } -} - - -void RsGxsNetService::locked_pushMsgTransactionFromList(std::list& reqList, const RsPeerId& peerId, const uint32_t& transN) -{ -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peerId) << "locked_pushMsgTransactionFromList()" << std::endl; - GXSNETDEBUG_P_(peerId) << " nelems = " << reqList.size() << std::endl; - GXSNETDEBUG_P_(peerId) << " peerId = " << peerId << std::endl; - GXSNETDEBUG_P_(peerId) << " transN = " << transN << std::endl; -#endif -#ifdef NXS_NET_DEBUG_5 - GXSNETDEBUG_P_ (peerId) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - sending message request to peer " - << peerId << " for " << reqList.size() << " messages" << std::endl; -#endif - RsNxsTransacItem* transac = new RsNxsTransacItem(mServType); - transac->transactFlag = RsNxsTransacItem::FLAG_TYPE_MSG_LIST_REQ - | RsNxsTransacItem::FLAG_BEGIN_P1; - transac->timestamp = 0; - transac->nItems = reqList.size(); - transac->PeerId(peerId); - transac->transactionNumber = transN; - NxsTransaction* newTrans = new NxsTransaction(); - newTrans->mItems = reqList; - newTrans->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; - newTrans->mTimeOut = time(NULL) + mTransactionTimeOut; - // create transaction copy with your id to indicate - // its an outgoing transaction - newTrans->mTransaction = new RsNxsTransacItem(*transac); - newTrans->mTransaction->PeerId(mOwnId); - - if (locked_addTransaction(newTrans)) - generic_sendItem(transac); - else - { - delete newTrans; - delete transac; - } - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peerId) << " Requested new transaction for " << reqList.size() << " items." << std::endl; -#endif -} - -void RsGxsNetService::locked_genReqMsgTransaction(NxsTransaction* tr) -{ - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG___ << "RsGxsNetService::genReqMsgTransaction()" << std::endl; -#endif - - // to create a transaction you need to know who you are transacting with - // then what msgs to request - // then add an active Transaction for request - - std::list msgItemL; - std::list::iterator lit = tr->mItems.begin(); - - // first get item list sent from transaction - for(; lit != tr->mItems.end(); ++lit) - { - RsNxsSyncMsgItem* item = dynamic_cast(*lit); - if(item) - { - msgItemL.push_back(item); - }else - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(item->PeerId()) << "RsGxsNetService::genReqMsgTransaction(): item failed cast to RsNxsSyncMsgItem* " << std::endl; -#endif - } - } -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " found " << msgItemL.size()<< " messages in this transaction." << std::endl; -#endif - - if(msgItemL.empty()) - return; - - // get grp id for this transaction - RsNxsSyncMsgItem* item = msgItemL.front(); - const RsGxsGroupId& grpId = item->grpId; - - // store the count for the peer who sent the message list - uint32_t mcount = msgItemL.size() ; - RsPeerId pid = msgItemL.front()->PeerId() ; - - RsGxsGrpConfig& gnsr(locked_getGrpConfig(grpId)); - - std::set::size_type oldSuppliersCount = gnsr.suppliers.ids.size(); - uint32_t oldVisibleCount = gnsr.max_visible_count; - - gnsr.suppliers.ids.insert(pid) ; - gnsr.max_visible_count = std::max(gnsr.max_visible_count, mcount) ; - - if (oldVisibleCount != gnsr.max_visible_count || oldSuppliersCount != gnsr.suppliers.ids.size()) - mNewStatsToNotify.insert(grpId) ; - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << " grpId = " << grpId << std::endl; - GXSNETDEBUG_PG(item->PeerId(),grpId) << " retrieving grp mesta data..." << std::endl; -#endif - RsGxsGrpMetaTemporaryMap grpMetaMap; - grpMetaMap[grpId] = NULL; - - mDataStore->retrieveGxsGrpMetaData(grpMetaMap); - const auto& grpMeta = grpMetaMap[grpId]; - - if(grpMeta == NULL) // this should not happen, but just in case... - { - std::cerr << "(EE) grpMeta is NULL in " << __PRETTY_FUNCTION__ << " line " << __LINE__ << ". This is very unexpected." << std::endl; - return ; - } - - if(! (grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED )) - { - // For unsubscribed groups, we update the timestamp something more recent, so that the group content will not be asked to the same - // peer again, unless the peer has new info about it. It's important to use the same clock (this is peer's clock) so that - // we never compare times from different (and potentially badly sync-ed clocks) - - std::cerr << "(EE) stepping in part of the code (" << __PRETTY_FUNCTION__ << ") where we shouldn't. This is a bug." << std::endl; - -#ifdef TO_REMOVE - locked_stampPeerGroupUpdateTime(pid,grpId,tr->mTransaction->updateTS,msgItemL.size()) ; -#endif - return ; - } - -#ifdef TO_REMOVE - int cutoff = 0; - if(grpMeta != NULL) - cutoff = grpMeta->mReputationCutOff; -#endif - - GxsMsgReq reqIds; - reqIds[grpId] = std::set(); - GxsMsgMetaResult result; - mDataStore->retrieveGxsMsgMetaData(reqIds, result); - auto& msgMetaV = result[grpId]; - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << " retrieving grp message list..." << std::endl; - GXSNETDEBUG_PG(item->PeerId(),grpId) << " grp locally contains " << msgMetaV.size() << " messsages." << std::endl; -#endif - std::set msgIdSet; - - // put ids in set for each searching - for(auto vit=msgMetaV.begin(); vit != msgMetaV.end(); ++vit) - msgIdSet.insert((*vit)->mMsgId); - - msgMetaV.clear(); - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << " grp locally contains " << msgIdSet.size() << " unique messsages." << std::endl; -#endif - // get unique id for this transaction - uint32_t transN = locked_getTransactionId(); - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << " new transaction ID: " << transN << std::endl; -#endif - // add msgs that you don't have to request list - std::list::iterator llit = msgItemL.begin(); - std::list reqList; - int reqListSize = 0 ; - - const RsPeerId peerFrom = tr->mTransaction->PeerId(); - - std::list peers; - peers.push_back(tr->mTransaction->PeerId()); - bool reqListSizeExceeded = false ; - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << " sorting items..." << std::endl; -#endif - for(; llit != msgItemL.end(); ++llit) - { - RsNxsSyncMsgItem*& syncItem = *llit; - const RsGxsMessageId& msgId = syncItem->msgId; - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << " msg ID = " << msgId ; -#endif - if(reqListSize >= (int)MAX_REQLIST_SIZE) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << ". reqlist too big. Pruning out this item for now." << std::endl; -#endif - reqListSizeExceeded = true ; - continue ; // we should actually break, but we need to print some debug info. - } - - if(reqListSize < (int)MAX_REQLIST_SIZE && msgIdSet.find(msgId) == msgIdSet.end()) - { - - bool noAuthor = syncItem->authorId.isNull(); - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << ", reqlist size=" << reqListSize << ", message not present." ; -#endif - // grp meta must be present if author present - - if(!noAuthor && grpMeta == NULL) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << ", no group meta found. Givign up." << std::endl; -#endif - continue; - } - - // The algorithm on request of message is: - // - // - always re-check for author ban level - // - if author is locally banned, do not download. - // - if author is not locally banned, download, whatever friends' opinion might be. - - if( mReputations->overallReputationLevel(syncItem->authorId) == - RsReputationLevel::LOCALLY_NEGATIVE ) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << ", Identity " << syncItem->authorId << " is banned. Not requesting message!" << std::endl; -#endif - continue ; - } - - if(mRejectedMessages.find(msgId) != mRejectedMessages.end()) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << ", message has been recently rejected. Not requesting message!" << std::endl; -#endif - continue ; - } - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << ", passed! Adding message to req list." << std::endl; -#endif - RsNxsSyncMsgItem* msgItem = new RsNxsSyncMsgItem(mServType); - msgItem->grpId = grpId; - msgItem->msgId = msgId; - msgItem->flag = RsNxsSyncMsgItem::FLAG_REQUEST; - msgItem->transactionNumber = transN; - msgItem->PeerId(peerFrom); - reqList.push_back(msgItem); - ++reqListSize ; - } -#ifdef NXS_NET_DEBUG_1 - else - GXSNETDEBUG_PG(item->PeerId(),grpId) << ". already here." << std::endl; -#endif - } - - if(!reqList.empty()) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << " Request list: " << reqList.size() << " elements." << std::endl; -#endif - locked_pushMsgTransactionFromList(reqList, tr->mTransaction->PeerId(), transN); - - if(reqListSizeExceeded) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << " Marking update operation as unfinished." << std::endl; -#endif - mPartialMsgUpdates[tr->mTransaction->PeerId()].insert(item->grpId) ; - } - else - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << " Marking update operation as terminal." << std::endl; -#endif - mPartialMsgUpdates[tr->mTransaction->PeerId()].erase(item->grpId) ; - } - } - else - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(item->PeerId(),grpId) << " Request list is empty. Not doing anything. " << std::endl; -#endif - // The list to req is empty. That means we already have all messages that this peer can - // provide. So we can stamp the group from this peer to be up to date. - - // Part of this is already achieved in two other places: - // - the GroupStats exchange system, which counts the messages at each peer. It could also supply TS for the messages, but it does not for the time being - // - client TS are updated when receiving messages - - locked_stampPeerGroupUpdateTime(pid,grpId,tr->mTransaction->updateTS,msgItemL.size()) ; - } -} - -void RsGxsNetService::locked_stampPeerGroupUpdateTime(const RsPeerId& pid,const RsGxsGroupId& grpId,rstime_t tm,uint32_t n_messages) -{ - RsGxsMsgUpdate& up(mClientMsgUpdateMap[pid]); - - up.msgUpdateInfos[grpId].time_stamp = tm; - up.msgUpdateInfos[grpId].message_count = std::max(n_messages, up.msgUpdateInfos[grpId].message_count) ; - - IndicateConfigChanged(); -} - -void RsGxsNetService::locked_pushGrpTransactionFromList( std::list& reqList, const RsPeerId& peerId, const uint32_t& transN) -{ -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peerId) << "locked_pushGrpTransactionFromList()" << std::endl; - GXSNETDEBUG_P_(peerId) << " nelems = " << reqList.size() << std::endl; - GXSNETDEBUG_P_(peerId) << " peerId = " << peerId << std::endl; - GXSNETDEBUG_P_(peerId) << " transN = " << transN << std::endl; -#endif -#ifdef NXS_NET_DEBUG_5 - GXSNETDEBUG_P_ (peerId) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - sending group request to peer " - << peerId << " for " << reqList.size() << " groups" << std::endl; -#endif - RsNxsTransacItem* transac = new RsNxsTransacItem(mServType); - transac->transactFlag = RsNxsTransacItem::FLAG_TYPE_GRP_LIST_REQ - | RsNxsTransacItem::FLAG_BEGIN_P1; - transac->timestamp = 0; - transac->nItems = reqList.size(); - transac->PeerId(peerId); - transac->transactionNumber = transN; - NxsTransaction* newTrans = new NxsTransaction(); - newTrans->mItems = reqList; - newTrans->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; - newTrans->mTimeOut = time(NULL) + mTransactionTimeOut; - newTrans->mTransaction = new RsNxsTransacItem(*transac); - newTrans->mTransaction->PeerId(mOwnId); - - if (locked_addTransaction(newTrans)) - generic_sendItem(transac); - else - { - delete newTrans; - delete transac; - } -} -void RsGxsNetService::addGroupItemToList(NxsTransaction*& tr, const RsGxsGroupId& grpId, uint32_t& transN, std::list& reqList) -{ -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grpId) << "RsGxsNetService::addGroupItemToList() Added GroupID: << grpId" << std::endl; -#endif - - RsNxsSyncGrpItem* grpItem = new RsNxsSyncGrpItem(mServType); - grpItem->PeerId(tr->mTransaction->PeerId()); - grpItem->grpId = grpId; - grpItem->flag = RsNxsSyncMsgItem::FLAG_REQUEST; - grpItem->transactionNumber = transN; - reqList.push_back(grpItem); -} - -void RsGxsNetService::locked_genReqGrpTransaction(NxsTransaction* tr) -{ - // to create a transaction you need to know who you are transacting with - // then what grps to request - // then add an active Transaction for request - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << "locked_genReqGrpTransaction(): " << std::endl; -#endif - - std::list grpItemL; - RsGxsGrpMetaTemporaryMap grpMetaMap; - - for(std::list::iterator lit = tr->mItems.begin(); lit != tr->mItems.end(); ++lit) - { - RsNxsSyncGrpItem* item = dynamic_cast(*lit); - if(item) - { - grpItemL.push_back(item); - grpMetaMap[item->grpId] = NULL; - } - else - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),item->grpId) << "RsGxsNetService::genReqGrpTransaction(): item failed to caste to RsNxsSyncMsgItem* " << std::endl; -#endif - } - } - - if (grpItemL.empty()) - { - // Normally the client grp updateTS is set after the transaction, but if no transaction is to happen, we have to set it here. - // Possible change: always do the update of the grpClientTS here. Needs to be tested... - - RsGxsGrpUpdate& item (mClientGrpUpdateMap[tr->mTransaction->PeerId()]); - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " reqList is empty, updating anyway ClientGrpUpdate TS for peer " << tr->mTransaction->PeerId() << " to: " << tr->mTransaction->updateTS << std::endl; -#endif - - if(item.grpUpdateTS != tr->mTransaction->updateTS) - { - item.grpUpdateTS = tr->mTransaction->updateTS; - IndicateConfigChanged(); - } - return; - } - - mDataStore->retrieveGxsGrpMetaData(grpMetaMap); - - // now do compare and add loop - std::list::iterator llit = grpItemL.begin(); - std::list reqList; - - uint32_t transN = locked_getTransactionId(); - - std::list peers; - peers.push_back(tr->mTransaction->PeerId()); - - for(; llit != grpItemL.end(); ++llit) - { - RsNxsSyncGrpItem*& grpSyncItem = *llit; - const RsGxsGroupId& grpId = grpSyncItem->grpId; - - auto metaIter = grpMetaMap.find(grpId); - bool haveItem = false; - bool latestVersion = false; - - if (metaIter != grpMetaMap.end() && metaIter->second) - { - haveItem = true; - latestVersion = grpSyncItem->publishTs > metaIter->second->mPublishTs; - } - // FIXTESTS global variable rsReputations not available in unittests! - - if( mReputations->overallReputationLevel(RsGxsId(grpSyncItem->grpId)) == RsReputationLevel::LOCALLY_NEGATIVE ) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grpId) << " Identity " << grpSyncItem->grpId << " is banned. Not GXS-syncing group." << std::endl; -#endif - continue ; - } - - if( (mGrpAutoSync && !haveItem) || latestVersion) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grpId) << " Identity " << grpId << " will be sync-ed using GXS. mGrpAutoSync:" << mGrpAutoSync << " haveItem:" << haveItem << " latest_version: " << latestVersion << std::endl; -#endif - addGroupItemToList(tr, grpId, transN, reqList); - } - } - - if(!reqList.empty()) - locked_pushGrpTransactionFromList(reqList, tr->mTransaction->PeerId(), transN); - else - { - // Normally the client grp updateTS is set after the transaction, but if no transaction is to happen, we have to set it here. - // Possible change: always do the update of the grpClientTS here. Needs to be tested... - - RsGxsGrpUpdate& item (mClientGrpUpdateMap[tr->mTransaction->PeerId()]); - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " reqList is empty, updating anyway ClientGrpUpdate TS for peer " << tr->mTransaction->PeerId() << " to: " << tr->mTransaction->updateTS << std::endl; -#endif - - if(item.grpUpdateTS != tr->mTransaction->updateTS) - { - item.grpUpdateTS = tr->mTransaction->updateTS; - IndicateConfigChanged(); - } - } - -} - -void RsGxsNetService::locked_genSendGrpsTransaction(NxsTransaction* tr) -{ - -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << "locked_genSendGrpsTransaction() Generating Grp data send from TransN: " << tr->mTransaction->transactionNumber << std::endl; -#endif - - // go groups requested in transaction tr - - std::list::iterator lit = tr->mItems.begin(); - - t_RsGxsGenericDataTemporaryMap grps ; - - for(;lit != tr->mItems.end(); ++lit) - { - RsNxsSyncGrpItem* item = dynamic_cast(*lit); - if (item) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),item->grpId) << "locked_genSendGrpsTransaction() retrieving data for group \"" << item->grpId << "\"" << std::endl; -#endif - grps[item->grpId] = NULL; - } - else - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),item->grpId) << "RsGxsNetService::locked_genSendGrpsTransaction(): item failed to caste to RsNxsSyncGrpItem* " << std::endl; -#endif - } - } - - if(!grps.empty()) - mDataStore->retrieveNxsGrps(grps, false); - else - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << "RsGxsNetService::locked_genSendGrpsTransaction(): no group to request! This is unexpected" << std::endl; -#endif - return; - } - - NxsTransaction* newTr = new NxsTransaction(); - newTr->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; - - uint32_t transN = locked_getTransactionId(); - - // store grp items to send in transaction - std::map::iterator mit = grps.begin(); - RsPeerId peerId = tr->mTransaction->PeerId(); - for(;mit != grps.end(); ++mit) - { -#warning csoler: Should make sure that no private key information is sneaked in here for the grp - mit->second->PeerId(peerId); // set so it gets sent to right peer - mit->second->transactionNumber = transN; - newTr->mItems.push_back(mit->second); - mit->second = NULL ; // avoids deletion -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),mit->first) << "RsGxsNetService::locked_genSendGrpsTransaction(): adding grp data of group \"" << mit->first << "\" to transaction" << std::endl; -#endif - } - - if(newTr->mItems.empty()){ - delete newTr; - return; - } - - uint32_t updateTS = 0; - updateTS = mGrpServerUpdate.grpUpdateTS; - -#ifdef NXS_NET_DEBUG_5 - GXSNETDEBUG_P_ (tr->mTransaction->PeerId()) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - sending global group TS " - << updateTS << " to peer " << tr->mTransaction->PeerId() << std::endl; -#endif - RsNxsTransacItem* ntr = new RsNxsTransacItem(mServType); - ntr->transactionNumber = transN; - ntr->transactFlag = RsNxsTransacItem::FLAG_BEGIN_P1 | RsNxsTransacItem::FLAG_TYPE_GRPS; - ntr->updateTS = updateTS; - ntr->nItems = grps.size(); - ntr->PeerId(tr->mTransaction->PeerId()); - - newTr->mTransaction = new RsNxsTransacItem(*ntr); - newTr->mTransaction->PeerId(mOwnId); - newTr->mTimeOut = time(NULL) + mTransactionTimeOut; - - ntr->PeerId(tr->mTransaction->PeerId()); - - if(locked_addTransaction(newTr)) - generic_sendItem(ntr); - else - { - delete ntr ; - delete newTr; - } - - return; -} - -void RsGxsNetService::runVetting() -{ - // The vetting operation consists in transforming pending group/msg Id requests and grp/msg content requests - // into real transactions, based on the authorisations of the Peer Id these transactions are targeted to using the - // reputation system. - // - - RS_STACK_MUTEX(mNxsMutex) ; - -#ifdef TO_BE_REMOVED - // Author response vetting is disabled since not used, as the reputations are currently not async-ed anymore. - - std::vector::iterator vit = mPendingResp.begin(); - - for(; vit != mPendingResp.end(); ) - { - AuthorPending* ap = *vit; - - if(ap->accepted() || ap->expired()) - { - // add to transactions - if(AuthorPending::MSG_PEND == ap->getType()) - { - MsgRespPending* mrp = static_cast(ap); - locked_createTransactionFromPending(mrp); - } - else if(AuthorPending::GRP_PEND == ap->getType()) - { - GrpRespPending* grp = static_cast(ap); - locked_createTransactionFromPending(grp); - }else - std::cerr << "RsGxsNetService::runVetting(): Unknown pending type! Type: " << ap->getType() << std::endl; - - delete ap; - vit = mPendingResp.erase(vit); - } - else - { - ++vit; - } - - } -#endif - - - // now lets do circle vetting - std::vector::iterator vit2 = mPendingCircleVets.begin(); - for(; vit2 != mPendingCircleVets.end(); ) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG___ << " Examining/clearing pending vetting of type " << (*vit2)->getType() << std::endl; -#endif - GrpCircleVetting*& gcv = *vit2; - if(gcv->cleared() || gcv->expired()) - { - if(gcv->getType() == GrpCircleVetting::GRP_ID_PEND) - { - GrpCircleIdRequestVetting* gcirv = static_cast(gcv); -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_P_(gcirv->mPeerId) << " vetting is a GRP ID PENDING Response" << std::endl; -#endif - - if(!locked_createTransactionFromPending(gcirv)) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_P_(gcirv->mPeerId) << " Response sent!" << std::endl; -#endif - ++vit2 ; - continue ; - } - } - else if(gcv->getType() == GrpCircleVetting::MSG_ID_SEND_PEND) - { - MsgCircleIdsRequestVetting* mcirv = static_cast(gcv); - -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_P_(mcirv->mPeerId) << " vetting is a MSG ID PENDING Response" << std::endl; -#endif - if(mcirv->cleared()) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_P_(mcirv->mPeerId) << " vetting cleared! Sending..." << std::endl; -#endif - if(!locked_createTransactionFromPending(mcirv)) - continue ; // keep it in the list for retry - } - } - else - { -#ifdef NXS_NET_DEBUG_4 - std::cerr << "RsGxsNetService::runVetting(): Unknown Circle pending type! Type: " << gcv->getType() << std::endl; -#endif - } - - delete gcv; - vit2 = mPendingCircleVets.erase(vit2); - } - else - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG___ << " ... not cleared yet." << std::endl; -#endif - ++vit2; - } - } -} - -void RsGxsNetService::locked_genSendMsgsTransaction(NxsTransaction* tr) -{ -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << "locked_genSendMsgsTransaction() Generating Msg data send fron TransN: " << tr->mTransaction->transactionNumber << std::endl; -#endif - - // go groups requested in transaction tr - - std::list::iterator lit = tr->mItems.begin(); - - GxsMsgReq msgIds; - GxsMsgResult msgs; - - if(tr->mItems.empty()){ - return; - } - - // hacky assumes a transaction only consist of a single grpId - RsGxsGroupId grpId; - - for(;lit != tr->mItems.end(); ++lit) - { - RsNxsSyncMsgItem* item = dynamic_cast(*lit); - if (item) - { - msgIds[item->grpId].insert(item->msgId); - - if(grpId.isNull()) - grpId = item->grpId; - else if(grpId != item->grpId) - { - std::cerr << "RsGxsNetService::locked_genSendMsgsTransaction(): transaction on two different groups! ERROR!" << std::endl; - return ; - } - } - else - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grpId) << "RsGxsNetService::locked_genSendMsgsTransaction(): item failed to caste to RsNxsSyncMsgItem* " << std::endl; -#endif - } - } - -#ifdef CODE_TO_ENCRYPT_MESSAGE_DATA - // now if transaction is limited to an external group, encrypt it for members of the group. - - RsGxsCircleId encryption_circle ; - std::map grp; - grp[grpId] = NULL ; - - mDataStore->retrieveGxsGrpMetaData(grp); - - RsGxsGrpMetaData *grpMeta = grp[grpId] ; - - if(grpMeta == NULL) - { - std::cerr << "(EE) cannot retrieve group meta data for message transaction " << tr->mTransaction->transactionNumber << std::endl; - return ; - } - - encryption_circle = grpMeta->mCircleId ; - delete grpMeta ; - grp.clear() ; -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grpId) << " Msg transaction items will be encrypted for circle " << std::endl; -#endif -#endif - - mDataStore->retrieveNxsMsgs(msgIds, msgs, false); - - NxsTransaction* newTr = new NxsTransaction(); - newTr->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; - - uint32_t transN = locked_getTransactionId(); - - // store msg items to send in transaction - GxsMsgResult::iterator mit = msgs.begin(); - RsPeerId peerId = tr->mTransaction->PeerId(); - uint32_t msgSize = 0; - - for(;mit != msgs.end(); ++mit) - { - std::vector& msgV = mit->second; - std::vector::iterator vit = msgV.begin(); - - for(; vit != msgV.end(); ++vit) - { - RsNxsMsg* msg = *vit; - msg->PeerId(peerId); - msg->transactionNumber = transN; - - // Quick trick to clamp messages with an exceptionnally large size. Signature will fail on client side, and the message - // will be rejected. - - if(msg->msg.bin_len > MAX_ALLOWED_GXS_MESSAGE_SIZE) - { - std::cerr << "(WW) message with ID " << msg->msgId << " in group " << msg->grpId << " exceeds size limit of " << MAX_ALLOWED_GXS_MESSAGE_SIZE << " bytes. Actual size is " << msg->msg.bin_len << " bytes. Message will be truncated and rejected at client." << std::endl; - msg->msg.bin_len = 1 ; // arbitrary small size, but not 0. No need to send the data since it's going to be rejected. - } - -#ifdef NXS_FRAG - MsgFragments fragments; - fragmentMsg(*msg, fragments); - - delete msg ; - - MsgFragments::iterator mit = fragments.begin(); - - for(; mit != fragments.end(); ++mit) - { - newTr->mItems.push_back(*mit); - msgSize++; - } -#else - - msg->count = 1; // only one piece. This is to keep compatibility if we ever implement fragmenting in the future. - msg->pos = 0; - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(tr->mTransaction->PeerId(),msg->grpId) << " sending msg Id " << msg->msgId << " in Group " << msg->grpId << std::endl; -#endif - - newTr->mItems.push_back(msg); - msgSize++; -#endif - -#ifdef CODE_TO_ENCRYPT_MESSAGE_DATA - // encrypt - - if(!encryption_circle.isNull()) - { - uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ; - - RsNxsEncryptedDataItem encrypted_msg_item = NULL ; - - if(encryptSingleNxsItem(msg,encryption_circle,encrypted_msg_item,status)) - { - newTr->mItems.push_back(msg); - delete msg ; - } - else - { - } - } - else - { - newTr->mItems.push_back(msg); - - msgSize++; - } -#endif - } - } - - if(newTr->mItems.empty()){ - delete newTr; - return; - } - - // now send a transaction item and store the transaction data - - uint32_t updateTS = mServerMsgUpdateMap[grpId].msgUpdateTS; - - RsNxsTransacItem* ntr = new RsNxsTransacItem(mServType); - ntr->transactionNumber = transN; - ntr->transactFlag = RsNxsTransacItem::FLAG_BEGIN_P1 | - RsNxsTransacItem::FLAG_TYPE_MSGS; - ntr->updateTS = updateTS; - ntr->nItems = msgSize; - ntr->PeerId(peerId); - - newTr->mTransaction = new RsNxsTransacItem(*ntr); - newTr->mTransaction->PeerId(mOwnId); - newTr->mTimeOut = time(NULL) + mTransactionTimeOut; - -#ifdef NXS_NET_DEBUG_5 - GXSNETDEBUG_PG (peerId,grpId) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - sending message update to peer " << peerId << " for group " << grpId << " with TS=" << nice_time_stamp(time(NULL),updateTS) <<" (secs ago)" << std::endl; - -#endif - ntr->PeerId(tr->mTransaction->PeerId()); - - if(locked_addTransaction(newTr)) - generic_sendItem(ntr); - else - { - delete ntr ; - delete newTr; - } - - return; -} -uint32_t RsGxsNetService::locked_getTransactionId() -{ - return ++mTransactionN; -} -bool RsGxsNetService::locked_addTransaction(NxsTransaction* tr) -{ - const RsPeerId& peer = tr->mTransaction->PeerId(); -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peer) << "locked_addTransaction() " << std::endl; -#endif - uint32_t transN = tr->mTransaction->transactionNumber; - TransactionIdMap& transMap = mTransactions[peer]; - bool transNumExist = transMap.find(transN) != transMap.end(); - - if(transNumExist) - { -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_P_(peer) << " Transaction number exist already, transN: " << transN << std::endl; -#endif - return false; - } - - transMap[transN] = tr; - - return true; -} - -// Turns a single RsNxsItem into an encrypted one, suitable for the supplied destination circle. -// Returns false when the keys are not loaded. Question to solve: what do we do if we miss some keys?? -// We should probably send anyway. - -bool RsGxsNetService::encryptSingleNxsItem(RsNxsItem *item, const RsGxsCircleId& destination_circle, const RsGxsGroupId& destination_group, RsNxsItem *&encrypted_item, uint32_t& status) -{ - encrypted_item = NULL ; - status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ; -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_ (item->PeerId()) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - Encrypting single item for peer " << item->PeerId() << ", for circle ID " << destination_circle << std::endl; -#endif - // 1 - Find out the list of GXS ids to encrypt for - // We could do smarter things (like see if the peer_id owns one of the circle's identities - // but for now we aim at the simplest solution: encrypt for all identities in the circle. - - std::list recipients ; - - if(!mCircles->recipients(destination_circle,destination_group,recipients)) - { - std::cerr << " (EE) Cannot encrypt transaction: recipients list not available. Should re-try later." << std::endl; - status = RS_NXS_ITEM_ENCRYPTION_STATUS_CIRCLE_ERROR ; - return false ; - } - - if(recipients.empty()) - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(item->PeerId()) << " (EE) No recipients found for circle " << destination_circle << ". Circle not in cache, or empty circle?" << std::endl; -#endif - return false ; - } - -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_ (item->PeerId()) << " Dest Ids: " << std::endl; -#endif - std::vector recipient_keys ; - - for(std::list::const_iterator it(recipients.begin());it!=recipients.end();++it) - { - RsTlvPublicRSAKey pkey ; - - if(!mGixs->getKey(*it,pkey)) - { - std::cerr << " (EE) Cannot retrieve public key " << *it << " for circle encryption. Should retry later?" << std::endl; - - // we should probably request the key? - status = RS_NXS_ITEM_ENCRYPTION_STATUS_GXS_KEY_MISSING ; - continue ; - } -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_ (item->PeerId()) << " added key " << *it << std::endl; -#endif - recipient_keys.push_back(pkey) ; - } - - // 2 - call GXSSecurity to make a header item that encrypts for the given list of peers. - -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_ (item->PeerId()) << " Encrypting..." << std::endl; -#endif - uint32_t size = RsNxsSerialiser(mServType).size(item) ; - RsTemporaryMemory tempmem( size ) ; - - if(!RsNxsSerialiser(mServType).serialise(item,tempmem,&size)) - { - std::cerr << " (EE) Cannot serialise item. Something went wrong." << std::endl; - status = RS_NXS_ITEM_ENCRYPTION_STATUS_SERIALISATION_ERROR ; - return false ; - } - - unsigned char *encrypted_data = NULL ; - uint32_t encrypted_len = 0 ; - - if(!GxsSecurity::encrypt(encrypted_data, encrypted_len,tempmem,size,recipient_keys)) - { - std::cerr << " (EE) Cannot multi-encrypt item. Something went wrong." << std::endl; - status = RS_NXS_ITEM_ENCRYPTION_STATUS_ENCRYPTION_ERROR ; - return false ; - } - - RsNxsEncryptedDataItem *enc_item = new RsNxsEncryptedDataItem(mServType) ; - - enc_item->encrypted_data.bin_len = encrypted_len ; - enc_item->encrypted_data.bin_data = encrypted_data ; - - // also copy all the important data. - - enc_item->transactionNumber = item->transactionNumber ; - enc_item->PeerId(item->PeerId()) ; - - encrypted_item = enc_item ; -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(item->PeerId()) << " encrypted item of size " << encrypted_len << std::endl; -#endif - status = RS_NXS_ITEM_ENCRYPTION_STATUS_NO_ERROR ; - - return true ; -} - -// Tries to decrypt the transaction. First load the keys and process all items. -// If keys are loaded, encrypted items that cannot be decrypted are discarded. -// Otherwise the transaction is untouched for retry later. - -bool RsGxsNetService::processTransactionForDecryption(NxsTransaction *tr) -{ -#ifdef NXS_NET_DEBUG_7 - RsPeerId peerId = tr->mTransaction->PeerId() ; - GXSNETDEBUG_P_(peerId) << "RsGxsNetService::decryptTransaction()" << std::endl; -#endif - - std::list decrypted_items ; - std::vector private_keys ; - - // get all private keys. Normally we should look into the circle name and only supply the keys that we have - - for(std::list::iterator it(tr->mItems.begin());it!=tr->mItems.end();) - { - RsNxsEncryptedDataItem *encrypted_item = dynamic_cast(*it) ; - - if(encrypted_item == NULL) - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(peerId) << " skipping unencrypted item..." << std::endl; -#endif - ++it ; - continue ; - } - - // remove the encrypted item. After that it points to the next item to handle - it = tr->mItems.erase(it) ; - - RsNxsItem *nxsitem = NULL ; - - if(decryptSingleNxsItem(encrypted_item,nxsitem,&private_keys)) - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(peerId) << " Replacing the encrypted item with the clear one." << std::endl; -#endif - tr->mItems.insert(it,nxsitem) ; // inserts before it, so no need to ++it - } - - delete encrypted_item ; - } - - return true ; -} - -bool RsGxsNetService::decryptSingleNxsItem(const RsNxsEncryptedDataItem *encrypted_item, RsNxsItem *& nxsitem,std::vector *pprivate_keys) -{ - // if private_keys storage is supplied use/update them, otherwise, find which key should be used, and store them in a local std::vector. - - nxsitem = NULL ; - std::vector local_keys ; - std::vector& private_keys = pprivate_keys?(*pprivate_keys):local_keys ; - - // we need the private keys to decrypt the item. First load them in! - bool key_loading_failed = false ; - - if(private_keys.empty()) - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(encrypted_item->PeerId()) << " need to retrieve private keys..." << std::endl; -#endif - - std::list own_keys ; - mGixs->getOwnIds(own_keys) ; - - for(std::list::const_iterator it(own_keys.begin());it!=own_keys.end();++it) - { - RsTlvPrivateRSAKey private_key ; - - if(mGixs->getPrivateKey(*it,private_key)) - { - private_keys.push_back(private_key) ; -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(encrypted_item->PeerId())<< " retrieved private key " << *it << std::endl; -#endif - } - else - { - std::cerr << " (EE) Cannot retrieve private key for ID " << *it << std::endl; - key_loading_failed = true ; - break ; - } - } - } - if(key_loading_failed) - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(encrypted_item->PeerId()) << " Some keys not loaded.Returning false to retry later." << std::endl; -#endif - return false ; - } - - // we do this only when something actually needs to be decrypted. - - unsigned char *decrypted_mem = NULL; - uint32_t decrypted_len =0; - -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(encrypted_item->PeerId())<< " Trying to decrypt item..." ; -#endif - - if(!GxsSecurity::decrypt(decrypted_mem,decrypted_len, (uint8_t*)encrypted_item->encrypted_data.bin_data,encrypted_item->encrypted_data.bin_len,private_keys)) - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(encrypted_item->PeerId()) << " Failed! Cannot decrypt this item." << std::endl; -#endif - decrypted_mem = NULL ; // for safety - return false ; - } -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_P_(encrypted_item->PeerId())<< " Succeeded! deserialising..." << std::endl; -#endif - - // deserialise the item - - RsItem *ditem = NULL ; - - if(decrypted_mem!=NULL) - { - ditem = RsNxsSerialiser(mServType).deserialise(decrypted_mem,&decrypted_len) ; - free(decrypted_mem) ; - - if(ditem != NULL) - { - ditem->PeerId(encrypted_item->PeerId()) ; // This is needed because the deserialised item has no peer id - nxsitem = dynamic_cast(ditem) ; - } - else - std::cerr << " Cannot deserialise. Item encoding error!" << std::endl; - - return (nxsitem != NULL) ; - } - return false ; -} - -void RsGxsNetService::cleanTransactionItems(NxsTransaction* tr) const -{ - std::list::iterator lit = tr->mItems.begin(); - - for(; lit != tr->mItems.end(); ++lit) - { - delete *lit; - } - - tr->mItems.clear(); -} - -void RsGxsNetService::locked_pushGrpRespFromList(std::list& respList, const RsPeerId& peer, const uint32_t& transN) -{ -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(peer) << "locked_pushGrpResponseFromList()" << std::endl; - GXSNETDEBUG_P_(peer) << " nelems = " << respList.size() << std::endl; - GXSNETDEBUG_P_(peer) << " peerId = " << peer << std::endl; - GXSNETDEBUG_P_(peer) << " transN = " << transN << std::endl; -#endif - NxsTransaction* tr = new NxsTransaction(); - tr->mItems = respList; - - tr->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; - RsNxsTransacItem* trItem = new RsNxsTransacItem(mServType); - trItem->transactFlag = RsNxsTransacItem::FLAG_BEGIN_P1 - | RsNxsTransacItem::FLAG_TYPE_GRP_LIST_RESP; - trItem->nItems = respList.size(); - trItem->timestamp = 0; - trItem->PeerId(peer); - trItem->transactionNumber = transN; -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_ (peer) << "Setting tr->mTransaction->updateTS to " << mGrpServerUpdate.grpUpdateTS << std::endl; -#endif - trItem->updateTS = mGrpServerUpdate.grpUpdateTS; - - // also make a copy for the resident transaction - tr->mTransaction = new RsNxsTransacItem(*trItem); - tr->mTransaction->PeerId(mOwnId); - tr->mTimeOut = time(NULL) + mTransactionTimeOut; - // signal peer to prepare for transaction -#ifdef NXS_NET_DEBUG_5 - GXSNETDEBUG_P_ (peer) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - sending group response to peer " - << peer << " with " << respList.size() << " groups " << std::endl; -#endif - if(locked_addTransaction(tr)) - generic_sendItem(trItem); - else - { - delete tr ; - delete trItem ; - } -} - -bool RsGxsNetService::locked_CanReceiveUpdate(const RsNxsSyncGrpReqItem *item) -{ - // Do we have new updates for this peer? - // The received TS is in our own clock, but send to us by the friend. - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(item->PeerId()) << " local modification time stamp: " << std::dec<< time(NULL) - mGrpServerUpdate.grpUpdateTS << " secs ago. Update sent: " << - ((item->updateTS < mGrpServerUpdate.grpUpdateTS)?"YES":"NO") << std::endl; -#endif - return item->updateTS < mGrpServerUpdate.grpUpdateTS && locked_checkResendingOfUpdates(item->PeerId(),RsGxsGroupId(),item->updateTS,mGrpServerUpdate.grpUpdateTsRecords[item->PeerId()]) ; -} - -void RsGxsNetService::handleRecvSyncGroup(RsNxsSyncGrpReqItem *item) -{ - if (!item) - return; - - RS_STACK_MUTEX(mNxsMutex) ; - - RsPeerId peer = item->PeerId(); -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(peer) << "HandleRecvSyncGroup(): Service: " << mServType << " from " << peer << ", Last update TS (from myself) sent from peer is T = " << std::dec<< time(NULL) - item->updateTS << " secs ago" << std::endl; -#endif - - if(!locked_CanReceiveUpdate(item)) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(peer) << " RsGxsNetService::handleRecvSyncGroup() update will not be sent." << std::endl; -#endif - return; - } - - RsGxsGrpMetaTemporaryMap grp; - mDataStore->retrieveGxsGrpMetaData(grp); - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(peer) << " RsGxsNetService::handleRecvSyncGroup() retrieving local list of groups..." << std::endl; -#endif - if(grp.empty()) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(peer) << " RsGxsNetService::handleRecvSyncGroup() Grp Empty" << std::endl; -#endif - return; - } - - std::list itemL; - - uint32_t transN = locked_getTransactionId(); - - std::vector toVet; -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(peer) << " Group list beings being sent: " << std::endl; -#endif - - for(auto mit = grp.begin(); mit != grp.end(); ++mit) - { - const auto& grpMeta = mit->second; - - // Only send info about subscribed groups. - - if(grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) - { - - // check if you can send this id to peer - // or if you need to add to the holding - // pen for peer to be vetted - - bool should_encrypt = false ; - - if(canSendGrpId(peer, *grpMeta, toVet,should_encrypt)) - { - RsNxsSyncGrpItem* gItem = new RsNxsSyncGrpItem(mServType); - gItem->flag = RsNxsSyncGrpItem::FLAG_RESPONSE; - gItem->grpId = mit->first; - gItem->publishTs = mit->second->mPublishTs; - gItem->authorId = grpMeta->mAuthorId; - gItem->PeerId(peer); - gItem->transactionNumber = transN; - - if(should_encrypt) - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_PG(peer,mit->first) << " item for this grpId should be encrypted." << std::endl; -#endif - RsNxsItem *encrypted_item = NULL ; - uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ; - - if(encryptSingleNxsItem(gItem, grpMeta->mCircleId,mit->first, encrypted_item,status)) - itemL.push_back(encrypted_item) ; - else - { - switch(status) - { - case RS_NXS_ITEM_ENCRYPTION_STATUS_CIRCLE_ERROR: - case RS_NXS_ITEM_ENCRYPTION_STATUS_GXS_KEY_MISSING: toVet.push_back(GrpIdCircleVet(grpMeta->mGroupId, grpMeta->mCircleId, grpMeta->mAuthorId)); -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_PG(peer,mit->first) << " Could not encrypt item for grpId " << grpMeta->mGroupId << " for circle " << grpMeta->mCircleId << ". Will try later. Adding to vetting list." << std::endl; -#endif - break ; - default: - std::cerr << " Could not encrypt item for grpId " << grpMeta->mGroupId << " for circle " << grpMeta->mCircleId << ". Not sending it." << std::endl; - } - } - delete gItem ; - } - else - itemL.push_back(gItem); - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(peer,mit->first) << " sending item for Grp " << mit->first << " name=" << grpMeta->mGroupName << ", publishTS=" << std::dec<< time(NULL) - mit->second->mPublishTs << " secs ago to peer ID " << peer << std::endl; -#endif - } - } - } - - if(!toVet.empty()) - mPendingCircleVets.push_back(new GrpCircleIdRequestVetting(mCircles, mPgpUtils, toVet, peer)); - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_P_(peer) << " final list sent (after vetting): " << itemL.size() << " elements." << std::endl; -#endif - locked_pushGrpRespFromList(itemL, peer, transN); - - return; -} - - - -bool RsGxsNetService::canSendGrpId(const RsPeerId& sslId, const RsGxsGrpMetaData& grpMeta, std::vector& /* toVet */, bool& should_encrypt) -{ -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << "RsGxsNetService::canSendGrpId()"<< std::endl; -#endif - // check if that peer is a virtual peer id, in which case we only send/recv data to/from it items for the group it's requested for - - RsGxsGroupId peer_grp ; - if(mAllowDistSync && mGxsNetTunnel != NULL && mGxsNetTunnel->isDistantPeer(RsGxsNetTunnelVirtualPeerId(sslId),peer_grp) && peer_grp != grpMeta.mGroupId) - { -#warning (cyril) make sure that this is not a problem for cross-service sending of items -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Distant peer designed for group " << peer_grp << ": cannot request sync for different group." << std::endl; -#endif - return false ; - } - - // first do the simple checks - uint8_t circleType = grpMeta.mCircleType; - - if(circleType == GXS_CIRCLE_TYPE_LOCAL) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId)<< " LOCAL_CIRCLE, cannot send"<< std::endl; -#endif - return false; - } - else if(circleType == GXS_CIRCLE_TYPE_PUBLIC || circleType == GXS_CIRCLE_TYPE_UNKNOWN) // this complies with the fact that p3IdService does not initialise the circle type. - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId)<< " PUBLIC_CIRCLE, can send"<< std::endl; -#endif - return true; - } - else if(circleType == GXS_CIRCLE_TYPE_EXTERNAL) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId)<< " EXTERNAL_CIRCLE, will be sent encrypted."<< std::endl; -#endif - should_encrypt = true ; - return true ; - } - else if(circleType == GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " YOUREYESONLY, checking further" << std::endl; -#endif - bool res = checkPermissionsForFriendGroup(sslId,grpMeta) ; -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Final answer: " << res << std::endl; -#endif - return res ; -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId)<< " YOUREYESONLY, checking further"<< std::endl; -#endif - } - else - { - std::cerr << "(EE) unknown value found in circle type for group " << grpMeta.mGroupId << ": " << (int)circleType << ": this is probably a bug in the design of the group creation." << std::endl; - return false; - } -} - -bool RsGxsNetService::checkCanRecvMsgFromPeer(const RsPeerId& sslId, const RsGxsGrpMetaData& grpMeta, RsGxsCircleId& should_encrypt_id) -{ - -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << "RsGxsNetService::checkCanRecvMsgFromPeer()"; - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " peer Id = " << sslId << ", grpId=" << grpMeta.mGroupId <isDistantPeer(RsGxsNetTunnelVirtualPeerId(sslId),peer_grp) && peer_grp != grpMeta.mGroupId) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Distant peer designed for group " << peer_grp << ": cannot request sync for different group." << std::endl; -#endif - return false ; - } - - // first do the simple checks - uint8_t circleType = grpMeta.mCircleType; - should_encrypt_id.clear() ; - - if(circleType == GXS_CIRCLE_TYPE_LOCAL) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " LOCAL_CIRCLE, cannot request sync from peer" << std::endl; -#endif - return false; - } - - if(circleType == GXS_CIRCLE_TYPE_PUBLIC) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " PUBLIC_CIRCLE, can request msg sync" << std::endl; -#endif - return true; - } - - if(circleType == GXS_CIRCLE_TYPE_EXTERNAL) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: EXTERNAL => returning true. Msgs will be encrypted." << std::endl; -#endif - should_encrypt_id = grpMeta.mCircleId ; - return true ; - } - - if(circleType == GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY) // do not attempt to sync msg unless to originator or those permitted - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " YOUREYESONLY, checking further" << std::endl; -#endif - bool res = checkPermissionsForFriendGroup(sslId,grpMeta) ; -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Final answer: " << res << std::endl; -#endif - return res ; - } - - return true; -} - -bool RsGxsNetService::locked_checkResendingOfUpdates(const RsPeerId& pid,const RsGxsGroupId& grpId,rstime_t incoming_ts,RsPeerUpdateTsRecord& rec) -{ - rstime_t now = time(NULL); - - // Now we check if the peer is sending the same outdated TS for the same time in a short while. This would mean the peer - // hasn't finished processing the updates we're sending and we shouldn't send new data anymore. Of course the peer might - // have disconnected or so, which means that we need to be careful about not sending. As a compromise we still send, but - // after waiting for a while (See - - if(rec.mLastTsReceived == incoming_ts && rec.mTs + SAFETY_DELAY_FOR_UNSUCCESSFUL_UPDATE > now) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(pid,grpId) << "(II) peer " << pid << " already sent the same TS " << (long int)now-(long int)rec.mTs << " secs ago for that group ID. Will not send msg list again for a while to prevent clogging..." << std::endl; -#else - (void) pid; - (void) grpId; -#endif - return false; - } - - rec.mLastTsReceived = incoming_ts; - rec.mTs = now; - - return true; -} - -bool RsGxsNetService::locked_CanReceiveUpdate(RsNxsSyncMsgReqItem *item,bool& grp_is_known) -{ - // Do we have new updates for this peer? - // Here we compare times in the same clock: our own clock, so it should be fine. - - grp_is_known = false ; - - if(item->flag & RsNxsSyncMsgReqItem::FLAG_USE_HASHED_GROUP_ID) - { - // Item contains the hashed group ID in order to protect is from friends who don't know it. So we de-hash it using bruteforce over known group IDs for this peer. - // We could save the de-hash result. But the cost is quite light, since the number of encrypted groups per service is usually low. - - for(ServerMsgMap::iterator it(mServerMsgUpdateMap.begin());it!=mServerMsgUpdateMap.end();++it) - if(item->grpId == hashGrpId(it->first,item->PeerId())) - { - item->grpId = it->first ; - item->flag &= ~RsNxsSyncMsgReqItem::FLAG_USE_HASHED_GROUP_ID; -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << "(II) de-hashed group ID " << it->first << " from hash " << item->grpId << " and peer id " << item->PeerId() << std::endl; -#endif - grp_is_known = true ; - - // The order of tests below is important because we want to only modify the map of requests records if the request actually is a valid requests instead of - // a simple check that nothing's changed. - - return item->updateTS < it->second.msgUpdateTS && locked_checkResendingOfUpdates(item->PeerId(),item->grpId,item->updateTS,it->second.msgUpdateTsRecords[item->PeerId()]) ; - } - - return false ; - } - - ServerMsgMap::iterator cit = mServerMsgUpdateMap.find(item->grpId); - - if(cit != mServerMsgUpdateMap.end()) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " local time stamp: " << std::dec<< time(NULL) - cit->second.msgUpdateTS << " secs ago. Update sent: " << (item->updateTS < cit->second.msgUpdateTS) << std::endl; -#endif - grp_is_known = true ; - - return item->updateTS < cit->second.msgUpdateTS && locked_checkResendingOfUpdates(item->PeerId(),item->grpId,item->updateTS,cit->second.msgUpdateTsRecords[item->PeerId()]) ; - } - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " no local time stamp for this grp. "<< std::endl; -#endif - - return false; -} - -void RsGxsNetService::handleRecvSyncMessage(RsNxsSyncMsgReqItem *item,bool item_was_encrypted) -{ - if (!item) - return; - - RS_STACK_MUTEX(mNxsMutex) ; - - const RsPeerId& peer = item->PeerId(); - bool grp_is_known = false; - bool was_circle_protected = item_was_encrypted || bool(item->flag & RsNxsSyncMsgReqItem::FLAG_USE_HASHED_GROUP_ID); - - // This call determines if the peer can receive updates from us, meaning that our last TS is larger than what the peer sent. - // It also changes the items' group id into the un-hashed group ID if the group is a distant group. - - bool peer_can_receive_update = locked_CanReceiveUpdate(item, grp_is_known); - - if(item_was_encrypted) - std::cerr << "(WW) got an encrypted msg sync req. from " << item->PeerId() << ". This will not send messages updates for group " << item->grpId << std::endl; - - // Insert the PeerId in suppliers list for this grpId -#ifdef NXS_NET_DEBUG_6 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << "RsGxsNetService::handleRecvSyncMessage(): Inserting PeerId " << item->PeerId() << " in suppliers list for group " << item->grpId << std::endl; -#endif -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << "handleRecvSyncMsg(): Received last update TS of group " << item->grpId << ", for peer " << peer << ", TS = " << time(NULL) - item->updateTS << " secs ago." ; -#endif - - // We update suppliers in two cases: - // Case 1: the grp is known because it is the hash of an existing group, but it's not yet in the server config map - // Case 2: the grp is not known, possibly because it was deleted, but there's an entry in mServerGrpConfigMap due to statistics gathering. Still, statistics are only - // gathered from known suppliers. So statistics never add new suppliers. These are only added here. - - if(grp_is_known || mServerGrpConfigMap.find(item->grpId)!=mServerGrpConfigMap.end()) - { - RsGxsGrpConfig& rec(locked_getGrpConfig(item->grpId)); // this creates it if needed. When the grp is unknown (and hashed) this will would create a unused entry - rec.suppliers.ids.insert(peer) ; - } - if(!peer_can_receive_update) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " no update will be sent." << std::endl; -#endif - return; - } - - RsGxsGrpMetaTemporaryMap grpMetas; - grpMetas[item->grpId] = NULL; - - mDataStore->retrieveGxsGrpMetaData(grpMetas); - const auto& grpMeta = grpMetas[item->grpId]; - - if(grpMeta == NULL) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " Grp is unknown." << std::endl; -#endif - return; - } - if(!(grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED )) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " Grp is not subscribed." << std::endl; -#endif - return ; - } - - if( (grpMeta->mCircleType == GXS_CIRCLE_TYPE_EXTERNAL) != was_circle_protected ) - { - std::cerr << "(EE) received a sync Msg request for group " << item->grpId << " from peer " << item->PeerId() ; - if(!was_circle_protected) - std::cerr << ". The group is tied to an external circle (ID=" << grpMeta->mCircleId << ") but the request wasn't encrypted." << std::endl; - else - std::cerr << ". The group is not tied to an external circle (ID=" << grpMeta->mCircleId << ") but the request was encrypted." << std::endl; - - return ; - } - - GxsMsgReq req; - req[item->grpId] = std::set(); - - GxsMsgMetaResult metaResult; - mDataStore->retrieveGxsMsgMetaData(req, metaResult); - auto& msgMetas = metaResult[item->grpId]; - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " retrieving message meta data." << std::endl; -#endif - if(req.empty()) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " No msg meta data.." << std::endl; -#endif - } -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " Sending MSG meta data created since TS=" << item->createdSinceTS << std::endl; -#endif - - std::list itemL; - - uint32_t transN = locked_getTransactionId(); - RsGxsCircleId should_encrypt_to_this_circle_id ; - -#ifndef RS_GXS_SEND_ALL - rstime_t now = time(NULL) ; -#endif - -#ifndef RS_GXS_SEND_ALL - uint32_t max_send_delay = locked_getGrpConfig(item->grpId).msg_req_delay; // we should use "sync" but there's only one variable used in the GUI: the req one. -#endif - - if(canSendMsgIds(msgMetas, *grpMeta, peer, should_encrypt_to_this_circle_id)) - { - for(auto vit = msgMetas.begin();vit != msgMetas.end(); ++vit) - { - const auto& m = *vit; - - // Check reputation - - if(!m->mAuthorId.isNull()) - { - RsIdentityDetails details ; - - if(!rsIdentity->getIdDetails(m->mAuthorId,details)) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " not sending grp message ID " << (*vit)->mMsgId << ", because the identity of the author (" << m->mAuthorId << ") is not accessible (unknown/not cached)" << std::endl; -#endif - continue ; - } - - if(details.mReputation.mOverallReputationLevel < minReputationForForwardingMessages(grpMeta->mSignFlags, details.mFlags)) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " not sending item ID " << (*vit)->mMsgId << ", because the author is flags " << std::hex << details.mFlags << std::dec << " and reputation level " << (int) details.mReputation.mOverallReputationLevel << std::endl; -#endif - continue ; - } - } - // Check publish TS -#ifndef RS_GXS_SEND_ALL - if(item->createdSinceTS > (*vit)->mPublishTs || ((max_send_delay > 0) && (*vit)->mPublishTs + max_send_delay < now)) -#else - if(item->createdSinceTS > (*vit)->mPublishTs) -#endif - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " not sending item ID " << (*vit)->mMsgId << ", because it is too old (publishTS = " << (time(NULL)-(*vit)->mPublishTs)/86400 << " days ago" << std::endl; -#endif - continue ; - } - - RsNxsSyncMsgItem* mItem = new RsNxsSyncMsgItem(mServType); - mItem->flag = RsNxsSyncGrpItem::FLAG_RESPONSE; - mItem->grpId = m->mGroupId; - mItem->msgId = m->mMsgId; - mItem->authorId = m->mAuthorId; - mItem->PeerId(peer); - mItem->transactionNumber = transN; - - if(!should_encrypt_to_this_circle_id.isNull()) - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " sending info item for msg id " << mItem->msgId << ". Transaction will be encrypted for group " << should_encrypt_to_this_circle_id << std::endl; -#endif - RsNxsItem *encrypted_item = NULL ; - uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ; - - if(encryptSingleNxsItem(mItem, grpMeta->mCircleId,m->mGroupId, encrypted_item,status)) - { - itemL.push_back(encrypted_item) ; - delete mItem ; - } - else - { - // Something's not ready (probably the circle content. We could put on a vetting list, but actually the client will re-ask the list asap. - - std::cerr << " (EE) Cannot encrypt msg meta data. MsgId=" << mItem->msgId << ", grpId=" << mItem->grpId << ", circleId=" << should_encrypt_to_this_circle_id << ". Dropping the whole list." << std::endl; - - for(std::list::const_iterator it(itemL.begin());it!=itemL.end();++it) - delete *it ; - - itemL.clear() ; - delete mItem ; - break ; - } - } - else - { -#ifdef NXS_NET_DEBUG_7 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " sending info item for msg id " << mItem->msgId << " in clear." << std::endl; -#endif - itemL.push_back(mItem); - } - } - } -#ifdef NXS_NET_DEBUG_0 - else - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " vetting forbids sending. Nothing will be sent." << itemL.size() << " items." << std::endl; -#endif - - if(!itemL.empty()) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " sending final msg info list of " << itemL.size() << " items." << std::endl; -#endif - locked_pushMsgRespFromList(itemL, peer, item->grpId,transN); - } -#ifdef NXS_NET_DEBUG_0 - else - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " list is empty! Not sending anything." << std::endl; -#endif - - - // release meta resource - // for(std::vector::iterator vit = msgMetas.begin(); vit != msgMetas.end(); ++vit) - // delete *vit; -} - -void RsGxsNetService::locked_pushMsgRespFromList(std::list& itemL, const RsPeerId& sslId, const RsGxsGroupId& grp_id,const uint32_t& transN) -{ -#ifdef NXS_NET_DEBUG_1 - GXSNETDEBUG_PG(sslId,grp_id) << "locked_pushMsgResponseFromList()" << std::endl; - GXSNETDEBUG_PG(sslId,grp_id) << " nelems = " << itemL.size() << std::endl; - GXSNETDEBUG_PG(sslId,grp_id) << " peerId = " << sslId << std::endl; - GXSNETDEBUG_PG(sslId,grp_id) << " transN = " << transN << std::endl; -#endif - NxsTransaction* tr = new NxsTransaction(); - tr->mItems = itemL; - tr->mFlag = NxsTransaction::FLAG_STATE_WAITING_CONFIRM; - - RsNxsTransacItem* trItem = new RsNxsTransacItem(mServType); - trItem->transactFlag = RsNxsTransacItem::FLAG_BEGIN_P1 | RsNxsTransacItem::FLAG_TYPE_MSG_LIST_RESP; - trItem->nItems = itemL.size(); - trItem->timestamp = 0; - trItem->PeerId(sslId); - trItem->transactionNumber = transN; - - // also make a copy for the resident transaction - tr->mTransaction = new RsNxsTransacItem(*trItem); - tr->mTransaction->PeerId(mOwnId); - tr->mTimeOut = time(NULL) + mTransactionTimeOut; - - // This time stamp is not supposed to be used on the other side. We just set it to avoid sending an uninitialiszed value. - trItem->updateTS = mServerMsgUpdateMap[grp_id].msgUpdateTS; - -#ifdef NXS_NET_DEBUG_5 - GXSNETDEBUG_P_ (sslId) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - sending messages response to peer " - << sslId << " with " << itemL.size() << " messages " << std::endl; -#endif - // signal peer to prepare for transaction - if(locked_addTransaction(tr)) - generic_sendItem(trItem); - else - { - delete tr ; - delete trItem ; - } -} - -bool RsGxsNetService::canSendMsgIds(std::vector >& msgMetas, const RsGxsGrpMetaData& grpMeta, const RsPeerId& sslId,RsGxsCircleId& should_encrypt_id) -{ -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << "RsGxsNetService::canSendMsgIds() CIRCLE VETTING" << std::endl; -#endif - // check if that peer is a virtual peer id, in which case we only send/recv data to/from it items for the group it's requested for - - RsGxsGroupId peer_grp ; - if(mAllowDistSync && mGxsNetTunnel != NULL && mGxsNetTunnel->isDistantPeer(RsGxsNetTunnelVirtualPeerId(sslId),peer_grp) && peer_grp != grpMeta.mGroupId) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Distant peer designed for group " << peer_grp << ": cannot request sync for different group." << std::endl; -#endif - return false ; - } - - // first do the simple checks - uint8_t circleType = grpMeta.mCircleType; - - if(circleType == GXS_CIRCLE_TYPE_LOCAL) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: LOCAL => returning false" << std::endl; -#endif - return false; - } - else if(circleType == GXS_CIRCLE_TYPE_PUBLIC || circleType == GXS_CIRCLE_TYPE_UNKNOWN) // this complies with the fact that p3IdService does not initialise the circle type. - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: PUBLIC => returning true" << std::endl; -#endif - return true; - } - else if(circleType == GXS_CIRCLE_TYPE_EXTERNAL) - { - const RsGxsCircleId& circleId = grpMeta.mCircleId; -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: EXTERNAL => returning true. Msgs ids list will be encrypted." << std::endl; -#endif - should_encrypt_id = circleId ; - - // For each message ID, check that the author is in the circle. If not, do not send the message, which means, remove it from the list. - // Unsigned messages are still transmitted. This is because in some groups (channels) the posts are not signed. Whether an unsigned post - // is allowed at this point is anyway already vetted by the RsGxsGenExchange service. - - // Messages that stay in the list will be sent. As a consequence true is always returned. - // Messages put in vetting list will be dealt with later - - std::vector toVet; - - for(uint32_t i=0;imAuthorId.isNull() ) // keep the message in this case - ++i ; - else - { - if(mCircles->isLoaded(circleId) && mCircles->isRecipient(circleId, grpMeta.mGroupId, msgMetas[i]->mAuthorId)) - { - ++i ; - continue ; - } - - MsgIdCircleVet mic(msgMetas[i]->mMsgId, msgMetas[i]->mAuthorId); - toVet.push_back(mic); -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " deleting MsgMeta entry for msg ID " << msgMetas[i]->mMsgId << " signed by " << msgMetas[i]->mAuthorId << " who is not in group circle " << circleId << std::endl; -#endif - - //delete msgMetas[i] ; - msgMetas[i] = msgMetas[msgMetas.size()-1] ; - msgMetas.pop_back() ; - } - -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle info not loaded. Putting in vetting list and returning false." << std::endl; -#endif - if(!toVet.empty()) - mPendingCircleVets.push_back(new MsgCircleIdsRequestVetting(mCircles, mPgpUtils, toVet, grpMeta.mGroupId, sslId, grpMeta.mCircleId)); - - return true ; - } - else if(circleType == GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY) - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " YOUREYESONLY, checking further" << std::endl; -#endif - bool res = checkPermissionsForFriendGroup(sslId,grpMeta) ; -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Final answer: " << res << std::endl; -#endif - return res ; - } - else - { - std::cerr << "(EE) unknown value found in circle type for group " << grpMeta.mGroupId << ": " << (int)circleType << ": this is probably a bug in the design of the group creation." << std::endl; - return false; - } -} - -/** inherited methods **/ - -bool RsGxsNetService::checkPermissionsForFriendGroup(const RsPeerId& sslId,const RsGxsGrpMetaData& grpMeta) -{ -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: YOUR EYES ONLY - ID = " << grpMeta.mInternalCircle << std::endl; -#endif - // a non empty internal circle id means this - // is the personal circle owner - if(!grpMeta.mInternalCircle.isNull()) - { - RsGroupInfo ginfo ; - RsPgpId pgpId = mPgpUtils->getPgpId(sslId) ; - -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Group internal circle: " << grpMeta.mInternalCircle << ", We're owner. Sending to everyone in the group." << std::endl; - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Current destination is PGP Id: " << pgpId << std::endl; -#endif - if(!rsPeers->getGroupInfo(RsNodeGroupId(grpMeta.mInternalCircle),ginfo)) - { - std::cerr << "(EE) Cannot get information for internal circle (group node) ID " << grpMeta.mInternalCircle << " which conditions dissemination of GXS group " << grpMeta.mGroupId << std::endl; - return false ; - } - - bool res = (ginfo.peerIds.find(pgpId) != ginfo.peerIds.end()); - -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Final Answer is: " << res << std::endl; -#endif - return res ; - } - else - { - // An empty internal circle id means this peer can only - // send circle related info from peer he received it from. - // Normally this should be a pgp-based decision, but if we do that, - // A ---> B ----> A' ---...--->B' , then A' will also send to B' since B is the - // originator for A'. So A will lose control of who can see the data. This should - // be discussed further... - -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Empty internal circle: cannot only send/recv info to/from Peer we received it from (grpMeta.mOriginator=" << grpMeta.mOriginator << ")" << std::endl; - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Final answer is: " << (grpMeta.mOriginator == sslId) << std::endl; -#endif - if(grpMeta.mOriginator == sslId) - return true; - else - return false; - } -} - -void RsGxsNetService::pauseSynchronisation(bool /* enabled */) -{ - std::cerr << "(EE) RsGxsNetService::pauseSynchronisation() called, but not implemented." << std::endl; -} - -void RsGxsNetService::setSyncAge(const RsGxsGroupId &grpId, uint32_t age_in_secs) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - locked_checkDelay(age_in_secs) ; - - RsGxsGrpConfig& conf(locked_getGrpConfig(grpId)); - - if(conf.msg_req_delay != age_in_secs) - { - conf.msg_req_delay = age_in_secs; - - // we also need to zero the client TS, in order to trigger a new sync - locked_resetClientTS(grpId); - - IndicateConfigChanged(); - - // also send an event so that UI is updated - - mNewGrpSyncParamsToNotify.insert(grpId); - } -} -void RsGxsNetService::setKeepAge(const RsGxsGroupId &grpId, uint32_t age_in_secs) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - locked_checkDelay(age_in_secs) ; - - RsGxsGrpConfig& conf(locked_getGrpConfig(grpId)); - - if(conf.msg_keep_delay != age_in_secs) - { - conf.msg_keep_delay = age_in_secs; - IndicateConfigChanged(); - } -} - -RsGxsGrpConfig& RsGxsNetService::locked_getGrpConfig(const RsGxsGroupId& grp_id) -{ - GrpConfigMap::iterator it = mServerGrpConfigMap.find(grp_id); - - if(it == mServerGrpConfigMap.end()) - { - RsGxsGrpConfig& conf(mServerGrpConfigMap[grp_id]) ; - - conf.msg_keep_delay = mDefaultMsgStorePeriod; - conf.msg_send_delay = mDefaultMsgSyncPeriod; - conf.msg_req_delay = mDefaultMsgSyncPeriod; - - conf.max_visible_count = 0 ; - conf.statistics_update_TS = 0 ; - conf.last_group_modification_TS = 0 ; - - return conf ; - } - else - return it->second; -} - -uint32_t RsGxsNetService::getSyncAge(const RsGxsGroupId& grpId) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - return locked_getGrpConfig(grpId).msg_req_delay ; -} -uint32_t RsGxsNetService::getKeepAge(const RsGxsGroupId& grpId) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - return locked_getGrpConfig(grpId).msg_keep_delay ; -} - -int RsGxsNetService::requestGrp( - const std::list& grpIds, const RsPeerId& peerId ) -{ -#ifdef NXS_NET_DEBUG_0 - RS_DBG("Adding explicit groups requests to peer: ", peerId); - for(auto& grpId: std::as_const(grpIds)) RS_DBG("\t Group ID: ", grpId); -#endif - - RS_STACK_MUTEX(mNxsMutex); - mExplicitRequest[peerId].insert(grpIds.begin(), grpIds.end()); - return 1; -} - -void RsGxsNetService::processExplicitGroupRequests() -{ - RS_STACK_MUTEX(mNxsMutex); - - for(auto& cit: std::as_const(mExplicitRequest)) - { -#ifdef NXS_NET_DEBUG_0 - RS_DBG("sending pending explicit group requests to peer ", cit.first); -#endif - const RsPeerId& peerId = cit.first; - const std::set& groupIdList = cit.second; - - std::list grpSyncItems; - uint32_t transN = locked_getTransactionId(); - for(auto& grpId: std::as_const(groupIdList)) - { -#ifdef NXS_NET_DEBUG_0 - RS_DBG("\t group request for group ID: ", grpId); -#endif - RsNxsSyncGrpItem* item = new RsNxsSyncGrpItem(mServType); - item->grpId = grpId; - item->PeerId(peerId); - item->flag = RsNxsSyncGrpItem::FLAG_REQUEST; - item->transactionNumber = transN; - grpSyncItems.push_back(item); - } - - if(!grpSyncItems.empty()) - locked_pushGrpTransactionFromList(grpSyncItems, peerId, transN); - } - - mExplicitRequest.clear(); -} - -int RsGxsNetService::sharePublishKey(const RsGxsGroupId& grpId,const std::set& peers) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - mPendingPublishKeyRecipients[grpId] = peers ; -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG__G(grpId) << "RsGxsNetService::sharePublishKeys() " << (void*)this << " adding publish keys for grp " << grpId << " to sending list" << std::endl; -#endif - - return true ; -} - -void RsGxsNetService::sharePublishKeysPending() -{ - RS_STACK_MUTEX(mNxsMutex) ; - - if(mPendingPublishKeyRecipients.empty()) - return ; - -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG___ << "RsGxsNetService::sharePublishKeys() " << (void*)this << std::endl; -#endif - // get list of peers that are online - - std::set peersOnline; - std::list toDelete; - std::map >::iterator mit ; - - mNetMgr->getOnlineList(mServiceInfo.mServiceType, peersOnline); - -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG___ << " " << peersOnline.size() << " peers online." << std::endl; -#endif - /* send public key to peers online */ - - for(mit = mPendingPublishKeyRecipients.begin(); mit != mPendingPublishKeyRecipients.end(); ++mit) - { - // Compute the set of peers to send to. We start with this, to avoid retrieving the data for nothing. - - std::list recipients ; - std::set offline_recipients ; - - for(std::set::const_iterator it(mit->second.begin());it!=mit->second.end();++it) - if(peersOnline.find(*it) != peersOnline.end()) - { -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG_P_(*it) << " " << *it << ": online. Adding." << std::endl; -#endif - recipients.push_back(*it) ; - } - else - { -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG_P_(*it) << " " << *it << ": offline. Keeping for next try." << std::endl; -#endif - offline_recipients.insert(*it) ; - } - - // If empty, skip - - if(recipients.empty()) - { -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG___ << " No recipients online. Skipping." << std::endl; -#endif - continue ; - } - - // Get the meta data for this group Id - // - RsGxsGrpMetaTemporaryMap grpMetaMap; - grpMetaMap[mit->first] = NULL; - mDataStore->retrieveGxsGrpMetaData(grpMetaMap); - - // Find the publish keys in the retrieved info - - const auto& grpMeta = grpMetaMap[mit->first] ; - - if(grpMeta == NULL) - { - std::cerr << "(EE) RsGxsNetService::sharePublishKeys() Publish keys cannot be found for group " << mit->first << std::endl; - continue ; - } - - const RsTlvSecurityKeySet& keys = grpMeta->keys; - - std::map::const_iterator kit = keys.private_keys.begin(), kit_end = keys.private_keys.end(); - bool publish_key_found = false; - RsTlvPrivateRSAKey publishKey ; - - for(; kit != kit_end && !publish_key_found; ++kit) - { - publish_key_found = (kit->second.keyFlags == (RSTLV_KEY_DISTRIB_PUBLISH | RSTLV_KEY_TYPE_FULL)); - publishKey = kit->second ; - } - - if(!publish_key_found) - { - std::cerr << "(EE) no publish key in group " << mit->first << ". Cannot share!" << std::endl; - continue ; - } - - -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG__G(grpMeta->mGroupId) << " using publish key ID=" << publishKey.keyId << ", flags=" << publishKey.keyFlags << std::endl; -#endif - for(std::list::const_iterator it(recipients.begin());it!=recipients.end();++it) - { - /* Create publish key sharing item */ - RsNxsGroupPublishKeyItem *publishKeyItem = new RsNxsGroupPublishKeyItem(mServType); - - publishKeyItem->clear(); - publishKeyItem->grpId = mit->first; - - publishKeyItem->private_key = publishKey ; - publishKeyItem->PeerId(*it); - - generic_sendItem(publishKeyItem); -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG_PG(*it,grpMeta->mGroupId) << " sent key item to " << *it << std::endl; -#endif - } - - mit->second = offline_recipients ; - - // If given peers have all received key(s) then stop sending for group - if(offline_recipients.empty()) - toDelete.push_back(mit->first); - } - - // delete pending peer list which are done with - for(std::list::const_iterator lit = toDelete.begin(); lit != toDelete.end(); ++lit) - mPendingPublishKeyRecipients.erase(*lit); -} - -void RsGxsNetService::handleRecvPublishKeys(RsNxsGroupPublishKeyItem *item) -{ -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << "RsGxsNetService::sharePublishKeys() " << std::endl; -#endif - - if (!item) - return; - - RS_STACK_MUTEX(mNxsMutex) ; - -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " PeerId : " << item->PeerId() << std::endl; - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " GrpId: " << item->grpId << std::endl; - GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " Got key Item: " << item->private_key.keyId << std::endl; -#endif - - // Get the meta data for this group Id - // - RsGxsGrpMetaTemporaryMap grpMetaMap; - grpMetaMap[item->grpId] = NULL; - - mDataStore->retrieveGxsGrpMetaData(grpMetaMap); - - // update the publish keys in this group meta info - - const auto& grpMeta = grpMetaMap[item->grpId] ; - if (!grpMeta) { - std::cerr << "(EE) RsGxsNetService::handleRecvPublishKeys() grpMeta not found." << std::endl; - return ; - } - - // Check that the keys correspond, and that FULL keys are supplied, etc. - -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG_PG(item->PeerId(),item->grpId)<< " Key received: " << std::endl; -#endif - - bool admin = (item->private_key.keyFlags & RSTLV_KEY_DISTRIB_ADMIN) && (item->private_key.keyFlags & RSTLV_KEY_TYPE_FULL) ; - bool publi = (item->private_key.keyFlags & RSTLV_KEY_DISTRIB_PUBLISH) && (item->private_key.keyFlags & RSTLV_KEY_TYPE_FULL) ; - -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG_PG(item->PeerId(),item->grpId)<< " Key id = " << item->private_key.keyId << " admin=" << admin << ", publish=" << publi << " ts=" << item->private_key.endTS << std::endl; -#endif - - if(!(!admin && publi)) - { - std::cerr << " Key is not a publish private key. Discarding!" << std::endl; - return ; - } - // Also check that we don't already have full keys for that group. - - if(grpMeta->keys.public_keys.find(item->private_key.keyId) == grpMeta->keys.public_keys.end()) - { - std::cerr << " (EE) Key not found in known group keys. This is an inconsistency." << std::endl; - return ; - } - - if(grpMeta->keys.private_keys.find(item->private_key.keyId) != grpMeta->keys.private_keys.end()) - { -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG_PG(item->PeerId(),item->grpId)<< " (EE) Publish key already present in database. Discarding message." << std::endl; -#endif - mNewPublishKeysToNotify.insert(item->grpId) ; - return ; - } - - // Store/update the info. - - RsTlvSecurityKeySet keys = grpMeta->keys ; - keys.private_keys[item->private_key.keyId] = item->private_key ; - - bool ret = mDataStore->updateGroupKeys(item->grpId,keys, grpMeta->mSubscribeFlags | GXS_SERV::GROUP_SUBSCRIBE_PUBLISH) ; - - if(ret) - { -#ifdef NXS_NET_DEBUG_3 - GXSNETDEBUG_PG(item->PeerId(),item->grpId)<< " updated database with new publish keys." << std::endl; -#endif - mNewPublishKeysToNotify.insert(item->grpId) ; - } - else - { - std::cerr << "(EE) could not update database. Something went wrong." << std::endl; - } -} - -std::error_condition RsGxsNetService::requestPull(std::set peers) -{ - /* If specific peers are passed as paramether ask only to them */ - if(peers.empty()) - { - mNetMgr->getOnlineList(mServiceInfo.mServiceType, peers); - - if(mAllowDistSync && mGxsNetTunnel != nullptr) - { - /* Grab all online virtual peers of distant tunnels for the current - * service. */ - - std::list vpids ; - mGxsNetTunnel->getVirtualPeers(vpids); - - for(auto it(vpids.begin());it!=vpids.end();++it) - peers.insert(RsPeerId(*it)) ; - } - } - - // Still empty? Reports there are no available peers - if (peers.empty()) return std::errc::network_down; - - for(auto& peerId: std::as_const(peers)) - { - auto item = new RsNxsPullRequestItem(mServType); - item->PeerId(peerId); - generic_sendItem(item); - } - - return std::error_condition(); -} - -void RsGxsNetService::handlePullRequest(RsNxsPullRequestItem *item) -{ - checkUpdatesFromPeers(std::set{item->PeerId()}); -} - -bool RsGxsNetService::getGroupServerUpdateTS(const RsGxsGroupId& gid,rstime_t& group_server_update_TS, rstime_t& msg_server_update_TS) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - group_server_update_TS = mGrpServerUpdate.grpUpdateTS ; - - ServerMsgMap::iterator it = mServerMsgUpdateMap.find(gid) ; - - if(mServerMsgUpdateMap.end() == it) - msg_server_update_TS = 0 ; - else - msg_server_update_TS = it->second.msgUpdateTS ; - - return true ; -} - -bool RsGxsNetService::removeGroups(const std::list& groups) -{ - RS_STACK_MUTEX(mNxsMutex) ; - -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG___ << "Removing group information from deleted groups:" << std::endl; -#endif - - for(std::list::const_iterator git(groups.begin());git!=groups.end();++git) - { -#ifdef NXS_NET_DEBUG_0 - GXSNETDEBUG__G(*git) << " deleting info for group " << *git << std::endl; -#endif - - // Here we do not use locked_getGrpConfig() because we dont want the entry to be created if it doesnot already exist. - - GrpConfigMap::iterator it = mServerGrpConfigMap.find(*git) ; - - if(it != mServerGrpConfigMap.end()) - { - it->second.suppliers.TlvClear(); // we dont erase the entry, because we want to keep the user-defined sync parameters. - it->second.max_visible_count = 0; - } - - mServerMsgUpdateMap.erase(*git) ; - - for(ClientMsgMap::iterator it(mClientMsgUpdateMap.begin());it!=mClientMsgUpdateMap.end();++it) - it->second.msgUpdateInfos.erase(*git) ; - - // This last step is very important: it makes RS re-sync all groups after deleting, with every new peer. If may happen indeed that groups - // are deleted because there's no suppliers since the actual supplier friend is offline for too long. In this case, the group needs - // to re-appear when the friend who is a subscriber comes online again. - - mClientGrpUpdateMap.clear(); - } - - IndicateConfigChanged(); - return true ; -} - -bool RsGxsNetService::isDistantPeer(const RsPeerId& pid) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - if(!mAllowDistSync || mGxsNetTunnel == NULL) - return false ; - - RsGxsGroupId group_id ; - - return mGxsNetTunnel->isDistantPeer(RsGxsNetTunnelVirtualPeerId(pid),group_id); -} - -bool RsGxsNetService::stampMsgServerUpdateTS(const RsGxsGroupId& gid) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - return locked_stampMsgServerUpdateTS(gid) ; -} - -bool RsGxsNetService::locked_stampMsgServerUpdateTS(const RsGxsGroupId& gid) -{ - RsGxsServerMsgUpdate& m(mServerMsgUpdateMap[gid]); - - m.msgUpdateTS = time(NULL) ; - - return true; -} - -DistantSearchGroupStatus RsGxsNetService::getDistantSearchStatus(const RsGxsGroupId& group_id) -{ - auto it = mSearchedGroups.find(group_id); - - if(it != mSearchedGroups.end()) - return it->second.status; - - for(auto it2:mDistantSearchResults) - if(it2.second.find(group_id) != it2.second.end()) - return DistantSearchGroupStatus::CAN_BE_REQUESTED; - - return DistantSearchGroupStatus::UNKNOWN; -} - -TurtleRequestId RsGxsNetService::turtleGroupRequest(const RsGxsGroupId& group_id) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - rstime_t now = time(NULL); - auto it = mSearchedGroups.find(group_id) ; - - if(mSearchedGroups.end() != it && (it->second.ts + MIN_DELAY_BETWEEN_GROUP_SEARCH > now)) - { - std::cerr << "(WW) Last turtle request was " << now - it->second.ts << " secs ago. Not searching again." << std::endl; - return it->second.request_id; - } - -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG__G(group_id) << " requesting group id " << group_id << " using turtle" << std::endl; -#endif - TurtleRequestId req = mGxsNetTunnel->turtleGroupRequest(group_id,this) ; - - GroupRequestRecord& rec(mSearchedGroups[group_id]) ; - - rec.request_id = req; - rec.ts = now; - rec.status = DistantSearchGroupStatus::ONGOING_REQUEST; - - mSearchRequests[req] = group_id; - - return req; -} -TurtleRequestId RsGxsNetService::turtleSearchRequest(const std::string& match_string) -{ - return mGxsNetTunnel->turtleSearchRequest(match_string,this) ; -} - -static bool termSearch(const std::string& src, const std::string& substring) -{ - /* always ignore case */ - return src.end() != std::search( - src.begin(), src.end(), substring.begin(), substring.end(), - RsRegularExpression::CompareCharIC() ); -} - - -bool RsGxsNetService::retrieveDistantSearchResults(TurtleRequestId req,std::map& group_infos) -{ - RS_STACK_MUTEX(mNxsMutex) ; - - auto it = mDistantSearchResults.find(req) ; - - if(it == mDistantSearchResults.end()) - return false ; - - group_infos = it->second; - return true ; -} -bool RsGxsNetService::retrieveDistantGroupSummary(const RsGxsGroupId& group_id,RsGxsGroupSearchResults& gs) -{ - RS_STACK_MUTEX(mNxsMutex) ; - for(auto it(mDistantSearchResults.begin());it!=mDistantSearchResults.end();++it) - { - auto it2 = it->second.find(group_id) ; - - if(it2 != it->second.end()) - { - gs = it2->second; - return true ; - } - } - return false ; -} -bool RsGxsNetService::clearDistantSearchResults(const TurtleRequestId& id) -{ - RS_STACK_MUTEX(mNxsMutex) ; - mDistantSearchResults.erase(id); - return true ; -} - -void RsGxsNetService::receiveTurtleSearchResults( - TurtleRequestId req, const std::list& group_infos ) -{ - std::set groupsToNotifyResults; - - { - RS_STACK_MUTEX(mNxsMutex); - - RsGxsGrpMetaTemporaryMap grpMeta; - std::map& search_results_map(mDistantSearchResults[req]); - -#ifdef NXS_NET_DEBUG_9 - std::cerr << "Received group summary through turtle search for the following groups:" << std::endl; -#endif - - for(const RsGxsGroupSummary& gps : group_infos) - { - std::cerr <<" " << gps.mGroupId << " \"" << gps.mGroupName << "\"" << std::endl; - grpMeta[gps.mGroupId] = nullptr; - } - - mDataStore->retrieveGxsGrpMetaData(grpMeta); - -#ifdef NXS_NET_DEBUG_9 - std::cerr << "Retrieved data store group data for the following groups:" <mGroupName << std::endl; -#endif - - for (const RsGxsGroupSummary& gps : group_infos) - { -#ifdef TO_REMOVE - /* Because of deep search is enabled search results may bring more - * info then we already have also about post that are indexed by - * xapian, so we don't apply this filter anymore. */ - - /* Only keep groups that are not locally known, and groups that are - * not already in the mDistantSearchResults structure. - * mDataStore may in some situations allocate an empty group meta - * data, so it's important to test that the group meta is both non - * null and actually corresponds to the group id we seek. */ - auto& meta(grpMeta[gps.mGroupId]); - if(meta != nullptr && meta->mGroupId == gps.mGroupId) continue; -#endif // def TO_REMOVE - - const RsGxsGroupId& grpId(gps.mGroupId); - - groupsToNotifyResults.insert(grpId); - - // Find search results place for this particular group - -#ifdef NXS_NET_DEBUG_9 - std::cerr << " Adding gps=" << gps.mGroupId << " name=\"" << gps.mGroupName << "\" gps.mSearchContext=\"" << gps.mSearchContext << "\"" << std::endl; -#endif - RsGxsGroupSearchResults& eGpS(search_results_map[grpId]); - - if(eGpS.mGroupId != grpId) // not initialized yet. So we do it now. - { - eGpS.mGroupId = gps.mGroupId; - eGpS.mGroupName = gps.mGroupName; - eGpS.mAuthorId = gps.mAuthorId; - eGpS.mPublishTs = gps.mPublishTs; - eGpS.mSignFlags = gps.mSignFlags; - } - // We should check that the above values are always the same for all info that is received. In the end, we'll - // request the group meta and check the signature, but it may be misleading to receive a forged information - // that is not the real one. - - ++eGpS.mPopularity; // increase popularity. This is not a real counting, but therefore some heuristic estimate. - eGpS.mNumberOfMessages = std::max( eGpS.mNumberOfMessages, gps.mNumberOfMessages ); - eGpS.mLastMessageTs = std::max( eGpS.mLastMessageTs, gps.mLastMessageTs ); - - if(gps.mSearchContext != gps.mGroupName) // this is a bit of a hack. We should have flags to tell where the search hit happens - eGpS.mSearchContexts.insert(gps.mSearchContext); - } - } // end RS_STACK_MUTEX(mNxsMutex); - - for(const RsGxsGroupId& grpId : groupsToNotifyResults) - mObserver->receiveDistantSearchResults(req, grpId); -} - -void RsGxsNetService::receiveTurtleSearchResults( - TurtleRequestId req, - const uint8_t* encrypted_group_data, uint32_t encrypted_group_data_len ) -{ -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___ << " received encrypted group data for turtle search request " << std::hex << req << std::dec << ": " << RsUtil::BinToHex(encrypted_group_data,encrypted_group_data_len,50) << std::endl; -#endif - auto it = mSearchRequests.find(req); - if(mSearchRequests.end() == it) - { - RS_WARN("Received search results for unknown request: ", req); - return; - } - RsGxsGroupId grpId = it->second; - - uint8_t encryption_master_key[32]; - Sha256CheckSum s = RsDirUtil::sha256sum(grpId.toByteArray(),grpId.SIZE_IN_BYTES); - memcpy(encryption_master_key,s.toByteArray(),32); - -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___ << " attempting data decryption with master key " << RsUtil::BinToHex(encryption_master_key,32) << std::endl; -#endif - unsigned char *clear_group_data = NULL; - uint32_t clear_group_data_len ; - - if(!librs::crypto::decryptAuthenticateData(encrypted_group_data,encrypted_group_data_len,encryption_master_key,clear_group_data,clear_group_data_len)) - { - std::cerr << "(EE) Could not decrypt data. Something went wrong. Wrong key??" << std::endl; - return ; - } - -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___ << " successfuly decrypted data : " << RsUtil::BinToHex(clear_group_data,clear_group_data_len,50) << std::endl; -#endif - uint32_t used_size = clear_group_data_len; - RsItem *item = RsNxsSerialiser(mServType).deserialise(clear_group_data,&used_size) ; - RsNxsGrp *nxs_identity_grp=nullptr; - - if(used_size < clear_group_data_len) - { - uint32_t remaining_size = clear_group_data_len-used_size ; - RsItem *item2 = RsNxsSerialiser(RS_SERVICE_GXS_TYPE_GXSID).deserialise(clear_group_data+used_size,&remaining_size) ; - - nxs_identity_grp = dynamic_cast(item2); - - if(!nxs_identity_grp) - std::cerr << "(EE) decrypted item contains more data that cannot be deserialized as a GxsId. Unexpected!" << std::endl; - - // We should probably check that the identity that is sent corresponds to the group author and don't add - // it otherwise. But in any case, this won't harm to add a new public identity. If that identity is banned, - // the group will be discarded in RsGenExchange anyway. - - if(nxs_identity_grp) - mGixs->receiveNewIdentity(nxs_identity_grp); - } - - free(clear_group_data); - clear_group_data = NULL ; - - RsNxsGrp *nxs_grp = dynamic_cast(item) ; - - if(nxs_grp == NULL) - { - std::cerr << "(EE) decrypted item is not a RsNxsGrp. Weird!" << std::endl; - return ; - } - -#ifdef NXS_NET_DEBUG_8 - if(nxs_identity_grp) - GXSNETDEBUG___ << " Serialized clear data contains a group " << nxs_grp->grpId << " in service " << std::hex << mServType << std::dec << " and a second identity item for an identity." << nxs_identity_grp->grpId << std::endl; - else - GXSNETDEBUG___ << " Serialized clear data contains a single GXS group for Grp Id " << nxs_grp->grpId << " in service " << std::hex << mServType << std::dec << std::endl; -#endif - - std::vector new_grps(1,nxs_grp); - - GroupRequestRecord& rec(mSearchedGroups[nxs_grp->grpId]) ; - rec.status = DistantSearchGroupStatus::HAVE_GROUP_DATA; - -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___ << " passing the grp data to observer." << std::endl; -#endif - mObserver->receiveNewGroups(new_grps); - mObserver->receiveDistantSearchResults(req, grpId); -} - -std::error_condition RsGxsNetService::distantSearchRequest( - rs_owner_ptr searchData, uint32_t dataSize, - RsServiceType serviceType, TurtleRequestId& requestId ) -{ - if(!mGxsNetTunnel) - { - free(searchData); - return std::errc::function_not_supported; - } - - return mGxsNetTunnel->turtleSearchRequest( - searchData, dataSize, serviceType, requestId ); -} - -std::error_condition RsGxsNetService::handleDistantSearchRequest( - rs_view_ptr requestData, uint32_t requestSize, - rs_owner_ptr& resultData, uint32_t& resultSize ) -{ - RS_DBG(""); - return mObserver->handleDistantSearchRequest( - requestData, requestSize, resultData, resultSize ); -} - -std::error_condition RsGxsNetService::receiveDistantSearchResult( - const TurtleRequestId requestId, - rs_owner_ptr& resultData, uint32_t& resultSize ) -{ - return mObserver->receiveDistantSearchResult( - requestId, resultData, resultSize ); -} - -bool RsGxsNetService::search( const std::string& substring, - std::list& group_infos ) -{ - group_infos.clear(); - - RsGxsGrpMetaTemporaryMap grpMetaMap; - { - RS_STACK_MUTEX(mNxsMutex) ; - mDataStore->retrieveGxsGrpMetaData(grpMetaMap); - } - - RsGroupNetworkStats stats; - for(auto it(grpMetaMap.begin());it!=grpMetaMap.end();++it) - if(it->second->mCircleType==GXS_CIRCLE_TYPE_PUBLIC && termSearch(it->second->mGroupName,substring)) - { - getGroupNetworkStats(it->first,stats); - - RsGxsGroupSummary s; - s.mGroupId = it->first; - s.mGroupName = it->second->mGroupName; - s.mSearchContext = it->second->mGroupName; - s.mSignFlags = it->second->mSignFlags; - s.mPublishTs = it->second->mPublishTs; - s.mAuthorId = it->second->mAuthorId; - s.mNumberOfMessages = stats.mMaxVisibleCount; - s.mLastMessageTs = stats.mLastGroupModificationTS; - s.mPopularity = it->second->mPop; - - group_infos.push_back(s); - } - -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___ << " performing local substring search in response to distant request. Found " << group_infos.size() << " responses." << std::endl; -#endif - return !group_infos.empty(); -} - -bool RsGxsNetService::search(const Sha1CheckSum& hashed_group_id,unsigned char *& encrypted_group_data,uint32_t& encrypted_group_data_len) -{ - // First look into the grp hash cache - -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___ << " Received group data request for hash " << hashed_group_id << std::endl; -#endif - auto it = mGroupHashCache.find(hashed_group_id) ; - RsNxsGrp *grp_data = NULL ; - - if(mGroupHashCache.end() != it) - { - grp_data = it->second; - } - else - { - // Now check if the last request was too close in time, in which case, we dont retrieve data. - - if(mLastCacheReloadTS + 60 > time(NULL)) - { - std::cerr << "(WW) Not found in cache, and last cache reload less than 60 secs ago. Returning false. " << std::endl; - return false ; - } - -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___ << " reloading group cache information" << std::endl; -#endif - RsNxsGrpDataTemporaryMap grpDataMap; - { - RS_STACK_MUTEX(mNxsMutex) ; - mDataStore->retrieveNxsGrps(grpDataMap, true); - mLastCacheReloadTS = time(NULL); - } - - for(auto it(grpDataMap.begin());it!=grpDataMap.end();++it) - if(it->second->metaData->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED ) // only cache subscribed groups - { - RsNxsGrp *grp = it->second ; - grp->metaData->keys.TlvClear() ;// clean private keys. This technically not needed, since metaData is not serialized, but I still prefer. - - Sha1CheckSum hash(RsDirUtil::sha1sum(it->first.toByteArray(),it->first.SIZE_IN_BYTES)); - - mGroupHashCache[hash] = grp ; - it->second = NULL ; // prevents deletion - - if(hash == hashed_group_id) - grp_data = grp ; - } - } - - if(!grp_data) - { -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___ << " no group found for hash " << hashed_group_id << ": returning false." << std::endl; -#endif - return false ; - } - -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___ << " found corresponding group data group id in cache group_id=" << grp_data->grpId << std::endl; -#endif - // Finally, serialize and encrypt the grp data - - uint32_t size = RsNxsSerialiser(mServType).size(grp_data); - RsNxsGrp *author_group=nullptr; - - if(!grp_data->metaData->mAuthorId.isNull()) - { -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___ << " this group has an author identity " << grp_data->metaData->mAuthorId << " that we need to send at the same time." << std::endl; -#endif - mGixs->retrieveNxsIdentity(grp_data->metaData->mAuthorId,author_group); // whatever gets the data - - if(!author_group) - { - std::cerr << "(EE) Cannot retrieve author group data " << grp_data->metaData->mAuthorId << " for GXS group " << grp_data->grpId << std::endl; - return false; - } - - delete author_group->metaData; // delete private information, just in case, but normally it is not serialized. - author_group->metaData = NULL ; - - size += RsNxsSerialiser(RS_SERVICE_GXS_TYPE_GXSID).size(author_group); - } - - RsTemporaryMemory mem(size) ; - uint32_t used_size=size; - - RsNxsSerialiser(mServType).serialise(grp_data,mem,&used_size) ; - - uint32_t remaining_size=size-used_size; - - if(author_group) - { -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___ << " Serializing author group data..." << std::endl; -#endif - RsNxsSerialiser(RS_SERVICE_GXS_TYPE_GXSID).serialise(author_group,mem+used_size,&remaining_size); - } - - uint8_t encryption_master_key[32]; - Sha256CheckSum s = RsDirUtil::sha256sum(grp_data->grpId.toByteArray(),grp_data->grpId.SIZE_IN_BYTES); - memcpy(encryption_master_key,s.toByteArray(),32); - -#ifdef NXS_NET_DEBUG_8 - GXSNETDEBUG___ << " sending data encrypted with master key " << RsUtil::BinToHex(encryption_master_key,32) << std::endl; -#endif - return librs::crypto::encryptAuthenticateData(mem,size,encryption_master_key,encrypted_group_data,encrypted_group_data_len); -} - diff --git a/libretroshare/src/gxs/rsgxsnetservice.h b/libretroshare/src/gxs/rsgxsnetservice.h deleted file mode 100644 index 015d01301..000000000 --- a/libretroshare/src/gxs/rsgxsnetservice.h +++ /dev/null @@ -1,682 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsnetservice.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Christopher Evi-Parker * - * Copyright (C) 2018-2021 Gioacchino Mazzurco * - * Copyright (C) 2019-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include - -#include "rsnxs.h" -#include "rsgds.h" -#include "rsnxsobserver.h" -#include "pqi/p3linkmgr.h" -#include "rsitems/rsnxsitems.h" -#include "rsitems/rsgxsupdateitems.h" -#include "rsgxsnettunnel.h" -#include "rsgxsnetutils.h" -#include "pqi/p3cfgmgr.h" -#include "rsgixs.h" -#include "util/rssharedptr.h" - -/// keep track of transaction number -typedef std::map TransactionIdMap; - -/// to keep track of peers active transactions -typedef std::map TransactionsPeerMap; - -class PgpAuxUtils; - -class RsGroupNetworkStatsRecord -{ - public: - RsGroupNetworkStatsRecord() { max_visible_count= 0 ; update_TS=0; } - - std::set suppliers ; - uint32_t max_visible_count ; - rstime_t update_TS ; -}; - -struct GroupRequestRecord -{ - GroupRequestRecord(): ts(0),request_id(0),status(DistantSearchGroupStatus::UNKNOWN) {} - - rstime_t ts ; - TurtleRequestId request_id; - DistantSearchGroupStatus status; -}; - -/*! - * This class implements the RsNetWorkExchangeService - * using transactions to handle synchrnisation of Nxs items between - * peers in a network - * Transactions requires the maintenance of several states between peers - * - * Thus a data structure maintains: peers, and their active transactions - * Then for each transaction it needs to be noted if this is an outgoing or incoming transaction - * Outgoing transaction are in 3 different states: - * 1. START 2. INITIATED 3. SENDING 4. END - * Incoming transaction are in 3 different states - * 1. START 2. RECEIVING 3. END - */ -class RsGxsNetService : - public RsNetworkExchangeService, public p3ThreadedService, public p3Config -{ -public: - - static const uint32_t FRAGMENT_SIZE; - /*! - * only one observer is allowed - * @param servType service type - * @param gds The data service which allows read access to a service/store - * @param nxsObs observer will be notified whenever new messages/grps - * @param nxsObs observer will be notified whenever new messages/grps - * arrive - */ - RsGxsNetService(uint16_t servType, RsGeneralDataService *gds, - RsNxsNetMgr *netMgr, - RsNxsObserver *nxsObs, // used to be = NULL. - const RsServiceInfo serviceInfo, - RsGixsReputation* reputations = NULL, RsGcxs* circles = NULL, RsGixs *gixs=NULL, - PgpAuxUtils *pgpUtils = NULL, RsGxsNetTunnelService *mGxsNT = NULL, - bool grpAutoSync = true, bool msgAutoSync = true,bool distSync=false, - uint32_t default_store_period = RS_GXS_DEFAULT_MSG_STORE_PERIOD, - uint32_t default_sync_period = RS_GXS_DEFAULT_MSG_REQ_PERIOD); - - virtual ~RsGxsNetService(); - - virtual RsServiceInfo getServiceInfo() override { return mServiceInfo; } - - virtual void getItemNames(std::map& names) const override ; - -public: - - - virtual uint16_t serviceType() const override { return mServType ; } - - /*! - * Use this to set how far back synchronisation and storage of messages should take place - * @param age the max age a sync/storage item can to be allowed in a synchronisation - */ - virtual void setSyncAge(const RsGxsGroupId& grpId,uint32_t age_in_secs)override ; - virtual void setKeepAge(const RsGxsGroupId& grpId,uint32_t age_in_secs)override ; - - virtual uint32_t getSyncAge(const RsGxsGroupId& id)override ; - virtual uint32_t getKeepAge(const RsGxsGroupId& id)override ; - - virtual uint32_t getDefaultSyncAge() override { return mDefaultMsgSyncPeriod ; } - virtual uint32_t getDefaultKeepAge() override { return mDefaultMsgStorePeriod ; } - - virtual void setDefaultKeepAge(uint32_t t) override { mDefaultMsgStorePeriod = t ; } - virtual void setDefaultSyncAge(uint32_t t) override { mDefaultMsgSyncPeriod = t ; } - - virtual bool msgAutoSync() const override { return mAllowMsgSync; } - virtual bool grpAutoSync() const override { return mGrpAutoSync; } - - /// @see RsNetworkExchangeService - std::error_condition distantSearchRequest( - rs_owner_ptr searchData, uint32_t dataSize, - RsServiceType serviceType, TurtleRequestId& requestId ) override; - - /// @see RsNetworkExchangeService - std::error_condition handleDistantSearchRequest( - rs_view_ptr requestData, uint32_t requestSize, - rs_owner_ptr& resultData, uint32_t& resultSize ) override; - - /// @see RsNetworkExchangeService - std::error_condition receiveDistantSearchResult( - const TurtleRequestId requestId, - rs_owner_ptr& resultData, uint32_t& resultSize ) override; - - /** Request group data via turtle search - * @param group_id */ - TurtleRequestId turtleGroupRequest(const RsGxsGroupId& group_id) override; - - /** - * @brief Search for matching groups names over turtle search. - * @deprecated this method is kept mostly for retrocompatibility with older - * peers, newly implemented search functions should instead be based on the - * service generic search. - * @see RsNetworkExchangeService - */ - RS_DEPRECATED_FOR(distantSearchRequest) - TurtleRequestId turtleSearchRequest(const std::string& match_string) override; - - /** @see RsNetworkExchangeService - * @deprecated kept for retrocompatibility with older peers, new code should - * instead be based on the service generic search */ - RS_DEPRECATED_FOR(receiveDistantSearchResult) - void receiveTurtleSearchResults( - TurtleRequestId req, - const uint8_t* encrypted_group_data, - uint32_t encrypted_group_data_len ) override; - - /** - * @deprecated kept for retrocompatibility with older peers, new code should - * instead be based on the service generic search */ - RS_DEPRECATED_FOR(handleRemoteSearchRequest) - virtual bool search( const std::string& substring, - std::list& group_infos) override; - virtual bool search(const Sha1CheckSum& hashed_group_id,unsigned char *& encrypted_group_data,uint32_t& encrypted_group_data_len)override ; - virtual void receiveTurtleSearchResults(TurtleRequestId req,const std::list& group_infos)override ; - - virtual bool retrieveDistantSearchResults(TurtleRequestId req, std::map &group_infos)override ; - virtual bool clearDistantSearchResults(const TurtleRequestId& id)override ; - virtual bool retrieveDistantGroupSummary(const RsGxsGroupId&, RsGxsGroupSearchResults &)override ; - virtual DistantSearchGroupStatus getDistantSearchStatus(const RsGxsGroupId&) override ; - - /*! - * pauses synchronisation of subscribed groups and request for group id - * from peers - * @param enabled set to false to disable pause, and true otherwise - */ - // NOT IMPLEMENTED - virtual void pauseSynchronisation(bool enabled)override ; - - - /*! - * Request for this message is sent through to peers on your network - * and how many hops from them you've indicated - * @param msgId the messages to retrieve - * @return request token to be redeemed - */ - virtual int requestMsg(const RsGxsGrpMsgIdPair& /* msgId */)override { return 0;} - - /*! - * Request for this group is sent through to peers on your network - * and how many hops from them you've indicated - * @param enabled set to false to disable pause, and true otherwise - * @return request token to be redeemed - */ - virtual int requestGrp(const std::list& grpId, const RsPeerId& peerId)override ; - - /*! - * share publish keys for the specified group with the peers in the specified list. - */ - - virtual int sharePublishKey(const RsGxsGroupId& grpId,const std::set& peers) override ; - - /*! - * Returns statistics for the group networking activity: popularity (number of friends subscribers) and max_visible_msg_count, - * that is the max nnumber of messages reported by a friend. - */ - virtual bool getGroupNetworkStats(const RsGxsGroupId& id,RsGroupNetworkStats& stats) override ; - - /*! - * Used to inform the net service that we changed subscription status. That helps - * optimising data transfer when e.g. unsubsribed groups are updated less often, etc - */ - virtual void subscribeStatusChanged(const RsGxsGroupId& id,bool subscribed) override ; - - virtual void rejectMessage(const RsGxsMessageId& msg_id) override ; - - virtual bool getGroupServerUpdateTS(const RsGxsGroupId& gid,rstime_t& grp_server_update_TS,rstime_t& msg_server_update_TS) override ; - virtual bool stampMsgServerUpdateTS(const RsGxsGroupId& gid) override ; - virtual bool removeGroups(const std::list& groups)override ; - virtual bool isDistantPeer(const RsPeerId& pid)override ; - - /* p3Config methods */ -public: - - bool loadList(std::list& load)override ; - bool saveList(bool &cleanup, std::list&)override ; - RsSerialiser *setupSerialiser()override ; - -public: - - /*! - * initiates synchronisation - */ - int tick()override ; - - void threadTick() override; /// @see RsTickingThread - - - /// @see RsNetworkExchangeService - std::error_condition checkUpdatesFromPeers( - std::set peers = std::set() ) override; - - /// @see RsNetworkExchangeService - std::error_condition requestPull( - std::set peers = std::set() ) override; - -private: - - /*! - * called when - * items are deemed to be waiting in p3Service item queue - */ - void recvNxsItemQueue(); - - - /** S: Transaction processing **/ - - /*! - * These process transactions which are in a wait state - * Also moves transaction which have been completed to - * the completed transactions list - */ - void processTransactions(); - - /*! - * Process completed transaction, which either simply - * retires a transaction or additionally generates a response - * to the completed transaction - */ - void processCompletedTransactions(); - - /*! - * Process transaction owned/started by user - * @param tr transaction to process, ownership stays with callee - */ - void locked_processCompletedOutgoingTrans(NxsTransaction* tr); - - /*! - * Process transactions started/owned by other peers - * @param tr transaction to process, ownership stays with callee - */ - void locked_processCompletedIncomingTrans(NxsTransaction* tr); - - - /*! - * Process a transaction item, assumes a general lock - * @param item the transaction item to process - * @return false ownership of item left with callee - */ - bool locked_processTransac(RsNxsTransacItem* item); - - /*! - * This adds a transaction - * completeted transaction list - * If this is an outgoing transaction, transaction id is - * decrement - * @param trans transaction to add - */ - void locked_completeTransaction(NxsTransaction* trans); - - /*! - * \brief locked_stampMsgServerUpdateTS - * updates the server msg time stamp. This function is the locked method for the one above with similar name - * \param gid group id to stamp. - * \return - */ - bool locked_stampMsgServerUpdateTS(const RsGxsGroupId& gid); - /*! - * This retrieves a unique transaction id that - * can be used in an outgoing transaction - */ - uint32_t locked_getTransactionId(); - - /*! - * This attempts to push the transaction id counter back if you have - * active outgoing transactions in play - */ - bool attemptRecoverIds(); - - /*! - * The cb listener is the owner of the grps - * @param grps - */ - //void notifyListenerGrps(std::list& grps); - - /*! - * The cb listener is the owner of the msgs - * @param msgs - */ - //void notifyListenerMsgs(std::list& msgs); - - /*! - * Generates new transaction to send msg requests based on list - * of msgs received from peer stored in passed transaction - * @param tr transaction responsible for generating msg request - */ - void locked_genReqMsgTransaction(NxsTransaction* tr); - - /*! - * Generates new transaction to send grp requests based on list - * of grps received from peer stored in passed transaction - * @param tr transaction responsible for generating grp request - */ - void locked_genReqGrpTransaction(NxsTransaction* tr); - - /*! - * This first checks if one can send a grpId based circles - * If it can send, then it call locked_genSendMsgsTransaction - * @param tr transaction responsible for generating grp request - * @see locked_genSendMsgsTransaction - */ - void locked_checkSendMsgsTransaction(NxsTransaction* tr); - - /*! - * Generates new transaction to send msg data based on list - * of grpids received from peer stored in passed transaction - * @param tr transaction responsible for generating grp request - */ - void locked_genSendMsgsTransaction(NxsTransaction* tr); - - /*! - * Generates new transaction to send grp data based on list - * of grps received from peer stored in passed transaction - * @param tr transaction responsible for generating grp request - */ - void locked_genSendGrpsTransaction(NxsTransaction* tr); - - /*! - * convenience function to add a transaction to list - * @param tr transaction to add - */ - bool locked_addTransaction(NxsTransaction* tr); - - void cleanTransactionItems(NxsTransaction* tr) const; - - /*! - * @param tr the transaction to check for timeout - * @return false if transaction has timed out, true otherwise - */ - bool locked_checkTransacTimedOut(NxsTransaction* tr); - - /** E: Transaction processing **/ - - /** S: item handlers **/ - - /*! - * This attempts handles transaction items - * ownership of item is left with callee if this method returns false - * @param item transaction item to handle - * @return false if transaction could not be handled, ownership of item is left with callee - */ - bool handleTransaction(RsNxsItem* item); - - /*! - * Handles an nxs item for group synchronisation - * by startin a transaction and sending a list - * of groups held by user - * @param item contains grp sync info - */ - void handleRecvSyncGroup(RsNxsSyncGrpReqItem* item); - - /*! - * Handles an nxs item for group statistics - * @param item contaims update time stamp and number of messages - */ - void handleRecvSyncGrpStatistics(RsNxsSyncGrpStatsItem *grs); - - /*! - * Handles an nxs item for msgs synchronisation - * @param item contaims msg sync info - */ - void handleRecvSyncMessage(RsNxsSyncMsgReqItem* item,bool item_was_encrypted); - - /*! - * Handles an nxs item for group publish key - * @param item contaims keys/grp info - */ - void handleRecvPublishKeys(RsNxsGroupPublishKeyItem*) ; - - /*! - * Handles a nxs pull request item from a given friend/tunnel - * @param item contaims keys/grp info - */ - void handlePullRequest(RsNxsPullRequestItem *item); - - /** E: item handlers **/ - - - void runVetting(); - - /*! - * @param peerId The peer to vet to see if they can receive this groupid - * @param grpMeta this is the meta item to determine if it can be sent to given peer - * @param toVet groupid/peer to vet are stored here if their circle id is not cached - * @return false, if you cannot send to this peer, true otherwise - */ - bool canSendGrpId(const RsPeerId& sslId, const RsGxsGrpMetaData& grpMeta, std::vector& toVet, bool &should_encrypt); - bool canSendMsgIds(std::vector > &msgMetas, const RsGxsGrpMetaData&, const RsPeerId& sslId, RsGxsCircleId &should_encrypt_id); - - /*! - * \brief checkPermissionsForFriendGroup - * Checks that we can send/recv from that node, given that the grpMeta has a distribution limited to a local circle. - * \param sslId Candidate peer to send to or to receive from. - * \param grpMeta Contains info about the group id, internal circle id, etc. - * \return true only when the internal exists and validates as a friend node group, and contains the owner of sslId. - */ - bool checkPermissionsForFriendGroup(const RsPeerId& sslId,const RsGxsGrpMetaData& grpMeta) ; - - bool checkCanRecvMsgFromPeer(const RsPeerId& sslId, const RsGxsGrpMetaData& meta, RsGxsCircleId& should_encrypt_id); - - void locked_createTransactionFromPending(MsgRespPending* grpPend); - void locked_createTransactionFromPending(GrpRespPending* msgPend); - bool locked_createTransactionFromPending(GrpCircleIdRequestVetting* grpPend) ; - bool locked_createTransactionFromPending(MsgCircleIdsRequestVetting* grpPend) ; - - void locked_pushGrpTransactionFromList(std::list& reqList, const RsPeerId& peerId, const uint32_t& transN); // forms a grp list request - void locked_pushMsgTransactionFromList(std::list& reqList, const RsPeerId& peerId, const uint32_t& transN); // forms a msg list request - void locked_pushGrpRespFromList(std::list& respList, const RsPeerId& peer, const uint32_t& transN); - void locked_pushMsgRespFromList(std::list& itemL, const RsPeerId& sslId, const RsGxsGroupId &grp_id, const uint32_t& transN); - - void checkDistantSyncState(); - - void syncGrpStatistics(); - void addGroupItemToList(NxsTransaction*& tr, - const RsGxsGroupId& grpId, uint32_t& transN, - std::list& reqList); - - //bool locked_canReceive(const RsGxsGrpMetaData * const grpMeta, const RsPeerId& peerId); - - void processExplicitGroupRequests(); - - void locked_doMsgUpdateWork(const RsNxsTransacItem* nxsTrans, const RsGxsGroupId& grpId); - - void updateServerSyncTS(); -#ifdef TO_REMOVE - void updateClientSyncTS(); -#endif - - bool locked_CanReceiveUpdate(const RsNxsSyncGrpReqItem *item); - bool locked_CanReceiveUpdate(RsNxsSyncMsgReqItem *item, bool &grp_is_known); - void locked_resetClientTS(const RsGxsGroupId& grpId); - bool locked_checkResendingOfUpdates(const RsPeerId& pid, const RsGxsGroupId &grpId, rstime_t incoming_ts, RsPeerUpdateTsRecord& rec); - - static RsGxsGroupId hashGrpId(const RsGxsGroupId& gid,const RsPeerId& pid) ; - - RsGxsGrpConfig& locked_getGrpConfig(const RsGxsGroupId& grp_id); -private: - - typedef std::vector GrpFragments; - typedef std::vector MsgFragments; - - /*! - * Loops over pending publish key orders. - */ - void sharePublishKeysPending() ; - - /*! - * Fragment a message into individual fragments which are at most 150kb - * @param msg message to fragment - * @param msgFragments fragmented message - * @return false if fragmentation fails true otherwise - */ - bool fragmentMsg(RsNxsMsg& msg, MsgFragments& msgFragments) const; - - /*! - * Fragment a group into individual fragments which are at most 150kb - * @param grp group to fragment - * @param grpFragments fragmented group - * @return false if fragmentation fails true other wise - */ - bool fragmentGrp(RsNxsGrp& grp, GrpFragments& grpFragments) const; - - /*! - * Fragment a message into individual fragments which are at most 150kb - * @param msg message to fragment - * @param msgFragments fragmented message - * @return NULL if not possible to reconstruct message from fragment, - * pointer to defragments nxs message is possible - */ - RsNxsMsg* deFragmentMsg(MsgFragments& msgFragments) const; - - /*! - * Fragment a group into individual fragments which are at most 150kb - * @param grp group to fragment - * @param grpFragments fragmented group - * @return NULL if not possible to reconstruct group from fragment, - * pointer to defragments nxs group is possible - */ - RsNxsGrp* deFragmentGrp(GrpFragments& grpFragments) const; - - - /*! - * Note that if all fragments for a message are not found then its fragments are dropped - * @param fragments message fragments which are not necessarily from the same message - * @param partFragments the partitioned fragments (into message ids) - */ - void collateMsgFragments(MsgFragments &fragments, std::map& partFragments) const; - - /*! - * Note that if all fragments for a group are not found then its fragments are dropped - * @param fragments group fragments which are not necessarily from the same group - * @param partFragments the partitioned fragments (into message ids) - */ - void collateGrpFragments(GrpFragments fragments, std::map& partFragments) const; - - /*! - * stamp the group info from that particular peer at the given time. - */ - - void locked_stampPeerGroupUpdateTime(const RsPeerId& pid,const RsGxsGroupId& grpId,rstime_t tm,uint32_t n_messages) ; - - /*! - * encrypts/decrypts the transaction for the destination circle id. - */ - bool encryptSingleNxsItem(RsNxsItem *item, const RsGxsCircleId& destination_circle, const RsGxsGroupId &destination_group, RsNxsItem *& encrypted_item, uint32_t &status) ; - bool decryptSingleNxsItem(const RsNxsEncryptedDataItem *encrypted_item, RsNxsItem *&nxsitem, std::vector *private_keys=NULL); - bool processTransactionForDecryption(NxsTransaction *tr); // return false when the keys are not loaded => need retry later - - void cleanRejectedMessages(); - void processObserverNotifications(); - - void generic_sendItem(rs_owner_ptr si); - RsItem *generic_recvItem(); - -private: - - static void locked_checkDelay(uint32_t& time_in_secs); - - /*** transactions ***/ - - /// active transactions - TransactionsPeerMap mTransactions; - - /// completed transactions - std::list mComplTransactions; - - /// transaction id counter - uint32_t mTransactionN; - - /*** transactions ***/ - - /*** synchronisation ***/ - std::list mSyncGrp; - std::list mSyncMsg; - /*** synchronisation ***/ - - RsNxsObserver* mObserver; - RsGeneralDataService* mDataStore; - uint16_t mServType; - - // how much time must elapse before a timeout failure - // for an active transaction - uint32_t mTransactionTimeOut; - - RsPeerId mOwnId; - - RsNxsNetMgr* mNetMgr; - - /// for other members save transactions - RsMutex mNxsMutex; - - uint32_t mSyncTs; - uint32_t mLastKeyPublishTs; - uint32_t mLastCleanRejectedMessages; - - const uint32_t mSYNC_PERIOD; - int mUpdateCounter ; - - RsGcxs* mCircles; - RsGixs *mGixs; - RsGixsReputation* mReputations; - PgpAuxUtils *mPgpUtils; - RsGxsNetTunnelService *mGxsNetTunnel; - - bool mGrpAutoSync; - bool mAllowMsgSync; - bool mAllowDistSync; - - // need to be verfied - std::vector mPendingResp; - std::vector mPendingCircleVets; - std::map > mPendingPublishKeyRecipients ; - std::map > mExplicitRequest; - std::map > mPartialMsgUpdates ; - - // nxs sync optimisation - // can pull dynamically the latest timestamp for each message - -public: - - typedef std::map ClientMsgMap; - typedef std::map ServerMsgMap; - typedef std::map ClientGrpMap; - typedef std::map GrpConfigMap; -private: - - ClientMsgMap mClientMsgUpdateMap; - ServerMsgMap mServerMsgUpdateMap; - ClientGrpMap mClientGrpUpdateMap; - GrpConfigMap mServerGrpConfigMap; - - RsGxsServerGrpUpdate mGrpServerUpdate; - RsServiceInfo mServiceInfo; - - std::map mRejectedMessages; - - std::vector mNewGroupsToNotify ; - std::vector mNewMessagesToNotify ; - std::set mNewStatsToNotify ; - std::set mNewPublishKeysToNotify ; - std::set mNewGrpSyncParamsToNotify ; - - // Distant search result map - std::map > mDistantSearchResults ; - - void debugDump(); - - uint32_t mDefaultMsgStorePeriod ; - uint32_t mDefaultMsgSyncPeriod ; - - std::map mGroupHashCache; - std::map mSearchRequests; - std::map mSearchedGroups ; - rstime_t mLastCacheReloadTS ; - - bool mUseMetaCache; -}; diff --git a/libretroshare/src/gxs/rsgxsnettunnel.cc b/libretroshare/src/gxs/rsgxsnettunnel.cc deleted file mode 100644 index 7f70ffa42..000000000 --- a/libretroshare/src/gxs/rsgxsnettunnel.cc +++ /dev/null @@ -1,1489 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: gxsnettunnel.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2018 Cyril Soler * - * Copyright (C) 2019-2021 Gioacchino Mazzurco * - * Copyright (C) 2019-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "util/rsdir.h" -#include "util/rstime.h" -#include "retroshare/rspeers.h" -#include "serialiser/rstypeserializer.h" -#include "gxs/rsnxs.h" -#include "rsgxsnettunnel.h" - -/*extern*/ RsGxsDistSync* rsGxsDistSync = nullptr; - -//#define DEBUG_RSGXSNETTUNNEL 1 - -#define GXS_NET_TUNNEL_NOT_IMPLEMENTED() { std::cerr << __PRETTY_FUNCTION__ << ": not yet implemented." << std::endl; } -#define GXS_NET_TUNNEL_DEBUG() std::cerr << time(NULL) << " : GXS_NET_TUNNEL: " << __FUNCTION__ << " : " -#define GXS_NET_TUNNEL_ERROR() std::cerr << "(EE) GXS_NET_TUNNEL ERROR : " - -static const uint32_t RS_GXS_NET_TUNNEL_MAX_ALLOWED_HITS_GROUP_DATA = 1; -static const uint32_t RS_GXS_NET_TUNNEL_MAX_ALLOWED_HITS_GROUP_SEARCH = 100; - - -RsGxsNetTunnelService::RsGxsNetTunnelService(): mGxsNetTunnelMtx("GxsNetTunnel") -{ - mRandomBias.clear(); - - /* adds some variance in order to avoid doing all this tasks at once across - * services */ - auto now = time(nullptr); - mLastKeepAlive = now + (RsRandom::random_u32()%20); - mLastAutoWash = now + (RsRandom::random_u32()%20); - mLastDump = now + (RsRandom::random_u32()%20); -} - -//============================================================================// -// Transport Items // -//============================================================================// - -enum class RsGxsNetTunnelItemSubtypes : uint8_t -{ - VIRTUAL_PEER = 0x01, - - KEEP_ALIVE = 0x02, - - RANDOM_BIAS = 0x03, - - /// @deprecated kept only for retrocompatibility @see SERVICE_SEARCH_REQUEST - SEARCH_SUBSTRING = 0x04, - - SEARCH_GROUP_REQUEST = 0x05, - - // SEARCH_GROUP_SUMMARY = 0x06, removed - - SEARCH_GROUP_DATA = 0x07, - - /// @deprecated kept only for retrocompatibility @see SERVICE_SEARCH_REPLY - SEARCH_GROUP_SUMMARY = 0x08, - - /** Generic search request generated and handled by specific service - * (channels, forums...) */ - SERVICE_SEARCH_REQUEST = 0x09, - - /** Generic search reply generated and handled by specific service - * (channels, forums...) */ - SERVICE_SEARCH_REPLY = 0x0a -}; - -RS_DEPRECATED_FOR(RsServiceType::GXS_DISTANT) -constexpr uint16_t RS_SERVICE_TYPE_GXS_NET_TUNNEL = - static_cast(RsServiceType::GXS_DISTANT); - -RS_DEPRECATED_FOR(RsGxsNetTunnelItemSubtypes) -const uint8_t RS_PKT_SUBTYPE_GXS_NET_TUNNEL_VIRTUAL_PEER = 0x01 ; -RS_DEPRECATED_FOR(RsGxsNetTunnelItemSubtypes) -const uint8_t RS_PKT_SUBTYPE_GXS_NET_TUNNEL_KEEP_ALIVE = 0x02 ; -RS_DEPRECATED_FOR(RsGxsNetTunnelItemSubtypes) -const uint8_t RS_PKT_SUBTYPE_GXS_NET_TUNNEL_RANDOM_BIAS = 0x03 ; -RS_DEPRECATED_FOR(RsGxsNetTunnelItemSubtypes) -const uint8_t RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_SUBSTRING = 0x04 ; -RS_DEPRECATED_FOR(RsGxsNetTunnelItemSubtypes) -const uint8_t RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_GROUP_REQUEST = 0x05 ; -RS_DEPRECATED_FOR(RsGxsNetTunnelItemSubtypes) -const uint8_t RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_GROUP_DATA = 0x07 ; -RS_DEPRECATED_FOR(RsGxsNetTunnelItemSubtypes) -const uint8_t RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_GROUP_SUMMARY = 0x08; -// Do not add new subitems types as const, use RsGxsNetTunnelItemSubtypes instead - -struct RsGxsNetTunnelItem: RsItem -{ -public: - explicit RsGxsNetTunnelItem(RsGxsNetTunnelItemSubtypes subtype): - RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_NET_TUNNEL, - static_cast(subtype) ) - { - /* no priority. All items are encapsulated into generic Turtle items - * anyway. */ - } - - virtual ~RsGxsNetTunnelItem() = default; - virtual void clear() {} - - RS_DEPRECATED_FOR("RsGxsNetTunnelItem(RsGxsNetTunnelItemSubtypes subtype)") - explicit RsGxsNetTunnelItem(uint8_t item_subtype): - RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_NET_TUNNEL, - item_subtype ) - { - // no priority. All items are encapsulated into generic Turtle items anyway. - } -}; - -class RsGxsNetTunnelVirtualPeerItem: public RsGxsNetTunnelItem -{ -public: - RsGxsNetTunnelVirtualPeerItem() :RsGxsNetTunnelItem(RS_PKT_SUBTYPE_GXS_NET_TUNNEL_VIRTUAL_PEER) {} - - virtual ~RsGxsNetTunnelVirtualPeerItem() {} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) - { - RsTypeSerializer::serial_process(j,ctx,virtual_peer_id,"virtual_peer_id") ; - } - - RsPeerId virtual_peer_id ; -}; - -class RsGxsNetTunnelKeepAliveItem: public RsGxsNetTunnelItem -{ -public: - RsGxsNetTunnelKeepAliveItem() :RsGxsNetTunnelItem(RS_PKT_SUBTYPE_GXS_NET_TUNNEL_KEEP_ALIVE) {} - - virtual ~RsGxsNetTunnelKeepAliveItem() {} - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */) {} -}; - -class RsGxsNetTunnelRandomBiasItem: public RsGxsNetTunnelItem -{ -public: - explicit RsGxsNetTunnelRandomBiasItem() : RsGxsNetTunnelItem(RS_PKT_SUBTYPE_GXS_NET_TUNNEL_RANDOM_BIAS) { clear();} - virtual ~RsGxsNetTunnelRandomBiasItem() {} - - virtual void clear() { mRandomBias.clear() ; } - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) - { - RsTypeSerializer::serial_process(j,ctx,mRandomBias,"random bias") ; - } - - Bias20Bytes mRandomBias; // Cannot be a simple char[] because of serialization. -}; - -struct RsGxsServiceTurtleSearchReqItem: RsGxsNetTunnelItem -{ - RsGxsServiceTurtleSearchReqItem(): - RsGxsNetTunnelItem(RsGxsNetTunnelItemSubtypes::SERVICE_SEARCH_REQUEST), - mServiceType(RsServiceType::NONE), mSearchData(nullptr), - mSearchDataSize(0) {} - - explicit RsGxsServiceTurtleSearchReqItem(RsServiceType service): - RsGxsNetTunnelItem(RsGxsNetTunnelItemSubtypes::SERVICE_SEARCH_REQUEST), - mServiceType(service), mSearchData(nullptr), mSearchDataSize(0) {} - - /// Type of the service which originated the search request - RsServiceType mServiceType; - - uint8_t* mSearchData; /// Service search request data - uint32_t mSearchDataSize; /// Search data size - - /// @see RsSerializable - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(mServiceType); - - RsTypeSerializer::RawMemoryWrapper prox(mSearchData, mSearchDataSize); - RsTypeSerializer::serial_process(j, ctx, prox, "mSearchData"); - } - - /// @see RsItem - void clear() override - { - free(mSearchData); - mSearchData = nullptr; - mSearchDataSize = 0; - } - - ~RsGxsServiceTurtleSearchReqItem() override { clear(); } -}; - -struct RsGxsServiceTurtleSearchReplyItem: RsGxsNetTunnelItem -{ - RsGxsServiceTurtleSearchReplyItem(): - RsGxsNetTunnelItem(RsGxsNetTunnelItemSubtypes::SERVICE_SEARCH_REPLY), - mServiceType(RsServiceType::NONE), mReplyData(nullptr), - mReplyDataSize(0) {} - - explicit RsGxsServiceTurtleSearchReplyItem(RsServiceType service): - RsGxsNetTunnelItem(RsGxsNetTunnelItemSubtypes::SERVICE_SEARCH_REPLY), - mServiceType(service), mReplyData(nullptr), mReplyDataSize(0) {} - - /// Type of the service which originated the search request - RsServiceType mServiceType; - - uint8_t* mReplyData; /// Service search reply data - uint32_t mReplyDataSize; /// Search reply data size - - /// @see RsSerializable - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(mServiceType); - - RsTypeSerializer::RawMemoryWrapper prox(mReplyData, mReplyDataSize); - RsTypeSerializer::serial_process(j, ctx, prox, "mSearchData"); - } - - /// @see RsItem - void clear() override - { - free(mReplyData); - mReplyData = nullptr; - mReplyDataSize = 0; - } - - ~RsGxsServiceTurtleSearchReplyItem() override { clear(); } -}; - -class RS_DEPRECATED_FOR(RsGxsServiceTurtleSearchItem) -RsGxsNetTunnelTurtleSearchSubstringItem: public RsGxsNetTunnelItem -{ -public: - explicit RsGxsNetTunnelTurtleSearchSubstringItem(): RsGxsNetTunnelItem(RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_SUBSTRING) {} - virtual ~RsGxsNetTunnelTurtleSearchSubstringItem() {} - - uint16_t service ; - std::string substring_match ; - - virtual void clear() { substring_match.clear() ; } - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) - { - RsTypeSerializer::serial_process(j,ctx,service,"service") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_KEY,substring_match,"substring_match") ; - } -}; - -class RsGxsNetTunnelTurtleSearchGroupRequestItem: public RsGxsNetTunnelItem -{ -public: - explicit RsGxsNetTunnelTurtleSearchGroupRequestItem(): RsGxsNetTunnelItem(RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_GROUP_REQUEST) {} - virtual ~RsGxsNetTunnelTurtleSearchGroupRequestItem() {} - - uint16_t service ; - Sha1CheckSum hashed_group_id ; - - virtual void clear() { hashed_group_id.clear() ; } - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) - { - RsTypeSerializer::serial_process(j,ctx,service,"service") ; - RsTypeSerializer::serial_process(j,ctx,hashed_group_id,"hashed_group_id") ; - } -}; - -class RsGxsNetTunnelTurtleSearchGroupSummaryItem: public RsGxsNetTunnelItem -{ -public: - explicit RsGxsNetTunnelTurtleSearchGroupSummaryItem(): RsGxsNetTunnelItem(RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_GROUP_SUMMARY) {} - virtual ~RsGxsNetTunnelTurtleSearchGroupSummaryItem() {} - - uint16_t service ; - std::list group_infos; - - virtual void clear() { group_infos.clear() ; } - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) - { - RsTypeSerializer::serial_process(j,ctx,service,"service") ; - RsTypeSerializer::serial_process(j,ctx,group_infos,"group_infos") ; - } -}; - -class RsGxsNetTunnelTurtleSearchGroupDataItem: public RsGxsNetTunnelItem -{ -public: - explicit RsGxsNetTunnelTurtleSearchGroupDataItem() - : RsGxsNetTunnelItem(RS_PKT_SUBTYPE_GXS_NET_TUNNEL_TURTLE_SEARCH_GROUP_DATA), - encrypted_group_data(NULL), - encrypted_group_data_len(0) - {} - - virtual ~RsGxsNetTunnelTurtleSearchGroupDataItem() {} - - uint16_t service ; - unsigned char *encrypted_group_data ; - uint32_t encrypted_group_data_len ; - - virtual void clear() { free(encrypted_group_data);encrypted_group_data=NULL;encrypted_group_data_len=0; } - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) - { - RsTypeSerializer::serial_process(j,ctx,service,"service") ; - - RsTypeSerializer::TlvMemBlock_proxy prox(encrypted_group_data,encrypted_group_data_len) ; - RsTypeSerializer::serial_process(j,ctx,prox,"encrypted_group_data") ; - } -}; - -class RsGxsNetTunnelSerializer: public RsServiceSerializer -{ -public: - RsGxsNetTunnelSerializer(): - RsServiceSerializer(RS_SERVICE_TYPE_GXS_NET_TUNNEL) {} - - virtual RsItem *create_item(uint16_t service,uint8_t item_subtype) const - { - if(service != RS_SERVICE_TYPE_GXS_NET_TUNNEL) - { - RS_ERR( "received item with wrong service ID ", service); - print_stacktrace(); - return nullptr; - } - - switch(static_cast(item_subtype)) - { - case RsGxsNetTunnelItemSubtypes::VIRTUAL_PEER: - return new RsGxsNetTunnelVirtualPeerItem; - case RsGxsNetTunnelItemSubtypes::KEEP_ALIVE: - return new RsGxsNetTunnelKeepAliveItem; - case RsGxsNetTunnelItemSubtypes::RANDOM_BIAS: - return new RsGxsNetTunnelRandomBiasItem; - case RsGxsNetTunnelItemSubtypes::SEARCH_SUBSTRING: - return new RsGxsNetTunnelTurtleSearchSubstringItem; - case RsGxsNetTunnelItemSubtypes::SEARCH_GROUP_REQUEST: - return new RsGxsNetTunnelTurtleSearchGroupRequestItem; - case RsGxsNetTunnelItemSubtypes::SEARCH_GROUP_SUMMARY: - return new RsGxsNetTunnelTurtleSearchGroupSummaryItem; - case RsGxsNetTunnelItemSubtypes::SEARCH_GROUP_DATA: - return new RsGxsNetTunnelTurtleSearchGroupDataItem; - case RsGxsNetTunnelItemSubtypes::SERVICE_SEARCH_REQUEST: - return new RsGxsServiceTurtleSearchReqItem; - case RsGxsNetTunnelItemSubtypes::SERVICE_SEARCH_REPLY: - return new RsGxsServiceTurtleSearchReplyItem; - default: - RS_ERR("Unkonown item type: ", static_cast(item_subtype)); - return nullptr; - } - } -}; - -//===========================================================================================================================================// -// Interface with rest of the software // -//===========================================================================================================================================// - -uint16_t RsGxsNetTunnelService::serviceId() const -{ - return RS_SERVICE_TYPE_GXS_NET_TUNNEL; -} - -bool RsGxsNetTunnelService::registerSearchableService(RsNetworkExchangeService *gxs_service) -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - - mSearchableServices[gxs_service->serviceType()] = gxs_service ; - - return true; -} - -class DataAutoDelete -{ -public: - DataAutoDelete(unsigned char *& data) : mData(data) {} - ~DataAutoDelete() { free(mData); mData=NULL ; } - unsigned char *& mData; -}; - -RsGxsNetTunnelService::~RsGxsNetTunnelService() -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - - // This is needed because we need to clear these structure in a mutex protected environment - // Also this calls the destructor of the objects which calls the freeing of memory e.g. allocated in the incoming data list. - - mGroups.clear(); - mHandledHashes.clear(); - mVirtualPeers.clear(); - - for(auto it(mIncomingData.begin());it!=mIncomingData.end();++it) - for(auto it2(it->second.begin());it2!=it->second.end();++it2) - delete it2->second; - - mIncomingData.clear(); -} - -bool RsGxsNetTunnelService::isDistantPeer(const RsGxsNetTunnelVirtualPeerId& virtual_peer, RsGxsGroupId& group_id) -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - - auto it = mVirtualPeers.find(virtual_peer) ; - - if(it != mVirtualPeers.end()) - { - group_id = it->second.group_id ; - return true ; - } - else - return false ; -} - -bool RsGxsNetTunnelService::receiveTunnelData(uint16_t service_id, unsigned char *& data, uint32_t& data_len, RsGxsNetTunnelVirtualPeerId& virtual_peer) -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - - std::list >& lst(mIncomingData[service_id]); - - if(lst.empty()) - { - data = NULL; - data_len = 0; - return false ; - } - - data = (unsigned char*)lst.front().second->bin_data ; - data_len = lst.front().second->bin_len ; - virtual_peer = lst.front().first; - - lst.front().second->bin_data = NULL ; // avoids deletion - lst.front().second->bin_len = 0 ; // avoids deletion - - delete lst.front().second; - lst.pop_front(); - - return true; -} - -bool RsGxsNetTunnelService::sendTunnelData(uint16_t /* service_id */,unsigned char *& data,uint32_t data_len,const RsGxsNetTunnelVirtualPeerId& virtual_peer) -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - // The item is serialized and encrypted using chacha20+SHA256, using the generic turtle encryption, and then sent to the turtle router. - - DataAutoDelete iad(data) ; // This ensures the item is deleted whatsoever when leaving - - // 1 - find the virtual peer and the proper master key to encrypt with, and check that all the info is known - - auto it = mVirtualPeers.find(virtual_peer) ; - - if(it == mVirtualPeers.end()) - { - GXS_NET_TUNNEL_ERROR() << "cannot find virtual peer " << virtual_peer << ". Data is dropped." << std::endl; - return false ; - } - - if(it->second.vpid_status != RsGxsNetTunnelVirtualPeerInfo::RS_GXS_NET_TUNNEL_VP_STATUS_ACTIVE) - { - GXS_NET_TUNNEL_ERROR() << "virtual peer " << virtual_peer << " is not active. Data is dropped." << std::endl; - return false ; - } - - // 2 - encrypt and send the item. - - RsTurtleGenericDataItem *encrypted_turtle_item = NULL ; - - if(!p3turtle::encryptData(data,data_len,it->second.encryption_master_key,encrypted_turtle_item)) - { - GXS_NET_TUNNEL_ERROR() << "cannot encrypt. Something's wrong. Data is dropped." << std::endl; - return false ; - } - - mTurtle->sendTurtleData(it->second.turtle_virtual_peer_id,encrypted_turtle_item) ; - - return true ; -} - -bool RsGxsNetTunnelService::getVirtualPeers(std::list& peers) -{ - // This function has two effects: - // - return the virtual peers for this group - // - passively set the group as "managed", so that it we answer tunnel requests. - - RS_STACK_MUTEX(mGxsNetTunnelMtx); - - // update the hash entry if needed - - for(auto it(mVirtualPeers.begin());it!=mVirtualPeers.end();++it) - peers.push_back(it->first) ; - -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " returning " << peers.size() << " peers." << std::endl; -#endif - - return true ; -} - -bool RsGxsNetTunnelService::requestDistantPeers(uint16_t service_id, const RsGxsGroupId& group_id) -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - - // Now ask the turtle router to manage a tunnel for that hash. - - RsGxsNetTunnelGroupInfo& ginfo( mGroups[group_id] ) ; - - if(ginfo.group_policy < RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_POLICY_ACTIVE) - ginfo.group_policy = RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_POLICY_ACTIVE; - - ginfo.hash = calculateGroupHash(group_id) ; - ginfo.service_id = service_id; - - mHandledHashes[ginfo.hash] = group_id ; - - // we dont set the group policy here. It will only be set if no peers, or too few peers are available. -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " requesting peers for group " << group_id << std::endl; -#endif - - return true; -} - -bool RsGxsNetTunnelService::releaseDistantPeers(uint16_t /* service_id */,const RsGxsGroupId& group_id) -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - - // Ask turtle router to stop requesting tunnels for that hash. - - RsGxsNetTunnelGroupInfo& ginfo( mGroups[group_id] ) ; - - ginfo.group_policy = RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_POLICY_PASSIVE; - ginfo.hash = calculateGroupHash(group_id) ; - - mHandledHashes[ginfo.hash] = group_id ; // yes, we do not remove, because we're supposed to answer tunnel requests from other peers. - - mTurtle->stopMonitoringTunnels(ginfo.hash) ; - -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " releasing peers for group " << group_id << std::endl; -#endif - return true; -} - -void RsGxsNetTunnelService::dump() const -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - - static std::string group_status_str[4] = { - std::string("[UNKNOWN ]"), - std::string("[IDLE ]"), - std::string("[TUNNELS_REQUESTED]"), - std::string("[VPIDS_AVAILABLE ]") - }; - - static std::string group_policy_str[4] = { - std::string("[UNKNOWN ]"), - std::string("[PASSIVE ]"), - std::string("[ACTIVE ]"), - std::string("[REQUESTING]"), - }; - static std::string vpid_status_str[3] = { - std::string("[UNKNOWN ]"), - std::string("[TUNNEL_OK]"), - std::string("[ACTIVE ]") - }; - - std::cerr << "GxsNetTunnelService dump (this=" << (void*)this << ": " << std::endl; - std::cerr << " Managed GXS groups: " << std::endl; - - for(auto it(mGroups.begin());it!=mGroups.end();++it) - { - std::cerr << " " << it->first << " hash: " << it->second.hash << " policy: " << group_policy_str[it->second.group_policy] << " status: " << group_status_str[it->second.group_status] << " Last contact: " << time(NULL) - it->second.last_contact << " secs ago" << std::endl; - - if(!it->second.virtual_peers.empty()) - std::cerr << " virtual peers:" << std::endl; - for(auto it2(it->second.virtual_peers.begin());it2!=it->second.virtual_peers.end();++it2) - std::cerr << " " << *it2 << std::endl; - } - - std::cerr << " Virtual peers: " << std::endl; - for(auto it(mVirtualPeers.begin());it!=mVirtualPeers.end();++it) - std::cerr << " GXS Peer:" << it->first << " Turtle:" << it->second.turtle_virtual_peer_id - << " status: " << vpid_status_str[it->second.vpid_status] - << " group_id: " << it->second.group_id - << " direction: " << (int)it->second.side - << " last seen " << time(NULL)-it->second.last_contact << " secs ago" - << " ekey: " << RsUtil::BinToHex(it->second.encryption_master_key,RS_GXS_TUNNEL_CONST_EKEY_SIZE,10) << std::endl; - - std::cerr << " Virtual peer turtle => GXS conversion table: " << std::endl; - for(auto it(mTurtle2GxsPeer.begin());it!=mTurtle2GxsPeer.end();++it) - std::cerr << " " << it->first << " => " << it->second << std::endl; - - std::cerr << " Hashes: " << std::endl; - for(auto it(mHandledHashes.begin());it!=mHandledHashes.end();++it) - std::cerr << " hash: " << it->first << " GroupId: " << it->second << std::endl; - - std::cerr << " Incoming data: " << std::endl; - for(auto it(mIncomingData.begin());it!=mIncomingData.end();++it) - { - std::cerr << " service " << std::hex << it->first << std::dec << std::endl; - - for(auto it2(it->second.begin());it2!=it->second.end();++it2) - std::cerr << " peer id " << it2->first << " " << (void*)it2->second << std::endl; - } -} - -//===========================================================================================================================================// -// Interaction with Turtle Router // -//===========================================================================================================================================// - -void RsGxsNetTunnelService::connectToTurtleRouter(p3turtle *tr) -{ - mTurtle = tr ; - mTurtle->registerTunnelService(this) ; -} - -bool RsGxsNetTunnelService::handleTunnelRequest(const RsFileHash &hash,const RsPeerId& /* peer_id */) -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - // We simply check for wether a managed group has a hash that corresponds to the given hash. - - return mHandledHashes.find(hash) != mHandledHashes.end(); -} - -void RsGxsNetTunnelService::receiveTurtleData(const RsTurtleGenericTunnelItem *item, const RsFileHash& hash, const RsPeerId& turtle_virtual_peer_id, RsTurtleGenericTunnelItem::Direction direction) -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " received turtle data for vpid " << turtle_virtual_peer_id << " for hash " << hash << " in direction " << (int)direction << std::endl; -#endif - - if(item->PacketSubType() != RS_TURTLE_SUBTYPE_GENERIC_DATA) - { - GXS_NET_TUNNEL_ERROR() << "item with type " << std::hex << item->PacketSubType() << std::dec << " received by GxsNetTunnel, but is not handled!" << std::endl; - return; - } - // find the group id - - auto it4 = mHandledHashes.find(hash) ; - - if(it4 == mHandledHashes.end()) - { - GXS_NET_TUNNEL_ERROR() << "Cannot find hash " << hash << " to be handled by GxsNetTunnel" << std::endl; - return; - } - RsGxsGroupId group_id = it4->second; - - // Now check if we got an item to advertise a virtual peer - - unsigned char *data = NULL ; - uint32_t data_size = 0 ; - - // generate the decryption key based on virtual peer id and group id - - uint8_t encryption_master_key[RS_GXS_TUNNEL_CONST_EKEY_SIZE] ; - - generateEncryptionKey(group_id,turtle_virtual_peer_id,encryption_master_key); - - if(!p3turtle::decryptItem(static_cast(item),encryption_master_key,data,data_size)) - { - GXS_NET_TUNNEL_ERROR() << "Cannot decrypt data!" << std::endl; - - if(data) - free(data) ; - - return ; - } - - uint16_t service_id = getRsItemService(getRsItemId(data)); - - if(service_id == RS_SERVICE_TYPE_GXS_NET_TUNNEL) - { - RsItem *decrypted_item = RsGxsNetTunnelSerializer().deserialise(data,&data_size); - RsGxsNetTunnelVirtualPeerItem *pid_item = dynamic_cast(decrypted_item) ; - - if(!pid_item) // this handles the case of a KeepAlive packet. - { - delete decrypted_item ; - free(data); - return ; - } - -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " item is a virtual peer id item with vpid = "<< pid_item->virtual_peer_id - << " for group " << group_id << ". Setting virtual peer." << std::endl; -#endif - // we receive a virtual peer id, so we need to update the local information for this peer id - - mTurtle2GxsPeer[turtle_virtual_peer_id] = pid_item->virtual_peer_id ; - - RsGxsNetTunnelVirtualPeerInfo& vp_info(mVirtualPeers[pid_item->virtual_peer_id]) ; - delete pid_item; - - vp_info.vpid_status = RsGxsNetTunnelVirtualPeerInfo::RS_GXS_NET_TUNNEL_VP_STATUS_ACTIVE ; // status of the peer - vp_info.side = direction; // client/server - vp_info.last_contact = time(NULL); // last time some data was sent/recvd - vp_info.group_id = group_id; - vp_info.service_id = mGroups[group_id].service_id ; - - memcpy(vp_info.encryption_master_key,encryption_master_key,RS_GXS_TUNNEL_CONST_EKEY_SIZE); - - vp_info.turtle_virtual_peer_id = turtle_virtual_peer_id; // turtle peer to use when sending data to this vpid. - - free(data); - - return ; - } - - - // item is a generic data item for the client. Let's store the data in the appropriate incoming data queue. - - auto it = mTurtle2GxsPeer.find(turtle_virtual_peer_id) ; - - if(it == mTurtle2GxsPeer.end()) - { - GXS_NET_TUNNEL_ERROR() << "item received by GxsNetTunnel for vpid " << turtle_virtual_peer_id << " but this vpid is unknown! Removing this vpid from group " << group_id << std::endl; - - // this situation is inconsistent: the first item that should go through the tunnel is a virtual peer info, so if we don't have one, it means that - // this virtual peer is dead. We should therefore remove it from the list of vpids for this group. - - mGroups[group_id].virtual_peers.erase(turtle_virtual_peer_id) ; - - free(data); - return; - } - - RsGxsNetTunnelVirtualPeerId gxs_vpid = it->second ; - - auto it2 = mVirtualPeers.find(gxs_vpid) ; - - if(it2 == mVirtualPeers.end()) - { - GXS_NET_TUNNEL_ERROR() << "item received by GxsNetTunnel for GXS vpid " << gxs_vpid << " but the virtual peer id is missing!" << std::endl; - free(data); - return; - } - - if(service_id != it2->second.service_id && service_id != RS_SERVICE_GXS_TYPE_GXSID) - { - GXS_NET_TUNNEL_ERROR() << " received an item for VPID " << gxs_vpid << " openned for service " << it2->second.service_id << " that is not for that service nor for GXS Id service (service=" << std::hex << service_id << std::dec << ". Rejecting!" << std::endl; - free(data); - return ; - } - it2->second.vpid_status = RsGxsNetTunnelVirtualPeerInfo::RS_GXS_NET_TUNNEL_VP_STATUS_ACTIVE ; // status of the peer - it2->second.last_contact = time(NULL); // last time some data was sent/recvd from this peer - - mGroups[group_id].last_contact = time(NULL); // last time some data as received for this group - -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << "item contains generic data for VPID " << gxs_vpid << ". service_id = " << std::hex << service_id << std::dec << ". Storing in incoming list" << std::endl; -#endif - - // push the data into the incoming data list - - RsTlvBinaryData *bind = new RsTlvBinaryData; - bind->tlvtype = 0; - bind->bin_len = data_size; - bind->bin_data = data; - - mIncomingData[service_id].push_back(std::make_pair(gxs_vpid,bind)) ; -} - -void RsGxsNetTunnelService::addVirtualPeer(const TurtleFileHash& hash, const TurtleVirtualPeerId& vpid,RsTurtleGenericTunnelItem::Direction dir) -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - - auto it = mHandledHashes.find(hash) ; - - if(it == mHandledHashes.end()) - { - std::cerr << "RsGxsNetTunnelService::addVirtualPeer(): error! hash " << hash << " is not handled. Cannot add vpid " << vpid << " in direction " << dir << std::endl; - return ; - } - -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " adding virtual peer " << vpid << " for hash " << hash << " in direction " << dir << std::endl; -#endif - const RsGxsGroupId group_id(it->second) ; - - RsGxsNetTunnelGroupInfo& ginfo( mGroups[group_id] ) ; - ginfo.group_status = RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_STATUS_VPIDS_AVAILABLE ; - ginfo.virtual_peers.insert(vpid); - - uint8_t encryption_master_key[RS_GXS_TUNNEL_CONST_EKEY_SIZE]; - - generateEncryptionKey(group_id,vpid,encryption_master_key ); - - // We need to send our own virtual peer id to the other end of the tunnel - - RsGxsNetTunnelVirtualPeerId net_service_virtual_peer = locked_makeVirtualPeerId(group_id); - -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " sending back virtual peer name " << net_service_virtual_peer << " to end of tunnel" << std::endl; -#endif - RsGxsNetTunnelVirtualPeerItem pitem ; - pitem.virtual_peer_id = net_service_virtual_peer ; - - RsTemporaryMemory tmpmem( RsGxsNetTunnelSerializer().size(&pitem) ) ; - uint32_t len = tmpmem.size(); - - RsGxsNetTunnelSerializer().serialise(&pitem,tmpmem,&len); - - RsTurtleGenericDataItem *encrypted_turtle_item = NULL ; - - if(p3turtle::encryptData(tmpmem,len,encryption_master_key,encrypted_turtle_item)) - mPendingTurtleItems.push_back(std::make_pair(vpid,encrypted_turtle_item)) ; // we cannot send directly because of turtle mutex locked before calling addVirtualPeer. - else - GXS_NET_TUNNEL_ERROR() << "cannot encrypt. Something's wrong. Data is dropped." << std::endl; -} - -void RsGxsNetTunnelService::removeVirtualPeer(const TurtleFileHash& hash, const TurtleVirtualPeerId& vpid) -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " removing virtual peer " << vpid << " for hash " << hash << std::endl; -#endif - mTurtle2GxsPeer.erase(vpid); - - auto it = mHandledHashes.find(hash) ; - - if(it == mHandledHashes.end()) - { - std::cerr << "RsGxsNetTunnelService::removeVirtualPeer(): error! hash " << hash << " is not handled. Cannot remove vpid " << vpid << std::endl; - return ; - } - - const RsGxsGroupId group_id(it->second) ; - - RsGxsNetTunnelGroupInfo& ginfo( mGroups[group_id] ) ; - - ginfo.virtual_peers.erase(vpid); - - if(ginfo.virtual_peers.empty()) - { - ginfo.group_status = RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_STATUS_IDLE ; - -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " no more virtual peers for group " << group_id << ": setting status to TUNNELS_REQUESTED" << std::endl; -#endif - } -} - -RsFileHash RsGxsNetTunnelService::calculateGroupHash(const RsGxsGroupId& group_id) const -{ - return RsDirUtil::sha1sum(group_id.toByteArray(),RsGxsGroupId::SIZE_IN_BYTES) ; -} - -void RsGxsNetTunnelService::generateEncryptionKey(const RsGxsGroupId& group_id,const TurtleVirtualPeerId& vpid,unsigned char key[RS_GXS_TUNNEL_CONST_EKEY_SIZE]) -{ - // The key is generated as H(group_id | vpid) - // Because group_id is not known it shouldn't be possible to recover the key by observing the traffic. - - assert(Sha256CheckSum::SIZE_IN_BYTES == 32) ; - - unsigned char mem[RsGxsGroupId::SIZE_IN_BYTES + TurtleVirtualPeerId::SIZE_IN_BYTES] ; - - memcpy(mem ,group_id.toByteArray(),RsGxsGroupId::SIZE_IN_BYTES) ; - memcpy(mem+RsGxsGroupId::SIZE_IN_BYTES,vpid.toByteArray() ,TurtleVirtualPeerId::SIZE_IN_BYTES) ; - - memcpy( key, RsDirUtil::sha256sum(mem,RsGxsGroupId::SIZE_IN_BYTES+TurtleVirtualPeerId::SIZE_IN_BYTES).toByteArray(), RS_GXS_TUNNEL_CONST_EKEY_SIZE ) ; -} - -//===========================================================================================================================================// -// Service parts // -//===========================================================================================================================================// - -void RsGxsNetTunnelService::threadTick() -{ - while(!mPendingTurtleItems.empty()) - { - auto& it(mPendingTurtleItems.front()); - - mTurtle->sendTurtleData(it.first,it.second) ; - mPendingTurtleItems.pop_front(); - } - - rstime_t now = time(NULL); - - // cleanup - - if(mLastAutoWash + 5 < now) - { - autowash(); - mLastAutoWash = now; - } - - if(mLastKeepAlive + 20 < now) - { - mLastKeepAlive = now ; - sendKeepAlivePackets() ; - } - -#ifdef DEBUG_RSGXSNETTUNNEL - if(mLastDump + 10 < now) - { - mLastDump = now; - dump(); - } -#endif - - for(uint32_t i=0;i<2;++i) - { - if(shouldStop()) - return; - rstime::rs_usleep(500*1000) ; // 1 sec - } -} - -const Bias20Bytes& RsGxsNetTunnelService::locked_randomBias() -{ - if(mRandomBias.isNull()) - { - mRandomBias = Bias20Bytes::random(); - IndicateConfigChanged(); - - std::cerr << "Initialized RsGxsNetTunnel random bias to " << RsUtil::BinToHex(mRandomBias.toByteArray(),mRandomBias.SIZE_IN_BYTES) << std::endl; - } - - return mRandomBias ; -} - -RsGxsNetTunnelVirtualPeerId RsGxsNetTunnelService::locked_makeVirtualPeerId(const RsGxsGroupId& group_id) -{ - assert(RsPeerId::SIZE_IN_BYTES <= Sha1CheckSum::SIZE_IN_BYTES) ;// so that we can build the virtual PeerId from a SHA1 sum. - - // We compute sha1( GroupId | mRandomBias ) and trunk it to 16 bytes in order to compute a RsPeerId - - Bias20Bytes rb(locked_randomBias()); - - unsigned char mem[group_id.SIZE_IN_BYTES + rb.SIZE_IN_BYTES]; - - memcpy(mem ,group_id.toByteArray(),group_id.SIZE_IN_BYTES) ; - memcpy(mem+group_id.SIZE_IN_BYTES,rb.toByteArray(),rb.SIZE_IN_BYTES) ; - - return RsGxsNetTunnelVirtualPeerId(RsDirUtil::sha1sum(mem,group_id.SIZE_IN_BYTES+rb.SIZE_IN_BYTES).toByteArray()); -} - - -void RsGxsNetTunnelService::sendKeepAlivePackets() -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " sending keep-alive packets. " << std::endl; -#endif - - // We send KA packets for each GXS virtual peer. The advantage is that unused tunnels will automatically die which eliminates duplicate tunnels - // automatically. We only send from the client side. - - for(auto it(mVirtualPeers.begin());it!=mVirtualPeers.end();++it) - { - RsGxsNetTunnelVirtualPeerId own_gxs_vpid = locked_makeVirtualPeerId(it->second.group_id) ; - -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " virtual peer " << it->first << " through tunnel " << it->second.turtle_virtual_peer_id << " for group " << it->second.group_id ; -#endif - - if(own_gxs_vpid < it->first) - { -#ifdef DEBUG_RSGXSNETTUNNEL - std::cerr << ": sent!" << std::endl; -#endif - RsGxsNetTunnelKeepAliveItem pitem ; - RsTemporaryMemory tmpmem( RsGxsNetTunnelSerializer().size(&pitem) ) ; - uint32_t len = tmpmem.size(); - - RsGxsNetTunnelSerializer().serialise(&pitem,tmpmem,&len); - - RsTurtleGenericDataItem *encrypted_turtle_item = NULL ; - - if(p3turtle::encryptData(tmpmem,len,it->second.encryption_master_key,encrypted_turtle_item)) - mPendingTurtleItems.push_back(std::make_pair(it->second.turtle_virtual_peer_id,encrypted_turtle_item)) ; - - it->second.last_contact = time(NULL) ; - } -#ifdef DEBUG_RSGXSNETTUNNEL - else - std::cerr << ": ignored!" << std::endl; -#endif - } -} - -void RsGxsNetTunnelService::autowash() -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " performing per-group consistency test." << std::endl; -#endif - for(auto it(mGroups.begin());it!=mGroups.end();++it) - { - RsGxsNetTunnelVirtualPeerId own_gxs_vpid = locked_makeVirtualPeerId(it->first) ; - RsGxsNetTunnelGroupInfo& ginfo(it->second) ; - bool should_monitor_tunnels = false ; - -#ifdef DEBUG_RSGXSNETTUNNEL - GXS_NET_TUNNEL_DEBUG() << " group " << it->first << ": " ; -#endif - // check whether the group already has GXS virtual peers with suppliers. If so, we can set the GRP policy as passive. - - if(ginfo.group_policy >= RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_POLICY_ACTIVE) - { - bool found = false ; - - // check wether one virtual peer provided by GXS has ID > own ID. In this case we leave the priority to it. - - for(auto it2(ginfo.virtual_peers.begin());!found && it2!=ginfo.virtual_peers.end();++it2) - { - auto it3 = mTurtle2GxsPeer.find(*it2) ; - - if( it3 != mTurtle2GxsPeer.end() && it3->second < own_gxs_vpid) - found = true ; - } - - if(found) - { -#ifdef DEBUG_RSGXSNETTUNNEL - std::cerr << " active, with client-side peers : "; -#endif - should_monitor_tunnels = false ; - ginfo.group_policy = RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_POLICY_ACTIVE ; - } - else - { - should_monitor_tunnels = true ; - ginfo.group_policy = RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_POLICY_REQUESTING ; -#ifdef DEBUG_RSGXSNETTUNNEL - std::cerr << " active, and no client-side peers available : " ; -#endif - } - } -#ifdef DEBUG_RSGXSNETTUNNEL - else - std::cerr << " passive : "; -#endif - - // We should also check whether the group is supplied using another tunnel. If so, no need to request tunnels. - // Otherwise the engine will keep requesting tunnels for all groups. -#warning CODE MISSING HERE - - if(should_monitor_tunnels) - { -#ifdef DEBUG_RSGXSNETTUNNEL - std::cerr << " requesting tunnels" << std::endl; -#endif - mTurtle->monitorTunnels(ginfo.hash,this,false) ; - } - else - { -#ifdef DEBUG_RSGXSNETTUNNEL - std::cerr << " dropping tunnels" << std::endl; -#endif - mTurtle->stopMonitoringTunnels(ginfo.hash); - } - } -} - -bool RsGxsNetTunnelService::saveList(bool& cleanup, std::list& save) -{ - RsGxsNetTunnelRandomBiasItem *it2 = new RsGxsNetTunnelRandomBiasItem() ; - - { - RS_STACK_MUTEX(mGxsNetTunnelMtx); - it2->mRandomBias = mRandomBias; - std::cerr << "Saving RsGxsNetTunnel random bias to disc" << std::endl; - } - - save.push_back(it2) ; - cleanup = true ; - - return true; -} - -bool RsGxsNetTunnelService::loadList(std::list &load) -{ - RsGxsNetTunnelRandomBiasItem *rbsi ; - - for(auto it(load.begin());it!=load.end();++it) - { - if((rbsi = dynamic_cast(*it))!=NULL) - { - RS_STACK_MUTEX(mGxsNetTunnelMtx); - mRandomBias = rbsi->mRandomBias; - - std::cerr << "Loaded RsGxsNetTunnel random bias from disc: " << RsUtil::BinToHex(mRandomBias.toByteArray(),mRandomBias.SIZE_IN_BYTES) << std::endl; - } - else - GXS_NET_TUNNEL_ERROR() << " unknown item in config file: type=" << std::hex << (*it)->PacketId() << std::dec << std::endl; - - delete *it; - } - - return true; -} - -RsSerialiser *RsGxsNetTunnelService::setupSerialiser() -{ - RsSerialiser *ser = new RsSerialiser ; - ser->addSerialType(new RsGxsNetTunnelSerializer) ; - - return ser ; -} - -//===========================================================================================================================================// -// Turtle Search system // -//===========================================================================================================================================// - -TurtleRequestId RsGxsNetTunnelService::turtleGroupRequest(const RsGxsGroupId& group_id,RsNetworkExchangeService *client_service) -{ - Sha1CheckSum hashed_group_id = RsDirUtil::sha1sum(group_id.toByteArray(),group_id.SIZE_IN_BYTES) ; - - GXS_NET_TUNNEL_DEBUG() << ": starting a turtle group request for grp \"" << group_id << "\" hashed to \"" << hashed_group_id << "\"" << std::endl; - - RsGxsNetTunnelTurtleSearchGroupRequestItem search_item ; - search_item.hashed_group_id = hashed_group_id ; - search_item.service = client_service->serviceType() ; - - uint32_t size = RsGxsNetTunnelSerializer().size(&search_item) ; - unsigned char *mem = (unsigned char*)rs_malloc(size) ; - - if(mem == NULL) - return 0 ; - - RsGxsNetTunnelSerializer().serialise(&search_item,mem,&size); - - return mTurtle->turtleSearch(mem,size,this) ; -} - -TurtleRequestId RsGxsNetTunnelService::turtleSearchRequest( - const std::string& match_string, - RsNetworkExchangeService* client_service ) -{ - GXS_NET_TUNNEL_DEBUG() << ": starting a turtle search request for string \"" << match_string << "\"" << std::endl; - - RsGxsNetTunnelTurtleSearchSubstringItem search_item ; - search_item.substring_match = match_string ; - search_item.service = client_service->serviceType() ; - - uint32_t size = RsGxsNetTunnelSerializer().size(&search_item) ; - uint8_t* mem = rs_malloc(size); - - if(mem == NULL) - return 0 ; - - RsGxsNetTunnelSerializer().serialise(&search_item,mem,&size); - - RS_STACK_MUTEX(mGxsNetTunnelMtx); - return mTurtle->turtleSearch(mem,size,this) ; -} - -std::error_condition RsGxsNetTunnelService::turtleSearchRequest( - rs_owner_ptr searchData, uint32_t dataSize, - RsServiceType serviceType, TurtleRequestId& requestId ) -{ - if(!searchData || !dataSize || serviceType == RsServiceType::NONE) - return std::errc::invalid_argument; - - RsGxsServiceTurtleSearchReqItem searchItem(serviceType); - searchItem.mSearchDataSize = dataSize; - searchItem.mSearchData = searchData; - - RsGxsNetTunnelSerializer tSerializer; - - uint32_t size = tSerializer.size(&searchItem); - uint8_t* buf = rs_malloc(size); - - tSerializer.serialise(&searchItem, buf, &size); - - requestId = mTurtle->turtleSearch(buf, size, this); - if(!requestId) return std::errc::result_out_of_range; - - return std::error_condition(); -} - -rs_view_ptr -RsGxsNetTunnelService::retrievieSearchableServiceLocking(uint16_t serviceType) -{ - RS_STACK_MUTEX(mGxsNetTunnelMtx); - auto it = mSearchableServices.find(serviceType); - if( it != mSearchableServices.end()) return it->second; - return nullptr; -} - -bool RsGxsNetTunnelService::receiveSearchRequest( - uint8_t* search_request_data, uint32_t search_request_data_len, - uint8_t*& search_result_data, uint32_t& search_result_data_size, - uint32_t& max_allowed_hits ) -{ - /* Must return true only if there are matching results available, false in - * all other cases. @see RsTurleClientService */ - - RS_DBG3(""); - - RsGxsNetTunnelSerializer tSerializer; - - std::unique_ptr item; - item.reset(tSerializer.deserialise( - search_request_data, &search_request_data_len )); - - if(!item) - { - RS_ERR( "Deserialization failed: ", - search_request_data, search_request_data_len, item.get() ); - print_stacktrace(); - return false; - } - - switch(static_cast(item->PacketSubType())) - { - case RsGxsNetTunnelItemSubtypes::SEARCH_SUBSTRING: - { - if(!search_result_data) - { - RS_ERR( "Got item with TURTLE_SEARCH_SUBSTRING without space for " - "results!" ); - print_stacktrace(); - break; - } - - auto substring_sr = - dynamic_cast(item.get()); - if(!substring_sr) - { - RS_WARN( "Got item with TURTLE_SEARCH_SUBSTRING subtype: ", - item->PacketSubType(), " but casting failed!"); - break; - } - - max_allowed_hits = RS_GXS_NET_TUNNEL_MAX_ALLOWED_HITS_GROUP_SEARCH; - std::list results; - auto tService = retrievieSearchableServiceLocking(substring_sr->service); - if(tService && tService->search(substring_sr->substring_match, results)) - { - RsGxsNetTunnelTurtleSearchGroupSummaryItem search_result_item; - search_result_item.service = substring_sr->service; - search_result_item.group_infos = results; - search_result_data_size = tSerializer.size(&search_result_item); - search_result_data = rs_malloc(search_result_data_size); - - tSerializer.serialise( - &search_result_item, search_result_data, - &search_result_data_size ); - - return true; - } - - break; - } - case RsGxsNetTunnelItemSubtypes::SEARCH_GROUP_REQUEST: - { - auto *substring_gr = - dynamic_cast(item.get()); - - if(!substring_gr) - { - RS_WARN( "Got item with TURTLE_SEARCH_GROUP_REQUEST subtype: ", - item->PacketSubType(), " but casting failed!" ); - break; - } - - max_allowed_hits = RS_GXS_NET_TUNNEL_MAX_ALLOWED_HITS_GROUP_DATA; - uint8_t* encrypted_group_data = nullptr; - uint32_t encrypted_group_data_len = 0; - - auto tService = retrievieSearchableServiceLocking(substring_gr->service); - if(tService && tService->search( - substring_gr->hashed_group_id, - encrypted_group_data, encrypted_group_data_len )) - { - RsGxsNetTunnelTurtleSearchGroupDataItem search_result_item; - search_result_item.service = substring_gr->service; - search_result_item.encrypted_group_data = encrypted_group_data; - search_result_item.encrypted_group_data_len = encrypted_group_data_len; - search_result_data_size = tSerializer.size(&search_result_item); - search_result_data = rs_malloc(search_result_data_size); - - tSerializer.serialise( - &search_result_item, - search_result_data, &search_result_data_size ); - return true; - } - break; - } - case RsGxsNetTunnelItemSubtypes::SERVICE_SEARCH_REQUEST: - { - RS_DBG3("SERVICE_SEARCH_REQUEST"); - - auto searchItem = - static_cast(item.get()); - - max_allowed_hits = RS_GXS_NET_TUNNEL_MAX_ALLOWED_HITS_GROUP_SEARCH; - - uint16_t sType = static_cast(searchItem->mServiceType); - auto sService = retrievieSearchableServiceLocking(sType); - if(!sService) - { - RS_WARN("Got search request for non searchable service: ", sType); - break; - } - - RsGxsServiceTurtleSearchReplyItem replyItem(searchItem->mServiceType); - - auto errc = sService->handleDistantSearchRequest( - searchItem->mSearchData, searchItem->mSearchDataSize, - replyItem.mReplyData, replyItem.mReplyDataSize ); - if(errc) - { - // Some error has been reported by the searchable service - RS_WARN("searchable service: ", sType , " reported: ", errc); - break; - } - - if( (!replyItem.mReplyData && replyItem.mReplyDataSize) || - (replyItem.mReplyData && !replyItem.mReplyDataSize) ) - { - // Inconsistent behaviour from searcheable service - RS_ERR( "searchable service: ", sType , " silently failed handling " - "inconsistent result mReplyData: ", replyItem.mReplyData, - " mReplyDataSize: ", replyItem.mReplyDataSize ); - break; - } - - /* Our node have 0 matching results */ - if(!replyItem.mReplyData && !replyItem.mReplyDataSize) - break; - - search_result_data_size = tSerializer.size(&replyItem); - search_result_data = rs_malloc(search_result_data_size); - - tSerializer.serialise( - &replyItem, search_result_data, &search_result_data_size ); - - return true; - } - default: - RS_WARN("Got unknown item type: ", item->PacketSubType()); - break; - } - - return false; -} - -void RsGxsNetTunnelService::receiveSearchResult( - TurtleSearchRequestId request_id, - uint8_t* search_result_data, uint32_t search_result_data_len ) -{ - RS_DBG3(request_id); - - std::unique_ptr item; - item.reset(RsGxsNetTunnelSerializer().deserialise( - search_result_data,&search_result_data_len )); - - auto castFailedWarn = [](const uint8_t subtype) - { - RS_WARN( "Got item with subtype: ", subtype, - " but cast failed!" ); - }; - - auto searchableServiceGet = [this](const auto pservice) - { - auto service = static_cast(pservice); - auto it = mSearchableServices.find(service); - if(it == mSearchableServices.end()) - { - RS_WARN( "got item for service ", service, - " which is not in the searchable services list." ); - return static_cast(nullptr); - } - - return it->second; - }; - - const auto tSubtype = item->PacketSubType(); - switch (static_cast(tSubtype)) - { - case RsGxsNetTunnelItemSubtypes::SEARCH_GROUP_SUMMARY: - { - auto result_gs = - dynamic_cast( - item.get() ); - - if(!result_gs) - { - castFailedWarn(tSubtype); - break; - } - - RS_DBG2( " got result is of type group summary result for service ", - result_gs->service ); - - auto service = searchableServiceGet(result_gs->service); - if(service) - service->receiveTurtleSearchResults( - request_id, result_gs->group_infos ); - return; - } - case RsGxsNetTunnelItemSubtypes::SEARCH_GROUP_DATA: - { - auto result_gd = - dynamic_cast(item.get()); - - if(!result_gd) - { - castFailedWarn(tSubtype); - break; - } - - RS_DBG2("got group data result for service: ", result_gd->service); - - auto service = searchableServiceGet(result_gd->service); - if(service) - service->receiveTurtleSearchResults( - request_id, - result_gd->encrypted_group_data, - result_gd->encrypted_group_data_len ); - - /* Ensure ownershipt is passed down preventing deletion */ - result_gd->encrypted_group_data = nullptr; - break; - } - case RsGxsNetTunnelItemSubtypes::SERVICE_SEARCH_REPLY: - { - auto searchReply = - static_cast(item.get()); - - auto service = searchableServiceGet(searchReply->mServiceType); - if(service) - service->receiveDistantSearchResult( - request_id, - searchReply->mReplyData, - searchReply->mReplyDataSize ); - - /* Ensure memory ownership is passed down preventing deletion */ - searchReply->mReplyData = nullptr; - break; - } - default: - RS_WARN("got item of unknown type: ", item->PacketSubType()); - break; - } -} - -void RsGxsNetTunnelService::getStatistics( - std::map& groups, - std::map& virtual_peers, - std::map& - turtle_vpid_to_net_tunnel_vpid, Bias20Bytes& bias ) const -{ - groups = mGroups ; - virtual_peers = mVirtualPeers ; - turtle_vpid_to_net_tunnel_vpid = mTurtle2GxsPeer; - bias = mRandomBias ; -} - - - - - - - - - - - - - - - - - - - - diff --git a/libretroshare/src/gxs/rsgxsnettunnel.h b/libretroshare/src/gxs/rsgxsnettunnel.h deleted file mode 100644 index c7f9ac1f3..000000000 --- a/libretroshare/src/gxs/rsgxsnettunnel.h +++ /dev/null @@ -1,298 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: gxsnettunnel.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2018 Cyril Soler * - * Copyright (C) 2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#pragma once - -#include -#include - -#include "turtle/p3turtle.h" -#include "retroshare/rsgxsdistsync.h" - -/*! - * \brief The RsGxsNetTunnelService class takes care of requesting tunnels to the turtle router, through which it is possible to sync - * a particular GXS group. For each group, a set of virtual peers, corresponding to active tunnels will be made available - * to RsGxsNetService. - * - * It is the responsibility of RsGxsNetService to activate/desactivate tunnels for each particular group, depending on wether the group - * is already available at regular friends or not. - * - * Tunnel management is done at the level of groups rather than services, because we would like to keep the possibility to not - * request tunnels for some groups which do not need it, and only request tunnels for specific groups that cannot be provided - * by direct connections. - */ - -// Protocol: -// * request tunnels based on H(GroupId) -// * encrypt tunnel data using chacha20+HMAC-SHA256 using AEAD( GroupId, 96bits IV, tunnel ID ) (similar to what FT does) -// * when tunnel is established, exchange virtual peer names: vpid = H( GroupID | Random bias ) -// * when vpid is known, notify the client (GXS net service) which can use the virtual peer to sync -// * only use a single tunnel per virtual peer ID -// - -// Client ------------------ TR(H(GroupId)) --------------> Server | -// | Turtle -// Client <-------------------- T OK ---------------------- Server | -// - -// Here, a turtle vpid is known | [ addVirtualPeer() called by turtle ] -// - -// [Encrypted traffic using H(GroupId | Tunnel ID, 96bits IV)] | -// | -// Client <--------- VPID = H( Random IV | GroupId ) ------ Server | -// | | | -// +--------------> Mark the virtual peer active <-----------+ | Encrypted traffic decoded locally and sorted -// | -// Here, a consistent virtual peer ID is known | -// | -// Client <------------------- GXS Data ------------------> Server | -// - -// Notes: -// * tunnels are established symmetrically. If a distant peers wants to sync the same group, they'll have to open a single tunnel, with a different ID. -// Groups therefore have two states: -// - managed : the group can be used to answer tunnel requests. If server tunnels are established, the group will be synced with these peers -// - tunneled: the group will actively request tunnels. If tunnels are established both ways, the same virtual peers will be used so the tunnels are "merged". -// * In practice, that means one of the two tunnels will not be used and therefore die. -// * If a tunneled group already has enough virtual peers, it will not request for tunnels itself. -// -// Group policy | Request tunnels | SyncWithPeers | Item receipt -// --------------------+-------------------+-----------------------+---------------- -// Passive | no | If peers present | If peers present -// Active | yes, if no peers | If peers present | If peers present -// | | | -// -// * when a service has the DistSync flag set, groups to sync are communicated passively to the GxsNetTunnel service when requesting distant peers. -// However, a call should be made to set a particular group policy to "ACTIVE" for group that do not have peers and need some. -// -// * services also need to retrieve GXS data items that come out of tunnels. These will be available as (data,len) type, since they are not de-serialized. -// -// * GxsNetService stores data information (such as update maps) per peerId, so it makes sense to use the same PeerId for all groups of a given service -// Therefore, virtual peers are stored separately from groups, because each one can sync multiple groups. -// -// * virtual peers are also shared among services. This reduces the required amount of tunnels and tunnel requests to send. -// -// * tunnels for a given service may also be used by the net service of p3IdService in order to explicitely request missing GxsIds. -// So GxsNetTunnel somehow allows different services to use the same tunnel. However we make sure that this traffic is limited to only p3IdService. -// -// How do we know that a group needs distant sync? -// * look into GrpConfigMap for suppliers. Suppliers is cleared at load. -// * last_update_TS in GrpConfigMap is randomised so it cannot be used -// * we need a way to know that there's no suppliers for good reasons (not that we just started) -// -// Security -// * the question of sync-ing with distant anonymous peers is a bit tricky because these peers can try to generate fake requests or change which messages are available -// and there is no way to prevent it. We therefore rely on GXS data integrity system to prevent this to happen. -// - -struct RsGxsNetTunnelItem; -class RsNetworkExchangeService ; - -class RsGxsNetTunnelService: - public RsTurtleClientService, public RsTickingThread, public p3Config, - public RsGxsDistSync -{ -public: - RsGxsNetTunnelService(); - ~RsGxsNetTunnelService() override; - - /*! - * \brief registerSearchableService - * Adds the network exchange service as a possible search source. This is used to allow distant search on the corresponding - * GXS service. - * \return - * always returns true. - */ - bool registerSearchableService(RsNetworkExchangeService *) ; - - /*! - * \brief Manage tunnels for this group - * @param group_id group for which tunnels should be released - */ - bool requestDistantPeers(uint16_t service_id,const RsGxsGroupId&group_id) ; - - /*! - * \brief Stop managing tunnels for this group - * @param group_id group for which tunnels should be released - */ - bool releaseDistantPeers(uint16_t service_id, const RsGxsGroupId&group_id) ; - - /*! - * \brief Get the list of active virtual peers for a given group. This implies that a tunnel is up and - * alive. This function also "registers" the group which allows to handle tunnel requests in the server side. - */ - bool getVirtualPeers(std::list& peers) ; // returns the virtual peers for this service - - /*! - * \brief serviceId - * Overloads the method in RsTurtleClientService. - * \return - * The service id for RsGxsNetTunnel. - */ - uint16_t serviceId() const ; - - /*! - * \brief sendData - * send data to this virtual peer, and takes memory ownership (deletes the item) - * \param item item to send - * \param virtual_peer destination virtual peer - * \return - * true if succeeded. - */ - bool sendTunnelData(uint16_t service_id,unsigned char *& data, uint32_t data_len, const RsGxsNetTunnelVirtualPeerId& virtual_peer) ; - - /*! - * \brief receiveData - * returns the next piece of data received, and the virtual GXS peer that sended it. - * \param data memory check containing the data. Memory ownership belongs to the client. - * \param data_len length of memory chunk - * \param virtual_peer peer who sent the data - * \return - * true if something is returned. If not, data is set to NULL, data_len to 0. - */ - bool receiveTunnelData(uint16_t service_id, unsigned char *& data, uint32_t& data_len, RsGxsNetTunnelVirtualPeerId& virtual_peer) ; - - /*! - * \brief isDistantPeer - * returns wether the peer is in the list of available distant peers or not - * \param group_id returned by the service to indicate which group this peer id is designed for. - * \return true if the peer is a distant GXS peer. - */ - - bool isDistantPeer(const RsGxsNetTunnelVirtualPeerId& virtual_peer,RsGxsGroupId& group_id) ; - - /*! - * \brief dumps all information about monitored groups. - */ - void dump() const; - - /*! - * Should be called after allocating a RsGxsNetTunnelService - * \param tr turtle router object - */ - void connectToTurtleRouter(p3turtle *tr) override; - - /** Gxs services (channels, forums...) are supposed to use this to request - * searches on distant peers */ - std::error_condition turtleSearchRequest( - rs_owner_ptr searchData, uint32_t dataSize, - RsServiceType serviceType, TurtleRequestId& requestId ); - - ///@see RsTurtleClientService - bool receiveSearchRequest( - unsigned char* search_request_data, - uint32_t search_request_data_len, - unsigned char*& search_result_data, - uint32_t& search_result_data_len, - uint32_t& max_allowed_hits ) override; - - ///@see RsTurtleClientService - virtual void receiveSearchResult( - TurtleSearchRequestId request_id, - unsigned char* search_result_data, - uint32_t search_result_data_len ) override; - - TurtleRequestId turtleGroupRequest( - const RsGxsGroupId& group_id, - RsNetworkExchangeService* client_service ); - - /// @see RsTickingThread - void threadTick() override; - - // Overloads p3Config - - RsSerialiser *setupSerialiser(); - bool saveList(bool& cleanup, std::list& save); - bool loadList(std::list &load); - - // Overloads RsGxsDistSync - - void getStatistics(std::map& groups, // groups on the client and server side - std::map& virtual_peers, // current virtual peers, which group they provide, and how to talk to them through turtle - std::map& turtle_vpid_to_net_tunnel_vpid, - Bias20Bytes& bias) const; - - RS_DEPRECATED - TurtleRequestId turtleSearchRequest( - const std::string& match_string, - RsNetworkExchangeService* client_service ); - -protected: - // interaction with turtle router - - virtual bool handleTunnelRequest(const RsFileHash &hash,const RsPeerId& peer_id) ; - virtual void receiveTurtleData(const RsTurtleGenericTunnelItem *item,const RsFileHash& hash,const RsPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction) ; - void addVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&,RsTurtleGenericTunnelItem::Direction dir) ; - void removeVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&) ; - const Bias20Bytes& locked_randomBias() ; - - p3turtle *mTurtle ; - - static const uint32_t RS_GXS_TUNNEL_CONST_RANDOM_BIAS_SIZE = 20 ; - static const uint32_t RS_GXS_TUNNEL_CONST_EKEY_SIZE = 32 ; - - mutable Bias20Bytes mRandomBias ; // constant accross reboots. Allows to disguise the real SSL id while providing a consistent value accross time. -private: - void autowash() ; - void sendKeepAlivePackets() ; - void handleIncoming(RsGxsNetTunnelItem *item) ; - void flush_pending_items(); - rs_view_ptr retrievieSearchableServiceLocking( - uint16_t serviceType ); - - std::map mGroups ; // groups on the client and server side - - std::map mVirtualPeers ; // current virtual peers, which group they provide, and how to talk to them through turtle - std::map mHandledHashes ; // hashes asked to turtle. Used to answer tunnel requests - std::map mTurtle2GxsPeer ; // convertion table to find GXS peer id from turtle - - std::list > mPendingTurtleItems ; // items that need to be sent off-turtle Mutex. - - std::map > > mIncomingData; // list of incoming data items - - std::map mSearchableServices ; - - /*! - * \brief Generates the hash to request tunnels for this group. This hash is only used by turtle, and is used to - * hide the real group id. - */ - - RsFileHash calculateGroupHash(const RsGxsGroupId&group_id) const ; - - /*! - * \brief makeVirtualPeerIdForGroup creates a virtual peer id that can be used and that will be constant accross time, whatever the - * tunnel ID and turtle virtual peer id. This allows RsGxsNetService to keep sync-ing the data consistently. - */ - - RsGxsNetTunnelVirtualPeerId locked_makeVirtualPeerId(const RsGxsGroupId& group_id) ; - - static void generateEncryptionKey(const RsGxsGroupId& group_id,const TurtleVirtualPeerId& vpid,unsigned char key[RS_GXS_TUNNEL_CONST_EKEY_SIZE]) ; - - mutable RsMutex mGxsNetTunnelMtx; - - friend class RsGxsTunnelRandomBiasItem ; - friend class StoreHere ; - - rstime_t mLastKeepAlive ; - rstime_t mLastAutoWash ; - rstime_t mLastDump ; -}; - diff --git a/libretroshare/src/gxs/rsgxsnetutils.cc b/libretroshare/src/gxs/rsgxsnetutils.cc deleted file mode 100644 index 6d759da7e..000000000 --- a/libretroshare/src/gxs/rsgxsnetutils.cc +++ /dev/null @@ -1,319 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsnetutils.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2013 by Christopher Evi-Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "rsgxsnetutils.h" -#include "pqi/p3servicecontrol.h" -#include "pgp/pgpauxutils.h" - - const rstime_t AuthorPending::EXPIRY_PERIOD_OFFSET = 30; // 30 seconds - const int AuthorPending::MSG_PEND = 1; - const int AuthorPending::GRP_PEND = 2; - -AuthorPending::AuthorPending(RsGixsReputation* rep, rstime_t timeStamp) : mRep(rep), mTimeStamp(timeStamp) {} - -AuthorPending::~AuthorPending() {} - -bool AuthorPending::expired() const -{ - return time(NULL) > (mTimeStamp + EXPIRY_PERIOD_OFFSET); -} - -bool AuthorPending::getAuthorRep(GixsReputation& rep, const RsGxsId& authorId, const RsPeerId& /*peerId*/) -{ - rep.id = authorId ; - rep.reputation_level = - static_cast(mRep->overallReputationLevel(authorId)); - -#warning csoler 2017-01-10: Can it happen that reputations do not have the info yet? - return true ; -#ifdef TO_BE_REMOVED - { - return mRep->getReputation(authorId, rep); - } - - std::list peers; - peers.push_back(peerId); - mRep->loadReputation(authorId, peers); - return false; -#endif -} - -MsgAuthEntry::MsgAuthEntry() - : mPassedVetting(false) {} - - -GrpAuthEntry::GrpAuthEntry() - : mPassedVetting(false) {} - - - -MsgRespPending::MsgRespPending(RsGixsReputation* rep, const RsPeerId& peerId, const MsgAuthorV& msgAuthV, int cutOff) - : AuthorPending(rep, time(NULL)), mPeerId(peerId), mMsgAuthV(msgAuthV), mCutOff(cutOff) -{ -} - -GrpRespPending::GrpRespPending(RsGixsReputation* rep, const RsPeerId& peerId, const GrpAuthorV& grpAuthV, int cutOff) - : AuthorPending(rep, time(NULL)), mPeerId(peerId), mGrpAuthV(grpAuthV), mCutOff(cutOff) -{ -} - -int MsgRespPending::getType() const -{ - return MSG_PEND; -} - -bool MsgRespPending::accepted() -{ - MsgAuthorV::iterator cit = mMsgAuthV.begin(); - MsgAuthorV::size_type count = 0; - for(; cit != mMsgAuthV.end(); ++cit) - { - MsgAuthEntry& entry = *cit; - - if(!entry.mPassedVetting) - { - GixsReputation rep; - if(getAuthorRep(rep, entry.mAuthorId, mPeerId)) - { - if(rep.reputation_level >= (uint32_t)mCutOff) - { - entry.mPassedVetting = true; - count++; - } - } - - }else - { - count++; - } - } - - return count == mMsgAuthV.size(); -} - -int GrpRespPending::getType() const -{ - return GRP_PEND; -} - -bool GrpRespPending::accepted() -{ - GrpAuthorV::iterator cit = mGrpAuthV.begin(); - GrpAuthorV::size_type count = 0; - for(; cit != mGrpAuthV.end(); ++cit) - { - GrpAuthEntry& entry = *cit; - - if(!entry.mPassedVetting) - { - GixsReputation rep; - - if(getAuthorRep(rep, entry.mAuthorId, mPeerId)) - { - if(rep.reputation_level >= (uint32_t)mCutOff) - { - entry.mPassedVetting = true; - count++; - } - } - - }else - { - count++; - } - } - - return count == mGrpAuthV.size(); -} - - - -/** NxsTransaction definition **/ - -const uint8_t NxsTransaction::FLAG_STATE_STARTING = 0x0001; // when -const uint8_t NxsTransaction::FLAG_STATE_RECEIVING = 0x0002; // begin receiving items for incoming trans -const uint8_t NxsTransaction::FLAG_STATE_SENDING = 0x0004; // begin sending items for outgoing trans -const uint8_t NxsTransaction::FLAG_STATE_FAILED = 0x0010; -const uint8_t NxsTransaction::FLAG_STATE_WAITING_CONFIRM = 0x0020; -const uint8_t NxsTransaction::FLAG_STATE_COMPLETED = 0x0080; // originaly 0x008, but probably a typo, but we cannot change it since it would break backward compatibility. - - -NxsTransaction::NxsTransaction() - : mFlag(0), mTimeOut(0), mTransaction(NULL) { - -} - -NxsTransaction::~NxsTransaction(){ - - std::list::iterator lit = mItems.begin(); - - for(; lit != mItems.end(); ++lit) - { - delete *lit; - *lit = NULL; - } - - if(mTransaction) - delete mTransaction; - - mTransaction = NULL; -} - - -/* Net Manager */ - -RsNxsNetMgrImpl::RsNxsNetMgrImpl(p3ServiceControl *sc) - : mServiceCtrl(sc) -{ - -} - - -const RsPeerId& RsNxsNetMgrImpl::getOwnId() -{ - return mServiceCtrl->getOwnId(); -} - -void RsNxsNetMgrImpl::getOnlineList(const uint32_t serviceId, std::set &ssl_peers) -{ - mServiceCtrl->getPeersConnected(serviceId, ssl_peers); -} - -const rstime_t GrpCircleVetting::EXPIRY_PERIOD_OFFSET = 5; // 10 seconds -const int GrpCircleVetting::GRP_ID_PEND = 1; -const int GrpCircleVetting::GRP_ITEM_PEND = 2; -const int GrpCircleVetting::MSG_ID_SEND_PEND = 3; -const int GrpCircleVetting::MSG_ID_RECV_PEND = 3; - - -GrpIdCircleVet::GrpIdCircleVet(const RsGxsGroupId& grpId, const RsGxsCircleId& circleId, const RsGxsId& authId) - : mGroupId(grpId), mCircleId(circleId), mAuthorId(authId), mCleared(false) {} - -GrpCircleVetting::GrpCircleVetting(RsGcxs* const circles, PgpAuxUtils *pgpUtils) - : mCircles(circles), mPgpUtils(pgpUtils), mTimeStamp(time(NULL)) {} - -GrpCircleVetting::~GrpCircleVetting() {} - -bool GrpCircleVetting::expired() -{ - return time(NULL) > (mTimeStamp + EXPIRY_PERIOD_OFFSET); -} -bool GrpCircleVetting::canSend( - const RsPeerId& peerId, const RsGxsCircleId& circleId, - bool& should_encrypt ) -{ - if(mCircles->isLoaded(circleId)) - { - const RsPgpId& pgpId = mPgpUtils->getPgpId(peerId); - return mCircles->canSend(circleId, pgpId,should_encrypt); - } - - mCircles->loadCircle(circleId); - - return false; -} - -GrpCircleIdRequestVetting::GrpCircleIdRequestVetting( - RsGcxs* const circles, - PgpAuxUtils *pgpUtils, - std::vector grpCircleV, const RsPeerId& peerId) - : GrpCircleVetting(circles, pgpUtils), mGrpCircleV(grpCircleV), mPeerId(peerId) {} - -bool GrpCircleIdRequestVetting::cleared() -{ - std::vector::size_type i, count=0; - for(i = 0; i < mGrpCircleV.size(); ++i) - { - GrpIdCircleVet& gic = mGrpCircleV[i]; - - if(!gic.mCleared) - { - if(canSend(mPeerId, gic.mCircleId,gic.mShouldEncrypt)) - { - gic.mCleared = true; - count++; - } - } - else - { - count++; - } - - } - - return count == mGrpCircleV.size(); -} - -int GrpCircleIdRequestVetting::getType() const -{ - return GRP_ID_PEND; -} - -MsgIdCircleVet::MsgIdCircleVet(const RsGxsMessageId& msgId, - const RsGxsId& authorId) - : mMsgId(msgId), mAuthorId(authorId) { -} - -MsgCircleIdsRequestVetting::MsgCircleIdsRequestVetting(RsGcxs* const circles, - PgpAuxUtils *pgpUtils, - std::vector msgs, const RsGxsGroupId& grpId, - const RsPeerId& peerId, const RsGxsCircleId& circleId) -: GrpCircleVetting(circles, pgpUtils), mMsgs(msgs), mGrpId(grpId), mPeerId(peerId), mCircleId(circleId) {} - -bool MsgCircleIdsRequestVetting::cleared() -{ - if(!mCircles->isLoaded(mCircleId)) - { - mCircles->loadCircle(mCircleId); - return false ; - } - - uint32_t filtered_out_msgs=0; - - for(uint32_t i=0;iisRecipient(mCircleId,mGrpId,mMsgs[i].mAuthorId)) - { - ++filtered_out_msgs; - mMsgs[i] = mMsgs[mMsgs.size()-1] ; - mMsgs.pop_back(); - } - else - ++i ; - - if(filtered_out_msgs>0) - std::cerr << "(WW) " << filtered_out_msgs << " messages not sent because they are signed by author(s) not member of that circle " << mCircleId << std::endl; - - RsPgpId pgpId = mPgpUtils->getPgpId(mPeerId); - bool can_send_res = mCircles->canSend(mCircleId, pgpId,mShouldEncrypt); - - if(mShouldEncrypt) // that means the circle is external - return true ; - else - return can_send_res ; -} - -int MsgCircleIdsRequestVetting::getType() const -{ - return MSG_ID_SEND_PEND; -} - - diff --git a/libretroshare/src/gxs/rsgxsnetutils.h b/libretroshare/src/gxs/rsgxsnetutils.h deleted file mode 100644 index 2ed229de0..000000000 --- a/libretroshare/src/gxs/rsgxsnetutils.h +++ /dev/null @@ -1,290 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsnetutils.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2013 by Christopher Evi-Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef RSGXSNETUTILS_H_ -#define RSGXSNETUTILS_H_ - -#include -#include "retroshare/rsgxsifacetypes.h" -#include "rsitems/rsnxsitems.h" -#include "rsgixs.h" - -class p3ServiceControl; -class PgpAuxUtils; - -/*! - * This represents a transaction made - * with the NxsNetService in all states - * of operation until completion - * - */ -class NxsTransaction -{ - -public: - - static const uint8_t FLAG_STATE_STARTING; // when - static const uint8_t FLAG_STATE_RECEIVING; // begin receiving items for incoming trans - static const uint8_t FLAG_STATE_SENDING; // begin sending items for outgoing trans - static const uint8_t FLAG_STATE_COMPLETED; - static const uint8_t FLAG_STATE_FAILED; - static const uint8_t FLAG_STATE_WAITING_CONFIRM; - - NxsTransaction(); - ~NxsTransaction(); - - uint32_t mFlag; // current state of transaction - uint32_t mTimeOut; - - /*! - * this contains who we - * c what peer this transaction involves. - * c The type of transaction - * c transaction id - * c timeout set for this transaction - * c and itemCount - */ - RsNxsTransacItem* mTransaction; - std::list mItems; // items received or sent -}; - -/*! - * An abstraction of the net manager - * for retrieving Rs peers whom you will be synchronising - * and also you own Id - * Useful for testing also (abstracts away Rs's p3NetMgr) - */ -class RsNxsNetMgr -{ - -public: - - virtual ~RsNxsNetMgr(){}; - virtual const RsPeerId& getOwnId() = 0; - virtual void getOnlineList(const uint32_t serviceId, std::set& ssl_peers) = 0; - -}; - -class RsNxsNetMgrImpl : public RsNxsNetMgr -{ - -public: - - RsNxsNetMgrImpl(p3ServiceControl* sc); - virtual ~RsNxsNetMgrImpl(){}; - - virtual const RsPeerId& getOwnId(); - virtual void getOnlineList(const uint32_t serviceId, std::set& ssl_peers); - -private: - - // No need for mutex as this is constant in the class. - p3ServiceControl* mServiceCtrl; - -}; - -/*! - * Partial abstract class - * which represents - * items waiting to be vetted - * on account of their author Id - */ -class AuthorPending -{ -public: - - static const int MSG_PEND; - static const int GRP_PEND; - static const rstime_t EXPIRY_PERIOD_OFFSET; - - AuthorPending(RsGixsReputation* rep, rstime_t timeStamp); - virtual ~AuthorPending(); - virtual int getType() const = 0 ; - - /*! - * @return true if all authors pass vetting and their messages - * should be requested - */ - virtual bool accepted() = 0; - - /*! - * @return true if message is past set expiry date - */ - bool expired() const; - -protected: - - /*! - * Convenience function to get author reputation - * @param rep reputation of author - * @param authorId reputation to get - * @return true if successfully retrieve repution - */ - bool getAuthorRep(GixsReputation& rep, const RsGxsId& authorId, const RsPeerId& peerId); - -private: - - RsGixsReputation* mRep; - rstime_t mTimeStamp; -}; - -class MsgAuthEntry -{ - -public: - - MsgAuthEntry(); - - RsGxsMessageId mMsgId; - RsGxsGroupId mGrpId; - RsGxsId mAuthorId; - bool mPassedVetting; - -}; - -class GrpAuthEntry -{ - -public: - - GrpAuthEntry(); - - RsGxsGroupId mGrpId; - RsGxsId mAuthorId; - bool mPassedVetting; -}; - -typedef std::vector MsgAuthorV; -typedef std::vector GrpAuthorV; - -class MsgRespPending : public AuthorPending -{ -public: - - MsgRespPending(RsGixsReputation* rep, const RsPeerId& peerId, const MsgAuthorV& msgAuthV, int cutOff = 0); - - int getType() const; - bool accepted(); - RsPeerId mPeerId; - MsgAuthorV mMsgAuthV; - int mCutOff; -}; - -class GrpRespPending : public AuthorPending -{ -public: - - GrpRespPending(RsGixsReputation* rep, const RsPeerId& peerId, const GrpAuthorV& grpAuthV, int cutOff = 0); - int getType() const; - bool accepted(); - RsPeerId mPeerId; - GrpAuthorV mGrpAuthV; - int mCutOff; -}; - - -/////////////// - -class GrpIdCircleVet -{ -public: - GrpIdCircleVet(const RsGxsGroupId& grpId, const RsGxsCircleId& circleId, const RsGxsId& authId); - RsGxsGroupId mGroupId; - RsGxsCircleId mCircleId; - RsGxsId mAuthorId; - - bool mCleared; - bool mShouldEncrypt; -}; - -class MsgIdCircleVet -{ -public: - MsgIdCircleVet(const RsGxsMessageId& grpId, const RsGxsId& authorId); - - RsGxsMessageId mMsgId; - RsGxsId mAuthorId; -}; - -class GrpItemCircleVet -{ -public: - RsNxsGrp* grpItem; - RsGxsCircleId mCircleId; - bool mCleared; -}; - -class GrpCircleVetting -{ -public: - - static const rstime_t EXPIRY_PERIOD_OFFSET; - static const int GRP_ID_PEND; - static const int GRP_ITEM_PEND; - static const int MSG_ID_SEND_PEND; - static const int MSG_ID_RECV_PEND; - - - GrpCircleVetting(RsGcxs* const circles, PgpAuxUtils *pgpUtils); - virtual ~GrpCircleVetting(); - bool expired(); - virtual int getType() const = 0; - virtual bool cleared() = 0; - -protected: - bool canSend(const RsPeerId& peerId, const RsGxsCircleId& circleId, bool& should_encrypt); - - RsGcxs* const mCircles; - PgpAuxUtils *mPgpUtils; - rstime_t mTimeStamp; -}; - -class GrpCircleIdRequestVetting : public GrpCircleVetting -{ -public: - GrpCircleIdRequestVetting(RsGcxs* const circles, - PgpAuxUtils *pgpUtils, - std::vector mGrpCircleV, const RsPeerId& peerId); - bool cleared(); - int getType() const; - std::vector mGrpCircleV; - RsPeerId mPeerId; -}; - -class MsgCircleIdsRequestVetting : public GrpCircleVetting -{ -public: - MsgCircleIdsRequestVetting(RsGcxs* const circles, - PgpAuxUtils *auxUtils, - std::vector msgs, const RsGxsGroupId& grpId, - const RsPeerId& peerId, const RsGxsCircleId& circleId); - bool cleared(); - int getType() const; - std::vector mMsgs; - RsGxsGroupId mGrpId; - RsPeerId mPeerId; - RsGxsCircleId mCircleId; - bool mShouldEncrypt; -}; - - -#endif /* RSGXSNETUTILS_H_ */ diff --git a/libretroshare/src/gxs/rsgxsnotify.h b/libretroshare/src/gxs/rsgxsnotify.h deleted file mode 100644 index 030d9f26f..000000000 --- a/libretroshare/src/gxs/rsgxsnotify.h +++ /dev/null @@ -1,109 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs/: rsgxsnotify.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2015 Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#pragma once - -/*! - * The aim of this class is to implement notifications internally to GXS, which are - * mostly used by RsGenExchange to send information to specific services. These services - * then interpret these changes and turn them into human-readable/processed service-specific changes. - */ - -#include "retroshare/rsids.h" - -class RsGxsNotify -{ -public: - RsGxsNotify(const RsGxsGroupId& gid): mGroupId(gid){} - virtual ~RsGxsNotify()=default; - - enum NotifyType - { - TYPE_UNKNOWN = 0x00, - TYPE_PUBLISHED = 0x01, - TYPE_RECEIVED_NEW = 0x02, - TYPE_PROCESSED = 0x03, - TYPE_RECEIVED_PUBLISHKEY = 0x04, - TYPE_RECEIVED_DISTANT_SEARCH_RESULTS = 0x05, - TYPE_STATISTICS_CHANGED = 0x06, - TYPE_UPDATED = 0x07, - TYPE_MESSAGE_DELETED = 0x08, - TYPE_GROUP_DELETED = 0x09, - TYPE_GROUP_SYNC_PARAMETERS_UPDATED = 0x0a, - }; - - virtual NotifyType getType() = 0; - - RsGxsGroupId mGroupId; // Group id of the group we're talking about. When the group is deleted, it's useful to know which group - // that was although there is no pointers to the actual group data anymore. -}; - -/*! - * Relevant to group changes - */ -class RsGxsGroupChange : public RsGxsNotify -{ -public: - RsGxsGroupChange(NotifyType type, const RsGxsGroupId& gid,bool metaChange) : RsGxsNotify(gid),mNewGroupItem(nullptr),mOldGroupItem(nullptr), mNotifyType(type), mMetaChange(metaChange) {} - virtual ~RsGxsGroupChange() override { delete mOldGroupItem; delete mNewGroupItem ; } - - NotifyType getType() override { return mNotifyType;} - bool metaChange() { return mMetaChange; } - - RsGxsGrpItem *mNewGroupItem; // Valid when a group has changed, or a new group is received. - RsGxsGrpItem *mOldGroupItem; // only valid when mNotifyType is TYPE_UPDATED - -protected: - NotifyType mNotifyType; - bool mMetaChange; -}; - -/*! - * Relevant to message changes - */ -class RsGxsMsgChange : public RsGxsNotify -{ -public: - RsGxsMsgChange(NotifyType type, const RsGxsGroupId& gid, const RsGxsMessageId& msg_id,bool metaChange) - : RsGxsNotify(gid), mMsgId(msg_id), mNewMsgItem(nullptr),NOTIFY_TYPE(type), mMetaChange(metaChange) {} - virtual ~RsGxsMsgChange() override { delete mNewMsgItem ; } - - RsGxsMessageId mMsgId; - RsGxsMsgItem *mNewMsgItem; - - NotifyType getType(){ return NOTIFY_TYPE;} - bool metaChange() { return mMetaChange; } -private: - const NotifyType NOTIFY_TYPE; - bool mMetaChange; -}; - -struct RsGxsMsgDeletedChange : RsGxsNotify -{ - RsGxsMsgDeletedChange( - const RsGxsGroupId& gid, const RsGxsMessageId& msgId): - RsGxsNotify(gid), messageId(msgId) {} - - NotifyType getType() override { return TYPE_MESSAGE_DELETED; } - - const RsGxsMessageId messageId; -}; diff --git a/libretroshare/src/gxs/rsgxsrequesttypes.cc b/libretroshare/src/gxs/rsgxsrequesttypes.cc deleted file mode 100644 index e10a4efc3..000000000 --- a/libretroshare/src/gxs/rsgxsrequesttypes.cc +++ /dev/null @@ -1,175 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsrequesttypes.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Christopher Evi-Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "rsgxsrequesttypes.h" -#include "util/rsstd.h" - -std::ostream& operator<<(std::ostream& o,const GxsRequest& g) -{ - return g.print(o); -} - - -std::ostream& GroupMetaReq::print(std::ostream& o) const -{ - o << "[Request type=GroupMeta groupIds (size=" << mGroupIds.size() << "): " ; - - if(!mGroupIds.empty()) - { - o << *mGroupIds.begin() ; - - if(mGroupIds.size() > 1) - o << " ..." ; - } - - o << "]" ; - - return o; -} -std::ostream& GroupIdReq::print(std::ostream& o) const -{ - return o << "[Request type=GroupIdReq" << "]" ; -} - -std::ostream& GroupSerializedDataReq::print(std::ostream& o) const -{ - return o << "[Request type=GroupSerializedData" << "]" ; -} - -std::ostream& GroupDataReq::print(std::ostream& o) const -{ - o << "[Request type=GroupDataReq groupIds (size=" << mGroupIds.size() << "): " ; - - if(!mGroupIds.empty()) - { - o << *mGroupIds.begin() ; - - if(mGroupIds.size() > 1) - o << " ..." ; - } - - o << "]" ; - - return o; -} - -std::ostream& MsgIdReq::print(std::ostream& o) const -{ - return o << "[Request type=MsgId" << "]" ; -} - -std::ostream& MsgMetaReq::print(std::ostream& o) const -{ - o << "[Request type=MsgMetaReq groups (size=" << mMsgIds.size() << "): " ; - - if(!mMsgIds.empty()) - { - o << mMsgIds.begin()->first << " (" << mMsgIds.begin()->second.size() << " messages)"; - - if(mMsgIds.size() > 1) - o << " ..." ; - } - - o << "]" ; - - return o; -} - -std::ostream& MsgDataReq::print(std::ostream& o) const -{ - o << "[Request type=MsgDataReq groups (size=" << mMsgIds.size() << "): " ; - - if(!mMsgIds.empty()) - { - o << mMsgIds.begin()->first << " (" << mMsgIds.begin()->second.size() << " messages)"; - - if(mMsgIds.size() > 1) - o << " ..." ; - } - - o << "]" ; - - return o; -} - -std::ostream& MsgRelatedInfoReq::print(std::ostream& o) const -{ - o << "[Request type=MsgRelatedInfo msgIds (size=" << mMsgIds.size() << "): " ; - - if(!mMsgIds.empty()) - { - o << mMsgIds.begin()->first ; - - if(mMsgIds.size() > 1) - o << " ..." ; - } - - o << "]" ; - - return o; -} - -std::ostream& GroupSetFlagReq::print(std::ostream& o) const -{ - return o << "[Request type=GroupFlagSet grpId=" << grpId << "]" ; -} - - - -std::ostream& ServiceStatisticRequest::print(std::ostream& o) const -{ - return o << "[Request type=ServiceStatistics" << "]" ; -} - -std::ostream& GroupStatisticRequest::print(std::ostream& o) const -{ - return o << "[Request type=GroupStatistics grpId=" << mGrpId << "]" ; -} - -GroupMetaReq::~GroupMetaReq() -{ - //rsstd::delete_all(mGroupMetaData.begin(), mGroupMetaData.end()); // now memory ownership is kept by the cache. - mGroupMetaData.clear(); -} - -GroupDataReq::~GroupDataReq() -{ - rsstd::delete_all(mGroupData.begin(), mGroupData.end()); -} - -MsgDataReq::~MsgDataReq() -{ - for (NxsMsgDataResult::iterator it = mMsgData.begin(); it != mMsgData.end(); ++it) { - rsstd::delete_all(it->second.begin(), it->second.end()); - } -} - -MsgRelatedInfoReq::~MsgRelatedInfoReq() -{ - for (NxsMsgRelatedDataResult::iterator dataIt = mMsgDataResult.begin(); dataIt != mMsgDataResult.end(); ++dataIt) - rsstd::delete_all(dataIt->second.begin(), dataIt->second.end()); -} -std::ostream& MessageSetFlagReq::print(std::ostream& o) const -{ - return o << "[Request type=MsgFlagSet" << "]" ; -} - diff --git a/libretroshare/src/gxs/rsgxsrequesttypes.h b/libretroshare/src/gxs/rsgxsrequesttypes.h deleted file mode 100644 index dd9ddb7cd..000000000 --- a/libretroshare/src/gxs/rsgxsrequesttypes.h +++ /dev/null @@ -1,176 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsrequesttypes.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Christopher Evi-Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RSGXSREQUESTTYPES_H_ -#define RSGXSREQUESTTYPES_H_ - -#include "retroshare/rstokenservice.h" -#include "gxs/rsgds.h" -#include "util/rsdeprecate.h" - -struct GxsRequest -{ - GxsRequest() : - token(0), reqTime(0), clientAnswerType(0), reqType(0), - status(RsTokenService::FAILED) {} - virtual ~GxsRequest() {} - - uint32_t token; - uint32_t reqTime; - - uint32_t clientAnswerType; /// This is made available to the clients in order to keep track of why specific requests where sent.. - uint32_t reqType; - RsTokReqOptions Options; - - RsTokenService::GxsRequestStatus status; - - virtual std::ostream& print(std::ostream& o) const = 0; -}; - -std::ostream& operator<<(std::ostream& o,const GxsRequest& g); - -class GroupMetaReq : public GxsRequest -{ -public: - virtual ~GroupMetaReq(); - - virtual std::ostream& print(std::ostream& o) const override; -public: - std::list mGroupIds; - std::list > mGroupMetaData; -}; - -class GroupIdReq : public GxsRequest -{ -public: - virtual std::ostream& print(std::ostream& o) const override ; - - std::list mGroupIds; - std::list mGroupIdResult; -}; -class GroupSerializedDataReq : public GxsRequest -{ -public: - virtual std::ostream& print(std::ostream& o) const override ; - - std::list mGroupIds; - std::list mGroupData; -}; - -class GroupDataReq : public GxsRequest -{ -public: - virtual ~GroupDataReq(); - - virtual std::ostream& print(std::ostream& o) const override; -public: - std::list mGroupIds; - std::list mGroupData; -}; - -class MsgIdReq : public GxsRequest -{ -public: - virtual std::ostream& print(std::ostream& o) const override ; - - GxsMsgReq mMsgIds; - GxsMsgIdResult mMsgIdResult; -}; - -class MsgMetaReq : public GxsRequest -{ -public: - virtual ~MsgMetaReq() = default; - - virtual std::ostream& print(std::ostream& o) const override; - -public: - GxsMsgReq mMsgIds; - GxsMsgMetaResult mMsgMetaData; -}; - -class MsgDataReq : public GxsRequest -{ -public: - virtual ~MsgDataReq(); - - virtual std::ostream& print(std::ostream& o) const override; -public: - GxsMsgReq mMsgIds; - NxsMsgDataResult mMsgData; -}; - -class ServiceStatisticRequest: public GxsRequest -{ -public: - virtual std::ostream& print(std::ostream& o) const override ; - GxsServiceStatistic mServiceStatistic; -}; - -struct GroupStatisticRequest: public GxsRequest -{ -public: - virtual std::ostream& print(std::ostream& o) const override ; - - RsGxsGroupId mGrpId; - GxsGroupStatistic mGroupStatistic; -}; - -class MsgRelatedInfoReq : public GxsRequest -{ -public: - virtual ~MsgRelatedInfoReq(); - - std::ostream& print(std::ostream& o) const override; -public: - std::vector mMsgIds; - MsgRelatedIdResult mMsgIdResult; - MsgRelatedMetaResult mMsgMetaResult; - NxsMsgRelatedDataResult mMsgDataResult; -}; - -class GroupSetFlagReq : public GxsRequest -{ -public: - virtual std::ostream& print(std::ostream& o) const override ; - - const static uint32_t FLAG_SUBSCRIBE; - const static uint32_t FLAG_STATUS; - - uint8_t type; - uint32_t flag; - uint32_t flagMask; - RsGxsGroupId grpId; -}; - -class MessageSetFlagReq : public GxsRequest -{ -public: - const static uint32_t FLAG_STATUS; - - virtual std::ostream& print(std::ostream& o) const override ; - uint8_t type; - uint32_t flag; - uint32_t flagMask; - RsGxsGrpMsgIdPair msgId; -}; - -#endif /* RSGXSREQUESTTYPES_H_ */ diff --git a/libretroshare/src/gxs/rsgxsutil.cc b/libretroshare/src/gxs/rsgxsutil.cc deleted file mode 100644 index 16e30c3b3..000000000 --- a/libretroshare/src/gxs/rsgxsutil.cc +++ /dev/null @@ -1,463 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsutil.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2013 Christopher Evi-Parker * - * Copyright (C) 2018-2021 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "util/rstime.h" - -#include "rsgxsutil.h" -#include "retroshare/rsgxsflags.h" -#include "retroshare/rspeers.h" -#include "pqi/pqihash.h" -#include "gxs/rsgixs.h" - -// The goals of this set of methods is to check GXS messages and groups for consistency, mostly -// re-ferifying signatures and hashes, to make sure that the data hasn't been tempered. This shouldn't -// happen anyway, but we still conduct these test as an extra safety measure. - -static const uint32_t MAX_GXS_IDS_REQUESTS_NET = 10 ; // max number of requests from cache/net (avoids killing the system!) - -// #define DEBUG_GXSUTIL 1 - -#ifdef DEBUG_GXSUTIL -#define GXSUTIL_DEBUG() std::cerr << "[" << time(NULL) << "] : GXS_UTIL : " << __FUNCTION__ << " : " -#endif - -RsGxsCleanUp::RsGxsCleanUp(RsGeneralDataService* const dataService, RsGenExchange *genex, uint32_t chunkSize) -: mDs(dataService), mGenExchangeClient(genex), CHUNK_SIZE(chunkSize) -{ -} - -bool RsGxsCleanUp::clean(RsGxsGroupId& next_group_to_check,std::vector& grps_to_delete,GxsMsgReq& messages_to_delete) -{ - RsGxsGrpMetaTemporaryMap grpMetaMap; - mDs->retrieveGxsGrpMetaData(grpMetaMap); - - rstime_t now = time(NULL); - -#ifdef DEBUG_GXSUTIL - uint16_t service_type = mGenExchangeClient->serviceType() ; - GXSUTIL_DEBUG() << " Cleaning up groups in service " << std::hex << service_type << std::dec << " starting at group " << next_group_to_check << std::endl; -#endif - // This method stores/takes the next group to check. This allows to limit group checking to a small part of the total groups - // in the situation where it takes too much time. So when arriving here, we must start again from where we left last time. - - if(grpMetaMap.empty()) // nothing to do. - { - next_group_to_check.clear(); - return true; - } - - auto it = next_group_to_check.isNull()?grpMetaMap.begin() : grpMetaMap.find(next_group_to_check); - - if(it == grpMetaMap.end()) // group wasn't found - it = grpMetaMap.begin(); - - bool full_round = false; // did we have the time to test all groups? - next_group_to_check = it->first; // covers the case where next_group_to_check is null or not found - - while(true) // check all groups, starting from the one indicated as parameter - { - const RsGxsGrpMetaData& grpMeta = *(it->second); - - // first check if we keep the group or not - - if(!mGenExchangeClient->service_checkIfGroupIsStillUsed(grpMeta)) - { -#ifdef DEBUG_GXSUTIL - std::cerr << " Scheduling group " << grpMeta.mGroupId << " for removal." << std::endl; -#endif - grps_to_delete.push_back(grpMeta.mGroupId); - } - else - { - const RsGxsGroupId& grpId = grpMeta.mGroupId; - GxsMsgReq req; - GxsMsgMetaResult result; - - req[grpId] = std::set(); - mDs->retrieveGxsMsgMetaData(req, result); - - GxsMsgMetaResult::iterator mit = result.begin(); - -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << " Cleaning up group message for group ID " << grpId << std::endl; -#endif - uint32_t store_period = mGenExchangeClient->getStoragePeriod(grpId) ; - - for(; mit != result.end(); ++mit) - { - auto& metaV = mit->second; - - // First, make a map of which message have a child message. This allows to only delete messages that dont have child messages. - // A more accurate way to go would be to compute the time of the oldest message and possibly delete all the branch, but in the - // end the message tree will be deleted slice after slice, which should still be reasonnably fast. - // - std::set messages_with_kids ; - - for( uint32_t i=0;imParentId.isNull()) - messages_with_kids.insert(metaV[i]->mParentId) ; - - for( uint32_t i=0;imMsgId)!=messages_with_kids.end()); - - // check if expired - bool remove = store_period > 0 && ((meta->mPublishTs + store_period) < now) && !have_kids; - - // check client does not want the message kept regardless of age - remove &= !(meta->mMsgStatus & GXS_SERV::GXS_MSG_STATUS_KEEP_FOREVER); - - // if not subscribed remove messages (can optimise this really) - remove = remove || (grpMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_NOT_SUBSCRIBED); - remove = remove || !(grpMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED); - -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << " msg id " << meta->mMsgId << " in grp " << grpId << ": keep_flag=" << bool(meta->mMsgStatus & GXS_SERV::GXS_MSG_STATUS_KEEP_FOREVER) - << " subscribed: " << bool(grpMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) << " store_period: " << store_period - << " kids: " << have_kids << " now - meta->mPublishTs: " << now - meta->mPublishTs ; -#endif - - if( remove ) - { - messages_to_delete[grpId].insert(meta->mMsgId); -#ifdef DEBUG_GXSUTIL - std::cerr << " Scheduling for removal." << std::endl; -#endif - } -#ifdef DEBUG_GXSUTIL - else - std::cerr << std::endl; -#endif - //delete meta; - } - } - } - - ++it; - - if(it == grpMetaMap.end()) - it = grpMetaMap.begin(); - - // check if we looped already - - if(it->first == next_group_to_check) - { -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << "Had the time to test all groups. Will start again at " << it->first << std::endl; -#endif - full_round = true; - break; - } - - // now check if we spent too much time on this already - - rstime_t tm = time(nullptr); - - //if(tm > now + 1) // we spent more than 1 sec on the job already - if(tm > now) // we spent more than 1 sec on the job already - { -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << "Aborting cleanup because it took too much time already. Next group left to be " << it->first << std::endl; -#endif - next_group_to_check = it->first; - full_round = false; - break; - } - } - - return full_round; -} - -RsGxsIntegrityCheck::RsGxsIntegrityCheck( - RsGeneralDataService* const dataService, RsGenExchange* genex, - RsSerialType&, RsGixs* gixs ) - : mDs(dataService), mGenExchangeClient(genex), - mDone(false), mIntegrityMutex("integrity"), mGixs(gixs) {} - -void RsGxsIntegrityCheck::run() -{ - std::vector grps_to_delete; - GxsMsgReq msgs_to_delete; - - check(mGenExchangeClient->serviceType(), mGixs, mDs); - - RS_STACK_MUTEX(mIntegrityMutex); - mDone = true; -} - -bool RsGxsIntegrityCheck::check(uint16_t service_type, RsGixs *mgixs, RsGeneralDataService *mds) -{ -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << "Parsing all groups and messages MetaData in service " << std::hex << mds->serviceType() << std::endl; -#endif - // first take out all the groups - std::map > grp; - - mds->retrieveGxsGrpMetaData(grp); - - GxsMsgReq msgIds; - - std::map used_gxs_ids ; - std::set subscribed_groups ; - - // Check that message ids... - - for( auto git = grp.begin(); git != grp.end(); ++git ) - { - const auto& grpMeta = git->second; - - if (mds->retrieveMsgIds(grpMeta->mGroupId, msgIds[grpMeta->mGroupId]) == 1) - { - if(grpMeta->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) - { - subscribed_groups.insert(git->first); - - if(!grpMeta->mAuthorId.isNull()) - { -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << "TimeStamping group authors' key ID " << grpMeta->mAuthorId << " in group ID " << grpMeta->mGroupId << std::endl; -#endif - if( rsReputations && rsReputations->overallReputationLevel( grpMeta->mAuthorId ) > RsReputationLevel::LOCALLY_NEGATIVE ) - used_gxs_ids.insert(std::make_pair(grpMeta->mAuthorId, RsIdentityUsage(RsServiceType(service_type), RsIdentityUsage::GROUP_AUTHOR_KEEP_ALIVE,grpMeta->mGroupId))); - } - } - } - else - msgIds.erase(msgIds.find(grpMeta->mGroupId)); // could not get them, so group is removed from list. - } - - // now messages - GxsMsgMetaResult msgMetas; - - mds->retrieveGxsMsgMetaData(msgIds, msgMetas); - - for(auto mit=msgMetas.begin(); mit != msgMetas.end(); ++mit) - { - const auto& msgM = mit->second; - - for(auto vit=msgM.begin(); vit != msgM.end(); ++vit) - { - const auto& meta = *vit; - - if (subscribed_groups.count(meta->mGroupId)) - if(!meta->mAuthorId.isNull()) - { -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << "TimeStamping message authors' key ID " << meta->mAuthorId << " in message " << meta->mMsgId << ", group ID " << meta->mGroupId<< std::endl; -#endif - if( rsReputations && rsReputations->overallReputationLevel( meta->mAuthorId ) > RsReputationLevel::LOCALLY_NEGATIVE ) - used_gxs_ids.insert(std::make_pair(meta->mAuthorId,RsIdentityUsage(RsServiceType(service_type), - RsIdentityUsage::MESSAGE_AUTHOR_KEEP_ALIVE, - meta->mGroupId, - meta->mMsgId, - meta->mParentId, - meta->mThreadId))) ; - } - } - } - - { -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << "At end of pass, this is the list used GXS ids: " << std::endl; - GXSUTIL_DEBUG() << " requesting them to GXS identity service to enforce loading." << std::endl; -#endif - - std::list connected_friends ; - rsPeers->getOnlineList(connected_friends) ; - - std::vector > gxs_ids ; - - for(std::map::const_iterator it(used_gxs_ids.begin());it!=used_gxs_ids.end();++it) - { - gxs_ids.push_back(*it) ; -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << " " << it->first << std::endl; -#endif - } - uint32_t nb_requested_not_in_cache = 0; - -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << " issuing random get on friends for non existing IDs" << std::endl; -#endif - - // now request a cache update for them, which triggers downloading from friends, if missing. - - for(;nb_requested_not_in_cachehaveKey(gxs_ids[n].first)) // checks if we have it already in the cache (conservative way to ensure that we atually have it) - { - mgixs->requestKey(gxs_ids[n].first,connected_friends,gxs_ids[n].second); - - ++nb_requested_not_in_cache ; -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << " ... from cache/net" << std::endl; -#endif - } - else - { -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << " ... already in cache" << std::endl; -#endif - } - mgixs->timeStampKey(gxs_ids[n].first,gxs_ids[n].second); - - gxs_ids[n] = gxs_ids[gxs_ids.size()-1] ; - gxs_ids.pop_back() ; - } -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << " total actual cache requests: "<< nb_requested_not_in_cache << std::endl; -#endif - } - - return true; -} - -bool RsGxsSinglePassIntegrityCheck::check( - uint16_t /*service_type*/, RsGixs* /*mgixs*/, RsGeneralDataService* mds, - std::vector& grpsToDel, GxsMsgReq& msgsToDel ) -{ -#ifdef DEBUG_GXSUTIL - GXSUTIL_DEBUG() << "Parsing all groups and messages data in service " << std::hex << mds->serviceType() << " for integrity check. Could take a while..." << std::endl; -#endif - - // first take out all the groups - std::map grp; - mds->retrieveNxsGrps(grp, true); - GxsMsgReq msgIds; - GxsMsgReq grps; - - std::map used_gxs_ids ; - std::set subscribed_groups ; - - // compute hash and compare to stored value, if it fails then simply add it - // to list - for( std::map::iterator git = grp.begin(); git != grp.end(); ++git ) - { - RsNxsGrp* grp = git->second; - RsFileHash currHash; - pqihash pHash; - pHash.addData(grp->grp.bin_data, grp->grp.bin_len); - pHash.Complete(currHash); - - if(currHash == grp->metaData->mHash) - { - // Get all message ids of group, store them in msgIds, creating the grp entry at the same time. - - if (mds->retrieveMsgIds(grp->grpId, msgIds[grp->grpId]) == 1) - { - // store the group for retrieveNxsMsgs - grps[grp->grpId]; - - if(grp->metaData->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) - subscribed_groups.insert(git->first); - } - else - msgIds.erase(msgIds.find(grp->grpId)); // could not get them, so group is removed from list. - } - else - { - RS_WARN( "deleting group ", grp->grpId, - " with wrong hash or null/corrupted meta data. meta=", - grp->metaData ); - grpsToDel.push_back(grp->grpId); - } - - delete grp; - } - - // now messages - GxsMsgResult msgs; - - mds->retrieveNxsMsgs(grps, msgs, true); - - // Check msg ids and messages. Go through all message IDs referred to by the db call - // and verify that the message belongs to the nxs msg data that was just retrieved. - - for(auto& msgIdsIt:msgIds) - { - const RsGxsGroupId& grpId = msgIdsIt.first; - std::set& msgIdV = msgIdsIt.second; - - std::set nxsMsgS; - std::vector& nxsMsgV = msgs[grpId]; - - // To make the search efficient, we first build a set of msgIds to search in. - // Set build and search are both O(n log(n)). - - for(auto& nxsMsg:nxsMsgV) - if(nxsMsg) - nxsMsgS.insert(nxsMsg->msgId); - - for (auto& msgId:msgIdV) - if(nxsMsgS.find(msgId) == nxsMsgS.end()) - msgsToDel[grpId].insert(msgId); - } - - for(auto mit = msgs.begin(); mit != msgs.end(); ++mit) - { - std::vector& msgV = mit->second; - std::vector::iterator vit = msgV.begin(); - - for(; vit != msgV.end(); ++vit) - { - RsNxsMsg* msg = *vit; - RsFileHash currHash; - pqihash pHash; - pHash.addData(msg->msg.bin_data, msg->msg.bin_len); - pHash.Complete(currHash); - - if(msg->metaData == NULL || currHash != msg->metaData->mHash) - { - RS_WARN( "deleting message ", msg->msgId, " in group ", - msg->grpId, - " with wrong hash or null/corrupted meta data. meta=", - static_cast(msg->metaData) ); - msgsToDel[msg->grpId].insert(msg->msgId); - } - - delete msg; - } - } - - return true; -} -bool RsGxsIntegrityCheck::isDone() -{ - RS_STACK_MUTEX(mIntegrityMutex); - return mDone; -} - -void RsGxsIntegrityCheck::getDeletedIds(std::vector& grpIds, GxsMsgReq& msgIds) -{ - RS_STACK_MUTEX(mIntegrityMutex); - grpIds = mDeletedGrps; - msgIds = mDeletedMsgs; -} - diff --git a/libretroshare/src/gxs/rsgxsutil.h b/libretroshare/src/gxs/rsgxsutil.h deleted file mode 100644 index 21fd6bb06..000000000 --- a/libretroshare/src/gxs/rsgxsutil.h +++ /dev/null @@ -1,238 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsutil.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2013 Christopher Evi-Parker * - * Copyright (C) 2018-2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#pragma once - -#include -#include "rsitems/rsnxsitems.h" -#include "rsgds.h" - -class RsGixs ; -class RsGenExchange ; -class RsGeneralDataService ; - -// temporary holds a map of pointers to class T, and destroys all pointers on delete. - -class non_copiable -{ -public: - non_copiable() {} -private: - non_copiable& operator=(const non_copiable&) { return *this ;} - non_copiable(const non_copiable&) {} -}; - -template -class t_RsGxsGenericDataTemporaryMap: public std::map, public non_copiable -{ -public: - virtual ~t_RsGxsGenericDataTemporaryMap() - { - clear() ; - } - - virtual void clear() - { - for(typename t_RsGxsGenericDataTemporaryMap::iterator it = this->begin();it!=this->end();++it) - if(it->second != NULL) - delete it->second ; - - std::map::clear() ; - } -}; - -template -class t_RsGxsGenericDataTemporaryMapVector: public std::map >, public non_copiable -{ -public: - virtual ~t_RsGxsGenericDataTemporaryMapVector() - { - clear() ; - } - - virtual void clear() - { - for(typename t_RsGxsGenericDataTemporaryMapVector::iterator it = this->begin();it!=this->end();++it) - { - for(uint32_t i=0;isecond.size();++i) - delete it->second[i] ; - - it->second.clear(); - } - - std::map >::clear() ; - } -}; - -template -class t_RsGxsGenericDataTemporaryList: public std::list, public non_copiable -{ -public: - virtual ~t_RsGxsGenericDataTemporaryList() - { - clear() ; - } - - virtual void clear() - { - for(typename t_RsGxsGenericDataTemporaryList::iterator it = this->begin();it!=this->end();++it) - delete *it; - - std::list::clear() ; - } -}; - -typedef std::map > RsGxsGrpMetaTemporaryMap; // This map doesn't need to delete elements since it holds -typedef std::map > > RsGxsMsgMetaTemporaryMap; // shared_ptr's. - -typedef t_RsGxsGenericDataTemporaryMap RsNxsGrpDataTemporaryMap; -typedef t_RsGxsGenericDataTemporaryMapVector RsNxsMsgDataTemporaryMap ; - -typedef t_RsGxsGenericDataTemporaryList RsNxsGrpDataTemporaryList ; -typedef t_RsGxsGenericDataTemporaryList RsNxsMsgDataTemporaryList ; - -inline RsGxsGrpMsgIdPair getMsgIdPair(RsNxsMsg& msg) -{ - return RsGxsGrpMsgIdPair(std::make_pair(msg.grpId, msg.msgId)); -} - -inline RsGxsGrpMsgIdPair getMsgIdPair(RsGxsMsgItem& msg) -{ - return RsGxsGrpMsgIdPair(std::make_pair(msg.meta.mGroupId, msg.meta.mMsgId)); -} - -/*! - * Does message clean up based on individual group expirations first - * if avialable. If not then deletion s - */ -class RsGxsCleanUp -{ -public: - - /*! - * - * @param dataService - * @param mGroupTS - * @param chunkSize - * @param sleepPeriod - */ - RsGxsCleanUp(RsGeneralDataService* const dataService, RsGenExchange *genex, uint32_t chunkSize); - - /*! - * On construction this should be called to progress deletions - * Deletion will process by chunk size - * @return true if no more messages to delete, false otherwise - */ - bool clean(RsGxsGroupId& next_group_to_check,std::vector& grps_to_delete,GxsMsgReq& messages_to_delete); - -private: - - RsGeneralDataService* const mDs; - RsGenExchange *mGenExchangeClient; - uint32_t CHUNK_SIZE; -}; - -/*! - * Checks the integrity message and groups - * in rsDataService using computed hash - */ -class RsGxsIntegrityCheck : public RsThread -{ - - enum CheckState { CheckStart, CheckChecking }; - -public: - RsGxsIntegrityCheck( RsGeneralDataService* const dataService, - RsGenExchange* genex, RsSerialType&, - RsGixs* gixs ); - - static bool check(uint16_t service_type, RsGixs *mgixs, RsGeneralDataService *mds); - bool isDone(); - - void run(); - - void getDeletedIds(std::vector &grpIds, GxsMsgReq &msgIds); - -private: - - RsGeneralDataService* const mDs; - RsGenExchange *mGenExchangeClient; - bool mDone; - RsMutex mIntegrityMutex; - std::vector mDeletedGrps; - GxsMsgReq mDeletedMsgs; - - RsGixs* mGixs; -}; - -/*! - * Checks the integrity message and groups - * in rsDataService using computed hash - */ -class RsGxsSinglePassIntegrityCheck -{ -public: - static bool check( - uint16_t service_type, RsGixs* mgixs, RsGeneralDataService* mds, - std::vector& grpsToDel, GxsMsgReq& msgsToDel ); -}; - -class GroupUpdate -{ -public: - GroupUpdate() : oldGrpMeta(NULL), newGrp(NULL), validUpdate(false) - {} - const RsGxsGrpMetaData* oldGrpMeta; - RsNxsGrp* newGrp; - bool validUpdate; -}; - -class GroupUpdatePublish -{ -public: - GroupUpdatePublish(RsGxsGrpItem* item, uint32_t token) - : grpItem(item), mToken(token) {} - RsGxsGrpItem* grpItem; - uint32_t mToken; -}; - -class GroupDeletePublish -{ -public: - GroupDeletePublish(const RsGxsGroupId& grpId, uint32_t token) - : mGroupId(grpId), mToken(token) {} - RsGxsGroupId mGroupId; - uint32_t mToken; -}; - - -class MsgDeletePublish -{ -public: - MsgDeletePublish(const GxsMsgReq& msgs, uint32_t token) - : mMsgs(msgs), mToken(token) {} - - GxsMsgReq mMsgs ; - uint32_t mToken; -}; diff --git a/libretroshare/src/gxs/rsnxs.h b/libretroshare/src/gxs/rsnxs.h deleted file mode 100644 index 2197d0e7a..000000000 --- a/libretroshare/src/gxs/rsnxs.h +++ /dev/null @@ -1,344 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsnxs.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2011 Robert Fernie * - * Copyright (C) 2011 Christopher Evi-Parker * - * Copyright (C) 2019-2021 Gioacchino Mazzurco * - * Copyright (C) 2019-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include -#include - -#include "util/rstime.h" -#include "services/p3service.h" -#include "retroshare/rsreputations.h" -#include "retroshare/rsidentity.h" -#include "retroshare/rsturtle.h" -#include "rsgds.h" - -/*! - * Retroshare General Network Exchange Service: \n - * Interface: - * - This provides a module to service peer's requests for GXS messages \n - * and also request GXS messages from other peers. \n - * - The general mode of operation is to sychronise all messages/grps between - * peers - * - * The interface is sparse as this service is mostly making the requests to other GXS components - * - * Groups: - * - As this is where exchanges occur between peers, this is also where group's relationships - * should get resolved as far as - * - Per implemented GXS there are a set of rules which will determine whether data is transferred - * between any set of groups - * - * 1 allow transfers to any group - * 2 transfers only between group - * - the also group matrix settings which is by default everyone can transfer to each other - */ - -class RsNetworkExchangeService -{ -public: - RsNetworkExchangeService() = default; - virtual ~RsNetworkExchangeService() = default; - - virtual uint16_t serviceType() const =0; - /*! - * Use this to set how far back synchronisation of messages should take place - * @param age in seconds the max age a sync/store item can to be allowed in a synchronisation - */ - virtual void setSyncAge(const RsGxsGroupId& id,uint32_t age_in_secs) =0; - virtual void setKeepAge(const RsGxsGroupId& id,uint32_t age_in_secs) =0; - - virtual uint32_t getSyncAge(const RsGxsGroupId& id) =0; - virtual uint32_t getKeepAge(const RsGxsGroupId& id) =0; - - virtual void setDefaultKeepAge(uint32_t t) =0; - virtual void setDefaultSyncAge(uint32_t t) =0; - - virtual uint32_t getDefaultSyncAge() =0; - virtual uint32_t getDefaultKeepAge() =0; - - virtual bool msgAutoSync() const =0; - virtual bool grpAutoSync() const =0; - - //////////////////////////////////////////////////////////////////////////// - /// DISTANT SEARCH FUNCTIONS /// - //////////////////////////////////////////////////////////////////////////// - - /// Trigger remote generic GXS service search - virtual std::error_condition distantSearchRequest( - rs_owner_ptr searchData, uint32_t dataSize, - RsServiceType serviceType, TurtleRequestId& requestId ) = 0; - - /// Handle remote generic GXS services search requests to specific service - virtual std::error_condition handleDistantSearchRequest( - rs_view_ptr requestData, uint32_t requestSize, - rs_owner_ptr& resultData, uint32_t& resultSize ) = 0; - - /// Receive remote generic GXS services search result - virtual std::error_condition receiveDistantSearchResult( - const TurtleRequestId requestId, - rs_owner_ptr& resultData, uint32_t& resultSize ) = 0; - - /*! - * \brief turtleGroupRequest - * Requests a particular group meta data. The request protects the group ID. - * \param group_id - * \return - * returns the turtle request ID that might be associated to some results. - */ - virtual TurtleRequestId turtleGroupRequest(const RsGxsGroupId& group_id)=0; - - /*! - * \brief turtleSearchRequest - * Uses distant search to match the substring to the group meta data. - * \param match_string - * \return - * returns the turtle request ID that might be associated to some results. - */ - virtual TurtleRequestId turtleSearchRequest(const std::string& match_string)=0; - - /*! - * \brief receiveTurtleSearchResults - * Called by turtle (through RsGxsNetTunnel) when new results are received - * \param req Turtle search request ID associated with this result - * \param group_infos Group summary information for the groups returned by the search - */ - virtual void receiveTurtleSearchResults(TurtleRequestId req,const std::list& group_infos)=0; - - /*! - * \brief receiveTurtleSearchResults - * Called by turtle (through RsGxsNetTunnel) when new data is received - * \param req Turtle search request ID associated with this result - * \param encrypted_group_data Group data - */ - RS_DEPRECATED_FOR("receiveDistantSearchResult") - virtual void receiveTurtleSearchResults( - TurtleRequestId req, - rs_owner_ptr encrypted_group_data, - uint32_t encrypted_group_data_len ) = 0; - - /*! - * \brief retrieveTurtleSearchResults - * To be used to retrieve the search results that have been notified (or not) - * \param req request that match the results to retrieve - * \param group_infos results to retrieve. - * \return - * false when the request is unknown. - */ - virtual bool retrieveDistantSearchResults(TurtleRequestId req, std::map &group_infos)=0; - /*! - * \brief getDistantSearchResults - * \param id - * \param group_infos - * \return - */ - virtual bool clearDistantSearchResults(const TurtleRequestId& id)=0; - virtual bool retrieveDistantGroupSummary(const RsGxsGroupId&,RsGxsGroupSearchResults&)=0; - - RS_DEPRECATED_FOR("handleDistantSearchRequest and distantSearchRequest") - virtual bool search(const std::string& substring,std::list& group_infos) =0; - - virtual bool search(const Sha1CheckSum& hashed_group_id,unsigned char *& encrypted_group_data,uint32_t& encrypted_group_data_len)=0; - - /*! - * \brief getDistantSearchStatus - * Request status of a possibly ongoing/finished search. If UNKNOWN is returned, it means that no - * such group is under request - * \return - */ - virtual DistantSearchGroupStatus getDistantSearchStatus(const RsGxsGroupId&) =0; - - /*! - * Initiates a search through the network - * This returns messages which contains the search terms set in RsGxsSearch - * @param search contains search terms of requested from service - * @param hops how far into friend tree for search - * @return search token that can be redeemed later, implementation should indicate how this should be used - */ - //virtual int searchMsgs(RsGxsSearch* search, uint8_t hops = 1, bool retrieve = 0) = 0; - - /*! - * Initiates a search of groups through the network which goes - * a given number of hops deep into your friend network - * @param search contains search term requested from service - * @param hops number of hops deep into peer network - * @return search token that can be redeemed later - */ - //virtual int searchGrps(RsGxsSearch* search, uint8_t hops = 1, bool retrieve = 0) = 0; - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /// DATA ACCESS FUNCTIONS /// - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - /*! - * pauses synchronisation of subscribed groups and request for group id - * from peers - * @param enabled set to false to disable pause, and true otherwise - */ - virtual void pauseSynchronisation(bool enabled) = 0; - - - /*! - * Request for this message is sent through to peers on your network - * and how many hops from them you've indicated - * @param msgId the messages to retrieve - * @return request token to be redeemed - */ - virtual int requestMsg(const RsGxsGrpMsgIdPair& msgId) = 0; - - /*! - * Request for this group is sent through to peers on your network - * and how many hops from them you've indicated - * @param enabled set to false to disable pause, and true otherwise - * @return request token to be redeemed - */ - virtual int requestGrp(const std::list& grpId, const RsPeerId& peerId) = 0; - - /*! - * returns some stats about this group related to the network visibility. - * For now, only one statistics: - * max_known_messages: max number of messages reported by a friend. This is used to display unsubscribed group content. - */ - virtual bool getGroupNetworkStats(const RsGxsGroupId& grpId,RsGroupNetworkStats& stats)=0; - - virtual void subscribeStatusChanged(const RsGxsGroupId& id,bool subscribed) =0; - - /*! - * Request for this group is sent through to peers on your network - * and how many hops from them you've indicated - */ - virtual int sharePublishKey(const RsGxsGroupId& grpId,const std::set& peers)=0 ; - - /*! - * \brief rejectMessage - * Tells the network exchange service to not download this message again, at least for some time (maybe 24h or more) - * in order to avoid cluttering the network pipe with copied of this rejected message. - * \param msgId - */ - virtual void rejectMessage(const RsGxsMessageId& msgId) =0; - - /*! - * \brief getGroupServerUpdateTS - * Returns the server update time stamp for that group. This is used for synchronisation of TS between - * various network exchange services, suhc as channels/circles or forums/circles - * \param gid group for that request - * \param tm time stamp computed - * \return false if the group is not found, true otherwise - */ - virtual bool getGroupServerUpdateTS(const RsGxsGroupId& gid,rstime_t& grp_server_update_TS,rstime_t& msg_server_update_TS) =0; - - /*! - * \brief stampMsgServerUpdateTS - * Updates the msgServerUpdateMap structure to time(NULL), so as to trigger sending msg lists to friends. - * This is needed when e.g. posting a new message to a group. - * \param gid the group to stamp in msgServerUpdateMap - * \return - */ - virtual bool stampMsgServerUpdateTS(const RsGxsGroupId& gid) =0; - - /*! - * \brief isDistantPeer - * \param pid peer that is a virtual peer provided by GxsNetTunnel - * \return - * true if the peer exists (adn therefore is online) - */ - virtual bool isDistantPeer(const RsPeerId& pid)=0; - - /*! - * \brief removeGroups - * Removes time stamp information from the list of groups. This allows to re-sync them if suppliers are present. - * \param groups list of groups to remove from the update maps - * \return true if nothing bad happens. - */ - virtual bool removeGroups(const std::list& groups)=0; - - /*! - * \brief minReputationForForwardingMessages - * Encodes the policy for sending/requesting messages depending on anti-spam settings. - * - * \param group_sign_flags Sign flags from the group meta data - * \param identity_flags Flags of the identity - * \return - */ - static RsReputationLevel minReputationForRequestingMessages( - uint32_t /* group_sign_flags */, uint32_t /* identity_flags */ ) - { - // We always request messages, except if the author identity is locally banned. - return RsReputationLevel::REMOTELY_NEGATIVE; - } - static RsReputationLevel minReputationForForwardingMessages( - uint32_t group_sign_flags, uint32_t identity_flags ) - { - // If anti-spam is enabled, do not send messages from authors with bad reputation. The policy is to only forward messages if the reputation of the author is at least - // equal to the minimal reputation in the table below (R=remotely, L=locally, P=positive, N=negative, O=neutral) : - // - // - // +----------------------------------------------------+ - // | Identity flags | - // +----------------------------------------------------+ - // | Anonymous Signed Signed+Known | - // +-------------+-----------+----------------------------------------------------+ - // | |NONE | O O O | - // | Forum flags |GPG_AUTHED | RP O O | - // | |GPG_KNOWN | RP RP O | - // +-------------+-----------+----------------------------------------------------+ - // - - if(identity_flags & RS_IDENTITY_FLAGS_PGP_KNOWN) - return RsReputationLevel::NEUTRAL; - else if(identity_flags & RS_IDENTITY_FLAGS_PGP_LINKED) - { - if(group_sign_flags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG_KNOWN) - return RsReputationLevel::REMOTELY_POSITIVE; - else - return RsReputationLevel::NEUTRAL; - } - else - { - if( (group_sign_flags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG_KNOWN) || (group_sign_flags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG)) - return RsReputationLevel::REMOTELY_POSITIVE; - else - return RsReputationLevel::NEUTRAL; - } - } - - /** - * @brief Check if new stuff is available from peers - * @param peers peers to check, if empty all available peers are checked - */ - virtual std::error_condition checkUpdatesFromPeers( - std::set peers = std::set() ) = 0; - - /** - * @brief request online peers to pull updates from our node ASAP - * @param peers peers to which request pull from, if empty all available - * peers are requested to pull - * @return success or error details - */ - virtual std::error_condition requestPull( - std::set peers = std::set() ) = 0; -}; diff --git a/libretroshare/src/gxs/rsnxsobserver.cpp b/libretroshare/src/gxs/rsnxsobserver.cpp deleted file mode 100644 index 2b5ab0d8a..000000000 --- a/libretroshare/src/gxs/rsnxsobserver.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/******************************************************************************* - * RetroShare General eXchange System * - * * - * Copyright (C) 2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "gxs/rsnxsobserver.h" - -const RsNxsObserverErrorCategory RsNxsObserverErrorCategory::instance; - -std::error_condition RsNxsObserverErrorCategory::default_error_condition(int ev) -const noexcept -{ - switch(static_cast(ev)) - { - case RsNxsObserverErrorNum::NOT_OVERRIDDEN_BY_OBSERVER: - return std::errc::operation_not_supported; - default: - return std::error_condition(ev, *this); - } -} diff --git a/libretroshare/src/gxs/rsnxsobserver.h b/libretroshare/src/gxs/rsnxsobserver.h deleted file mode 100644 index 9d81e7656..000000000 --- a/libretroshare/src/gxs/rsnxsobserver.h +++ /dev/null @@ -1,159 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxs: rsgxsobserver.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2011-2012 Robert Fernie * - * Copyright (C) 2011-2012 Christopher Evi-Parker * - * Copyright (C) 2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include - -#include "retroshare/rsgxsiface.h" -#include "rsitems/rsnxsitems.h" -#include "util/rsdebug.h" - -typedef uint32_t TurtleRequestId; - -enum class RsNxsObserverErrorNum : int32_t -{ - NOT_OVERRIDDEN_BY_OBSERVER = 2004, -}; - -struct RsNxsObserverErrorCategory: std::error_category -{ - const char* name() const noexcept override - { return "RetroShare NXS Observer"; } - - std::string message(int ev) const override - { - switch (static_cast(ev)) - { - case RsNxsObserverErrorNum::NOT_OVERRIDDEN_BY_OBSERVER: - return "Method not overridden by observer"; - default: - return rsErrorNotInCategory(ev, name()); - } - } - - std::error_condition default_error_condition(int ev) const noexcept override; - - const static RsNxsObserverErrorCategory instance; -}; - - -namespace std -{ -/** Register RsNxsObserverErrorNum as an error condition enum, must be in std - * namespace */ -template<> struct is_error_condition_enum : true_type {}; -} - -/** Provide RsJsonApiErrorNum conversion to std::error_condition, must be in - * same namespace of RsJsonApiErrorNum */ -inline std::error_condition make_error_condition(RsNxsObserverErrorNum e) noexcept -{ - return std::error_condition( - static_cast(e), RsNxsObserverErrorCategory::instance ); -}; - -class RsNxsObserver -{ -public: - - /*! - * @param messages messages are deleted after function returns - */ - virtual void receiveNewMessages(const std::vector& messages) = 0; - - /*! - * @param groups groups are deleted after function returns - */ - virtual void receiveNewGroups(const std::vector& groups) = 0; - - /*! - * \brief receiveDistantSearchResults - * Called when new distant search result arrive. - * \param grpId - */ - virtual void receiveDistantSearchResults(TurtleRequestId /*id*/,const RsGxsGroupId& /*grpId*/) - { - std::cerr << __PRETTY_FUNCTION__ << ": not overloaded but still called. Nothing will happen." << std::endl; - } - - /** If advanced search functionalities like deep indexing are supported at - * observer/service level, this method should be overridden to handle search - * requests there. - * @param[in] requestData search query - * @param[in] requestSize search query size - * @param[out] resultData results data storage for a pointer to search - * result reply data or nullptr if no mathing results where found - * @param[out] resultSize storage for results data size or 0 if no matching - * results where found - * @return Error details or success, NOT_OVERRIDDEN_BY_OBSERVER is - * returned to inform the caller that this method was not overridden by the - * observer so do not use it for other meanings. */ - virtual std::error_condition handleDistantSearchRequest( - rs_view_ptr requestData, uint32_t requestSize, - rs_owner_ptr& resultData, uint32_t& resultSize ) - { - /* Avoid unused paramethers warning this way so doxygen can still parse - * paramethers documentation */ - (void) requestData; (void) requestSize; - (void) resultData; (void) resultSize; - return RsNxsObserverErrorNum::NOT_OVERRIDDEN_BY_OBSERVER; - } - - /** If advanced search functionalities like deep indexing are supported at - * observer/service level, this method should be overridden to handle search - * results there. - * @param[in] requestId search query id - * @param[out] resultData results data - * @param[out] resultSize results data size - * @return Error details or success, NOT_OVERRIDDEN_BY_OBSERVER is - * returned to inform the caller that this method was not overridden by the - * observer so do not use it for other meanings. */ - virtual std::error_condition receiveDistantSearchResult( - const TurtleRequestId requestId, - rs_owner_ptr& resultData, uint32_t& resultSize ) - { - (void) requestId; (void) resultData; (void) resultSize; - return RsNxsObserverErrorNum::NOT_OVERRIDDEN_BY_OBSERVER; - } - - /*! - * @param grpId group id - */ - virtual void notifyReceivePublishKey(const RsGxsGroupId &grpId) = 0; - - /*! - * \brief notifyChangedGroupSyncParams - * \param caled when a group sync parameter is updated - */ - virtual void notifyChangedGroupSyncParams(const RsGxsGroupId &grpId) = 0; - /*! - * @param grpId group id - */ - virtual void notifyChangedGroupStats(const RsGxsGroupId &grpId) = 0; - - RsNxsObserver() = default; - virtual ~RsNxsObserver() = default; -}; diff --git a/libretroshare/src/gxstrans/p3gxstrans.cc b/libretroshare/src/gxstrans/p3gxstrans.cc deleted file mode 100644 index 354cf812f..000000000 --- a/libretroshare/src/gxstrans/p3gxstrans.cc +++ /dev/null @@ -1,1405 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxstrans: p3gxstrans.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "util/rsdir.h" -#include "gxstrans/p3gxstrans.h" -#include "util/stacktrace.h" -#include "util/rsdebug.h" - -//#define DEBUG_GXSTRANS 1 - -typedef unsigned int uint; - -/*extern*/ RsGxsTrans* rsGxsTrans = nullptr; - -const uint32_t p3GxsTrans::MAX_DELAY_BETWEEN_CLEANUPS = 900; // every 15 mins. Could be less. - -p3GxsTrans::~p3GxsTrans() -{ - // (cyril) this cannot be called here! There's chances the thread that saves configs will be dead already! - //p3Config::saveConfiguration(); - - { - RS_STACK_MUTEX(mIngoingMutex); - for ( auto& kv : mIncomingQueue) delete kv.second; - } -} - -bool p3GxsTrans::getDataStatistics(GxsTransStatistics& stats) -{ - { - RS_STACK_MUTEX(mDataMutex); - stats.prefered_group_id = mPreferredGroupId; - } - stats.outgoing_records.clear(); - - { - RS_STACK_MUTEX(mOutgoingMutex); - - for ( auto it = mOutgoingQueue.begin(); it != mOutgoingQueue.end(); ++it) - { - const OutgoingRecord& pr(it->second); - - RsGxsTransOutgoingRecord rec ; - rec.status = pr.status ; - rec.send_TS = pr.sent_ts ; - rec.group_id = pr.group_id ; - rec.trans_id = pr.mailItem.mailId ; - rec.recipient = pr.recipient ; - rec.data_size = pr.mailData.size(); - rec.data_hash = RsDirUtil::sha1sum(pr.mailData.data(),pr.mailData.size()); - rec.client_service = pr.clientService ; - - stats.outgoing_records.push_back(rec) ; - } - } - - return true; -} - -bool p3GxsTrans::sendData( RsGxsTransId& mailId, - GxsTransSubServices service, - const RsGxsId& own_gxsid, const RsGxsId& recipient, - const uint8_t* data, uint32_t size, - RsGxsTransEncryptionMode cm ) -{ -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::sendEmail(...)" << std::endl; -#endif - - if(!mIdService.isOwnId(own_gxsid)) - { - std::cerr << "p3GxsTrans::sendEmail(...) isOwnId(own_gxsid) false!" - << std::endl; - return false; - } - - if(recipient.isNull()) - { - std::cerr << "p3GxsTrans::sendEmail(...) got invalid recipient" - << std::endl; - print_stacktrace(); - return false; - } - - OutgoingRecord pr( recipient, service, data, size ); - - pr.mailItem.clear(); - pr.author = own_gxsid; //pr.mailItem.meta.mAuthorId = own_gxsid; - pr.mailItem.cryptoType = cm; - pr.mailItem.mailId = RSRandom::random_u64(); - - { - RS_STACK_MUTEX(mOutgoingMutex); - mOutgoingQueue.insert(prMap::value_type(pr.mailItem.mailId, pr)); - } - - mailId = pr.mailItem.mailId; - - IndicateConfigChanged(); // This causes the saving of the message after all data has been filled in. - return true; -} - -bool p3GxsTrans::querySendStatus(RsGxsTransId mailId, GxsTransSendStatus& st) -{ - RS_STACK_MUTEX(mOutgoingMutex); - auto it = mOutgoingQueue.find(mailId); - if( it != mOutgoingQueue.end() ) - { - st = it->second.status; - return true; - } - return false; -} - -void p3GxsTrans::registerGxsTransClient( - GxsTransSubServices serviceType, GxsTransClient* service) -{ - RS_STACK_MUTEX(mServClientsMutex); - mServClients[serviceType] = service; -} - -void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) -{ -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::handleResponse(" << token << ", " << req_type << ", " << status << ")" << std::endl; -#endif - if (status != RsTokenService::COMPLETE) - return; //For now, only manage Complete request - - bool changed = false ; - - switch (req_type) - { - case GROUPS_LIST: - { -#ifdef DEBUG_GXSTRANS - std::cerr << " Reviewing available groups. " << std::endl; -#endif - std::vector groups; - getGroupData(token, groups); - - // First recompute the prefered group Id. - - { - RS_STACK_MUTEX(mDataMutex); - - for( auto grp : groups ) - { - locked_supersedePreferredGroup(grp->meta.mGroupId); - - if(RsGenExchange::getStoragePeriod(grp->meta.mGroupId) != GXS_STORAGE_PERIOD) - { - std::cerr << "(WW) forcing storage period in GxsTrans group " << grp->meta.mGroupId << " to " << GXS_STORAGE_PERIOD << " seconds. Value was " << RsGenExchange::getStoragePeriod(grp->meta.mGroupId) << std::endl; - - RsGenExchange::setStoragePeriod(grp->meta.mGroupId,GXS_STORAGE_PERIOD) ; - } - } - } - -#ifdef DEBUG_GXSTRANS - std::cerr << " computed preferred group id: " << mPreferredGroupId << std::endl; -#endif - for( auto grp : groups ) - { - /* For each group check if it is better candidate then - * preferredGroupId, if it is supplant it and subscribe if it is not - * subscribed yet. - * Otherwise if it has recent messages subscribe. - * If the group was already subscribed has no recent messages - * unsubscribe. - */ - - const RsGroupMetaData& meta = grp->meta; - bool subscribed = IS_GROUP_SUBSCRIBED(meta.mSubscribeFlags); - - // if mLastPost is 0, then the group is not subscribed, so it only has impact on shouldSubscribe. In any case, a group - // with no information shouldn't be subscribed, so the olderThen() test is still valid in the case mLastPost=0. - - bool old = olderThen( meta.mLastPost, UNUSED_GROUP_UNSUBSCRIBE_INTERVAL ); - uint32_t token; - - bool shouldSubscribe = false ; - bool shouldUnSubscribe = false ; - { - RS_STACK_MUTEX(mDataMutex); - - shouldSubscribe = (!subscribed) && ((!old)|| meta.mGroupId == mPreferredGroupId ); - shouldUnSubscribe = ( subscribed) && old && meta.mGroupId != mPreferredGroupId; - } - -#ifdef DEBUG_GXSTRANS - std::cout << " group " << grp->meta.mGroupId << ", subscribed: " << subscribed << " last post: " << meta.mLastPost << " should subscribe: "<< shouldSubscribe - << ", should unsubscribe: " << shouldUnSubscribe << std::endl; -#endif - if(shouldSubscribe) - RsGenExchange::subscribeToGroup(token, meta.mGroupId, true); - else if(shouldUnSubscribe) - RsGenExchange::subscribeToGroup(token, meta.mGroupId, false); - -#ifdef GXS_MAIL_GRP_DEBUG - char buff[30]; - struct tm* timeinfo; - timeinfo = localtime(&meta.mLastPost); - strftime(buff, sizeof(buff), "%Y %b %d %H:%M", timeinfo); - - std::cout << "p3GxsTrans::handleResponse(...) GROUPS_LIST " - << "meta.mGroupId: " << meta.mGroupId - << " meta.mLastPost: " << buff - << " subscribed: " << subscribed - << " old: " << old - << " shoudlSubscribe: " << shoudlSubscribe - << " shoudlUnSubscribe: " << shoudlUnSubscribe - << std::endl; -#endif // GXS_MAIL_GRP_DEBUG - - delete grp; - } - - bool have_preferred_group = false ; - - { - RS_STACK_MUTEX(mDataMutex); - have_preferred_group = !mPreferredGroupId.isNull(); - } - - if(!have_preferred_group) - { - /* This is true only at first run when we haven't received mail - * distribuition groups from friends */ - -#ifdef DEBUG_GXSTRANS - std::cerr << "p3GxsTrans::handleResponse(...) preferredGroupId.isNu" - << "ll() let's create a new group." << std::endl; -#endif - uint32_t token; - publishGroup(token, new RsGxsTransGroupItem()); - queueRequest(token, GROUP_CREATE); - } - - break; - } - case GROUP_CREATE: - { -#ifdef DEBUG_GXSTRANS - std::cerr << "p3GxsTrans::handleResponse(...) GROUP_CREATE" << std::endl; -#endif - RsGxsGroupId grpId; - acknowledgeTokenGrp(token, grpId); - - RS_STACK_MUTEX(mDataMutex); - locked_supersedePreferredGroup(grpId); - break; - } - case MAILS_UPDATE: - { -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::handleResponse(...) MAILS_UPDATE" << std::endl; -#endif - typedef std::map > GxsMsgDataMap; - GxsMsgDataMap gpMsgMap; - getMsgData(token, gpMsgMap); - for ( GxsMsgDataMap::iterator gIt = gpMsgMap.begin(); - gIt != gpMsgMap.end(); ++gIt ) - { - typedef std::vector vT; - vT& mv(gIt->second); - for( vT::const_iterator mIt = mv.begin(); mIt != mv.end(); ++mIt ) - { - RsGxsMsgItem* gIt = *mIt; - switch(static_cast(gIt->PacketSubType())) - { - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL: - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT: - { - RsGxsTransBaseMsgItem* mb = dynamic_cast(*mIt); - - if(mb) - { - RS_STACK_MUTEX(mIngoingMutex); - mIncomingQueue.insert(inMap::value_type(mb->mailId,mb)); - - changed = true ; - } - else - std::cerr << "p3GxsTrans::handleResponse(...) " - << "GXS_MAIL_SUBTYPE_MAIL cast error, " - << "something really wrong is happening" - << std::endl; - break; - } - default: - std::cerr << "p3GxsTrans::handleResponse(...) MAILS_UPDATE " - << "Unknown mail subtype : " - << static_cast(gIt->PacketSubType()) - << std::endl; - delete gIt; - break; - } - } - } - break; - } - default: - std::cerr << "p3GxsTrans::handleResponse(...) Unknown req_type: " - << req_type << std::endl; - break; - } - - if(changed) - IndicateConfigChanged(); -} -void p3GxsTrans::GxsTransIntegrityCleanupThread::getPerUserStatistics(std::map& m) -{ - RS_STACK_MUTEX(mMtx) ; - - m = total_message_size_and_count ; -} - -void p3GxsTrans::GxsTransIntegrityCleanupThread::getMessagesToDelete(GxsMsgReq& m) -{ - RS_STACK_MUTEX(mMtx) ; - - m = mMsgToDel ; - mMsgToDel.clear(); -} - -// This method does two things: -// 1 - cleaning up old messages and messages for which an ACK has been received. -// 2 - building per user statistics across groups. This is important because it allows to mitigate the excess of -// messages, which might be due to spam. -// -// Note: the anti-spam system is disabled the level of GXS, because we want to allow to send anonymous messages -// between identities that might not have a reputation yet. Still, messages from identities with a bad reputation -// are still deleted by GXS. -// -// The group limits are enforced according to the following rules: -// * a temporal sliding window is computed for each identity and the number of messages signed by this identity is counted -// * -// -// -// Deleted messages are notified to the RsGxsNetService part which keeps a list of delete messages so as not to request them again -// during the same session. This allows to safely delete messages while avoiding re-synchronisation from friend nodes. - -void p3GxsTrans::GxsTransIntegrityCleanupThread::run() -{ - // first take out all the groups - - std::map grp; - mDs->retrieveNxsGrps(grp, true); - -#ifdef DEBUG_GXSTRANS - std::cerr << "GxsTransIntegrityCleanupThread::run()" << std::endl; -#endif - - // compute hash and compare to stored value, if it fails then simply add it - // to list - - GxsMsgReq grps; - for(std::map::iterator git = grp.begin(); git != grp.end(); ++git) - { - RsNxsGrp* grp = git->second; - - // store the group for retrieveNxsMsgs - grps[grp->grpId]; - - delete grp; - } - - // now messages - - std::map totalMessageSizeAndCount; - - std::map > stored_msgs ; - std::list received_msgs ; - - GxsMsgResult msgs; - mDs->retrieveNxsMsgs(grps, msgs, true); - - for(GxsMsgResult::iterator mit = msgs.begin();mit != msgs.end(); ++mit) - { - std::vector& msgV = mit->second; - std::vector::iterator vit = msgV.begin(); -#ifdef DEBUG_GXSTRANS - std::cerr << "Group " << mit->first << ": " << std::endl; -#endif - - for(; vit != msgV.end(); ++vit) - { - RsNxsMsg* msg = *vit; - - RsGxsTransSerializer s ; - uint32_t size = msg->msg.bin_len; - RsItem *item = s.deserialise(msg->msg.bin_data,&size); - RsGxsTransMailItem *mitem ; - RsGxsTransPresignedReceipt *pitem ; - - if(item == NULL) - std::cerr << " Unrecocognised item type!" << std::endl; - else if(NULL != (mitem = dynamic_cast(item))) - { -#ifdef DEBUG_GXSTRANS - std::cerr << " " << msg->metaData->mMsgId << ": Mail data with ID " << std::hex << std::setfill('0') << std::setw(16) << mitem->mailId << std::dec << " from " << msg->metaData->mAuthorId << " size: " << msg->msg.bin_len << std::endl; -#endif - - stored_msgs[mitem->mailId] = std::make_pair(msg->metaData->mGroupId,msg->metaData->mMsgId) ; - } - else if(NULL != (pitem = dynamic_cast(item))) - { -#ifdef DEBUG_GXSTRANS - std::cerr << " " << msg->metaData->mMsgId << ": Signed rcpt of ID " << std::hex << pitem->mailId << std::dec << " from " << msg->metaData->mAuthorId << " size: " << msg->msg.bin_len << std::endl; -#endif - - received_msgs.push_back(pitem->mailId) ; - } - else - std::cerr << " Unknown item type!" << std::endl; - - totalMessageSizeAndCount[msg->metaData->mAuthorId].size += msg->msg.bin_len ; - totalMessageSizeAndCount[msg->metaData->mAuthorId].count++; - delete msg; - - delete item; - } - } - - // From the collected information, build a list of group messages to delete. - - GxsMsgReq msgsToDel ; - -#ifdef DEBUG_GXSTRANS - std::cerr << "Msg removal report:" << std::endl; - - std::cerr << " Per user size and count: " << std::endl; - for(std::map::const_iterator it(totalMessageSizeAndCount.begin());it!=totalMessageSizeAndCount.end();++it) - std::cerr << " " << it->first << ": " << it->second.count << " messages, for a total size of " << it->second.size << " bytes." << std::endl; -#endif - - for(std::list::const_iterator it(received_msgs.begin());it!=received_msgs.end();++it) - { - std::map >::const_iterator it2 = stored_msgs.find(*it) ; - - if(stored_msgs.end() != it2) - { - msgsToDel[it2->second.first].insert(it2->second.second); - -#ifdef DEBUG_GXSTRANS - std::cerr << " scheduling msg " << std::hex << it2->second.first << "," << it2->second.second << " for deletion." << std::endl; -#endif - } - } - - RS_STACK_MUTEX(mMtx) ; - mMsgToDel = msgsToDel ; - total_message_size_and_count = totalMessageSizeAndCount; - mDone = true; -} - -bool p3GxsTrans::GxsTransIntegrityCleanupThread::isDone() -{ - RS_STACK_MUTEX(mMtx) ; - return mDone ; -} -void p3GxsTrans::service_tick() -{ - GxsTokenQueue::checkRequests(); - - rstime_t now = time(NULL); - bool changed = false ; - - if(mLastMsgCleanup + MAX_DELAY_BETWEEN_CLEANUPS < now) - { - RS_STACK_MUTEX(mPerUserStatsMutex); - if(!mCleanupThread) - mCleanupThread = new GxsTransIntegrityCleanupThread(getDataStore()); - - if(mCleanupThread->isRunning()) - std::cerr << "Cleanup thread is already running. Not running it again!" << std::endl; - else - { -#ifdef DEBUG_GXSTRANS - std::cerr << "Starting GxsIntegrity cleanup thread." << std::endl; -#endif - - mCleanupThread->start() ; - mLastMsgCleanup = now ; - } - - // This forces to review all groups, and decide to subscribe or not to each of them. - - requestGroupsData(); - } - - // now grab collected messages to delete - - if(mCleanupThread != NULL && mCleanupThread->isDone()) - { - RS_STACK_MUTEX(mPerUserStatsMutex); - GxsMsgReq msgToDel ; - - mCleanupThread->getMessagesToDelete(msgToDel) ; - - if(!msgToDel.empty()) - { -#ifdef DEBUG_GXSTRANS - std::cerr << "p3GxsTrans::service_tick(): deleting messages." << std::endl; -#endif - uint32_t token ; - deleteMsgs(token,msgToDel); - } - - mCleanupThread->getPerUserStatistics(per_user_statistics) ; - -#ifdef DEBUG_GXSTRANS - std::cerr << "p3GxsTrans: Got new set of per user statistics:"<< std::endl; - for(std::map::const_iterator it(per_user_statistics.begin());it!=per_user_statistics.end();++it) - std::cerr << " " << it->first << ": " << it->second.count << " " << it->second.size << std::endl; -#endif - // Waiting here is very important because the thread may still be updating its semaphores after setting isDone() to true - // If we delete it during this operation it will corrupt the stack and cause unpredictable errors. - - while(mCleanupThread->isRunning()) - { - std::cerr << "Waiting for mCleanupThread to terminate..." << std::endl; - rstime::rs_usleep(500*1000); - } - - delete mCleanupThread; - mCleanupThread=NULL ; - } - - { - RS_STACK_MUTEX(mOutgoingMutex); - for ( auto it = mOutgoingQueue.begin(); it != mOutgoingQueue.end(); ) - { - OutgoingRecord& pr(it->second); - GxsTransSendStatus oldStatus = pr.status; - - locked_processOutgoingRecord(pr); - - if (oldStatus != pr.status) notifyClientService(pr); - if( pr.status >= GxsTransSendStatus::RECEIPT_RECEIVED ) - { - it = mOutgoingQueue.erase(it); - changed = true ; - } - else ++it; - } - } - - - { - RS_STACK_MUTEX(mIngoingMutex); - for( auto it = mIncomingQueue.begin(); it != mIncomingQueue.end(); ) - { - switch(static_cast( it->second->PacketSubType())) - { - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL: - { - RsGxsTransMailItem* msg = dynamic_cast(it->second); - - if(!msg) - { - std::cerr << "p3GxsTrans::service_tick() (EE) " - << "GXS_MAIL_SUBTYPE_MAIL dynamic_cast failed, " - << "something really wrong is happening!" - << std::endl; - } - else - { -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::service_tick() " - << "GXS_MAIL_SUBTYPE_MAIL handling: " - << msg->meta.mMsgId - << " with cryptoType: " - << static_cast(msg->cryptoType) - << " recipientHint: " << msg->recipientHint - << " mailId: "<< msg->mailId - << " payload.size(): " << msg->payload.size() - << std::endl; -#endif - handleEncryptedMail(msg); - } - break; - } - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT: - { - RsGxsTransPresignedReceipt* rcpt = dynamic_cast(it->second); - - if(!rcpt) - { - std::cerr << "p3GxsTrans::service_tick() (EE) " - << "GXS_MAIL_SUBTYPE_RECEIPT dynamic_cast failed," - << " something really wrong is happening!" - << std::endl; - } - else if(mIdService.isOwnId(rcpt->meta.mAuthorId)) - { - /* It is a receipt for a mail sent by this node live it in - * ingoingQueue so processOutgoingRecord(...) will take care - * of it at next tick */ - ++it; - continue; - } - else - { - /* It is a receipt for a message sent by someone else - * we can delete original mail from our GXS DB without - * waiting for GXS_STORAGE_PERIOD, this has been implemented - * already by Cyril into GxsTransIntegrityCleanupThread */ - } - break; - } - default: - std::cerr << "p3GxsTrans::service_tick() (EE) got something " - << "really unknown into ingoingQueue!!" << std::endl; - break; - } - - delete it->second ; - it = mIncomingQueue.erase(it); - changed = true ; - } - } - - if(changed) - IndicateConfigChanged(); -} - -RsGenExchange::ServiceCreate_Return p3GxsTrans::service_CreateGroup( - RsGxsGrpItem* /*grpItem*/, RsTlvSecurityKeySet& /*keySet*/ ) -{ -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::service_CreateGroup(...) " - << grpItem->meta.mGroupId << std::endl; -#endif - return SERVICE_CREATE_SUCCESS; -} - -void p3GxsTrans::notifyChanges(std::vector& changes) -{ -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::notifyChanges(...)" << std::endl; -#endif - std::list grps_to_request; - GxsMsgReq msgs_to_request; - - for( auto it = changes.begin(); it != changes.end(); ++it ) - { - RsGxsGroupChange* grpChange = dynamic_cast(*it); - RsGxsMsgChange* msgChange = dynamic_cast(*it); - - if (grpChange) - { -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::notifyChanges(...) grpChange" << std::endl; -#endif - grps_to_request.push_back(grpChange->mGroupId); - } - else if(msgChange) - { -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::notifyChanges(...) msgChange" << std::endl; -#endif - - msgs_to_request[msgChange->mGroupId].insert(msgChange->mMsgId); - -#ifdef DEBUG_GXSTRANS - for( GxsMsgReq::const_iterator it = msgChange->msgChangeMap.begin(); - it != msgChange->msgChangeMap.end(); ++it ) - { - const RsGxsGroupId& grpId = it->first; - const std::vector& msgsIds = it->second; - typedef std::vector::const_iterator itT; - for(itT vit = msgsIds.begin(); vit != msgsIds.end(); ++vit) - { - const RsGxsMessageId& msgId = *vit; - std::cout << "p3GxsTrans::notifyChanges(...) got " - << "notification for message " << msgId - << " in group " << grpId << std::endl; - } - } -#endif - } - delete *it; - } - - if(!msgs_to_request.empty()) - { - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - RsGenExchange::getTokenService()->requestMsgInfo( token, 0xcaca, opts, msgs_to_request); - - GxsTokenQueue::queueRequest(token, MAILS_UPDATE); - } - - - if(!grps_to_request.empty()) - requestGroupsData(&grps_to_request); -} - -uint32_t p3GxsTrans::AuthenPolicy() -{ - uint32_t policy = 0; - uint32_t flag = 0; - - // This ensure propagated message have valid author signature - flag = GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN | - GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; - RsGenExchange::setAuthenPolicyFlag( flag, policy, - RsGenExchange::PUBLIC_GRP_BITS ); - - /* This ensure that in for restricted and private groups only authorized - * authors get the messages. Really not used ATM but don't hurts. */ - flag |= GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN | - GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN; - RsGenExchange::setAuthenPolicyFlag( flag, policy, - RsGenExchange::RESTRICTED_GRP_BITS ); - RsGenExchange::setAuthenPolicyFlag( flag, policy, - RsGenExchange::PRIVATE_GRP_BITS ); - - /* This seems never used RetroShare wide but we should investigate it - * more before considering this conclusive */ - flag = 0; - RsGenExchange::setAuthenPolicyFlag( flag, policy, - RsGenExchange::GRP_OPTION_BITS ); - - return policy; -} - -bool p3GxsTrans::requestGroupsData(const std::list* groupIds) -{ - // std::cout << "p3GxsTrans::requestGroupsList()" << std::endl; - uint32_t token=0; - RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - if(!groupIds) - RsGenExchange::getTokenService()->requestGroupInfo(token, 0xcaca, opts); - else - RsGenExchange::getTokenService()->requestGroupInfo(token, 0xcaca, opts, *groupIds); - - GxsTokenQueue::queueRequest(token, GROUPS_LIST); - return true; -} - -bool p3GxsTrans::handleEncryptedMail(const RsGxsTransMailItem* mail) -{ -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::handleEcryptedMail(...)" << std::endl; -#endif - - std::set decryptIds; - std::list ownIds; - mIdService.getOwnIds(ownIds); - for(auto it = ownIds.begin(); it != ownIds.end(); ++it) - if(mail->maybeRecipient(*it)) decryptIds.insert(*it); - - // Hint match none of our own ids - if(decryptIds.empty()) - { -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::handleEcryptedMail(...) hint doesn't match" << std::endl; -#endif - return true; - } - - switch (mail->cryptoType) - { - case RsGxsTransEncryptionMode::CLEAR_TEXT: - { - uint16_t csri = 0; - uint32_t off = 0; - getRawUInt16(&mail->payload[0], mail->payload.size(), &off, &csri); - -#ifdef DEBUG_GXSTRANS - std::cerr << "service: " << csri << " got CLEAR_TEXT mail!" - << std::endl; -#endif - /* As we cannot verify recipient without encryption, just pass the hint - * as recipient */ - return dispatchDecryptedMail( mail->meta.mAuthorId, mail->recipientHint, - &mail->payload[0], mail->payload.size() ); - } - case RsGxsTransEncryptionMode::RSA: - { - bool ok = true; - for( std::set::const_iterator it = decryptIds.begin(); - it != decryptIds.end(); ++it ) - { - const RsGxsId& decryptId(*it); - uint8_t* decrypted_data = NULL; - uint32_t decrypted_data_size = 0; - uint32_t decryption_error; - if( mIdService.decryptData( &mail->payload[0], - mail->payload.size(), decrypted_data, - decrypted_data_size, decryptId, - decryption_error ) ) - ok = ok && dispatchDecryptedMail( mail->meta.mAuthorId, - decryptId, decrypted_data, - decrypted_data_size ); - free(decrypted_data); - } - return ok; - } - default: - std::cout << "Unknown encryption type:" - << static_cast(mail->cryptoType) << std::endl; - return false; - } -} - -bool p3GxsTrans::dispatchDecryptedMail( const RsGxsId& authorId, - const RsGxsId& decryptId, - const uint8_t* decrypted_data, - uint32_t decrypted_data_size ) -{ -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::dispatchDecryptedMail(, , " << decrypted_data_size - << ")" << std::endl; -#endif - - uint16_t csri = 0; - uint32_t offset = 0; - if(!getRawUInt16( decrypted_data, decrypted_data_size, &offset, &csri)) - { - std::cerr << "p3GxsTrans::dispatchDecryptedMail(...) (EE) fatal error " - << "deserializing service type, something really wrong is " - << "happening!" << std::endl; - return false; - } - GxsTransSubServices rsrvc = static_cast(csri); - - uint32_t rcptsize = decrypted_data_size - offset; - RsNxsTransPresignedReceipt* receipt = - static_cast( - RsNxsSerialiser(RS_SERVICE_TYPE_GXS_TRANS).deserialise( - const_cast(&decrypted_data[offset]), &rcptsize )); - offset += rcptsize; - if(!receipt) - { - std::cerr << "p3GxsTrans::dispatchDecryptedMail(...) (EE) fatal error " - << "deserializing presigned return receipt , something really" - << " wrong is happening!" << std::endl; - return false; - } -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::dispatchDecryptedMail(...) dispatching receipt " - << "with: msgId: " << receipt->msgId << std::endl; -#endif - - std::vector rcct; rcct.push_back(receipt); - RsGenExchange::receiveNewMessages(rcct); - - GxsTransClient* recipientService = NULL; - { - RS_STACK_MUTEX(mServClientsMutex); - recipientService = mServClients[rsrvc]; - } - - if(recipientService) - return recipientService->receiveGxsTransMail( - authorId, decryptId, &decrypted_data[offset], - decrypted_data_size-offset ); - else - { - std::cerr << "p3GxsTrans::dispatchReceivedMail(...) " - << "got message for unknown service: " - << csri << std::endl; - return false; - } -} - -void p3GxsTrans::locked_processOutgoingRecord(OutgoingRecord& pr) -{ - //std::cout << "p3GxsTrans::processRecord(...)" << std::endl; - - switch (pr.status) - { - case GxsTransSendStatus::PENDING_PROCESSING: - { - pr.mailItem.saltRecipientHint(pr.recipient); - pr.mailItem.saltRecipientHint(RsGxsId::random()); - pr.sent_ts = time(NULL) ; //pr.mailItem.meta.mPublishTs = time(NULL); - } - /* fallthrough */ - case GxsTransSendStatus::PENDING_PREFERRED_GROUP: - { - RS_STACK_MUTEX(mDataMutex); - - if(mPreferredGroupId.isNull()) - { - requestGroupsData(); - pr.status = GxsTransSendStatus::PENDING_PREFERRED_GROUP; - break; - } - - pr.group_id = mPreferredGroupId ; //pr.mailItem.meta.mGroupId = mPreferredGroupId; - } - /* fallthrough */ - case GxsTransSendStatus::PENDING_RECEIPT_CREATE: - { - RsGxsTransPresignedReceipt grcpt; - grcpt.meta.mAuthorId = pr.author ; //grcpt.meta = pr.mailItem.meta; - grcpt.meta.mGroupId = pr.group_id ; //grcpt.meta = pr.mailItem.meta; - grcpt.meta.mMsgId.clear() ; - grcpt.meta.mParentId.clear() ; - grcpt.meta.mOrigMsgId.clear() ; - grcpt.meta.mPublishTs = time(NULL); - grcpt.mailId = pr.mailItem.mailId; - uint32_t grsz = RsGxsTransSerializer().size(&grcpt); - std::vector grsrz; - grsrz.resize(grsz); - RsGxsTransSerializer().serialise(&grcpt, &grsrz[0], &grsz); - - { - RS_STACK_MUTEX(mDataMutex); - pr.presignedReceipt.grpId = mPreferredGroupId; - } - pr.presignedReceipt.metaData = new RsGxsMsgMetaData(); - *pr.presignedReceipt.metaData = grcpt.meta; - pr.presignedReceipt.msg.setBinData(&grsrz[0], grsz); - } - /* fallthrough */ - case GxsTransSendStatus::PENDING_RECEIPT_SIGNATURE: // (cyril) This step is never actually used. - { - switch (RsGenExchange::createMessage(&pr.presignedReceipt)) - { - case CREATE_SUCCESS: break; - case CREATE_FAIL_TRY_LATER: - pr.status = GxsTransSendStatus::PENDING_RECEIPT_CREATE; - return; - default: - pr.status = GxsTransSendStatus::FAILED_RECEIPT_SIGNATURE; - goto processingFailed; - } - - uint32_t metaSize = pr.presignedReceipt.metaData->serial_size(); - std::vector srx; srx.resize(metaSize); - pr.presignedReceipt.metaData->serialise(&srx[0], &metaSize); - pr.presignedReceipt.meta.setBinData(&srx[0], metaSize); - } - /* fallthrough */ - case GxsTransSendStatus::PENDING_PAYLOAD_CREATE: - { - uint16_t serv = static_cast(pr.clientService); - uint32_t rcptsize = RsGxsTransSerializer().size(&pr.presignedReceipt); - uint32_t datasize = pr.mailData.size(); - pr.mailItem.payload.resize(2 + rcptsize + datasize); - uint32_t offset = 0; - setRawUInt16(&pr.mailItem.payload[0], 2, &offset, serv); - RsGxsTransSerializer().serialise(&pr.presignedReceipt, - &pr.mailItem.payload[offset], - &rcptsize); - offset += rcptsize; - memcpy(&pr.mailItem.payload[offset], &pr.mailData[0], datasize); - } - /* fallthrough */ - case GxsTransSendStatus::PENDING_PAYLOAD_ENCRYPT: - { - switch (pr.mailItem.cryptoType) - { - case RsGxsTransEncryptionMode::CLEAR_TEXT: - { - RsWarn() << __PRETTY_FUNCTION__ << " you are sending a mail " - << "without encryption, everyone can read it!" - << std::endl; - break; - } - case RsGxsTransEncryptionMode::RSA: - { - uint8_t* encryptedData = NULL; - uint32_t encryptedSize = 0; - uint32_t encryptError = 0; - if( mIdService.encryptData( &pr.mailItem.payload[0], - pr.mailItem.payload.size(), - encryptedData, encryptedSize, - pr.recipient, encryptError, true ) ) - { - pr.mailItem.payload.resize(encryptedSize); - memcpy( &pr.mailItem.payload[0], encryptedData, encryptedSize ); - free(encryptedData); - break; - } - else - { - RsErr() << __PRETTY_FUNCTION__ << " RSA encryption failed! " - << "error_status: " << encryptError << std::endl; - pr.status = GxsTransSendStatus::FAILED_ENCRYPTION; - goto processingFailed; - } - } - case RsGxsTransEncryptionMode::UNDEFINED_ENCRYPTION: - default: - RsErr() << __PRETTY_FUNCTION__ << " attempt to send mail with " - << "wrong EncryptionMode: " - << static_cast(pr.mailItem.cryptoType) - << " dropping mail!" << std::endl; - pr.status = GxsTransSendStatus::FAILED_ENCRYPTION; - goto processingFailed; - } - } - /* fallthrough */ - case GxsTransSendStatus::PENDING_PUBLISH: - { -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::sendEmail(...) sending mail to: " - << pr.recipient - << " with cryptoType: " - << static_cast(pr.mailItem.cryptoType) - << " recipientHint: " << pr.mailItem.recipientHint - << " receiptId: " << pr.mailItem.mailId - << " payload size: " << pr.mailItem.payload.size() - << std::endl; -#endif - - RsGxsTransMailItem *mail_item = new RsGxsTransMailItem(pr.mailItem); - - // pr.mailItem.meta is *not* serialised. So it is important to not rely on what's in it! - - mail_item->meta.mGroupId = pr.group_id ; - mail_item->meta.mAuthorId = pr.author ; - - mail_item->meta.mMsgId.clear(); - mail_item->meta.mParentId.clear(); - mail_item->meta.mOrigMsgId.clear(); - - uint32_t token; - publishMsg(token, mail_item) ; - - pr.status = GxsTransSendStatus::PENDING_RECEIPT_RECEIVE; - - IndicateConfigChanged(); // This causes the saving of the message after pr.status has changed. - break; - } - //case GxsTransSendStatus::PENDING_TRANSFER: - case GxsTransSendStatus::PENDING_RECEIPT_RECEIVE: - { - RS_STACK_MUTEX(mIngoingMutex); - auto range = mIncomingQueue.equal_range(pr.mailItem.mailId); - bool changed = false; - bool received = false; - - for( auto it = range.first; it != range.second; ++it) - { - RsGxsTransPresignedReceipt* rt = dynamic_cast(it->second); - - if(rt && mIdService.isOwnId(rt->meta.mAuthorId)) - { - mIncomingQueue.erase(it); delete rt; - pr.status = GxsTransSendStatus::RECEIPT_RECEIVED; - - changed = true; - received = true; - break; - } - } - - if(!received && time(nullptr) - pr.sent_ts > GXS_STORAGE_PERIOD) - { - changed = true; - pr.status = GxsTransSendStatus::FAILED_TIMED_OUT; - } - - if(changed) - IndicateConfigChanged(); - - break; - } - case GxsTransSendStatus::RECEIPT_RECEIVED: - break; - -processingFailed: - case GxsTransSendStatus::FAILED_RECEIPT_SIGNATURE: - case GxsTransSendStatus::FAILED_ENCRYPTION: - case GxsTransSendStatus::FAILED_TIMED_OUT: - default: - RsErr() << __PRETTY_FUNCTION__ << " processing:" << pr.mailItem.mailId - << " failed with: " << static_cast(pr.status) - << std::endl; - break; - } -} - -void p3GxsTrans::notifyClientService(const OutgoingRecord& pr) -{ - RS_STACK_MUTEX(mServClientsMutex); - auto it = mServClients.find(pr.clientService); - if( it != mServClients.end()) - { - GxsTransClient* serv(it->second); - if(serv) - { - serv->notifyGxsTransSendStatus(pr.mailItem.mailId, pr.status); - return; - } - } - - std::cerr << "p3GxsTrans::processRecord(...) (EE) processed" - << " mail for unkown service: " - << static_cast(pr.clientService) - << " fatally failed with: " - << static_cast(pr.status) << std::endl; - print_stacktrace(); -} - -RsSerialiser* p3GxsTrans::setupSerialiser() -{ - RsSerialiser* rss = new RsSerialiser; - rss->addSerialType(new RsGxsTransSerializer); - return rss; -} - -bool p3GxsTrans::saveList(bool &cleanup, std::list& saveList) -{ -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::saveList(...)" << saveList.size() << " " << mIncomingQueue.size() << " " << mOutgoingQueue.size() << std::endl; -#endif - - mOutgoingMutex.lock(); - mIngoingMutex.lock(); - - for ( auto& kv : mOutgoingQueue ) - { -#ifdef DEBUG_GXSTRANS - std::cerr << "Saving outgoing item, ID " << std::hex << std::setfill('0') << std::setw(16) << kv.first << std::dec << "Group id: " << kv.second.group_id << ", TS=" << kv.second.sent_ts << std::endl; -#endif - saveList.push_back(&kv.second); - } - for ( auto& kv : mIncomingQueue ) - { -#ifdef DEBUG_GXSTRANS - std::cerr << "Saving incoming item, ID " << std::hex << std::setfill('0') << std::setw(16) << kv.first << std::endl; -#endif - saveList.push_back(kv.second); - } - -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::saveList(...)" << saveList.size() << " " << mIncomingQueue.size() << " " << mOutgoingQueue.size() << std::endl; -#endif - - cleanup = false; - return true; -} - -void p3GxsTrans::saveDone() -{ - mOutgoingMutex.unlock(); - mIngoingMutex.unlock(); -} - -bool p3GxsTrans::loadList(std::list&loadList) -{ -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::loadList(...) " << loadList.size() << " " - << mIncomingQueue.size() << " " << mOutgoingQueue.size() - << std::endl; -#endif - - for(auto& v : loadList) - switch(static_cast(v->PacketSubType())) - { - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL: - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT: - { - RsGxsTransBaseMsgItem* mi = dynamic_cast(v); - if(mi) - { - RS_STACK_MUTEX(mIngoingMutex); - mIncomingQueue.insert(inMap::value_type(mi->mailId, mi)); - } - break; - } - case GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM_deprecated: - { - OutgoingRecord_deprecated* dot = dynamic_cast(v); - - if(dot) - { - std::cerr << "(EE) Read a deprecated GxsTrans outgoing item. Converting to new format..." << std::endl; - - OutgoingRecord ot(dot->recipient,dot->clientService,&dot->mailData[0],dot->mailData.size()) ; - - ot.status = dot->status ; - - ot.author.clear(); // These 3 fields cannot be stored in mailItem.meta, which is not serialised, so they are lost. - ot.group_id.clear() ; - ot.sent_ts = 0; - - ot.mailItem = dot->mailItem ; - ot.presignedReceipt = dot->presignedReceipt; - - RS_STACK_MUTEX(mOutgoingMutex); - mOutgoingQueue.insert(prMap::value_type(ot.mailItem.mailId, ot)); - -#ifdef DEBUG_GXSTRANS - std::cerr << "Loaded outgoing item (converted), ID " << std::hex << std::setfill('0') << std::setw(16) << ot.mailItem.mailId<< std::dec << ", Group id: " << ot.group_id << ", TS=" << ot.sent_ts << std::endl; -#endif - } - delete v; - break; - } - - case GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM: - { - OutgoingRecord* ot = dynamic_cast(v); - if(ot) - { - RS_STACK_MUTEX(mOutgoingMutex); - mOutgoingQueue.insert( - prMap::value_type(ot->mailItem.mailId, *ot)); - -#ifdef DEBUG_GXSTRANS - std::cerr << "Loading outgoing item, ID " << std::hex << std::setfill('0') << std::setw(16) << ot->mailItem.mailId<< std::dec << "Group id: " << ot->group_id << ", TS=" << ot->sent_ts << std::endl; -#endif - } - delete v; - break; - } - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_GROUP: - default: - std::cerr << "p3GxsTrans::loadList(...) (EE) got item with " - << "unhandled type: " - << static_cast(v->PacketSubType()) - << std::endl; - delete v; - break; - } - -#ifdef DEBUG_GXSTRANS - std::cout << "p3GxsTrans::loadList(...) " << loadList.size() << " " - << mIncomingQueue.size() << " " << mOutgoingQueue.size() - << std::endl; -#endif - - return true; -} - -bool p3GxsTrans::acceptNewMessage(const RsGxsMsgMetaData *msgMeta,uint32_t msg_size) -{ - // 1 - check the total size of the msgs for the author of this particular msg. - - // 2 - Reject depending on embedded limits. - - // Depending on reputation, the messages will be rejected: - // - // Reputation | Maximum msg count | Maximum msg size - // ------------+----------------------+------------------ - // Negative | 0 | 0 // This is already handled by the anti-spam - // R-Negative | 10 | 10k - // Neutral | 100 | 20k - // R-Positive | 400 | 1M - // Positive | 1000 | 2M - - // Ideally these values should be left as user-defined parameters, with the - // default values below used as backup. - - static const uint32_t GXSTRANS_MAX_COUNT_REMOTELY_NEGATIVE_DEFAULT = 10 ; - static const uint32_t GXSTRANS_MAX_COUNT_NEUTRAL_DEFAULT = 40 ; - static const uint32_t GXSTRANS_MAX_COUNT_REMOTELY_POSITIVE_DEFAULT = 400 ; - static const uint32_t GXSTRANS_MAX_COUNT_LOCALLY_POSITIVE_DEFAULT = 1000 ; - - static const uint32_t GXSTRANS_MAX_SIZE_REMOTELY_NEGATIVE_DEFAULT = 10 * 1024 ; - static const uint32_t GXSTRANS_MAX_SIZE_NEUTRAL_DEFAULT = 200 * 1024 ; - static const uint32_t GXSTRANS_MAX_SIZE_REMOTELY_POSITIVE_DEFAULT = 1024 * 1024 ; - static const uint32_t GXSTRANS_MAX_SIZE_LOCALLY_POSITIVE_DEFAULT = 2 * 1024 * 1024 ; - - uint32_t max_count = 0 ; - uint32_t max_size = 0 ; - uint32_t identity_flags = 0 ; - - RsReputationLevel rep_lev = - rsReputations->overallReputationLevel( - msgMeta->mAuthorId, &identity_flags ); - - switch(rep_lev) - { - case RsReputationLevel::REMOTELY_NEGATIVE: - max_count = GXSTRANS_MAX_COUNT_REMOTELY_NEGATIVE_DEFAULT; - max_size = GXSTRANS_MAX_SIZE_REMOTELY_NEGATIVE_DEFAULT; - break ; - case RsReputationLevel::NEUTRAL: - max_count = GXSTRANS_MAX_COUNT_NEUTRAL_DEFAULT; - max_size = GXSTRANS_MAX_SIZE_NEUTRAL_DEFAULT; - break; - case RsReputationLevel::REMOTELY_POSITIVE: - max_count = GXSTRANS_MAX_COUNT_REMOTELY_POSITIVE_DEFAULT; - max_size = GXSTRANS_MAX_SIZE_REMOTELY_POSITIVE_DEFAULT; - break; - case RsReputationLevel::LOCALLY_POSITIVE: - max_count = GXSTRANS_MAX_COUNT_LOCALLY_POSITIVE_DEFAULT; - max_size = GXSTRANS_MAX_SIZE_LOCALLY_POSITIVE_DEFAULT; - break; - case RsReputationLevel::LOCALLY_NEGATIVE: // fallthrough - default: - max_count = 0; - max_size = 0; - break; - } - - bool pgp_linked = identity_flags & RS_IDENTITY_FLAGS_PGP_LINKED; - - if(rep_lev <= RsReputationLevel::NEUTRAL && !pgp_linked) - { - max_count /= 10 ; - max_size /= 10 ; - } - - RS_STACK_MUTEX(mPerUserStatsMutex); - - MsgSizeCount& s(per_user_statistics[msgMeta->mAuthorId]); - -#ifdef DEBUG_GXSTRANS - std::cerr << "GxsTrans::acceptMessage(): size=" << msg_size << ", grp=" << msgMeta->mGroupId << ", gxs_id=" << msgMeta->mAuthorId << ", pgp_linked=" << pgp_linked << ", current (size,cnt)=(" - << s.size << "," << s.count << ") reputation=" << rep_lev << ", limits=(" << max_size << "," << max_count << ") " ; -#endif - - if(s.size + msg_size > max_size || 1+s.count > max_count) - { -#ifdef DEBUG_GXSTRANS - std::cerr << "=> rejected." << std::endl; -#endif - return false ; - } - else - { -#ifdef DEBUG_GXSTRANS - std::cerr << "=> accepted." << std::endl; -#endif - - s.count++ ; - s.size += msg_size ; // update the statistics, so that it's not possible to pass a bunch of msgs at once below the limits. - - return true ; - } -} - - -bool p3GxsTrans::getGroupStatistics(std::map& stats) -{ - uint32_t token1; - - RsTokReqOptions opts1; - opts1.mReqType = GXS_REQUEST_TYPE_GROUP_META; - if( !requestGroupInfo(token1, opts1) || waitToken(token1) != RsTokenService::COMPLETE ) - return false; - - std::list group_metas; - getGroupSummary(token1,group_metas); - - for(auto& group_meta:group_metas) - { - RsGxsTransGroupStatistics& stat(stats[group_meta.mGroupId]); - - uint32_t token2; - if(!RsGxsIfaceHelper::requestGroupStatistic(token2,group_meta.mGroupId) || waitToken(token2) != RsTokenService::COMPLETE) - continue; - - RsGenExchange::getGroupStatistic(token2,stat); - - stat.popularity = group_meta.mPop ; - stat.subscribed = IS_GROUP_SUBSCRIBED(group_meta.mSubscribeFlags) ; - stat.mGrpId = group_meta.mGroupId ; - - std::vector metas; - - uint32_t token3; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_META; - - std::list groupIds; - groupIds.push_back(group_meta.mGroupId); - - if( !requestMsgInfo(token3, opts, groupIds) || waitToken(token3, std::chrono::seconds(5)) != RsTokenService::COMPLETE ) - continue; - - GxsMsgMetaMap metaMap; - if(!RsGenExchange::getMsgMeta(token3, metaMap) || metaMap.size() != 1) - continue; - - for(auto& meta: metaMap.begin()->second) - stat.addMessageMeta(group_meta.mGroupId,meta) ; - } - - return true; -} - - diff --git a/libretroshare/src/gxstrans/p3gxstrans.h b/libretroshare/src/gxstrans/p3gxstrans.h deleted file mode 100644 index aff7b9eda..000000000 --- a/libretroshare/src/gxstrans/p3gxstrans.h +++ /dev/null @@ -1,342 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxstrans: p3gxstrans.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include - -#include "retroshare/rsgxsifacetypes.h" // For RsGxsId, RsGxsCircleId -#include "gxs/gxstokenqueue.h" // For GxsTokenQueue -#include "gxstrans/p3gxstransitems.h" -#include "services/p3idservice.h" // For p3IdService -#include "util/rsthreads.h" -#include "retroshare/rsgxstrans.h" - -class p3GxsTrans; - -/// Services who want to make use of p3GxsTrans should inherit this struct -struct GxsTransClient -{ - /** - * This will be called by p3GxsTrans to dispatch mails to the subservice - * @param authorId message sender - * @param decryptId recipient id - * @param data buffer containing the decrypted data - * @param dataSize size of the buffer - * @return true if dispatching goes fine, false otherwise - */ - virtual bool receiveGxsTransMail( const RsGxsId& authorId, - const RsGxsId& recipientId, - const uint8_t* data, uint32_t dataSize - ) = 0; - - /** - * This will be called by p3GxsTrans to notify the subservice about the - * status of a sent email. - * @param originalMessage message for with the notification is made - * @param status the new status of the message - * @return true if notification goes fine, false otherwise (ignored ATM) - */ - virtual bool notifyGxsTransSendStatus( RsGxsTransId mailId, - GxsTransSendStatus status ) = 0; -}; - -struct MsgSizeCount -{ - MsgSizeCount() : size(0),count(0) {} - - uint32_t size ; - uint32_t count ; -}; - -/** - * @brief p3GxsTrans asyncronous redundant small mail trasport on top of GXS. - * p3GxsTrans is capable of asynchronous mail delivery and acknowledgement. - * p3GxsTrans is meant to be capable of multiple encryption options, - * @see RsGxsTransEncryptionMode at moment messages are encrypted using RSA - * unless the user ask for them being sent in clear text ( this is not supposed - * to happen in non testing environment so warnings and stack traces are printed - * in the log if an attempt to send something in clear text is made ). - * p3GxsTrans try to hide metadata so the travelling message signed by the author - * but the recipient is not disclosed, instead to avoid everyone trying to - * decrypt every message a hint has been introduced, the hint is calculated in a - * way that one can easily prove that a message is not destined to someone, but - * cannot prove the message is destined to someone - * @see RsGxsTransMailItem::recipientHint for more details. - * p3GxsTrans expose a simple API to send and receive mails, the API also - * provide notification for the sending mail status @see sendMail(...), - * @see querySendStatus(...), @see registerGxsTransClient(...), - * @see GxsTransClient::receiveGxsTransMail(...), - * @see GxsTransClient::notifyGxsTransSendStatus(...). - */ -class p3GxsTrans : public RsGenExchange, public GxsTokenQueue, public p3Config, public RsGxsTrans -{ -public: - p3GxsTrans( RsGeneralDataService* gds, RsNetworkExchangeService* nes, - p3IdService& identities ) : - RsGenExchange( gds, nes, new RsGxsTransSerializer(), - RS_SERVICE_TYPE_GXS_TRANS, &identities, - AuthenPolicy()), - GxsTokenQueue(this), - RsGxsTrans(static_cast(*this)), - // always check 30 secs after start) - mLastMsgCleanup(time(NULL) - MAX_DELAY_BETWEEN_CLEANUPS + 30), - mIdService(identities), - mServClientsMutex("p3GxsTrans client services map mutex"), - mOutgoingMutex("p3GxsTrans outgoing queue map mutex"), - mIngoingMutex("p3GxsTrans ingoing queue map mutex"), - mCleanupThread(nullptr), - mPerUserStatsMutex("p3GxsTrans user stats mutex"), - mDataMutex("p3GxsTrans data mutex") {} - - virtual ~p3GxsTrans(); - - /*! - * \brief getStatistics - * Gathers all sorts of statistics about the data transported by p3GxsTrans, in order to display info about the running status, - * message transport, etc. This is a blocking call. Use it in a thread. - * \param stats This structure contains all statistics information. - * \return true is the call succeeds. - */ - - virtual bool getDataStatistics(GxsTransStatistics& stats) override; - - /*! - * \brief getGroupStatistics - * Gathers statistics about GXS groups and messages used by GxsTrans to transport data. This is a blocking call. Use it in a thread. - * \param stats - * \return true if the data collection succeeds. - */ - virtual bool getGroupStatistics(std::map& stats) override; - - /** - * Send an email to recipient, in the process author of the email is - * disclosed to the network (because the sent GXS item is signed), while - * recipient is not @see RsGxsTransMailItem::recipientHint for details on - * recipient protection. - * This method is part of the public interface of this service. - * @return true if the mail will be sent, false if not - */ - bool sendData( RsGxsTransId& mailId, - GxsTransSubServices service, - const RsGxsId& own_gxsid, const RsGxsId& recipient, - const uint8_t* data, uint32_t size, - RsGxsTransEncryptionMode cm = RsGxsTransEncryptionMode::RSA - ); - - /** - * This method is part of the public interface of this service. - * @return false if mail is not found in outgoing queue, true otherwise - */ - bool querySendStatus( RsGxsTransId mailId, GxsTransSendStatus& st ); - - /** - * Register a client service to p3GxsTrans to receive mails via - * GxsTransClient::receiveGxsTransMail(...) callback - * This method is part of the public interface of this service. - */ - void registerGxsTransClient( GxsTransSubServices serviceType, - GxsTransClient* service ); - - /// @see RsGenExchange::getServiceInfo() - virtual RsServiceInfo getServiceInfo() override { return RsServiceInfo( RS_SERVICE_TYPE_GXS_TRANS, "GXS Mails", 0, 1, 0, 1 ); } - - static const uint32_t GXS_STORAGE_PERIOD = 15*86400; // 15 days. - static const uint32_t GXS_SYNC_PERIOD = 15*86400; -private: - /** Time interval of inactivity before a distribution group is unsubscribed. - * Approximatively 3 months seems ok ATM. */ - const static int32_t UNUSED_GROUP_UNSUBSCRIBE_INTERVAL = 16*86400; // 16 days - - /** - * This should be as little as possible as the size of the database can grow - * very fast taking in account we are handling mails for the whole network. - * We do prefer to resend a not acknowledged yet mail after - * GXS_STORAGE_PERIOD has passed and keep it little. - * Tought it can't be too little as this may cause signed receipts to - * get lost thus causing resend and fastly grow perceived async latency, in - * case two sporadically connected users sends mails each other. - * While it is ok for signed acknowledged to stays in the DB for a - * full GXS_STORAGE_PERIOD, mails should be removed as soon as a valid - * signed acknowledged is received for each of them. - * Two weeks seems fair ATM. - */ - static const uint32_t MAX_DELAY_BETWEEN_CLEANUPS ; // every 20 mins. Could be less. - - rstime_t mLastMsgCleanup ; - - /// Define how the backend should handle authentication based on signatures - static uint32_t AuthenPolicy(); - - /// Types to mark queries in tokens queue - enum GxsReqResTypes - { - GROUPS_LIST = 1, - GROUP_CREATE = 2, - MAILS_UPDATE = 3 - }; - - /// Store the id of the preferred GXS group to send emails - RsGxsGroupId mPreferredGroupId; - - /// Used for items {de,en}cryption - p3IdService& mIdService; - - /// Stores pointers to client services to notify them about new mails - std::map mServClients; - RsMutex mServClientsMutex; - - /** - * @brief Keep track of outgoing mails. - * Records enter the queue when a mail is sent, and are removed when a - * receipt has been received or sending is considered definetly failed. - * Items are saved in config for consistence accross RetroShare shutdowns. - */ - typedef std::map prMap; - prMap mOutgoingQueue; - RsMutex mOutgoingMutex; - void locked_processOutgoingRecord(OutgoingRecord& r); - - /** - * @brief Ingoing mail and receipt processing queue. - * At shutdown remaining items are saved in config and then deleted in - * destructor for consistence accross RetroShare instances. - * In order to avoid malicious messages ( non malicious collision has 1/2^64 - * probablity ) to smash items in the queue thus causing previous incoming - * item to not being processed and memleaked multimap is used instead of map - * for incoming queue. - */ - typedef std::unordered_multimap inMap; - inMap mIncomingQueue; - RsMutex mIngoingMutex; - - /// @see GxsTokenQueue::handleResponse(uint32_t token, uint32_t req_type - /// , RsTokenService::GxsRequestStatus status) - virtual void handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) override; - - /// @see RsGenExchange::service_tick() - virtual void service_tick() override; - - /// @see RsGenExchange::service_CreateGroup(...) - RsGenExchange::ServiceCreate_Return service_CreateGroup( - RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& ) override; - - /// @see RsGenExchange::notifyChanges(std::vector &changes) - void notifyChanges(std::vector &changes) override; - - /// @see p3Config::setupSerialiser() - virtual RsSerialiser* setupSerialiser() override; - - /// @see p3Config::saveList(bool &cleanup, std::list&) - virtual bool saveList(bool &cleanup, std::list&saveList) override; - - /// @see p3Config::saveDone() - void saveDone() override; - - /// @see p3Config::loadList(std::list&) - virtual bool loadList(std::list& loadList) override; - - /// Request groups list to GXS backend. Async method. - bool requestGroupsData(const std::list* groupIds = NULL); - - /** - * Check if current preferredGroupId is the best against potentialGrId, if - * the passed one is better update it. - * Useful when GXS backend notifies groups changes, or when a reponse to an - * async grop request (@see GXS_REQUEST_TYPE_GROUP_*) is received. - * @return true if preferredGroupId has been supeseded by potentialGrId - * false otherwise. - */ - bool inline locked_supersedePreferredGroup(const RsGxsGroupId& potentialGrId) - { - if(mPreferredGroupId < potentialGrId) - { - // std::cerr << "supersedePreferredGroup(...) " << potentialGrId << " supersed " << mPreferredGroupId << std::endl; - mPreferredGroupId = potentialGrId; - return true; - } - return false; - } - - /** @return true if has passed more then interval seconds between timeStamp - * and ref. @param ref by default now is taked as reference. */ - bool static inline olderThen(rstime_t timeStamp, int32_t interval, - rstime_t ref = time(NULL)) - { return (timeStamp + interval) < ref; } - - - /// Decrypt email content and pass it to dispatchDecryptedMail(...) - bool handleEncryptedMail(const RsGxsTransMailItem* mail); - - /// Dispatch the message to the recipient service - bool dispatchDecryptedMail( const RsGxsId& authorId, - const RsGxsId& decryptId, - const uint8_t* decrypted_data, - uint32_t decrypted_data_size ); - - void notifyClientService(const OutgoingRecord& pr); - - /// Checks the integrity message and groups - class GxsTransIntegrityCleanupThread : public RsThread - { - enum CheckState { CheckStart, CheckChecking }; - - public: - explicit GxsTransIntegrityCleanupThread( - RsGeneralDataService* const dataService ): - mDs(dataService), mMtx("GxsTransIntegrityCheck"), mDone(false) {} - - bool isDone(); - void run(); - - void getDeletedIds(std::list& grpIds, std::map >& msgIds); - - void getMessagesToDelete(GxsMsgReq& req) ; - void getPerUserStatistics(std::map& m) ; - - private: - RsGeneralDataService* const mDs; - RsMutex mMtx ; - - GxsMsgReq mMsgToDel ; - std::map total_message_size_and_count; - bool mDone; - }; - - // Overloaded from RsGenExchange. - - bool acceptNewMessage(const RsGxsMsgMetaData *msgMeta, uint32_t size) override; - - GxsTransIntegrityCleanupThread *mCleanupThread ; - - // statistics of the load across all groups, per user. - - RsMutex mPerUserStatsMutex; - std::map per_user_statistics ; - - // Mutex to protect local data - - RsMutex mDataMutex; -}; - diff --git a/libretroshare/src/gxstrans/p3gxstransitems.cc b/libretroshare/src/gxstrans/p3gxstransitems.cc deleted file mode 100644 index 733d40bec..000000000 --- a/libretroshare/src/gxstrans/p3gxstransitems.cc +++ /dev/null @@ -1,68 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxstrans: p3gxstrans.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016-2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "gxstrans/p3gxstransitems.h" -#include "serialiser/rstypeserializer.h" - -const RsGxsId RsGxsTransMailItem::allRecipientsHint("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); - -OutgoingRecord_deprecated::OutgoingRecord_deprecated() - : RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_TRANS, static_cast(GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM_deprecated) ) { clear();} - -OutgoingRecord::OutgoingRecord() - : RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_TRANS, static_cast(GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM) ) { clear();} - -OutgoingRecord::OutgoingRecord( RsGxsId rec, GxsTransSubServices cs, - const uint8_t* data, uint32_t size ) : - RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_TRANS, - static_cast(GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM) ), - status(GxsTransSendStatus::PENDING_PROCESSING), recipient(rec), - clientService(cs) -{ - mailData.resize(size); - memcpy(&mailData[0], data, size); -} - -void OutgoingRecord_deprecated::serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - RS_SERIAL_PROCESS(status); - RS_SERIAL_PROCESS(recipient); - RS_SERIAL_PROCESS(mailItem); - RS_SERIAL_PROCESS(mailData); - RS_SERIAL_PROCESS(clientService); - RS_SERIAL_PROCESS(presignedReceipt); -} - -void OutgoingRecord::serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) -{ - RS_SERIAL_PROCESS(status); - RS_SERIAL_PROCESS(recipient); - RS_SERIAL_PROCESS(author); - RS_SERIAL_PROCESS(group_id); - RS_SERIAL_PROCESS(sent_ts); - RS_SERIAL_PROCESS(mailItem); - RS_SERIAL_PROCESS(mailData); - RS_SERIAL_PROCESS(clientService); - RS_SERIAL_PROCESS(presignedReceipt); -} diff --git a/libretroshare/src/gxstrans/p3gxstransitems.h b/libretroshare/src/gxstrans/p3gxstransitems.h deleted file mode 100644 index f2cab3cfe..000000000 --- a/libretroshare/src/gxstrans/p3gxstransitems.h +++ /dev/null @@ -1,270 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxstrans: p3gxstrans.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016-2017 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include - -#include "rsitems/rsgxsitems.h" -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstlvidset.h" -#include "retroshare/rsgxsflags.h" -#include "retroshare/rsgxstrans.h" -#include "retroshare/rsgxscircles.h" // For: GXS_CIRCLE_TYPE_PUBLIC -#include "services/p3idservice.h" -#include "serialiser/rstypeserializer.h" - -class RsNxsTransPresignedReceipt : public RsNxsMsg -{ -public: - RsNxsTransPresignedReceipt() : RsNxsMsg(RS_SERVICE_TYPE_GXS_TRANS) {} - - virtual ~RsNxsTransPresignedReceipt() {} -}; - -class RsGxsTransBaseMsgItem : public RsGxsMsgItem -{ -public: - explicit RsGxsTransBaseMsgItem(GxsTransItemsSubtypes subtype) : - RsGxsMsgItem( RS_SERVICE_TYPE_GXS_TRANS, - static_cast(subtype) ), mailId(0) {} - - virtual ~RsGxsTransBaseMsgItem() {} - - RsGxsTransId mailId; - - void inline clear() - { - mailId = 0; - meta = RsMsgMetaData(); - } - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { RS_SERIAL_PROCESS(mailId); } -}; - -class RsGxsTransPresignedReceipt : public RsGxsTransBaseMsgItem -{ -public: - RsGxsTransPresignedReceipt() : RsGxsTransBaseMsgItem(GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT) {} - virtual ~RsGxsTransPresignedReceipt() {} -}; - -enum class RsGxsTransEncryptionMode : uint8_t -{ - CLEAR_TEXT = 1, - RSA = 2, - UNDEFINED_ENCRYPTION = 250 -}; - -class RsGxsTransMailItem : public RsGxsTransBaseMsgItem -{ -public: - RsGxsTransMailItem() : - RsGxsTransBaseMsgItem(GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL), - cryptoType(RsGxsTransEncryptionMode::UNDEFINED_ENCRYPTION) {} - - virtual ~RsGxsTransMailItem() {} - - RsGxsTransEncryptionMode cryptoType; - - /** - * @brief recipientHint used instead of plain recipient id, so sender can - * decide the equilibrium between exposing the recipient and the cost of - * completely anonymize it. So a bunch of luky non recipient can conclude - * rapidly that they are not the recipient without trying to decrypt the - * message. - * - * To be able to decide how much metadata we disclose sending a message we - * send an hint instead of the recipient id in clear, the hint cannot be - * false (the recipient would discard the mail) but may be arbitrarly - * obscure like 0xFF...FF so potentially everyone could be the recipient, or - * may expose the complete recipient id or be a middle ground. - * To calculate arbitrary precise hint one do a bitwise OR of the recipients - * keys and an arbitrary salt, the more recipients has the mail and the more - * 1 bits has the salt the less accurate is the hint. - * This way the sender is able to adjust the metadata privacy needed for the - * message, in the more private case (recipientHint == 0xFFF...FFF) no one - * has a clue about who is the actual recipient, while this imply the cost - * that every potencial recipient has to try to decrypt it to know if it is - * for herself. This way a bunch of non recipients can rapidly discover that - * the message is not directed to them without attempting it's decryption. - * - * To check if one id may be the recipient of the mail or not one need to - * bitwise compare the hint with the id, if at least one bit of the hint is - * 0 while the corresponding bit in the id is 1 then the id cannot be the - * recipient of the mail. - * - * Note that by design one can prove that an id is not recipient of the mail - * but cannot prove it is. - * Also in the extreme case of using 0x00...00 as salt that is equivalent - * to not salting at all (aka the plain recipient id is used as hint) a - * malicious observer could not demostrate in a conclusive manner that the - * mail is directed to the actual recipient as the "apparently" - * corresponding hint may be fruit of a "luky" salting of another id. - */ - RsGxsId recipientHint; - void inline saltRecipientHint(const RsGxsId& salt) - { recipientHint = recipientHint | salt; } - - /** - * @brief maybeRecipient given an id and an hint check if they match - * @see recipientHint - * @return true if the id may be recipient of the hint, false otherwise - */ - bool inline maybeRecipient(const RsGxsId& id) const - { return (~id|recipientHint) == allRecipientsHint; } - - const static RsGxsId allRecipientsHint; - - /** This should travel encrypted, unless EncryptionMode::CLEAR_TEXT - * is specified */ - std::vector payload; - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RsGxsTransBaseMsgItem::serial_process(j, ctx); - RS_SERIAL_PROCESS(cryptoType); - RS_SERIAL_PROCESS(recipientHint); - RS_SERIAL_PROCESS(payload); - } - - void clear() - { - RsGxsTransBaseMsgItem::clear(); - cryptoType = RsGxsTransEncryptionMode::UNDEFINED_ENCRYPTION; - recipientHint.clear(); - payload.clear(); - } - - /// Maximum mail size in bytes 10 MiB is more than anything sane can need - const static uint32_t MAX_SIZE = 10*8*1024*1024; -}; - -class RsGxsTransGroupItem : public RsGxsGrpItem -{ -public: - RsGxsTransGroupItem() : - RsGxsGrpItem( RS_SERVICE_TYPE_GXS_TRANS, - static_cast( - GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_GROUP) ) - { - meta.mGroupFlags = GXS_SERV::FLAG_PRIVACY_PUBLIC; - meta.mGroupName = "Mail"; - meta.mCircleType = GXS_CIRCLE_TYPE_PUBLIC; - } - virtual ~RsGxsTransGroupItem() {} - - // TODO: Talk with Cyril why there is no RsGxsGrpItem::serial_process - virtual void serial_process(RsGenericSerializer::SerializeJob /*j*/, - RsGenericSerializer::SerializeContext& /*ctx*/) - {} - - void clear() {} -}; - -class RsGxsTransSerializer; - -class OutgoingRecord_deprecated : public RsItem -{ -public: - OutgoingRecord_deprecated( RsGxsId rec, GxsTransSubServices cs, const uint8_t* data, uint32_t size ); - - virtual ~OutgoingRecord_deprecated() {} - - GxsTransSendStatus status; - RsGxsId recipient; - /// Don't use a pointer would be invalid after publish - RsGxsTransMailItem mailItem; - - std::vector mailData; - GxsTransSubServices clientService; - - RsNxsTransPresignedReceipt presignedReceipt; - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ); - - void clear() {} - -private: - friend class RsGxsTransSerializer; - OutgoingRecord_deprecated(); -}; - -class OutgoingRecord : public RsItem -{ -public: - OutgoingRecord( RsGxsId rec, GxsTransSubServices cs, - const uint8_t* data, uint32_t size ); - - virtual ~OutgoingRecord() {} - - GxsTransSendStatus status; - RsGxsId recipient; - - RsGxsId author; // These 3 fields cannot be stored in mailItem.meta, which is not serialised. - RsGxsGroupId group_id ; - uint32_t sent_ts ; - - /// Don't use a pointer would be invalid after publish - RsGxsTransMailItem mailItem; - - std::vector mailData; - GxsTransSubServices clientService; - - RsNxsTransPresignedReceipt presignedReceipt; - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ); - - void clear() {} - -private: - friend class RsGxsTransSerializer; - OutgoingRecord(); -}; - - -class RsGxsTransSerializer : public RsServiceSerializer -{ -public: - RsGxsTransSerializer() : RsServiceSerializer(RS_SERVICE_TYPE_GXS_TRANS) {} - virtual ~RsGxsTransSerializer() {} - - RsItem* create_item(uint16_t service_id, uint8_t item_sub_id) const - { - if(service_id != RS_SERVICE_TYPE_GXS_TRANS) return NULL; - - switch(static_cast(item_sub_id)) - { - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL: return new RsGxsTransMailItem(); - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT: return new RsGxsTransPresignedReceipt(); - case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_GROUP: return new RsGxsTransGroupItem(); - case GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM_deprecated: return new OutgoingRecord_deprecated(); - case GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM: return new OutgoingRecord(); - default: return NULL; - } - } -}; - diff --git a/libretroshare/src/gxstunnel/p3gxstunnel.cc b/libretroshare/src/gxstunnel/p3gxstunnel.cc deleted file mode 100644 index e500f82b0..000000000 --- a/libretroshare/src/gxstunnel/p3gxstunnel.cc +++ /dev/null @@ -1,1774 +0,0 @@ -/******************************************************************************* - * libretroshare/src/chat: distantchat.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2015 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include - -#include "openssl/rand.h" -#include "openssl/dh.h" -#include "openssl/err.h" - -#include "crypto/rsaes.h" -#include "util/rsprint.h" -#include "util/rsmemory.h" - -#include -#include - -#include -#include -#include -#include -#include - -#include "p3gxstunnel.h" - -//#define DEBUG_GXS_TUNNEL - -static const uint32_t GXS_TUNNEL_KEEP_ALIVE_TIMEOUT = 6 ; // send keep alive packet so as to avoid tunnel breaks. - -static const uint32_t RS_GXS_TUNNEL_DH_STATUS_UNINITIALIZED = 0x0000 ; -static const uint32_t RS_GXS_TUNNEL_DH_STATUS_HALF_KEY_DONE = 0x0001 ; -static const uint32_t RS_GXS_TUNNEL_DH_STATUS_KEY_AVAILABLE = 0x0002 ; - -static const uint32_t RS_GXS_TUNNEL_DELAY_BETWEEN_RESEND = 10 ; // re-send every 10 secs. -static const uint32_t RS_GXS_TUNNEL_DATA_PRINT_STORAGE_DELAY = 600 ; // store old message ids for 10 minutes. - -static const uint32_t GXS_TUNNEL_ENCRYPTION_HMAC_SIZE = SHA_DIGEST_LENGTH ; -static const uint32_t GXS_TUNNEL_ENCRYPTION_IV_SIZE = 8 ; - -#ifdef DEBUG_GXS_TUNNEL -static const uint32_t INTERVAL_BETWEEN_DEBUG_DUMP = 10 ; -#endif - -static std::string GXS_TUNNEL_APP_NAME = "GxsTunnels" ; - -static const uint8_t GXS_TUNNEL_APP_MAJOR_VERSION = 0x01 ; -static const uint8_t GXS_TUNNEL_APP_MINOR_VERSION = 0x00 ; -static const uint8_t GXS_TUNNEL_MIN_MAJOR_VERSION = 0x01 ; -static const uint8_t GXS_TUNNEL_MIN_MINOR_VERSION = 0x00 ; - -RsGxsTunnelService *rsGxsTunnel = NULL ; - -p3GxsTunnelService::p3GxsTunnelService(RsGixs *pids) - : mGixs(pids), mGxsTunnelMtx("GXS tunnel") -{ - mTurtle = NULL ; - mCurrentPacketCounter = 0 ; -} - -void p3GxsTunnelService::connectToTurtleRouter(p3turtle *tr) -{ - mTurtle = tr ; - tr->registerTunnelService(this) ; -} - -bool p3GxsTunnelService::registerClientService(uint32_t service_id,RsGxsTunnelService::RsGxsTunnelClientService *service) -{ - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - if(mRegisteredServices.find(service_id) != mRegisteredServices.end()) - { - std::cerr << "(EE) p3GxsTunnelService::registerClientService(): trying to register client " << std::hex << service_id << std::dec << ", which is already registered!" << std::endl; - return false; - } -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "p3GxsTunnelService::registerClientService(): registering client service " << std::hex << service_id << std::dec << std::endl; -#endif - - mRegisteredServices[service_id] = service ; - return true ; -} - -int p3GxsTunnelService::tick() -{ - -#ifdef DEBUG_GXS_TUNNEL - rstime_t now = time(NULL); - static rstime_t last_dump = 0; - - if(now > last_dump + INTERVAL_BETWEEN_DEBUG_DUMP ) - { - last_dump = now ; - debug_dump() ; - } -#endif - - flush() ; - - return 0 ; -} - -RsServiceInfo p3GxsTunnelService::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_GXS_TUNNEL, - GXS_TUNNEL_APP_NAME, - GXS_TUNNEL_APP_MAJOR_VERSION, - GXS_TUNNEL_APP_MINOR_VERSION, - GXS_TUNNEL_MIN_MAJOR_VERSION, - GXS_TUNNEL_MIN_MINOR_VERSION); -} - -void p3GxsTunnelService::flush() -{ - // Flush pending DH items. This is a higher priority, so we deal with them first. - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "p3GxsTunnelService::flush() flushing pending items." << std::endl; -#endif - { - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - for(std::list::iterator it=pendingDHItems.begin();it!=pendingDHItems.end();) - if(locked_sendClearTunnelData(*it) ) - { - delete *it ; - it = pendingDHItems.erase(it) ; - } - else - ++it ; - } - - // Flush items that could not be sent, probably because of a Mutex protected zone. - // - { - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - for(std::list::iterator it=pendingGxsTunnelItems.begin();it!=pendingGxsTunnelItems.end();) - if(locked_sendEncryptedTunnelData(*it) ) - { - delete *it ; - it = pendingGxsTunnelItems.erase(it) ; - } - else - { - ++it ; -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "Cannot send encrypted data item to tunnel " << (*it)->PeerId() << std::endl; -#endif - } - } - - // Look at pending data item, and re-send them if necessary. - - { - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - rstime_t now = time(NULL) ; - - for(std::map::iterator it = pendingGxsTunnelDataItems.begin();it != pendingGxsTunnelDataItems.end();++it) - if(now > RS_GXS_TUNNEL_DELAY_BETWEEN_RESEND + it->second.last_sending_attempt) - { - if(locked_sendEncryptedTunnelData(it->second.data_item)) - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " sending data item #" << std::hex << it->first << std::dec << std::endl; -#endif - it->second.last_sending_attempt = now ; - } -#ifdef DEBUG_GXS_TUNNEL - else - std::cerr << " Cannot send item " << std::hex << it->first << std::dec << std::endl; -#endif - } - } - - // TODO: also sweep GXS id map and disable any ID with no virtual peer id in the list. - - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - rstime_t now = time(NULL) ; - - for(std::map::iterator it(_gxs_tunnel_contacts.begin());it!=_gxs_tunnel_contacts.end();) - { - // All sorts of cleaning. We start with the ones that may remove stuff, for efficiency reasons. - - // 1 - Remove any tunnel that was remotely closed, since we cannot use it anymore. - - if(it->second.status == RS_GXS_TUNNEL_STATUS_REMOTELY_CLOSED && it->second.last_contact + 20 < now) - { - std::map::iterator tmp = it ; - ++tmp ; - _gxs_tunnel_contacts.erase(it) ; - it=tmp ; - continue ; - } - - // 2 - re-digg tunnels that have died out of inaction - - if(it->second.last_contact+20+GXS_TUNNEL_KEEP_ALIVE_TIMEOUT < now && it->second.status == RS_GXS_TUNNEL_STATUS_CAN_TALK) - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "(II) GxsTunnelService:: connection interrupted with peer." << std::endl; -#endif - - it->second.status = RS_GXS_TUNNEL_STATUS_TUNNEL_DN ; - it->second.virtual_peer_id.clear() ; - - // Also reset turtle router monitoring so as to make the tunnel handling more responsive. If we don't do that, - // the TR will wait 60 secs for the tunnel to die, which causes a significant waiting time in the chat window. - - if(it->second.direction == RsTurtleGenericTunnelItem::DIRECTION_SERVER) - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "(II) GxsTunnelService:: forcing new tunnel campain." << std::endl; -#endif - - mTurtle->forceReDiggTunnels( randomHashFromDestinationGxsId(it->second.to_gxs_id) ); - } - } - - // send keep alive packets to active tunnels. - - if(it->second.last_keep_alive_sent + GXS_TUNNEL_KEEP_ALIVE_TIMEOUT < now && it->second.status == RS_GXS_TUNNEL_STATUS_CAN_TALK) - { - RsGxsTunnelStatusItem *cs = new RsGxsTunnelStatusItem ; - - cs->status = RS_GXS_TUNNEL_FLAG_KEEP_ALIVE; - cs->PeerId(RsPeerId(it->first)) ; - - // we send off-mutex to avoid deadlock. - - pendingGxsTunnelItems.push_back(cs) ; - - it->second.last_keep_alive_sent = now ; -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "(II) GxsTunnelService:: Sending keep alive packet to gxs id " << it->first << std::endl; -#endif - } - - // clean old received data prints. - - for(std::map::iterator it2=it->second.received_data_prints.begin();it2!=it->second.received_data_prints.end();) - if(now > it2->second + RS_GXS_TUNNEL_DATA_PRINT_STORAGE_DELAY) - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "(II) erasing old data print for message #" << it2->first << " in tunnel " << it->first << std::endl; -#endif - std::map::iterator tmp(it2) ; - ++tmp ; - it->second.received_data_prints.erase(it2) ; - it2 = tmp ; - } - else - ++it2 ; - - ++it ; - } -} - -// In this function the PeerId is the GXS tunnel ID. - -void p3GxsTunnelService::handleIncomingItem(const RsGxsTunnelId& tunnel_id,RsGxsTunnelItem *item) -{ - if(item == NULL) - return ; - - // We have 3 things to do: - // - // 1 - if it's a data item, send an ACK - // 2 - if it's an ack item, mark the item as properly received, and remove it from the queue - // 3 - if it's a status item, act accordingly. - - switch(item->PacketSubType()) - { - - case RS_PKT_SUBTYPE_GXS_TUNNEL_DATA: handleRecvTunnelDataItem(tunnel_id,dynamic_cast(item)) ; - break ; - - case RS_PKT_SUBTYPE_GXS_TUNNEL_DATA_ACK: handleRecvTunnelDataAckItem(tunnel_id,dynamic_cast(item)) ; - break ; - - case RS_PKT_SUBTYPE_GXS_TUNNEL_STATUS: handleRecvStatusItem(tunnel_id,dynamic_cast(item)) ; - break ; - - default: - std::cerr << "(EE) impossible situation. DH items should be handled at the service level" << std::endl; - } - - delete item ; -} - -void p3GxsTunnelService::handleRecvTunnelDataAckItem(const RsGxsTunnelId &/*id*/,RsGxsTunnelDataAckItem *item) -{ - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "p3GxsTunnelService::handling RecvTunnelDataAckItem()" << std::endl; - std::cerr << " item counter = " << std::hex << item->unique_item_counter << std::dec << std::endl; -#endif - - // remove it from the queue. - - std::map::iterator it = pendingGxsTunnelDataItems.find(item->unique_item_counter) ; - - if(it == pendingGxsTunnelDataItems.end()) - { - std::cerr << " (EE) item number " << std::hex << item->unique_item_counter << std::dec << " is unknown. This is unexpected." << std::endl; - return ; - } - - delete it->second.data_item ; - pendingGxsTunnelDataItems.erase(it) ; -} - -void p3GxsTunnelService::handleRecvTunnelDataItem(const RsGxsTunnelId& tunnel_id,RsGxsTunnelDataItem *item) -{ - // imediately send an ACK for this item - - RsGxsTunnelDataAckItem *ackitem = new RsGxsTunnelDataAckItem ; - - ackitem->unique_item_counter = item->unique_item_counter ; - ackitem->PeerId(RsPeerId(tunnel_id)) ; - - { - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - pendingGxsTunnelItems.push_back(ackitem) ; // we use the queue that does not need an ACK, in order to avoid an infinite loop ;-) - } - - // notify the client for the received data - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "p3GxsTunnelService::handleRecvTunnelDataItem()" << std::endl; - std::cerr << " data size = " << item->data_size << std::endl; - std::cerr << " service id = " << std::hex << item->service_id << std::dec << std::endl; - std::cerr << " counter id = " << std::hex << item->unique_item_counter << std::dec << std::endl; -#endif - - RsGxsTunnelClientService *service = NULL ; - RsGxsId peer_from ; - bool is_client_side = false ; - - { - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - std::map::const_iterator it = mRegisteredServices.find(item->service_id) ; - - if(it == mRegisteredServices.end()) - { - std::cerr << " (EE) no registered service with ID " << std::hex << item->service_id << std::dec << ". Rejecting item." << std::endl; - return ; - } - service = it->second ; - - std::map::iterator it2 = _gxs_tunnel_contacts.find(tunnel_id) ; - - if(it2 != _gxs_tunnel_contacts.end()) - { - it2->second.client_services.insert(item->service_id) ; - peer_from = it2->second.to_gxs_id ; - is_client_side = (it2->second.direction == RsTurtleGenericDataItem::DIRECTION_SERVER); - } - - // Check if the item has already been received. This is necessary because we actually re-send items until an ACK is received. If the ACK gets lost (connection interrupted) the - // item may be received twice. This is conservative and ensure that no item is lost nor received twice. - - if(it2->second.received_data_prints.find(item->unique_item_counter) != it2->second.received_data_prints.end()) - { - std::cerr << "(WW) received the same data item #" << std::hex << item->unique_item_counter << std::dec << " twice in last 20 mins. Tunnel id=" << tunnel_id << ". Probably a replay. Item will be dropped." << std::endl; - return ; - } - it2->second.received_data_prints[item->unique_item_counter] = time(NULL) ; - } - - if(service->acceptDataFromPeer(peer_from,tunnel_id,is_client_side)) - service->receiveData(tunnel_id,item->data,item->data_size) ; - - item->data = NULL ; // avoids deletion, since the client has the memory now - item->data_size = 0 ; -} - -void p3GxsTunnelService::handleRecvStatusItem(const RsGxsTunnelId& tunnel_id, RsGxsTunnelStatusItem *cs) -{ - std::vector notifications ; - std::set clients ; - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "p3GxsTunnelService::handleRecvStatusItem(): tunnel_id=" << tunnel_id << " status=" << cs->status << std::endl; -#endif - - switch(cs->status) - { - case RS_GXS_TUNNEL_FLAG_CLOSING_DISTANT_CONNECTION: - { - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it = _gxs_tunnel_contacts.find(tunnel_id) ; - - if(it == _gxs_tunnel_contacts.end()) - { - std::cerr << "(EE) Cannot mark tunnel connection as closed. No connection openned for tunnel id " << tunnel_id << ". Unexpected situation." << std::endl; - return ; - } - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Marking distant chat as remotely closed for tunnel id " << tunnel_id << std::endl; -#endif - if(it->second.direction == RsTurtleGenericDataItem::DIRECTION_CLIENT) - { - it->second.status = RS_GXS_TUNNEL_STATUS_REMOTELY_CLOSED ; -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " This is server side. The tunnel cannot be re-openned, so we give it up." << std::endl; -#endif - } - else - { - it->second.status = RS_GXS_TUNNEL_STATUS_TUNNEL_DN ; -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " This is client side. The tunnel will be re-openned automatically." << std::endl; -#endif - } - - notifications.push_back(RS_GXS_TUNNEL_STATUS_REMOTELY_CLOSED) ; - } // nothing more to do, because the decryption routing will update the last_contact time when decrypting. - break ; - - case RS_GXS_TUNNEL_FLAG_KEEP_ALIVE: -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "GxsTunnelService::handleRecvGxsTunnelStatusItem(): received keep alive packet for inactive tunnel! peerId=" << cs->PeerId() << " tunnel=" << tunnel_id << std::endl; -#endif - break ; - - case RS_GXS_TUNNEL_FLAG_ACK_DISTANT_CONNECTION: - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "Received ACK item from the distant peer!" << std::endl; -#endif - - // in this case we notify the clients using this tunnel. - - notifications.push_back(RS_GXS_TUNNEL_STATUS_CAN_TALK) ; - } - break ; - - default: - std::cerr << "(EE) unhandled tunnel status " << std::hex << cs->status << std::dec << std::endl; - break ; - } - - // notify all clients - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " notifying clients. Prending notifications: " << notifications.size() << std::endl; -#endif - - if(notifications.size() > 0) - { - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it = _gxs_tunnel_contacts.find(tunnel_id) ; - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " " << it->second.client_services.size() << " client services for tunnel id " << tunnel_id << std::endl; -#endif - - for(std::set::const_iterator it2(it->second.client_services.begin());it2!=it->second.client_services.end();++it2) - { - std::map::const_iterator it3=mRegisteredServices.find(*it2) ; - - if(it3 != mRegisteredServices.end()) - clients.insert(it3->second) ; - } - } - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " notifying " << clients.size() << " clients." << std::endl; -#endif - - for(std::set::const_iterator it(clients.begin());it!=clients.end();++it) - for(uint32_t i=0;inotifyTunnelStatus(tunnel_id,notifications[i]) ; -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " notifying client " << (void*)(*it) << " of status " << notifications[i] << std::endl; -#endif - } -} - -bool p3GxsTunnelService::handleTunnelRequest(const RsFileHash& hash,const RsPeerId& /*peer_id*/) -{ - RsStackMutex stack(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - // look into owned GXS ids, and see if the hash corresponds to the expected hash - // - std::list own_id_list ; - rsIdentity->getOwnIds(own_id_list) ; - - // extract the GXS id from the hash - - RsGxsId destination_id = destinationGxsIdFromHash(hash) ; - - // linear search. Not costly because we have typically a low number of IDs. Otherwise, this really should be avoided! - - for(std::list::const_iterator it(own_id_list.begin());it!=own_id_list.end();++it) - if(*it == destination_id) - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "GxsTunnelService::handleTunnelRequest: received tunnel request for hash " << hash << std::endl; - std::cerr << " answering true!" << std::endl; -#endif - return true ; - } - - return false ; -} - -void p3GxsTunnelService::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir) -{ -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "GxsTunnelService:: received new virtual peer " << virtual_peer_id << " for hash " << hash << ", dir=" << dir << std::endl; -#endif - RsGxsId own_gxs_id ; - - { - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - GxsTunnelDHInfo& dhinfo( _gxs_tunnel_virtual_peer_ids[virtual_peer_id] ) ; - dhinfo.gxs_id.clear() ; - - if(dhinfo.dh != NULL) - DH_free(dhinfo.dh) ; - - dhinfo.dh = NULL ; - dhinfo.direction = dir ; - dhinfo.hash = hash ; - dhinfo.status = RS_GXS_TUNNEL_DH_STATUS_UNINITIALIZED ; - dhinfo.tunnel_id.clear(); - - if(dir == RsTurtleGenericTunnelItem::DIRECTION_CLIENT) // server side - { - // check that a tunnel is not already working for this hash. If so, give up. - - own_gxs_id = destinationGxsIdFromHash(hash) ; - } - else // client side - { - std::map::const_iterator it = _gxs_tunnel_contacts.begin(); - - while(it != _gxs_tunnel_contacts.end() && it->second.hash != hash) ++it ; - - if(it == _gxs_tunnel_contacts.end()) - { - std::cerr << "(EE) no pre-registered peer for hash " << hash << " on client side. This is a bug." << std::endl; - return ; - } - - if(it->second.status == RS_GXS_TUNNEL_STATUS_CAN_TALK) - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " virtual peer is for a distant chat session that is already openned and alive. Giving it up." << std::endl; -#endif - return ; - } - - own_gxs_id = it->second.own_gxs_id ; - } - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Creating new virtual peer ID entry and empty DH session key." << std::endl; -#endif - - } - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Adding virtual peer " << virtual_peer_id << " for chat hash " << hash << std::endl; -#endif - - // Start a new DH session for this tunnel - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - locked_restartDHSession(virtual_peer_id,own_gxs_id) ; -} - -void p3GxsTunnelService::locked_restartDHSession(const RsPeerId& virtual_peer_id,const RsGxsId& own_gxs_id) -{ -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "Starting new DH session." << std::endl; -#endif - GxsTunnelDHInfo& dhinfo = _gxs_tunnel_virtual_peer_ids[virtual_peer_id] ; // creates it, if necessary - - dhinfo.status = RS_GXS_TUNNEL_DH_STATUS_UNINITIALIZED ; - dhinfo.own_gxs_id = own_gxs_id ; - - if(!locked_initDHSessionKey(dhinfo.dh)) - { - std::cerr << " (EE) Cannot start DH session. Something went wrong." << std::endl; - return ; - } - dhinfo.status = RS_GXS_TUNNEL_DH_STATUS_HALF_KEY_DONE ; - - if(!locked_sendDHPublicKey(dhinfo.dh,own_gxs_id,virtual_peer_id)) - std::cerr << " (EE) Cannot send DH public key. Something went wrong." << std::endl; -} - -void p3GxsTunnelService::removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) -{ - bool tunnel_dn = false ; - std::set client_services ; - RsGxsTunnelId tunnel_id ; - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "GxsTunnelService: Removing virtual peer " << virtual_peer_id << " for hash " << hash << std::endl; -#else - /* remove unused parameter warnings */ - (void) hash; -#endif - { - RsStackMutex stack(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - RsGxsId gxs_id ; - std::map::iterator it = _gxs_tunnel_virtual_peer_ids.find(virtual_peer_id) ; - - if(it == _gxs_tunnel_virtual_peer_ids.end()) - { - std::cerr << "(EE) Cannot remove virtual peer " << virtual_peer_id << ": not found in tunnel list!!" << std::endl; - return ; - } - - tunnel_id = it->second.tunnel_id ; - - if(it->second.dh != NULL) - DH_free(it->second.dh) ; - - _gxs_tunnel_virtual_peer_ids.erase(it) ; - - std::map::iterator it2 = _gxs_tunnel_contacts.find(tunnel_id) ; - - if(it2 == _gxs_tunnel_contacts.end()) - { - std::cerr << "(EE) Cannot find tunnel id " << tunnel_id << " in contact list. Weird." << std::endl; - return ; - } - if(it2->second.virtual_peer_id == virtual_peer_id) - { - it2->second.status = RS_GXS_TUNNEL_STATUS_TUNNEL_DN ; - it2->second.virtual_peer_id.clear() ; - tunnel_dn = true ; - } - - for(std::set::const_iterator it(it2->second.client_services.begin());it!=it2->second.client_services.end();++it) - { - std::map::const_iterator it2 = mRegisteredServices.find(*it) ; - - if(it2 != mRegisteredServices.end()) - client_services.insert(it2->second) ; - } - } - - if(tunnel_dn) - { - // notify all client services that this tunnel is down - - for(std::set::const_iterator it(client_services.begin());it!=client_services.end();++it) - (*it)->notifyTunnelStatus(tunnel_id,RS_GXS_TUNNEL_STATUS_TUNNEL_DN) ; - } -} - -void p3GxsTunnelService::receiveTurtleData(const RsTurtleGenericTunnelItem *gitem, const RsFileHash& hash, const RsPeerId& virtual_peer_id, RsTurtleGenericTunnelItem::Direction direction) -{ -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "GxsTunnelService::receiveTurtleData(): Received turtle data. " << std::endl; - std::cerr << " hash = " << hash << std::endl; - std::cerr << " vpid = " << virtual_peer_id << std::endl; - std::cerr << " acting as = " << direction << std::endl; -#else - /* remove unused parameter warnings */ - (void) direction; -#endif - - void *data_bytes; - uint32_t data_size ; - bool accept_fast_items = false; - - const RsTurtleGenericFastDataItem *fitem = dynamic_cast(gitem) ; - - if(fitem != NULL) - { - data_bytes = fitem->data_bytes ; - data_size = fitem->data_size ; - accept_fast_items = true; - } - else - { - const RsTurtleGenericDataItem *item = dynamic_cast(gitem) ; - - if(item == NULL) - { - std::cerr << "(EE) item is not a data item. That is an error." << std::endl; - return ; - } - data_bytes = item->data_bytes ; - data_size = item->data_size ; - } - - // Call the AES crypto module - // - the IV is the first 8 bytes of item->data_bytes - - if(data_size < 8) - { - std::cerr << "(EE) item encrypted data stream is too small: size = " << data_size << std::endl; - return ; - } - if(*((uint64_t*)data_bytes) != 0) // WTF?? we should use flags - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Item is encrypted." << std::endl; -#endif - - // if cannot decrypt, it means the key is wrong. We need to re-negociate a new key. - - handleEncryptedData((uint8_t*)data_bytes,data_size,hash,virtual_peer_id,accept_fast_items) ; - } - else - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Item is not encrypted." << std::endl; -#endif - - // Now try deserialise the decrypted data to make an RsItem out of it. - // - uint32_t pktsize = data_size-8; - RsItem *citem = RsGxsTunnelSerialiser().deserialise(&((uint8_t*)data_bytes)[8],&pktsize) ; - - if(citem == NULL) - { - std::cerr << "(EE) item could not be de-serialized. That is an error." << std::endl; - return ; - } - - // DH key items are sent even before we know who we speak to, so the virtual peer id is used in this - // case only. - RsGxsTunnelDHPublicKeyItem *dhitem = dynamic_cast(citem) ; - - if(dhitem != NULL) - { - dhitem->PeerId(virtual_peer_id) ; - handleRecvDHPublicKey(dhitem) ; - } - else - std::cerr << "(EE) Deserialiased item has unexpected type." << std::endl; - - delete citem ; - } -} - -// This function encrypts the given data and adds a MAC and an IV into a serialised memory chunk that is then sent through the tunnel. - -#ifndef V07_NON_BACKWARD_COMPATIBLE_CHANGE_004 -bool p3GxsTunnelService::handleEncryptedData(const uint8_t *data_bytes,uint32_t data_size,const TurtleFileHash& hash,const RsPeerId& virtual_peer_id,bool accepts_fast_items) -#else -bool p3GxsTunnelService::handleEncryptedData(const uint8_t *data_bytes,uint32_t data_size,const TurtleFileHash& hash,const RsPeerId& virtual_peer_id) -#endif -{ -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "p3GxsTunnelService::handleEncryptedDataItem()" << std::endl; - std::cerr << " size = " << data_size << std::endl; - std::cerr << " data = " << (void*)data_bytes << std::endl; - std::cerr << " IV = " << std::hex << *(uint64_t*)data_bytes << std::dec << std::endl; - std::cerr << " data = " << RsUtil::BinToHex((unsigned char*)data_bytes,data_size,100) ; - std::cerr << std::endl; -#endif - - RsGxsTunnelItem *citem = NULL; - RsGxsTunnelId tunnel_id; - - { - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - uint32_t encrypted_size = data_size - GXS_TUNNEL_ENCRYPTION_IV_SIZE - GXS_TUNNEL_ENCRYPTION_HMAC_SIZE; - uint32_t decrypted_size = RsAES::get_buffer_size(encrypted_size); - uint8_t *encrypted_data = (uint8_t*)data_bytes+GXS_TUNNEL_ENCRYPTION_IV_SIZE+GXS_TUNNEL_ENCRYPTION_HMAC_SIZE; - - RsTemporaryMemory decrypted_data(decrypted_size); - uint8_t aes_key[GXS_TUNNEL_AES_KEY_SIZE] ; - - if(!decrypted_data) - return false ; - - std::map::iterator it = _gxs_tunnel_virtual_peer_ids.find(virtual_peer_id) ; - - if(it == _gxs_tunnel_virtual_peer_ids.end()) - { - std::cerr << "(EE) item is not coming out of a registered tunnel. Weird. hash=" << hash << ", peer id = " << virtual_peer_id << std::endl; - return false ; - } - - tunnel_id = it->second.tunnel_id ; - std::map::iterator it2 = _gxs_tunnel_contacts.find(tunnel_id) ; - - if(it2 == _gxs_tunnel_contacts.end()) - { - std::cerr << "(EE) no tunnel data for tunnel ID=" << tunnel_id << ". This is a bug." << std::endl; - return false ; - } -#ifndef V07_NON_BACKWARD_COMPATIBLE_CHANGE_004 - if(accepts_fast_items) - { - if(!it2->second.accepts_fast_turtle_items) - std::cerr << "(II) received probe for Fast track turtle items for tunnel VPID " << it2->second.virtual_peer_id << ": switching to Fast items mode." << std::endl; - - it2->second.accepts_fast_turtle_items = true; - } -#endif - - memcpy(aes_key,it2->second.aes_key,GXS_TUNNEL_AES_KEY_SIZE) ; - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Using IV: " << std::hex << *(uint64_t*)data_bytes << std::dec << std::endl; - std::cerr << " Decrypted buffer size: " << decrypted_size << std::endl; - std::cerr << " key : " << RsUtil::BinToHex((unsigned char*)aes_key,GXS_TUNNEL_AES_KEY_SIZE) << std::endl; - std::cerr << " hmac : " << RsUtil::BinToHex((unsigned char*)data_bytes+GXS_TUNNEL_ENCRYPTION_IV_SIZE,GXS_TUNNEL_ENCRYPTION_HMAC_SIZE) << std::endl; - std::cerr << " data : " << RsUtil::BinToHex((unsigned char*)data_bytes,data_size,100) << std::endl; -#endif - // first, check the HMAC - - unsigned char *hm = HMAC(EVP_sha1(),aes_key,GXS_TUNNEL_AES_KEY_SIZE,encrypted_data,encrypted_size,NULL,NULL) ; - - if(memcmp(hm,&data_bytes[GXS_TUNNEL_ENCRYPTION_IV_SIZE],GXS_TUNNEL_ENCRYPTION_HMAC_SIZE)) - { - std::cerr << "(EE) packet HMAC does not match. Computed HMAC=" << RsUtil::BinToHex((char*)hm,GXS_TUNNEL_ENCRYPTION_HMAC_SIZE) << std::endl; - std::cerr << "(EE) resetting new DH session." << std::endl; - - locked_restartDHSession(virtual_peer_id,it2->second.own_gxs_id) ; - - return false ; - } - - if(!RsAES::aes_decrypt_8_16(encrypted_data,encrypted_size, aes_key,(uint8_t*)data_bytes,decrypted_data,decrypted_size)) - { - std::cerr << "(EE) packet decryption failed." << std::endl; - std::cerr << "(EE) resetting new DH session." << std::endl; - - locked_restartDHSession(virtual_peer_id,it2->second.own_gxs_id) ; - - return false ; - } - it2->second.status = RS_GXS_TUNNEL_STATUS_CAN_TALK ; - it2->second.last_contact = time(NULL) ; - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "(II) Decrypted data: size=" << decrypted_size << std::endl; -#endif - - // Now try deserialise the decrypted data to make an RsItem out of it. - // - citem = dynamic_cast(RsGxsTunnelSerialiser().deserialise(decrypted_data,&decrypted_size)) ; - - if(citem == NULL) - { - std::cerr << "(EE) item could not be de-serialized. That is an error." << std::endl; - return true; - } - - it2->second.total_received += decrypted_size ; - - // DH key items are sent even before we know who we speak to, so the virtual peer id is used in this - // case only. - - citem->PeerId(virtual_peer_id) ; - } - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "(II) Setting peer id to " << citem->PeerId() << std::endl; -#endif - handleIncomingItem(tunnel_id,citem) ; // Treats the item, and deletes it - - return true ; -} - -void p3GxsTunnelService::handleRecvDHPublicKey(RsGxsTunnelDHPublicKeyItem *item) -{ - if (!item) - { - std::cerr << "p3GxsTunnelService: Received null DH public key item. This should not happen." << std::endl; - return; - } - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "GxsTunnelService: Received DH public key." << std::endl; - item->print(std::cerr, 0) ; -#endif - - // Look for the current state of the key agreement. - - TurtleVirtualPeerId vpid = item->PeerId() ; - - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it = _gxs_tunnel_virtual_peer_ids.find(vpid) ; - - if(it == _gxs_tunnel_virtual_peer_ids.end()) - { - std::cerr << " (EE) Cannot find hash in gxs_tunnel peer list!!" << std::endl; - return ; - } - - // Now check the signature of the DH public key item. - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Checking signature. " << std::endl; -#endif - - uint32_t pubkey_size = BN_num_bytes(item->public_key) ; - RsTemporaryMemory data(pubkey_size) ; - BN_bn2bin(item->public_key, data) ; - - RsTlvPublicRSAKey signature_key ; - - // We need to get the key of the sender, but if the key is not cached, we - // need to get it first. So we let the system work for 2-3 seconds before - // giving up. Normally this would only cause a delay for uncached keys, - // which is rare. To force the system to cache the key, we first call for - // getIdDetails(). - // - RsIdentityDetails details ; - RsGxsId senders_id( item->signature.keyId ) ; - - for(int i=0;i<6;++i) - if(!mGixs->getKey(senders_id,signature_key) || signature_key.keyData.bin_data == NULL) - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Cannot get key. Waiting for caching. try " << i << "/6" << std::endl; -#endif - usleep(500 * 1000) ; // sleep for 500 msec. - } - else - break ; - - if(signature_key.keyData.bin_data == NULL) - { - std::cerr << " (EE) Key unknown for checking signature from " << senders_id << ", can't verify signature. Using key provided in DH packet (without adding to the keyring)." << std::endl; - - // check GXS key for defects. - - if(!GxsSecurity::checkPublicKey(item->gxs_key)) - { - std::cerr << "(SS) Security error in distant chat DH handshake: supplied key " << item->gxs_key.keyId << " is inconsistent. Refusing chat!" << std::endl; - return ; - } - if(item->gxs_key.keyId != item->signature.keyId) - { - std::cerr << "(SS) Security error in distant chat DH handshake: supplied key " << item->gxs_key.keyId << " is not the same than the item's signature key " << item->signature.keyId << ". Refusing chat!" << std::endl; - return ; - } - - signature_key = item->gxs_key ; - } - - if(!GxsSecurity::validateSignature((char*)(unsigned char*)data,pubkey_size,signature_key,item->signature)) - { - std::cerr << "(SS) Signature was verified and it doesn't check! This is a security issue!" << std::endl; - return ; - } - mGixs->timeStampKey(item->signature.keyId,RsIdentityUsage(RsServiceType::GXS_TUNNEL,RsIdentityUsage::GXS_TUNNEL_DH_SIGNATURE_CHECK)); - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Signature checks! Sender's ID = " << senders_id << std::endl; - std::cerr << " Computing AES key" << std::endl; -#endif - - if(it->second.dh == NULL) - { - std::cerr << " (EE) no DH information for that peer. This is an error." << std::endl; - return ; - } - if(it->second.status == RS_GXS_TUNNEL_DH_STATUS_KEY_AVAILABLE) - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " DH Session already set for this tunnel. Re-initing a new session!" << std::endl; -#endif - - locked_restartDHSession(vpid,it->second.own_gxs_id) ; - } - - // gets current key params. By default, should contain all null pointers. - // - RsGxsId own_id = it->second.own_gxs_id ; - - RsGxsTunnelId tunnel_id = makeGxsTunnelId(own_id,senders_id) ; - - it->second.tunnel_id = tunnel_id ; - it->second.gxs_id = senders_id ; - - // Looks for the DH params. If not there yet, create them. - // - int size = DH_size(it->second.dh) ; - RsTemporaryMemory key_buff(size) ; - - if(size != DH_compute_key(key_buff,item->public_key,it->second.dh)) - { - std::cerr << " (EE) DH computation failed. Probably a bug. Error code=" << ERR_get_error() << std::endl; - return ; - } - it->second.status = RS_GXS_TUNNEL_DH_STATUS_KEY_AVAILABLE ; - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " DH key computation successed. New key in place." << std::endl; -#endif - // make a hash of destination and source GXS ids in order to create the tunnel name - - GxsTunnelPeerInfo& pinfo(_gxs_tunnel_contacts[tunnel_id]) ; - - // Now hash the key buffer into a 16 bytes key. - - assert(GXS_TUNNEL_AES_KEY_SIZE <= Sha1CheckSum::SIZE_IN_BYTES) ; - memcpy(pinfo.aes_key, RsDirUtil::sha1sum(key_buff,size).toByteArray(),GXS_TUNNEL_AES_KEY_SIZE) ; - - pinfo.last_contact = time(NULL) ; - pinfo.last_keep_alive_sent = time(NULL) ; - pinfo.status = RS_GXS_TUNNEL_STATUS_CAN_TALK ; - pinfo.virtual_peer_id = vpid ; - pinfo.direction = it->second.direction ; - pinfo.own_gxs_id = own_id ; - pinfo.to_gxs_id = item->signature.keyId; // this is already set for client side but not for server side. - - // note: the hash might still be nn initialised on server side. - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " DH key computed. Tunnel is now secured!" << std::endl; - std::cerr << " Key computed: " << RsUtil::BinToHex((char*)pinfo.aes_key,16) << std::endl; - std::cerr << " Sending a ACK packet." << std::endl; -#endif - - // then we send an ACK packet to notify that the tunnel works. That's useful - // because it makes the peer at the other end of the tunnel know that all - // intermediate peer in the tunnel are able to transmit the data. - // However, it is not possible here to call sendTurtleData(), without dead-locking - // the turtle router, so we store the item is a list of items to be sent. - - RsGxsTunnelStatusItem *cs = new RsGxsTunnelStatusItem ; - - cs->status = RS_GXS_TUNNEL_FLAG_ACK_DISTANT_CONNECTION; - cs->PeerId(RsPeerId(tunnel_id)) ; - - pendingGxsTunnelItems.push_back(cs) ; -} - -// Note: for some obscure reason, the typedef does not work here. Looks like a compiler error. So I use the primary type. - -/*static*/ RsGxsTunnelId p3GxsTunnelService::makeGxsTunnelId( - const RsGxsId &own_id, const RsGxsId &distant_id ) -{ - unsigned char mem[RsGxsId::SIZE_IN_BYTES * 2] ; - - // Always sort the ids, as a matter to avoid confusion between the two. Also that generates the same tunnel ID on both sides - // which helps debugging. If the code is right this is not needed anyway. - - if(own_id < distant_id) - { - memcpy(mem, own_id.toByteArray(), RsGxsId::SIZE_IN_BYTES) ; - memcpy(mem+RsGxsId::SIZE_IN_BYTES, distant_id.toByteArray(), RsGxsId::SIZE_IN_BYTES) ; - } - else - { - memcpy(mem, distant_id.toByteArray(), RsGxsId::SIZE_IN_BYTES) ; - memcpy(mem+RsGxsId::SIZE_IN_BYTES, own_id.toByteArray(), RsGxsId::SIZE_IN_BYTES) ; - } - - assert( RsGxsTunnelId::SIZE_IN_BYTES <= Sha1CheckSum::SIZE_IN_BYTES ) ; - - return RsGxsTunnelId( RsDirUtil::sha1sum(mem, 2*RsGxsId::SIZE_IN_BYTES).toByteArray() ) ; -} - -bool p3GxsTunnelService::locked_sendDHPublicKey(const DH *dh,const RsGxsId& own_gxs_id,const RsPeerId& virtual_peer_id) -{ - if(dh == NULL) - { - std::cerr << " (EE) DH struct is not initialised! Error." << std::endl; - return false ; - } - - RsGxsTunnelDHPublicKeyItem *dhitem = new RsGxsTunnelDHPublicKeyItem ; -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - dhitem->public_key = BN_dup(dh->pub_key) ; -#else - const BIGNUM *pub_key=NULL ; - DH_get0_key(dh,&pub_key,NULL) ; - dhitem->public_key = BN_dup(pub_key) ; -#endif - - // we should also sign the data and check the signature on the other end. - // - RsTlvKeySignature signature ; - RsTlvPrivateRSAKey signature_key ; - RsTlvPublicRSAKey signature_key_public ; - - uint32_t error_status ; - - uint32_t size = BN_num_bytes(dhitem->public_key) ; - - RsTemporaryMemory data(size) ; - - if(data == NULL) - { - delete(dhitem); - return false ; - } - - BN_bn2bin(dhitem->public_key, data) ; - - if(!mGixs->signData((unsigned char*)data,size,own_gxs_id,signature,error_status)) - { - switch(error_status) - { - case RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE: std::cerr << "(EE) Key is not available. Cannot sign." << std::endl; - break ; - default: std::cerr << "(EE) Unknown error when signing" << std::endl; - break ; - } - delete(dhitem); - return false; - } - - if(!mGixs->getKey(own_gxs_id,signature_key_public)) - { - std::cerr << " (EE) Could not retrieve own public key for ID = " << own_gxs_id << ". Giging up sending DH session params." << std::endl; - return false ; - } - - - assert(!(signature_key_public.keyFlags & RSTLV_KEY_TYPE_FULL)) ; - - dhitem->signature = signature ; - dhitem->gxs_key = signature_key_public ; - dhitem->PeerId(virtual_peer_id) ; - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Pushing DH session key item to pending distant messages..." << std::endl; - dhitem->print(std::cerr, 2) ; - std::cerr << std::endl; -#endif - pendingDHItems.push_back(dhitem) ; // sent off-mutex to avoid deadlocking. - - return true ; -} - -bool p3GxsTunnelService::locked_initDHSessionKey(DH *& dh) -{ - // We use our own DH group prime. This has been generated with command-line openssl and checked. - - static const std::string dh_prime_2048_hex = "B3B86A844550486C7EA459FA468D3A8EFD71139593FE1C658BBEFA9B2FC0AD2628242C2CDC2F91F5B220ED29AAC271192A7374DFA28CDDCA70252F342D0821273940344A7A6A3CB70C7897A39864309F6CAC5C7EA18020EF882693CA2C12BB211B7BA8367D5A7C7252A5B5E840C9E8F081469EBA0B98BCC3F593A4D9C4D5DF539362084F1B9581316C1F80FDAD452FD56DBC6B8ED0775F596F7BB22A3FE2B4753764221528D33DB4140DE58083DB660E3E105123FC963BFF108AC3A268B7380FFA72005A1515C371287C5706FFA6062C9AC73A9B1A6AC842C2764CDACFC85556607E86611FDF486C222E4896CDF6908F239E177ACC641FCBFF72A758D1C10CBB" ; - - if(dh != NULL) - { - DH_free(dh) ; - dh = NULL ; - } - - dh = DH_new() ; - - if(!dh) - { - std::cerr << " (EE) DH_new() failed." << std::endl; - return false ; - } - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - BN_hex2bn(&dh->p,dh_prime_2048_hex.c_str()) ; - BN_hex2bn(&dh->g,"5") ; -#else - BIGNUM *pp=NULL ; - BIGNUM *gg=NULL ; - - BN_hex2bn(&pp,dh_prime_2048_hex.c_str()) ; - BN_hex2bn(&gg,"5") ; - - DH_set0_pqg(dh,pp,NULL,gg) ; -#endif - - int codes = 0 ; - - if(!DH_check(dh, &codes) || codes != 0) - { - std::cerr << " (EE) DH check failed!" << std::endl; - return false ; - } - - if(!DH_generate_key(dh)) - { - std::cerr << " (EE) DH generate_key() failed! Error code = " << ERR_get_error() << std::endl; - return false ; - } -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " (II) DH Session key inited." << std::endl; -#endif - return true ; -} - -// Sends the item in clear. This is only used for DH key exchange. -// in this case only, the item's PeerId is equal to the virtual peer Id for the tunnel, -// since we ight not now the tunnel id yet. - -bool p3GxsTunnelService::locked_sendClearTunnelData(RsGxsTunnelDHPublicKeyItem *item) -{ -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "GxsTunnelService::sendClearTunnelData(): try sending item " << (void*)item << " to peer " << item->PeerId() << std::endl; -#endif - - // make a RsTurtleGenericData item out of it, and send it in clear. - // this is compatible with nodes older than 0.6.6 - RsTurtleGenericDataItem *gitem = new RsTurtleGenericDataItem ; - // force item priority to QOS_PRIORITY_RS_TURTLE_GENERIC_FAST_DATA to make the DH exchange faster on 0.6.6+ nodes - // this will not affect old nodes - gitem->setPriorityLevel(QOS_PRIORITY_RS_TURTLE_GENERIC_FAST_DATA); - - RsGxsTunnelSerialiser ser ; - - uint32_t rssize = ser.size(item); - - gitem->data_size = rssize + 8 ; - gitem->data_bytes = rs_malloc(rssize+8) ; - - if(gitem->data_bytes == NULL) - { - delete gitem ; - return false ; - } - // by convention, we use a IV of 0 for unencrypted data. - memset(gitem->data_bytes,0,8) ; - - if(!ser.serialise(item,&((uint8_t*)gitem->data_bytes)[8],&rssize)) - { - std::cerr << "(EE) Could not serialise item!!!" << std::endl; - delete gitem ; - return false; - } - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " GxsTunnelService::sendClearTunnelData(): Sending clear data to virtual peer: " << item->PeerId() << std::endl; - std::cerr << " gitem->data_size = " << gitem->data_size << std::endl; - std::cerr << " data = " << RsUtil::BinToHex((unsigned char*)gitem->data_bytes,gitem->data_size,100) ; - std::cerr << std::endl; -#endif - mTurtle->sendTurtleData(item->PeerId(),gitem) ; - - return true ; -} - -// Sends this item using secured/authenticated method, thx to the establshed cryptographic channel. - -bool p3GxsTunnelService::locked_sendEncryptedTunnelData(RsGxsTunnelItem *item) -{ - RsGxsTunnelSerialiser ser; - - uint32_t rssize = ser.size(item); - RsTemporaryMemory buff(rssize) ; - - if(!ser.serialise(item,buff,&rssize)) - { - std::cerr << "(EE) GxsTunnelService::sendEncryptedTunnelData(): Could not serialise item!" << std::endl; - return false; - } - - uint8_t aes_key[GXS_TUNNEL_AES_KEY_SIZE] ; - uint64_t IV = 0; - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "Sending encrypted data to tunnel with vpid " << item->PeerId() << std::endl; -#endif - - RsGxsTunnelId tunnel_id ( item->PeerId() ); - - std::map::iterator it = _gxs_tunnel_contacts.find(tunnel_id) ; - - if(it == _gxs_tunnel_contacts.end()) - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Cannot find contact key info for tunnel id " - << tunnel_id << ". Cannot send message!" << std::endl; -#endif - return false; - } - if(it->second.status != RS_GXS_TUNNEL_STATUS_CAN_TALK) - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "(EE) Cannot talk to tunnel id " << tunnel_id << ". Tunnel status is: " << it->second.status << std::endl; -#endif - return false; - } - - it->second.total_sent += rssize ; // counts the size of clear data that is sent - - memcpy(aes_key,it->second.aes_key,GXS_TUNNEL_AES_KEY_SIZE) ; - RsPeerId virtual_peer_id = it->second.virtual_peer_id ; - - while(IV == 0) IV = RSRandom::random_u64() ; // make a random 8 bytes IV, that is not 0 - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "GxsTunnelService::sendEncryptedTunnelData(): tunnel found. Encrypting data." << std::endl; -#endif - - // Now encrypt this data using AES. - // - uint32_t encrypted_size = RsAES::get_buffer_size(rssize); - RsTemporaryMemory encrypted_data(encrypted_size) ; - - if(!RsAES::aes_crypt_8_16(buff,rssize,aes_key,(uint8_t*)&IV,encrypted_data,encrypted_size)) - { - std::cerr << "(EE) packet encryption failed." << std::endl; - return false; - } - - // make a TurtleGenericData item out of it: - // - - uint32_t data_size = encrypted_size + GXS_TUNNEL_ENCRYPTION_IV_SIZE + GXS_TUNNEL_ENCRYPTION_HMAC_SIZE ; - void *data_bytes = rs_malloc(data_size) ; - - if(data_bytes == NULL) - return false ; - - memcpy(& ((uint8_t*)data_bytes)[0] ,&IV,8) ; - - unsigned int md_len = GXS_TUNNEL_ENCRYPTION_HMAC_SIZE ; - HMAC(EVP_sha1(),aes_key,GXS_TUNNEL_AES_KEY_SIZE,encrypted_data,encrypted_size,&(((uint8_t*)data_bytes)[GXS_TUNNEL_ENCRYPTION_IV_SIZE]),&md_len) ; - - memcpy(& (((uint8_t*)data_bytes)[GXS_TUNNEL_ENCRYPTION_HMAC_SIZE+GXS_TUNNEL_ENCRYPTION_IV_SIZE]),encrypted_data,encrypted_size) ; - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Using IV: " << std::hex << IV << std::dec << std::endl; - std::cerr << " Using Key: " << RsUtil::BinToHex((char*)aes_key,GXS_TUNNEL_AES_KEY_SIZE) ; std::cerr << std::endl; - std::cerr << " hmac: " << RsUtil::BinToHex((char*)data_bytes,GXS_TUNNEL_ENCRYPTION_HMAC_SIZE) << std::endl; -#endif -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "GxsTunnelService::sendEncryptedTunnelData(): Sending encrypted data to virtual peer: " << virtual_peer_id << std::endl; - std::cerr << " data_size = " << data_size << std::endl; - std::cerr << " serialised data = " << RsUtil::BinToHex((unsigned char*)data_bytes,data_size,100) ; - std::cerr << std::endl; -#endif - - // We send the item through the turtle tunnel. We do that using the new 'fast' item type if the tunnel accepts it, and using the old slow one otherwise. - // Still if the tunnel hasn't been probed, we duplicate the packet using the new fast item format. The packet being received twice on the other side will - // be discarded with a warning. - // Note that because the data is deleted by sendTurtleData(), we need to send all packets at the end, and properly duplicate the data when needed. - -#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_004 - RsTurtleGenericFastDataItem *gitem = new RsTurtleGenericFastDataItem; - gitem->data_bytes = data_bytes; - gitem->data_size = data_size ; -#else - RsTurtleGenericDataItem *gitem = NULL; - RsTurtleGenericFastDataItem *gitem2 = NULL; - - if(!it->second.accepts_fast_turtle_items) - { - std::cerr << "Sending old format (slow) item for packet IV=" << std::hex << IV << std::dec << " in tunnel VPID=" << it->second.virtual_peer_id << std::endl; - gitem = new RsTurtleGenericDataItem ; - - gitem->data_bytes = data_bytes; - gitem->data_size = data_size ; - } - - if(it->second.accepts_fast_turtle_items || !it->second.already_probed_for_fast_items) - { - std::cerr << "Sending new format (fast) item for packet IV=" << std::hex << IV << std::dec << " in tunnel VPID=" << it->second.virtual_peer_id << std::endl; - gitem2 = new RsTurtleGenericFastDataItem ; - - if(gitem != NULL) // duplicate the data because it was already sent in gitem. - { - gitem2->data_bytes = rs_malloc(data_size); - gitem2->data_size = data_size ; - memcpy(gitem2->data_bytes,data_bytes,data_size); - } - else - { - gitem2->data_bytes = data_bytes; - gitem2->data_size = data_size ; - } - - it->second.already_probed_for_fast_items = true; - - } - if(gitem2) mTurtle->sendTurtleData(virtual_peer_id,gitem2) ; -#endif - if(gitem) mTurtle->sendTurtleData(virtual_peer_id,gitem) ; - - return true ; -} - -bool p3GxsTunnelService::requestSecuredTunnel(const RsGxsId& to_gxs_id, const RsGxsId& from_gxs_id, RsGxsTunnelId &tunnel_id, uint32_t service_id, uint32_t& error_code) -{ - // should be a parameter. - - std::list lst ; - mGixs->getOwnIds(lst) ; - - bool found = false ; - for(std::list::const_iterator it = lst.begin();it!=lst.end();++it) - if(*it == from_gxs_id) - { - found=true; - break ; - } - - if(!found) - { - std::cerr << " (EE) Cannot start distant chat, since GXS id " << from_gxs_id << " is not available." << std::endl; - error_code = RS_GXS_TUNNEL_ERROR_UNKNOWN_GXS_ID ; - return false ; - } - RsGxsId own_gxs_id = from_gxs_id ; - - startClientGxsTunnelConnection(to_gxs_id,own_gxs_id,service_id,tunnel_id) ; - - error_code = RS_GXS_TUNNEL_ERROR_NO_ERROR ; - - return true ; -} - -// This method generates an ID that should be unique for each packet sent to a same peer. Rather than a random value, -// we use this counter because outgoing items are sorted in a map by their counter value. Using an increasing value -// ensures that the packets are sent in the same order than received from the service. This can be useful in some cases, -// for instance when services split their items while expecting them to arrive in the same order. - -uint64_t p3GxsTunnelService::locked_getPacketCounter() -{ - return mCurrentPacketCounter++ ; -} - -bool p3GxsTunnelService::sendData(const RsGxsTunnelId &tunnel_id, uint32_t service_id, const uint8_t *data, uint32_t size) -{ - // make sure that the tunnel ID is registered. - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "p3GxsTunnelService::sendData()" << std::endl; - std::cerr << " tunnel id : " << tunnel_id << std::endl; - std::cerr << " data size : " << size << std::endl; - std::cerr << " service id: " << std::hex << service_id << std::dec << std::endl; -#endif - - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - std::map::const_iterator it = _gxs_tunnel_contacts.find(tunnel_id) ; - - if(it == _gxs_tunnel_contacts.end()) - { - std::cerr << " (EE) no tunnel known with this ID. Sorry!" << std::endl; - return false ; - } - - // make sure the service is registered. - - if(mRegisteredServices.find(service_id) == mRegisteredServices.end()) - { - std::cerr << " (EE) no service registered with this ID. Please call rsGxsTunnel->registerClientService() at some point." << std::endl; - return false ; - } - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " verifications fine! Storing in out queue with:" << std::endl; -#endif - - RsGxsTunnelDataItem *item = new RsGxsTunnelDataItem ; - - item->unique_item_counter = locked_getPacketCounter() ;// this allows to make the item unique, while respecting the packet order! - item->flags = 0; // not used yet. - item->service_id = service_id; - item->data_size = size; // encrypted data size - item->data = (uint8_t*)rs_malloc(size); // encrypted data - - if(item->data == NULL) - delete item ; - - item->PeerId(RsPeerId(tunnel_id)) ; - memcpy(item->data,data,size) ; - - GxsTunnelData& tdata( pendingGxsTunnelDataItems[item->unique_item_counter] ) ; - - tdata.data_item = item ; - tdata.last_sending_attempt = 0 ; // never sent until now - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " counter id : " << std::hex << item->unique_item_counter << std::dec << std::endl; -#endif - - return true ; -} - - -void p3GxsTunnelService::startClientGxsTunnelConnection(const RsGxsId& to_gxs_id,const RsGxsId& from_gxs_id,uint32_t service_id,RsGxsTunnelId& tunnel_id) -{ - // compute a random hash for that pair, and init the DH session for it so that we can recognise it when we get the virtual peer for it. - - RsFileHash hash = randomHashFromDestinationGxsId(to_gxs_id) ; - - tunnel_id = makeGxsTunnelId(from_gxs_id,to_gxs_id) ; - - { - RsStackMutex stack(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - if(_gxs_tunnel_contacts.find(tunnel_id) != _gxs_tunnel_contacts.end()) - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "GxsTunnelService:: asking GXS tunnel for a configuration that already exits.Ignoring." << std::endl; -#endif - return ; - } - } - - GxsTunnelPeerInfo info ; - - rstime_t now = time(NULL) ; - - info.last_contact = now ; - info.last_keep_alive_sent = now ; - info.status = RS_GXS_TUNNEL_STATUS_TUNNEL_DN ; - info.own_gxs_id = from_gxs_id ; - info.to_gxs_id = to_gxs_id ; - info.hash = hash ; - info.direction = RsTurtleGenericTunnelItem::DIRECTION_SERVER ; - info.virtual_peer_id.clear(); - info.client_services.insert(service_id) ; - - memset(info.aes_key,0,GXS_TUNNEL_AES_KEY_SIZE) ; - - { - RsStackMutex stack(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - _gxs_tunnel_contacts[tunnel_id] = info ; - } - -#ifdef DEBUG_GXS_TUNNEL - std::cerr << "Starting distant chat to " << to_gxs_id << ", hash = " << hash << ", from " << from_gxs_id << std::endl; - std::cerr << "Asking turtle router to monitor tunnels for hash " << hash << std::endl; -#endif - - // Now ask the turtle router to manage a tunnel for that hash. - - mTurtle->monitorTunnels(hash,this,false) ; -} - -TurtleFileHash p3GxsTunnelService::randomHashFromDestinationGxsId(const RsGxsId& destination) -{ - // This is in prevision for the "secured GXS tunnel" service, which will need a service ID to register, - // just like GRouter does. - - assert( destination.SIZE_IN_BYTES == 16) ; - assert(Sha1CheckSum::SIZE_IN_BYTES == 20) ; - - uint8_t bytes[20] ; - memcpy(&bytes[4],destination.toByteArray(),16) ; - - RAND_bytes(&bytes[0],4) ; // fill the 4 first bytes with random crap. Very important to allow tunnels from different sources and statistically avoid collisions. - - // We could rehash this, with a secret key to get a HMAC. That would allow to publish secret distant chat - // passphrases. I'll do this later if needed. - - return Sha1CheckSum(bytes) ; // this does not compute a hash, and that is on purpose. -} - -RsGxsId p3GxsTunnelService::destinationGxsIdFromHash(const TurtleFileHash& sum) -{ - assert( RsGxsId::SIZE_IN_BYTES == 16) ; - assert(Sha1CheckSum::SIZE_IN_BYTES == 20) ; - - return RsGxsId(&sum.toByteArray()[4]);// takes the last 16 bytes -} - -bool p3GxsTunnelService::getTunnelInfo(const RsGxsTunnelId& tunnel_id,GxsTunnelInfo& info) -{ - RS_STACK_MUTEX(mGxsTunnelMtx); - - std::map::const_iterator it = _gxs_tunnel_contacts.find(tunnel_id) ; - - if(it == _gxs_tunnel_contacts.end()) - return false ; - - info.destination_gxs_id = it->second.to_gxs_id; - info.source_gxs_id = it->second.own_gxs_id; - info.tunnel_status = it->second.status; - info.total_size_sent = it->second.total_sent; - info.total_size_received= it->second.total_received; - info.is_client_side = (it->second.direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT); - - // Data packets - - info.pending_data_packets = 0; - RsPeerId p(tunnel_id); - - for(auto it(pendingGxsTunnelDataItems.begin());it!=pendingGxsTunnelDataItems.end();++it) - if(it->second.data_item->PeerId() == p) - ++info.pending_data_packets ; - - info.total_data_packets_sent=0 ; - info.total_data_packets_received=0 ; - - return true ; -} - -bool p3GxsTunnelService::closeExistingTunnel(const RsGxsTunnelId& tunnel_id, uint32_t service_id) -{ - // two cases: - // - client needs to stop asking for tunnels => remove the hash from the list of tunnelled files - // - server needs to only close the window and let the tunnel die. But the window should only open - // if a message arrives. - - TurtleFileHash hash ; - TurtleVirtualPeerId vpid ; - bool close_tunnel = false ; - int direction ; - { - RsStackMutex stack(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - std::map::iterator it = _gxs_tunnel_contacts.find(tunnel_id) ; - - if(it == _gxs_tunnel_contacts.end()) - { - std::cerr << "(EE) Cannot close distant tunnel connection. No connection openned for tunnel id " << tunnel_id << std::endl; - - // We cannot stop tunnels, since their peer id is lost. Anyway, they'll die of starving. - - return false ; - } - vpid = it->second.virtual_peer_id ; - - std::map::const_iterator it2 = _gxs_tunnel_virtual_peer_ids.find(vpid) ; - - if(it2 != _gxs_tunnel_virtual_peer_ids.end()) - hash = it2->second.hash ; - else - hash = it->second.hash ; - - // check how many clients are used. If empty, close the tunnel - - std::set::iterator it3 = it->second.client_services.find(service_id) ; - - if(it3 == it->second.client_services.end()) - { - std::cerr << "(EE) service id not currently using that tunnel. This is an error." << std::endl; - return false; - } - - it->second.client_services.erase(it3) ; - direction = it->second.direction ; - - if(it->second.client_services.empty()) - close_tunnel = true ; - } - - if(close_tunnel) - { - // send a status item saying that we're closing the connection -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " Sending a ACK to close the tunnel since we're managing it and it's not used by any service. tunnel id=." << tunnel_id << std::endl; -#endif - - RsGxsTunnelStatusItem *cs = new RsGxsTunnelStatusItem ; - - cs->status = RS_GXS_TUNNEL_FLAG_CLOSING_DISTANT_CONNECTION; - cs->PeerId(RsPeerId(tunnel_id)) ; - - locked_sendEncryptedTunnelData(cs) ; // that needs to be done off-mutex and before we close the tunnel also ignoring failure. - - if(direction == RsTurtleGenericTunnelItem::DIRECTION_SERVER) // nothing more to do for server side. - { -#ifdef DEBUG_GXS_TUNNEL - std::cerr << " This is client side. Stopping tunnel manageement for tunnel_id " << tunnel_id << std::endl; -#endif - mTurtle->stopMonitoringTunnels( hash ) ; // still valid if the hash is null - } - - RsStackMutex stack(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - std::map::iterator it = _gxs_tunnel_contacts.find(tunnel_id) ; - - if(it == _gxs_tunnel_contacts.end()) // server side. Nothing to do. - { - std::cerr << "(EE) Cannot close chat associated to tunnel id " << tunnel_id << ": not found." << std::endl; - return false ; - } - - _gxs_tunnel_contacts.erase(it) ; - - // GxsTunnelService::removeVirtualPeerId() will be called by the turtle service. - } - return true ; -} - -bool p3GxsTunnelService::getTunnelsInfo(std::vector &infos) -{ - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - for(std::map::const_iterator it(_gxs_tunnel_contacts.begin());it!=_gxs_tunnel_contacts.end();++it) - { - GxsTunnelInfo ti ; - - ti.tunnel_id = it->first ; - ti.destination_gxs_id = it->second.to_gxs_id ; - ti.source_gxs_id = it->second.own_gxs_id ; - ti.tunnel_status = it->second.status ; - ti.total_size_sent = it->second.total_sent ; - ti.total_size_received = it->second.total_received ; - - ti.pending_data_packets = 0; - RsPeerId p(it->first); - for(auto it(pendingGxsTunnelDataItems.begin());it!=pendingGxsTunnelDataItems.end();++it) - if(it->second.data_item->PeerId() == p) - ++ti.pending_data_packets ; - - ti.total_data_packets_sent =0; // not accounted for yet. - ti.total_data_packets_received=0 ; // not accounted for yet. - - infos.push_back(ti) ; - } - - return true ; -} - -void p3GxsTunnelService::debug_dump() -{ - RS_STACK_MUTEX(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/ - - rstime_t now = time(NULL) ; - - std::cerr << "p3GxsTunnelService::debug_dump()" << std::endl; - std::cerr << " Registered client services: " << std::endl; - - for(std::map::const_iterator it=mRegisteredServices.begin();it!=mRegisteredServices.end();++it) - std::cerr << std::hex << " " << it->first << " - " << (void*)it->second << std::dec << std::endl; - - std::cerr << " Active tunnels" << std::endl; - - for(std::map::const_iterator it=_gxs_tunnel_contacts.begin();it!=_gxs_tunnel_contacts.end();++it) - std::cerr << " tunnel_id=" << it->first << " vpid=" << it->second.virtual_peer_id << " status=" << it->second.status << " direction=" << it->second.direction << " last_contact=" << (now-it->second.last_contact) <<" secs ago. Last_keep_alive_sent:" << (now - it->second.last_keep_alive_sent) << " secs ago." << std::endl; - - std::cerr << " Virtual peers:" << std::endl; - - for(std::map::const_iterator it=_gxs_tunnel_virtual_peer_ids.begin();it!=_gxs_tunnel_virtual_peer_ids.end();++it) - std::cerr << " vpid=" << it->first << " to=" << it->second.gxs_id << " from=" << it->second.own_gxs_id << " tunnel_id=" << it->second.tunnel_id << " status=" << it->second.status << " direction=" << it->second.direction << " hash=" << it->second.hash << std::endl; - - std::cerr << " Pending items: " << std::endl; - std::cerr << " DH : " << pendingDHItems.size() << std::endl; - std::cerr << " Tunnel Management: " << pendingGxsTunnelItems.size() << std::endl; - std::cerr << " Data (client) : " << pendingGxsTunnelDataItems.size() << std::endl; -} - - - - - - - - - - - - - - - - diff --git a/libretroshare/src/gxstunnel/p3gxstunnel.h b/libretroshare/src/gxstunnel/p3gxstunnel.h deleted file mode 100644 index d6e200678..000000000 --- a/libretroshare/src/gxstunnel/p3gxstunnel.h +++ /dev/null @@ -1,274 +0,0 @@ -/******************************************************************************* - * libretroshare/src/chat: distantchat.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2015 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -// Generic tunnel service -// -// Preconditions: -// * the secured tunnel service takes care of: -// - tunnel health: tunnels are kept alive using special items, re-openned when necessary, etc. -// - transport: items are ACK-ed and re-sent if never received -// - encryption: items are all encrypted and authenticated using PFS(DH)+HMAC(sha1)+AES(128) -// * each tunnel is associated to a specific GXS id on both sides. Consequently, services that request tunnels from different IDs to a -// server for the same GXS id need to be handled correctly. -// * client services must register to the secured tunnel service if they want to use it. -// * multiple services can use the same tunnel. Items contain a service Id that is obtained when registering to the secured tunnel service. -// -// GUI -// * the GUI should show for each tunnel: -// - starting and ending GXS ids -// - tunnel status (DH ok, closed from distant peer, locally closed, etc) -// - amount of data that is transferred in the tunnel -// - number of pending items (and total size) -// - number ACKed items both ways. -// -// We can use an additional tab "Authenticated tunnels" in the statistics->turtle window for that purpose. -// -// Interaction with services: -// -// Services request tunnels from a given GXS id and to a given GXS id. When ready, they get a handle (type = RsGxsTunnelId) -// -// Services send data in the tunnel using the virtual peer id -// -// Data is send to a service ID (could be any existing service ID). The endpoint of the tunnel must register each service, in order to -// allow the data to be transmitted/sent from/to that service. Otherwise an error is issued. -// -// Encryption -// * the whole tunnel traffic is encrypted using AES-128 with random IV -// * a random key is established using DH key exchange for each connection (establishment of a new virtual peer) -// * encrypted items are authenticated with HMAC(sha1). -// * DH public keys are the only chunks of data that travel un-encrypted along the tunnel. They are -// signed to avoid any MITM interactions. No time-stamp is used in DH exchange since a replay attack would not work. -// -// Algorithms -// -// * we need two layers: the turtle layer, and the GXS id layer. -// - for each pair of GXS ids talking, a single turtle tunnel is used -// - that tunnel can be shared by multiple services using it. -// - services are responsoble for asking tunnels and also droppping them when unused. -// - at the turtle layer, the tunnel will be effectively closed only when no service uses it. -// * IDs -// TurtleVirtualPeerId: -// - Used by tunnel service for each turtle tunnel -// - one virtual peer ID per GXS tunnel -// -// GxsTunnelId: -// - one GxsTunnelId per couple of GXS ids. But we also need to allow multiple services to use the tunnel. -// -// * at the turtle layer: -// - accept virtual peers from turtle tunnel service. The hash for that VP only depends on the server GXS id at server side, which is our -// own ID at server side, and destination ID at client side. What happens if two different clients request to talk to the same GXS id? (same hash) -// They should use different virtual peers, so it should be ok. -// -// Turtle hash: [ 0 ---------------15 16---19 ] -// Destination Random -// -// We Use 16 bytes to target the exact destination of the hash. The source part is just 4 arbitrary bytes that need to be different for all source -// IDs that come from the same peer, which is quite likely to be sufficient. The real source of the tunnel will make itself known when sending the -// DH key. -// -// * at the GXS layer -// - we should be able to have as many tunnels as they are different couples of GXS ids to interact. That means the tunnel should be determined -// by a mix between our own GXS id and the GXS id we're talking to. That is what the TunnelVirtualPeer is. -// -// -// RequestTunnel(source_own_id,destination_id) - -// | | -// +---------------------------> p3Turtle::monitorTunnels( hash(destination_id) ) | -// | | -// [Turtle async work] -------------------+ | Turtle layer: one virtual peer id -// | | | -// handleTunnelRequest() <-----------------------------------------------+ | | -// | | | -// +---------------- keep record in _gxs_tunnel_virtual_peer_id, initiate DH exchange | - -// | | -// handleDHPublicKey() <-----------------------------------------------------------------------------+ | -// | | -// +---------------- update _gxs_tunnel_contacts[ tunnel_hash = hash(own_id, destination_id) ] | GxsTunnelId level -// | | -// +---------------- notify client service that Peer(destination_id, tunnel_hash) is ready to talk to | -// - - -#include -#include -#include -#include - -class RsGixs ; - -static const uint32_t GXS_TUNNEL_AES_KEY_SIZE = 16 ; - -class p3GxsTunnelService: public RsGxsTunnelService, public RsTurtleClientService, public p3Service -{ -public: - explicit p3GxsTunnelService(RsGixs *pids) ; - virtual void connectToTurtleRouter(p3turtle *) override; - - uint16_t serviceId() const override { return RS_SERVICE_TYPE_GXS_TUNNEL ; } - - // Creates the invite if the public key of the distant peer is available. - // Om success, stores the invite in the map above, so that we can respond to tunnel requests. - // - virtual bool requestSecuredTunnel(const RsGxsId& to_id,const RsGxsId& from_id,RsGxsTunnelId& tunnel_id,uint32_t service_id,uint32_t& error_code) override ; - virtual bool closeExistingTunnel(const RsGxsTunnelId &tunnel_id,uint32_t service_id) override ; - virtual bool getTunnelsInfo(std::vector& infos) override ; - virtual bool getTunnelInfo(const RsGxsTunnelId& tunnel_id,GxsTunnelInfo& info) override ; - virtual bool sendData(const RsGxsTunnelId& tunnel_id,uint32_t service_id,const uint8_t *data,uint32_t size) override ; - virtual bool registerClientService(uint32_t service_id,RsGxsTunnelClientService *service) override ; - - // derived from p3service - - virtual int tick() override; - virtual RsServiceInfo getServiceInfo() override; - -private: - void flush() ; - virtual void handleIncomingItem(const RsGxsTunnelId &tunnel_id, RsGxsTunnelItem *) ; - - class GxsTunnelPeerInfo - { - public: - GxsTunnelPeerInfo() - : last_contact(0), last_keep_alive_sent(0), status(0), direction(0) - , total_sent(0), total_received(0) - #ifndef V07_NON_BACKWARD_COMPATIBLE_CHANGE_004 - , accepts_fast_turtle_items(false) - , already_probed_for_fast_items(false) - #endif - { - memset(aes_key, 0, GXS_TUNNEL_AES_KEY_SIZE); - } - - rstime_t last_contact ; // used to keep track of working connexion - rstime_t last_keep_alive_sent ; // last time we sent a keep alive packet. - - unsigned char aes_key[GXS_TUNNEL_AES_KEY_SIZE] ; - - uint32_t status ; // info: do we have a tunnel ? - RsPeerId virtual_peer_id; // given by the turtle router. Identifies the tunnel. - RsGxsId to_gxs_id; // gxs id we're talking to - RsGxsId own_gxs_id ; // gxs id we're using to talk. - RsTurtleGenericTunnelItem::Direction direction ; // specifiec wether we are client(managing the tunnel) or server. - TurtleFileHash hash ; // hash that is last used. This is necessary for handling tunnel establishment - std::set client_services ; // services that used this tunnel - std::map received_data_prints ; // list of recently received messages, to avoid duplicates. Kept for 20 mins at most. - uint32_t total_sent ; // total data sent to this peer - uint32_t total_received ; // total data received by this peer -#ifndef V07_NON_BACKWARD_COMPATIBLE_CHANGE_004 - bool accepts_fast_turtle_items; // does the tunnel accept RsTurtleGenericFastDataItem type? - bool already_probed_for_fast_items; // has the tunnel been probed already? If not, a fast item will be sent -#endif - }; - - class GxsTunnelDHInfo - { - public: - GxsTunnelDHInfo() : dh(0), direction(0), status(0) {} - - DH *dh ; - RsGxsId gxs_id ; - RsGxsId own_gxs_id ; - RsGxsTunnelId tunnel_id ; // this is a proxy, since we cna always recompute that from the two previous values. - RsTurtleGenericTunnelItem::Direction direction ; - uint32_t status ; - TurtleFileHash hash ; - }; - - struct GxsTunnelData - { - RsGxsTunnelDataItem *data_item ; - rstime_t last_sending_attempt ; - }; - - // This maps contains the current peers to talk to with distant chat. - // - std::map _gxs_tunnel_contacts ; // current peers we can talk to - std::map _gxs_tunnel_virtual_peer_ids ; // current virtual peers. Used to figure out tunnels, etc. - - // List of items to be sent asap. Used to store items that we cannot pass directly to - // sendTurtleData(), because of Mutex protection. - - std::map pendingGxsTunnelDataItems ; // items that need provable transport and encryption - std::list pendingGxsTunnelItems ; // items that do not need provable transport, yet need encryption - std::list pendingDHItems ; - - // Overloaded from RsTurtleClientService - - virtual bool handleTunnelRequest(const RsFileHash &hash,const RsPeerId& peer_id) override; - virtual void receiveTurtleData(const RsTurtleGenericTunnelItem *item,const RsFileHash& hash,const RsPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction) override; - void addVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&,RsTurtleGenericTunnelItem::Direction dir) override; - void removeVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&) override; - - // session handling handles - - void startClientGxsTunnelConnection(const RsGxsId &to_gxs_id, const RsGxsId& from_gxs_id, uint32_t service_id, RsGxsTunnelId &tunnel_id) ; - void locked_restartDHSession(const RsPeerId &virtual_peer_id, const RsGxsId &own_gxs_id) ; - - // utility functions - - static TurtleFileHash randomHashFromDestinationGxsId(const RsGxsId& destination) ; - static RsGxsId destinationGxsIdFromHash(const TurtleFileHash& sum) ; - - // Cryptography management - - void handleRecvDHPublicKey(RsGxsTunnelDHPublicKeyItem *item) ; - bool locked_sendDHPublicKey(const DH *dh, const RsGxsId& own_gxs_id, const RsPeerId& virtual_peer_id) ; - bool locked_initDHSessionKey(DH *&dh); - uint64_t locked_getPacketCounter(); - - TurtleVirtualPeerId virtualPeerIdFromHash(const TurtleFileHash& hash) ; // ... and to a hash for p3turtle - - // item handling - - void handleRecvStatusItem(const RsGxsTunnelId& id,RsGxsTunnelStatusItem *item) ; - void handleRecvTunnelDataItem(const RsGxsTunnelId& id,RsGxsTunnelDataItem *item) ; - void handleRecvTunnelDataAckItem(const RsGxsTunnelId &id, RsGxsTunnelDataAckItem *item); - - // Comunication with Turtle service - - bool locked_sendEncryptedTunnelData(RsGxsTunnelItem *item) ; - bool locked_sendClearTunnelData(RsGxsTunnelDHPublicKeyItem *item); // this limits the usage to DH items. Others should be encrypted! - -#ifndef V07_NON_BACKWARD_COMPATIBLE_CHANGE_004 - bool handleEncryptedData(const uint8_t *data_bytes, uint32_t data_size, const TurtleFileHash& hash, const RsPeerId& virtual_peer_id, bool accepts_fast_items) ; -#else - bool handleEncryptedData(const uint8_t *data_bytes, uint32_t data_size, const TurtleFileHash& hash, const RsPeerId& virtual_peer_id) ; -#endif - - // local data - - p3turtle *mTurtle ; - RsGixs *mGixs ; - RsMutex mGxsTunnelMtx ; - - uint64_t mCurrentPacketCounter ; - - std::map mRegisteredServices ; - - void debug_dump(); - -public: - /// creates a unique tunnel ID from two GXS ids. - static RsGxsTunnelId makeGxsTunnelId( const RsGxsId &own_id, - const RsGxsId &distant_id ); -}; - diff --git a/libretroshare/src/gxstunnel/rsgxstunnelitems.cc b/libretroshare/src/gxstunnel/rsgxstunnelitems.cc deleted file mode 100644 index f86529c3b..000000000 --- a/libretroshare/src/gxstunnel/rsgxstunnelitems.cc +++ /dev/null @@ -1,138 +0,0 @@ -/******************************************************************************* - * libretroshare/src/gxstunnel: rsgxstunnelitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2015 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include -#include "util/rstime.h" -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rstypeserializer.h" -#include "util/rsprint.h" -#include "util/rsmemory.h" - -#include "gxstunnel/rsgxstunnelitems.h" - -//#define GXS_TUNNEL_ITEM_DEBUG 1 - -RsItem *RsGxsTunnelSerialiser::create_item(uint16_t service,uint8_t item_subtype) const -{ - if(service != RS_SERVICE_TYPE_GXS_TUNNEL) - return NULL ; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_GXS_TUNNEL_DATA: return new RsGxsTunnelDataItem(); - case RS_PKT_SUBTYPE_GXS_TUNNEL_DATA_ACK: return new RsGxsTunnelDataAckItem(); - case RS_PKT_SUBTYPE_GXS_TUNNEL_DH_PUBLIC_KEY: return new RsGxsTunnelDHPublicKeyItem(); - case RS_PKT_SUBTYPE_GXS_TUNNEL_STATUS: return new RsGxsTunnelStatusItem(); - default: - return NULL ; - } -} - -RsGxsTunnelDHPublicKeyItem::~RsGxsTunnelDHPublicKeyItem() -{ - BN_free(public_key) ; -} - -void RsGxsTunnelDHPublicKeyItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,public_key,"public_key") ; - RsTypeSerializer::serial_process(j,ctx,signature,"signature") ; - RsTypeSerializer::serial_process(j,ctx,gxs_key,"gxs_key") ; -} - -template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, BIGNUM * const & member) -{ - uint32_t s = BN_num_bytes(member) ; - - if(size < offset + 4 + s) - return false ; - - bool ok = true ; - ok &= setRawUInt32(data, size, &offset, s); - - BN_bn2bin(member,&((unsigned char *)data)[offset]) ; - offset += s ; - - return ok; -} -template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, BIGNUM *& member) -{ - uint32_t s=0 ; - bool ok = true ; - ok &= getRawUInt32(data, size, &offset, &s); - - if(s > size || size - s < offset) - return false ; - - member = BN_bin2bn(&((unsigned char *)data)[offset],s,NULL) ; - offset += s ; - - return ok; -} -template<> uint32_t RsTypeSerializer::serial_size(BIGNUM * const & member) -{ - return 4 + BN_num_bytes(member) ; -} -template<> void RsTypeSerializer::print_data(const std::string& name,BIGNUM * const & /* member */) -{ - std::cerr << "[BIGNUM] : " << name << std::endl; -} - -RS_TYPE_SERIALIZER_TO_JSON_NOT_IMPLEMENTED_DEF(BIGNUM*) -RS_TYPE_SERIALIZER_FROM_JSON_NOT_IMPLEMENTED_DEF(BIGNUM*) - -void RsGxsTunnelStatusItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,status,"status") ; -} - -void RsGxsTunnelDataItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,unique_item_counter,"unique_item_counter") ; - RsTypeSerializer::serial_process(j,ctx,flags ,"flags") ; - RsTypeSerializer::serial_process(j,ctx,service_id ,"service_id") ; - - RsTypeSerializer::TlvMemBlock_proxy mem(data,data_size) ; - RsTypeSerializer::serial_process(j,ctx,mem,"data") ; -} -void RsGxsTunnelDataAckItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,unique_item_counter,"unique_item_counter") ; -} - - - - - - - - - - - - - - - - - diff --git a/libretroshare/src/gxstunnel/rsgxstunnelitems.h b/libretroshare/src/gxstunnel/rsgxstunnelitems.h deleted file mode 100644 index a098c8c05..000000000 --- a/libretroshare/src/gxstunnel/rsgxstunnelitems.h +++ /dev/null @@ -1,151 +0,0 @@ -/******************************************************************************* - * libretroshare/src/chat: rsgxstunnelitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2015 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include - -#include "rsitems/rsserviceids.h" -#include "rsitems/itempriorities.h" -#include "rsitems/rsitem.h" - -#include "retroshare/rstypes.h" -#include "serialiser/rstlvkeys.h" -#include "serialiser/rsserial.h" - -#include "serialiser/rstlvidset.h" -#include "serialiser/rstlvfileitem.h" - -/* chat Flags */ -const uint32_t RS_GXS_TUNNEL_FLAG_CLOSING_DISTANT_CONNECTION = 0x0400; -const uint32_t RS_GXS_TUNNEL_FLAG_ACK_DISTANT_CONNECTION = 0x0800; -const uint32_t RS_GXS_TUNNEL_FLAG_KEEP_ALIVE = 0x1000; - -const uint8_t RS_PKT_SUBTYPE_GXS_TUNNEL_DATA = 0x01 ; -const uint8_t RS_PKT_SUBTYPE_GXS_TUNNEL_DH_PUBLIC_KEY = 0x02 ; -const uint8_t RS_PKT_SUBTYPE_GXS_TUNNEL_STATUS = 0x03 ; -const uint8_t RS_PKT_SUBTYPE_GXS_TUNNEL_DATA_ACK = 0x04 ; - -typedef uint64_t GxsTunnelDHSessionId ; - -class RsGxsTunnelItem: public RsItem -{ - public: - explicit RsGxsTunnelItem(uint8_t item_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_GXS_TUNNEL,item_subtype) - { - setPriorityLevel(QOS_PRIORITY_RS_CHAT_ITEM) ; - } - - virtual ~RsGxsTunnelItem() {} - virtual void clear() {} -}; - -/*! - * For sending distant communication data. The item is not encrypted after being serialised, but the data it. - * The MAC is computed over encrypted data using the PFS key. All other items (except DH keys) are serialised, encrypted, and - * sent as data in a RsGxsTunnelDataItem. - * - * @see p3GxsTunnelService - */ -class RsGxsTunnelDataItem: public RsGxsTunnelItem -{ -public: - RsGxsTunnelDataItem() :RsGxsTunnelItem(RS_PKT_SUBTYPE_GXS_TUNNEL_DATA), unique_item_counter(0), flags(0), service_id(0), data_size(0), data(NULL) {} - explicit RsGxsTunnelDataItem(uint8_t subtype) :RsGxsTunnelItem(subtype) , unique_item_counter(0), flags(0), service_id(0), data_size(0), data(NULL) {} - - virtual ~RsGxsTunnelDataItem() {} - virtual void clear() {} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint64_t unique_item_counter; // this allows to make the item unique - uint32_t flags; // mainly NEEDS_HACK? - uint32_t service_id ; - uint32_t data_size ; // encrypted data size - unsigned char *data ; // encrypted data -}; - -// Used to send status of connection. This can be closing orders, flushing orders, etc. -// These items are always sent encrypted. - -class RsGxsTunnelStatusItem: public RsGxsTunnelItem -{ - public: - RsGxsTunnelStatusItem() :RsGxsTunnelItem(RS_PKT_SUBTYPE_GXS_TUNNEL_STATUS) , status(0) {} - RsGxsTunnelStatusItem(void *data,uint32_t size) ; // deserialization - - virtual ~RsGxsTunnelStatusItem() {} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t status ; -}; - -// Used to confirm reception of an encrypted item. - -class RsGxsTunnelDataAckItem: public RsGxsTunnelItem -{ - public: - RsGxsTunnelDataAckItem() :RsGxsTunnelItem(RS_PKT_SUBTYPE_GXS_TUNNEL_DATA_ACK), unique_item_counter(0) {} - RsGxsTunnelDataAckItem(void *data,uint32_t size) ; // deserialization - - virtual ~RsGxsTunnelDataAckItem() {} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint64_t unique_item_counter ; // unique identifier for that item -}; - - -// This class contains the public Diffie-Hellman parameters to be sent -// when performing a DH agreement over a distant chat tunnel. -// -class RsGxsTunnelDHPublicKeyItem: public RsGxsTunnelItem -{ - public: - RsGxsTunnelDHPublicKeyItem() :RsGxsTunnelItem(RS_PKT_SUBTYPE_GXS_TUNNEL_DH_PUBLIC_KEY), public_key(NULL) {} - RsGxsTunnelDHPublicKeyItem(void *data,uint32_t size) ; // deserialization - - virtual ~RsGxsTunnelDHPublicKeyItem() ; - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - // Private data to DH public key item - // - BIGNUM *public_key ; - - RsTlvKeySignature signature ; // signs the public key in a row. - RsTlvPublicRSAKey gxs_key ; // public key of the signer - - private: - // make the object non copy-able - RsGxsTunnelDHPublicKeyItem(const RsGxsTunnelDHPublicKeyItem&) : RsGxsTunnelItem(RS_PKT_SUBTYPE_GXS_TUNNEL_DH_PUBLIC_KEY), public_key(NULL) {} - const RsGxsTunnelDHPublicKeyItem& operator=(const RsGxsTunnelDHPublicKeyItem&) { public_key = NULL; return *this ;} -}; - -class RsGxsTunnelSerialiser: public RsServiceSerializer -{ -public: - RsGxsTunnelSerialiser() :RsServiceSerializer(RS_SERVICE_TYPE_GXS_TUNNEL) {} - - virtual RsItem *create_item(uint16_t service,uint8_t item_subtype) const ; -}; - diff --git a/libretroshare/src/jsonapi/README.adoc b/libretroshare/src/jsonapi/README.adoc deleted file mode 100644 index 64284b85c..000000000 --- a/libretroshare/src/jsonapi/README.adoc +++ /dev/null @@ -1,447 +0,0 @@ -// SPDX-FileCopyrightText: (C) 2004-2019 Retroshare Team -// SPDX-License-Identifier: CC0-1.0 - -RetroShare JSON API -=================== - -:Cxx: C++ - -== How to use RetroShare JSON API - -Look for methods marked with +@jsonapi+ doxygen custom command into -+libretroshare/src/retroshare+. The method path is composed by service instance -pointer name like +rsGxsChannels+ for +RsGxsChannels+, and the method name like -+createGroup+ and pass the input paramethers as a JSON object. - -.Service instance pointer in rsgxschannels.h -[source,cpp] --------------------------------------------------------------------------------- -/** - * Pointer to global instance of RsGxsChannels service implementation - * @jsonapi{development} - */ -extern RsGxsChannels* rsGxsChannels; --------------------------------------------------------------------------------- - -.Method declaration in rsgxschannels.h -[source,cpp] --------------------------------------------------------------------------------- - /** - * @brief Request channel creation. - * The action is performed asyncronously, so it could fail in a subsequent - * phase even after returning true. - * @jsonapi{development} - * @param[out] token Storage for RsTokenService token to track request - * status. - * @param[in] group Channel data (name, description...) - * @return false on error, true otherwise - */ - virtual bool createGroup(uint32_t& token, RsGxsChannelGroup& group) = 0; --------------------------------------------------------------------------------- - -.paramethers.json -[source,json] --------------------------------------------------------------------------------- -{ - "group":{ - "mMeta":{ - "mGroupName":"JSON test group", - "mGroupFlags":4, - "mSignFlags":520 - }, - "mDescription":"JSON test group description" - }, - "caller_data":"Here can go any kind of JSON data (even objects) that the caller want to get back together with the response" -} --------------------------------------------------------------------------------- - -.Calling the JSON API with curl on the terminal -[source,bash] --------------------------------------------------------------------------------- -curl -u $API_USER --data @paramethers.json http://127.0.0.1:9092/rsGxsChannels/createGroup --------------------------------------------------------------------------------- - -.JSON API call result -[source,json] --------------------------------------------------------------------------------- -{ - "caller_data": "Here can go any kind of JSON data (even objects) that the caller want to get back together with the response", - "retval": true, - "token": 3 -} --------------------------------------------------------------------------------- - -Even if it is less efficient because of URL encoding HTTP +GET+ method is -supported too, so in cases where the client cannot use +POST+ she can still use -+GET+ taking care of encoding the JSON data. With +curl+ this can be done at -least in two different ways. - -.Calling the JSON API with GET method with curl on the terminal -[source,bash] --------------------------------------------------------------------------------- -curl -u $API_USER --get --data-urlencode jsonData@paramethers.json \ - http://127.0.0.1:9092/rsGxsChannels/createGroup --------------------------------------------------------------------------------- - -Letting +curl+ do the encoding is much more elegant but it is semantically -equivalent to the following. - -.Calling the JSON API with GET method and pre-encoded data with curl on the terminal --------------------------------------------------------------------------------- -curl -u $API_USER http://127.0.0.1:9092/rsGxsChannels/createGroup?jsonData=%7B%0A%20%20%20%20%22group%22%3A%7B%0A%20%20%20%20%20%20%20%20%22mMeta%22%3A%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22mGroupName%22%3A%22JSON%20test%20group%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22mGroupFlags%22%3A4%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22mSignFlags%22%3A520%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%22mDescription%22%3A%22JSON%20test%20group%20description%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20%22caller_data%22%3A%22Here%20can%20go%20any%20kind%20of%20JSON%20data%20%28even%20objects%29%20that%20the%20caller%20want%20to%20get%20back%20together%20with%20the%20response%22%0A%7D --------------------------------------------------------------------------------- - -Note that using +GET+ method +?jsonData=+ and then the JSON data URL encoded are -added after the path in the HTTP request. - - -== JSON API authentication - -Most of JSON API methods require authentication as they give access to -RetroShare user data, and we don't want any application running on the system -eventually by other users be able to access private data indiscriminately. -JSON API support HTTP Basic as authentication scheme, this is enough as JSON API -server is intented for usage on the same system (127.0.0.1) not over an -untrusted network. -If you need to use JSON API over an untrusted network consider using a reverse -proxy with HTTPS such as NGINX in front of JSON API server. -If RetroShare login has been effectuated through the JSON API you can use your -location SSLID as username and your PGP password as credential for the JSON API, -but we suggests you use specific meaningful and human readable credentials for -each JSON API client so the human user can have better control over which client -can access the JSON API. - -.NewToken.json -[source,json] --------------------------------------------------------------------------------- -{ - "token": "myNewUser:myNewPassword" -} --------------------------------------------------------------------------------- - -.An authenticated client can authorize new tokens like this --------------------------------------------------------------------------------- -curl -u $API_USER --data @NewToken.json http://127.0.0.1:9092/jsonApiServer/authorizeToken --------------------------------------------------------------------------------- - -.An unauthenticated JSON API client can request access with --------------------------------------------------------------------------------- -curl --data @NewToken.json http://127.0.0.1:9092/jsonApiServer/requestNewTokenAutorization --------------------------------------------------------------------------------- - -When an unauthenticated client request his token to be authorized, JSON API -server will try to ask confirmation to the human user if possible through -+mNewAccessRequestCallback+, if it is not possible or the user didn't authorized -the token +false+ is returned. - - -== Offer new RetroShare services through JSON API - -To offer a retroshare service through the JSON API, first of all one need find -the global pointer to the service instance and document it in doxygen syntax, -plus marking with the custom doxygen command +@jsonapi{RS_VERSION}+ where -+RS_VERSION+ is the retroshare version in which this service became available -with the current semantic (major changes to the service semantic, changes the -meaning of the service itself, so the version should be updated in the -documentation in that case). - -.Service instance pointer in rsgxschannels.h -[source,cpp] --------------------------------------------------------------------------------- -/** - * Pointer to global instance of RsGxsChannels service implementation - * @jsonapi{development} - */ -extern RsGxsChannels* rsGxsChannels; --------------------------------------------------------------------------------- - - -Once the service instance itself is known to the JSON API you need to document -in doxygen syntax and mark with the custom doxygen command -+@jsonapi{RS_VERSION}+ the methods of the service that you want to make -available through JSON API. - -.Offering RsGxsChannels::getChannelDownloadDirectory in rsgxschannels.h -[source,cpp] --------------------------------------------------------------------------------- - /** - * Get download directory for the given channel - * @jsonapi{development} - * @param[in] channelId id of the channel - * @param[out] directory reference to string where to store the path - * @return false on error, true otherwise - */ - virtual bool getChannelDownloadDirectory( const RsGxsGroupId& channelId, - std::string& directory ) = 0; --------------------------------------------------------------------------------- - -For each paramether you must specify if it is used as input +@param[in]+ as -output +@param[out]+ or both +@param[inout]+. Paramethers and return value -types must be of a type supported by +RsTypeSerializer+ which already support -most basic types (+bool+, +std::string+...), +RsSerializable+ and containers of -them like +std::vector+. Paramethers passed by value and by -reference of those types are both supported, while passing by pointer is not -supported. If your paramether or return +class+/+struct+ type is not supported -yet by +RsTypeSerializer+ most convenient approach is to make it derive from -+RsSerializable+ and implement +serial_process+ method like I did with -+RsGxsChannelGroup+. - -.Deriving RsGxsChannelGroup from RsSerializable in rsgxschannels.h -[source,cpp] --------------------------------------------------------------------------------- -struct RsGxsChannelGroup : RsSerializable -{ - RsGroupMetaData mMeta; - std::string mDescription; - RsGxsImage mImage; - - bool mAutoDownload; - - /// @see RsSerializable - virtual void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(mMeta); - RS_SERIAL_PROCESS(mDescription); - RS_SERIAL_PROCESS(mImage); - RS_SERIAL_PROCESS(mAutoDownload); - } -}; --------------------------------------------------------------------------------- - -You can do the same recursively for any member of your +struct+ that is not yet -supported by +RsTypeSerializer+. - -Some Retroshare {Cxx} API functions are asyncronous, historically RetroShare -didn't follow a policy on how to expose asyncronous API so differents services -and some times even differents method of the same service follow differents -asyncronous patterns, thus making automatic generation of JSON API wrappers for -those methods impractical. Instead of dealing with all those differents patterns -I have chosed to support only one new pattern taking advantage of modern {Cxx}11 -and restbed features. On the {Cxx}11 side lambdas and +std::function+s are used, -on the restbed side Server Side Events are used to send asyncronous results. - -Lets see an example so it will be much esier to understand. - -.RsGxsChannels::turtleSearchRequest asyncronous API -[source,cpp] --------------------------------------------------------------------------------- - /** - * @brief Request remote channels search - * @jsonapi{development} - * @param[in] matchString string to look for in the search - * @param multiCallback function that will be called each time a search - * result is received - * @param[in] maxWait maximum wait time in seconds for search results - * @return false on error, true otherwise - */ - virtual bool turtleSearchRequest( - const std::string& matchString, - const std::function& multiCallback, - std::time_t maxWait = 300 ) = 0; --------------------------------------------------------------------------------- - -+RsGxsChannels::turtleSearchRequest(...)+ is an asyncronous method because it -send a channel search request on turtle network and then everytime a result is -received from the network +multiCallback+ is called and the result is passed as -parameter. To be supported by the automatic JSON API wrappers generator an -asyncronous method need a parameter of type +std::function+ called -+callback+ if the callback will be called only once or +multiCallback+ if the -callback is expected to be called more then once like in this case. -A second mandatory parameter is +maxWait+ of type +std::time_t+ it indicates the -maximum amount of time in seconds for which the caller is willing to wait for -results, in case the timeout is reached the callback will not be called anymore. - -[IMPORTANT] -================================================================================ -+callback+ and +multiCallback+ parameters documentation must *not* specify -+[in]+, +[out]+, +[inout]+, in Doxygen documentation as this would fool the -automatic wrapper generator, and ultimately break the compilation. -================================================================================ - -.RsFiles::turtleSearchRequest asyncronous JSON API usage example -[source,bash] --------------------------------------------------------------------------------- -$ cat turtle_search.json -{ - "matchString":"linux" -} -$ curl --data @turtle_search.json http://127.0.0.1:9092/rsFiles/turtleSearchRequest -data: {"retval":true} - -data: {"results":[{"size":157631,"hash":"69709b4d01025584a8def5cd78ebbd1a3cf3fd05","name":"kill_bill_linux_1024x768.jpg"},{"size":192560,"hash":"000000000000000000009a93e5be8486c496f46c","name":"coffee_box_linux2.jpg"},{"size":455087,"hash":"9a93e5be8486c496f46c00000000000000000000","name":"Linux.png"},{"size":182004,"hash":"e8845280912ebf3779e400000000000000000000","name":"Linux_2_6.png"}]} - -data: {"results":[{"size":668,"hash":"e8845280912ebf3779e400000000000000000000","name":"linux.png"},{"size":70,"hash":"e8845280912ebf3779e400000000000000000000","name":"kali-linux-2016.2-amd64.txt.sha1sum"},{"size":3076767744,"hash":"e8845280912ebf3779e400000000000000000000","name":"kali-linux-2016.2-amd64.iso"},{"size":2780872,"hash":"e8845280912ebf3779e400000000000000000000","name":"openwrt-ar71xx-generic-vmlinux.bin"},{"size":917504,"hash":"e8845280912ebf3779e400000000000000000000","name":"openwrt-ar71xx-generic-vmlinux.lzma"},{"size":2278404096,"hash":"e8845280912ebf3779e400000000000000000000","name":"gentoo-linux-livedvd-amd64-multilib-20160704.iso"},{"size":151770333,"hash":"e8845280912ebf3779e400000000000000000000","name":"flashtool-0.9.23.0-linux.tar.7z"},{"size":2847372,"hash":"e8845280912ebf3779e400000000000000000000","name":"openwrt-ar71xx-generic-vmlinux.elf"},{"size":1310720,"hash":"e8845280912ebf3779e400000000000000000000","name":"openwrt-ar71xx-generic-vmlinux.gz"},{"size":987809,"hash":"e8845280912ebf3779e400000000000000000000","name":"openwrt-ar71xx-generic-vmlinux-lzma.elf"}]} - --------------------------------------------------------------------------------- - -By default JSON API methods requires client authentication and their wrappers -are automatically generated by +json-api-generator+. -In some cases methods need do be accessible without authentication such as -+rsLoginHelper/getLocations+ so in the doxygen documentaion they have the custom -command +@jsonapi{RS_VERSION,unauthenticated}+. -Other methods such as +/rsControl/rsGlobalShutDown+ need special care so they -are marked with the custom doxygen command +@jsonapi{RS_VERSION,manualwrapper}+ -and their wrappers are not automatically generated but written manually into -+JsonApiServer::JsonApiServer(...)+. - -== Quirks - -=== 64 bits integers handling - -While JSON doesn't have problems representing 64 bits integers JavaScript, Dart -and other languages are not capable to handle those numbers natively. -To overcome this limitation JSON API output 64 bit integers as an object with -two keys, one as proper integer and one as string representation. - -.JSON API 64 bit integer output example -[source,json] --------------------------------------------------------------------------------- -"lobby_id": { "xint64": 6215642878098695544, "xstr64": "6215642878098695544" } --------------------------------------------------------------------------------- - -So from languages that have proper 64bit integers support like Python or C++ one -better read from `xint64` which is represented as a JSON integer, from languages -where there is no proper 64bit integers support like JavaScript one can read from -`xstr64` which is represented as JSON string (note that the first is not wrapped -in "" while the latter is). - -When one input a 64bit integer into the JSON API it first try to parse it as if -it was sent the old way for retrocompatibility. - -.JSON API 64 bit integer deprecated format input example -[source,json] --------------------------------------------------------------------------------- -"lobby_id":6215642878098695544 --------------------------------------------------------------------------------- - -This way is *DEPRECATED* and may disappear in the future, it is TEMPORALLY kept -only for retrocompatibiliy with old clients. - -If retrocompatible parsing attempt fail then it try to parse with the new way -with proper JSON integer format. - -.JSON API 64 bit integer new proper integer format input example -[source,json] --------------------------------------------------------------------------------- -lobby_id": { "xint64": 6215642878098695544 } --------------------------------------------------------------------------------- - -If this fails then it try to parse with the new way with JSON string format. - -.JSON API 64 bit integer new string format input example -[source,json] --------------------------------------------------------------------------------- -"lobby_id": { "xstr64": "6215642878098695544" } --------------------------------------------------------------------------------- - -[WARNING] -================================================================================ -Clients written in languages without proper 64bit integers support must -use *ONLY* the string format otherwise they will send approximated values and -get unexpected results from the JSON API, because parsing will success but the -value will not be exactly the one you believe you sent. -================================================================================ - - -== A bit of history - -=== First writings about this - -The previous attempt of exposing a RetroShare JSON API is called +libresapi+ and -unfortunatley it requires a bunch of boilerplate code when we want to expose -something present in the {Cxx} API in the JSON API. - -As an example here you can see the libresapi that exposes part of the retroshare -chat {Cxx} API and lot of boilerplate code just to convert {Cxx} objects to JSON - -https://github.com/RetroShare/RetroShare/blob/v0.6.4/libresapi/src/api/ChatHandler.cpp#L44 - -To avoid the {Cxx} to JSON and back conversion boilerplate code I have worked out -an extension to our {Cxx} serialization code so it is capable to serialize and -deserialize to JSON you can see it in this pull request - -https://github.com/RetroShare/RetroShare/pull/1155 - -So first step toward having a good API is to take advantage of the fact that RS -is now capable of converting C++ objects from and to JSON. - -The current API is accessible via HTTP and unix socket, there is no -authentication in both of them, so anyone having access to the HTTP server or to -the unix socket can access the API without extra restrictions. -Expecially for the HTTP API this is a big risk because also if the http server -listen on 127.0.0.1 every application on the machine (even rogue javascript -running on your web browser) can access that and for example on android it is -not safe at all (because of that I implemented the unix socket access so at -least in android API was reasonably safe) because of this. - -A second step to improve the API would be to implement some kind of API -authentication mechanism (it would be nice that the mechanism is handled at API -level and not at transport level so we can use it for any API trasport not just -HTTP for example) - -The HTTP server used by libresapi is libmicrohttpd server that is very minimal, -it doesn't provide HTTPS nor modern HTTP goodies, like server notifications, -websockets etc. because the lack of support we have a token polling mechanism in -libresapi to avoid polling for every thing but it is still ugly, so if we can -completely get rid of polling in the API that would be really nice. -I have done a crawl to look for a replacement and briefly looked at - -- https://www.gnu.org/software/libmicrohttpd/ -- http://wolkykim.github.io/libasyncd/ -- https://github.com/corvusoft/restbed -- https://code.facebook.com/posts/1503205539947302/introducing-proxygen-facebook-s-c-http-framework/ -- https://github.com/cmouse/yahttp - -taking in account a few metrics like modern HTTP goodies support, license, -platform support, external dependencies and documentation it seemed to me that -restbed is the more appropriate. - -Another source of boilerplate code into libresapi is the mapping between JSON -API requests and C++ API methods as an example you can look at this - -https://github.com/RetroShare/RetroShare/blob/v0.6.4/libresapi/src/api/ChatHandler.cpp#L158 - -and this - -https://github.com/RetroShare/RetroShare/blob/v0.6.4/libresapi/src/api/ApiServer.cpp#L253 - -The abstract logic of this thing is, when libreasapi get a request like -+/chat/initiate_distant_chat+ then call -+ChatHandler::handleInitiateDistantChatConnexion+ which in turn is just a -wrapper of +RsMsgs::initiateDistantChatConnexion+ all this process is basically -implemented as boilerplate code and would be unnecessary in a smarter design of -the API because almost all the information needed is already present in the -C++ API +libretroshare/src/retroshare+. - -So a third step to improve the JSON API would be to remove this source of -boilerplate code by automatizing the mapping between C++ and JSON API call. - -This may result a little tricky as language parsing or other adevanced things -may be required. - -Hope this dive is useful for you + -Cheers + -G10h4ck - -=== Second writings about this - -I have been investigating a bit more about: -[verse, G10h4ck] -________________________________________________________________________________ -So a third step to improve the JSON API would be to remove this source of -boilerplate code by automatizing the mapping between C++ and JSON API call -________________________________________________________________________________ - -After spending some hours investigating this topic the most reasonable approach -seems to: - -1. Properly document headers in +libretroshare/src/retroshare/+ in doxygen syntax -specifying wihich params are input and/or output (doxygen sysntax for this is -+@param[in/out/inout]+) this will be the API documentation too. - -2. At compile time use doxygen to generate XML description of the headers and use -the XML to generate the JSON api server stub. -http://www.stack.nl/~dimitri/doxygen/manual/customize.html#xmlgenerator - -3. Enjoy diff --git a/libretroshare/src/jsonapi/async-method-wrapper-template.cpp.tmpl b/libretroshare/src/jsonapi/async-method-wrapper-template.cpp.tmpl deleted file mode 100644 index 29f53ad48..000000000 --- a/libretroshare/src/jsonapi/async-method-wrapper-template.cpp.tmpl +++ /dev/null @@ -1,80 +0,0 @@ -/******************************************************************************* - * RetroShare JSON API * - * * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License version 3 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -registerHandler( "$%apiPath%$", - [this](const std::shared_ptr session) -{ - const std::multimap headers - { - { "Connection", "keep-alive" }, - { "Content-Type", "text/event-stream" } - }; - session->yield(rb::OK, headers); - - size_t reqSize = session->get_request()->get_header("Content-Length", 0); - session->fetch( reqSize, [this]( - const std::shared_ptr session, - const rb::Bytes& body ) - { - INITIALIZE_API_CALL_JSON_CONTEXT; - - if( !checkRsServicePtrReady( - $%instanceName%$, "$%instanceName%$", cAns, session ) ) - return; - -$%paramsDeclaration%$ - -$%inputParamsDeserialization%$ - - const std::weak_ptr weakService(mService); - const std::weak_ptr weakSession(session); - $%callbackName%$ = [weakService, weakSession]($%callbackParams%$) - { - auto session = weakSession.lock(); - if(!session || session->is_closed()) return; - - auto lService = weakService.lock(); - if(!lService || lService->is_down()) return; - -$%callbackParamsSerialization%$ - - std::stringstream sStream; - sStream << "data: " << compactJSON << ctx.mJson << "\n\n"; - const std::string message = sStream.str(); - - lService->schedule( [weakSession, message]() - { - auto session = weakSession.lock(); - if(!session || session->is_closed()) return; - session->yield(message); - $%sessionEarlyClose%$ - } ); - }; - -$%functionCall%$ - -$%outputParamsSerialization%$ - - // return them to the API caller - std::stringstream message; - message << "data: " << compactJSON << cAns.mJson << "\n\n"; - session->yield(message.str()); - $%sessionDelayedClose%$ - } ); -}, $%requiresAuth%$ ); diff --git a/libretroshare/src/jsonapi/jsonapi-generator-doxygen.conf b/libretroshare/src/jsonapi/jsonapi-generator-doxygen.conf deleted file mode 100644 index 0edd1de3e..000000000 --- a/libretroshare/src/jsonapi/jsonapi-generator-doxygen.conf +++ /dev/null @@ -1,230 +0,0 @@ -DOXYFILE_ENCODING = UTF-8 -PROJECT_NAME = "libretroshare" - -ALIASES += jsonapi{1}="\xmlonly\endxmlonly" -ALIASES += jsonapi{2}="\xmlonly\endxmlonly" - -# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the -# documentation from any documented member that it re-implements. -# The default value is: YES. - -INHERIT_DOCS = YES - -# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments -# according to the Markdown format, which allows for more readable -# documentation. See http://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by doxygen, so you can -# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in -# case of backward compatibilities issues. -# The default value is: YES. - -MARKDOWN_SUPPORT = YES - -# When enabled doxygen tries to link words that correspond to documented -# classes, or namespaces to their corresponding documentation. Such a link can -# be prevented in individual cases by putting a % sign in front of the word or -# globally by setting AUTOLINK_SUPPORT to NO. -# The default value is: YES. - -AUTOLINK_SUPPORT = YES - - -# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in -# documentation are documented, even if no documentation was available. Private -# class members and static file members will be hidden unless the -# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. -# Note: This will also disable the warnings about undocumented members that are -# normally produced when WARNINGS is set to YES. -# The default value is: NO. - -EXTRACT_ALL = YES - - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all -# undocumented members inside documented classes or files. If set to NO these -# members will be included in the various overviews, but no documentation -# section is generated. This option has no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. If set -# to NO, these classes will be included in the various overviews. This option -# has no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_CLASSES = NO - - -#--------------------------------------------------------------------------- -# Configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag is used to specify the files and/or directories that contain -# documented source files. You may enter file names like myfile.cpp or -# directories like /usr/src/myproject. Separate the files or directories with -# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING -# Note: If this tag is empty the current directory is searched. - -#INPUT = - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses -# libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: https://www.gnu.org/software/libiconv/) for the list of -# possible encodings. -# The default value is: UTF-8. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and -# *.h) to filter out the source-files in the directories. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# read by doxygen. -# -# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, -# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, -# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, -# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, -# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. - -FILE_PATTERNS = *.c \ - *.cc \ - *.cxx \ - *.cpp \ - *.c++ \ - *.java \ - *.ii \ - *.ixx \ - *.ipp \ - *.i++ \ - *.inl \ - *.idl \ - *.ddl \ - *.odl \ - *.h \ - *.hh \ - *.hxx \ - *.hpp \ - *.h++ \ - *.cs \ - *.d \ - *.php \ - *.php4 \ - *.php5 \ - *.phtml \ - *.inc \ - *.m \ - *.markdown \ - *.md \ - *.mm \ - *.dox \ - *.py \ - *.pyw \ - *.f90 \ - *.f95 \ - *.f03 \ - *.f08 \ - *.f \ - *.for \ - *.tcl \ - *.vhd \ - *.vhdl \ - *.ucf \ - *.qsf - -# The RECURSIVE tag can be used to specify whether or not subdirectories should -# be searched for input files as well. -# The default value is: NO. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should be -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. -# -# Note that relative paths are relative to the directory from which doxygen is -# run. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or -# directories that are symbolic links (a Unix file system feature) are excluded -# from the input. -# The default value is: NO. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories use the pattern */test/* - -EXCLUDE_SYMBOLS = - - -#--------------------------------------------------------------------------- -# Configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output -# The default value is: YES. - -GENERATE_HTML = NO - -# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output. -# The default value is: YES. - -GENERATE_LATEX = NO - -# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that -# captures the structure of the code including all documentation. -# The default value is: NO. - -GENERATE_XML = YES - - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all -# C-preprocessor directives found in the sources and include files. -# The default value is: YES. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names -# in the source code. If set to NO, only conditional compilation will be -# performed. Macro expansion can be done in a controlled way by setting -# EXPAND_ONLY_PREDEF to YES. -# The default value is: NO. -# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then -# the macro expansion is limited to the macros specified with the PREDEFINED and -# EXPAND_AS_DEFINED tags. -# The default value is: NO. -# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. - -EXPAND_ONLY_PREDEF = NO - diff --git a/libretroshare/src/jsonapi/jsonapi-generator.py b/libretroshare/src/jsonapi/jsonapi-generator.py deleted file mode 100755 index accf9a0cd..000000000 --- a/libretroshare/src/jsonapi/jsonapi-generator.py +++ /dev/null @@ -1,365 +0,0 @@ -#!/usr/bin/python3 - -# RetroShare JSON API generator -# -# Copyright (C) 2019 selankon -# Copyright (C) 2021 Gioacchino Mazzurco -# Copyright (C) 2021 AsociaciĆ³n Civil Altermundi -# -# This program is free software: you can redistribute it and/or modify it under -# the terms of the GNU Affero General Public License as published by the -# Free Software Foundation, version 3. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. -# See the GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License along -# with this program. If not, see -# -# SPDX-FileCopyrightText: Retroshare Team -# SPDX-License-Identifier: AGPL-3.0-only - - -# Original idea and implementation by G10h4ck (jsonapi-generator.cpp) -# Initial python reimplementation by Sehraf -# -# This python 3 script has superseded the original C++/Qt implementation this -# and is now used at build time in without depending on Qt. - -import os -import sys - -import xml.etree.ElementTree as ET -from string import Template - - -class MethodParam: - _type = '' - _name = '' - _defval = '' - _in = False - _out = False - _isMultiCallback = False - _isSingleCallback = False - - -class TemplateOwn(Template): - delimiter = '$%' - pattern = ''' - \$%(?: - (?P\$\%) | # Escape sequence of two delimiters - (?P[_a-z][_a-z0-9]*)%\$ | # delimiter and a Python identifier - {(?P[_a-z][_a-z0-9]*)} | # delimiter and a braced identifier - (?P) # Other ill-formed delimiter exprs - ) - ''' - - -def getText(e): - return "".join(e.itertext()) - - -def processFile(file): - try: - dom1 = ET.parse(file).getroot() - except FileNotFoundError: - print('Can\'t open:', file) - - headerFileInfo = dom1[0].findall('location')[0].attrib['file'] - headerRelPath = os.path.dirname(headerFileInfo).split('/')[-1] + '/' + os.path.basename(headerFileInfo) - - for sectDef in dom1.findall('.//memberdef'): - if sectDef.attrib['kind'] != 'variable' or sectDef.find('.//jsonapi') == None: - continue - - instanceName = sectDef.find('name').text - typeName = sectDef.find('type/ref').text - - typeFilePath = sectDef.find('type/ref').attrib['refid'] - - try: - dom2 = ET.parse(doxPrefix + typeFilePath + '.xml').getroot() - except FileNotFoundError: - print('Can\'t open:', doxPrefix + typeFilePath + '.xml') - - for member in dom2.findall('.//member'): - refid = member.attrib['refid'] - methodName = member.find('name').text - - requiresAuth = True - - defFilePath = refid.split('_')[0] + '.xml' - defFile = defFilePath - - print('Looking for', typeName, methodName, 'into', typeFilePath) - - try: - defDoc = ET.parse(doxPrefix + defFilePath).getroot() - except FileNotFoundError: - print('Can\'t open:', doxPrefix + defFilePath) - - memberdef = None - for tmpMBD in defDoc.findall('.//memberdef'): - tmpId = tmpMBD.attrib['id'] - tmpKind = tmpMBD.attrib['kind'] - tmpJsonApiTagList = tmpMBD.findall('.//jsonapi') - - if len(tmpJsonApiTagList) != 0 and tmpId == refid and tmpKind == 'function': - tmpJsonApiTag = tmpJsonApiTagList[0] - - tmpAccessValue = None - if 'access' in tmpJsonApiTag.attrib: - tmpAccessValue = tmpJsonApiTag.attrib['access'] - - requiresAuth = 'unauthenticated' != tmpAccessValue; - - if 'manualwrapper' != tmpAccessValue: - memberdef = tmpMBD - - break - - if memberdef == None: - continue - - apiPath = '/' + instanceName + '/' + methodName - - retvalType = getText(memberdef.find('type')) - # Apparently some xml declarations include new lines ('\n') and/or multiple spaces - # Strip them using python magic - retvalType = ' '.join(retvalType.split()) - - paramsMap = {} - orderedParamNames = [] - - hasInput = False - hasOutput = False - hasSingleCallback = False - hasMultiCallback = False - callbackName = '' - callbackParams = '' - - for tmpPE in memberdef.findall('param'): - mp = MethodParam() - - pName = getText(tmpPE.find('declname')) - tmpDefval = tmpPE.find('defval') - mp._defval = getText(tmpDefval) if tmpDefval != None else '' - pType = getText(tmpPE.find('type')) - - if pType.startswith('const '): pType = pType[6:] - if pType.startswith('std::function'): - if pType.endswith('&'): pType = pType[:-1] - if pName.startswith('multiCallback'): - mp._isMultiCallback = True - hasMultiCallback = True - elif pName.startswith('callback'): - mp._isSingleCallback = True - hasSingleCallback = True - callbackName = pName - callbackParams = pType - else: - pType = pType.replace('&', '').replace(' ', '') - - # Apparently some xml declarations include new lines ('\n') and/or multiple spaces - # Strip them using python magic - pType = ' '.join(pType.split()) - mp._defval = ' '.join(mp._defval.split()) - - mp._type = pType - mp._name = pName - - paramsMap[pName] = mp - orderedParamNames.append(pName) - - for tmpPN in memberdef.findall('.//parametername'): - tmpParam = paramsMap[tmpPN.text] - tmpD = tmpPN.attrib['direction'] if 'direction' in tmpPN.attrib else '' - - if 'in' in tmpD: - tmpParam._in = True - hasInput = True - if 'out' in tmpD: - tmpParam._out = True - hasOutput = True - - # Params sanity check - for pmKey in paramsMap: - pm = paramsMap[pmKey] - if not (pm._isMultiCallback or pm._isSingleCallback or pm._in or pm._out): - print('ERROR', 'Parameter:', pm._name, 'of:', apiPath, - 'declared in:', headerRelPath, - 'miss doxygen parameter direction attribute!', - defFile) - sys.exit() - - functionCall = '\t\t' - if retvalType != 'void': - functionCall += retvalType + ' retval = ' - hasOutput = True - functionCall += instanceName + '->' + methodName + '(' - functionCall += ', '.join(orderedParamNames) + ');\n' - - print(instanceName, apiPath, retvalType, typeName, methodName) - for pn in orderedParamNames: - mp = paramsMap[pn] - print('\t', mp._type, mp._name, mp._in, mp._out) - - inputParamsDeserialization = '' - if hasInput: - inputParamsDeserialization += '\t\t{\n' - inputParamsDeserialization += '\t\t\tRsGenericSerializer::SerializeContext& ctx(cReq);\n' - inputParamsDeserialization += '\t\t\tRsGenericSerializer::SerializeJob j(RsGenericSerializer::FROM_JSON);\n'; - - outputParamsSerialization = '' - if hasOutput: - outputParamsSerialization += '\t\t{\n' - outputParamsSerialization += '\t\t\tRsGenericSerializer::SerializeContext& ctx(cAns);\n' - outputParamsSerialization += '\t\t\tRsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON);\n'; - - paramsDeclaration = '' - for pn in orderedParamNames: - mp = paramsMap[pn] - paramsDeclaration += '\t\t' + mp._type + ' ' + mp._name - if mp._defval != '': - paramsDeclaration += ' = ' + mp._defval - paramsDeclaration += ';\n' - if mp._in: - inputParamsDeserialization += '\t\t\tRS_SERIAL_PROCESS(' - inputParamsDeserialization += mp._name + ');\n' - if mp._out: - outputParamsSerialization += '\t\t\tRS_SERIAL_PROCESS(' - outputParamsSerialization += mp._name + ');\n' - - if hasInput: - inputParamsDeserialization += '\t\t}\n' - if retvalType != 'void': - outputParamsSerialization += '\t\t\tRS_SERIAL_PROCESS(retval);\n' - if hasOutput: - outputParamsSerialization += '\t\t}\n' - - captureVars = '' - - sessionEarlyClose = '' - if hasSingleCallback: - sessionEarlyClose = 'session->close();' - - sessionDelayedClose = '' - if hasMultiCallback: - sessionDelayedClose = """ - RsThread::async( [=]() - { - std::this_thread::sleep_for( - std::chrono::seconds(maxWait+120) ); - auto lService = weakService.lock(); - if(!lService || lService->is_down()) return; - lService->schedule( [=]() - { - auto session = weakSession.lock(); - if(session && session->is_open()) - session->close(); - } ); - } ); -""" - captureVars = 'this' - - callbackParamsSerialization = '' - - if hasSingleCallback or hasMultiCallback or (callbackParams.find('(') + 2 < callbackParams.find(')')): - cbs = '' - - callbackParams = callbackParams.split('(')[1] - callbackParams = callbackParams.split(')')[0] - - cbs += '\t\t\tRsGenericSerializer::SerializeContext ctx;\n' - - for cbPar in callbackParams.split(','): - isConst = cbPar.startswith('const ') - pSep = ' ' - isRef = '&' in cbPar - if isRef: pSep = '&' - sepIndex = cbPar.rfind(pSep) + 1 - cpt = cbPar[0:sepIndex][6:] - cpn = cbPar[sepIndex:] - - cbs += '\t\t\tRsTypeSerializer::serial_process(' - cbs += 'RsGenericSerializer::TO_JSON, ctx, ' - if isConst: - cbs += 'const_cast<' - cbs += cpt - cbs += '>(' - cbs += cpn - if isConst: cbs += ')' - cbs += ', "' - cbs += cpn - cbs += '" );\n' - - callbackParamsSerialization += cbs - - substitutionsMap = dict() - substitutionsMap['paramsDeclaration'] = paramsDeclaration - substitutionsMap['inputParamsDeserialization'] = inputParamsDeserialization - substitutionsMap['outputParamsSerialization'] = outputParamsSerialization - substitutionsMap['instanceName'] = instanceName - substitutionsMap['functionCall'] = functionCall - substitutionsMap['apiPath'] = apiPath - substitutionsMap['sessionEarlyClose'] = sessionEarlyClose - substitutionsMap['sessionDelayedClose'] = sessionDelayedClose - substitutionsMap['captureVars'] = captureVars - substitutionsMap['callbackName'] = callbackName - substitutionsMap['callbackParams'] = callbackParams - substitutionsMap['callbackParamsSerialization'] = callbackParamsSerialization - substitutionsMap['requiresAuth'] = 'true' if requiresAuth else 'false' - - # print(substitutionsMap) - - templFilePath = sourcePath - if hasMultiCallback or hasSingleCallback: - templFilePath += '/async-method-wrapper-template.cpp.tmpl' - else: - templFilePath += '/method-wrapper-template.cpp.tmpl' - - templFile = open(templFilePath, 'r') - wrapperDef = TemplateOwn(templFile.read()) - - tmp = wrapperDef.substitute(substitutionsMap) - wrappersDefFile.write(tmp) - - cppApiIncludesSet.add('#include "' + headerRelPath + '"\n') - - -if len(sys.argv) != 3: - print('Usage:', sys.argv[0], 'SOURCE_PATH OUTPUT_PATH Got:', sys.argv[:]) - sys.exit(-1) - -sourcePath = str(sys.argv[1]) -outputPath = str(sys.argv[2]) -doxPrefix = outputPath + '/xml/' - -try: - wrappersDefFile = open(outputPath + '/jsonapi-wrappers.inl', 'w') -except FileNotFoundError: - print('Can\'t open:', outputPath + '/jsonapi-wrappers.inl') - -try: - cppApiIncludesFile = open(outputPath + '/jsonapi-includes.inl', 'w'); -except FileNotFoundError: - print('Can\'t open:', outputPath + '/jsonapi-includes.inl') - -cppApiIncludesSet = set() - -filesIterator = None -try: - filesIterator = os.listdir(doxPrefix) -except FileNotFoundError: - print("Doxygen xml output dir not found: ", doxPrefix) - os.exit(-1) - -for file in filesIterator: - if file.endswith("8h.xml"): - processFile(os.path.join(doxPrefix, file)) - - -for incl in cppApiIncludesSet: - cppApiIncludesFile.write(incl) diff --git a/libretroshare/src/jsonapi/jsonapi.cpp b/libretroshare/src/jsonapi/jsonapi.cpp deleted file mode 100644 index 2f2ded30c..000000000 --- a/libretroshare/src/jsonapi/jsonapi.cpp +++ /dev/null @@ -1,834 +0,0 @@ -/* - * RetroShare JSON API - * - * Copyright (C) 2018-2020 Gioacchino Mazzurco - * Copyright (C) 2019-2020 AsociaciĆ³n Civil Altermundi - * - * This program is free software: you can redistribute it and/or modify it under - * the terms of the GNU Affero General Public License as published by the - * Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. - * See the GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see - * - * SPDX-FileCopyrightText: 2004-2020 RetroShare Team - * SPDX-License-Identifier: AGPL-3.0-only - */ - -#include -#include -#include -#include -#include -#include - - -#include "jsonapi.h" - -#include "util/rsjson.h" -#include "retroshare/rsfiles.h" -#include "util/radix64.h" -#include "retroshare/rsinit.h" -#include "util/rsnet.h" -#include "retroshare/rsiface.h" -#include "retroshare/rsinit.h" -#include "util/rsurl.h" -#include "util/rstime.h" -#include "retroshare/rsevents.h" -#include "retroshare/rsversion.h" - -// Generated at compile time -#include "jsonapi-includes.inl" - -/*extern*/ RsJsonApi* rsJsonApi = nullptr; - -const std::string RsJsonApi::DEFAULT_BINDING_ADDRESS = "127.0.0.1"; - -/*static*/ const std::multimap -JsonApiServer::corsHeaders = -{ - { "Access-Control-Allow-Origin", "*" }, - { "Access-Control-Allow-Methods", "GET, POST, OPTIONS"}, - { "Access-Control-Allow-Headers", "Authorization,DNT,User-Agent," - "X-Requested-With,If-Modified-Since," - "Cache-Control,Content-Type,Range" }, - { "Access-Control-Expose-Headers", "Content-Length,Content-Range" } -}; - -/*static*/ const std::multimap -JsonApiServer::corsOptionsHeaders = -{ - { "Access-Control-Allow-Origin", "*" }, - { "Access-Control-Allow-Methods", "GET, POST, OPTIONS"}, - { "Access-Control-Allow-Headers", "Authorization,DNT,User-Agent," - "X-Requested-With,If-Modified-Since," - "Cache-Control,Content-Type,Range" }, - { "Access-Control-Max-Age", "1728000" }, // 20 days - { "Content-Type", "text/plain; charset=utf-8" }, - { "Content-Length", "0" } -}; - -/* static */ const RsJsonApiErrorCategory RsJsonApiErrorCategory::instance; - -#define INITIALIZE_API_CALL_JSON_CONTEXT \ - RsGenericSerializer::SerializeContext cReq( \ - nullptr, 0, \ - RsSerializationFlags::YIELDING ); \ - RsJson& jReq(cReq.mJson); \ - if(session->get_request()->get_method() == "GET") \ - { \ - const std::string jrqp(session->get_request()->get_query_parameter("jsonData")); \ - jReq.Parse(jrqp.c_str(), jrqp.size()); \ - } \ - else \ - jReq.Parse(reinterpret_cast(body.data()), body.size()); \ -\ - RsGenericSerializer::SerializeContext cAns; \ - RsJson& jAns(cAns.mJson); \ -\ - /* if caller specified caller_data put it back in the answhere */ \ - const char kcd[] = "caller_data"; \ - if(jReq.HasMember(kcd)) \ - jAns.AddMember(kcd, jReq[kcd], jAns.GetAllocator()) - -#define DEFAULT_API_CALL_JSON_RETURN(RET_CODE) \ - std::stringstream ss; \ - ss << jAns; \ - std::string&& ans(ss.str()); \ - auto headers = corsHeaders; \ - headers.insert({ "Content-Type", "application/json" }); \ - headers.insert({ "Content-Length", std::to_string(ans.length()) }); \ - session->close(RET_CODE, ans, headers) - - -/*static*/ bool JsonApiServer::checkRsServicePtrReady( - const void* serviceInstance, const std::string& serviceName, - RsGenericSerializer::SerializeContext& ctx, - const std::shared_ptr session ) -{ - if(serviceInstance) return true; - - std::string jsonApiError = __PRETTY_FUNCTION__; - jsonApiError += "Service: "; - jsonApiError += serviceName; - jsonApiError += " not initialized!"; - - RsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON); - RS_SERIAL_PROCESS(jsonApiError); - - RsJson& jAns(ctx.mJson); - DEFAULT_API_CALL_JSON_RETURN(rb::CONFLICT); - return false; -} - -void JsonApiServer::unProtectedRestart() -{ - /* Extremely sensitive stuff! - * Make sure you read documentation in header before changing or use!! */ - - fullstop(); - RsThread::start("JSON API Server"); -} - -bool RsJsonApi::parseToken( - const std::string& clear_token, std::string& user,std::string& passwd ) -{ - auto colonIndex = std::string::npos; - const auto tkLen = clear_token.length(); - - for(uint32_t i=0; i < tkLen; ++i) - if(clear_token[i] == ':') { colonIndex = i; break; } - - user = clear_token.substr(0, colonIndex); - - if(colonIndex < tkLen) - passwd = clear_token.substr(colonIndex + 1); - - return true; -} - -JsonApiServer::JsonApiServer(): configMutex("JsonApiServer config"), - mService(nullptr), - mListeningPort(RsJsonApi::DEFAULT_PORT), - mBindingAddress(RsJsonApi::DEFAULT_BINDING_ADDRESS), - mRestartReqTS(0) -{ -#if defined(RS_THREAD_FORCE_STOP) && defined(RS_JSONAPI_DEBUG_SERVICE_STOP) - /* When called in bursts it seems that Restbed::Service::stop() doesn't - * always does the job, to debug those cases it has been useful to ask - * RsThread to force it to stop for us. */ - RsThread::setStopTimeout(10); -#endif - -#if !RS_VERSION_AT_LEAST(0,6,6) - registerHandler("/rsLoginHelper/createLocation", - [this](const std::shared_ptr session) - { - auto reqSize = session->get_request()->get_header("Content-Length", 0); - session->fetch( static_cast(reqSize), [this]( - const std::shared_ptr session, - const rb::Bytes& body ) - { - INITIALIZE_API_CALL_JSON_CONTEXT; - - RsLoginHelper::Location location; - std::string password; - std::string errorMessage; - bool makeHidden = false; - bool makeAutoTor = false; - std::string createToken; - - // deserialize input parameters from JSON - { - RsGenericSerializer::SerializeContext& ctx(cReq); - RsGenericSerializer::SerializeJob j(RsGenericSerializer::FROM_JSON); - RS_SERIAL_PROCESS(location); - RS_SERIAL_PROCESS(password); - RS_SERIAL_PROCESS(makeHidden); - RS_SERIAL_PROCESS(makeAutoTor); - RS_SERIAL_PROCESS(createToken); - } - - // call retroshare C++ API - bool retval = rsLoginHelper->createLocation( - location, password, errorMessage, makeHidden, - makeAutoTor ); - - std::string tokenUser, tokenPw; - if(retval && parseToken(createToken, tokenUser, tokenPw)) - authorizeUser(tokenUser,tokenPw); - - // serialize out parameters and return value to JSON - { - RsGenericSerializer::SerializeContext& ctx(cAns); - RsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON); - RS_SERIAL_PROCESS(location); - RS_SERIAL_PROCESS(errorMessage); - RS_SERIAL_PROCESS(retval); - } - - // return them to the API caller - DEFAULT_API_CALL_JSON_RETURN(rb::OK); - } ); - }, false); -#endif // !RS_VERSION_AT_LEAST(0,6,6) - - registerHandler("/rsLoginHelper/createLocationV2", - [this](const std::shared_ptr session) - { - auto reqSize = session->get_request()->get_header("Content-Length", 0); - session->fetch( static_cast(reqSize), [this]( - const std::shared_ptr session, - const rb::Bytes& body ) - { - INITIALIZE_API_CALL_JSON_CONTEXT; - - RsPeerId locationId; - RsPgpId pgpId; - std::string locationName; - std::string pgpName; - std::string password; - - // JSON API only - std::string apiUser; - std::string apiPass; - - // deserialize input parameters from JSON - { - RsGenericSerializer::SerializeContext& ctx(cReq); - RsGenericSerializer::SerializeJob j(RsGenericSerializer::FROM_JSON); - RS_SERIAL_PROCESS(locationId); - RS_SERIAL_PROCESS(pgpId); - RS_SERIAL_PROCESS(locationName); - RS_SERIAL_PROCESS(pgpName); - RS_SERIAL_PROCESS(password); - - // JSON API only - RS_SERIAL_PROCESS(apiUser); - RS_SERIAL_PROCESS(apiPass); - } - - std::error_condition retval; - - if(apiUser.empty()) - retval = RsJsonApiErrorNum::TOKEN_FORMAT_INVALID; - - if(!retval) - retval = badApiCredientalsFormat(apiUser, apiPass); - - if(!retval) // call retroshare C++ API - retval = rsLoginHelper->createLocationV2( - locationId, pgpId, locationName, pgpName, password ); - - if(!retval) retval = authorizeUser(apiUser, apiPass); - - // serialize out parameters and return value to JSON - { - RsGenericSerializer::SerializeContext& ctx(cAns); - RsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON); - RS_SERIAL_PROCESS(locationId); - RS_SERIAL_PROCESS(pgpId); - RS_SERIAL_PROCESS(retval); - } - - // return them to the API caller - DEFAULT_API_CALL_JSON_RETURN(rb::OK); - } ); - }, false); - - registerHandler("/rsControl/rsGlobalShutDown", - [](const std::shared_ptr session) - { - auto reqSize = session->get_request()->get_header("Content-Length", 0); - session->fetch( static_cast(reqSize), []( - const std::shared_ptr session, - const rb::Bytes& body ) - { - INITIALIZE_API_CALL_JSON_CONTEXT; - DEFAULT_API_CALL_JSON_RETURN(rb::OK); - - /* Wrap inside RsThread::async because this call - * RsThread::fullstop() also on JSON API server thread. - * Calling RsThread::fullstop() from it's own thread should never - * happen and if it happens an error message is printed - * accordingly by RsThread::fullstop() */ - RsThread::async([](){ rsControl->rsGlobalShutDown(); }); - } ); - }, true); - - registerHandler("/rsFiles/getFileData", - [](const std::shared_ptr session) - { - auto reqSize = session->get_request()->get_header("Content-Length", 0); - session->fetch( static_cast(reqSize), []( - const std::shared_ptr session, - const rb::Bytes& body ) - { - INITIALIZE_API_CALL_JSON_CONTEXT; - - if(!checkRsServicePtrReady(rsFiles, "rsFiles", cAns, session)) - return; - - RsFileHash hash; - uint64_t offset; - uint32_t requested_size; - bool retval = false; - std::string errorMessage; - std::string base64data; - - // deserialize input parameters from JSON - { - RsGenericSerializer::SerializeContext& ctx(cReq); - RsGenericSerializer::SerializeJob j(RsGenericSerializer::FROM_JSON); - RS_SERIAL_PROCESS(hash); - RS_SERIAL_PROCESS(offset); - RS_SERIAL_PROCESS(requested_size); - } - - if(requested_size > 10485760) - errorMessage = "requested_size is too big! Better less then 1M"; - else - { - std::vector buffer(requested_size); - - // call retroshare C++ API - retval = rsFiles->getFileData( - hash, offset, requested_size, buffer.data()); - - Radix64::encode(buffer.data(), requested_size, base64data); - } - - // serialize out parameters and return value to JSON - { - RsGenericSerializer::SerializeContext& ctx(cAns); - RsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON); - RS_SERIAL_PROCESS(retval); - RS_SERIAL_PROCESS(requested_size); - RS_SERIAL_PROCESS(base64data); - if(!errorMessage.empty()) RS_SERIAL_PROCESS(errorMessage); - } - - DEFAULT_API_CALL_JSON_RETURN(rb::OK); - } ); - }, true); - - registerHandler("/rsEvents/registerEventsHandler", - [this](const std::shared_ptr session) - { - const std::weak_ptr weakService(mService); - auto headers = corsHeaders; - headers.insert({ "Connection", "keep-alive" }); - headers.insert({ "Content-Type", "text/event-stream" }); - session->yield(rb::OK, headers); - - size_t reqSize = static_cast( - session->get_request()->get_header("Content-Length", 0) ); - session->fetch( reqSize, [weakService]( - const std::shared_ptr session, - const rb::Bytes& body ) - { - INITIALIZE_API_CALL_JSON_CONTEXT; - - if( !checkRsServicePtrReady( - rsEvents, "rsEvents", cAns, session ) ) - return; - - RsEventType eventType = RsEventType::__NONE; - - // deserialize input parameters from JSON - { - RsGenericSerializer::SerializeContext& ctx(cReq); - RsGenericSerializer::SerializeJob j(RsGenericSerializer::FROM_JSON); - RS_SERIAL_PROCESS(eventType); - } - - const std::weak_ptr weakSession(session); - RsEventsHandlerId_t hId = rsEvents->generateUniqueHandlerId(); - std::function)> multiCallback = - [weakSession, weakService, hId]( - std::shared_ptr event ) - { - auto lService = weakService.lock(); - if(!lService || lService->is_down()) - { - if(rsEvents) rsEvents->unregisterEventsHandler(hId); - return; - } - - lService->schedule( [weakSession, hId, event]() - { - auto session = weakSession.lock(); - if(!session || session->is_closed()) - { - if(rsEvents) rsEvents->unregisterEventsHandler(hId); - return; - } - - RsGenericSerializer::SerializeContext ctx; - RsTypeSerializer::serial_process( - RsGenericSerializer::TO_JSON, ctx, - *const_cast(event.get()), "event" ); - - std::stringstream message; - message << "data: " << compactJSON << ctx.mJson << "\n\n"; - - session->yield(message.str()); - } ); - }; - - std::error_condition retval = rsEvents->registerEventsHandler( - multiCallback, hId, eventType ); - - { - RsGenericSerializer::SerializeContext& ctx(cAns); - RsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON); - RS_SERIAL_PROCESS(retval); - } - - // return them to the API caller - std::stringstream message; - message << "data: " << compactJSON << cAns.mJson << "\n\n"; - session->yield(message.str()); - } ); - }, true); - - registerHandler("/rsJsonApi/restart", - [this](const std::shared_ptr session) - { - auto reqSize = session->get_request()->get_header("Content-Length", 0); - session->fetch( static_cast(reqSize), [this]( - const std::shared_ptr session, - const rb::Bytes& body ) - { - INITIALIZE_API_CALL_JSON_CONTEXT; - - std::error_condition retval; - - const auto now = time(nullptr); - if(mRestartReqTS.exchange(now) + RESTART_BURST_PROTECTION > now) - retval = RsJsonApiErrorNum::NOT_A_MACHINE_GUN; - - // serialize out parameters and return value to JSON - { - RsGenericSerializer::SerializeContext& ctx(cAns); - RsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON); - RS_SERIAL_PROCESS(retval); - } - - DEFAULT_API_CALL_JSON_RETURN(rb::OK); - - /* Wrap inside RsThread::async because this call fullstop() on - * JSON API server thread. - * Calling RsThread::fullstop() from it's own thread should never - * happen and if it happens an error message is printed - * accordingly by RsThread::fullstop() */ - if(!retval) RsThread::async([this](){ unProtectedRestart(); }); - } ); - }, true); - -// Generated at compile time -#include "jsonapi-wrappers.inl" -} - -void JsonApiServer::registerHandler( - const std::string& path, - const std::function)>& handler, - bool requiresAutentication ) -{ - std::shared_ptr resource(new rb::Resource); - resource->set_path(path); - resource->set_method_handler("GET", handler); - resource->set_method_handler("POST", handler); - resource->set_method_handler("OPTIONS", handleCorsOptions); - - if(requiresAutentication) - resource->set_authentication_handler( - [this, path]( - const std::shared_ptr session, - const std::function)>& callback ) - { - /* Declare outside the lambda to avoid returning a dangling - * reference */ - RsWarn tWarn; - const auto authFail = - [&](int status) -> std::ostream& - { - /* Capture session by reference as it is cheaper then copying - * shared_ptr by value which is not needed in this case */ - - session->close(status, corsOptionsHeaders); - return tWarn << "JsonApiServer authentication handler " - "blocked an attempt to call JSON API " - "authenticated method: " << path; - }; - - if(session->get_request()->get_method() == "OPTIONS") - { - callback(session); - return; - } - - if(!rsLoginHelper->isLoggedIn()) - { - authFail(rb::CONFLICT) << " before RetroShare login" - << std::endl; - return; - } - - std::istringstream authHeader; - authHeader.str(session->get_request()->get_header("Authorization")); - - std::string authToken; - std::getline(authHeader, authToken, ' '); - - if(authToken != "Basic") - { - authFail(rb::UNAUTHORIZED) - << " with wrong Authorization header: " - << authHeader.str() << std::endl; - return; - } - - std::getline(authHeader, authToken, ' '); - authToken = decodeToken(authToken); - - std::error_condition ec; - if(isAuthTokenValid(authToken, ec)) callback(session); - else - { - std::string tUser; - parseToken(authToken, tUser, RS_DEFAULT_STORAGE_PARAM(std::string)); - authFail(rb::UNAUTHORIZED) - << " user: " << tUser << ec << std::endl; - } - } ); - - mResources.push_back(resource); -} - -void JsonApiServer::setNewAccessRequestCallback( - const std::function& callback ) -{ mNewAccessRequestCallback = callback; } - -/*static*/ std::error_condition JsonApiServer::badApiCredientalsFormat( - const std::string& user, const std::string& passwd ) -{ - if(user.find(':') < std::string::npos) - return RsJsonApiErrorNum::API_USER_CONTAIN_COLON; - - if(user.empty()) - RsWarn() << __PRETTY_FUNCTION__ << " User is empty, are you sure " - << "this what you wanted?" << std::endl; - - if(passwd.empty()) - RsWarn() << __PRETTY_FUNCTION__ << " Password is empty, are you sure " - << "this what you wanted?" << std::endl; - - return std::error_condition(); -} - -std::error_condition JsonApiServer::requestNewTokenAutorization( - const std::string& user, const std::string& passwd ) -{ - auto ec = badApiCredientalsFormat(user, passwd); - if(ec) return ec; - - if(!rsLoginHelper->isLoggedIn()) - return RsJsonApiErrorNum::CANNOT_EXECUTE_BEFORE_RS_LOGIN; - - if(mNewAccessRequestCallback(user, passwd)) - return authorizeUser(user, passwd); - - return RsJsonApiErrorNum::AUTHORIZATION_REQUEST_DENIED; -} - -bool JsonApiServer::isAuthTokenValid( - const std::string& token, std::error_condition& error ) -{ - RS_STACK_MUTEX(configMutex); - - const auto failure = [&error](RsJsonApiErrorNum e) -> bool - { - error = e; - return false; - }; - - const auto success = [&error]() - { - error.clear(); - return true; - }; - - std::string user,passwd; - if(!parseToken(token, user, passwd)) - return failure(RsJsonApiErrorNum::TOKEN_FORMAT_INVALID); - - auto it = mAuthTokenStorage.mAuthorizedTokens.find(user); - if(it == mAuthTokenStorage.mAuthorizedTokens.end()) - return failure(RsJsonApiErrorNum::UNKNOWN_API_USER); - - // attempt avoiding +else CRYPTO_memcmp+ being optimized away - int noOptimiz = 1; - - /* Do not use mAuthTokenStorage.mAuthorizedTokens.count(token), because - * std::string comparison is usually not constant time on content to be - * faster, so an attacker may use timings to guess authorized tokens */ - - if( passwd.size() == it->second.size() && - ( noOptimiz = CRYPTO_memcmp( - passwd.data(), it->second.data(), it->second.size() ) ) == 0 ) - return success(); - // Make token size guessing harder - else noOptimiz = CRYPTO_memcmp(passwd.data(), passwd.data(), passwd.size()); - - /* At this point we are sure password is wrong, and one could think to - * plainly `return false` still this ugly and apparently unuseful extra - * calculation is here to avoid `else CRYPTO_memcmp` being optimized away, - * so a pontential attacker cannot guess password size based on timing */ - return static_cast(noOptimiz) + 1 == 0 ? - success() : failure(RsJsonApiErrorNum::WRONG_API_PASSWORD); -} - -std::map JsonApiServer::getAuthorizedTokens() -{ - RS_STACK_MUTEX(configMutex); - return mAuthTokenStorage.mAuthorizedTokens; -} - -bool JsonApiServer::revokeAuthToken(const std::string& token) -{ - RS_STACK_MUTEX(configMutex); - if(mAuthTokenStorage.mAuthorizedTokens.erase(token)) - { - IndicateConfigChanged(); - return true; - } - return false; -} - -void JsonApiServer::connectToConfigManager(p3ConfigMgr& cfgmgr) -{ - cfgmgr.addConfiguration("jsonapi.cfg",this); - - RsFileHash hash; - loadConfiguration(hash); -} - -std::error_condition JsonApiServer::authorizeUser( - const std::string& user, const std::string& passwd ) -{ - auto ec = badApiCredientalsFormat(user, passwd); - if(ec) return ec; - - RS_STACK_MUTEX(configMutex); - - std::string& p(mAuthTokenStorage.mAuthorizedTokens[user]); - if(p != passwd) - { - p = passwd; - IndicateConfigChanged(); - } - return ec; -} - -/*static*/ std::string JsonApiServer::decodeToken(const std::string& radix64_token) -{ - std::vector decodedVect(Radix64::decode(radix64_token)); - std::string decodedToken( - reinterpret_cast(&decodedVect[0]), - decodedVect.size() ); - return decodedToken; -} - -RsSerialiser* JsonApiServer::setupSerialiser() -{ - RsSerialiser* rss = new RsSerialiser; - rss->addSerialType(new JsonApiConfigSerializer); - return rss; -} - -bool JsonApiServer::saveList(bool& cleanup, std::list& saveItems) -{ - cleanup = false; - configMutex.lock(); - saveItems.push_back(&mAuthTokenStorage); - return true; -} - -bool JsonApiServer::loadList(std::list& loadList) -{ - for(RsItem* it : loadList) - switch (static_cast(it->PacketSubType())) - { - case JsonApiItemsType::AuthTokenItem: - mAuthTokenStorage = *static_cast(it); - delete it; - break; - default: - delete it; - break; - } - return true; -} - -void JsonApiServer::saveDone() { configMutex.unlock(); } - -void JsonApiServer::handleCorsOptions( - const std::shared_ptr session ) -{ session->close(rb::NO_CONTENT, corsOptionsHeaders); } - -void JsonApiServer::registerResourceProvider(const JsonApiResourceProvider& rp) -{ mResourceProviders.insert(rp); } -void JsonApiServer::unregisterResourceProvider(const JsonApiResourceProvider& rp) -{ mResourceProviders.erase(rp); } -bool JsonApiServer::hasResourceProvider(const JsonApiResourceProvider& rp) -{ return mResourceProviders.find(rp) != mResourceProviders.end(); } - -std::vector > JsonApiServer::getResources() const -{ - auto tab = mResources; - - for(auto& rp: mResourceProviders) - for(auto r: rp.get().getResources()) tab.push_back(r); - - return tab; -} - -std::error_condition JsonApiServer::restart() -{ - const auto now = time(nullptr); - if(mRestartReqTS.exchange(now) + RESTART_BURST_PROTECTION > now) - return RsJsonApiErrorNum::NOT_A_MACHINE_GUN; - - unProtectedRestart(); - return std::error_condition(); -} - -void JsonApiServer::onStopRequested() -{ - auto tService = std::atomic_exchange( - &mService, std::shared_ptr(nullptr) ); - if(tService) tService->stop(); -} - -uint16_t JsonApiServer::listeningPort() const { return mListeningPort; } -void JsonApiServer::setListeningPort(uint16_t p) { mListeningPort = p; } -void JsonApiServer::setBindingAddress(const std::string& bindAddress) -{ mBindingAddress = bindAddress; } -std::string JsonApiServer::getBindingAddress() const { return mBindingAddress; } - -void JsonApiServer::run() -{ - auto settings = std::make_shared(); - settings->set_port(mListeningPort); - settings->set_bind_address(mBindingAddress); - settings->set_default_header("Connection", "close"); - - auto tService = std::make_shared(); - - for(auto& r: getResources()) tService->publish(r); - - try - { - RsUrl apiUrl; apiUrl.setScheme("http").setHost(mBindingAddress) - .setPort(mListeningPort); - RsInfo() << __PRETTY_FUNCTION__ << " JSON API server listening on " - << apiUrl.toString() << std::endl; - - /* re-allocating mService is important because it deletes the existing - * service and therefore leaves the listening port open */ - auto tExpected = std::shared_ptr(nullptr); - if(atomic_compare_exchange_strong(&mService, &tExpected, tService)) - tService->start(settings); - else - { - RsErr() << __PRETTY_FUNCTION__ << " mService was expected to be " - << " null, instead we got: " << tExpected - << " something wrong happened JsonApiServer won't start" - << std::endl; - print_stacktrace(); - } - } - catch(std::exception& e) - { - /* TODO: find a way to report back programmatically if failed listening - * port */ - RS_ERR("Failure starting JSON API server: ", e.what()); - print_stacktrace(); - return; - } - - RsDbg() << __PRETTY_FUNCTION__ << " finished!" << std::endl; -} - -/*static*/ void RsJsonApi::version( - uint32_t& major, uint32_t& minor, uint32_t& mini, std::string& extra, - std::string& human ) -{ - major = RS_MAJOR_VERSION; - minor = RS_MINOR_VERSION; - mini = RS_MINI_VERSION; - extra = RS_EXTRA_VERSION; - human = RS_HUMAN_READABLE_VERSION; -} - -std::error_condition RsJsonApiErrorCategory::default_error_condition(int ev) const noexcept -{ - switch(static_cast(ev)) - { - case RsJsonApiErrorNum::TOKEN_FORMAT_INVALID: // fallthrough - case RsJsonApiErrorNum::UNKNOWN_API_USER: // fallthrough - case RsJsonApiErrorNum::WRONG_API_PASSWORD: // fallthrough - case RsJsonApiErrorNum::AUTHORIZATION_REQUEST_DENIED: - return std::errc::permission_denied; - case RsJsonApiErrorNum::API_USER_CONTAIN_COLON: - return std::errc::invalid_argument; - default: - return std::error_condition(ev, *this); - } -} diff --git a/libretroshare/src/jsonapi/jsonapi.h b/libretroshare/src/jsonapi/jsonapi.h deleted file mode 100644 index 317d4066f..000000000 --- a/libretroshare/src/jsonapi/jsonapi.h +++ /dev/null @@ -1,234 +0,0 @@ -/* - * RetroShare JSON API - * - * Copyright (C) 2018-2020 Gioacchino Mazzurco - * Copyright (C) 2019-2020 AsociaciĆ³n Civil Altermundi - * - * This program is free software: you can redistribute it and/or modify it under - * the terms of the GNU Affero General Public License as published by the - * Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. - * See the GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see - * - * SPDX-FileCopyrightText: 2004-2019 RetroShare Team - * SPDX-License-Identifier: AGPL-3.0-only - */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "util/rsthreads.h" -#include "pqi/p3cfgmgr.h" -#include "rsitems/rsitem.h" -#include "jsonapi/jsonapiitems.h" -#include "retroshare/rsjsonapi.h" -#include "util/rsthreads.h" - -namespace rb = restbed; - -/** Interface to provide addotional resources to JsonApiServer */ -class JsonApiResourceProvider -{ -public: - virtual ~JsonApiResourceProvider() = default; - - virtual std::vector> getResources() const = 0; - - inline bool operator< (const JsonApiResourceProvider& rp) const - { return this < &rp; } -}; - -/** - * Uses p3Config to securely store persistent JSON API authorization tokens - */ -class JsonApiServer : public p3Config, public RsThread, public RsJsonApi -{ -public: - JsonApiServer(); - ~JsonApiServer() override = default; - - std::vector> getResources() const; - - /// @see RsJsonApi - void fullstop() override { RsThread::fullstop(); } - - /// @see RsJsonApi - std::error_condition restart() override; - - /// @see RsJsonApi - void askForStop() override { RsThread::askForStop(); } - - /// @see RsJsonApi - inline bool isRunning() override { return RsThread::isRunning(); } - - /// @see RsJsonApi - void setListeningPort(uint16_t port) override; - - /// @see RsJsonApi - void setBindingAddress(const std::string& bindAddress) override; - - /// @see RsJsonApi - std::string getBindingAddress() const override; - - /// @see RsJsonApi - uint16_t listeningPort() const override; - - /// @see RsJsonApi - void connectToConfigManager(p3ConfigMgr& cfgmgr) override; - - /// @see RsJsonApi - virtual std::error_condition authorizeUser( - const std::string& user, const std::string& passwd ) override; - - /// @see RsJsonApi - std::map getAuthorizedTokens() override; - - /// @see RsJsonApi - bool revokeAuthToken(const std::string& user) override; - - /// @see RsJsonApi - bool isAuthTokenValid( - const std::string& token, - std::error_condition& error = RS_DEFAULT_STORAGE_PARAM(std::error_condition) - ) override; - - /// @see RsJsonAPI - std::error_condition requestNewTokenAutorization( - const std::string& user, const std::string& password ) override; - - /// @see RsJsonApi - void registerResourceProvider(const JsonApiResourceProvider&) override; - - /// @see RsJsonApi - void unregisterResourceProvider(const JsonApiResourceProvider&) override; - - /// @see RsJsonApi - bool hasResourceProvider(const JsonApiResourceProvider&) override; - - /** - * @brief Get decoded version of the given encoded token - * @param[in] radix64_token encoded - * @return token decoded - */ - static std::string decodeToken(const std::string& radix64_token); - - /** - * Register an unique handler for a resource path - * @param[in] path Path into which publish the API call - * @param[in] handler function which will be called to handle the requested - * @param[in] requiresAutentication specify if the API call must be - * autenticated or not. - */ - void registerHandler( - const std::string& path, - const std::function)>& handler, - bool requiresAutentication = true ); - - /** - * @brief Set new access request callback - * @param callback function to call when a new JSON API access is requested - */ - void setNewAccessRequestCallback( - const std::function& - callback ); - -protected: - /// @see RsThread - void onStopRequested() override; - - static std::error_condition badApiCredientalsFormat( - const std::string& user, const std::string& passwd ); - -private: - /// @see RsThread - void run() override; - - /// @see p3Config::setupSerialiser - RsSerialiser* setupSerialiser() override; - - /// @see p3Config::saveList - bool saveList(bool &cleanup, std::list& saveItems) override; - - /// @see p3Config::loadList - bool loadList(std::list& loadList) override; - - /// @see p3Config::saveDone - void saveDone() override; - - /// Called when new JSON API auth token is requested to be authorized - std::function - mNewAccessRequestCallback; - - /// Encrypted persistent storage for authorized JSON API tokens - JsonApiServerAuthTokenStorage mAuthTokenStorage; - RsMutex configMutex; - - static const std::multimap corsHeaders; - static const std::multimap corsOptionsHeaders; - static void handleCorsOptions(const std::shared_ptr session); - - static bool checkRsServicePtrReady( - const void* serviceInstance, const std::string& serviceName, - RsGenericSerializer::SerializeContext& ctx, - const std::shared_ptr session ); - - static inline bool checkRsServicePtrReady( - const std::shared_ptr serviceInstance, - const std::string& serviceName, - RsGenericSerializer::SerializeContext& ctx, - const std::shared_ptr session ) - { - return checkRsServicePtrReady( - serviceInstance.get(), serviceName, ctx, session ); - } - - std::vector> mResources; - std::set< - std::reference_wrapper, - std::less > mResourceProviders; - - /** - * This pointer should be accessed via std::atomic_* operations, up until - * now only very critical operations like reallocation, are done that way, - * but this is not still 100% thread safe, but seems to handle all of the - * test cases (no crash, no deadlock), once we switch to C++20 we shoud - * change this into std::atomic> which - * will automatically handle atomic access properly all the times - */ - std::shared_ptr mService; - - uint16_t mListeningPort; - std::string mBindingAddress; - - /// @see unProtectedRestart() - std::atomic mRestartReqTS; - - /// @see unProtectedRestart() - constexpr static rstime_t RESTART_BURST_PROTECTION = 7; - - /** It is very important to protect this method from being called in bursts, - * because Restbed::Service::stop() together with - * Restbed::Service::start(...), which are called internally, silently fails - * if combined in bursts, probably because they have to deal with - * listening/releasing TCP port. - * @see JsonApiServer::restart() and @see JsonApiServer::JsonApiServer() - * implementation to understand how correctly use this. - */ - void unProtectedRestart(); -}; - diff --git a/libretroshare/src/jsonapi/jsonapiitems.h b/libretroshare/src/jsonapi/jsonapiitems.h deleted file mode 100644 index eba871e98..000000000 --- a/libretroshare/src/jsonapi/jsonapiitems.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * RetroShare JSON API - * - * Copyright (C) 2018-2019 Gioacchino Mazzurco - * - * This program is free software: you can redistribute it and/or modify it under - * the terms of the GNU Affero General Public License as published by the - * Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. - * See the GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see - * - * SPDX-FileCopyrightText: 2004-2019 RetroShare Team - * SPDX-License-Identifier: AGPL-3.0-only - */ - -#pragma once - -#include -#include "util/rstime.h" -#include -#include - -#include "rsitems/rsitem.h" -#include "rsitems/rsserviceids.h" -#include "serialiser/rsserializer.h" -#include "serialiser/rsserializable.h" - -enum class JsonApiItemsType : uint8_t { AuthTokenItem_deprecated = 0, AuthTokenItem = 1 }; - -struct JsonApiServerAuthTokenStorage : RsItem -{ - JsonApiServerAuthTokenStorage() : - RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_JSONAPI, - static_cast(JsonApiItemsType::AuthTokenItem) ) {} - - /// @see RsSerializable - virtual void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) - { - RS_SERIAL_PROCESS(mAuthorizedTokens); - } - - /// @see RsItem - virtual void clear() { mAuthorizedTokens.clear(); } - - std::map mAuthorizedTokens; -}; - - -struct JsonApiConfigSerializer : RsServiceSerializer -{ - JsonApiConfigSerializer() : RsServiceSerializer(RS_SERVICE_TYPE_JSONAPI) {} - virtual ~JsonApiConfigSerializer() {} - - RsItem* create_item(uint16_t service_id, uint8_t item_sub_id) const - { - if(service_id != RS_SERVICE_TYPE_JSONAPI) return nullptr; - - switch(static_cast(item_sub_id)) - { - case JsonApiItemsType::AuthTokenItem: return new JsonApiServerAuthTokenStorage(); - default: return nullptr; - } - } -}; - - diff --git a/libretroshare/src/jsonapi/method-wrapper-template.cpp.tmpl b/libretroshare/src/jsonapi/method-wrapper-template.cpp.tmpl deleted file mode 100644 index a3927fba9..000000000 --- a/libretroshare/src/jsonapi/method-wrapper-template.cpp.tmpl +++ /dev/null @@ -1,50 +0,0 @@ -/******************************************************************************* - * RetroShare JSON API * - * * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Affero General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Affero General Public License for more details. * - * * - * You should have received a copy of the GNU Affero General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -registerHandler( "$%apiPath%$", - [](const std::shared_ptr session) -{ - size_t reqSize = session->get_request()->get_header("Content-Length", 0); - session->fetch( reqSize, []( - const std::shared_ptr session, - const rb::Bytes& body ) - { - INITIALIZE_API_CALL_JSON_CONTEXT; - - if( !checkRsServicePtrReady( - $%instanceName%$, "$%instanceName%$", cAns, session ) ) - return; - -$%paramsDeclaration%$ - - // deserialize input parameters from JSON -$%inputParamsDeserialization%$ - - // call retroshare C++ API -$%functionCall%$ - - // serialize out parameters and return value to JSON -$%outputParamsSerialization%$ - - // return them to the API caller - DEFAULT_API_CALL_JSON_RETURN(rb::OK); - } ); -}, $%requiresAuth%$ ); - diff --git a/libretroshare/src/jsonapi/p3webui.cc b/libretroshare/src/jsonapi/p3webui.cc deleted file mode 100644 index acb907c5d..000000000 --- a/libretroshare/src/jsonapi/p3webui.cc +++ /dev/null @@ -1,196 +0,0 @@ -/* - * RetroShare Web User Interface - * - * Copyright (C) 2019 Cyril Soler - * - * This program is free software: you can redistribute it and/or modify it under - * the terms of the GNU Affero General Public License as published by the - * Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. - * See the GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see - * - * SPDX-FileCopyrightText: 2004-2019 RetroShare Team - * SPDX-License-Identifier: AGPL-3.0-only - */ - -#include "p3webui.h" - -#include -#include -#include -#include -#include -#include - -#include "util/rsthreads.h" -#include "util/rsdebug.h" -#include "retroshare/rswebui.h" -#include "rsserver/rsaccounts.h" -#include "retroshare/rsjsonapi.h" - -#define DEBUG_RS_WEBUI 1 - -/*extern*/ RsWebUi* rsWebUi = new p3WebUI; - -enum MimeTypeIndex -{ - TEXT_HTML, - TEXT_CSS, - TEXT_SVG, - TEXT_TTF, - TEXT_WOFF, - APPLICATION_OCTET_STREAM, -}; - -static const constexpr char* const mime_types[] = -{ - "text/html", - "text/css", - "image/svg+xml", - "font/ttf", - "font/woff", - "application/octet-stream", -}; - -const std::string RsWebUi::DEFAULT_BASE_DIRECTORY = - RsAccountsDetail::PathDataDirectory(false) + "/webui/"; - -static std::string _base_directory = RsWebUi::DEFAULT_BASE_DIRECTORY; - -template class handler -{ -public: - static void get_handler( const std::shared_ptr< restbed::Session > session ) - { - const auto request = session->get_request( ); - const std::string filename = request->get_path_parameter( "filename" ); - std::string directory = request->get_path_parameter( "dir" ); - - if(!directory.empty()) directory += "/"; - - std::string resource_filename = _base_directory + "/" + directory + filename; - RsDbg() << "Reading file: \"" << resource_filename << "\"" << std::endl; - std::ifstream stream( resource_filename, std::ifstream::binary); - - if(stream.is_open()) - { - const std::vector body = std::vector( - std::istreambuf_iterator(stream), - std::istreambuf_iterator() ); - - RsDbg() << __PRETTY_FUNCTION__ - << " body length=" << body.size() << std::endl; - - const std::multimap headers - { - { "Content-Type", mime_types[MIME_TYPE_INDEX] }, - { "Content-Length", std::to_string(body.size()) } - }; - - session->close(restbed::OK, body, headers); - } - else - { - RsErr() << __PRETTY_FUNCTION__ << "Could not open file: " - << resource_filename << std::endl; - session->close(restbed::NOT_FOUND); - } - } -}; - -std::vector< std::shared_ptr > p3WebUI::getResources() const -{ - static std::vector< std::shared_ptr > rtab; - - if(rtab.empty()) - { - auto resource1 = std::make_shared< restbed::Resource >(); - resource1->set_paths( { - "/{filename: index.html}", - "/{filename: app.js}", - } - ); - resource1->set_method_handler( "GET", handler::get_handler ); - - auto resource2 = std::make_shared< restbed::Resource >(); - resource2->set_paths( { - "/{dir: css}/{filename: fontawesome.css}", - "/{dir: css}/{filename: solid.css}", - "/{filename: app.css}", - } ); - resource2->set_method_handler( "GET", handler::get_handler ); - - auto resource3 = std::make_shared< restbed::Resource >(); - resource3->set_paths( { - "/{dir: data}/{filename: retroshare.svg}", - "/{dir: webfonts}/{filename: fa-solid-900.svg}", - } ); - resource3->set_method_handler( "GET", handler::get_handler ); - - auto resource4 = std::make_shared< restbed::Resource >(); - resource4->set_paths( { - "/{dir: webfonts}/{filename: fa-solid-900.ttf}", - } ); - resource4->set_method_handler( "GET", handler::get_handler ); - - auto resource5 = std::make_shared< restbed::Resource >(); - resource5->set_paths( { - "/{dir: webfonts}/{filename: fa-solid-900.woff}", - "/{dir: webfonts}/{filename: fa-solid-900.woff2}", - } ); - resource5->set_method_handler( "GET", handler::get_handler ); - - auto resource6 = std::make_shared< restbed::Resource >(); - resource6->set_paths( { - "/{dir: webfonts}/{filename: fa-solid-900.eot}", - } ); - resource6->set_method_handler( "GET", handler::get_handler ); - - rtab.push_back(resource1); - rtab.push_back(resource2); - rtab.push_back(resource3); - rtab.push_back(resource4); - rtab.push_back(resource5); - rtab.push_back(resource6); - } - - return rtab; -} - - -void p3WebUI::setHtmlFilesDirectory(const std::string& html_dir) -{ - _base_directory = html_dir; -} - -bool p3WebUI::isRunning() const -{ return rsJsonApi->isRunning() && rsJsonApi->hasResourceProvider(*this); } - -void p3WebUI::setUserPassword(const std::string& passwd) -{ - RsDbg() << __PRETTY_FUNCTION__ << " Updating webui token with new passwd \"" - << passwd << "\"" << std::endl; - - if(!rsJsonApi->authorizeUser("webui",passwd)) - std::cerr << "(EE) Cannot register webui token. Some error occurred when calling authorizeUser()" << std::endl; -} - -bool p3WebUI::restart() -{ - rsJsonApi->registerResourceProvider(*this); - rsJsonApi->restart(); - return true; -} - -bool p3WebUI::stop() -{ - rsJsonApi->unregisterResourceProvider(*this); - rsJsonApi->restart(); - return true; -} diff --git a/libretroshare/src/jsonapi/p3webui.h b/libretroshare/src/jsonapi/p3webui.h deleted file mode 100644 index b67927ab7..000000000 --- a/libretroshare/src/jsonapi/p3webui.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * RetroShare Web User Interface - * - * Copyright (C) 2019 Cyril Soler - * - * This program is free software: you can redistribute it and/or modify it under - * the terms of the GNU Affero General Public License as published by the - * Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. - * See the GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see - * - * SPDX-FileCopyrightText: 2004-2019 RetroShare Team - * SPDX-License-Identifier: AGPL-3.0-only - */ - -#pragma once - -#include -#include -#include - -#include "retroshare/rswebui.h" -#include "jsonapi/jsonapi.h" - -class p3WebUI: public RsWebUi, public JsonApiResourceProvider -{ -public: - ~p3WebUI() override = default; - - // implements RsWebUI - - virtual void setHtmlFilesDirectory(const std::string& html_dir) override; - virtual void setUserPassword(const std::string& passwd) override; - - virtual bool restart() override ; - virtual bool stop() override ; - bool isRunning() const override; - // implements JsonApiResourceProvider - - virtual std::vector > getResources() const override; -}; diff --git a/libretroshare/src/libretroshare.pro b/libretroshare/src/libretroshare.pro deleted file mode 100644 index 4d84b6fc7..000000000 --- a/libretroshare/src/libretroshare.pro +++ /dev/null @@ -1,1175 +0,0 @@ -# SPDX-FileCopyrightText: (C) 2004-2021 Retroshare Team -# SPDX-License-Identifier: CC0-1.0 - -!include("../../retroshare.pri"): error("Could not include file ../../retroshare.pri") - -TEMPLATE = lib -CONFIG -= qt -libretroshare_shared { - CONFIG += shared -} else { - CONFIG += staticlib -} - -TARGET = retroshare -TARGET_PRL = libretroshare -DESTDIR = lib - -!include("use_libretroshare.pri"):error("Including") - -QMAKE_CXXFLAGS += -fPIC - -## Uncomment to enable Unfinished Services. -#CONFIG += wikipoos -#CONFIG += gxsthewire -#CONFIG += gxsphotoshare - -debug { -# DEFINES *= DEBUG -# DEFINES *= OPENDHT_DEBUG DHT_DEBUG CONN_DEBUG DEBUG_UDP_SORTER P3DISC_DEBUG DEBUG_UDP_LAYER FT_DEBUG EXTADDRSEARCH_DEBUG -# DEFINES *= CONTROL_DEBUG FT_DEBUG DEBUG_FTCHUNK P3TURTLE_DEBUG -# DEFINES *= P3TURTLE_DEBUG -# DEFINES *= NET_DEBUG -# DEFINES *= DISTRIB_DEBUG -# DEFINES *= P3TURTLE_DEBUG FT_DEBUG DEBUG_FTCHUNK MPLEX_DEBUG -# DEFINES *= STATUS_DEBUG SERV_DEBUG RSSERIAL_DEBUG #CONN_DEBUG - - QMAKE_CXXFLAGS -= -O2 -fomit-frame-pointer - QMAKE_CXXFLAGS *= -g -fno-omit-frame-pointer -} - -CONFIG += file_lists - -file_lists { - HEADERS *= file_sharing/p3filelists.h \ - file_sharing/hash_cache.h \ - file_sharing/filelist_io.h \ - file_sharing/directory_storage.h \ - file_sharing/directory_updater.h \ - file_sharing/rsfilelistitems.h \ - file_sharing/dir_hierarchy.h \ - file_sharing/file_sharing_defaults.h - - SOURCES *= file_sharing/p3filelists.cc \ - file_sharing/hash_cache.cc \ - file_sharing/filelist_io.cc \ - file_sharing/directory_storage.cc \ - file_sharing/directory_updater.cc \ - file_sharing/dir_hierarchy.cc \ - file_sharing/file_tree.cc \ - file_sharing/rsfilelistitems.cc -} - - -dsdv { -DEFINES *= SERVICES_DSDV -HEADERS += unused/p3dsdv.h \ - unused/rstlvdsdv.h \ - unused/rsdsdvitems.h \ - unused/rsdsdv.h - -SOURCES *= unused/rstlvdsdv.cc \ - unused/rsdsdvitems.cc \ - unused/p3dsdv.cc -} -bitdht { - -HEADERS += dht/p3bitdht.h \ - dht/connectstatebox.h - -SOURCES += dht/p3bitdht.cc \ - dht/p3bitdht_interface.cc \ - dht/p3bitdht_peers.cc \ - dht/p3bitdht_peernet.cc \ - dht/p3bitdht_relay.cc \ - dht/connectstatebox.cc - -HEADERS += tcponudp/udppeer.h \ - tcponudp/bio_tou.h \ - tcponudp/tcppacket.h \ - tcponudp/tcpstream.h \ - tcponudp/tou.h \ - tcponudp/udprelay.h \ - tcponudp/rsudpstack.h \ - pqi/pqissludp.h \ - -SOURCES += tcponudp/udppeer.cc \ - tcponudp/tcppacket.cc \ - tcponudp/tcpstream.cc \ - tcponudp/tou.cc \ - tcponudp/bss_tou.cc \ - tcponudp/udprelay.cc \ - pqi/pqissludp.cc \ - - useDhtStunner { - HEADERS += dht/stunaddrassist.h \ - tcponudp/udpstunner.h - - SOURCES += tcponudp/udpstunner.cc - - DEFINES += RS_USE_DHT_STUNNER - } - - DEFINES *= RS_USE_BITDHT - - BITDHT_DIR = ../../libbitdht/src - DEPENDPATH += . $${BITDHT_DIR} - INCLUDEPATH += . $${BITDHT_DIR} - PRE_TARGETDEPS *= $${BITDHT_DIR}/lib/libbitdht.a - LIBS *= $${BITDHT_DIR}/lib/libbitdht.a -} - - - - -PUBLIC_HEADERS = retroshare/rsdisc.h \ - retroshare/rsgossipdiscovery \ - retroshare/rsevents.h \ - retroshare/rsexpr.h \ - retroshare/rsfiles.h \ - retroshare/rshistory.h \ - retroshare/rsids.h \ - retroshare/rsiface.h \ - retroshare/rsinit.h \ - retroshare/rsplugin.h \ - retroshare/rsloginhandler.h \ - retroshare/rsmsgs.h \ - retroshare/rsnotify.h \ - retroshare/rspeers.h \ - retroshare/rsstatus.h \ - retroshare/rsturtle.h \ - retroshare/rsbanlist.h \ - retroshare/rstypes.h \ - retroshare/rsdht.h \ - retroshare/rsrtt.h \ - retroshare/rsconfig.h \ - retroshare/rsversion.h \ - retroshare/rsservicecontrol.h \ - retroshare/rsgxsdistsync.h - -rs_webui { - PUBLIC_HEADERS += retroshare/rswebui.h - SOURCES += jsonapi/p3webui.cc - HEADERS += jsonapi/p3webui.h -} - -HEADERS += plugins/pluginmanager.h \ - plugins/dlfcn_win32.h \ - rsitems/rspluginitems.h \ - util/i2pcommon.h \ - util/rsinitedptr.h - -HEADERS += $$PUBLIC_HEADERS - -################################# Linux ########################################## -linux-* { - CONFIG += link_pkgconfig - - QMAKE_CXXFLAGS *= -D_FILE_OFFSET_BITS=64 - QMAKE_CC = $${QMAKE_CXX} - - no_sqlcipher { - PKGCONFIG *= sqlite3 - } else { - SQLCIPHER_OK = $$system(pkg-config --exists sqlcipher && echo yes) - isEmpty(SQLCIPHER_OK) { - # We need a explicit path here, to force using the home version of sqlite3 that really encrypts the database. - exists(../../../lib/sqlcipher/.libs/libsqlcipher.a) { - LIBS += ../../../lib/sqlcipher/.libs/libsqlcipher.a - DEPENDPATH += ../../../lib/ - INCLUDEPATH += ../../../lib/ - } else { - error("libsqlcipher is not installed and libsqlcipher.a not found. SQLCIPHER is necessary for encrypted database, to build with unencrypted database, run: qmake CONFIG+=no_sqlcipher") - } - } else { - # Workaround for broken sqlcipher packages, e.g. Ubuntu 14.04 - # https://bugs.launchpad.net/ubuntu/+source/sqlcipher/+bug/1493928 - # PKGCONFIG *= sqlcipher - LIBS *= -lsqlcipher - } - } - - contains(RS_UPNP_LIB, threadutil) { # ensure we don't break libpnp-1.8.x - # Check if the systems libupnp-1.6.x has been Debian-patched - !system(grep -E 'char[[:space:]]+PublisherUrl' /usr/include/upnp/upnp.h >/dev/null 2>&1) { - # Patched libupnp or new unreleased version - DEFINES *= PATCHED_LIBUPNP - } - } - - PKGCONFIG *= libssl - equals(RS_UPNP_LIB, "upnp ixml threadutil"):PKGCONFIG *= libupnp - PKGCONFIG *= libcrypto zlib - no_sqlcipher:PKGCONFIG *= sqlite3 - LIBS *= -ldl - - DEFINES *= PLUGIN_DIR=\"\\\"$${PLUGIN_DIR}\\\"\" - DEFINES *= RS_DATA_DIR=\"\\\"$${RS_DATA_DIR}\\\"\" -} - -linux-g++ { - OBJECTS_DIR = temp/linux-g++/obj -} - -linux-g++-64 { - OBJECTS_DIR = temp/linux-g++-64/obj -} - -version_detail_bash_script { - warning("Version detail script is deprecated.") - warning("Remove references to version_detail_bash_script from all of your build scripts!") -} - -#################### Cross compilation for windows under Linux #################### - -win32-x-g++ { - OBJECTS_DIR = temp/win32xgcc/obj - DEFINES *= WINDOWS_SYS WIN32 WIN_CROSS_UBUNTU - QMAKE_CXXFLAGS *= -Wmissing-include-dirs - QMAKE_CC = i586-mingw32msvc-g++ - QMAKE_LIB = i586-mingw32msvc-ar - QMAKE_AR = i586-mingw32msvc-ar - DEFINES *= STATICLIB WIN32 - - SSL_DIR=../../../../openssl - UPNPC_DIR = ../../../../miniupnpc-1.3 - GPG_ERROR_DIR = ../../../../libgpg-error-1.7 - GPGME_DIR = ../../../../gpgme-1.1.8 - - INCLUDEPATH *= /usr/i586-mingw32msvc/include ${HOME}/.wine/drive_c/pthreads/include/ -} -################################# Windows ########################################## - -win32-g++|win32-clang-g++ { - QMAKE_CC = $${QMAKE_CXX} - OBJECTS_DIR = temp/obj - MOC_DIR = temp/moc - !libretroshare_shared:DEFINES *= STATICLIB - - # Switch off optimization for release version - QMAKE_CXXFLAGS_RELEASE -= -O2 - QMAKE_CXXFLAGS_RELEASE += -O0 - QMAKE_CFLAGS_RELEASE -= -O2 - QMAKE_CFLAGS_RELEASE += -O0 - - # Switch on optimization for debug version - #QMAKE_CXXFLAGS_DEBUG += -O2 - #QMAKE_CFLAGS_DEBUG += -O2 - - DEFINES += USE_CMD_ARGS - - wLibs = ws2_32 gdi32 uuid iphlpapi crypt32 ole32 winmm - LIBS += $$linkDynamicLibs(wLibs) -} - -################################# MacOSX ########################################## - -mac { - QMAKE_CC = $${QMAKE_CXX} - OBJECTS_DIR = temp/obj - MOC_DIR = temp/moc - - # Beautiful Hack to fix 64bit file access. - QMAKE_CXXFLAGS *= -Dfseeko64=fseeko -Dftello64=ftello -Dfopen64=fopen -Dvstatfs64=vstatfs - - for(lib, LIB_DIR):LIBS += -L"$$lib" - for(bin, BIN_DIR):LIBS += -L"$$bin" - - DEPENDPATH += . $$INC_DIR - INCLUDEPATH += . $$INC_DIR - INCLUDEPATH += ../../../. - - # We need a explicit path here, to force using the home version of sqlite3 that really encrypts the database. - LIBS += /usr/local/lib/libsqlcipher.a - #LIBS += -lsqlite3 - - DEFINES *= PLUGIN_DIR=\"\\\"$${PLUGIN_DIR}\\\"\" - DEFINES *= RS_DATA_DIR=\"\\\"$${RS_DATA_DIR}\\\"\" -} - -################################# FreeBSD ########################################## - -freebsd-* { - INCLUDEPATH *= /usr/local/include/gpgme - INCLUDEPATH *= /usr/local/include/glib-2.0 - - QMAKE_CXXFLAGS *= -Dfseeko64=fseeko -Dftello64=ftello -Dstat64=stat -Dstatvfs64=statvfs -Dfopen64=fopen -} - -################################# OpenBSD ########################################## - -openbsd-* { - INCLUDEPATH *= /usr/local/include - INCLUDEPATH += $$system(pkg-config --cflags glib-2.0 | sed -e "s/-I//g") - - QMAKE_CXXFLAGS *= -Dfseeko64=fseeko -Dftello64=ftello -Dstat64=stat -Dstatvfs64=statvfs -Dfopen64=fopen -} - -################################# Haiku ########################################## - -haiku-* { - - QMAKE_CXXFLAGS *= -Dfseeko64=fseeko -Dftello64=ftello -Dstat64=stat -Dstatvfs64=statvfs -Dfopen64=fopen - OPENPGPSDK_DIR = ../../openpgpsdk/src - INCLUDEPATH *= $${OPENPGPSDK_DIR} ../openpgpsdk - DEFINES *= NO_SQLCIPHER - CONFIG += release - DESTDIR = lib -} - -################################### COMMON stuff ################################## - -# openpgpsdk -OPENPGPSDK_DIR = ../../openpgpsdk/src -DEPENDPATH *= $${OPENPGPSDK_DIR} -INCLUDEPATH *= $${OPENPGPSDK_DIR} -PRE_TARGETDEPS *= $${OPENPGPSDK_DIR}/lib/libops.a -LIBS *= $${OPENPGPSDK_DIR}/lib/libops.a -lbz2 - -################################### HEADERS & SOURCES ############################# - -HEADERS += ft/ftchunkmap.h \ - ft/ftcontroller.h \ - ft/ftdata.h \ - ft/ftdatamultiplex.h \ - ft/ftextralist.h \ - ft/ftfilecreator.h \ - ft/ftfileprovider.h \ - ft/ftfilesearch.h \ - ft/ftsearch.h \ - ft/ftserver.h \ - ft/fttransfermodule.h \ - ft/ftturtlefiletransferitem.h - -HEADERS += crypto/chacha20.h \ - crypto/rsaes.h \ - crypto/hashstream.h \ - crypto/rscrypto.h - -HEADERS += file_sharing/directory_updater.h \ - file_sharing/directory_list.h \ - file_sharing/p3filelists.h - -HEADERS += chat/distantchat.h \ - chat/p3chatservice.h \ - chat/distributedchat.h \ - chat/rschatitems.h - -HEADERS += pqi/authssl.h \ - pqi/authgpg.h \ - pgp/pgphandler.h \ - pgp/openpgpsdkhandler.h \ - pgp/pgpkeyutil.h \ - pqi/pqifdbin.h \ - pqi/rstcpsocket.h \ - pgp/rscertificate.h \ - pgp/pgpauxutils.h \ - pqi/p3cfgmgr.h \ - pqi/p3peermgr.h \ - pqi/p3linkmgr.h \ - pqi/p3netmgr.h \ - pqi/p3notify.h \ - pqi/p3upnpmgr.h \ - pqi/pqiqos.h \ - pqi/pqi.h \ - pqi/pqi_base.h \ - pqi/pqiassist.h \ - pqi/pqibin.h \ - pqi/pqihandler.h \ - pqi/pqihash.h \ - pqi/p3historymgr.h \ - pqi/pqiindic.h \ - pqi/pqiipset.h \ - pqi/pqilistener.h \ - pqi/pqiloopback.h \ - pqi/pqimonitor.h \ - pqi/pqinetwork.h \ - pqi/pqiperson.h \ - pqi/pqipersongrp.h \ - pqi/pqiservice.h \ - pqi/pqiservicemonitor.h \ - pqi/pqissl.h \ - pqi/pqissllistener.h \ - pqi/pqisslpersongrp.h \ - pqi/pqiproxy.h \ - pqi/pqisslproxy.h \ - pqi/pqistore.h \ - pqi/pqistreamer.h \ - pqi/pqithreadstreamer.h \ - pqi/pqiqosstreamer.h \ - pqi/sslfns.h \ - pqi/pqinetstatebox.h \ - pqi/p3servicecontrol.h - -HEADERS += rsserver/p3face.h \ - rsserver/p3history.h \ - rsserver/p3msgs.h \ - rsserver/p3peers.h \ - rsserver/p3status.h \ - rsserver/rsaccounts.h \ - rsserver/p3serverconfig.h - -HEADERS += grouter/groutercache.h \ - retroshare/rsgrouter.h \ - grouter/grouteritems.h \ - grouter/p3grouter.h \ - grouter/groutermatrix.h \ - grouter/groutertypes.h \ - grouter/grouterclientservice.h - -HEADERS += rsitems/rsitem.h \ - rsitems/itempriorities.h \ - serialiser/rsbaseserial.h \ - rsitems/rsfiletransferitems.h \ - rsitems/rsconfigitems.h \ - rsitems/rshistoryitems.h \ - rsitems/rsmsgitems.h \ - serialiser/rsserial.h \ - rsitems/rsserviceids.h \ - rsitems/rsstatusitems.h \ - serialiser/rstlvaddrs.h \ - serialiser/rstlvbase.h \ - serialiser/rstlvitem.h \ - serialiser/rstlvidset.h \ - serialiser/rstlvfileitem.h \ - serialiser/rstlvimage.h \ - serialiser/rstlvstring.h \ - serialiser/rstlvbinary.h \ - serialiser/rstlvkeys.h \ - serialiser/rstlvkeyvalue.h \ - serialiser/rstlvgenericparam.h \ - serialiser/rstlvgenericmap.h \ - serialiser/rstlvgenericmap.inl \ - serialiser/rstlvlist.h \ - serialiser/rstlvmaps.h \ - serialiser/rstlvbanlist.h \ - rsitems/rsbanlistitems.h \ - rsitems/rsbwctrlitems.h \ - gossipdiscovery/gossipdiscoveryitems.h \ - rsitems/rsheartbeatitems.h \ - rsitems/rsrttitems.h \ - rsitems/rsgxsrecognitems.h \ - rsitems/rsgxsupdateitems.h \ - rsitems/rsserviceinfoitems.h \ - -HEADERS += \ - services/rseventsservice.h \ - services/autoproxy/rsautoproxymonitor.h \ - services/p3msgservice.h \ - services/p3service.h \ - services/p3statusservice.h \ - services/p3banlist.h \ - services/p3bwctrl.h \ - gossipdiscovery/p3gossipdiscovery.h \ - services/p3heartbeat.h \ - services/p3rtt.h \ - services/p3serviceinfo.h \ - -HEADERS += turtle/p3turtle.h \ - turtle/rsturtleitem.h \ - turtle/turtletypes.h \ - turtle/turtleclientservice.h - -HEADERS += util/folderiterator.h \ - util/rsdebug.h \ - util/rsdebuglevel0.h \ - util/rsdebuglevel1.h \ - util/rsdebuglevel2.h \ - util/rsdebuglevel3.h \ - util/rsdebuglevel4.h \ - util/rskbdinput.h \ - util/rsmemory.h \ - util/smallobject.h \ - util/rsdir.h \ - util/rsfile.h \ - util/argstream.h \ - util/rsdiscspace.h \ - util/rsnet.h \ - util/extaddrfinder.h \ - util/dnsresolver.h \ - util/radix32.h \ - util/radix64.h \ - util/rsbase64.h \ - util/rsendian.h \ - util/rsinitedptr.h \ - util/rsprint.h \ - util/rsstring.h \ - util/rsstd.h \ - util/rsthreads.h \ - util/rswin.h \ - util/rsrandom.h \ - util/rsmemcache.h \ - util/rstickevent.h \ - util/rsrecogn.h \ - util/rstime.h \ - util/stacktrace.h \ - util/rsdeprecate.h \ - util/cxx11retrocompat.h \ - util/cxx14retrocompat.h \ - util/cxx17retrocompat.h \ - util/cxx23retrocompat.h \ - util/rsurl.h - -SOURCES += ft/ftchunkmap.cc \ - ft/ftcontroller.cc \ - ft/ftdatamultiplex.cc \ - ft/ftextralist.cc \ - ft/ftfilecreator.cc \ - ft/ftfileprovider.cc \ - ft/ftfilesearch.cc \ - ft/ftserver.cc \ - ft/fttransfermodule.cc \ - ft/ftturtlefiletransferitem.cc \ - util/i2pcommon.cpp - -SOURCES += crypto/chacha20.cpp \ - crypto/hashstream.cc\ - crypto/rsaes.cc \ - crypto/rscrypto.cpp - -SOURCES += chat/distantchat.cc \ - chat/p3chatservice.cc \ - chat/distributedchat.cc \ - chat/rschatitems.cc - -SOURCES += pqi/authgpg.cc \ - pqi/authssl.cc \ - pgp/pgphandler.cc \ - pgp/openpgpsdkhandler.cc \ - pgp/pgpkeyutil.cc \ - pgp/rscertificate.cc \ - pgp/pgpauxutils.cc \ - pqi/p3cfgmgr.cc \ - pqi/p3peermgr.cc \ - pqi/p3linkmgr.cc \ - pqi/pqifdbin.cc \ - pqi/rstcpsocket.cc \ - pqi/p3netmgr.cc \ - pqi/p3notify.cc \ - pqi/pqiqos.cc \ - pqi/pqibin.cc \ - pqi/pqihandler.cc \ - pqi/p3historymgr.cc \ - pqi/pqiipset.cc \ - pqi/pqiloopback.cc \ - pqi/pqimonitor.cc \ - pqi/pqinetwork.cc \ - pqi/pqiperson.cc \ - pqi/pqipersongrp.cc \ - pqi/pqiservice.cc \ - pqi/pqissl.cc \ - pqi/pqissllistener.cc \ - pqi/pqisslpersongrp.cc \ - pqi/pqiproxy.cc \ - pqi/pqisslproxy.cc \ - pqi/pqistore.cc \ - pqi/pqistreamer.cc \ - pqi/pqithreadstreamer.cc \ - pqi/pqiqosstreamer.cc \ - pqi/sslfns.cc \ - pqi/pqinetstatebox.cc \ - pqi/p3servicecontrol.cc - -SOURCES += rsserver/p3face-config.cc \ - rsserver/p3face-server.cc \ - rsserver/p3face-info.cc \ - rsserver/p3history.cc \ - rsserver/p3msgs.cc \ - rsserver/p3peers.cc \ - rsserver/p3status.cc \ - rsserver/rsinit.cc \ - rsserver/rsaccounts.cc \ - rsserver/rsloginhandler.cc \ - rsserver/p3serverconfig.cc - -SOURCES += grouter/p3grouter.cc \ - grouter/grouteritems.cc \ - grouter/groutermatrix.cc - -SOURCES += plugins/pluginmanager.cc \ - plugins/dlfcn_win32.cc - -SOURCES += serialiser/rsbaseserial.cc \ - rsitems/rsfiletransferitems.cc \ - rsitems/rsconfigitems.cc \ - rsitems/rshistoryitems.cc \ - rsitems/rsmsgitems.cc \ - serialiser/rsserial.cc \ - serialiser/rstlvaddrs.cc \ - serialiser/rstlvbase.cc \ - serialiser/rstlvitem.cc \ - serialiser/rstlvidset.cc \ - serialiser/rstlvfileitem.cc \ - serialiser/rstlvimage.cc \ - serialiser/rstlvstring.cc \ - serialiser/rstlvbinary.cc \ - serialiser/rstlvkeys.cc \ - serialiser/rstlvkeyvalue.cc \ - serialiser/rstlvgenericparam.cc \ - serialiser/rstlvbanlist.cc \ - rsitems/rsbanlistitems.cc \ - rsitems/rsbwctrlitems.cc \ - gossipdiscovery/gossipdiscoveryitems.cc \ - rsitems/rsrttitems.cc \ - rsitems/rsgxsrecognitems.cc \ - rsitems/rsgxsupdateitems.cc \ - rsitems/rsserviceinfoitems.cc \ - - -SOURCES += services/autoproxy/rsautoproxymonitor.cc \ - services/rseventsservice.cc \ - services/p3msgservice.cc \ - services/p3service.cc \ - services/p3statusservice.cc \ - services/p3banlist.cc \ - services/p3bwctrl.cc \ - gossipdiscovery/p3gossipdiscovery.cc \ - services/p3heartbeat.cc \ - services/p3rtt.cc \ - services/p3serviceinfo.cc \ - -SOURCES += turtle/p3turtle.cc \ - turtle/rsturtleitem.cc - -SOURCES += util/folderiterator.cc \ - util/rsdebug.cc \ - util/rskbdinput.cc \ - util/rsexpr.cc \ - util/smallobject.cc \ - util/rsdir.cc \ - util/rsfile.cc \ - util/rsdiscspace.cc \ - util/rsnet.cc \ - util/rsnet_ss.cc \ - util/rsdnsutils.cc \ - util/extaddrfinder.cc \ - util/dnsresolver.cc \ - util/rsprint.cc \ - util/rsstring.cc \ - util/rsthreads.cc \ - util/rsrandom.cc \ - util/rstickevent.cc \ - util/rsrecogn.cc \ - util/rstime.cc \ - util/rsurl.cc \ - util/rsbase64.cc - -equals(RS_UPNP_LIB, miniupnpc) { - HEADERS += rs_upnp/upnputil.h rs_upnp/upnphandler_miniupnp.h - SOURCES += rs_upnp/upnputil.cc rs_upnp/upnphandler_miniupnp.cc -} - -contains(RS_UPNP_LIB, upnp) { - HEADERS += rs_upnp/upnp18_retrocompat.h - HEADERS += rs_upnp/UPnPBase.h rs_upnp/upnphandler_libupnp.h - SOURCES += rs_upnp/UPnPBase.cpp rs_upnp/upnphandler_libupnp.cc -} - -# new gxs cache system -# this should be disabled for releases until further notice. - -DEFINES *= SQLITE_HAS_CODEC -DEFINES *= GXS_ENABLE_SYNC_MSGS - -HEADERS += rsitems/rsnxsitems.h \ - rsitems/rsgxsitems.h \ - retroshare/rstokenservice.h \ - retroshare/rsgxsservice.h \ - retroshare/rsgxsflags.h \ - retroshare/rsgxsifacetypes.h \ - retroshare/rsgxsiface.h \ - retroshare/rsgxscommon.h \ - retroshare/rsgxsifacehelper.h \ - util/retrodb.h \ - util/rsdbbind.h \ - util/contentvalue.h \ - gxs/rsgxsutil.h \ - gxs/rsgxsnotify.h \ - gxs/gxssecurity.h \ - gxs/rsgds.h \ - gxs/rsgxs.h \ - gxs/rsdataservice.h \ - gxs/rsgxsnetservice.h \ - gxs/rsgxsnettunnel.h \ - gxs/rsgenexchange.h \ - gxs/rsnxs.h \ - gxs/rsnxsobserver.h \ - gxs/rsgxsdata.h \ - gxs/rsgxsdataaccess.h \ - gxs/gxstokenqueue.h \ - gxs/rsgxsnetutils.h \ - gxs/rsgxsrequesttypes.h - - -SOURCES += rsitems/rsnxsitems.cc \ - rsitems/rsgxsitems.cc \ - util/retrodb.cc \ - util/contentvalue.cc \ - util/rsdbbind.cc \ - gxs/gxssecurity.cc \ - gxs/rsgxsdataaccess.cc \ - gxs/rsdataservice.cc \ - gxs/rsgenexchange.cc \ - gxs/rsgxsnetservice.cc \ - gxs/rsgxsnettunnel.cc \ - gxs/rsgxsdata.cc \ - gxs/gxstokenqueue.cc \ - gxs/rsgxsnetutils.cc \ - gxs/rsgxsutil.cc \ - gxs/rsgxsrequesttypes.cc \ - gxs/rsnxsobserver.cpp - -# Tor -HEADERS += retroshare/rstor.h - -HEADERS += tor/AddOnionCommand.h \ - tor/AuthenticateCommand.h \ - tor/CryptoKey.h \ - tor/GetConfCommand.h \ - tor/HiddenService.h \ - tor/PendingOperation.h \ - tor/ProtocolInfoCommand.h \ - tor/TorTypes.h \ - tor/SetConfCommand.h \ - tor/StrUtil.h \ - tor/bytearray.h \ - tor/TorControl.h \ - tor/TorControlCommand.h \ - tor/TorControlSocket.h \ - tor/TorManager.h \ - tor/TorProcess.h - -SOURCES += tor/AddOnionCommand.cpp \ - tor/AuthenticateCommand.cpp \ - tor/GetConfCommand.cpp \ - tor/HiddenService.cpp \ - tor/ProtocolInfoCommand.cpp \ - tor/SetConfCommand.cpp \ - tor/TorControlCommand.cpp \ - tor/TorControl.cpp \ - tor/TorControlSocket.cpp \ - tor/TorManager.cpp \ - tor/TorProcess.cpp \ - tor/CryptoKey.cpp \ - tor/PendingOperation.cpp \ - tor/StrUtil.cpp - -# gxs tunnels -HEADERS += gxstunnel/p3gxstunnel.h \ - gxstunnel/rsgxstunnelitems.h \ - retroshare/rsgxstunnel.h - -SOURCES += gxstunnel/p3gxstunnel.cc \ - gxstunnel/rsgxstunnelitems.cc - -# new serialization code -HEADERS += serialiser/rsserializable.h \ - serialiser/rsserializer.h \ - serialiser/rstypeserializer.h \ - util/rsjson.h - -SOURCES += serialiser/rsserializable.cc \ - serialiser/rsserializer.cc \ - serialiser/rstypeserializer.cc \ - util/rsjson.cc - -# Identity Service -HEADERS += retroshare/rsidentity.h \ - retroshare/rsreputations.h \ - gxs/rsgixs.h \ - services/p3idservice.h \ - rsitems/rsgxsiditems.h \ - services/p3gxsreputation.h \ - rsitems/rsgxsreputationitems.h \ - -SOURCES += services/p3idservice.cc \ - rsitems/rsgxsiditems.cc \ - services/p3gxsreputation.cc \ - rsitems/rsgxsreputationitems.cc \ - -# GxsCircles Service -HEADERS += services/p3gxscircles.h \ - rsitems/rsgxscircleitems.h \ - retroshare/rsgxscircles.h \ - -SOURCES += services/p3gxscircles.cc \ - rsitems/rsgxscircleitems.cc \ - -# GxsForums Service -HEADERS += retroshare/rsgxsforums.h \ - services/p3gxsforums.h \ - rsitems/rsgxsforumitems.h - -SOURCES += services/p3gxsforums.cc \ - rsitems/rsgxsforumitems.cc \ - -# GxsChannels Service -HEADERS += retroshare/rsgxschannels.h \ - services/p3gxschannels.h \ - services/p3gxscommon.h \ - rsitems/rsgxscommentitems.h \ - rsitems/rsgxschannelitems.h \ - -SOURCES += services/p3gxschannels.cc \ - services/p3gxscommon.cc \ - rsitems/rsgxscommentitems.cc \ - rsitems/rsgxschannelitems.cc \ - -wikipoos { - DEFINES *= RS_USE_WIKI - - # Wiki Service - HEADERS += retroshare/rswiki.h \ - services/p3wiki.h \ - rsitems/rswikiitems.h - - SOURCES += services/p3wiki.cc \ - rsitems/rswikiitems.cc \ -} - -# Friend server - -rs_efs { - DEFINES *= RS_EMBEDED_FRIEND_SERVER - - HEADERS += friend_server/fsclient.h \ - friend_server/fsitem.h \ - friend_server/fsmanager.h \ - retroshare/rsfriendserver.h - - SOURCES += friend_server/fsclient.cc \ - friend_server/fsmanager.cc -} - -# The Wire - -gxsthewire { - DEFINES *= RS_USE_WIRE - - # Wire Service - HEADERS += retroshare/rswire.h \ - services/p3wire.h \ - rsitems/rswireitems.h - - SOURCES += services/p3wire.cc \ - rsitems/rswireitems.cc \ -} - -# Posted Service -HEADERS += services/p3postbase.h \ - services/p3posted.h \ - retroshare/rsposted.h \ - rsitems/rsposteditems.h - -SOURCES += services/p3postbase.cc \ - services/p3posted.cc \ - rsitems/rsposteditems.cc - -gxsphotoshare { - DEFINES *= RS_USE_PHOTO - - #Photo Service - HEADERS += services/p3photoservice.h \ - retroshare/rsphoto.h \ - rsitems/rsphotoitems.h \ - - SOURCES += services/p3photoservice.cc \ - rsitems/rsphotoitems.cc \ -} - -rs_gxs_trans { - HEADERS += gxstrans/p3gxstransitems.h gxstrans/p3gxstrans.h - SOURCES += gxstrans/p3gxstransitems.cc gxstrans/p3gxstrans.cc -} - -rs_jsonapi { - JSONAPI_GENERATOR_SRC=$$clean_path($${RS_SRC_PATH}/jsonapi-generator/src/) - JSONAPI_GENERATOR_OUT=$$clean_path($${RS_BUILD_PATH}/jsonapi-generator/src/) - isEmpty(JSONAPI_GENERATOR_EXE) { - win32 { - CONFIG(release, debug|release) { - JSONAPI_GENERATOR_EXE=$$clean_path($${JSONAPI_GENERATOR_OUT}/release/jsonapi-generator.exe) - } - CONFIG(debug, debug|release) { - JSONAPI_GENERATOR_EXE=$$clean_path($${JSONAPI_GENERATOR_OUT}/debug/jsonapi-generator.exe) - } - } else { - JSONAPI_GENERATOR_EXE=$$clean_path($${JSONAPI_GENERATOR_OUT}/jsonapi-generator) - } - } - - DOXIGEN_INPUT_DIRECTORY=$$clean_path($${PWD}) - DOXIGEN_CONFIG_SRC=$$clean_path($${RS_SRC_PATH}/jsonapi-generator/src/jsonapi-generator-doxygen.conf) - DOXIGEN_CONFIG_OUT=$$clean_path($${JSONAPI_GENERATOR_OUT}/jsonapi-generator-doxygen-final.conf) - WRAPPERS_INCL_FILE=$$clean_path($${JSONAPI_GENERATOR_OUT}/jsonapi-includes.inl) - WRAPPERS_REG_FILE=$$clean_path($${JSONAPI_GENERATOR_OUT}/jsonapi-wrappers.inl) - - no_rs_cross_compiling { - DUMMYRESTBEDINPUT = FORCE - CMAKE_GENERATOR_OVERRIDE="" - win32-g++|win32-clang-g++ { - isEmpty(QMAKE_SH) { - CMAKE_GENERATOR_OVERRIDE="-G \"MinGW Makefiles\"" - } else { - CMAKE_GENERATOR_OVERRIDE="-G \"MSYS Makefiles\"" - } - } - genrestbedlib.name = Generating librestbed. - genrestbedlib.input = DUMMYRESTBEDINPUT - genrestbedlib.output = $$clean_path($${RESTBED_BUILD_PATH}/librestbed.a) - genrestbedlib.CONFIG += target_predeps combine - genrestbedlib.variable_out = PRE_TARGETDEPS - win32-g++:isEmpty(QMAKE_SH) { - genrestbedlib.commands = \ - cd /D $$shell_path($${RS_SRC_PATH}) && git submodule update --init supportlibs/restbed || cd . $$escape_expand(\\n\\t) \ - cd /D $$shell_path($${RESTBED_SRC_PATH}) && git submodule update --init dependency/asio || cd . $$escape_expand(\\n\\t) \ - cd /D $$shell_path($${RESTBED_SRC_PATH}) && git submodule update --init dependency/catch || cd . $$escape_expand(\\n\\t )\ - cd /D $$shell_path($${RESTBED_SRC_PATH}) && git submodule update --init dependency/kashmir || cd . $$escape_expand(\\n\\t) \ - $(CHK_DIR_EXISTS) $$shell_path($$UDP_DISCOVERY_BUILD_PATH) $(MKDIR) $$shell_path($${UDP_DISCOVERY_BUILD_PATH}) $$escape_expand(\\n\\t) - } else { - genrestbedlib.commands = \ - cd $${RS_SRC_PATH} && ( \ - git submodule update --init supportlibs/restbed ; \ - cd $${RESTBED_SRC_PATH} ; \ - git submodule update --init dependency/asio ; \ - git submodule update --init dependency/catch ; \ - git submodule update --init dependency/kashmir ; \ - true ) && \ - mkdir -p $${RESTBED_BUILD_PATH} && - } - genrestbedlib.commands += \ - cd $$shell_path($${RESTBED_BUILD_PATH}) && \ - cmake \ - -DCMAKE_CXX_COMPILER=$$QMAKE_CXX \ - \"-DCMAKE_CXX_FLAGS=$${QMAKE_CXXFLAGS}\" \ - $${CMAKE_GENERATOR_OVERRIDE} -DBUILD_SSL=OFF \ - -DCMAKE_INSTALL_PREFIX=. -B. \ - -H$$shell_path($${RESTBED_SRC_PATH}) && \ - $(MAKE) - QMAKE_EXTRA_COMPILERS += genrestbedlib - - RESTBED_HEADER_FILE=$$clean_path($${RESTBED_BUILD_PATH}/include/restbed) - genrestbedheader.name = Generating restbed header. - genrestbedheader.input = genrestbedlib.output - genrestbedheader.output = $${RESTBED_HEADER_FILE} - genrestbedheader.CONFIG += target_predeps no_link - genrestbedheader.variable_out = HEADERS - genrestbedheader.commands = cd $$shell_path($${RESTBED_BUILD_PATH}) && $(MAKE) install - QMAKE_EXTRA_COMPILERS += genrestbedheader - } - - INCLUDEPATH *= $${JSONAPI_GENERATOR_OUT} - DEPENDPATH *= $${JSONAPI_GENERATOR_OUT} - APIHEADERS = $$files($${RS_SRC_PATH}/libretroshare/src/retroshare/*.h) - #Make sure that the jsonapigenerator executable are ready - APIHEADERS += $${JSONAPI_GENERATOR_EXE} - - genjsonapi.name = Generating jsonapi headers. - genjsonapi.input = APIHEADERS - genjsonapi.output = $${WRAPPERS_INCL_FILE} $${WRAPPERS_REG_FILE} - genjsonapi.clean = $${WRAPPERS_INCL_FILE} $${WRAPPERS_REG_FILE} - genjsonapi.CONFIG += target_predeps combine no_link - genjsonapi.variable_out = HEADERS - win32-g++:isEmpty(QMAKE_SH) { - genjsonapi.commands = \ - $(CHK_DIR_EXISTS) $$shell_path($$JSONAPI_GENERATOR_OUT) $(MKDIR) $$shell_path($${JSONAPI_GENERATOR_OUT}) $$escape_expand(\\n\\t) - } else { - genjsonapi.commands = \ - mkdir -p $${JSONAPI_GENERATOR_OUT} && \ - cp $${DOXIGEN_CONFIG_SRC} $${DOXIGEN_CONFIG_OUT} && \ - echo OUTPUT_DIRECTORY=$${JSONAPI_GENERATOR_OUT} >> $${DOXIGEN_CONFIG_OUT} && \ - echo INPUT=$${DOXIGEN_INPUT_DIRECTORY} >> $${DOXIGEN_CONFIG_OUT} && \ - doxygen $${DOXIGEN_CONFIG_OUT} && - } - genjsonapi.commands += \ - $${JSONAPI_GENERATOR_EXE} $${JSONAPI_GENERATOR_SRC} $${JSONAPI_GENERATOR_OUT} - QMAKE_EXTRA_COMPILERS += genjsonapi - - # Force recalculation of libretroshare dependencies see https://stackoverflow.com/a/47884045 - QMAKE_EXTRA_TARGETS += libretroshare - - HEADERS += jsonapi/jsonapi.h jsonapi/jsonapiitems.h retroshare/rsjsonapi.h - SOURCES += jsonapi/jsonapi.cpp -} - -rs_deep_forums_index { - HEADERS *= deep_search/commonutils.hpp - SOURCES *= deep_search/commonutils.cpp - - HEADERS += deep_search/forumsindex.hpp - SOURCES += deep_search/forumsindex.cpp -} - -rs_deep_channels_index { - HEADERS *= deep_search/commonutils.hpp - SOURCES *= deep_search/commonutils.cpp - - HEADERS += deep_search/channelsindex.hpp - SOURCES += deep_search/channelsindex.cpp -} - -rs_deep_files_index { - HEADERS *= deep_search/commonutils.hpp - SOURCES *= deep_search/commonutils.cpp - - HEADERS += deep_search/filesindex.hpp - SOURCES += deep_search/filesindex.cpp -} - -rs_deep_files_index_ogg { - HEADERS += deep_search/filesoggindexer.hpp -} - -rs_deep_files_index_flac { - HEADERS += deep_search/filesflacindexer.hpp -} - -rs_deep_files_index_taglib { - HEADERS += deep_search/filestaglibindexer.hpp -} - -rs_broadcast_discovery { - HEADERS += retroshare/rsbroadcastdiscovery.h \ - services/broadcastdiscoveryservice.h - SOURCES += services/broadcastdiscoveryservice.cc - - no_rs_cross_compiling { - DUMMYQMAKECOMPILERINPUT = FORCE - CMAKE_GENERATOR_OVERRIDE="" - win32-g++|win32-clang-g++ { - isEmpty(QMAKE_SH) { - CMAKE_GENERATOR_OVERRIDE="-G \"MinGW Makefiles\"" - } else { - CMAKE_GENERATOR_OVERRIDE="-G \"MSYS Makefiles\"" - } - } - udpdiscoverycpplib.name = Generating libudp-discovery.a. - udpdiscoverycpplib.input = DUMMYQMAKECOMPILERINPUT - udpdiscoverycpplib.output = $$clean_path($${UDP_DISCOVERY_BUILD_PATH}/libudp-discovery.a) - udpdiscoverycpplib.CONFIG += target_predeps combine - udpdiscoverycpplib.variable_out = PRE_TARGETDEPS - win32-g++:isEmpty(QMAKE_SH) { - udpdiscoverycpplib.commands = \ - cd /D $$shell_path($${RS_SRC_PATH}) && git submodule update --init supportlibs/udp-discovery-cpp || cd . $$escape_expand(\\n\\t) \ - $(CHK_DIR_EXISTS) $$shell_path($$UDP_DISCOVERY_BUILD_PATH) $(MKDIR) $$shell_path($${UDP_DISCOVERY_BUILD_PATH}) $$escape_expand(\\n\\t) - } else { - udpdiscoverycpplib.commands = \ - cd $${RS_SRC_PATH} && ( \ - git submodule update --init supportlibs/udp-discovery-cpp || \ - true ) && \ - mkdir -p $${UDP_DISCOVERY_BUILD_PATH} && - } - udpdiscoverycpplib.commands += \ - cd $$shell_path($${UDP_DISCOVERY_BUILD_PATH}) && \ - cmake -DCMAKE_C_COMPILER=$$fixQmakeCC($$QMAKE_CC) \ - -DCMAKE_CXX_COMPILER=$$QMAKE_CXX \ - \"-DCMAKE_CXX_FLAGS=$${QMAKE_CXXFLAGS}\" \ - $${CMAKE_GENERATOR_OVERRIDE} \ - -DBUILD_EXAMPLE=OFF -DBUILD_TOOL=OFF \ - -DCMAKE_INSTALL_PREFIX=. -B. \ - -H$$shell_path($${UDP_DISCOVERY_SRC_PATH}) && \ - $(MAKE) - QMAKE_EXTRA_COMPILERS += udpdiscoverycpplib - } -} - -rs_sam3 { - SOURCES += \ - services/autoproxy/p3i2psam3.cpp \ - pqi/pqissli2psam3.cpp \ - - HEADERS += \ - services/autoproxy/p3i2psam3.h \ - pqi/pqissli2psam3.h \ -} - -rs_sam3_libsam3 { - DUMMYQMAKECOMPILERINPUT = FORCE - libsam3.name = Generating libsam3. - libsam3.input = DUMMYQMAKECOMPILERINPUT - libsam3.output = $$clean_path($${LIBSAM3_BUILD_PATH}/libsam3.a) - libsam3.CONFIG += target_predeps combine - libsam3.variable_out = PRE_TARGETDEPS - win32-g++:isEmpty(QMAKE_SH) { - LIBSAM3_MAKE_PARAMS = CC=gcc - libsam3.commands = \ - cd /D $$shell_path($${RS_SRC_PATH}) && git submodule update --init supportlibs/libsam3 || cd . $$escape_expand(\\n\\t) \ - $(CHK_DIR_EXISTS) $$shell_path($$LIBSAM3_BUILD_PATH) $(MKDIR) $$shell_path($${LIBSAM3_BUILD_PATH}) $$escape_expand(\\n\\t) \ - $(COPY_DIR) $$shell_path($${LIBSAM3_SRC_PATH}) $$shell_path($${LIBSAM3_BUILD_PATH}) || cd . $$escape_expand(\\n\\t) - } else { - LIBSAM3_MAKE_PARAMS = - libsam3.commands = \ - cd $${RS_SRC_PATH} && ( \ - git submodule update --init supportlibs/libsam3 || \ - true ) && \ - mkdir -p $${LIBSAM3_BUILD_PATH} && \ - (cp -r $${LIBSAM3_SRC_PATH}/* $${LIBSAM3_BUILD_PATH} || true) && - } - libsam3.commands += \ - cd $$shell_path($${LIBSAM3_BUILD_PATH}) && \ - $(MAKE) build $${LIBSAM3_MAKE_PARAMS} - QMAKE_EXTRA_COMPILERS += libsam3 -} - -########################################################################################################### -# OLD CONFIG OPTIONS. -# Not used much - but might be useful one day. -# - -testnetwork { - # used in rsserver/rsinit.cc Enabled Port Restrictions, and makes Proxy Port next to Dht Port. - DEFINES *= LOCALNET_TESTING - - # used in tcponudp/udprelay.cc Debugging Info for Relays. - DEFINES *= DEBUG_UDP_RELAY - - # used in tcponudp/udpstunner.[h | cc] enables local stun (careful - modifies class variables). - DEFINES *= UDPSTUN_ALLOW_LOCALNET - - # used in pqi/p3linkmgr.cc prints out extra debug. - DEFINES *= LINKMGR_DEBUG_LINKTYPE - - # used in dht/connectstatebox to reduce connection times and display debug. - # DEFINES *= TESTING_PERIODS - # DEFINES *= DEBUG_CONNECTBOX -} - - -test_bitdht { - # DISABLE TCP CONNECTIONS... - DEFINES *= P3CONNMGR_NO_TCP_CONNECTIONS - - # NO AUTO CONNECTIONS??? FOR TESTING DHT STATUS. - DEFINES *= P3CONNMGR_NO_AUTO_CONNECTION - - # ENABLED UDP NOW. -} - -################################# Android ##################################### - -android-* { - lessThan(ANDROID_API_VERSION, 24) { -## @See: rs_android/README-ifaddrs-android.adoc - HEADERS += \ - rs_android/ifaddrs-android.h \ - rs_android/LocalArray.h \ - rs_android/ScopedFd.h - } - -## Static library are very susceptible to order in command line - sLibs = bz2 $$RS_UPNP_LIB $$RS_SQL_LIB ssl crypto - - LIBS += $$linkStaticLibs(sLibs) - PRE_TARGETDEPS += $$pretargetStaticLibs(sLibs) - - HEADERS += \ - rs_android/largefile_retrocompat.hpp \ - rs_android/androidcoutcerrcatcher.hpp \ - rs_android/retroshareserviceandroid.hpp \ - rs_android/rsjni.hpp - - SOURCES += rs_android/rsjni.cpp \ - rs_android/retroshareserviceandroid.cpp \ - rs_android/errorconditionwrap.cpp -} - diff --git a/libretroshare/src/pgp/openpgpsdkhandler.cc b/libretroshare/src/pgp/openpgpsdkhandler.cc deleted file mode 100644 index c619ca4c5..000000000 --- a/libretroshare/src/pgp/openpgpsdkhandler.cc +++ /dev/null @@ -1,1815 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pgp: pgphandler.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include -#include -#include -#include -#include -#include -#include - -#ifdef WINDOWS_SYS -#include -#include "util/rsstring.h" -#include "util/rswin.h" -#endif - -extern "C" { -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -} -#include "openpgpsdkhandler.h" - -#include "util/rsdir.h" -#include "util/rsdiscspace.h" -#include "util/rsmemory.h" -#include "pgp/pgpkeyutil.h" -#include "retroshare/rspeers.h" - -static const uint32_t PGP_CERTIFICATE_LIMIT_MAX_NAME_SIZE = 64 ; -static const uint32_t PGP_CERTIFICATE_LIMIT_MAX_EMAIL_SIZE = 64 ; -static const uint32_t PGP_CERTIFICATE_LIMIT_MAX_PASSWD_SIZE = 1024 ; - -//#define DEBUG_PGPHANDLER 1 -//#define PGPHANDLER_DSA_SUPPORT - -ops_keyring_t *OpenPGPSDKHandler::allocateOPSKeyring() -{ - ops_keyring_t *kr = (ops_keyring_t*)rs_malloc(sizeof(ops_keyring_t)) ; - - if(kr == NULL) - return NULL ; - - kr->nkeys = 0 ; - kr->nkeys_allocated = 0 ; - kr->keys = 0 ; - - return kr ; -} - -ops_parse_cb_return_t cb_get_passphrase(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)// __attribute__((unused))) -{ - const ops_parser_content_union_t *content=&content_->content; - bool prev_was_bad = false ; - - switch(content_->tag) - { - case OPS_PARSER_CMD_GET_SK_PASSPHRASE_PREV_WAS_BAD: prev_was_bad = true ; - /* fallthrough */ - case OPS_PARSER_CMD_GET_SK_PASSPHRASE: - { - std::string passwd; - std::string uid_hint ; - - if(cbinfo->cryptinfo.keydata->nuids > 0) - uid_hint = std::string((const char *)cbinfo->cryptinfo.keydata->uids[0].user_id) ; - uid_hint += "(" + RsPgpId(cbinfo->cryptinfo.keydata->key_id).toStdString()+")" ; - - bool cancelled = false ; - passwd = PGPHandler::passphraseCallback()(NULL,"",uid_hint.c_str(),NULL,prev_was_bad,&cancelled) ; - - if(cancelled) - *(unsigned char *)cbinfo->arg = 1; - - *(content->secret_key_passphrase.passphrase)= (char *)ops_mallocz(passwd.length()+1) ; - memcpy(*(content->secret_key_passphrase.passphrase),passwd.c_str(),passwd.length()) ; - return OPS_KEEP_MEMORY; - } - break; - - default: - break; - } - - return OPS_RELEASE_MEMORY; -} - -OpenPGPSDKHandler::OpenPGPSDKHandler(const std::string& pubring, const std::string& secring,const std::string& trustdb,const std::string& pgp_lock_filename) - : PGPHandler(pubring,secring,trustdb,pgp_lock_filename) -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - // Allocate public and secret keyrings. - // - _pubring = allocateOPSKeyring() ; - _secring = allocateOPSKeyring() ; - - // Check that the file exists. If not, create a void keyring. - - FILE *ftest ; - ftest = RsDirUtil::rs_fopen(pubring.c_str(),"rb") ; - bool pubring_exist = (ftest != NULL) ; - if(ftest != NULL) - fclose(ftest) ; - ftest = RsDirUtil::rs_fopen(secring.c_str(),"rb") ; - bool secring_exist = (ftest != NULL) ; - if(ftest != NULL) - fclose(ftest) ; - - // Read public and secret keyrings from supplied files. - // - if(pubring_exist) - { - if(ops_false == ops_keyring_read_from_file(_pubring, false, pubring.c_str())) - throw std::runtime_error("OpenPGPSDKHandler::readKeyRing(): cannot read pubring. File corrupted.") ; - } - else - RsErr() << "pubring file \"" << pubring << "\" not found. Creating a void keyring." ; - - const ops_keydata_t *keydata ; - int i=0 ; - while( (keydata = ops_keyring_get_key_by_index(_pubring,i)) != NULL ) - { - PGPCertificateInfo& cert(_public_keyring_map[ RsPgpId(keydata->key_id) ]) ; - - // Init all certificates. - - initCertificateInfo(cert,keydata,i) ; - - // Validate signatures. - - validateAndUpdateSignatures(cert,keydata) ; - - ++i ; - } - _pubring_last_update_time = time(NULL) ; - _pubring_changed = false; - - RsErr() << "Pubring read successfully." ; - - if(secring_exist) - { - if(ops_false == ops_keyring_read_from_file(_secring, false, secring.c_str())) - throw std::runtime_error("OpenPGPSDKHandler::readKeyRing(): cannot read secring. File corrupted.") ; - } - else - RsErr() << "secring file \"" << secring << "\" not found. Creating a void keyring." ; - - i=0 ; - while( (keydata = ops_keyring_get_key_by_index(_secring,i)) != NULL ) - { - initCertificateInfo(_secret_keyring_map[ RsPgpId(keydata->key_id) ],keydata,i) ; - ++i ; - } - _secring_last_update_time = time(NULL) ; - - RsErr() << "Secring read successfully." ; - - locked_readPrivateTrustDatabase() ; - _trustdb_last_update_time = time(NULL) ; -} - -void OpenPGPSDKHandler::initCertificateInfo(PGPCertificateInfo& cert,const ops_keydata_t *keydata,uint32_t index) -{ - // Parse certificate name - // - - if(keydata->uids != NULL) - { - std::string namestring( (char *)keydata->uids[0].user_id ) ; - - cert._name = "" ; - uint32_t i=0; - while(i < namestring.length() && namestring[i] != '(' && namestring[i] != '<') { cert._name += namestring[i] ; ++i ;} - - // trim right spaces - std::string::size_type found = cert._name.find_last_not_of(' '); - if (found != std::string::npos) - cert._name.erase(found + 1); - else - cert._name.clear(); // all whitespace - - std::string& next = (namestring[i] == '(')?cert._comment:cert._email ; - ++i ; - next = "" ; - while(i < namestring.length() && namestring[i] != ')' && namestring[i] != '>') { next += namestring[i] ; ++i ;} - - while(i < namestring.length() && namestring[i] != '(' && namestring[i] != '<') { next += namestring[i] ; ++i ;} - - if(i< namestring.length()) - { - std::string& next2 = (namestring[i] == '(')?cert._comment:cert._email ; - ++i ; - next2 = "" ; - while(i < namestring.length() && namestring[i] != ')' && namestring[i] != '>') { next2 += namestring[i] ; ++i ;} - } - } - - cert._trustLvl = 1 ; // to be setup accordingly - cert._validLvl = 1 ; // to be setup accordingly - cert._key_index = index ; - cert._flags = 0 ; - cert._time_stamp = 0 ;// "never" by default. Will be updated by trust database, and effective key usage. - - switch(keydata->key.pkey.algorithm) - { - case OPS_PKA_RSA: cert._type = PGPCertificateInfo::PGP_CERTIFICATE_TYPE_RSA ; - break ; - case OPS_PKA_DSA: cert._type = PGPCertificateInfo::PGP_CERTIFICATE_TYPE_DSA ; - cert._flags |= PGPCertificateInfo::PGP_CERTIFICATE_FLAG_UNSUPPORTED_ALGORITHM ; - break ; - default: cert._type = PGPCertificateInfo::PGP_CERTIFICATE_TYPE_UNKNOWN ; - cert._flags |= PGPCertificateInfo::PGP_CERTIFICATE_FLAG_UNSUPPORTED_ALGORITHM ; - break ; - } - - ops_fingerprint_t f ; - ops_fingerprint(&f,&keydata->key.pkey) ; - - cert._fpr = PGPFingerprintType(f.fingerprint) ; -} - -bool OpenPGPSDKHandler::validateAndUpdateSignatures(PGPCertificateInfo& cert,const ops_keydata_t *keydata) -{ - ops_validate_result_t* result=(ops_validate_result_t*)ops_mallocz(sizeof *result); - ops_boolean_t res = ops_validate_key_signatures(result,keydata,_pubring,cb_get_passphrase) ; - - if(res == ops_false) - { - static ops_boolean_t already = 0 ; - if(!already) - { - RsErr() << "(WW) Error in OpenPGPSDKHandler::validateAndUpdateSignatures(). Validation failed for at least some signatures." ; - already = 1 ; - } - } - - bool ret = false ; - - // Parse signers. - // - - if(result != NULL) - for(size_t i=0;ivalid_count;++i) - { - RsPgpId signer_id(result->valid_sigs[i].signer_id); - - if(cert.signers.find(signer_id) == cert.signers.end()) - { - cert.signers.insert(signer_id) ; - ret = true ; - } - } - - ops_validate_result_free(result) ; - - return ret ; -} - -OpenPGPSDKHandler::~OpenPGPSDKHandler() -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. -#ifdef DEBUG_PGPHANDLER - RsErr() << "Freeing OpenPGPSDKHandler. Deleting keyrings." ; -#endif - - // no need to free the the _map_ elements. They will be freed by the following calls: - // - ops_keyring_free(_pubring) ; - ops_keyring_free(_secring) ; - - free(_pubring) ; - free(_secring) ; -} - -void OpenPGPSDKHandler::printOPSKeys() const -{ - RsErr() << "Public keyring list from OPS:" ; - ops_keyring_list(_pubring) ; -} - -bool OpenPGPSDKHandler::haveSecretKey(const RsPgpId& id) const -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - return locked_getSecretKey(id) != NULL ; -} - -bool OpenPGPSDKHandler::availableGPGCertificatesWithPrivateKeys(std::list& ids) -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - // go through secret keyring, and check that we have the pubkey as well. - // - - const ops_keydata_t *keydata = NULL ; - int i=0 ; - - while( (keydata = ops_keyring_get_key_by_index(_secring,i++)) != NULL ) - if(ops_keyring_find_key_by_id(_pubring,keydata->key_id) != NULL) // check that the key is in the pubring as well - { -#ifdef PGPHANDLER_DSA_SUPPORT - if(keydata->key.pkey.algorithm == OPS_PKA_RSA || keydata->key.pkey.algorithm == OPS_PKA_DSA) -#else - if(keydata->key.pkey.algorithm == OPS_PKA_RSA) -#endif - ids.push_back(RsPgpId(keydata->key_id)) ; -#ifdef DEBUG_PGPHANDLER - else - RsErr() << "Skipping keypair " << RsPgpId(keydata->key_id).toStdString() << ", unsupported algorithm: " << keydata->key.pkey.algorithm ; -#endif - } - - return true ; -} - -bool OpenPGPSDKHandler::GeneratePGPCertificate(const std::string& name, const std::string& email, const std::string& passphrase, RsPgpId& pgpId, const int keynumbits, std::string& errString) -{ - // Some basic checks - - if(!RsDiscSpace::checkForDiscSpace(RS_PGP_DIRECTORY)) - { - errString = std::string("(EE) low disc space in pgp directory. Can't write safely to keyring.") ; - return false ; - } - if(name.length() > PGP_CERTIFICATE_LIMIT_MAX_NAME_SIZE) - { - errString = std::string("(EE) name in certificate exceeds the maximum allowed name size") ; - return false ; - } - if(email.length() > PGP_CERTIFICATE_LIMIT_MAX_EMAIL_SIZE) - { - errString = std::string("(EE) email in certificate exceeds the maximum allowed email size") ; - return false ; - } - if(passphrase.length() > PGP_CERTIFICATE_LIMIT_MAX_PASSWD_SIZE) - { - errString = std::string("(EE) passphrase in certificate exceeds the maximum allowed passphrase size") ; - return false ; - } - if(keynumbits % 1024 != 0) - { - errString = std::string("(EE) RSA key length is not a multiple of 1024") ; - return false ; - } - - // Now the real thing - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - RsStackFileLock flck(_pgp_lock_filename) ; // lock access to PGP directory. - - // 1 - generate keypair - RSA-2048 - // - ops_user_id_t uid ; - char *s = strdup((name + " (Generated by RetroShare) <" + email + ">" ).c_str()) ; - uid.user_id = (unsigned char *)s ; - unsigned long int e = 65537 ; // some prime number - - ops_keydata_t *key = ops_rsa_create_selfsigned_keypair(keynumbits, e, &uid) ; - - free(s) ; - - if(!key) - return false ; - - // 2 - save the private key encrypted to a temporary memory buffer, so as to read an encrypted key to memory - - ops_create_info_t *cinfo = NULL ; - ops_memory_t *buf = NULL ; - ops_setup_memory_write(&cinfo, &buf, 0); - - if(!ops_write_transferable_secret_key(key,(unsigned char *)passphrase.c_str(),passphrase.length(),ops_false,cinfo)) - { - errString = std::string("(EE) Cannot encode secret key to memory!!") ; - return false ; - } - - // 3 - read the memory chunk into an encrypted keyring - - ops_keyring_t *tmp_secring = allocateOPSKeyring() ; - - if(! ops_keyring_read_from_mem(tmp_secring, ops_false, buf)) - { - errString = std::string("(EE) Cannot re-read key from memory!!") ; - return false ; - } - ops_teardown_memory_write(cinfo,buf); // cleanup memory - - // 4 - copy the encrypted private key to the private keyring - - pgpId = RsPgpId(tmp_secring->keys[0].key_id) ; - addNewKeyToOPSKeyring(_secring,tmp_secring->keys[0]) ; - initCertificateInfo(_secret_keyring_map[ pgpId ],&tmp_secring->keys[0],_secring->nkeys-1) ; - -#ifdef DEBUG_PGPHANDLER - RsErr() << "Added new secret key with id " << pgpId.toStdString() << " to secret keyring." ; -#endif - ops_keyring_free(tmp_secring) ; - free(tmp_secring) ; - - // 5 - add key to secret keyring on disk. - - cinfo = NULL ; - std::string secring_path_tmp = _secring_path + ".tmp" ; - - if(RsDirUtil::fileExists(_secring_path) && !RsDirUtil::copyFile(_secring_path,secring_path_tmp)) - { - errString= std::string("Cannot copy secret keyring !! Disk full? Out of disk quota?") ; - return false ; - } - int fd=ops_setup_file_append(&cinfo, secring_path_tmp.c_str()); - - if(!ops_write_transferable_secret_key(key,(unsigned char *)passphrase.c_str(),passphrase.length(),ops_false,cinfo)) - { - errString= std::string("Cannot encode secret key to disk!! Disk full? Out of disk quota?") ; - return false ; - } - ops_teardown_file_write(cinfo,fd) ; - - if(!RsDirUtil::renameFile(secring_path_tmp,_secring_path)) - { - errString= std::string("Cannot rename tmp secret key file ") + secring_path_tmp + " into " + _secring_path +". Disk error?" ; - return false ; - } - - // 6 - copy the public key to the public keyring on disk - - cinfo = NULL ; - std::string pubring_path_tmp = _pubring_path + ".tmp" ; - - if(RsDirUtil::fileExists(_pubring_path) && !RsDirUtil::copyFile(_pubring_path,pubring_path_tmp)) - { - errString= std::string("Cannot encode secret key to disk!! Disk full? Out of disk quota?") ; - return false ; - } - fd=ops_setup_file_append(&cinfo, pubring_path_tmp.c_str()); - - if(!ops_write_transferable_public_key(key, ops_false, cinfo)) - { - errString=std::string("Cannot encode secret key to memory!!") ; - return false ; - } - ops_teardown_file_write(cinfo,fd) ; - - if(!RsDirUtil::renameFile(pubring_path_tmp,_pubring_path)) - { - errString= std::string("Cannot rename tmp public key file ") + pubring_path_tmp + " into " + _pubring_path +". Disk error?" ; - return false ; - } - // 7 - clean - ops_keydata_free(key) ; - - // 8 - re-read the key from the public keyring, and add it to memory. - - _pubring_last_update_time = 0 ; // force update pubring from disk. - locked_syncPublicKeyring() ; - -#ifdef DEBUG_PGPHANDLER - RsErr() << "Added new public key with id " << pgpId.toStdString() << " to public keyring." ; -#endif - - // 9 - Update some flags. - - privateTrustCertificate(pgpId,PGPCertificateInfo::PGP_CERTIFICATE_TRUST_ULTIMATE) ; - - return true ; -} - -std::string OpenPGPSDKHandler::makeRadixEncodedPGPKey(const ops_keydata_t *key,bool include_signatures) -{ - ops_create_info_t* cinfo; - ops_memory_t *buf = NULL ; - ops_setup_memory_write(&cinfo, &buf, 0); - ops_boolean_t armoured = ops_true ; - - if(key->type == OPS_PTAG_CT_PUBLIC_KEY) - { - if(ops_write_transferable_public_key_from_packet_data(key,armoured,cinfo) != ops_true) - return "ERROR: This key cannot be processed by RetroShare because\nDSA certificates are not yet handled." ; - } - else if(key->type == OPS_PTAG_CT_ENCRYPTED_SECRET_KEY) - { - if(ops_write_transferable_secret_key_from_packet_data(key,armoured,cinfo) != ops_true) - return "ERROR: This key cannot be processed by RetroShare because\nDSA certificates are not yet handled." ; - } - else - { - ops_create_info_delete(cinfo); - RsErr() << "Unhandled key type " << key->type ; - return "ERROR: Cannot write key. Unhandled key type. " ; - } - - ops_writer_close(cinfo) ; - - std::string res((char *)ops_memory_get_data(buf),ops_memory_get_length(buf)) ; - ops_teardown_memory_write(cinfo,buf); - - if(!include_signatures) - { - std::string tmp ; - if(PGPKeyManagement::createMinimalKey(res,tmp) ) - res = tmp ; - } - - return res ; -} - -const ops_keydata_t *OpenPGPSDKHandler::locked_getSecretKey(const RsPgpId& id) const -{ - std::map::const_iterator res = _secret_keyring_map.find(id) ; - - if(res == _secret_keyring_map.end()) - return NULL ; - else - return ops_keyring_get_key_by_index(_secring,res->second._key_index) ; -} -const ops_keydata_t *OpenPGPSDKHandler::locked_getPublicKey(const RsPgpId& id,bool stamp_the_key) const -{ - std::map::const_iterator res = _public_keyring_map.find(id) ; - - if(res == _public_keyring_map.end()) - return NULL ; - else - { - if(stamp_the_key) // Should we stamp the key as used? - { - static rstime_t last_update_db_because_of_stamp = 0 ; - rstime_t now = time(NULL) ; - - res->second._time_stamp = now ; - - if(now > last_update_db_because_of_stamp + 3600) // only update database once every hour. No need to do it more often. - { - _trustdb_changed = true ; - last_update_db_because_of_stamp = now ; - } - } - return ops_keyring_get_key_by_index(_pubring,res->second._key_index) ; - } -} - -std::string OpenPGPSDKHandler::SaveCertificateToString(const RsPgpId& id,bool include_signatures) const -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - const ops_keydata_t *key = locked_getPublicKey(id,false) ; - - if(key == NULL) - { - RsErr() << "Cannot output key " << id.toStdString() << ": not found in keyring." ; - return "" ; - } - - return makeRadixEncodedPGPKey(key,include_signatures) ; -} - -bool OpenPGPSDKHandler::exportPublicKey( const RsPgpId& id, unsigned char*& mem_block, size_t& mem_size, bool armoured, bool include_signatures ) const -{ - mem_block = nullptr; mem_size = 0; // clear just in case - - if(armoured) - { - RsErr() << __PRETTY_FUNCTION__ << " should not be used with " - << "armoured=true, because there's a bug in the armoured export" - << " of OPS" ; - print_stacktrace(); - return false; - } - - RS_STACK_MUTEX(pgphandlerMtx); - const ops_keydata_t* key = locked_getPublicKey(id,false); - - if(!key) - { - RsErr() << __PRETTY_FUNCTION__ << " key id: " << id - << " not found in keyring." ; - return false; - } - - ops_create_info_t* cinfo; - ops_memory_t *buf = nullptr; - ops_setup_memory_write(&cinfo, &buf, 0); - - if(ops_write_transferable_public_key_from_packet_data( - key, armoured, cinfo ) != ops_true) - { - RsErr() << __PRETTY_FUNCTION__ << " This key id " << id - << " cannot be processed by RetroShare because DSA certificates" - << " support is not implemented yet." ; - return false; - } - - ops_writer_close(cinfo); - - mem_size = ops_memory_get_length(buf); - mem_block = reinterpret_cast(malloc(mem_size)); - memcpy(mem_block,ops_memory_get_data(buf),mem_size); - - ops_teardown_memory_write(cinfo,buf); - - if(!include_signatures) - { - size_t new_size; - PGPKeyManagement::findLengthOfMinimalKey(mem_block, mem_size, new_size); - mem_size = new_size; - } - - return true; -} - -bool OpenPGPSDKHandler::exportGPGKeyPair(const std::string& filename,const RsPgpId& exported_key_id) const -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - const ops_keydata_t *pubkey = locked_getPublicKey(exported_key_id,false) ; - - if(pubkey == NULL) - { - RsErr() << "Cannot output key " << exported_key_id.toStdString() << ": not found in public keyring." ; - return false ; - } - const ops_keydata_t *seckey = locked_getSecretKey(exported_key_id) ; - - if(seckey == NULL) - { - RsErr() << "Cannot output key " << exported_key_id.toStdString() << ": not found in secret keyring." ; - return false ; - } - - FILE *f = RsDirUtil::rs_fopen(filename.c_str(),"w") ; - if(f == NULL) - { - RsErr() << "Cannot output key " << exported_key_id.toStdString() << ": file " << filename << " cannot be written. Please check for permissions, quotas, disk space." ; - return false ; - } - - fprintf(f,"%s\n", makeRadixEncodedPGPKey(pubkey,true).c_str()) ; - fprintf(f,"%s\n", makeRadixEncodedPGPKey(seckey,true).c_str()) ; - - fclose(f) ; - return true ; -} - -bool OpenPGPSDKHandler::exportGPGKeyPairToString( std::string& data, const RsPgpId& exportedKeyId, bool includeSignatures, std::string& errorMsg ) const -{ - RS_STACK_MUTEX(pgphandlerMtx); - - const ops_keydata_t *pubkey = locked_getPublicKey(exportedKeyId,false); - - if(!pubkey) - { - errorMsg = "Cannot output key " + exportedKeyId.toStdString() + - ": not found in public keyring."; - return false; - } - const ops_keydata_t *seckey = locked_getSecretKey(exportedKeyId); - - if(!seckey) - { - errorMsg = "Cannot output key " + exportedKeyId.toStdString() + - ": not found in secret keyring."; - return false; - } - - data = makeRadixEncodedPGPKey(pubkey, includeSignatures); - data += "\n"; - data += makeRadixEncodedPGPKey(seckey, includeSignatures); - data += "\n"; - return true; -} - -bool OpenPGPSDKHandler::getGPGDetailsFromBinaryBlock(const unsigned char *mem_block,size_t mem_size,RsPgpId& key_id, std::string& name, std::list& signers) const -{ - ops_keyring_t *tmp_keyring = allocateOPSKeyring(); - ops_memory_t *mem = ops_memory_new() ; - ops_memory_add(mem,mem_block,mem_size); - - if(!ops_keyring_read_from_mem(tmp_keyring,ops_false,mem)) - { - ops_keyring_free(tmp_keyring) ; - free(tmp_keyring) ; - ops_memory_release(mem) ; - free(mem) ; - - RsErr() << "Could not read key. Format error?" ; - //error_string = std::string("Could not read key. Format error?") ; - return false ; - } - ops_memory_release(mem) ; - free(mem) ; - //error_string.clear() ; - - if(tmp_keyring->nkeys != 1) - { - RsErr() << "No or incomplete/invalid key in supplied pgp block." ; - return false ; - } - if(tmp_keyring->keys[0].uids == NULL) - { - RsErr() << "No uid in supplied key." ; - return false ; - } - - key_id = RsPgpId(tmp_keyring->keys[0].key_id) ; - name = std::string((char *)tmp_keyring->keys[0].uids[0].user_id) ; - - // now parse signatures. - // - ops_validate_result_t* result=(ops_validate_result_t*)ops_mallocz(sizeof *result); - ops_boolean_t res ; - - { - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - res = ops_validate_key_signatures(result,&tmp_keyring->keys[0],_pubring,cb_get_passphrase) ; - } - - if(res == ops_false) - RsErr() << "(WW) Error in OpenPGPSDKHandler::validateAndUpdateSignatures(). Validation failed for at least some signatures." ; - - // also add self-signature if any (there should be!). - // - res = ops_validate_key_signatures(result,&tmp_keyring->keys[0],tmp_keyring,cb_get_passphrase) ; - - if(res == ops_false) - RsErr() << "(WW) Error in OpenPGPSDKHandler::validateAndUpdateSignatures(). Validation failed for at least some signatures." ; - - // Parse signers. - // - - std::set signers_set ; // Use a set to remove duplicates. - - if(result != NULL) - for(size_t i=0;ivalid_count;++i) - signers_set.insert(RsPgpId(result->valid_sigs[i].signer_id)) ; - - ops_validate_result_free(result) ; - - ops_keyring_free(tmp_keyring) ; - free(tmp_keyring) ; - - // write to the output variable - - signers.clear() ; - - for(std::set::const_iterator it(signers_set.begin());it!=signers_set.end();++it) - signers.push_back(*it) ; - - return true ; -} - -bool OpenPGPSDKHandler::importGPGKeyPair(const std::string& filename,RsPgpId& imported_key_id,std::string& import_error) -{ - import_error = "" ; - - // 1 - Test for file existance - // - FILE *ftest = RsDirUtil::rs_fopen(filename.c_str(),"r") ; - - if(ftest == NULL) - { - import_error = "Cannot open file " + filename + " for read. Please check access permissions." ; - return false ; - } - - fclose(ftest) ; - - // 2 - Read keyring from supplied file. - // - ops_keyring_t *tmp_keyring = allocateOPSKeyring(); - - if(ops_false == ops_keyring_read_from_file(tmp_keyring, ops_true, filename.c_str())) - { - import_error = "OpenPGPSDKHandler::readKeyRing(): cannot read key file. File corrupted?" ; - free(tmp_keyring); - return false ; - } - - return checkAndImportKeyPair(tmp_keyring, imported_key_id, import_error); -} - -bool OpenPGPSDKHandler::importGPGKeyPairFromString(const std::string &data, RsPgpId &imported_key_id, std::string &import_error) -{ - import_error = "" ; - - ops_memory_t* mem = ops_memory_new(); - ops_memory_add(mem, (unsigned char*)data.data(), data.length()); - - ops_keyring_t *tmp_keyring = allocateOPSKeyring(); - - if(ops_false == ops_keyring_read_from_mem(tmp_keyring, ops_true, mem)) - { - import_error = "OpenPGPSDKHandler::importGPGKeyPairFromString(): cannot parse key data" ; - free(tmp_keyring); - return false ; - } - return checkAndImportKeyPair(tmp_keyring, imported_key_id, import_error); -} - -bool OpenPGPSDKHandler::checkAndImportKeyPair(ops_keyring_t *tmp_keyring, RsPgpId &imported_key_id, std::string &import_error) -{ - if(tmp_keyring == 0) - { - import_error = "OpenPGPSDKHandler::checkAndImportKey(): keyring is null" ; - return false; - } - - if(tmp_keyring->nkeys != 2) - { - import_error = "OpenPGPSDKHandler::importKeyPair(): file does not contain a valid keypair." ; - if(tmp_keyring->nkeys > 2) - import_error += "\nMake sure that your key is a RSA key (DSA is not yet supported) and does not contain subkeys (not supported yet)."; - return false ; - } - - // 3 - Test that keyring contains a valid keypair. - // - const ops_keydata_t *pubkey = NULL ; - const ops_keydata_t *seckey = NULL ; - - if(tmp_keyring->keys[0].type == OPS_PTAG_CT_PUBLIC_KEY) - pubkey = &tmp_keyring->keys[0] ; - else if(tmp_keyring->keys[0].type == OPS_PTAG_CT_ENCRYPTED_SECRET_KEY) - seckey = &tmp_keyring->keys[0] ; - else - { - import_error = "Unrecognised key type in key file for key #0. Giving up." ; - RsErr() << "Unrecognised key type " << tmp_keyring->keys[0].type << " in key file for key #0. Giving up." ; - return false ; - } - if(tmp_keyring->keys[1].type == OPS_PTAG_CT_PUBLIC_KEY) - pubkey = &tmp_keyring->keys[1] ; - else if(tmp_keyring->keys[1].type == OPS_PTAG_CT_ENCRYPTED_SECRET_KEY) - seckey = &tmp_keyring->keys[1] ; - else - { - import_error = "Unrecognised key type in key file for key #1. Giving up." ; - RsErr() << "Unrecognised key type " << tmp_keyring->keys[1].type << " in key file for key #1. Giving up." ; - return false ; - } - - if(pubkey == nullptr || seckey == nullptr || pubkey == seckey) - { - import_error = "File does not contain a public and a private key. Sorry." ; - return false ; - } - if(memcmp( pubkey->fingerprint.fingerprint, - seckey->fingerprint.fingerprint, - RsPgpFingerprint::SIZE_IN_BYTES ) != 0) - { - import_error = "Public and private keys do nt have the same fingerprint. Sorry!" ; - return false ; - } - if(pubkey->key.pkey.version != 4) - { - import_error = "Public key is not version 4. Rejected!" ; - return false ; - } - - // 4 - now check self-signature for this keypair. For this we build a dummy keyring containing only the key. - // - ops_validate_result_t *result=(ops_validate_result_t*)ops_mallocz(sizeof *result); - - ops_keyring_t dummy_keyring ; - dummy_keyring.nkeys=1 ; - dummy_keyring.nkeys_allocated=1 ; - dummy_keyring.keys=const_cast(pubkey) ; - - ops_validate_key_signatures(result, const_cast(pubkey), &dummy_keyring, cb_get_passphrase) ; - - // Check that signatures contain at least one certification from the user id. - // - bool found = false ; - - for(uint32_t i=0;ivalid_count;++i) - if(!memcmp( - static_cast(result->valid_sigs[i].signer_id), - pubkey->key_id, - RsPgpId::SIZE_IN_BYTES )) - { - found = true ; - break ; - } - - if(!found) - { - import_error = "Cannot validate self signature for the imported key. Sorry." ; - return false ; - } - ops_validate_result_free(result); - - if(!RsDiscSpace::checkForDiscSpace(RS_PGP_DIRECTORY)) - { - import_error = std::string("(EE) low disc space in pgp directory. Can't write safely to keyring.") ; - return false ; - } - // 5 - All test passed. Adding key to keyring. - // - { - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - imported_key_id = RsPgpId(pubkey->key_id) ; - - if(locked_getSecretKey(imported_key_id) == NULL) - { - RsStackFileLock flck(_pgp_lock_filename) ; // lock access to PGP directory. - - ops_create_info_t *cinfo = NULL ; - - // Make a copy of the secret keyring - // - std::string secring_path_tmp = _secring_path + ".tmp" ; - if(RsDirUtil::fileExists(_secring_path) && !RsDirUtil::copyFile(_secring_path,secring_path_tmp)) - { - import_error = "(EE) Cannot write secret key to disk!! Disk full? Out of disk quota. Keyring will be left untouched." ; - return false ; - } - - // Append the new key - - int fd=ops_setup_file_append(&cinfo, secring_path_tmp.c_str()); - - if(!ops_write_transferable_secret_key_from_packet_data(seckey,ops_false,cinfo)) - { - import_error = "(EE) Cannot encode secret key to disk!! Disk full? Out of disk quota?" ; - return false ; - } - ops_teardown_file_write(cinfo,fd) ; - - // Rename the new keyring to overwrite the old one. - // - if(!RsDirUtil::renameFile(secring_path_tmp,_secring_path)) - { - import_error = " (EE) Cannot move temp file " + secring_path_tmp + ". Bad write permissions?" ; - return false ; - } - - addNewKeyToOPSKeyring(_secring,*seckey) ; - initCertificateInfo(_secret_keyring_map[ imported_key_id ],seckey,_secring->nkeys-1) ; - } - else - import_error = "Private key already exists! Not importing it again." ; - - if(locked_addOrMergeKey(_pubring,_public_keyring_map,pubkey)) - _pubring_changed = true ; - } - - // 6 - clean - // - ops_keyring_free(tmp_keyring) ; - free(tmp_keyring); - - // write public key to disk - syncDatabase(); - - return true ; -} - -void OpenPGPSDKHandler::addNewKeyToOPSKeyring(ops_keyring_t *kr,const ops_keydata_t& key) -{ - if(kr->nkeys >= kr->nkeys_allocated) - { - kr->keys = (ops_keydata_t *)realloc(kr->keys,(kr->nkeys+1)*sizeof(ops_keydata_t)) ; - kr->nkeys_allocated = kr->nkeys+1; - } - memset(&kr->keys[kr->nkeys],0,sizeof(ops_keydata_t)) ; - ops_keydata_copy(&kr->keys[kr->nkeys],&key) ; - kr->nkeys++ ; -} - -bool OpenPGPSDKHandler::LoadCertificateFromBinaryData(const unsigned char *data,uint32_t data_len,RsPgpId& id,std::string& error_string) -{ - return LoadCertificate(data,data_len,ops_false,id,error_string); -} - -bool OpenPGPSDKHandler::LoadCertificateFromString(const std::string& pgp_cert,RsPgpId& id,std::string& error_string) -{ - return LoadCertificate((unsigned char*)(pgp_cert.c_str()),pgp_cert.length(),ops_true,id,error_string); -} - -bool OpenPGPSDKHandler::LoadCertificate(const unsigned char *data,uint32_t data_len,bool armoured,RsPgpId& id,std::string& error_string) -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. -#ifdef DEBUG_PGPHANDLER - RsErr() << "Reading new key from string: " ; -#endif - - ops_keyring_t *tmp_keyring = allocateOPSKeyring(); - ops_memory_t *mem = ops_memory_new() ; - ops_memory_add(mem,data,data_len) ; - - if(!ops_keyring_read_from_mem(tmp_keyring,armoured,mem)) - { - ops_keyring_free(tmp_keyring) ; - free(tmp_keyring) ; - ops_memory_release(mem) ; - free(mem) ; - - RsErr() << "Could not read key. Format error?" ; - error_string = std::string("Could not read key. Format error?") ; - return false ; - } - ops_memory_release(mem) ; - free(mem) ; - error_string.clear() ; - - // Check that there is exactly one key in this data packet. - // - if(tmp_keyring->nkeys != 1) - { - RsErr() << "Loaded certificate contains more than one PGP key. This is not allowed." ; - error_string = "Loaded certificate contains more than one PGP key. This is not allowed." ; - return false ; - } - - const ops_keydata_t *keydata = ops_keyring_get_key_by_index(tmp_keyring,0); - - // Check that the key is a version 4 key - // - if(keydata->key.pkey.version != 4) - { - error_string = "Public key is not version 4. Rejected!" ; - RsErr() << "Received a key with unhandled version number (" << keydata->key.pkey.version << ")" ; - return false ; - } - - // Check that the key is correctly self-signed. - // - ops_validate_result_t* result=(ops_validate_result_t*)ops_mallocz(sizeof *result); - - ops_validate_key_signatures(result,keydata,tmp_keyring,cb_get_passphrase) ; - - bool found = false ; - - for(uint32_t i=0;ivalid_count;++i) - if(!memcmp( - static_cast(result->valid_sigs[i].signer_id), - keydata->key_id, - RsPgpId::SIZE_IN_BYTES )) - { - found = true ; - break ; - } - - if(!found) - { - error_string = "This key is not self-signed. This is required by Retroshare." ; - RsErr() << "This key is not self-signed. This is required by Retroshare." ; - ops_validate_result_free(result); - return false ; - } - ops_validate_result_free(result); - -#ifdef DEBUG_PGPHANDLER - RsErr() << " Key read correctly: " ; - ops_keyring_list(tmp_keyring) ; -#endif - - int i=0 ; - - while( (keydata = ops_keyring_get_key_by_index(tmp_keyring,i++)) != NULL ) - if(locked_addOrMergeKey(_pubring,_public_keyring_map,keydata)) - { - _pubring_changed = true ; -#ifdef DEBUG_PGPHANDLER - RsErr() << " Added the key in the main public keyring." ; -#endif - } - else - RsErr() << "Key already in public keyring." ; - - if(tmp_keyring->nkeys > 0) - id = RsPgpId(tmp_keyring->keys[0].key_id) ; - else - return false ; - - ops_keyring_free(tmp_keyring) ; - free(tmp_keyring) ; - - _pubring_changed = true ; - - return true ; -} - -bool OpenPGPSDKHandler::locked_addOrMergeKey(ops_keyring_t *keyring,std::map& kmap,const ops_keydata_t *keydata) -{ - bool ret = false ; - RsPgpId id(keydata->key_id) ; - -#ifdef DEBUG_PGPHANDLER - RsErr() << "AddOrMergeKey():" ; - RsErr() << " id: " << id.toStdString() ; -#endif - - // See if the key is already in the keyring - const ops_keydata_t *existing_key = NULL; - std::map::const_iterator res = kmap.find(id) ; - - // Checks that - // - the key is referenced by keyid - // - the map is initialized - // - the fingerprint matches! - // - if(res == kmap.end() || (existing_key = ops_keyring_get_key_by_index(keyring,res->second._key_index)) == NULL) - { -#ifdef DEBUG_PGPHANDLER - RsErr() << " Key is new. Adding it to keyring" ; -#endif - addNewKeyToOPSKeyring(keyring,*keydata) ; // the key is new. - initCertificateInfo(kmap[id],keydata,keyring->nkeys-1) ; - existing_key = &(keyring->keys[keyring->nkeys-1]) ; - ret = true ; - } - else - { - if(memcmp( existing_key->fingerprint.fingerprint, - keydata->fingerprint.fingerprint, - RsPgpFingerprint::SIZE_IN_BYTES )) - { - RsErr() << "(EE) attempt to merge key with identical id, but different fingerprint!" ; - return false ; - } - -#ifdef DEBUG_PGPHANDLER - RsErr() << " Key exists. Merging signatures." ; -#endif - ret = mergeKeySignatures(const_cast(existing_key),keydata) ; - - if(ret) - initCertificateInfo(kmap[id],existing_key,res->second._key_index) ; - } - - if(ret) - { - validateAndUpdateSignatures(kmap[id],existing_key) ; - kmap[id]._time_stamp = time(NULL) ; - } - - return ret ; -} - -bool OpenPGPSDKHandler::encryptTextToFile(const RsPgpId& key_id,const std::string& text,const std::string& outfile) -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - const ops_keydata_t *public_key = locked_getPublicKey(key_id,true) ; - - if(public_key == NULL) - { - RsErr() << "Cannot get public key of id " << key_id.toStdString() ; - return false ; - } - - if(public_key->type != OPS_PTAG_CT_PUBLIC_KEY) - { - RsErr() << "OpenPGPSDKHandler::encryptTextToFile(): ERROR: supplied id did not return a public key!" ; - return false ; - } - - std::string outfile_tmp = outfile + ".tmp" ; - - ops_create_info_t *info; - int fd = ops_setup_file_write(&info, outfile_tmp.c_str(), ops_true); - - if (fd < 0) - { - RsErr() << "OpenPGPSDKHandler::encryptTextToFile(): ERROR: Cannot write to " << outfile_tmp ; - return false ; - } - - if(!ops_encrypt_stream(info, public_key, NULL, ops_false, ops_true)) - { - RsErr() << "OpenPGPSDKHandler::encryptTextToFile(): ERROR: encryption failed." ; - return false ; - } - - ops_write(text.c_str(), text.length(), info); - ops_teardown_file_write(info, fd); - - if(!RsDirUtil::renameFile(outfile_tmp,outfile)) - { - RsErr() << "OpenPGPSDKHandler::encryptTextToFile(): ERROR: Cannot rename " + outfile_tmp + " to " + outfile + ". Disk error?" ; - return false ; - } - - return true ; -} - -bool OpenPGPSDKHandler::encryptDataBin(const RsPgpId& key_id,const void *data, const uint32_t len, unsigned char *encrypted_data, unsigned int *encrypted_data_len) -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - const ops_keydata_t *public_key = locked_getPublicKey(key_id,true) ; - - if(public_key == NULL) - { - RsErr() << "Cannot get public key of id " << key_id.toStdString() ; - return false ; - } - - if(public_key->type != OPS_PTAG_CT_PUBLIC_KEY) - { - RsErr() << "OpenPGPSDKHandler::encryptTextToFile(): ERROR: supplied id did not return a public key!" ; - return false ; - } - if(public_key->key.pkey.algorithm != OPS_PKA_RSA) - { - RsErr() << "OpenPGPSDKHandler::encryptTextToFile(): ERROR: supplied key id " << key_id.toStdString() << " is not an RSA key (DSA for instance, is not supported)!" ; - return false ; - } - ops_create_info_t *info; - ops_memory_t *buf = NULL ; - ops_setup_memory_write(&info, &buf, 0); - bool res = true; - - if(!ops_encrypt_stream(info, public_key, NULL, ops_false, ops_false)) - { - RsErr() << "Encryption failed." ; - res = false ; - } - - ops_write(data,len,info); - ops_writer_close(info); - ops_create_info_delete(info); - - int tlen = ops_memory_get_length(buf) ; - - if( (int)*encrypted_data_len >= tlen) - { - if(res) - { - memcpy(encrypted_data,ops_memory_get_data(buf),tlen) ; - *encrypted_data_len = tlen ; - res = true ; - } - } - else - { - RsErr() << "Not enough room to fit encrypted data. Size given=" << *encrypted_data_len << ", required=" << tlen ; - res = false ; - } - - ops_memory_release(buf) ; - free(buf) ; - - return res ; -} - -bool OpenPGPSDKHandler::decryptDataBin(const RsPgpId& /*key_id*/,const void *encrypted_data, const uint32_t encrypted_len, unsigned char *data, unsigned int *data_len) -{ - int out_length ; - unsigned char *out ; - ops_boolean_t res = ops_decrypt_memory((const unsigned char *)encrypted_data,encrypted_len,&out,&out_length,_secring,ops_false,cb_get_passphrase) ; - - if(*data_len < (unsigned int)out_length) - { - RsErr() << "Not enough room to store decrypted data! Please give more."; - return false ; - } - - *data_len = (unsigned int)out_length ; - memcpy(data,out,out_length) ; - free(out) ; - - return (bool)res ; -} - -bool OpenPGPSDKHandler::decryptTextFromFile(const RsPgpId&,std::string& text,const std::string& inputfile) -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - unsigned char *out_buf = NULL ; - std::string buf ; - - FILE *f = RsDirUtil::rs_fopen(inputfile.c_str(),"rb") ; - - if (f == NULL) - { - RsErr() << "Cannot open file " << inputfile << " for read." ; - return false; - } - - int c ; - while( (c = fgetc(f))!= EOF) - buf += (unsigned char)c; - - fclose(f) ; - -#ifdef DEBUG_PGPHANDLER - RsErr() << "OpenPGPSDKHandler::decryptTextFromFile: read a file of length " << std::dec << buf.length() ; - RsErr() << "buf=\"" << buf << "\"" ; -#endif - - int out_length ; - ops_boolean_t res = ops_decrypt_memory((const unsigned char *)buf.c_str(),buf.length(),&out_buf,&out_length,_secring,ops_true,cb_get_passphrase) ; - - text = std::string((char *)out_buf,out_length) ; - free (out_buf); - return (bool)res ; -} - -bool OpenPGPSDKHandler::SignDataBin(const RsPgpId& id,const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen,bool use_raw_signature, std::string reason /* = "" */) -{ - // need to find the key and to decrypt it. - ops_keydata_t *key = nullptr; - { - RS_STACK_MUTEX(pgphandlerMtx); // lock access to PGP memory structures. - const ops_keydata_t *test_key = locked_getSecretKey(id); - if(!test_key) - { - RsErr("Cannot sign: no secret key with id ", id.toStdString() ); - return false ; - } - // Copy key as it may take time for user to respond. - key = ops_keydata_new(); - ops_keydata_copy(key, test_key); - } - - std::string uid_hint ; - if(key->nuids > 0) - uid_hint = std::string((const char *)key->uids[0].user_id) ; - uid_hint += "(" + RsPgpId(key->key_id).toStdString()+")" ; - -#ifdef DEBUG_PGPHANDLER - ops_fingerprint_t f ; - ops_fingerprint(&f,&key->key.pkey) ; - - PGPFingerprintType fp(f.fingerprint) ; -#endif - - bool last_passwd_was_wrong = false ; - ops_secret_key_t *secret_key = nullptr ; - - for(int i=0;i<3;++i) - { - bool cancelled =false; - // Need to be outside of mutex to not block GUI. - std::string passphrase = _passphrase_callback(NULL,reason.c_str(),uid_hint.c_str(),"Please enter password for encrypting your key : ",last_passwd_was_wrong,&cancelled) ;//TODO reason - - secret_key = ops_decrypt_secret_key_from_data(key,passphrase.c_str()) ; - - if(cancelled) - { - RsErr() << "Key entering cancelled" ; - ops_keydata_free(key); - return false ; - } - if(secret_key) - break ; - - RsErr() << "Key decryption went wrong. Wrong password?" ; - last_passwd_was_wrong = true ; - } - // No more need of key, free it. - ops_keydata_free(key); - - if(!secret_key) - { - RsErr() << "Could not obtain secret key. Signature cancelled." ; - return false ; - } - - // then do the signature. - - RS_STACK_MUTEX(pgphandlerMtx); // lock access to PGP memory structures. - - ops_boolean_t not_raw = !use_raw_signature ; -#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_002 - ops_memory_t *memres = ops_sign_buf(data,len,OPS_SIG_BINARY,OPS_HASH_SHA256,secret_key,ops_false,ops_false,not_raw,not_raw) ; -#else - ops_memory_t *memres = ops_sign_buf(data,len,OPS_SIG_BINARY,OPS_HASH_SHA1,secret_key,ops_false,ops_false,not_raw,not_raw) ; -#endif - - if(!memres) - return false ; - - bool res ; - uint32_t slen = (uint32_t)ops_memory_get_length(memres); - - if(*signlen >= slen) - { - *signlen = slen ; - - memcpy(sign,ops_memory_get_data(memres),*signlen) ; - res = true ; - } - else - { - RsErr() << "(EE) memory chunk is not large enough for signature packet. Requred size: " << slen << " bytes." ; - res = false ; - } - - ops_memory_release(memres) ; - free(memres) ; - ops_secret_key_free(secret_key) ; - free(secret_key) ; - -#ifdef DEBUG_PGPHANDLER - RsErr() << "Signed with fingerprint " << fp.toStdString() << ", length " << std::dec << *signlen << ", literal data length = " << len ; - RsErr() << "Signature body: " ; - hexdump( (unsigned char *)data, len) ; - RsErr() ; - RsErr() << "Data: " ; - hexdump( (unsigned char *)sign,*signlen) ; - RsErr() ; -#endif - return res ; -} - -bool OpenPGPSDKHandler::privateSignCertificate(const RsPgpId& ownId,const RsPgpId& id_of_key_to_sign) -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - ops_keydata_t *key_to_sign = const_cast(locked_getPublicKey(id_of_key_to_sign,true)) ; - - if(key_to_sign == NULL) - { - RsErr() << "Cannot sign: no public key with id " << id_of_key_to_sign.toStdString() ; - return false ; - } - - // 1 - get decrypted secret key - // - const ops_keydata_t *skey = locked_getSecretKey(ownId) ; - - if(!skey) - { - RsErr() << "Cannot sign: no secret key with id " << ownId.toStdString() ; - return false ; - } - const ops_keydata_t *pkey = locked_getPublicKey(ownId,true) ; - - if(!pkey) - { - RsErr() << "Cannot sign: no public key with id " << ownId.toStdString() ; - return false ; - } - - bool cancelled = false; - std::string passphrase = _passphrase_callback(NULL,"",RsPgpId(skey->key_id).toStdString().c_str(),"Please enter passwd for encrypting your key : ",false,&cancelled) ; - - ops_secret_key_t *secret_key = ops_decrypt_secret_key_from_data(skey,passphrase.c_str()) ; - - if(cancelled) - { - RsErr() << "Key cancelled by used." ; - return false ; - } - if(!secret_key) - { - RsErr() << "Key decryption went wrong. Wrong passwd?" ; - return false ; - } - - // 2 - then do the signature. - - if(!ops_sign_key(key_to_sign,pkey->key_id,secret_key)) - { - RsErr() << "Key signature went wrong. Wrong passwd?" ; - return false ; - } - - // 3 - free memory - // - ops_secret_key_free(secret_key) ; - free(secret_key) ; - - _pubring_changed = true ; - - // 4 - update signatures. - // - PGPCertificateInfo& cert(_public_keyring_map[ id_of_key_to_sign ]) ; - validateAndUpdateSignatures(cert,key_to_sign) ; - cert._flags |= PGPCertificateInfo::PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE ; - - return true ; -} - -bool OpenPGPSDKHandler::getKeyFingerprint(const RsPgpId& id, RsPgpFingerprint& fp) const -{ - RS_STACK_MUTEX(pgphandlerMtx); - - const ops_keydata_t *key = locked_getPublicKey(id,false) ; - - if(!key) return false; - - ops_fingerprint_t f ; - ops_fingerprint(&f,&key->key.pkey) ; - - fp = RsPgpFingerprint::fromBufferUnsafe(f.fingerprint); - - return true ; -} - -bool OpenPGPSDKHandler::VerifySignBin(const void *literal_data, uint32_t literal_data_length, unsigned char *sign, unsigned int sign_len, const PGPFingerprintType& key_fingerprint) -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - RsPgpId id = RsPgpId(key_fingerprint.toByteArray() + PGPFingerprintType::SIZE_IN_BYTES - RsPgpId::SIZE_IN_BYTES) ; - const ops_keydata_t *key = locked_getPublicKey(id,true) ; - - if(key == NULL) - { - RsErr() << "No key returned by fingerprint " << key_fingerprint.toStdString() << ", and ID " << id.toStdString() << ", signature verification failed!" ; - return false ; - } - - // Check that fingerprint is the same. - const ops_public_key_t *pkey = &key->key.pkey ; - ops_fingerprint_t fp ; - ops_fingerprint(&fp,pkey) ; - - if(key_fingerprint != PGPFingerprintType(fp.fingerprint)) - { - RsErr() << "Key fingerprint does not match " << key_fingerprint.toStdString() << ", for ID " << id.toStdString() << ", signature verification failed!" ; - return false ; - } - -#ifdef DEBUG_PGPHANDLER - RsErr() << "Verifying signature from fingerprint " << key_fingerprint.toStdString() << ", length " << std::dec << sign_len << ", literal data length = " << literal_data_length ; - RsErr() << "Signature body: " ; - hexdump( (unsigned char *)sign,sign_len) ; - RsErr() ; - RsErr() << "Signed data: " ; - hexdump( (unsigned char *)literal_data, literal_data_length) ; - RsErr() ; -#endif - - return ops_validate_detached_signature(literal_data,literal_data_length,sign,sign_len,key) ; -} - -// Lexicographic order on signature packets -// -bool operator<(const ops_packet_t& p1,const ops_packet_t& p2) -{ - if(p1.length < p2.length) - return true ; - if(p1.length > p2.length) - return false ; - - for(uint32_t i=0;i p2.raw[i]) - return false ; - } - return false ; -} - -bool OpenPGPSDKHandler::mergeKeySignatures(ops_keydata_t *dst,const ops_keydata_t *src) -{ - // First sort all signatures into lists to see which is new, which is not new - -#ifdef DEBUG_PGPHANDLER - RsErr() << "Merging signatures for key " << RsPgpId(dst->key_id).toStdString() ; -#endif - std::set dst_packets ; - - for(uint32_t i=0;inpackets;++i) dst_packets.insert(dst->packets[i]) ; - - std::set to_add ; - - for(uint32_t i=0;inpackets;++i) - if(dst_packets.find(src->packets[i]) == dst_packets.end()) - { - uint8_t tag ; - uint32_t length ; - unsigned char *tmp_data = src->packets[i].raw ; // put it in a tmp variable because read_packetHeader() will modify it!! - - PGPKeyParser::read_packetHeader(tmp_data,tag,length) ; - - if(tag == PGPKeyParser::PGP_PACKET_TAG_SIGNATURE) - to_add.insert(src->packets[i]) ; -#ifdef DEBUG_PGPHANDLER - else - RsErr() << " Packet with tag 0x" << std::hex << (int)(src->packets[i].raw[0]) << std::dec << " not merged, because it is not a signature." ; -#endif - } - - for(std::set::const_iterator it(to_add.begin());it!=to_add.end();++it) - { -#ifdef DEBUG_PGPHANDLER - RsErr() << " Adding packet with tag 0x" << std::hex << (int)(*it).raw[0] << std::dec ; -#endif - ops_add_packet_to_keydata(dst,&*it) ; - } - return to_add.size() > 0 ; -} - -bool OpenPGPSDKHandler::syncDatabase() -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - RsStackFileLock flck(_pgp_lock_filename) ; // lock access to PGP directory. - -#ifdef DEBUG_PGPHANDLER - RsErr() << "Sync-ing keyrings." ; -#endif - locked_syncPublicKeyring() ; - //locked_syncSecretKeyring() ; - - // Now sync the trust database as well. - // - locked_syncTrustDatabase() ; - -#ifdef DEBUG_PGPHANDLER - RsErr() << "Done. " ; -#endif - return true ; -} - -bool OpenPGPSDKHandler::locked_syncPublicKeyring() -{ - struct stat64 buf ; -#ifdef WINDOWS_SYS - std::wstring wfullname; - librs::util::ConvertUtf8ToUtf16(_pubring_path, wfullname); - if(-1 == _wstati64(wfullname.c_str(), &buf)) -#else - if(-1 == stat64(_pubring_path.c_str(), &buf)) -#endif - { - RsErr() << "OpenPGPSDKHandler::syncDatabase(): can't stat file " << _pubring_path << ". Can't sync public keyring." ; - buf.st_mtime = 0; - } - - if(_pubring_last_update_time < buf.st_mtime) - { - RsErr() << "Detected change on disk of public keyring. Merging!" << std::endl ; - - locked_mergeKeyringFromDisk(_pubring,_public_keyring_map,_pubring_path) ; - _pubring_last_update_time = buf.st_mtime ; - } - - // Now check if the pubring was locally modified, which needs saving it again - if(_pubring_changed && RsDiscSpace::checkForDiscSpace(RS_PGP_DIRECTORY)) - { - std::string tmp_keyring_file = _pubring_path + ".tmp" ; - - RsErr() << "Local changes in public keyring. Writing to disk..." ; - if(!ops_write_keyring_to_file(_pubring,ops_false,tmp_keyring_file.c_str(),ops_true)) - { - RsErr() << "Cannot write public keyring tmp file. Disk full? Disk quota exceeded?" ; - return false ; - } - if(!RsDirUtil::renameFile(tmp_keyring_file,_pubring_path)) - { - RsErr() << "Cannot rename tmp pubring file " << tmp_keyring_file << " into actual pubring file " << _pubring_path << ". Check writing permissions?!?" ; - return false ; - } - - RsErr() << "Done." ; - _pubring_last_update_time = time(NULL) ; // should we get this value from the disk instead?? - _pubring_changed = false ; - } - return true ; -} - -void OpenPGPSDKHandler::locked_mergeKeyringFromDisk(ops_keyring_t *keyring, - std::map& kmap, - const std::string& keyring_file) -{ -#ifdef DEBUG_PGPHANDLER - RsErr() << "Merging keyring " << keyring_file << " from disk to memory." ; -#endif - - // 1 - load keyring into a temporary keyring list. - ops_keyring_t *tmp_keyring = OpenPGPSDKHandler::allocateOPSKeyring() ; - - if(ops_false == ops_keyring_read_from_file(tmp_keyring, false, keyring_file.c_str())) - { - RsErr() << "OpenPGPSDKHandler::locked_mergeKeyringFromDisk(): cannot read keyring. File corrupted?" ; - ops_keyring_free(tmp_keyring) ; - return ; - } - - // 2 - load new keys and merge existing key signatures - - for(int i=0;inkeys;++i) - locked_addOrMergeKey(keyring,kmap,&tmp_keyring->keys[i]) ;// we dont' account for the return value. This is disk merging, not local changes. - - // 4 - clean - ops_keyring_free(tmp_keyring) ; -} - -bool OpenPGPSDKHandler::removeKeysFromPGPKeyring(const std::set& keys_to_remove,std::string& backup_file,uint32_t& error_code) -{ - // 1 - lock everything. - // - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - RsStackFileLock flck(_pgp_lock_filename) ; // lock access to PGP directory. - - error_code = PGP_KEYRING_REMOVAL_ERROR_NO_ERROR ; - - for(std::set::const_iterator it(keys_to_remove.begin());it!=keys_to_remove.end();++it) - if(locked_getSecretKey(*it) != NULL) - { - RsErr() << "(EE) OpenPGPSDKHandler:: can't remove key " << (*it).toStdString() << " since its shared by a secret key! Operation cancelled." ; - error_code = PGP_KEYRING_REMOVAL_ERROR_CANT_REMOVE_SECRET_KEYS ; - return false ; - } - - // 2 - sync everything. - // - locked_syncPublicKeyring() ; - - // 3 - make a backup of the public keyring - // - char template_name[_pubring_path.length()+8] ; - sprintf(template_name,"%s.XXXXXX",_pubring_path.c_str()) ; - -#if defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K8 - int fd_keyring_backup(mkstemp(template_name)); - if (fd_keyring_backup == -1) -#else - if(mktemp(template_name) == NULL) -#endif - { - RsErr() << "OpenPGPSDKHandler::removeKeysFromPGPKeyring(): cannot create keyring backup file. Giving up." ; - error_code = PGP_KEYRING_REMOVAL_ERROR_CANNOT_CREATE_BACKUP ; - return false ; - } -#if defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K8 - close(fd_keyring_backup); // TODO: keep the file open and use the fd -#endif - - if(!ops_write_keyring_to_file(_pubring,ops_false,template_name,ops_true)) - { - RsErr() << "OpenPGPSDKHandler::removeKeysFromPGPKeyring(): cannot write keyring backup file. Giving up." ; - error_code = PGP_KEYRING_REMOVAL_ERROR_CANNOT_WRITE_BACKUP ; - return false ; - } - backup_file = std::string(template_name,_pubring_path.length()+7) ; - - RsErr() << "Keyring was backed up to file " << backup_file ; - - // Remove keys from the keyring, and update the keyring map. - // - for(std::set::const_iterator it(keys_to_remove.begin());it!=keys_to_remove.end();++it) - { - if(locked_getSecretKey(*it) != NULL) - { - RsErr() << "(EE) OpenPGPSDKHandler:: can't remove key " << (*it).toStdString() << " since its shared by a secret key!" ; - continue ; - } - - std::map::iterator res = _public_keyring_map.find(*it) ; - - if(res == _public_keyring_map.end()) - { - RsErr() << "(EE) OpenPGPSDKHandler:: can't remove key " << (*it).toStdString() << " from keyring: key not found." ; - continue ; - } - - if(res->second._key_index >= (unsigned int)_pubring->nkeys || RsPgpId(_pubring->keys[res->second._key_index].key_id) != *it) - { - RsErr() << "(EE) OpenPGPSDKHandler:: can't remove key " << (*it).toStdString() << ". Inconsistency found." ; - error_code = PGP_KEYRING_REMOVAL_ERROR_DATA_INCONSISTENCY ; - return false ; - } - - // Move the last key to the freed place. This deletes the key in place. - // - ops_keyring_remove_key(_pubring,res->second._key_index) ; - - // Erase the info from the keyring map. - // - _public_keyring_map.erase(res) ; - - // now update all indices back. This internal look is very costly, but it avoids deleting the wrong keys, since the keyring structure is - // changed by ops_keyring_remove_key and therefore indices don't point to the correct location anymore. - - int i=0 ; - const ops_keydata_t *keydata ; - while( (keydata = ops_keyring_get_key_by_index(_pubring,i)) != NULL ) - { - PGPCertificateInfo& cert(_public_keyring_map[ RsPgpId(keydata->key_id) ]) ; - cert._key_index = i ; - ++i ; - } - } - - // Everything went well, sync back the keyring on disk - - _pubring_changed = true ; - _trustdb_changed = true ; - - locked_syncPublicKeyring() ; - locked_syncTrustDatabase() ; - - return true ; -} diff --git a/libretroshare/src/pgp/openpgpsdkhandler.h b/libretroshare/src/pgp/openpgpsdkhandler.h deleted file mode 100644 index 8aff1459b..000000000 --- a/libretroshare/src/pgp/openpgpsdkhandler.h +++ /dev/null @@ -1,116 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pgp: pgphandler.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include -#include - -#include "util/rsthreads.h" -#include "pgp/pgphandler.h" -#include "retroshare/rstypes.h" - -extern "C" { - // we should make sure later on to get rid of these structures in the .h - #include "openpgpsdk/keyring.h" -} - -/// This class offer an abstract pgp handler to be used in RetroShare. -class OpenPGPSDKHandler: public PGPHandler -{ -public: - OpenPGPSDKHandler( const std::string& path_to_public_keyring, - const std::string& path_to_secret_keyring, - const std::string& path_to_trust_database, - const std::string& pgp_lock_file) ; - - virtual ~OpenPGPSDKHandler() ; - - //================================================================================================// - // Implemented API from PGPHandler // - //================================================================================================// - - //virtual std::string makeRadixEncodedPGPKey(uint32_t key_index,bool include_signatures) override; - virtual bool removeKeysFromPGPKeyring(const std::set& key_ids,std::string& backup_file,uint32_t& error_code) override; - virtual bool availableGPGCertificatesWithPrivateKeys(std::list& ids) override; - virtual bool GeneratePGPCertificate(const std::string& name, const std::string& email, const std::string& passphrase, RsPgpId& pgpId, const int keynumbits, std::string& errString) override; - - virtual std::string SaveCertificateToString(const RsPgpId& id,bool include_signatures) const override; - virtual bool exportPublicKey( const RsPgpId& id, unsigned char*& mem_block, size_t& mem_size, bool armoured, bool include_signatures ) const override; - - virtual bool exportGPGKeyPair(const std::string& filename,const RsPgpId& exported_key_id) const override; - virtual bool exportGPGKeyPairToString( std::string& data, const RsPgpId& exportedKeyId, bool includeSignatures, std::string& errorMsg ) const override; - virtual bool getGPGDetailsFromBinaryBlock(const unsigned char *mem_block,size_t mem_size,RsPgpId& key_id, std::string& name, std::list& signers) const override; - virtual bool importGPGKeyPair(const std::string& filename,RsPgpId& imported_key_id,std::string& import_error) override; - virtual bool importGPGKeyPairFromString(const std::string &data, RsPgpId &imported_key_id, std::string &import_error) override; - virtual bool LoadCertificateFromBinaryData(const unsigned char *data,uint32_t data_len,RsPgpId& id,std::string& error_string) override; - virtual bool LoadCertificateFromString(const std::string& pgp_cert,RsPgpId& id,std::string& error_string) override; - virtual bool encryptTextToFile(const RsPgpId& key_id,const std::string& text,const std::string& outfile) override; - virtual bool encryptDataBin(const RsPgpId& key_id,const void *data, const uint32_t len, unsigned char *encrypted_data, unsigned int *encrypted_data_len) override; - virtual bool decryptDataBin(const RsPgpId& /*key_id*/,const void *encrypted_data, const uint32_t encrypted_len, unsigned char *data, unsigned int *data_len) override; - virtual bool decryptTextFromFile(const RsPgpId&,std::string& text,const std::string& inputfile) override; - virtual bool SignDataBin(const RsPgpId& id,const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen,bool use_raw_signature, std::string reason /* = "" */) override; - virtual bool privateSignCertificate(const RsPgpId& ownId,const RsPgpId& id_of_key_to_sign) override; - virtual bool VerifySignBin(const void *literal_data, uint32_t literal_data_length, unsigned char *sign, unsigned int sign_len, const PGPFingerprintType& key_fingerprint) override; - virtual bool getKeyFingerprint(const RsPgpId& id, RsPgpFingerprint& fp) const override; - virtual bool haveSecretKey(const RsPgpId& id) const override; - virtual bool syncDatabase() override; - private: - bool locked_syncPublicKeyring() ; - - void initCertificateInfo(PGPCertificateInfo& cert,const ops_keydata_t *keydata,uint32_t i) ; - bool LoadCertificate(const unsigned char *data,uint32_t data_len,bool armoured,RsPgpId& id,std::string& error_string) ; - - // Returns true if the signatures have been updated - // - bool validateAndUpdateSignatures(PGPCertificateInfo& cert,const ops_keydata_t *keydata) ; - - /** Check public/private key and import them into the keyring - * @param keyring keyring with the new public/private key pair. Will be freed by the function. - * @param imported_key_id PGP id of the imported key - * @param import_error human readbale error message - * @returns true on success - * */ - bool checkAndImportKeyPair(ops_keyring_t *keyring, RsPgpId& imported_key_id,std::string& import_error); - - const ops_keydata_t *locked_getPublicKey(const RsPgpId&,bool stamp_the_key) const; - const ops_keydata_t *locked_getSecretKey(const RsPgpId&) const ; - - void locked_mergeKeyringFromDisk(ops_keyring_t *keyring, std::map& kmap, const std::string& keyring_file) ; - bool locked_addOrMergeKey(ops_keyring_t *keyring,std::map& kmap,const ops_keydata_t *keydata) ; - - // Members. - // - ops_keyring_t *_pubring ; - ops_keyring_t *_secring ; - - void printOPSKeys() const; - - // Helper functions. - // - static std::string makeRadixEncodedPGPKey(const ops_keydata_t *key,bool include_signatures) ; - static ops_keyring_t *allocateOPSKeyring() ; - static void addNewKeyToOPSKeyring(ops_keyring_t*, const ops_keydata_t&) ; - static bool mergeKeySignatures(ops_keydata_t *dst,const ops_keydata_t *src) ; // returns true if signature lists are different -}; diff --git a/libretroshare/src/pgp/pgpauxutils.cc b/libretroshare/src/pgp/pgpauxutils.cc deleted file mode 100644 index c87985fab..000000000 --- a/libretroshare/src/pgp/pgpauxutils.cc +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pgp: pgpauxutils.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "pgp/pgpauxutils.h" - -#include "pqi/authgpg.h" -#include "rsserver/p3face.h" -#include "retroshare/rsiface.h" -#include "retroshare/rspeers.h" - -PgpAuxUtilsImpl::PgpAuxUtilsImpl() -{ - return; -} - - -const RsPgpId& PgpAuxUtilsImpl::getPGPOwnId() -{ - return AuthPGP::getPgpOwnId(); -} - -RsPgpId PgpAuxUtilsImpl::getPgpId(const RsPeerId& sslid) -{ - return rsPeers->getGPGId(sslid); -} - -bool PgpAuxUtilsImpl::getKeyFingerprint(const RsPgpId& id,PGPFingerprintType& fp) const -{ - return AuthPGP::getKeyFingerprint(id, fp); -} - -bool PgpAuxUtilsImpl::VerifySignBin(const void *data, - uint32_t len, - unsigned char *sign, - unsigned int signlen, - const PGPFingerprintType& withfingerprint) - -{ - return AuthPGP::VerifySignBin(data, len, sign, signlen, withfingerprint); -} - -bool PgpAuxUtilsImpl::getPgpAllList(std::list &ids) -{ - return AuthPGP::getPgpAllList(ids); -} - -bool PgpAuxUtilsImpl::parseSignature(unsigned char *sign, unsigned int signlen, RsPgpId& issuer) const -{ - return AuthPGP::parseSignature(sign,signlen,issuer); -} - - - - diff --git a/libretroshare/src/pgp/pgpauxutils.h b/libretroshare/src/pgp/pgpauxutils.h deleted file mode 100644 index aa897c0e1..000000000 --- a/libretroshare/src/pgp/pgpauxutils.h +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pgp: pgpauxutils.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include "retroshare/rsids.h" -#include "retroshare/rstypes.h" -#include "util/rsdeprecate.h" - -/* This is a small collection of PGP functions that are widely used in libretroshare. - * This interface class allows these functions to be easily mocked for testing. - */ - -class PgpAuxUtils -{ - public: - virtual ~PgpAuxUtils(){} - - virtual const RsPgpId &getPGPOwnId() = 0; - virtual RsPgpId getPgpId(const RsPeerId& sslid) = 0; - virtual bool getPgpAllList(std::list &ids) = 0; - virtual bool getKeyFingerprint(const RsPgpId& id,PGPFingerprintType& fp) const = 0; - - virtual bool parseSignature(unsigned char *sign, unsigned int signlen, RsPgpId& issuer) const =0; - virtual bool VerifySignBin(const void *data, uint32_t len, unsigned char *sign, unsigned int signlen, const PGPFingerprintType& withfingerprint) = 0; -}; - -class PgpAuxUtilsImpl: public PgpAuxUtils -{ -public: - PgpAuxUtilsImpl(); - - virtual const RsPgpId &getPGPOwnId(); - virtual RsPgpId getPgpId(const RsPeerId& sslid); - - virtual bool parseSignature(unsigned char *sign, unsigned int signlen, RsPgpId& issuer) const ; - virtual bool getKeyFingerprint(const RsPgpId& id,PGPFingerprintType& fp) const; - virtual bool VerifySignBin(const void *data, uint32_t len, unsigned char *sign, unsigned int signlen, const PGPFingerprintType& withfingerprint); - virtual bool getPgpAllList(std::list &ids); -}; - - diff --git a/libretroshare/src/pgp/pgphandler.cc b/libretroshare/src/pgp/pgphandler.cc deleted file mode 100644 index 2d3625f24..000000000 --- a/libretroshare/src/pgp/pgphandler.cc +++ /dev/null @@ -1,392 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pgp: pgphandler.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include -#include -#include -#include -#include -#include -#include - -#ifdef WINDOWS_SYS -#include -#include "util/rsstring.h" -#include "util/rswin.h" -#endif - -#include "pgphandler.h" -#include "retroshare/rsiface.h" // For rsicontrol. -#include "retroshare/rspeers.h" // For rsicontrol. -#include "util/rsdir.h" -#include "util/rsdiscspace.h" -#include "util/rsmemory.h" -#include "pgp/pgpkeyutil.h" - -static const uint32_t PGP_CERTIFICATE_LIMIT_MAX_NAME_SIZE = 64 ; -static const uint32_t PGP_CERTIFICATE_LIMIT_MAX_EMAIL_SIZE = 64 ; -static const uint32_t PGP_CERTIFICATE_LIMIT_MAX_PASSWD_SIZE = 1024 ; - -//#define DEBUG_PGPHANDLER 1 -//#define PGPHANDLER_DSA_SUPPORT - -PassphraseCallback PGPHandler::_passphrase_callback = NULL ; - -void PGPHandler::setPassphraseCallback(PassphraseCallback cb) -{ - _passphrase_callback = cb ; -} - -PGPHandler::PGPHandler(const std::string& pubring, const std::string& secring,const std::string& trustdb,const std::string& pgp_lock_filename) - : pgphandlerMtx(std::string("PGPHandler")), _pubring_path(pubring),_secring_path(secring),_trustdb_path(trustdb),_pgp_lock_filename(pgp_lock_filename) -{ -} - -PGPHandler::~PGPHandler() -{ -} - -bool PGPHandler::printKeys() const -{ -#ifdef DEBUG_PGPHANDLER - RsErr() << "Printing details of all " << std::dec << _public_keyring_map.size() << " keys: " ; -#endif - - for(std::map::const_iterator it(_public_keyring_map.begin()); it != _public_keyring_map.end(); ++it) - { - RsErr() << "PGP Key: " << it->first.toStdString() ; - - RsErr() << "\tName : " << it->second._name ; - RsErr() << "\tEmail : " << it->second._email ; - RsErr() << "\tOwnSign : " << (it->second._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE) ; - RsErr() << "\tAccept Connect: " << (it->second._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION) ; - RsErr() << "\ttrustLvl : " << it->second._trustLvl ; - RsErr() << "\tvalidLvl : " << it->second._validLvl ; - RsErr() << "\tUse time stamp: " << it->second._time_stamp ; - RsErr() << "\tfingerprint : " << it->second._fpr.toStdString() ; - RsErr() << "\tSigners : " << it->second.signers.size() ; - - std::set::const_iterator sit; - for(sit = it->second.signers.begin(); sit != it->second.signers.end(); ++sit) - { - RsErr() << "\t\tSigner ID:" << (*sit).toStdString() << ", Name: " ; - const PGPCertificateInfo *info = PGPHandler::getCertificateInfo(*sit) ; - - if(info != NULL) - RsErr() << info->_name ; - - RsErr() << std::endl ; - } - } - return true ; -} - -const PGPCertificateInfo *PGPHandler::getCertificateInfo(const RsPgpId& id) const -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - std::map::const_iterator it( _public_keyring_map.find(id) ) ; - - if(it != _public_keyring_map.end()) - return &it->second; - else - return NULL ; -} - -void PGPHandler::updateOwnSignatureFlag(const RsPgpId& own_id) -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - if(_public_keyring_map.find(own_id)==_public_keyring_map.end()) - { - RsErr() << __func__ << ": key with id=" << own_id.toStdString() << " not in keyring." ; - // return now, because the following operation would add an entry to _public_keyring_map - return; - } - - PGPCertificateInfo& own_cert(_public_keyring_map[ own_id ]) ; - - for(std::map::iterator it=_public_keyring_map.begin();it!=_public_keyring_map.end();++it) - locked_updateOwnSignatureFlag(it->second,it->first,own_cert,own_id) ; -} -void PGPHandler::updateOwnSignatureFlag(const RsPgpId& cert_id,const RsPgpId& own_id) -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - std::map::iterator it( _public_keyring_map.find(cert_id) ) ; - - if(it == _public_keyring_map.end()) - { - RsErr() << "updateOwnSignatureFlag: Cannot get certificate for string " << cert_id.toStdString() << ". This is probably a bug." ; - return ; - } - - PGPCertificateInfo& cert( it->second ); - - PGPCertificateInfo& own_cert(_public_keyring_map[ own_id ]) ; - - locked_updateOwnSignatureFlag(cert,cert_id,own_cert,own_id) ; -} -void PGPHandler::locked_updateOwnSignatureFlag(PGPCertificateInfo& cert,const RsPgpId& cert_id,PGPCertificateInfo& own_cert,const RsPgpId& own_id_str) -{ - if(cert.signers.find(own_id_str) != cert.signers.end()) - cert._flags |= PGPCertificateInfo::PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE ; - else - cert._flags &= ~PGPCertificateInfo::PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE ; - - if(own_cert.signers.find( cert_id ) != own_cert.signers.end()) - cert._flags |= PGPCertificateInfo::PGP_CERTIFICATE_FLAG_HAS_SIGNED_ME ; - else - cert._flags &= ~PGPCertificateInfo::PGP_CERTIFICATE_FLAG_HAS_SIGNED_ME ; -} - -/*static*/ RsPgpId PGPHandler::pgpIdFromFingerprint(const RsPgpFingerprint& f) -{ - return RsPgpId::fromBufferUnsafe( - f.toByteArray() + - RsPgpFingerprint::SIZE_IN_BYTES - RsPgpId::SIZE_IN_BYTES ); -} - -void PGPHandler::setAcceptConnexion(const RsPgpId& id,bool b) -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures. - - std::map::iterator res = _public_keyring_map.find(id) ; - - if(res != _public_keyring_map.end()) - { - if(b) - res->second._flags |= PGPCertificateInfo::PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION ; - else - res->second._flags &= ~PGPCertificateInfo::PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION ; - } -} - -bool PGPHandler::getGPGFilteredList(std::list& list,bool (*filter)(const PGPCertificateInfo&)) const -{ - RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP directory. - list.clear() ; - - for(std::map::const_iterator it(_public_keyring_map.begin());it!=_public_keyring_map.end();++it) - if( filter == NULL || (*filter)(it->second) ) - list.push_back(RsPgpId(it->first)) ; - - return true ; -} - -bool PGPHandler::isPgpPubKeyAvailable(const RsPgpId &id) -{ return _public_keyring_map.find(id) != _public_keyring_map.end(); } - -bool PGPHandler::isGPGId(const RsPgpId &id) -{ - return _public_keyring_map.find(id) != _public_keyring_map.end() ; -} - -bool PGPHandler::isGPGSigned(const RsPgpId &id) -{ - std::map::const_iterator res = _public_keyring_map.find(id) ; - return res != _public_keyring_map.end() && (res->second._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE) ; -} - -bool PGPHandler::isGPGAccepted(const RsPgpId &id) -{ - std::map::const_iterator res = _public_keyring_map.find(id) ; - return (res != _public_keyring_map.end()) && (res->second._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION) ; -} - -bool PGPHandler::parseSignature(unsigned char *sign, unsigned int signlen,RsPgpId& issuer_id) -{ - PGPSignatureInfo info ; - - if(!PGPKeyManagement::parseSignature(sign,signlen,info)) - return false ; - - unsigned char bytes[8] ; - for(int i=0;i<8;++i) - { - bytes[7-i] = info.issuer & 0xff ; - info.issuer >>= 8 ; - } - issuer_id = RsPgpId(bytes) ; - - return true ; -} - -bool PGPHandler::privateTrustCertificate(const RsPgpId& id,int trustlvl) -{ - if(trustlvl < 0 || trustlvl >= 6 || trustlvl == 1) - { - RsErr() << "Invalid trust level " << trustlvl << " passed to privateTrustCertificate." ; - return false ; - } - - std::map::iterator it = _public_keyring_map.find(id); - - if(it == _public_keyring_map.end()) - { - RsErr() << "(EE) Key id " << id.toStdString() << " not in the keyring. Can't setup trust level." ; - return false ; - } - - if( (int)it->second._trustLvl != trustlvl ) - _trustdb_changed = true ; - - it->second._trustLvl = trustlvl ; - - return true ; -} - -struct PrivateTrustPacket -{ - /// pgp id in unsigned char format. - unsigned char user_id[RsPgpId::SIZE_IN_BYTES]; - uint8_t trust_level ; // trust level. From 0 to 6. - uint32_t time_stamp ; // last time the cert was ever used, in seconds since the epoch. 0 means not initialized. -}; - -void PGPHandler::locked_readPrivateTrustDatabase() -{ - FILE *fdb = RsDirUtil::rs_fopen(_trustdb_path.c_str(),"rb") ; -#ifdef DEBUG_PGPHANDLER - RsErr() << "PGPHandler: Reading private trust database." ; -#endif - - if(fdb == NULL) - { - RsErr() << " private trust database not found. No trust info loaded." << std::endl ; - return ; - } - std::map::iterator it ; - PrivateTrustPacket trustpacket; - int n_packets = 0 ; - - while(fread((void*)&trustpacket,sizeof(PrivateTrustPacket),1,fdb) == 1) - { - it = _public_keyring_map.find(RsPgpId(trustpacket.user_id)) ; - - if(it == _public_keyring_map.end()) - { - RsErr() << " (WW) Trust packet found for unknown key id " << RsPgpId(trustpacket.user_id).toStdString() ; - continue ; - } - if(trustpacket.trust_level > 6) - { - RsErr() << " (WW) Trust packet found with unexpected trust level " << trustpacket.trust_level ; - continue ; - } - - ++n_packets ; - it->second._trustLvl = trustpacket.trust_level ; - - if(trustpacket.time_stamp > it->second._time_stamp) // only update time stamp if the loaded time stamp is newer - it->second._time_stamp = trustpacket.time_stamp ; - } - - fclose(fdb) ; - - RsErr() << "PGPHandler: Successfully read " << std::hex << n_packets << std::dec << " trust packets." ; -} - -bool PGPHandler::locked_writePrivateTrustDatabase() -{ - FILE *fdb = RsDirUtil::rs_fopen((_trustdb_path+".tmp").c_str(),"wb") ; -#ifdef DEBUG_PGPHANDLER - RsErr() << "PGPHandler: Reading private trust database." ; -#endif - - if(fdb == NULL) - { - RsErr() << " (EE) Can't open private trust database file " << _trustdb_path << " for write. Giving up!" << std::endl ; - return false; - } - PrivateTrustPacket trustpacket ; - /* Clear PrivateTrustPacket struct to suppress valgrind warnings due to the compiler extra padding*/ - memset(&trustpacket, 0, sizeof(PrivateTrustPacket)); - - for( std::map::iterator it = - _public_keyring_map.begin(); it!=_public_keyring_map.end(); ++it ) - { - memcpy( trustpacket.user_id, - it->first.toByteArray(), - RsPgpId::SIZE_IN_BYTES ); - trustpacket.trust_level = it->second._trustLvl ; - trustpacket.time_stamp = it->second._time_stamp ; - - if(fwrite((void*)&trustpacket,sizeof(PrivateTrustPacket),1,fdb) != 1) - { - RsErr() << " (EE) Cannot write to trust database " << _trustdb_path << ". Disc full, or quota exceeded ? Leaving database untouched." ; - fclose(fdb) ; - return false; - } - } - - fclose(fdb) ; - - if(!RsDirUtil::renameFile(_trustdb_path+".tmp",_trustdb_path)) - { - RsErr() << " (EE) Cannot move temp file " << _trustdb_path+".tmp" << ". Bad write permissions?" ; - return false ; - } - else - return true ; -} - -bool PGPHandler::locked_syncTrustDatabase() -{ - struct stat64 buf ; -#ifdef WINDOWS_SYS - std::wstring wfullname; - librs::util::ConvertUtf8ToUtf16(_trustdb_path, wfullname); - if(-1 == _wstati64(wfullname.c_str(), &buf)) -#else - if(-1 == stat64(_trustdb_path.c_str(), &buf)) -#endif - { - RsErr() << "PGPHandler::syncDatabase(): can't stat file " << _trustdb_path << ". Will force write it." ; - _trustdb_changed = true ; // we force write of trust database if it does not exist. - buf.st_mtime = 0; - } - - if(_trustdb_last_update_time < buf.st_mtime) - { - RsErr() << "Detected change on disk of trust database. " << std::endl ; - - locked_readPrivateTrustDatabase(); - _trustdb_last_update_time = time(NULL) ; - } - - if(_trustdb_changed) - { - RsErr() << "Local changes in trust database. Writing to disk..." ; - if(!locked_writePrivateTrustDatabase()) - RsErr() << "Cannot write trust database. Disk full? Disk quota exceeded?" ; - else - { - RsErr() << "Done." ; - _trustdb_last_update_time = time(NULL) ; - _trustdb_changed = false ; - } - } - return true ; -} - - - diff --git a/libretroshare/src/pgp/pgphandler.h b/libretroshare/src/pgp/pgphandler.h deleted file mode 100644 index 19323b142..000000000 --- a/libretroshare/src/pgp/pgphandler.h +++ /dev/null @@ -1,230 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pgp: pgphandler.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -typedef std::string (*PassphraseCallback)(void *data, const char *uid_title, const char *uid_hint, const char *passphrase_info, int prev_was_bad,bool *cancelled) ; - -class PGPCertificateInfo -{ - public: - PGPCertificateInfo() : _trustLvl(0), _validLvl(0), _flags(0), _type(0), _time_stamp(0), _key_index(0) {} - - std::string _name; - std::string _email; - std::string _comment; - - std::set signers; - - uint32_t _trustLvl; - uint32_t _validLvl; - uint32_t _flags ; - uint32_t _type ; - - mutable rstime_t _time_stamp ; // last time the key was used (received, used for signature verification, etc) - - PGPFingerprintType _fpr; /* fingerprint */ - - // Index to array of keys in the public keyring. Dependign on the specific implementation - // of how the keyring is stored, this may be used differently. - - uint32_t _key_index ; - - static const uint32_t PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION = 0x0001 ; - static const uint32_t PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE = 0x0002 ; - static const uint32_t PGP_CERTIFICATE_FLAG_HAS_SIGNED_ME = 0x0004 ; - static const uint32_t PGP_CERTIFICATE_FLAG_UNSUPPORTED_ALGORITHM = 0x0008 ; // set when the key is not RSA, so that RS avoids to use it. - - static const uint8_t PGP_CERTIFICATE_TRUST_UNDEFINED = 0x00 ; - static const uint8_t PGP_CERTIFICATE_TRUST_NEVER = 0x02 ; - static const uint8_t PGP_CERTIFICATE_TRUST_MARGINALLY = 0x03 ; - static const uint8_t PGP_CERTIFICATE_TRUST_FULLY = 0x04 ; - static const uint8_t PGP_CERTIFICATE_TRUST_ULTIMATE = 0x05 ; - - static const uint8_t PGP_CERTIFICATE_TYPE_UNKNOWN = 0x00 ; - static const uint8_t PGP_CERTIFICATE_TYPE_DSA = 0x01 ; - static const uint8_t PGP_CERTIFICATE_TYPE_RSA = 0x02 ; -}; - -/// This class offer an abstract pgp handler to be used in RetroShare. -class PGPHandler -{ -public: - PGPHandler( const std::string& path_to_public_keyring, - const std::string& path_to_secret_keyring, - const std::string& path_to_trust_database, - const std::string& pgp_lock_file) ; - - virtual ~PGPHandler() ; - - //=======================================================================================// - // Methods that needs to be derived depending on how PGP is implemented // - //=======================================================================================// - - // Removes the given keys from the keyring. Also backup the keyring to a file which name is automatically generated - // and given pack for proper display. - // - virtual bool removeKeysFromPGPKeyring(const std::set& key_ids,std::string& backup_file,uint32_t& error_code) =0; - //virtual std::string makeRadixEncodedPGPKey(uint32_t key_index,bool include_signatures) =0; - - virtual bool availableGPGCertificatesWithPrivateKeys(std::list& ids)=0; - virtual bool GeneratePGPCertificate(const std::string& name, const std::string& email, const std::string& passwd, RsPgpId& pgpId, const int keynumbits, std::string& errString) =0; - - virtual std::string SaveCertificateToString(const RsPgpId& id,bool include_signatures) const=0; - - /** The caller is in charge of freeing `mem` once finished */ - virtual bool exportPublicKey( const RsPgpId& id, unsigned char*& mem_block, size_t& mem_size, bool armoured, bool include_signatures ) const =0; - - virtual bool exportGPGKeyPair(const std::string& filename,const RsPgpId& exported_key_id) const=0; - virtual bool exportGPGKeyPairToString( std::string& data, const RsPgpId& exportedKeyId, bool includeSignatures, std::string& errorMsg ) const =0; - - // Gets info about the key. Who are the signers, what's the owner's name, etc. - // - virtual bool getGPGDetailsFromBinaryBlock(const unsigned char *mem,size_t mem_size,RsPgpId& key_id, std::string& name, std::list& signers) const =0; - - virtual bool importGPGKeyPair(const std::string& filename,RsPgpId& imported_id,std::string& import_error) =0; - /** - * @param ids list of gpg certificate ids (note, not the actual certificates) - */ - - virtual bool importGPGKeyPairFromString(const std::string& data,RsPgpId& imported_id,std::string& import_error) =0; - - virtual bool LoadCertificateFromString(const std::string& pem, RsPgpId& gpg_id, std::string& error_string)=0; - virtual bool LoadCertificateFromBinaryData(const unsigned char *bin_data,uint32_t bin_data_len, RsPgpId& gpg_id, std::string& error_string)=0; - - virtual bool encryptTextToFile(const RsPgpId& key_id,const std::string& text,const std::string& outfile) =0; - virtual bool decryptTextFromFile(const RsPgpId& key_id,std::string& text,const std::string& encrypted_inputfile) =0; - - // The client should supply a memory chunk to store the data. The length will be updated to the real length of the data. - // - virtual bool encryptDataBin(const RsPgpId& key_id,const void *data, const uint32_t len , unsigned char *encrypted_data, unsigned int *encrypted_data_len) =0; - virtual bool decryptDataBin(const RsPgpId& key_id,const void *encrypted_data, const uint32_t encrypted_len , unsigned char *data, unsigned int *data_len) =0; - - virtual bool SignDataBin(const RsPgpId& id, const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen, bool make_raw_signature=false, std::string reason = "") =0; - virtual bool privateSignCertificate(const RsPgpId& own_id,const RsPgpId& id_of_key_to_sign) =0; - virtual bool VerifySignBin(const void *data, uint32_t data_len, unsigned char *sign, unsigned int sign_len, const PGPFingerprintType& withfingerprint) =0; - /** - * @brief Get PGP fingerprint for the given key - * @param id PGP 64bit key id - * @param fp storage for the retrived key fingerpring, the contained value - * is meaningfull only if true is returned - * @return true if the key was found, false if not - */ - virtual bool getKeyFingerprint(const RsPgpId& id, RsPgpFingerprint& fp) const=0; - - virtual bool haveSecretKey(const RsPgpId& id) const =0; - - // Syncs the keyrings and trust database between memory and disk. The algorithm is: - // 1 - lock the keyrings - // 2 - compare file modification dates with last writing date - // - if file is modified, load it, and merge with memory - // 3 - look into memory modification flags - // - if flag says keyring has changed, write to disk - // - virtual bool syncDatabase() =0; - - - //=======================================================================================// - // Common methods to PGPHandler // - //=======================================================================================// - - bool getGPGFilteredList(std::list& list,bool (*filter)(const PGPCertificateInfo&) = NULL) const ; - - bool parseSignature(unsigned char *sign, unsigned int signlen,RsPgpId& issuer_id) ; - - void setAcceptConnexion(const RsPgpId&,bool) ; - - void updateOwnSignatureFlag(const RsPgpId& ownId) ; - void updateOwnSignatureFlag(const RsPgpId& pgp_id,const RsPgpId& ownId) ; - - void locked_updateOwnSignatureFlag(PGPCertificateInfo&, const RsPgpId&, PGPCertificateInfo&, const RsPgpId&) ; - - //bool isKeySupported(const RsPgpId& id) const ; - - bool privateTrustCertificate(const RsPgpId& id,int valid_level) ; - - // Write keyring - - //bool writeSecretKeyring() ; - //bool writePublicKeyring() ; - - const PGPCertificateInfo *getCertificateInfo(const RsPgpId& id) const ; - - RS_DEPRECATED_FOR(isPgpPubKeyAvailable) - bool isGPGId(const RsPgpId &id); - bool isGPGSigned(const RsPgpId &id); - bool isGPGAccepted(const RsPgpId &id); - - static void setPassphraseCallback(PassphraseCallback cb) ; - static PassphraseCallback passphraseCallback() { return _passphrase_callback ; } - - /** - * @brief Check if a PGP publick key is available - * @param id id of the key to check - * @return true if the public key for the given id is available, - * false otherwise - */ - bool isPgpPubKeyAvailable(const RsPgpId& id); - - /** - * @brief Convert PGP fingerprint to PGP 64bit id - * @param f PGP fingerprint to convert - * @return PGP 64bit id extracted from fingerprint - */ - static RsPgpId pgpIdFromFingerprint(const RsPgpFingerprint& f); - - // Debug stuff. - virtual bool printKeys() const ; - - protected: - void locked_readPrivateTrustDatabase() ; - bool locked_writePrivateTrustDatabase() ; - bool locked_syncTrustDatabase() ; - - // Members. - // - mutable RsMutex pgphandlerMtx ; - - std::map _public_keyring_map ; // used for fast access to keys. Gives the index in the keyring. - std::map _secret_keyring_map ; - - const std::string _pubring_path ; - const std::string _secring_path ; - const std::string _trustdb_path ; - const std::string _pgp_lock_filename ; - - bool _pubring_changed ; - mutable bool _trustdb_changed ; - - rstime_t _pubring_last_update_time ; - rstime_t _secring_last_update_time ; - rstime_t _trustdb_last_update_time ; - - static PassphraseCallback _passphrase_callback ; -}; diff --git a/libretroshare/src/pgp/pgpkeyutil.cc b/libretroshare/src/pgp/pgpkeyutil.cc deleted file mode 100644 index 105556ebb..000000000 --- a/libretroshare/src/pgp/pgpkeyutil.cc +++ /dev/null @@ -1,427 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pgp: pgpkeyutil.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include -#include -#include -#include "pgpkeyutil.h" - -#include -#include - -/****************************/ -/* #define DEBUG_PGPUTIL 1 */ -/****************************/ - -#define PGP_CRC24_INIT 0xB704CEL -#define PGP_CRC24_POLY 0x1864CFBL - -#define PGP_CERTIFICATE_START_STRING "-----BEGIN PGP PUBLIC KEY BLOCK-----" -#define PGP_CERTIFICATE_END_STRING "-----END PGP PUBLIC KEY BLOCK-----" -// -// All size are big endian -// MPI: 2 bytes size (length in bits) + string of octets -// -bool PGPKeyManagement::createMinimalKey(const std::string& pgp_certificate,std::string& cleaned_certificate) -{ - try - { - // 0 - Extract Radix64 portion of the certificate - // - std::string version_string ; - std::string radix_cert = PGPKeyParser::extractRadixPartFromArmouredKey(pgp_certificate,version_string) ; - - // 1 - Convert armored key into binary key - // - std::vector keydata = Radix64::decode(radix_cert) ; - - size_t new_len ; - findLengthOfMinimalKey(keydata.data(), keydata.size(), new_len) ; - - cleaned_certificate = makeArmouredKey(keydata.data(), new_len, version_string) ; - return true ; - } - catch(std::exception& e) - { - cleaned_certificate = "" ; - std::cerr << "Certificate cleaning failed: " << e.what() << std::endl; - return false ; - } -} - -void PGPKeyManagement::findLengthOfMinimalKey(const unsigned char *keydata,size_t len,size_t& new_len) -{ - unsigned char *data = (unsigned char *)keydata ; - -#ifdef DEBUG_PGPUTIL - std::cerr << "Total size: " << len << std::endl; -#endif - - uint8_t packet_tag; - uint32_t packet_length ; - - // 2 - parse key data, only keep public key data, user id and self-signature. - - bool public_key=false ; - bool own_signature=false ; - bool user_id=false ; - - while(true) - { - PGPKeyParser::read_packetHeader(data,packet_tag,packet_length) ; -#ifdef DEBUG_PGPUTIL - std::cerr << "Header:" << std::endl; - std::cerr << " Packet tag: " << (int)packet_tag << std::endl; - std::cerr << " Packet length: " << packet_length << std::endl; -#endif - - data += packet_length ; - - if(packet_tag == PGPKeyParser::PGP_PACKET_TAG_PUBLIC_KEY) - public_key = true ; - if(packet_tag == PGPKeyParser::PGP_PACKET_TAG_USER_ID) - user_id = true ; - if(packet_tag == PGPKeyParser::PGP_PACKET_TAG_SIGNATURE) - own_signature = true ; - - if(public_key && own_signature && user_id) - break ; - - if( (uint64_t)data - (uint64_t)keydata >= len ) - break ; - } - - new_len = (uint64_t)data - (uint64_t)keydata ; -} - -std::string PGPKeyParser::extractRadixPartFromArmouredKey(const std::string& pgp_certificate,std::string& version_string) -{ - int n = pgp_certificate.length() ; - int i=0 ; - version_string = "" ; - - while(i < n && pgp_certificate[i] != '\n') ++i ; // remove first part -----BEGIN PGP CERTIFICATE----- - ++i ; - while(i < n && pgp_certificate[i] != '\n') version_string += pgp_certificate[i++] ; // remove first part Version: [fdfdfdf] - ++i ; - while(i < n && pgp_certificate[i] != '\n') ++i ; // remove blank line - - ++i ; - - int j=n-1 ; - - while(j>0 && pgp_certificate[j] != '=' && j>=i) --j ; - - std::string radix_cert = pgp_certificate.substr(i,j-i) ; - -#ifdef DEBUG_PGPUTIL - std::cerr << "extracted radix cert: " << std::endl; - std::cerr << radix_cert ; -#endif - return radix_cert ; -} - - -std::string PGPKeyManagement::makeArmouredKey(const unsigned char *keydata,size_t key_size,const std::string& version_string) -{ - std::string outstring ; - Radix64::encode(keydata,key_size,outstring) ; - - uint32_t crc = compute24bitsCRC((unsigned char *)keydata,key_size) ; - - unsigned char tmp[3] = { uint8_t((crc >> 16) & 0xff), uint8_t((crc >> 8) & 0xff), uint8_t(crc & 0xff) } ; - std::string crc_string ; - Radix64::encode(tmp,3,crc_string) ; - -#ifdef DEBUG_PGPUTIL - std::cerr << "After signature pruning: " << std::endl; - std::cerr << outstring << std::endl; -#endif - - std::string certificate = std::string(PGP_CERTIFICATE_START_STRING) + "\n" + version_string + "\n\n" ; - - for(uint32_t i=0;i= hashed_size ) - break ; - } - // non hashed sub-packets are ignored for now. - - return issuer_found ; -} - -uint64_t PGPKeyParser::read_KeyID(unsigned char *& data) -{ - uint64_t val = 0 ; - - val |= uint64_t( *data ) << 56 ; ++data ; - val |= uint64_t( *data ) << 48 ; ++data ; - val |= uint64_t( *data ) << 40 ; ++data ; - val |= uint64_t( *data ) << 32 ; ++data ; - val |= uint64_t( *data ) << 24 ; ++data ; - val |= uint64_t( *data ) << 16 ; ++data ; - val |= uint64_t( *data ) << 8 ; ++data ; - val |= uint64_t( *data ) << 0 ; ++data ; - - return val ; -} - -uint32_t PGPKeyParser::write_125Size(unsigned char *data,uint32_t size) -{ - if(size < 192)//192 To know if size is coded with One Char < 0xC0 - { - data[0] = size ; - return 1; - } - - if(size < 8384)//8384 To know if size is coded with Two Chars < 0xE0. See RFC4880 - { - data[1] = (size - 192) & 0xFF ;//Warning data[1] could be "negative", recode it using 8bits type - data[0] = ((size - 192 - data[1]) >> 8) + 192 ; - - return 2 ; - } - - data[0] = 0xFF ; //Else size is coded with 4 Chars + 1 at 0xFF - data[1] = (size >> 24) & 0xFF ; - data[2] = (size >> 16) & 0xFF ; - data[3] = (size >> 8) & 0xFF ; - data[4] = (size ) & 0xFF ; - - return 5 ; -} - -uint32_t PGPKeyParser::read_125Size(unsigned char *& data) -{ - uint8_t b1 = *data ; - ++data ; - - if (b1 < 192) //192 Size is coded with One Char. See RFC4880 https://tools.ietf.org/html/rfc4880#section-4.2.2.1 - return b1 ; - - uint8_t b2 = *data ; - ++data ; - - if (b1 < 224)//224 = 0xC0+0x20 Size is coded with Two Chars - return ( (b1-192) << 8 ) + b2 + 192 ; // see RFC4880 - - if(b1 != 0xFF)// Else Coded with 4 Chars but first == 0xFF - throw std::runtime_error("GPG parsing error") ; - - uint8_t b3 = *data ; ++data ; - uint8_t b4 = *data ; ++data ; - uint8_t b5 = *data ; ++data ; - - return (b2 << 24) | (b3 << 16) | (b4 << 8) | b5 ; -} - -uint32_t PGPKeyParser::read_partialBodyLength(unsigned char *& data) -{ - uint8_t b1 =*data ; - ++data ; - - return 1 << (b1 & 0x1F) ; -} - - -void PGPKeyParser::read_packetHeader(unsigned char *& data,uint8_t& packet_tag,uint32_t& packet_length) -{ - uint8_t b1 = *data ; - ++data ; - - bool new_format = b1 & 0x40 ; - - if(new_format) - { -#ifdef DEBUG_PGPUTIL - std::cerr << "Packet is in new format" << std::endl; -#endif - packet_tag = b1 & 0x3f ; - packet_length = read_125Size(data) ; - } - else - { -#ifdef DEBUG_PGPUTIL - std::cerr << "Packet is in old format" << std::endl; -#endif - uint8_t length_type = b1 & 0x03 ; - packet_tag = (b1 & 0x3c) >> 2 ; - - int length_size ; - switch(length_type) - { - case 0: length_size = 1 ; - break ; - case 1: length_size = 2 ; - break ; - case 2: length_size = 4 ; - break ; - default: - throw std::runtime_error("Unhandled length type!") ; - } - - packet_length = 0 ; - for(int k=0;k * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -// refer to RFC4880 specif document for loading GPG public keys: -// -// 11.1: transferable public keys -// Global structure of transferable public keys -// -// - one public key packet (see 12.2) -// - zero or more revocation signatures (See signature type 5.2.1 for key signature types) -// -// - user certification signatures (0x10 or 0x13) -// -// - 5.2.2: Signature format packet -// - 5.2.3.1: signature subpacket specification -// -// - 4.3: packet tags (1 byte) - -#pragma once - -#include -#include - -static const uint8_t PGP_PACKET_TAG_HASH_ALGORITHM_UNKNOWN = 0 ; -static const uint8_t PGP_PACKET_TAG_HASH_ALGORITHM_MD5 = 1 ; -static const uint8_t PGP_PACKET_TAG_HASH_ALGORITHM_SHA1 = 2 ; -static const uint8_t PGP_PACKET_TAG_HASH_ALGORITHM_SHA256 = 8 ; -static const uint8_t PGP_PACKET_TAG_HASH_ALGORITHM_SHA512 = 10 ; - -static const uint8_t PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_UNKNOWN = 0 ; -static const uint8_t PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_RSA_ES = 1 ; -static const uint8_t PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_RSA_E = 2 ; -static const uint8_t PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_RSA_S = 3 ; -static const uint8_t PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_DSA = 17 ; - -static const uint8_t PGP_PACKET_TAG_SIGNATURE_VERSION_UNKNOWN = 0 ; -static const uint8_t PGP_PACKET_TAG_SIGNATURE_VERSION_V3 = 3 ; -static const uint8_t PGP_PACKET_TAG_SIGNATURE_VERSION_V4 = 4 ; - -static const uint8_t PGP_PACKET_TAG_SIGNATURE_TYPE_UNKNOWN = 0xff ; -static const uint8_t PGP_PACKET_TAG_SIGNATURE_TYPE_BINARY_DOCUMENT = 0x00 ; -static const uint8_t PGP_PACKET_TAG_SIGNATURE_TYPE_CANONICAL_TEXT = 0x01 ; -static const uint8_t PGP_PACKET_TAG_SIGNATURE_TYPE_STANDALONE_SIG = 0x02 ; -// All other consts for signature types not used, so not defines. - -class PGPSignatureInfo -{ -public: - PGPSignatureInfo() : - signature_version (PGP_PACKET_TAG_SIGNATURE_VERSION_UNKNOWN), - signature_type (PGP_PACKET_TAG_SIGNATURE_TYPE_UNKNOWN), - issuer (0), - public_key_algorithm(PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_UNKNOWN), - hash_algorithm (PGP_PACKET_TAG_HASH_ALGORITHM_UNKNOWN) - {} - - uint8_t signature_version ; - uint8_t signature_type ; - uint64_t issuer ; - uint8_t public_key_algorithm ; - uint8_t hash_algorithm ; -}; - -class PGPKeyInfo -{ -public: - PGPKeyInfo() {} - - std::string user_id; - unsigned char fingerprint[20]; -}; - - -// This class handles GPG keys. For now we only clean them from signatures, but -// in the future, we might cache them to avoid unnecessary calls to gpgme. -// -class PGPKeyManagement -{ - public: - // Create a minimal key, removing all signatures and third party info. - // Input: a clean PGP certificate (starts with "----BEGIN", - // ends with "-----END PGP PUBLIC KEY BLOCK-----" - // Output: the same certificate without signatures. - // - // Returns: - // - // true if the certificate cleaning succeeded - // false otherwise. - // - static bool createMinimalKey(const std::string& pgp_certificate,std::string& cleaned_certificate) ; - - static void findLengthOfMinimalKey(const unsigned char *keydata,size_t key_len,size_t& minimal_key_len) ; - static std::string makeArmouredKey(const unsigned char *keydata,size_t key_size,const std::string& version_string) ; - - // Computes the 24 bits CRC checksum necessary to all PGP data. - // - static uint32_t compute24bitsCRC(unsigned char *data,size_t len) ; - - static bool parseSignature(const unsigned char *signature, size_t sign_len, PGPSignatureInfo& info) ; - - static bool parsePGPPublicKey(const unsigned char *keydata, size_t keylen, PGPKeyInfo& info); -}; - -// This class handles the parsing of PGP packet headers under various (old and new) formats. -// -class PGPKeyParser -{ - public: - // These constants correspond to packet tags from RFC4880 - - static const uint8_t PGP_PACKET_TAG_PUBLIC_KEY = 6 ; - static const uint8_t PGP_PACKET_TAG_USER_ID = 13 ; - static const uint8_t PGP_PACKET_TAG_SIGNATURE = 2 ; - static const uint8_t PGP_PACKET_TAG_ISSUER = 16 ; - - // These functions read and move the data pointer to the next byte after the read section. - // - static uint64_t read_KeyID(unsigned char *& data) ; - static uint32_t read_125Size(unsigned char *& data) ; - static uint32_t read_partialBodyLength(unsigned char *& data) ; - static void read_packetHeader(unsigned char *&data, uint8_t& packet_tag, uint32_t& packet_length) ; - - // These functions write, and indicate how many bytes where written. - // - static uint32_t write_125Size(unsigned char *data,uint32_t size) ; - - // Helper functions - // - static std::string extractRadixPartFromArmouredKey(const std::string& pgp_cert,std::string& version_string); -}; - - diff --git a/libretroshare/src/pgp/rscertificate.cc b/libretroshare/src/pgp/rscertificate.cc deleted file mode 100644 index 41448fd64..000000000 --- a/libretroshare/src/pgp/rscertificate.cc +++ /dev/null @@ -1,761 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pgp: rscertificate.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016 Cyril Soler * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include -#include -#include -#include - -#include -#include -#include -#include -#include "rscertificate.h" -#include "util/rsstring.h" -#include "util/stacktrace.h" -#include "util/rsdebug.h" - -//#define DEBUG_RSCERTIFICATE - -static const uint8_t CERTIFICATE_VERSION_06 = 0x06; - -enum CertificatePtag : uint8_t -{ - CERTIFICATE_PTAG_PGP_SECTION = 0x01, - CERTIFICATE_PTAG_EXTIPANDPORT_SECTION = 0x02, - CERTIFICATE_PTAG_LOCIPANDPORT_SECTION = 0x03, - CERTIFICATE_PTAG_DNS_SECTION = 0x04, - CERTIFICATE_PTAG_SSLID_SECTION = 0x05, - CERTIFICATE_PTAG_NAME_SECTION = 0x06, - CERTIFICATE_PTAG_CHECKSUM_SECTION = 0x07, - CERTIFICATE_PTAG_HIDDENNODE_SECTION = 0x08, - CERTIFICATE_PTAG_VERSION_SECTION = 0x09, - CERTIFICATE_PTAG_EXTRA_LOCATOR = 10 -}; - -static bool is_acceptable_radix64Char(char c) -{ - return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '+' || c == '/' || c == '=' ; -} - - -RsCertificate::~RsCertificate() -{ - delete[] binary_pgp_key ; -} - -void RsCertificate::addPacket(uint8_t ptag, const unsigned char *mem, size_t size, unsigned char *& buf, size_t& offset, size_t& buf_size) -{ - // Check that the buffer has sufficient size. If not, increase it. - - while(offset + size + 6 >= buf_size) - { - unsigned char *newbuf = new unsigned char[2*buf_size] ; - - memcpy(newbuf, buf, buf_size) ; - buf_size *= 2 ; - - delete[] buf ; - - buf = newbuf ; - } - - // Write ptag and size - - buf[offset] = ptag ; - offset += 1 ; - - offset += PGPKeyParser::write_125Size(&buf[offset],size) ; - - // Copy the data - - memcpy(&buf[offset], mem, size) ; - offset += size ; -} - -const RsCertificate&RsCertificate::operator=(const RsCertificate&) -{ - memset(ipv4_external_ip_and_port,0,6); - memset(ipv4_internal_ip_and_port,0,6); - binary_pgp_key = nullptr; - binary_pgp_key_size = 0; - only_pgp = false; - hidden_node = false; - return *this; -} - -std::string RsCertificate::toStdString() const -{ - //std::string res ; - size_t BS = 1000 ; - size_t p = 0 ; - unsigned char *buf = new unsigned char[BS] ; - - addPacket( CERTIFICATE_PTAG_VERSION_SECTION, &CERTIFICATE_VERSION_06 , 1 , buf, p, BS ) ; - addPacket( CERTIFICATE_PTAG_PGP_SECTION , binary_pgp_key , binary_pgp_key_size , buf, p, BS ) ; - - if(!only_pgp) - { - if (hidden_node) - { - addPacket( CERTIFICATE_PTAG_HIDDENNODE_SECTION, (unsigned char *)hidden_node_address.c_str(), hidden_node_address.length() , buf, p, BS ) ; - } - else - { - addPacket( CERTIFICATE_PTAG_EXTIPANDPORT_SECTION, ipv4_external_ip_and_port , 6 , buf, p, BS ) ; - addPacket( CERTIFICATE_PTAG_LOCIPANDPORT_SECTION, ipv4_internal_ip_and_port , 6 , buf, p, BS ) ; - addPacket( CERTIFICATE_PTAG_DNS_SECTION , (unsigned char *)dns_name.c_str() , dns_name.length() , buf, p, BS ) ; - } - - addPacket( CERTIFICATE_PTAG_NAME_SECTION , (unsigned char *)location_name.c_str() ,location_name.length() , buf, p, BS ) ; - addPacket( CERTIFICATE_PTAG_SSLID_SECTION , location_id.toByteArray() ,location_id.SIZE_IN_BYTES, buf, p, BS ) ; - - for (const RsUrl& locator : mLocators) - { - std::string urlStr(locator.toString()); - addPacket( CERTIFICATE_PTAG_EXTRA_LOCATOR, - (unsigned char *) urlStr.c_str(), urlStr.size(), - buf, p, BS ); - } - } - - uint32_t computed_crc = PGPKeyManagement::compute24bitsCRC(buf,p) ; - - // handle endian issues. - unsigned char mem[3] ; - mem[0] = computed_crc & 0xff ; - mem[1] = (computed_crc >> 8 ) & 0xff ; - mem[2] = (computed_crc >> 16) & 0xff ; - - addPacket( CERTIFICATE_PTAG_CHECKSUM_SECTION,mem,3,buf,p,BS) ; - - std::string out_string ; - - Radix64::encode(buf, p, out_string) ; - - // Now slice up to 64 chars. - // - std::string out2 ; - static const int LINE_LENGTH = 64 ; - - for(int i=0;i<(int)out_string.length();++i) - { - out2 += out_string[i] ; - - if(i % LINE_LENGTH == LINE_LENGTH-1) - out2 += '\n' ; - } - - delete[] buf ; - return out2 ; -} - -RsCertificate::RsCertificate(const RsPeerDetails& Detail, const unsigned char *binary_pgp_block,size_t binary_pgp_block_size) - :pgp_version("Version: OpenPGP:SDK v0.9") -{ - if(binary_pgp_block_size == 0 || binary_pgp_block == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " is deprecated because it can " - << "miserably fail like this! " << std::endl; - print_stacktrace(); - throw std::runtime_error("Cannot init a certificate with a void key block."); - } - - binary_pgp_key = new unsigned char[binary_pgp_block_size] ; - memcpy(binary_pgp_key,binary_pgp_block,binary_pgp_block_size) ; - binary_pgp_key_size = binary_pgp_block_size ; - - if(!Detail.isOnlyGPGdetail) - { - only_pgp = false ; - location_id = RsPeerId( Detail.id ) ; - location_name = Detail.location ; - - if (Detail.isHiddenNode) - { - hidden_node = true; - hidden_node_address = Detail.hiddenNodeAddress; - rs_sprintf_append(hidden_node_address, ":%u", Detail.hiddenNodePort); - - memset(ipv4_internal_ip_and_port,0,6) ; - memset(ipv4_external_ip_and_port,0,6) ; - dns_name = "" ; - } - else - { - hidden_node = false; - hidden_node_address = ""; - - try - { - scan_ip(Detail.localAddr,Detail.localPort,ipv4_internal_ip_and_port); - } - catch(...) - { - std::cerr << "RsCertificate::Invalid LocalAddress: " - << Detail.localAddr << std::endl; - memset(ipv4_internal_ip_and_port,0,6); - } - - - try - { - scan_ip(Detail.extAddr,Detail.extPort,ipv4_external_ip_and_port); - } - catch(...) - { - std::cerr << "RsCertificate::Invalid ExternalAddress: " - << Detail.extAddr << std::endl; - memset(ipv4_external_ip_and_port,0,6) ; - } - - dns_name = Detail.dyndns; - - for(auto&& ipr : Detail.ipAddressList) - mLocators.insert(RsUrl(ipr.substr(0, ipr.find(' ')))); - } - } - else - { - only_pgp = true ; - hidden_node = false; - hidden_node_address = ""; - location_id = RsPeerId() ; - location_name = "" ; - memset(ipv4_internal_ip_and_port,0,6) ; - memset(ipv4_external_ip_and_port,0,6) ; - dns_name = "" ; - } -} - - -/*static*/ std::unique_ptr RsCertificate::fromMemoryBlock( - const RsPeerDetails& details, const uint8_t* binary_pgp_block, - size_t binary_pgp_block_size ) -{ - if(binary_pgp_block_size == 0 || binary_pgp_block == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " invalid parameters! " << std::endl; - print_stacktrace(); - return nullptr; - } - - std::unique_ptr crt(new RsCertificate); - - crt->binary_pgp_key = new uint8_t[binary_pgp_block_size]; - memcpy(crt->binary_pgp_key, binary_pgp_block, binary_pgp_block_size); - crt->binary_pgp_key_size = binary_pgp_block_size; - - if(!details.isOnlyGPGdetail) - { - crt->only_pgp = false; - crt->location_id = RsPeerId(details.id); - crt->location_name = details.location; - - if (details.isHiddenNode) - { - crt->hidden_node = true; - crt->hidden_node_address = details.hiddenNodeAddress; - rs_sprintf_append( - crt->hidden_node_address, ":%u", details.hiddenNodePort); - - memset(crt->ipv4_internal_ip_and_port, 0, 6); - memset(crt->ipv4_external_ip_and_port, 0, 6); - crt->dns_name = ""; - } - else - { - crt->hidden_node = false; - crt->hidden_node_address = ""; - - try - { - scan_ip( details.localAddr, details.localPort, - crt->ipv4_internal_ip_and_port ); - } - catch(...) - { - RsErr() << __PRETTY_FUNCTION__ << " Invalid LocalAddress: " - << details.localAddr << std::endl; - memset(crt->ipv4_internal_ip_and_port, 0, 6); - } - - try - { - scan_ip( details.extAddr, details.extPort, - crt->ipv4_external_ip_and_port ); - } - catch(...) - { - RsErr() << __PRETTY_FUNCTION__ << " Invalid ExternalAddress: " - << details.extAddr << std::endl; - memset(crt->ipv4_external_ip_and_port, 0, 6); - } - - crt->dns_name = details.dyndns; - - for(auto&& ipr : details.ipAddressList) - crt->mLocators.insert(RsUrl(ipr.substr(0, ipr.find(' ')))); - } - } - else - { - crt->only_pgp = true; - crt->hidden_node = false; - crt->hidden_node_address = ""; - crt->location_id = RsPeerId(); - crt->location_name = ""; - memset(crt->ipv4_internal_ip_and_port, 0, 6); - memset(crt->ipv4_external_ip_and_port, 0, 6); - crt->dns_name = ""; - } - - return crt; // Implicit move semantic -} - -void RsCertificate::scan_ip(const std::string& ip_string, unsigned short port,unsigned char *ip_and_port) -{ - int d0,d1,d2,d3 ; - - if(4 != sscanf(ip_string.c_str(),"%d.%d.%d.%d",&d0,&d1,&d2,&d3)) - throw std::runtime_error( "Cannot parse ip from given string." ); - - ip_and_port[0] = d0 ; - ip_and_port[1] = d1 ; - ip_and_port[2] = d2 ; - ip_and_port[3] = d3 ; - - ip_and_port[4] = (port >> 8 ) & 0xff ; - ip_and_port[5] = port & 0xff ; -} - -/*static*/ std::unique_ptr RsCertificate::fromString( - const std::string& instr, uint32_t& err_code ) -{ - Dbg3() << __PRETTY_FUNCTION__ << std::endl; - - std::unique_ptr crt(new RsCertificate); - - std::string str; - err_code = CERTIFICATE_PARSING_ERROR_NO_ERROR; - - // 0 - clean the string and check that it is pure radix64 - for(uint32_t i=0;i bf = Radix64::decode(str); - size_t size = bf.size(); - - bool checksum_check_passed = false; - unsigned char* buf = bf.data(); - size_t total_s = 0; - crt->only_pgp = true; - uint8_t certificate_version = 0x00; - - while(total_s < size) - { - uint8_t ptag = buf[0]; - buf = &buf[1]; - - unsigned char *buf2 = buf; - uint32_t s = 0; - - try { s = PGPKeyParser::read_125Size(buf); } - catch (...) - { - err_code = CERTIFICATE_PARSING_ERROR_SIZE_ERROR; - return nullptr; - } - - total_s += 1 + ( - reinterpret_cast(buf) - - reinterpret_cast(buf2) ); - - if(total_s > size) - { - err_code = CERTIFICATE_PARSING_ERROR_SIZE_ERROR; - return nullptr; - } - - Dbg3() << __PRETTY_FUNCTION__ << " Read ptag: " - << static_cast(ptag) - << ", size " << s << ", total_s = " << total_s - << ", expected total = " << size << std::endl; - - switch(ptag) - { - case CERTIFICATE_PTAG_VERSION_SECTION: - certificate_version = buf[0]; - break; - case CERTIFICATE_PTAG_PGP_SECTION: - crt->binary_pgp_key = new unsigned char[s]; - memcpy(crt->binary_pgp_key, buf, s); - crt->binary_pgp_key_size = s; - break; - case CERTIFICATE_PTAG_NAME_SECTION: - crt->location_name = - std::string(reinterpret_cast(buf), s); - break; - case CERTIFICATE_PTAG_SSLID_SECTION: - if(s != crt->location_id.SIZE_IN_BYTES) - { - err_code = CERTIFICATE_PARSING_ERROR_INVALID_LOCATION_ID; - return nullptr; - } - // We just checked buffer size so next line is not unsafe - crt->location_id = RsPeerId::fromBufferUnsafe(buf); - crt->only_pgp = false; - break; - case CERTIFICATE_PTAG_DNS_SECTION: - crt->dns_name = std::string(reinterpret_cast(buf), s); - break; - case CERTIFICATE_PTAG_HIDDENNODE_SECTION: - crt->hidden_node_address = - std::string(reinterpret_cast(buf),s); - crt->hidden_node = true; - break; - case CERTIFICATE_PTAG_LOCIPANDPORT_SECTION: - if(s != 6) - { - err_code = CERTIFICATE_PARSING_ERROR_INVALID_LOCAL_IP; - return nullptr; - } - memcpy(crt->ipv4_internal_ip_and_port, buf, s); - break; - case CERTIFICATE_PTAG_EXTIPANDPORT_SECTION: - if(s != 6) - { - err_code = CERTIFICATE_PARSING_ERROR_INVALID_EXTERNAL_IP; - return nullptr; - } - memcpy(crt->ipv4_external_ip_and_port, buf, s); - break; - case CERTIFICATE_PTAG_CHECKSUM_SECTION: - { - if(s != 3 || total_s+3 != size) - { - err_code = - CERTIFICATE_PARSING_ERROR_INVALID_CHECKSUM_SECTION; - return nullptr; - } - uint32_t computed_crc = - PGPKeyManagement::compute24bitsCRC(bf.data(),size-5); - uint32_t certificate_crc = static_cast( - buf[0] + (buf[1] << 8) + (buf[2] << 16) ); - if(computed_crc != certificate_crc) - { - err_code = CERTIFICATE_PARSING_ERROR_CHECKSUM_ERROR; - return nullptr; - } - else checksum_check_passed = true; - break; - } - case CERTIFICATE_PTAG_EXTRA_LOCATOR: - crt->mLocators.insert( - RsUrl(std::string(reinterpret_cast(buf), s))); - break; - default: - RsWarn() << __PRETTY_FUNCTION__ << " unknwown ptag: " - << static_cast(ptag) - << " in certificate! Ignoring it." << std::endl; - break; - } - - buf = &buf[s]; - total_s += s; - } - - if(!checksum_check_passed) - { - err_code = CERTIFICATE_PARSING_ERROR_MISSING_CHECKSUM; - return nullptr; - } - - if(certificate_version != CERTIFICATE_VERSION_06) - { - err_code = CERTIFICATE_PARSING_ERROR_WRONG_VERSION; - return nullptr; - } - - Dbg3() << __PRETTY_FUNCTION__ << " Certificate version: " - << static_cast(certificate_version) << std::endl; - - if(total_s != size) - RsWarn() << __PRETTY_FUNCTION__ << " Certificate contains trailing " - << "characters. Weird." << std::endl; - - return crt; // Implicit move semantic -} - -std::string RsCertificate::hidden_node_string() const -{ - if ((!only_pgp) && (hidden_node)) - { - return hidden_node_address; - } - - std::string empty; - return empty; -} - -std::string RsCertificate::ext_ip_string() const -{ - std::ostringstream os ; - os << (int)ipv4_external_ip_and_port[0] << "." << (int)ipv4_external_ip_and_port[1] << "." << (int)ipv4_external_ip_and_port[2] << "." << (int)ipv4_external_ip_and_port[3] ; - return os.str() ; -} - -std::string RsCertificate::loc_ip_string() const -{ - std::ostringstream os ; - os << (int)ipv4_internal_ip_and_port[0] << "." << (int)ipv4_internal_ip_and_port[1] << "." << (int)ipv4_internal_ip_and_port[2] << "." << (int)ipv4_internal_ip_and_port[3] ; - return os.str() ; -} - -unsigned short RsCertificate::ext_port_us() const -{ - return (int)ipv4_external_ip_and_port[4]*256 + (int)ipv4_external_ip_and_port[5] ; -} - -unsigned short RsCertificate::loc_port_us() const -{ - return (int)ipv4_internal_ip_and_port[4]*256 + (int)ipv4_internal_ip_and_port[5] ; -} - -bool RsCertificate::cleanCertificate( const std::string& input, std::string& output, Format& format, uint32_t& error_code, bool check_content, RsPeerDetails& details) -{ - if(cleanRadix64(input,output,error_code)) - { - - if(rsPeers->parseShortInvite(output,details,error_code)) - { - format = RS_CERTIFICATE_SHORT_RADIX; - return true; - } - - //Clear details. As parseShortInvite may make it dirty. - details = RsPeerDetails(); - format = RS_CERTIFICATE_RADIX; - - if(!check_content) return true; - - return rsPeers->loadDetailsFromStringCert(input,details,error_code); - } - - return false; -} - -std::string RsCertificate::armouredPGPKey() const -{ - return PGPKeyManagement::makeArmouredKey(binary_pgp_key,binary_pgp_key_size,pgp_version) ; -} - -// Yeah, this is simple, and that is what's good about the radix format. Can't be broken ;-) -// -bool RsCertificate::cleanRadix64(const std::string& instr,std::string& str,uint32_t& error_code) -{ - error_code = RS_PEER_CERT_CLEANING_CODE_NO_ERROR ; - - // 0 - clean the string and check that it is pure radix64 - // - for(uint32_t i=0;i bf = Radix64::decode(rsInvite); - size_t size = bf.size(); - - unsigned char* buf = bf.data(); - size_t total_s = 0; - bool CRC_ok = false ; // not checked yet - - while(total_s < size) - { - RsShortInviteFieldType ptag = RsShortInviteFieldType(buf[0]); - buf = &buf[1]; - - unsigned char *buf2 = buf; - uint32_t s = 0; - - try { s = PGPKeyParser::read_125Size(buf); } - catch (...) - { - err_code = CERTIFICATE_PARSING_ERROR_SIZE_ERROR; - return false; - } - - total_s += 1 + ( reinterpret_cast(buf) - reinterpret_cast(buf2) ); - - if(total_s > size) - { - err_code = CERTIFICATE_PARSING_ERROR_SIZE_ERROR; - return false; - } - - Dbg3() << __PRETTY_FUNCTION__ << " Read ptag: " - << static_cast(ptag) - << ", size " << s << ", total_s = " << total_s - << ", expected total = " << size << std::endl; - - switch(ptag) - { - case RsShortInviteFieldType::SSL_ID: - details.id = RsPeerId::fromBufferUnsafe(buf) ; - break; - - case RsShortInviteFieldType::PEER_NAME: - details.name = std::string((char*)buf,s); - break; - - case RsShortInviteFieldType::PGP_FINGERPRINT: - details.fpr = RsPgpFingerprint::fromBufferUnsafe(buf); - details.gpg_id = PGPHandler::pgpIdFromFingerprint(details.fpr); - break; - - case RsShortInviteFieldType::LOCATOR: - { - std::string locatorStr((char*)buf,s); - details.ipAddressList.push_back(locatorStr); - } - break; - - case RsShortInviteFieldType::DNS_LOCATOR: - details.extPort = (((int)buf[0]) << 8) + buf[1]; - details.dyndns = std::string((char*)&buf[2],s-2); - break; - - case RsShortInviteFieldType::LOC4_LOCATOR: - { - uint32_t t4Addr = (((uint32_t)buf[0]) << 24)+(((uint32_t)buf[1])<<16)+(((uint32_t)buf[2])<<8) + (uint32_t)buf[3]; - sockaddr_in tLocalAddr; - tLocalAddr.sin_addr.s_addr = t4Addr; - - details.localAddr = rs_inet_ntoa(tLocalAddr.sin_addr); - details.localPort = (((uint32_t)buf[4])<<8) + (uint32_t)buf[5]; - } - break; - - case RsShortInviteFieldType::EXT4_LOCATOR: - { - uint32_t t4Addr = (((uint32_t)buf[0]) << 24)+(((uint32_t)buf[1])<<16)+(((uint32_t)buf[2])<<8) + (uint32_t)buf[3]; - sockaddr_in tExtAddr; - tExtAddr.sin_addr.s_addr = t4Addr; - - details.extAddr = rs_inet_ntoa(tExtAddr.sin_addr); - details.extPort = (((uint32_t)buf[4])<<8) + (uint32_t)buf[5]; - } - break; - - case RsShortInviteFieldType::HIDDEN_LOCATOR: - details.hiddenType = (((uint32_t)buf[0]) << 24)+(((uint32_t)buf[1])<<16)+(((uint32_t)buf[2])<<8) + (uint32_t)buf[3]; - details.hiddenNodePort = (((uint32_t)buf[4]) << 8)+ (uint32_t)buf[5]; - details.isHiddenNode = true; - details.hiddenNodeAddress = std::string((char*)&buf[6],s-6); - break; - - case RsShortInviteFieldType::CHECKSUM: - { - if(s != 3 || total_s+3 != size) // make sure the checksum is the last section - { - err_code = CERTIFICATE_PARSING_ERROR_INVALID_CHECKSUM_SECTION; - return false; - } - uint32_t computed_crc = PGPKeyManagement::compute24bitsCRC(bf.data(),size-5); - uint32_t certificate_crc = static_cast( buf[0] + (buf[1] << 8) + (buf[2] << 16) ); - - if(computed_crc != certificate_crc) - { - err_code = CERTIFICATE_PARSING_ERROR_CHECKSUM_ERROR; - return false; - } - CRC_ok = true; - break; - } - - } - - buf = &buf[s]; - total_s += s; - } - - if(details.id.isNull()) - { - err_code = CERTIFICATE_PARSING_ERROR_MISSING_LOCATION_ID; - return false; - } - if(!CRC_ok) - { - err_code = CERTIFICATE_PARSING_ERROR_CHECKSUM_ERROR; - return false; - } - - return true; -} - - - - - - - diff --git a/libretroshare/src/pgp/rscertificate.h b/libretroshare/src/pgp/rscertificate.h deleted file mode 100644 index 28e3c2bae..000000000 --- a/libretroshare/src/pgp/rscertificate.h +++ /dev/null @@ -1,156 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pgp: rscertificate.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016 Cyril Soler * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include "retroshare/rstypes.h" -#include "util/rsurl.h" -#include "util/rsmemory.h" -#include "util/rsdebug.h" - -#include -#include -#include - -struct RsPeerDetails; - -class RsCertificate -{ -public: - enum class RsShortInviteFieldType : uint8_t - { - SSL_ID = 0x00, - PEER_NAME = 0x01, - LOCATOR = 0x02, - PGP_FINGERPRINT = 0x03, - CHECKSUM = 0x04, - - /* The following will be deprecated, and ported to LOCATOR when generic transport layer will be implemented */ - HIDDEN_LOCATOR = 0x90, - DNS_LOCATOR = 0x91, - EXT4_LOCATOR = 0x92, // external IPv4 address - LOC4_LOCATOR = 0x93 // local IPv4 address - }; - - typedef enum { RS_CERTIFICATE_OLD_FORMAT, RS_CERTIFICATE_RADIX, RS_CERTIFICATE_SHORT_RADIX } Format; - - /** - * @brief Create certificate object from certificate string - * @param[in] str radix format certificate string - * @param[out] errorCode Optional storage for eventual error code, - * meaningful only on failure - * @return nullptr on failure, pointer to the generated certificate - * otherwise - */ - static std::unique_ptr fromString( - const std::string& str, - uint32_t& errorCode = RS_DEFAULT_STORAGE_PARAM(uint32_t) ); - - /** - * @brief Create certificate object from peer details and PGP memory block - * @param[in] details peer details - * @param[in] binary_pgp_block pointer to PGP memory block - * @param[in] binary_pgp_block_size size of PGP memory block - * @return nullptr on failure, pointer to the generated certificate - * otherwise - */ - static std::unique_ptr fromMemoryBlock( - const RsPeerDetails& details, const uint8_t* binary_pgp_block, - size_t binary_pgp_block_size ); - - ~RsCertificate(); - - static bool decodeRadix64ShortInvite(const std::string& short_invite_b64,RsPeerDetails& det,uint32_t& error_code); - - /// Convert to certificate radix string - std::string toStdString() const; - - std::string ext_ip_string() const; - std::string loc_ip_string() const; - std::string location_name_string() const { return location_name; } - std::string dns_string() const { return dns_name ; } - RsPeerId sslid() const { return location_id ; } - std::string hidden_node_string() const; - - std::string armouredPGPKey() const; - - unsigned short ext_port_us() const; - unsigned short loc_port_us() const; - - const unsigned char *pgp_key() const { return binary_pgp_key ; } - size_t pgp_key_size() const { return binary_pgp_key_size ; } - - static bool cleanCertificate( - const std::string& input, std::string& output, - RsCertificate::Format& format, uint32_t& error_code, bool check_content, RsPeerDetails& details); - - const std::set& locators() const { return mLocators; } - - /** - * @deprecated using this costructor may raise exception that cause - * crash if not handled. - */ - RS_DEPRECATED_FOR("RsCertificate::fromMemoryBlock(...)") - RsCertificate( const RsPeerDetails& details, - const unsigned char *gpg_mem_block, - size_t gpg_mem_block_size ); - -private: - // new radix format - static bool cleanRadix64(const std::string& input, std::string& output, uint32_t &); - - static void scan_ip( const std::string& ip_string, unsigned short port, - unsigned char *destination_memory ); - - static void addPacket(uint8_t ptag, const unsigned char *mem, size_t size, - unsigned char*& buf, size_t& offset, size_t& buf_size); - - RsCertificate(const RsCertificate&) {} /// non copy-able - const RsCertificate& operator=(const RsCertificate&); /// non copy-able - - /// @brief Costruct an empty certificate - RsCertificate() : - ipv4_external_ip_and_port{0,0,0,0,0,0}, - ipv4_internal_ip_and_port{0,0,0,0,0,0}, - binary_pgp_key(nullptr), binary_pgp_key_size(0), - pgp_version("Version: OpenPGP:SDK v0.9"), only_pgp(true), - hidden_node(false) {} - - unsigned char ipv4_external_ip_and_port[6]; - unsigned char ipv4_internal_ip_and_port[6]; - - unsigned char *binary_pgp_key; - size_t binary_pgp_key_size; - - std::string location_name; - RsPeerId location_id; - std::string pgp_version; - std::string dns_name; - std::string hidden_node_address; - std::set mLocators; - - bool only_pgp ; /// does the cert contain only pgp info? - bool hidden_node; /// IP or hidden Node Address. - - RS_SET_CONTEXT_DEBUG_LEVEL(1) -}; - diff --git a/libretroshare/src/plugins/dlfcn_win32.cc b/libretroshare/src/plugins/dlfcn_win32.cc deleted file mode 100644 index b669cfa54..000000000 --- a/libretroshare/src/plugins/dlfcn_win32.cc +++ /dev/null @@ -1,322 +0,0 @@ -/******************************************************************************* - * libretroshare/src/plugins: dlfcn_win32.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007 Ramiro Polla * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifdef WINDOWS_SYS - -#include -#include -#include - -#include "dlfcn_win32.h" - -/* Note: - * MSDN says these functions are not thread-safe. We make no efforts to have - * any kind of thread safety. - */ - -typedef struct global_object { - HMODULE hModule; - struct global_object *previous; - struct global_object *next; -} global_object; - -static global_object first_object; - -/* These functions implement a double linked list for the global objects. */ -static global_object *global_search( HMODULE hModule ) -{ - global_object *pobject; - - if( hModule == NULL ) - return NULL; - - for( pobject = &first_object; pobject ; pobject = pobject->next ) - if( pobject->hModule == hModule ) - return pobject; - - return NULL; -} - -static void global_add( HMODULE hModule ) -{ - global_object *pobject; - global_object *nobject; - - if( hModule == NULL ) - return; - - pobject = global_search( hModule ); - - /* Do not add object again if it's already on the list */ - if( pobject ) - return; - - for( pobject = &first_object; pobject->next ; pobject = pobject->next ); - - nobject = (global_object*) malloc( sizeof(global_object) ); - - /* Should this be enough to fail global_add, and therefore also fail - * dlopen? - */ - if( !nobject ) - return; - - pobject->next = nobject; - nobject->next = NULL; - nobject->previous = pobject; - nobject->hModule = hModule; -} - -static void global_rem( HMODULE hModule ) -{ - global_object *pobject; - - if( hModule == NULL ) - return; - - pobject = global_search( hModule ); - - if( !pobject ) - return; - - if( pobject->next ) - pobject->next->previous = pobject->previous; - if( pobject->previous ) - pobject->previous->next = pobject->next; - - free( pobject ); -} - -/* POSIX says dlerror( ) doesn't have to be thread-safe, so we use one - * static buffer. - * MSDN says the buffer cannot be larger than 64K bytes, so we set it to - * the limit. - */ -static char error_buffer[65535]; -static char *current_error; - -static int copy_string( char *dest, int dest_size, const char *src ) -{ - int i = 0; - - /* gcc should optimize this out */ - if( !src && !dest ) - return 0; - - for( i = 0 ; i < dest_size-1 ; i++ ) - { - if( !src[i] ) - break; - else - dest[i] = src[i]; - } - dest[i] = '\0'; - - return i; -} - -static void save_err_str( const char *str ) -{ - DWORD dwMessageId; - DWORD pos; - - dwMessageId = GetLastError( ); - - if( dwMessageId == 0 ) - return; - - /* Format error message to: - * "": - */ - pos = copy_string( error_buffer, sizeof(error_buffer), "\"" ); - pos += copy_string( error_buffer+pos, sizeof(error_buffer)-pos, str ); - pos += copy_string( error_buffer+pos, sizeof(error_buffer)-pos, "\": " ); - pos += FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwMessageId, - MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), - error_buffer+pos, sizeof(error_buffer)-pos, NULL ); - - if( pos > 1 ) - { - /* POSIX says the string must not have trailing */ - if( error_buffer[pos-2] == '\r' && error_buffer[pos-1] == '\n' ) - error_buffer[pos-2] = '\0'; - } - - current_error = error_buffer; -} - -static void save_err_ptr_str( const void *ptr ) -{ - char ptr_buf[19]; /* 0x up to 64 bits. */ - - sprintf( ptr_buf, "0x%p", ptr ); - - save_err_str( ptr_buf ); -} - -void *dlopen( const char *file, int mode ) -{ - HMODULE hModule; - UINT uMode; - - current_error = NULL; - - /* Do not let Windows display the critical-error-handler message box */ - uMode = SetErrorMode( SEM_FAILCRITICALERRORS ); - - if( file == 0 ) - { - /* POSIX says that if the value of file is 0, a handle on a global - * symbol object must be provided. That object must be able to access - * all symbols from the original program file, and any objects loaded - * with the RTLD_GLOBAL flag. - * The return value from GetModuleHandle( ) allows us to retrieve - * symbols only from the original program file. For objects loaded with - * the RTLD_GLOBAL flag, we create our own list later on. - */ - hModule = GetModuleHandle( NULL ); - - if( !hModule ) - save_err_ptr_str( file ); - } - else - { - char lpFileName[MAX_PATH]; - unsigned int i; - - /* MSDN says backslashes *must* be used instead of forward slashes. */ - for( i = 0 ; i < sizeof(lpFileName)-1 ; i++ ) - { - if( !file[i] ) - break; - else if( file[i] == '/' ) - lpFileName[i] = '\\'; - else - lpFileName[i] = file[i]; - } - lpFileName[i] = '\0'; - - /* POSIX says the search path is implementation-defined. - * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely - * to UNIX's search paths (start with system folders instead of current - * folder). - */ - hModule = LoadLibraryExA( (LPSTR) lpFileName, NULL, - LOAD_WITH_ALTERED_SEARCH_PATH ); - - /* If the object was loaded with RTLD_GLOBAL, add it to list of global - * objects, so that its symbols may be retrieved even if the handle for - * the original program file is passed. POSIX says that if the same - * file is specified in multiple invocations, and any of them are - * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the - * symbols will remain global. - */ - if( !hModule ) - save_err_str( lpFileName ); - else if( (mode & RTLD_GLOBAL) ) - global_add( hModule ); - } - - /* Return to previous state of the error-mode bit flags. */ - SetErrorMode( uMode ); - - return (void *) hModule; -} - -int dlclose( void *handle ) -{ - HMODULE hModule = (HMODULE) handle; - BOOL ret; - - current_error = NULL; - - ret = FreeLibrary( hModule ); - - /* If the object was loaded with RTLD_GLOBAL, remove it from list of global - * objects. - */ - if( ret ) - global_rem( hModule ); - else - save_err_ptr_str( handle ); - - /* dlclose's return value in inverted in relation to FreeLibrary's. */ - ret = !ret; - - return (int) ret; -} - -void *dlsym( void *handle, const char *name ) -{ - FARPROC symbol; - - current_error = NULL; - - symbol = GetProcAddress( (HINSTANCE) handle, name ); - - if( symbol == NULL ) - { - HMODULE hModule; - - /* If the handle for the original program file is passed, also search - * in all globally loaded objects. - */ - - hModule = GetModuleHandle( NULL ); - - if( hModule == handle ) - { - global_object *pobject; - - for( pobject = &first_object; pobject ; pobject = pobject->next ) - { - if( pobject->hModule ) - { - symbol = GetProcAddress( pobject->hModule, name ); - if( symbol != NULL ) - break; - } - } - } - - // Do not close the handle of the calling process -// CloseHandle( hModule ); - } - - if( symbol == NULL ) - save_err_str( name ); - - return (void*) symbol; -} - -char *dlerror( void ) -{ - char *error_pointer = current_error; - - /* POSIX says that invoking dlerror( ) a second time, immediately following - * a prior invocation, shall result in NULL being returned. - */ - current_error = NULL; - - return error_pointer; -} -#endif diff --git a/libretroshare/src/plugins/dlfcn_win32.h b/libretroshare/src/plugins/dlfcn_win32.h deleted file mode 100644 index 3298777dd..000000000 --- a/libretroshare/src/plugins/dlfcn_win32.h +++ /dev/null @@ -1,51 +0,0 @@ -/******************************************************************************* - * libretroshare/src/plugins: dlfcn_win32.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007 Ramiro Polla * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#ifdef WINDOWS_SYS -#ifndef DLFCN_H -#define DLFCN_H - -/* POSIX says these are implementation-defined. - * To simplify use with Windows API, we treat them the same way. - */ - -#define RTLD_LAZY 0 -#define RTLD_NOW 0 - -#define RTLD_GLOBAL (1 << 1) -#define RTLD_LOCAL (1 << 2) - -/* These two were added in The Open Group Base Specifications Issue 6. - * Note: All other RTLD_* flags in any dlfcn.h are not standard compliant. - */ - -#define RTLD_DEFAULT 0 -#define RTLD_NEXT 0 - -void *dlopen ( const char *file, int mode ); -int dlclose( void *handle ); -void *dlsym ( void *handle, const char *name ); -char *dlerror( void ); - -#endif /* DLFCN_H */ -#endif /* WINDOWS_SYS */ diff --git a/libretroshare/src/plugins/pluginmanager.cc b/libretroshare/src/plugins/pluginmanager.cc deleted file mode 100644 index dcd474f8f..000000000 --- a/libretroshare/src/plugins/pluginmanager.cc +++ /dev/null @@ -1,586 +0,0 @@ -/******************************************************************************* - * libretroshare/src/plugins: pluginmanager.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include - -#include "pluginmanager.h" -#include - -#if 0 -#include -#include -#include -#endif - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// lets disable the plugin system for now, as it's unfinished. -#ifdef WINDOWS_SYS -#include "dlfcn_win32.h" -#else -#include -#endif - -// #define DEBUG_PLUGIN_MANAGER 1 - -std::string RsPluginManager::_plugin_entry_symbol = "RETROSHARE_PLUGIN_provide" ; -std::string RsPluginManager::_plugin_revision_symbol = "RETROSHARE_PLUGIN_revision" ; -std::string RsPluginManager::_plugin_API_symbol = "RETROSHARE_PLUGIN_api" ; - -std::string RsPluginManager::_local_cache_dir ; -std::string RsPluginManager::_remote_cache_dir ; -std::vector RsPluginManager::_plugin_directories ; - -RsServiceControl *RsPluginManager::_service_control = NULL ; - -typedef RsPlugin *(*RetroSharePluginEntry)(void) ; -RsPluginHandler *rsPlugins ; - -RsPluginManager::RsPluginManager(const RsFileHash &hash) - : p3Config(),_current_executable_hash(hash) -{ - _allow_all_plugins = false ; -} - -bool RsPluginManager::loadConfiguration(RsFileHash &loadHash) -{ - return p3Config::loadConfiguration(loadHash); -} - -void RsPluginManager::loadConfiguration() -{ - RsFileHash dummyHash; - p3Config::loadConfiguration(dummyHash); -} - -void RsPluginManager::setInterfaces(RsPlugInInterfaces &interfaces) -{ - std::cerr << "RsPluginManager::setInterfaces() " << std::endl; - - for(uint32_t i=0;i<_plugins.size();++i) - if(_plugins[i].plugin != NULL) - { - std::cerr << " setting iterface for plugin " << _plugins[i].plugin->getPluginName() << ", with RS_ID " << _plugins[i].plugin->rs_service_id() << std::endl ; - _plugins[i].plugin->setInterfaces(interfaces); - } -} - -void RsPluginManager::setCacheDirectories(const std::string& local_cache, const std::string& remote_cache) -{ - _local_cache_dir = local_cache ; - _remote_cache_dir = remote_cache ; -} - -bool RsPluginManager::acceptablePluginName(const std::string& name) -{ - // Needs some windows specific code here - // -#ifdef WINDOWS_SYS - return name.size() > 4 && name.substr(name.size() - 4) == ".dll"; -#elif defined(__MACH__) - return name.size() > 6 && !strcmp(name.c_str()+name.size()-6,".dylib") ; -#else - return name.size() > 3 && !strcmp(name.c_str()+name.size()-3,".so") ; -#endif -} - -void RsPluginManager::disablePlugin(const RsFileHash& hash) -{ - std::set::iterator it = _accepted_hashes.find(hash) ; - - if(it != _accepted_hashes.end()) - { - std::cerr << "RsPluginManager::disablePlugin(): removing hash " << hash << " from white list" << std::endl; - - _accepted_hashes.erase(it) ; - IndicateConfigChanged() ; - } - if(_rejected_hashes.find(hash) == _rejected_hashes.end()) - { - std::cerr << "RsPluginManager::enablePlugin(): inserting hash " << hash << " in black list" << std::endl; - - _rejected_hashes.insert(hash) ; - IndicateConfigChanged() ; - } -} - -void RsPluginManager::enablePlugin(const RsFileHash& hash) -{ - if(_accepted_hashes.find(hash) == _accepted_hashes.end()) - { - std::cerr << "RsPluginManager::enablePlugin(): inserting hash " << hash << " in white list" << std::endl; - - _accepted_hashes.insert(hash) ; - IndicateConfigChanged() ; - } - std::set::const_iterator it(_rejected_hashes.find(hash)) ; - - if(it != _rejected_hashes.end()) - { - std::cerr << "RsPluginManager::enablePlugin(): removing hash " << hash << " from black list" << std::endl; - - _rejected_hashes.erase(it) ; - IndicateConfigChanged() ; - } -} - -void RsPluginManager::loadPlugins(const std::vector& plugin_directories) -{ - _plugin_directories = plugin_directories ; - _plugin_entry_symbol = "RETROSHARE_PLUGIN_provide" ; - _plugin_revision_symbol = "RETROSHARE_PLUGIN_revision" ; - - // 0 - get the list of files to read - - bool first_time = (_accepted_hashes.empty()) && _rejected_hashes.empty() ; - - for(uint32_t i=0;ip3_service(); - if (service) - { - pqih->removeService(service); - } - - _plugins[i].plugin->stop(); - delete _plugins[i].plugin; - _plugins[i].plugin = NULL; - } - if (_plugins[i].handle) - { - dlclose(_plugins[i].handle); - _plugins[i].handle = NULL; - } - } -} - -void RsPluginManager::getPluginStatus(int i,uint32_t& status,std::string& file_name,RsFileHash &hash,uint32_t& svn_revision,std::string& error_string) const -{ - if((uint32_t)i >= _plugins.size()) - return ; - - status = _plugins[i].status ; - error_string = _plugins[i].info_string ; - hash = _plugins[i].file_hash ; - file_name = _plugins[i].file_name ; - svn_revision = _plugins[i].svn_revision ; -} - -bool RsPluginManager::getAllowAllPlugins() const -{ - return _allow_all_plugins ; -} -void RsPluginManager::allowAllPlugins(bool b) -{ - _allow_all_plugins = b ; - IndicateConfigChanged() ; -} -RsSerialiser *RsPluginManager::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser ; - rss->addSerialType(new RsPluginSerialiser()) ; - rss->addSerialType(new RsGeneralConfigSerialiser()) ; - - return rss ; -} - -void RsPluginManager::loadPlugins(const std::vector& plugins) -{ - for(uint32_t i=0;isetPlugInHandler(this); // WIN fix, cannot share global space with shared libraries - - // The following choice is conservative by forcing RS to resolve all dependencies at - // the time of loading the plugin. - - pinfo.status = PLUGIN_STATUS_LOADED ; - - _plugins.push_back(pinfo) ; - return true; -} - -bool RsPluginManager::loadPlugin(const std::string& plugin_name,bool first_time) -{ - std::cerr << " Loading plugin " << plugin_name << std::endl; - - PluginInfo pf ; - pf.plugin = NULL ; - pf.file_name = plugin_name ; - pf.info_string = "" ; - std::cerr << " -> hashing." << std::endl; - uint64_t size ; - - // Stage 1 - get information related to file (hash, name, ...) - // - if(!RsDirUtil::getFileHash(plugin_name,pf.file_hash,size)) - { - std::cerr << " -> cannot hash file. Plugin read canceled." << std::endl; - return false; - } - - _plugins.push_back(pf) ; - PluginInfo& pinfo(_plugins.back()) ; - - std::cerr << " -> hash = " << pinfo.file_hash << std::endl; - - if(!_allow_all_plugins) - { - if(_accepted_hashes.find(pinfo.file_hash) == _accepted_hashes.end() && _rejected_hashes.find(pinfo.file_hash) == _rejected_hashes.end() ) - if(!RsServer::notify()->askForPluginConfirmation(pinfo.file_name,pinfo.file_hash.toStdString(),first_time)) - _rejected_hashes.insert(pinfo.file_hash) ; // accepted hashes are treated at the end, for security. - - if(_rejected_hashes.find(pinfo.file_hash) != _rejected_hashes.end() ) - { - pinfo.status = PLUGIN_STATUS_REJECTED_HASH ; - std::cerr << " -> hash rejected. Giving up plugin. " << std::endl; - return false ; - } - } - else - std::cerr << " -> ALLOW_ALL_PLUGINS Enabled => plugin loaded by default." << std::endl; - - std::cerr << " -> hash authorized. Loading plugin. " << std::endl; - - // Stage 2 - open with dlopen, and get some basic info. - // - - // The following choice is conservative by forcing RS to resolve all dependencies at - // the time of loading the plugin. - - int link_mode = RTLD_NOW | RTLD_GLOBAL ; - - void *handle = dlopen(plugin_name.c_str(),link_mode) ; - - if(handle == NULL) - { - const char *val = dlerror() ; - std::cerr << " Cannot open plugin: " << val << std::endl ; - pinfo.status = PLUGIN_STATUS_DLOPEN_ERROR ; - pinfo.info_string = val ; - return false ; - } - - void *prev = dlsym(handle,_plugin_revision_symbol.c_str()) ; pinfo.svn_revision = (prev == NULL) ? 0 : (*(uint32_t *)prev) ; - void *papi = dlsym(handle,_plugin_API_symbol.c_str()) ; pinfo.API_version = (papi == NULL) ? 0 : (*(uint32_t *)papi) ; - - std::cerr << " -> plugin revision number: " << pinfo.svn_revision << std::endl; - std::cerr << " plugin API number : " << std::hex << pinfo.API_version << std::dec << std::endl; - - // Check that the plugin provides a svn revision number and a API number - // - if(pinfo.API_version == 0) - { - std::cerr << " -> No API version number." << std::endl; - pinfo.status = PLUGIN_STATUS_MISSING_API ; - pinfo.info_string = "" ; - dlclose(handle); - return false ; - } -#ifdef TO_REMOVE - if(pinfo.svn_revision == 0) - { - std::cerr << " -> No svn revision number." << std::endl; - pinfo.status = PLUGIN_STATUS_MISSING_SVN ; - pinfo.info_string = "" ; - dlclose(handle); - return false ; - } -#endif - - // Now look for the plugin class symbol. - // - void *pfe = dlsym(handle,_plugin_entry_symbol.c_str()) ; - - if(pfe == NULL) - { - std::cerr << dlerror() << std::endl ; - pinfo.status = PLUGIN_STATUS_MISSING_SYMBOL ; - pinfo.info_string = _plugin_entry_symbol ; - dlclose(handle); - return false ; - } - std::cerr << " -> Added function entry for symbol " << _plugin_entry_symbol << std::endl ; - - RsPlugin *p = ( (*(RetroSharePluginEntry)pfe)() ) ; - - if(p == NULL) - { - std::cerr << " Plugin entry function " << _plugin_entry_symbol << " returns NULL ! It should return an object of type RsPlugin* " << std::endl; - pinfo.status = PLUGIN_STATUS_NULL_PLUGIN ; - pinfo.info_string = "Plugin entry " + _plugin_entry_symbol + "() return NULL" ; - dlclose(handle); - return false ; - } - - pinfo.status = PLUGIN_STATUS_LOADED ; - pinfo.plugin = p ; - pinfo.handle = handle; - p->setPlugInHandler(this); // WIN fix, cannot share global space with shared libraries - pinfo.info_string = "" ; - - _accepted_hashes.insert(pinfo.file_hash) ; // do it now, to avoid putting in list a plugin that might have crashed during the load. - return true; -} - -const std::string& RsPluginManager::getLocalCacheDir() const -{ - assert(!_local_cache_dir.empty()) ; - return _local_cache_dir ; -} -const std::string& RsPluginManager::getRemoteCacheDir() const -{ - assert(!_remote_cache_dir.empty()) ; - return _remote_cache_dir ; -} -RsServiceControl *RsPluginManager::getServiceControl() const -{ - assert(_service_control); - return _service_control ; -} -void RsPluginManager::slowTickPlugins(rstime_t seconds) -{ - for(uint32_t i=0;i<_plugins.size();++i) - if(_plugins[i].plugin != NULL && _plugins[i].plugin->rs_cache_service() != NULL && (seconds % _plugins[i].plugin->rs_cache_service()->tickDelay() )) - { -#ifdef DEBUG_PLUGIN_MANAGER - std::cerr << " ticking plugin " << _plugins[i].plugin->getPluginName() << std::endl; -#endif - _plugins[i].plugin->rs_cache_service()->tick() ; - } -} - -void RsPluginManager::registerCacheServices() -{ - // this is removed since the old cache syste is gone, but we need to make it register new GXS group services instead. -#ifdef REMOVED - std::cerr << " Registering cache services." << std::endl; - - for(uint32_t i=0;i<_plugins.size();++i) - if(_plugins[i].plugin != NULL && _plugins[i].plugin->rs_cache_service() != NULL) - { - //rsFiles->getCacheStrapper()->addCachePair(CachePair(_plugins[i].plugin->rs_cache_service(),_plugins[i].plugin->rs_cache_service(),CacheId(_plugins[i].plugin->rs_service_id(), 0))) ; - std::cerr << " adding new cache pair for plugin " << _plugins[i].plugin->getPluginName() << ", with RS_ID " << _plugins[i].plugin->rs_service_id() << std::endl ; - } -#endif -} - -void RsPluginManager::registerClientServices(p3ServiceServer *pqih) -{ - std::cerr << " Registering pqi services." << std::endl; - - for(uint32_t i=0;i<_plugins.size();++i) - //if(_plugins[i].plugin != NULL && _plugins[i].plugin->rs_pqi_service() != NULL) - if(_plugins[i].plugin != NULL && _plugins[i].plugin->p3_service() != NULL) - { - //pqih->addService(_plugins[i].plugin->rs_pqi_service(), true) ; - pqih->addService(_plugins[i].plugin->p3_service(), true) ; - std::cerr << " Added pqi service for plugin " << _plugins[i].plugin->getPluginName() << std::endl; - } -} - -void RsPluginManager::addConfigurations(p3ConfigMgr *ConfigMgr) -{ - std::cerr << " Registering configuration files." << std::endl; - - for(uint32_t i=0;i<_plugins.size();++i) - if(_plugins[i].plugin != NULL && _plugins[i].plugin->configurationFileName().length() > 0) - { - if( _plugins[i].plugin->rs_cache_service() != NULL) - ConfigMgr->addConfiguration(_plugins[i].plugin->configurationFileName(), _plugins[i].plugin->rs_cache_service()); - //else if(_plugins[i].plugin->rs_pqi_service() != NULL) - // ConfigMgr->addConfiguration(_plugins[i].plugin->configurationFileName(), _plugins[i].plugin->rs_pqi_service()); - else if(_plugins[i].plugin->p3_config() != NULL) - ConfigMgr->addConfiguration(_plugins[i].plugin->configurationFileName(), _plugins[i].plugin->p3_config()); - else - continue ; - - std::cerr << " Added configuration for plugin " << _plugins[i].plugin->getPluginName() << ", with file " << _plugins[i].plugin->configurationFileName() << std::endl; - } -} - -bool RsPluginManager::loadList(std::list& list) -{ - std::set accepted_hash_candidates ; - std::set rejected_hash_candidates ; - - std::cerr << "RsPluginManager::loadList(): " << std::endl; - RsFileHash reference_executable_hash ; - - std::list::iterator it; - for(it = list.begin(); it != list.end(); ++it) - { - RsConfigKeyValueSet *witem = dynamic_cast(*it) ; - - if(witem) - for(std::list::const_iterator kit = witem->tlvkvs.pairs.begin(); kit != witem->tlvkvs.pairs.end(); ++kit) - { - if((*kit).key == "ALLOW_ALL_PLUGINS") - { - _allow_all_plugins = (kit->value == "YES"); - - if(_allow_all_plugins) - std::cerr << "WARNING: Allowing all plugins. No hash will be checked. Be careful! " << std::endl ; - } - else if((*kit).key == "REFERENCE_EXECUTABLE_HASH") - { - reference_executable_hash = RsFileHash(kit->value) ; - std::cerr << " Reference executable hash: " << kit->value << std::endl; - } - else if((*kit).key == "ACCEPTED") - { - accepted_hash_candidates.insert(RsFileHash((*kit).value)) ; - std::cerr << " Accepted hash: " << (*kit).value << std::endl; - } - else if((*kit).key == "REJECTED") - { - rejected_hash_candidates.insert(RsFileHash((*kit).value)) ; - std::cerr << " Rejected hash: " << (*kit).value << std::endl; - } - } - - delete (*it); - } - - // Rejected hashes are always kept, so that RS wont ask again if the executable hash has changed. - // - _rejected_hashes = rejected_hash_candidates ; - - if(reference_executable_hash == _current_executable_hash) - { - std::cerr << "(II) Executable hash matches. Updating the list of accepted/rejected plugins." << std::endl; - - _accepted_hashes = accepted_hash_candidates ; - } - else - std::cerr << "(WW) Executable hashes do not match. Executable hash has changed. Discarding the list of accepted/rejected plugins." << std::endl; - - return true; -} - -bool RsPluginManager::saveList(bool& cleanup, std::list& list) -{ - std::cerr << "PluginManager: saving list." << std::endl; - cleanup = true ; - - RsConfigKeyValueSet *witem = new RsConfigKeyValueSet ; - RsTlvKeyValue kv; - kv.key = "ALLOW_ALL_PLUGINS" ; - kv.value = _allow_all_plugins?"YES":"NO" ; - witem->tlvkvs.pairs.push_back(kv) ; - - kv.key = "REFERENCE_EXECUTABLE_HASH" ; - kv.value = _current_executable_hash.toStdString() ; - witem->tlvkvs.pairs.push_back(kv) ; - - std::cerr << " Saving current executable hash: " << kv.value << std::endl; - - // now push accepted and rejected hashes. - - for(std::set::const_iterator it(_accepted_hashes.begin());it!=_accepted_hashes.end();++it) - { - witem->tlvkvs.pairs.push_back( RsTlvKeyValue( "ACCEPTED", (*it).toStdString() ) ) ; - std::cerr << " " << *it << " : " << "ACCEPTED" << std::endl; - } - - for(std::set::const_iterator it(_rejected_hashes.begin());it!=_rejected_hashes.end();++it) - { - witem->tlvkvs.pairs.push_back( RsTlvKeyValue( "REJECTED", (*it).toStdString() ) ) ; - std::cerr << " " << *it << " : " << "REJECTED" << std::endl; - } - - list.push_back(witem) ; - - return true; -} - -RsPQIService::RsPQIService(uint16_t /*service_type*/, uint32_t /*tick_delay_in_seconds*/, RsPluginHandler* /*pgHandler*/) - : p3Service(),p3Config() -{ -} - diff --git a/libretroshare/src/plugins/pluginmanager.h b/libretroshare/src/plugins/pluginmanager.h deleted file mode 100644 index 965706bf1..000000000 --- a/libretroshare/src/plugins/pluginmanager.h +++ /dev/null @@ -1,159 +0,0 @@ -/******************************************************************************* - * libretroshare/src/plugins: pluginmanager.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include -#include - -class p3ConfigMgr ; -class p3ServiceServer ; -class p3LinkMgr ; - -class PluginInfo -{ -public: - PluginInfo() : handle(NULL), plugin(NULL), API_version(0), svn_revision(0), status(0) {} - - public: - // Handle of the loaded plugin. - // - void *handle; - - // Main object provided by the plugin. NULL is the plugin could not be loaded. - // - RsPlugin *plugin ; - - // Information related to the file. Do not require the plugin to be loaded nor the DSO to be openned. - // - RsFileHash file_hash ; - std::string file_name ; - - // Information coming from directly loaded symbols. The plugin is responsible for providing them. - // - std::string creator ; // creator of the plugin - std::string name ; // name of the plugin - uint32_t API_version ; // API version. - uint32_t svn_revision ; // Coming from scripts. Same svn version but changing hash could be a security issue. - - // This info is filled when accessing the .so, and loading the plugin. - // - uint32_t status ; // See the flags in retroshare/rsplugin.h - std::string info_string ; -}; - -class RsPluginManager: public RsPluginHandler, public p3Config -{ - public: - explicit RsPluginManager(const RsFileHash& current_executable_sha1_hash) ; - virtual ~RsPluginManager() {} - - // ------------ Derived from RsPluginHandler ----------------// - // - virtual int nbPlugins() const { return _plugins.size() ; } - virtual RsPlugin *plugin(int i) { return _plugins[i].plugin ; } - virtual const std::vector& getPluginDirectories() const { return _plugin_directories ; } - virtual void getPluginStatus(int i, uint32_t& status,std::string& file_name, RsFileHash& hash,uint32_t& svn_revision,std::string& error_string) const ; - virtual void enablePlugin(const RsFileHash& hash) ; - virtual void disablePlugin(const RsFileHash &hash) ; - - virtual void slowTickPlugins(rstime_t sec) ; - virtual const std::string& getLocalCacheDir() const ; - virtual const std::string& getRemoteCacheDir() const ; - virtual RsServiceControl *getServiceControl() const ; - - virtual void allowAllPlugins(bool b) ; - virtual bool getAllowAllPlugins() const ; - - // ---------------- Derived from p3Config -------------------// - // - bool saveList(bool& cleanup, std::list& list) ; - bool loadList(std::list& list) ; - virtual RsSerialiser* setupSerialiser() ; - - // -------------------- Own members -------------------------// - // - virtual void addConfigurations(p3ConfigMgr *cfgMgr) ; - virtual bool loadConfiguration(RsFileHash &loadHash) ; - virtual void loadConfiguration() ; - - /*! - * sets interfaces for all loaded plugins - * @param interfaces - */ - void setInterfaces(RsPlugInInterfaces& interfaces); - - static bool acceptablePluginName(const std::string& s) ; - static void setCacheDirectories(const std::string& local,const std::string& remote) ; - static void setServiceControl(RsServiceControl *cm) { _service_control = cm ; } - - // Normal plugin loading system. Parses through the plugin directories and loads - // dso libraries, checks for the hash, and loads/rejects plugins according to - // the user's choice. - // - void loadPlugins(const std::vector& plugin_directories) ; - - // Explicit function to load a plugin programatically. - // No hash-checking is performed (there's no DSO file to hash!) - // Mostly convenient for insering plugins in development. - // - void loadPlugins(const std::vector& explicit_plugin_entries) ; - - void stopPlugins(p3ServiceServer *pqih); - - void registerCacheServices() ; - void registerClientServices(p3ServiceServer *pqih) ; - - private: - bool loadPlugin(RsPlugin *) ; - bool loadPlugin(const std::string& shared_library_name, bool first_time) ; - RsFileHash hashPlugin(const std::string& shared_library_name) ; - - std::vector _plugins ; - - // Should allow - // - searching - // - saving all hash - // - // At start - // * load reference executable hash. Compare with current executable. - // - if different => flush all plugin hashes from cache - // - if equal, - // - std::set _accepted_hashes ; // accepted hash values for reference executable hash. - std::set _rejected_hashes ; // rejected hash values for reference executable hash. - RsFileHash _current_executable_hash ; // At all times, the list of accepted plugins should be related to the current hash of the executable. - bool _allow_all_plugins ; - - static std::string _plugin_entry_symbol ; - static std::string _plugin_revision_symbol ; - static std::string _plugin_API_symbol ; - static std::string _remote_cache_dir ; - static std::string _local_cache_dir ; - - static RsServiceControl *_service_control ; - - static std::vector _plugin_directories ; -}; - diff --git a/libretroshare/src/plugins/rscacheservice.h b/libretroshare/src/plugins/rscacheservice.h deleted file mode 100644 index 82f43e0de..000000000 --- a/libretroshare/src/plugins/rscacheservice.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "plugins/pluginmanager.h" - -// This code needs to be re-written to work with GXS. For now it is obsolete. -// - -// The following class abstracts the construction of a cache service. The user only has to -// supply RS with a type ID. If the ID is already in use, RS will complain. -// -class RsCacheService: /* public CacheSource, public CacheStore, */ public p3Config -{ - public: - RsCacheService(uint16_t type,uint32_t tick_delay_in_seconds, RsPluginHandler* pgHandler) ; - - uint32_t tickDelay() const { return _tick_delay_in_seconds ; } - virtual void tick() {} - - // Functions from p3config - // - virtual RsSerialiser *setupSerialiser() { return NULL ; } - virtual bool saveList(bool&, std::list&) =0; - virtual bool loadList(std::list&) =0; - - private: - uint32_t _tick_delay_in_seconds ; -}; diff --git a/libretroshare/src/plugins/rspqiservice.h b/libretroshare/src/plugins/rspqiservice.h deleted file mode 100644 index f4ee6f313..000000000 --- a/libretroshare/src/plugins/rspqiservice.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "services/p3service.h" -#include "plugins/pluginmanager.h" - -// The following class abstracts the construction of a peer-to-peer service. The user only has to -// supply RS with a type ID. If the ID is already in use, RS will complain. -// -class RsPQIService: public p3Service, public p3Config -{ - public: - RsPQIService(uint16_t type,uint32_t tick_delay_in_seconds, RsPluginHandler* pgHandler) ; - - uint32_t tickDelay() const { return _tick_delay_in_seconds ; } - virtual int tick() = 0 ; - - // Functions from p3config - // - virtual RsSerialiser *setupSerialiser() { return NULL ; } - virtual bool saveList(bool&, std::list&) =0 ; - virtual bool loadList(std::list&) =0 ; - - private: - uint32_t _tick_delay_in_seconds ; -}; - diff --git a/libretroshare/src/pqi/authgpg.cc b/libretroshare/src/pqi/authgpg.cc deleted file mode 100644 index f7a6fb6c3..000000000 --- a/libretroshare/src/pqi/authgpg.cc +++ /dev/null @@ -1,811 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: authgpg.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008-2009 by Robert Fernie, Retroshare Team. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "authgpg.h" -#include "retroshare/rsiface.h" // For rsicontrol. -#include "retroshare/rspeers.h" // For RsPeerDetails. -#ifdef WINDOWS_SYS -#include "retroshare/rsinit.h" -#endif -#include "rsserver/p3face.h" -#include "pqi/p3notify.h" -#include "pgp/pgphandler.h" - -#include -#include -#include -#include /* for (u)sleep() */ -#include -#include -#include -#include -#include "rsitems/rsconfigitems.h" - -#define LIMIT_CERTIFICATE_SIZE 1 -#define MAX_CERTIFICATE_SIZE 10000 - -//#define DEBUG_AUTHGPG 1 - -//const rstime_t STORE_KEY_TIMEOUT = 1 * 60 * 60; //store key is call around every hour - -AuthPGP *AuthPGP::_instance = NULL ; - -void cleanupZombies(int numkill); // function to cleanup zombies under OSX. - -//#define GPG_DEBUG 1 - -/* Function to sign X509_REQ via GPGme. */ - -int AuthPGP::availablePgpCertificatesWithPrivateKeys(std::list& pgpIds) -{ - return instance()->mPgpHandler->availableGPGCertificatesWithPrivateKeys(pgpIds); -} -bool AuthPGP::getPgpDetailsFromBinaryBlock(const unsigned char *mem,size_t mem_size,RsPgpId& key_id, std::string& name, std::list& signers) -{ - return instance()->mPgpHandler->getGPGDetailsFromBinaryBlock(mem,mem_size,key_id,name,signers); -} -void AuthPGP::registerToConfigMgr(const std::string& fname,p3ConfigMgr *CfgMgr) -{ - CfgMgr->addConfiguration(fname, instance()); -} -bool AuthPGP::decryptTextFromFile(std::string& text,const std::string& inputfile) -{ - return instance()->mPgpHandler->decryptTextFromFile(instance()->mOwnGpgId,text,inputfile) ; -} - -bool AuthPGP::removeKeysFromPGPKeyring(const std::set& pgp_ids,std::string& backup_file,uint32_t& error_code) -{ -// std::list pids ; -// -// for(std::list::const_iterator it(pgp_ids.begin());it!=pgp_ids.end();++it) -// pids.push_back(RsPgpId(*it)) ; - - return instance()->mPgpHandler->removeKeysFromPGPKeyring(pgp_ids,backup_file,error_code) ; -} - -// bool AuthGPG::decryptTextFromString(std::string& encrypted_text,std::string& output) -// { -// return instance()->mPgpHandler->decryptTextFromString(mOwnGpgId,encrypted_text,output) ; -// } - -bool AuthPGP::encryptTextToFile(const std::string& text,const std::string& outfile) -{ - return instance()->mPgpHandler->encryptTextToFile(instance()->mOwnGpgId,text,outfile) ; -} - -// bool AuthGPG::encryptTextToString(const std::string& pgp_id,const std::string& text,std::string& outstr) -// { -// return instance()->mPgpHandler->encryptTextToString(RsPgpId(pgp_id),text,outstr) ; -// } - -std::string pgp_pwd_callback(void * /*hook*/, const char *uid_title, const char *uid_hint, const char * /*passphrase_info*/, int prev_was_bad,bool *cancelled) -{ -#ifdef GPG_DEBUG2 - fprintf(stderr, "pgp_pwd_callback() called.\n"); -#endif - std::string password; - RsServer::notify()->askForPassword(uid_title, uid_hint, prev_was_bad, password,cancelled) ; - - return password ; -} - -void AuthPGP::init( - const std::string& path_to_public_keyring, - const std::string& path_to_secret_keyring, - const std::string& path_to_trustdb, - const std::string& pgp_lock_file) -{ - if(_instance != NULL) - { - exit(); - std::cerr << "AuthGPG::init() called twice!" << std::endl ; - } - -// if(cb) instance()->mPgpHandler->setPassphraseCallback(cb);else - instance()->mPgpHandler->setPassphraseCallback(pgp_pwd_callback); - _instance = new AuthPGP( path_to_public_keyring, - path_to_secret_keyring, - path_to_trustdb, pgp_lock_file ); -} - -void AuthPGP::exit() -{ - if(_instance) - { - _instance->fullstop(); - delete _instance; - _instance = nullptr; - } -} - -AuthPGP::AuthPGP(const std::string& path_to_public_keyring,const std::string& path_to_secret_keyring,const std::string& path_to_trustdb,const std::string& pgp_lock_file) - :p3Config(), - gpgMtxService("AuthGPG-service"), - gpgMtxEngine("AuthGPG-engine"), - gpgMtxData("AuthGPG-data"), - mStoreKeyTime(0), - gpgKeySelected(false), - _force_sync_database(false), - mCount(0) -{ - mPgpHandler = new OpenPGPSDKHandler(path_to_public_keyring,path_to_secret_keyring,path_to_trustdb,pgp_lock_file); - - start("AuthGPG"); -} - -/* This function is called when retroshare is first started - * to get the list of available GPG certificates. - * This function should only return certs for which - * the private(secret) keys are available. - * - * returns false if GnuPG is not available. - */ -//bool AuthGPG::availableGPGCertificatesWithPrivateKeys(std::list &ids) -//{ -// std::list pids ; -// -// mPgpHandler->availableGPGCertificatesWithPrivateKeys(pids) ; -// -// for(std::list::const_iterator it(pids.begin());it!=pids.end();++it) -// ids.push_back( (*it).toStdString() ) ; -// -// /* return false if there are no private keys */ -// return !ids.empty(); -//} - -/* You can initialise Retroshare with - * (a) load existing certificate. - * (b) a new certificate. - * - * This function must be called successfully (return == 1) - * before anything else can be done. (except above fn). - */ -int AuthPGP::PgpInit(const RsPgpId &ownId) -{ -#ifdef DEBUG_AUTHGPG - std::cerr << "AuthGPG::GPGInit() called with own gpg id : " << ownId.toStdString() << std::endl; -#endif - - instance()->mOwnGpgId = ownId; - - //force the validity of the private key. When set to unknown, it caused signature and text encryptions bugs - instance()->privateTrustCertificate(ownId, 5); - instance()->mPgpHandler->updateOwnSignatureFlag(ownId) ; - -#ifdef DEBUG_AUTHGPG - std::cerr << "AuthGPG::GPGInit finished." << std::endl; -#endif - - return 1; -} - - AuthPGP::~AuthPGP() -{ -} - -void AuthPGP::threadTick() -{ - rstime::rs_usleep(100 * 1000); //100 msec - - /// every 100 milliseconds - processServices(); - - /// every ten seconds - if (++mCount >= 100 || _force_sync_database) { - RsStackMutex stack(gpgMtxService); ///******* LOCKED ****** - - /// The call does multiple things at once: - /// - checks whether the keyring has changed in memory - /// - checks whether the keyring has changed on disk. - /// - merges/updates according to status. - /// - mPgpHandler->syncDatabase() ; - mCount = 0; - _force_sync_database = false ; - }//if (++count >= 100 || _force_sync_database) -} - -void AuthPGP::processServices() -{ - AuthGPGOperation *operation = NULL; - AuthGPGService *service = NULL; - - { - RsStackMutex stack(gpgMtxService); /******* LOCKED ******/ - - std::list::iterator serviceIt; - for (serviceIt = services.begin(); serviceIt != services.end(); ++serviceIt) { - operation = (*serviceIt)->getGPGOperation(); - if (operation) { - service = *serviceIt; - break; - } - } - } /******* UNLOCKED ******/ - - if (operation == NULL) { - /* nothing to do */ - return; - } - - if (service == NULL) { - /* huh ? */ - delete operation; - return; - } - - AuthGPGOperationLoadOrSave *loadOrSave = dynamic_cast(operation); - if (loadOrSave) - { - if (loadOrSave->m_load) - { - /* process load operation */ - - - /* load the certificate */ - - - /* don't bother loading - if we already have the certificate */ - if (mPgpHandler->isGPGId(loadOrSave->m_certGpgId)) - { -#ifdef GPG_DEBUG - std::cerr << "AuthGPGimpl::processServices() Skipping load - already have it" << std::endl; -#endif - } - else - { -#ifdef GPG_DEBUG - std::cerr << "AuthGPGimpl::processServices() Process load operation" << std::endl; -#endif - std::string error_string ; - RsPgpId pgp_id ; - LoadCertificateFromString(loadOrSave->m_certGpg, pgp_id,error_string); - loadOrSave->m_certGpgId = pgp_id; - } - - - - } else { - /* process save operation */ - -#ifdef GPG_DEBUG - std::cerr << "AuthGPGimpl::processServices() Process save operation" << std::endl; -#endif - - /* save the certificate to string */ - /***** - * #define DISABLE_CERTIFICATE_SEND 1 - ****/ - - loadOrSave->m_certGpg = SaveCertificateToString(loadOrSave->m_certGpgId,true); - -#ifdef GPG_DEBUG - std::cerr << "Certificate for: " << loadOrSave->m_certGpgId << " is: "; - std::cerr << std::endl; - std::cerr << loadOrSave->m_certGpg; - std::cerr << std::endl; -#endif - - } - - service->setGPGOperation(loadOrSave); - } - else - { -#ifdef GPG_DEBUG - std::cerr << "AuthGPGimpl::processServices() Unknown operation" << std::endl; -#endif - } - - delete operation; -} - -bool AuthPGP::DoOwnSignature(const void *data, unsigned int datalen, void *buf_sigout, unsigned int *outl, std::string reason /* = "" */) -{ - return instance()->mPgpHandler->SignDataBin(mOwnGpgId,data,datalen,(unsigned char *)buf_sigout,outl,false,reason) ; -} - - -/* import to GnuPG and other Certificates */ -bool AuthPGP::VerifySignature(const void *data, int datalen, const void *sig, unsigned int siglen, const PGPFingerprintType& withfingerprint) -{ - return instance()->mPgpHandler->VerifySignBin((unsigned char*)data,datalen,(unsigned char*)sig,siglen,withfingerprint) ; -} - -bool AuthPGP::parseSignature(const void *sig, unsigned int siglen, RsPgpId& issuer_id) -{ - return instance()->mPgpHandler->parseSignature((unsigned char*)sig,siglen,issuer_id) ; -} - -bool AuthPGP::exportProfile(const std::string& fname,const RsPgpId& exported_id) -{ - return instance()->mPgpHandler->exportGPGKeyPair(fname,exported_id) ; -} - -bool AuthPGP::exportIdentityToString( - std::string& data, const RsPgpId& pgpId, bool includeSignatures, - std::string& errorMsg ) -{ - return instance()->mPgpHandler->exportGPGKeyPairToString( - data, pgpId, includeSignatures, errorMsg); -} - -bool AuthPGP::importProfile(const std::string& fname,RsPgpId& imported_id,std::string& import_error) -{ - return instance()->mPgpHandler->importGPGKeyPair(fname,imported_id,import_error) ; -} - -bool AuthPGP::importProfileFromString(const std::string &data, RsPgpId &gpg_id, std::string &import_error) -{ - return instance()->mPgpHandler->importGPGKeyPairFromString(data, gpg_id, import_error); -} - -bool AuthPGP::active() -{ - RsStackMutex stack(instance()->gpgMtxData); /******* LOCKED ******/ - - return instance()->gpgKeySelected; -} - -bool AuthPGP::GeneratePgpCertificate(const std::string& name, const std::string& email, const std::string& passwd, RsPgpId& pgpId, const int keynumbits, std::string& errString) -{ - RsStackMutex stack(instance()->gpgMtxEngine); /******* LOCKED ******/ - - return instance()->mPgpHandler->GeneratePGPCertificate(name, email, passwd, pgpId, keynumbits, errString) ; -} - -/**** These Two are common */ -std::string AuthPGP::getPgpName(const RsPgpId& id,bool *success) -{ - RsStackMutex stack(instance()->gpgMtxData); /******* LOCKED ******/ - - const PGPCertificateInfo *info = instance()->mPgpHandler->getCertificateInfo(id) ; - - if(info != NULL) - { - if(success != NULL) *success = true ; - return info->_name ; - } - else - { - if(success != NULL) *success = false ; - return "[Unknown PGP Cert name]" ; - } -} - -AuthPGP *AuthPGP::instance() -{ - if(!_instance) - { - RsFatal() << "AuthGPG::instance() called before AuthGPG::init()! This should not happen." << std::endl; - return nullptr; - } - - return _instance; -} -bool AuthPGP::isPGPId(const RsPgpId& id) -{ - return instance()->mPgpHandler->isGPGId(id); -} -/**** These Two are common */ -std::string AuthPGP::getPgpEmail(const RsPgpId& id,bool *success) -{ - RsStackMutex stack(instance()->gpgMtxData); /******* LOCKED ******/ - const PGPCertificateInfo *info = instance()->mPgpHandler->getCertificateInfo(id) ; - - if(info != NULL) - { - if(success != NULL) *success = true ; - return info->_email ; - } - else - { - if(success != NULL) *success = false ; - return "[Unknown PGP Cert email]" ; - } -} - -/**** GPG versions ***/ - -const RsPgpId& AuthPGP::getPgpOwnId() -{ - RsStackMutex stack(instance()->gpgMtxData); /******* LOCKED ******/ - return instance()->mOwnGpgId ; -} - -std::string AuthPGP::getPgpOwnName() -{ - return getPgpName(instance()->mOwnGpgId) ; -} - -bool AuthPGP::getPgpAllList(std::list &ids) -{ - RsStackMutex stack(instance()->gpgMtxData); /******* LOCKED ******/ - - instance()->mPgpHandler->getGPGFilteredList(ids) ; - - return true; -} -const PGPCertificateInfo *AuthPGP::getCertInfoFromStdString(const std::string& pgp_id) const -{ - try - { - return instance()->mPgpHandler->getCertificateInfo(RsPgpId(pgp_id)) ; - } - catch(std::exception& e) - { - std::cerr << "(EE) exception raised while constructing a PGP certificate from id \"" << pgp_id << "\": " << e.what() << std::endl; - return NULL ; - } -} -bool AuthPGP::haveSecretKey(const RsPgpId& id) -{ - return instance()->mPgpHandler->haveSecretKey(id) ; -} -bool AuthPGP::isKeySupported(const RsPgpId& id) -{ - const PGPCertificateInfo *pc = instance()->mPgpHandler->getCertificateInfo(id) ; - - if(pc == NULL) - return false ; - - return !(pc->_flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_UNSUPPORTED_ALGORITHM) ; -} - -bool AuthPGP::getPgpDetails(const RsPgpId& pgp_id, RsPeerDetails &d) -{ - RsStackMutex stack(instance()->gpgMtxData); /******* LOCKED ******/ - - const PGPCertificateInfo *pc = instance()->mPgpHandler->getCertificateInfo(pgp_id) ; - - if(pc == NULL) - return false ; - - const PGPCertificateInfo& cert(*pc) ; - - d.id.clear() ; - d.gpg_id = pgp_id ; - d.name = cert._name; - d.lastUsed = cert._time_stamp; - d.email = cert._email; - d.trustLvl = cert._trustLvl; - d.validLvl = cert._trustLvl; - d.ownsign = cert._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE; - d.gpgSigners.clear() ; - - for(std::set::const_iterator it(cert.signers.begin());it!=cert.signers.end();++it) - d.gpgSigners.push_back( *it ) ; - - d.fpr = cert._fpr ; - d.accept_connection = cert._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION; - d.hasSignedMe = cert._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_HAS_SIGNED_ME; - - return true; -} - -bool AuthPGP::getGPGFilteredList(std::list& list,bool (*filter)(const PGPCertificateInfo&)) -{ - return instance()->mPgpHandler->getGPGFilteredList(list,filter) ; -} - -static bool filter_Validity(const PGPCertificateInfo& /*info*/) { return true ; } //{ return info._validLvl >= PGPCertificateInfo::GPGME_VALIDITY_MARGINAL ; } -static bool filter_Accepted(const PGPCertificateInfo& info) { return info._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION ; } -static bool filter_OwnSigned(const PGPCertificateInfo& info) { return info._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE ; } - -bool AuthPGP::getPgpValidList(std::list &ids) -{ - return getGPGFilteredList(ids,&filter_Validity); -} - -bool AuthPGP::getPgpAcceptedList(std::list &ids) -{ - return getGPGFilteredList(ids,&filter_Accepted); -} - -bool AuthPGP::getPgpSignedList(std::list &ids) -{ - return getGPGFilteredList(ids,&filter_OwnSigned); -} - -// bool AuthGPG::getCachedGPGCertificate(const RsPgpId &id, std::string &certificate) -// { -// RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ -// #ifdef LIMIT_CERTIFICATE_SIZE -// certificate = instance()->mPgpHandler->SaveCertificateToString(RsPgpId(id),false) ; -// #else -// certificate = instance()->mPgpHandler->SaveCertificateToString(RsPgpId(id),true) ; -// #endif -// -// // #ifdef LIMIT_CERTIFICATE_SIZE -// // std::string cleaned_key ; -// // if(PGPKeyManagement::createMinimalKey(certificate,cleaned_key)) -// // certificate = cleaned_key ; -// // #endif -// -// return certificate.length() > 0 ; -// } - -/***************************************************************** - * Loading and Saving Certificates - this has to - * be able to handle both openpgp and X509 certificates. - * - * X509 are passed onto AuthSSL, OpenPGP are passed to gpgme. - * - */ - - -/* SKTAN : do not know how to use std::string id */ - std::string AuthPGP::SaveCertificateToString(const RsPgpId &id,bool include_signatures) - { - RsStackMutex stack(instance()->gpgMtxEngine); /******* LOCKED ******/ - - return instance()->mPgpHandler->SaveCertificateToString(id,include_signatures) ; - } -/* import to GnuPG and other Certificates */ -bool AuthPGP::LoadPGPKeyFromBinaryData(const unsigned char *data,uint32_t data_len, RsPgpId& gpg_id,std::string& error_string) -{ - RsStackMutex stack(instance()->gpgMtxEngine); /******* LOCKED ******/ - - if(instance()->mPgpHandler->LoadCertificateFromBinaryData(data,data_len,gpg_id,error_string)) - { - instance()->mPgpHandler->updateOwnSignatureFlag(gpg_id,instance()->mOwnGpgId) ; - return true ; - } - - return false ; -} - -/* import to GnuPG and other Certificates */ -bool AuthPGP::LoadCertificateFromString(const std::string &str, RsPgpId& gpg_id,std::string& error_string) -{ - RsStackMutex stack(instance()->gpgMtxEngine); /******* LOCKED ******/ - - if(instance()->mPgpHandler->LoadCertificateFromString(str,gpg_id,error_string)) - { - instance()->mPgpHandler->updateOwnSignatureFlag(gpg_id,instance()->mOwnGpgId) ; - return true ; - } - - return false ; -} - -/***************************************************************** - * Auth...? Signing, Revoke, Trust are all done at - * the PGP level.... - * - * Only Signing of SSL is done at setup. - * Auth should be done... ?? not sure - * maybe - * - */ - - -/*************************************/ - -/* These take PGP Ids */ -bool AuthPGP::AllowConnection(const RsPgpId& gpg_id, bool accept) -{ -#ifdef GPG_DEBUG - std::cerr << "AuthGPG::AllowConnection(" << gpg_id << ")" << std::endl; -#endif - - /* Was a "Reload Certificates" here -> be shouldn't be needed -> and very expensive, try without. */ - { - RsStackMutex stack(instance()->gpgMtxData); - instance()->mPgpHandler->setAcceptConnexion(gpg_id,accept) ; - } - - instance()->IndicateConfigChanged(); - - RsServer::notify()->notifyListChange(NOTIFY_LIST_FRIENDS, accept ? NOTIFY_TYPE_ADD : NOTIFY_TYPE_DEL); - - return true; -} - -/* These take PGP Ids */ -bool AuthPGP::SignCertificateLevel0(const RsPgpId &id) -{ -#ifdef GPG_DEBUG - std::cerr << "AuthGPG::SignCertificat(" << id << ")" << std::endl; -#endif - - return instance()->privateSignCertificate(id) ; -} - -bool AuthPGP::RevokeCertificate(const RsPgpId &id) -{ - /* remove unused parameter warnings */ - (void) id; - -#ifdef GPG_DEBUG - std::cerr << "AuthGPG::RevokeCertificate(" << id << ") not implemented yet" << std::endl; -#endif - - return false; -} - -bool AuthPGP::TrustCertificate(const RsPgpId& id, int trustlvl) -{ -#ifdef GPG_DEBUG - std::cerr << "AuthGPG::TrustCertificate(" << id << ", " << trustlvl << ")" << std::endl; -#endif - return instance()->privateTrustCertificate(id, trustlvl) ; -} - -bool AuthPGP::encryptDataBin(const RsPgpId& pgp_id,const void *data, unsigned int datalen, unsigned char *sign, unsigned int *signlen) -{ - return instance()->mPgpHandler->encryptDataBin(RsPgpId(pgp_id),data,datalen,sign,signlen) ; -} - -bool AuthPGP::decryptDataBin(const void *data, unsigned int datalen, unsigned char *sign, unsigned int *signlen) -{ - return instance()->mPgpHandler->decryptDataBin(instance()->mOwnGpgId,data,datalen,sign,signlen) ; -} -bool AuthPGP::SignDataBin(const void *data, unsigned int datalen, unsigned char *sign, unsigned int *signlen, std::string reason /*= ""*/) -{ - return instance()->DoOwnSignature(data, datalen, sign, signlen, reason); -} - -bool AuthPGP::exportPublicKey( const RsPgpId& id, unsigned char*& mem_block, size_t& mem_size, bool armoured, bool include_signatures ) -{ - return instance()->mPgpHandler->exportPublicKey(id,mem_block,mem_size,armoured,include_signatures); -} - -bool AuthPGP::isPgpPubKeyAvailable(const RsPgpId& pgp_id) -{ - return instance()->mPgpHandler->isPgpPubKeyAvailable(pgp_id); -} -bool AuthPGP::getKeyFingerprint(const RsPgpId& id,PGPFingerprintType& fp) -{ - return instance()->mPgpHandler->getKeyFingerprint(id,fp); -} -bool AuthPGP::VerifySignBin(const void *data, uint32_t datalen, unsigned char *sign, unsigned int signlen, const PGPFingerprintType& withfingerprint) -{ - return instance()->VerifySignature(data, datalen, sign, signlen, withfingerprint); -} - -/* Sign/Trust stuff */ - -int AuthPGP::privateSignCertificate(const RsPgpId &id) -{ - RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ - - int ret = mPgpHandler->privateSignCertificate(mOwnGpgId,id) ; - _force_sync_database = true ; - return ret ; -} - -/* revoke the signature on Certificate */ -int AuthPGP::privateRevokeCertificate(const RsPgpId &/*id*/) -{ - //RsStackMutex stack(gpgMtx); /******* LOCKED ******/ - std::cerr << __PRETTY_FUNCTION__ << ": not implemented!" << std::endl; - - return 0; -} - -int AuthPGP::privateTrustCertificate(const RsPgpId& id, int trustlvl) -{ - RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ - - // csoler: Why are we not allowing this when the peer is not in the accepted peers list?? - // The trust level is only a user-defined property that has nothing to - // do with the fact that we allow connections or not. - - if(!isPGPAccepted(id)) - return 0; - - int res = instance()->mPgpHandler->privateTrustCertificate(id,trustlvl) ; - _force_sync_database = true ; - return res ; -} - -// -----------------------------------------------------------------------------------// -// -------------------------------- Config functions ------------------------------ // -// -----------------------------------------------------------------------------------// -// -RsSerialiser *AuthPGP::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser ; - rss->addSerialType(new RsGeneralConfigSerialiser()); - return rss ; -} -bool AuthPGP::isPGPAccepted(const RsPgpId& id) -{ - return instance()->mPgpHandler->isGPGAccepted(id); -} - -bool AuthPGP::saveList(bool& cleanup, std::list& lst) -{ -#ifdef GPG_DEBUG - std::cerr << "AuthGPG::saveList() called" << std::endl ; -#endif - std::list ids ; - getPgpAcceptedList(ids) ; // needs to be done before the lock - - RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ - - cleanup = true ; - - // Now save config for network digging strategies - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; - - for (std::list::const_iterator it(ids.begin()); it != ids.end(); ++it) - if((*it) != mOwnGpgId) // skip our own id. - { - RsTlvKeyValue kv; - kv.key = (*it).toStdString() ; -#ifdef GPG_DEBUG - std::cerr << "AuthGPG::saveList() called (it->second) : " << (it->second) << std::endl ; -#endif - kv.value = "TRUE"; - vitem->tlvkvs.pairs.push_back(kv) ; - } - lst.push_back(vitem); - - return true; -} - -bool AuthPGP::loadList(std::list& load) -{ -#ifdef GPG_DEBUG - std::cerr << "AuthGPG::loadList() Item Count: " << load.size() << std::endl; -#endif - - RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ - /* load the list of accepted gpg keys */ - std::list::iterator it; - for(it = load.begin(); it != load.end(); ++it) - { - RsConfigKeyValueSet *vitem = dynamic_cast(*it); - if(vitem) - { -#ifdef GPG_DEBUG - std::cerr << "AuthGPG::loadList() General Variable Config Item:" << std::endl; - vitem->print(std::cerr, 10); - std::cerr << std::endl; -#endif - - std::list::iterator kit; - for(kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) - if (kit->key != mOwnGpgId.toStdString()) - instance()->mPgpHandler->setAcceptConnexion(RsPgpId(kit->key), (kit->value == "TRUE")); - } - delete (*it); - } - load.clear() ; - return true; -} - -bool AuthPGP::addService(AuthGPGService *service) -{ - RsStackMutex stack(instance()->gpgMtxService); /********* LOCKED *********/ - - if (std::find(instance()->services.begin(), instance()->services.end(), service) != instance()->services.end()) { - /* it exists already! */ - return false; - } - - instance()->services.push_back(service); - return true; -} - - diff --git a/libretroshare/src/pqi/authgpg.h b/libretroshare/src/pqi/authgpg.h deleted file mode 100644 index 1db1ad482..000000000 --- a/libretroshare/src/pqi/authgpg.h +++ /dev/null @@ -1,314 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: authgpg.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008-2009 by Raghu Dev R. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -/**** - * Here's GPG policy : - * By default, all pgpg keys imported via a RS user (make friend and accept friend action) are signed at level 0. - * All signed keys by RS are set to be trusted marginally. You can change it to full or no trust in the friend profile - * For a key to be marginaly valid, it has to be signed by one fully trusted key, or at least by 3 marginally trusted keys. - * All keys that have at least marginal validity are designed as valid in RS. They are shown in the RS gui in order to be signed. - * If there is no validity then the key is not shown. - */ - -#ifndef RS_GPG_AUTH_HEADER -#define RS_GPG_AUTH_HEADER - -#include "util/rsthreads.h" -#include "pqi/p3cfgmgr.h" -#include "pgp/openpgpsdkhandler.h" - -#define MAX_GPG_SIGNATURE_SIZE 4096 - -struct RsPeerDetails; - -/*! - * gpgcert is the identifier for a person. - * It is a wrapper class for a OpenPGP certificate. - */ - -class AuthGPGOperation -{ -public: - explicit AuthGPGOperation(void *userdata) - { - m_userdata = userdata; - } - virtual ~AuthGPGOperation() {} - -public: - void *m_userdata; -}; - -class AuthGPGOperationLoadOrSave : public AuthGPGOperation -{ -public: - AuthGPGOperationLoadOrSave(bool load, const RsPgpId &gpgId, const std::string &gpgCert, void *userdata) - : AuthGPGOperation(userdata) - { - m_load = load; - if (m_load) { - m_certGpg = gpgCert; - m_certGpgId = gpgId; - } else { - m_certGpgId = gpgId; - } - } - -public: - bool m_load; - RsPgpId m_certGpgId; // set for save & load. - std::string m_certGpg; // set for load -}; - -class AuthGPGService -{ -public: - AuthGPGService() {} - ~AuthGPGService() {} - - virtual AuthGPGOperation *getGPGOperation() = 0; - virtual void setGPGOperation(AuthGPGOperation *operation) = 0; -}; - -class AuthPGP: public p3Config, public RsTickingThread -{ -public: - static void init(const std::string& path_to_pubring, - const std::string& path_to_secring, - const std::string& path_to_trustdb, - const std::string& pgp_lock_file); - - static void registerToConfigMgr(const std::string& fname,p3ConfigMgr *CfgMgr); - static void exit(); - - static bool isPGPId(const RsPgpId& id) ; - static bool isPGPAccepted(const RsPgpId& id) ; - - /** - * @param ids list of gpg certificate ids (note, not the actual certificates) - */ - //virtual bool availableGPGCertificatesWithPrivateKeys(std::list &ids); - - /*********************************************************************************/ - /************************* STAGE 1 ***********************************************/ - /*********************************************************************************/ - /***** - * STAGE 1: Initialisation.... As we are switching to OpenPGP the init functions - * will be different. Just move the initialisation functions over.... - * - * As GPGMe requires external calls to the GPG executable, which could potentially - * be expensive, We'll want to cache the GPG keys in this class. - * This should be done at initialisation, and saved in a map. - * (see storage at the end of the class) - * - ****/ - static bool active(); - - // /* Initialize */ - // virtual bool InitAuth (); - // virtual bool CloseAuth(); - - /* Init by generating new Own PGP Cert, or selecting existing PGP Cert */ - - static int PgpInit(const RsPgpId &ownId); - static bool GeneratePgpCertificate(const std::string& name, const std::string& email, const std::string& passwd, RsPgpId &pgpId, const int keynumbits, std::string &errString); - - static bool getPgpDetailsFromBinaryBlock(const unsigned char *mem,size_t mem_size,RsPgpId& key_id, std::string& name, std::list& signers) ; - static int availablePgpCertificatesWithPrivateKeys(std::list& pgpIds); - - /*********************************************************************************/ - /************************* STAGE 3 ***********************************************/ - /*********************************************************************************/ - /***** - * STAGE 3: These are some of the most commonly used functions in Retroshare. - * - * More commonly used functions. - * - * provide access to details in cache list. - * - ****/ - static std::string getPgpName(const RsPgpId &pgp_id,bool *success = NULL); - static std::string getPgpEmail(const RsPgpId &pgp_id,bool *success = NULL); - - static bool exportPublicKey( const RsPgpId& id, unsigned char*& mem_block, size_t& mem_size, bool armoured, bool include_signatures ); - - /* PGP web of trust management */ - static const RsPgpId& getPgpOwnId(); - static std::string getPgpOwnName(); - - //virtual std::string getGPGOwnEmail(); - static bool getKeyFingerprint(const RsPgpId& id,PGPFingerprintType& fp) ; - static bool isKeySupported(const RsPgpId &id) ; - static bool isPgpPubKeyAvailable(const RsPgpId& pgp_id); - static bool haveSecretKey(const RsPgpId &id) ; - static bool getPgpDetails(const RsPgpId& id, RsPeerDetails &d); - static bool getPgpAllList(std::list &ids); - static bool getPgpValidList(std::list &ids); - static bool getPgpAcceptedList(std::list &ids); - static bool getPgpSignedList(std::list &ids); - static bool importProfile(const std::string& filename,RsPgpId& gpg_id,std::string& import_error) ; - static bool importProfileFromString(const std::string& data,RsPgpId& gpg_id,std::string& import_error) ; - static bool exportProfile(const std::string& filename,const RsPgpId& gpg_id) ; - static bool exportIdentityToString( - std::string& data, const RsPgpId& pgpId, bool includeSignatures, - std::string& errorMsg ); - - static bool removeKeysFromPGPKeyring(const std::set &pgp_ids,std::string& backup_file,uint32_t& error_code) ; - - /*********************************************************************************/ - /************************* STAGE 4 ***********************************************/ - /*********************************************************************************/ - /***** - * STAGE 4: Loading and Saving Certificates. (Strings and Files) - * - ****/ - static bool LoadCertificateFromString(const std::string &pem, RsPgpId& gpg_id,std::string& error_string); - static bool LoadPGPKeyFromBinaryData(const unsigned char *data,uint32_t data_len, RsPgpId& gpg_id,std::string& error_string); - static std::string SaveCertificateToString(const RsPgpId &id,bool include_signatures) ; - - // Cached certificates. - //bool getCachedGPGCertificate(const RsPgpId &id, std::string &certificate); - - /*********************************************************************************/ - /************************* STAGE 6 ***********************************************/ - /*********************************************************************************/ - /***** - * STAGE 6: Authentication, Trust and Signing. - * - * This is some of the harder functions, but they should have been - * done in gpgroot already. - * - ****/ - static bool AllowConnection(const RsPgpId &gpg_id, bool accept); - - static bool SignCertificateLevel0(const RsPgpId &id); - static bool RevokeCertificate(const RsPgpId &id); /* Particularly hard - leave for later */ - - static bool TrustCertificate(const RsPgpId& id, int trustlvl); //trustlvl is 2 for none, 3 for marginal and 4 for full trust - - /*********************************************************************************/ - /************************* STAGE 7 ***********************************************/ - /*********************************************************************************/ - /***** - * STAGE 7: Signing Data. - * - * There should also be Encryption Functions... (do later). - * - ****/ - static bool SignDataBin(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen, std::string reason = ""); - static bool VerifySignBin(const void*, uint32_t, unsigned char*, unsigned int, const PGPFingerprintType& withfingerprint); - static bool parseSignature(const void *sig, unsigned int siglen, RsPgpId& issuer_id); - - static bool encryptDataBin(const RsPgpId& pgp_id,const void *data, const uint32_t len, unsigned char *encr, unsigned int *encrlen); - static bool decryptDataBin(const void *data, const uint32_t len, unsigned char *decr, unsigned int *decrlen); - - static bool decryptTextFromFile( std::string& text,const std::string& filename); - static bool encryptTextToFile (const std::string& text,const std::string& filename); - -// virtual bool decryptTextFromString( std::string& encrypted_text,std::string& clear_string); -// virtual bool encryptTextToString (const std::string& pgp_id,const std::string& clear_text,std::string& encrypted_string); - - static bool getGPGFilteredList(std::list& list,bool (*filter)(const PGPCertificateInfo&) = NULL) ; - - //END of PGP public functions - - /* GPG service */ - static bool addService(AuthGPGService *service) ; - - // This is for debug purpose only. Don't use it !! - static void setAuthGPG_debug(AuthPGP *auth_gpg) { _instance = auth_gpg ; } - - protected: - AuthPGP(const std::string& path_to_pubring, const std::string& path_to_secring,const std::string& path_to_trustdb,const std::string& pgp_lock_file); - virtual ~AuthPGP(); - - /*****************************************************************/ - /*********************** p3config ******************************/ - /* Key Functions to be overloaded for Full Configuration */ - virtual RsSerialiser *setupSerialiser() override; - virtual bool saveList(bool &cleanup, std::list&) override; - virtual bool loadList(std::list& load) override; - /*****************************************************************/ - -private: - // Gets the certificate pointer and returns NULL if the string is invalid, or the - // cert was not found. - // - const PGPCertificateInfo *getCertInfoFromStdString(const std::string& ) const; - - /* SKTAN */ - //void showData(gpgme_data_t dh); - //void createDummyFriends(void); //NYI - - /* Internal functions */ - bool DoOwnSignature(const void *, unsigned int, void *, unsigned int *, std::string reason); - bool VerifySignature(const void *data, int datalen, const void *sig, unsigned int siglen, const PGPFingerprintType& withfingerprint); - - /* Sign/Trust stuff */ - int privateSignCertificate(const RsPgpId &id); - int privateRevokeCertificate(const RsPgpId &id); /* revoke the signature on Certificate */ - int privateTrustCertificate(const RsPgpId& id, int trustlvl); - - // store all keys in map mKeyList to avoid calling gpgme exe repeatedly - //bool storeAllKeys(); - //bool storeAllKeys_tick(); - - // Not used anymore - // bool updateTrustAllKeys_locked(); - - /* GPG service */ - void processServices(); - - bool printAllKeys_locked(); - bool printOwnKeys_locked(); - - void threadTick() override; /// @see RsTickingThread - -private: - static AuthPGP *instance(); - - RsMutex gpgMtxService; - RsMutex gpgMtxEngine; - - /* Below is protected via the mutex */ - - // gpgme_engine_info_t INFO; - // gpgme_ctx_t CTX; - - RsMutex gpgMtxData; - /* Below is protected via the mutex */ - - rstime_t mStoreKeyTime; - - PGPHandler *mPgpHandler; - - RsPgpId mOwnGpgId; - bool gpgKeySelected; - bool _force_sync_database ; - uint32_t mCount ; - - std::list services ; - - static AuthPGP *_instance ; -}; - -#endif diff --git a/libretroshare/src/pqi/authssl.cc b/libretroshare/src/pqi/authssl.cc deleted file mode 100644 index 9d70121a3..000000000 --- a/libretroshare/src/pqi/authssl.cc +++ /dev/null @@ -1,1848 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: authssl.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2008 Robert Fernie * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifdef WINDOWS_SYS -#include "util/rswin.h" -#endif // WINDOWS_SYS - -#include "authssl.h" -#include "sslfns.h" - -#include "pqinetwork.h" -#include "authgpg.h" -#include "rsitems/rsconfigitems.h" -#include "util/rsdebug.h" -#include "util/rsdir.h" -#include "util/rsstring.h" -#include "pgp/pgpkeyutil.h" - -#include "retroshare/rspeers.h" // for RsPeerDetails structure -#include "retroshare/rsids.h" // for RsPeerDetails structure -#include "rsserver/p3face.h" - -/******************** notify of new Cert **************************/ - -#include -#include - -#include - -/* SSL connection diagnostic */ - -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_UNKNOWN = 0x00 ; -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_OK = 0x01 ; -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_CERTIFICATE_NOT_VALID = 0x02 ; -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_ISSUER_UNKNOWN = 0x03 ; -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_MALLOC_ERROR = 0x04 ; -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE = 0x05 ; -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_CERTIFICATE_MISSING = 0x06 ; -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_HASH_ALGORITHM_NOT_ACCEPTED = 0x07 ; -//const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_KEY_ALGORITHM_NOT_ACCEPTED = 0x08 ; -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE_TYPE = 0x09 ; -const uint32_t RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE_VERSION = 0x0a ; - -/**** - * #define AUTHSSL_DEBUG 1 - ***/ - -static pthread_mutex_t* mutex_buf = nullptr; - -struct CRYPTO_dynlock_value -{ - pthread_mutex_t mutex; -}; - -# if OPENSSL_VERSION_NUMBER < 0x10100000L -/** - * OpenSSL locking function. - * - * @param mode lock mode - * @param n lock number - * @param file source file name - * @param line source file line number - * @return none - */ -static void locking_function(int mode, int n, const char */*file*/, int /*line*/) -{ - if (mode & CRYPTO_LOCK) { - pthread_mutex_lock(&mutex_buf[n]); - } else { - pthread_mutex_unlock(&mutex_buf[n]); - } -} -#endif - -# if OPENSSL_VERSION_NUMBER < 0x10100000L -/** - * OpenSSL uniq id function. - * - * @return thread id - */ -static unsigned long id_function(void) -{ -#if defined( WINDOWS_SYS) && !defined(WIN_PTHREADS_H) - return (unsigned long) pthread_self().p; -#else - return (unsigned long) pthread_self(); -#endif -} -#endif - -# if OPENSSL_VERSION_NUMBER < 0x10100000L -/** - * OpenSSL allocate and initialize dynamic crypto lock. - * - * @param file source file name - * @param line source file line number - */ -static struct CRYPTO_dynlock_value *dyn_create_function(const char */*file*/, int /*line*/) -{ - struct CRYPTO_dynlock_value *value; - - value = (struct CRYPTO_dynlock_value*) rs_malloc(sizeof(struct CRYPTO_dynlock_value)); - if (!value) - return NULL; - - pthread_mutex_init(&value->mutex, NULL); - - return value; -} -#endif - -# if OPENSSL_VERSION_NUMBER < 0x10100000L -/** - * OpenSSL dynamic locking function. - * - * @param mode lock mode - * @param l lock structure pointer - * @param file source file name - * @param line source file line number - * @return none - */ -static void dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l, const char */*file*/, int /*line*/) -{ - if (mode & CRYPTO_LOCK) { - pthread_mutex_lock(&l->mutex); - } else { - pthread_mutex_unlock(&l->mutex); - } -} -#endif - -# if OPENSSL_VERSION_NUMBER < 0x10100000L -/** - * OpenSSL destroy dynamic crypto lock. - * - * @param l lock structure pointer - * @param file source file name - * @param line source file line number - * @return none - */ -static void dyn_destroy_function(struct CRYPTO_dynlock_value *l, const char */*file*/, int /*line*/) -{ - pthread_mutex_destroy(&l->mutex); - free(l); -} -#endif - -/** - * Initialize TLS library. - * - * @return true on success, false on error - */ -bool tls_init() -{ - /* static locks area */ - mutex_buf = (pthread_mutex_t*) rs_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t)); - if (mutex_buf == NULL) - return false; - - for (int i = 0; i < CRYPTO_num_locks(); i++) { - pthread_mutex_init(&mutex_buf[i], NULL); - } -# if OPENSSL_VERSION_NUMBER < 0x10100000L - /* static locks callbacks */ - CRYPTO_set_locking_callback(locking_function); - CRYPTO_set_id_callback(id_function); - /* dynamic locks callbacks */ - CRYPTO_set_dynlock_create_callback(dyn_create_function); - CRYPTO_set_dynlock_lock_callback(dyn_lock_function); - CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function); -#endif - return true; -} - -/** - * Cleanup TLS library. - * - * @return 0 - */ -void tls_cleanup() -{ - CRYPTO_set_dynlock_create_callback(NULL); - CRYPTO_set_dynlock_lock_callback(NULL); - CRYPTO_set_dynlock_destroy_callback(NULL); - - CRYPTO_set_locking_callback(NULL); - CRYPTO_set_id_callback(NULL); - - if (mutex_buf != NULL) { - for (int i = 0; i < CRYPTO_num_locks(); i++) { - pthread_mutex_destroy(&mutex_buf[i]); - } - free(mutex_buf); - mutex_buf = NULL; - } -} - -/*static*/ AuthSSL& AuthSSL::instance() -{ - static AuthSSLimpl mInstance; - return mInstance; -} - -AuthSSL* AuthSSL::getAuthSSL() { return &instance(); } - -AuthSSL::~AuthSSL() = default; - - -/********************************************************************************/ -/********************************************************************************/ -/********************* Cert Search / Add / Remove **************************/ -/********************************************************************************/ -/********************************************************************************/ - -static int verify_x509_callback(int preverify_ok, X509_STORE_CTX *ctx); - -std::string RsX509Cert::getCertName(const X509& x509) -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - return getX509CNString(x509.cert_info->subject); -#else - return getX509CNString(X509_get_subject_name(&x509)); -#endif -} - -std::string RsX509Cert::getCertLocation(const X509& x509) -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - return getX509LocString(x509.cert_info->subject); -#else - return getX509LocString(X509_get_subject_name(&x509)); -#endif -} - -std::string RsX509Cert::getCertOrg(const X509& x509) -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - return getX509OrgString(x509.cert_info->subject); -#else - return getX509OrgString(X509_get_subject_name(&x509)); -#endif -} - -/*static*/ RsPgpId RsX509Cert::getCertIssuer(const X509& x509) -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - return RsPgpId(getX509CNString(x509.cert_info->issuer)); -#else - return RsPgpId(getX509CNString(X509_get_issuer_name(&x509))); -#endif -} - -/*static*/ std::string RsX509Cert::getCertIssuerString(const X509& x509) -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - return getX509CNString(x509.cert_info->issuer); -#else - return getX509CNString(X509_get_issuer_name(&x509)); -#endif -} - -/*static*/ RsPeerId RsX509Cert::getCertSslId(const X509& x509) -{ - RsPeerId sslid; - return getX509id(const_cast(&x509), sslid) ? sslid : RsPeerId(); -} - -/************************************************************************ - * - * - * CODE IS DIVIDED INTO - * - * 1) SSL Setup. - * 3) Cert Access. - * 4) Cert Sign / Verify. - * 5) Cert Authentication - * 2) Cert Add / Remove - * 6) Cert Storage - */ - -/********************************************************************************/ -/********************************************************************************/ -/********************* Cert Search / Add / Remove **************************/ -/********************************************************************************/ -/********************************************************************************/ - - -AuthSSLimpl::AuthSSLimpl() : - p3Config(), sslctx(nullptr), mOwnCert(nullptr), sslMtx("AuthSSL"), - mOwnPrivateKey(nullptr), mOwnPublicKey(nullptr), init(0) {} - -AuthSSLimpl::~AuthSSLimpl() -{ - RS_STACK_MUTEX(sslMtx); - - SSL_CTX_free(sslctx); - X509_free(mOwnCert); - - EVP_PKEY_free(mOwnPrivateKey); - EVP_PKEY_free(mOwnPublicKey); - - for(auto pcert: mCerts) - X509_free(pcert.second); -} - -bool AuthSSLimpl::active() { return init; } - -int AuthSSLimpl::InitAuth( - const char* cert_file, const char* priv_key_file, const char* passwd, - std::string locationName ) -{ - /* single call here si don't need to invoke mutex yet */ - static int initLib = 0; - if (!initLib) - { - initLib = 1; - - if (!tls_init()) { - return 0; - } - - SSL_load_error_strings(); - SSL_library_init(); - } - - - if (init == 1) - { - std::cerr << "AuthSSLimpl::InitAuth already initialized." << std::endl; - return 1; - } - - if ((cert_file == NULL) || - (priv_key_file == NULL) || - (passwd == NULL)) - { - //fprintf(stderr, "sslroot::initssl() missing parameters!\n"); - return 0; - } - - - // actions_to_seed_PRNG(); - RAND_seed(passwd, strlen(passwd)); - - std::cerr << "SSL Library Init!" << std::endl; - - // setup connection method - sslctx = SSL_CTX_new(SSLv23_method()); - SSL_CTX_set_options(sslctx,SSL_OP_NO_SSLv3) ; - - //SSL_OP_SINGLE_DH_USE CVE-2016-0701 - //https://www.openssl.org/docs/manmaster/ssl/SSL_CTX_set_options.html - //If "strong" primes were used, it is not strictly necessary to generate a new DH key during each handshake but it is also recommended. SSL_OP_SINGLE_DH_USE should therefore be enabled whenever temporary/ephemeral DH parameters are used. - //SSL_CTX_set_options() adds the options set via bitmask in options to ctx. Options already set before are not cleared! - SSL_CTX_set_options(sslctx,SSL_OP_SINGLE_DH_USE) ; - - - // Setup cipher lists: - // - // std::string cipherString = "HIGH:!DSS:!aNULL:!3DES"; - // std::string cipherString = "DEFAULT"; - // - // The current cipher list asks in priority for EDH which provides PFS. However EDH needs proper - // parameters to be set on the server side, so if we're a client for a RS instance that has no DH params, - // the connection will be refused. So we happend the HIGH cipher suite just after. In oder to force - // PFS, at the risk of not always connecting, one should use: - // - // std::string cipherString = "kEDH:HIGH:!DSS:!aNULL:!3DES"; - // - // The following safe primes are 2048/4096 bits long. Should be enough. - // - // std::string dh_prime_2048_dec = "30651576830996935311378276950670996791883170963804289256203421500259588715033040934547350194073369837229137842804826417332761673984632102152477971341551955103053338169949165519208562998954887445690136488713010579430413255432398961330773637820158790237012997356731669148258317860643591694814197514454546928317578771868379525705082166818553884557266645700906836702542808787791878865135741211056957383668479369231868698451684633965462539374994559481908068730787128654626819903401038534403722014687647173327537458614224702967073490136394698912372792187651228785689025073104374674728645661275001416541267543884923191810923"; - // - //Not used (should be here: /libretroshare/src/gxstunnel/p3gxstunnel.cc:1131 - //std::string dh_prime_2048_hex = "B3B86A844550486C7EA459FA468D3A8EFD71139593FE1C658BBEFA9B2FC0AD2628242C2CDC2F91F5B220ED29AAC271192A7374DFA28CDDCA70252F342D0821273940344A7A6A3CB70C7897A39864309F6CAC5C7EA18020EF882693CA2C12BB211B7BA8367D5A7C7252A5B5E840C9E8F081469EBA0B98BCC3F593A4D9C4D5DF539362084F1B9581316C1F80FDAD452FD56DBC6B8ED0775F596F7BB22A3FE2B4753764221528D33DB4140DE58083DB660E3E105123FC963BFF108AC3A268B7380FFA72005A1515C371287C5706FFA6062C9AC73A9B1A6AC842C2764CDACFC85556607E86611FDF486C222E4896CDF6908F239E177ACC641FCBFF72A758D1C10CBB" ; - - std::string dh_prime_4096_hex = "A6F5777292D9E6BB95559C9124B9119E6771F11F2048C8FE74F4E8140494520972A087EF1D60B73894F1C5D509DD15D96CF379E9DDD46CE51B748085BACB440D915565782C73AF3A9580CE788441D1DA4D114E3D302CAB45A061ABCFC1F7E9200AE019CB923B77E096FA9377454A16FFE91D86535FF23E075B3E714F785CD7606E9CBD9D06F01CAFA2271883D649F13ABE170D714F6B6EC064C5BF35C4F4BDA5EF5ED5E70D5DC78F1AC1CDC04EEDAE8ADD65C4A9E27368E0B2C8595DD7626D763BFFB15364B3CCA9FCE814B9226B35FE652F4B041F0FF6694D6A482B0EF48CA41163D083AD2DE7B7A068BB05C0453E9D008551C7F67993A3EF2C4874F0244F78C4E0997BD31AB3BD88446916B499B2513DD5BA002063BD38D2CE55D29D071399D5CEE99458AF6FDC104A61CA3FACDAC803CBDE62B4C0EAC946D0E12F05CE9E94497110D64E611D957423B8AA412D84EC83E6E70E0977A31D6EE056D0527D4667D7242A77C9B679D191562E4026DA9C35FF85666296D872ED548E0FFE1A677FCC373C1F490CAB4F53DFD8735C0F1DF02FEAD824A217FDF4E3404D38A5BBC719C6622630FCD34F6F1968AF1B66A4AB1A9FCF653DA96EB3A42AF6FCFEA0547B8F314A527C519949007D7FA1726FF3D33EC46393B0207AA029E5EA574BDAC94D78894B22A2E3303E65A3F820DF57DB44951DE4E973C016C57F7A242D0BC53BC563AF" ; - - std::string cipherString = "kEDH+HIGH:!DSS:!aNULL:!3DES:!EXP"; - - SSL_CTX_set_cipher_list(sslctx, cipherString.c_str()); - - DH* dh = DH_new(); - int codes = 0; - bool pfs_enabled = true ; - - if (dh) - { -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - BN_hex2bn(&dh->p,dh_prime_4096_hex.c_str()) ; - BN_hex2bn(&dh->g,"5") ; -#else - BIGNUM *pp=NULL,*gg=NULL ; - - BN_hex2bn(&pp,dh_prime_4096_hex.c_str()) ; - BN_hex2bn(&gg,"5"); - - DH_set0_pqg(dh,pp,NULL,gg) ; -#endif - - std::cout.flush() ; - -#ifndef RS_DISABLE_DIFFIE_HELLMAN_INIT_CHECK - if(DH_check(dh, &codes) && codes == 0) - SSL_CTX_set_tmp_dh(sslctx, dh); - else - pfs_enabled = false; -#else // ndef RS_DISABLE_DIFFIE_HELLMAN_INIT_CHECK - /* DH_check(...) is not strictly necessary and on Android devices it - * takes at least one minute which is untolerable there */ - SSL_CTX_set_tmp_dh(sslctx, dh); -#endif // ndef RS_DISABLE_DIFFIE_HELLMAN_INIT_CHECK - } - else - pfs_enabled = false ; - - // certificates (Set Local Server Certificate). - FILE *ownfp = RsDirUtil::rs_fopen(cert_file, "r"); - if (ownfp == NULL) - { - std::cerr << "Couldn't open Own Certificate!" << std::endl; - return -1; - } - - // get xPGP certificate. - X509 *x509 = PEM_read_X509(ownfp, NULL, NULL, NULL); - - fclose(ownfp); - - if (x509 == NULL) - { - std::cerr << "AuthSSLimpl::InitAuth() PEM_read_X509() Failed"; - std::cerr << std::endl; - return -1; - } - - int result = SSL_CTX_use_certificate(sslctx, x509); - -#if OPENSSL_VERSION_NUMBER >= 0x10101000L - if(result != 1) - { - // In debian Buster, openssl security level is set to 2 which preclude the use of SHA1, originally used to sign RS certificates. - // As a consequence, on these systems, locations created with RS previously to Jan.2020 will not start unless we revert the - // security level to a value of 1. - - int save_sec = SSL_CTX_get_security_level(sslctx); - SSL_CTX_set_security_level(sslctx,1); - result = SSL_CTX_use_certificate(sslctx, x509); - - if(result == 1) - { - std::cerr << std::endl; - std::cerr << " Your Retroshare certificate uses low security settings that are incompatible " << std::endl; - std::cerr << "(WW) with current security level " << save_sec << " of the OpenSSL library. Retroshare will still start " << std::endl; - std::cerr << " (with security level set to 1), but you should probably create a new location." << std::endl; - std::cerr << std::endl; - } - } -#endif - - if(result != 1) - { - std::cerr << "(EE) Cannot use your Retroshare certificate. Some error occured in SSL_CTX_use_certificate()" << std::endl; - return -1; - } - - mOwnPublicKey = X509_get_pubkey(x509); - - // get private key - FILE *pkfp = RsDirUtil::rs_fopen(priv_key_file, "rb"); - if (pkfp == NULL) - { - std::cerr << "Couldn't Open PrivKey File!" << std::endl; - CloseAuth(); - return -1; - } - - mOwnPrivateKey = PEM_read_PrivateKey(pkfp, NULL, NULL, (void *) passwd); - fclose(pkfp); - - if (mOwnPrivateKey == NULL) - { - std::cerr << "AuthSSLimpl::InitAuth() PEM_read_PrivateKey() Failed"; - std::cerr << std::endl; - return -1; - } - SSL_CTX_use_PrivateKey(sslctx, mOwnPrivateKey); - - if (1 != SSL_CTX_check_private_key(sslctx)) - { - std::cerr << "Issues With Private Key! - Doesn't match your Cert" << std::endl; - std::cerr << "Check your input key/certificate:" << std::endl; - std::cerr << priv_key_file << " & " << cert_file; - std::cerr << std::endl; - CloseAuth(); - return -1; - } - - RsPeerId mownidstr ; - - if (!getX509id(x509, mownidstr)) - { - std::cerr << "AuthSSLimpl::InitAuth() getX509id() Failed"; - std::cerr << std::endl; - - /* bad certificate */ - CloseAuth(); - return -1; - } - mOwnId = mownidstr ; - - assert(!mOwnId.isNull()) ; - - /* Check that Certificate is Ok ( virtual function ) - * for gpg/pgp or CA verification - */ - - if (!validateOwnCertificate(x509, mOwnPrivateKey)) - { - std::cerr << "AuthSSLimpl::InitAuth() validateOwnCertificate() Failed"; - std::cerr << std::endl; - - /* bad certificate */ - CloseAuth(); - exit(1); - return -1; - } - - - // enable verification of certificates (PEER) - // and install verify callback. - SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER | - SSL_VERIFY_FAIL_IF_NO_PEER_CERT, - verify_x509_callback); - - std::cerr << "SSL Verification Set" << std::endl; - - mOwnCert = x509; - - std::cerr << "Inited SSL context: " << std::endl; - std::cerr << " Certificate: " << mOwnId << std::endl; - std::cerr << " cipher list: " << cipherString << std::endl; - std::cerr << " PFS enabled: " << (pfs_enabled?"YES":"NO") ; - if(codes > 0) - { - std::cerr << " (reason: " ; - if(codes & DH_CHECK_P_NOT_PRIME ) std::cerr << "Not a prime number, " ; - if(codes & DH_CHECK_P_NOT_SAFE_PRIME) std::cerr << "Not a safe prime number, " ; - if(codes & DH_UNABLE_TO_CHECK_GENERATOR) std::cerr << "unable to check generator, " ; - if(codes & DH_NOT_SUITABLE_GENERATOR) std::cerr << "not a suitable generator" ; - std::cerr << ")" << std::endl; - } - else - std::cerr << std::endl; - - mOwnLocationName = locationName; - - init = 1; - return 1; -} - -/* Dummy function to be overloaded by real implementation */ -bool AuthSSLimpl::validateOwnCertificate(X509 *x509, EVP_PKEY *pkey) -{ - (void) pkey; /* remove unused parameter warning */ - - uint32_t diagnostic ; - - /* standard authentication */ - if (!AuthX509WithGPG(x509,true,diagnostic)) - { - std::cerr << "Validate Own certificate ERROR: diagnostic = " << diagnostic << std::endl; - return false; - } - return true; -} - -bool AuthSSLimpl::CloseAuth() -{ - tls_cleanup(); - -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSLimpl::CloseAuth()"; - std::cerr << std::endl; -#endif - SSL_CTX_free(sslctx); - - // clean up private key.... - // remove certificates etc -> opposite of initssl. - init = 0; - return 1; -} - -/* Context handling */ -SSL_CTX *AuthSSLimpl::getCTX() -{ -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSLimpl::getCTX()"; - std::cerr << std::endl; -#endif - return sslctx; -} - -const RsPeerId& AuthSSLimpl::OwnId() -{ -#ifdef AUTHSSL_DEBUG -// std::cerr << "AuthSSLimpl::OwnId()" << std::endl; -#endif - return mOwnId; -} - -std::string AuthSSLimpl::getOwnLocation() -{ return mOwnLocationName; } - -std::string AuthSSLimpl::SaveOwnCertificateToString() -{ return saveX509ToPEM(mOwnCert); } - -/********************************************************************************/ -/********************************************************************************/ -/********************* Cert Search / Add / Remove **************************/ -/********************************************************************************/ -/********************************************************************************/ - -bool AuthSSLimpl::SignData(std::string input, std::string &sign) -{ - return SignData(input.c_str(), input.length(), sign); -} - -bool AuthSSLimpl::SignData(const void *data, const uint32_t len, std::string &sign) -{ - - RsStackMutex stack(sslMtx); /***** STACK LOCK MUTEX *****/ - - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - unsigned int signlen = EVP_PKEY_size(mOwnPrivateKey); - unsigned char signature[signlen] ; - memset(signature,0,signlen) ; - - if (0 == EVP_SignInit(mdctx, EVP_sha1())) - { - std::cerr << "EVP_SignInit Failure!" << std::endl; - - EVP_MD_CTX_destroy(mdctx); - return false; - } - - if (0 == EVP_SignUpdate(mdctx, data, len)) - { - std::cerr << "EVP_SignUpdate Failure!" << std::endl; - - EVP_MD_CTX_destroy(mdctx); - return false; - } - - if (0 == EVP_SignFinal(mdctx, signature, &signlen, mOwnPrivateKey)) - { - std::cerr << "EVP_SignFinal Failure!" << std::endl; - - EVP_MD_CTX_destroy(mdctx); - return false; - } - - EVP_MD_CTX_destroy(mdctx); - - sign.clear(); - for(uint32_t i = 0; i < signlen; i++) - { - rs_sprintf_append(sign, "%02x", (uint32_t) (signature[i])); - } - - return true; -} - -bool AuthSSLimpl::SignDataBin(std::string input, unsigned char *sign, unsigned int *signlen) -{ - return SignDataBin(input.c_str(), input.length(), sign, signlen); -} - -bool AuthSSLimpl::SignDataBin(const void *data, const uint32_t len, - unsigned char *sign, unsigned int *signlen) -{ - RsStackMutex stack(sslMtx); /***** STACK LOCK MUTEX *****/ - return SSL_SignDataBin(data, len, sign, signlen, mOwnPrivateKey); -} - - -bool AuthSSLimpl::VerifySignBin(const void *data, const uint32_t len, - unsigned char *sign, unsigned int signlen, const RsPeerId& sslId) -{ - /* find certificate. - * if we don't have - fail. - */ - - RsStackMutex stack(sslMtx); /***** STACK LOCK MUTEX *****/ - - /* find the peer */ - X509* peercert; - if (sslId == mOwnId) peercert = mOwnCert; - else if (!locked_FindCert(sslId, &peercert)) - { - std::cerr << "VerifySignBin() no peer" << std::endl; - return false; - } - - return SSL_VerifySignBin(data, len, sign, signlen, peercert); -} - -bool AuthSSLimpl::VerifyOwnSignBin(const void *data, const uint32_t len, - unsigned char *sign, unsigned int signlen) -{ return SSL_VerifySignBin(data, len, sign, signlen, mOwnCert); } - - -/********************************************************************************/ -/********************************************************************************/ -/********************* Sign and Auth with GPG **************************/ -/********************************************************************************/ -/********************************************************************************/ - -/* Note these functions don't need Mutexes - - * only using GPG functions - which lock themselves - */ - -X509 *AuthSSLimpl::SignX509ReqWithGPG(X509_REQ *req, long /*days*/) -{ - /* Transform the X509_REQ into a suitable format to - * generate DIGEST hash. (for SSL to do grunt work) - */ - -#define SERIAL_RAND_BITS 64 - - //const EVP_MD *digest = EVP_sha1(); - EVP_PKEY *tmppkey; - X509 *x509 = X509_new(); - if (x509 == NULL) - { - std::cerr << "AuthSSLimpl::SignX509Req() FAIL" << std::endl; - return NULL; - } - - //long version = 0x00; - unsigned long chtype = MBSTRING_UTF8; - X509_NAME *issuer_name = X509_NAME_new(); - X509_NAME_add_entry_by_txt(issuer_name, "CN", chtype, (unsigned char *) AuthPGP::getPgpOwnId().toStdString().c_str(), -1, -1, 0); -/**** - X509_NAME_add_entry_by_NID(issuer_name, 48, 0, - (unsigned char *) "email@email.com", -1, -1, 0); - X509_NAME_add_entry_by_txt(issuer_name, "O", chtype, - (unsigned char *) "org", -1, -1, 0); - X509_NAME_add_entry_by_txt(x509_name, "L", chtype, - (unsigned char *) "loc", -1, -1, 0); -****/ - - std::cerr << "AuthSSLimpl::SignX509Req() Issuer name: " << AuthPGP::getPgpOwnId().toStdString() << std::endl; - -#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_002 - static const uint64_t CERTIFICATE_SERIAL_NUMBER = RS_CERTIFICATE_VERSION_NUMBER_07_0001 ; -#else -#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_001 - static const uint64_t CERTIFICATE_SERIAL_NUMBER = RS_CERTIFICATE_VERSION_NUMBER_06_0001 ; -#else - static const uint64_t CERTIFICATE_SERIAL_NUMBER = RS_CERTIFICATE_VERSION_NUMBER_06_0000 ; -#endif -#endif - - BIGNUM *btmp = BN_new(); - BN_set_word(btmp,CERTIFICATE_SERIAL_NUMBER) ; - -#ifdef OLD_CODE - if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0)) - { - std::cerr << "AuthSSLimpl::SignX509Req() rand FAIL" << std::endl; - return NULL; - } -#endif - ASN1_INTEGER *serial = ASN1_INTEGER_new(); - - if (!BN_to_ASN1_INTEGER(btmp, serial)) - { - std::cerr << "AuthSSLimpl::SignX509Req() asn1 FAIL" << std::endl; - return NULL; - } - BN_free(btmp); - - if (!X509_set_serialNumber(x509, serial)) - { - std::cerr << "AuthSSLimpl::SignX509Req() serial FAIL" << std::endl; - return NULL; - } - ASN1_INTEGER_free(serial); - - /* Generate SUITABLE issuer name. - * Must reference OpenPGP key, that is used to verify it - */ - - if (!X509_set_issuer_name(x509, issuer_name)) - { - std::cerr << "AuthSSLimpl::SignX509Req() issue FAIL" << std::endl; - return NULL; - } - X509_NAME_free(issuer_name); - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - // (does not leak the key creation date to the outside anymore. for more privacy) - ASN1_TIME_set(X509_get_notBefore(x509), 0); - ASN1_TIME_set(X509_get_notAfter(x509), 0); -#else - // NEW code, set validity time between 2010 and 2110 (remember to change it when, if OpenSSL check it by default. ;) ) - // (does not leak the key creation date to the outside anymore. for more privacy) - if (!ASN1_TIME_set_string(X509_getm_notBefore(x509), "20100101000000Z")) - { - RsErr() << __PRETTY_FUNCTION__ << " Set notBefore FAIL" << std::endl; - return NULL; - } - if (!ASN1_TIME_set_string(X509_getm_notAfter(x509), "21100101000000Z")) - { - RsErr() << __PRETTY_FUNCTION__ << " Set notAfter FAIL" << std::endl; - return NULL; - } -#endif - - if (!X509_set_subject_name(x509, X509_REQ_get_subject_name(req))) - { - std::cerr << "AuthSSLimpl::SignX509Req() sub FAIL" << std::endl; - return NULL; - } - - tmppkey = X509_REQ_get_pubkey(req); - if (!tmppkey || !X509_set_pubkey(x509,tmppkey)) - { - std::cerr << "AuthSSLimpl::SignX509Req() pub FAIL" << std::endl; - return NULL; - } - - std::cerr << "X509 Cert, prepared for signing" << std::endl; - - /*** NOW The Manual signing bit (HACKED FROM asn1/a_sign.c) ***/ - // - // The code has been copied in order to use the PGP signing instead of supplying the - // private EVP_KEY to ASN1_sign(), which would be another alternative. - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - int (*i2d)(X509_CINF*, unsigned char**) = i2d_X509_CINF; - X509_ALGOR *algor1 = x509->cert_info->signature; - X509_ALGOR *algor2 = x509->sig_alg; - ASN1_BIT_STRING *signature = x509->signature; - X509_CINF *data = x509->cert_info; -#else - const X509_ALGOR *algor1 = X509_get0_tbs_sigalg(x509) ; - const X509_ALGOR *algor2 = NULL ; - - const ASN1_BIT_STRING *tmp_signature = NULL ; - - X509_get0_signature(&tmp_signature,&algor2,x509); - - ASN1_BIT_STRING *signature = const_cast(tmp_signature); -#endif - //EVP_PKEY *pkey = NULL; -#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_002 - const EVP_MD *type = EVP_sha256(); -#else - const EVP_MD *type = EVP_sha1(); -#endif - - EVP_MD_CTX *ctx = EVP_MD_CTX_create(); - int inl=0; - X509_ALGOR *a; - - /* FIX ALGORITHMS */ - - a = const_cast(algor1); -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - ASN1_TYPE_free(a->parameter); - a->parameter=ASN1_TYPE_new(); - a->parameter->type=V_ASN1_NULL; - - ASN1_OBJECT_free(a->algorithm); - a->algorithm=OBJ_nid2obj(type->pkey_type); -#else - X509_ALGOR_set0(a,OBJ_nid2obj(EVP_MD_pkey_type(type)),V_ASN1_NULL,NULL); -#endif - - a = const_cast(algor2); -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - ASN1_TYPE_free(a->parameter); - a->parameter=ASN1_TYPE_new(); - a->parameter->type=V_ASN1_NULL; - - ASN1_OBJECT_free(a->algorithm); - a->algorithm=OBJ_nid2obj(type->pkey_type); -#else - X509_ALGOR_set0(a,OBJ_nid2obj(EVP_MD_pkey_type(type)),V_ASN1_NULL,NULL); -#endif - - - std::cerr << "Algorithms Fixed" << std::endl; - - unsigned int sigoutl=2048; // hashoutl; //EVP_PKEY_size(pkey); - unsigned char *buf_sigout=(unsigned char *)OPENSSL_malloc((unsigned int)sigoutl); - - /* input buffer */ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - inl=i2d(data,NULL); - unsigned char *buf_in=(unsigned char *)OPENSSL_malloc((unsigned int)inl); - - if(buf_in == NULL) - { - sigoutl=0; - fprintf(stderr, "AuthSSLimpl::SignX509Req: ASN1err(ASN1_F_ASN1_SIGN,ERR_R_MALLOC_FAILURE)\n"); - return NULL ; - } - unsigned char *p=buf_in; // This because i2d modifies the pointer after writing to it. - i2d(data,&p); -#else - unsigned char *buf_in=NULL; - inl=i2d_re_X509_tbs(x509,&buf_in) ; // this does the i2d over x509->cert_info -#endif - -#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_003 - if((buf_in == NULL) || (buf_sigout == NULL)) - { - sigoutl=0; - fprintf(stderr, "AuthSSLimpl::SignX509Req: ASN1err(ASN1_F_ASN1_SIGN,ERR_R_MALLOC_FAILURE)\n"); - goto err; - } - std::cerr << "Buffers Allocated" << std::endl; - - /* NOW Sign via GPG Functions */ - if (!AuthPGP::SignDataBin(buf_in, inl, buf_sigout, (unsigned int *) &sigoutl,"AuthSSLimpl::SignX509ReqWithGPG()")) - { - sigoutl = 0; - goto err; - } -#else - unsigned int hashoutl=EVP_MD_size(type); - unsigned char *buf_hashout=(unsigned char *)OPENSSL_malloc((unsigned int)hashoutl); - - if((buf_hashout == NULL) || (buf_sigout == NULL)) - { - hashoutl=0; - sigoutl=0; - fprintf(stderr, "AuthSSLimpl::SignX509Req: ASN1err(ASN1_F_ASN1_SIGN,ERR_R_MALLOC_FAILURE)\n"); - goto err; - } - std::cerr << "Buffers Allocated" << std::endl; - - /* data in buf_in, ready to be hashed */ - EVP_DigestInit_ex(ctx,type, NULL); - EVP_DigestUpdate(ctx,(unsigned char *)buf_in,inl); - if (!EVP_DigestFinal(ctx,(unsigned char *)buf_hashout, (unsigned int *)&hashoutl)) - { - hashoutl=0; - fprintf(stderr, "AuthSSLimpl::SignX509Req: ASN1err(ASN1_F_ASN1_SIGN,ERR_R_EVP_LIB)\n"); - goto err; - } - - std::cerr << "Digest Applied: len: " << hashoutl << std::endl; - - /* NOW Sign via GPG Functions */ - if (!AuthGPG::getAuthGPG()->SignDataBin(buf_hashout, hashoutl, buf_sigout, (unsigned int *) &sigoutl,"AuthSSLimpl::SignX509ReqWithGPG()")) - { - sigoutl = 0; - goto err; - } -#endif - - std::cerr << "Buffer Sizes: in: " << inl; -#ifndef V07_NON_BACKWARD_COMPATIBLE_CHANGE_003 - std::cerr << " HashOut: " << hashoutl; -#endif - std::cerr << " SigOut: " << sigoutl; - std::cerr << std::endl; - - //passphrase = "NULL"; - - std::cerr << "Signature done: len:" << sigoutl << std::endl; - - /* ADD Signature back into Cert... Signed!. */ - - if (signature->data != NULL) OPENSSL_free(signature->data); - signature->data=buf_sigout; - buf_sigout=NULL; - signature->length=sigoutl; - /* In the interests of compatibility, I'll make sure that - * the bit string has a 'not-used bits' value of 0 - */ - signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); - signature->flags|=ASN1_STRING_FLAG_BITS_LEFT; - - std::cerr << "Certificate Complete" << std::endl; - - EVP_MD_CTX_destroy(ctx) ; - - // debug - // { - // int pkey_nid = OBJ_obj2nid(x509->sig_alg->algorithm); - // const char* sslbuf = OBJ_nid2ln(pkey_nid); - // std::cerr << "Signature hash algorithm: " << sslbuf << std::endl; - // } - - return x509; - - /* XXX CLEANUP */ - err: - /* cleanup */ - if(buf_in != NULL) - OPENSSL_free(buf_in) ; -#ifndef V07_NON_BACKWARD_COMPATIBLE_CHANGE_003 - if(buf_hashout != NULL) - OPENSSL_free(buf_hashout) ; -#endif - if(buf_sigout != NULL) - OPENSSL_free(buf_sigout) ; - std::cerr << "GPGAuthMgr::SignX509Req() err: FAIL" << std::endl; - - return NULL; -} - - -bool AuthSSLimpl::AuthX509WithGPG(X509 *x509,bool verbose, uint32_t& diagnostic) -{ - RsPgpId issuer = RsX509Cert::getCertIssuer(*x509); - RsPeerDetails pd; - if (!AuthPGP::getPgpDetails(issuer, pd)) - { - RsInfo() << __PRETTY_FUNCTION__ << " X509 NOT authenticated : " - << "AuthGPG::getAuthGPG()->getGPGDetails(" << issuer - << ",...) returned false." << std::endl; - diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_ISSUER_UNKNOWN; - return false; - } - else - Dbg3() << __PRETTY_FUNCTION__ << " issuer: " << issuer << " found" - << std::endl; - - /* verify GPG signature */ - /*** NOW The Manual signing bit (HACKED FROM asn1/a_sign.c) ***/ - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - int (*i2d)(X509_CINF*, unsigned char**) = i2d_X509_CINF; - ASN1_BIT_STRING* signature = x509->signature; - X509_CINF* data = x509->cert_info; -#else - const ASN1_BIT_STRING* signature = nullptr; - const X509_ALGOR* algor2 = nullptr; - X509_get0_signature(&signature,&algor2,x509); -#endif - - uint32_t certificate_version = getX509RetroshareCertificateVersion(x509); - - EVP_MD_CTX* ctx = EVP_MD_CTX_create(); - int inl = 0; - - const unsigned char* signed_data = nullptr; - uint32_t signed_data_length = 0; - - /* input buffer */ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - inl = i2d(data, nullptr); - unsigned char* buf_in = static_cast( - OPENSSL_malloc(static_cast(inl)) ); - unsigned char* p = nullptr; -#else - unsigned char* buf_in = nullptr; - inl=i2d_re_X509_tbs(x509,&buf_in) ; // this does the i2d over x509->cert_info -#endif - - if(buf_in == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ - << " ASN1err(ASN1_F_ASN1_SIGN,ERR_R_MALLOC_FAILURE)" << std::endl; - diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_MALLOC_ERROR ; - return false; - } - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - p = buf_in; - i2d(data,&p); -#endif - - { // this scope is to avoid cross-initialization jumps to err. - - const Sha1CheckSum sha1 = RsDirUtil::sha1sum( - buf_in, static_cast(inl) ); - - if(certificate_version < RS_CERTIFICATE_VERSION_NUMBER_07_0001) - { - /* If the certificate belongs to 0.6 version, we hash it here, and - * then re-hash the hash it in the PGP signature */ - signed_data = sha1.toByteArray(); - signed_data_length = sha1.SIZE_IN_BYTES; - } - else - { - signed_data = buf_in ; - signed_data_length = static_cast(inl); - } - - /* NOW check sign via GPG Functions */ - - Dbg2() << __PRETTY_FUNCTION__ - << " verifying the PGP Key signature with finger print: " - << pd.fpr << std::endl; - - /* Take a early look at signature parameters. In particular we dont - * accept signatures with unsecure hash algorithms */ - - PGPSignatureInfo signature_info ; - PGPKeyManagement::parseSignature( - signature->data, static_cast(signature->length), - signature_info ); - - if(signature_info.signature_version != PGP_PACKET_TAG_SIGNATURE_VERSION_V4) - { - diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE_VERSION; - goto err; - } - - std::string sigtypestring; - - switch(signature_info.signature_type) - { - case PGP_PACKET_TAG_SIGNATURE_TYPE_BINARY_DOCUMENT: break; - case PGP_PACKET_TAG_SIGNATURE_TYPE_STANDALONE_SIG: /*fallthrough*/ - case PGP_PACKET_TAG_SIGNATURE_TYPE_CANONICAL_TEXT: /*fallthrough*/ - case PGP_PACKET_TAG_SIGNATURE_TYPE_UNKNOWN: /*fallthrough*/ - default: - diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE_TYPE; - goto err; - } - - switch(signature_info.public_key_algorithm) - { - case PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_RSA_ES: /*fallthrough*/ - case PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_RSA_S: - sigtypestring = "RSA"; - break ; - case PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_DSA: - sigtypestring = "DSA"; - break ; - case PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_RSA_E: /*fallthrough*/ - case PGP_PACKET_TAG_PUBLIC_KEY_ALGORITHM_UNKNOWN: /*fallthrough*/ - default: - diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_HASH_ALGORITHM_NOT_ACCEPTED ; - goto err ; - } - - switch(signature_info.hash_algorithm) - { - case PGP_PACKET_TAG_HASH_ALGORITHM_SHA1: - sigtypestring += "+SHA1"; - break; - case PGP_PACKET_TAG_HASH_ALGORITHM_SHA256: - sigtypestring += "+SHA256"; - break; - case PGP_PACKET_TAG_HASH_ALGORITHM_SHA512: - sigtypestring += "+SHA512"; - break; - // We dont accept signatures with unknown or weak hash algorithms. - case PGP_PACKET_TAG_HASH_ALGORITHM_MD5: /*fallthrough*/ - case PGP_PACKET_TAG_HASH_ALGORITHM_UNKNOWN: /*fallthrough*/ - default: - diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_HASH_ALGORITHM_NOT_ACCEPTED; - goto err; - } - - // passed, verify the signature itself - - if (!AuthPGP::VerifySignBin( signed_data, signed_data_length, signature->data, static_cast(signature->length), pd.fpr )) - { - diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE; - goto err; - } - - if(verbose) - RsInfo() << " Verified: " << sigtypestring - << " signature of certificate sslId: " - << RsX509Cert::getCertSslId(*x509) - << ", Version " << std::hex << certificate_version << std::dec - << " using PGP key " << pd.fpr << " " << pd.name << std::endl; - } - - EVP_MD_CTX_destroy(ctx); - - OPENSSL_free(buf_in); - - diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_OK; - - return true; - -err: // TODO: this label is very short and might collide every easly - RsInfo() << __PRETTY_FUNCTION__ << " X509 PGP authentication failed with " - << "diagnostic: " << diagnostic << std::endl; - - if(buf_in) OPENSSL_free(buf_in); - - return false; -} - -/********************************************************************************/ -/********************************************************************************/ -/**************************** encrypt / decrypt fns ****************************/ -/********************************************************************************/ -/********************************************************************************/ - -static int verify_x509_callback(int preverify_ok, X509_STORE_CTX *ctx) -{ return AuthSSL::instance().VerifyX509Callback(preverify_ok, ctx); } - -int AuthSSLimpl::VerifyX509Callback(int /*preverify_ok*/, X509_STORE_CTX* ctx) -{ - /* According to OpenSSL documentation must return 0 if verification failed - * and 1 if succeded (aka can continue connection). - * About preverify_ok OpenSSL documentation doesn't tell which value is - * passed to the first callback in the authentication chain, it just says - * that the result of previous step is passed down, so I have tested it - * and we get passed 0 always so in our case as there is no other - * verifications step vefore we ignore it completely */ - - constexpr int verificationFailed = 0; - constexpr int verificationSuccess = 1; - - using Evt_t = RsAuthSslConnectionAutenticationEvent; - std::unique_ptr ev = std::unique_ptr(new Evt_t); - - X509* x509Cert = X509_STORE_CTX_get_current_cert(ctx); - if(!x509Cert) - { - std::string errMsg = "Cannot get certificate! OpenSSL error: " + - std::to_string(X509_STORE_CTX_get_error(ctx)) + " depth: " + - std::to_string(X509_STORE_CTX_get_error_depth(ctx)); - - RsErr() << __PRETTY_FUNCTION__ << " " << errMsg << std::endl; - - return verificationFailed; - } - - RsPeerId sslId = RsX509Cert::getCertSslId(*x509Cert); - std::string sslCn = RsX509Cert::getCertIssuerString(*x509Cert); - - RsPgpId pgpId(sslCn); - - if(sslCn.length() == RsPgpFingerprint::SIZE_IN_BYTES*2) - { - RsPgpFingerprint pgpFpr(sslCn); // we also accept fingerprint format, so that in the future we can switch to fingerprints without backward compatibility issues - - if(!pgpFpr.isNull()) - pgpId = PGPHandler::pgpIdFromFingerprint(pgpFpr); // in the future, we drop PGP ids and keep the fingerprint all along - } - - if(sslId.isNull()) - { - std::string errMsg = "x509Cert has invalid sslId!"; - - RsInfo() << __PRETTY_FUNCTION__ << " " << errMsg << std::endl; - - if(rsEvents) - { - ev->mSslCn = sslCn; - ev->mSslId = sslId; - ev->mPgpId = pgpId; - ev->mErrorMsg = errMsg; - ev->mErrorCode = RsAuthSslError::MISSING_AUTHENTICATION_INFO; - - rsEvents->postEvent(std::move(ev)); - } - - return verificationFailed; - } - - if(pgpId.isNull()) - { - std::string errMsg = "x509Cert has invalid pgpId! sslCn >>>" + sslCn + - "<<<"; - - RsInfo() << __PRETTY_FUNCTION__ << " " << errMsg << std::endl; - - if(rsEvents) - { - ev->mSslId = sslId; - ev->mSslCn = sslCn; - ev->mErrorMsg = errMsg; - ev->mErrorCode = RsAuthSslError::MISSING_AUTHENTICATION_INFO; - - rsEvents->postEvent(std::move(ev)); - } - - return verificationFailed; - } - - bool isSslOnlyFriend = false; - - // For SSL only friends (ones added through short invites) we check that the fingerprint - // in the key (det.gpg_id) matches the one of the handshake. - { - RsPeerDetails det; - - if(rsPeers->getPeerDetails(sslId,det)) - isSslOnlyFriend = det.skip_pgp_signature_validation; - - if(det.skip_pgp_signature_validation && det.gpg_id != pgpId)// in the future, we should compare fingerprints instead - { - std::string errorMsg = "Peer " + sslId.toStdString() + " trying to connect with issuer ID " + pgpId.toStdString() - + " whereas key ID " + det.gpg_id.toStdString() + " was expected! Refusing connection." ; - - RsErr() << __PRETTY_FUNCTION__ << errorMsg << std::endl; - - if(rsEvents) - { - ev->mSslId = sslId; - ev->mSslCn = sslCn; - ev->mPgpId = pgpId; - ev->mErrorMsg = errorMsg; - ev->mErrorCode = RsAuthSslError::MISMATCHED_PGP_ID; - rsEvents->postEvent(std::move(ev)); - } - - return verificationFailed; - } - } - - uint32_t auth_diagnostic; - if(!isSslOnlyFriend && !AuthX509WithGPG(x509Cert,true, auth_diagnostic)) - { - std::string errMsg = "Certificate was rejected because PGP " - "signature verification failed with diagnostic: " - + std::to_string(auth_diagnostic) + " certName: " + - RsX509Cert::getCertName(*x509Cert) + " sslId: " + - RsX509Cert::getCertSslId(*x509Cert).toStdString() + - " issuerString: " + RsX509Cert::getCertIssuerString(*x509Cert); - - RsInfo() << __PRETTY_FUNCTION__ << " " << errMsg << std::endl; - - if(rsEvents) - { - ev->mSslId = sslId; - ev->mSslCn = sslCn; - ev->mPgpId = pgpId; - - switch(auth_diagnostic) - { - case RS_SSL_HANDSHAKE_DIAGNOSTIC_ISSUER_UNKNOWN: - ev->mErrorCode = RsAuthSslError::NOT_A_FRIEND; - break; - case RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE: - ev->mErrorCode = RsAuthSslError::PGP_SIGNATURE_VALIDATION_FAILED; - break; - default: - ev->mErrorCode = RsAuthSslError::MISSING_AUTHENTICATION_INFO; - break; - } - - ev->mErrorMsg = errMsg; - rsEvents->postEvent(std::move(ev)); - } - - if (auth_diagnostic == RS_SSL_HANDSHAKE_DIAGNOSTIC_ISSUER_UNKNOWN) - RsServer::notify()->AddPopupMessage(RS_POPUP_CONNECT_ATTEMPT, pgpId.toStdString(), sslCn, sslId.toStdString()); /* notify Connect Attempt */ - - return verificationFailed; - } -#ifdef AUTHSSL_DEBUG - std::cerr << "******* VerifyX509Callback cert: " << std::hex << ctx->cert <mSslId = sslId; - ev->mSslCn = sslCn; - ev->mPgpId = pgpId; - ev->mErrorMsg = errMsg; - ev->mErrorCode = RsAuthSslError::NOT_A_FRIEND; - rsEvents->postEvent(std::move(ev)); - } - - RsServer::notify()->AddPopupMessage(RS_POPUP_CONNECT_ATTEMPT, pgpId.toStdString(), sslCn, sslId.toStdString()); /* notify Connect Attempt */ - - return verificationFailed; - } - - LocalStoreCert(x509Cert); - - RsInfo() << __PRETTY_FUNCTION__ << " authentication successfull for " - << "sslId: " << sslId << " isSslOnlyFriend: " << isSslOnlyFriend - << std::endl; - - return verificationSuccess; -} - -bool AuthSSLimpl::parseX509DetailsFromFile( const std::string& certFilePath, RsPeerId& certId, RsPgpId& issuer, std::string& location ) -{ - FILE* tmpfp = RsDirUtil::rs_fopen(certFilePath.c_str(), "r"); - if(!tmpfp) - { - RsErr() << __PRETTY_FUNCTION__ << " Failed to open Certificate File: " - << certFilePath << std::endl; - return false; - } - - // get xPGP certificate. - X509* x509 = PEM_read_X509(tmpfp, nullptr, nullptr, nullptr); - fclose(tmpfp); - - if(!x509) - { - RsErr() << __PRETTY_FUNCTION__ << " PEM_read_X509 failed!" << std::endl; - return false; - } - - uint32_t diagnostic = 0; - - if(!AuthX509WithGPG(x509,false, diagnostic)) - { - RsErr() << __PRETTY_FUNCTION__ << " AuthX509WithGPG failed with " - << "diagnostic: " << diagnostic << std::endl; - - X509_free(x509); - return false; - } - - certId = RsX509Cert::getCertSslId(*x509); - issuer = RsX509Cert::getCertIssuer(*x509); - location = RsX509Cert::getCertLocation(*x509); - - X509_free(x509); - - if(certId.isNull() || issuer.isNull()) return false; - - return true; -} - - -/********************************************************************************/ -/********************************************************************************/ -/**************************** encrypt / decrypt fns ****************************/ -/********************************************************************************/ -/********************************************************************************/ - - -bool AuthSSLimpl::encrypt(void *&out, int &outlen, const void *in, int inlen, const RsPeerId& peerId) -{ - RS_STACK_MUTEX(sslMtx); - - /*const*/ EVP_PKEY* public_key = nullptr; - if (peerId == mOwnId) { public_key = mOwnPublicKey; } - else - { - auto it = mCerts.find(peerId); - - if (it == mCerts.end()) - { - RsErr() << __PRETTY_FUNCTION__ << " public key not found." << std::endl; - return false; - } - else public_key = const_cast( RsX509Cert::getPubKey(*it->second) ); - } - - EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - int eklen, net_ekl; - unsigned char *ek; - unsigned char iv[EVP_MAX_IV_LENGTH]; - int out_currOffset = 0; - int out_offset = 0; - - int max_evp_key_size = EVP_PKEY_size(public_key); - ek = (unsigned char*)rs_malloc(max_evp_key_size); - - if(ek == NULL) - return false ; - - const EVP_CIPHER *cipher = EVP_aes_128_cbc(); - int cipher_block_size = EVP_CIPHER_block_size(cipher); - int size_net_ekl = sizeof(net_ekl); - - int max_outlen = inlen + cipher_block_size + EVP_MAX_IV_LENGTH + max_evp_key_size + size_net_ekl; - - // intialize context and send store encrypted cipher in ek - if(!EVP_SealInit(ctx, EVP_aes_128_cbc(), &ek, &eklen, iv, &public_key, 1)) { - free(ek); - return false; - } - - // now assign memory to out accounting for data, and cipher block size, key length, and key length val - out = (unsigned char*)rs_malloc(inlen + cipher_block_size + size_net_ekl + eklen + EVP_MAX_IV_LENGTH); - - if(out == NULL) - { - free(ek) ; - return false ; - } - net_ekl = htonl(eklen); - memcpy((unsigned char*)out + out_offset, &net_ekl, size_net_ekl); - out_offset += size_net_ekl; - - memcpy((unsigned char*)out + out_offset, ek, eklen); - out_offset += eklen; - - memcpy((unsigned char*)out + out_offset, iv, EVP_MAX_IV_LENGTH); - out_offset += EVP_MAX_IV_LENGTH; - - // now encrypt actual data - if(!EVP_SealUpdate(ctx, (unsigned char*) out + out_offset, &out_currOffset, (unsigned char*) in, inlen)) { - free(ek); - free(out); - out = NULL; - return false; - } - - // move along to partial block space - out_offset += out_currOffset; - - // add padding - if(!EVP_SealFinal(ctx, (unsigned char*) out + out_offset, &out_currOffset)) { - free(ek); - free(out) ; - out = NULL; - return false; - } - - // move to end - out_offset += out_currOffset; - - // make sure offset has not gone passed valid memory bounds - if(out_offset > max_outlen) return false; - - // free encrypted key data - free(ek); - - EVP_CIPHER_CTX_free(ctx); - - outlen = out_offset; - - #ifdef DISTRIB_DEBUG - std::cerr << "Authssl::encrypt() finished with outlen : " << outlen << std::endl; - #endif - - return true; -} - -bool AuthSSLimpl::decrypt(void *&out, int &outlen, const void *in, int inlen) -{ - RsStackMutex stack(sslMtx); /******* LOCKED ******/ - - - -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSLimpl::decrypt() called with inlen : " << inlen << std::endl; -#endif - //TODO : use ssl to decrypt the binary input buffer -// out = malloc(inlen); -// memcpy(out, in, inlen); -// outlen = inlen; - EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - int eklen = 0, net_ekl = 0; - unsigned char iv[EVP_MAX_IV_LENGTH]; - int ek_mkl = EVP_PKEY_size(mOwnPrivateKey); - unsigned char *ek = (unsigned char*)malloc(ek_mkl); - - if(ek == NULL) - { - std::cerr << "(EE) Cannot allocate memory for " << ek_mkl << " bytes in " << __PRETTY_FUNCTION__ << std::endl; - return false ; - } - - int in_offset = 0, out_currOffset = 0; - int size_net_ekl = sizeof(net_ekl); - - if(size_net_ekl > inlen) { - free(ek); - return false; - } - - memcpy(&net_ekl, (unsigned char*)in, size_net_ekl); - eklen = ntohl(net_ekl); - in_offset += size_net_ekl; - - if(eklen > (inlen-in_offset)) { - free(ek); - return false; - } - - memcpy(ek, (unsigned char*)in + in_offset, eklen); - in_offset += eklen; - - if(EVP_MAX_IV_LENGTH > (inlen-in_offset)) { - free(ek); - return false; - } - - memcpy(iv, (unsigned char*)in + in_offset, EVP_MAX_IV_LENGTH); - in_offset += EVP_MAX_IV_LENGTH; - - const EVP_CIPHER* cipher = EVP_aes_128_cbc(); - - if(0 == EVP_OpenInit(ctx, cipher, ek, eklen, iv, mOwnPrivateKey)) { - free(ek); - return false; - } - - out = (unsigned char*)rs_malloc(inlen - in_offset); - - if(out == NULL) - { - free(ek) ; - return false ; - } - if(!EVP_OpenUpdate(ctx, (unsigned char*) out, &out_currOffset, (unsigned char*)in + in_offset, inlen - in_offset)) { - free(ek); - free(out) ; - out = NULL; - return false; - } - - //in_offset += out_currOffset; - outlen += out_currOffset; - - if(!EVP_OpenFinal(ctx, (unsigned char*)out + out_currOffset, &out_currOffset)) { - free(ek); - free(out) ; - out = NULL; - return false; - } - - outlen += out_currOffset; - - if(ek != NULL) - free(ek); - - EVP_CIPHER_CTX_free(ctx); - -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSLimpl::decrypt() finished with outlen : " << outlen << std::endl; -#endif - - return true; -} - -/* Locked search -> internal help function */ -bool AuthSSLimpl::locked_FindCert(const RsPeerId& id, X509** cert) -{ - std::map::iterator it; - - if (mCerts.end() != (it = mCerts.find(id))) - { - *cert = it->second; - return true; - } - return false; -} - - -/* Remove Certificate */ - -bool AuthSSLimpl::RemoveX509(RsPeerId id) -{ - std::map::iterator it; - - RsStackMutex stack(sslMtx); /******* LOCKED ******/ - - if (mCerts.end() != (it = mCerts.find(id))) - { - X509* cert = it->second; - X509_free(cert); - mCerts.erase(it); - return true; - } - return false; -} - - -bool AuthSSLimpl::LocalStoreCert(X509* x509) -{ - //store the certificate in the local cert list - RsPeerId peerId ; - if(!getX509id(x509, peerId)) - { - std::cerr << "AuthSSLimpl::LocalStoreCert() Cannot retrieve peer id from certificate." << std::endl; -#ifdef AUTHSSL_DEBUG -#endif - return false; - } - - if(peerId.isNull()) - { - std::cerr << "AuthSSLimpl::LocalStoreCert(): invalid peer id \"" << peerId << "\"" << std::endl; - return false ; - } - - - RsStackMutex stack(sslMtx); /******* LOCKED ******/ - - if (peerId == mOwnId) - { -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSLimpl::LocalStoreCert() not storing own certificate" << std::endl; -#endif - return false; - } - - /* do a search */ - std::map::iterator it; - - if (mCerts.end() != (it = mCerts.find(peerId))) - { - X509* cert = it->second; - - /* found something */ - /* check that they are exact */ - if (0 != X509_cmp(cert, x509)) - { - /* MAJOR ERROR */ - std::cerr << "ERROR : AuthSSLimpl::LocalStoreCert() got two ssl certificates with identical ids -> dropping second"; - std::cerr << std::endl; - return false; - } - /* otherwise - we have it already */ - return false; - } - -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSLimpl::LocalStoreCert() storing certificate for " << peerId << std::endl; -#endif - mCerts[peerId] = X509_dup(x509); - - /* flag for saving config */ - IndicateConfigChanged(); - return true ; -} - - -/********************************************************************************/ -/********************************************************************************/ -/************************ Config Functions **********************************/ -/********************************************************************************/ -/********************************************************************************/ - - -RsSerialiser *AuthSSLimpl::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsGeneralConfigSerialiser()); - return rss ; -} - -bool AuthSSLimpl::saveList(bool& cleanup, std::list& lst) -{ - #ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSLimpl::saveList() called" << std::endl ; - #endif - - RsStackMutex stack(sslMtx); /******* LOCKED ******/ - - cleanup = true ; - - // Now save config for network digging strategies - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; - std::map::iterator mapIt; - for (mapIt = mCerts.begin(); mapIt != mCerts.end(); ++mapIt) { - if (mapIt->first == mOwnId) { - continue; - } - RsTlvKeyValue kv; - kv.key = mapIt->first.toStdString(); - #ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSLimpl::saveList() called (mapIt->first) : " << (mapIt->first) << std::endl ; - #endif - kv.value = saveX509ToPEM(mapIt->second); - vitem->tlvkvs.pairs.push_back(kv) ; - } - lst.push_back(vitem); - - return true ; -} - -bool AuthSSLimpl::loadList(std::list& load) -{ - #ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSLimpl::loadList() Item Count: " << load.size() << std::endl; - #endif - - /* load the list of accepted gpg keys */ - std::list::iterator it; - for(it = load.begin(); it != load.end(); ++it) { - RsConfigKeyValueSet *vitem = dynamic_cast(*it); - - if(vitem) - { -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSLimpl::loadList() General Variable Config Item:" << std::endl; - vitem->print(std::cerr, 10); - std::cerr << std::endl; -#endif - - std::list::iterator kit; - for(kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) - { - if (RsPeerId(kit->key) == mOwnId) { - continue; - } - - X509 *peer = loadX509FromPEM(kit->value); - /* authenticate it */ - uint32_t diagnos ; - if (peer && AuthX509WithGPG(peer,false,diagnos)) - LocalStoreCert(peer); - - X509_free(peer); - } - } - delete (*it); - } - load.clear() ; - return true; -} - -const EVP_PKEY*RsX509Cert::getPubKey(const X509& x509) -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - return x509.cert_info->key->pkey; -#else - return X509_get0_pubkey(&x509); -#endif -} diff --git a/libretroshare/src/pqi/authssl.h b/libretroshare/src/pqi/authssl.h deleted file mode 100644 index ddd5dc86d..000000000 --- a/libretroshare/src/pqi/authssl.h +++ /dev/null @@ -1,261 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: authssl.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2008 Robert Fernie * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - - -#include -#include - -#include -#include - -#include "util/rsthreads.h" -#include "pqi/pqi_base.h" -#include "pqi/pqinetwork.h" -#include "pqi/p3cfgmgr.h" -#include "util/rsmemory.h" -#include "retroshare/rsevents.h" - -/** - * Functions to interact elegantly with X509 certificates, using this functions - * you can avoid annoying #ifdef *SSL_VERSION_NUMBER all around the code. - * Function names should be self descriptive. - */ -namespace RsX509Cert -{ -std::string getCertName(const X509& x509); -std::string getCertLocation(const X509& x509); -std::string getCertOrg(const X509& x509); -RsPgpId getCertIssuer(const X509& x509); -std::string getCertIssuerString(const X509& x509); -RsPeerId getCertSslId(const X509& x509); -const EVP_PKEY* getPubKey(const X509& x509); -}; - -/** - * This is an implementation of SSL certificate authentication with PGP - * signatures, instead of centralized certification authority. - */ -class AuthSSL -{ -public: - static AuthSSL& instance(); - - RS_DEPRECATED_FOR(AuthSSL::instance()) - static AuthSSL* getAuthSSL(); - - /* Initialisation Functions (Unique) */ - virtual bool validateOwnCertificate(X509 *x509, EVP_PKEY *pkey) = 0; - - virtual bool active() = 0; - virtual int InitAuth( - const char* srvr_cert, const char* priv_key, const char* passwd, - std::string locationName ) = 0; - virtual bool CloseAuth() = 0; - - /*********** Overloaded Functions from p3AuthMgr **********/ - - /* get Certificate Id */ - virtual const RsPeerId& OwnId() = 0; - virtual std::string getOwnLocation() = 0; - - /* Load/Save certificates */ - virtual std::string SaveOwnCertificateToString() = 0; - - /* Sign / Encrypt / Verify Data */ - virtual bool SignData(std::string input, std::string &sign) = 0; - virtual bool SignData( - const void* data, const uint32_t len, std::string& sign ) = 0; - - virtual bool SignDataBin(std::string, unsigned char*, unsigned int*) = 0; - virtual bool SignDataBin( - const void*, uint32_t, unsigned char*, unsigned int* ) = 0; - virtual bool VerifyOwnSignBin( - const void*, uint32_t, unsigned char*, unsigned int ) = 0; - virtual bool VerifySignBin( - const void* data, const uint32_t len, unsigned char* sign, - unsigned int signlen, const RsPeerId& sslId ) = 0; - - /// return false if failed - virtual bool encrypt( - void*& out, int& outlen, const void* in, int inlen, - const RsPeerId& peerId ) = 0; - /// return false if failed - virtual bool decrypt(void*& out, int& outlen, const void* in, int inlen) = 0; - - virtual X509* SignX509ReqWithGPG(X509_REQ* req, long days) = 0; - - /** - * @brief Verify PGP signature correcteness on given X509 certificate - * Beware this doesn't check if the PGP signer is friend or not, just if the - * signature is valid! - * @param[in] x509 pointer ti the X509 certificate to check - * @param[out] diagnostic one of RS_SSL_HANDSHAKE_DIAGNOSTIC_* diagnostic - * codes - * @param[in] verbose if true, prints the authentication result to screen. - * @return true if correctly signed, false otherwise - */ - virtual bool AuthX509WithGPG( - X509* x509, - bool verbose, - uint32_t& diagnostic = RS_DEFAULT_STORAGE_PARAM(uint32_t) - ) = 0; - - /** - * @brief Callback provided to OpenSSL to authenticate connections - * This is the ultimate place where connection attempts get accepted - * if authenticated or refused if not authenticated. - * Emits @see RsAuthSslConnectionAutenticationEvent. - * @param preverify_ok passed by OpenSSL ignored as this call is the first - * in the authentication callback chain - * @param ctx OpenSSL connection context - * @return 0 if authentication failed, 1 if success see OpenSSL - * documentation - */ - virtual int VerifyX509Callback(int preverify_ok, X509_STORE_CTX* ctx) = 0; - - /// SSL specific functions used in pqissl/pqissllistener - virtual SSL_CTX* getCTX() = 0; - - /** - * This function parse X509 certificate from the file and return some - * verified informations, like ID and signer - * @return false on error, true otherwise - */ - virtual bool parseX509DetailsFromFile( - const std::string& certFilePath, RsPeerId& certId, RsPgpId& issuer, - std::string& location ) = 0; - - virtual ~AuthSSL(); - -protected: - AuthSSL() {} - - RS_SET_CONTEXT_DEBUG_LEVEL(2) -}; - - -class AuthSSLimpl : public AuthSSL, public p3Config -{ -public: - - /** Initialisation Functions (Unique) */ - AuthSSLimpl(); - virtual ~AuthSSLimpl(); - - bool validateOwnCertificate(X509 *x509, EVP_PKEY *pkey) override; - - bool active() override; - int InitAuth( const char *srvr_cert, const char *priv_key, - const char *passwd, std::string locationName ) - override; - - bool CloseAuth() override; - - /*********** Overloaded Functions from p3AuthMgr **********/ - - const RsPeerId& OwnId() override; - virtual std::string getOwnLocation() override; - - /* Load/Save certificates */ - virtual std::string SaveOwnCertificateToString() override; - - /* Sign / Encrypt / Verify Data */ - bool SignData(std::string input, std::string &sign) override; - bool SignData( - const void *data, const uint32_t len, std::string &sign) override; - - bool SignDataBin(std::string, unsigned char*, unsigned int*) override; - virtual bool SignDataBin( - const void*, uint32_t, unsigned char*, unsigned int*) override; - bool VerifyOwnSignBin( - const void*, uint32_t, unsigned char*, unsigned int) override; - virtual bool VerifySignBin( - const void *data, const uint32_t len, unsigned char *sign, - unsigned int signlen, const RsPeerId& sslId) override; - - bool encrypt( - void*& out, int& outlen, const void* in, int inlen, - const RsPeerId& peerId ) override; - bool decrypt(void *&out, int &outlen, const void *in, int inlen) override; - - virtual X509* SignX509ReqWithGPG(X509_REQ *req, long days) override; - - /// @see AuthSSL - bool AuthX509WithGPG(X509 *x509, bool verbose, uint32_t& auth_diagnostic) override; - - /// @see AuthSSL - int VerifyX509Callback(int preverify_ok, X509_STORE_CTX *ctx) override; - - /// @see AuthSSL - bool parseX509DetailsFromFile( - const std::string& certFilePath, RsPeerId& certId, - RsPgpId& issuer, std::string& location ) override; - - -/*****************************************************************/ -/*********************** p3config ******************************/ - /* Key Functions to be overloaded for Full Configuration */ - RsSerialiser* setupSerialiser() override; - bool saveList(bool &cleanup, std::list& ) override; - bool loadList(std::list& load) override; -/*****************************************************************/ - -public: - /* SSL specific functions used in pqissl/pqissllistener */ - SSL_CTX* getCTX() override; - -private: - - bool LocalStoreCert(X509* x509); - bool RemoveX509(const RsPeerId id); - - /*********** LOCKED Functions ******/ - bool locked_FindCert(const RsPeerId& id, X509** cert); - - /* Data */ - /* these variables are constants -> don't need to protect */ - SSL_CTX *sslctx; - RsPeerId mOwnId; - X509* mOwnCert; - - /** - * If the location name is included in SSL certificate it becomes a public - * information, because anyone able to open an SSL connection to the host is - * able to read it. To avoid that location name is now stored separately and - * and not included in the SSL certificate. - */ - std::string mOwnLocationName; - - RsMutex sslMtx; /* protects all below */ - - EVP_PKEY* mOwnPrivateKey; - EVP_PKEY* mOwnPublicKey; - - int init; - std::map mCerts; - - RsPgpId _last_gpgid_to_connect; - std::string _last_sslcn_to_connect; - RsPeerId _last_sslid_to_connect; -}; diff --git a/libretroshare/src/pqi/p3cfgmgr.cc b/libretroshare/src/pqi/p3cfgmgr.cc deleted file mode 100644 index e51f9fe52..000000000 --- a/libretroshare/src/pqi/p3cfgmgr.cc +++ /dev/null @@ -1,615 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3cfgmgr.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie, Retroshare Team. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "util/rsdir.h" -//#include "retroshare/rspeers.h" -#include "pqi/p3cfgmgr.h" -#include "pqi/authssl.h" -#include "pqi/pqibin.h" -#include "pqi/pqistore.h" -#include -#include -#include -#include "util/rsstring.h" - -#include "rsitems/rsconfigitems.h" - -/* -#define CONFIG_DEBUG 1 -*/ -#define BACKEDUP_SAVE - - -p3ConfigMgr::p3ConfigMgr(std::string dir) - :basedir(dir), cfgMtx("p3ConfigMgr"), - mConfigSaveActive(true) -{ -} - -void p3ConfigMgr::tick() -{ - bool toSave = false; - - { - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - - /* iterate through and check if any have changed */ - std::list::iterator it; - for(it = mConfigs.begin(); it != mConfigs.end(); ++it) - { - if ((*it)->HasConfigChanged(0)) - { - -#ifdef CONFIG_DEBUG - std::cerr << "p3ConfigMgr::tick() Config Changed - Element: "; - std::cerr << *it; - std::cerr << std::endl; -#endif - - toSave = true; - } - } - - /* disable saving before exit */ - if (!mConfigSaveActive) - { - toSave = false; - } - } - - if (toSave) - { - saveConfiguration(); - } -} - - -void p3ConfigMgr::saveConfiguration() -{ - if(!RsDiscSpace::checkForDiscSpace(RS_CONFIG_DIRECTORY)) - return ; - - saveConfig(); - - -} - -void p3ConfigMgr::saveConfig() -{ - - bool ok= true; - - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - - std::list::iterator it; - for(it = mConfigs.begin(); it != mConfigs.end(); ++it) - { - if ((*it)->HasConfigChanged(1)) - { -#ifdef CONFIG_DEBUG - std::cerr << "p3ConfigMgr::globalSaveConfig() Saving Element: "; - std::cerr << *it; - std::cerr << std::endl; -#endif - ok &= (*it)->saveConfiguration(); - } - /* save metaconfig */ - } - return; -} - - -void p3ConfigMgr::loadConfiguration() -{ - loadConfig(); - - return; -} - -void p3ConfigMgr::loadConfig() -{ - std::list::iterator cit; - RsFileHash dummyHash ; - for (cit = mConfigs.begin(); cit != mConfigs.end(); ++cit) - { -#ifdef CONFIG_DEBUG - std::cerr << "p3ConfigMgr::loadConfig() Element: "; - std::cerr << *cit <<" Dummy Hash: " << dummyHash; - std::cerr << std::endl; -#endif - - (*cit)->loadConfiguration(dummyHash); - - /* force config to NOT CHANGED */ - (*cit)->HasConfigChanged(0); - (*cit)->HasConfigChanged(1); - } - - return; -} - - -void p3ConfigMgr::addConfiguration(std::string file, pqiConfig *conf) -{ - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - - /* construct filename */ - std::string filename = basedir; - if (basedir != "") - { - filename += "/"; - } - filename += "config/"; - filename += file; - - std::list::iterator cit = std::find(mConfigs.begin(),mConfigs.end(),conf); - if (cit != mConfigs.end()) - { - std::cerr << "p3Config::addConfiguration() Config already added"; - std::cerr << std::endl; - std::cerr << "\tOriginal filename " << (*cit)->Filename(); - std::cerr << std::endl; - std::cerr << "\tIgnoring new filename " << filename; - std::cerr << std::endl; - return; - } - // Also check that the filename is not already registered for another config - - for(std::list::iterator it = mConfigs.begin(); it!= mConfigs.end();) - if((*it)->filename == filename) - { - std::cerr << "(WW) Registering a config for file \"" << filename << "\" that is already registered. Replacing previous component." << std::endl; - it = mConfigs.erase(it); - } - else - ++it; - - conf->setFilename(filename);// (cyril) this is quite terrible. The constructor of pqiConfig should take the filename as parameter and hold the information. - mConfigs.push_back(conf); -} - - -void p3ConfigMgr::completeConfiguration() -{ - saveConfiguration(); - - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - mConfigSaveActive = false; -} - - - -p3Config::p3Config() - :pqiConfig() -{ - return; -} - - -bool p3Config::loadConfiguration(RsFileHash& /* loadHash */) -{ - return loadConfig(); -} - -bool p3Config::loadConfig() -{ - -#ifdef CONFIG_DEBUG - std::cerr << "p3Config::loadConfig() loading Configuration\n File: " << Filename() << std::endl; -#endif - - bool pass = true; - std::string cfgFname = Filename(); - std::string cfgFnameBackup = cfgFname + ".tmp"; - - std::string signFname = Filename() +".sgn"; - std::string signFnameBackup = signFname + ".tmp"; - - std::list load; - std::list::iterator it; - - // try 1st attempt - if(!loadAttempt(cfgFname, signFname, load)) - { - -#ifdef CONFIG_DEBUG - std::cerr << "p3Config::loadConfig() Failed to Load" << std::endl; -#endif - - /* bad load */ - for(it = load.begin(); it != load.end(); ++it) - { - delete (*it); - } - pass = false; - - load.clear(); - } - - // try 2nd attempt with backup files if first failed - if(!pass) - { - if(!loadAttempt(cfgFnameBackup, signFnameBackup, load)) - { - -#ifdef CONFIG_DEBUG - std::cerr << "p3Config::loadConfig() Failed on 2nd Pass" << std::endl; -#endif - - /* bad load */ - for(it = load.begin(); it != load.end(); ++it) - { - delete (*it); - } - pass = false; - } - else - pass = true; - } - - - - if(pass) - loadList(load); - else - return false; - - return pass; -} - -bool p3Config::loadAttempt(const std::string& cfgFname,const std::string& signFname, std::list& load) -{ - -#ifdef CONFIG_DEBUG - std::cerr << "p3Config::loadAttempt() \nFilename: " << cfgFname << std::endl; -#endif - - - uint32_t bioflags = BIN_FLAGS_HASH_DATA | BIN_FLAGS_READABLE; - uint32_t stream_flags = BIN_FLAGS_READABLE; - - BinEncryptedFileInterface *bio = new BinEncryptedFileInterface(cfgFname.c_str(), bioflags); - pqiSSLstore stream(setupSerialiser(), RsPeerId(), bio, stream_flags); - - if(!stream.getEncryptedItems(load)) - { -#ifdef CONFIG_DEBUG - std::cerr << "p3Config::loadAttempt() Error occurred trying to load Item" << std::endl; -#endif - return false; - } - - /* set hash */ - setHash(bio->gethash()); - - // In order to check the signature that is stored on disk, we compute the hash of the current data (which should match the hash of the data on disc because we just read it), - // and validate the signature from the disk on this data. The config file data is therefore hashed twice. Not a security issue, but - // this is a bit inelegant. - - std::string signatureRead; - RsFileHash strHash(Hash()); - - BinFileInterface bfi(signFname.c_str(), BIN_FLAGS_READABLE); - - if(bfi.getFileSize() == 0) - return false ; - - RsTemporaryMemory mem(bfi.getFileSize()) ; - - if(!bfi.readdata(mem,mem.size())) - return false; - - // signature is stored as ascii so we need to convert it back to binary - - RsTemporaryMemory mem2(bfi.getFileSize()/2) ; - - if(!RsUtil::HexToBin(std::string((char*)(unsigned char*)mem,mem.size()),mem2,mem2.size())) - { - std::cerr << "Input string is not a Hex string!!"<< std::endl; - return false ; - } - - bool signature_checks = AuthSSL::getAuthSSL()->VerifyOwnSignBin(strHash.toByteArray(), RsFileHash::SIZE_IN_BYTES,mem2,mem2.size()); - - std::cerr << "(II) checked signature of config file " << cfgFname << ": " << (signature_checks?"OK":"Wrong!") << std::endl; - - return signature_checks; -} - -bool p3Config::saveConfiguration() -{ - return saveConfig(); -} - -bool p3Config::saveConfig() -{ - bool cleanup = true; - std::list toSave; - saveList(cleanup, toSave); - - // temporarily append new to files as these will replace current configuration - std::string newCfgFname = Filename() + "_new"; - std::string newSignFname = Filename() + ".sgn" + "_new"; - - std::string tmpCfgFname = Filename() + ".tmp"; - std::string tmpSignFname = Filename() + ".sgn" + ".tmp"; - - std::string cfgFname = Filename(); - std::string signFname = Filename() + ".sgn"; - - std::cerr << "(II) Saving configuration file " << cfgFname << std::endl; - - uint32_t bioflags = BIN_FLAGS_HASH_DATA | BIN_FLAGS_WRITEABLE; - uint32_t stream_flags = BIN_FLAGS_WRITEABLE; - bool written = true; - - if (!cleanup) - stream_flags |= BIN_FLAGS_NO_DELETE; - - BinEncryptedFileInterface *cfg_bio = new BinEncryptedFileInterface(newCfgFname.c_str(), bioflags); - pqiSSLstore *stream = new pqiSSLstore(setupSerialiser(), RsPeerId(), cfg_bio, stream_flags); - - written = written && stream->encryptedSendItems(toSave); - - if(!written) - std::cerr << "(EE) Error while writing config file " << Filename() << ": file dropped!!" << std::endl; - - /* store the hash */ - setHash(cfg_bio->gethash()); - - // bio is taken care of in stream's destructor, also forces file to close - delete stream; - - /* sign data */ - std::string signature; - RsFileHash strHash(Hash()); - AuthSSL::getAuthSSL()->SignData(strHash.toByteArray(),strHash.SIZE_IN_BYTES, signature); - - /* write signature to configuration */ - BinMemInterface *signbio = new BinMemInterface(signature.c_str(), - signature.length(), BIN_FLAGS_READABLE); - - signbio->writetofile(newSignFname.c_str()); - - delete signbio; - - // now rewrite current files to temp files - // rename back-up to current file - if(!RsDirUtil::renameFile(cfgFname, tmpCfgFname) || !RsDirUtil::renameFile(signFname, tmpSignFname)){ -#ifdef CONFIG_DEBUG - std::cerr << "p3Config::backedUpFileSave() Failed to rename backup meta files: " << std::endl - << cfgFname << " to " << tmpCfgFname << std::endl - << signFname << " to " << tmpSignFname << std::endl; -#endif - written = false; - } - - - - // now rewrite current files to temp files - // rename back-up to current file - if(!RsDirUtil::renameFile(newCfgFname, cfgFname) || !RsDirUtil::renameFile(newSignFname, signFname)){ - #ifdef CONFIG_DEBUG - std::cerr << "p3Config::() Failed to rename meta files: " << std::endl - << newCfgFname << " to " << cfgFname << std::endl - << newSignFname << " to " << signFname << std::endl; - #endif - - written = false; - } - - - - saveDone(); // callback to inherited class to unlock any Mutexes protecting saveList() data - - return written; - -} - - -/**************************** CONFIGURATION CLASSES ********************/ - -p3GeneralConfig::p3GeneralConfig() - :p3Config() -{ - return; -} - - // General Configuration System -std::string p3GeneralConfig::getSetting(const std::string &opt) -{ -#ifdef CONFIG_DEBUG - std::cerr << "p3GeneralConfig::getSetting(" << opt << ")"; - std::cerr << std::endl; -#endif - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - - /* extract from config */ - std::map::iterator it; - if (settings.end() == (it = settings.find(opt))) - { - std::string nullstring; - return nullstring; - } - return it->second; -} - -void p3GeneralConfig::setSetting(const std::string &opt, const std::string &val) -{ -#ifdef CONFIG_DEBUG - std::cerr << "p3GeneralConfig::setSetting(" << opt << " = " << val << ")"; - std::cerr << std::endl; -#endif - { - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - - /* extract from config */ - std::map::iterator it; - if (settings.end() != (it = settings.find(opt))) - { - if (it->second == val) - { - /* no change */ - return; - } - } - - settings[opt] = val; - } - /* outside mutex */ - IndicateConfigChanged(); - - return; -} - -RsSerialiser *p3GeneralConfig::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsGeneralConfigSerialiser()); - return rss; -} - -bool p3GeneralConfig::saveList(bool &cleanup, std::list& savelist) -{ - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - -#ifdef CONFIG_DEBUG - std::cerr << "p3GeneralConfig::saveList() KV sets: " << settings.size(); - std::cerr << std::endl; -#endif - - cleanup = true; - - - RsConfigKeyValueSet *item = new RsConfigKeyValueSet(); - std::map::iterator it; - for(it = settings.begin(); it != settings.end(); ++it) - { - RsTlvKeyValue kv; - kv.key = it->first; - kv.value = it->second; - item->tlvkvs.pairs.push_back(kv); - - /* make sure we don't overload it */ - if (item->tlvkvs.TlvSize() > 4000) - { - savelist.push_back(item); - item = new RsConfigKeyValueSet(); - } - } - - if (item->tlvkvs.pairs.size() > 0) - { - savelist.push_back(item); - } else - delete item; - - return true; -} - - -bool p3GeneralConfig::loadList(std::list& load) -{ -#ifdef CONFIG_DEBUG - std::cerr << "p3GeneralConfig::loadList() count: " << load.size(); - std::cerr << std::endl; -#endif - - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - - /* add into settings */ - RsConfigKeyValueSet *item = NULL; - std::list::iterator it; - std::list::iterator kit; - - for(it = load.begin(); it != load.end();) - { - item = dynamic_cast(*it); - if (item) - { - for(kit = item->tlvkvs.pairs.begin(); - kit != item->tlvkvs.pairs.end(); ++kit) - { - settings[kit->key] = kit->value; - } - } - - /* cleanup */ - delete (*it); - it = load.erase(it); - } - - return true; -} - - -/**** MUTEX NOTE: - * have protected all, but think that - * only the Indication and hash really need it - */ - -pqiConfig::pqiConfig() - : cfgMtx("pqiConfig"), ConfInd(2) -{ - return; -} - -pqiConfig::~pqiConfig() -{ - return; -} - -const std::string& pqiConfig::Filename() -{ - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - return filename; -} - -const RsFileHash& pqiConfig::Hash() -{ - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - return hash; -} - -void pqiConfig::IndicateConfigChanged() -{ - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - ConfInd.IndicateChanged(); -} - -bool pqiConfig::HasConfigChanged(uint16_t idx) -{ - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - return ConfInd.Changed(idx); -} - -void pqiConfig::setFilename(const std::string& name) -{ - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - filename = name; -} - -void pqiConfig::setHash(const RsFileHash& h) -{ - RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ - hash = h; -} - diff --git a/libretroshare/src/pqi/p3cfgmgr.h b/libretroshare/src/pqi/p3cfgmgr.h deleted file mode 100644 index 768855d38..000000000 --- a/libretroshare/src/pqi/p3cfgmgr.h +++ /dev/null @@ -1,284 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3cfgmgr.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef P3_CONFIG_MGR_HEADER -#define P3_CONFIG_MGR_HEADER - -#include -#include -#include - -#include "pqi/pqi_base.h" -#include "pqi/pqiindic.h" -#include "pqi/pqinetwork.h" -#include "util/rsthreads.h" -#include "pqi/pqibin.h" - -/***** Configuration Management ***** - * - * we need to store: - * (1) Certificates. - * (2) List of Friends / Net Configuration - * (3) Stun List. / DHT peers. - * (4) general config. - * - * - * At top level we need: - * - * - type / filename / size / hash - - * and the file signed... - * - * - */ - -/**** THESE are STORED in CONFIGURATION FILES.... - * Cannot be changed - * - *********************/ - -/* CACHE ID Must be at the END so that other configurations - * are loaded First (Cache Config --> Cache Loading) - */ - -class p3ConfigMgr; - - - -//! abstract class for configuration saving -/*! - * Aim is that active objects in retroshare can dervie from this class - * and implement their method of saving and loading their configuration - */ -class pqiConfig -{ - public: - pqiConfig(); -virtual ~pqiConfig(); - -/** - * loads configuration of object - * @param loadHash This is the hash that will be compared to confirm saved configuration has not - * been tampered with - */ -virtual bool loadConfiguration(RsFileHash &loadHash) = 0; - -/** - * save configuration of object - */ -virtual bool saveConfiguration() = 0; - -/** - * The name of the configuration file - */ -const std::string& Filename(); - -/** - * The hash computed for this configuration, can use this to compare to externally stored hash - * for validation checking - */ -const RsFileHash& Hash(); - - protected: - -/** - * Checks if configuration has changed - */ -virtual void IndicateConfigChanged(); -void setHash(const RsFileHash& h); - - RsMutex cfgMtx; - - /** - * This sets the name of the pqi configuation file - */ - void setFilename(const std::string& name); - -private: - /** - * @param an index for the Confind which contains list of configuarations that can be tracked - */ - bool HasConfigChanged(uint16_t idx); - - Indicator ConfInd; - - std::string filename; - RsFileHash hash; - - friend class p3ConfigMgr; - /* so it can access: - * setFilename() and HasConfigChanged() - */ -}; - - - -/***********************************************************************************************/ - -/*! - * MUTEX NOTE - * Class data is protected by mutex's so that anyone can call these - * functions, at any time. - */ -class p3ConfigMgr -{ - public: - - /** - * @param bdir base directory: where config files will be saved - */ - explicit p3ConfigMgr(std::string bdir); - - /** - * checks and update all added configurations - * @see rsserver - */ - void tick(); - - /** - * save all added configuation including configuration files - * creates global signature file - */ - void saveConfiguration(); - - /** - * loads all configurations - */ - void loadConfiguration(); - - /** - * @param file The name for new configuration - * @param conf to the configuration to use - */ - void addConfiguration(std::string file, pqiConfig *conf); - - /** saves config, and disables further saving - * used for exiting the system - */ - void completeConfiguration(); - - - - private: - - /** - * saves configuration of pqiconfigs in object configs - */ - void saveConfig(); - - /** - * - */ - void loadConfig(); - - const std::string basedir; - - RsMutex cfgMtx; /* below is protected */ - - bool mConfigSaveActive; - std::list mConfigs; -}; - - - -/***************************************************************************************************/ - - -/** - * @brief Abstract class for configuration saving. - * Aimed at rs services that uses RsItem config data, provide a way for RS - * services to save and load particular configurations as items. - */ -class p3Config : public pqiConfig -{ -public: - p3Config(); - - virtual bool loadConfiguration(RsFileHash &loadHash); - virtual bool saveConfiguration(); - -protected: - - /// Key Functions to be overloaded for Full Configuration - virtual RsSerialiser *setupSerialiser() = 0; - - /** - * saves list of derived object - * @param cleanup this inform you if you need to call saveDone() to - * unlock/allow access to resources pointed to by handles (list) - * returned by function: thus false, call saveDone after returned list - * finished with and vice versa - * @return list of config items derived object wants to saves - */ - virtual bool saveList(bool &cleanup, std::list&) = 0; - - /** - * loads up list of configs items for derived object - * @param load list of config items to load up - */ - virtual bool loadList(std::list& load) = 0; - - /** - * callback for mutex unlocking - * in derived classes (should only be needed if cleanup = false) - */ - virtual void saveDone() {} - -private: - - bool loadConfig(); - bool saveConfig(); - - bool loadAttempt( const std::string&, const std::string&, - std::list& load ); -}; // end of p3Config - - -class p3GeneralConfig: public p3Config -{ - public: - p3GeneralConfig(); - -// General Configuration System -std::string getSetting(const std::string &opt); -void setSetting(const std::string &opt, const std::string &val); - - protected: - - /* Key Functions to be overloaded for Full Configuration */ -virtual RsSerialiser *setupSerialiser(); -virtual bool saveList(bool &cleanup, std::list&); -virtual bool loadList(std::list& ); - - private: - - /* protected by pqiConfig mutex as well! */ -std::map settings; - - -}; - - - - - - - -#endif // P3_CONFIG_MGR_HEADER diff --git a/libretroshare/src/pqi/p3historymgr.cc b/libretroshare/src/pqi/p3historymgr.cc deleted file mode 100644 index a15d18075..000000000 --- a/libretroshare/src/pqi/p3historymgr.cc +++ /dev/null @@ -1,697 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3historymgr.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Thunder. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "util/rstime.h" - -#include "p3historymgr.h" -#include "rsitems/rshistoryitems.h" -#include "rsitems/rsconfigitems.h" -#include "retroshare/rsiface.h" -#include "retroshare/rspeers.h" -#include "rsitems/rsmsgitems.h" -#include "rsserver/p3face.h" -#include "util/rsstring.h" - -/**** - * #define HISTMGR_DEBUG 1 - ***/ - -// clean too old messages every 5 minutes -// -#define MSG_HISTORY_CLEANING_PERIOD 300 - -RsHistory *rsHistory = NULL; - -p3HistoryMgr::p3HistoryMgr() - : p3Config() - , nextMsgId(1) - , mPublicEnable(false), mLobbyEnable(true), mPrivateEnable(true), mDistantEnable(true) - , mPublicSaveCount(0), mLobbySaveCount(0), mPrivateSaveCount(0), mDistantSaveCount(0) - , mMaxStorageDurationSeconds(10*86400) // store for 10 days at most. - , mLastCleanTime(0) - , mHistoryMtx("p3HistoryMgr") -{ -} - -p3HistoryMgr::~p3HistoryMgr() -{ -} - -/***** p3HistoryMgr *****/ - -void p3HistoryMgr::addMessage(const ChatMessage& cm) -{ - uint32_t addMsgId = 0; - - rstime_t now = time(NULL) ; - - if(mLastCleanTime + MSG_HISTORY_CLEANING_PERIOD < now) - { - cleanOldMessages() ; - mLastCleanTime = now ; - } - - { - RsStackMutex stack(mHistoryMtx); /********** STACK LOCKED MTX ******/ - - RsPeerId msgPeerId; // id of sending peer - RsPeerId chatPeerId; // id of chat endpoint - std::string peerName; //name of sending peer - - if (cm.chat_id.isBroadcast() && mPublicEnable == true) { - peerName = rsPeers->getPeerName(cm.broadcast_peer_id); - } - else if (cm.chat_id.isPeerId() && mPrivateEnable == true) { - msgPeerId = cm.incoming ? cm.chat_id.toPeerId() : rsPeers->getOwnId(); - peerName = rsPeers->getPeerName(msgPeerId); - } - else if (cm.chat_id.isLobbyId() && mLobbyEnable == true) { - msgPeerId = RsPeerId(cm.lobby_peer_gxs_id); - RsIdentityDetails details; - if (rsIdentity->getIdDetails(cm.lobby_peer_gxs_id, details)) - peerName = details.mNickname; - else - peerName = cm.lobby_peer_gxs_id.toStdString(); - } - else if(cm.chat_id.isDistantChatId()&& mDistantEnable == true) - { - DistantChatPeerInfo dcpinfo; - if (rsMsgs->getDistantChatStatus(cm.chat_id.toDistantChatId(), dcpinfo)) - { - RsIdentityDetails det; - RsGxsId writer_id = cm.incoming?(dcpinfo.to_id):(dcpinfo.own_id); - - if(rsIdentity->getIdDetails(writer_id,det)) - peerName = det.mNickname; - else - peerName = writer_id.toStdString(); - - msgPeerId = cm.incoming?RsPeerId(dcpinfo.own_id):RsPeerId(dcpinfo.to_id); - } - else - { - RS_ERR( "Cannot retrieve friend name for distant chat ", cm.chat_id.toDistantChatId() ); - peerName = ""; - } - - } - else - return; - - if(!chatIdToVirtualPeerId(cm.chat_id, chatPeerId)) - return; - - RsHistoryMsgItem* item = new RsHistoryMsgItem; - item->chatPeerId = chatPeerId; - item->incoming = cm.incoming; - item->msgPeerId = msgPeerId; - item->peerName = peerName; - item->sendTime = cm.sendTime; - item->recvTime = cm.recvTime; - - item->message = cm.msg ; - //librs::util::ConvertUtf16ToUtf8(chatItem->message, item->message); - - std::map >::iterator mit = mMessages.find(item->chatPeerId); - if (mit != mMessages.end()) { - item->msgId = nextMsgId++; - mit->second.insert(std::make_pair(item->msgId, item)); - addMsgId = item->msgId; - - // check the limit - uint32_t limit; - if (chatPeerId.isNull()) - limit = mPublicSaveCount; - else if (cm.chat_id.isLobbyId()) - limit = mLobbySaveCount; - else - limit = mPrivateSaveCount; - - if (limit) { - while (mit->second.size() > limit) { - delete(mit->second.begin()->second); - mit->second.erase(mit->second.begin()); - } - } - } else { - std::map msgs; - item->msgId = nextMsgId++; - msgs.insert(std::make_pair(item->msgId, item)); - mMessages.insert(std::make_pair(item->chatPeerId, msgs)); - addMsgId = item->msgId; - - // no need to check the limit - } - - IndicateConfigChanged(); - } - - if (addMsgId) { - RsServer::notify()->notifyHistoryChanged(addMsgId, NOTIFY_TYPE_ADD); - } -} - -void p3HistoryMgr::cleanOldMessages() -{ - RsStackMutex stack(mHistoryMtx); /********** STACK LOCKED MTX ******/ - -#ifdef HISTMGR_DEBUG - std::cerr << "****** cleaning old messages." << std::endl; -#endif - rstime_t now = time(NULL) ; - bool changed = false ; - - for(std::map >::iterator mit = mMessages.begin(); mit != mMessages.end();) - { - if (mMaxStorageDurationSeconds > 0) - { - for(std::map::iterator lit = mit->second.begin();lit!=mit->second.end();) - if(lit->second->recvTime + mMaxStorageDurationSeconds < now) - { - std::map::iterator lit2 = lit ; - ++lit2 ; - -#ifdef HISTMGR_DEBUG - std::cerr << " removing msg id " << lit->first << ", for peer id " << mit->first << std::endl; -#endif - delete lit->second ; - - mit->second.erase(lit) ; - lit = lit2 ; - - changed = true ; - } - else - ++lit ; - } - - if(mit->second.empty()) - { - std::map >::iterator mit2 = mit ; - ++mit2 ; -#ifdef HISTMGR_DEBUG - std::cerr << " removing peer id " << mit->first << ", since it has no messages" << std::endl; -#endif - mMessages.erase(mit) ; - mit = mit2 ; - - changed = true ; - } - else - ++mit ; - } - - if(changed) - IndicateConfigChanged() ; -} - -/***** p3Config *****/ - -RsSerialiser* p3HistoryMgr::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser; - rss->addSerialType(new RsHistorySerialiser); - rss->addSerialType(new RsGeneralConfigSerialiser()); - - return rss; -} - -bool p3HistoryMgr::saveList(bool& cleanup, std::list& saveData) -{ - cleanup = false; - - mHistoryMtx.lock(); /********** STACK LOCKED MTX ******/ - - std::map >::iterator mit; - std::map::iterator lit; - for (mit = mMessages.begin(); mit != mMessages.end(); ++mit) { - for (lit = mit->second.begin(); lit != mit->second.end(); ++lit) { - if (lit->second->saveToDisc) { - saveData.push_back(lit->second); - } - } - } - - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet; - - RsTlvKeyValue kv; - kv.key = "PUBLIC_ENABLE"; - kv.value = mPublicEnable ? "TRUE" : "FALSE"; - vitem->tlvkvs.pairs.push_back(kv); - - kv.key = "PRIVATE_ENABLE"; - kv.value = mPrivateEnable ? "TRUE" : "FALSE"; - vitem->tlvkvs.pairs.push_back(kv); - - kv.key = "LOBBY_ENABLE"; - kv.value = mLobbyEnable ? "TRUE" : "FALSE"; - vitem->tlvkvs.pairs.push_back(kv); - - kv.key = "DISTANT_ENABLE"; - kv.value = mDistantEnable ? "TRUE" : "FALSE"; - vitem->tlvkvs.pairs.push_back(kv); - - kv.key = "MAX_STORAGE_TIME"; - rs_sprintf(kv.value,"%d",mMaxStorageDurationSeconds) ; - vitem->tlvkvs.pairs.push_back(kv); - - kv.key = "LOBBY_SAVECOUNT"; - rs_sprintf(kv.value, "%lu", mLobbySaveCount); - vitem->tlvkvs.pairs.push_back(kv); - - kv.key = "PUBLIC_SAVECOUNT"; - rs_sprintf(kv.value, "%lu", mPublicSaveCount); - vitem->tlvkvs.pairs.push_back(kv); - - kv.key = "PRIVATE_SAVECOUNT"; - rs_sprintf(kv.value, "%lu", mPrivateSaveCount); - vitem->tlvkvs.pairs.push_back(kv); - - kv.key = "DISTANT_SAVECOUNT"; - rs_sprintf(kv.value, "%lu", mDistantSaveCount); - vitem->tlvkvs.pairs.push_back(kv); - - saveData.push_back(vitem); - saveCleanupList.push_back(vitem); - - return true; -} - -void p3HistoryMgr::saveDone() -{ - /* clean up the save List */ - std::list::iterator it; - for (it = saveCleanupList.begin(); it != saveCleanupList.end(); ++it) { - delete (*it); - } - - saveCleanupList.clear(); - - /* unlock mutex */ - mHistoryMtx.unlock(); /****** MUTEX UNLOCKED *******/ -} - -bool p3HistoryMgr::loadList(std::list& load) -{ - RsStackMutex stack(mHistoryMtx); /********** STACK LOCKED MTX ******/ - - RsHistoryMsgItem *msgItem; - std::list::iterator it; - - for (it = load.begin(); it != load.end(); ++it) - { - if (NULL != (msgItem = dynamic_cast(*it))) { - - std::map >::iterator mit = mMessages.find(msgItem->chatPeerId); - msgItem->msgId = nextMsgId++; - -#ifdef HISTMGR_DEBUG - std::cerr << "Loading msg history item: peer id=" << msgItem->chatPeerId << "), msg id =" << msgItem->msgId << std::endl; -#endif - - if (mit != mMessages.end()) { - mit->second.insert(std::make_pair(msgItem->msgId, msgItem)); - } else { - std::map msgs; - msgs.insert(std::make_pair(msgItem->msgId, msgItem)); - mMessages.insert(std::make_pair(msgItem->chatPeerId, msgs)); - } - - // don't delete the item !! - - continue; - } - - RsConfigKeyValueSet *rskv ; - if (NULL != (rskv = dynamic_cast(*it))) { - for (std::list::const_iterator kit = rskv->tlvkvs.pairs.begin(); kit != rskv->tlvkvs.pairs.end(); ++kit) { - if (kit->key == "PUBLIC_ENABLE") { - mPublicEnable = (kit->value == "TRUE") ? true : false; - continue; - } - - if (kit->key == "PRIVATE_ENABLE") { - mPrivateEnable = (kit->value == "TRUE") ? true : false; - continue; - } - - if (kit->key == "LOBBY_ENABLE") { - mLobbyEnable = (kit->value == "TRUE") ? true : false; - continue; - } - - if (kit->key == "DISTANT_ENABLE") { - mDistantEnable = (kit->value == "TRUE") ? true : false; - continue; - } - - if (kit->key == "MAX_STORAGE_TIME") { - uint32_t val ; - if (sscanf(kit->value.c_str(), "%u", &val) == 1) - mMaxStorageDurationSeconds = val ; - -#ifdef HISTMGR_DEBUG - std::cerr << "Loaded max storage time for history = " << val << " seconds" << std::endl; -#endif - continue; - } - - if (kit->key == "PUBLIC_SAVECOUNT") { - mPublicSaveCount = atoi(kit->value.c_str()); - continue; - } - if (kit->key == "PRIVATE_SAVECOUNT") { - mPrivateSaveCount = atoi(kit->value.c_str()); - continue; - } - if (kit->key == "LOBBY_SAVECOUNT") { - mLobbySaveCount = atoi(kit->value.c_str()); - continue; - } - if (kit->key == "DISTANT_SAVECOUNT") { - mDistantSaveCount = atoi(kit->value.c_str()); - continue; - } - } - - delete (*it); - continue; - } - - // delete unknown items - delete (*it); - } - - load.clear() ; - return true; -} - -// have to convert to virtual peer id, to be able to use existing serialiser and file format -bool p3HistoryMgr::chatIdToVirtualPeerId(const ChatId& chat_id, RsPeerId &peer_id) -{ - if (chat_id.isBroadcast()) { - peer_id = RsPeerId(); - return true; - } - if (chat_id.isPeerId()) { - peer_id = chat_id.toPeerId(); - return true; - } - if (chat_id.isLobbyId()) { - if(sizeof(ChatLobbyId) > RsPeerId::SIZE_IN_BYTES){ - std::cerr << "p3HistoryMgr::chatIdToVirtualPeerId() ERROR: ChatLobbyId does not fit into virtual peer id. Please report this error." << std::endl; - return false; - } - uint8_t bytes[RsPeerId::SIZE_IN_BYTES] ; - memset(bytes,0,RsPeerId::SIZE_IN_BYTES) ; - ChatLobbyId lobby_id = chat_id.toLobbyId(); - memcpy(bytes,&lobby_id,sizeof(ChatLobbyId)); - peer_id = RsPeerId(bytes); - return true; - } - - if (chat_id.isDistantChatId()) { - peer_id = RsPeerId(chat_id.toDistantChatId()); - return true; - } - - return false; -} - -/***** p3History *****/ - -static void convertMsg(const RsHistoryMsgItem* item, HistoryMsg &msg) -{ - msg.msgId = item->msgId; - msg.chatPeerId = item->chatPeerId; - msg.incoming = item->incoming; - msg.peerId = item->msgPeerId; - msg.peerName = item->peerName; - msg.sendTime = item->sendTime; - msg.recvTime = item->recvTime; - msg.message = item->message; -} - -bool p3HistoryMgr::getMessages(const ChatId &chatId, std::list &msgs, uint32_t loadCount) -{ - msgs.clear(); - - RsStackMutex stack(mHistoryMtx); /********** STACK LOCKED MTX ******/ - - RsPeerId chatPeerId; - bool enabled = false; - if (chatId.isBroadcast() && mPublicEnable == true) { - enabled = true; - } - if (chatId.isPeerId() && mPrivateEnable == true) { - enabled = true; - } - if (chatId.isLobbyId() && mLobbyEnable == true) { - enabled = true; - } - if (chatId.isDistantChatId() && mDistantEnable == true) { - enabled = true; - } - - if(enabled == false) - return false; - - if(!chatIdToVirtualPeerId(chatId, chatPeerId)) - return false; - -#ifdef HISTMGR_DEBUG - std::cerr << "Getting history for virtual peer " << chatPeerId << std::endl; -#endif - - uint32_t foundCount = 0; - - std::map >::iterator mit = mMessages.find(chatPeerId); - - if (mit != mMessages.end()) - { - std::map::reverse_iterator lit; - - for (lit = mit->second.rbegin(); lit != mit->second.rend(); ++lit) - { - HistoryMsg msg; - convertMsg(lit->second, msg); - msgs.insert(msgs.begin(), msg); - foundCount++; - if (loadCount && foundCount >= loadCount) { - break; - } - } - } -#ifdef HISTMGR_DEBUG - std::cerr << msgs.size() << " messages added." << std::endl; -#endif - - return true; -} - -bool p3HistoryMgr::getMessage(uint32_t msgId, HistoryMsg &msg) -{ - RsStackMutex stack(mHistoryMtx); /********** STACK LOCKED MTX ******/ - - std::map >::iterator mit; - for (mit = mMessages.begin(); mit != mMessages.end(); ++mit) { - std::map::iterator lit = mit->second.find(msgId); - if (lit != mit->second.end()) { - convertMsg(lit->second, msg); - return true; - } - } - - return false; -} - -void p3HistoryMgr::clear(const ChatId &chatId) -{ - { - RsStackMutex stack(mHistoryMtx); /********** STACK LOCKED MTX ******/ - - RsPeerId chatPeerId; - if(!chatIdToVirtualPeerId(chatId, chatPeerId)) - return; - -#ifdef HISTMGR_DEBUG - std::cerr << "********** p3History::clear()called for virtual peer id " << chatPeerId << std::endl; -#endif - - std::map >::iterator mit = mMessages.find(chatPeerId); - if (mit == mMessages.end()) { - return; - } - - std::map::iterator lit; - for (lit = mit->second.begin(); lit != mit->second.end(); ++lit) { - delete(lit->second); - } - mit->second.clear(); - mMessages.erase(mit); - - IndicateConfigChanged(); - } - - RsServer::notify()->notifyHistoryChanged(0, NOTIFY_TYPE_MOD); -} - -void p3HistoryMgr::removeMessages(const std::list &msgIds) -{ - std::list ids = msgIds; - std::list removedIds; - std::list::iterator iit; - -#ifdef HISTMGR_DEBUG - std::cerr << "********** p3History::removeMessages called()" << std::endl; -#endif - { - RsStackMutex stack(mHistoryMtx); /********** STACK LOCKED MTX ******/ - - std::map >::iterator mit; - for (mit = mMessages.begin(); mit != mMessages.end(); ++mit) - { - iit = ids.begin(); - while ( !ids.empty() || (iit != ids.end()) ) - { - std::map::iterator lit = mit->second.find(*iit); - if (lit != mit->second.end()) - { -#ifdef HISTMGR_DEBUG - std::cerr << "**** Removing " << mit->first << " msg id = " << lit->first << std::endl; -#endif - - delete(lit->second); - mit->second.erase(lit); - - removedIds.push_back(*iit); - iit = ids.erase(iit); - - continue; - } - - ++iit; - } - } - } - - if (!removedIds.empty()) - { - IndicateConfigChanged(); - - for (iit = removedIds.begin(); iit != removedIds.end(); ++iit) - RsServer::notify()->notifyHistoryChanged(*iit, NOTIFY_TYPE_DEL); - } -} - -bool p3HistoryMgr::getEnable(uint32_t chat_type) -{ - switch(chat_type) - { - case RS_HISTORY_TYPE_PUBLIC : return mPublicEnable ; - case RS_HISTORY_TYPE_LOBBY : return mLobbyEnable ; - case RS_HISTORY_TYPE_PRIVATE: return mPrivateEnable ; - case RS_HISTORY_TYPE_DISTANT: return mDistantEnable ; - default: - std::cerr << "Unexpected value " << chat_type<< " in p3HistoryMgr::getEnable(): this is a bug." << std::endl; - return 0 ; - } -} - -uint32_t p3HistoryMgr::getMaxStorageDuration() -{ - return mMaxStorageDurationSeconds ; -} - - -void p3HistoryMgr::setMaxStorageDuration(uint32_t seconds) -{ - if(mMaxStorageDurationSeconds != seconds) - IndicateConfigChanged() ; - - mMaxStorageDurationSeconds = seconds ; -} - -void p3HistoryMgr::setEnable(uint32_t chat_type, bool enable) -{ - bool oldValue; - - switch(chat_type) - { - case RS_HISTORY_TYPE_PUBLIC : oldValue = mPublicEnable ; - mPublicEnable = enable ; - break ; - - case RS_HISTORY_TYPE_LOBBY : oldValue = mLobbyEnable ; - mLobbyEnable = enable; - break ; - - case RS_HISTORY_TYPE_PRIVATE: oldValue = mPrivateEnable ; - mPrivateEnable = enable ; - break ; - case RS_HISTORY_TYPE_DISTANT: oldValue = mDistantEnable ; - mDistantEnable = enable ; - break ; - default: - return; - } - - if (oldValue != enable) - IndicateConfigChanged(); -} - -uint32_t p3HistoryMgr::getSaveCount(uint32_t chat_type) -{ - switch(chat_type) - { - case RS_HISTORY_TYPE_PUBLIC : return mPublicSaveCount ; - case RS_HISTORY_TYPE_LOBBY : return mLobbySaveCount ; - case RS_HISTORY_TYPE_PRIVATE: return mPrivateSaveCount ; - default: - std::cerr << "Unexpected value " << chat_type<< " in p3HistoryMgr::getSaveCount(): this is a bug." << std::endl; - return 0 ; - } -} - -void p3HistoryMgr::setSaveCount(uint32_t chat_type, uint32_t count) -{ - uint32_t oldValue; - - switch(chat_type) - { - case RS_HISTORY_TYPE_PUBLIC : oldValue = mPublicSaveCount ; - mPublicSaveCount = count ; - break ; - - case RS_HISTORY_TYPE_LOBBY : oldValue = mLobbySaveCount ; - mLobbySaveCount = count; - break ; - - case RS_HISTORY_TYPE_PRIVATE: oldValue = mPrivateSaveCount ; - mPrivateSaveCount = count ; - break ; - default: - return; - } - - if (oldValue != count) - IndicateConfigChanged(); -} diff --git a/libretroshare/src/pqi/p3historymgr.h b/libretroshare/src/pqi/p3historymgr.h deleted file mode 100644 index a74eff67e..000000000 --- a/libretroshare/src/pqi/p3historymgr.h +++ /dev/null @@ -1,100 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3historymgr.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Thunder. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_P3_HISTORY_MGR_H -#define RS_P3_HISTORY_MGR_H - -#include -#include - -#include "rsitems/rshistoryitems.h" -#include "retroshare/rshistory.h" -#include "pqi/p3cfgmgr.h" - -class RsChatMsgItem; -class ChatMessage; - -//! handles history -/*! - * The is a retroshare service which allows peers - * to store the history of the chat messages - */ -class p3HistoryMgr: public p3Config -{ -public: - p3HistoryMgr(); - virtual ~p3HistoryMgr(); - - /******** p3HistoryMgr *********/ - - void addMessage(const ChatMessage &cm); - - /********* RsHistory ***********/ - - bool getMessages(const ChatId &chatPeerId, std::list &msgs, uint32_t loadCount); - bool getMessage(uint32_t msgId, HistoryMsg &msg); - void clear(const ChatId &chatPeerId); - void removeMessages(const std::list &msgIds); - - virtual bool getEnable(uint32_t chat_type); - virtual void setEnable(uint32_t chat_type, bool enable); - virtual uint32_t getSaveCount(uint32_t chat_type); - virtual void setSaveCount(uint32_t chat_type, uint32_t count); - virtual void setMaxStorageDuration(uint32_t seconds) ; - virtual uint32_t getMaxStorageDuration() ; - - /********* p3config ************/ - - virtual RsSerialiser *setupSerialiser(); - virtual bool saveList(bool& cleanup, std::list& saveData); - virtual void saveDone(); - virtual bool loadList(std::list& load); - - static bool chatIdToVirtualPeerId(const ChatId& chat_id, RsPeerId& peer_id); - -private: - uint32_t nextMsgId; - std::map > mMessages; - - // Removes messages stored for more than mMaxMsgStorageDurationSeconds seconds. - // This avoids the stored list to grow crazy with time. - // - void cleanOldMessages() ; - - bool mPublicEnable; - bool mLobbyEnable; - bool mPrivateEnable; - bool mDistantEnable; - - uint32_t mPublicSaveCount; - uint32_t mLobbySaveCount; - uint32_t mPrivateSaveCount; - uint32_t mDistantSaveCount; - - uint32_t mMaxStorageDurationSeconds ; - rstime_t mLastCleanTime ; - - std::list saveCleanupList; /* TEMPORARY LIST WHEN SAVING */ - - RsMutex mHistoryMtx; -}; - -#endif diff --git a/libretroshare/src/pqi/p3linkmgr.cc b/libretroshare/src/pqi/p3linkmgr.cc deleted file mode 100644 index 97a889b79..000000000 --- a/libretroshare/src/pqi/p3linkmgr.cc +++ /dev/null @@ -1,2209 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3linkmgr.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2011 by Robert Fernie. * - * Copyright (C) 2015-2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "pqi/p3linkmgr.h" - -#include "pqi/p3peermgr.h" -#include "pqi/p3netmgr.h" - -#include "rsserver/p3face.h" -#include "pqi/authssl.h" -#include "tcponudp/tou.h" -#include "util/extaddrfinder.h" -#include "util/dnsresolver.h" -#include "util/rsnet.h" -#include "pqi/authgpg.h" - - -#include "util/rsprint.h" -#include "util/rsdebug.h" -#include "util/rsstring.h" - -#include "rsitems/rsconfigitems.h" - -#include "retroshare/rsiface.h" -#include "retroshare/rspeers.h" -#include "retroshare/rsdht.h" -#include "retroshare/rsbanlist.h" - -/* Network setup States */ - -static struct RsLog::logInfo p3connectzoneInfo = {RsLog::Default, "p3connect"}; -#define p3connectzone &p3connectzoneInfo - -/**** - * #define LINKMGR_DEBUG 1 - * #define LINKMGR_DEBUG_LOG 1 - * #define LINKMGR_DEBUG_CONNFAIL 1 - * #define LINKMGR_DEBUG_ACTIONS 1 - * #define LINKMGR_DEBUG_LINKTYPE 1 - ***/ - -/**** - * #define DISABLE_UDP_CONNECTIONS 1 - ***/ - -/**** - * #define P3CONNMGR_NO_TCP_CONNECTIONS 1 - ***/ -/**** - * #define P3CONNMGR_NO_AUTO_CONNECTION 1 - ***/ - -//#define P3CONNMGR_NO_TCP_CONNECTIONS 1 - -const uint32_t P3CONNMGR_TCP_DEFAULT_DELAY = 3; /* 2 Seconds? is it be enough! */ -//const uint32_t P3CONNMGR_UDP_DEFAULT_DELAY = 3; /* 2 Seconds? is it be enough! */ - -const uint32_t P3CONNMGR_TCP_DEFAULT_PERIOD = 10; -const uint32_t P3CONNMGR_UDP_DEFAULT_PERIOD = 30; // this represents how long it stays at the default TTL (4), before rising. - -#define MAX_AVAIL_PERIOD 230 //times a peer stay in available state when not connected -#define MIN_RETRY_PERIOD 140 - -#define MAX_RANDOM_ATTEMPT_OFFSET 6 // seconds. - -void printConnectState(std::ostream &out, peerConnectState &peer); - -peerConnectAddress::peerConnectAddress() - :delay(0), period(0), type(0), flags(0), ts(0), bandwidth(0), domain_port(0) -{ - sockaddr_storage_clear(addr); - sockaddr_storage_clear(proxyaddr); - sockaddr_storage_clear(srcaddr); -} - - -peerAddrInfo::peerAddrInfo() - :found(false), type(0), ts(0) -{ -} - -peerConnectState::peerConnectState() - : dhtVisible(false), - connecttype(0), - actAsServer(false), - lastavailable(0), - lastattempt(0), - name(""), - state(0), - actions(0), - linkType(0), - source(0), - inConnAttempt(false), - wasDeniedConnection(false), - deniedTS(0), - deniedInConnAttempt(false) -{ -} - -std::string textPeerConnectState(peerConnectState &state) -{ - return "Id: " + state.id.toStdString() + "\n"; -} - -/********* - * NOTES: - * - * p3LinkMgr doesn't store anything. All configuration is handled by p3PeerMgr. - * - * p3LinkMgr recvs the Discovery / Dht / Status updates.... tries the address. - * at success the address is pushed to p3PeerMgr for storage. - * - */ - - -p3LinkMgrIMPL::p3LinkMgrIMPL(p3PeerMgrIMPL *peerMgr, p3NetMgrIMPL *netMgr) - :mPeerMgr(peerMgr), mNetMgr(netMgr), mLinkMtx("p3LinkMgr"),mStatusChanged(false) -{ - - { - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - mDNSResolver = new DNSResolver(); - mRetryPeriod = MIN_RETRY_PERIOD; - - /* setup Banned Ip Address - static for now - */ - - struct sockaddr_storage bip; - sockaddr_storage_clear(bip); - struct sockaddr_in *addr = (struct sockaddr_in *) &bip; - addr->sin_family = AF_INET; - addr->sin_addr.s_addr = 1; - addr->sin_port = htons(0); - - mBannedIpList.push_back(bip); - } - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgr() Startup" << std::endl; -#endif - - return; -} - -p3LinkMgrIMPL::~p3LinkMgrIMPL() -{ - delete(mDNSResolver); -} - -bool p3LinkMgrIMPL::setLocalAddress(const struct sockaddr_storage &addr) -{ - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - mLocalAddress = addr; - - return true ; -} - -bool p3LinkMgrIMPL::getLocalAddress(struct sockaddr_storage &addr) -{ - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - addr = mLocalAddress; - return true; -} - - -bool p3LinkMgrIMPL::isOnline(const RsPeerId &ssl_id) -{ - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - std::map::iterator it; - it = mFriendList.find(ssl_id); - if (it == mFriendList.end()) - { - return false; - } - - if (it->second.state & RS_PEER_S_CONNECTED) - { - return true; - } - return false; -} - - - -uint32_t p3LinkMgrIMPL::getLinkType(const RsPeerId &ssl_id) -{ - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - std::map::iterator it; - it = mFriendList.find(ssl_id); - if (it == mFriendList.end()) - { - return 0; - } - - if (it->second.state & RS_PEER_S_CONNECTED) - { - return it->second.linkType; - } - return 0; -} - - - -void p3LinkMgrIMPL::getOnlineList(std::list &ssl_peers) -{ - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - std::map::iterator it; - for(it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - if (it->second.state & RS_PEER_S_CONNECTED) - { - ssl_peers.push_back(it->first); - } - } - return; -} - -void p3LinkMgrIMPL::getFriendList(std::list &ssl_peers) -{ - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - std::map::iterator it; - for(it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - ssl_peers.push_back(it->first); - } - return; -} - -bool p3LinkMgrIMPL::getPeerName(const RsPeerId &ssl_id, std::string &name) -{ - return mPeerMgr->getPeerName(ssl_id, name); -} - - -bool p3LinkMgrIMPL::getFriendNetStatus(const RsPeerId &id, peerConnectState &state) -{ - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - std::map::iterator it; - it = mFriendList.find(id); - if (it == mFriendList.end()) - { - return false; - } - - state = it->second; - - return true; -} - - - -void p3LinkMgrIMPL::setFriendVisibility(const RsPeerId &id, bool isVisible) -{ - /* set visibility */ - { - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - std::map::iterator it; - it = mFriendList.find(id); - if (it == mFriendList.end()) - { - /* */ - std::cerr << "p3LinkMgrIMPL::setFriendVisibility() ERROR peer unknown: " << id; - std::cerr << std::endl; - return; - } - - if (it->second.dhtVisible == isVisible) - { - /* no change in state */ - return; - } - - it->second.dhtVisible = isVisible; - - if (it->second.state & RS_PEER_S_CONNECTED) - { - /* dont worry about it */ - return; - } - } - - /* switch the NetAssistOn/Off */ - mNetMgr->netAssistFriend(id, isVisible); -} - - -void p3LinkMgrIMPL::tick() -{ - statusTick(); - tickMonitors(); -} - - -void p3LinkMgrIMPL::statusTick() -{ - /* iterate through peers ... - * if been available for long time ... remove flag - * if last attempt a while - retryConnect. - * etc. - */ - -#ifdef LINKMGR_DEBUG_TICK - std::cerr << "p3LinkMgrIMPL::statusTick()" << std::endl; -#endif - std::list retryIds; - //std::list dummyToRemove; - - { - rstime_t now = time(NULL); - rstime_t oldavail = now - MAX_AVAIL_PERIOD; - rstime_t retry = now - mRetryPeriod; - - RsStackMutex stack(mLinkMtx); /****** LOCK MUTEX ******/ - std::map::iterator it; - for(it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - if (it->second.state & RS_PEER_S_CONNECTED) - { - continue; - } - - if ((it->second.state & RS_PEER_S_ONLINE) && - (it->second.lastavailable < oldavail)) - { -#ifdef LINKMGR_DEBUG_TICK - std::cerr << "p3LinkMgrIMPL::statusTick() ONLINE TIMEOUT for: "; - std::cerr << it->first; - std::cerr << std::endl; -#endif - it->second.state &= (~RS_PEER_S_ONLINE); - } - - if (it->second.lastattempt < retry) - { - retryIds.push_back(it->first); - } - } - } - -#ifndef P3CONNMGR_NO_AUTO_CONNECTION - std::list::iterator it2; - for(it2 = retryIds.begin(); it2 != retryIds.end(); ++it2) - { -#ifdef LINKMGR_DEBUG_TICK - std::cerr << "p3LinkMgrIMPL::statusTick() RETRY TIMEOUT for: "; - std::cerr << *it2; - std::cerr << std::endl; -#endif - /* retry it! */ - retryConnect(*it2); - } - -#endif - -} - - -/******************************** Network Status ********************************* - * Configuration Loading / Saving. - */ - -void p3LinkMgrIMPL::addMonitor(pqiMonitor *mon) -{ - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - std::list::iterator it; - it = std::find(clients.begin(), clients.end(), mon); - if (it != clients.end()) - { - return; - } - - mon->setLinkMgr(this); - clients.push_back(mon); - return; -} - -void p3LinkMgrIMPL::removeMonitor(pqiMonitor *mon) -{ - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - std::list::iterator it; - it = std::find(clients.begin(), clients.end(), mon); - if (it == clients.end()) - { - return; - } - (*it)->setLinkMgr(NULL); - clients.erase(it); - - return; -} - -void p3LinkMgrIMPL::tickMonitors() -{ - bool doStatusChange = false; - std::list actionList; - std::map::iterator it; - - { - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - if (mStatusChanged) - { -#ifdef LINKMGR_DEBUG_ACTIONS - std::cerr << "p3LinkMgrIMPL::tickMonitors() StatusChanged! List:" << std::endl; -#endif - /* assemble list */ - for(it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - if (it->second.actions) - { - /* add in */ - pqipeer peer; - peer.id = it->second.id; - peer.name = it->second.name; - peer.state = it->second.state; - peer.actions = it->second.actions; - - /* reset action */ - it->second.actions = 0; - - actionList.push_back(peer); - -#ifdef LINKMGR_DEBUG_ACTIONS - std::cerr << "Friend: " << peer.name << " Id: " << peer.id.toStdString() << " State: " << peer.state; - if (peer.state & RS_PEER_S_FRIEND) - std::cerr << " S:RS_PEER_S_FRIEND"; - if (peer.state & RS_PEER_S_ONLINE) - std::cerr << " S:RS_PEER_S_ONLINE"; - if (peer.state & RS_PEER_S_CONNECTED) - std::cerr << " S:RS_PEER_S_CONNECTED"; - std::cerr << " Actions: " << peer.actions; - if (peer.actions & RS_PEER_NEW) - std::cerr << " A:RS_PEER_NEW"; - if (peer.actions & RS_PEER_MOVED) - std::cerr << " A:RS_PEER_MOVED"; - if (peer.actions & RS_PEER_CONNECTED) - std::cerr << " A:RS_PEER_CONNECTED"; - if (peer.actions & RS_PEER_DISCONNECTED) - std::cerr << " A:RS_PEER_DISCONNECTED"; - if (peer.actions & RS_PEER_CONNECT_REQ) - std::cerr << " A:RS_PEER_CONNECT_REQ"; - - std::cerr << std::endl; -#endif - -// if(peer.actions & RS_PEER_CONNECTED) -// { -// pqiIpAddress ip; -// ip.mAddr = it->second.currentConnAddrAttempt.addr; -// ip.mSeenTime = time(NULL); -// ip.mSrc = time(NULL); -// -// mPeerMgr->updateCurrentAddress(it->second.id,) -// std::cerr << "Peer " << it->second.id << " connected with IP " << sockaddr_storage_tostring(it->second.currentConnAddrAttempt.addr) << std::endl; -// } - - /* notify GUI */ - if (rsEvents && (peer.actions & RS_PEER_CONNECTED)) - { - auto e = std::make_shared(); - e->mConnectionInfoCode = RsConnectionEventCode::PEER_CONNECTED; - e->mSslId = peer.id; - rsEvents->postEvent(e); - } - if (rsEvents && (peer.actions & RS_PEER_DISCONNECTED)) - { - auto e = std::make_shared(); - e->mConnectionInfoCode = RsConnectionEventCode::PEER_DISCONNECTED; - e->mSslId = peer.id; - rsEvents->postEvent(e); - } - } - } - - /* do the Others as well! */ - for(it = mOthersList.begin(); it != mOthersList.end(); ++it) - { - if (it->second.actions) - { - /* add in */ - pqipeer peer; - peer.id = it->second.id; - peer.name = it->second.name; - peer.state = it->second.state; - peer.actions = it->second.actions; - - /* reset action */ - it->second.actions = 0; - -#ifdef LINKMGR_DEBUG_ACTIONS - std::cerr << "Other: " << peer.name << " Id: " << peer.id.toStdString() << " State: " << peer.state; - if (peer.state & RS_PEER_S_FRIEND) - std::cerr << " S:RS_PEER_S_FRIEND"; - if (peer.state & RS_PEER_S_ONLINE) - std::cerr << " S:RS_PEER_S_ONLINE"; - if (peer.state & RS_PEER_S_CONNECTED) - std::cerr << " S:RS_PEER_S_CONNECTED"; - std::cerr << " Actions: " << peer.actions; - if (peer.actions & RS_PEER_NEW) - std::cerr << " A:RS_PEER_NEW"; - if (peer.actions & RS_PEER_MOVED) - std::cerr << " A:RS_PEER_MOVED"; - if (peer.actions & RS_PEER_CONNECTED) - std::cerr << " A:RS_PEER_CONNECTED"; - if (peer.actions & RS_PEER_DISCONNECTED) - std::cerr << " A:RS_PEER_DISCONNECTED"; - if (peer.actions & RS_PEER_CONNECT_REQ) - std::cerr << " A:RS_PEER_CONNECT_REQ"; - - std::cerr << std::endl; -#endif - - actionList.push_back(peer); - } - } - mStatusChanged = false; - doStatusChange = true; - - } - } /****** UNLOCK STACK MUTEX ******/ - - - - - /* NOTE - clients is accessed without mutex protection!!!! - * At the moment this is okay - as they are only added at the start. - * IF this changes ---- must fix with second Mutex. - */ - - if (doStatusChange) - { -#ifdef LINKMGR_DEBUG_ACTIONS - std::cerr << "Sending to " << clients.size() << " monitorClients" << std::endl; -#endif - - /* send to all monitors */ - std::list::iterator mit; - for(mit = clients.begin(); mit != clients.end(); ++mit) - { - (*mit)->statusChange(actionList); - } - } - -#ifdef WINDOWS_SYS -/////////////////////////////////////////////////////////// -// hack for too many connections - - /* notify all monitors */ - std::list::iterator mit; - for(mit = clients.begin(); mit != clients.end(); ++mit) { - (*mit)->statusChanged(); - } - -/////////////////////////////////////////////////////////// -#endif - - { - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - /* Now Cleanup OthersList (served its purpose (MOVE Action)) */ - mOthersList.clear(); - } - -} - - -const RsPeerId& p3LinkMgrIMPL::getOwnId() -{ - return AuthSSL::getAuthSSL()->OwnId(); -} - - -bool p3LinkMgrIMPL::connectAttempt(const RsPeerId &id, struct sockaddr_storage &raddr, - struct sockaddr_storage &proxyaddr, - struct sockaddr_storage &srcaddr, - uint32_t &delay, uint32_t &period, uint32_t &type, uint32_t &flags, uint32_t &bandwidth, - std::string &domain_addr, uint16_t &domain_port) - -{ - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - /* check for existing */ - std::map::iterator it; - it = mFriendList.find(id); - if (it == mFriendList.end()) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectAttempt() FAILED Not in FriendList! id: " << id << std::endl; -#endif - - return false; - } - - if (it->second.connAddrs.size() < 1) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectAttempt() FAILED No ConnectAddresses id: " << id << std::endl; -#endif - return false; - } - - - if (it->second.state & RS_PEER_S_CONNECTED) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectAttempt() Already FLAGGED as connected!!!!" << std::endl; - std::cerr << "p3LinkMgrIMPL::connectAttempt() But allowing anyway!!!" << std::endl; -#endif - - rslog(RSL_WARNING, p3connectzone, "p3LinkMgrIMPL::connectAttempt() ERROR ALREADY CONNECTED"); - - } - -#ifdef LINKMGR_DEBUG_LOG - rslog(RSL_WARNING, p3connectzone, "p3LinkMgrIMPL::connectAttempt() called id: " + id.toStdString()); -#endif - - it->second.lastattempt = time(NULL); - it->second.inConnAttempt = true; - it->second.currentConnAddrAttempt = it->second.connAddrs.front(); - it->second.connAddrs.pop_front(); - - raddr = it->second.currentConnAddrAttempt.addr; - delay = it->second.currentConnAddrAttempt.delay; - period = it->second.currentConnAddrAttempt.period; - type = it->second.currentConnAddrAttempt.type; - flags = it->second.currentConnAddrAttempt.flags; - - proxyaddr = it->second.currentConnAddrAttempt.proxyaddr; - srcaddr = it->second.currentConnAddrAttempt.srcaddr; - bandwidth = it->second.currentConnAddrAttempt.bandwidth; - - domain_addr = it->second.currentConnAddrAttempt.domain_addr; - domain_port = it->second.currentConnAddrAttempt.domain_port; - - /********* Setup LinkType parameters **********/ - -#define TRICKLE_LIMIT 2001 // 2kb -#define LOW_BANDWIDTH_LIMIT 5001 // 5kb - -#ifdef LINKMGR_DEBUG_LINKTYPE - std::cerr << "p3LinkMgrIMPL::connectAttempt() Setting up LinkType" << std::endl; - std::cerr << "p3LinkMgrIMPL::connectAttempt() type = " << type << std::endl; -#endif - - it->second.linkType = 0; - if (type & RS_NET_CONN_TCP_ALL) - { -#ifdef LINKMGR_DEBUG_LINKTYPE - std::cerr << "p3LinkMgrIMPL::connectAttempt() type & TCP_ALL => TCP_UNKNOWN" << std::endl; -#endif - it->second.linkType |= RS_NET_CONN_TRANS_TCP_UNKNOWN; - } - else if (type & RS_NET_CONN_UDP_ALL) - { - if (flags & RS_CB_FLAG_MODE_UDP_DIRECT) - { -#ifdef LINKMGR_DEBUG_LINKTYPE - std::cerr << "p3LinkMgrIMPL::connectAttempt() type & UDP_ALL && flags & DIRECT => UDP_DIRECT" << std::endl; -#endif - it->second.linkType |= RS_NET_CONN_TRANS_UDP_DIRECT; - } - else if (flags & RS_CB_FLAG_MODE_UDP_PROXY) - { -#ifdef LINKMGR_DEBUG_LINKTYPE - std::cerr << "p3LinkMgrIMPL::connectAttempt() type & UDP_ALL && flags & PROXY => UDP_PROXY" << std::endl; -#endif - it->second.linkType |= RS_NET_CONN_TRANS_UDP_PROXY; - } - else if (flags & RS_CB_FLAG_MODE_UDP_RELAY) - { -#ifdef LINKMGR_DEBUG_LINKTYPE - std::cerr << "p3LinkMgrIMPL::connectAttempt() type & UDP_ALL && flags & RELAY => UDP_RELAY" << std::endl; -#endif - it->second.linkType |= RS_NET_CONN_TRANS_UDP_RELAY; - } - else - { -#ifdef LINKMGR_DEBUG_LINKTYPE - std::cerr << "p3LinkMgrIMPL::connectAttempt() type & UDP_ALL && else => UDP_UNKNOWN" << std::endl; -#endif - it->second.linkType |= RS_NET_CONN_TRANS_UDP_UNKNOWN; - } - } - else - { -#ifdef LINKMGR_DEBUG_LINKTYPE - std::cerr << "p3LinkMgrIMPL::connectAttempt() else => TRANS_UNKNOWN" << std::endl; -#endif - it->second.linkType |= RS_NET_CONN_TRANS_UNKNOWN; - } - - if ((type & RS_NET_CONN_UDP_ALL) && (flags & RS_CB_FLAG_MODE_UDP_RELAY)) - { - if (bandwidth < TRICKLE_LIMIT) - { -#ifdef LINKMGR_DEBUG_LINKTYPE - std::cerr << "p3LinkMgrIMPL::connectAttempt() flags & RELAY && band < TRICKLE => SPEED_TRICKLE" << std::endl; -#endif - it->second.linkType |= RS_NET_CONN_SPEED_TRICKLE; - } - else if (bandwidth < LOW_BANDWIDTH_LIMIT) - { -#ifdef LINKMGR_DEBUG_LINKTYPE - std::cerr << "p3LinkMgrIMPL::connectAttempt() flags & RELAY && band < LOW => SPEED_LOW" << std::endl; -#endif - it->second.linkType |= RS_NET_CONN_SPEED_LOW; - } - else - { -#ifdef LINKMGR_DEBUG_LINKTYPE - std::cerr << "p3LinkMgrIMPL::connectAttempt() flags & RELAY && else => SPEED_NORMAL" << std::endl; -#endif - it->second.linkType |= RS_NET_CONN_SPEED_NORMAL; - } - } - else - { -#ifdef LINKMGR_DEBUG_LINKTYPE - std::cerr << "p3LinkMgrIMPL::connectAttempt() else => SPEED_NORMAL" << std::endl; -#endif - it->second.linkType |= RS_NET_CONN_SPEED_NORMAL; - } - - uint32_t connType = mPeerMgr->getConnectionType(id); - it->second.linkType |= connType; - -#ifdef LINKMGR_DEBUG_LINKTYPE - std::cerr << "p3LinkMgrIMPL::connectAttempt() connType: " << connType << std::endl; - std::cerr << "p3LinkMgrIMPL::connectAttempt() final LinkType: " << it->second.linkType << std::endl; - - - std::cerr << "p3LinkMgrIMPL::connectAttempt() found an address: id: " << id << std::endl; - std::cerr << " laddr: " << sockaddr_storage_tostring(raddr) << " delay: " << delay << " period: " << period; - std::cerr << " type: " << type << std::endl; - std::cerr << "p3LinkMgrIMPL::connectAttempt() set LinkType to: " << it->second.linkType << std::endl; -#endif - - - /********* Setup LinkType parameters **********/ - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectAttempt() found an address: id: " << id << std::endl; - std::cerr << " laddr: " << sockaddr_storage_tostring(raddr) << " delay: " << delay << " period: " << period; - std::cerr << " type: " << type << std::endl; - std::cerr << "p3LinkMgrIMPL::connectAttempt() set LinkType to: " << it->second.linkType << std::endl; -#endif - if (sockaddr_storage_isnull(raddr)) { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectAttempt() WARNING: address or port is null" << std::endl; - std::cerr << " type: " << type << std::endl; -#endif - } - - return true; -} - - -/**************************** - * Update state, - * trigger retry if necessary, - * - * remove from DHT? - * - */ - -bool p3LinkMgrIMPL::connectResult(const RsPeerId &id, bool success, bool isIncomingConnection, uint32_t flags, const struct sockaddr_storage &remote_peer_address) -{ - bool doDhtAssist = false ; - bool updatePeerAddr = false; - bool updateLastContact = false; - -#ifdef LINKMGR_DEBUG - std::cerr << "Connection result with peer " << id << ": " << success << ". Is incoming: " << isIncomingConnection << ", remote addr: " << sockaddr_storage_tostring(remote_peer_address) << std::endl; -#endif - - { - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - - if (id == getOwnId()) - { - rslog(RSL_ALERT, p3connectzone, "p3LinkMgrIMPL::connectResult() ERROR Trying to Connect to OwnId: " + id.toStdString()); - - return false; - } - /* check for existing */ - std::map::iterator it; - it = mFriendList.find(id); - if (it == mFriendList.end()) - { - rslog(RSL_ALERT, p3connectzone, "p3LinkMgrIMPL::connectResult() ERROR Missing Friend: " + id.toStdString()); - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectResult() ERROR, missing Friend " << " id: " << id << std::endl; -#endif - return false; - } - - /* now we can tell if we think we were connected - proper point to log */ - - { - std::string out = "p3LinkMgrIMPL::connectResult() id: " + id.toStdString(); - if (success) - { - out += " SUCCESS "; - if (it->second.state & RS_PEER_S_CONNECTED) - { - out += " WARNING: State says: Already Connected"; - } - } - else - { - if (it->second.state & RS_PEER_S_CONNECTED) - { - out += " FAILURE OF THE CONNECTION (Was Connected)"; - } - else - { - out += " FAILED ATTEMPT (Not Connected)"; - } - } -#ifdef LINKMGR_DEBUG_LOG - rslog(RSL_WARNING, p3connectzone, out); -#endif - } - - - - if (success) - { - /* update address (should also come through from DISC) */ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectResult() Connect!: id: " << id << std::endl; - std::cerr << " Success: " << success << " flags: " << flags << ", remote IP = " << sockaddr_storage_iptostring(remote_peer_address) << std::endl; -#endif - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectResult() Connect!: id: " << id << std::endl; - std::cerr << " Success: " << success << " flags: " << flags << std::endl; - - rslog(RSL_WARNING, p3connectzone, "p3LinkMgrIMPL::connectResult() Success"); -#endif - - /* change state */ - it->second.state |= RS_PEER_S_CONNECTED; - it->second.actions |= RS_PEER_CONNECTED; - it->second.connecttype = flags; - it->second.connectaddr = remote_peer_address; - - it->second.actAsServer = isIncomingConnection; - - updateLastContact = true; /* time of connect */ - - /* only update the peer's address if we were in a connect attempt. - * Otherwise, they connected to us, and the address will be a - * random port of their outgoing TCP socket - * - * NB even if we received the connection, the IP address is likely to okay. - */ - - //used to send back to the peer it's own ext address - //it->second.currentserveraddr = remote_peer_address; - - // THIS TEST IS A Bit BAD XXX, we should update their address anyway... - // This means we only update connections that we've made.. so maybe not too bad? - - if ((it->second.inConnAttempt) && - (sockaddr_storage_same(it->second.currentConnAddrAttempt.addr, remote_peer_address))) - { - updatePeerAddr = true; -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectResult() adding current peer address in list." << std::endl; -#endif - } - - /* remove other attempts */ - it->second.inConnAttempt = false; - it->second.connAddrs.clear(); - mStatusChanged = true; - } - else - { -#ifdef LINKMGR_DEBUG_CONNFAIL - std::cerr << "p3LinkMgrIMPL::connectResult() Disconnect/Fail: flags: " << flags << " id: " << id; - std::cerr << std::endl; - - if (it->second.inConnAttempt) - { - std::cerr << "p3LinkMgrIMPL::connectResult() Likely Connect Fail, as inConnAttempt Flag is set"; - std::cerr << std::endl; - } - if (it->second.state & RS_PEER_S_CONNECTED) - { - std::cerr << "p3LinkMgrIMPL::connectResult() Likely DISCONNECT, as state set to Connected"; - std::cerr << std::endl; - } -#endif - - it->second.inConnAttempt = false; - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectResult() Disconnect/Fail: id: " << id << std::endl; - std::cerr << " Success: " << success << " flags: " << flags << std::endl; -#endif - - /* if currently connected -> flag as failed */ - if (it->second.state & RS_PEER_S_CONNECTED) - { - it->second.state &= (~RS_PEER_S_CONNECTED); - it->second.actions |= RS_PEER_DISCONNECTED; - mStatusChanged = true; - - updateLastContact = true; /* time of disconnect */ - } - - if (it->second.connAddrs.size() >= 1) - { - it->second.actions |= RS_PEER_CONNECT_REQ; - mStatusChanged = true; - } - - if (it->second.dhtVisible) - { - doDhtAssist = true; - } - } - } - - if (updatePeerAddr) - { - pqiIpAddress raddr; - raddr.mAddr = remote_peer_address; - raddr.mSeenTime = time(NULL); - raddr.mSrc = 0; - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectResult() Success and we initiated connection... Updating Address"; - std::cerr << std::endl; -#endif - mPeerMgr->updateCurrentAddress(id, raddr); - } - - if (updateLastContact) - { - mPeerMgr->updateLastContact(id); - } - - - /* inform NetAssist of result. This is slightly duplicating below, as we switch it on/off - * in a second anyway. However, the FAILURE of UDP connection, must be informed. - * - * actually the way the DHT works at the moment, both forms of feedback are required. - * this handles connection requests, the other searches. As they are independent... do both. - */ - - if (flags == RS_NET_CONN_UDP_ALL) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectResult() Sending Feedback for UDP connection"; - std::cerr << std::endl; -#endif - if (success) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectResult() UDP Update CONNECTED to: " << id; - std::cerr << std::endl; -#endif - - mNetMgr->netAssistStatusUpdate(id, NETMGR_DHT_FEEDBACK_CONNECTED); - } - else - { -#ifdef LINKMGR_DEBUG - - std::cerr << "p3LinkMgrIMPL::connectResult() UDP Update FAILED to: " << id; - std::cerr << std::endl; -#endif - - /* have no differentiation between failure and closed? */ - mNetMgr->netAssistStatusUpdate(id, NETMGR_DHT_FEEDBACK_CONN_FAILED); - } - } - - - if (success) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectResult() Success switching off DhtAssist for friend: " << id; - std::cerr << std::endl; -#endif - /* always switch it off now */ - mNetMgr->netAssistFriend(id,false); - - /* inform NetMgr that we know this peers address: but only if external address */ - if (sockaddr_storage_isExternalNet(remote_peer_address)) - { - mNetMgr->netAssistKnownPeer(id,remote_peer_address, - NETASSIST_KNOWN_PEER_FRIEND | NETASSIST_KNOWN_PEER_ONLINE); - } - } - else - { - if (doDhtAssist) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectResult() Fail, Enabling DhtAssist for: " << id; - std::cerr << std::endl; -#endif - mNetMgr->netAssistFriend(id,true) ; - } - else - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::connectResult() Fail, No DhtAssist, as No DHT visibility for: " << id; - std::cerr << std::endl; -#endif - } - - /* inform NetMgr that this peer is offline */ - mNetMgr->netAssistKnownPeer(id,remote_peer_address, NETASSIST_KNOWN_PEER_FRIEND | NETASSIST_KNOWN_PEER_OFFLINE); - } - - return success; -} - -/******************************** Feedback ...... ********************************* - * From various sources - */ - -void p3LinkMgrIMPL::peerStatus(const RsPeerId& id, const pqiIpAddrSet &addrs, - uint32_t type, uint32_t flags, uint32_t source) -{ - /* HACKED UP FIX ****/ - - std::map::iterator it; - bool isFriend = true; - - rstime_t now = time(NULL); - - peerAddrInfo details; - details.type = type; - details.found = true; - details.addrs = addrs; - details.ts = now; - - bool updateNetConfig = (source == RS_CB_PERSON); - uint32_t peer_vs_disc = 0; - uint32_t peer_vs_dht = 0; - uint32_t peerNetMode = 0; - - int ownNetMode; - { - peerState ps; - mPeerMgr->getOwnNetStatus(ps); - ownNetMode = ps.netMode; - } - { - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - { - /* Log */ - std::string out = "p3LinkMgrIMPL::peerStatus() id: " + id.toStdString(); - rs_sprintf_append(out, " type: %lu flags: %lu source: %lu\n", type, flags, source); - addrs.printAddrs(out); - - rslog(RSL_WARNING, p3connectzone, out); -#ifdef LINKMGR_DEBUG - std::cerr << out << std::endl; -#endif - } - - /* look up the id */ - it = mFriendList.find(id); - if (it == mFriendList.end()) - { - /* check Others list */ - isFriend = false; - it = mOthersList.find(id); - if (it == mOthersList.end()) - { - /* not found - ignore */ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerStatus() Peer Not Found - Ignore" << std::endl; -#endif - return; - } -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerStatus() Peer is in mOthersList" << std::endl; -#endif - } - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerStatus() Current Peer State:" << std::endl; - printConnectState(std::cerr, it->second); - std::cerr << std::endl; -#endif - - /* update the status */ - - /* if source is DHT */ - if (source == RS_CB_DHT) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerStatus() Update From DHT:"; - std::cerr << std::endl; -#endif - /* DHT can tell us about - * 1) connect type (UDP/TCP/etc) - * 2) local/external address - */ - it->second.source = RS_CB_DHT; - it->second.dht = details; - - /* If we get a info -> then they are online */ - it->second.state |= RS_PEER_S_ONLINE; - it->second.lastavailable = now; - - } - else if (source == RS_CB_DISC) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerStatus() Update From DISC:"; - std::cerr << std::endl; -#endif - /* DISC can tell us about - * 1) connect type (UDP/TCP/etc) - * 2) local/external addresses - */ - it->second.source = RS_CB_DISC; - it->second.disc = details; - - - if (flags & RS_NET_FLAGS_ONLINE) - { - it->second.actions |= RS_PEER_ONLINE; - it->second.state |= RS_PEER_S_ONLINE; - it->second.lastavailable = now; - mStatusChanged = true; - } - - } - else if (source == RS_CB_PERSON) - { - /* PERSON can tell us about - * 1) online / offline - * 2) connect address - * -> update all! - */ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerStatus() Update From PERSON:"; - std::cerr << std::endl; -#endif - - it->second.source = RS_CB_PERSON; - it->second.peer = details; - - it->second.state |= RS_PEER_S_ONLINE; - it->second.lastavailable = now; - - /* must be online to recv info (should be connected too!) - * but no need for action as should be connected already - * - * One problem with these states... is that we will never find them via DHT - * if these flags are switched off here... If we get a connection attempt via DHT - * we should switch the DHT search back on. - */ - - peerNetMode = 0; //it->second.netMode &= (~RS_NET_MODE_ACTUAL); /* clear actual flags */ - if (flags & RS_NET_FLAGS_EXTERNAL_ADDR) - { - peerNetMode = RS_NET_MODE_EXT; - } - else if (flags & RS_NET_FLAGS_STABLE_UDP) - { - peerNetMode = RS_NET_MODE_UDP; - } - else - { - peerNetMode = RS_NET_MODE_UNREACHABLE; - } - - - /* always update VIS status */ - if (flags & RS_NET_FLAGS_USE_DISC) - { - peer_vs_disc = RS_VS_DISC_FULL; - } - else - { - peer_vs_disc = RS_VS_DISC_OFF; - } - - if (flags & RS_NET_FLAGS_USE_DHT) - { - peer_vs_dht = RS_VS_DHT_FULL; - } - else - { - peer_vs_dht = RS_VS_DHT_OFF; - } - - - } - - /* Determine Reachability (only advisory) */ - if (ownNetMode & RS_NET_MODE_UDP) - { - if ((details.type & RS_NET_CONN_UDP_DHT_SYNC) || - (details.type & RS_NET_CONN_TCP_EXTERNAL)) - { - /* reachable! */ - it->second.state &= (~RS_PEER_S_UNREACHABLE); - } - else - { - /* unreachable */ - it->second.state |= RS_PEER_S_UNREACHABLE; - } - } - else if (ownNetMode & RS_NET_MODE_UNREACHABLE) - { - if (details.type & RS_NET_CONN_TCP_EXTERNAL) - { - /* reachable! */ - it->second.state &= (~RS_PEER_S_UNREACHABLE); - } - else - { - /* unreachable */ - it->second.state |= RS_PEER_S_UNREACHABLE; - } - } - else - { - it->second.state &= (~RS_PEER_S_UNREACHABLE); - } - - if (!isFriend) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerStatus() NOT FRIEND " << " id: " << id << std::endl; -#endif - - { - rslog(RSL_WARNING, p3connectzone, "p3LinkMgrIMPL::peerStatus() NO CONNECT (not friend)"); - } - return; - } - - /* if already connected -> done */ - if (it->second.state & RS_PEER_S_CONNECTED) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerStatus() PEER ONLINE ALREADY " << " id: " << id << std::endl; -#endif - { - /* Log */ - rslog(RSL_WARNING, p3connectzone, "p3LinkMgrIMPL::peerStatus() NO CONNECT (already connected!)"); - } - - return; - } - - - } /****** STACK UNLOCK MUTEX *******/ - - bool newAddrs = mPeerMgr->updateAddressList(id, addrs); - if (updateNetConfig) - { - mPeerMgr -> setVisState(id, peer_vs_disc, peer_vs_dht); - mPeerMgr -> setNetworkMode(id, peerNetMode); - } - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerStatus()" << " id: " << id; - std::cerr << " type: " << type << " flags: " << flags; - std::cerr << " source: " << source << std::endl; - std::cerr << " addrs: " << std::endl; - std::string out; - addrs.printAddrs(out); - std::cerr << out << std::endl; - -#endif - -#ifndef P3CONNMGR_NO_AUTO_CONNECTION - -#ifndef P3CONNMGR_NO_TCP_CONNECTIONS - if (newAddrs) - { - retryConnectTCP(id); - } - -#endif // P3CONNMGR_NO_TCP_CONNECTIONS - - -#else -#endif // P3CONNMGR_NO_AUTO_CONNECTION - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerStatus() Resulting Peer State:" << std::endl; - printConnectState(std::cerr, it->second); - std::cerr << std::endl; -#endif - -} - -/* This has become very unwieldy - as extra arguments are required for UDP connections */ -void p3LinkMgrIMPL::peerConnectRequest( - const RsPeerId& id, const sockaddr_storage &raddr, - const sockaddr_storage &proxyaddr, const sockaddr_storage &srcaddr, - uint32_t source, uint32_t flags, uint32_t delay, uint32_t bandwidth ) -{ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerConnectRequest() id: " << id; - std::cerr << " raddr: " << sockaddr_storage_tostring(raddr); - std::cerr << " proxyaddr: " << sockaddr_storage_tostring(proxyaddr); - std::cerr << " srcaddr: " << sockaddr_storage_tostring(srcaddr); - std::cerr << " source: " << source; - std::cerr << " flags: " << flags; - std::cerr << " delay: " << delay; - std::cerr << " bandwidth: " << bandwidth; - std::cerr << std::endl; -#endif - { - /* Log */ - std::string out = "p3LinkMgrIMPL::peerConnectRequest() id: " + id.toStdString(); - out += " raddr: "; - out += sockaddr_storage_tostring(raddr); - out += " proxyaddr: "; - out += sockaddr_storage_tostring(proxyaddr); - out += " srcaddr: "; - out += sockaddr_storage_tostring(srcaddr); - - rs_sprintf_append(out, " source: %lu", source); - rs_sprintf_append(out, " flags: %lu", flags); - rs_sprintf_append(out, " delay: %lu", delay); - rs_sprintf_append(out, " bandwidth: %lu", bandwidth); - - rslog(RSL_WARNING, p3connectzone, out); - } - - /******************** TCP PART *****************************/ - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerConnectRequest() (From DHT Only)" << std::endl; -#endif - - if (source == RS_CB_DHT) - { - - if (flags & RS_CB_FLAG_MODE_TCP) - { - -#ifndef P3CONNMGR_NO_TCP_CONNECTIONS - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerConnectRequest() DHT says Online ==> so try TCP"; - std::cerr << std::endl; -#endif - { - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - std::map::iterator it; - if (mFriendList.end() == (it = mFriendList.find(id))) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerConnectRequest() ERROR Peer is not Friend" << std::endl; -#endif - return; - } - - /* if already connected -> done */ - if (it->second.state & RS_PEER_S_CONNECTED) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerConnectRequest() ERROR Peer Already Connected" << std::endl; -#endif - return; - } - /* setup specific attempt for DHT found address. */ - locked_ConnectAttempt_SpecificAddress(&(it->second), raddr); - } - - retryConnect(id); - -#endif - - } - else - { - /* UDP Attempt! */ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::peerConnectRequest() DHT says CONNECT ==> tryConnectUDP()"; - std::cerr << std::endl; -#endif - tryConnectUDP(id, raddr, proxyaddr, srcaddr, flags, delay, bandwidth); - - } - return; - - } - else - { // IS THIS USED??? - std::cerr << "p3LinkMgrIMPL::peerConnectRequest() ERROR source OTHER ==> NOOP" << std::endl; - std::cerr << std::endl; - - return; - } -} - - -/*******************************************************************/ -/*******************************************************************/ - /*************** External Control ****************/ -bool p3LinkMgrIMPL::retryConnect(const RsPeerId &id) -{ - /* push all available addresses onto the connect addr stack */ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::retryConnect() id: " << id << std::endl; -#endif - -#ifndef P3CONNMGR_NO_TCP_CONNECTIONS - - retryConnectTCP(id); - -#endif // P3CONNMGR_NO_TCP_CONNECTIONS - - return true; -} - - - -bool p3LinkMgrIMPL::tryConnectUDP(const RsPeerId &id, const struct sockaddr_storage &rUdpAddr, - const struct sockaddr_storage &proxyaddr, const struct sockaddr_storage &srcaddr, - uint32_t flags, uint32_t delay, uint32_t bandwidth) - -{ - -#ifdef DISABLE_UDP_CONNECTIONS - - std::cerr << "p3LinkMgrIMPL::tryConnectUDP() CONNECTIONS DISABLED FOR NOW... id: " << id << std::endl; - - std::cerr << "p3LinkMgrIMPL::tryConnectUDP() PARAMS id: " << id; - std::cerr << " raddr: " << rs_inet_ntoa(rUdpAddr.sin_addr) << ":" << ntohs(rUdpAddr.sin_port); - std::cerr << " proxyaddr: " << rs_inet_ntoa(proxyaddr.sin_addr) << ":" << ntohs(proxyaddr.sin_port); - std::cerr << " srcaddr: " << rs_inet_ntoa(srcaddr.sin_addr) << ":" << ntohs(srcaddr.sin_port); - std::cerr << " flags: " << flags; - std::cerr << " delay: " << delay; - std::cerr << " bandwidth: " << bandwidth; - std::cerr << std::endl; - - mNetMgr->netAssistStatusUpdate(id, NETMGR_DHT_FEEDBACK_CONN_FAILED); - - return false; -#endif - - if (mPeerMgr->isHidden()) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::tryConnectUDP() isHidden(): no connection attempts for : " << id; - std::cerr << std::endl; -#endif - return false; - } - - - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - /* push all available addresses onto the connect addr stack */ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::tryConnectUDP() id: " << id << std::endl; -#endif - - if (id == getOwnId()) { - #ifdef LINKMGR_DEBUG - rslog(RSL_WARNING, p3connectzone, "p3LinkMgrIMPL::retryConnectUDP() Failed, connecting to own id: "); - #endif - return false; - } - - /* look up the id */ - std::map::iterator it; - if (mFriendList.end() == (it = mFriendList.find(id))) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::retryConnectUDP() Peer is not Friend" << std::endl; -#endif - return false; - } - - /* if already connected -> done */ - if (it->second.state & RS_PEER_S_CONNECTED) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::retryConnectUDP() Peer Already Connected" << std::endl; -#endif - return false; - } - - /* Explicit Request to start the UDP connection */ - if (sockaddr_storage_isValidNet(rUdpAddr)) - { -#ifdef LINKMGR_DEBUG - std::cerr << "Adding udp connection attempt: "; - std::cerr << "Addr: " << sockaddr_storage_tostring(rUdpAddr); - std::cerr << std::endl; -#endif - peerConnectAddress pca; - pca.addr = rUdpAddr; - pca.type = RS_NET_CONN_UDP_PEER_SYNC; - pca.delay = delay; - pca.ts = time(NULL); - pca.period = P3CONNMGR_UDP_DEFAULT_PERIOD; - pca.flags = flags; - - pca.proxyaddr = proxyaddr; - pca.srcaddr = srcaddr; - pca.bandwidth = bandwidth; - - // Push address to the front... so it happens quickly (before any timings are lost). - addAddressIfUnique(it->second.connAddrs, pca, true); - } - - /* finish it off */ - return locked_ConnectAttempt_Complete(&(it->second)); -} - - - - -/* push all available addresses onto the connect addr stack... - * with the following exceptions: - * - id is our own - * - id is not our friend - * - id is already connected - * - id is hidden but of an unkown type - * - we are hidden but id is not - */ -bool p3LinkMgrIMPL::retryConnectTCP(const RsPeerId &id) -{ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::retryConnectTCP() id: " << id << std::endl; -#endif - - if (id == getOwnId()) return false; - - { - RS_STACK_MUTEX(mLinkMtx); - std::map::iterator it = mFriendList.find(id); - if ( it == mFriendList.end() ) return false; - if ( it->second.state & RS_PEER_S_CONNECTED ) return false; - } - - // Extract the required info from p3PeerMgr - - // first possibility - is it a hidden peer - if (mPeerMgr->isHiddenPeer(id)) - { - /* check for valid hidden type */ - uint32_t type = mPeerMgr->getHiddenType(id); - if ( type & (~RS_HIDDEN_TYPE_MASK) ) return false; - - /* then we just have one connect attempt via the Proxy */ - struct sockaddr_storage proxy_addr; - std::string domain_addr; - uint16_t domain_port; - if ( mPeerMgr->getProxyAddress(id, proxy_addr, domain_addr, domain_port) ) - { - RS_STACK_MUTEX(mLinkMtx); - std::map::iterator it = mFriendList.find(id); - if (it != mFriendList.end()) - { - locked_ConnectAttempt_ProxyAddress(&(it->second), type, proxy_addr, domain_addr, domain_port); - return locked_ConnectAttempt_Complete(&(it->second)); - } - } - - return false; - } - - if (mPeerMgr->isHidden()) return false; - - struct sockaddr_storage lAddr; - struct sockaddr_storage eAddr; - pqiIpAddrSet histAddrs; - std::string dyndns; - if (mPeerMgr->getConnectAddresses(id, lAddr, eAddr, histAddrs, dyndns)) - { - RS_STACK_MUTEX(mLinkMtx); - - std::map::iterator it = mFriendList.find(id); - if ( it != mFriendList.end() ) - { - locked_ConnectAttempt_CurrentAddresses(&(it->second), lAddr, eAddr); - - uint16_t dynPort = 0; - if (!sockaddr_storage_isnull(eAddr)) dynPort = sockaddr_storage_port(eAddr); - if (!dynPort && !sockaddr_storage_isnull(lAddr)) - dynPort = sockaddr_storage_port(lAddr); - if (dynPort) - locked_ConnectAttempt_AddDynDNS(&(it->second), dyndns, dynPort); - - locked_ConnectAttempt_HistoricalAddresses(&(it->second), histAddrs); - - // finish it off - return locked_ConnectAttempt_Complete(&(it->second)); - } - else - std::cerr << "p3LinkMgrIMPL::retryConnectTCP() ERROR failed to find friend data : " << id << std::endl; - } - else - std::cerr << "p3LinkMgrIMPL::retryConnectTCP() ERROR failed to get addresses from PeerMgr for: " << id << std::endl; - - return false; -} - -bool p3LinkMgrIMPL::locked_CheckPotentialAddr(const sockaddr_storage& addr) -{ - /* if invalid - quick rejection */ - if ( ! sockaddr_storage_isValidNet(addr) ) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_CheckPotentialAddr() REJECTING - INVALID"; - std::cerr << std::endl; -#endif - return false; - } - - std::list::const_iterator it; - for(it = mBannedIpList.begin(); it != mBannedIpList.end(); ++it) - { -#ifdef LINKMGR_DEBUG - std::cerr << "Checking IP w.r.t. banned IP " << sockaddr_storage_iptostring(*it) << std::endl; -#endif - - if (sockaddr_storage_sameip(*it, addr)) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_CheckPotentialAddr() REJECTING - ON BANNED IPLIST"; - std::cerr << std::endl; -#endif - return false; - } - } - - if(rsBanList != NULL && !rsBanList->isAddressAccepted(addr, RSBANLIST_CHECKING_FLAGS_BLACKLIST)) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_CheckPotentialAddr() adding to local Banned IPList"; - std::cerr << std::endl; -#endif - return false ; - } - - return true; -} - - -void p3LinkMgrIMPL::locked_ConnectAttempt_SpecificAddress(peerConnectState *peer, const struct sockaddr_storage &remoteAddr) -{ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_SpecificAddresses()"; - std::cerr << std::endl; -#endif - if(locked_CheckPotentialAddr(remoteAddr)) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_SpecificAddresses() "; - std::cerr << "Adding tcp connection attempt: "; - std::cerr << "Addr: " << sockaddr_storage_tostring(remoteAddr); - std::cerr << std::endl; -#endif - peerConnectAddress pca; - pca.addr = remoteAddr; - pca.type = RS_NET_CONN_TCP_EXTERNAL; - pca.delay = P3CONNMGR_TCP_DEFAULT_DELAY; - pca.ts = time(NULL); - pca.period = P3CONNMGR_TCP_DEFAULT_PERIOD; - sockaddr_storage_clear(pca.proxyaddr); - sockaddr_storage_clear(pca.srcaddr); - pca.bandwidth = 0; - - addAddressIfUnique(peer->connAddrs, pca, false); - } -} - - -void p3LinkMgrIMPL::locked_ConnectAttempt_CurrentAddresses(peerConnectState *peer, const struct sockaddr_storage &localAddr, const struct sockaddr_storage &serverAddr) -{ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_CurrentAddresses()"; - std::cerr << std::endl; -#endif - // Just push all the addresses onto the stack. - /* try "current addresses" first */ - if (locked_CheckPotentialAddr(localAddr)) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_CurrentAddresses() "; - std::cerr << "Adding tcp connection attempt: "; - std::cerr << "Current Local Addr: " << sockaddr_storage_tostring(localAddr); - std::cerr << std::endl; -#endif - peerConnectAddress pca; - pca.addr = localAddr; - pca.type = RS_NET_CONN_TCP_LOCAL; - pca.delay = P3CONNMGR_TCP_DEFAULT_DELAY; - pca.ts = time(NULL); - pca.period = P3CONNMGR_TCP_DEFAULT_PERIOD; - sockaddr_storage_clear(pca.proxyaddr); - sockaddr_storage_clear(pca.srcaddr); - pca.bandwidth = 0; - - addAddressIfUnique(peer->connAddrs, pca, false); - } - - if (locked_CheckPotentialAddr(serverAddr)) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_CurrentAddresses() "; - std::cerr << "Adding tcp connection attempt: "; - std::cerr << "Current Ext Addr: " << sockaddr_storage_tostring(serverAddr); - std::cerr << std::endl; -#endif - peerConnectAddress pca; - pca.addr = serverAddr; - pca.type = RS_NET_CONN_TCP_EXTERNAL; - pca.delay = P3CONNMGR_TCP_DEFAULT_DELAY; - pca.ts = time(NULL); - pca.period = P3CONNMGR_TCP_DEFAULT_PERIOD; - sockaddr_storage_clear(pca.proxyaddr); - sockaddr_storage_clear(pca.srcaddr); - pca.bandwidth = 0; - - addAddressIfUnique(peer->connAddrs, pca, false); - } -} - - -void p3LinkMgrIMPL::locked_ConnectAttempt_HistoricalAddresses(peerConnectState *peer, const pqiIpAddrSet &ipAddrs) -{ - /* now try historical addresses */ - /* try local addresses first */ - std::list::const_iterator ait; - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_HistoricalAddresses()"; - std::cerr << std::endl; -#endif - for(ait = ipAddrs.mLocal.mAddrs.begin(); ait != ipAddrs.mLocal.mAddrs.end(); ++ait) - { - if (locked_CheckPotentialAddr(ait->mAddr)) - { - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_HistoricalAddresses() "; - std::cerr << "Adding tcp connection attempt: "; - std::cerr << "Local Addr: " << sockaddr_storage_tostring(ait->mAddr); - std::cerr << std::endl; -#endif - - peerConnectAddress pca; - pca.addr = ait->mAddr; - pca.type = RS_NET_CONN_TCP_LOCAL; - pca.delay = P3CONNMGR_TCP_DEFAULT_DELAY; - pca.ts = time(NULL); - pca.period = P3CONNMGR_TCP_DEFAULT_PERIOD; - sockaddr_storage_clear(pca.proxyaddr); - sockaddr_storage_clear(pca.srcaddr); - pca.bandwidth = 0; - - addAddressIfUnique(peer->connAddrs, pca, false); - } - } - - for(ait = ipAddrs.mExt.mAddrs.begin(); - ait != ipAddrs.mExt.mAddrs.end(); ++ait) - { - if (locked_CheckPotentialAddr(ait->mAddr)) - { - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_HistoricalAddresses() "; - std::cerr << "Adding tcp connection attempt: "; - std::cerr << "Ext Addr: " << sockaddr_storage_tostring(ait->mAddr); - std::cerr << std::endl; -#endif - peerConnectAddress pca; - pca.addr = ait->mAddr; - pca.type = RS_NET_CONN_TCP_EXTERNAL; - pca.delay = P3CONNMGR_TCP_DEFAULT_DELAY; - pca.ts = time(NULL); - pca.period = P3CONNMGR_TCP_DEFAULT_PERIOD; - sockaddr_storage_clear(pca.proxyaddr); - sockaddr_storage_clear(pca.srcaddr); - pca.bandwidth = 0; - - addAddressIfUnique(peer->connAddrs, pca, false); - } - } -} - - -void p3LinkMgrIMPL::locked_ConnectAttempt_AddDynDNS(peerConnectState *peer, std::string dyndns, uint16_t port) -{ - /* try dyndns address too */ - struct sockaddr_storage addr; - if (!dyndns.empty() && port) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_AddDynDNS() Looking up DynDNS address: " << dyndns << std::endl; -#endif - if(mDNSResolver->getIPAddressFromString(dyndns, addr)) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_AddDynDNS() "; - std::cerr << "Adding tcp connection attempt: "; - std::cerr << "DynDNS Addr: " << sockaddr_storage_iptostring(addr); - std::cerr << ":" << port; - std::cerr << std::endl; -#endif - peerConnectAddress pca; - sockaddr_storage_copyip(pca.addr, addr); - sockaddr_storage_setport(pca.addr, port); - pca.type = RS_NET_CONN_TCP_EXTERNAL; - //for the delay, we add a random time and some more time when the friend list is big - pca.delay = P3CONNMGR_TCP_DEFAULT_DELAY; - pca.ts = time(NULL); - pca.period = P3CONNMGR_TCP_DEFAULT_PERIOD; - - sockaddr_storage_clear(pca.proxyaddr); - sockaddr_storage_clear(pca.srcaddr); - pca.bandwidth = 0; - - /* check address validity */ - if (locked_CheckPotentialAddr(pca.addr)) - { - addAddressIfUnique(peer->connAddrs, pca, true); - } - } - else - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_AddDynDNS() DNSResolver hasn't found addr yet"; - std::cerr << std::endl; -#endif - } - } - else - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_AddDynDNS() Address(" << dyndns << ") or Port(" << port << ") NULL ignoring"; - std::cerr << std::endl; -#endif - } -} - - -void p3LinkMgrIMPL::locked_ConnectAttempt_ProxyAddress(peerConnectState *peer, const uint32_t type, const struct sockaddr_storage &proxy_addr, const std::string &domain_addr, uint16_t domain_port) -{ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_ProxyAddress() trying address: " << domain_addr << ":" << domain_port << std::endl; -#endif - peerConnectAddress pca; - pca.addr = proxy_addr; - - switch (type) { - case RS_HIDDEN_TYPE_TOR: - pca.type = RS_NET_CONN_TCP_HIDDEN_TOR; - break; - case RS_HIDDEN_TYPE_I2P: - pca.type = RS_NET_CONN_TCP_HIDDEN_I2P; - break; - case RS_HIDDEN_TYPE_UNKNOWN: - default: - /**** THIS CASE SHOULD NOT BE TRIGGERED - since this function is called with a valid hidden type only ****/ - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_ProxyAddress() hidden type of addr: " << domain_addr << " is unkown -> THIS SHOULD NEVER HAPPEN!" << std::endl; - std::cerr << " - peer : " << peer->id << "(" << peer->name << ")" << std::endl; - std::cerr << " - proxy: " << sockaddr_storage_tostring(proxy_addr) << std::endl; - std::cerr << " - addr : " << domain_addr << ":" << domain_port << std::endl; - pca.type = RS_NET_CONN_TCP_UNKNOW_TOPOLOGY; - } - - //for the delay, we add a random time and some more time when the friend list is big - pca.delay = P3CONNMGR_TCP_DEFAULT_DELAY; - pca.ts = time(NULL); - pca.period = P3CONNMGR_TCP_DEFAULT_PERIOD; - - sockaddr_storage_clear(pca.proxyaddr); - sockaddr_storage_clear(pca.srcaddr); - pca.bandwidth = 0; - - pca.domain_addr = domain_addr; - pca.domain_port = domain_port; - - /* check address validity */ - if (locked_CheckPotentialAddr(pca.addr)) - { - addAddressIfUnique(peer->connAddrs, pca, true); - } -} - - -bool p3LinkMgrIMPL::addAddressIfUnique(std::list &addrList, peerConnectAddress &pca, bool pushFront) -{ - /* iterate through the list, and make sure it isn't already - * in the list - */ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::addAddressIfUnique() Checking Address: " << sockaddr_storage_iptostring(pca.addr); - std::cerr << std::endl; -#endif - - std::list::iterator it; - for(it = addrList.begin(); it != addrList.end(); ++it) - { - if (sockaddr_storage_same(pca.addr, it->addr) && - (pca.type == it->type)) - { -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::addAddressIfUnique() Discarding Duplicate Address"; - std::cerr << std::endl; -#endif - /* already */ - return false; - } - } - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::addAddressIfUnique() Adding New Address"; - std::cerr << std::endl; -#endif - - if (pushFront) - { - addrList.push_front(pca); - } - else - { - addrList.push_back(pca); - } - - return true; -} - - - -bool p3LinkMgrIMPL::locked_ConnectAttempt_Complete(peerConnectState *peer) -{ - - /* flag as last attempt to prevent loop */ - //add a random perturbation between 0 and 2 sec. - peer->lastattempt = time(NULL) + rand() % MAX_RANDOM_ATTEMPT_OFFSET; - - if (peer->inConnAttempt) - { - /* -> it'll automatically use the addresses we added */ -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_Complete() Already in CONNECT ATTEMPT"; - std::cerr << std::endl; - std::cerr << "p3LinkMgrIMPL::locked_ConnectAttempt_Complete() Remaining ConnAddr Count: " << peer->connAddrs.size(); - std::cerr << std::endl; -#endif - return true; - } - - /* start a connection attempt */ - if (peer->connAddrs.size() > 0) - { -#ifdef LINKMGR_DEBUG - std::string out = "p3LinkMgrIMPL::locked_ConnectAttempt_Complete() Started CONNECT ATTEMPT!\n" ; - rs_sprintf_append(out, "p3LinkMgrIMPL::locked_ConnectAttempt_Complete() ConnAddr Count: %u", peer->connAddrs.size()); - rslog(RSL_DEBUG_ALERT, p3connectzone, out); - std::cerr << out << std::endl; -#endif - - peer->actions |= RS_PEER_CONNECT_REQ; - mStatusChanged = true; - return true; - } - else - { -#ifdef LINKMGR_DEBUG - std::string out = "p3LinkMgrIMPL::locked_ConnectAttempt_Complete() No addr in the connect attempt list. Not suitable for CONNECT ATTEMPT!"; - rslog(RSL_DEBUG_ALERT, p3connectzone, out); - std::cerr << out << std::endl; -#endif - return false; - } - return false; -} - - -/*********************************************************************************************************** - ************************************* Handling of Friends ************************************************* - ***********************************************************************************************************/ - -int p3LinkMgrIMPL::addFriend(const RsPeerId &id, bool isVisible) -{ -#ifdef LINKMGR_DEBUG_LOG - rslog(RSL_WARNING, p3connectzone, "p3LinkMgr::addFriend() id: " + id.toStdString()); -#endif - { - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - -#ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::addFriend(" << id << "," << isVisible << ")"; - std::cerr << std::endl; -#endif - - std::map::iterator it; - it = mFriendList.find(id); - - if (it != mFriendList.end()) - { - std::cerr << "p3LinkMgrIMPL::addFriend() ERROR, friend already exists : " << id; - std::cerr << std::endl; - return 0; - } - - peerConnectState pcs; - pcs.dhtVisible = isVisible; - pcs.id = id; - pcs.name = "NoName"; - pcs.state = RS_PEER_S_FRIEND; - pcs.actions = RS_PEER_NEW; - pcs.linkType = RS_NET_CONN_SPEED_UNKNOWN ; - - mFriendList[id] = pcs; - - mStatusChanged = true; - } - - mNetMgr->netAssistFriend(id, isVisible); - - return 1; -} - - -int p3LinkMgrIMPL::removeFriend(const RsPeerId &id) -{ - rslog(RSL_WARNING, p3connectzone, "p3LinkMgr::removeFriend() id: " + id.toStdString()); - - { - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - #ifdef LINKMGR_DEBUG - std::cerr << "p3LinkMgrIMPL::removeFriend(" << id << ")"; - std::cerr << std::endl; - #endif - - std::map::iterator it; - it = mFriendList.find(id); - - if (it == mFriendList.end()) - { - std::cerr << "p3LinkMgrIMPL::removeFriend() ERROR, friend not there : " << id; - std::cerr << std::endl; - return 0; - } - - /* Move to OthersList (so remove can be handled via the action) */ - peerConnectState peer = it->second; - - peer.state &= (~RS_PEER_S_FRIEND); - peer.state &= (~RS_PEER_S_CONNECTED); - peer.state &= (~RS_PEER_S_ONLINE); - peer.actions = RS_PEER_MOVED; - peer.inConnAttempt = false; - mOthersList[id] = peer; - - mStatusChanged = true; - - mFriendList.erase(it); - } - - mNetMgr->netAssistFriend(id, false); - - return 1; -} - -void p3LinkMgrIMPL::disconnectFriend(const RsPeerId& id) -{ - std::list disconnect_clients ; - - { - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - disconnect_clients = clients ; - - std::cerr << "Disconnecting friend " << id << std::endl; - - std::map::iterator it; - it = mFriendList.find(id); - - if (it == mFriendList.end()) - { - std::cerr << "p3LinkMgrIMPL::removeFriend() ERROR, friend not there : " << id; - std::cerr << std::endl; - return ; - } - - /* Move to OthersList (so remove can be handled via the action) */ - peerConnectState peer = it->second; - - peer.state &= (~RS_PEER_S_CONNECTED); - peer.state &= (~RS_PEER_S_ONLINE); - peer.actions = RS_PEER_DISCONNECTED; - peer.inConnAttempt = false; - } - - for(std::list::const_iterator it(disconnect_clients.begin());it!=disconnect_clients.end();++it) - (*it)->disconnectPeer(id) ; -} - -void p3LinkMgrIMPL::printPeerLists(std::ostream &out) -{ - { - RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/ - - out << "p3LinkMgrIMPL::printPeerLists() Friend List"; - out << std::endl; - - - std::map::iterator it; - for(it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - out << "\t SSL ID: " << it->second.id.toStdString(); - out << "\t State: " << it->second.state; - out << std::endl; - } - - out << "p3LinkMgrIMPL::printPeerLists() Others List"; - out << std::endl; - for(it = mOthersList.begin(); it != mOthersList.end(); ++it) - { - out << "\t SSL ID: " << it->second.id.toStdString(); - out << "\t State: " << it->second.state; - } - } - - return; -} - -bool p3LinkMgrIMPL::checkPotentialAddr(const sockaddr_storage& addr) -{ - RS_STACK_MUTEX(mLinkMtx); - return locked_CheckPotentialAddr(addr); -} - - -void printConnectState(std::ostream &out, peerConnectState &peer) -{ - - out << "Friend: " << peer.name << " Id: " << peer.id.toStdString() << " State: " << peer.state; - if (peer.state & RS_PEER_S_FRIEND) - out << " S:RS_PEER_S_FRIEND"; - if (peer.state & RS_PEER_S_ONLINE) - out << " S:RS_PEER_S_ONLINE"; - if (peer.state & RS_PEER_S_CONNECTED) - out << " S:RS_PEER_S_CONNECTED"; - out << " Actions: " << peer.actions; - if (peer.actions & RS_PEER_NEW) - out << " A:RS_PEER_NEW"; - if (peer.actions & RS_PEER_MOVED) - out << " A:RS_PEER_MOVED"; - if (peer.actions & RS_PEER_CONNECTED) - out << " A:RS_PEER_CONNECTED"; - if (peer.actions & RS_PEER_DISCONNECTED) - out << " A:RS_PEER_DISCONNECTED"; - if (peer.actions & RS_PEER_CONNECT_REQ) - out << " A:RS_PEER_CONNECT_REQ"; - - out << std::endl; - return; -} - - - diff --git a/libretroshare/src/pqi/p3linkmgr.h b/libretroshare/src/pqi/p3linkmgr.h deleted file mode 100644 index 3b2c5c638..000000000 --- a/libretroshare/src/pqi/p3linkmgr.h +++ /dev/null @@ -1,340 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3linkmgr.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_LINK_MANAGER_HEADER -#define MRK_PQI_LINK_MANAGER_HEADER - -#include "pqi/pqimonitor.h" -#include "pqi/pqiipset.h" -#include "util/rstime.h" -#include "pqi/pqiassist.h" - -#include "pqi/p3cfgmgr.h" - -#include "util/rsthreads.h" - -class ExtAddrFinder ; -class DNSResolver ; - - -/* order of attempts ... */ -const uint32_t RS_NET_CONN_TCP_ALL = 0x00ff; -const uint32_t RS_NET_CONN_UDP_ALL = 0x0f00; - -const uint32_t RS_NET_CONN_TCP_LOCAL = 0x0001; -const uint32_t RS_NET_CONN_TCP_EXTERNAL = 0x0002; -const uint32_t RS_NET_CONN_TCP_UNKNOW_TOPOLOGY = 0x0004; -const uint32_t RS_NET_CONN_TCP_HIDDEN_TOR = 0x0008; -const uint32_t RS_NET_CONN_TCP_HIDDEN_I2P = 0x0010; - -const uint32_t RS_NET_CONN_UDP_DHT_SYNC = 0x0100; -const uint32_t RS_NET_CONN_UDP_PEER_SYNC = 0x0200; /* coming soon */ - -// These are set in pqipersongroup. -const uint32_t RS_TCP_STD_TIMEOUT_PERIOD = 5; /* 5 seconds! */ -const uint32_t RS_TCP_HIDDEN_TIMEOUT_PERIOD = 30; /* 30 seconds! */ -const uint32_t RS_UDP_STD_TIMEOUT_PERIOD = 80; /* 80 secs, allows UDP TTL to get to 40! - Plenty of time (30+80) = 110 secs */ - -class peerAddrInfo -{ - public: - peerAddrInfo(); /* init */ - - bool found; - uint32_t type; - pqiIpAddrSet addrs; - rstime_t ts; -}; - -class peerConnectAddress -{ - public: - peerConnectAddress(); /* init */ - - struct sockaddr_storage addr; - uint32_t delay; /* to stop simultaneous connects */ - uint32_t period; /* UDP only */ - uint32_t type; - uint32_t flags; /* CB FLAGS defined in pqimonitor.h */ - rstime_t ts; - - // Extra Parameters for Relay connections. - struct sockaddr_storage proxyaddr; - struct sockaddr_storage srcaddr; - uint32_t bandwidth; - - // Extra Parameters for Proxy/Hidden connection. - std::string domain_addr; - uint16_t domain_port; -}; - -class peerConnectState -{ - public: - peerConnectState(); /* init */ - - RsPeerId id; - - /***** Below here not stored permanently *****/ - - bool dhtVisible; - - uint32_t connecttype; // RS_NET_CONN_TCP_ALL / RS_NET_CONN_UDP_ALL - bool actAsServer; - rstime_t lastavailable; - rstime_t lastattempt; - - std::string name; - - uint32_t state; - uint32_t actions; - uint32_t linkType; - - uint32_t source; /* most current source */ - peerAddrInfo dht; - peerAddrInfo disc; - peerAddrInfo peer; - - struct sockaddr_storage connectaddr; // current connection address. Can be local or external. - - /* a list of connect attempts to make (in order) */ - bool inConnAttempt; - peerConnectAddress currentConnAddrAttempt; - std::list connAddrs; - - /* information about denial */ - bool wasDeniedConnection; - rstime_t deniedTS; - bool deniedInConnAttempt; /* is below valid */ - peerConnectAddress deniedConnectionAttempt; -}; - -class p3tunnel; -class RsPeerGroupItem_deprecated; -struct RsGroupInfo; - -class p3PeerMgr; -class p3NetMgr; - -class p3PeerMgrIMPL; -class p3NetMgrIMPL; - -std::string textPeerConnectState(peerConnectState &state); - -/******* - * Virtual Interface to allow testing - * - */ - -class p3LinkMgr: public pqiConnectCb -{ - public: - - p3LinkMgr() { return; } -virtual ~p3LinkMgr() { return; } - - -virtual const RsPeerId& getOwnId() = 0; -virtual bool isOnline(const RsPeerId &ssl_id) = 0; -virtual void getOnlineList(std::list &ssl_peers) = 0; -virtual bool getPeerName(const RsPeerId &ssl_id, std::string &name) = 0; -virtual uint32_t getLinkType(const RsPeerId &ssl_id) = 0; - - /**************** handle monitors *****************/ -virtual void addMonitor(pqiMonitor *mon) = 0; -virtual void removeMonitor(pqiMonitor *mon) = 0; - - /****************** Connections *******************/ -virtual bool connectAttempt(const RsPeerId &id, struct sockaddr_storage &raddr, - struct sockaddr_storage &proxyaddr, struct sockaddr_storage &srcaddr, - uint32_t &delay, uint32_t &period, uint32_t &type, uint32_t &flags, uint32_t &bandwidth, - std::string &domain_addr, uint16_t &domain_port) = 0; - -virtual bool connectResult(const RsPeerId &id, bool success, bool isIncomingConnection, uint32_t flags, const struct sockaddr_storage &remote_peer_address) = 0; -virtual bool retryConnect(const RsPeerId &id) = 0; - - /* Network Addresses */ -virtual bool setLocalAddress(const struct sockaddr_storage &addr) = 0; -virtual bool getLocalAddress(struct sockaddr_storage &addr) = 0; - - /************* DEPRECIATED FUNCTIONS (TO REMOVE) ********/ - -virtual void getFriendList(std::list &ssl_peers) = 0; // ONLY used by p3peers.cc USE p3PeerMgr instead. -virtual bool getFriendNetStatus(const RsPeerId &id, peerConnectState &state) = 0; // ONLY used by p3peers.cc - - virtual bool checkPotentialAddr(const sockaddr_storage& addr) = 0; - - /************* DEPRECIATED FUNCTIONS (TO REMOVE) ********/ -virtual int addFriend(const RsPeerId &ssl_id, bool isVisible) = 0; - /******* overloaded from pqiConnectCb *************/ -// THESE MUSTn't BE specfied HERE - as overloaded from pqiConnectCb. -//virtual void peerStatus(std::string id, const pqiIpAddrSet &addrs, -// uint32_t type, uint32_t flags, uint32_t source) = 0; -//virtual void peerConnectRequest(std::string id, const struct sockaddr_storage &raddr, -// const struct sockaddr_storage &proxyaddr, const struct sockaddr_storage &srcaddr, -// uint32_t source, uint32_t flags, uint32_t delay, uint32_t bandwidth) = 0; - -/****************************************************************************/ -/****************************************************************************/ -/****************************************************************************/ - -}; - - - -class p3LinkMgrIMPL: public p3LinkMgr -{ - public: - -/************************************************************************************************/ -/* EXTERNAL INTERFACE */ -/************************************************************************************************/ - -virtual const RsPeerId& getOwnId(); -virtual bool isOnline(const RsPeerId &ssl_id); -virtual void getOnlineList(std::list &ssl_peers); -virtual bool getPeerName(const RsPeerId &ssl_id, std::string &name); -virtual uint32_t getLinkType(const RsPeerId &ssl_id); - - - /**************** handle monitors *****************/ -virtual void addMonitor(pqiMonitor *mon); -virtual void removeMonitor(pqiMonitor *mon); - - /****************** Connections *******************/ -virtual bool connectAttempt(const RsPeerId &id, struct sockaddr_storage &raddr, - struct sockaddr_storage &proxyaddr, struct sockaddr_storage &srcaddr, - uint32_t &delay, uint32_t &period, uint32_t &type, uint32_t &flags, uint32_t &bandwidth, - std::string &domain_addr, uint16_t &domain_port); - -virtual bool connectResult(const RsPeerId &id, bool success, bool isIncomingConnection, uint32_t flags, const struct sockaddr_storage &remote_peer_address); -virtual bool retryConnect(const RsPeerId &id); - - /* Network Addresses */ -virtual bool setLocalAddress(const struct sockaddr_storage &addr); -virtual bool getLocalAddress(struct sockaddr_storage &addr); - - /******* overloaded from pqiConnectCb *************/ -virtual void peerStatus(const RsPeerId& id, const pqiIpAddrSet &addrs, - uint32_t type, uint32_t flags, uint32_t source); -virtual void peerConnectRequest(const RsPeerId& id, const struct sockaddr_storage &raddr, - const struct sockaddr_storage &proxyaddr, const struct sockaddr_storage &srcaddr, - uint32_t source, uint32_t flags, uint32_t delay, uint32_t bandwidth); - - - /************* DEPRECIATED FUNCTIONS (TO REMOVE) ********/ - -virtual void getFriendList(std::list &ssl_peers); // ONLY used by p3peers.cc USE p3PeerMgr instead. -virtual bool getFriendNetStatus(const RsPeerId &id, peerConnectState &state); // ONLY used by p3peers.cc - -/************************************************************************************************/ -/* Extra IMPL Functions (used by p3PeerMgr, p3NetMgr + Setup) */ -/************************************************************************************************/ - - p3LinkMgrIMPL(p3PeerMgrIMPL *peerMgr, p3NetMgrIMPL *netMgr); - virtual ~p3LinkMgrIMPL(); - -void tick(); - - /* THIS COULD BE ADDED TO INTERFACE */ -void setFriendVisibility(const RsPeerId &id, bool isVisible); - - void disconnectFriend(const RsPeerId& id) ; - - /* add/remove friends */ -virtual int addFriend(const RsPeerId &ssl_id, bool isVisible); -int removeFriend(const RsPeerId &ssl_id); - -void printPeerLists(std::ostream &out); - - virtual bool checkPotentialAddr(const sockaddr_storage& addr); - -protected: - /* THESE CAN PROBABLY BE REMOVED */ -//bool shutdown(); /* blocking shutdown call */ -//bool getOwnNetStatus(peerConnectState &state); - - -protected: - /****************** Internal Interface *******************/ - - /* Internal Functions */ -void statusTick(); - - /* monitor control */ -void tickMonitors(); - - /* connect attempts UDP */ -bool tryConnectUDP(const RsPeerId &id, const struct sockaddr_storage &rUdpAddr, - const struct sockaddr_storage &proxyaddr, const struct sockaddr_storage &srcaddr, - uint32_t flags, uint32_t delay, uint32_t bandwidth); - - /* connect attempts TCP */ -bool retryConnectTCP(const RsPeerId &id); - -void locked_ConnectAttempt_SpecificAddress(peerConnectState *peer, const struct sockaddr_storage &remoteAddr); -void locked_ConnectAttempt_CurrentAddresses(peerConnectState *peer, const struct sockaddr_storage &localAddr, const struct sockaddr_storage &serverAddr); -void locked_ConnectAttempt_HistoricalAddresses(peerConnectState *peer, const pqiIpAddrSet &ipAddrs); -void locked_ConnectAttempt_AddDynDNS(peerConnectState *peer, std::string dyndns, uint16_t dynPort); -void locked_ConnectAttempt_AddTunnel(peerConnectState *peer); -void locked_ConnectAttempt_ProxyAddress(peerConnectState *peer, const uint32_t type, const struct sockaddr_storage &proxy_addr, const std::string &domain_addr, uint16_t domain_port); - -bool locked_ConnectAttempt_Complete(peerConnectState *peer); - - bool locked_CheckPotentialAddr(const sockaddr_storage& addr); - -bool addAddressIfUnique(std::list &addrList, peerConnectAddress &pca, bool pushFront); - - -private: - // These should have their own Mutex Protection, - //p3tunnel *mP3tunnel; - DNSResolver *mDNSResolver ; - - p3PeerMgrIMPL *mPeerMgr; - p3NetMgrIMPL *mNetMgr; - - RsMutex mLinkMtx; /* protects below */ - - uint32_t mRetryPeriod; - - bool mStatusChanged; - - struct sockaddr_storage mLocalAddress; - - std::list clients; - - bool mAllowTunnelConnection; - - /* external Address determination */ - //bool mUpnpAddrValid, mStunAddrValid; - //struct sockaddr_in mUpnpExtAddr; - - //peerConnectState mOwnState; - - std::map mFriendList; - std::map mOthersList; - - /* relatively static list of banned ip addresses */ - std::list mBannedIpList; -}; - -#endif // MRK_PQI_LINK_MANAGER_HEADER diff --git a/libretroshare/src/pqi/p3netmgr.cc b/libretroshare/src/pqi/p3netmgr.cc deleted file mode 100644 index 21e45ac16..000000000 --- a/libretroshare/src/pqi/p3netmgr.cc +++ /dev/null @@ -1,2088 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3netmgr.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2007-2011 Robert Fernie * - * Copyright (C) 2015-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "util/rstime.h" -#include - -#include "pqi/p3netmgr.h" - -#include "pqi/p3peermgr.h" -#include "pqi/p3linkmgr.h" - -#include "util/rsnet.h" -#include "util/rsrandom.h" -#include "util/rsdebug.h" - -#include "util/extaddrfinder.h" -#include "util/dnsresolver.h" - - -struct RsLog::logInfo p3netmgrzoneInfo = {RsLog::Default, "p3netmgr"}; -#define p3netmgrzone &p3netmgrzoneInfo - -#include "rsitems/rsconfigitems.h" - -#include "retroshare/rsiface.h" -#include "retroshare/rsconfig.h" -#include "retroshare/rsbanlist.h" - -/* Network setup States */ - -constexpr uint32_t RS_NET_NEEDS_RESET = 0x0000; -constexpr uint32_t RS_NET_UNKNOWN = 0x0001; -constexpr uint32_t RS_NET_UPNP_INIT = 0x0002; -constexpr uint32_t RS_NET_UPNP_SETUP = 0x0003; -constexpr uint32_t RS_NET_EXT_SETUP = 0x0004; -constexpr uint32_t RS_NET_DONE = 0x0005; -constexpr uint32_t RS_NET_LOOPBACK = 0x0006; -//constexpr uint32_t RS_NET_DOWN = 0x0007; -constexpr uint32_t RS_NET_SHUTDOWN = 0x00FF; //Highest value to not restart UPnP nor ExtAddrFinder - -/* Stun modes (TODO) */ -//const uint32_t RS_STUN_DHT = 0x0001; -//const uint32_t RS_STUN_DONE = 0x0002; -//const uint32_t RS_STUN_LIST_MIN = 100; -//const uint32_t RS_STUN_FOUND_MIN = 10; - -const uint32_t MAX_UPNP_INIT = 60; /* seconds UPnP timeout */ -const uint32_t MAX_UPNP_COMPLETE = 600; /* 10 min... seems to take a while */ -//const uint32_t MAX_NETWORK_INIT = 70; /* timeout before network reset */ - -//const uint32_t MIN_TIME_BETWEEN_NET_RESET = 5; - -const uint32_t MIN_TIME_EXT_FINDER_UPDATE = 300; /* 5min to check if external IP is changed */ - -/**** - * #define NETMGR_DEBUG 1 - * #define NETMGR_DEBUG_RESET 1 - * #define NETMGR_DEBUG_TICK 1 - * #define NETMGR_DEBUG_STATEBOX 1 - ***/ -// #define NETMGR_DEBUG 1 -// #define NETMGR_DEBUG_RESET 1 -// #define NETMGR_DEBUG_TICK 1 -// #define NETMGR_DEBUG_STATEBOX 1 - -pqiNetStatus::pqiNetStatus() : - mExtAddrOk(false), mExtAddrStableOk(false), mUpnpOk(false), mDhtOk(false), - mDhtNetworkSize(0), mDhtRsNetworkSize(0), mResetReq(false) -{ - sockaddr_storage_clear(mLocalAddr); - sockaddr_storage_clear(mExtAddr); -} - - - -void pqiNetStatus::print(std::ostream &out) -{ - out << "pqiNetStatus: "; - out << " mExtAddrOk: " << mExtAddrOk; - out << " mExtAddrStableOk: " << mExtAddrStableOk; - out << std::endl; - out << " mUpnpOk: " << mUpnpOk; - out << " mDhtOk: " << mDhtOk; - out << " mResetReq: " << mResetReq; - out << std::endl; - out << "mDhtNetworkSize: " << mDhtNetworkSize << " mDhtRsNetworkSize: " << mDhtRsNetworkSize; - out << std::endl; - out << "mLocalAddr: " << sockaddr_storage_tostring(mLocalAddr) << " "; - out << "mExtAddr: " << sockaddr_storage_tostring(mExtAddr) << " "; - out << std::endl; -} - - -p3NetMgrIMPL::p3NetMgrIMPL() - : mPeerMgr(nullptr), mLinkMgr(nullptr) - , mNetMtx("p3NetMgr"), mNetMode(RS_NET_MODE_UDP), mVsDisc(RS_VS_DISC_FULL), mVsDht(RS_VS_DHT_FULL)// default to full. - , mNetInitTS(0), mNetStatus(RS_NET_UNKNOWN), mStatusChanged(false) - , mUseExtAddrFinder(true), mNetExtAddrFinderTs(0), mDoNotNetCheckUntilTs(0) -{ - - { - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - - mExtAddrFinder = new ExtAddrFinder(); - - mNetFlags = pqiNetStatus(); - mOldNetFlags = pqiNetStatus(); - - mOldNatType = RsNatTypeMode::UNKNOWN; - mOldNatHole = RsNatHoleMode::UNKNOWN; - sockaddr_storage_clear(mLocalAddr); - sockaddr_storage_clear(mExtAddr); - - // force to IPv4 for the moment. - mLocalAddr.ss_family = AF_INET; - mExtAddr.ss_family = AF_INET; - - } - -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgr() Startup" << std::endl; -#endif - - rslog(RSL_WARNING, p3netmgrzone, "p3NetMgr() Startup, resetting network"); - netReset(); - - return; -} - -void p3NetMgrIMPL::setManagers(p3PeerMgr *peerMgr, p3LinkMgr *linkMgr) -{ - mPeerMgr = peerMgr; - mLinkMgr = linkMgr; -} - -#ifdef RS_USE_DHT_STUNNER -void p3NetMgrIMPL::setAddrAssist(pqiAddrAssist *dhtStun, pqiAddrAssist *proxyStun) -{ - mDhtStunner = dhtStun; - mProxyStunner = proxyStun; -} -#endif // RS_USE_DHT_STUNNER - - -/***** Framework / initial implementation for a connection manager. - * - * This needs a state machine for Initialisation. - * - * Network state: - * RS_NET_UNKNOWN - * RS_NET_EXT_UNKNOWN * forwarded port (but Unknown Ext IP) * - * RS_NET_EXT_KNOWN * forwarded port with known IP/Port. * - * - * RS_NET_UPNP_CHECK * checking for UPnP * - * RS_NET_UPNP_KNOWN * confirmed UPnP ext Ip/port * - * - * RS_NET_UDP_UNKNOWN * not Ext/UPnP - to determine Ext IP/Port * - * RS_NET_UDP_KNOWN * have Stunned for Ext Addr * - * - * Transitions: - * - * RS_NET_UNKNOWN -(config)-> RS_NET_EXT_UNKNOWN - * RS_NET_UNKNOWN -(config)-> RS_NET_UPNP_UNKNOWN - * RS_NET_UNKNOWN -(config)-> RS_NET_UDP_UNKNOWN - * - * RS_NET_EXT_UNKNOWN -(DHT(ip)/Stun)-> RS_NET_EXT_KNOWN - * - * RS_NET_UPNP_UNKNOWN -(Upnp)-> RS_NET_UPNP_KNOWN - * RS_NET_UPNP_UNKNOWN -(timout/Upnp)-> RS_NET_UDP_UNKNOWN - * - * RS_NET_UDP_UNKNOWN -(stun)-> RS_NET_UDP_KNOWN - * - * - * STUN state: - * RS_STUN_INIT * done nothing * - * RS_STUN_DHT * looking up peers * - * RS_STUN_DONE * found active peer and stunned * - * - * - * Steps. - ******************************************************************* - * (1) Startup. - * - UDP port setup. - * - DHT setup. - * - Get Stun Keys -> add to DHT. - * - Feedback from DHT -> ask UDP to stun. - * - * (1) determine Network mode. - * If external Port.... Done: - * (2) - ******************************************************************* - * Stable operation: - * (1) tick and check peers. - * (2) handle callback. - * (3) notify of new/failed connections. - * - * - */ - -/* Called to reseet the whole network stack. this call is - * triggered by udp stun address tracking. - * - * must: - * - reset UPnP and DHT. - * - - */ - -void p3NetMgrIMPL::netReset() -{ -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netReset() Called" << std::endl; -#endif - rslog(RSL_ALERT, p3netmgrzone, "p3NetMgr::netReset() Called"); - - shutdown(); /* blocking shutdown call */ - { - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - mNetStatus = RS_NET_UNKNOWN; - } - - // Will initiate a new call for determining the external ip. - if (mUseExtAddrFinder) - { -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netReset() restarting AddrFinder" << std::endl; -#endif - mExtAddrFinder->reset(true) ; - } - else - { -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netReset() ExtAddrFinder Disabled" << std::endl; -#endif - } - -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netReset() resetting NetStatus" << std::endl; -#endif - - /* reset tcp network - if necessary */ - { - /* NOTE: nNetListeners should be protected via the Mutex. - * HOWEVER, as we NEVER change this list - once its setup - * we can get away without it - and assume its constant. - * - * NB: (*it)->reset_listener must be out of the mutex, - * as it calls back to p3ConnMgr. - */ - - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - - struct sockaddr_storage iaddr = mLocalAddr; - -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netReset() resetting listeners" << std::endl; -#endif - std::list::const_iterator it; - for(it = mNetListeners.begin(); it != mNetListeners.end(); ++it) - { - (*it)->resetListener(iaddr); -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netReset() reset listener" << std::endl; -#endif - } - } - - { - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - netStatusReset_locked(); - } - - updateNetStateBox_reset(); - -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netReset() done" << std::endl; -#endif -} - - -void p3NetMgrIMPL::netStatusReset_locked() -{ - //std::cerr << "p3NetMgrIMPL::netStatusReset()" << std::endl;; - - mNetFlags = pqiNetStatus(); -} - - -bool p3NetMgrIMPL::shutdown() /* blocking shutdown call */ -{ -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::shutdown()"; - std::cerr << std::endl; -#endif - { - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - mNetStatus = RS_NET_SHUTDOWN; - mNetInitTS = time(NULL); - netStatusReset_locked(); - } - netAssistFirewallShutdown(); - netAssistConnectShutdown(); - - return true; -} - - - - - - - - - -void p3NetMgrIMPL::netStartup() -{ - /* startup stuff */ - - /* StunInit gets a list of peers, and asks the DHT to find them... - * This is needed for all systems so startup straight away - */ -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netStartup()" << std::endl; -#endif - - netDhtInit(); - - /* decide which net setup mode we're going into - */ - - - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - - mNetInitTS = time(NULL); - netStatusReset_locked(); - -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netStartup() resetting mNetInitTS / Status" << std::endl; -#endif - mNetMode &= ~(RS_NET_MODE_ACTUAL); - - switch(mNetMode & RS_NET_MODE_TRYMODE) - { - - case RS_NET_MODE_TRY_EXT: /* v similar to UDP */ -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netStartup() TRY_EXT mode"; - std::cerr << std::endl; -#endif - mNetMode |= RS_NET_MODE_EXT; - mNetStatus = RS_NET_EXT_SETUP; - break; - - case RS_NET_MODE_TRY_UDP: -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netStartup() TRY_UDP mode"; - std::cerr << std::endl; -#endif - mNetMode |= RS_NET_MODE_UDP; - mNetStatus = RS_NET_EXT_SETUP; - break; - - case RS_NET_MODE_TRY_LOOPBACK: -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netStartup() TRY_LOOPBACK mode"; - std::cerr << std::endl; -#endif - mNetMode |= RS_NET_MODE_HIDDEN; - mNetStatus = RS_NET_LOOPBACK; - break; - - default: // Fall through. - -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netStartup() UNKNOWN mode"; - std::cerr << std::endl; -#endif - - case RS_NET_MODE_TRY_UPNP: -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::netStartup() TRY_UPNP mode"; - std::cerr << std::endl; -#endif - /* Force it here (could be default!) */ - mNetMode |= RS_NET_MODE_TRY_UPNP; - mNetMode |= RS_NET_MODE_UDP; /* set to UDP, upgraded is UPnP is Okay */ - mNetStatus = RS_NET_UPNP_INIT; - break; - } -} - - -void p3NetMgrIMPL::tick() -{ - rstime_t now = time(nullptr); - rstime_t dontCheckNetUntil; - { RS_STACK_MUTEX(mNetMtx); dontCheckNetUntil = mDoNotNetCheckUntilTs; } - - if(now >= dontCheckNetUntil) netStatusTick(); - - uint32_t netStatus; { RS_STACK_MUTEX(mNetMtx); netStatus = mNetStatus; } - switch (netStatus) - { - case RS_NET_LOOPBACK: - if(dontCheckNetUntil <= now) - { - RS_STACK_MUTEX(mNetMtx); - mDoNotNetCheckUntilTs = now + 30; - } - break; - default: - netAssistTick(); - updateNetStateBox_temporal(); -#ifdef RS_USE_DHT_STUNNER - if (mDhtStunner) mDhtStunner->tick(); - if (mProxyStunner) mProxyStunner->tick(); -#endif // RS_USE_DHT_STUNNER - break; - } -} - -#define STARTUP_DELAY 5 - - -void p3NetMgrIMPL::netStatusTick() -{ - -#ifdef NETMGR_DEBUG_TICK - std::cerr << "p3NetMgrIMPL::netTick()" << std::endl; - - std::cerr << "p3NetMgrIMPL::netTick() mNetMode: " << std::hex << mNetMode; - std::cerr << " ACTUALMODE: " << (mNetMode & RS_NET_MODE_ACTUAL); - std::cerr << " TRYMODE: " << (mNetMode & RS_NET_MODE_TRYMODE); - std::cerr << std::endl; -#endif - - // Check whether we are stuck on loopback. This happens if RS starts when - // the computer is not yet connected to the internet. In such a case we - // periodically check for a local net address. - // - checkNetAddress() ; - - uint32_t netStatus = 0; - rstime_t age = 0; - bool needExtFinderUpdate = false; - { - RS_STACK_MUTEX(mNetMtx); /************** LOCK MUTEX ***************/ - - netStatus = mNetStatus; - age = time(NULL) - mNetInitTS; - - needExtFinderUpdate = netStatus == RS_NET_DONE; - needExtFinderUpdate &= mNetExtAddrFinderTs < time(nullptr); - if(needExtFinderUpdate) - mNetExtAddrFinderTs = time(nullptr) + MIN_TIME_EXT_FINDER_UPDATE; - } - - if( mUseExtAddrFinder - && ( netStatus <= RS_NET_UPNP_SETUP - || needExtFinderUpdate) ) - { - sockaddr_storage tmpip; - sockaddr_storage_copy( mLocalAddr, tmpip); // copies local port and correctly inits the IP family -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - RS_DBG("Asking ExtAddrFinder for IP. Initializing port with ", sockaddr_storage_port(tmpip)); -#endif - - if(mExtAddrFinder->hasValidIPV4(tmpip)) - { - if(!sockaddr_storage_same(tmpip,mExtAddr)) - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - RS_DBG("Ext supplied by ExtAddrFinder. ExtAddr: ", tmpip); -#endif - setExtAddress(tmpip); - } - } - else if(mExtAddrFinder->hasValidIPV6(tmpip)) - { - if(!sockaddr_storage_same(tmpip,mExtAddr)) - { - //Only if no IPv4 else, reset connections on setExtAddress() -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - RS_DBG("Ext supplied by ExtAddrFinder. ExtAddr: ", tmpip); -#endif - setExtAddress(tmpip); - } - } - } - - switch(netStatus) - { - case RS_NET_NEEDS_RESET: - -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netTick() STATUS: NEEDS_RESET" << std::endl; -#endif - rslog(RSL_WARNING, p3netmgrzone, "p3NetMgr::netTick() RS_NET_NEEDS_RESET, resetting network"); - - netReset(); - break; - - case RS_NET_UNKNOWN: -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netTick() STATUS: UNKNOWN" << std::endl; -#endif - - /* add a small delay to stop restarting straight after a RESET - * This is so can we shutdown cleanly - */ - if (age < STARTUP_DELAY) - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netTick() Delaying Startup" << std::endl; -#endif - } - else - { - netStartup(); - } - - break; - - case RS_NET_UPNP_INIT: -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netTick() STATUS: UPNP_INIT" << std::endl; -#endif - netUpnpInit(); - break; - - case RS_NET_UPNP_SETUP: -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netTick() STATUS: UPNP_SETUP" << std::endl; -#endif - netUpnpCheck(); - break; - - - case RS_NET_EXT_SETUP: -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netTick() STATUS: EXT_SETUP" << std::endl; -#endif - // This could take a lot of time on some systems to get there: - // (e.g. 10 mins to get passed upnp on windows), so it would be better to call it right away, so other external address finding - // systems still have a chance to run early. - - netExtCheck(); - break; - - case RS_NET_DONE: -#ifdef NETMGR_DEBUG_TICK - std::cerr << "p3NetMgrIMPL::netTick() STATUS: DONE" << std::endl; -#endif - - break; - - case RS_NET_LOOPBACK: - //don't do a shutdown because a client in a computer without local network might be usefull for debug. - //shutdown(); -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netTick() STATUS: RS_NET_LOOPBACK" << std::endl; -#endif - default: - break; - } - - return; -} - - -void p3NetMgrIMPL::netDhtInit() -{ -#if defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netDhtInit()" << std::endl; -#endif - - uint32_t vs = 0; - { - RS_STACK_MUTEX(mNetMtx); /*********** LOCKED MUTEX ************/ - vs = mVsDht; - } - - enableNetAssistConnect(vs != RS_VS_DHT_OFF); -} - - -void p3NetMgrIMPL::netUpnpInit() -{ -#if defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netUpnpInit()" << std::endl; -#endif - uint16_t eport, iport; - - mNetMtx.lock(); /* LOCK MUTEX */ - - /* get the ports from the configuration */ - - mNetStatus = RS_NET_UPNP_SETUP; - iport = sockaddr_storage_port(mLocalAddr); - eport = sockaddr_storage_port(mExtAddr); - if ((eport < 1000) || (eport > 30000)) - { - eport = iport; - } - - mNetMtx.unlock(); /* UNLOCK MUTEX */ - - netAssistFirewallPorts(iport, eport); - enableNetAssistFirewall(true); -} - -void p3NetMgrIMPL::netUpnpCheck() -{ - /* grab timestamp */ - mNetMtx.lock(); /* LOCK MUTEX */ - - rstime_t delta = time(NULL) - mNetInitTS; - -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netUpnpCheck() age: " << delta << std::endl; -#endif - - mNetMtx.unlock(); /* UNLOCK MUTEX */ - - struct sockaddr_storage extAddr; - int upnpState = netAssistFirewallActive(); - - if (((upnpState == 0) && (delta > (rstime_t)MAX_UPNP_INIT)) || - ((upnpState > 0) && (delta > (rstime_t)MAX_UPNP_COMPLETE))) - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netUpnpCheck() "; - std::cerr << "Upnp Check failed." << std::endl; -#endif - /* fallback to UDP startup */ - mNetMtx.lock(); /* LOCK MUTEX */ - - /* UPnP Failed us! */ - mNetStatus = RS_NET_EXT_SETUP; - mNetFlags.mUpnpOk = false; - - mNetMtx.unlock(); /* UNLOCK MUTEX */ - } - else if ((upnpState > 0) && netAssistExtAddress(extAddr)) - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netUpnpCheck() "; - std::cerr << "Upnp Check success state: " << upnpState << std::endl; -#endif - /* switch to UDP startup */ - mNetMtx.lock(); /* LOCK MUTEX */ - - /* Set Net Status flags .... - * we now have external upnp address. Golden! - * don't set netOk flag until have seen some traffic. - */ - if (sockaddr_storage_isValidNet(extAddr)) - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netUpnpCheck() "; - std::cerr << "UpnpAddr: " << sockaddr_storage_tostring(extAddr); - std::cerr << std::endl; -#endif - mNetFlags.mUpnpOk = true; - mNetFlags.mExtAddr = extAddr; - mNetFlags.mExtAddrOk = true; - mNetFlags.mExtAddrStableOk = true; - - mNetStatus = RS_NET_EXT_SETUP; - /* Fix netMode & Clear others! */ - mNetMode = RS_NET_MODE_TRY_UPNP | RS_NET_MODE_UPNP; - } - mNetMtx.unlock(); /* UNLOCK MUTEX */ - } - else - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netUpnpCheck() "; - std::cerr << "Upnp Check Continues: status: " << upnpState << std::endl; -#endif - } - -} - -class ZeroInt -{ - public: - ZeroInt() { n=0; } - uint32_t n ; -}; - -void p3NetMgrIMPL::netExtCheck() -{ -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck()" << std::endl; -#endif - bool netSetupDone = false; - - { - RS_STACK_MUTEX(mNetMtx); - - bool isStable = false; - sockaddr_storage tmpip; - - std::map address_votes; - - /* check for External Address */ - /* in order of importance */ - /* (1) UPnP -> which handles itself */ - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() Ext Not Ok" << std::endl; -#endif - /* net Assist */ - if ( netAssistExtAddress(tmpip) && - sockaddr_storage_isValidNet(tmpip) && - sockaddr_storage_ipv6_to_ipv4(tmpip) ) - { - if( !rsBanList || - rsBanList->isAddressAccepted( - tmpip, RSBANLIST_CHECKING_FLAGS_BLACKLIST ) ) - { - // must be stable??? - isStable = true; - mNetFlags.mExtAddrOk = true; - mNetFlags.mExtAddrStableOk = isStable; - address_votes[tmpip].n++ ; - std::cerr << __PRETTY_FUNCTION__ << " NetAssistAddress " - << " reported external address " - << sockaddr_storage_iptostring(tmpip) - << std::endl; - } - else - std::cerr << "(SS) netAssisExternalAddress returned banned " - << "own IP " << sockaddr_storage_iptostring(tmpip) - << " (banned). Rejecting." << std::endl; - } - } - - /* ask ExtAddrFinder */ - { - /* ExtAddrFinder */ - if (mUseExtAddrFinder) - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - RS_DBG("checking ExtAddrFinder"); -#endif - sockaddr_storage tmpip; - sockaddr_storage_copy( mLocalAddr, tmpip); // copies local port and correctly inits the IP family - - // Test for IPv4 first to be compatible with older versions. - if (mExtAddrFinder->hasValidIPV4(tmpip)) - { - sockaddr_storage_setport(tmpip, guessNewExtPort()); - - mNetFlags.mExtAddrOk = true; - - address_votes[tmpip].n++ ; - - /* XXX HACK TO FIX drbob: ALLOWING - * ExtAddrFinder -> ExtAddrStableOk = true - * (which it is not normally) */ - mNetFlags.mExtAddrStableOk = true; - - RS_DBG("Reported external IPv4 address ", sockaddr_storage_iptostring(tmpip)); - } - else if (mExtAddrFinder->hasValidIPV6(tmpip)) - { - sockaddr_storage_setport(tmpip, guessNewExtPort()); - - mNetFlags.mExtAddrOk = true; - - address_votes[tmpip].n++ ; - - /* XXX HACK TO FIX drbob: ALLOWING - * ExtAddrFinder -> ExtAddrStableOk = true - * (which it is not normally) */ - mNetFlags.mExtAddrStableOk = true; - - RS_DBG("Reported external IPv6 address ", sockaddr_storage_iptostring(tmpip)); - } - } - } - - /* also ask peer mgr. */ - if (mPeerMgr) - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() checking mPeerMgr" << std::endl; -#endif - uint8_t isstable; // unused - sockaddr_storage tmpaddr; - - if ( mPeerMgr->getExtAddressReportedByFriends(tmpaddr, isstable) && sockaddr_storage_ipv6_to_ipv4(tmpaddr) ) - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() Ext supplied by friends" << std::endl; -#endif - sockaddr_storage_setport(tmpaddr, guessNewExtPort()); - -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() "; - std::cerr << "ExtAddr: " << sockaddr_storage_tostring(tmpip); - std::cerr << std::endl; -#endif - - mNetFlags.mExtAddrOk = true; - mNetFlags.mExtAddrStableOk = isstable; - - address_votes[tmpaddr].n++; - - std::cerr << __PRETTY_FUNCTION__ << " PeerMgr reported external" - << " address " - << sockaddr_storage_iptostring(tmpaddr) << std::endl; - } -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - else - std::cerr << " No reliable address returned." << std::endl; -#endif - } - -#ifdef ALLOW_DHT_STUNNER - // (cyril) I disabled this because it's pretty dangerous. The DHT can report a wrong address quite easily - // if the other DHT peers are not collaborating. - // (sehraf) For the record: The udp stunner uses multiple (as for now: two) peers to ensure that the IP recieved is the correct one, see UdpStunner::locked_checkExternalAddress() - // Nevertheless this stays a more risky method to determine the external ip address. - - /* lastly ask the DhtStunner as fallback */ - if (address_votes.empty()) { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() Ext Not Ok, Checking DhtStunner" << std::endl; -#endif - uint8_t isstable = 0; - struct sockaddr_storage tmpaddr; - sockaddr_storage_clear(tmpaddr); - - if (mDhtStunner) - { - /* input network bits */ - if (mDhtStunner->getExternalAddr(tmpaddr, isstable)) - { - if((rsBanList == NULL) || rsBanList->isAddressAccepted(tmpaddr,RSBANLIST_CHECKING_FLAGS_BLACKLIST)) - { - // must be stable??? - isStable = (isstable == 1); - //mNetFlags.mExtAddr = tmpaddr; - mNetFlags.mExtAddrOk = true; - mNetFlags.mExtAddrStableOk = isStable; - - address_votes[tmpaddr].n++ ; -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::netExtCheck() From DhtStunner: "; - std::cerr << sockaddr_storage_tostring(tmpaddr); - std::cerr << " Stable: " << (uint32_t) isstable; - std::cerr << std::endl; -#endif - } - else - std::cerr << "(SS) DHTStunner returned wrong own IP " << sockaddr_storage_iptostring(tmpaddr) << " (banned). Rejecting." << std::endl; - } - } - } -#endif - - /* any other sources ??? */ - - /* finalise address */ - if (mNetFlags.mExtAddrOk) - { - // look at votes. - - std::cerr << "Figuring out ext addr from voting:" << std::endl; - uint32_t admax = 0 ; - - for(std::map::const_iterator it(address_votes.begin());it!=address_votes.end();++it) - { - std::cerr << " Vote: " << sockaddr_storage_iptostring(it->first) << " : " << it->second.n << " votes." ; - - if(it->second.n > admax) - { - mNetFlags.mExtAddr = it->first ; - admax = it->second.n ; - - std::cerr << " Kept!" << std::endl; - } - else - std::cerr << " Discarded." << std::endl; - } - -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() "; - std::cerr << "ExtAddr: " << sockaddr_storage_tostring(mNetFlags.mExtAddr); - std::cerr << std::endl; -#endif - //update ip address list - mExtAddr = mNetFlags.mExtAddr; - - mNetStatus = RS_NET_DONE; - netSetupDone = true; - -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() Ext Ok: RS_NET_DONE" << std::endl; -#endif - - - - if (!mNetFlags.mExtAddrStableOk) - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netUdpCheck() UDP Unstable :( "; - std::cerr << std::endl; - std::cerr << "p3NetMgrIMPL::netUdpCheck() We are unreachable"; - std::cerr << std::endl; - std::cerr << "netMode => RS_NET_MODE_UNREACHABLE"; - std::cerr << std::endl; -#endif - - // Due to the new UDP connections - we can still connect some of the time! - // So limit warning! - - //mNetMode &= ~(RS_NET_MODE_ACTUAL); - //mNetMode |= RS_NET_MODE_UNREACHABLE; - - /* send a system warning message */ - //pqiNotify *notify = getPqiNotify(); - //if (notify) - { - //std::string title = - // "Warning: Bad Firewall Configuration"; - - std::string msg; - msg += " **** WARNING **** \n"; - msg += "Retroshare has detected that you are behind"; - msg += " a restrictive Firewall\n"; - msg += "\n"; - msg += "You will have limited connectivity to other firewalled peers\n"; - msg += "\n"; - msg += "You can fix this by:\n"; - msg += " (1) opening an External Port\n"; - msg += " (2) enabling UPnP, or\n"; - msg += " (3) get a new (approved) Firewall/Router\n"; - - //notify->AddSysMessage(0, RS_SYS_WARNING, title, msg); - - std::cerr << msg << std::endl; - } - - } - - } - - if (mNetFlags.mExtAddrOk) - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() setting netAssistSetAddress()" << std::endl; -#endif - netAssistSetAddress(mNetFlags.mLocalAddr, mNetFlags.mExtAddr, mNetMode); - } - - /* flag unreachables! */ - if ((mNetFlags.mExtAddrOk) && (!mNetFlags.mExtAddrStableOk)) - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() Ext Unstable - Unreachable Check" << std::endl; -#endif - } - } - - if (netSetupDone) - { - RS_DBG("netSetupDone"); - - /* Setup NetStateBox with this info */ - updateNetStateBox_startup(); - - /* update PeerMgr with correct info */ - if (mPeerMgr) - { - mPeerMgr->UpdateOwnAddress(mLocalAddr, mExtAddr); - } - - /* inform DHT about our external IPV4 address, it doesn't support IPv6 for now.*/ - if(sockaddr_storage_ipv6_to_ipv4(mExtAddr)) - { - RsPeerId fakeId; - netAssistKnownPeer(fakeId, mExtAddr, NETASSIST_KNOWN_PEER_SELF | NETASSIST_KNOWN_PEER_ONLINE); - } - - RS_INFO("Network Setup Complete"); - } -} - -/********************************************************************************************** - ************************************** Interfaces ***************************************** - **********************************************************************************************/ - -bool p3NetMgrIMPL::checkNetAddress() -{ - bool addrChanged = false; - bool validAddr = false; - bool needOwnAddrUpdate = false; - - sockaddr_storage prefAddr; - sockaddr_storage oldAddr; - - if (mNetMode & RS_NET_MODE_TRY_LOOPBACK) - { - RsInfo() << __PRETTY_FUNCTION__ <<" network mode set to LOOPBACK," - << " forcing address to 127.0.0.1" << std::endl; - - sockaddr_storage_ipv4_aton(prefAddr, "127.0.0.1"); - validAddr = true; - } - else - { - /* TODO: Sat Oct 24 15:51:24 CEST 2015 The fact of having just one local - * address is a flawed assumption, this should be redesigned as soon as - * possible. It will require complete reenginering of the network layer - * code. */ - - /* For retro-compatibility strictly accept only IPv4 addresses here, - * IPv6 addresses are handled in a retro-compatible manner in - * p3PeerMgrIMPL::UpdateOwnAddress */ - std::vector addrs; - if (getLocalAddresses(addrs)) - { - for (auto it = addrs.begin(); it != addrs.end(); ++it) - { - sockaddr_storage& addr(*it); - if( sockaddr_storage_isValidNet(addr) && - !sockaddr_storage_isLoopbackNet(addr) && - !sockaddr_storage_isLinkLocalNet(addr) && - sockaddr_storage_ipv6_to_ipv4(addr) ) - { - prefAddr = addr; - validAddr = true; - break; - } - } - - /* If no satisfactory local address has been found yet relax and - * accept also link local addresses */ - if(!validAddr) for (auto it = addrs.begin(); it!=addrs.end(); ++it) - { - sockaddr_storage& addr(*it); - if( sockaddr_storage_isValidNet(addr) && - !sockaddr_storage_isLoopbackNet(addr) && - sockaddr_storage_ipv6_to_ipv4(addr) ) - { - prefAddr = addr; - validAddr = true; - break; - } - } - - /* If no satisfactory local address has been found yet relax and - * accept also loopback addresses */ - if(!validAddr) for (auto it = addrs.begin(); it!=addrs.end(); ++it) - { - sockaddr_storage& addr(*it); - if( sockaddr_storage_isValidNet(addr) && - sockaddr_storage_ipv6_to_ipv4(addr) ) - { - prefAddr = addr; - validAddr = true; - break; - } - } - } - } - - if (!validAddr) - { - RS_ERR("no valid local network address found. Report to developers."); - print_stacktrace(); - - return false; - } - - /* check addresses */ - { RS_STACK_MUTEX(mNetMtx); - - sockaddr_storage_copy(mLocalAddr, oldAddr); - addrChanged = !sockaddr_storage_sameip(prefAddr, mLocalAddr); - - // update address. - sockaddr_storage_copyip(mLocalAddr, prefAddr); - sockaddr_storage_copy(mLocalAddr, mNetFlags.mLocalAddr); - - if(sockaddr_storage_isLoopbackNet(mLocalAddr)) - mNetStatus = RS_NET_LOOPBACK; - - // Check if local port is valid, reset it if not - if (!sockaddr_storage_port(mLocalAddr)) - { - /* Using same port as external may make some NAT happier */ - uint16_t port = sockaddr_storage_port(mExtAddr); - - /* Avoid to automatically set a local port to a reserved one < 1024 - * that needs special permissions or root access. - * This do not impede the user to set a reserved port manually, - * which make sense in some cases. */ - - std::cerr << __PRETTY_FUNCTION__ << " local port is 0. Ext port is " << port ; - - while (port < 1025) - port = static_cast(RsRandom::random_u32()); - - std::cerr << " new ext port is " << port << ": using these for local/ext ports" << std::endl; - - sockaddr_storage_setport(mLocalAddr, port); - sockaddr_storage_setport(mExtAddr, port); // this accounts for when the port was updated - addrChanged = true; - } - - } // RS_STACK_MUTEX(mNetMtx); - - if (addrChanged) - { - RsInfo() << __PRETTY_FUNCTION__ << " local address changed, resetting network." << std::endl; - - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mNetworkEventCode = RsNetworkEventCode::LOCAL_IP_UPDATED; - ev->mIPAddress = sockaddr_storage_iptostring(mLocalAddr); - rsEvents->postEvent(ev); - } - - needOwnAddrUpdate = true; - - netReset(); - } - - if (mPeerMgr) - { - // Retrieve last known IP, if none, update own addresse to get current. - peerState ps; - mPeerMgr->getOwnNetStatus(ps); - needOwnAddrUpdate |= ps.ipAddrs.mLocal.mAddrs.empty(); - needOwnAddrUpdate |= ps.ipAddrs.mExt.mAddrs.empty(); - if (needOwnAddrUpdate) - { - mPeerMgr->UpdateOwnAddress(mLocalAddr, mExtAddr); - } - } - - return true; -} - - -/********************************************************************************************** - ************************************** Interfaces ***************************************** - **********************************************************************************************/ - -/* to allow resets of network stuff */ -void p3NetMgrIMPL::addNetListener(pqiNetListener *listener) -{ - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - mNetListeners.push_back(listener); -} - - - -bool p3NetMgrIMPL::setLocalAddress(const struct sockaddr_storage &addr) -{ - bool changed = false; - { - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - if (!sockaddr_storage_same(mLocalAddr, addr)) - { - changed = true; - } - - mLocalAddr = addr; - mPeerMgr->UpdateOwnAddress(mLocalAddr, mExtAddr); - } - - if (changed) - { -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::setLocalAddress() Calling NetReset" << std::endl; -#endif - rslog(RSL_WARNING, p3netmgrzone, "p3NetMgr::setLocalAddress() local address changed, resetting network"); - netReset(); - } - return true; -} -bool p3NetMgrIMPL::getExtAddress(struct sockaddr_storage& addr) -{ - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - - if(mNetFlags.mExtAddrOk) - { - addr = mNetFlags.mExtAddr ; - return true ; - } - else - return false ; -} - -bool p3NetMgrIMPL::setExtAddress(const struct sockaddr_storage &addr) -{ - bool changed = false; - { - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - if (!sockaddr_storage_same(mExtAddr, addr)) - { - changed = true; - } - - mExtAddr = addr; - mPeerMgr->UpdateOwnAddress(mLocalAddr, mExtAddr); - } - - if (changed) - { -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::setExtAddress() Calling NetReset" << std::endl; -#endif - - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mNetworkEventCode = RsNetworkEventCode::EXTERNAL_IP_UPDATED; - ev->mIPAddress = sockaddr_storage_iptostring(addr); - rsEvents->postEvent(ev); - } - - rslog(RSL_WARNING, p3netmgrzone, "p3NetMgr::setExtAddress() ext address changed, resetting network"); - netReset(); - } - return true; -} - -bool p3NetMgrIMPL::setNetworkMode(uint32_t netMode) -{ - uint32_t oldNetMode; - { - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - /* only change TRY flags */ - - oldNetMode = mNetMode; - -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::setNetworkMode()"; - std::cerr << " Existing netMode: " << mNetMode; - std::cerr << " Input netMode: " << netMode; - std::cerr << std::endl; -#endif - mNetMode &= ~(RS_NET_MODE_TRYMODE); - - switch(netMode & RS_NET_MODE_ACTUAL) - { - case RS_NET_MODE_EXT: - mNetMode |= RS_NET_MODE_TRY_EXT; - break; - case RS_NET_MODE_UPNP: - mNetMode |= RS_NET_MODE_TRY_UPNP; - break; - case RS_NET_MODE_HIDDEN: - mNetMode |= RS_NET_MODE_TRY_LOOPBACK; - break; - default: - case RS_NET_MODE_UDP: - mNetMode |= RS_NET_MODE_TRY_UDP; - break; - } - } - - - if ((netMode & RS_NET_MODE_ACTUAL) != (oldNetMode & RS_NET_MODE_ACTUAL)) - { -#ifdef NETMGR_DEBUG_RESET - std::cerr << "p3NetMgrIMPL::setNetworkMode() Calling NetReset" << std::endl; -#endif - rslog(RSL_WARNING, p3netmgrzone, "p3NetMgr::setNetworkMode() Net Mode changed, resetting network"); - netReset(); - } - return true; -} - - -bool p3NetMgrIMPL::setVisState(uint16_t vs_disc, uint16_t vs_dht) -{ - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - mVsDisc = vs_disc; - mVsDht = vs_dht; - - /* if we've started up - then tweak Dht On/Off */ - if (mNetStatus != RS_NET_UNKNOWN) - { - enableNetAssistConnect(mVsDht != RS_VS_DHT_OFF); - } - - return true; -} - - -/********************************************************************************************** - ************************************** Interfaces ***************************************** - **********************************************************************************************/ - -void p3NetMgrIMPL::addNetAssistFirewall(uint32_t id, pqiNetAssistFirewall *fwAgent) -{ - mFwAgents[id] = fwAgent; -} - - -bool p3NetMgrIMPL::enableNetAssistFirewall(bool on) -{ - std::map::iterator it; - for(it = mFwAgents.begin(); it != mFwAgents.end(); ++it) - { - (it->second)->enable(on); - } - return true; -} - - -bool p3NetMgrIMPL::netAssistFirewallEnabled() -{ - std::map::iterator it; - for(it = mFwAgents.begin(); it != mFwAgents.end(); ++it) - { - if ((it->second)->getEnabled()) - { - return true; - } - } - return false; -} - -bool p3NetMgrIMPL::netAssistFirewallActive() -{ - std::map::iterator it; - for(it = mFwAgents.begin(); it != mFwAgents.end(); ++it) - { - if ((it->second)->getActive()) - { - return true; - } - } - return false; -} - -bool p3NetMgrIMPL::netAssistFirewallShutdown() -{ - std::map::iterator it; - for(it = mFwAgents.begin(); it != mFwAgents.end(); ++it) - { - (it->second)->shutdown(); - } - return true; -} - -bool p3NetMgrIMPL::netAssistFirewallPorts(uint16_t iport, uint16_t eport) -{ - std::map::iterator it; - for(it = mFwAgents.begin(); it != mFwAgents.end(); ++it) - { - (it->second)->setInternalPort(iport); - (it->second)->setExternalPort(eport); - } - return true; -} - - -bool p3NetMgrIMPL::netAssistExtAddress(struct sockaddr_storage &extAddr) -{ - std::map::iterator it; - for(it = mFwAgents.begin(); it != mFwAgents.end(); ++it) - { - if ((it->second)->getActive()) - { - if ((it->second)->getExternalAddress(extAddr)) - { - return true; - } - } - } - return false; -} - - -void p3NetMgrIMPL::addNetAssistConnect(uint32_t id, pqiNetAssistConnect *dht) -{ - mDhts[id] = dht; -} - -bool p3NetMgrIMPL::enableNetAssistConnect(bool on) -{ - -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::enableNetAssistConnect(" << on << ")"; - std::cerr << std::endl; -#endif - - std::map::iterator it; - for(it = mDhts.begin(); it != mDhts.end(); ++it) - { - (it->second)->enable(on); - } - return true; -} - -bool p3NetMgrIMPL::netAssistConnectEnabled() -{ - std::map::iterator it; - for(it = mDhts.begin(); it != mDhts.end(); ++it) - { - if ((it->second)->getEnabled()) - { -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::netAssistConnectEnabled() YES"; - std::cerr << std::endl; -#endif - - return true; - } - } - -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::netAssistConnectEnabled() NO"; - std::cerr << std::endl; -#endif - - return false; -} - -bool p3NetMgrIMPL::netAssistConnectActive() -{ - std::map::iterator it; - for(it = mDhts.begin(); it != mDhts.end(); ++it) - { - if ((it->second)->getActive()) - - { -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::netAssistConnectActive() ACTIVE"; - std::cerr << std::endl; -#endif - - return true; - } - } - -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::netAssistConnectActive() INACTIVE"; - std::cerr << std::endl; -#endif - - return false; -} - -bool p3NetMgrIMPL::netAssistConnectStats(uint32_t &netsize, uint32_t &localnetsize) -{ - std::map::iterator it; - for(it = mDhts.begin(); it != mDhts.end(); ++it) - { - if (((it->second)->getActive()) && ((it->second)->getNetworkStats(netsize, localnetsize))) - - { -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::netAssistConnectStats("; - std::cerr << netsize << ", " << localnetsize << ")"; - std::cerr << std::endl; -#endif - - return true; - } - } - -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::netAssistConnectStats() INACTIVE"; - std::cerr << std::endl; -#endif - - return false; -} - -bool p3NetMgrIMPL::netAssistConnectShutdown() -{ -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::netAssistConnectShutdown()"; - std::cerr << std::endl; -#endif - - std::map::iterator it; - for(it = mDhts.begin(); it != mDhts.end(); ++it) - { - (it->second)->shutdown(); - } - return true; -} - -bool p3NetMgrIMPL::netAssistFriend(const RsPeerId &id, bool on) -{ - std::map::iterator it; - -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::netAssistFriend(" << id << ", " << on << ")"; - std::cerr << std::endl; -#endif - - for(it = mDhts.begin(); it != mDhts.end(); ++it) - { - if (on) - (it->second)->findPeer(id); - else - (it->second)->dropPeer(id); - } - return true; -} - - -bool p3NetMgrIMPL::netAssistKnownPeer(const RsPeerId &id, const struct sockaddr_storage &addr, uint32_t flags) -{ - std::map::iterator it; - -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::netAssistKnownPeer(" << id << ")"; - std::cerr << std::endl; -#endif - - for(it = mDhts.begin(); it != mDhts.end(); ++it) - { - (it->second)->addKnownPeer(id, addr, flags); - } - return true; -} - -bool p3NetMgrIMPL::netAssistBadPeer(const struct sockaddr_storage &addr, uint32_t reason, uint32_t flags, uint32_t age) -{ - std::map::iterator it; - -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::netAssistBadPeer(" << sockaddr_storage_iptostring(addr) << ")"; - std::cerr << std::endl; -#endif - - for(it = mDhts.begin(); it != mDhts.end(); ++it) - { - (it->second)->addBadPeer(addr, reason, flags, age); - } - return true; -} - - -bool p3NetMgrIMPL::netAssistAttach(bool on) -{ - std::map::iterator it; - -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::netAssistAttach(" << on << ")"; - std::cerr << std::endl; -#endif - - for(it = mDhts.begin(); it != mDhts.end(); ++it) - { - (it->second)->setAttachMode(on); - } - return true; -} - - - -bool p3NetMgrIMPL::netAssistStatusUpdate(const RsPeerId &id, int state) -{ - std::map::iterator it; - -#ifdef NETMGR_DEBUG - std::cerr << "p3NetMgrIMPL::netAssistStatusUpdate(" << id << ", " << state << ")"; - std::cerr << std::endl; -#endif - - for(it = mDhts.begin(); it != mDhts.end(); ++it) - { - (it->second)->ConnectionFeedback(id, state); - } - return true; -} - - -bool p3NetMgrIMPL::netAssistSetAddress( const struct sockaddr_storage & /*laddr*/, - const struct sockaddr_storage & /*eaddr*/, - uint32_t /*mode*/) -{ -#if 0 - std::map::iterator it; - for(it = mDhts.begin(); it != mDhts.end(); ++it) - { - (it->second)->setExternalInterface(laddr, eaddr, mode); - } -#endif - return true; -} - -void p3NetMgrIMPL::netAssistTick() -{ - std::map::iterator it; - for(it = mDhts.begin(); it != mDhts.end(); ++it) - { - (it->second)->tick(); - } - - std::map::iterator fit; - for(fit = mFwAgents.begin(); fit != mFwAgents.end(); ++fit) - { - (fit->second)->tick(); - } - return; -} - - - -/********************************************************************** - ********************************************************************** - ******************** Network State *********************************** - ********************************************************************** - **********************************************************************/ - -bool p3NetMgrIMPL::getUPnPState() -{ - return netAssistFirewallActive(); -} - -bool p3NetMgrIMPL::getUPnPEnabled() -{ - return netAssistFirewallEnabled(); -} - -bool p3NetMgrIMPL::getDHTEnabled() -{ - return netAssistConnectEnabled(); -} - - -void p3NetMgrIMPL::getNetStatus(pqiNetStatus &status) -{ - /* cannot lock local stack, then call DHT... as this can cause lock up */ - /* must extract data... then update mNetFlags */ - - bool dhtOk = netAssistConnectActive(); - uint32_t netsize = 0, rsnetsize = 0; - netAssistConnectStats(netsize, rsnetsize); - - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - - /* quick update of the stuff that can change! */ - mNetFlags.mDhtOk = dhtOk; - mNetFlags.mDhtNetworkSize = netsize; - mNetFlags.mDhtRsNetworkSize = rsnetsize; - - status = mNetFlags; -} - - - - - - - - - -/********************************************************************************************** - ************************************** ExtAddrFinder ***************************************** - **********************************************************************************************/ - -bool p3NetMgrIMPL::getIPServersEnabled() -{ - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - return mUseExtAddrFinder; -} - -void p3NetMgrIMPL::getIPServersList(std::list& ip_servers) -{ - mExtAddrFinder->getIPServersList(ip_servers); -} - -void p3NetMgrIMPL::getCurrentExtIPList(std::list& ip_list) -{ - ip_list.clear(); - sockaddr_storage addr; - if(mExtAddrFinder->hasValidIPV4(addr)) - ip_list.push_back(sockaddr_storage_iptostring(addr)); - if(mExtAddrFinder->hasValidIPV6(addr)) - ip_list.push_back(sockaddr_storage_iptostring(addr)); -} - -void p3NetMgrIMPL::setIPServersEnabled(bool b) -{ - if (mUseExtAddrFinder != b) - { - mExtAddrFinder->reset(true); - if (b) - mExtAddrFinder->start_request(); - } - - { - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - mUseExtAddrFinder = b; - } - -#ifdef NETMGR_DEBUG - RS_DBG("set mUseExtAddrFinder to ", b); -#endif - -} - - - -/********************************************************************************************** - ************************************** NetStateBox ****************************************** - **********************************************************************************************/ - -RsNetState p3NetMgrIMPL::getNetStateMode() -{ - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - return mNetStateBox.getNetStateMode(); -} - -RsNetworkMode p3NetMgrIMPL::getNetworkMode() -{ - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - return mNetStateBox.getNetworkMode(); -} - -RsNatTypeMode p3NetMgrIMPL::getNatTypeMode() -{ - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - return mNetStateBox.getNatTypeMode(); -} - -RsNatHoleMode p3NetMgrIMPL::getNatHoleMode() -{ - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - return mNetStateBox.getNatHoleMode(); -} - -RsConnectModes p3NetMgrIMPL::getConnectModes() -{ - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - return mNetStateBox.getConnectModes(); -} - - -/* These are the regular updates from Dht / Stunners */ -void p3NetMgrIMPL::updateNetStateBox_temporal() -{ -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_temporal() "; - std::cerr << std::endl; -#endif - struct sockaddr_storage tmpaddr; - sockaddr_storage_clear(tmpaddr); - -#ifdef RS_USE_DHT_STUNNER - uint8_t isstable = 0; - - if (mDhtStunner) - { - - /* input network bits */ - if (mDhtStunner->getExternalAddr(tmpaddr, isstable)) - { - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - mNetStateBox.setAddressStunDht(tmpaddr, isstable); - -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_temporal() DhtStunner: "; - std::cerr << sockaddr_storage_tostring(tmpaddr); - std::cerr << " Stable: " << (uint32_t) isstable; - std::cerr << std::endl; -#endif - - } - } - - if (mProxyStunner) - { - - /* input network bits */ - if (mProxyStunner->getExternalAddr(tmpaddr, isstable)) - { - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - mNetStateBox.setAddressStunProxy(tmpaddr, isstable); - -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_temporal() ProxyStunner: "; - std::cerr << sockaddr_storage_tostring(tmpaddr); - std::cerr << " Stable: " << (uint32_t) isstable; - std::cerr << std::endl; -#endif - - } - } -#endif // RS_USE_DHT_STUNNER - - - { - bool dhtOn = netAssistConnectEnabled(); - bool dhtActive = netAssistConnectActive(); - - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - mNetStateBox.setDhtState(dhtOn, dhtActive); - } - - - /* now we check if a WebIP address is required? */ - -#ifdef NETMGR_DEBUG_STATEBOX - { - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - - auto netstate = mNetStateBox.getNetStateMode(); - auto netMode = mNetStateBox.getNetworkMode(); - auto natType = mNetStateBox.getNatTypeMode(); - auto natHole = mNetStateBox.getNatHoleMode(); - auto connect = mNetStateBox.getConnectModes(); -#ifdef SUSPENDED - auto netstatestr = NetStateNetStateString(netstate); - auto connectstr = NetStateConnectModesString(connect); - auto natholestr = NetStateNatHoleString(natHole); - auto nattypestr = NetStateNatTypeString(natType); - auto netmodestr = NetStateNetworkModeString(netMode); - - std::cerr << "p3NetMgrIMPL::updateNetStateBox_temporal() NetStateBox Thinking"; - std::cerr << std::endl; - std::cerr << "\tNetState: " << netstatestr; - std::cerr << std::endl; - std::cerr << "\tConnectModes: " << connectstr; - std::cerr << std::endl; - std::cerr << "\tNetworkMode: " << netmodestr; - std::cerr << std::endl; - std::cerr << "\tNatHole: " << natholestr; - std::cerr << std::endl; - std::cerr << "\tNatType: " << nattypestr; - std::cerr << std::endl; -#endif - - } -#endif - - updateNatSetting(); - -} - -#define NET_STUNNER_PERIOD_FAST (-1) // default of Stunner. -#define NET_STUNNER_PERIOD_SLOW (120) // This needs to be as small Routers will allow... try 2 minutes. -// FOR TESTING ONLY. -//#define NET_STUNNER_PERIOD_SLOW (60) // 3 minutes. - -void p3NetMgrIMPL::updateNatSetting() -{ - bool updateRefreshRate = false; - RsNatTypeMode natType = RsNatTypeMode::UNKNOWN; - RsNatHoleMode natHole = RsNatHoleMode::UNKNOWN; - { - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - - natType = mNetStateBox.getNatTypeMode(); - natHole = mNetStateBox.getNatHoleMode(); - if ((natType != mOldNatType) || (natHole != mOldNatHole)) - { - mOldNatType = natType; - mOldNatHole = natHole; - updateRefreshRate = true; - -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_temporal() NatType Change!"; -// std::cerr << "\tNatType: " << NetStateNatTypeString(natType); -// std::cerr << "\tNatHole: "k << NetStateNatHoleString(natHole); - - std::cerr << std::endl; -#endif - - - } - } - - - // MUST also use this chance to set ATTACH flag for DHT. - if (updateRefreshRate) - { -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_temporal() Updating Refresh Rate, based on changed NatType"; - std::cerr << std::endl; -#endif - -#ifdef RS_USE_DHT_STUNNER - if (mProxyStunner) { - switch(natType) - { - case RsNatTypeMode::RESTRICTED_CONE: - { - if ((natHole == RsNatHoleMode::NONE) || (natHole == RsNatHoleMode::UNKNOWN)) - { - mProxyStunner->setRefreshPeriod(NET_STUNNER_PERIOD_FAST); - } - else - { - mProxyStunner->setRefreshPeriod(NET_STUNNER_PERIOD_SLOW); - } - break; - } - case RsNatTypeMode::NONE: - case RsNatTypeMode::UNKNOWN: - case RsNatTypeMode::SYMMETRIC: - case RsNatTypeMode::DETERM_SYM: - case RsNatTypeMode::FULL_CONE: - case RsNatTypeMode::OTHER: - - mProxyStunner->setRefreshPeriod(NET_STUNNER_PERIOD_SLOW); - break; - } - } -#endif // RS_USE_DHT_STUNNER - - /* This controls the Attach mode of the DHT... - * which effectively makes the DHT "attach" to Open Nodes. - * So that messages can get through. - * We only want to be attached - if we don't have a stable DHT port. - */ - if ((natHole == RsNatHoleMode::NONE) || (natHole == RsNatHoleMode::UNKNOWN)) - { - switch(natType) - { - /* switch to attach mode if we have a bad firewall */ - case RsNatTypeMode::UNKNOWN: - case RsNatTypeMode::SYMMETRIC: - case RsNatTypeMode::RESTRICTED_CONE: - case RsNatTypeMode::DETERM_SYM: - case RsNatTypeMode::OTHER: - netAssistAttach(true); - - break; - /* switch off attach mode if we have a nice firewall */ - case RsNatTypeMode::NONE: - case RsNatTypeMode::FULL_CONE: - netAssistAttach(false); - break; - } - } - else - { - // Switch off Firewall Mode (Attach) - netAssistAttach(false); - } - } -} - - - -void p3NetMgrIMPL::updateNetStateBox_startup() -{ -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_startup() "; - std::cerr << std::endl; -#endif - { - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - - /* fill in the data */ - struct sockaddr_storage tmpip; - - /* net Assist */ - if (netAssistExtAddress(tmpip)) - { - -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_startup() "; - std::cerr << "Ext supplied from netAssistExternalAddress()"; - std::cerr << std::endl; -#endif - - if (sockaddr_storage_isValidNet(tmpip)) - { -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_startup() "; - std::cerr << "netAssist Returned: " << sockaddr_storage_tostring(tmpip); - std::cerr << std::endl; -#endif - mNetStateBox.setAddressUPnP(true, tmpip); - } - else - { - mNetStateBox.setAddressUPnP(false, tmpip); -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_startup() "; - std::cerr << "ERROR Bad Address supplied from netAssistExternalAddress()"; - std::cerr << std::endl; -#endif - } - } - else - { -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_startup() "; - std::cerr << " netAssistExtAddress() is not active"; - std::cerr << std::endl; -#endif - mNetStateBox.setAddressUPnP(false, tmpip); - } - - - /* ExtAddrFinder */ - if (mUseExtAddrFinder) - { - tmpip = mLocalAddr; - bool extFinderOk = mExtAddrFinder->hasValidIPV4(tmpip); - - if (extFinderOk) - { - sockaddr_storage_setport(tmpip, guessNewExtPort()); - -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_startup() "; - std::cerr << "ExtAddrFinder Returned: " << sockaddr_storage_iptostring(tmpip); - std::cerr << std::endl; -#endif - - mNetStateBox.setAddressWebIP(true, tmpip); - } - else - { - mNetStateBox.setAddressWebIP(false, tmpip); -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_startup() "; - std::cerr << " ExtAddrFinder hasn't found an address yet"; - std::cerr << std::endl; -#endif - } - } - else - { -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::updateNetStateBox_startup() "; - std::cerr << " ExtAddrFinder is not active"; - std::cerr << std::endl; -#endif - mNetStateBox.setAddressWebIP(false, tmpip); - } - - - /* finally - if the user has set Forwarded, pass it on */ - if (mNetMode & RS_NET_MODE_TRY_EXT) - { - mNetStateBox.setPortForwarded(true, 0); // Port unknown for now. - } - } -} - -void p3NetMgrIMPL::updateNetStateBox_reset() -{ - { - RS_STACK_MUTEX(mNetMtx); /****** STACK LOCK MUTEX *******/ - - mNetStateBox.reset(); - - mOldNatHole = RsNatHoleMode::UNKNOWN; - mOldNatType = RsNatTypeMode::UNKNOWN; - - } -} - -p3NetMgr::~p3NetMgr() = default; -pqiNetAssist::~pqiNetAssist() = default; -pqiNetAssistPeerShare::~pqiNetAssistPeerShare() = default; -pqiNetAssistConnect::~pqiNetAssistConnect() = default; diff --git a/libretroshare/src/pqi/p3netmgr.h b/libretroshare/src/pqi/p3netmgr.h deleted file mode 100644 index e7b341098..000000000 --- a/libretroshare/src/pqi/p3netmgr.h +++ /dev/null @@ -1,333 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3netmgr.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2007-2008 Robert Fernie * - * Copyright (C) 2015-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include "pqi/pqimonitor.h" -#include "pqi/pqiipset.h" -#include "pqi/pqiassist.h" -#include "pqi/pqinetstatebox.h" -#include "pqi/p3cfgmgr.h" -#include "util/rsthreads.h" -#include "util/rsdebug.h" - -class ExtAddrFinder ; -class DNSResolver ; - - /* RS_VIS_STATE_XXXX - * determines how public this peer wants to be... - * - * STD = advertise to Peers / DHT checking etc - * GRAY = share with friends / but not DHT - * DARK = hidden from all - * BROWN? = hidden from friends / but on DHT - */ - - - -struct pqiNetStatus -{ - pqiNetStatus(); - - bool mExtAddrOk; // have external address. - bool mExtAddrStableOk; // stable external address. - bool mUpnpOk; // upnp is ok. - bool mDhtOk; // dht is ok. - - uint32_t mDhtNetworkSize; - uint32_t mDhtRsNetworkSize; - - struct sockaddr_storage mLocalAddr; // percieved ext addr. - struct sockaddr_storage mExtAddr; // percieved ext addr. - - bool mResetReq; // Not Used yet!. - - void print(std::ostream &out); -}; - -class p3PeerMgr; -class p3LinkMgr; - -class p3PeerMgrIMPL; -class p3LinkMgrIMPL; - -class rsUdpStack; -class UdpStunner; -class p3BitDht; -class UdpRelayReceiver; - - -#define NETMGR_DHT_FEEDBACK_CONNECTED 0x0001 -#define NETMGR_DHT_FEEDBACK_CONN_FAILED 0x0002 -#define NETMGR_DHT_FEEDBACK_CONN_CLOSED 0x0003 - - -/********** - * p3NetMgr Interface.... - * This allows a drop-in replacement for testing. - */ - -class p3NetMgr -{ -public: - - /*************** External Control ****************/ - - // Setup Network State. -virtual bool setNetworkMode(uint32_t netMode) = 0; -virtual bool setVisState(uint16_t vs_disc, uint16_t vs_dht) = 0; - - // Switch DHT On/Off. -virtual bool netAssistFriend(const RsPeerId &id, bool on) = 0; -virtual bool netAssistKnownPeer(const RsPeerId &id, const struct sockaddr_storage &addr, uint32_t flags) = 0; -virtual bool netAssistBadPeer(const struct sockaddr_storage &addr, uint32_t reason, uint32_t flags, uint32_t age) = 0; -virtual bool netAssistStatusUpdate(const RsPeerId &id, int mode) = 0; - - /* Get Network State */ -virtual RsNetState getNetStateMode() = 0; -virtual RsNetworkMode getNetworkMode() = 0; -virtual RsNatTypeMode getNatTypeMode() = 0; -virtual RsNatHoleMode getNatHoleMode() = 0; -virtual RsConnectModes getConnectModes() = 0; - - /* Shut It Down! */ -virtual bool shutdown() = 0; /* blocking shutdown call */ - - /************* DEPRECIATED FUNCTIONS (TO REMOVE) ********/ - - // THESE SHOULD BE MOVED TO p3PeerMgr (as it controls the config). - // The functional object should be transformed into a NetAssistFirewall object. - // ONLY USED by p3peers.cc & p3peermgr.cc -virtual bool getIPServersEnabled() = 0; -virtual void setIPServersEnabled(bool b) = 0; -virtual void getIPServersList(std::list& ip_servers) = 0; -virtual void getCurrentExtIPList(std::list& ip_list) = 0; - - // ONLY USED by p3face-config.cc WHICH WILL BE REMOVED. -virtual void getNetStatus(pqiNetStatus &status) = 0; -virtual bool getUPnPState() = 0; -virtual bool getUPnPEnabled() = 0; -virtual bool getDHTEnabled() = 0; - - virtual ~p3NetMgr(); -}; - - -class p3NetMgrIMPL: public p3NetMgr -{ -public: - - p3NetMgrIMPL(); - -/************************************************************************************************/ -/* EXTERNAL INTERFACE */ -/************************************************************************************************/ - - /*************** External Control ****************/ - - // Setup Network State. -virtual bool setNetworkMode(uint32_t netMode); -virtual bool setVisState(uint16_t vs_disc, uint16_t vs_dht); - - // Switch DHT On/Off. -virtual bool netAssistFriend(const RsPeerId &id, bool on); -virtual bool netAssistKnownPeer(const RsPeerId &id, const struct sockaddr_storage &addr, uint32_t flags); -virtual bool netAssistBadPeer(const struct sockaddr_storage &addr, uint32_t reason, uint32_t flags, uint32_t age); -virtual bool netAssistStatusUpdate(const RsPeerId &id, int mode); - - /* Get Network State */ -virtual RsNetState getNetStateMode(); -virtual RsNetworkMode getNetworkMode(); -virtual RsNatTypeMode getNatTypeMode(); -virtual RsNatHoleMode getNatHoleMode(); -virtual RsConnectModes getConnectModes(); - - /* Shut It Down! */ -virtual bool shutdown(); /* blocking shutdown call */ - - /************* DEPRECIATED FUNCTIONS (TO REMOVE) ********/ - - // THESE SHOULD BE MOVED TO p3PeerMgr (as it controls the config). - // The functional object should be transformed into a NetAssistFirewall object. - // ONLY USED by p3peers.cc & p3peermgr.cc -virtual bool getIPServersEnabled(); -virtual void setIPServersEnabled(bool b); -virtual void getIPServersList(std::list& ip_servers); -virtual void getCurrentExtIPList(std::list& ip_list); - - // ONLY USED by p3face-config.cc WHICH WILL BE REMOVED. -virtual void getNetStatus(pqiNetStatus &status); -virtual bool getUPnPState(); -virtual bool getUPnPEnabled(); -virtual bool getDHTEnabled(); - -/************************************************************************************************/ -/* Extra IMPL Functions (used by p3PeerMgr, p3NetMgr + Setup) */ -/************************************************************************************************/ - -void setManagers(p3PeerMgr *peerMgr, p3LinkMgr *linkMgr); -#ifdef RS_USE_DHT_STUNNER -void setAddrAssist(pqiAddrAssist *dhtStun, pqiAddrAssist *proxyStun); -#endif // RS_USE_DHT_STUNNER - -void tick(); - - // THESE MIGHT BE ADDED TO INTERFACE. -bool setLocalAddress(const struct sockaddr_storage &addr); -bool setExtAddress(const struct sockaddr_storage &addr); -bool getExtAddress(sockaddr_storage &addr); - - /*************** Setup ***************************/ -void addNetAssistConnect(uint32_t type, pqiNetAssistConnect *); -void addNetAssistFirewall(uint32_t type, pqiNetAssistFirewall *); - -void addNetListener(pqiNetListener *listener); - - // SHOULD MAKE THIS PROTECTED. -bool checkNetAddress(); /* check our address is sensible */ - -protected: - /****************** Internal Interface *******************/ -bool enableNetAssistFirewall(bool on); -bool netAssistFirewallEnabled(); -bool netAssistFirewallActive(); -bool netAssistFirewallShutdown(); - -bool enableNetAssistConnect(bool on); -bool netAssistConnectEnabled(); -bool netAssistConnectActive(); -bool netAssistConnectShutdown(); -bool netAssistConnectStats(uint32_t &netsize, uint32_t &localnetsize); - -void netAssistTick(); - -/* Assist Firewall */ -bool netAssistExtAddress(struct sockaddr_storage &extAddr); -bool netAssistFirewallPorts(uint16_t iport, uint16_t eport); - - /* Assist Connect */ -//virtual bool netAssistFriend(std::string id, bool on); (PUBLIC) -bool netAssistSetAddress(const struct sockaddr_storage &laddr, - const struct sockaddr_storage &eaddr, - uint32_t mode); - -bool netAssistAttach(bool on); - - - /* Internal Functions */ -void netReset(); - -void statusTick(); -void netStatusTick(); -void netStartup(); - - /* startup the bits */ -void netDhtInit(); -void netUdpInit(); -void netStunInit(); - - - -void netInit(); - -void netExtInit(); -void netExtCheck(); - -void netUpnpInit(); -void netUpnpCheck(); - -void netUnreachableCheck(); - - - /* net state via NetStateBox */ -void updateNetStateBox_temporal(); -void updateNetStateBox_startup(); -void updateNetStateBox_reset(); - void updateNatSetting(); - - /** Conservatively guess new external port, previous approach (aka always - * reset it to local port) break setups where external manually - * forwarded port is different then local port. A common case is having - * SSLH listening on port 80 on the router with public IP forwanding - * plain HTTP connections to a web server and --anyprot connections to - * retroshare to make censor/BOFH/bad firewall life a little more - * difficult */ - uint16_t guessNewExtPort() - { - uint16_t newExtPort = sockaddr_storage_port(mExtAddr); - if(!newExtPort) newExtPort = sockaddr_storage_port(mLocalAddr); - return newExtPort; - } - -private: - // These should have there own Mutex Protection, - ExtAddrFinder *mExtAddrFinder ; - - /* These are considered static from a MUTEX perspective */ - std::map mFwAgents; - std::map mDhts; - - std::list mNetListeners; - - p3PeerMgr *mPeerMgr; - p3LinkMgr *mLinkMgr; - - //p3BitDht *mBitDht; -#ifdef RS_USE_DHT_STUNNER - pqiAddrAssist *mDhtStunner = nullptr; - pqiAddrAssist *mProxyStunner = nullptr; -#endif // RS_USE_DHT_STUNNER - - RsMutex mNetMtx; /* protects below */ - -void netStatusReset_locked(); - - // TODO: Sat Oct 24 15:51:24 CEST 2015 The fact of having just two possible address is a flawed assumption, this should be redesigned soon. - struct sockaddr_storage mLocalAddr; - struct sockaddr_storage mExtAddr; - - uint32_t mNetMode; - uint16_t mVsDisc; - uint16_t mVsDht; - - rstime_t mNetInitTS; - uint32_t mNetStatus; - - bool mStatusChanged; - - bool mUseExtAddrFinder; - rstime_t mNetExtAddrFinderTs; - - /* network status flags (read by rsiface) */ - pqiNetStatus mNetFlags; - pqiNetStatus mOldNetFlags; - - - // Improved NetStatusBox, which uses the Stunners! - pqiNetStateBox mNetStateBox; - - rstime_t mDoNotNetCheckUntilTs; - RsNatTypeMode mOldNatType; - RsNatHoleMode mOldNatHole; - - RS_SET_CONTEXT_DEBUG_LEVEL(2) -}; diff --git a/libretroshare/src/pqi/p3notify.cc b/libretroshare/src/pqi/p3notify.cc deleted file mode 100644 index 772a7e9bb..000000000 --- a/libretroshare/src/pqi/p3notify.cc +++ /dev/null @@ -1,314 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3notify.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2007-2008 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "pqi/p3notify.h" -#include -#include - -RsNotify *rsNotify = NULL ; - -/* Output for retroshare-gui */ -bool p3Notify::NotifySysMessage(uint32_t &sysid, uint32_t &type, - std::string &title, std::string &msg) -{ - RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ - if (pendingSysMsgs.size() > 0) - { - p3NotifySysMsg smsg = pendingSysMsgs.front(); - pendingSysMsgs.pop_front(); - - sysid = smsg.sysid; - type = smsg.type; - title = smsg.title; - msg = smsg.msg; - - return true; - } - - return false; -} - - /* Output for retroshare-gui */ -bool p3Notify::NotifyLogMessage(uint32_t &sysid, uint32_t &type, - std::string &title, std::string &msg) -{ - RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ - if (pendingLogMsgs.size() > 0) - { - p3NotifyLogMsg smsg = pendingLogMsgs.front(); - pendingLogMsgs.pop_front(); - - sysid = smsg.sysid; - type = smsg.type; - title = smsg.title; - msg = smsg.msg; - - return true; - } - - return false; -} - - -bool p3Notify::NotifyPopupMessage(uint32_t &ptype, std::string &name, std::string &title, std::string &msg) -{ - RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ - if (pendingPopupMsgs.size() > 0) - { - p3NotifyPopupMsg pmsg = pendingPopupMsgs.front(); - pendingPopupMsgs.pop_front(); - - ptype = pmsg.type; - name = pmsg.name; - title = pmsg.title; - msg = pmsg.msg; - - return true; - } - - return false; -} - - - /* Control over Messages */ -bool p3Notify::GetSysMessageList(std::map &list) -{ - (void) list; /* suppress unused parameter warning */ - return false; -} - -bool p3Notify::GetPopupMessageList(std::map &list) -{ - (void) list; /* suppress unused parameter warning */ - return false; -} - - -bool p3Notify::SetSysMessageMode(uint32_t sysid, uint32_t mode) -{ - (void) sysid; /* suppress unused parameter warning */ - (void) mode; /* suppress unused parameter warning */ - return false; -} - -bool p3Notify::SetPopupMessageMode(uint32_t ptype, uint32_t mode) -{ - (void) ptype; /* suppress unused parameter warning */ - (void) mode; /* suppress unused parameter warning */ - return false; -} - - - /* Input from libretroshare */ -bool p3Notify::AddPopupMessage(uint32_t ptype, const std::string& name, const std::string& title, const std::string& msg) -{ - RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ - - p3NotifyPopupMsg pmsg; - - pmsg.type = ptype; - pmsg.name = name; - pmsg.title = title; - pmsg.msg = msg; - - pendingPopupMsgs.push_back(pmsg); - - return true; -} - - -bool p3Notify::AddSysMessage(uint32_t sysid, uint32_t type, const std::string& title, const std::string& msg) -{ - RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ - - p3NotifySysMsg smsg; - - smsg.sysid = sysid; - smsg.type = type; - smsg.title = title; - smsg.msg = msg; - - pendingSysMsgs.push_back(smsg); - - return true; -} - -bool p3Notify::AddLogMessage(uint32_t sysid, uint32_t type, const std::string& title, const std::string& msg) -{ - RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ - - p3NotifyLogMsg smsg; - - smsg.sysid = sysid; - smsg.type = type; - smsg.title = title; - smsg.msg = msg; - - pendingLogMsgs.push_back(smsg); - - return true; -} - - -bool p3Notify::GetFeedItem(RsFeedItem &item) -{ - RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ - if (pendingNewsFeed.size() > 0) - { - item = pendingNewsFeed.front(); - pendingNewsFeed.pop_front(); - - return true; - } - - return false; -} - - -bool p3Notify::AddFeedItem(uint32_t type, const std::string& id1, const std::string& id2, const std::string& id3, const std::string& id4, uint32_t result1) -{ - RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ - pendingNewsFeed.push_back(RsFeedItem(type, id1, id2, id3, id4, result1)); - - return true; -} - -bool p3Notify::ClearFeedItems(uint32_t type) -{ - RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ - - std::list::iterator it; - for(it = pendingNewsFeed.begin(); it != pendingNewsFeed.end(); ) - { - if (it->mType == type) - { - it = pendingNewsFeed.erase(it); - } - else - { - ++it; - } - } - return true; -} - -#define FOR_ALL_NOTIFY_CLIENTS for(std::list::const_iterator it(notifyClients.begin());it!=notifyClients.end();++it) - -void p3Notify::notifyChatLobbyEvent(uint64_t lobby_id, uint32_t event_type,const RsGxsId& nickname,const std::string& any_string) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyChatLobbyEvent(lobby_id,event_type,nickname,any_string) ; } - -void p3Notify::notifyListPreChange(int list, int type) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyListPreChange(list,type) ; } -void p3Notify::notifyListChange (int list, int type) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyListChange (list,type) ; } - -void p3Notify::notifyErrorMsg (int list, int sev, std::string msg) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyErrorMsg(list,sev,msg) ; } -void p3Notify::notifyChatMessage (const ChatMessage &msg) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyChatMessage(msg) ; } -void p3Notify::notifyChatStatus (const ChatId& chat_id, const std::string& status_string) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyChatStatus(chat_id,status_string) ; } -void p3Notify::notifyChatCleared (const ChatId& chat_id) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyChatCleared(chat_id) ; } - -void p3Notify::notifyChatLobbyTimeShift (int time_shift) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyChatLobbyTimeShift(time_shift) ; } -void p3Notify::notifyCustomState (const std::string& peer_id , const std::string& status_string ) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyCustomState (peer_id,status_string) ; } -void p3Notify::notifyHashingInfo (uint32_t type , const std::string& fileinfo ) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyHashingInfo (type,fileinfo) ; } -void p3Notify::notifyTurtleSearchResult (const RsPeerId& pid , uint32_t search_id , const std::list& files ) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyTurtleSearchResult(pid,search_id,files) ; } -#warning MISSING CODE HERE -//void p3Notify::notifyTurtleSearchResult (uint32_t search_id , const std::list& groups ) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyTurtleSearchResult(search_id,groups) ; } -void p3Notify::notifyPeerHasNewAvatar (std::string peer_id ) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyPeerHasNewAvatar(peer_id) ; } -void p3Notify::notifyOwnAvatarChanged () { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyOwnAvatarChanged() ; } -void p3Notify::notifyOwnStatusMessageChanged() { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyOwnStatusMessageChanged() ; } -void p3Notify::notifyDiskFull (uint32_t location , uint32_t size_limit_in_MB ) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyDiskFull (location,size_limit_in_MB) ; } -void p3Notify::notifyPeerStatusChanged (const std::string& peer_id , uint32_t status ) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyPeerStatusChanged (peer_id,status) ; } - -void p3Notify::notifyPeerStatusChangedSummary () { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyPeerStatusChangedSummary() ; } -void p3Notify::notifyDiscInfoChanged () { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyDiscInfoChanged () ; } - -void p3Notify::notifyDownloadComplete (const std::string& fileHash ) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyDownloadComplete (fileHash) ; } -void p3Notify::notifyDownloadCompleteCount (uint32_t count ) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyDownloadCompleteCount (count) ; } -void p3Notify::notifyHistoryChanged (uint32_t msgId , int type) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyHistoryChanged (msgId,type) ; } - -bool p3Notify::cachePgpPassphrase(const std::string& s) -{ - clearPgpPassphrase() ; - cached_pgp_passphrase = s ; - - std::cerr << "(WW) Caching PGP passphrase." << std::endl; - return true ; -} -bool p3Notify::clearPgpPassphrase() -{ - std::cerr << "(WW) Clearing PGP passphrase." << std::endl; - - // Just whipe out the memory instead of just releasing it. - - for(uint32_t i=0;iaskForPassword(title,key_details,prev_is_bad,password,*cancelled) ) - return true; - - return false ; -} -bool p3Notify::askForPluginConfirmation (const std::string& plugin_filename, const std::string& plugin_file_hash,bool first_time) -{ - FOR_ALL_NOTIFY_CLIENTS - if( (*it)->askForPluginConfirmation(plugin_filename,plugin_file_hash,first_time)) - return true ; - - return false ; -} - -void p3Notify::registerNotifyClient(NotifyClient *cl) -{ - notifyClients.push_back(cl) ; -} - -bool p3Notify::unregisterNotifyClient(NotifyClient *nc) -{ - std::list::iterator it = std::find(notifyClients.begin(), notifyClients.end(), nc); - if(it != notifyClients.end()) - { - notifyClients.erase(it); - return true; - } - else - { - return false; - } -} diff --git a/libretroshare/src/pqi/p3notify.h b/libretroshare/src/pqi/p3notify.h deleted file mode 100644 index 3d78cdf8c..000000000 --- a/libretroshare/src/pqi/p3notify.h +++ /dev/null @@ -1,145 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3notify.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_P3_NOTIFY_INTERFACE_H -#define RS_P3_NOTIFY_INTERFACE_H - -#include "retroshare/rsnotify.h" -#include "retroshare/rsturtle.h" - -#include "util/rsthreads.h" - -class p3NotifySysMsg -{ - public: - - uint32_t sysid; - uint32_t type; - std::string title; - std::string msg; -}; - -class p3NotifyLogMsg -{ - public: - - uint32_t sysid; - uint32_t type; - std::string title; - std::string msg; -}; - -class p3NotifyPopupMsg -{ - public: - - uint32_t type; - std::string name; - std::string title; - std::string msg; -}; - - -class p3Notify: public RsNotify -{ - public: - - p3Notify() : noteMtx("p3Notify"), _disableAskPassword(false) { return; } - virtual ~p3Notify() { return; } - - virtual void registerNotifyClient(NotifyClient *nc) ; - virtual bool unregisterNotifyClient(NotifyClient *nc) ; - - /* Pull output methods for retroshare-gui */ - virtual bool NotifySysMessage(uint32_t &sysid, uint32_t &type, std::string &title, std::string &msg); - virtual bool NotifyPopupMessage(uint32_t &ptype, std::string &name, std::string &title, std::string &msg); - virtual bool NotifyLogMessage(uint32_t &sysid, uint32_t &type, std::string &title, std::string &msg); - - virtual bool GetFeedItem(RsFeedItem &item); - - /* Control over Messages */ - bool GetSysMessageList(std::map &list); - bool GetPopupMessageList(std::map &list); - - bool SetSysMessageMode(uint32_t sysid, uint32_t mode); - bool SetPopupMessageMode(uint32_t ptype, uint32_t mode); - - /* Notify messages */ - bool AddPopupMessage(uint32_t ptype, const std::string& name, const std::string& title, const std::string& msg); - bool AddSysMessage(uint32_t sysid, uint32_t type, const std::string& title, const std::string& msg); - bool AddLogMessage(uint32_t sysid, uint32_t type, const std::string& title, const std::string& msg); - bool AddFeedItem(uint32_t type, const std::string& id1, const std::string& id2 = "", const std::string& id3 = "", const std::string& id4 = "", uint32_t result1 = 0); - bool ClearFeedItems(uint32_t type); - - // Notifications of clients. Can be called from anywhere inside libretroshare. - // - void notifyListPreChange (int /* list */, int /* type */) ; - void notifyListChange (int /* list */, int /* type */) ; - void notifyErrorMsg (int /* list */, int /* sev */, std::string /* msg */) ; - void notifyChatMessage (const ChatMessage& /* msg */) ; - void notifyChatStatus (const ChatId& /* chat_id */, const std::string& /* status_string */) ; - void notifyChatCleared (const ChatId& /* chat_id */) ; - void notifyChatLobbyEvent (uint64_t /* lobby id */, uint32_t /* event type */ , const RsGxsId & /* nickname */, const std::string& /* any string */) ; - void notifyChatLobbyTimeShift (int /* time_shift*/) ; - void notifyCustomState (const std::string& /* peer_id */, const std::string& /* status_string */) ; - void notifyHashingInfo (uint32_t /* type */, const std::string& /* fileinfo */) ; - void notifyTurtleSearchResult (const RsPeerId &pid, uint32_t /* search_id */, const std::list& /* files */) ; -#warning MISSING CODE HERE -// void notifyTurtleSearchResult (uint32_t /* search_id */, const std::list& /* groups */) ; - void notifyPeerHasNewAvatar (std::string /* peer_id */) ; - void notifyOwnAvatarChanged () ; - void notifyOwnStatusMessageChanged () ; - void notifyDiskFull (uint32_t /* location */, uint32_t /* size limit in MB */) ; - void notifyPeerStatusChanged (const std::string& /* peer_id */, uint32_t /* status */) ; - void notifyConnectionWithoutCert (); - - void notifyPeerStatusChangedSummary () ; - void notifyDiscInfoChanged () ; - - void notifyDownloadComplete (const std::string& /* fileHash */) ; - void notifyDownloadCompleteCount (uint32_t /* count */) ; - void notifyHistoryChanged (uint32_t /* msgId */, int /* type */) ; - - bool askForPassword (const std::string& title, const std::string& /* key_details */, bool /* prev_is_bad */, std::string&, bool *cancelled /* password */ ) ; - bool askForPluginConfirmation (const std::string& /* plugin_filename */, const std::string& /* plugin_file_hash */,bool first_time) ; - - virtual bool cachePgpPassphrase (const std::string& /* pgp_passphrase */) ; - virtual bool clearPgpPassphrase () ; - - virtual bool setDisableAskPassword (const bool /*bValue*/) ; - - private: - - RsMutex noteMtx; - - std::list pendingSysMsgs; - std::list pendingLogMsgs; - std::list pendingPopupMsgs; - std::list pendingNewsFeed; - - std::list notifyClients ; - - std::string cached_pgp_passphrase; - bool _disableAskPassword; -}; - - -#endif diff --git a/libretroshare/src/pqi/p3peermgr.cc b/libretroshare/src/pqi/p3peermgr.cc deleted file mode 100644 index d4ff9f95d..000000000 --- a/libretroshare/src/pqi/p3peermgr.cc +++ /dev/null @@ -1,3183 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3peermgr.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2007-2011 Robert Fernie * - * Copyright (C) 2015-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include // for std::vector -#include // for std::random_shuffle - -#include "rsserver/p3face.h" -#include "util/rsnet.h" -#include "pqi/authgpg.h" -#include "pqi/authssl.h" - -#include "pqi/p3peermgr.h" -#include "pqi/p3linkmgr.h" -#include "pqi/p3netmgr.h" -#include "pqi/p3historymgr.h" -#include "pqi/pqinetwork.h" // for getLocalAddresses - -#include "util/rsprint.h" -#include "util/rsstring.h" -#include "util/rsdebug.h" - -#include "rsitems/rsconfigitems.h" - -#include "retroshare/rsiface.h" // Needed for rsicontrol (should remove this dependancy) -#include "retroshare/rspeers.h" // Needed for Group Parameters. -#include "retroshare/rsbanlist.h" // Needed for banned IPs - -/* Network setup States */ - -//Defined and used in /libretroshare/src/pqi/p3netmgr.cc -//const uint32_t RS_NET_NEEDS_RESET = 0x0000; -//const uint32_t RS_NET_UNKNOWN = 0x0001; -//const uint32_t RS_NET_UPNP_INIT = 0x0002; -//const uint32_t RS_NET_UPNP_SETUP = 0x0003; -//const uint32_t RS_NET_EXT_SETUP = 0x0004; -//const uint32_t RS_NET_DONE = 0x0005; -//const uint32_t RS_NET_LOOPBACK = 0x0006; -//const uint32_t RS_NET_DOWN = 0x0007; - -//const uint32_t MIN_TIME_BETWEEN_NET_RESET = 5; - -//const uint32_t PEER_IP_CONNECT_STATE_MAX_LIST_SIZE = 4; - -static struct RsLog::logInfo p3peermgrzoneInfo = {RsLog::Default, "p3peermgr"}; -#define p3peermgrzone &p3peermgrzoneInfo - -/**** - * #define PEER_DEBUG 1 - * #define PEER_DEBUG_LOG 1 - ***/ - -#define MAX_AVAIL_PERIOD 230 //times a peer stay in available state when not connected -#define MIN_RETRY_PERIOD 140 - -static const std::string kConfigDefaultProxyServerIpAddr = "127.0.0.1"; -static const uint16_t kConfigDefaultProxyServerPortTor = 9050; // standard port. -static const uint16_t kConfigDefaultProxyServerPortI2P = 4447; // I2Pd's standard port - -static const std::string kConfigKeyExtIpFinder = "USE_EXTR_IP_FINDER"; -static const std::string kConfigKeyProxyServerIpAddrTor = "PROXY_SERVER_IPADDR"; -static const std::string kConfigKeyProxyServerPortTor = "PROXY_SERVER_PORT"; -static const std::string kConfigKeyProxyServerIpAddrI2P = "PROXY_SERVER_IPADDR_I2P"; -static const std::string kConfigKeyProxyServerPortI2P = "PROXY_SERVER_PORT_I2P"; - -void printConnectState(std::ostream &out, peerState &peer); - -peerState::peerState() - :skip_pgp_signature_validation(false),netMode(RS_NET_MODE_UNKNOWN), vs_disc(RS_VS_DISC_FULL), vs_dht(RS_VS_DHT_FULL), lastcontact(0), - hiddenNode(false), hiddenPort(0), hiddenType(RS_HIDDEN_TYPE_NONE) -{ - sockaddr_storage_clear(localaddr); - sockaddr_storage_clear(serveraddr); - - return; -} - -std::string textPeerConnectState(peerState &state) -{ - std::string out = "Id: " + state.id.toStdString() + "\n"; - rs_sprintf_append(out, "NetMode: %lu\n", state.netMode); - rs_sprintf_append(out, "VisState: Disc: %u Dht: %u\n", state.vs_disc, state.vs_dht); - - out += "laddr: "; - out += sockaddr_storage_tostring(state.localaddr); - out += "\neaddr: "; - out += sockaddr_storage_tostring(state.serveraddr); - out += "\n"; - - return out; -} - - -p3PeerMgrIMPL::p3PeerMgrIMPL(const RsPeerId& ssl_own_id, const RsPgpId& gpg_own_id, const std::string& gpg_own_name, const std::string& ssl_own_location) - :p3Config(), mPeerMtx("p3PeerMgr"), mStatusChanged(false) -{ - - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - mLinkMgr = NULL; - mNetMgr = NULL; - - /* setup basics of own state */ - mOwnState.id = ssl_own_id ; - mOwnState.gpg_id = gpg_own_id ; - mOwnState.name = gpg_own_name ; - mOwnState.location = ssl_own_location ; - mOwnState.netMode = RS_NET_MODE_UPNP; // Default to UPNP. - mOwnState.vs_disc = RS_VS_DISC_FULL; - mOwnState.vs_dht = RS_VS_DHT_FULL; - - // setup default ProxyServerAddress. - // Tor - sockaddr_storage_clear(mProxyServerAddressTor); - sockaddr_storage_ipv4_aton(mProxyServerAddressTor, - kConfigDefaultProxyServerIpAddr.c_str()); - sockaddr_storage_ipv4_setport(mProxyServerAddressTor, - kConfigDefaultProxyServerPortTor); - // I2P - sockaddr_storage_clear(mProxyServerAddressI2P); - sockaddr_storage_ipv4_aton(mProxyServerAddressI2P, - kConfigDefaultProxyServerIpAddr.c_str()); - sockaddr_storage_ipv4_setport(mProxyServerAddressI2P, - kConfigDefaultProxyServerPortI2P); - - mProxyServerStatusTor = RS_NET_PROXY_STATUS_UNKNOWN ; - mProxyServerStatusI2P = RS_NET_PROXY_STATUS_UNKNOWN; - } - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgr() Startup" << std::endl; -#endif - - - return; -} - -void p3PeerMgrIMPL::setManagers(p3LinkMgrIMPL *linkMgr, p3NetMgrIMPL *netMgr) -{ - mLinkMgr = linkMgr; - mNetMgr = netMgr; -} - - -bool p3PeerMgrIMPL::setupHiddenNode(const std::string &hiddenAddress, const uint16_t hiddenPort) -{ - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setupHiddenNode()"; - std::cerr << " Address: " << hiddenAddress; - std::cerr << " Port: " << hiddenPort; - std::cerr << std::endl; -#endif - - mOwnState.hiddenNode = true; - mOwnState.hiddenPort = hiddenPort; - mOwnState.hiddenDomain = hiddenAddress; - mOwnState.hiddenType = hiddenDomainToHiddenType(hiddenAddress); - } - - forceHiddenNode(); - return true; -} - - -bool p3PeerMgrIMPL::forceHiddenNode() -{ - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - if (RS_NET_MODE_HIDDEN != mOwnState.netMode) - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::forceHiddenNode() Required!"; - std::cerr << std::endl; -#endif - } - mOwnState.hiddenNode = true; - mOwnState.hiddenType = hiddenDomainToHiddenType(mOwnState.hiddenDomain); - - // force external address - otherwise its invalid. - sockaddr_storage_clear(mOwnState.serveraddr); - sockaddr_storage_ipv4_aton(mOwnState.serveraddr, "0.0.0.0"); - sockaddr_storage_ipv4_setport(mOwnState.serveraddr, 0); - } - - setOwnNetworkMode(RS_NET_MODE_HIDDEN); - - // switch off DHT too. - setOwnVisState(mOwnState.vs_disc, RS_VS_DHT_OFF); - - // Force the Port. - struct sockaddr_storage loopback; - sockaddr_storage_clear(loopback); - sockaddr_storage_ipv4_aton(loopback, "127.0.0.1"); - uint16_t port = sockaddr_storage_port(mOwnState.localaddr); - sockaddr_storage_ipv4_setport(loopback, port); - - setLocalAddress(AuthSSL::getAuthSSL()->OwnId(), loopback); - - mNetMgr->setIPServersEnabled(false); - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - return true; -} - - -bool p3PeerMgrIMPL::setOwnNetworkMode(uint32_t netMode) -{ - bool changed = false; - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setOwnNetworkMode() :"; - std::cerr << " Existing netMode: " << mOwnState.netMode; - std::cerr << " Input netMode: " << netMode; - std::cerr << std::endl; -#endif - - if (mOwnState.netMode != (netMode & RS_NET_MODE_ACTUAL)) - { - mOwnState.netMode = (netMode & RS_NET_MODE_ACTUAL); - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - changed = true; - } - } - - // Pass on Flags to NetMgr. - mNetMgr->setNetworkMode((netMode & RS_NET_MODE_ACTUAL)); - return changed; -} - -bool p3PeerMgrIMPL::setOwnVisState(uint16_t vs_disc, uint16_t vs_dht) -{ - bool changed = false; - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - std::string out; - rs_sprintf(out, "p3PeerMgr::setOwnVisState() Existing vis: %u/%u Input vis: %u/%u", - mOwnState.vs_disc, mOwnState.vs_dht, vs_disc, vs_dht); - rslog(RSL_WARNING, p3peermgrzone, out); - -#ifdef PEER_DEBUG - std::cerr << out.c_str() << std::endl; -#endif - - if (mOwnState.vs_disc != vs_disc || mOwnState.vs_dht != vs_dht) - { - mOwnState.vs_disc = vs_disc; - mOwnState.vs_dht = vs_dht; - changed = true; - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - } - } - - // Pass on Flags to NetMgr. - mNetMgr->setVisState(vs_disc, vs_dht); - - return changed; -} - - -void p3PeerMgrIMPL::tick() -{ - static const rstime_t INTERVAL_BETWEEN_LOCATION_CLEANING = 300 ; // Remove unused locations and clean IPs every 10 minutes. - - static rstime_t last_friends_check = time(NULL) ; // first cleaning after 1 hour. - - rstime_t now = time(NULL) ; - - if(now > INTERVAL_BETWEEN_LOCATION_CLEANING + last_friends_check ) - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::tick(): cleaning unused locations." << std::endl ; -#endif - - rslog(RSL_WARNING, p3peermgrzone, "p3PeerMgr::tick() removeUnusedLocations()"); - - removeUnusedLocations() ; - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::tick(): cleaning banned/old IPs." << std::endl ; -#endif - removeBannedIps() ; - - last_friends_check = now ; - } -} - - -/******************************** Network Status ********************************* - * Configuration Loading / Saving. - */ - - -const RsPeerId& p3PeerMgrIMPL::getOwnId() -{ - return AuthSSL::getAuthSSL()->OwnId(); -} - - -bool p3PeerMgrIMPL::getOwnNetStatus(peerState &state) -{ - RS_STACK_MUTEX(mPeerMtx); - state = mOwnState; - return true; -} - -bool p3PeerMgrIMPL::isFriend(const RsPeerId& id) -{ -#ifdef PEER_DEBUG_COMMON - std::cerr << "p3PeerMgrIMPL::isFriend(" << id << ") called" << std::endl; -#endif - RS_STACK_MUTEX(mPeerMtx); - bool ret = (mFriendList.end() != mFriendList.find(id)); -#ifdef PEER_DEBUG_COMMON - std::cerr << "p3PeerMgrIMPL::isFriend(" << id << ") returning : " << ret << std::endl; -#endif - return ret; -} -bool p3PeerMgrIMPL::isSslOnlyFriend(const RsPeerId& id) -{ -#ifdef PEER_DEBUG_COMMON - std::cerr << "p3PeerMgrIMPL::isFriend(" << id << ") called" << std::endl; -#endif - RS_STACK_MUTEX(mPeerMtx); - auto it = mFriendList.find(id); - bool ret = it != mFriendList.end() && it->second.skip_pgp_signature_validation ; - -#ifdef PEER_DEBUG_COMMON - std::cerr << "p3PeerMgrIMPL::isFriend(" << id << ") returning : " << ret << std::endl; -#endif - return ret; -} - -bool p3PeerMgrIMPL::getPeerName(const RsPeerId &ssl_id, std::string &name) -{ - RS_STACK_MUTEX(mPeerMtx); - - /* check for existing */ - std::map::iterator it; - it = mFriendList.find(ssl_id); - if (it == mFriendList.end()) - { - return false; - } - - name = it->second.name + " (" + it->second.location + ")"; - return true; -} - -bool p3PeerMgrIMPL::getGpgId(const RsPeerId &ssl_id, RsPgpId &gpgId) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - /* check for existing */ - std::map::iterator it; - it = mFriendList.find(ssl_id); - if (it == mFriendList.end()) - { - return false; - } - - gpgId = it->second.gpg_id; - return true; -} - -/**** HIDDEN STUFF ****/ - -bool p3PeerMgrIMPL::isHidden() -{ - RS_STACK_MUTEX(mPeerMtx); - return mOwnState.hiddenNode; -} - -/** - * @brief checks the hidden type of the own peer. - * @param type type to check - * @return true when the peer has the same hidden type than type - */ -bool p3PeerMgrIMPL::isHidden(const uint32_t type) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - switch (type) { - case RS_HIDDEN_TYPE_TOR: - return mOwnState.hiddenType == RS_HIDDEN_TYPE_TOR; - break; - case RS_HIDDEN_TYPE_I2P: - return mOwnState.hiddenType == RS_HIDDEN_TYPE_I2P; - break; - default: -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::isHidden(" << type << ") unkown type -> false"; - std::cerr << std::endl; -#endif - return false; - break; - } -} - -bool p3PeerMgrIMPL::isHiddenPeer(const RsPeerId &ssl_id) -{ - return isHiddenPeer(ssl_id, RS_HIDDEN_TYPE_NONE); -} - -/** - * @brief checks the hidden type of a given ssl id. When type RS_HIDDEN_TYPE_NONE is choosen it returns the 'hiddenNode' value instead - * @param ssl_id to check - * @param type type to check. Use RS_HIDDEN_TYPE_NONE to check 'hiddenNode' value - * @return true when the peer has the same hidden type than type - */ -bool p3PeerMgrIMPL::isHiddenPeer(const RsPeerId &ssl_id, const uint32_t type) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - /* check for existing */ - std::map::iterator it; - it = mFriendList.find(ssl_id); - if (it == mFriendList.end()) - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::isHiddenPeer(" << ssl_id << ") Missing Peer => false"; - std::cerr << std::endl; -#endif - - return false; - } - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::isHiddenPeer(" << ssl_id << ") = " << (it->second).hiddenNode; - std::cerr << std::endl; -#endif - switch (type) { - case RS_HIDDEN_TYPE_TOR: - return (it->second).hiddenType == RS_HIDDEN_TYPE_TOR; - break; - case RS_HIDDEN_TYPE_I2P: - return (it->second).hiddenType == RS_HIDDEN_TYPE_I2P; - break; - default: - return (it->second).hiddenNode; - break; - } -} - -bool hasEnding (std::string const &fullString, std::string const &ending) { - if (fullString.length() < ending.length()) - return false; - - return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending)); -} - -/** - * @brief resolves the hidden type (tor or i2p) from a domain - * @param domain to check - * @return RS_HIDDEN_TYPE_TOR, RS_HIDDEN_TYPE_I2P or RS_HIDDEN_TYPE_NONE - * - * Tor: ^[a-z2-7]{16}\.onion$ - * - * I2P: There is more than one address: - * - pub. key in base64 - * - hash in base32 ( ^[a-z2-7]{52}\.b32\.i2p$ ) - * - "normal" .i2p domains - */ -uint32_t p3PeerMgrIMPL::hiddenDomainToHiddenType(const std::string &domain) -{ - if(hasEnding(domain, ".onion")) - return RS_HIDDEN_TYPE_TOR; - if(hasEnding(domain, ".i2p")) - return RS_HIDDEN_TYPE_I2P; - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::hiddenDomainToHiddenType() unknown hidden type: " << domain; - std::cerr << std::endl; -#endif - return RS_HIDDEN_TYPE_UNKNOWN; -} - -/** - * @brief returns the hidden type of a peer - * @param ssl_id peer id - * @return hidden type - */ -uint32_t p3PeerMgrIMPL::getHiddenType(const RsPeerId &ssl_id) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - if (ssl_id == AuthSSL::getAuthSSL()->OwnId()) - return mOwnState.hiddenType; - - /* check for existing */ - std::map::iterator it; - it = mFriendList.find(ssl_id); - if (it == mFriendList.end()) - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::getHiddenType(" << ssl_id << ") Missing Peer => false"; - std::cerr << std::endl; -#endif - - return false; - } - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::getHiddenType(" << ssl_id << ") = " << (it->second).hiddenType; - std::cerr << std::endl; -#endif - return (it->second).hiddenType; -} - -bool p3PeerMgrIMPL::isHiddenNode(const RsPeerId& id) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - if (id == AuthSSL::getAuthSSL()->OwnId()) - return mOwnState.hiddenNode ; - else - { - std::map::const_iterator it = mFriendList.find(id); - - if (it == mFriendList.end()) - { - std::cerr << "p3PeerMgrIMPL::isHiddenNode() Peer Not Found" << std::endl; - return false; - } - return it->second.hiddenNode ; - } -} - -/** - * @brief sets hidden domain and port for a given ssl ID - * @param ssl_id peer to set domain and port for - * @param domain_addr - * @param domain_port - * @return true on success - */ -bool p3PeerMgrIMPL::setHiddenDomainPort(const RsPeerId &ssl_id, const std::string &domain_addr, const uint16_t domain_port) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setHiddenDomainPort()"; - std::cerr << std::endl; -#endif - - std::string domain = domain_addr; - // trim whitespace! - size_t pos = domain.find_last_not_of(" \t\n"); - if (std::string::npos != pos) - { - domain = domain.substr(0, pos + 1); - } - pos = domain.find_first_not_of(" \t\n"); - if (std::string::npos != pos) - { - domain = domain.substr(pos); - } - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - if (ssl_id == AuthSSL::getAuthSSL()->OwnId()) - { - mOwnState.hiddenNode = true; - mOwnState.hiddenDomain = domain; - mOwnState.hiddenPort = domain_port; - mOwnState.hiddenType = hiddenDomainToHiddenType(domain); -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setHiddenDomainPort() Set own State"; - std::cerr << std::endl; -#endif - return true; - } - - /* check for existing */ - std::map::iterator it; - it = mFriendList.find(ssl_id); - if (it == mFriendList.end()) - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setHiddenDomainPort() Peer Not Found"; - std::cerr << std::endl; -#endif - return false; - } - - it->second.hiddenDomain = domain; - it->second.hiddenPort = domain_port; - it->second.hiddenNode = true; - it->second.hiddenType = hiddenDomainToHiddenType(domain); -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setHiddenDomainPort() Set Peers State"; - std::cerr << std::endl; -#endif - - return true; -} - -/** - * @brief sets the proxy server address for a hidden service - * @param type hidden service type - * @param proxy_addr proxy address - * @return true on success - */ -bool p3PeerMgrIMPL::setProxyServerAddress(const uint32_t type, const struct sockaddr_storage &proxy_addr) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - switch (type) { - case RS_HIDDEN_TYPE_I2P: - if (!sockaddr_storage_same(mProxyServerAddressI2P, proxy_addr)) - { - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - mProxyServerAddressI2P = proxy_addr; - } - break; - case RS_HIDDEN_TYPE_TOR: - if (!sockaddr_storage_same(mProxyServerAddressTor, proxy_addr)) - { - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - mProxyServerAddressTor = proxy_addr; - } - break; - case RS_HIDDEN_TYPE_UNKNOWN: - default: -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setProxyServerAddress() unknown hidden type " << type << " -> false"; - std::cerr << std::endl; -#endif - return false; - } - - return true; -} - -bool p3PeerMgrIMPL::resetOwnExternalAddressList() -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - mOwnState.ipAddrs.mLocal.mAddrs.clear() ; - mOwnState.ipAddrs.mExt.mAddrs.clear() ; - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - return true ; -} - -/** - * @brief returs proxy server status for a hidden service proxy - * @param type hidden service type - * @param proxy_status - * @return true on success - */ -bool p3PeerMgrIMPL::getProxyServerStatus(const uint32_t type, uint32_t& proxy_status) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - switch (type) { - case RS_HIDDEN_TYPE_I2P: - proxy_status = mProxyServerStatusI2P; - break; - case RS_HIDDEN_TYPE_TOR: - proxy_status = mProxyServerStatusTor; - break; - case RS_HIDDEN_TYPE_UNKNOWN: - default: -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::getProxyServerStatus() unknown hidden type " << type << " -> false"; - std::cerr << std::endl; -#endif - return false; - } - - return true; -} - -/** - * @brief returs proxy server address for a hidden service proxy - * @param type hidden service type - * @param proxy_addr - * @return true on success - */ -bool p3PeerMgrIMPL::getProxyServerAddress(const uint32_t type, struct sockaddr_storage &proxy_addr) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - switch (type) { - case RS_HIDDEN_TYPE_I2P: - proxy_addr = mProxyServerAddressI2P; - break; - case RS_HIDDEN_TYPE_TOR: - proxy_addr = mProxyServerAddressTor; - break; - case RS_HIDDEN_TYPE_UNKNOWN: - default: -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::getProxyServerAddress() unknown hidden type " << type << " -> false"; - std::cerr << std::endl; -#endif - return false; - } - return true; -} - -/** - * @brief looks up the proxy address and domain/port that have to be used when connecting to a peer - * @param ssl_id peer to connect to - * @param proxy_addr proxy address to be used - * @param domain_addr domain to connect to - * @param domain_port port to connect to - * @return true on success - */ -bool p3PeerMgrIMPL::getProxyAddress(const RsPeerId &ssl_id, struct sockaddr_storage &proxy_addr, std::string &domain_addr, uint16_t &domain_port) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - /* check for existing */ - std::map::iterator it; - it = mFriendList.find(ssl_id); - if (it == mFriendList.end()) - { - return false; - } - - if (!it->second.hiddenNode) - { - return false; - } - - domain_addr = it->second.hiddenDomain; - domain_port = it->second.hiddenPort; - - switch (it->second.hiddenType) { - case RS_HIDDEN_TYPE_I2P: - proxy_addr = mProxyServerAddressI2P; - break; - case RS_HIDDEN_TYPE_TOR: - proxy_addr = mProxyServerAddressTor; - break; - case RS_HIDDEN_TYPE_UNKNOWN: - default: -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::getProxyAddress() no valid hidden type (" << it->second.hiddenType << ") for peer id " << ssl_id << " -> false"; - std::cerr << std::endl; -#endif - return false; - } - return true; -} - -// Placeholder until we implement this functionality. -uint32_t p3PeerMgrIMPL::getConnectionType(const RsPeerId &/*sslId*/) -{ - return RS_NET_CONN_TYPE_FRIEND; -} - -int p3PeerMgrIMPL::getFriendCount(bool ssl, bool online) -{ - if (online) { - // count only online id's - std::list onlineIds; - mLinkMgr->getOnlineList(onlineIds); - - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - std::set gpgIds; - int count = 0; - - std::map::iterator it; - for(it = mFriendList.begin(); it != mFriendList.end(); ++it) { - if (online && std::find(onlineIds.begin(), onlineIds.end(), it->first) == onlineIds.end()) { - continue; - } - if (ssl) { - // count ssl id's only - count++; - } else { - // count unique gpg id's - gpgIds.insert(it->second.gpg_id); - } - } - - return ssl ? count : gpgIds.size(); - } - - if (ssl) { - // count all ssl id's - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - return mFriendList.size(); - } - - // count all gpg id's - std::list gpgIds; - AuthPGP::getPgpAcceptedList(gpgIds); - - // add own gpg id, if we have more than one location - std::list ownSslIds; - getAssociatedPeers(AuthPGP::getPgpOwnId(), ownSslIds); - - return gpgIds.size() + ((ownSslIds.size() > 0) ? 1 : 0); -} - -bool p3PeerMgrIMPL::getFriendNetStatus(const RsPeerId &id, peerState &state) -{ - RS_STACK_MUTEX(mPeerMtx); - - /* check for existing */ - std::map::iterator it; - it = mFriendList.find(id); - if (it == mFriendList.end()) return false; - - state = it->second; - return true; -} - - -int p3PeerMgrIMPL::getConnectAddresses( - const RsPeerId &id, sockaddr_storage &lAddr, sockaddr_storage &eAddr, - pqiIpAddrSet &histAddrs, std::string &dyndns ) -{ - - RS_STACK_MUTEX(mPeerMtx); - - /* check for existing */ - std::map::iterator it; - it = mFriendList.find(id); - if (it == mFriendList.end()) - { - /* ERROR */ - std::cerr << "p3PeerMgrIMPL::getConnectAddresses() ERROR unknown Peer"; - std::cerr << std::endl; - return 0; - } - - lAddr = it->second.localaddr; - eAddr = it->second.serveraddr; - histAddrs = it->second.ipAddrs; - dyndns = it->second.dyndns; - - return 1; -} - - - -bool p3PeerMgrIMPL::haveOnceConnected() -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - /* check for existing */ - for(auto it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - if (it->second.lastcontact > 0) - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::haveOnceConnected() lastcontact: "; - std::cerr << time(NULL) - it->second.lastcontact << " for id: " << it->first; - std::cerr << std::endl; -#endif - - return true; - } - } - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::haveOnceConnected() all Last Contacts = 0"; - std::cerr << std::endl; -#endif - - return false; -} - - -bool p3PeerMgrIMPL::notifyPgpKeyReceived(const RsPgpId& pgp_id) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - bool changed = false; - - for(auto it(mFriendList.begin());it!=mFriendList.end();++it) - { - if(it->second.gpg_id == pgp_id) - { - std::cerr << "(WW) notification that full key " << pgp_id << " is available. Reseting short invite flag for peer " << it->first << std::endl; - it->second.skip_pgp_signature_validation = false; - - changed = true; - } - } - - if(changed) - IndicateConfigChanged(); - - return true; -} - -/*******************************************************************/ -/*******************************************************************/ - -bool p3PeerMgrIMPL::addFriend(const RsPeerId& input_id, const RsPgpId& input_gpg_id, uint32_t netMode, uint16_t vs_disc, uint16_t vs_dht, rstime_t lastContact,ServicePermissionFlags service_flags) -{ - bool notifyLinkMgr = false; - RsPeerId id = input_id ; - RsPgpId gpg_id = input_gpg_id ; - -#ifdef PEER_DEBUG_LOG - rslog(RSL_WARNING, p3peermgrzone, "p3PeerMgr::addFriend() id: " + id.toStdString()); -#endif - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - - if (id == AuthSSL::getAuthSSL()->OwnId()) - { - RsErr() << "p3PeerMgrIMPL::addFriend() cannot add own id as a friend. That's a bug!" << std::endl; - /* (1) already exists */ - return false; - } - /* so four possibilities - * (1) already exists as friend -> do nothing. - * (2) is in others list -> move over. - * (3) is non-existant -> create new one. - */ - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::addFriend() " << id << "; gpg_id : " << gpg_id << std::endl; -#endif - - std::map::iterator it; - if (mFriendList.end() != (it=mFriendList.find(id))) - { - // The friend may already be here, including with a short invite (meaning the PGP key is unknown). - - if(it->second.gpg_id != input_gpg_id)// already exists as a friend with a different PGP id!! - { - RsErr() << "Trying to add SSL id (" << id << ") that is already a friend with existing PGP key (" << it->second.gpg_id << ") but using a different PGP key (" << input_gpg_id << "). This is a bug!" << std::endl; - return false; - } - else - return true; /* (1) already exists */ - } - - // check that the PGP key is known - - if(!AuthPGP::isPGPId(gpg_id)) - { - RsErr() << "Trying to add SSL id (" << id << ") to be validated with unknown PGP key (" << gpg_id << ". This is a bug!" << std::endl; - return false; - } - - //Authentication is now tested at connection time, we don't store the ssl cert anymore - // - if (!AuthPGP::isPGPAccepted(gpg_id) && gpg_id != AuthPGP::getPgpOwnId()) - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::addFriend() gpg is not accepted" << std::endl; -#endif - /* no auth */ - return false; - } - - // after that, we know that we have the key, because AuthGPG wouldn't answer yes for a key it doesn't know. - - /* check if it is in others */ -// if (mOthersList.end() != (it = mOthersList.find(id))) -// { -// /* (2) in mOthersList -> move over */ -//#ifdef PEER_DEBUG -// std::cerr << "p3PeerMgrIMPL::addFriend() Move from Others" << std::endl; -//#endif -// if(!it->second.gpg_id.isNull() && it->second.gpg_id != input_gpg_id)// already exists as a friend with a different PGP id!! -// RsErr() << "Trying to add SSL id (" << id << ") that is already known (but not friend) with existing PGP key (" << it->second.gpg_id -// << ") but using a different PGP key (" << input_gpg_id << "). This looks like a bug! The friend will be added again with the new PGP key ID." << std::endl; -// -// mFriendList[id] = it->second; -// mOthersList.erase(it); -// -// it = mFriendList.find(id); -// -// /* setup connectivity parameters */ -// it->second.vs_disc = vs_disc; -// it->second.vs_dht = vs_dht; -// -// it->second.netMode = netMode; -// it->second.lastcontact = lastContact; -// -// it->second.gpg_id = input_gpg_id; -// it->second.skip_pgp_signature_validation = false; -// -// mStatusChanged = true; -// -// notifyLinkMgr = true; -// -// IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ -// } -// else - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::addFriend() Creating New Entry" << std::endl; -#endif - - /* create a new entry */ - peerState pstate; - - pstate.id = id; - pstate.gpg_id = gpg_id; - pstate.name = AuthPGP::getPgpName(gpg_id); - - pstate.vs_disc = vs_disc; - pstate.vs_dht = vs_dht; - pstate.netMode = netMode; - pstate.lastcontact = lastContact; - - pstate.gpg_id = input_gpg_id; - pstate.skip_pgp_signature_validation = false; - - /* addr & timestamps -> auto cleared */ - - mFriendList[id] = pstate; - - mStatusChanged = true; - - notifyLinkMgr = true; - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - } - - if (notifyLinkMgr) - { - mLinkMgr->addFriend(id, vs_dht != RS_VS_DHT_OFF); - } - - service_flags &= servicePermissionFlags(gpg_id) ; // Always reduce the permissions. -#ifdef RS_CHATSERVER //Defined by chatserver - setServicePermissionFlags(gpg_id,RS_NODE_PERM_NONE) ; -#else - setServicePermissionFlags(gpg_id,service_flags) ; -#endif - -#ifdef PEER_DEBUG - printPeerLists(std::cerr); - mLinkMgr->printPeerLists(std::cerr); -#endif - - return true; -} - - -bool p3PeerMgrIMPL::addSslOnlyFriend( const RsPeerId& sslId, const RsPgpId& pgp_id, const RsPeerDetails& dt ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(sslId.isNull()) - return failure("Cannot add a null ID as SSL-only friend"); - - if(pgp_id.isNull()) - return failure( " Cannot add as SSL-only friend a peer with null PGP"); - - if(sslId == getOwnId()) - return failure( "Cannot add yourself as SSL-only friend id:" + - sslId.toStdString() ); - - bool alreadySslFriend = false; - peerState pstate; - - { RS_STACK_MUTEX(mPeerMtx); - auto it = mFriendList.find(sslId); - if( it != mFriendList.end() ) - { - alreadySslFriend = true; - - /* If it is already friend override pstate so we don't loose already - * known information about the peer, in particular overriding - * pstate.skip_pgp_signature_validation is important for security. - */ - pstate = it->second; - } - } // RS_STACK_MUTEX(mPeerMtx); - - /* If it is already friend check if PGP id of the invite matches with the - * PGP id we already know, to avoid nasty tricks with malevolently forged - * short invites.*/ - if(alreadySslFriend && pstate.gpg_id != pgp_id) - return failure( "Cannot SSL-only friend for a pre-existing friend with " - "mismatching PGP-id known: " + - pstate.gpg_id.toStdString() + " new: " + - pgp_id.toStdString() ); - - /* It is very important to be expecially carefull setting - * pstate.skip_pgp_signature_validation to true because this effectively - * disables PGP signature verification on connection attempt. - * This check in particular avoid someone attempting to trick the user into - * accepting as SSL-only friend a malevolently forged short invite, with the - * PGP id of an already known friend but the SSL-id of a location generated - * by the attacker which doesn't have access to the legitimate PGP - * certificate. - * In that case being pstate.skip_pgp_signature_validation false on - * connection attempt the PGP signaure verification would fail and the - * connection closed. - * Instead if pstate.skip_pgp_signature_validation would have been - * superficially set to true the PGP signature verification would have been - * skipped and the attacker connection would be accepted. - * If the PGP key is available add it as full friend. */ - if(AuthPGP::isPgpPubKeyAvailable(pgp_id)) - AuthPGP::AllowConnection(pgp_id, true); - else - pstate.skip_pgp_signature_validation = true; - - pstate.gpg_id = pgp_id; - pstate.id = sslId; - - /* At this point if we got info about the peer just update with the new - * values. */ - if(!dt.name.empty()) pstate.name = dt.name; - if(!dt.dyndns.empty()) - { - pstate.dyndns = dt.dyndns; - if(dt.extPort) - { - /* If there is no IPv4 address available yet add a placeholder to - * not loose the port, because the address is invalid. */ - if(!sockaddr_storage_isValidNet(pstate.serveraddr)) - sockaddr_storage_inet_pton(pstate.serveraddr, "192.0.2.0"); - sockaddr_storage_setport(pstate.serveraddr, dt.extPort); - } - } - pstate.hiddenNode = dt.isHiddenNode; - if(!dt.hiddenNodeAddress.empty()) - pstate.hiddenDomain = dt.hiddenNodeAddress; - if(dt.hiddenNodePort) pstate.hiddenPort = dt.hiddenNodePort; - if(dt.hiddenType) pstate.hiddenType = dt.hiddenType; - if(!dt.location.empty()) pstate.location = dt.location; - - { RS_STACK_MUTEX(mPeerMtx); - mFriendList[sslId] = pstate; - mStatusChanged = true; - } // RS_STACK_MUTEX(mPeerMtx); - - IndicateConfigChanged(); - mLinkMgr->addFriend(sslId, dt.vs_dht != RS_VS_DHT_OFF); - - /* To update IP addresses is much more confortable to use locators, beside - * of the easy to use another benefit is that this way we don't loose - * previously known IP addresses */ - if(!dt.isHiddenNode) - { - for(const std::string& ipStr : dt.ipAddressList) - addPeerLocator(sslId, RsUrl(ipStr)); - - if(dt.extPort && !dt.extAddr.empty()) - { - RsUrl locator; - locator.setScheme("ipv4").setHost(dt.extAddr) - .setPort(dt.extPort); - addPeerLocator(sslId, locator); - } - - if(dt.localPort && !dt.localAddr.empty()) - { - RsUrl locator; - locator.setScheme("ipv4").setHost(dt.localAddr) - .setPort(dt.localPort); - addPeerLocator(sslId, locator); - } - } - - return true; -} - -bool p3PeerMgrIMPL::removeFriend(const RsPgpId &id) -{ -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::removeFriend() for id : " << id << std::endl; - std::cerr << "p3PeerMgrIMPL::removeFriend() mFriendList.size() : " << mFriendList.size() << std::endl; -#endif - - rslog(RSL_WARNING, p3peermgrzone, "p3PeerMgr::removeFriend() id: " + id.toStdString()); - - std::list sslid_toRemove; // This is a list of SSLIds. - rsPeers->getAssociatedSSLIds(id,sslid_toRemove) ; - - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - /* move to othersList */ - //bool success = false; - std::map::iterator it; - //remove ssl and gpg_ids - for(it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - if (find(sslid_toRemove.begin(),sslid_toRemove.end(),it->second.id) != sslid_toRemove.end()) - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::removeFriend() friend found in the list." << id << std::endl; -#endif - peerState peer = it->second; - - sslid_toRemove.push_back(it->second.id); - - //mOthersList[it->second.id] = peer; - mStatusChanged = true; - - //success = true; - } - } - - for(std::list::iterator rit = sslid_toRemove.begin(); rit != sslid_toRemove.end(); ++rit) - if (mFriendList.end() != (it = mFriendList.find(*rit))) - mFriendList.erase(it); - - std::map::iterator it2 = mFriendsPermissionFlags.find(id) ; - - if(it2 != mFriendsPermissionFlags.end()) - mFriendsPermissionFlags.erase(it2); - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::removeFriend() new mFriendList.size() : " << mFriendList.size() << std::endl; -#endif - } - - std::list::iterator rit; - for(rit = sslid_toRemove.begin(); rit != sslid_toRemove.end(); ++rit) - { - mLinkMgr->removeFriend(*rit); - } - - /* remove id from all groups */ - - std::list ids ; - ids.push_back(id) ; - assignPeersToGroup(RsNodeGroupId(), ids, false); - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - -#ifdef PEER_DEBUG - printPeerLists(std::cerr); - mLinkMgr->printPeerLists(std::cerr); -#endif - - return !sslid_toRemove.empty(); -} -bool p3PeerMgrIMPL::removeFriend(const RsPeerId &id, bool removePgpId) -{ - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::removeFriend() for id : " << id << std::endl; - std::cerr << "p3PeerMgrIMPL::removeFriend() mFriendList.size() : " << mFriendList.size() << std::endl; -#endif - - rslog(RSL_WARNING, p3peermgrzone, "p3PeerMgr::removeFriend() id: " + id.toStdString()); - - std::list sslid_toRemove; // This is a list of SSLIds. - std::list pgpid_toRemove; // This is a list of SSLIds. - - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - /* move to othersList */ - //bool success = false; - std::map::iterator it; - //remove ssl and gpg_ids - for(it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - if (it->second.id == id) - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::removeFriend() friend found in the list." << id << std::endl; -#endif - peerState peer = it->second; - - sslid_toRemove.push_back(it->second.id); - if(removePgpId) - pgpid_toRemove.push_back(it->second.gpg_id); - - //mOthersList[id] = peer; - mStatusChanged = true; - - //success = true; - } - } - - for(std::list::iterator rit = sslid_toRemove.begin(); rit != sslid_toRemove.end(); ++rit) - if (mFriendList.end() != (it = mFriendList.find(*rit))) - mFriendList.erase(it); - - std::map::iterator it2 ; - - for(std::list::iterator rit = pgpid_toRemove.begin(); rit != pgpid_toRemove.end(); ++rit) - if (mFriendsPermissionFlags.end() != (it2 = mFriendsPermissionFlags.find(*rit))) - mFriendsPermissionFlags.erase(it2); - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::removeFriend() new mFriendList.size() : " << mFriendList.size() << std::endl; -#endif - } - - std::list::iterator rit; - for(rit = sslid_toRemove.begin(); rit != sslid_toRemove.end(); ++rit) - { - mLinkMgr->removeFriend(*rit); - } - - /* remove id from all groups */ - - assignPeersToGroup(RsNodeGroupId(), pgpid_toRemove, false); - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - -#ifdef PEER_DEBUG - printPeerLists(std::cerr); - mLinkMgr->printPeerLists(std::cerr); -#endif - - return !sslid_toRemove.empty(); -} - - -void p3PeerMgrIMPL::printPeerLists(std::ostream &out) -{ - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - out << "p3PeerMgrIMPL::printPeerLists() Friend List"; - out << std::endl; - - - std::map::iterator it; - for(it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - out << "\t SSL ID: " << it->second.id; - out << "\t GPG ID: " << it->second.gpg_id; - out << std::endl; - } - -// out << "p3PeerMgrIMPL::printPeerLists() Others List"; -// out << std::endl; -// for(it = mOthersList.begin(); it != mOthersList.end(); ++it) -// { -// out << "\t SSL ID: " << it->second.id; -// out << "\t GPG ID: " << it->second.gpg_id; -// out << std::endl; -// } - } - - return; -} - - - -/*******************************************************************/ -/*******************************************************************/ - - -/********************************************************************** - ********************************************************************** - ******************** External Setup ********************************** - ********************************************************************** - **********************************************************************/ - - -/* This function should only be called from NetMgr, - * as it doesn't call back to there. - */ - -bool p3PeerMgrIMPL::UpdateOwnAddress( const sockaddr_storage& pLocalAddr, - const sockaddr_storage& pExtAddr ) -{ - sockaddr_storage localAddr; - sockaddr_storage_copy(pLocalAddr, localAddr); - sockaddr_storage_ipv6_to_ipv4(localAddr); - - sockaddr_storage extAddr; - sockaddr_storage_copy(pExtAddr, extAddr); - sockaddr_storage_ipv6_to_ipv4(extAddr); - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress(" - << sockaddr_storage_tostring(localAddr) << ", " - << sockaddr_storage_tostring(extAddr) << ")" << std::endl; -#endif - - if( rsBanList && - !rsBanList->isAddressAccepted(localAddr, - RSBANLIST_CHECKING_FLAGS_BLACKLIST) ) - { - std::cerr << "(SS) Trying to set own IP to a banned IP " - << sockaddr_storage_iptostring(localAddr) << ". This probably" - << "means that a friend in under traffic re-routing attack." - << std::endl; - return false; - } - - { - RS_STACK_MUTEX(mPeerMtx); - - //update ip address list - pqiIpAddress ipAddressTimed; - sockaddr_storage_copy(localAddr, ipAddressTimed.mAddr); - ipAddressTimed.mSeenTime = time(NULL); - ipAddressTimed.mSrc = 0; - mOwnState.ipAddrs.updateLocalAddrs(ipAddressTimed); - - if(!mOwnState.hiddenNode) - { - /* Workaround to spread multiple local ip addresses when presents. - * This is needed because RS wrongly assumes that there is just one - * active local ip address at time. */ - std::vector addrs; - if(getLocalAddresses(addrs)) - { - /* To work around MAX_ADDRESS_LIST_SIZE addresses limitation, - * let's shuffle the list of local addresses in the hope that - * with enough time every local address is advertised to - * trusted nodes so they may try to connect to all of them - * including the most convenient if a local connection exists. - */ - std::random_shuffle(addrs.begin(), addrs.end()); - - for (auto it = addrs.begin(); it!=addrs.end(); ++it) - { - sockaddr_storage& addr(*it); - if( sockaddr_storage_isValidNet(addr) && - !sockaddr_storage_isLoopbackNet(addr) && - /* Avoid IPv6 link local addresses as we don't have - * implemented the logic needed to handle sin6_scope_id. - * To properly handle sin6_scope_id it would probably - * require deep reenginering of the RetroShare - * networking stack */ - !sockaddr_storage_ipv6_isLinkLocalNet(addr) ) - { - sockaddr_storage_ipv6_to_ipv4(addr); - pqiIpAddress pqiIp; - sockaddr_storage_clear(pqiIp.mAddr); - pqiIp.mAddr.ss_family = addr.ss_family; - sockaddr_storage_copyip(pqiIp.mAddr, addr); - sockaddr_storage_setport( - pqiIp.mAddr, - sockaddr_storage_port(localAddr) ); - pqiIp.mSeenTime = time(nullptr); - pqiIp.mSrc = 0; - mOwnState.ipAddrs.updateLocalAddrs(pqiIp); - } - } - } - } - - sockaddr_storage_copy(localAddr, mOwnState.localaddr); - } - - - { - RS_STACK_MUTEX(mPeerMtx); - - //update ip address list - pqiIpAddress ipAddressTimed; - sockaddr_storage_copy(extAddr, ipAddressTimed.mAddr); - ipAddressTimed.mSeenTime = time(NULL); - ipAddressTimed.mSrc = 0; - mOwnState.ipAddrs.updateExtAddrs(ipAddressTimed); - - /* Attempted Fix to MANUAL FORWARD Mode.... - * don't update the server address - if we are in this mode - * - * It is okay - if they get it wrong, as we put the address in the address list anyway. - * This should keep people happy, and allow for misconfiguration! - */ - - if (mOwnState.netMode & RS_NET_MODE_TRY_EXT) - { - /**** THIS CASE SHOULD NOT BE TRIGGERED ****/ - std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress() Disabling Update of Server Port "; - std::cerr << " as MANUAL FORWARD Mode (ERROR - SHOULD NOT BE TRIGGERED: TRY_EXT_MODE)"; - std::cerr << std::endl; - std::cerr << "Address is Now: "; - std::cerr << sockaddr_storage_tostring(mOwnState.serveraddr); - std::cerr << std::endl; - } - else if (mOwnState.netMode & RS_NET_MODE_EXT) - { - sockaddr_storage_copyip(mOwnState.serveraddr, extAddr); - - std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress() Disabling Update of Server Port "; - std::cerr << " as MANUAL FORWARD Mode"; - std::cerr << std::endl; - std::cerr << "Address is Now: "; - std::cerr << sockaddr_storage_tostring(mOwnState.serveraddr); - std::cerr << std::endl; - } - else - { - sockaddr_storage_copy(extAddr, mOwnState.serveraddr); - } - } - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - mLinkMgr->setLocalAddress(localAddr); - - return true; -} - - -bool p3PeerMgrIMPL::addPeerLocator(const RsPeerId &sslId, const RsUrl& locator) -{ - std::string host(locator.host()); - pqiIpAddress ip; - if(!locator.hasPort() || host.empty() || - !sockaddr_storage_inet_pton(ip.mAddr, host) || - !sockaddr_storage_setport(ip.mAddr, locator.port())) return false; - ip.mSeenTime = time(NULL); - - bool changed = false; - - if (sslId == AuthSSL::getAuthSSL()->OwnId()) - { - RS_STACK_MUTEX(mPeerMtx); - changed = mOwnState.ipAddrs.updateLocalAddrs(ip); - } - else - { - RS_STACK_MUTEX(mPeerMtx); - auto it = mFriendList.find(sslId); - if (it == mFriendList.end()) - { -#ifdef PEER_DEBUG - std::cerr << __PRETTY_FUNCTION__ << "cannot add address " << "info, peer id: " << sslId << " not found in list" << std::endl; -#endif - return false; - } - - changed = it->second.ipAddrs.updateLocalAddrs(ip); - } - - if (changed) - { -#ifdef PEER_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " Added locator: " - << locator.toString() << std::endl; -#endif - IndicateConfigChanged(); - } - return changed; -} - -bool p3PeerMgrIMPL::setLocalAddress( const RsPeerId &id, - const sockaddr_storage &addr ) -{ - bool changed = false; - - if (id == AuthSSL::getAuthSSL()->OwnId()) - { - { - RS_STACK_MUTEX(mPeerMtx); - if (!sockaddr_storage_same(mOwnState.localaddr, addr)) - { - mOwnState.localaddr = addr; - changed = true; - } - } - - if (changed) - { - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - mNetMgr->setLocalAddress(addr); - mLinkMgr->setLocalAddress(addr); - } - return changed; - } - - RS_STACK_MUTEX(mPeerMtx); - /* check if it is a friend */ - std::map::iterator it; - if (mFriendList.end() == (it = mFriendList.find(id))) - { - std::cerr << "(EE) p3PeerMgrIMPL::setLocalAddress() cannot add addres " << "info : peer id not found in friend list id: " << id << std::endl; - return false; - } - - /* "it" points to peer */ - if (!sockaddr_storage_same(it->second.localaddr, addr)) - { - it->second.localaddr = addr; - changed = true; - } - -#if 0 - //update ip address list - IpAddressTimed ipAddressTimed; - ipAddressTimed.ipAddr = addr; - ipAddressTimed.seenTime = time(NULL); - it->second.updateIpAddressList(ipAddressTimed); -#endif - - if (changed) IndicateConfigChanged(); - return changed; -} - -bool p3PeerMgrIMPL::setExtAddress( const RsPeerId &id, - const sockaddr_storage &addr ) -{ - bool changed = false; - uint32_t check_res = 0; - - if(rsBanList && !rsBanList->isAddressAccepted( - addr, RSBANLIST_CHECKING_FLAGS_BLACKLIST, check_res )) - { - RsErr() << __PRETTY_FUNCTION__ << " trying to set external contact " - << "address for peer: " << id << " to a banned address " << addr - << std::endl; - return false; - } - - if (id == AuthSSL::getAuthSSL()->OwnId()) - { - { - RS_STACK_MUTEX(mPeerMtx); - if (!sockaddr_storage_same(mOwnState.serveraddr, addr)) - { - mOwnState.serveraddr = addr; - changed = true; - } - } - - mNetMgr->setExtAddress(addr); - - return changed; - } - - RS_STACK_MUTEX(mPeerMtx); - /* check if it is a friend */ - std::map::iterator it; - if (mFriendList.end() == (it = mFriendList.find(id))) - { - std::cerr << "(EE) p3PeerMgrIMPL::setExtAddress() cannot add addres " << "info : peer id not found in friend list id: " << id << std::endl; - return false; - } - - /* "it" points to peer */ - if (!sockaddr_storage_same(it->second.serveraddr, addr)) - { - it->second.serveraddr = addr; - changed = true; - } - -#if 0 - //update ip address list - IpAddressTimed ipAddressTimed; - ipAddressTimed.ipAddr = addr; - ipAddressTimed.seenTime = time(NULL); - it->second.updateIpAddressList(ipAddressTimed); -#endif - - if (changed) { - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - } - - return changed; -} - - -bool p3PeerMgrIMPL::setDynDNS(const RsPeerId &id, const std::string &dyndns) -{ - bool changed = false; - - if (id == AuthSSL::getAuthSSL()->OwnId()) - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - if (mOwnState.dyndns.compare(dyndns) != 0) { - mOwnState.dyndns = dyndns; - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - changed = true; - } - return changed; - } - - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - /* check if it is a friend */ - std::map::iterator it; - if (mFriendList.end() == (it = mFriendList.find(id))) - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setDynDNS() cannot add dyn dns info : peer id not found in friend list id: " << id << std::endl; -#endif - return false; - } - - /* "it" points to peer */ - if (it->second.dyndns.compare(dyndns) != 0) { - it->second.dyndns = dyndns; - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - changed = true; - } - - return changed; -} - -namespace pqi { - -struct ZeroedInt -{ - ZeroedInt() { n=0 ;} - int n ; -}; - -} - -bool p3PeerMgrIMPL::addCandidateForOwnExternalAddress(const RsPeerId &from, const sockaddr_storage &addr) -{ - // The algorithm is the following: - // - collect for each friend the last external connection address that is reported - // - everytime the list is changed, parse it entirely and - // * emit a warnign when the address is unknown - // * if multiple peers report the same address => notify the LinkMgr that the external address had changed. - - sockaddr_storage addr_filtered ; - sockaddr_storage_clear(addr_filtered) ; - sockaddr_storage_copyip(addr_filtered,addr) ; - -#ifndef PEER_DEBUG - std::cerr << "Own external address is " << sockaddr_storage_iptostring(addr_filtered) << ", as reported by friend " << from << std::endl; -#endif - - if(!sockaddr_storage_isExternalNet(addr_filtered)) - { -#ifdef PEER_DEBUG - std::cerr << " address is not an external address. Returning false" << std::endl ; -#endif - return false ; - } - - // Update a list of own IPs: - // - remove old values for that same peer - // - remove values for non connected peers - - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - mReportedOwnAddresses[from] = addr_filtered ; - - for(std::map::iterator it(mReportedOwnAddresses.begin());it!=mReportedOwnAddresses.end();) - if(!mLinkMgr->isOnline(it->first)) - { - std::map::iterator tmp(it) ; - ++tmp ; - mReportedOwnAddresses.erase(it) ; - it=tmp ; - } - else - ++it ; - - sockaddr_storage current_best_ext_address_guess ; - uint32_t count ; - - locked_computeCurrentBestOwnExtAddressCandidate(current_best_ext_address_guess,count) ; - - std::cerr << "p3PeerMgr:: Current external address is calculated to be: " << sockaddr_storage_iptostring(current_best_ext_address_guess) << " (simultaneously reported by " << count << " peers)." << std::endl; - } - - // now current - - sockaddr_storage own_addr ; - - if(!mNetMgr->getExtAddress(own_addr)) - { -#ifdef PEER_DEBUG - std::cerr << " cannot get current external address. Returning false" << std::endl; -#endif - return false ; - } -#ifdef PEER_DEBUG - std::cerr << " current external address is known to be " << sockaddr_storage_iptostring(own_addr) << std::endl; -#endif - - // Notify for every friend that has reported a wrong external address, except if that address is in the IP whitelist. - - if((rsBanList && !rsBanList->isAddressAccepted(addr_filtered, RSBANLIST_CHECKING_FLAGS_WHITELIST)) - && !sockaddr_storage_sameip(own_addr, addr_filtered) ) - { - RsInfo() << __PRETTY_FUNCTION__ << " Peer " << from - << " reports a connection address (" << addr_filtered - <<") that is not your current external address (" - << own_addr << "). This is weird." << std::endl; - - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mSslId = from; - ev->mOwnLocator = RsUrl(own_addr); - ev->mReportedLocator = RsUrl(addr); - ev->mConnectionInfoCode = RsConnectionEventCode::PEER_REPORTS_WRONG_IP; - rsEvents->postEvent(ev); - } - } - - // we could also sweep over all connected friends and see if some report a different address. - - return true ; -} - -bool p3PeerMgrIMPL::locked_computeCurrentBestOwnExtAddressCandidate(sockaddr_storage& addr, uint32_t& count) -{ - sockaddr_storage_clear(addr); - std::map addr_counts ; - - for(std::map::iterator it(mReportedOwnAddresses.begin());it!=mReportedOwnAddresses.end();++it) - ++addr_counts[it->second].n ; - -#ifdef PEER_DEBUG - std::cerr << "Current ext addr statistics:" << std::endl; -#endif - - count = 0 ; - - for(std::map::const_iterator it(addr_counts.begin());it!=addr_counts.end();++it) - { - if(uint32_t(it->second.n) > count) - { - addr = it->first ; - count = it->second.n ; - } - -#ifdef PEER_DEBUG - std::cerr << sockaddr_storage_iptostring(it->first) << " : " << it->second.n << std::endl; -#endif - } - - return count > 0 ; -} - -bool p3PeerMgrIMPL::getExtAddressReportedByFriends(sockaddr_storage &addr, uint8_t& /*isstable*/) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - uint32_t count =0; - - locked_computeCurrentBestOwnExtAddressCandidate(addr,count) ; - -#ifdef PEER_DEBUG - std::cerr << "Estimation count = " << count << ". Trusted? = " << (count>=2) << std::endl; -#endif - - return count >= 2 ;// 2 is not conservative enough. 3 should be probably better. -} - -static bool cleanIpList(std::list& lst,const RsPeerId& pid,p3LinkMgr *link_mgr) -{ - bool changed = false ; -#ifdef PEER_DEBUG - rstime_t now = time(NULL) ; -#endif - - for(std::list::iterator it2(lst.begin());it2 != lst.end();) - { -#ifdef PEER_DEBUG - std::cerr << "Checking IP address " << sockaddr_storage_iptostring( (*it2).mAddr) << " for peer " << pid << ", age = " << now - (*it2).mSeenTime << std::endl; -#else - /* remove unused parameter warnings */ - (void) pid; -#endif - if(!link_mgr->checkPotentialAddr((*it2).mAddr)) - { -#ifdef PEER_DEBUG - std::cerr << " (SS) Removing Banned/old IP address " << sockaddr_storage_iptostring( (*it2).mAddr) << " from peer " << pid << ", age = " << now - (*it2).mSeenTime << std::endl; -#endif - - std::list::iterator ittmp = it2 ; - ++ittmp ; - lst.erase(it2) ; - it2 = ittmp ; - - changed = true ; - } - else - ++it2 ; - } - - return changed ; -} - -bool p3PeerMgrIMPL::updateAddressList(const RsPeerId& id, const pqiIpAddrSet &addrs) -{ -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setAddressList() called for id : " << id << std::endl; -#endif - // first clean the list from potentially banned IPs. - - pqiIpAddrSet clean_set = addrs ; - - cleanIpList(clean_set.mExt.mAddrs,id,mLinkMgr) ; - cleanIpList(clean_set.mLocal.mAddrs,id,mLinkMgr) ; - - bool am_I_a_hidden_node = isHiddenNode(getOwnId()) ; - - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - /* check if it is our own ip */ - if (id == getOwnId()) - { - mOwnState.ipAddrs.updateAddrs(clean_set); - return true; - } - - /* check if it is a friend */ - std::map::iterator it; - if (mFriendList.end() == (it = mFriendList.find(id))) - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setLocalAddress() cannot add addres info : peer id not found in friend list. id: " << id << std::endl; -#endif - return false; - } - - /* "it" points to peer */ - - if(!am_I_a_hidden_node) - it->second.ipAddrs.updateAddrs(clean_set); - else - it->second.ipAddrs.clear(); - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setLocalAddress() Updated Address for: " << id; - std::cerr << std::endl; - std::string addrstr; - it->second.ipAddrs.printAddrs(addrstr); - std::cerr << addrstr; - std::cerr << std::endl; -#endif - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - return true; -} - - -bool p3PeerMgrIMPL::updateCurrentAddress(const RsPeerId& id, const pqiIpAddress &addr) -{ -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::updateCurrentAddress() called for id : " << id << std::endl; -#endif - - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - /* cannot be own id */ - - /* check if it is a friend */ - std::map::iterator it; - if (mFriendList.end() == (it = mFriendList.find(id))) - { - std::cerr << "p3PeerMgrIMPL::updateCurrentAddress() ERROR peer id not found: " << id << std::endl; - return false; - } - - if (sockaddr_storage_isPrivateNet(addr.mAddr)) - { - it->second.ipAddrs.updateLocalAddrs(addr); - it->second.localaddr = addr.mAddr; - } - else - { - it->second.ipAddrs.updateExtAddrs(addr); - it->second.serveraddr = addr.mAddr; - } - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::updatedCurrentAddress() Updated Address for: " << id; - std::cerr << std::endl; - std::string addrstr; - it->second.ipAddrs.printAddrs(addrstr); - std::cerr << addrstr; - std::cerr << std::endl; -#endif - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - return true; -} - - -bool p3PeerMgrIMPL::updateLastContact(const RsPeerId& id) -{ -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::updateLastContact() called for id : " << id << std::endl; -#endif - - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - /* cannot be own id */ - - /* check if it is a friend */ - std::map::iterator it; - if (mFriendList.end() == (it = mFriendList.find(id))) - { - std::cerr << "p3PeerMgrIMPL::updateLastContact() ERROR peer id not found: " << id << std::endl; - return false; - } - - it->second.lastcontact = time(NULL); - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - return true; -} - -bool p3PeerMgrIMPL::setNetworkMode(const RsPeerId &id, uint32_t netMode) -{ - if (id == AuthSSL::getAuthSSL()->OwnId()) - { - return setOwnNetworkMode(netMode); - } - - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - /* check if it is a friend */ - std::map::iterator it; - if (mFriendList.end() == (it = mFriendList.find(id))) - { - return false; - } - - bool changed = false; - - /* "it" points to peer */ - if (it->second.netMode != netMode) - { - it->second.netMode = netMode; - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - changed = true; - } - - return changed; -} - -bool p3PeerMgrIMPL::setLocation(const RsPeerId &id, const std::string &location) -{ - bool changed = false; - - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setLocation() called for id : " << id << "; with location " << location << std::endl; -#endif - if (id == AuthSSL::getAuthSSL()->OwnId()) - { - if (mOwnState.location.compare(location) != 0) { - mOwnState.location = location; - changed = true; - } - return changed; - } - - /* check if it is a friend */ - std::map::iterator it; - if (mFriendList.end() != (it = mFriendList.find(id))) { - if (it->second.location.compare(location) != 0) { - it->second.location = location; - changed = true; - } - } - return changed; -} - -bool p3PeerMgrIMPL::setVisState(const RsPeerId &id, uint16_t vs_disc, uint16_t vs_dht) -{ - { - std::string out; - rs_sprintf(out, "p3PeerMgr::setVisState(%s, %u, %u)", id.toStdString().c_str(), vs_disc, vs_dht); - rslog(RSL_WARNING, p3peermgrzone, out); - } - - if (id == AuthSSL::getAuthSSL()->OwnId()) - { - return setOwnVisState(vs_disc, vs_dht); - } - - bool isFriend = false; - bool changed = false; - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - /* check if it is a friend */ - std::map::iterator it; - if (mFriendList.end() == (it = mFriendList.find(id))) - { - return false; - } - else - { - isFriend = true; - } - - /* "it" points to peer */ - if ((it->second.vs_disc != vs_disc) || (it->second.vs_dht = vs_dht)) - { - it->second.vs_disc = vs_disc; - it->second.vs_dht = vs_dht; - changed = true; - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::setVisState(" << id << ", DISC: " << vs_disc << " DHT: " << vs_dht << ") "; - std::cerr << " NAME: " << it->second.name; - - switch(it->second.vs_disc) - { - default: - case RS_VS_DISC_OFF: - std::cerr << " NO-DISC "; - break; - case RS_VS_DISC_MINIMAL: - std::cerr << " MIN-DISC "; - break; - case RS_VS_DISC_FULL: - std::cerr << " FULL-DISC "; - break; - } - switch(it->second.vs_dht) - { - default: - case RS_VS_DHT_OFF: - std::cerr << " NO-DHT "; - break; - case RS_VS_DHT_PASSIVE: - std::cerr << " PASSIVE-DHT "; - break; - case RS_VS_DHT_FULL: - std::cerr << " FULL-DHT "; - break; - } - std::cerr << std::endl; -#endif - } - } - if(isFriend && changed) - { - mLinkMgr->setFriendVisibility(id, vs_dht != RS_VS_DHT_OFF); - } - - if (changed) { - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - } - - return changed; -} - - - - -/*******************************************************************/ - - -/********************************************************************** - ********************************************************************** - ******************** p3Config functions ****************************** - ********************************************************************** - **********************************************************************/ - - /* Key Functions to be overloaded for Full Configuration */ - -RsSerialiser *p3PeerMgrIMPL::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsPeerConfigSerialiser()); - rss->addSerialType(new RsGeneralConfigSerialiser()) ; - - return rss; -} - - -bool p3PeerMgrIMPL::saveList(bool &cleanup, std::list& saveData) -{ - /* create a list of current peers */ - cleanup = true; - bool useExtAddrFinder = mNetMgr->getIPServersEnabled(); - - /* gather these information before mPeerMtx is locked! */ - struct sockaddr_storage proxy_addr_tor, proxy_addr_i2p; - getProxyServerAddress(RS_HIDDEN_TYPE_TOR, proxy_addr_tor); - getProxyServerAddress(RS_HIDDEN_TYPE_I2P, proxy_addr_i2p); - - mPeerMtx.lock(); /****** MUTEX LOCKED *******/ - - RsPeerNetItem *item = new RsPeerNetItem(); - item->clear(); - - item->nodePeerId = getOwnId(); - item->pgpId = mOwnState.gpg_id; - item->location = mOwnState.location; - -#if 0 - if (mOwnState.netMode & RS_NET_MODE_TRY_EXT) - { - item->netMode = RS_NET_MODE_EXT; - } - else if (mOwnState.netMode & RS_NET_MODE_TRY_UPNP) - { - item->netMode = RS_NET_MODE_UPNP; - } - else - { - item->netMode = RS_NET_MODE_UDP; - } -#endif - item->netMode = mOwnState.netMode; - - item->vs_disc = mOwnState.vs_disc; - item->vs_dht = mOwnState.vs_dht; - - item->lastContact = mOwnState.lastcontact; - - item->localAddrV4.addr = mOwnState.localaddr; - item->extAddrV4.addr = mOwnState.serveraddr; - sockaddr_storage_clear(item->localAddrV6.addr); - sockaddr_storage_clear(item->extAddrV6.addr); - - item->dyndns = mOwnState.dyndns; - mOwnState.ipAddrs.mLocal.loadTlv(item->localAddrList); - mOwnState.ipAddrs.mExt.loadTlv(item->extAddrList); - item->domain_addr = mOwnState.hiddenDomain; - item->domain_port = mOwnState.hiddenPort; - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::saveList() Own Config Item:" << std::endl; - item->print(std::cerr, 10); - std::cerr << std::endl; -#endif - - saveData.push_back(item); - - /* iterate through all friends and save */ - std::map::iterator it; - for(it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - item = new RsPeerNetItem(); - item->clear(); - - item->nodePeerId = it->first; - item->pgpId = (it->second).gpg_id; - item->location = (it->second).location; - item->netMode = (it->second).netMode; - item->vs_disc = (it->second).vs_disc; - item->vs_dht = (it->second).vs_dht; - - item->lastContact = (it->second).lastcontact; - - item->localAddrV4.addr = (it->second).localaddr; - item->extAddrV4.addr = (it->second).serveraddr; - sockaddr_storage_clear(item->localAddrV6.addr); - sockaddr_storage_clear(item->extAddrV6.addr); - - - item->dyndns = (it->second).dyndns; - (it->second).ipAddrs.mLocal.loadTlv(item->localAddrList); - (it->second).ipAddrs.mExt.loadTlv(item->extAddrList); - - item->domain_addr = (it->second).hiddenDomain; - item->domain_port = (it->second).hiddenPort; - - saveData.push_back(item); -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::saveList() Peer Config Item:" << std::endl; - item->print(std::cerr, 10); - std::cerr << std::endl; -#endif - } - - RsPeerBandwidthLimitsItem *pblitem = new RsPeerBandwidthLimitsItem ; - pblitem->peers = mPeerBandwidthLimits ; - saveData.push_back(pblitem) ; - - RsPeerServicePermissionItem *sitem = new RsPeerServicePermissionItem ; - - for(std::map::const_iterator it(mFriendsPermissionFlags.begin());it!=mFriendsPermissionFlags.end();++it) - { - sitem->pgp_ids.push_back(it->first) ; - sitem->service_flags.push_back(it->second) ; - } - - saveData.push_back(sitem) ; - - // Now save config for network digging strategies - - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; - - RsTlvKeyValue kv; - kv.key = kConfigKeyExtIpFinder; - kv.value = (useExtAddrFinder)?"TRUE":"FALSE" ; - vitem->tlvkvs.pairs.push_back(kv) ; - - - // Store Proxy Server. - // Tor -#ifdef PEER_DEBUG - std::cerr << "Saving proxyServerAddress for Tor: " << sockaddr_storage_tostring(proxy_addr_tor); - std::cerr << std::endl; -#endif - - kv.key = kConfigKeyProxyServerIpAddrTor; - kv.value = sockaddr_storage_iptostring(proxy_addr_tor); - vitem->tlvkvs.pairs.push_back(kv) ; - - kv.key = kConfigKeyProxyServerPortTor; - kv.value = sockaddr_storage_porttostring(proxy_addr_tor); - vitem->tlvkvs.pairs.push_back(kv) ; - - // I2P -#ifdef PEER_DEBUG - std::cerr << "Saving proxyServerAddress for I2P: " << sockaddr_storage_tostring(proxy_addr_i2p); - std::cerr << std::endl; -#endif - - kv.key = kConfigKeyProxyServerIpAddrI2P; - kv.value = sockaddr_storage_iptostring(proxy_addr_i2p); - vitem->tlvkvs.pairs.push_back(kv) ; - - kv.key = kConfigKeyProxyServerPortI2P; - kv.value = sockaddr_storage_porttostring(proxy_addr_i2p); - vitem->tlvkvs.pairs.push_back(kv) ; - - saveData.push_back(vitem); - - /* save groups */ - - for ( std::map::iterator groupIt = groupList.begin(); groupIt != groupList.end(); ++groupIt) - { - RsNodeGroupItem *itm = new RsNodeGroupItem(groupIt->second); - saveData.push_back(itm) ; - } - - return true; -} - -bool p3PeerMgrIMPL::getMaxRates(const RsPeerId& pid,uint32_t& maxUp,uint32_t& maxDn) -{ - RsPgpId pgp_id ; - - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - std::map::const_iterator it = mFriendList.find(pid) ; - - if(it == mFriendList.end()) - { - maxUp = 0; - maxDn = 0; - return false ; - } - - pgp_id = it->second.gpg_id ; - } - - return getMaxRates(pgp_id,maxUp,maxDn) ; -} - -bool p3PeerMgrIMPL::getMaxRates(const RsPgpId& pid,uint32_t& maxUp,uint32_t& maxDn) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - std::map::const_iterator it2 = mPeerBandwidthLimits.find(pid) ; - - if(it2 != mPeerBandwidthLimits.end()) - { - maxUp = it2->second.max_up_rate_kbs ; - maxDn = it2->second.max_dl_rate_kbs ; - return true ; - } - else - { - maxUp = 0; - maxDn = 0; - return false ; - } -} -bool p3PeerMgrIMPL::setMaxRates(const RsPgpId& pid,uint32_t maxUp,uint32_t maxDn) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - PeerBandwidthLimits& p(mPeerBandwidthLimits[pid]) ; - - if(maxUp == p.max_up_rate_kbs && maxDn == p.max_dl_rate_kbs) - return true ; - - std::cerr << "Updating max rates for peer " << pid << " to " << maxUp << " kB/s (up), " << maxDn << " kB/s (dn)" << std::endl; - - p.max_up_rate_kbs = maxUp ; - p.max_dl_rate_kbs = maxDn ; - - IndicateConfigChanged(); - - return true ; -} - -void p3PeerMgrIMPL::saveDone() -{ - /* clean up the save List */ - std::list::iterator it; - for(it = saveCleanupList.begin(); it != saveCleanupList.end(); ++it) - { - delete (*it); - } - - saveCleanupList.clear(); - - /* unlock mutex */ - mPeerMtx.unlock(); /****** MUTEX UNLOCKED *******/ -} - -bool p3PeerMgrIMPL::loadList(std::list& load) -{ - // DEFAULTS. - bool useExtAddrFinder = true; - std::string proxyIpAddressTor = kConfigDefaultProxyServerIpAddr; - uint16_t proxyPortTor = kConfigDefaultProxyServerPortTor; - std::string proxyIpAddressI2P = kConfigDefaultProxyServerIpAddr; - uint16_t proxyPortI2P = kConfigDefaultProxyServerPortI2P; - - if (load.empty()) { - std::cerr << "p3PeerMgrIMPL::loadList() list is empty, it may be a configuration problem." << std::endl; - return false; - } - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::loadList() Item Count: " << load.size() << std::endl; -#endif - - RsPeerId ownId = getOwnId(); - bool am_I_a_hidden_node = isHiddenNode(ownId) ; - - /* load the list of peers */ - std::list::iterator it; - for(it = load.begin(); it != load.end(); ++it) - { - RsPeerNetItem *pitem = dynamic_cast(*it); - if (pitem) - { - RsPeerId peer_id = pitem->nodePeerId ; - RsPgpId peer_pgp_id = pitem->pgpId ; - - if (peer_id == ownId) - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::loadList() Own Config Item:" << std::endl; - pitem->print(std::cerr, 10); - std::cerr << std::endl; -#endif - /* add ownConfig */ - setOwnNetworkMode(pitem->netMode); - setOwnVisState(pitem->vs_disc, pitem->vs_dht); - - mOwnState.gpg_id = AuthPGP::getPgpOwnId(); - mOwnState.location = AuthSSL::getAuthSSL()->getOwnLocation(); - } - else - { -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::loadList() Peer Config Item:" << std::endl; - pitem->print(std::cerr, 10); - std::cerr << std::endl; -#endif - /* ************* */ - // permission flags is used as a mask for the existing perms, so we set it to 0xffff - - RsPeerDetails det ; - if(!rsPeers->getGPGDetails(peer_pgp_id,det)) - { - // would be better to add flags into RsPeerNetItem so that we already have this information. However, it's possible that the PGP key - // has been added in the meantime, so the peer would be loaded with the right pGP key attached. - - RsInfo() << __PRETTY_FUNCTION__ << " loading SSL-only " << "friend: " << peer_id << " " << pitem->location << std::endl; - addSslOnlyFriend(peer_id,peer_pgp_id); - } - else if(!addFriend( peer_id, peer_pgp_id, pitem->netMode, pitem->vs_disc, pitem->vs_dht, pitem->lastContact, RS_NODE_PERM_ALL )) - { - RsInfo() << __PRETTY_FUNCTION__ << " cannot add friend friend: " << peer_id << " " << pitem->location << ". Somthing's wrong." << std::endl; - } - setLocation(pitem->nodePeerId, pitem->location); - } - - if (pitem->netMode == RS_NET_MODE_HIDDEN) - { - /* set only the hidden stuff & localAddress */ - setLocalAddress(peer_id, pitem->localAddrV4.addr); - setHiddenDomainPort(peer_id, pitem->domain_addr, pitem->domain_port); - - } - else - { - pqiIpAddrSet addrs; - - if(!am_I_a_hidden_node) // clear IPs if w're a hidden node. Friend's clear node IPs where previously sent. - { - setLocalAddress(peer_id, pitem->localAddrV4.addr); - setExtAddress(peer_id, pitem->extAddrV4.addr); - setDynDNS (peer_id, pitem->dyndns); - - /* convert addresses */ - addrs.mLocal.extractFromTlv(pitem->localAddrList); - addrs.mExt.extractFromTlv(pitem->extAddrList); - } - - updateAddressList(peer_id, addrs); - } - - delete(*it); - - continue; - } - - RsConfigKeyValueSet *vitem = dynamic_cast(*it) ; - if (vitem) - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::loadList() General Variable Config Item:" << std::endl; - vitem->print(std::cerr, 10); - std::cerr << std::endl; -#endif - std::list::iterator kit; - for(kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) - { - if (kit->key == kConfigKeyExtIpFinder) - { - useExtAddrFinder = (kit->value == "TRUE"); -#ifdef PEER_DEBUG - std::cerr << "setting use_extr_addr_finder to " << useExtAddrFinder << std::endl ; -#endif - } - // Tor - else if (kit->key == kConfigKeyProxyServerIpAddrTor) - { - proxyIpAddressTor = kit->value; -#ifdef PEER_DEBUG - std::cerr << "Loaded proxyIpAddress for Tor: " << proxyIpAddressTor; - std::cerr << std::endl ; -#endif - - } - else if (kit->key == kConfigKeyProxyServerPortTor) - { - uint16_t p = atoi(kit->value.c_str()); - - if(p >= 1024) - proxyPortTor = p; -#ifdef PEER_DEBUG - std::cerr << "Loaded proxyPort for Tor: " << proxyPortTor; - std::cerr << std::endl ; -#endif - } - // I2p - else if (kit->key == kConfigKeyProxyServerIpAddrI2P) - { - proxyIpAddressI2P = kit->value; -#ifdef PEER_DEBUG - std::cerr << "Loaded proxyIpAddress for I2P: " << proxyIpAddressI2P; - std::cerr << std::endl ; -#endif - } - else if (kit->key == kConfigKeyProxyServerPortI2P) - { - uint16_t p = atoi(kit->value.c_str()); - - if(p >= 1024) - proxyPortI2P = p; -#ifdef PEER_DEBUG - std::cerr << "Loaded proxyPort for I2P: " << proxyPortI2P; - std::cerr << std::endl ; -#endif - } - } - - delete(*it); - - continue; - } - - RsNodeGroupItem *gitem2 = dynamic_cast(*it) ; - - if (gitem2) - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgrIMPL::loadList() Peer group item:" << std::endl; - gitem->print(std::cerr, 10); - std::cerr << std::endl; -#endif - RsGroupInfo info ; - info.peerIds = gitem2->pgpList.ids ; - info.id = gitem2->id ; - info.name = gitem2->name ; - info.flag = gitem2->flag ; - - std::cerr << "(II) Loaded group in new format. ID = " << info.id << std::endl; - groupList[info.id] = info ; - - delete *it ; - continue; - } - RsPeerBandwidthLimitsItem *pblitem = dynamic_cast(*it) ; - - if(pblitem) - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - -#ifdef PEER_DEBUG - std::cerr << "Loaded service permission item: " << std::endl; -#endif - mPeerBandwidthLimits = pblitem->peers ; - } - RsPeerServicePermissionItem *sitem = dynamic_cast(*it) ; - - if(sitem) - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - -#ifdef PEER_DEBUG - std::cerr << "Loaded service permission item: " << std::endl; -#endif - - for(uint32_t i=0;ipgp_ids.size();++i) - if(AuthPGP::isPGPAccepted(sitem->pgp_ids[i]) || sitem->pgp_ids[i] == AuthPGP::getPgpOwnId()) - { - mFriendsPermissionFlags[sitem->pgp_ids[i]] = sitem->service_flags[i] ; -#ifdef PEER_DEBUG - std::cerr << " " << sitem->pgp_ids[i] << " - " << sitem->service_flags[i] << std::endl; -#endif - } -#ifdef PEER_DEBUG - else - std::cerr << " " << sitem->pgp_ids[i] << " - Not a friend!" << std::endl; -#endif - } - - delete (*it); - } - - { - /* set missing groupIds */ - - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - /* Standard groups */ - const int standardGroupCount = 5; - const RsNodeGroupId standardGroupIds [standardGroupCount] = { RS_GROUP_ID_FRIENDS, RS_GROUP_ID_FAMILY, RS_GROUP_ID_COWORKERS, RS_GROUP_ID_OTHERS, RS_GROUP_ID_FAVORITES }; - const char *standardGroupNames[standardGroupCount] = { RS_GROUP_DEFAULT_NAME_FRIENDS, RS_GROUP_DEFAULT_NAME_FAMILY, RS_GROUP_DEFAULT_NAME_COWORKERS, RS_GROUP_DEFAULT_NAME_OTHERS, RS_GROUP_DEFAULT_NAME_FAVORITES }; - - for(uint32_t k=0;ktoStdString() << " from group " << group_pair.first.toStdString() << " because it is not a friend anymore" << std::endl; - - auto tmp = profileIdIt; - ++tmp; - group_pair.second.peerIds.erase(profileIdIt); - profileIdIt=tmp; - - IndicateConfigChanged(); - } - } - } - - // If we are hidden - don't want ExtAddrFinder - ever! - if (isHidden()) - useExtAddrFinder = false; - - mNetMgr->setIPServersEnabled(useExtAddrFinder); - - // Configure Proxy Server. - struct sockaddr_storage proxy_addr; - // Tor - sockaddr_storage_clear(proxy_addr); - sockaddr_storage_ipv4_aton(proxy_addr, proxyIpAddressTor.c_str()); - sockaddr_storage_ipv4_setport(proxy_addr, proxyPortTor); - - if (sockaddr_storage_isValidNet(proxy_addr)) - { - setProxyServerAddress(RS_HIDDEN_TYPE_TOR, proxy_addr); - } - - // I2P - sockaddr_storage_clear(proxy_addr); - sockaddr_storage_ipv4_aton(proxy_addr, proxyIpAddressI2P.c_str()); - sockaddr_storage_ipv4_setport(proxy_addr, proxyPortI2P); - - if (sockaddr_storage_isValidNet(proxy_addr)) - { - setProxyServerAddress(RS_HIDDEN_TYPE_I2P, proxy_addr); - } - - load.clear() ; - return true; -} - - -#if 0 - -void printConnectState(std::ostream &out, peerState &peer) -{ - - out << "Friend: " << peer.name << " Id: " << peer.id << " State: " << peer.state; - if (peer.state & RS_PEER_S_FRIEND) - out << " S:RS_PEER_S_FRIEND"; - if (peer.state & RS_PEER_S_ONLINE) - out << " S:RS_PEER_S_ONLINE"; - if (peer.state & RS_PEER_S_CONNECTED) - out << " S:RS_PEER_S_CONNECTED"; - out << " Actions: " << peer.actions; - if (peer.actions & RS_PEER_NEW) - out << " A:RS_PEER_NEW"; - if (peer.actions & RS_PEER_MOVED) - out << " A:RS_PEER_MOVED"; - if (peer.actions & RS_PEER_CONNECTED) - out << " A:RS_PEER_CONNECTED"; - if (peer.actions & RS_PEER_DISCONNECTED) - out << " A:RS_PEER_DISCONNECTED"; - if (peer.actions & RS_PEER_CONNECT_REQ) - out << " A:RS_PEER_CONNECT_REQ"; - - out << std::endl; - return; -} - -#endif - - -/********************************************************************** - ********************************************************************** - ************************** Groups ************************************ - ********************************************************************** - **********************************************************************/ - -bool p3PeerMgrIMPL::addGroup(RsGroupInfo &groupInfo) -{ - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - do { groupInfo.id = RsNodeGroupId::random(); } while(groupList.find(groupInfo.id) != groupList.end()) ; - - RsGroupInfo groupItem(groupInfo) ; - - // remove standard flag - - groupItem.flag &= ~RS_GROUP_FLAG_STANDARD; - groupList[groupInfo.id] = groupItem; - - std::cerr << "(II) Added new group with ID " << groupInfo.id << ", name=\"" << groupInfo.name << "\"" << std::endl; - } - - RsServer::notify()->notifyListChange(NOTIFY_LIST_GROUPLIST, NOTIFY_TYPE_ADD); - - IndicateConfigChanged(); - - return true; -} - -bool p3PeerMgrIMPL::editGroup(const RsNodeGroupId& groupId, RsGroupInfo &groupInfo) -{ - if (groupId.isNull()) - return false; - - bool changed = false; - - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - std::map::iterator it = groupList.find(groupId) ; - - if(it == groupList.end()) - { - std::cerr << "(EE) cannot find local node group with ID " << groupId << std::endl; - return false ; - } - - if (it->second.flag & RS_GROUP_FLAG_STANDARD) - { - // can't edit standard groups - std::cerr << "(EE) cannot edit standard group with ID " << groupId << std::endl; - return false ; - } - else - { - changed = true; - it->second = groupInfo; - } - } - - if (changed) - { - RsServer::notify()->notifyListChange(NOTIFY_LIST_GROUPLIST, NOTIFY_TYPE_MOD); - - IndicateConfigChanged(); - } - - return changed; -} - -bool p3PeerMgrIMPL::removeGroup(const RsNodeGroupId& groupId) -{ - bool changed = false; - - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - std::map::iterator it = groupList.find(groupId) ; - - if (it != groupList.end()) { - if (it->second.flag & RS_GROUP_FLAG_STANDARD) - { - // can't remove standard groups - std::cerr << "(EE) cannot remove standard group with ID " << groupId << std::endl; - return false ; - } -#warning csoler: we need to check that the local group is not used. Otherwise deleting it is going to cause problems! -// else if(!it->second.used_gxs_groups.empty()) -// { -// std::cerr << "(EE) cannot remove standard group with ID " << groupId << " because it is used in the following groups: " << std::endl; -// for(std::set::const_iterator it2(it->second.used_gxs_groups.begin());it2!=it->second.used_gxs_groups.end();++it2) -// std::cerr << " " << *it2 << std::endl; -// -// return false ; -// } - else - { - changed = true; - groupList.erase(it); - } - } - } - - if (changed) { - RsServer::notify()->notifyListChange(NOTIFY_LIST_GROUPLIST, NOTIFY_TYPE_DEL); - - IndicateConfigChanged(); - } - - return changed; -} - -bool p3PeerMgrIMPL::getGroupInfoByName(const std::string& groupName, RsGroupInfo &groupInfo) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - for(std::map::iterator it = groupList.begin();it!=groupList.end();++it) - if(it->second.name == groupName) - { - groupInfo = it->second ; - return true ; - } - - std::cerr << "(EE) getGroupInfoByName: no known group for name " << groupName << std::endl; - return false ; -} -bool p3PeerMgrIMPL::getGroupInfo(const RsNodeGroupId& groupId, RsGroupInfo &groupInfo) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - std::map::iterator it = groupList.find(groupId) ; - - if(it == groupList.end()) - return false ; - - groupInfo = it->second; - - return true; -} - -bool p3PeerMgrIMPL::getGroupInfoList(std::list& groupInfoList) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - for(std::map ::const_iterator groupIt = groupList.begin(); groupIt != groupList.end(); ++groupIt) - groupInfoList.push_back(groupIt->second) ; - - return true; -} - -// groupId.isNull() && assign == false -> remove from all groups - -bool p3PeerMgrIMPL::assignPeersToGroup(const RsNodeGroupId &groupId, const std::list &peerIds, bool assign) -{ - if (groupId.isNull() && assign == true) - return false; - - if (peerIds.empty()) - return false; - - bool changed = false; - - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - for (std::map::iterator groupIt = groupList.begin(); groupIt != groupList.end(); ++groupIt) - if (groupId.isNull() || groupIt->first == groupId) - { - RsGroupInfo& groupItem = groupIt->second; - - for (std::list::const_iterator peerIt = peerIds.begin(); peerIt != peerIds.end(); ++peerIt) - { - //std::set::iterator peerIt1 = groupItem.peerIds.find(*peerIt); - - if (assign) - { - groupItem.peerIds.insert(*peerIt); - changed = true; - } - else - { - groupItem.peerIds.erase(*peerIt); - changed = true; - } - } - - if (!groupId.isNull()) - break; - } - } - - if (changed) { - RsServer::notify()->notifyListChange(NOTIFY_LIST_GROUPLIST, NOTIFY_TYPE_MOD); - - IndicateConfigChanged(); - } - - return changed; -} - - -/********************************************************************** - ********************************************************************** - ******************** Service permission stuff ************************ - ********************************************************************** - **********************************************************************/ - -ServicePermissionFlags p3PeerMgrIMPL::servicePermissionFlags(const RsPeerId& ssl_id) -{ - RsPgpId gpg_id ; - - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - std::map::const_iterator it = mFriendList.find(ssl_id); - - if(it == mFriendList.end()) - return RS_NODE_PERM_DEFAULT ; - - gpg_id = it->second.gpg_id ; - } - - return servicePermissionFlags(gpg_id) ; -} - - -ServicePermissionFlags p3PeerMgrIMPL::servicePermissionFlags(const RsPgpId& pgp_id) -{ - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - std::map::const_iterator it = mFriendsPermissionFlags.find( pgp_id ) ; - - if(it == mFriendsPermissionFlags.end()) - return RS_NODE_PERM_DEFAULT ; - else - return it->second ; - } -} -void p3PeerMgrIMPL::setServicePermissionFlags(const RsPgpId& pgp_id, const ServicePermissionFlags& flags) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - // Check that we have a PGP id. This should not be necessary, but because - // we use std::string, anything can get passed down here. - // - - mFriendsPermissionFlags[pgp_id] = flags ; - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ -} - -/********************************************************************** - ********************************************************************** - ******************** Stuff moved from p3peers ************************ - ********************************************************************** - **********************************************************************/ - -bool p3PeerMgrIMPL::removeAllFriendLocations(const RsPgpId &gpgid) -{ - std::list sslIds; - if (!getAssociatedPeers(gpgid, sslIds)) - { - return false; - } - - std::list::iterator it; - for(it = sslIds.begin(); it != sslIds.end(); ++it) - { - removeFriend(*it, true); - } - - return true; -} - - -bool p3PeerMgrIMPL::getAssociatedPeers(const RsPgpId &gpg_id, std::list &ids) -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgr::getAssociatedPeers() for id : " << gpg_id << std::endl; -#endif - - int count = 0; - std::map::iterator it; - for(it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - if (it->second.gpg_id == gpg_id) - { - count++; - ids.push_back(it->first); - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgr::getAssociatedPeers() found ssl id : " << it->first << std::endl; -#endif - - } - } - - return (count > 0); -} - -// goes through the list of known friend IPs and remove the ones that are banned by p3LinkMgr. - - -bool p3PeerMgrIMPL::removeBannedIps() -{ - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - -#ifdef PEER_DEBUG - std::cerr << "Cleaning known IPs for all peers." << std::endl; -#endif - - bool changed = false ; - for( std::map::iterator it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - if(cleanIpList(it->second.ipAddrs.mExt.mAddrs,it->first,mLinkMgr)) changed = true ; - if(cleanIpList(it->second.ipAddrs.mLocal.mAddrs,it->first,mLinkMgr)) changed = true ; - - if(rsBanList!=NULL && !rsBanList->isAddressAccepted(it->second.serveraddr,RSBANLIST_CHECKING_FLAGS_BLACKLIST)) - { - sockaddr_storage_clear(it->second.serveraddr) ; - std::cerr << "(SS) Peer " << it->first << " has a banned server address. Wiping it out." << std::endl; - } - } - - if(cleanIpList(mOwnState.ipAddrs.mExt.mAddrs,mOwnState.id,mLinkMgr) ) changed = true ; - if(cleanIpList(mOwnState.ipAddrs.mLocal.mAddrs,mOwnState.id,mLinkMgr) ) changed = true ; - - if(changed) - IndicateConfigChanged(); - - return true ; -} - -// /* This only removes SSL certs, that are old... Can end up with no Certs per GPG Id -// * We are removing the concept of a "DummyId" - There is no need for it. -// */ -// -// bool isDummyFriend(RsPeerId id) -// { -// bool ret = (id.substr(0,5) == "dummy"); -// return ret; -// } - -/** - * @brief p3PeerMgrIMPL::removeUnusedLocations Removes all location offline for RS_PEER_OFFLINE_DELETE seconds or more. Keeps the most recent location per PGP id. - * @return true on success - * - * This function removes all location that are offline for too long defined by RS_PEER_OFFLINE_DELETE. - * It also makes sure that at least one location (the most recent) is kept. - * - * The idea of the function is the following: - * - keep track if there is at least one location per PGP id that is not offline for too long - * -> hasRecentLocation - * - keep track of most recent location per PGP id that is offline for too long (and its time stamp) - * -> mostRecentLocation - * -> mostRecentTime - * - * When a location is found that is offline for too long the following points are checked from the top to the bottom: - * 1) remove it when the PGP id has a location that is not offline for too long - * 2) remove it when the PGP id has a more recent location - * 3) keep it when it is the most recent location - * This location will possibly be removed when a more recent (but still offline for too long) is found - */ -bool p3PeerMgrIMPL::removeUnusedLocations() -{ - std::list toRemove; - std::map mostRecentTime; - - const rstime_t now = time(NULL); - - std::list pgpList ; - - if (!rsPeers->getGPGAcceptedList(pgpList)) - return false ; - - { - RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/ - - // First put a sensible number in all PGP ids - - for(std::list::const_iterator it = pgpList.begin(); it != pgpList.end(); ++it) - mostRecentTime[*it] = (rstime_t)0; - -#ifdef PEER_DEBUG - std::cerr << "p3PeerMgr::removeUnusedLocations()" << std::endl; -#endif - // Then compute the most recently used location for all PGP ids - - for( std::map::iterator it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - rstime_t& bst(mostRecentTime[it->second.gpg_id]) ; - bst = std::max(bst,it->second.lastcontact) ; - } - - // And remove all locations that are too old and also older than the most recent location. Doing this we're sure to always keep at least one location per PGP id. - - for( std::map::iterator it = mFriendList.begin(); it != mFriendList.end(); ++it) - { - if (now > it->second.lastcontact + RS_PEER_OFFLINE_DELETE && it->second.lastcontact < mostRecentTime[it->second.gpg_id]) - toRemove.push_back(it->first); -#ifdef PEER_DEBUG - std::cerr << "Location " << it->first << " PGP id " << it->second.gpg_id << " last contact " << it->second.lastcontact << " remove: " << (now > it->second.lastcontact + RS_PEER_OFFLINE_DELETE) << " most recent: " << mostRecentTime[it->second.gpg_id] - << ". Final result remove: " << (it->second.lastcontact < mostRecentTime[it->second.gpg_id] && now > it->second.lastcontact + RS_PEER_OFFLINE_DELETE )<< std::endl; -#endif - } - } - - for (std::list::iterator it = toRemove.begin(); it != toRemove.end(); ++it) - removeFriend(*it, false) ; - - return true; -} - -p3PeerMgr::~p3PeerMgr() = default; diff --git a/libretroshare/src/pqi/p3peermgr.h b/libretroshare/src/pqi/p3peermgr.h deleted file mode 100644 index 2cc9e4888..000000000 --- a/libretroshare/src/pqi/p3peermgr.h +++ /dev/null @@ -1,431 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3peermgr.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2007-2011 Robert Fernie * - * Copyright (C) 2015-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_PEER_MANAGER_HEADER -#define MRK_PQI_PEER_MANAGER_HEADER - -#include -#include "pqi/pqimonitor.h" -#include "pqi/pqiipset.h" -#include "pqi/pqiassist.h" - -#include "pqi/p3cfgmgr.h" - -#include "util/rsthreads.h" - -/* RS_VIS_STATE -> specified in rspeers.h - */ - - /* Startup Modes (confirmed later) */ -const uint32_t RS_NET_MODE_TRYMODE = 0xff00; - -const uint32_t RS_NET_MODE_TRY_EXT = 0x0100; -const uint32_t RS_NET_MODE_TRY_UPNP = 0x0200; -const uint32_t RS_NET_MODE_TRY_UDP = 0x0400; -const uint32_t RS_NET_MODE_TRY_LOOPBACK = 0x0800; - - /* Actual State */ -const uint32_t RS_NET_MODE_ACTUAL = 0x00ff; - -const uint32_t RS_NET_MODE_UNKNOWN = 0x0000; -const uint32_t RS_NET_MODE_EXT = 0x0001; -const uint32_t RS_NET_MODE_UPNP = 0x0002; -const uint32_t RS_NET_MODE_UDP = 0x0004; -const uint32_t RS_NET_MODE_HIDDEN = 0x0008; -const uint32_t RS_NET_MODE_UNREACHABLE = 0x0010; - - -/* flags of peerStatus */ -const uint32_t RS_NET_FLAGS_USE_DISC = 0x0001; -const uint32_t RS_NET_FLAGS_USE_DHT = 0x0002; -const uint32_t RS_NET_FLAGS_ONLINE = 0x0004; -const uint32_t RS_NET_FLAGS_EXTERNAL_ADDR = 0x0008; -const uint32_t RS_NET_FLAGS_STABLE_UDP = 0x0010; -const uint32_t RS_NET_FLAGS_TRUSTS_ME = 0x0020; - -/* - * remove locations offline since 90 days - * stopt sending locations via discovery when offline for +30 days - */ -const rstime_t RS_PEER_OFFLINE_DELETE = (90 * 24 * 3600); -const rstime_t RS_PEER_OFFLINE_NO_DISC = (30 * 24 * 3600); - -class peerState -{ - public: - peerState(); /* init */ - - RsPeerId id; - RsPgpId gpg_id; - - // This flag is used when adding a single SSL cert as friend without adding its PGP key in the friend list. This allows to - // have short invites. However, because this represent a significant security risk, we perform multiple consistency checks - // whenever we use this flag, in particular: - // flat is true <==> friend SSL cert is in the friend list, but PGP id is not in the friend list - - bool skip_pgp_signature_validation; - - uint32_t netMode; /* EXT / UPNP / UDP / HIDDEN / INVALID */ - /* visState */ - uint16_t vs_disc; - uint16_t vs_dht; - - struct sockaddr_storage localaddr; - struct sockaddr_storage serveraddr; - std::string dyndns; - - rstime_t lastcontact; - - /* list of addresses from various sources */ - pqiIpAddrSet ipAddrs; - - bool hiddenNode; /* all IP addresses / dyndns must be blank */ - std::string hiddenDomain; - uint16_t hiddenPort; - uint32_t hiddenType; - - std::string location; - std::string name; - - uint32_t maxUpRate ; - uint32_t maxDnRate ; -}; - -class RsNodeGroupItem; -struct RsGroupInfo; - -class p3LinkMgr; -class p3NetMgr; - -class p3LinkMgrIMPL; -class p3NetMgrIMPL; - -class p3PeerMgr -{ -public: - virtual bool addFriend( const RsPeerId &ssl_id, const RsPgpId &gpg_id, - uint32_t netMode = RS_NET_MODE_UDP, - uint16_t vsDisc = RS_VS_DISC_FULL, - uint16_t vsDht = RS_VS_DHT_FULL, - rstime_t lastContact = 0, - ServicePermissionFlags = ServicePermissionFlags(RS_NODE_PERM_DEFAULT) ) = 0; - - virtual bool addSslOnlyFriend( - const RsPeerId& sslId, - const RsPgpId& pgpId, - const RsPeerDetails& details = RsPeerDetails() ) = 0; - - // Calling this removed the skip_pgp_signature_validation flag on all peers which PGP key is the one supplied. - virtual bool notifyPgpKeyReceived(const RsPgpId& pgp_key_id) = 0; - - virtual bool removeFriend(const RsPeerId &ssl_id, bool removePgpId) = 0; - virtual bool isFriend(const RsPeerId& ssl_id) = 0; - virtual bool isSslOnlyFriend(const RsPeerId &ssl_id)=0; - -virtual bool getAssociatedPeers(const RsPgpId &gpg_id, std::list &ids) = 0; -virtual bool removeAllFriendLocations(const RsPgpId &gpgid) = 0; - - - /******************** Groups **********************/ - /* This is solely used by p3peers - makes sense */ - -virtual bool addGroup(RsGroupInfo &groupInfo) = 0; -virtual bool editGroup(const RsNodeGroupId &groupId, RsGroupInfo &groupInfo) = 0; -virtual bool removeGroup(const RsNodeGroupId &groupId) = 0; -virtual bool getGroupInfo(const RsNodeGroupId &groupId, RsGroupInfo &groupInfo) = 0; -virtual bool getGroupInfoByName(const std::string& groupName, RsGroupInfo &groupInfo) = 0; -virtual bool getGroupInfoList(std::list &groupInfoList) = 0; -virtual bool assignPeersToGroup(const RsNodeGroupId &groupId, const std::list &peerIds, bool assign) = 0; - - virtual bool resetOwnExternalAddressList() = 0 ; - - virtual ServicePermissionFlags servicePermissionFlags(const RsPgpId& gpg_id) =0; - virtual ServicePermissionFlags servicePermissionFlags(const RsPeerId& ssl_id) =0; - virtual void setServicePermissionFlags(const RsPgpId& gpg_id,const ServicePermissionFlags& flags) =0; - - /**************** Set Net Info ****************/ - /* - * These functions are used by: - * 1) p3linkmgr - * 2) p3peers - reasonable - * 3) p3disc - reasonable - */ - - virtual bool addPeerLocator(const RsPeerId &ssl_id, const RsUrl& locator) = 0; -virtual bool setLocalAddress(const RsPeerId &id, const struct sockaddr_storage &addr) = 0; -virtual bool setExtAddress(const RsPeerId &id, const struct sockaddr_storage &addr) = 0; -virtual bool setDynDNS(const RsPeerId &id, const std::string &dyndns) = 0; -virtual bool addCandidateForOwnExternalAddress(const RsPeerId& from, const struct sockaddr_storage &addr) = 0; -virtual bool getExtAddressReportedByFriends(struct sockaddr_storage& addr,uint8_t& isstable) = 0; - -virtual bool setNetworkMode(const RsPeerId &id, uint32_t netMode) = 0; -virtual bool setVisState(const RsPeerId &id, uint16_t vs_disc, uint16_t vs_dht) = 0; - -virtual bool setLocation(const RsPeerId &pid, const std::string &location) = 0; -virtual bool setHiddenDomainPort(const RsPeerId &id, const std::string &domain_addr, const uint16_t domain_port) = 0; -virtual bool isHiddenNode(const RsPeerId& id) = 0 ; - -virtual bool updateCurrentAddress(const RsPeerId& id, const pqiIpAddress &addr) = 0; -virtual bool updateLastContact(const RsPeerId& id) = 0; -virtual bool updateAddressList(const RsPeerId& id, const pqiIpAddrSet &addrs) = 0; - - - // THIS MUST ONLY BE CALLED BY NETMGR!!!! -virtual bool UpdateOwnAddress(const struct sockaddr_storage &local_addr, const struct sockaddr_storage &ext_addr) = 0; - - /**************** Net Status Info ****************/ - /* - * MUST RATIONALISE THE DATA FROM THESE FUNCTIONS - * These functions are used by: - * 1) p3face-config ... to remove! - * 2) p3peers - reasonable - * 3) p3disc - reasonable - */ - -virtual bool getOwnNetStatus(peerState &state) = 0; -virtual bool getFriendNetStatus(const RsPeerId &id, peerState &state) = 0; - -virtual bool getPeerName(const RsPeerId &ssl_id, std::string &name) = 0; -virtual bool getGpgId(const RsPeerId &sslId, RsPgpId &gpgId) = 0; -virtual uint32_t getConnectionType(const RsPeerId &sslId) = 0; - -virtual bool setProxyServerAddress(const uint32_t type, const struct sockaddr_storage &proxy_addr) = 0; -virtual bool getProxyServerAddress(const uint32_t type, struct sockaddr_storage &proxy_addr) = 0; -virtual bool getProxyServerStatus(const uint32_t type, uint32_t& status) = 0; -virtual bool isHidden() = 0; -virtual bool isHidden(const uint32_t type) = 0; -virtual bool isHiddenPeer(const RsPeerId &ssl_id) = 0; -virtual bool isHiddenPeer(const RsPeerId &ssl_id, const uint32_t type) = 0; -virtual bool getProxyAddress(const RsPeerId &ssl_id, struct sockaddr_storage &proxy_addr, std::string &domain_addr, uint16_t &domain_port) = 0; -virtual uint32_t hiddenDomainToHiddenType(const std::string &domain) = 0; -virtual uint32_t getHiddenType(const RsPeerId &ssl_id) = 0; - - -virtual int getFriendCount(bool ssl, bool online) = 0; -virtual bool setMaxRates(const RsPgpId& pid,uint32_t maxUp,uint32_t maxDn)=0; -virtual bool getMaxRates(const RsPgpId& pid,uint32_t& maxUp,uint32_t& maxDn)=0; -virtual bool getMaxRates(const RsPeerId& pid,uint32_t& maxUp,uint32_t& maxDn)=0; - - /************* DEPRECIATED FUNCTIONS (TO REMOVE) ********/ - - // Single Use Function... shouldn't be here. used by p3serverconfig.cc -virtual bool haveOnceConnected() = 0; - -virtual bool locked_computeCurrentBestOwnExtAddressCandidate(sockaddr_storage &addr, uint32_t &count)=0; - -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ -/*************************************************************************************************/ - - virtual ~p3PeerMgr(); -}; - - -class p3PeerMgrIMPL: public p3PeerMgr, public p3Config -{ -public: - - /************************************************************************************************/ - /* EXTERNAL INTERFACE */ - /************************************************************************************************/ - - virtual bool addFriend(const RsPeerId&ssl_id, const RsPgpId&gpg_id, uint32_t netMode = RS_NET_MODE_UDP, - uint16_t vsDisc = RS_VS_DISC_FULL, uint16_t vsDht = RS_VS_DHT_FULL, - rstime_t lastContact = 0,ServicePermissionFlags = ServicePermissionFlags(RS_NODE_PERM_DEFAULT)); - - bool addSslOnlyFriend(const RsPeerId& sslId, const RsPgpId &pgp_id, const RsPeerDetails& details = RsPeerDetails() ) override; - - virtual bool notifyPgpKeyReceived(const RsPgpId& pgp_key_id) override; - - virtual bool removeFriend(const RsPeerId &ssl_id, bool removePgpId); - virtual bool removeFriend(const RsPgpId &pgp_id); - - virtual bool isFriend(const RsPeerId &ssl_id); - virtual bool isSslOnlyFriend(const RsPeerId &ssl_id); - - virtual bool getAssociatedPeers(const RsPgpId &gpg_id, std::list &ids); - virtual bool removeAllFriendLocations(const RsPgpId &gpgid); - - - /******************** Groups **********************/ - /* This is solely used by p3peers - makes sense */ - - virtual bool addGroup(RsGroupInfo &groupInfo); - virtual bool editGroup(const RsNodeGroupId &groupId, RsGroupInfo &groupInfo); - virtual bool removeGroup(const RsNodeGroupId &groupId); - virtual bool getGroupInfo(const RsNodeGroupId &groupId, RsGroupInfo &groupInfo); - virtual bool getGroupInfoByName(const std::string& groupName, RsGroupInfo &groupInfo) ; - virtual bool getGroupInfoList(std::list &groupInfoList); - virtual bool assignPeersToGroup(const RsNodeGroupId &groupId, const std::list &peerIds, bool assign); - - virtual ServicePermissionFlags servicePermissionFlags(const RsPgpId& gpg_id) ; - virtual ServicePermissionFlags servicePermissionFlags(const RsPeerId& ssl_id) ; - virtual void setServicePermissionFlags(const RsPgpId& gpg_id,const ServicePermissionFlags& flags) ; - - /**************** Set Net Info ****************/ - /* - * These functions are used by: - * 1) p3linkmgr - * 2) p3peers - reasonable - * 3) p3disc - reasonable - */ - - virtual bool addPeerLocator(const RsPeerId &ssl_id, const RsUrl& locator); - virtual bool setLocalAddress(const RsPeerId &id, const struct sockaddr_storage &addr); - virtual bool setExtAddress(const RsPeerId &id, const struct sockaddr_storage &addr); - virtual bool setDynDNS(const RsPeerId &id, const std::string &dyndns); - virtual bool addCandidateForOwnExternalAddress(const RsPeerId& from, const struct sockaddr_storage &addr) ; - virtual bool getExtAddressReportedByFriends(struct sockaddr_storage& addr, uint8_t &isstable) ; - - virtual bool setNetworkMode(const RsPeerId &id, uint32_t netMode); - virtual bool setVisState(const RsPeerId &id, uint16_t vs_disc, uint16_t vs_dht); - - virtual bool setLocation(const RsPeerId &pid, const std::string &location); - virtual bool setHiddenDomainPort(const RsPeerId &id, const std::string &domain_addr, const uint16_t domain_port); - virtual bool isHiddenNode(const RsPeerId& id); - - virtual bool updateCurrentAddress(const RsPeerId& id, const pqiIpAddress &addr); - virtual bool updateLastContact(const RsPeerId& id); - virtual bool updateAddressList(const RsPeerId& id, const pqiIpAddrSet &addrs); - - virtual bool resetOwnExternalAddressList() ; - - // THIS MUST ONLY BE CALLED BY NETMGR!!!! - virtual bool UpdateOwnAddress(const struct sockaddr_storage &local_addr, const struct sockaddr_storage &ext_addr); - /**************** Net Status Info ****************/ - /* - * MUST RATIONALISE THE DATA FROM THESE FUNCTIONS - * These functions are used by: - * 1) p3face-config ... to remove! - * 2) p3peers - reasonable - * 3) p3disc - reasonable - */ - - virtual bool getOwnNetStatus(peerState &state); - virtual bool getFriendNetStatus(const RsPeerId &id, peerState &state); - - virtual bool getPeerName(const RsPeerId& ssl_id, std::string& name); - virtual bool getGpgId(const RsPeerId& sslId, RsPgpId& gpgId); - virtual uint32_t getConnectionType(const RsPeerId& sslId); - - virtual bool setProxyServerAddress(const uint32_t type, const struct sockaddr_storage &proxy_addr); - virtual bool getProxyServerAddress(const uint32_t type, struct sockaddr_storage &proxy_addr); - virtual bool getProxyServerStatus(const uint32_t type, uint32_t &proxy_status); - virtual bool isHidden(); - virtual bool isHidden(const uint32_t type); - virtual bool isHiddenPeer(const RsPeerId &ssl_id); - virtual bool isHiddenPeer(const RsPeerId &ssl_id, const uint32_t type); - virtual bool getProxyAddress(const RsPeerId& ssl_id, struct sockaddr_storage &proxy_addr, std::string &domain_addr, uint16_t &domain_port); - virtual uint32_t hiddenDomainToHiddenType(const std::string &domain); - virtual uint32_t getHiddenType(const RsPeerId &ssl_id); - - virtual int getFriendCount(bool ssl, bool online); - - /************* DEPRECIATED FUNCTIONS (TO REMOVE) ********/ - - // Single Use Function... shouldn't be here. used by p3serverconfig.cc - virtual bool haveOnceConnected(); - - virtual bool setMaxRates(const RsPgpId& pid,uint32_t maxUp,uint32_t maxDn); - virtual bool getMaxRates(const RsPgpId& pid,uint32_t& maxUp,uint32_t& maxDn); - virtual bool getMaxRates(const RsPeerId& pid,uint32_t& maxUp,uint32_t& maxDn); - - /************************************************************************************************/ - /* Extra IMPL Functions (used by p3LinkMgr, p3NetMgr + Setup) */ - /************************************************************************************************/ - - p3PeerMgrIMPL( const RsPeerId& ssl_own_id, - const RsPgpId& gpg_own_id, - const std::string& gpg_own_name, - const std::string& ssl_own_location) ; - - void setManagers(p3LinkMgrIMPL *linkMgr, p3NetMgrIMPL *netMgr); - - bool forceHiddenNode(); - bool setupHiddenNode(const std::string &hiddenAddress, const uint16_t hiddenPort); - - void tick(); - - const RsPeerId& getOwnId(); - bool setOwnNetworkMode(uint32_t netMode); - bool setOwnVisState(uint16_t vs_disc, uint16_t vs_dht); - - int getConnectAddresses( const RsPeerId &id, sockaddr_storage &lAddr, - sockaddr_storage &eAddr, pqiIpAddrSet &histAddrs, - std::string &dyndns ); - - -protected: - /* Internal Functions */ - - bool removeUnusedLocations(); - bool removeBannedIps(); - - void printPeerLists(std::ostream &out); - - virtual bool locked_computeCurrentBestOwnExtAddressCandidate(sockaddr_storage &addr, uint32_t &count); - -protected: - /*****************************************************************/ - /*********************** p3config ******************************/ - /* Key Functions to be overloaded for Full Configuration */ - virtual RsSerialiser *setupSerialiser(); - virtual bool saveList(bool &cleanup, std::list&); - virtual void saveDone(); - virtual bool loadList(std::list& load); - /*****************************************************************/ - - /* other important managers */ - - p3LinkMgrIMPL *mLinkMgr; - p3NetMgrIMPL *mNetMgr; - -private: - RsMutex mPeerMtx; /* protects below */ - - bool mStatusChanged; - - std::list clients; - - peerState mOwnState; - - std::map mFriendList; // - - std::map mReportedOwnAddresses ; - - std::map groupList; - //uint32_t lastGroupId; - - std::list saveCleanupList; /* TEMPORARY LIST WHEN SAVING */ - - std::map mFriendsPermissionFlags ; // permission flags for each gpg key - std::map mPeerBandwidthLimits ; // bandwidth limits for each gpg key - - struct sockaddr_storage mProxyServerAddressTor; - struct sockaddr_storage mProxyServerAddressI2P; - uint32_t mProxyServerStatusTor ; - uint32_t mProxyServerStatusI2P ; - -}; - -#endif // MRK_PQI_PEER_MANAGER_HEADER diff --git a/libretroshare/src/pqi/p3servicecontrol.cc b/libretroshare/src/pqi/p3servicecontrol.cc deleted file mode 100644 index 9bf3b3c62..000000000 --- a/libretroshare/src/pqi/p3servicecontrol.cc +++ /dev/null @@ -1,1416 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3servicecontrol.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2014-2014 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include - -#include "p3servicecontrol.h" -#include "rsitems/rsserviceids.h" -#include "rsitems/rsitem.h" -#include "serialiser/rstypeserializer.h" -#include "rsitems/rsnxsitems.h" -#include "pqi/p3cfgmgr.h" -#include "pqi/pqiservice.h" -#include "retroshare/rspeers.h" -#include "retroshare/rsevents.h" - -/*******************************/ -// #define SERVICECONTROL_DEBUG 1 -/*******************************/ - -static const uint8_t RS_PKT_SUBTYPE_SERVICE_CONTROL_SERVICE_PERMISSIONS = 0x01 ; - -class RsServiceControlItem: public RsItem -{ -public: - explicit RsServiceControlItem(uint8_t item_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_SERVICE_CONTROL,item_subtype) {} -}; - -class RsServicePermissionItem: public RsServiceControlItem, public RsServicePermissions -{ -public: - RsServicePermissionItem(): RsServiceControlItem(RS_PKT_SUBTYPE_SERVICE_CONTROL_SERVICE_PERMISSIONS) {} - explicit RsServicePermissionItem(const RsServicePermissions& perms) : RsServiceControlItem(RS_PKT_SUBTYPE_SERVICE_CONTROL_SERVICE_PERMISSIONS), RsServicePermissions(perms) {} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) - { - RsTypeSerializer::serial_process(j,ctx,mServiceId,"mServiceId") ; - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_NAME,mServiceName,"mServiceName") ; - RsTypeSerializer::serial_process (j,ctx,mDefaultAllowed,"mDefaultAllowed") ; - - RsTypeSerializer::serial_process (j,ctx,mPeersAllowed,"mPeersAllowed"); - RsTypeSerializer::serial_process (j,ctx,mPeersDenied ,"mPeersDenied"); - } - - virtual void clear() {} -}; - -class ServiceControlSerialiser: public RsServiceSerializer -{ -public: - ServiceControlSerialiser() : RsServiceSerializer(RS_SERVICE_TYPE_SERVICE_CONTROL) {} - - virtual RsItem *create_item(uint16_t service,uint8_t item_subtype) const - { - if(RS_SERVICE_TYPE_SERVICE_CONTROL != service) - return NULL; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_SERVICE_CONTROL_SERVICE_PERMISSIONS: return new RsServicePermissionItem(); - default: - return NULL ; - } - } -}; - -RsServiceControl *rsServiceControl = NULL; - -p3ServiceControl::p3ServiceControl(p3LinkMgr *linkMgr) - : RsServiceControl(), p3Config(), - mLinkMgr(linkMgr), mOwnPeerId(linkMgr->getOwnId()), - mCtrlMtx("p3ServiceControl"), mMonitorMtx("P3ServiceControl::Monitor"), - mServiceServer(NULL) -{ - mSerialiser = new ServiceControlSerialiser ; -} - -RsSerialiser *p3ServiceControl::setupSerialiser() -{ - RsSerialiser *serial = new RsSerialiser; - serial->addSerialType(new ServiceControlSerialiser) ; - - return serial ; -} - -const RsPeerId& p3ServiceControl::getOwnId() -{ - return mOwnPeerId; -} - -bool p3ServiceControl::getServiceItemNames(uint32_t serviceId,std::map& names) -{ - if(mServiceServer != NULL) - return mServiceServer->getServiceItemNames(serviceId,names) ; - - return false ; -} - -/* Interface for Services */ -bool p3ServiceControl::registerService(const RsServiceInfo &info, bool defaultOn) -{ - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - - std::map::iterator it; - it = mOwnServices.find(info.mServiceType); - if (it != mOwnServices.end()) - { - std::cerr << "p3ServiceControl::registerService() ERROR Duplicate Service ID"; - std::cerr << std::endl; - return false; - } - - /* sanity check ServiceInfo */ - mOwnServices[info.mServiceType] = info; - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::registerService() Registered ServiceID: " << info.mServiceType; - std::cerr << std::endl; - std::cerr << "p3ServiceControl::registerService() ServiceName: " << info.mServiceName; - std::cerr << std::endl; -#endif - - - /* create default permissions for this service - * this will be overwritten by configuration (if it exists). - */ - - createDefaultPermissions_locked(info.mServiceType, info.mServiceName, defaultOn); - return true; -} - -bool p3ServiceControl::deregisterService(uint32_t serviceId) -{ - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - - std::map::iterator it; - it = mOwnServices.find(serviceId); - if (it == mOwnServices.end()) - { - std::cerr << "p3ServiceControl::deregisterService() ERROR No matching Service ID"; - std::cerr << std::endl; - return false; - } - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::deregisterService() Removed ServiceID: " << serviceId; - std::cerr << std::endl; -#endif - mOwnServices.erase(it); - return true; -} - - -/* Interface for Services */ -bool p3ServiceControl::registerServiceMonitor(pqiServiceMonitor *monitor, uint32_t serviceId) -{ - RsStackMutex stack(mMonitorMtx); /***** LOCK STACK MUTEX ****/ - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::registerServiceMonitor() for ServiceId: "; - std::cerr << serviceId; - std::cerr << std::endl; -#endif - - mMonitors.insert(std::make_pair(serviceId, monitor)); - return true; -} - - -bool p3ServiceControl::deregisterServiceMonitor(pqiServiceMonitor *monitor) -{ - RsStackMutex stack(mMonitorMtx); /***** LOCK STACK MUTEX ****/ - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::deregisterServiceMonitor()"; - std::cerr << std::endl; -#endif - - std::multimap::iterator it; - for(it = mMonitors.begin(); it != mMonitors.end(); ) - { - if (it->second == monitor) - { - mMonitors.erase(it++); - } - else - { - ++it; - } - } - return true; -} - -/* Interface to p3ServiceInfo */ -void p3ServiceControl::getServiceChanges(std::set &updateSet) -{ - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::getServiceChanges()"; - std::cerr << std::endl; -#endif - - std::set::iterator it; - for (it = mUpdatedSet.begin(); it != mUpdatedSet.end(); ++it) - { - updateSet.insert(*it); - } - - mUpdatedSet.clear(); -} - -std::string p3ServiceControl::getServiceName(uint32_t service_id) -{ - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - - std::map::const_iterator it = mOwnServices.find(service_id) ; - - if(it == mOwnServices.end()) - { - std::cerr << "(EE) Cannot find own service for ID = " << std::hex << service_id << std::dec << std::endl; - return std::string(); - } - - return it->second.mServiceName; -} - -bool p3ServiceControl::getOwnServices(RsPeerServiceInfo &info) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::getOwnServices()"; - std::cerr << std::endl; -#endif - - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - - info.mPeerId.clear() ; - info.mServiceList = mOwnServices; - return true; -} - - -bool p3ServiceControl::getServicesAllowed(const RsPeerId &peerId, RsPeerServiceInfo &info) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::getServicesAllowed(" << peerId.toStdString() << ")"; - std::cerr << std::endl; -#endif - - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - - info.mPeerId = peerId; - - // For each registered Service.. check if peer has permissions. - std::map::iterator it; - for(it = mOwnServices.begin(); it != mOwnServices.end(); ++it) - { - if (peerHasPermissionForService_locked(peerId, it->first)) - { - info.mServiceList[it->first] = it->second; - } - } - return true; -} - -bool p3ServiceControl::peerHasPermissionForService_locked(const RsPeerId &peerId, uint32_t serviceId) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::peerHasPermissionForService_locked()"; - std::cerr << std::endl; -#endif - - std::map::iterator it; - it = mServicePermissionMap.find(serviceId); - if (it == mServicePermissionMap.end()) - { - return false; - } - return it->second.peerHasPermission(peerId); -} - -// This is used by both RsServiceControl and p3ServiceInfo. -bool p3ServiceControl::getServicesProvided(const RsPeerId &peerId, RsPeerServiceInfo &info) -{ - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::getServicesProvided()"; - std::cerr << std::endl; -#endif - - std::map::iterator it; - it = mServicesProvided.find(peerId); - if (it == mServicesProvided.end()) - { - return false; - } - - info = it->second; - return true; -} - -bool p3ServiceControl::updateServicesProvided(const RsPeerId &peerId, const RsPeerServiceInfo &info) -{ - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updateServicesProvided() from: " << peerId.toStdString(); - std::cerr << std::endl; - std::cerr << info; - std::cerr << std::endl; -#endif - - mServicesProvided[peerId] = info; - updateFilterByPeer_locked(peerId); - - IndicateConfigChanged() ; - return true; -} - -/* External Interface to RsServiceControl */ -bool p3ServiceControl::getServicePermissions(uint32_t serviceId, RsServicePermissions &permissions) -{ - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::getServicePermissions()"; - std::cerr << std::endl; -#endif - - std::map::iterator it; - - it = mServicePermissionMap.find(serviceId); - if (it == mServicePermissionMap.end()) - { - return false; - } - permissions = it->second; - return true; -} - -bool p3ServiceControl::createDefaultPermissions_locked(uint32_t serviceId, const std::string& serviceName, bool defaultOn) -{ - std::map::iterator it; - it = mServicePermissionMap.find(serviceId); - if (it == mServicePermissionMap.end()) - { - RsServicePermissions perms; - perms.mServiceId = serviceId; - perms.mServiceName = serviceName; - perms.mDefaultAllowed = defaultOn; - - mServicePermissionMap[serviceId] = perms; - IndicateConfigChanged() ; - return true; - } - return false; -} - - -bool p3ServiceControl::updateServicePermissions(uint32_t serviceId, const RsServicePermissions &permissions) -{ - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updateServicePermissions()"; - std::cerr << std::endl; -#endif - - std::map::iterator it; - it = mServicePermissionMap.find(serviceId); - if (it == mServicePermissionMap.end()) - { - std::cerr << "p3ServiceControl::updateServicePermissions()"; - std::cerr << " ERROR missing previous permissions"; - std::cerr << std::endl; - // ERROR. - return false; - } - - std::list onlinePeers; - mLinkMgr->getOnlineList(onlinePeers); - std::list::const_iterator pit; - if (it != mServicePermissionMap.end()) - { - for(pit = onlinePeers.begin(); pit != onlinePeers.end(); ++pit) - { - if (it->second.peerHasPermission(*pit) != - permissions.peerHasPermission(*pit)) - { - mUpdatedSet.insert(*pit); - } - } - } - - it->second = permissions; - it->second.mServiceId = serviceId; // just to make sure! - - // This is overkill - but will update everything. - updateAllFilters_locked(); - IndicateConfigChanged() ; - return true; -} - - -/****************************************************************************/ -/****************************************************************************/ -/****************************************************************************/ -/****************************************************************************/ - -// This is the basic system... -// which will be a little slow (2x maps). -// -// Potential improvement is to push the RsPeerFilter -// to the pqiStreamer, (when items have been sorted by peers already!). -// but we will do this later. - -bool p3ServiceControl::checkFilter(uint32_t serviceId, const RsPeerId &peerId) -{ - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::checkFilter() "; - std::cerr << " ServiceId: " << serviceId; -#endif - - std::map::iterator it; - it = mOwnServices.find(serviceId); - if (it != mOwnServices.end()) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << " ServiceName: " << it->second.mServiceName; -#endif - } - else - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << " ServiceName: Unknown! "; -#endif - } - -#ifdef SERVICECONTROL_DEBUG - std::cerr << " PeerId: " << peerId.toStdString(); - std::cerr << std::endl; -#endif - - // must allow ServiceInfo through, or we have nothing! - if (serviceId == RsServiceInfo::RsServiceInfoUIn16ToFullServiceId(RS_SERVICE_TYPE_SERVICEINFO)) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::checkFilter() Allowed SERVICEINFO"; - std::cerr << std::endl; -#endif - return true; - } - - - std::map::const_iterator pit; - pit = mPeerFilterMap.find(peerId); - if (pit == mPeerFilterMap.end()) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::checkFilter() Denied No PeerId"; - std::cerr << std::endl; -#endif - return false; - } - - if (pit->second.mDenyAll) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::checkFilter() Denied Peer.DenyAll"; - std::cerr << std::endl; -#endif - return false; - } - - if (pit->second.mAllowAll) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::checkFilter() Allowed Peer.AllowAll"; - std::cerr << std::endl; -#endif - return true; - } - - std::set::const_iterator sit; - sit = pit->second.mAllowedServices.find(serviceId); - if (sit == pit->second.mAllowedServices.end()) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::checkFilter() Denied !Peer.find(serviceId)"; - std::cerr << std::endl; -#endif - return false; - } -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::checkFilter() Allowed Peer.find(serviceId)"; - std::cerr << std::endl; -#endif - return true; -} - -bool versionOkay(uint16_t version_major, uint16_t version_minor, - uint16_t min_version_major, uint16_t min_version_minor) -{ - if (version_major > min_version_major) - { - return true; - } - if (version_major == min_version_major) - { - return (version_minor >= min_version_minor); - } - return false; -} - - -bool ServiceInfoCompatible(const RsServiceInfo &info1, const RsServiceInfo &info2) -{ - // Id, or Name mismatch. - if ((info1.mServiceType != info2.mServiceType) || - (info1.mServiceName != info2.mServiceName)) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "servicesCompatible: Type/Name mismatch"; - std::cerr << std::endl; - std::cerr << "Info1 ID: " << info1.mServiceType; - std::cerr << " " << info1.mServiceName; - std::cerr << std::endl; - std::cerr << "Info2 ID: " << info2.mServiceType; - std::cerr << " " << info2.mServiceName; - std::cerr << std::endl; -#endif - return false; - } - - // ensure that info1 meets minimum requirements for info2 - if (!versionOkay(info1.mVersionMajor, info1.mVersionMinor, - info2.mMinVersionMajor, info2.mMinVersionMinor)) - { - return false; - } - - // ensure that info2 meets minimum requirements for info1 - if (!versionOkay(info2.mVersionMajor, info2.mVersionMinor, - info1.mMinVersionMajor, info1.mMinVersionMinor)) - { - return false; - } - return true; -} - - -bool p3ServiceControl::updateFilterByPeer(const RsPeerId &peerId) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updateFilterByPeer()"; - std::cerr << std::endl; -#endif - - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - return updateFilterByPeer_locked(peerId); -} - - -bool p3ServiceControl::updateAllFilters() -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updateAllFilters()"; - std::cerr << std::endl; -#endif - - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - - return updateAllFilters_locked(); -} - - -bool p3ServiceControl::updateAllFilters_locked() -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updateAllFilters_locked()"; - std::cerr << std::endl; -#endif - - // Create a peerSet from ServicesProvided + PeerFilters. - // This will completely refresh the Filters. - std::set peerSet; - std::set::const_iterator pit; - - std::map::const_iterator it; - for(it = mServicesProvided.begin(); it != mServicesProvided.end(); ++it) - { - peerSet.insert(it->first); - } - - std::map::const_iterator fit; - for(fit = mPeerFilterMap.begin(); fit != mPeerFilterMap.end(); ++fit) - { - peerSet.insert(fit->first); - } - - for(pit = peerSet.begin(); pit != peerSet.end(); ++pit) - { - updateFilterByPeer_locked(*pit); - } - return true; -} - - -// create filter. (the easy way). -bool p3ServiceControl::updateFilterByPeer_locked(const RsPeerId &peerId) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updateFilterByPeer_locked() : " << peerId.toStdString(); - std::cerr << std::endl; -#endif - - ServicePeerFilter originalFilter; - ServicePeerFilter peerFilter; - - std::map::iterator fit; - fit = mPeerFilterMap.find(peerId); - if (fit != mPeerFilterMap.end()) - { - originalFilter = fit->second; - } - - std::map::iterator it; - it = mServicesProvided.find(peerId); - if (it == mServicesProvided.end()) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updateFilterByPeer_locked() Empty ... Clearing"; - std::cerr << std::endl; -#endif - - // empty, remove... - recordFilterChanges_locked(peerId, originalFilter, peerFilter); - if (fit != mPeerFilterMap.end()) - { - std::cerr << std::endl; - mPeerFilterMap.erase(fit); - } - return true; - } - - // For each registered Service.. check if services compatible. - // then check for permissions. - - // similar maps, can iterate through in parallel. - std::map::const_iterator oit = mOwnServices.begin(); - std::map::const_iterator eoit = mOwnServices.end(); - std::map::const_iterator tit = it->second.mServiceList.begin(); - std::map::const_iterator etit = it->second.mServiceList.end(); - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updateFilterByPeer_locked() Comparing lists"; - std::cerr << std::endl; -#endif - - - while((oit != eoit) && (tit != etit)) - { - if (oit->first == tit->first) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "\tChecking Matching Service ID: " << oit->first; - std::cerr << std::endl; -#endif - /* match of service IDs */ - /* check if compatible */ - if (ServiceInfoCompatible(oit->second, tit->second)) - { - if (peerHasPermissionForService_locked(peerId, oit->first)) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "\t\tMatched Service ID: " << oit->first; - std::cerr << std::endl; -#endif - peerFilter.mAllowedServices.insert(oit->first); - } - } - ++oit; - ++tit; - } - else - { - if (oit->first < tit->first) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "\tSkipping Only Own Service ID: " << oit->first; - std::cerr << std::endl; -#endif - ++oit; - } - else - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "\tSkipping Only Peer Service ID: " << tit->first; - std::cerr << std::endl; -#endif - ++tit; - } - } - } - - // small optimisations. - if (peerFilter.mAllowedServices.empty()) - { - peerFilter.mDenyAll = true; - } - else - { - peerFilter.mDenyAll = false; - if (peerFilter.mAllowedServices.size() == mOwnServices.size()) - { - peerFilter.mAllowAll = true; - } - } - - // update or remove. - if (peerFilter.mDenyAll) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updateFilterByPeer_locked() Empty(2) ... Clearing"; - std::cerr << std::endl; -#endif - - if (fit != mPeerFilterMap.end()) - { - mPeerFilterMap.erase(fit); - } - } - else - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updateFilterByPeer_locked() Installing PeerFilter"; - std::cerr << std::endl; -#endif - mPeerFilterMap[peerId] = peerFilter; - } - recordFilterChanges_locked(peerId, originalFilter, peerFilter); - - using Evt_t = RsPeerStateChangedEvent; - if(rsEvents) - rsEvents->postEvent(std::unique_ptr(new Evt_t(peerId))); - - return true; -} - -void p3ServiceControl::recordFilterChanges_locked(const RsPeerId &peerId, - ServicePeerFilter &originalFilter, ServicePeerFilter &updatedFilter) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::recordFilterChanges_locked()"; - std::cerr << std::endl; - std::cerr << "PeerId: " << peerId.toStdString(); - std::cerr << std::endl; - std::cerr << "OriginalFilter: " << originalFilter; - std::cerr << std::endl; - std::cerr << "UpdatedFilter: " << updatedFilter; - std::cerr << std::endl; -#endif - - /* find differences */ - //std::map changes; - std::set::const_iterator it1, it2, eit1, eit2; - it1 = originalFilter.mAllowedServices.begin(); - eit1 = originalFilter.mAllowedServices.end(); - it2 = updatedFilter.mAllowedServices.begin(); - eit2 = updatedFilter.mAllowedServices.end(); - - while((it1 != eit1) && (it2 != eit2)) - { - if (*it1 < *it2) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "Removed Service: " << *it1; - std::cerr << std::endl; -#endif - // removal - //changes[*it1] = false; - filterChangeRemoved_locked(peerId, *it1); - ++it1; - } - else if (*it2 < *it1) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "Added Service: " << *it2; - std::cerr << std::endl; -#endif - // addition. - filterChangeAdded_locked(peerId, *it2); - //changes[*it2] = true; - ++it2; - } - else - { - ++it1; - ++it2; - } - } - - // Handle the unfinished Set. - for(; it1 != eit1; ++it1) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "Removed Service: " << *it1; - std::cerr << std::endl; -#endif - // removal - //changes[*it1] = false; - filterChangeRemoved_locked(peerId, *it1); - } - - for(; it2 != eit2; ++it2) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "Added Service: " << *it2; - std::cerr << std::endl; -#endif - // addition. - //changes[*it2] = true; - filterChangeAdded_locked(peerId, *it2); - } - - // Can remove changes map... as only used below. -#if 0 - // now we to store for later notifications. - std::map::const_iterator cit; - for(cit = changes.begin(); cit != changes.end(); ++cit) - { - ServiceNotifications ¬es = mNotifications[cit->first]; - if (cit->second) - { - notes.mAdded.insert(peerId); - } - else - { - notes.mRemoved.insert(peerId); - } - } -#endif - -} - - -// when they go offline, etc. -void p3ServiceControl::removePeer(const RsPeerId &peerId) -{ - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::removePeer() : " << peerId.toStdString(); - std::cerr << std::endl; -#endif - - ServicePeerFilter originalFilter; - bool hadFilter = false; - { - std::map::iterator fit; - fit = mPeerFilterMap.find(peerId); - if (fit != mPeerFilterMap.end()) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::removePeer() clearing mPeerFilterMap"; - std::cerr << std::endl; -#endif - - hadFilter = true; - originalFilter = fit->second; - mPeerFilterMap.erase(fit); - } - else - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::removePeer() Nothing in mPeerFilterMap"; - std::cerr << std::endl; -#endif - } - } - - { - std::map::iterator sit; - sit = mServicesProvided.find(peerId); - if (sit != mServicesProvided.end()) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::removePeer() clearing mServicesProvided"; - std::cerr << std::endl; -#endif - - mServicesProvided.erase(sit); - } - else - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::removePeer() Nothing in mServicesProvided"; - std::cerr << std::endl; -#endif - } - } - - if (hadFilter) - { - ServicePeerFilter emptyFilter; - recordFilterChanges_locked(peerId, originalFilter, emptyFilter); - } -} - -/****************************************************************************/ -/****************************************************************************/ -// need to provide list of connected peers per service. -// these are collected here. - -void p3ServiceControl::filterChangeRemoved_locked(const RsPeerId &peerId, uint32_t serviceId) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::filterChangeRemoved_locked(" << peerId.toStdString(); - std::cerr << ", " << serviceId << ")"; - std::cerr << std::endl; -#endif - - //std::map >::iterator mit; - - std::set &peerSet = mServicePeerMap[serviceId]; - std::set::iterator sit; - - sit = peerSet.find(peerId); - if (sit != peerSet.end()) - { - peerSet.erase(sit); - } - else - { - // ERROR - std::cerr << "p3ServiceControl::filterChangeRemoved_locked() ERROR NOT FOUND"; - std::cerr << std::endl; - } - - // Add to Notifications too. - ServiceNotifications ¬es = mNotifications[serviceId]; - notes.mRemoved.insert(peerId); -} - - -void p3ServiceControl::filterChangeAdded_locked(const RsPeerId &peerId, uint32_t serviceId) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::filterChangeAdded_locked(" << peerId.toStdString(); - std::cerr << ", " << serviceId << ")"; - std::cerr << std::endl; -#endif - - //std::map >::iterator mit; - - std::set &peerSet = mServicePeerMap[serviceId]; - - // This bit is only for error checking. - std::set::iterator sit = peerSet.find(peerId); - if (sit != peerSet.end()) - { - // ERROR. - std::cerr << "p3ServiceControl::filterChangeAdded_locked() ERROR NOT FOUND"; - std::cerr << std::endl; - } - peerSet.insert(peerId); - - // Add to Notifications too. - ServiceNotifications ¬es = mNotifications[serviceId]; - notes.mAdded.insert(peerId); -} - - - -void p3ServiceControl::getPeersConnected(uint32_t serviceId, std::set &peerSet) -{ - RS_STACK_MUTEX(mCtrlMtx); - - std::map >::iterator mit; - mit = mServicePeerMap.find(serviceId); - if (mit != mServicePeerMap.end()) - { - peerSet = mit->second; - } - else - { - peerSet.clear(); - } -} - - -bool p3ServiceControl::isPeerConnected(uint32_t serviceId, const RsPeerId &peerId) -{ - RS_STACK_MUTEX(mCtrlMtx); - - std::map >::iterator mit; - mit = mServicePeerMap.find(serviceId); - if (mit != mServicePeerMap.end()) - { - std::set::iterator sit; - sit = mit->second.find(peerId); - return (sit != mit->second.end()); - } - - return false; -} - - -/****************************************************************************/ -/****************************************************************************/ - -void p3ServiceControl::tick() -{ - notifyAboutFriends(); - notifyServices(); - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::tick()"; - std::cerr << std::endl; -#endif -} - -// configuration. -bool p3ServiceControl::saveList(bool &cleanup, std::list &saveList) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::saveList()"; - std::cerr << std::endl; -#endif - cleanup = true ; - - for(std::map::iterator it(mServicePermissionMap.begin());it!=mServicePermissionMap.end();++it) - { - RsServicePermissionItem *item = new RsServicePermissionItem(it->second) ; - saveList.push_back(item) ; - } - return true; -} - -bool p3ServiceControl::loadList(std::list& loadList) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::loadList()"; - std::cerr << std::endl; -#endif - for(std::list::const_iterator it(loadList.begin());it!=loadList.end();++it) - { - RsServicePermissionItem *item = dynamic_cast(*it) ; - - if(item != NULL) - mServicePermissionMap[item->mServiceId] = *item ; - - delete *it ; - } - - loadList.clear() ; - return true; -} - - -/****************************************************************************/ -/****************************************************************************/ - - // pqiMonitor. -void p3ServiceControl::statusChange(const std::list &plist) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::statusChange()"; - std::cerr << std::endl; -#endif - - std::list::const_iterator pit; - for(pit = plist.begin(); pit != plist.end(); ++pit) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::statusChange() for peer: "; - std::cerr << " peer: " << (pit->id).toStdString(); - std::cerr << " state: " << pit->state; - std::cerr << " actions: " << pit->actions; - std::cerr << std::endl; -#endif - if (pit->state & RS_PEER_S_FRIEND) - { - // Connected / Disconnected. (interal actions). - if (pit->actions & RS_PEER_CONNECTED) - { - updatePeerConnect(pit->id); - } - else if (pit->actions & RS_PEER_DISCONNECTED) - { - updatePeerDisconnect(pit->id); - } - - // Added / Removed. (pass on notifications). - if (pit->actions & RS_PEER_NEW) - { - updatePeerNew(pit->id); - } - } - else - { - if (pit->actions & RS_PEER_MOVED) - { - updatePeerRemoved(pit->id); - } - } - } - return; -} - -// Update Peer status. -void p3ServiceControl::updatePeerConnect(const RsPeerId &peerId) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updatePeerConnect(): " << peerId.toStdString(); - std::cerr << std::endl; -#else - (void)peerId; -#endif - return; -} - -void p3ServiceControl::updatePeerDisconnect(const RsPeerId &peerId) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updatePeerDisconnect(): " << peerId.toStdString(); - std::cerr << std::endl; -#endif - - removePeer(peerId); - return; -} - - -// Update Peer status. -void p3ServiceControl::updatePeerNew(const RsPeerId &peerId) -{ - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updatePeerNew(): " << peerId.toStdString(); - std::cerr << std::endl; -#endif - - pqiServicePeer peer; - peer.id = peerId; - peer.actions = RS_SERVICE_PEER_NEW; - mFriendNotifications.push_back(peer); - - return; -} - -void p3ServiceControl::updatePeerRemoved(const RsPeerId &peerId) -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::updatePeerRemoved(): " << peerId.toStdString(); - std::cerr << std::endl; -#endif - - removePeer(peerId); - - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - - pqiServicePeer peer; - peer.id = peerId; - peer.actions = RS_SERVICE_PEER_REMOVED; - mFriendNotifications.push_back(peer); - - return; -} - -/****************************************************************************/ -/****************************************************************************/ - - -void p3ServiceControl::notifyAboutFriends() -{ - std::list friendNotifications; - { - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - - if (mFriendNotifications.empty()) - { - return; - } -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::notifyAboutFriends(): Something has changed!"; - std::cerr << std::endl; -#endif - - mFriendNotifications.swap(friendNotifications); - } - - { - RsStackMutex stack(mMonitorMtx); /***** LOCK STACK MUTEX ****/ - - std::multimap::const_iterator sit; - for(sit = mMonitors.begin(); sit != mMonitors.end(); ++sit) - { - sit->second->statusChange(friendNotifications); - } - } -} - - -void p3ServiceControl::notifyServices() -{ - std::map notifications; - { - RsStackMutex stack(mCtrlMtx); /***** LOCK STACK MUTEX ****/ - - if (mNotifications.empty()) - { - return; - } - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::notifyServices()"; - std::cerr << std::endl; -#endif - - mNotifications.swap(notifications); - } - - { - RsStackMutex stack(mMonitorMtx); /***** LOCK STACK MUTEX ****/ - - std::map::const_iterator it; - std::multimap::const_iterator sit, eit; - for(it = notifications.begin(); it != notifications.end(); ++it) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::notifyServices(): Notifications for Service: " << it->first; - std::cerr << std::endl; -#endif - - sit = mMonitors.lower_bound(it->first); - eit = mMonitors.upper_bound(it->first); - if (sit == eit) - { - /* nothing to notify - skip */ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::notifyServices(): Noone Monitoring ... skipping"; - std::cerr << std::endl; -#endif - - continue; - } - - std::list peers; - std::set::const_iterator pit; - for(pit = it->second.mAdded.begin(); - pit != it->second.mAdded.end(); ++pit) - { - pqiServicePeer peer; - peer.id = *pit; - peer.actions = RS_SERVICE_PEER_CONNECTED; - - peers.push_back(peer); - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::notifyServices(): Peer: " << *pit << " CONNECTED"; - std::cerr << std::endl; -#endif - } - - for(pit = it->second.mRemoved.begin(); - pit != it->second.mRemoved.end(); ++pit) - { - pqiServicePeer peer; - peer.id = *pit; - peer.actions = RS_SERVICE_PEER_DISCONNECTED; - - peers.push_back(peer); - -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::notifyServices(): Peer: " << *pit << " DISCONNECTED"; - std::cerr << std::endl; -#endif - } - - for(; sit != eit; ++sit) - { -#ifdef SERVICECONTROL_DEBUG - std::cerr << "p3ServiceControl::notifyServices(): Sending to Monitoring Service"; - std::cerr << std::endl; -#endif - - sit->second->statusChange(peers); - } - } - } -} - - -/****************************************************************************/ -/****************************************************************************/ - - -RsServicePermissions::RsServicePermissions() -:mServiceId(0), mServiceName(), mDefaultAllowed(false) -{ - return; -} - -bool RsServicePermissions::peerHasPermission(const RsPeerId &peerId) const -{ -#ifdef SERVICECONTROL_DEBUG - std::cerr << "RsServicePermissions::peerHasPermission()"; - std::cerr << std::endl; -#endif - - std::set::const_iterator it; - if (mDefaultAllowed) - { - it = mPeersDenied.find(peerId); - return (it == mPeersDenied.end()); - } - else - { - it = mPeersAllowed.find(peerId); - return (it != mPeersAllowed.end()); - } -} - -void RsServicePermissions::setPermission(const RsPeerId& peerId) -{ - std::set::const_iterator it; - if (mDefaultAllowed) - { - it = mPeersDenied.find(peerId); - mPeersDenied.erase(it) ; - } - else - mPeersAllowed.insert(peerId); -} -void RsServicePermissions::resetPermission(const RsPeerId& peerId) -{ - std::set::const_iterator it; - if (!mDefaultAllowed) - { - it = mPeersAllowed.find(peerId); - mPeersAllowed.erase(it) ; - } - else - mPeersDenied.insert(peerId); -} - -RsServiceInfo::RsServiceInfo( - const uint16_t service_type, - const std::string& service_name, - const uint16_t version_major, - const uint16_t version_minor, - const uint16_t min_version_major, - const uint16_t min_version_minor) - :mServiceName(service_name), - mServiceType(RsServiceInfoUIn16ToFullServiceId(service_type)), - mVersionMajor(version_major), - mVersionMinor(version_minor), - mMinVersionMajor(min_version_major), - mMinVersionMinor(min_version_minor) -{ - return; -} - -unsigned int RsServiceInfo::RsServiceInfoUIn16ToFullServiceId(uint16_t serviceType) -{ - return (((uint32_t) RS_PKT_VERSION_SERVICE) << 24) + (((uint32_t) serviceType) << 8); -} - - -RsServiceInfo::RsServiceInfo() - :mServiceName("unknown"), - mServiceType(0), - mVersionMajor(0), - mVersionMinor(0), - mMinVersionMajor(0), - mMinVersionMinor(0) -{ - return; -} - -std::ostream &operator<<(std::ostream &out, const ServicePeerFilter &filter) -{ - out << "ServicePeerFilter DenyAll: " << filter.mDenyAll; - out << " AllowAll: " << filter.mAllowAll; - out << " Matched Services: "; - std::set::const_iterator it; - for(it = filter.mAllowedServices.begin(); it != filter.mAllowedServices.end(); ++it) - { - out << *it << " "; - } - out << std::endl; - return out; -} - - diff --git a/libretroshare/src/pqi/p3servicecontrol.h b/libretroshare/src/pqi/p3servicecontrol.h deleted file mode 100644 index fa4e4f37e..000000000 --- a/libretroshare/src/pqi/p3servicecontrol.h +++ /dev/null @@ -1,205 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3servicecontrol.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014-2014 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef P3_SERVICE_CONTROL_HEADER -#define P3_SERVICE_CONTROL_HEADER - -#include -#include - -#include "retroshare/rsservicecontrol.h" -#include "pqi/p3cfgmgr.h" -#include "pqi/pqimonitor.h" -#include "pqi/pqiservicemonitor.h" -#include "pqi/p3linkmgr.h" - -class p3ServiceServer ; - -class ServiceNotifications -{ - public: - std::set mAdded; - std::set mRemoved; -}; - -class ServicePeerFilter -{ - public: - ServicePeerFilter() - :mDenyAll(true), mAllowAll(false) {} - - bool mDenyAll; - bool mAllowAll; - std::set mAllowedServices; -}; - -std::ostream &operator<<(std::ostream &out, const ServicePeerFilter &filter); - -class ServiceControlSerialiser ; - -class p3ServiceControl: public RsServiceControl, public pqiMonitor, public p3Config -{ -public: - - /** - */ - explicit p3ServiceControl(p3LinkMgr *linkMgr); - - /** - * checks and update all added configurations - * @see rsserver - */ - void tick(); - - /** - * provided so that services don't need linkMgr, and can get all info - * from ServiceControl. - * @see rsserver - */ - -virtual const RsPeerId& getOwnId(); - - /** - * External Interface (RsServiceControl). - */ - -virtual bool getOwnServices(RsPeerServiceInfo &info); -virtual std::string getServiceName(uint32_t service_id) ; - - // This is what is passed to peers, can be displayed by GUI too. -virtual bool getServicesAllowed(const RsPeerId &peerId, RsPeerServiceInfo &info); - - // Information provided by peer. -virtual bool getServicesProvided(const RsPeerId &peerId, RsPeerServiceInfo &info); - - // Main Permission Interface. -virtual bool getServicePermissions(uint32_t serviceId, RsServicePermissions &permissions); -virtual bool updateServicePermissions(uint32_t serviceId, const RsServicePermissions &permissions); - - // Get List of Peers using this Service. -virtual void getPeersConnected(uint32_t serviceId, std::set &peerSet); -virtual bool isPeerConnected(uint32_t serviceId, const RsPeerId &peerId); - - // Gets the list of items used by that service -virtual bool getServiceItemNames(uint32_t serviceId,std::map& names) ; - - /** - * Registration for all Services. - */ - -virtual bool registerService(const RsServiceInfo &info, bool defaultOn); -virtual bool deregisterService(uint32_t serviceId); - -virtual bool registerServiceMonitor(pqiServiceMonitor *monitor, uint32_t serviceId); -virtual bool deregisterServiceMonitor(pqiServiceMonitor *monitor); - - /** - * - */ - - - // Filter for services. -virtual bool checkFilter(uint32_t serviceId, const RsPeerId &peerId); - - /** - * Interface for ServiceInfo service. - */ - - // ServicesAllowed have changed for these peers. -virtual void getServiceChanges(std::set &updateSet); - - // Input from peers. -virtual bool updateServicesProvided(const RsPeerId &peerId, const RsPeerServiceInfo &info); - - // pqiMonitor. -virtual void statusChange(const std::list &plist); - - virtual void setServiceServer(p3ServiceServer *p) { mServiceServer = p ; } - -protected: - // configuration. -virtual bool saveList(bool &cleanup, std::list&); -virtual bool loadList(std::list& load); -virtual RsSerialiser *setupSerialiser() ; - -private: - -void notifyServices(); -void notifyAboutFriends(); - -void updatePeerConnect(const RsPeerId &peerId); -void updatePeerDisconnect(const RsPeerId &peerId); -void updatePeerNew(const RsPeerId &peerId); -void updatePeerRemoved(const RsPeerId &peerId); - -void removePeer(const RsPeerId &peerId); - - -bool updateAllFilters(); -bool updateAllFilters_locked(); -bool updateFilterByPeer(const RsPeerId &peerId); -bool updateFilterByPeer_locked(const RsPeerId &peerId); - - - void recordFilterChanges_locked(const RsPeerId &peerId, - ServicePeerFilter &originalFilter, ServicePeerFilter &updatedFilter); - - // Called from recordFilterChanges. - void filterChangeAdded_locked(const RsPeerId &peerId, uint32_t serviceId); - void filterChangeRemoved_locked(const RsPeerId &peerId, uint32_t serviceId); - -bool createDefaultPermissions_locked(uint32_t serviceId, const std::string& serviceName, bool defaultOn); -bool peerHasPermissionForService_locked(const RsPeerId &peerId, uint32_t serviceId); - - p3LinkMgr *mLinkMgr; - const RsPeerId mOwnPeerId; // const from constructor - - RsMutex mCtrlMtx; /* below is protected */ - - std::set mUpdatedSet; - - // From registration / deregistration. - std::map mOwnServices; - // From peers. - std::map mServicesProvided; - // derived from all the others. - std::map mPeerFilterMap; - - std::map mNotifications; - std::list mFriendNotifications; - - // Map of Connected Peers per Service. - std::map > mServicePeerMap; - - // Separate mutex here - must not hold both at the same time! - RsMutex mMonitorMtx; /* below is protected */ - std::multimap mMonitors; - - ServiceControlSerialiser *mSerialiser ; - - // Below here is saved in Configuration. - std::map mServicePermissionMap; - - p3ServiceServer *mServiceServer ; -}; - - -#endif // P3_SERVICE_CONTROL_HEADER diff --git a/libretroshare/src/pqi/p3upnpmgr.h b/libretroshare/src/pqi/p3upnpmgr.h deleted file mode 100644 index 6f58aa8ae..000000000 --- a/libretroshare/src/pqi/p3upnpmgr.h +++ /dev/null @@ -1,54 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: p3upnpmgr.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2007 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef MRK_P3_UPNP_MANAGER_H -#define MRK_P3_UPNP_MANAGER_H - -/* platform independent networking... */ -#include "util/rsthreads.h" -#include "pqi/pqinetwork.h" - -class p3UpnpMgr: public pqiNetAssistFirewall -{ - public: - -virtual ~p3UpnpMgr() { return; } - - /* External Interface */ -virtual void enable(bool on) = 0; /* launches thread to start it up */ -virtual void shutdown() = 0; /* blocking shutdown call */ -virtual void restart() = 0; /* must be called if ports change */ - -virtual bool getEnabled() = 0; -virtual bool getActive() = 0; - - /* the address that the listening port is on */ -virtual void setInternalPort(unsigned short iport_in) = 0; -virtual void setExternalPort(unsigned short eport_in) = 0; - - /* as determined by uPnP */ -virtual bool getInternalAddress(struct sockaddr_storage &addr) = 0; -virtual bool getExternalAddress(struct sockaddr_storage &addr) = 0; - -}; - -#endif /* MRK_P3_UPNP_MANAGER_H */ - diff --git a/libretroshare/src/pqi/pqi.h b/libretroshare/src/pqi/pqi.h deleted file mode 100644 index 1bf581ff1..000000000 --- a/libretroshare/src/pqi/pqi.h +++ /dev/null @@ -1,53 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqi.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef PQI_TOP_HEADER -#define PQI_TOP_HEADER - -#include "rsitems/rsitem.h" - -class P3Interface -{ -public: - P3Interface() {return; } -virtual ~P3Interface() {return; } - -virtual int tick() { return 1; } -virtual int status() { return 1; } - -virtual int SendRsRawItem(RsRawItem *) = 0; -}; - - -/** - * @brief Interface to allow outgoing messages to be sent directly through to - * the pqiperson, rather than being queued - */ -class pqiPublisher -{ - public: -virtual ~pqiPublisher() { return; } -virtual bool sendItem(RsRawItem *item) = 0; - -}; - - -#endif // PQI_TOP_HEADER diff --git a/libretroshare/src/pqi/pqi_base.h b/libretroshare/src/pqi/pqi_base.h deleted file mode 100644 index 72d5d540b..000000000 --- a/libretroshare/src/pqi/pqi_base.h +++ /dev/null @@ -1,418 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqi_base.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef PQI_BASE_ITEM_HEADER -#define PQI_BASE_ITEM_HEADER - -#include -#include -#include -#include -#include -#include - -#include "pqi/pqinetwork.h" - -struct RSTrafficClue; - -/*** Base DataTypes: ****/ -#include "serialiser/rsserial.h" -#include "retroshare/rstypes.h" - -int getPQIsearchId(); -int fixme(char *str, int n); - -struct RsPeerCryptoParams; - -//! controlling data rates -/*! - * For controlling data rates. - * #define DEBUG_RATECAP 1 - */ - -class RsBwRates -{ - public: - RsBwRates() - :mRateIn(0), mRateOut(0), mMaxRateIn(0), mMaxRateOut(0), mQueueIn(0), mQueueOut(0) {return;} - float mRateIn; - float mRateOut; - float mMaxRateIn; - float mMaxRateOut; - int mQueueIn; - int mQueueOut; -}; - - -class RateInterface -{ - -public: - - RateInterface() - :bw_in(0), bw_out(0), bwMax_in(0), bwMax_out(0), - bwCapEnabled(false), bwCap_in(0), bwCap_out(0) { return; } - - virtual ~RateInterface() { return; } - - virtual void getRates(RsBwRates &rates) - { - rates.mRateIn = bw_in; - rates.mRateOut = bw_out; - rates.mMaxRateIn = bwMax_in; - rates.mMaxRateOut = bwMax_out; - return; - } - - virtual int gatherStatistics(std::list& /* outqueue_lst */,std::list& /* inqueue_lst */) { return 0;} - - virtual int getQueueSize(bool /* in */) { return 0;} - virtual float getRate(bool in) - { - if (in) - return bw_in; - return bw_out; - } - - virtual float getMaxRate(bool in) - { - if (in) - return bwMax_in; - return bwMax_out; - } - - virtual void setMaxRate(bool in, float val) - { - if (in) - { - bwMax_in = val; - if (bwCapEnabled) - { - if (bwMax_in > bwCap_in) - { - bwMax_in = bwCap_in; - } - } - } - else - { - bwMax_out = val; - if (bwCapEnabled) - { - if (bwMax_out > bwCap_out) - { - bwMax_out = bwCap_out; - } - } - } - - return; - } - - - virtual void setRateCap(float val_in, float val_out) - { - if ((val_in == 0) && (val_out == 0)) - { -#ifdef DEBUG_RATECAP - std::cerr << "RateInterface::setRateCap() Now disabled" << std::endl; -#endif - bwCapEnabled = false; - } - else - { -#ifdef DEBUG_RATECAP - std::cerr << "RateInterface::setRateCap() Enabled "; - std::cerr << "in: " << bwCap_in << " out: " << bwCap_out << std::endl; -#endif - bwCapEnabled = true; - bwCap_in = val_in; - bwCap_out = val_out; - } - return; - } - -protected: - - virtual void setRate(bool in, float val) - { - if (in) - bw_in = val; - else - bw_out = val; - return; - } - -private: - float bw_in, bw_out, bwMax_in, bwMax_out; - bool bwCapEnabled; - float bwCap_in, bwCap_out; - -}; - - -class NetInterface; - -//! The basic exchange interface. -/*! - * - * This inherits the RateInterface, as Bandwidth control - * is critical to a networked application. - **/ -class PQInterface: public RateInterface -{ -public: - explicit PQInterface(const RsPeerId &id) : - traf_in(0), traf_out(0), peerId(id) {} - virtual ~PQInterface() {} - - /*! - * allows user to send RsItems to a particular facility (file, network) - */ - virtual int SendItem(RsItem *) = 0; - - // this function is overloaded in classes that need the serilized size to be returned. - virtual int SendItem(RsItem *item,uint32_t& size) - { - size = 0 ; - - static bool already=false ; - if(!already) - { - std::cerr << "Warning: PQInterface::SendItem(RsItem*,uint32_t&) calledbut not overloaded! Serialized size will not be returned." << std::endl; - already=true ; - } - return SendItem(item) ; - } - - virtual bool getCryptoParams(RsPeerCryptoParams&) { return false ;} - - /*! - * Retrieve RsItem from a facility - */ - virtual RsItem *GetItem() = 0; - virtual bool RecvItem(RsItem * /*item*/ ) { return false; } /* alternative for for GetItem(), when we want to push */ - - /** - * also there are tick + person id functions. - */ - virtual int tick() { return 0; } - virtual int status() { return 0; } - virtual const RsPeerId& PeerId() { return peerId; } - - // the callback from NetInterface Connection Events. - virtual int notifyEvent(NetInterface * /*ni*/, int /*event*/, - const sockaddr_storage & /*remote_peer_address*/) - { return 0; } - - virtual uint64_t getTraffic(bool in) - { - uint64_t ret = 0; - if (in) - { - ret = traf_in; - traf_in = 0; - return ret; - } - ret = traf_out; - traf_out = 0; - return ret; - } - uint64_t traf_in; - uint64_t traf_out; - - private: - - RsPeerId peerId; -}; - - - -/**** Consts for pqiperson -> placed here for NetBinDummy usage() */ - -const uint32_t PQI_CONNECT_TCP = 0x0001; -const uint32_t PQI_CONNECT_UDP = 0x0002; -const uint32_t PQI_CONNECT_HIDDEN_TOR_TCP = 0x0004; -const uint32_t PQI_CONNECT_HIDDEN_I2P_TCP = 0x0008; - - -#define BIN_FLAGS_NO_CLOSE 0x0001 -#define BIN_FLAGS_READABLE 0x0002 -#define BIN_FLAGS_WRITEABLE 0x0004 -#define BIN_FLAGS_NO_DELETE 0x0008 -#define BIN_FLAGS_HASH_DATA 0x0010 - -/*! - * This defines the binary interface used by Network/loopback/file - * interfaces - * e.g. sending binary data to file or to memory or even through a socket - */ -class BinInterface -{ -public: - BinInterface() {} - virtual ~BinInterface() {} - - /** - * To be called loop, for updating state - */ - virtual int tick() = 0; - - /** - * Sends data to a prescribed location (implementation dependent) - *@param data what will be sent - *@param len the size of data pointed to in memory - *@returns total number of bytes actually sent - */ - virtual int senddata(void *data, int len) = 0; - - /** - * reads data from a prescribed location (implementation dependent) - *@param data what will be sent - *@param len the size of data pointed to in memory - */ - virtual int readdata(void *data, int len) = 0; - - /** - * Is more particular the case of the sending data through a socket (internet) - * moretoread and candsend, take a microsec timeout argument. - * - */ - virtual int netstatus() = 0; - virtual int isactive() = 0; - virtual bool moretoread(uint32_t usec) = 0; - virtual bool cansend(uint32_t usec) = 0; - - /** - * method for streamer to shutdown bininterface - **/ - virtual int close() = 0; - - /** - * If hashing data - **/ - virtual RsFileHash gethash() = 0; - - /** - * Number of bytes read/sent - */ - virtual uint64_t bytecount() { return 0; } - - /** - * used by pqistreamer to limit transfers - **/ - virtual bool bandwidthLimited() { return true; } -}; - - - -static const int NET_CONNECT_RECEIVED = 1; -static const int NET_CONNECT_SUCCESS = 2; -static const int NET_CONNECT_UNREACHABLE = 3; -static const int NET_CONNECT_FIREWALLED = 4; -static const int NET_CONNECT_FAILED = 5; - -static const uint32_t NET_PARAM_CONNECT_DELAY = 1; -static const uint32_t NET_PARAM_CONNECT_PERIOD = 2; -static const uint32_t NET_PARAM_CONNECT_TIMEOUT = 3; -static const uint32_t NET_PARAM_CONNECT_FLAGS = 4; -static const uint32_t NET_PARAM_CONNECT_BANDWIDTH = 5; - -static const uint32_t NET_PARAM_CONNECT_PROXY = 6; -static const uint32_t NET_PARAM_CONNECT_SOURCE = 7; - -static const uint32_t NET_PARAM_CONNECT_DOMAIN_ADDRESS = 8; -static const uint32_t NET_PARAM_CONNECT_REMOTE_PORT = 9; - - -/*! - * ******************** Network INTERFACE *************************** - * This defines the Network interface used by sockets/SSL/XPGP - * interfaces - * - * NetInterface: very pure interface, so no tick.... - * - * It is passed a pointer to a PQInterface *parent, - * this is used to notify the system of Connect/Disconnect Events. - * - * Below are the Events for callback. - **/ -class NetInterface -{ -public: - - /** - * @param p_in used to notify system of connect/disconnect events - */ - NetInterface(PQInterface *p_in, const RsPeerId& id) : p(p_in), peerId(id) {} - - virtual ~NetInterface() {} - - /* TODO - * The data entrypoint is connect(const struct sockaddr_storage &raddr) - * To generalize NetInterface we should have a more general type for raddr - * As an example a string containing an url or encoded like a domain name - */ - virtual int connect(const struct sockaddr_storage &raddr) = 0; - - virtual int listen() = 0; - virtual int stoplistening() = 0; - virtual int disconnect() = 0; - virtual int reset() = 0; - virtual const RsPeerId& PeerId() { return peerId; } - virtual int getConnectAddress(struct sockaddr_storage &raddr) = 0; - - virtual bool connect_parameter(uint32_t type, uint32_t value) = 0; - virtual bool connect_parameter(uint32_t /* type */ , const std::string & /* value */ ) { return false; } // not generally used. - virtual bool connect_additional_address(uint32_t /*type*/, const struct sockaddr_storage & /*addr*/) { return false; } // only needed by udp. - -protected: - PQInterface *parent() { return p; } - -private: - PQInterface *p; - RsPeerId peerId; -}; - -//! network binary interface (abstract) -/** - * Should be used for networking and connecting to addresses - * - * @see pqissl - * @see NetInterface - * @see BinInterface - **/ -class NetBinInterface: public NetInterface, public BinInterface -{ -public: - NetBinInterface(PQInterface *parent, const RsPeerId& id) : - NetInterface(parent, id) {} - virtual ~NetBinInterface() {} -}; - -#define CHAN_SIGN_SIZE 16 -#define CERTSIGNLEN 16 /* actual byte length of signature */ -#define PQI_PEERID_LENGTH 32 /* When expanded into a string */ - - - -#endif // PQI_BASE_ITEM_HEADER - diff --git a/libretroshare/src/pqi/pqiassist.h b/libretroshare/src/pqi/pqiassist.h deleted file mode 100644 index e7b508a3e..000000000 --- a/libretroshare/src/pqi/pqiassist.h +++ /dev/null @@ -1,172 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiassist.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2007 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include "retroshare/rstypes.h" -#include "pqi/pqinetwork.h" -#include "pqi/pqimonitor.h" - -/** - * @file - * This header file provides interfaces for assisting the connections to - * friends. - */ - -class pqiNetAssist -{ -public: - - /* External Interface */ -virtual void enable(bool on) = 0; -virtual void shutdown() = 0; /* blocking call */ -virtual void restart() = 0; - -virtual bool getEnabled() = 0; -virtual bool getActive() = 0; - -virtual int tick() { return 0; } /* for internal accounting */ - - virtual ~pqiNetAssist(); -}; - -struct PortForwardParams -{ - uint32_t fwdId; - uint32_t status; - uint32_t typeFlags; - sockaddr_storage intAddr; - sockaddr_storage extaddr; -}; - -/** - * Provides interfaces to functionality like upnp and apple's equivalent. - */ -class pqiNetAssistFirewall: public pqiNetAssist -{ -public: - /* the address that the listening port is on */ -virtual void setInternalPort(unsigned short iport_in) = 0; -virtual void setExternalPort(unsigned short eport_in) = 0; - - /* as determined by uPnP */ -virtual bool getInternalAddress(struct sockaddr_storage &addr) = 0; -virtual bool getExternalAddress(struct sockaddr_storage &addr) = 0; - - - /* New Port Forward interface to support as many ports as necessary */ -virtual bool requestPortForward(const PortForwardParams ¶ms) = 0; -virtual bool statusPortForward(const uint32_t fwdId, PortForwardParams ¶ms) = 0; - - -}; - - -#define PNASS_TYPE_BADPEER 0x0001 -#define PNASS_REASON_UNKNOWN 0x0001 - -class pqiNetAssistPeerShare -{ -public: - /** share Addresses for various reasons (bad peers, etc) */ - virtual void updatePeer( - const RsPeerId& id, const struct sockaddr_storage &addr, - int type, int reason, int age ) = 0; - - virtual ~pqiNetAssistPeerShare(); -}; - - -#ifdef RS_USE_DHT_STUNNER -/* this is for the Stunners - * - * - */ - -class pqiAddrAssist -{ - public: - - pqiAddrAssist() { return; } -virtual ~pqiAddrAssist() { return; } - -virtual bool getExternalAddr(struct sockaddr_storage &remote, uint8_t &stable) = 0; -virtual void setRefreshPeriod(int32_t period) = 0; -virtual int tick() = 0; /* for internal accounting */ - -}; -#endif // RS_USE_DHT_STUNNER - -#define NETASSIST_KNOWN_PEER_OFFLINE 0x0001 -#define NETASSIST_KNOWN_PEER_ONLINE 0x0002 - -#define NETASSIST_KNOWN_PEER_WHITELIST 0x0100 -#define NETASSIST_KNOWN_PEER_FRIEND 0x0200 -#define NETASSIST_KNOWN_PEER_FOF 0x0400 -#define NETASSIST_KNOWN_PEER_RELAY 0x0800 -#define NETASSIST_KNOWN_PEER_SELF 0x1000 - -#define NETASSIST_KNOWN_PEER_TYPE_MASK 0xff00 - -/** - * Provides interfaces to other networks like DHT that can provide information. - * These classes would be expected to use the pqiMonitor callback system to - * notify the connectionMgr. - */ -class pqiNetAssistConnect: public pqiNetAssist -{ -public: - pqiNetAssistConnect(const RsPeerId& id, pqiConnectCb *cb) : - mPeerId(id), mConnCb(cb) {} - - /********** External DHT Interface ************************ - * These Functions are the external interface - * for the DHT, and must be non-blocking and return quickly - */ - - /* add / remove peers */ -virtual bool findPeer(const RsPeerId& id) = 0; -virtual bool dropPeer(const RsPeerId& id) = 0; - - /* add non-active peers (can still toggle active/non-active via above) */ -virtual int addBadPeer(const struct sockaddr_storage &addr, uint32_t reason, uint32_t flags, uint32_t age) = 0; -virtual int addKnownPeer(const RsPeerId &pid, const struct sockaddr_storage &addr, uint32_t flags) = 0; - -virtual void ConnectionFeedback(const RsPeerId& pid, int mode) = 0; - - /* extract current peer status */ -virtual bool getPeerStatus(const RsPeerId& id, - struct sockaddr_storage &laddr, struct sockaddr_storage &raddr, - uint32_t &type, uint32_t &mode) = 0; // DEPRECIATE. - -virtual bool setAttachMode(bool on) = 0; // FIXUP. - - /***** Stats for Network / DHT *****/ -virtual bool getNetworkStats(uint32_t &netsize, uint32_t &localnetsize) = 0; // DEPRECIATE. - - ~pqiNetAssistConnect() override; - -protected: - RsPeerId mPeerId; - pqiConnectCb *mConnCb; -}; diff --git a/libretroshare/src/pqi/pqibin.cc b/libretroshare/src/pqi/pqibin.cc deleted file mode 100644 index 75e0b4b39..000000000 --- a/libretroshare/src/pqi/pqibin.cc +++ /dev/null @@ -1,746 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqibin.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "pqi/pqibin.h" -#include "pqi/authssl.h" -#include "util/rsnet.h" -#include "util/rsdir.h" -#include "util/rsmemory.h" - -// #define DEBUG_PQIBIN - -BinFileInterface::BinFileInterface(const char *fname, int flags) - :bin_flags(flags), buf(NULL), hash(NULL), bcount(0) -{ - /* if read + write - open r+ */ - if ((bin_flags & BIN_FLAGS_READABLE) && - (bin_flags & BIN_FLAGS_WRITEABLE)) - { - buf = RsDirUtil::rs_fopen(fname, "rb+"); - /* if the file don't exist */ - if (!buf) - { - buf = RsDirUtil::rs_fopen(fname, "wb+"); - } - - } - else if (bin_flags & BIN_FLAGS_READABLE) - { - buf = RsDirUtil::rs_fopen(fname, "rb"); - } - else if (bin_flags & BIN_FLAGS_WRITEABLE) - { - // This is enough to remove old file in Linux... - // but not in windows.... (what to do) - buf = RsDirUtil::rs_fopen(fname, "wb"); - fflush(buf); /* this might help windows! */ - } - else - { - /* not read or write! */ - } - - if (buf) - { -#ifdef DEBUG_PQIBIN - std::cerr << "BinFileInterface: " << (void*)this << ": openned file " << fname << std::endl; -#endif - /* no problem */ - - /* go to the end */ - fseek(buf, 0L, SEEK_END); - /* get size */ - size = ftell(buf); - /* back to the start */ - fseek(buf, 0L, SEEK_SET); - } - else - { - size = 0; - } - - if (bin_flags & BIN_FLAGS_HASH_DATA) - { - hash = new pqihash(); - } -} - - -BinFileInterface::~BinFileInterface() -{ - if (buf) - { - fclose(buf); -#ifdef DEBUG_PQIBIN - std::cerr << "BinFileInterface: " << (void*)this << ": closed file " << std::endl; -#endif - } - - if (hash) - { - delete hash; - } -} - -int BinFileInterface::close() -{ - if (buf) - { - fclose(buf); -#ifdef DISTRIB_DEBUG - std::cerr << "BinFileInterface: " << (void*)this << ": closed file " << std::endl; -#endif - buf = NULL; - } - return 1; -} - -int BinFileInterface::senddata(void *data, int len) -{ - if (!buf) - return -1; - - if (1 != fwrite(data, len, 1, buf)) - { - return -1; - } - if (bin_flags & BIN_FLAGS_HASH_DATA) - { - hash->addData(data, len); - bcount += len; - } - return len; -} - -int BinFileInterface::readdata(void *data, int len) -{ - if (!buf) - return -1; - - if (1 != fread(data, len, 1, buf)) - { - return -1; - } - if (bin_flags & BIN_FLAGS_HASH_DATA) - { - hash->addData(data, len); - bcount += len; - } - return len; -} - -RsFileHash BinFileInterface::gethash() -{ - RsFileHash hashstr; - if (bin_flags & BIN_FLAGS_HASH_DATA) - { - hash->Complete(hashstr); - } - return hashstr; -} - -uint64_t BinFileInterface::bytecount() -{ - if (bin_flags & BIN_FLAGS_HASH_DATA) - { - return bcount; - } - return 0; -} - -uint64_t BinFileInterface::getFileSize() -{ - return size; -} - - - -BinEncryptedFileInterface::BinEncryptedFileInterface(const char* fname, int flags) - : BinFileInterface(fname, flags), data(NULL), haveData(false), sizeData(0), cpyCount(0) -{ -} - -BinEncryptedFileInterface::~BinEncryptedFileInterface() -{ - if((sizeData > 0) && data != NULL) - { - free(data); - } - -} - -int BinEncryptedFileInterface::senddata(void* data, int len) -{ - - void* encrytedData = NULL; - int encDataLen = 0; - - // encrypt using own ssl public key - if(len > 0) - AuthSSL::getAuthSSL()->encrypt((void*&)encrytedData, encDataLen, data, len, AuthSSL::getAuthSSL()->OwnId()); - else - return -1; - - - if((encDataLen > 0) && (encrytedData != NULL)) - { - BinFileInterface::senddata((unsigned char *)encrytedData, encDataLen); - free(encrytedData); - } - else - { - return -1; - } - - return len; -} - - -int BinEncryptedFileInterface::readdata(void* data, int len) -{ - // to respect the inherited behavior of BinInterface - // the whole file is read and decryped and store to be read by subsequent calls - char* encryptedData = NULL; - int encrypDataLen = 0; - - - if(!haveData) // read whole data for first call, or first call after close() - { - - uint64_t encrypDataLen64 = BinFileInterface::getFileSize(); - - if(encrypDataLen64 > uint64_t(~(int)0)) - { - std::cerr << __PRETTY_FUNCTION__ << ": cannot decrypt files of size > " << ~(int)0 << std::endl; - return -1 ; - } - encrypDataLen = (int)encrypDataLen64 ; - encryptedData = new char[encrypDataLen]; - - // make sure assign was successful - if(encryptedData == NULL) - return -1; - - - if(-1 == BinFileInterface::readdata(encryptedData, encrypDataLen)) - { - delete[] encryptedData; - return -1; - } - - if((encrypDataLen > 0) && (encryptedData != NULL)) - { - int sizeDataInt = 0 ; - - if(!AuthSSL::getAuthSSL()->decrypt((void*&)(this->data), sizeDataInt, encryptedData, encrypDataLen)) - { - delete[] encryptedData; - return -1; - } - - sizeData = sizeDataInt ; - haveData = true; - delete[] encryptedData; - } - - - if((uint64_t)len <= sizeData) - { - memcpy(data, this->data, len); - cpyCount += len; - } - else - { - std::cerr << "BinEncryptedFileInterface::readData(): Error, Asking for more data than present" << std::endl; - return -1; - } - } - else - { - - if((cpyCount + len) <= (uint64_t)sizeData) - { - memcpy(data, (void *) ((this->data) + cpyCount), len); - cpyCount += len; - } - else - { - std::cerr << "BinEncryptedFileInterface::readData(): Error, Asking for more data than present" << std::endl; - return -1; - } - } - - return len; -} - -int BinEncryptedFileInterface::close() -{ - if(data != NULL) - { - free(data); - sizeData = 0; - haveData = false; - cpyCount = 0; - } - - return BinFileInterface::close(); -} - -uint64_t BinEncryptedFileInterface::bytecount() -{ - return cpyCount; -} - -bool BinEncryptedFileInterface::moretoread(uint32_t /* usec */) -{ - if(haveData) - return (cpyCount < (uint64_t)sizeData); - else - return cpyCount < (uint64_t)getFileSize(); -} - -BinMemInterface::BinMemInterface(int defsize, int flags) - :bin_flags(flags), buf(NULL), size(defsize), - recvsize(0), readloc(0), hash(NULL), bcount(0) - { - buf = rs_malloc(defsize); - - if(buf == NULL) - { - close() ; - return ; - } - if (bin_flags & BIN_FLAGS_HASH_DATA) - { - hash = new pqihash(); - } - } - - -BinMemInterface::BinMemInterface(const void *data, const int defsize, int flags) - :bin_flags(flags), buf(NULL), size(defsize), - recvsize(0), readloc(0), hash(NULL), bcount(0) - { - buf = rs_malloc(defsize); - - if(buf == NULL) - { - close() ; - return ; - } - if (bin_flags & BIN_FLAGS_HASH_DATA) - { - hash = new pqihash(); - } - - /* just remove the const - * *BAD* but senddata don't change it anyway - */ - senddata((void *) data, defsize); - } - -BinMemInterface::~BinMemInterface() -{ - if (buf) - free(buf); - - if (hash) - delete hash; - return; -} - -int BinMemInterface::close() -{ - if (buf) - { - free(buf); - buf = NULL; - } - size = 0; - recvsize = 0; - readloc = 0; - return 1; -} - - /* some fns to mess with the memory */ -int BinMemInterface::fseek(int loc) - { - if (loc <= recvsize) - { - readloc = loc; - return 1; - } - return 0; - } - - -int BinMemInterface::senddata(void *data, const int len) - { - if(recvsize + len > size) - { - /* resize? */ - return -1; - } - memcpy((char *) buf + recvsize, data, len); - if (bin_flags & BIN_FLAGS_HASH_DATA) - { - hash->addData(data, len); - bcount += len; - } - recvsize += len; - return len; - } - - -int BinMemInterface::readdata(void *data, int len) - { - if(readloc + len > recvsize) - { - /* no more stuff? */ - return -1; - } - memcpy(data, (char *) buf + readloc, len); - if (bin_flags & BIN_FLAGS_HASH_DATA) - { - hash->addData(data, len); - bcount += len; - } - readloc += len; - return len; - } - - - -RsFileHash BinMemInterface::gethash() - { - RsFileHash hashstr; - if (bin_flags & BIN_FLAGS_HASH_DATA) - { - hash->Complete(hashstr); - } - return hashstr; - } - - -uint64_t BinMemInterface::bytecount() -{ - if (bin_flags & BIN_FLAGS_HASH_DATA) - { - return bcount; - } - return 0; -} - -bool BinMemInterface::writetofile(const char *fname) -{ - FILE *fd = RsDirUtil::rs_fopen(fname, "wb"); - if (!fd) - { - return false; - } - - if (1 != fwrite(buf, recvsize, 1, fd)) - { - fclose(fd); - return false; - } - - fclose(fd); - - return true; -} - -bool BinMemInterface::readfromfile(const char *fname) -{ - FILE *fd = RsDirUtil::rs_fopen(fname, "rb"); - if (!fd) - { - return false; - } - - /* get size */ - ::fseek(fd, 0L, SEEK_END); - int fsize = ftell(fd); - - if (fsize > size) - { - /* not enough room */ - std::cerr << "BinMemInterface::readfromfile() not enough room"; - std::cerr << std::endl; - - fclose(fd); - return false; - } - - ::fseek(fd, 0L, SEEK_SET); - if (1 != fread(buf, fsize, 1, fd)) - { - /* not enough room */ - std::cerr << "BinMemInterface::readfromfile() failed fread"; - std::cerr << std::endl; - - fclose(fd); - return false; - } - - recvsize = fsize; - readloc = 0; - fclose(fd); - - return true; -} - - -/**************************************************************************/ - - -void printNetBinID(std::ostream &out, const RsPeerId& id, uint32_t t) -{ - out << "NetBinId(" << id << ","; - if (t == PQI_CONNECT_TCP) - { - out << "TCP)"; - } - else if (t & (PQI_CONNECT_HIDDEN_TOR_TCP | PQI_CONNECT_HIDDEN_I2P_TCP)) - { - out << "HTCP"; - } - else - { - out << "UDP)"; - } -} - - -/************************** NetBinDummy ****************************** - * A test framework, - * - */ - -#include "pqi/pqiperson.h" - -const uint32_t DEFAULT_DUMMY_DELTA = 5; - -NetBinDummy::NetBinDummy(PQInterface *parent, const RsPeerId& id, uint32_t t) - :NetBinInterface(parent, id), type(t), dummyConnected(false), toConnect(false), connectDelta(DEFAULT_DUMMY_DELTA) -{ - return; -} - - // Net Interface -int NetBinDummy::connect(const struct sockaddr_storage &raddr) -{ - std::cerr << "NetBinDummy::connect("; - std::cerr << sockaddr_storage_tostring(raddr); - std::cerr << ") "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - - std::cerr << "NetBinDummy::dummyConnect = true!"; - std::cerr << std::endl; - - if (type == PQI_CONNECT_TCP) - { - std::cerr << "NetBinDummy:: Not connecting TCP"; - std::cerr << std::endl; - if (parent()) - { - //struct sockaddr_storage addr = raddr; - parent()->notifyEvent(this, CONNECT_FAILED, raddr); - } - } - else if (!dummyConnected) - { - toConnect = true; - connectTS = time(NULL) + connectDelta; - std::cerr << "NetBinDummy::toConnect = true, connect in: "; - std::cerr << connectDelta << " secs"; - std::cerr << std::endl; - } - else - { - std::cerr << "NetBinDummy:: Already Connected!"; - std::cerr << std::endl; - } - - return 1; -} - -int NetBinDummy::listen() -{ - std::cerr << "NetBinDummy::connect() "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - - return 1; -} - -int NetBinDummy::stoplistening() -{ - std::cerr << "NetBinDummy::stoplistening() "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - - return 1; -} - -int NetBinDummy::disconnect() -{ - std::cerr << "NetBinDummy::disconnect() "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - - std::cerr << "NetBinDummy::dummyConnect = false!"; - std::cerr << std::endl; - dummyConnected = false; - - if (parent()) - { - struct sockaddr_storage addr; - sockaddr_storage_clear(addr); - - parent()->notifyEvent(this, CONNECT_FAILED, addr); - } - - return 1; -} - -int NetBinDummy::reset() -{ - std::cerr << "NetBinDummy::reset() "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - - disconnect(); - - return 1; -} - - - // Bin Interface. -int NetBinDummy::tick() -{ - - if (toConnect) - { - if (connectTS < time(NULL)) - { - std::cerr << "NetBinDummy::tick() dummyConnected = true "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - dummyConnected = true; - toConnect = false; - if (parent()) - { - struct sockaddr_storage addr; - sockaddr_storage_clear(addr); - - parent()->notifyEvent(this, CONNECT_SUCCESS, addr); - } - } - else - { - std::cerr << "NetBinDummy::tick() toConnect "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - } - } - return 0; -} - -int NetBinDummy::senddata(void */*data*/, int len) -{ - std::cerr << "NetBinDummy::senddata() "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - - if (dummyConnected) - return len; - return 0; -} - -int NetBinDummy::readdata(void */*data*/, int /*len*/) -{ - std::cerr << "NetBinDummy::readdata() "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - - return 0; -} - -int NetBinDummy::netstatus() -{ - std::cerr << "NetBinDummy::netstatus() "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - - return 1; -} - -int NetBinDummy::isactive() -{ - std::cerr << "NetBinDummy::isactive() "; - printNetBinID(std::cerr, PeerId(), type); - if (dummyConnected) - std::cerr << " true "; - else - std::cerr << " false "; - std::cerr << std::endl; - - return dummyConnected; -} - -bool NetBinDummy::moretoread(uint32_t /* usec */) -{ - std::cerr << "NetBinDummy::moretoread() "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - - return false; -} - -bool NetBinDummy::cansend(uint32_t /* usec */) -{ - std::cerr << "NetBinDummy::cansend() "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - - return dummyConnected; -} - -int NetBinDummy::close() -{ - std::cerr << "NetBinDummy::close() "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - - return 1; -} - -RsFileHash NetBinDummy::gethash() -{ - std::cerr << "NetBinDummy::gethash() "; - printNetBinID(std::cerr, PeerId(), type); - std::cerr << std::endl; - - return RsFileHash(); -} - diff --git a/libretroshare/src/pqi/pqibin.h b/libretroshare/src/pqi/pqibin.h deleted file mode 100644 index 59a79622d..000000000 --- a/libretroshare/src/pqi/pqibin.h +++ /dev/null @@ -1,236 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqibin.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef PQI_BIN_INTERFACE_HEADER -#define PQI_BIN_INTERFACE_HEADER - - -#include "pqi/pqi_base.h" -#include "pqi/pqihash.h" -#include "util/rstime.h" - -#include - - -//! handles writing to binary files -/*! - * This allows for handling of binary file within Rs, In particular writing - * binary data to file declared in constructor - */ -class BinFileInterface: public BinInterface -{ -public: - BinFileInterface(const char *fname, int flags); -virtual ~BinFileInterface(); - -virtual int tick() { return 1; } - -virtual int senddata(void *data, int len); -virtual int readdata(void *data, int len); -virtual int netstatus() { return 1;} -virtual int isactive() { return (buf != NULL);} -virtual bool moretoread(uint32_t /* usec */ ) - { - if ((buf) && (bin_flags & BIN_FLAGS_READABLE)) - { - if ((size - ftell(buf)) > 0) - { - return true; - } - } - return false; - } - -virtual int close(); -virtual bool cansend(uint32_t /* usec */) - { - return (bin_flags & BIN_FLAGS_WRITEABLE); - } -virtual bool bandwidthLimited() { return false; } - -//! if HASHing is switched on -virtual RsFileHash gethash(); -virtual uint64_t bytecount(); - - virtual uint64_t getFileSize(); - -private: - int bin_flags; - FILE *buf; - uint64_t size; - pqihash *hash; - uint64_t bcount; -}; - -/*! - * use this for writing encrypted data to file using user's (ownid) ssl key - * hash for encrypted data is calculated, not the unencrypted data - */ -class BinEncryptedFileInterface : public BinFileInterface -{ -public: - - BinEncryptedFileInterface(const char *fname, int flags); - virtual ~BinEncryptedFileInterface(); - - /*! - * pls note if hashing is on, it is the hash of the encrypted data that is calculated - * also note, sif data is sent more than once, in a single instance of this object, then you will need to store the - * encrypted file size for each send externally as they are encrypted with different random keys. - * @param data data to be sent - * @param len length of data in bytes - * @return -1 if failed to write data, if not number bytes sent to file is returned - */ - int senddata(void *data, int len); - - /*! - * uses the hash of the encrypted data - * @param location to place data - * @param the length of data to be read - * @return -1 if failed to write data, if not number of bytes read is returned - */ - int readdata(void *data, int len); - - /*! - * this releases resources held by an instance - */ - int close(); - - uint64_t bytecount(); - bool moretoread(uint32_t usec); - -private: - - char* data; - bool haveData; - uint64_t sizeData; - uint64_t cpyCount; - -}; - -//! handles writing to reading/writing to memory -/*! - * This provide a memory interface for storing/retrieving information in memory - * to be read/sent elsewhere - */ -class BinMemInterface: public BinInterface -{ -public: - BinMemInterface(int defsize, int flags); - BinMemInterface(const void *data, const int size, int flags); -virtual ~BinMemInterface(); - - /* Extra Interfaces */ -int fseek(int loc); -int memsize() { return recvsize; } -void *memptr() { return buf; } - - /* file interface */ -bool writetofile(const char *fname); -bool readfromfile(const char *fname); - -virtual int tick() { return 1; } - -virtual int senddata(void *data, int len); -virtual int readdata(void *data, int len); -virtual int netstatus() { return 1; } -virtual int isactive() { return 1; } -virtual bool moretoread(uint32_t /* usec */) - { - if ((buf) && (bin_flags & BIN_FLAGS_READABLE )) - { - if (readloc < recvsize) - { - return true; - } - } - return false; - } - -virtual int close(); -virtual bool cansend(uint32_t /* usec */) - { - return (bin_flags & BIN_FLAGS_WRITEABLE); - } -virtual bool bandwidthLimited() { return false; } - -virtual RsFileHash gethash(); -virtual uint64_t bytecount(); - - private: - int bin_flags; - void *buf; - int size; - int recvsize; - int readloc; - pqihash *hash; - uint64_t bcount; -}; - - -class NetBinDummy: public NetBinInterface -{ -public: - NetBinDummy(PQInterface *parent, const RsPeerId& id, uint32_t t); -virtual ~NetBinDummy() { return; } - - // Net Interface -virtual int connect(const struct sockaddr_storage &raddr); -virtual int listen(); -virtual int stoplistening(); -virtual int disconnect(); -virtual int reset(); -virtual bool connect_parameter(uint32_t type, uint32_t value) - { - (void) type; /* suppress unused parameter warning */ - (void) value; /* suppress unused parameter warning */ - return false; - } -virtual int getConnectAddress(struct sockaddr_storage &raddr) - { - (void) raddr; /* suppress unused parameter warning */ - return 0; - } - - // Bin Interface. -virtual int tick(); - -virtual int senddata(void *data, int len); -virtual int readdata(void *data, int len); -virtual int netstatus(); -virtual int isactive(); -virtual bool moretoread(uint32_t usec); -virtual bool cansend(uint32_t usec); -virtual int close(); - -virtual RsFileHash gethash(); - - private: - uint32_t type; - bool dummyConnected; - bool toConnect; - uint32_t connectDelta; - rstime_t connectTS; -}; - - -#endif // PQI_BINARY_INTERFACES_HEADER - diff --git a/libretroshare/src/pqi/pqifdbin.cc b/libretroshare/src/pqi/pqifdbin.cc deleted file mode 100644 index 5ba6af155..000000000 --- a/libretroshare/src/pqi/pqifdbin.cc +++ /dev/null @@ -1,342 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: fsbio.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2021 by retroshare team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ - -#include "util/rsprint.h" -#include "util/rsfile.h" -#include "pqi/pqifdbin.h" - -RsFdBinInterface::RsFdBinInterface(int file_descriptor, bool is_socket) - : mCLintConnt(file_descriptor),mIsSocket(is_socket),mIsActive(false) -{ - mTotalReadBytes=0; - mTotalInBufferBytes=0; - mTotalWrittenBytes=0; - mTotalOutBufferBytes=0; - - if(file_descriptor!=0) - setSocket(file_descriptor); -} - -void RsFdBinInterface::setSocket(int s) -{ - if(mIsActive != 0) - { - RsErr() << "Changing socket to active FsBioInterface! Canceling all pending R/W data." ; - close(); - } -#ifndef WINDOWS_SYS - int flags = fcntl(s,F_GETFL); - - if(!(flags & O_NONBLOCK)) - { - RsWarn() << "Trying to use a blocking file descriptor in RsFdBinInterface. This is not going to work! Setting the socket to be non blocking."; - unix_fcntl_nonblock(s); - } - -#else - // On windows, there is no way to determine whether a socket is blocking or not, so we set it to non blocking whatsoever. - if (mIsSocket) { - unix_fcntl_nonblock(s); - } else { - RsFileUtil::set_fd_nonblock(s); - } -#endif - - mCLintConnt = s; - mIsActive = (s!=0); -} -int RsFdBinInterface::tick() -{ - if(!mIsActive) - { - RsErr() << "Ticking a non active FsBioInterface!" ; - return 0; - } - // 2 - read incoming data pending on existing connections - - int res=0; - - res += read_pending(); - res += write_pending(); - - return res; -} - -int RsFdBinInterface::read_pending() -{ - char inBuffer[1025]; - memset(inBuffer,0,1025); - - ssize_t readbytes; -#if WINDOWS_SYS - if (mIsSocket) - // Windows needs recv for sockets - readbytes = recv(mCLintConnt, inBuffer, sizeof(inBuffer), 0); - else -#endif - readbytes = read(mCLintConnt, inBuffer, sizeof(inBuffer)); // Needs read instead of recv which is only for sockets. - // Sockets should be set to non blocking by the client process. - - if(readbytes == 0) - { - RsDbg() << "Reached END of the stream!" ; - RsDbg() << "Closing!" ; - - close(); - return mTotalInBufferBytes; - } - if(readbytes < 0) - { - if(errno != 0 && errno != EWOULDBLOCK && errno != EAGAIN) -#ifdef WINDOWS_SYS - // A non blocking read to file descriptor gets ERROR_NO_DATA for empty data - if (mIsSocket == true || GetLastError() != ERROR_NO_DATA) -#endif - RsErr() << "read() failed. Errno=" << errno ; - - return mTotalInBufferBytes; - } - -#ifdef DEBUG_FS_BIN - RsDbg() << "clintConnt: " << mCLintConnt << ", readbytes: " << readbytes ; -#endif - - // display some debug info - - if(readbytes > 0) - { -#ifdef DEBUG_FS_BIN - RsDbg() << "Received the following bytes: " << RsUtil::BinToHex( reinterpret_cast(inBuffer),readbytes,50) << std::endl; - RsDbg() << "Received the following bytes: " << std::string(inBuffer,readbytes) << std::endl; -#endif - - void *ptr = malloc(readbytes); - - if(!ptr) - throw std::runtime_error("Cannot allocate memory! Go buy some RAM!"); - - memcpy(ptr,inBuffer,readbytes); - - in_buffer.push_back(std::make_pair(ptr,readbytes)); - mTotalInBufferBytes += readbytes; - mTotalReadBytes += readbytes; - -#ifdef DEBUG_FS_BIN - RsDbg() << "Socket: " << mCLintConnt << ". Total read: " << mTotalReadBytes << ". Buffer size: " << mTotalInBufferBytes ; -#endif - } - return mTotalInBufferBytes; -} - -int RsFdBinInterface::write_pending() -{ - if(out_buffer.empty()) - return mTotalOutBufferBytes; - - auto& p = out_buffer.front(); - int written; -#if WINDOWS_SYS - if (mIsSocket) - // Windows needs send for sockets - written = send(mCLintConnt, (char*) p.first, p.second, 0); - else -#endif - written = write(mCLintConnt, p.first, p.second); - - if(written < 0) - { - if(errno != EWOULDBLOCK && errno != EAGAIN) - RsErr() << "write() failed. Errno=" << errno ; - - return mTotalOutBufferBytes; - } - - if(written == 0) - { - RsErr() << "write() failed. Nothing sent."; - return mTotalOutBufferBytes; - } - -#ifdef DEBUG_FS_BIN - RsDbg() << "clintConnt: " << mCLintConnt << ", written: " << written ; -#endif - - // display some debug info - -#ifdef DEBUG_FS_BIN - RsDbg() << "Sent the following bytes: " << RsUtil::BinToHex( reinterpret_cast(p.first),written,50) << std::endl; -#endif - - if(written < p.second) - { - void *ptr = malloc(p.second - written); - - if(!ptr) - throw std::runtime_error("Cannot allocate memory! Go buy some RAM!"); - - memcpy(ptr,static_cast(p.first) + written,p.second - written); - free(p.first); - - out_buffer.front().first = ptr; - out_buffer.front().second = p.second - written; - } - else - { - free(p.first); - out_buffer.pop_front(); - } - - mTotalOutBufferBytes -= written; - mTotalWrittenBytes += written; - - return mTotalOutBufferBytes; -} - -RsFdBinInterface::~RsFdBinInterface() -{ - clean(); -} - -void RsFdBinInterface::clean() -{ - for(auto p:in_buffer) free(p.first); - for(auto p:out_buffer) free(p.first); - - in_buffer.clear(); - out_buffer.clear(); -} - -int RsFdBinInterface::readline(void *data, int len) -{ - int n=0; - - for(auto p:in_buffer) - for(int i=0;i(p.first)[i] == '\n') - return readdata(data,n+1); - - return 0; -} - -int RsFdBinInterface::readdata(void *data, int len) -{ - // read incoming bytes in the buffer - - int total_len = 0; - - while(total_len < len) - { - if(in_buffer.empty()) - { - mTotalInBufferBytes -= total_len; - return total_len; - } - - // If the remaining buffer is too large, chop of the beginning of it. - - if(total_len + in_buffer.front().second > len) - { - memcpy(&(static_cast(data)[total_len]),in_buffer.front().first,len - total_len); - - void *ptr = malloc(in_buffer.front().second - (len - total_len)); - memcpy(ptr,&(static_cast(in_buffer.front().first)[len - total_len]),in_buffer.front().second - (len - total_len)); - - free(in_buffer.front().first); - in_buffer.front().first = ptr; - in_buffer.front().second -= len-total_len; - - mTotalInBufferBytes -= len; - return len; - } - else // copy everything - { - memcpy(&(static_cast(data)[total_len]),in_buffer.front().first,in_buffer.front().second); - - total_len += in_buffer.front().second; - - free(in_buffer.front().first); - in_buffer.pop_front(); - } - } - mTotalInBufferBytes -= len; - return len; -} - -int RsFdBinInterface::senddata(void *data, int len) -{ - // shouldn't we better send in multiple packets, similarly to how we read? - - if(len == 0) - { - RsErr() << "Calling FsBioInterface::senddata() with null size or null data pointer"; - return 0; - } - void *ptr = malloc(len); - - if(!ptr) - { - RsErr() << "Cannot allocate data of size " << len ; - return 0; - } - - memcpy(ptr,data,len); - out_buffer.push_back(std::make_pair(ptr,len)); - - mTotalOutBufferBytes += len; - return len; -} -int RsFdBinInterface::netstatus() -{ - return mIsActive; // dummy response. -} - -int RsFdBinInterface::isactive() -{ - return mIsActive ; -} - -bool RsFdBinInterface::moretoread(uint32_t /* usec */) -{ - return mTotalInBufferBytes > 0; -} - -bool RsFdBinInterface::moretowrite(uint32_t /* usec */) -{ - return mTotalOutBufferBytes > 0 ; -} - -bool RsFdBinInterface::cansend(uint32_t) -{ - return isactive(); -} - -int RsFdBinInterface::close() -{ - RsDbg() << "Stopping network interface" << std::endl; - mIsActive = false; - mCLintConnt = 0; - clean(); - - return 1; -} - - diff --git a/libretroshare/src/pqi/pqifdbin.h b/libretroshare/src/pqi/pqifdbin.h deleted file mode 100644 index a3709c22e..000000000 --- a/libretroshare/src/pqi/pqifdbin.h +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************************* - * libretroshare/src/file_sharing: fsbio.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2021 by retroshare team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ - -#include "pqi/pqi_base.h" - -class RsFdBinInterface: public BinInterface -{ -public: - RsFdBinInterface(int file_descriptor, bool is_socket); - ~RsFdBinInterface(); - - // Implements BinInterface methods - - int tick() override; - - // Schedule data to be sent at the next tick(). The caller keeps memory ownership. - // - int senddata(void *data, int len) override; - - // Obtains new data from the interface. "data" needs to be initialized for room - // to len bytes. The returned value is the actual size of what was read. - // - int readdata(void *data, int len) override; - - // Read at most len bytes only if \n is encountered within that range. Otherwise, nothing is changed. - // - int readline(void *data, int len) ; - - int netstatus() override; - int isactive() override; - bool moretoread(uint32_t usec) override; - bool moretowrite(uint32_t usec) ; - bool cansend(uint32_t usec) override; - - int close() override; - - /** - * If hashing data - **/ - RsFileHash gethash() override { return RsFileHash() ; } - uint64_t bytecount() override { return mTotalReadBytes; } - - bool bandwidthLimited() override { return false; } - -protected: - void setSocket(int s); - void clean(); - -private: - int read_pending(); - int write_pending(); - - int mCLintConnt; - bool mIsSocket; - bool mIsActive; - uint32_t mTotalReadBytes; - uint32_t mTotalInBufferBytes; - uint32_t mTotalWrittenBytes; - uint32_t mTotalOutBufferBytes; - - std::list > in_buffer; - std::list > out_buffer; -}; - diff --git a/libretroshare/src/pqi/pqihandler.cc b/libretroshare/src/pqi/pqihandler.cc deleted file mode 100644 index 1864354a0..000000000 --- a/libretroshare/src/pqi/pqihandler.cc +++ /dev/null @@ -1,510 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqihandler.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "pqi/pqihandler.h" - -#include // for NULL -#include "util/rstime.h" // for time, rstime_t -#include // for sort -#include // for dec -#include // for string, char_traits, operator+, bas... -#include // for pair - -#include "pqi/pqi_base.h" // for PQInterface, RsBwRates -#include "retroshare/rsconfig.h" // for RSTrafficClue -#include "retroshare/rsids.h" // for t_RsGenericIdType -#include "retroshare/rspeers.h" // for RsPeers, rsPeers -#include "serialiser/rsserial.h" // for RsItem, RsRawItem -#include "util/rsdebug.h" // for pqioutput, PQL_DEBUG_BASIC, PQL_ALERT -#include "util/rsstring.h" // for rs_sprintf_append - -using std::dec; - -#ifdef WINDOWS_SYS -#include -#endif - -struct RsLog::logInfo pqihandlerzoneInfo = {RsLog::Default, "pqihandler"}; -#define pqihandlerzone &pqihandlerzoneInfo - -//static const int PQI_HANDLER_NB_PRIORITY_LEVELS = 10 ; -//static const float PQI_HANDLER_NB_PRIORITY_RATIO = 2 ; - -//#define UPDATE_RATES_DEBUG 1 -// #define DEBUG_TICK 1 -// #define RSITEM_DEBUG 1 - -pqihandler::pqihandler() : coreMtx("pqihandler") -{ - RS_STACK_MUTEX(coreMtx); /**************** LOCKED MUTEX ****************/ - - // setup minimal total+individual rates. - rateIndiv_out = 0.01; - rateIndiv_in = 0.01; - rateMax_out = 0.01; - rateMax_in = 0.01; - rateTotal_in = 0.0 ; - rateTotal_out = 0.0 ; - traffInSum = 0; - traffOutSum = 0; - last_m = time(NULL) ; - nb_ticks = 0 ; - mLastRateCapUpdate = 0 ; - ticks_per_sec = 5 ; // initial guess - return; -} - -int pqihandler::tick() -{ - int moreToTick = 0; - - { - RS_STACK_MUTEX(coreMtx); /**************** LOCKED MUTEX ****************/ - - // tick all interfaces... - std::map::iterator it; - for(it = mods.begin(); it != mods.end(); ++it) - { - if (0 < ((it -> second) -> pqi) -> tick()) - { -#ifdef DEBUG_TICK - std::cerr << "pqihandler::tick() moreToTick from mod()" << std::endl; -#endif - moreToTick = 1; - } - } -#ifdef TO_BE_REMOVED - // get the items, and queue them correctly - if (0 < locked_GetItems()) - { -#ifdef DEBUG_TICK - std::cerr << "pqihandler::tick() moreToTick from GetItems()" << std::endl; -#endif - moreToTick = 1; - } -#endif - } - - rstime_t now = time(NULL) ; - - if(now > mLastRateCapUpdate + 5) - { - std::map rateMap; - std::map::iterator it; - - - // every 5 secs, update the max rates for all modules - - RS_STACK_MUTEX(coreMtx); /**************** LOCKED MUTEX ****************/ - for(std::map::iterator it = mods.begin(); it != mods.end(); ++it) - { - // This is rather inelegant, but pqihandler has searchModules that are dynamically allocated, so the max rates - // need to be updated from inside. - uint32_t maxUp = 0,maxDn =0 ; - if (rsPeers->getPeerMaximumRates(it->first,maxUp,maxDn) ) - it->second->pqi->setRateCap(maxDn,maxUp);// mind the order! Dn first, than Up. - } - - mLastRateCapUpdate = now ; - } - - UpdateRates(); - return moreToTick; -} - - -bool pqihandler::queueOutRsItem(RsItem *item) -{ - RS_STACK_MUTEX(coreMtx); /**************** LOCKED MUTEX ****************/ - - uint32_t size ; - locked_HandleRsItem(item, size); - -#ifdef DEBUG_QOS - if(item->priority_level() == QOS_PRIORITY_UNKNOWN) - std::cerr << "Caught an unprioritized item !" << std::endl; - - print() ; -#endif - return true ; -} - -int pqihandler::status() -{ - std::map::iterator it; - RS_STACK_MUTEX(coreMtx); /**************** LOCKED MUTEX ****************/ - - { // for output - std::string out = "pqihandler::status() Active Modules:\n"; - - // display all interfaces... - for(it = mods.begin(); it != mods.end(); ++it) - { - rs_sprintf_append(out, "\tModule [%s] Pointer <%p>", it -> first.toStdString().c_str(), (void *) ((it -> second) -> pqi)); - } - - pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, out); - - } // end of output. - - - // status all interfaces... - for(it = mods.begin(); it != mods.end(); ++it) - { - ((it -> second) -> pqi) -> status(); - } - return 1; -} - -bool pqihandler::AddSearchModule(SearchModule *mod) -{ - RS_STACK_MUTEX(coreMtx); /**************** LOCKED MUTEX ****************/ - // if peerid used -> error. - //std::map::iterator it; - if (mod->peerid != mod->pqi->PeerId()) - { - // ERROR! - pqioutput(PQL_ALERT, pqihandlerzone, "ERROR peerid != PeerId!"); - return false; - } - - if (mod->peerid.isNull()) - { - // ERROR! - pqioutput(PQL_ALERT, pqihandlerzone, "ERROR peerid == NULL"); - return false; - } - - if (mods.find(mod->peerid) != mods.end()) - { - // ERROR! - pqioutput(PQL_ALERT, pqihandlerzone, "ERROR PeerId Module already exists!"); - return false; - } - - // store. - mods[mod->peerid] = mod; - return true; -} - -bool pqihandler::RemoveSearchModule(SearchModule *mod) -{ - RS_STACK_MUTEX(coreMtx); /**************** LOCKED MUTEX ****************/ - std::map::iterator it; - for(it = mods.begin(); it != mods.end(); ++it) - { - if (mod == it -> second) - { - mods.erase(it); - return true; - } - } - return false; -} - -// generalised output -int pqihandler::locked_HandleRsItem(RsItem *item, uint32_t& computed_size) -{ - computed_size = 0 ; - std::map::iterator it; - pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, - "pqihandler::HandleRsItem()"); - - pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, - "pqihandler::HandleRsItem() Sending to One Channel"); -#ifdef DEBUG_TICK - std::cerr << "pqihandler::HandleRsItem() Sending to One Channel" << std::endl; -#endif - - - // find module. - if ((it = mods.find(item->PeerId())) == mods.end()) - { - std::string out = "pqihandler::HandleRsItem() Invalid chan!"; - pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, out); -#ifdef DEBUG_TICK - std::cerr << out << std::endl; -#endif - - delete item; - return -1; - } - - std::string out = "pqihandler::HandleRsItem() sending to chan: " + it -> first.toStdString(); - pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, out); -#ifdef DEBUG_TICK - std::cerr << out << std::endl; -#endif - - // if yes send on item. - ((it -> second) -> pqi) -> SendItem(item,computed_size); - return 1; -} - -int pqihandler::SendRsRawItem(RsRawItem *ns) -{ - pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, "pqihandler::SendRsRawItem()"); - - // directly send item to streamers - - return queueOutRsItem(ns) ; -} - -int pqihandler::ExtractTrafficInfo(std::list& out_lst,std::list& in_lst) -{ - in_lst.clear() ; - out_lst.clear() ; - - for( std::map::iterator it = mods.begin(); it != mods.end(); ++it) - { - std::list ilst,olst ; - - (it -> second)->pqi->gatherStatistics(olst,ilst) ; - - for(std::list::const_iterator it(ilst.begin());it!=ilst.end();++it) in_lst.push_back(*it) ; - for(std::list::const_iterator it(olst.begin());it!=olst.end();++it) out_lst.push_back(*it) ; - } - - return 1 ; -} - -// NEW extern fn to extract rates. -int pqihandler::ExtractRates(std::map &ratemap, RsBwRates &total) -{ - total.mMaxRateIn = getMaxRate(true); - total.mMaxRateOut = getMaxRate(false); - total.mRateIn = 0; - total.mRateOut = 0; - total.mQueueIn = 0; - total.mQueueOut = 0; - - /* Lock once rates have been retrieved */ - RS_STACK_MUTEX(coreMtx); /**************** LOCKED MUTEX ****************/ - - std::map::iterator it; - for(it = mods.begin(); it != mods.end(); ++it) - { - SearchModule *mod = (it -> second); - - RsBwRates peerRates; - mod -> pqi -> getRates(peerRates); - - total.mRateIn += peerRates.mRateIn; - total.mRateOut += peerRates.mRateOut; - total.mQueueIn += peerRates.mQueueIn; - total.mQueueOut += peerRates.mQueueOut; - - ratemap[it->first] = peerRates; - - } - - return 1; -} - - - -// internal fn to send updates -int pqihandler::UpdateRates() -{ - std::map::iterator it; - - float avail_in = getMaxRate(true); - float avail_out = getMaxRate(false); - - float used_bw_in = 0; - float used_bw_out = 0; - - /* Lock once rates have been retrieved */ - RS_STACK_MUTEX(coreMtx); /**************** LOCKED MUTEX ****************/ - - int num_sm = mods.size(); - float used_bw_in_table[num_sm]; /* table of in bandwidth currently used by each module */ - float used_bw_out_table[num_sm]; /* table of out bandwidth currently used by each module */ - - // loop through modules to get the used bandwidth -#ifdef UPDATE_RATES_DEBUG - RsDbg() << "UPDATE_RATES pqihandler::UpdateRates Looping through modules" << std::endl; -#endif - - int index = 0; - - for(it = mods.begin(); it != mods.end(); ++it) - { - SearchModule *mod = (it -> second); - - traffInSum += mod -> pqi -> getTraffic(true); - traffOutSum += mod -> pqi -> getTraffic(false); - - float crate_in = mod -> pqi -> getRate(true); - float crate_out = mod -> pqi -> getRate(false); - - used_bw_in += crate_in; - used_bw_out += crate_out; - - /* fill the table of used bandwidths */ - used_bw_in_table[index] = crate_in; - used_bw_out_table[index] = crate_out; - - ++index; - } - -#ifdef UPDATE_RATES_DEBUG - RsDbg() << "UPDATE_RATES pqihandler::UpdateRates Sorting used_bw_out_table: " << num_sm << " entries" << std::endl; -#endif - - /* Sort the used bw in/out table in ascending order */ - std::sort(used_bw_in_table, used_bw_in_table + num_sm); - std::sort(used_bw_out_table, used_bw_out_table + num_sm); - -#ifdef UPDATE_RATES_DEBUG - RsDbg() << "UPDATE_RATES pqihandler::UpdateRates used_bw_out " << used_bw_out << std::endl; -#endif - - /* Calculate the optimal out_max value, taking into account avail_out and the out bw requested by modules */ - - float out_remaining_bw = avail_out; - float out_max_bw = 0; - bool keep_going = true; - int mod_index = 0; - - while (keep_going && (mod_index < num_sm)) { - float result = (num_sm - mod_index) * (used_bw_out_table[mod_index] - out_max_bw); - if (result > out_remaining_bw) { - /* There is not enough remaining out bw to satisfy all modules, - distribute the remaining out bw among modules, then exit */ - out_max_bw += out_remaining_bw / (num_sm - mod_index); - out_remaining_bw = 0; - keep_going = false; - } else { - /* Grant the requested out bandwidth to all modules, - then recalculate the remaining out bandwidth */ - out_remaining_bw -= result; - out_max_bw = used_bw_out_table[mod_index]; - ++mod_index; - } - } - -#ifdef UPDATE_RATES_DEBUG - RsDbg() << "UPDATE_RATES pqihandler::UpdateRates mod_index " << mod_index << " out_max_bw " << out_max_bw << " remaining out bw " << out_remaining_bw << std::endl; -#endif - - /* Allocate only 50 pct the remaining out bw, if any, to make the transition more smooth */ - out_max_bw = out_max_bw + 0.5 * out_remaining_bw; - - /* Calculate the optimal in_max value, taking into account avail_in and the in bw requested by modules */ - - float in_remaining_bw = avail_in; - float in_max_bw = 0; - keep_going = true; - mod_index = 0; - - while (keep_going && mod_index < num_sm) { - float result = (num_sm - mod_index) * (used_bw_in_table[mod_index] - in_max_bw); - if (result > in_remaining_bw) { - /* There is not enough remaining in bw to satisfy all modules, - distribute the remaining in bw among modules, then exit */ - in_max_bw += in_remaining_bw / (num_sm - mod_index); - in_remaining_bw = 0; - keep_going = false; - } else { - /* Grant the requested in bandwidth to all modules, - then recalculate the remaining in bandwidth */ - in_remaining_bw -= result; - in_max_bw = used_bw_in_table[mod_index]; - ++mod_index; - } - } - -#ifdef UPDATE_RATES_DEBUG - RsDbg() << "UPDATE_RATES pqihandler::UpdateRates mod_index " << mod_index << " in_max_bw " << in_max_bw << " remaining in bw " << in_remaining_bw << std::endl; -#endif - - // allocate only 75 pct of the remaining in bw, to make the transition more smooth - in_max_bw = in_max_bw + 0.75 * in_remaining_bw; - - // store current total in and out used bw - locked_StoreCurrentRates(used_bw_in, used_bw_out); - -#ifdef UPDATE_RATES_DEBUG - RsDbg() << "UPDATE_RATES pqihandler::UpdateRates setting new out_max " << out_max_bw << " in_max " << in_max_bw << std::endl; -#endif - - // retrieve the bandwidth limits provided by peers via BwCtrl - std::map rateMap; - rsConfig->getAllBandwidthRates(rateMap); - std::map::iterator rateMap_it; - -#ifdef UPDATE_RATES_DEBUG - // dump RsConfigurationDataRates - RsDbg() << "UPDATE_RATES pqihandler::UpdateRates RsConfigDataRates dump" << std::endl; - for (rateMap_it = rateMap.begin(); rateMap_it != rateMap.end(); rateMap_it++) - RsDbg () << "UPDATE_RATES pqihandler::UpdateRates PeerId " << rateMap_it->first.toStdString() << " mAllowedOut " << rateMap_it->second.mAllowedOut << std::endl; -#endif - - // update max rates - for(it = mods.begin(); it != mods.end(); ++it) - { - SearchModule *mod = (it -> second); - - // for our down bandwidth we use the calculated value without taking into account the max up provided by peers via BwCtrl - // this is harmless as they will control their up bw on their side - mod -> pqi -> setMaxRate(true, in_max_bw); - - // for our up bandwidth we take into account the max down provided by peers via BwCtrl - // because we don't want to clog our outqueues, the TCP buffers, and the peers inbound queues - mod -> pqi -> setMaxRate(false, out_max_bw); - if ((rateMap_it = rateMap.find(mod->pqi->PeerId())) != rateMap.end()) - if (rateMap_it->second.mAllowedOut > 0) - if (out_max_bw > rateMap_it->second.mAllowedOut) - mod -> pqi -> setMaxRate(false, rateMap_it->second.mAllowedOut); - } - -#ifdef UPDATE_RATES_DEBUG - // dump maxRates - for(it = mods.begin(); it != mods.end(); ++it) - { - SearchModule *mod = (it -> second); - RsDbg() << "UPDATE_RATES pqihandler::UpdateRates PeerID " << (mod ->pqi -> PeerId()).toStdString() << " new bandwidth limits up " << mod -> pqi -> getMaxRate(false) << " down " << mod -> pqi -> getMaxRate(true) << std::endl; - } -#endif - - return 1; -} - -void pqihandler::getCurrentRates(float &in, float &out) -{ - RS_STACK_MUTEX(coreMtx); /**************** LOCKED MUTEX ****************/ - - in = rateTotal_in; - out = rateTotal_out; -} - -void pqihandler::locked_StoreCurrentRates(float in, float out) -{ - rateTotal_in = in; - rateTotal_out = out; -} - -void pqihandler::GetTraffic(uint64_t &in, uint64_t &out) -{ - in = traffInSum; - out = traffOutSum; -} diff --git a/libretroshare/src/pqi/pqihandler.h b/libretroshare/src/pqi/pqihandler.h deleted file mode 100644 index 4bfd4f828..000000000 --- a/libretroshare/src/pqi/pqihandler.h +++ /dev/null @@ -1,152 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqihandler.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_HANDLER_HEADER -#define MRK_PQI_HANDLER_HEADER - -#include // for uint32_t -#include "util/rstime.h" // for rstime_t, NULL -#include // for list -#include // for map - -#include "pqi/pqi.h" // for P3Interface, pqiPublisher -#include "retroshare/rstypes.h" // for RsPeerId -#include "util/rsthreads.h" // for RsStackMutex, RsMutex - -class PQInterface; -struct RSTrafficClue; -class RsBwRates; -struct RsItem; -class RsRawItem; - -class SearchModule -{ - public: - SearchModule() : pqi(NULL) {} - - RsPeerId peerid ; - PQInterface *pqi; -}; - -// Presents a P3 Face to the world! -// and funnels data through to a PQInterface. -// -class pqihandler: public P3Interface, public pqiPublisher -{ - public: - pqihandler(); - - /**** Overloaded from pqiPublisher ****/ - virtual bool sendItem(RsRawItem *item) - { - return SendRsRawItem(item); - } - - bool AddSearchModule(SearchModule *mod); - bool RemoveSearchModule(SearchModule *mod); - - // Rest of P3Interface - virtual int tick(); - virtual int status(); - - // Service Data Interface - virtual int SendRsRawItem(RsRawItem *); -#ifdef TO_BE_REMOVED - virtual RsRawItem *GetRsRawItem(); -#endif - - // rate control. - //void setMaxRate(const RsPeerId& pid,bool in, uint32_t val_kBs); - void setMaxRate(bool in, float val); - float getMaxRate(bool in); - - void setMaxRates(const RsPeerId& pid,bool in,float val) ; - float getMaxRates(const RsPeerId& pid,bool in) ; - - void getCurrentRates(float &in, float &out); - - // TESTING INTERFACE. - int ExtractRates(std::map &ratemap, RsBwRates &totals); - int ExtractTrafficInfo(std::list &out_lst, std::list &in_lst); - - uint64_t traffInSum; - uint64_t traffOutSum; - void GetTraffic(uint64_t &in, uint64_t &out); - -protected: - /* check to be overloaded by those that can - * generates warnings otherwise - */ - - int locked_HandleRsItem(RsItem *ns, uint32_t& size); - bool queueOutRsItem(RsItem *) ; - -#ifdef TO_BE_REMOVED - int locked_GetItems(); - void locked_SortnStoreItem(RsItem *item); -#endif - - RsMutex coreMtx; /* MUTEX */ - - std::map mods; - - std::list in_service; - - private: - - // rate control. - int UpdateRates(); - void locked_StoreCurrentRates(float in, float out); - - float rateIndiv_in; - float rateIndiv_out; - float rateMax_in; - float rateMax_out; - - float rateTotal_in; - float rateTotal_out; - - uint32_t nb_ticks ; - rstime_t last_m ; - rstime_t mLastRateCapUpdate ; - float ticks_per_sec ; -}; - -inline void pqihandler::setMaxRate(bool in, float val) -{ - RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ - if (in) - rateMax_in = val; - else - rateMax_out = val; - return; -} - -inline float pqihandler::getMaxRate(bool in) -{ - RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ - if (in) - return rateMax_in; - else - return rateMax_out; -} - -#endif // MRK_PQI_HANDLER_HEADER diff --git a/libretroshare/src/pqi/pqihash.h b/libretroshare/src/pqi/pqihash.h deleted file mode 100644 index 9a36cb89c..000000000 --- a/libretroshare/src/pqi/pqihash.h +++ /dev/null @@ -1,93 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqihash.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008-2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef PQI_HASH_ -#define PQI_HASH_ - -#include -#include -#include -#include -#include -#include "util/rsstring.h" -#include "retroshare/rstypes.h" -#include - -class pqihash -{ - public: - pqihash() -{ - - sha_hash = new uint8_t[SHA_DIGEST_LENGTH]; - memset(sha_hash,0,SHA_DIGEST_LENGTH*sizeof(uint8_t)) ; - sha_ctx = new SHA_CTX; - SHA1_Init(sha_ctx); - doHash = true; -} - - ~pqihash() -{ - delete[] sha_hash; - delete sha_ctx; -} - - -void addData(const void *data, uint32_t len) -{ - if (doHash) - { - SHA1_Update(sha_ctx, data, len); - } -} - -void Complete(RsFileHash &hash) -{ - if (!doHash) - { - hash = endHash; - return; - } - - SHA1_Final(sha_hash, sha_ctx); - - endHash.clear(); - endHash = hash = Sha1CheckSum(sha_hash); - -// for(int i = 0; i < SHA_DIGEST_LENGTH; i++) -// { -// rs_sprintf_append(endHash, "%02x", (unsigned int) (sha_hash[i])); -// } -// hash = endHash; - doHash = false; - - return; -} - - private: - - bool doHash; - RsFileHash endHash; - uint8_t *sha_hash; - SHA_CTX *sha_ctx; -}; - -#endif diff --git a/libretroshare/src/pqi/pqiindic.h b/libretroshare/src/pqi/pqiindic.h deleted file mode 100644 index 28f619b16..000000000 --- a/libretroshare/src/pqi/pqiindic.h +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiindic.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_INDICATOR_HEADER -#define MRK_PQI_INDICATOR_HEADER - -#include - -// This will indicate to num different sources -// when the event has occured. - -class Indicator -{ - public: - explicit Indicator(uint16_t n = 1) - :num(n), changeFlags(n) {IndicateChanged();} -void IndicateChanged() - { - for(uint16_t i = 0; i < num; i++) - changeFlags[i]=true; - } - -bool Changed(uint16_t idx = 0) - { - /* catch overflow */ - if (idx > num - 1) - return false; - - bool ans = changeFlags[idx]; - changeFlags[idx] = false; - return ans; - } - - private: - uint16_t num; - std::vector changeFlags; -}; - - - -#endif diff --git a/libretroshare/src/pqi/pqiipset.cc b/libretroshare/src/pqi/pqiipset.cc deleted file mode 100644 index 6c273b47c..000000000 --- a/libretroshare/src/pqi/pqiipset.cc +++ /dev/null @@ -1,264 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiipset.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "util/rstime.h" -#include "pqi/pqiipset.h" -#include "util/rsstring.h" - -bool pqiIpAddress::sameAddress(const pqiIpAddress &a) const -{ - return sockaddr_storage_same(mAddr, a.mAddr); -} - - -bool pqiIpAddress::validAddress() const -{ - /* filter for unlikely addresses */ - if(sockaddr_storage_isLoopbackNet(mAddr)) - { -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddress::validAddress() ip parameter is loopback: disgarding." << std::endl ; -#endif - return false; - } - - if(sockaddr_storage_isnull(mAddr)) - { -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddress::validAddress() ip parameter is 0.0.0.0/1, or port is 0, ignoring." << std::endl; -#endif - return false; - } - - return true; - -} - - -bool pqiIpAddrList::updateIpAddressList(const pqiIpAddress &addr) -{ - std::list::iterator it; - bool add = false; - bool newAddr = true; - -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrList::updateIpAddressList()"; - std::cerr << std::endl; -#endif - - if (mAddrs.size() < MAX_ADDRESS_LIST_SIZE) - { -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrList::updateIpAddressList() small list: Add"; - std::cerr << std::endl; -#endif - add = true; - } - else if (mAddrs.back().mSeenTime < addr.mSeenTime) - { -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrList::updateIpAddressList() oldAddr: Add"; - std::cerr << std::endl; -#endif - add = true; - } - - if ((!add) || (!addr.validAddress())) - { -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrList::updateIpAddressList() not Add or !valid.. fail"; - std::cerr << std::endl; -#endif - return false; - } - - for(it = mAddrs.begin(); it != mAddrs.end(); ++it) - { - if (it->sameAddress(addr)) - { -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrList::updateIpAddressList() found duplicate"; - std::cerr << std::endl; -#endif - if (it->mSeenTime > addr.mSeenTime) - { -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrList::updateIpAddressList() orig better, returning"; - std::cerr << std::endl; -#endif - /* already better -> quit */ - return false; - } - -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrList::updateIpAddressList() deleting orig"; - std::cerr << std::endl; -#endif - it = mAddrs.erase(it); - newAddr = false; - break; - } - } - - // ordered by decreaseing time. (newest at front) - bool added = false; - for(it = mAddrs.begin(); it != mAddrs.end(); ++it) - { - if (it->mSeenTime < addr.mSeenTime) - { -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrList::updateIpAddressList() added orig SeenTime: " << it->mSeenTime << " new SeenTime: " << addr.mSeenTime; - std::cerr << std::endl; -#endif - - added = true; - mAddrs.insert(it, addr); - break; - } - } - if (!added) - { -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrList::updateIpAddressList() pushing to back"; - std::cerr << std::endl; -#endif - mAddrs.push_back(addr); - } - - /* pop if necessary */ - while (mAddrs.size() > MAX_ADDRESS_LIST_SIZE) - { -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrList::updateIpAddressList() popping back"; - std::cerr << std::endl; -#endif - mAddrs.pop_back(); - } - - return newAddr; -} - -void pqiIpAddrList::extractFromTlv(const RsTlvIpAddrSet &tlvAddrs) -{ - std::list::const_iterator it; - - //for(it = tlvAddrs.addrs.begin(); it != tlvAddrs.addrs.end() ; ++it) - for(it = tlvAddrs.mList.begin(); it != tlvAddrs.mList.end() ; ++it) - { - pqiIpAddress addr; - addr.mAddr = it->addr.addr; - addr.mSeenTime = it->seenTime; - addr.mSrc = it->source; - - mAddrs.push_back(addr); - } -} - -void pqiIpAddrList::loadTlv(RsTlvIpAddrSet &tlvAddrs) const -{ - std::list::const_iterator it; - - for(it = mAddrs.begin(); it != mAddrs.end() ; ++it) - { - RsTlvIpAddressInfo addr; - addr.addr.addr = it->mAddr; - addr.seenTime = it->mSeenTime; - addr.source = it->mSrc; - - //tlvAddrs.addrs.push_back(addr); - tlvAddrs.mList.push_back(addr); - } -} - - - -void pqiIpAddrList::printIpAddressList(std::string &out) const -{ - std::list::const_iterator it; - rstime_t now = time(NULL); - for(it = mAddrs.begin(); it != mAddrs.end(); ++it) - { - out += sockaddr_storage_tostring(it->mAddr); - rs_sprintf_append(out, "( %ld old)\n", now - it->mSeenTime); - } - return; -} - - -bool pqiIpAddrSet::updateLocalAddrs(const pqiIpAddress &addr) -{ - return mLocal.updateIpAddressList(addr); -} - -bool pqiIpAddrSet::updateExtAddrs(const pqiIpAddress &addr) -{ - return mExt.updateIpAddressList(addr); -} - -bool pqiIpAddrSet::updateAddrs(const pqiIpAddrSet &addrs) -{ -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrSet::updateAddrs()"; - std::cerr << std::endl; -#endif - - bool newAddrs = false; - std::list::const_iterator it; - for(it = addrs.mLocal.mAddrs.begin(); it != addrs.mLocal.mAddrs.end(); ++it) - { - if (mLocal.updateIpAddressList(*it)) - { -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrSet::updateAddrs() Updated Local Addr"; - std::cerr << std::endl; -#endif - newAddrs = true; - } - } - - for(it = addrs.mExt.mAddrs.begin(); it != addrs.mExt.mAddrs.end(); ++it) - { - if (mExt.updateIpAddressList(*it)) - { -#ifdef IPADDR_DEBUG - std::cerr << "pqiIpAddrSet::updateAddrs() Updated Ext Addr"; - std::cerr << std::endl; -#endif - newAddrs = true; - } - } - return newAddrs; -} - - - -void pqiIpAddrSet::printAddrs(std::string &out) const -{ - out += "Local Addresses: "; - mLocal.printIpAddressList(out); - out += "\nExt Addresses: "; - mExt.printIpAddressList(out); - out += "\n"; -} - - - - diff --git a/libretroshare/src/pqi/pqiipset.h b/libretroshare/src/pqi/pqiipset.h deleted file mode 100644 index 9f6c31b17..000000000 --- a/libretroshare/src/pqi/pqiipset.h +++ /dev/null @@ -1,77 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiipset.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009-2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef PQI_IP_SET_H -#define PQI_IP_SET_H - -#include "util/rsnet.h" -#include "serialiser/rstlvaddrs.h" -#include "util/rstime.h" - -#define MAX_ADDRESS_LIST_SIZE 10 - -class pqiIpAddress -{ - public: - bool sameAddress(const pqiIpAddress &a) const; - bool validAddress() const; - - struct sockaddr_storage mAddr; - rstime_t mSeenTime; - uint32_t mSrc; -}; - - -class pqiIpAddrList -{ - public: - - // returns true if new address added. - bool updateIpAddressList(const pqiIpAddress &addr); - void printIpAddressList(std::string &out) const; - void extractFromTlv(const RsTlvIpAddrSet &tlvAddrs); - void loadTlv(RsTlvIpAddrSet &tlvAddrs) const; - - // sorted list... based on seen time. - std::list mAddrs; -}; - - -class pqiIpAddrSet -{ - public: - - bool updateLocalAddrs(const pqiIpAddress &addr); - bool updateExtAddrs(const pqiIpAddress &addr); - bool updateAddrs(const pqiIpAddrSet &addrs); - void printAddrs(std::string &out) const; - pqiIpAddrList mLocal; - pqiIpAddrList mExt; - - void clear() - { - mLocal.mAddrs.clear(); - mExt.mAddrs.clear(); - } -}; - - -#endif diff --git a/libretroshare/src/pqi/pqilistener.h b/libretroshare/src/pqi/pqilistener.h deleted file mode 100644 index 5f748dc8f..000000000 --- a/libretroshare/src/pqi/pqilistener.h +++ /dev/null @@ -1,41 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqilistener.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_GENERIC_LISTEN_HEADER -#define MRK_PQI_GENERIC_LISTEN_HEADER - -// operating system specific network header. -#include "pqi/pqinetwork.h" - -class pqilistener -{ -public: - pqilistener() {} - virtual ~pqilistener() {} - virtual int tick() { return 1; } - virtual int status() { return 1; } - virtual int setListenAddr(const sockaddr_storage & /*addr*/) { return 1; } - virtual int setuplisten() { return 1; } - virtual int resetlisten() { return 1; } -}; - - -#endif // MRK_PQI_GENERIC_LISTEN_HEADER diff --git a/libretroshare/src/pqi/pqiloopback.cc b/libretroshare/src/pqi/pqiloopback.cc deleted file mode 100644 index 69e70488b..000000000 --- a/libretroshare/src/pqi/pqiloopback.cc +++ /dev/null @@ -1,89 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiloopback.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "pqi/pqiloopback.h" - -#include // for NULL - -struct RsItem; - -/*** -#define LOOPBACK_DEBUG 1 -***/ - -pqiloopback::pqiloopback(const RsPeerId& id) - :PQInterface(id) -{ - setMaxRate(true, 0); - setMaxRate(false, 0); - setRate(true, 0); - setRate(false, 0); - - return; -} - -pqiloopback::~pqiloopback() -{ - return; -} - -int pqiloopback::SendItem(RsItem *i) -{ - -#ifdef LOOPBACK_DEBUG - std::cerr << "pqiloopback::SendItem()"; - std::cerr << std::endl; - i->print(std::cerr); - std::cerr << std::endl; -#endif - objs.push_back(i); - return 1; -} - -RsItem * pqiloopback::GetItem() -{ - if (objs.size() > 0) - { - RsItem *pqi = objs.front(); - objs.pop_front(); -#ifdef LOOPBACK_DEBUG - std::cerr << "pqiloopback::GetItem()"; - std::cerr << std::endl; - pqi->print(std::cerr); - std::cerr << std::endl; -#endif - return pqi; - } - return NULL; -} - -// PQI interface. -int pqiloopback::tick() -{ - return 0; -} - -int pqiloopback::status() -{ - return 0; -} - - diff --git a/libretroshare/src/pqi/pqiloopback.h b/libretroshare/src/pqi/pqiloopback.h deleted file mode 100644 index f8d40e667..000000000 --- a/libretroshare/src/pqi/pqiloopback.h +++ /dev/null @@ -1,50 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiloopback.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_LOOPBACK_HEADER -#define MRK_PQI_LOOPBACK_HEADER - -#include // for list - -#include "pqi/pqi_base.h" // for NetInterface (ptr only), PQInterface -#include "retroshare/rstypes.h" // for RsPeerId - -struct RsItem; - -class pqiloopback: public PQInterface -{ -public: - pqiloopback(const RsPeerId& id); -virtual ~pqiloopback(); - -// search Interface. -virtual int SendItem(RsItem *item); -virtual RsItem *GetItem(); - -// PQI interface. -virtual int tick(); -virtual int status(); - -private: - std::list objs; -}; - -#endif //MRK_PQI_LOOPBACK_HEADER diff --git a/libretroshare/src/pqi/pqimonitor.cc b/libretroshare/src/pqi/pqimonitor.cc deleted file mode 100644 index 550cd7b5a..000000000 --- a/libretroshare/src/pqi/pqimonitor.cc +++ /dev/null @@ -1,93 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqimonitor.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "pqi/pqimonitor.h" -#include "pqi/pqinetwork.h" -#include "pqi/pqiipset.h" -#include "util/rsprint.h" - -/***** DUMMY Connect CB for testing *****/ - -#include - - -pqiConnectCbDummy::pqiConnectCbDummy() -{ - std::cerr << "pqiConnectCbDummy()" << std::endl; - return; -} - -pqiConnectCbDummy::~pqiConnectCbDummy() -{ - return; -} - -void pqiConnectCbDummy::peerStatus(const RsPeerId& id, const pqiIpAddrSet &addrs, - uint32_t type, uint32_t mode, uint32_t source) -{ - std::cerr << "pqiConnectCbDummy::peerStatus()"; - std::cerr << " id: " << id; - std::cerr << " type: " << type; - std::cerr << " mode: " << mode; - std::cerr << " source: " << source; - std::cerr << std::endl; - - std::cerr << " addrs: "; - std::cerr << std::endl; - std::string out; - addrs.printAddrs(out); - std::cerr << out << std::endl; -} - -void pqiConnectCbDummy::peerConnectRequest(const RsPeerId &id, const sockaddr_storage &raddr - , const sockaddr_storage &proxyaddr, const sockaddr_storage &srcaddr - , uint32_t source, uint32_t flags, uint32_t delay, uint32_t bandwidth) -{ - std::cerr << "pqiConnectCbDummy::peerConnectRequest()"; - std::cerr << " id: " << id; - std::cerr << " raddr: " << sockaddr_storage_tostring(raddr); - std::cerr << " proxyaddr: " << sockaddr_storage_tostring(proxyaddr); - std::cerr << " srcaddr: " << sockaddr_storage_tostring(srcaddr); - std::cerr << " source: " << source; - std::cerr << " flags: " << flags; - std::cerr << " delay: " << delay; - std::cerr << " bandwidth: " << bandwidth; - std::cerr << std::endl; -} - -void pqiMonitor::disconnectPeer(const RsPeerId &/*peer*/) -{ - std::cerr << "(EE) pqiMonitor::disconnectPeer() shouldn't be called!!!"<< std::endl; -} - -#if 0 -void pqiConnectCbDummy::stunStatus(std::string id, const struct sockaddr_storage *raddr, - uint32_t type, uint32_t flags) -{ - std::cerr << "pqiConnectCbDummy::stunStatus()"; - std::cerr << " idhash: " << RsUtil::BinToHex(id) << " raddr: " << sockaddr_storage_tostring(raddr); - std::cerr << " type: " << type; - std::cerr << " flags: " << flags; - std::cerr << std::endl; -} -#endif - - diff --git a/libretroshare/src/pqi/pqimonitor.h b/libretroshare/src/pqi/pqimonitor.h deleted file mode 100644 index 34a858e66..000000000 --- a/libretroshare/src/pqi/pqimonitor.h +++ /dev/null @@ -1,193 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqimonitor.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef PQI_MONITOR_H -#define PQI_MONITOR_H - -/**** Rough sketch of a Monitor class - * expect it to change significantly - * - */ - -#include -#include -#include -#include "pqi/pqiipset.h" -#include "retroshare/rstypes.h" - -/************** Define Type/Mode/Source ***************/ - - -/* STATE MASK */ -const uint32_t RS_PEER_STATE_MASK = 0x00ff; -const uint32_t RS_PEER_ACTION_MASK = 0xff00; - -/* STATE */ -const uint32_t RS_PEER_S_FRIEND = 0x0001; -const uint32_t RS_PEER_S_ONLINE = 0x0002; /* heard from recently..*/ -const uint32_t RS_PEER_S_CONNECTED = 0x0004; -const uint32_t RS_PEER_S_UNREACHABLE = 0x0008; - -/* ACTIONS */ -const uint32_t RS_PEER_NEW = 0x0001; /* new Peer */ -const uint32_t RS_PEER_ONLINE = 0x0002; -const uint32_t RS_PEER_CONNECTED = 0x0004; -const uint32_t RS_PEER_MOVED = 0x0008; /* moved from F->O or O->F */ -const uint32_t RS_PEER_DISCONNECTED = 0x0010; -const uint32_t RS_PEER_CONNECT_REQ = 0x0020; - -/* Stun Status Flags */ -//const uint32_t RS_STUN_SRC_DHT = 0x0001; -//const uint32_t RS_STUN_SRC_PEER = 0x0002; -const uint32_t RS_STUN_ONLINE = 0x0010; -const uint32_t RS_STUN_FRIEND = 0x0020; -const uint32_t RS_STUN_FRIEND_OF_FRIEND = 0x0040; - - -#define RS_CB_DHT 0x0001 /* from dht */ -#define RS_CB_DISC 0x0002 /* from peers */ -#define RS_CB_PERSON 0x0003 /* from connection */ -#define RS_CB_PROXY 0x0004 /* via proxy */ - - -#define RS_CB_FLAG_MASK_MODE 0x00ff -#define RS_CB_FLAG_MASK_ORDER 0xff00 - -#define RS_CB_FLAG_MODE_TCP 0x0001 -#define RS_CB_FLAG_MODE_UDP_DIRECT 0x0002 -#define RS_CB_FLAG_MODE_UDP_PROXY 0x0004 -#define RS_CB_FLAG_MODE_UDP_RELAY 0x0008 - -#define RS_CB_FLAG_ORDER_UNSPEC 0x0100 -#define RS_CB_FLAG_ORDER_PASSIVE 0x0200 -#define RS_CB_FLAG_ORDER_ACTIVE 0x0400 - -#define RSUDP_NUM_TOU_RECVERS 3 - -#define RSUDP_TOU_RECVER_DIRECT_IDX 0 -#define RSUDP_TOU_RECVER_PROXY_IDX 1 -#define RSUDP_TOU_RECVER_RELAY_IDX 2 - - -class pqipeer -{ - public: - RsPeerId id; - std::string name; - uint32_t state; - uint32_t actions; -}; - -class p3LinkMgr; - -/*! - * This class should be implemented - * to use the information that is passed to it via - * from the p3ConnectMngr - * Useful information is sent via ticks such as a peer's - * state and a peer's action - */ -class pqiMonitor -{ - public: - pqiMonitor() :mLinkMgr(NULL) { return; } -virtual ~pqiMonitor() { return; } - - /*! - * passes a handle the retroshare connection manager - */ - void setLinkMgr(p3LinkMgr *lm) { mLinkMgr = lm; } - - /*! - * this serves as a call back function for server which has - * a handle on the subclass and updates this subclass on the - * action of peer's of the client (state and action information) - * - *@param plist contains list of states and actions of the client's peers - */ -virtual void statusChange(const std::list &plist) = 0; - - // This is used to force disconnection of a peer, if e.g. something suspicious happenned. - - virtual void disconnectPeer(const RsPeerId& peer) ; - -#ifdef WINDOWS_SYS -/////////////////////////////////////////////////////////// -// hack for too many connections -virtual void statusChanged() {}; -/////////////////////////////////////////////////////////// -#endif - -//virtual void ownStatusChange(pqipeer &) { return; } // SIGNAL reset or similar. -//virtual void peerStatus(std::string id, uint32_t mode) = 0; - - protected: - p3LinkMgr *mLinkMgr; -}; - - - - -class pqiConnectCb -{ - public: -virtual ~pqiConnectCb() { return; } -virtual void peerStatus(const RsPeerId& id, const pqiIpAddrSet &addrs, - uint32_t type, uint32_t flags, uint32_t source) = 0; - -virtual void peerConnectRequest(const RsPeerId& id, const struct sockaddr_storage &raddr, - const struct sockaddr_storage &proxyaddr, const struct sockaddr_storage &srcaddr, - uint32_t source, uint32_t flags, uint32_t delay, uint32_t bandwidth) = 0; - - -//virtual void stunStatus(std::string id, const struct sockaddr_storage &raddr, uint32_t type, uint32_t flags) = 0; -}; - - -/**** DUMMY CB FOR TESTING (just prints) ****/ -class pqiConnectCbDummy: public pqiConnectCb -{ - public: - pqiConnectCbDummy(); -virtual ~pqiConnectCbDummy(); -virtual void peerStatus(const RsPeerId& id, const pqiIpAddrSet &addrs, - uint32_t type, uint32_t mode, uint32_t source); - - virtual void peerConnectRequest(const RsPeerId& id, const struct sockaddr_storage &raddr, - const struct sockaddr_storage &proxyaddr, const struct sockaddr_storage &srcaddr, - uint32_t source, uint32_t flags, uint32_t delay, uint32_t bandwidth); - -//virtual void stunStatus(std::string id, const struct sockaddr_storage &raddr, uint32_t type, uint32_t flags); -}; - - -/* network listener interface - used to reset network addresses */ -class pqiNetListener -{ - public: -virtual bool resetListener(const struct sockaddr_storage &local) = 0; - -}; - - -#endif // PQI_MONITOR_H - diff --git a/libretroshare/src/pqi/pqinetstatebox.cc b/libretroshare/src/pqi/pqinetstatebox.cc deleted file mode 100644 index 67d1fcef1..000000000 --- a/libretroshare/src/pqi/pqinetstatebox.cc +++ /dev/null @@ -1,616 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqinetstatebox.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "util/rsnet.h" -#include "pqi/pqinetstatebox.h" -#include "util/rstime.h" - -#ifdef RS_USE_BITDHT -#include "bitdht/bdiface.h" -#endif - -// External Interface. - -void pqiNetStateBox::setAddressStunDht(const struct sockaddr_storage &addr, bool stable) -{ - if ((!mStunDhtSet) || (mStunDhtStable != stable) || - (!sockaddr_storage_same(addr, mStunDhtAddr))) - { - mStunDhtSet = true; - mStunDhtStable = stable; - mStunDhtAddr = addr; - - mStatusOkay = false; - } - mStunDhtTS = time(NULL); -} - - -void pqiNetStateBox::setAddressStunProxy(const struct sockaddr_storage &addr, bool stable) -{ - if ((!mStunProxySet) || (mStunProxyStable != stable) || - (!sockaddr_storage_same(addr, mStunProxyAddr))) - { - - if (sockaddr_storage_sameip(addr,mStunProxyAddr)) - { - if (mStunProxyStable != stable) - { - mStunProxySemiStable = true; - } - } - else - { - mStunProxySemiStable = false; // change of address - must trigger this again! - } - - mStunProxySet = true; - mStunProxyStable = stable; - mStunProxyAddr = addr; - mStatusOkay = false; - } - mStunProxyTS = time(NULL); -} - - -void pqiNetStateBox::setAddressUPnP(bool active, const struct sockaddr_storage &addr) -{ - if ((!mUPnPSet) || (mUPnPActive != active) || - (!sockaddr_storage_same(addr, mUPnPAddr))) - { - mUPnPSet = true; - mUPnPAddr = addr; - mUPnPActive = active; - - mStatusOkay = false; - } - mUPnPTS = time(NULL); -} - - -void pqiNetStateBox::setAddressNatPMP(bool active, const struct sockaddr_storage &addr) -{ - if ((!mNatPMPSet) || (mNatPMPActive != active) || - (!sockaddr_storage_same(addr, mNatPMPAddr))) - { - mNatPMPSet = true; - mNatPMPAddr = addr; - mNatPMPActive = active; - - mStatusOkay = false; - } - mNatPMPTS = time(NULL); -} - - - -void pqiNetStateBox::setAddressWebIP(bool active, const struct sockaddr_storage &addr) -{ - if ((!mWebIPSet) || (mWebIPActive != active) || - (!sockaddr_storage_same(addr, mWebIPAddr))) - { - mWebIPSet = true; - mWebIPAddr = addr; - mWebIPActive = active; - - mStatusOkay = false; - } - mWebIPTS = time(NULL); -} - - -void pqiNetStateBox::setPortForwarded(bool /*active*/, uint16_t port) -{ - if ((!mPortForwardSet) || (mPortForwarded != port)) - - { - mPortForwardSet = true; - mPortForwarded = port; - - mStatusOkay = false; - } -} - - -void pqiNetStateBox::setDhtState(bool on, bool active) -{ - if ((!mDhtSet) || (mDhtActive != active) || (mDhtOn != on)) - { - mDhtSet = true; - mDhtActive = active; - mDhtOn = on; - - mStatusOkay = false; - } - mDhtTS = time(NULL); -} - - -/* Extract Net State */ -RsNetworkMode pqiNetStateBox::getNetworkMode() -{ - updateNetState(); - return mNetworkMode; -} - -RsNatTypeMode pqiNetStateBox::getNatTypeMode() -{ - updateNetState(); - return mNatTypeMode; -} - -RsNatHoleMode pqiNetStateBox::getNatHoleMode() -{ - updateNetState(); - return mNatHoleMode; -} - -RsConnectModes pqiNetStateBox::getConnectModes() -{ - updateNetState(); - return mConnectModes; -} - - -RsNetState pqiNetStateBox::getNetStateMode() -{ - updateNetState(); - return mNetStateMode; -} - - - -/******************************** Internal Workings *******************************/ -pqiNetStateBox::pqiNetStateBox() -{ - reset(); -} - - -void pqiNetStateBox::reset() -{ - - mStatusOkay = false; - //rstime_t mStatusTS; - - mNetworkMode = RsNetworkMode::UNKNOWN; - mNatTypeMode = RsNatTypeMode::UNKNOWN; - mNatHoleMode = RsNatHoleMode::UNKNOWN; - mConnectModes = RsConnectModes::NONE; - mNetStateMode = RsNetState::BAD_UNKNOWN; - - /* Parameters set externally */ - - mStunDhtSet = false; - mStunDhtTS = 0; - mStunDhtStable = false; - sockaddr_storage_clear(mStunDhtAddr); - - mStunProxySet = false; - mStunProxySemiStable = false; - mStunProxyTS = 0; - mStunProxyStable = false; - sockaddr_storage_clear(mStunProxyAddr); - - mUPnPSet = false; - mUPnPActive = false; - sockaddr_storage_clear(mUPnPAddr); - - mNatPMPSet = false; - mNatPMPActive = false; - sockaddr_storage_clear(mNatPMPAddr); - - mWebIPSet = false; - mWebIPActive = false; - sockaddr_storage_clear(mWebIPAddr); - - mPortForwardSet = false; - mPortForwarded = false; - - mDhtSet = false; - mDhtActive = false; - mDhtOn = false; - -} - -//#define NETSTATE_PARAM_TIMEOUT 600 -#define NETSTATE_PARAM_TIMEOUT 900 // Change to 15 minutes -> see if it has effect on reconnect time -#define NETSTATE_TIMEOUT 60 - - /* check/update Net State */ -int pqiNetStateBox::statusOkay() -{ - if (!mStatusOkay) - { - return 0; - } - rstime_t now = time(NULL); - if (now - mStatusTS > NETSTATE_TIMEOUT) - { - return 0; - } - return 1; -} - -int pqiNetStateBox::updateNetState() -{ - if (!statusOkay()) - { - determineNetworkState(); - } - return 1; -} - - - - -void pqiNetStateBox::clearOldNetworkData() -{ -#ifdef RS_USE_DHT_STUNNER - /* check if any measurements are too old to consider */ - rstime_t now = time(NULL); - if (now - mStunProxyTS > NETSTATE_PARAM_TIMEOUT) - { - mStunProxySet = false; - } - - if (now - mStunDhtTS > NETSTATE_PARAM_TIMEOUT) - { - mStunDhtSet = false; - } -#else - //Set values, as they are not updated. - mStunProxySet = true; - mStunDhtSet = true; - mStunProxyStable = true; - mStunDhtStable = true; -#endif - -} - - -void pqiNetStateBox::determineNetworkState() -{ - clearOldNetworkData(); - rstime_t now = time(NULL); - - /* now we use the remaining valid input to determine network state */ - - /* Most important Factor is whether we have DHT(STUN) info to ID connection */ - if (mDhtActive) - { - /* firstly lets try to identify OFFLINE / UNKNOWN */ - if ((!mStunProxySet) || (!mStunDhtSet)) - { - mNetworkMode = RsNetworkMode::UNKNOWN; - // Assume these. - mNatTypeMode = RsNatTypeMode::UNKNOWN; - mNatHoleMode = RsNatHoleMode::NONE; - mNetStateMode = RsNetState::BAD_UNKNOWN; - - //mExtAddress = .... unknown; - //mExtAddrStable = false; - } - else // Both Are Set! - { - if (!mStunDhtStable) - { - //mExtAddress = mStunDhtExtAddress; - //mExtAddrStable = false; - - if (mStunProxySemiStable) - { - /* I'm guessing this will be a common mode for modern NAT/Firewalls. - * a DETERMINISTIC SYMMETRIC NAT.... This is likely to be the - * next iteration on the RESTRICTED CONE firewall described below. - * If you Stun fast, it looks like a SYMMETRIC NAT, but if you let - * the NAT timeout, you get back your original port so it looks like - * a RESTRICTED CONE nat... - * - * This kind of NAT is passable, if you only attempt one connection at - * a time, and are careful about it! - * - * NB: The StunDht port will never get this mode. - * It has unsolicited traffic which triggers SYM mode - * - */ - - mNetworkMode = RsNetworkMode::BEHINDNAT; - mNatTypeMode = RsNatTypeMode::DETERM_SYM; - mNatHoleMode = RsNatHoleMode::NONE; - mNetStateMode = RsNetState::WARNING_NATTED; - - } - else if (!mStunProxyStable) - { - /* both unstable, Symmetric NAT, Firewalled, No UDP Hole */ - mNetworkMode = RsNetworkMode::BEHINDNAT; - mNatTypeMode = RsNatTypeMode::SYMMETRIC; - mNatHoleMode = RsNatHoleMode::NONE; - mNetStateMode = RsNetState::BAD_NATSYM; - } - else - { - /* if DhtStun Unstable, but ProxyStable, then we have - * an interesting case. This is close to a Debian Firewall - * I tested in the past.... - * - * The big difference between DhtStun and ProxyStun is - * that Dht Port receives unsolicated packets, - * while Proxy Port always sends an outgoing one first. - * - * In the case of the debian firewall, the unsolicated pkts - * caused the outgoing port to change. - * - * We will label this difference RESTRICTED vs FULL CONE, - * but that label is really fully accurate. (gray area). - */ - - mNetworkMode = RsNetworkMode::BEHINDNAT; - mNatTypeMode = RsNatTypeMode::RESTRICTED_CONE; - mNatHoleMode = RsNatHoleMode::NONE; - mNetStateMode = RsNetState::WARNING_NATTED; - } - } - else // Dht Stable. - { - /* DHT Stable port can be caused by: - * 1) Forwarded Port (UPNP, NATPMP, FORWARDED) - * 2) FULL CONE NAT. - * 3) EXT Port. - * Must look at Proxy Stability. - * - if Proxy Unstable, then must be forwarded port. - * - if Proxy Stable, then we cannot tell. - * -> Must use User Info (Upnp, PMP, Forwarded Flag). - * -> Also possible to be EXT Port (Check against iface) - */ - - //mExtAddress = mStunDhtExtAddress; - //mExtAddrStable = true; - - // Initial Fallback Guess at firewall state. - if (mStunProxySemiStable) - { - /* must be a forwarded port/ext or something similar */ - mNetworkMode = RsNetworkMode::BEHINDNAT; - mNatTypeMode = RsNatTypeMode::DETERM_SYM; - mNatHoleMode = RsNatHoleMode::FORWARDED; - mNetStateMode = RsNetState::GOOD; - } - else if (!mStunProxyStable) - { - /* must be a forwarded port/ext or something similar */ - mNetworkMode = RsNetworkMode::BEHINDNAT; - mNatTypeMode = RsNatTypeMode::SYMMETRIC; - mNatHoleMode = RsNatHoleMode::FORWARDED; - mNetStateMode = RsNetState::GOOD; - } - else - { - /* fallback is FULL CONE NAT */ - mNetworkMode = RsNetworkMode::BEHINDNAT; - mNatTypeMode = RsNatTypeMode::FULL_CONE; - mNatHoleMode = RsNatHoleMode::NONE; - mNetStateMode = RsNetState::WARNING_NATTED; - } - - if (mUPnPActive) - { - // This Mode is OKAY. - mNetworkMode = RsNetworkMode::BEHINDNAT; - // Use Fallback Guess. - //mNatTypeMode = RsNatTypeMode::UNKNOWN; - mNatHoleMode = RsNatHoleMode::UPNP; - mNetStateMode = RsNetState::GOOD; - //mExtAddress = ... from UPnP, should match StunDht. - //mExtAddrStable = true; - } - else if (mNatPMPActive) - { - // This Mode is OKAY. - mNetworkMode = RsNetworkMode::BEHINDNAT; - // Use Fallback Guess. - //mNatTypeMode = RsNatTypeMode::UNKNOWN; - mNatHoleMode = RsNatHoleMode::NATPMP; - mNetStateMode = RsNetState::GOOD; - //mExtAddress = ... from NatPMP, should match NatPMP - //mExtAddrStable = true; - } - else - { - bool isExtAddress = false; - - if (isExtAddress) - { - mNetworkMode = RsNetworkMode::EXTERNALIP; - mNatTypeMode = RsNatTypeMode::NONE; - mNatHoleMode = RsNatHoleMode::NONE; - mNetStateMode = RsNetState::GOOD; - - //mExtAddrStable = true; - } - else if (mPortForwardSet) - { - mNetworkMode = RsNetworkMode::BEHINDNAT; - // Use Fallback Guess. - //mNatTypeMode = RsNatTypeMode::UNKNOWN; - mNatHoleMode = RsNatHoleMode::FORWARDED; - mNetStateMode = RsNetState::ADV_FORWARD; - - //mExtAddrStable = true; // Probably, makin assumption. - } - else - { - /* At this point, we go with the fallback guesses */ - } - } - - } - } - } - else // DHT Inactive, must use other means... - { - /* If we get here we are dealing with a silly peer in "DarkMode". - * We have to primarily rely on the feedback from UPnP, PMP or WebSite "WhatsMyIp". - * This is in the "Advanced" Settings and liable to be set wrong. - * but thats the users fault! - */ - - if (mUPnPActive) - { - // This Mode is OKAY. - mNetworkMode = RsNetworkMode::BEHINDNAT; - mNatTypeMode = RsNatTypeMode::UNKNOWN; - mNatHoleMode = RsNatHoleMode::UPNP; - //mExtAddress = ... from UPnP. - //mExtAddrStable = true; - mNetStateMode = RsNetState::WARNING_NODHT; - } - else if (mNatPMPActive) - { - // This Mode is OKAY. - mNetworkMode = RsNetworkMode::BEHINDNAT; - mNatTypeMode = RsNatTypeMode::UNKNOWN; - mNatHoleMode = RsNatHoleMode::NATPMP; - //mExtAddress = ... from NatPMP. - //mExtAddrStable = true; - mNetStateMode = RsNetState::WARNING_NODHT; - } - else - { - /* if we reach this point, we really need a Web "WhatsMyIp" Check of our Ext Ip Address. */ - /* Check for the possibility of an EXT address ... */ - bool isExtAddress = false; - - //mExtAddress = ... from WhatsMyIp. - - if (isExtAddress) - { - mNetworkMode = RsNetworkMode::EXTERNALIP; - mNatTypeMode = RsNatTypeMode::NONE; - mNatHoleMode = RsNatHoleMode::NONE; - - //mExtAddrStable = true; - mNetStateMode = RsNetState::WARNING_NODHT; - } - else if (mPortForwardSet) - { - mNetworkMode = RsNetworkMode::BEHINDNAT; - mNatTypeMode = RsNatTypeMode::UNKNOWN; - mNatHoleMode = RsNatHoleMode::FORWARDED; - - //mExtAddrStable = true; // Probably, makin assumption. - mNetStateMode = RsNetState::WARNING_NODHT; - } - else - { - /* At this point we must assume firewalled. - * These people have destroyed the possibility of making connections ;( - * Should WARN about this. - */ - mNetworkMode = RsNetworkMode::BEHINDNAT; - mNatTypeMode = RsNatTypeMode::UNKNOWN; - mNatHoleMode = RsNatHoleMode::NONE; - mNetStateMode = RsNetState::BAD_NODHT_NAT; - - //mExtAddrStable = false; // Unlikely to be stable. - } - } - } - - workoutNetworkMode(); - - /* say that things are okay */ - mStatusOkay = true; - mStatusTS = now; -} - - - -/* based on calculated settings, what is the network mode - */ - -void pqiNetStateBox::workoutNetworkMode() -{ - /* connectModes are dependent on the other modes */ - mConnectModes = RsConnectModes::NONE; - switch(mNetworkMode) - { - case RsNetworkMode::UNKNOWN: - case RsNetworkMode::OFFLINE: - case RsNetworkMode::LOCALNET: - case RsNetworkMode::RESTARTING: - /* nothing here */ - break; - case RsNetworkMode::EXTERNALIP: - mConnectModes = RsConnectModes::OUTGOING_TCP; - mConnectModes |= RsConnectModes::ACCEPT_TCP; - - if (mDhtActive) - { - mConnectModes |= RsConnectModes::DIRECT_UDP; - /* if open port. don't want PROXY or RELAY connect - * because we should be able to do direct with EVERYONE. - * Ability to do Proxy is dependent on FIREWALL status. - * Technically could do RELAY, but disable both. - */ - //mConnectModes |= RsConnectModes::PROXY_UDP; - //mConnectModes |= RsConnectModes::RELAY_UDP; - } - break; - case RsNetworkMode::BEHINDNAT: - mConnectModes = RsConnectModes::OUTGOING_TCP; - - /* we're okay if there's a NAT HOLE */ - if ((mNatHoleMode == RsNatHoleMode::UPNP) || - (mNatHoleMode == RsNatHoleMode::NATPMP) || - (mNatHoleMode == RsNatHoleMode::FORWARDED)) - { - mConnectModes |= RsConnectModes::ACCEPT_TCP; - if (mDhtActive) - { - mConnectModes |= RsConnectModes::DIRECT_UDP; - /* dont want PROXY | RELAY with open ports */ - } - } - else - { - /* If behind NAT without NATHOLE, this is where RELAY | PROXY - * are useful. We Flag DIRECT connections, cos we can do these - * with peers with Open Ports. (but not with other NATted peers). - */ - if (mDhtActive) - { - mConnectModes |= RsConnectModes::DIRECT_UDP; - mConnectModes |= RsConnectModes::RELAY_UDP; - - if ((mNatTypeMode == RsNatTypeMode::RESTRICTED_CONE) || - (mNatTypeMode == RsNatTypeMode::FULL_CONE) || - (mNatTypeMode == RsNatTypeMode::DETERM_SYM)) - { - mConnectModes |= RsConnectModes::PROXY_UDP; - } - } - } - break; - } -} diff --git a/libretroshare/src/pqi/pqinetstatebox.h b/libretroshare/src/pqi/pqinetstatebox.h deleted file mode 100644 index 26b85345a..000000000 --- a/libretroshare/src/pqi/pqinetstatebox.h +++ /dev/null @@ -1,120 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqinetstatebox.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef PQI_NET_STATUS_BOX_H -#define PQI_NET_STATUS_BOX_H - -/* a little state box to determine network status */ - -#include -#include - -#include -#include - -/*** Network state - * Want this to be all encompassing. - * - */ - -class pqiNetStateBox -{ - public: - pqiNetStateBox(); - - void reset(); - - /* input network bits */ - void setAddressStunDht(const struct sockaddr_storage &addr, bool stable); - void setAddressStunProxy(const struct sockaddr_storage &addr, bool stable); - - void setAddressUPnP(bool active, const struct sockaddr_storage &addr); - void setAddressNatPMP(bool active, const struct sockaddr_storage &addr); - void setAddressWebIP(bool active, const struct sockaddr_storage &addr); - - void setPortForwarded(bool active, uint16_t port); - - void setDhtState(bool dhtOn, bool dhtActive); - - RsNetState getNetStateMode(); - RsNetworkMode getNetworkMode(); - RsNatTypeMode getNatTypeMode(); - RsNatHoleMode getNatHoleMode(); - RsConnectModes getConnectModes(); - - private: - - /* calculate network state */ - void clearOldNetworkData(); - void determineNetworkState(); - int statusOkay(); - int updateNetState(); - - /* more internal fns */ - void workoutNetworkMode(); - - bool mStatusOkay; - rstime_t mStatusTS; - - RsNetworkMode mNetworkMode; - RsNatTypeMode mNatTypeMode; - RsNatHoleMode mNatHoleMode; - RsConnectModes mConnectModes; - RsNetState mNetStateMode; - - /* Parameters set externally */ - - bool mStunDhtSet; - rstime_t mStunDhtTS; - bool mStunDhtStable; - struct sockaddr_storage mStunDhtAddr; - - bool mStunProxySet; - rstime_t mStunProxyTS; - bool mStunProxyStable; - bool mStunProxySemiStable; - struct sockaddr_storage mStunProxyAddr; - - bool mDhtSet; - rstime_t mDhtTS; - bool mDhtOn; - bool mDhtActive; - - bool mUPnPSet; - struct sockaddr_storage mUPnPAddr; - bool mUPnPActive; - rstime_t mUPnPTS; - - bool mNatPMPSet; - struct sockaddr_storage mNatPMPAddr; - bool mNatPMPActive; - rstime_t mNatPMPTS; - - bool mWebIPSet; - struct sockaddr_storage mWebIPAddr; - bool mWebIPActive; - rstime_t mWebIPTS; - - bool mPortForwardSet; - uint16_t mPortForwarded; -}; - -#endif diff --git a/libretroshare/src/pqi/pqinetwork.cc b/libretroshare/src/pqi/pqinetwork.cc deleted file mode 100644 index 57858cf94..000000000 --- a/libretroshare/src/pqi/pqinetwork.cc +++ /dev/null @@ -1,521 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqinetwork.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie * - * Copyright (C) 2015-2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include -#include -#include -#include - -#include "pqi/pqinetwork.h" -#include "util/rsnet.h" -#include "util/rsdebug.h" -#include "util/rsstring.h" -#include "util/rsnet.h" -#include "util/stacktrace.h" - -#ifdef WINDOWS_SYS -# include "util/rswin.h" -# include "util/rsmemory.h" -# include -#endif // WINDOWS_SYS - -/// @See: android_ifaddrs/README.adoc -#ifdef __ANDROID__ -# include -#endif // def __ANDROID__ - -#ifdef WINDOWS_SYS /* Windows - define errno */ -int errno; -#else /* Windows - define errno */ -#include -#endif - -#ifdef __HAIKU__ -# include -# define IFF_RUNNING 0x0001 -#endif - -static struct RsLog::logInfo pqinetzoneInfo = {RsLog::Default, "pqinet"}; -#define pqinetzone &pqinetzoneInfo - -/***** - * #define NET_DEBUG 1 - ****/ - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - -void showSocketError(std::string &out) -{ - int err = errno; - rs_sprintf_append(out, "\tSocket Error(%d) : %s\n", err, socket_errorType(err).c_str()); -} - -std::string socket_errorType(int err) -{ - if (err == EBADF) - { - return std::string("EBADF"); - } - else if (err == EINVAL) - { - return std::string("EINVAL"); - } - else if (err == EFAULT) - { - return std::string("EFAULT"); - } - else if (err == ENOTSOCK) - { - return std::string("ENOTSOCK"); - } - else if (err == EISCONN) - { - return std::string("EISCONN"); - } - else if (err == ECONNREFUSED) - { - return std::string("ECONNREFUSED"); - } - else if (err == ETIMEDOUT) - { - return std::string("ETIMEDOUT"); - } - else if (err == ENETUNREACH) - { - return std::string("ENETUNREACH"); - } - else if (err == EADDRINUSE) - { - return std::string("EADDRINUSE"); - } - else if (err == EINPROGRESS) - { - return std::string("EINPROGRESS"); - } - else if (err == EALREADY) - { - return std::string("EALREADY"); - } - else if (err == EAGAIN) - { - return std::string("EAGAIN"); - } - else if (err == EISCONN) - { - return std::string("EISCONN"); - } - else if (err == ENOTCONN) - { - return std::string("ENOTCONN"); - } - // These ones have been turning up in SSL CONNECTION FAILURES. - else if (err == EPIPE) - { - return std::string("EPIPE"); - } - else if (err == ECONNRESET) - { - return std::string("ECONNRESET"); - } - else if (err == EHOSTUNREACH) - { - return std::string("EHOSTUNREACH"); - } - else if (err == EADDRNOTAVAIL) - { - return std::string("EADDRNOTAVAIL"); - } - // - - return std::string("UNKNOWN ERROR CODE - ASK RS-DEVS TO ADD IT!"); -} - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#else - -void showSocketError(std::string &out) -{ - int err = WSAGetLastError(); - rs_sprintf_append(out, "\tSocket Error(%d) : %s\n", err, socket_errorType(err).c_str()); -} - - -std::string socket_errorType(int err) -{ - if (err == WSAEBADF) - { - return std::string("WSABADF"); - } - - - else if (err == WSAEINTR) - { - return std::string("WSAEINTR"); - } - else if (err == WSAEACCES) - { - return std::string("WSAEACCES"); - } - else if (err == WSAEFAULT) - { - return std::string("WSAEFAULT"); - } - else if (err == WSAEINVAL) - { - return std::string("WSAEINVAL"); - } - else if (err == WSAEMFILE) - { - return std::string("WSAEMFILE"); - } - else if (err == WSAEWOULDBLOCK) - { - return std::string("WSAEWOULDBLOCK"); - } - else if (err == WSAEINPROGRESS) - { - return std::string("WSAEINPROGRESS"); - } - else if (err == WSAEALREADY) - { - return std::string("WSAEALREADY"); - } - else if (err == WSAENOTSOCK) - { - return std::string("WSAENOTSOCK"); - } - else if (err == WSAEDESTADDRREQ) - { - return std::string("WSAEDESTADDRREQ"); - } - else if (err == WSAEMSGSIZE) - { - return std::string("WSAEMSGSIZE"); - } - else if (err == WSAEPROTOTYPE) - { - return std::string("WSAEPROTOTYPE"); - } - else if (err == WSAENOPROTOOPT) - { - return std::string("WSAENOPROTOOPT"); - } - else if (err == WSAENOTSOCK) - { - return std::string("WSAENOTSOCK"); - } - else if (err == WSAEISCONN) - { - return std::string("WSAISCONN"); - } - else if (err == WSAECONNREFUSED) - { - return std::string("WSACONNREFUSED"); - } - else if (err == WSAECONNRESET) - { - return std::string("WSACONNRESET"); - } - else if (err == WSAETIMEDOUT) - { - return std::string("WSATIMEDOUT"); - } - else if (err == WSAENETUNREACH) - { - return std::string("WSANETUNREACH"); - } - else if (err == WSAEADDRINUSE) - { - return std::string("WSAADDRINUSE"); - } - else if (err == WSAEAFNOSUPPORT) - { - return std::string("WSAEAFNOSUPPORT (normally UDP related!)"); - } - - return std::string("----WINDOWS OPERATING SYSTEM FAILURE----"); -} - -// implement the improved unix inet address fn. -// using old one. -int inet_aton(const char *name, struct in_addr *addr) -{ - return (((*addr).s_addr = inet_addr(name)) != INADDR_NONE); -} - -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - -#include "util/cxx17retrocompat.h" -#include -#ifdef WINDOWS_SYS -# include -# include -#elif defined(__ANDROID__) && __ANDROID_API__ < 24 -/// @See: android_ifaddrs/README.adoc -# include "rs_android/ifaddrs-android.h" -#else // not WINDOWS => Linux and other unixes -# include -# include -#endif // WINDOWS_SYS - -bool getLocalAddresses(std::vector& addrs) -{ - addrs.clear(); - -#ifdef WINDOWS_SYS - // Seems strange to me but M$ documentation suggests to allocate this way... - DWORD bf_size = 16000; - IP_ADAPTER_ADDRESSES* adapter_addresses = (IP_ADAPTER_ADDRESSES*) rs_malloc(bf_size); - - if(adapter_addresses == NULL) - return false ; - - DWORD error = GetAdaptersAddresses(AF_UNSPEC, - GAA_FLAG_SKIP_MULTICAST | - GAA_FLAG_SKIP_DNS_SERVER | - GAA_FLAG_SKIP_FRIENDLY_NAME, - NULL, - adapter_addresses, - &bf_size); - if (error != ERROR_SUCCESS) - { - std::cerr << "FATAL ERROR: getLocalAddresses failed!" << std::endl; - return false ; - } - - IP_ADAPTER_ADDRESSES* adapter(NULL); - for(adapter = adapter_addresses; NULL != adapter; adapter = adapter->Next) - { - IP_ADAPTER_UNICAST_ADDRESS* address; - for ( address = adapter->FirstUnicastAddress; address; address = address->Next) - { - sockaddr_storage tmp; - sockaddr_storage_clear(tmp); - if (sockaddr_storage_copyip(tmp, * reinterpret_cast(address->Address.lpSockaddr))) - addrs.push_back(tmp); - } - } - free(adapter_addresses); -#else // not WINDOWS_SYS => Linux and other unixes - struct ifaddrs *ifsaddrs, *ifa; - if(getifaddrs(&ifsaddrs) != 0) - { - RS_ERR( "getifaddrs failed with: ", errno, " ", - rs_errno_to_condition(errno) ); - print_stacktrace(); - return false; - } - for ( ifa = ifsaddrs; ifa; ifa = ifa->ifa_next ) - if ( ifa->ifa_addr && (ifa->ifa_flags & IFF_UP) ) - { - sockaddr_storage tmp; - sockaddr_storage_clear(tmp); - if(sockaddr_storage_copyip( - tmp, - *reinterpret_cast(ifa->ifa_addr) )) - addrs.push_back(tmp); - } - freeifaddrs(ifsaddrs); -#endif // WINDOWS_SYS - -#ifdef NET_DEBUG - auto&& dbg = RS_DBG("returning: ["); - for(auto& addr: std::as_const(addrs)) - dbg << sockaddr_storage_iptostring(addr) << ", "; - dbg << "]" << std::endl; -#endif - - return !addrs.empty(); -} - - -/************************************************************* - * Socket Library Wrapper Functions - * to get over the crapness of the windows. - * - */ - -int unix_close(int fd) -{ - int ret; -/******************* WINDOWS SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - ret = close(fd); -#else - -#ifdef NET_DEBUG - std::cerr << "unix_close()" << std::endl; -#endif - ret = closesocket(fd); - /* translate error */ -#endif -/******************* WINDOWS SPECIFIC PART ******************/ - return ret; -} - -int unix_socket(int domain, int type, int protocol) -{ - int osock = socket(domain, type, protocol); - -#ifdef WINDOWS_SYS -#ifdef NET_DEBUG - std::cerr << "unix_socket()" << std::endl; -#endif // NET_DEBUG - - if ((unsigned) osock == INVALID_SOCKET) - { - // Invalidate socket Unix style. - osock = -1; - errno = WinToUnixError(WSAGetLastError()); - } -#endif // WINDOWS_SYS - - return osock; -} - - -int unix_fcntl_nonblock(int fd) -{ - int ret; - -/******************* OS SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - int flags = fcntl(fd, F_GETFL); - ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK); - -#ifdef NET_DEBUG - std::cerr << "unix_fcntl_nonblock():" << ret << " errno:" << errno << std::endl; -#endif - -#else - unsigned long int on = 1; - ret = ioctlsocket(fd, FIONBIO, &on); - -#ifdef NET_DEBUG - std::cerr << "unix_fcntl_nonblock()" << std::endl; -#endif - if (ret != 0) - { - /* store unix-style error - */ - ret = -1; - errno = WinToUnixError(WSAGetLastError()); - } -#endif -/******************* WINDOWS SPECIFIC PART ******************/ - return ret; -} - - -int unix_connect(int fd, const sockaddr_storage &serv_addr) -{ -#ifdef NET_DEBUG - std::cerr << __PRETTY_FUNCTION__ << std::endl; -#endif - - int ret = connect( fd, (const struct sockaddr *) &serv_addr, - sizeof(struct sockaddr_in6) ); - -/******************* WINDOWS SPECIFIC PART ******************/ -#ifdef WINDOWS_SYS // WINDOWS - if (ret != 0) - { - errno = WinToUnixError(WSAGetLastError()); - ret = -1; - } -#endif -/******************* WINDOWS SPECIFIC PART ******************/ - return ret; -} - - -int unix_getsockopt_error(int sockfd, int *err) -{ - int ret; - *err = 1; -/******************* WINDOWS SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - socklen_t optlen = 4; - ret=getsockopt(sockfd, SOL_SOCKET, SO_ERROR, err, &optlen); -#else // WINDOWS_SYS - int optlen = 4; - ret=getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char *) err, &optlen); - /* translate */ -#ifdef NET_DEBUG - std::cerr << "unix_getsockopt_error() returned: " << (int) err << std::endl; -#endif - if (*err != 0) - { - *err = WinToUnixError(*err); - } -#endif -/******************* WINDOWS SPECIFIC PART ******************/ - return ret; -} - -/******************* WINDOWS SPECIFIC PART ******************/ -#ifdef WINDOWS_SYS // ie WINDOWS. - -int WinToUnixError(int error) -{ -#ifdef NET_DEBUG - std::cerr << "WinToUnixError(" << error << ")" << std::endl; -#endif - switch(error) - { - case WSAEINPROGRESS: - return EINPROGRESS; - break; - case WSAEWOULDBLOCK: - return EINPROGRESS; - break; - case WSAENETUNREACH: - return ENETUNREACH; - break; - case WSAETIMEDOUT: - return ETIMEDOUT; - break; - case WSAEHOSTDOWN: - return EHOSTDOWN; - break; - case WSAECONNREFUSED: - return ECONNREFUSED; - break; - case WSAECONNRESET: - return ECONNRESET; - break; - default: -#ifdef NET_DEBUG - std::cerr << "WinToUnixError(" << error << ") Code Unknown!"; - std::cerr << std::endl; -#endif - break; - } - return ECONNREFUSED; /* sensible default? */ -} - -#endif -/******************* WINDOWS SPECIFIC PART ******************/ diff --git a/libretroshare/src/pqi/pqinetwork.h b/libretroshare/src/pqi/pqinetwork.h deleted file mode 100644 index 9519bf197..000000000 --- a/libretroshare/src/pqi/pqinetwork.h +++ /dev/null @@ -1,112 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqinetwork.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie * - * Copyright (C) 2015-2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - -#include -#include -#include -#include - -#include -#include - -//socket blocking/options. -#include -#include - -#else - -#include "util/rsnet.h" /* more generic networking header */ - -// Some Network functions that are missing from windows. -int inet_aton(const char *name, struct in_addr *addr); - -extern int errno; /* Define extern errno, to duplicate unix behaviour */ - -/* define the Unix Error Codes that we use... - * NB. we should make the same, but not necessary - */ -#define EAGAIN 11 - -#define EUSERS 87 - -#define EHOSTDOWN 112 - -#ifndef __MINGW64_VERSION_MAJOR -#define EWOULDBLOCK EAGAIN - -#define ENOTSOCK 88 - -#define EOPNOTSUPP 95 - -#define EADDRINUSE 98 -#define EADDRNOTAVAIL 99 -#define ENETDOWN 100 -#define ENETUNREACH 101 - -#define ECONNRESET 104 - -#define ETIMEDOUT 10060 // value from pthread.h -#define ECONNREFUSED 111 -#define EHOSTUNREACH 113 -#define EALREADY 114 -#define EINPROGRESS 115 -#endif - -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - -#include -#include -#include - -#include "util/rsdeprecate.h" - -// Same def - different functions... -RS_DEPRECATED_FOR("use std::error_condition instead") -void showSocketError(std::string &out); - -RS_DEPRECATED_FOR("use std::error_condition instead") -std::string socket_errorType(int err); - -bool getLocalAddresses(std::vector & addrs); - -/* universal socket interface */ - -int unix_close(int sockfd); -int unix_socket(int domain, int type, int protocol); -int unix_fcntl_nonblock(int sockfd); -int unix_connect(int sockfd, const sockaddr_storage& serv_addr); -int unix_getsockopt_error(int sockfd, int *err); - -#ifdef WINDOWS_SYS // WINDOWS -/******************* WINDOWS SPECIFIC PART ******************/ -RS_DEPRECATED_FOR("use std::error_condition instead") -int WinToUnixError(int error); -#endif diff --git a/libretroshare/src/pqi/pqiperson.cc b/libretroshare/src/pqi/pqiperson.cc deleted file mode 100644 index 62d5e5412..000000000 --- a/libretroshare/src/pqi/pqiperson.cc +++ /dev/null @@ -1,697 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiperson.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "pqi/pqi.h" -#include "pqi/pqiperson.h" -#include "pqi/pqipersongrp.h" -#include "pqi/pqissl.h" -#include "util/rsdebug.h" -#include "util/rsstring.h" -#include "retroshare/rspeers.h" - -static struct RsLog::logInfo pqipersonzoneInfo = {RsLog::Default, "pqiperson"}; -#define pqipersonzone &pqipersonzoneInfo - -/**** - * #define PERSON_DEBUG 1 - ****/ - -pqiperson::pqiperson(const RsPeerId& id, pqipersongrp *pg) : - PQInterface(id), mNotifyMtx("pqiperson-notify"), mPersonMtx("pqiperson"), - active(false), activepqi(NULL), inConnectAttempt(false),// waittimes(0), - pqipg(pg) {} // TODO: must check id! - -pqiperson::~pqiperson() -{ - RS_STACK_MUTEX(mPersonMtx); - - // clean up the childrens - std::map::iterator it; - for(it = kids.begin(); it != kids.end(); ++it) - { - pqiconnect *pc = (it->second); - delete pc; - } - kids.clear(); -} - -int pqiperson::SendItem(RsItem *i,uint32_t& serialized_size) -{ - RS_STACK_MUTEX(mPersonMtx); - - if(active) - { - // every outgoing item goes through this function, so try to not waste cpu cycles - // check if debug output is wanted, to avoid unecessary work - // getZoneLevel() locks a global mutex and does a lookup in a map or returns a default value - // (not sure if this is a performance problem) - if (PQL_DEBUG_BASIC <= pqipersonzoneInfo.lvl) - { - std::string out = "pqiperson::SendItem() Active: Sending On\n"; - i->print_string(out, 5); // this can be very expensive -#ifdef PERSON_DEBUG - std::cerr << out << std::endl; -#endif - pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out); - } - return activepqi -> SendItem(i,serialized_size); - } - else - { - if (PQL_DEBUG_BASIC <= pqipersonzoneInfo.lvl) - { - std::string out = "pqiperson::SendItem()"; - out += " Not Active: Used to put in ToGo Store\n"; - out += " Now deleting..."; - pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out); - } - delete i; - } - return 0; // queued. -} - -RsItem *pqiperson::GetItem() -{ - RS_STACK_MUTEX(mPersonMtx); - - if (active) - return activepqi->GetItem(); - // else not possible. - return NULL; -} - -bool pqiperson::RecvItem(RsItem *item) -{ -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::RecvItem()" << std::endl; -#endif - - return pqipg->recvItem((RsRawItem *) item); -} - - -int pqiperson::status() -{ - RS_STACK_MUTEX(mPersonMtx); - - if (active) - return activepqi -> status(); - return -1; -} - -int pqiperson::receiveHeartbeat() -{ -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::receiveHeartbeat() from peer : " - << PeerId().toStdString() << std::endl; -#endif - - RS_STACK_MUTEX(mPersonMtx); - lastHeartbeatReceived = time(NULL); - - return 1; -} - -int pqiperson::tick() -{ - int activeTick = 0; - - { - RS_STACK_MUTEX(mPersonMtx); - -#ifdef PERSON_DEBUG - if(active) - { - std::cerr << "pqiperson: peer=" << (activepqi? (activepqi->PeerId()): (RsPeerId())) <<", active=" << active << ", last HB=" << time(NULL) - lastHeartbeatReceived << " secs ago." ; - if(lastHeartbeatReceived==0) - std::cerr << "!!!!!!!" << std::endl; - else - std::cerr << std::endl; - } -#endif - - //if lastHeartbeatReceived is 0, it might be not activated so don't do a net reset. - if ( active && time(NULL) > lastHeartbeatReceived + HEARTBEAT_REPEAT_TIME * 20) - { - int ageLastIncoming = time(NULL) - activepqi->getLastIncomingTS(); - -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::tick() WARNING No heartbeat from: " - << PeerId().toStdString() << " LastHeartbeat was: " - << time(NULL) - lastHeartbeatReceived - << "secs ago LastIncoming was: " << ageLastIncoming - << "secs ago" << std::endl; -#endif - - if (ageLastIncoming > 60) // Check timeout - { - std::cerr << "pqiperson::tick() " << PeerId().toStdString() << " No Heartbeat & No Packets for 60 secs -> assume dead." << std::endl; - this->reset_locked(); - } - - } - - - { -#ifdef PERSON_DEBUG - std::string statusStr = " inactive "; - if (active) - statusStr = " active "; - - std::string connectStr = " Not Connecting "; - if (inConnectAttempt) - connectStr = " In Connection Attempt "; - - std::cerr << "pqiperson::tick() Id: " << PeerId().toStdString() - << "activepqi: " << activepqi << " inConnectAttempt:" - << connectStr << std::endl; -#endif - - // tick the children. - std::map::iterator it; - for(it = kids.begin(); it != kids.end(); ++it) - { - if (0 < (it->second)->tick()) - activeTick = 1; -#ifdef PERSON_DEBUG - std::cerr << "\tTicking Child: "<< it->first << std::endl; -#endif - } - } - } - - // handle Notify Events that were generated. - processNotifyEvents(); - - return activeTick; -} - -// callback function for the child - notify of a change. -// This is only used for out-of-band info.... -// otherwise could get dangerous loops. -// - Actually, now we have - must store and process later. -int pqiperson::notifyEvent(NetInterface *ni, int newState, - const sockaddr_storage &remote_peer_address) -{ -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::notifyEvent() adding event to Queue. newState=" - << newState << " from IP = " - << sockaddr_storage_tostring(remote_peer_address) << std::endl; -#endif - - if (mPersonMtx.trylock()) - { - handleNotifyEvent_locked(ni, newState, remote_peer_address); - mPersonMtx.unlock(); - return 1; - } - - RS_STACK_MUTEX(mNotifyMtx); - mNotifyQueue.push_back(NotifyData(ni, newState, remote_peer_address)); - return 1; -} - -void pqiperson::processNotifyEvents() -{ - NetInterface *ni; - int state; - sockaddr_storage addr; - - while(1) // While there is notification to handle - { - { - RS_STACK_MUTEX(mNotifyMtx); - - if(mNotifyQueue.empty()) - return; - - NotifyData &data = mNotifyQueue.front(); - ni = data.mNi; - state = data.mState; - addr = data.mAddr; - - mNotifyQueue.pop_front(); - } - - RS_STACK_MUTEX(mPersonMtx); - handleNotifyEvent_locked(ni, state, addr); - } -} - - -int pqiperson::handleNotifyEvent_locked(NetInterface *ni, int newState, - const sockaddr_storage &remote_peer_address) -{ -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::handleNotifyEvent_locked() Id: " - << PeerId().toStdString() << " Message: " << newState - << " from: " << ni << std::endl; - int i = 0; -#endif - - /* find the pqi, */ - pqiconnect *pqi = NULL; - uint32_t type = 0; - std::map::iterator it; - - /* start again */ - for(it = kids.begin(); it != kids.end(); ++it) - { -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::handleNotifyEvent_locked() Kid# " << i - << " of " << kids.size() << " type: " << it->first - << " in_ni: " << ni << std::endl; - ++i; -#endif - - if ((it->second)->thisNetInterface(ni)) - { - pqi = (it->second); - type = (it->first); - } - } - - if (!pqi) - { - std::cerr << "pqiperson::handleNotifyEvent_locked Unknown Event Source!" - << std::endl; - return -1; - } - - - switch(newState) - { - case CONNECT_RECEIVED: - case CONNECT_SUCCESS: - { - - /* notify */ - if (pqipg) - { - pqissl *ssl = dynamic_cast(ni); - if(ssl) - pqipg->notifyConnect(PeerId(), type, true, ssl->actAsServer(), remote_peer_address); - else - pqipg->notifyConnect(PeerId(), type, true, false, remote_peer_address); - } - - if ((active) && (activepqi != pqi)) // already connected - trouble - { - // TODO: 2015/12/19 Is this block dead code? - - std::cerr << "pqiperson::handleNotifyEvent_locked Id: " - << PeerId().toStdString() << " CONNECT_SUCCESS+active->" - << "activing new connection, shutting others" - << std::endl; - - // This is the RESET that's killing the connections..... - //activepqi -> reset(); - // this causes a recursive call back into this fn. - // which cleans up state. - // we only do this if its not going to mess with new conn. - } - - /* now install a new one. */ - { -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::handleNotifyEvent_locked Id: " - << PeerId().toStdString() << " CONNECT_SUCCESS->marking " - << "so! (resetting others)" << std::endl; -#endif - - // mark as active. - active = true; - lastHeartbeatReceived = time(NULL) ; - activepqi = pqi; - inConnectAttempt = false; - - // STARTUP THREAD - activepqi->start("pqi " + PeerId().toStdString().substr(0, 11)); - - // reset all other children (clear up long UDP attempt) - for(it = kids.begin(); it != kids.end(); ++it) - if (!(it->second)->thisNetInterface(ni)) - it->second->reset(); - return 1; - } - break; - } - case CONNECT_UNREACHABLE: - case CONNECT_FIREWALLED: - case CONNECT_FAILED: - { - if (active && (activepqi == pqi)) - { -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::handleNotifyEvent_locked Id: " - << PeerId().toStdString() - << " CONNECT_FAILED->marking so!" << std::endl; -#endif - - activepqi->askForStop(); // STOP THREAD. - active = false; - activepqi = nullptr; - } -#ifdef PERSON_DEBUG - else - std::cerr << "pqiperson::handleNotifyEvent_locked Id: " - << PeerId().toStdString() + " CONNECT_FAILED-> from " - << "an unactive connection, don't flag the peer as " - << "not connected, just try next attempt !" << std::endl; -#endif - /* notify up */ - if (pqipg) - pqipg->notifyConnect(PeerId(), type, false, false, remote_peer_address); - - return 1; - } - default: - return -1; - } -} - -/***************** Not PQInterface Fns ***********************/ - -int pqiperson::reset() -{ - RS_STACK_MUTEX(mPersonMtx); - return reset_locked(); -} - -int pqiperson::reset_locked() -{ -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::reset_locked() resetting all pqiconnect for Id: " - << PeerId().toStdString() << std::endl; -#endif - - std::map::iterator it; - for(it = kids.begin(); it != kids.end(); ++it) - { - it->second->askForStop(); // STOP THREAD. - (it->second) -> reset(); - } - - activepqi = NULL; - active = false; - lastHeartbeatReceived = 0; - - return 1; -} - -int pqiperson::fullstopthreads() -{ -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::fullstopthreads() for Id: " - << PeerId().toStdString() << std::endl; -#endif - - RS_STACK_MUTEX(mPersonMtx); - - std::map::iterator it; - for(it = kids.begin(); it != kids.end(); ++it) - (it->second)->fullstop(); // WAIT FOR THREAD TO STOP. - - activepqi = NULL; - active = false; - lastHeartbeatReceived = 0; - - return 1; -} - -int pqiperson::addChildInterface(uint32_t type, pqiconnect *pqi) -{ -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::addChildInterface() : Id " - << PeerId().toStdString() << " " << type << std::endl; -#endif - - RS_STACK_MUTEX(mPersonMtx); - - kids[type] = pqi; - return 1; -} - -/***************** PRIVATE FUNCTIONS ***********************/ -// functions to iterate over the connects and change state. - - -int pqiperson::listen() -{ -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::listen() Id: " + PeerId().toStdString() << std::endl; -#endif - - RS_STACK_MUTEX(mPersonMtx); - - if (!active) - { - std::map::iterator it; - for(it = kids.begin(); it != kids.end(); ++it) - (it->second)->listen(); - } - return 1; -} - - -int pqiperson::stoplistening() -{ -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::stoplistening() Id: " + PeerId().toStdString() - << std::endl; -#endif - - RS_STACK_MUTEX(mPersonMtx); - - std::map::iterator it; - for(it = kids.begin(); it != kids.end(); ++it) - (it->second)->stoplistening(); - - return 1; -} - -int pqiperson::connect(uint32_t type, const sockaddr_storage &raddr, - const sockaddr_storage &proxyaddr, - const sockaddr_storage &srcaddr, - uint32_t delay, uint32_t period, uint32_t timeout, - uint32_t flags, uint32_t bandwidth, - const std::string &domain_addr, uint16_t domain_port) -{ -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::connect() Id: " << PeerId().toStdString() - << " type: " << type << " addr: " - << sockaddr_storage_tostring(raddr) << " proxyaddr: " - << sockaddr_storage_tostring(proxyaddr) << " srcaddr: " - << sockaddr_storage_tostring(srcaddr) << " delay: " << delay - << " period: " << period << " timeout: " << timeout << " flags: " - << flags << " bandwidth: " << bandwidth << std::endl; -#endif - - RS_STACK_MUTEX(mPersonMtx); - - std::map::iterator it; - - it = kids.find(type); - if (it == kids.end()) - { - /* notify of fail! */ - pqipg->notifyConnect(PeerId(), type, false, false, raddr); - return 0; - } - - pqiconnect *pqi = it->second; - -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::connect() resetting for new connection attempt" << std::endl; -#endif - - /* set the parameters */ - pqi->reset(); - -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::connect() clearing rate cap" << std::endl; -#endif - setRateCap_locked(0,0); - -#ifdef PERSON_DEBUG - std::cerr << "pqiperson::connect() setting connect_parameters" << std::endl; -#endif - - // These two are universal. - pqi->connect_parameter(NET_PARAM_CONNECT_DELAY, delay); - pqi->connect_parameter(NET_PARAM_CONNECT_TIMEOUT, timeout); - - // these 5 are only used by UDP connections. - pqi->connect_parameter(NET_PARAM_CONNECT_PERIOD, period); - pqi->connect_parameter(NET_PARAM_CONNECT_FLAGS, flags); - pqi->connect_parameter(NET_PARAM_CONNECT_BANDWIDTH, bandwidth); - - pqi->connect_additional_address(NET_PARAM_CONNECT_PROXY, proxyaddr); - pqi->connect_additional_address(NET_PARAM_CONNECT_SOURCE, srcaddr); - - // These are used by Proxy/Hidden - pqi->connect_parameter(NET_PARAM_CONNECT_DOMAIN_ADDRESS, domain_addr); - pqi->connect_parameter(NET_PARAM_CONNECT_REMOTE_PORT, domain_port); - - pqi->connect(raddr); - - // flag if we started a new connectionAttempt. - inConnectAttempt = true; - - return 1; -} - - -void pqiperson::getRates(RsBwRates &rates) -{ - RS_STACK_MUTEX(mPersonMtx); - - // get the rate from the active one. - if ((!active) || (activepqi == NULL)) - return; - - activepqi->getRates(rates); -} - -int pqiperson::gatherStatistics(std::list& out_lst, - std::list& in_lst) -{ - RS_STACK_MUTEX(mPersonMtx); - - // Get the rate from the active one. - if( (!active) || (activepqi == NULL) ) - return 0 ; - - return activepqi->gatherStatistics(out_lst, in_lst); -} - -int pqiperson::getQueueSize(bool in) -{ - RS_STACK_MUTEX(mPersonMtx); - - // get the rate from the active one. - if ((!active) || (activepqi == NULL)) - return 0; - - return activepqi->getQueueSize(in); -} - -bool pqiperson::getCryptoParams(RsPeerCryptoParams & params) -{ - RS_STACK_MUTEX(mPersonMtx); - - if(active && activepqi != NULL) - return activepqi->getCryptoParams(params); - else - { - params.connexion_state = 0; - params.cipher_name.clear(); - - return false ; - } -} - -bool pqiconnect::getCryptoParams(RsPeerCryptoParams & params) -{ - pqissl *ssl = dynamic_cast(ni); - - if(ssl != NULL) - { - ssl->getCryptoParams(params); - return true; - } - else - { - params.connexion_state = 0 ; - params.cipher_name.clear() ; - return false ; - } -} - -float pqiperson::getRate(bool in) -{ - RS_STACK_MUTEX(mPersonMtx); - - // get the rate from the active one. - if ((!active) || (activepqi == NULL)) - return 0; - - return activepqi -> getRate(in); -} - -uint64_t pqiperson::getTraffic(bool in) -{ - if ((!active) || (activepqi == NULL)) - return 0; - return activepqi -> getTraffic(in); -} - -void pqiperson::setMaxRate(bool in, float val) -{ - RS_STACK_MUTEX(mPersonMtx); - - // set to all of them. (and us) - PQInterface::setMaxRate(in, val); - // clean up the children. - std::map::iterator it; - for(it = kids.begin(); it != kids.end(); ++it) - (it->second) -> setMaxRate(in, val); -} - -void pqiperson::setRateCap(float val_in, float val_out) -{ - // This methods might be called all the way down from pqiperson::tick() down - // to pqissludp while completing a UDP connexion, causing a deadlock. - // - // We need to make sure the mutex is not already locked by current thread. If so, we call the - // locked version directly if not, we lock, call, and unlock, possibly waiting if the - // lock is already acquired by another thread. - // - // The lock cannot be locked by the same thread between the first test and - // the "else" statement, so there is no possibility for this code to fail. - // - // We could actually put that code in RsMutex::lock()? - // TODO: 2015/12/19 This code is already in RsMutex::lock() but is guarded - // by RSTHREAD_SELF_LOCKING_GUARD which is specifically unset in the header - // Why is that code guarded? Do it have an impact on performance? - // Or we should not get in the situation of trying to relock the mutex on - // the same thread NEVER? - - if(pthread_equal(mPersonMtx.owner(), pthread_self())) - // Unlocked, or already locked by same thread - setRateCap_locked(val_in, val_out); - else - { - // Lock was free or locked by different thread => wait. - RS_STACK_MUTEX(mPersonMtx); - setRateCap_locked(val_in, val_out); - } -} - -void pqiperson::setRateCap_locked(float val_in, float val_out) -{ - // set to all of them. (and us) - PQInterface::setRateCap(val_in, val_out); - // clean up the children. - std::map::iterator it; - for(it = kids.begin(); it != kids.end(); ++it) - (it->second)->setRateCap(val_in, val_out); -} diff --git a/libretroshare/src/pqi/pqiperson.h b/libretroshare/src/pqi/pqiperson.h deleted file mode 100644 index 59bae7834..000000000 --- a/libretroshare/src/pqi/pqiperson.h +++ /dev/null @@ -1,175 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiperson.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_PERSON_HEADER -#define MRK_PQI_PERSON_HEADER - - -#include -#include "pqi/pqi.h" -#include "util/rsnet.h" - -#include - -class pqiperson; -struct RsPeerCryptoParams; - -static const int CONNECT_RECEIVED = 1; -static const int CONNECT_SUCCESS = 2; -static const int CONNECT_UNREACHABLE = 3; -static const int CONNECT_FIREWALLED = 4; -static const int CONNECT_FAILED = 5; - -static const rstime_t HEARTBEAT_REPEAT_TIME = 5; - -#include "pqi/pqiqosstreamer.h" -#include "pqi/pqithreadstreamer.h" - -class pqiconnect : public pqiQoSstreamer, public NetInterface -{ -public: - pqiconnect(PQInterface *parent, RsSerialiser *rss, NetBinInterface *ni_in) : - pqiQoSstreamer(parent, rss, ni_in->PeerId(), ni_in, 0), // pqistreamer will cleanup NetInterface. - NetInterface(NULL, ni_in->PeerId()), // No need for callback - ni(ni_in) {} - - virtual ~pqiconnect() {} - virtual bool getCryptoParams(RsPeerCryptoParams& params); - - // presents a virtual NetInterface -> passes to ni. - virtual int connect(const struct sockaddr_storage &raddr) { return ni->connect(raddr); } - virtual int listen() { return ni->listen(); } - virtual int stoplistening() { return ni->stoplistening(); } - virtual int reset() { pqistreamer::reset(); return ni->reset(); } - virtual int disconnect() { return reset() ; } - virtual bool connect_parameter(uint32_t type, uint32_t value) { return ni->connect_parameter(type, value);} - virtual bool connect_parameter(uint32_t type, const std::string &value) { return ni->connect_parameter(type, value);} - virtual bool connect_additional_address(uint32_t type, const struct sockaddr_storage &addr) { return ni->connect_additional_address(type, addr); } - virtual int getConnectAddress(struct sockaddr_storage &raddr){ return ni->getConnectAddress(raddr); } - - // get the contact from the net side! - virtual const RsPeerId& PeerId() { return ni->PeerId(); } - - // to check if our interface. - virtual bool thisNetInterface(NetInterface *ni_in) { return (ni_in == ni); } - -protected: - NetBinInterface *ni; -}; - - -class pqipersongrp; - -class NotifyData -{ -public: - NotifyData() : mNi(NULL), mState(0) - { - sockaddr_storage_clear(mAddr); - } - - NotifyData(NetInterface *ni, int state, const sockaddr_storage &addr) : - mNi(ni), mState(state), mAddr(addr) {} - - NetInterface *mNi; - int mState; - sockaddr_storage mAddr; -}; - - -class pqiperson: public PQInterface -{ -public: - pqiperson(const RsPeerId& id, pqipersongrp *ppg); - virtual ~pqiperson(); // must clean up children. - - // control of the connection. - int reset(); - int listen(); - int stoplistening(); - - int connect(uint32_t type, const sockaddr_storage &raddr, - const sockaddr_storage &proxyaddr, const sockaddr_storage &srcaddr, - uint32_t delay, uint32_t period, uint32_t timeout, uint32_t flags, - uint32_t bandwidth, const std::string &domain_addr, uint16_t domain_port); - - int fullstopthreads(); - int receiveHeartbeat(); - - // add in connection method. - int addChildInterface(uint32_t type, pqiconnect *pqi); - - virtual bool getCryptoParams(RsPeerCryptoParams&); - - // The PQInterface interface. - virtual int SendItem(RsItem *,uint32_t& serialized_size); - virtual int SendItem(RsItem *item) - { - std::cerr << "Warning pqiperson::sendItem(RsItem*) should not be called." - << "Plz call SendItem(RsItem *,uint32_t& serialized_size) instead." - << std::endl; - uint32_t serialized_size; - return SendItem(item, serialized_size); - } - - virtual RsItem *GetItem(); - virtual bool RecvItem(RsItem *item); - - virtual int status(); - virtual int tick(); - - // overloaded callback function for the child - notify of a change. - virtual int notifyEvent(NetInterface *ni, int event, const struct sockaddr_storage &addr); - - // PQInterface for rate control overloaded.... - virtual int getQueueSize(bool in); - virtual void getRates(RsBwRates &rates); - virtual float getRate(bool in); - virtual uint64_t getTraffic(bool in); - virtual void setMaxRate(bool in, float val); - virtual void setRateCap(float val_in, float val_out); - virtual int gatherStatistics(std::list& outqueue_lst, - std::list& inqueue_lst); - -private: - void processNotifyEvents(); - int handleNotifyEvent_locked(NetInterface *ni, int event, - const sockaddr_storage &addr); - - RsMutex mNotifyMtx; // LOCKS Notify Queue - std::list mNotifyQueue; - - RsMutex mPersonMtx; // LOCKS below - - int reset_locked(); - - void setRateCap_locked(float val_in, float val_out); - - std::map kids; - bool active; - pqiconnect *activepqi; - bool inConnectAttempt; - //int waittimes; - rstime_t lastHeartbeatReceived; // use to track connection failure - pqipersongrp *pqipg; /* parent for callback */ -}; - -#endif diff --git a/libretroshare/src/pqi/pqipersongrp.cc b/libretroshare/src/pqi/pqipersongrp.cc deleted file mode 100644 index 7146be7de..000000000 --- a/libretroshare/src/pqi/pqipersongrp.cc +++ /dev/null @@ -1,721 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqipersongrp.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2008 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "pqi/pqipersongrp.h" -#include "pqi/p3linkmgr.h" -#include "util/rsdebug.h" -#include "util/rsprint.h" -#include "serialiser/rsserializer.h" - -#include - -static struct RsLog::logInfo pqipersongrpzoneInfo = {RsLog::Default, "pqipersongrp"}; -#define pqipersongrpzone &pqipersongrpzoneInfo - -#ifdef WINDOWS_SYS -/////////////////////////////////////////////////////////// -// hack for too many connections -#include "retroshare/rsinit.h" -static std::list waitingIds; -#define MAX_CONNECT_COUNT 3 -/////////////////////////////////////////////////////////// -#endif - -/**** - *#define PGRP_DEBUG 1 - *#define PGRP_DEBUG_LOG 1 - ****/ - -#define DEFAULT_DOWNLOAD_KB_RATE (200.0) -#define DEFAULT_UPLOAD_KB_RATE (50.0) - -/* MUTEX NOTES: - * Functions like GetRsRawItem() lock itself (pqihandler) and - * likewise ServiceServer and ConfigMgr mutex themselves. - * This means the only things we need to worry about are: - * pqilistener and when accessing pqihandlers data. - */ - - - // New speedy recv. -bool pqipersongrp::RecvRsRawItem(RsRawItem *item) -{ - std::cerr << "pqipersongrp::RecvRsRawItem()"; - std::cerr << std::endl; - - p3ServiceServer::recvItem(item); - - return true; -} - - - -#ifdef TO_BE_REMOVED -// handle the tunnel services. -int pqipersongrp::tickServiceRecv() -{ - RsRawItem *pqi = NULL; - int i = 0; - - pqioutput(PQL_DEBUG_ALL, pqipersongrpzone, "pqipersongrp::tickServiceRecv()"); - - //p3ServiceServer::tick(); - - while(NULL != (pqi = GetRsRawItem())) - { - static int ntimes=0 ; - if(++ntimes < 20) - { - std::cerr << "pqipersongrp::tickServiceRecv() GetRsRawItem()"; - std::cerr << " should never happen anymore! item data=" << RsUtil::BinToHex((char*)pqi->getRawData(),pqi->getRawLength()) ; - std::cerr << std::endl; - } - - ++i; - pqioutput(PQL_DEBUG_BASIC, pqipersongrpzone, - "pqipersongrp::tickServiceRecv() Incoming TunnelItem"); - recvItem(pqi); - } - - if (0 < i) - { - return 1; - } - return 0; -} -#endif - -// handle the tunnel services. - -// Improvements: -// This function is no longer necessary, and data is pushed directly to pqihandler. - -#ifdef TO_BE_REMOVED -int pqipersongrp::tickServiceSend() -{ - RsRawItem *pqi = NULL; - int i = 0; - - pqioutput(PQL_DEBUG_ALL, pqipersongrpzone, "pqipersongrp::tickServiceSend()"); - - p3ServiceServer::tick(); - - while(NULL != (pqi = outgoing())) /* outgoing has own locking */ - { - ++i; - pqioutput(PQL_DEBUG_BASIC, pqipersongrpzone, - "pqipersongrp::tickTunnelServer() OutGoing RsItem"); - - SendRsRawItem(pqi); /* Locked by pqihandler */ - } - if (0 < i) - { - return 1; - } - return 0; -} - -#endif - - - // init -pqipersongrp::pqipersongrp(p3ServiceControl *ctrl, unsigned long flags) - :pqihandler(), p3ServiceServer(this, ctrl), pqil(NULL), pqilMtx("pqipersongrp"), initFlags(flags) -{ -} - - -int pqipersongrp::tick() -{ - /* could limit the ticking of listener / tunnels to 1/sec... - * but not to important. - */ - - { - RsStackMutex stack(pqilMtx); /******* LOCKED MUTEX **********/ - if (pqil) - { - pqil -> tick(); - } - } /* UNLOCKED */ - - int i = 0; - -#ifdef TO_BE_REMOVED - if (tickServiceSend()) - { - i = 1; -#ifdef PGRP_DEBUG - std::cerr << "pqipersongrp::tick() moreToTick from tickServiceSend()" << std::endl; -#endif - } - if (pqihandler::tick()) /* does Send/Recv */ - { - i = 1; -#ifdef PGRP_DEBUG - std::cerr << "pqipersongrp::tick() moreToTick from pqihandler::tick()" << std::endl; -#endif - } - if (tickServiceRecv()) - { - i = 1; -#ifdef PGRP_DEBUG - std::cerr << "pqipersongrp::tick() moreToTick from tickServiceRecv()" << std::endl; -#endif - } -#endif - - if(pqihandler::tick()) - i=1; - - p3ServiceServer::tick(); - - return i; -} - -int pqipersongrp::status() -{ - { - RsStackMutex stack(pqilMtx); /******* LOCKED MUTEX **********/ - if (pqil) - { - pqil -> status(); - } - } /* UNLOCKED */ - - return pqihandler::status(); -} - - -/* Initialise pqilistener */ -int pqipersongrp::init_listener() -{ - /* extract our information from the p3ConnectMgr */ - if (initFlags & PQIPERSON_NO_LISTENER) - { - RsStackMutex stack(pqilMtx); /******* LOCKED MUTEX **********/ - pqil = NULL; - } - else - { - /* extract details from - */ - struct sockaddr_storage laddr; - mLinkMgr->getLocalAddress(laddr); - - RsStackMutex stack(pqilMtx); /******* LOCKED MUTEX **********/ - pqil = locked_createListener(laddr); - } - return 1; -} - -bool pqipersongrp::resetListener(const struct sockaddr_storage &local) -{ - #ifdef PGRP_DEBUG - std::cerr << "pqipersongrp::resetListener()" << std::endl; - #endif - - // stop it, - // change the address. - // restart. - - RsStackMutex stack(pqilMtx); /******* LOCKED MUTEX **********/ - - if (pqil != NULL) - { - #ifdef PGRP_DEBUG - std::cerr << "pqipersongrp::resetListener() haveListener" << std::endl; - #endif - - pqil -> resetlisten(); - pqil -> setListenAddr(local); - pqil -> setuplisten(); - - #ifdef PGRP_DEBUG - std::cerr << "pqipersongrp::resetListener() done!" << std::endl; - #endif - - } - return 1; -} - -void pqipersongrp::statusChange(const std::list &plist) -{ - - /* iterate through, only worry about the friends */ - std::list::const_iterator it; - for(it = plist.begin(); it != plist.end(); ++it) - { - if (it->state & RS_PEER_S_FRIEND) - { - /* now handle add/remove */ - if ((it->actions & RS_PEER_NEW) - || (it->actions & RS_PEER_MOVED)) - { - addPeer(it->id); - } - - if (it->actions & RS_PEER_CONNECT_REQ) - { - connectPeer(it->id); - } - } - else /* Not Friend */ - { - if (it->actions & RS_PEER_MOVED) - { - removePeer(it->id); - } - } - } -} - -#ifdef WINDOWS_SYS -/////////////////////////////////////////////////////////// -// hack for too many connections -void pqipersongrp::statusChanged() -{ -#warning "Windows connection limited hacked together - please fix" - - if (RsInit::isWindowsXP() == false) { - /* the problem only exist in Windows XP */ - RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ - waitingIds.clear(); - return; - } - - { - RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ - if (waitingIds.empty()) - { - /* nothing to do */ - return; - } - } - - /* check for active connections and start waiting id's */ - long connect_count = 0; - std::list toConnect; - - { - RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ - - /* get address from p3connmgr */ - if (!mLinkMgr) { - return; - } - - /* check for active connections and start waiting id's */ - std::list peers; - mLinkMgr->getFriendList(peers); - - /* count connection attempts */ - std::list::iterator peer; - for (peer = peers.begin(); peer != peers.end(); ++peer) { - peerConnectState state; - if (mLinkMgr->getFriendNetStatus(*peer, state) == false) { - continue; - } - - if (state.inConnAttempt) { - connect_count++; - if (connect_count >= MAX_CONNECT_COUNT) { -#ifdef PGRP_DEBUG - std::cerr << "pqipersongrp::statusChanged() Too many connections due to windows limitations. There are " << waitingIds.size() << " waiting connections." << std::endl; -#endif - return; - } - } - } - -#ifdef PGRP_DEBUG - std::cerr << "pqipersongrp::statusChanged() There are "; - std::cerr << connect_count << " connection attempts and " << waitingIds.size(); - std::cerr << " waiting connections. Can start "; - std::cerr << (MAX_CONNECT_COUNT - connect_count) << " connection attempts."; - std::cerr << std::endl; -#endif - - /* start some waiting id's */ - for (int i = connect_count; i < MAX_CONNECT_COUNT; i++) - { - if (waitingIds.empty()) { - break; - } - RsPeerId waitingId = waitingIds.front(); - waitingIds.pop_front(); - -#ifdef PGRP_DEBUG - std::cerr << " pqipersongrp::statusChanged() id: " << waitingId << " connect peer"; - std::cerr << std::endl; -#endif - - toConnect.push_back(waitingId); - } - } /* UNLOCKED */ - - std::list::iterator cit; - for(cit = toConnect.begin(); cit != toConnect.end(); ++cit) - { - connectPeer(*cit, true); - } -} -/////////////////////////////////////////////////////////// -#endif - -bool pqipersongrp::getCryptoParams(const RsPeerId& id,RsPeerCryptoParams& params) -{ - RsStackMutex stack(coreMtx); /******* LOCKED MUTEX **********/ - - std::map::iterator it = mods.find(id) ; - - if(it == mods.end()) - return false ; - - return it->second->pqi->getCryptoParams(params) ; - - //return locked_getCryptoParams(id,params) ; -} - -int pqipersongrp::addPeer(const RsPeerId& id) -{ - pqioutput(PQL_DEBUG_BASIC, pqipersongrpzone, "pqipersongrp::addPeer() PeerId: " + id.toStdString()); - - std::cerr << "pqipersongrp::addPeer() id: " << id; - std::cerr << std::endl; -#ifdef PGRP_DEBUG -#endif - - SearchModule *sm = NULL; - - { - // The Mutex is required here as pqiListener is not thread-safe. - RsStackMutex stack(pqilMtx); /******* LOCKED MUTEX **********/ - pqiperson *pqip = locked_createPerson(id, pqil); - - // attach to pqihandler - sm = new SearchModule(); - sm -> peerid = id; - sm -> pqi = pqip; - - // reset it to start it working. -#ifdef PGRP_DEBUG_LOG - pqioutput(PQL_WARNING, pqipersongrpzone, "pqipersongrp::addPeer() => reset() called to initialise new person"); -#endif - pqip -> reset(); - pqip -> listen(); - - } /* UNLOCKED */ - - return AddSearchModule(sm); -} - - -int pqipersongrp::removePeer(const RsPeerId& id) -{ - std::map::iterator it; - -#ifdef PGRP_DEBUG - std::cerr << "pqipersongrp::removePeer() id: " << id; - std::cerr << std::endl; -#endif - - RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ - - it = mods.find(id); - if (it != mods.end()) - { - SearchModule *mod = it->second; - pqiperson *p = (pqiperson *) mod -> pqi; - p -> stoplistening(); - pqioutput(PQL_WARNING, pqipersongrpzone, "pqipersongrp::removePeer() => reset() called before deleting person"); - p -> reset(); - p -> fullstopthreads(); - delete p; - mods.erase(it); - } - else - { - std::cerr << " pqipersongrp::removePeer() ERROR doesn't exist! id: " << id; - std::cerr << std::endl; - } - return 1; -} - -int pqipersongrp::tagHeartbeatRecvd(const RsPeerId& id) -{ - std::map::iterator it; - -#ifdef PGRP_DEBUG - std::cerr << " pqipersongrp::tagHeartbeatRecvd() id: " << id; - std::cerr << std::endl; -#endif - - RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ - - it = mods.find(id); - if (it != mods.end()) - { - SearchModule *mod = it->second; - pqiperson *p = (pqiperson *) mod -> pqi; - p->receiveHeartbeat(); - return 1; - } - return 0; -} - - - - - - -int pqipersongrp::connectPeer(const RsPeerId& id -#ifdef WINDOWS_SYS -/////////////////////////////////////////////////////////// -// hack for too many connections - , bool bConnect /*= false*/ -/////////////////////////////////////////////////////////// -#endif - ) -{ - RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ - - if (!mLinkMgr) - return 0; - - if (id == mLinkMgr->getOwnId()) - { -#ifdef PGRP_DEBUG - std::cerr << "pqipersongrp::connectPeer() ERROR Failed, connecting to own id." << std::endl; -#endif - return 0; - } - std::map::iterator it; - it = mods.find(id); - if (it == mods.end()) - { - return 0; - } - /* get the connect attempt details from the p3connmgr... */ - SearchModule *mod = it->second; - pqiperson *p = (pqiperson *) mod -> pqi; - -#ifdef WINDOWS_SYS - /////////////////////////////////////////////////////////// - // hack for too many connections - - if (RsInit::isWindowsXP()) { - /* the problem only exist in Windows XP */ - if (bConnect == false) { - /* check for id is waiting */ - if (std::find(waitingIds.begin(), waitingIds.end(), id) != waitingIds.end()) { - /* id is waiting for a connection */ -#ifdef PGRP_DEBUG - std::cerr << " pqipersongrp::connectPeer() id: " << id << " is already waiting "; - std::cerr << std::endl; -#endif - return 0; - } - - /* check for connection type of the next connect attempt */ - peerConnectState state; - if (mLinkMgr->getFriendNetStatus(id, state) == false) { -#ifdef PGRP_DEBUG - std::cerr << " pqipersongrp::connectPeer() id: " << id << " No friend net status"; - std::cerr << std::endl; -#endif - return 0; - } - if (state.connAddrs.size() < 1) { -#ifdef PGRP_DEBUG - std::cerr << " pqipersongrp::connectPeer() id: " << id << " No existing connect addresses"; - std::cerr << std::endl; -#endif - return 0; - } - const peerConnectAddress ¤tConnAddrAttempt = state.connAddrs.front(); - if (currentConnAddrAttempt.type & RS_NET_CONN_TCP_ALL) { -#ifdef PGRP_DEBUG - std::cerr << " pqipersongrp::connectPeer() id: " << id << " added to the waiting list"; - std::cerr << std::endl; -#endif - /* TCP connect, add id to waiting */ - waitingIds.push_back(id); - - /* wait for call to connectPeer with empty id */ - return 0; - } - - /* try all other types of connect directly */ - -#ifdef PGRP_DEBUG - std::cerr << " pqipersongrp::connectPeer() id: " << id << " connect directly without wait"; - std::cerr << std::endl; -#endif - } - - /* remove id from waiting */ - waitingIds.remove(id); - } - - /////////////////////////////////////////////////////////// -#endif - - struct sockaddr_storage addr; - uint32_t delay; - uint32_t period; - uint32_t timeout; - uint32_t type; - uint32_t flags = 0 ; - - struct sockaddr_storage proxyaddr; - struct sockaddr_storage srcaddr; - uint32_t bandwidth; - std::string domain_addr; - uint16_t domain_port; - - if (!mLinkMgr->connectAttempt(id, addr, proxyaddr, srcaddr, delay, period, type, flags, bandwidth, domain_addr, domain_port)) - { -#ifdef PGRP_DEBUG - std::cerr << " pqipersongrp::connectPeer() No Net Address"; - std::cerr << std::endl; -#endif - return 0; - } - -#ifdef PGRP_DEBUG - std::cerr << " pqipersongrp::connectPeer() connectAttempt data id: " << id; - std::cerr << " addr: " << sockaddr_storage_tostring(addr); - std::cerr << " delay: " << delay; - std::cerr << " period: " << period; - std::cerr << " type: " << type; - std::cerr << " flags: " << flags; - std::cerr << " domain_addr: " << domain_addr; - std::cerr << " domain_port: " << domain_port; - std::cerr << std::endl; -#endif - - - uint32_t ptype; - if (type & RS_NET_CONN_TCP_ALL) - { - switch (type) { - case RS_NET_CONN_TCP_HIDDEN_TOR: - ptype = PQI_CONNECT_HIDDEN_TOR_TCP; - timeout = RS_TCP_HIDDEN_TIMEOUT_PERIOD; - break; - case RS_NET_CONN_TCP_HIDDEN_I2P: - ptype = PQI_CONNECT_HIDDEN_I2P_TCP; - timeout = RS_TCP_HIDDEN_TIMEOUT_PERIOD; - break; - default: - ptype = PQI_CONNECT_TCP; - timeout = RS_TCP_STD_TIMEOUT_PERIOD; - break; - } -#ifdef PGRP_DEBUG - std::cerr << " pqipersongrp::connectPeer() connecting with TCP: Timeout :" << timeout; - std::cerr << std::endl; -#endif - } - else if (type & RS_NET_CONN_UDP_ALL) - { - ptype = PQI_CONNECT_UDP; - timeout = period + RS_UDP_STD_TIMEOUT_PERIOD; // Split of UNCERTAINTY + TIME FOR TTL to RISE to Connection. -#ifdef PGRP_DEBUG - std::cerr << " pqipersongrp::connectPeer() connecting with UDP: Timeout :" << timeout; - std::cerr << std::endl; -#endif - } - else - { -#ifdef PGRP_DEBUG - std::cerr << " pqipersongrp::connectPeer() Ignoring Unknown Type:" << type; - std::cerr << std::endl; -#endif - return 0; - } - - p->connect(ptype, addr, proxyaddr, srcaddr, delay, period, timeout, flags, bandwidth, domain_addr, domain_port); - - return 1; -} - -bool pqipersongrp::notifyConnect(const RsPeerId& id, uint32_t ptype, bool success, bool isIncomingConnection, const struct sockaddr_storage &raddr) -{ - uint32_t type = 0; - if (ptype == PQI_CONNECT_TCP) - { - type = RS_NET_CONN_TCP_ALL; - } - else if (ptype == PQI_CONNECT_UDP) - { - type = RS_NET_CONN_UDP_ALL; - } - - if (mLinkMgr) - mLinkMgr->connectResult(id, success, isIncomingConnection, type, raddr); - - return (NULL != mLinkMgr); -} - -/******************************** DUMMY Specific features ***************************/ - -#include "pqi/pqibin.h" - -pqilistener * pqipersongrpDummy::locked_createListener(const struct sockaddr_storage & /*laddr*/) -{ - pqilistener *listener = new pqilistener(); - return listener; -} - - -pqiperson * pqipersongrpDummy::locked_createPerson(const RsPeerId& id, pqilistener * /*listener*/) -{ - pqioutput(PQL_DEBUG_BASIC, pqipersongrpzone, "pqipersongrpDummy::createPerson() PeerId: " + id.toStdString()); - - pqiperson *pqip = new pqiperson(id, this); - - // TCP - NetBinDummy *d1 = new NetBinDummy(pqip, id, PQI_CONNECT_TCP); - - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsRawSerialiser()); - - pqiconnect *pqic = new pqiconnect(pqip, rss, d1); - - pqip -> addChildInterface(PQI_CONNECT_TCP, pqic); - - // UDP. - NetBinDummy *d2 = new NetBinDummy(pqip, id, PQI_CONNECT_UDP); - - RsSerialiser *rss2 = new RsSerialiser(); - rss2->addSerialType(new RsRawSerialiser()); - - pqiconnect *pqic2 = new pqiconnect(pqip, rss2, d2); - - pqip -> addChildInterface(PQI_CONNECT_UDP, pqic2); - - return pqip; -} - -/******************************** DUMMY Specific features ***************************/ - diff --git a/libretroshare/src/pqi/pqipersongrp.h b/libretroshare/src/pqi/pqipersongrp.h deleted file mode 100644 index 5b57aebb1..000000000 --- a/libretroshare/src/pqi/pqipersongrp.h +++ /dev/null @@ -1,141 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqipersongrp.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2008 Robert Fernie. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_PERSON_HANDLER_HEADER -#define MRK_PQI_PERSON_HANDLER_HEADER - -#include "pqi/pqihandler.h" -#include "pqi/pqiperson.h" -#include "pqi/pqilistener.h" -#include "pqi/pqiservice.h" -#include "pqi/pqimonitor.h" -#include "pqi/p3cfgmgr.h" - - -// So this is a specific implementation -// -// it is designed to have one pqilistensocket + a series of pqisockets -// -// as an added bonus, we are going to -// make this a pqitunnelserver, to which services can be attached. - -const unsigned long PQIPERSON_NO_LISTENER = 0x0001; - -const unsigned long PQIPERSON_ALL_BW_LIMITED = 0x0010; -struct RsPeerCryptoParams; - -class pqipersongrp: public pqihandler, public pqiMonitor, public p3ServiceServer, public pqiNetListener -{ - public: - pqipersongrp(p3ServiceControl *ctrl, unsigned long flags); - - /*************************** Setup *************************/ - /* pqilistener */ - -virtual bool resetListener(const struct sockaddr_storage &local); // overloaded from pqiNetListener -int init_listener(); - - /*************** pqiMonitor callback ***********************/ -virtual void statusChange(const std::list &plist); - -#ifdef WINDOWS_SYS -/////////////////////////////////////////////////////////// -// hack for too many connections -virtual void statusChanged(); -/////////////////////////////////////////////////////////// -#endif - - /******************* Peer Control **************************/ -virtual int addPeer(const RsPeerId& id); /* can be overloaded for testing */ -int removePeer(const RsPeerId& id); -int connectPeer(const RsPeerId& id -#ifdef WINDOWS_SYS -/////////////////////////////////////////////////////////// -// hack for too many connections - , bool bConnect = false -/////////////////////////////////////////////////////////// -#endif - ); - - // New speedy recv. -virtual bool RecvRsRawItem(RsRawItem *item); - - - /* Work-around to dodgy pointer stuff */ -int tagHeartbeatRecvd(const RsPeerId& id); - - /*** callback from children ****/ -bool notifyConnect(const RsPeerId& id, uint32_t type, bool success, bool isIncomingConnection, const struct sockaddr_storage &remote_peer_address); -//bool notifyConnect(std::string id, uint32_t type, bool success); - - // tick interfaces. -virtual int tick(); -virtual int status(); - -virtual bool getCryptoParams(const RsPeerId&,RsPeerCryptoParams&) ; - protected: - -virtual bool locked_getCryptoParams(const RsPeerId&, RsPeerCryptoParams&) { return false ;} - - /********* FUNCTIONS to OVERLOAD for specialisation ********/ - // THESE NEED TO BE LOCKED UNTIL PQILISTENER IS THREAD-SAFE. -virtual pqilistener *locked_createListener(const struct sockaddr_storage &laddr) = 0; -virtual pqiperson *locked_createPerson(const RsPeerId& id, pqilistener *listener) = 0; - /********* FUNCTIONS to OVERLOAD for specialisation ********/ - - /* Overloaded RsItem Check - * checks item->cid vs Person - */ -virtual int checkOutgoingRsItem(RsItem *item, int global) - { - (void) item; /* suppress unused parameter warning */ - (void) global; /* suppress unused parameter warning */ - return 1; - } - - private: - - // The serviceserver operation. - //int tickServiceRecv(); - //int tickServiceSend(); - - pqilistener *pqil; - RsMutex pqilMtx; /* MUTEX */ - unsigned long initFlags; -}; - -class pqipersongrpDummy: public pqipersongrp -{ - public: - pqipersongrpDummy(p3ServiceControl *ctrl, unsigned long flags) - :pqipersongrp(ctrl, flags) { return; } - - protected: - - /********* FUNCTIONS to OVERLOAD for specialisation ********/ -virtual pqilistener *locked_createListener(const struct sockaddr_storage &laddr); -virtual pqiperson *locked_createPerson(const RsPeerId& id, pqilistener *listener); - /********* FUNCTIONS to OVERLOAD for specialisation ********/ -}; - - - -#endif // MRK_PQI_PERSON_HANDLER_HEADER diff --git a/libretroshare/src/pqi/pqiproxy.cc b/libretroshare/src/pqi/pqiproxy.cc deleted file mode 100644 index 008466847..000000000 --- a/libretroshare/src/pqi/pqiproxy.cc +++ /dev/null @@ -1,469 +0,0 @@ -#include "util/rsdebug.h" -#include "util/rsnet.h" - -#include "pqi/pqiproxy.h" - -//#define PROXY_DEBUG 1 - -int pqiproxyconnection::proxy_negociate_connection(int sockfd) -{ - int ret = 0; - switch(mProxyState) - { - case PROXY_STATE_INIT: - ret = Proxy_Send_Method(sockfd); // checks basic conn, sends Method when able. - break; - - case PROXY_STATE_WAITING_METHOD_RESPONSE: - ret = Proxy_Send_Address(sockfd); // waits for Method Response, send Address when able. - break; - - case PROXY_STATE_WAITING_SOCKS_RESPONSE: - ret = Proxy_Connection_Complete(sockfd); // wait for ACK. - - if(ret < 1) - break; - - case PROXY_STATE_CONNECTION_COMPLETE: - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Basic_Connection_Complete() COMPLETED"; - std::cerr << std::endl; -#endif - - return 1; - - case PROXY_STATE_FAILED: - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Basic_Connection_Complete() FAILED"; - std::cerr << std::endl; -#endif - - return -1; - } - - if(ret < 0) - return -1; - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Basic_Connection_Complete() IN PROGRESS"; - std::cerr << std::endl; -#endif - - // In Progress. - return 0; -} - - -int pqiproxyconnection::Proxy_Send_Method(int sockfd) -{ - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Send_Method() Basic complete, sending Method"; - std::cerr << std::endl; -#endif - - /* send hello to proxy server */ - char method_hello_data[3] = { 0x05, 0x01, 0x00 }; // [ Ver | nMethods (1) | No Auth Method ] - - int sent = send(sockfd, method_hello_data, 3, 0); - if (sent != 3) - { - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Send_Method() Send Failure"; - std::cerr << std::endl; -#endif - return -1; - } - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Send_Method() Send Method Okay"; - std::cerr << std::endl; -#endif - - mProxyState = PROXY_STATE_WAITING_METHOD_RESPONSE; - - return 1; -} - -int pqiproxyconnection::Proxy_Method_Response(int sockfd) -{ - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response()"; - std::cerr << std::endl; -#endif - - /* get response from proxy server */ - - char method_response[2]; - - /* - first it was: - - int recvd = recv(sockfd, method_response, 2, MSG_WAITALL); - - this does not work on windows, because the socket is in nonblocking mode - the winsock reference says about the recv function and MSG_WAITALL: - - "Note that if the underlying transport does not support MSG_WAITALL, - or if the socket is in a non-blocking mode, then this call will fail with WSAEOPNOTSUPP." - - now it is a two step process: - - int recvd = recv(sockfd, method_response, 2, MSG_PEEK); // test how many bytes are in the input queue - if (enaugh bytes available){ - recvd = recv(sockfd, method_response, 2, 0); - } - - this does not work on windows: - if ((recvd == -1) && (errno == EAGAIN)) return TRY_AGAIN_LATER; - - instead have to do: - if ((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK)) return TRY_AGAIN_LATER; - */ - - // test how many bytes can be read from the queue - int recvd = recv(sockfd, method_response, 2, MSG_PEEK); - if (recvd != 2) - { -#ifdef WINDOWS_SYS - if ((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK)) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response() waiting for more data (windows)"; - std::cerr << std::endl; -#endif - return 0; - } -#endif - if ((recvd == -1) && (errno == EAGAIN)) - { - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response() EAGAIN"; - std::cerr << std::endl; -#endif - - return 0; - } - else if (recvd == -1) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response() recv error peek"; - std::cerr << std::endl; -#endif - return -1; - } - else - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response() waiting for more data"; - std::cerr << std::endl; -#endif - return 0; - } - } - - // read the bytes - recvd = recv(sockfd, method_response, 2, 0); - if (recvd != 2) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response() recv error"; - std::cerr << std::endl; -#endif - return -1; - } - - // does it make sense? - if (method_response[0] != 0x05) - { - - // Error. -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response() Error response[0] != 0x05. Is: "; - std::cerr << (uint32_t) method_response[0]; - std::cerr << std::endl; -#endif - return -1; - } - - if (method_response[1] != 0x00) - { - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response() Error response[0] != 0x00. Is: "; - std::cerr << (uint32_t) method_response[1]; - std::cerr << std::endl; -#endif - // Error. - return -1; - } - - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response() Response Okay"; - std::cerr << std::endl; -#endif - - return 1; -} - -#define MAX_SOCKS_REQUEST_LEN 262 // 4 + 1 + 255 + 2. - -int pqiproxyconnection::Proxy_Send_Address(int sockfd) -{ - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Send_Address() Checking Method Response"; - std::cerr << std::endl; -#endif - - // Check Method Response. - int ret = Proxy_Method_Response(sockfd); - if (ret != 1) - { - return ret; // Method Response not complete. - } - - char socks_request[MAX_SOCKS_REQUEST_LEN] = { - 0x05, // SOCKS VERSION. - 0x01, // CONNECT (Tor doesn't support BIND or UDP). - 0x00, // RESERVED. - 0x03, // ADDRESS TYPE (Domain Name) - 0x00, // Length of Domain name... the rest is variable so can't hard code it! - }; - - /* get the length of the domain name, pack so we can't overflow uint8_t */ - uint8_t len = mDomainAddress.length(); - socks_request[4] = len; - for(int i = 0; i < len; i++) - socks_request[5 + i] = mDomainAddress[i]; - - /* now add the port, being careful with packing */ - uint16_t net_port = htons(mRemotePort); - socks_request[5 + len] = ((uint8_t *) &net_port)[0]; - socks_request[5 + len + 1] = ((uint8_t *) &net_port)[1]; - - int pkt_len = 5 + len + 2; - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Send_Address() Sending String: "; - for(int i = 0; i < pkt_len; i++) - std::cerr << (uint32_t) socks_request[i]; - std::cerr << std::endl; -#endif - int sent = send(sockfd, socks_request, pkt_len, 0); - if (sent != pkt_len) - { - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Send_Address() Send Error"; - std::cerr << std::endl; -#endif - - return -1; - } - - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Send_Address() Sent Okay"; - std::cerr << std::endl; -#endif - - mProxyState = PROXY_STATE_WAITING_SOCKS_RESPONSE; - return 1; -} - -int pqiproxyconnection::Proxy_Connection_Complete(int sockfd) -{ - /* get response from proxy server */ - /* response is similar format to request - with variable length data */ - - char socks_response[MAX_SOCKS_REQUEST_LEN]; - - // test how many bytes can be read - int recvd = recv(sockfd, socks_response, 5, MSG_PEEK); - if (recvd != 5) - { -#ifdef WINDOWS_SYS - if ((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK)) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data (windows)"; - std::cerr << std::endl; -#endif - return 0; - } -#endif - if ((recvd == -1) && (errno == EAGAIN)) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() EAGAIN"; - std::cerr << std::endl; -#endif - return 0; - } - else if (recvd == -1) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error peek"; - std::cerr << std::endl; -#endif - return -1; - } - else - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data"; - std::cerr << std::endl; -#endif - return 0; - } - } - - // read the bytes - recvd = recv(sockfd, socks_response, 5, 0); - if (recvd != 5) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error"; - std::cerr << std::endl; -#endif - return -1; - } - - // error checking. - if (socks_response[0] != 0x05) - { - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR socks_response[0] != 0x05. is: "; - std::cerr << (uint32_t) socks_response[0]; - std::cerr << std::endl; -#endif - - // error. - return -1; - } - - if (socks_response[1] != 0x00) - { - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR socks_response[1] != 0x00. is: "; - std::cerr << (uint32_t) socks_response[1]; - std::cerr << std::endl; -#endif - - // connection failed. - return -1; - } - - int address_bytes = 0; - switch(socks_response[3]) // Address Type. - { - case 0x01: - // IPv4 4 address bytes. - address_bytes = 4; -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() IPv4 Address Type"; - std::cerr << std::endl; -#endif - break; - case 0x04: - // IPv6 16 address bytes. - address_bytes = 16; -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() IPv6 Address Type"; - std::cerr << std::endl; -#endif - break; - case 0x03: - // Variable address bytes - specified in next byte. - address_bytes = 1 + socks_response[4]; -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() Domain Address Type. len: " << address_bytes; - std::cerr << std::endl; -#endif - break; - default: - // unknown error. -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR Unknown Address Type"; - std::cerr << std::endl; -#endif - return -1; - break; - } - - - // test how many bytes can be read - recvd = recv(sockfd, &(socks_response[5]), address_bytes + 1, MSG_PEEK); // address_bytes - 1 + 2... - if (recvd != address_bytes + 1) - { -#ifdef WINDOWS_SYS - if((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK)) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data(2) (windows)"; - std::cerr << std::endl; -#endif - return 0; - } -#endif - if ((recvd == -1) && (errno == EAGAIN)) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR EAGAIN at end."; - std::cerr << std::endl; -#endif - // Waiting - shouldn't happen. - return 0; - } - else if (recvd == -1) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR recving(2)"; - std::cerr << std::endl; -#endif - return -1; - } - else - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data(2)"; - std::cerr << std::endl; -#endif - return 0; - } - } - - // read the bytes - recvd = recv(sockfd, &(socks_response[5]), address_bytes + 1, 0); // address_bytes - 1 + 2... - if (recvd != address_bytes + 1) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error (2)"; - std::cerr << std::endl; -#endif - return -1; - } - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() Received String: "; - for(int i = 0; i < 4 + address_bytes + 2; i++) - std::cerr << (uint32_t) socks_response[i]; - std::cerr << std::endl; -#endif - - // should print address. - // if we get here - connection is good!. - mProxyState = PROXY_STATE_CONNECTION_COMPLETE; - return 1; - -} - diff --git a/libretroshare/src/pqi/pqiproxy.h b/libretroshare/src/pqi/pqiproxy.h deleted file mode 100644 index 6862342bb..000000000 --- a/libretroshare/src/pqi/pqiproxy.h +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiproxy.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2013 by Robert Fernie. * - * Copyright 2004-2021 by retroshare team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#pragma once - -#include - -class pqiproxyconnection -{ -public: - enum ProxyState: uint8_t { - PROXY_STATE_FAILED = 0x00, - PROXY_STATE_INIT = 0x01, - PROXY_STATE_WAITING_METHOD_RESPONSE = 0x02, - PROXY_STATE_WAITING_SOCKS_RESPONSE = 0x03, - PROXY_STATE_CONNECTION_COMPLETE = 0x04 - }; - - pqiproxyconnection() : mProxyState(PROXY_STATE_INIT) {} - - /*! - * \brief proxy_negotiate_connection - * Negotiate the connection with the proxy that is connected with openned socket sockfd. The caller needs to - * connect the socket *before* trying to call proxy_negotiate_connection(). The function must be called as many times as - * necessary until it returns 1 (success) or -1 (error) in which case the socket needs to be closed. - * \return - * -1 : error. The socket must be closed as soon as possible. - * 0 : in progress. The function needs to be called again asap. - * 1 : proxy connection is fully negociated. Client can send data to the socket. - */ - int proxy_negociate_connection(int sockfd); - - void setRemotePort(uint16_t v) { mRemotePort = v; } - void setRemoteAddress(const std::string& s) { mDomainAddress = s; } - - ProxyState proxyConnectionState() const { return mProxyState ; } - - void proxy_init() { mProxyState = PROXY_STATE_INIT; } -private: - - ProxyState mProxyState; - - std::string mDomainAddress; - uint16_t mRemotePort; - - // These are the internal steps in setting up the Proxy Connection. - int Proxy_Send_Method(int sockfd); - int Proxy_Method_Response(int sockfd); - int Proxy_Send_Address(int sockfd); - int Proxy_Connection_Complete(int sockfd); -}; - diff --git a/libretroshare/src/pqi/pqiqos.cc b/libretroshare/src/pqi/pqiqos.cc deleted file mode 100644 index 0b2b484fa..000000000 --- a/libretroshare/src/pqi/pqiqos.cc +++ /dev/null @@ -1,156 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiqos.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2008 Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include -#include -#include -#include -#include - -#include "pqiqos.h" - -const uint32_t pqiQoS::MAX_PACKET_COUNTER_VALUE = (1 << 24) ; - -pqiQoS::pqiQoS(uint32_t nb_levels,float alpha) - : _item_queues(nb_levels),_alpha(alpha) -{ -#ifdef DEBUG - assert(pow(alpha,nb_levels) < 1e+20) ; -#endif - - float c = 1.0f ; - float inc = alpha ; - _nb_items = 0 ; - _id_counter = 0 ; - -for(int i=((int)nb_levels)-1;i>=0;--i,c *= alpha) - { - _item_queues[i]._threshold = c ; - _item_queues[i]._counter = 0 ; - _item_queues[i]._inc = inc ; - } -} - -void pqiQoS::clear() -{ - void *item ; - - for(uint32_t i=0;i<_item_queues.size();++i) - while( (item = _item_queues[i].pop()) != NULL) - free(item) ; - - _nb_items = 0 ; -} - -void pqiQoS::print() const -{ - std::cerr << "pqiQoS: " << _item_queues.size() << " levels, alpha=" << _alpha ; - std::cerr << " Size = " << _nb_items ; - std::cerr << " Queues: " ; - for(uint32_t i=0;i<_item_queues.size();++i) - std::cerr << _item_queues[i]._items.size() << " " ; - std::cerr << std::endl; -} - -void pqiQoS::in_rsItem(void *ptr,int size,int priority) -{ - if(uint32_t(priority) >= _item_queues.size()) - { - std::cerr << "pqiQoS::in_rsRawItem() ****Warning****: priority " << priority << " out of scope [0," << _item_queues.size()-1 << "]. Priority will be clamped to maximum value." << std::endl; - priority = _item_queues.size()-1 ; - } - - _item_queues[priority].push(ptr,size,_id_counter++) ; - ++_nb_items ; - - if(_id_counter >= MAX_PACKET_COUNTER_VALUE) - _id_counter = 0 ; -} - -// int pqiQoS::gatherStatistics(std::vector& per_service_count,std::vector& per_priority_count) const -// { -// assert(per_priority_count.size() == 10) ; -// assert(per_service_count.size() == 65536) ; -// -// for(uint32_t i=0;i<_item_queues.size();++i) -// { -// per_priority_count[i] += _item_queues[i].size() ; -// -// for(std::list::const_iterator it(_item_queues[i]._items.begin());it!=_item_queues[i]._items.end();++it) -// { -// uint32_t type = 0; -// uint32_t offset = 0; -// getRawUInt32((uint8_t*)(*it), 4, &offset, &type); -// -// uint16_t service_id = (type >> 8) & 0xffff ; -// -// ++per_service_count[service_id] ; -// } -// } -// return 1 ; -// } - - -void *pqiQoS::out_rsItem(uint32_t max_slice_size, uint32_t& size, bool& starts, bool& ends, uint32_t& packet_id) -{ - // Go through the queues. Increment counters. - - if(_nb_items == 0) - return NULL ; - - float inc = 1.0f ; - int i = _item_queues.size()-1 ; - - while(i > 0 && _item_queues[i]._items.empty()) - --i, inc = _item_queues[i]._inc ; - - int last = i ; - - for(int j=i;j>=0;--j) - if( (!_item_queues[j]._items.empty()) && ((_item_queues[j]._counter += inc) >= _item_queues[j]._threshold )) - { - last = j ; - _item_queues[j]._counter -= _item_queues[j]._threshold ; - } - - if(last >= 0) - { -#ifdef DEBUG - assert(_nb_items > 0) ; -#endif - - // now chop a slice of this item - - void *res = _item_queues[last].slice(max_slice_size,size,starts,ends,packet_id) ; - - if(ends) - --_nb_items ; - - return res ; - } - else - return NULL ; -} - - - - - diff --git a/libretroshare/src/pqi/pqiqos.h b/libretroshare/src/pqi/pqiqos.h deleted file mode 100644 index 74ff8ba77..000000000 --- a/libretroshare/src/pqi/pqiqos.h +++ /dev/null @@ -1,179 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiqos.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2008 Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -// This class handles the prioritisation of RsItem, based on the -// priority level. The QoS algorithm must ensure that: -// -// - lower priority items get out with lower rate than high priority items -// - items of equal priority get out of the queue in the same order than they got in -// - items of level n+1 are output \alpha times more often than items of level n. -// \alpha is a constant that is not necessarily an integer, but strictly > 1. -// - the set of possible priority levels is finite, and pre-determined. -// -#pragma once - -#include -#include -#include -#include -#include -#include - -#include - -class pqiQoS -{ -public: - pqiQoS(uint32_t max_levels,float alpha) ; - - struct ItemRecord - { - void *data ; - uint32_t current_offset ; - uint32_t size ; - uint32_t id ; - }; - - class ItemQueue - { - public: - ItemQueue() - : _threshold(0.0) - , _counter(0.0) - , _inc(0.0) - {} - void *pop() - { - if(_items.empty()) - return NULL ; - - void *item = _items.front().data ; - _items.pop_front() ; - - return item ; - } - - void *slice(uint32_t max_size,uint32_t& size,bool& starts,bool& ends,uint32_t& packet_id) - { - if(_items.empty()) - return NULL ; - - ItemRecord& rec(_items.front()) ; - packet_id = rec.id ; - - // readily get rid of the item if it can be sent as a whole - - if(rec.current_offset == 0 && rec.size < max_size) - { - starts = true ; - ends = true ; - size = rec.size ; - - return pop() ; - } - starts = (rec.current_offset == 0) ; - ends = (rec.current_offset + max_size >= rec.size) ; - - if(rec.size <= rec.current_offset) - { - std::cerr << "(EE) severe error in slicing in QoS." << std::endl; - pop() ; - return NULL ; - } - - size = std::min(max_size, uint32_t((int)rec.size - (int)rec.current_offset)) ; - void *mem = rs_malloc(size) ; - - if(!mem) - { - std::cerr << "(EE) memory allocation error in QoS." << std::endl; - pop() ; - return NULL ; - } - - memcpy(mem,&((unsigned char*)rec.data)[rec.current_offset],size) ; - - if(ends) // we're taking the whole stuff. So we can delete the entry. - { - free(rec.data) ; - _items.pop_front() ; - } - else - rec.current_offset += size ; // by construction, !ends implies rec.current_offset < rec.size - - return mem ; - } - - void push(void *item,uint32_t size,uint32_t id) - { - ItemRecord rec ; - - rec.data = item ; - rec.current_offset = 0 ; - rec.size = size ; - rec.id = id ; - - _items.push_back(rec) ; - } - - uint32_t size() const { return _items.size() ; } - - float _threshold ; - float _counter ; - float _inc ; - - std::list _items ; - }; - - // This function pops items from the queue, y order of priority - // - void *out_rsItem(uint32_t max_slice_size,uint32_t& size,bool& starts,bool& ends,uint32_t& packet_id) ; - - // This function is used to queue items. - // - void in_rsItem(void *item, int size, int priority) ; - - void print() const ; - uint64_t qos_queue_size() const { return _nb_items ; } - - // kills all waiting items. - void clear() ; - - // get some stats about what's going on. service_packets will contain the number of - // packets per service, and queue_sizes will contain the size of the different priority queues. - - //int gatherStatistics(std::vector& per_service_count,std::vector& per_priority_count) const ; - - void computeTotalItemSize() const ; - int debug_computeTotalItemSize() const ; -private: - // This vector stores the lists of items with equal priorities. - // - std::vector _item_queues ; - float _alpha ; - uint64_t _nb_items ; - uint32_t _id_counter ; - - static const uint32_t MAX_PACKET_COUNTER_VALUE ; -}; - - diff --git a/libretroshare/src/pqi/pqiqosstreamer.cc b/libretroshare/src/pqi/pqiqosstreamer.cc deleted file mode 100644 index 2818b3ee7..000000000 --- a/libretroshare/src/pqi/pqiqosstreamer.cc +++ /dev/null @@ -1,85 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiqosstreamer.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012-2012 Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "pqiqosstreamer.h" - -//#define DEBUG_PQIQOSSTREAMER 1 - -const float pqiQoSstreamer::PQI_QOS_STREAMER_ALPHA = 2.0f ; - -pqiQoSstreamer::pqiQoSstreamer(PQInterface *parent, RsSerialiser *rss, const RsPeerId& peerid, BinInterface *bio_in, int bio_flagsin) - : pqithreadstreamer(parent,rss,peerid,bio_in,bio_flagsin), pqiQoS(PQI_QOS_STREAMER_MAX_LEVELS, PQI_QOS_STREAMER_ALPHA) -{ - _total_item_size = 0 ; - _total_item_count = 0 ; -} - -int pqiQoSstreamer::getQueueSize(bool in) -{ - if(in) - return pqistreamer::getQueueSize(in) ; - else - { - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - return qos_queue_size() ; - } -} - -//int pqiQoSstreamer::locked_gatherStatistics(std::vector& per_service_count,std::vector& per_priority_count) const // extracting data. -//{ -// return pqiQoS::gatherStatistics(per_service_count,per_priority_count) ; -//} - -void pqiQoSstreamer::locked_storeInOutputQueue(void *ptr,int size,int priority) -{ - _total_item_size += size ; - ++_total_item_count ; - - pqiQoS::in_rsItem(ptr,size,priority) ; -} - -void pqiQoSstreamer::locked_clear_out_queue() -{ -#ifdef DEBUG_PQIQOSSTREAMER - if(qos_queue_size() > 0) - std::cerr << " pqiQoSstreamer::locked_clear_out_queue(): clearing " << qos_queue_size() << " pending outqueue elements." << std::endl; -#endif - - pqiQoS::clear() ; - _total_item_size = 0 ; - _total_item_count = 0 ; -} - -void *pqiQoSstreamer::locked_pop_out_data(uint32_t max_slice_size, uint32_t& size, bool& starts, bool& ends, uint32_t& packet_id) -{ - void *out = pqiQoS::out_rsItem(max_slice_size,size,starts,ends,packet_id) ; - - if(out != NULL) - { - _total_item_size -= size ; - - if(ends) - --_total_item_count ; - } - - return out ; -} - diff --git a/libretroshare/src/pqi/pqiqosstreamer.h b/libretroshare/src/pqi/pqiqosstreamer.h deleted file mode 100644 index 5964b6cbe..000000000 --- a/libretroshare/src/pqi/pqiqosstreamer.h +++ /dev/null @@ -1,49 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiqosstreamer.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012-2012 Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include "pqiqos.h" -#include "pqithreadstreamer.h" - -class pqiQoSstreamer: public pqithreadstreamer, public pqiQoS -{ - public: - pqiQoSstreamer(PQInterface *parent, RsSerialiser *rss, const RsPeerId& peerid, BinInterface *bio_in, int bio_flagsin); - - static const uint32_t PQI_QOS_STREAMER_MAX_LEVELS = 10 ; - static const float PQI_QOS_STREAMER_ALPHA ; - - virtual void locked_storeInOutputQueue(void *ptr, int size, int priority) ; - virtual int locked_out_queue_size() const { return _total_item_count ; } - virtual void locked_clear_out_queue() ; - virtual int locked_compute_out_pkt_size() const { return _total_item_size ; } - virtual void *locked_pop_out_data(uint32_t max_slice_size,uint32_t& size,bool& starts,bool& ends,uint32_t& packet_id); - //virtual int locked_gatherStatistics(std::vector& per_service_count,std::vector& per_priority_count) const; // extracting data. - - - virtual int getQueueSize(bool in) ; - - private: - uint32_t _total_item_size ; - uint32_t _total_item_count ; -}; - diff --git a/libretroshare/src/pqi/pqiservice.cc b/libretroshare/src/pqi/pqiservice.cc deleted file mode 100644 index e56ad45a0..000000000 --- a/libretroshare/src/pqi/pqiservice.cc +++ /dev/null @@ -1,203 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiservice.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2013 by Robert Fernie. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "pqi/pqiservice.h" -#include "util/rsdebug.h" -#include "util/rsstring.h" - -#ifdef SERVICE_DEBUG -const int pqiservicezone = 60478; -#endif - -/**** - * #define SERVICE_DEBUG 1 - ****/ - -void pqiService::setServiceServer(p3ServiceServerIface *server) -{ - mServiceServer = server; -} - -bool pqiService::send(RsRawItem *item) -{ - return mServiceServer->sendItem(item); -} - - -p3ServiceServer::p3ServiceServer(pqiPublisher *pub, p3ServiceControl *ctrl) : mPublisher(pub), mServiceControl(ctrl), srvMtx("p3ServiceServer") -{ - RS_STACK_MUTEX(srvMtx); /********* LOCKED *********/ - -#ifdef SERVICE_DEBUG - pqioutput(PQL_DEBUG_BASIC, pqiservicezone, - "p3ServiceServer::p3ServiceServer()"); -#endif - - return; -} - -int p3ServiceServer::addService(pqiService *ts, bool defaultOn) -{ - RS_STACK_MUTEX(srvMtx); /********* LOCKED *********/ - -#ifdef SERVICE_DEBUG - pqioutput(PQL_DEBUG_BASIC, pqiservicezone, - "p3ServiceServer::addService()"); -#endif - - RsServiceInfo info = ts->getServiceInfo(); - std::map::iterator it; - it = services.find(info.mServiceType); - if (it != services.end()) - { - std::cerr << "p3ServiceServer::addService(): Service already added with id " << info.mServiceType << "!" << std::endl; - // it exists already! - return -1; - } - - ts->setServiceServer(this); - services[info.mServiceType] = ts; - - // This doesn't need to be in Mutex. - mServiceControl->registerService(info,defaultOn); - - return 1; -} - -bool p3ServiceServer::getServiceItemNames(uint32_t service_type,std::map& names) -{ - RS_STACK_MUTEX(srvMtx); /********* LOCKED *********/ - - std::map::iterator it=services.find(service_type) ; - - if(it != services.end()) - { - it->second->getItemNames(names) ; - return true ; - } - else - return false ; -} - -int p3ServiceServer::removeService(pqiService *ts) -{ - RS_STACK_MUTEX(srvMtx); /********* LOCKED *********/ - -#ifdef SERVICE_DEBUG - pqioutput(PQL_DEBUG_BASIC, pqiservicezone, "p3ServiceServer::removeService()"); -#endif - - RsServiceInfo info = ts->getServiceInfo(); - - // This doesn't need to be in Mutex. - mServiceControl->deregisterService(info.mServiceType); - - std::map::iterator it = services.find(info.mServiceType); - if (it == services.end()) - { - std::cerr << "p3ServiceServer::removeService(): Service not found with id " << info.mServiceType << "!" << std::endl; - return -1; - } - - services.erase(it); - - return 1; -} - -bool p3ServiceServer::recvItem(RsRawItem *item) -{ - // Packet Filtering. - // This doesn't need to be in Mutex. - if (!mServiceControl->checkFilter(item->PacketId() & 0xffffff00, item->PeerId())) - { - delete item; - return false; - } - - pqiService *s = NULL; - - // access the service map under mutex lock - { - RS_STACK_MUTEX(srvMtx); - auto it = services.find(item -> PacketId() & 0xffffff00); - if (it == services.end()) - { - delete item; - return false; - } - s = it->second; - } - - // then call recv off mutex - bool result = s->recv(item); - return result; -} - -bool p3ServiceServer::sendItem(RsRawItem *item) -{ -#ifdef SERVICE_DEBUG - std::cerr << "p3ServiceServer::sendItem()"; - std::cerr << std::endl; - item -> print(std::cerr); - std::cerr << std::endl; -#endif - if (!item) - { - std::cerr << "p3ServiceServer::sendItem() Caught Null item"; - std::cerr << std::endl; - return false; - } - - // Packet Filtering. - if (!mServiceControl->checkFilter(item->PacketId() & 0xffffff00, item->PeerId())) - { -#ifdef SERVICE_DEBUG - std::cerr << "p3ServiceServer::sendItem() Fails Filtering for packet id=" << std::hex << item->PacketId() << std::dec << ", and peer " << item->PeerId() << std::endl; -#endif - delete item; - return false; - } - - mPublisher->sendItem(item); - - return true; -} - -int p3ServiceServer::tick() -{ - mServiceControl->tick(); - - // make a copy of the service map - std::map local_map; - { - RS_STACK_MUTEX(srvMtx); - local_map=services; - } - - // tick all services off mutex - for(auto it(local_map.begin());it!=local_map.end();++it) - { - (it->second)->tick(); - } - - return 1; - -} diff --git a/libretroshare/src/pqi/pqiservice.h b/libretroshare/src/pqi/pqiservice.h deleted file mode 100644 index ad983266e..000000000 --- a/libretroshare/src/pqi/pqiservice.h +++ /dev/null @@ -1,130 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiservice.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef PQI_SERVICE_HEADER -#define PQI_SERVICE_HEADER - -#include "pqi/pqi.h" -#include "pqi/pqi_base.h" -#include "util/rsthreads.h" - -#include "retroshare/rsservicecontrol.h" -#include "pqi/p3servicecontrol.h" - -// PQI Service, is a generic lower layer on which services can run on. -// -// these packets get passed through the -// server, to a service that is registered. -// -// example services: -// proxytunnel. -> p3proxy. -// sockettunnel -// -> either broadcast (attach to -// open socket instead -// of broadcast address) -// -> or requested/signon. -// -// games, -// voice -// video -// -// -// DataType is defined in the serialiser directory. - -class RsRawItem; -class p3ServiceServerIface; - - -class pqiService -{ -protected: - - pqiService() // our type of packets. - :mServiceServer(NULL) { return; } - - virtual ~pqiService() { return; } - -public: - void setServiceServer(p3ServiceServerIface *server); - // - virtual bool recv(RsRawItem *) = 0; - virtual bool send(RsRawItem *item); - - virtual RsServiceInfo getServiceInfo() = 0; - - virtual int tick() { return 0; } - - virtual void getItemNames(std::map& /*names*/) const {} // This does nothing by default. Service should derive it in order to give info for the UI - -private: - p3ServiceServerIface *mServiceServer; // const, no need for mutex. -}; - -#include - -/* We are pushing the packets back through p3ServiceServer, - * so that we can filter services at this level later... - * if we decide not to do this, pqiService can call through - * to the base level pqiPublisher instead. - */ - -// use interface to allow DI -class p3ServiceServerIface -{ -public: - - virtual ~p3ServiceServerIface() {} - - - virtual bool recvItem(RsRawItem *) = 0; - virtual bool sendItem(RsRawItem *) = 0; - - virtual bool getServiceItemNames(uint32_t service_type,std::map& names) =0; -}; - -class p3ServiceServer : public p3ServiceServerIface -{ -public: - p3ServiceServer(pqiPublisher *pub, p3ServiceControl *ctrl); - - int addService(pqiService *, bool defaultOn); - int removeService(pqiService *); - - bool recvItem(RsRawItem *); - bool sendItem(RsRawItem *); - - bool getServiceItemNames(uint32_t service_type, std::map& names) ; - - int tick(); -public: - -private: - - pqiPublisher *mPublisher; // constant no need for mutex. - p3ServiceControl *mServiceControl; - - RsMutex srvMtx; - std::map services; - -}; - - -#endif // PQI_SERVICE_HEADER diff --git a/libretroshare/src/pqi/pqiservicemonitor.h b/libretroshare/src/pqi/pqiservicemonitor.h deleted file mode 100644 index c101feac4..000000000 --- a/libretroshare/src/pqi/pqiservicemonitor.h +++ /dev/null @@ -1,61 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiservicemonitor.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef PQI_SERVICE_MONITOR_H -#define PQI_SERVICE_MONITOR_H - -#include -#include -#include -#include - -/* ACTIONS */ -const uint32_t RS_SERVICE_PEER_NEW = 0x0001; /* new Peer */ -const uint32_t RS_SERVICE_PEER_CONNECTED = 0x0002; /* service connected */ -const uint32_t RS_SERVICE_PEER_DISCONNECTED = 0x0010; -const uint32_t RS_SERVICE_PEER_REMOVED = 0x0020; - -class pqiServicePeer -{ - public: - RsPeerId id; - uint32_t actions; -}; - - -class pqiServiceMonitor -{ - public: - pqiServiceMonitor() { return; } -virtual ~pqiServiceMonitor() { return; } - - /*! - * this serves as a call back function for server which has - * a handle on the subclass and updates this subclass on the - * action of peer's of the client (state and action information) - * - *@param plist contains list of states and actions of the client's peers - */ -virtual void statusChange(const std::list &plist) = 0; -}; - -#endif // PQI_SERVICE_MONITOR_H diff --git a/libretroshare/src/pqi/pqissl.cc b/libretroshare/src/pqi/pqissl.cc deleted file mode 100644 index 6a455dfeb..000000000 --- a/libretroshare/src/pqi/pqissl.cc +++ /dev/null @@ -1,1884 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqissl.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * Copyright (C) 2015-2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "pqi/pqissl.h" -#include "pqi/pqinetwork.h" -#include "pqi/sslfns.h" - -#include "util/rsnet.h" -#include "util/rsdebug.h" -#include "util/rsstring.h" - -#include -#include -#include - -#include "pqi/pqissllistener.h" - -#include "pqi/p3linkmgr.h" -#include "retroshare/rspeers.h" -#include -#include - -#include "rsserver/p3face.h" - -static struct RsLog::logInfo pqisslzoneInfo = {RsLog::Default, "pqisslzone"}; -#define pqisslzone &pqisslzoneInfo - -/********* -#define WAITING_NOT 0 -#define WAITING_LOCAL_ADDR 1 -#define WAITING_REMOTE_ADDR 2 -#define WAITING_SOCK_CONNECT 3 -#define WAITING_SSL_CONNECTION 4 -#define WAITING_SSL_AUTHORISE 5 -#define WAITING_FAIL_INTERFACE 6 - -#define PQISSL_PASSIVE 0x00 -#define PQISSL_ACTIVE 0x01 - -const int PQISSL_LOCAL_FLAG = 0x01; -const int PQISSL_REMOTE_FLAG = 0x02; -const int PQISSL_UDP_FLAG = 0x02; -***********/ - -//#define PQISSL_DEBUG 1 -//#define PQISSL_LOG_DEBUG 1 -//#define PQISSL_LOG_DEBUG2 1 - -static const int PQISSL_MAX_READ_ZERO_COUNT = 20; -static const rstime_t PQISSL_MAX_READ_ZERO_TIME = 15; // 15 seconds of no data => reset. (atm HeartBeat pkt sent 5 secs) - -static const int PQISSL_SSL_CONNECT_TIMEOUT = 30; - -/********** PQI SSL STUFF ****************************************** - * - * A little note on the notifyEvent(FAILED).... - * - * this is called from - * (1) reset if needed! - * (2) Determine_Remote_Address (when all options have failed). - * - * reset() is only called when a TCP/SSL connection has been - * established, and there is an error. If there is a failed TCP - * connection, then an alternative address can be attempted. - * - * reset() is called from - * (1) destruction. - * (2) disconnect() - * (3) bad waiting state. - * - * // TCP/or SSL connection already established.... - * (5) pqissl::SSL_Connection_Complete() <- okay -> cos we made a TCP connection already. - * (6) pqissl::accept() <- okay cos something went wrong. - * (7) moretoread()/cansend() <- okay cos - * - */ - -pqissl::pqissl(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm) : - NetBinInterface(parent, parent->PeerId()), - mLinkMgr(lm), pqil(l), mSslMtx("pqissl"), active(false), certvalid(false), - waiting(WAITING_NOT), sslmode(PQISSL_ACTIVE), ssl_connection(NULL), - sockfd(-1), readpkt(NULL), pktlen(0), total_len(0), attempt_ts(0), - n_read_zero(0), mReadZeroTS(0), ssl_connect_timeout(0), mConnectDelay(0), - mConnectTS(0), mConnectTimeout(0), mTimeoutTS(0) -{ sockaddr_storage_clear(remote_addr); } - - pqissl::~pqissl() -{ - rslog(RSL_ALERT, pqisslzone, - "pqissl::~pqissl -> destroying pqissl"); - stoplistening(); /* remove from pqissllistener only */ - - rslog(RSL_ALERT, pqisslzone, "pqissl::~pqissl() -> calling reset()"); - reset(); - return; -} - - -/********** Implementation of NetInterface *************************/ - -int pqissl::connect(const struct sockaddr_storage &raddr) -{ - RS_STACK_MUTEX(mSslMtx); - - remote_addr = raddr; - return ConnectAttempt(); -} - -// tells pqilistener to listen for us. -int pqissl::listen() -{ - if (pqil) - { - return pqil -> addlistenaddr(PeerId(), this); - } - return 0; -} - -int pqissl::stoplistening() -{ - if (pqil) - { - pqil -> removeListenPort(PeerId()); - } - return 1; -} - -int pqissl::disconnect() -{ - rslog(RSL_ALERT, pqisslzone, "pqissl::disconnect() -> calling reset()"); - return reset(); -} - -int pqissl::getConnectAddress(struct sockaddr_storage &raddr) -{ - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - - raddr = remote_addr; - // TODO. - return (!sockaddr_storage_isnull(remote_addr)); -} - -/* BinInterface version of reset() for pqistreamer */ -int pqissl::close() -{ - rslog(RSL_ALERT, pqisslzone, "pqissl::close() -> calling reset()"); - return reset(); -} - -// put back on the listening queue. -int pqissl::reset() -{ - RS_STACK_MUTEX(mSslMtx); - return reset_locked(); -} - -int pqissl::reset_locked() -{ - std::string outLog; - bool neededReset = false; - - - /* a reset shouldn't cause us to stop listening - * only reasons for stoplistening() are; - * - * (1) destruction. - * (2) connection. - * (3) WillListen state change - * - */ - - outLog += "pqissl::reset():" + PeerId().toStdString(); - rs_sprintf_append(outLog, " (A: %d", (int) active); - rs_sprintf_append(outLog, " FD: %d", sockfd); - rs_sprintf_append(outLog, " W: %d", waiting); - rs_sprintf_append(outLog, " SSL: %p) ", ssl_connection); -#ifdef PQISSL_LOG_DEBUG - outLog += "\n"; -#endif - - - if (ssl_connection != NULL) - { - //outLog << "pqissl::reset() Shutting down SSL Connection"; - //outLog << std::endl; - SSL_shutdown(ssl_connection); - SSL_free (ssl_connection); - - neededReset = true; - } - - if (sockfd > 0) - { -#ifdef PQISSL_LOG_DEBUG - outLog += "pqissl::reset() Shutting down (active) socket\n"; -#endif - net_internal_close(sockfd); - sockfd = -1; - neededReset = true; - } - active = false; - sockfd = -1; - waiting = WAITING_NOT; - ssl_connection = NULL; - n_read_zero = 0; - mReadZeroTS = 0; - total_len = 0 ; - mTimeoutTS = 0; - - if (neededReset) - { -#ifdef PQISSL_LOG_DEBUG - outLog += "pqissl::reset() Reset Required!\n"; - outLog += "pqissl::reset() Will Attempt notifyEvent(FAILED)\n"; -#endif - } - -#ifdef PQISSL_LOG_DEBUG2 - rslog(RSL_ALERT, pqisslzone, outLog); -#endif - - // notify people of problem! - // but only if we really shut something down. - if (neededReset) - { - // clean up the streamer - if (parent()) - { - struct sockaddr_storage addr; - sockaddr_storage_clear(addr); - parent() -> notifyEvent(this, NET_CONNECT_FAILED, addr); - } - } - return 1; -} - -bool pqissl::connect_parameter(uint32_t type, uint32_t value) -{ -#ifdef PQISSL_LOG_DEBUG - std::cerr << "pqissl::connect_parameter() Peer: " << PeerId(); -#endif - - switch(type) - { - case NET_PARAM_CONNECT_DELAY: - { -#ifdef PQISSL_LOG_DEBUG - std::cerr << " DELAY: " << value << std::endl; -#endif - RS_STACK_MUTEX(mSslMtx); - mConnectDelay = value; - return true; - } - case NET_PARAM_CONNECT_TIMEOUT: - { -#ifdef PQISSL_LOG_DEBUG - std::cerr << " TIMEOUT: " << value << std::endl; -#endif - RS_STACK_MUTEX(mSslMtx); - mConnectTimeout = value; - return true; - } - default: - { -#ifdef PQISSL_LOG_DEBUG - std::cerr << " type: " << type << " value: " << value << std::endl; -#endif - return false; - } - } -} - - -/********** End of Implementation of NetInterface ******************/ -/********** Implementation of BinInterface ************************** - * Only status() + tick() are here ... as they are really related - * to the NetInterface, and not the BinInterface, - * - */ - -void pqissl::getCryptoParams(RsPeerCryptoParams& params) -{ - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - - if(active) - { - params.connexion_state = 1 ; - - char *desc = SSL_CIPHER_description(SSL_get_current_cipher(ssl_connection), NULL, 0); - params.cipher_name = std::string(desc); - OPENSSL_free(desc); - } - else - { - params.connexion_state = 0 ; - params.cipher_name.clear() ; - } -} - -bool pqissl::actAsServer() -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - return (bool)ssl_connection->server; -#else - return (bool)SSL_is_server(ssl_connection); -#endif -} - -/* returns ... - * -1 if inactive. - * 0 if connecting. - * 1 if connected. - */ - -int pqissl::status() -{ - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - -#ifdef PQISSL_LOG_DEBUG - std::string out = "pqissl::status()"; - - if (active) - { - int alg; - - out += " active: \n"; - // print out connection. - out += "Connected TO : " + PeerId().toStdString() + "\n"; - // print out cipher. - rs_sprintf_append(out, "\t\tSSL Cipher:%s", SSL_get_cipher(ssl_connection)); - rs_sprintf_append(out, " (%d:%d)", SSL_get_cipher_bits(ssl_connection, &alg), alg); - rs_sprintf_append(out, "Vers:%s\n\n", SSL_get_cipher_version(ssl_connection)); - } - else - { - out += " Waiting for connection!\n"; - } - - rslog(RSL_DEBUG_BASIC, pqisslzone, out); -#endif - - if (active) - { - return 1; - } - else if (waiting > 0) - { - return 0; - } - return -1; -} - - // tick...... -int pqissl::tick() -{ - // there is no reason to lock pqissl mutex now - // we will lock the mutex later if we actually need to call to ConnectAttempt - // RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - - // pqistreamer::tick(); - - // continue existing connection attempt. - if (!active) - { - // if we are waiting.. continue the connection (only) - if (waiting > 0) - { -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, "pqissl::tick() Continuing Connection Attempt!"); -#endif - // now lock pqissl mutex, that will take up to 10 ms - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - ConnectAttempt(); - return 1; - } - } - return 1; -} - -/********** End of Implementation of BinInterface ******************/ -/********** Internals of SSL Connection ****************************/ - - -int pqissl::ConnectAttempt() -{ - switch(waiting) - { - case WAITING_NOT: - - sslmode = PQISSL_ACTIVE; /* we're starting this one */ - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::ConnectAttempt() STATE = Not Waiting, starting connection"); -#endif - /* fallthrough */ - case WAITING_DELAY: - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::ConnectAttempt() STATE = Waiting Delay, starting connection"); -#endif - - return Delay_Connection(); - //return Initiate_Connection(); /* now called by Delay_Connection() */ - - break; - - case WAITING_SOCK_CONNECT: - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::ConnectAttempt() STATE = Waiting Sock Connect"); -#endif - - return Initiate_SSL_Connection(); - break; - - case WAITING_SSL_CONNECTION: - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::ConnectAttempt() STATE = Waiting SSL Connection"); -#endif - - return Authorise_SSL_Connection(); - break; - - case WAITING_SSL_AUTHORISE: - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::ConnectAttempt() STATE = Waiting SSL Authorise"); -#endif - - return Authorise_SSL_Connection(); - break; - case WAITING_FAIL_INTERFACE: - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::ConnectAttempt() Failed - Retrying"); -#endif - - return Failed_Connection(); - break; - - - default: - rslog(RSL_ALERT, pqisslzone, - "pqissl::ConnectAttempt() STATE = Unknown - calling reset()"); - - reset_locked(); - break; - } - rslog(RSL_ALERT, pqisslzone, "pqissl::ConnectAttempt() Unknown"); - - return -1; -} - - -/****************************** FAILED ATTEMPT ****************************** - * Determine the Remote Address. - * - * Specifics: - * TCP / UDP - * TCP - check for which interface to use. - * UDP - check for request proxies.... - * - * X509 / XPGP - Same. - * - */ - -int pqissl::Failed_Connection() -{ -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::ConnectAttempt() Failed - Notifying"); -#endif - - if (parent()) - { - struct sockaddr_storage addr; - sockaddr_storage_clear(addr); - parent() -> notifyEvent(this, NET_CONNECT_UNREACHABLE, addr); - } - - waiting = WAITING_NOT; - - return 1; -} - -/****************************** MAKE CONNECTION ***************************** - * Open Socket and Initiate Connection. - * - * Specifics: - * TCP / UDP - * TCP - socket()/connect() - * UDP - tou_socket()/tou_connect() - * - * X509 / XPGP - Same. - * - */ - -int pqissl::Delay_Connection() -{ -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Delay_Connection() Attempting Outgoing Connection...."); -#endif - - if (waiting == WAITING_NOT) - { - waiting = WAITING_DELAY; - - /* we cannot just jump to Initiate_Connection, - * but must switch to WAITING_DELAY for at least one cycle. - * to avoid deadlock between threads.... - * ie. so the connection stuff is called from tick(), rather than connect() - */ - - /* set Connection TS. - */ -#ifdef PQISSL_LOG_DEBUG - { - std::string out; - rs_sprintf(out, "pqissl::Delay_Connection() Delaying Connection to %s for %lu seconds", PeerId().toStdString(), mConnectDelay); - rslog(RSL_DEBUG_BASIC, pqisslzone, out); - } -#endif - - mConnectTS = time(NULL) + mConnectDelay; - return 0; - } - else if (waiting == WAITING_DELAY) - { -#ifdef PQISSL_LOG_DEBUG - { - std::string out; - rs_sprintf(out, "pqissl::Delay_Connection() Connection to %s starting in %ld seconds", PeerId().toStdString(), mConnectTS - time(NULL)); - rslog(RSL_DEBUG_BASIC, pqisslzone, out); - } -#endif - if (time(NULL) >= mConnectTS) - { - return Initiate_Connection(); - } - return 0; - } - - rslog(RSL_WARNING, pqisslzone, - "pqissl::Delay_Connection() Already Attempt in Progress!"); - return -1; -} - - -int pqissl::Initiate_Connection() -{ -#ifdef PQISSL_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " " - << sockaddr_storage_tostring(remote_addr) << std::endl; -#endif - - int err; - sockaddr_storage addr; sockaddr_storage_copy(remote_addr, addr); - - if(waiting != WAITING_DELAY) - { - std::cerr << __PRETTY_FUNCTION__ << " Already Attempt in Progress!" - << std::endl; - return -1; - } - - // open socket connection to addr. - int osock = unix_socket(PF_INET6, SOCK_STREAM, 0); - -#ifdef PQISSL_LOG_DEBUG - { - std::string out; - rs_sprintf(out, "pqissl::Initiate_Connection() osock = %d", osock); - rslog(RSL_DEBUG_BASIC, pqisslzone, out); - } -#endif - - if (osock < 0) - { - std::string out = "pqissl::Initiate_Connection() Failed to open socket!\n"; - out += "Socket Error:" + socket_errorType(errno); - rslog(RSL_WARNING, pqisslzone, out); - - net_internal_close(osock); - waiting = WAITING_FAIL_INTERFACE; - return -1; - } - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Initiate_Connection() Making Non-Blocking"); -#endif - - err = unix_fcntl_nonblock(osock); - if (err < 0) - { - std::string out; - rs_sprintf(out, "pqissl::Initiate_Connection() Error: Cannot make socket NON-Blocking: %d", err); - rslog(RSL_WARNING, pqisslzone, out); - - waiting = WAITING_FAIL_INTERFACE; - net_internal_close(osock); - return -1; - } - - if (sockaddr_storage_isnull(addr)) - { - rslog(RSL_WARNING, pqisslzone, "pqissl::Initiate_Connection() Invalid (0.0.0.0) Remote Address, Aborting Connect."); - waiting = WAITING_FAIL_INTERFACE; - net_internal_close(osock); - return -1; - } - -#ifdef WINDOWS_SYS - /* Set TCP buffer size for Windows systems */ - - int sockbufsize = 0; - int size = sizeof(int); - - err = getsockopt(osock, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, &size); -#ifdef PQISSL_DEBUG - if (err == 0) { - std::cerr << "pqissl::Initiate_Connection: Current TCP receive buffer size " << sockbufsize << std::endl; - } else { - std::cerr << "pqissl::Initiate_Connection: Error getting TCP receive buffer size. Error " << err << std::endl; - } -#endif - - sockbufsize = 0; - - err = getsockopt(osock, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, &size); -#ifdef PQISSL_DEBUG - if (err == 0) { - std::cerr << "pqissl::Initiate_Connection: Current TCP send buffer size " << sockbufsize << std::endl; - } else { - std::cerr << "pqissl::Initiate_Connection: Error getting TCP send buffer size. Error " << err << std::endl; - } -#endif - - sockbufsize = WINDOWS_TCP_BUFFER_SIZE; - - err = setsockopt(osock, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, sizeof(sockbufsize)); -#ifdef PQISSL_DEBUG - if (err == 0) { - std::cerr << "pqissl::Initiate_Connection: TCP receive buffer size set to " << sockbufsize << std::endl; - } else { - std::cerr << "pqissl::Initiate_Connection: Error setting TCP receive buffer size. Error " << err << std::endl; - } -#endif - - err = setsockopt(osock, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, sizeof(sockbufsize)); -#ifdef PQISSL_DEBUG - if (err == 0) { - std::cerr << "pqissl::Initiate_Connection: TCP send buffer size set to " << sockbufsize << std::endl; - } else { - std::cerr << "pqissl::Initiate_Connection: Error setting TCP send buffer size. Error " << err << std::endl; - } -#endif -#endif // WINDOWS_SYS - - /* Systems that supports dual stack sockets defines IPV6_V6ONLY and some set - * it to 1 by default. This enable dual stack socket on such systems. - * Systems which don't support dual stack (only Windows older then XP SP3) - * will support IPv6 only and not IPv4 */ -#ifdef IPV6_V6ONLY - int no = 0; - err = rs_setsockopt( osock, IPPROTO_IPV6, IPV6_V6ONLY, - reinterpret_cast(&no), sizeof(no) ); -#ifdef PQISSL_DEBUG - if (err) std::cerr << __PRETTY_FUNCTION__ - << " Error setting IPv6 socket dual stack: " - << errno << " " << strerror(errno) << std::endl; - else std::cerr << __PRETTY_FUNCTION__ - << " Setting IPv6 socket dual stack" << std::endl; -#endif // PQISSL_DEBUG -#endif // IPV6_V6ONLY - - mTimeoutTS = time(NULL) + mConnectTimeout; - //std::cerr << "Setting Connect Timeout " << mConnectTimeout << " Seconds into Future " << std::endl; - - sockaddr_storage_ipv4_to_ipv6(addr); -#ifdef PQISSL_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " Connecting To: " - << PeerId().toStdString() <<" via: " - << sockaddr_storage_tostring(addr) << std::endl; -#endif - - if (0 != (err = unix_connect(osock, addr))) - { - switch (errno) - { - case EINPROGRESS: - waiting = WAITING_SOCK_CONNECT; - sockfd = osock; - return 0; - default: -#ifdef PQISSL_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " Failure connect " - << sockaddr_storage_tostring(addr) - << " returns: " - << err << " -> errno: " << errno << " " - << socket_errorType(errno) << std::endl; -#endif - - net_internal_close(osock); - osock = -1; - waiting = WAITING_FAIL_INTERFACE; - return -1; - } - } - - waiting = WAITING_SOCK_CONNECT; - sockfd = osock; - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Initiate_Connection() Waiting for Socket Connect"); -#endif - - return 1; -} - - -/****************************** CHECK SOCKET ***************************** - * Check the Socket. - * - * select() and getsockopt(). - * - * Specifics: - * TCP / UDP - * TCP - select()/getsockopt() - * UDP - tou_error() - * - * X509 / XPGP - Same. - * - */ - -bool pqissl::CheckConnectionTimeout() -{ - /* new TimeOut code. */ - if (time(NULL) > mTimeoutTS) - { - std::string out; - rs_sprintf(out, "pqissl::Basic_Connection_Complete() Connection Timed Out. Peer: %s Period: %lu", PeerId().toStdString().c_str(), mConnectTimeout); - -#ifdef PQISSL_LOG_DEBUG2 - rslog(RSL_WARNING, pqisslzone, out); -#endif - /* as sockfd is valid, this should close it all up */ - -#ifdef PQISSL_LOG_DEBUG2 - rslog(RSL_ALERT, pqisslzone, "pqissl::Basic_Connection_Complete() -> calling reset()"); -#endif - reset_locked(); - return true; - } - return false; -} - - - -int pqissl::Basic_Connection_Complete() -{ -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Basic_Connection_Complete()..."); -#endif - - if (CheckConnectionTimeout()) - { - // calls reset. - return -1; - } - - if (waiting != WAITING_SOCK_CONNECT) - { - rslog(RSL_ALERT, pqisslzone, - "pqissl::Basic_Connection_Complete() Wrong Mode"); - return -1; - } - - if (sockfd == -1) - { - rslog(RSL_ALERT, pqisslzone, - "pqissl::Basic_Connection_Complete() problem with the socket descriptor. Aborting"); - rslog(RSL_ALERT, pqisslzone, "pqissl::Basic_Connection_Complete() -> calling reset()"); - reset_locked(); - return -1; - } - - // use select on the opened socket. - // Interestingly - This code might be portable.... - - fd_set ReadFDs, WriteFDs, ExceptFDs; - FD_ZERO(&ReadFDs); - FD_ZERO(&WriteFDs); - FD_ZERO(&ExceptFDs); - - FD_SET(sockfd, &ReadFDs); - FD_SET(sockfd, &WriteFDs); - FD_SET(sockfd, &ExceptFDs); - - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 0; - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Basic_Connection_Complete() Selecting ...."); -#endif - - int sr = 0; - if (0 > (sr = select(sockfd + 1, - &ReadFDs, &WriteFDs, &ExceptFDs, &timeout))) - { - // select error. - rslog(RSL_WARNING, pqisslzone, - "pqissl::Basic_Connection_Complete() Select ERROR(1)"); - - net_internal_close(sockfd); - sockfd=-1; - //reset(); - waiting = WAITING_FAIL_INTERFACE; - return -1; - } - -#ifdef PQISSL_LOG_DEBUG - { - std::string out; - rs_sprintf(out, "pqissl::Basic_Connection_Complete() Select returned %d", sr); - rslog(RSL_DEBUG_BASIC, pqisslzone, out); - } -#endif - - - if (FD_ISSET(sockfd, &ExceptFDs)) - { - // error - reset socket. - // this is a definite bad socket!. -#ifdef PQISSL_LOG_DEBUG2 - rslog(RSL_WARNING, pqisslzone, - "pqissl::Basic_Connection_Complete() Select ERROR(2)"); -#endif - net_internal_close(sockfd); - sockfd=-1; - //reset(); - waiting = WAITING_FAIL_INTERFACE; - return -1; - } - - if (FD_ISSET(sockfd, &WriteFDs)) - { -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Basic_Connection_Complete() Can Write!"); -#endif - } - else - { -#ifdef PQISSL_LOG_DEBUG - // happens frequently so switched to debug msg. - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Basic_Connection_Complete() Not Yet Ready!"); -#endif - return 0; - } - - if (FD_ISSET(sockfd, &ReadFDs)) - { -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Basic_Connection_Complete() Can Read!"); -#endif - } - else - { -#ifdef PQISSL_LOG_DEBUG - // not ready return -1; - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Basic_Connection_Complete() Cannot Read!"); -#endif - } - - int err = 1; - if (0==unix_getsockopt_error(sockfd, &err)) - { - if (err == 0) - { - { - std::string out; - rs_sprintf(out, "pqissl::Basic_Connection_Complete() TCP Connection Complete: cert: %s on osock: ", PeerId().toStdString().c_str(), sockfd); -#ifdef PQISSL_LOG_DEBUG2 - rslog(RSL_WARNING, pqisslzone, out); -#endif - } - return 1; - } - else if (err == EINPROGRESS) - { - rslog(RSL_WARNING, pqisslzone, "pqissl::Basic_Connection_Complete() EINPROGRESS: cert: " + PeerId().toStdString()); - - return 0; - } - else if ((err == ENETUNREACH) || (err == ETIMEDOUT)) - { - rslog(RSL_WARNING, pqisslzone, "pqissl::Basic_Connection_Complete() ENETUNREACH/ETIMEDOUT: cert: " + PeerId().toStdString()); - - // Then send unreachable message. - net_internal_close(sockfd); - sockfd=-1; - //reset(); - - waiting = WAITING_FAIL_INTERFACE; - - return -1; - } - else if ((err == EHOSTUNREACH) || (err == EHOSTDOWN)) - { -#ifdef PQISSL_DEBUG - rslog(RSL_WARNING, pqisslzone, "pqissl::Basic_Connection_Complete() EHOSTUNREACH/EHOSTDOWN: cert: " + PeerId().toStdString()); -#endif - // Then send unreachable message. - net_internal_close(sockfd); - sockfd=-1; - //reset(); - waiting = WAITING_FAIL_INTERFACE; - - return -1; - } - else if (err == ECONNREFUSED) - { -#ifdef PQISSL_DEBUG - rslog(RSL_WARNING, pqisslzone, "pqissl::Basic_Connection_Complete() ECONNREFUSED: cert: " + PeerId().toStdString()); -#endif - - // Then send unreachable message. - net_internal_close(sockfd); - sockfd=-1; - //reset(); - waiting = WAITING_FAIL_INTERFACE; - - return -1; - } - - std::string out; - rs_sprintf(out, "Error: Connection Failed UNKNOWN ERROR: %d - %s", err, socket_errorType(err).c_str()); - rslog(RSL_WARNING, pqisslzone, out); - - net_internal_close(sockfd); - sockfd=-1; - //reset(); // which will send Connect Failed, - return -1; - } - - rslog(RSL_ALERT, pqisslzone, - "pqissl::Basic_Connection_Complete() BAD GETSOCKOPT!"); - waiting = WAITING_FAIL_INTERFACE; - - return -1; -} - - -int pqissl::Initiate_SSL_Connection() -{ - int err; - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Initiate_SSL_Connection() Checking Basic Connection"); -#endif - - if (0 >= (err = Basic_Connection_Complete())) - { - return err; - } - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Initiate_SSL_Connection() Basic Connection Okay"); -#endif - - // setup timeout value. - ssl_connect_timeout = time(NULL) + PQISSL_SSL_CONNECT_TIMEOUT; - - // Perform SSL magic. - // library already inited by sslroot(). - SSL *ssl = SSL_new(AuthSSL::getAuthSSL()->getCTX()); - if (ssl == NULL) - { - rslog(RSL_ALERT, pqisslzone, - "pqissl::Initiate_SSL_Connection() SSL_new failed!"); - - exit(1); - return -1; - } - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Initiate_SSL_Connection() SSL Connection Okay"); -#endif - - if(ssl_connection != NULL) - { - SSL_shutdown(ssl_connection); - SSL_free(ssl_connection) ; - } - - ssl_connection = ssl; - - net_internal_SSL_set_fd(ssl, sockfd); - if (err < 1) - { - std::string out = "pqissl::Initiate_SSL_Connection() SSL_set_fd failed!\n"; - printSSLError(ssl, err, SSL_get_error(ssl, err), ERR_get_error(), out); - - rslog(RSL_ALERT, pqisslzone, out); - } - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Initiate_SSL_Connection() Waiting for SSL Connection"); -#endif - - waiting = WAITING_SSL_CONNECTION; - return 1; -} - -int pqissl::SSL_Connection_Complete() -{ -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::SSL_Connection_Complete()??? ... Checking"); -#endif - - if (waiting == WAITING_SSL_AUTHORISE) - { - rslog(RSL_ALERT, pqisslzone, - "pqissl::SSL_Connection_Complete() Waiting = W_SSL_AUTH"); - - return 1; - } - if (waiting != WAITING_SSL_CONNECTION) - { - rslog(RSL_ALERT, pqisslzone, - "pqissl::SSL_Connection_Complete() Still Waiting.."); - - return -1; - } - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::SSL_Connection_Complete() Attempting SSL_connect"); -#endif - - /* if we are passive - then accept! */ - int err; - - if (sslmode == PQISSL_ACTIVE) - { -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, "--------> Active Connect! Client side."); -#endif - err = SSL_connect(ssl_connection); - } - else - { -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, "--------> Passive Accept! Server side."); -#endif - err = SSL_accept(ssl_connection); - } - - if (err != 1) - { - int serr = SSL_get_error(ssl_connection, err); - if ((serr == SSL_ERROR_WANT_READ) || (serr == SSL_ERROR_WANT_WRITE)) - { -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "Waiting for SSL handshake!"); -#endif - - waiting = WAITING_SSL_CONNECTION; - return 0; - } - - if(rsEvents) - { - X509 *x509 = SSL_get_peer_certificate(ssl_connection); - - if(x509) - { - auto ev = std::make_shared(); - ev->mSslId = RsX509Cert::getCertSslId(*x509); - ev->mErrorCode = RsAuthSslError::PEER_REFUSED_CONNECTION; - - if(!ev->mSslId.isNull()) - rsEvents->postEvent(ev); - } - } - - std::string out; - rs_sprintf(out, "pqissl::SSL_Connection_Complete()\nIssues with SSL Connect(%d)!\n", err); - printSSLError(ssl_connection, err, serr, ERR_get_error(), out); - - rslog(RSL_WARNING, pqisslzone, out); - - rslog(RSL_ALERT, pqisslzone, "pqissl::SSL_Connection_Complete() -> calling reset()"); - reset_locked(); - waiting = WAITING_FAIL_INTERFACE; - - return -1; - } - // if we get here... success v quickly. - - rslog(RSL_WARNING, pqisslzone, "pqissl::SSL_Connection_Complete() Success!: Peer: " + PeerId().toStdString()); - - waiting = WAITING_SSL_AUTHORISE; - return 1; -} - -int pqissl::Authorise_SSL_Connection() -{ - Dbg3() << __PRETTY_FUNCTION__ << std::endl; - - constexpr int failure = -1; - - if (time(nullptr) > ssl_connect_timeout) - { - RsInfo() << __PRETTY_FUNCTION__ << " Connection timed out reset!" - << std::endl; - reset_locked(); - } - - int err; - if (0 >= (err = SSL_Connection_Complete())) return err; - - Dbg3() << __PRETTY_FUNCTION__ << "SSL_Connection_Complete success." - << std::endl; - - // reset switch. - waiting = WAITING_NOT; - -#ifdef RS_PQISSL_AUTH_DOUBLE_CHECK - X509* peercert = SSL_get_peer_certificate(ssl_connection); - if (!peercert) - { - RsFatal() << __PRETTY_FUNCTION__ << " failed to retrieve peer " - << "certificate at this point this should never happen!" - << std::endl; - print_stacktrace(); - exit(failure); - } - - RsPeerId certPeerId = RsX509Cert::getCertSslId(*peercert); - if (RsPeerId(certPeerId) != PeerId()) - { - RsErr() << __PRETTY_FUNCTION__ << " the cert Id doesn't match the peer " - << "id we're trying to connect to." << std::endl; - - /* TODO: Considering how difficult is managing to get a connection to a - * friend nowadays on the Internet because of evil NAT everywhere. - * If the cert is from a friend anyway we should find a way to make good - * use of this connection instead of throwing it away... */ - - X509_free(peercert); - reset_locked(); - return failure; - } - - /* At this point the actual connection authentication has already been - * performed in AuthSSL::VerifyX509Callback, any furter authentication check - * like the followings are redundant. */ - - bool isSslOnlyFriend = rsPeers->isSslOnlyFriend(certPeerId); - - uint32_t authErrCode = 0; - if( !isSslOnlyFriend && !AuthSSL::instance().AuthX509WithGPG(peercert,false, authErrCode) ) - { - RsFatal() << __PRETTY_FUNCTION__ << " failure verifying peer " - << "certificate signature. This should never happen at this " - << "point!" << std::endl; - print_stacktrace(); - - X509_free(peercert); // not needed but just in case we change to return - exit(failure); - } - - RsPgpId pgpId = RsX509Cert::getCertIssuer(*peercert); - if( !isSslOnlyFriend && pgpId != AuthPGP::getPgpOwnId() && !AuthPGP::isPGPAccepted(pgpId) ) - { - RsFatal() << __PRETTY_FUNCTION__ << " pgpId: " << pgpId - << " is not friend. It is very unlikely to happen at this " - << "point! Either the user must have been so fast to deny " - << "friendship just after VerifyX509Callback have returned " - << "success and just before this code being executed, or " - << "something really fishy is happening! Share the full log " - << "with developers." << std::endl; - print_stacktrace(); - - X509_free(peercert); // not needed but just in case we change to return - exit(failure); - } -#endif // def RS_PQISSL_AUTH_REDUNDANT_CHECK - - Dbg2() << __PRETTY_FUNCTION__ << " Accepting connection to peer: " - << PeerId() << " with address: " << remote_addr << std::endl; - - return accept_locked(ssl_connection, sockfd, remote_addr); -} - - -/* This function is public, and callable from pqilistener - so must be mutex protected */ -int pqissl::accept( SSL *ssl, int fd, - const sockaddr_storage &foreign_addr) -{ -#ifdef PQISSL_DEBUG - std::cerr << __PRETTY_FUNCTION__ << std::endl; -#endif - - RS_STACK_MUTEX(mSslMtx); - return accept_locked(ssl, fd, foreign_addr); -} - -int pqissl::accept_locked( SSL *ssl, int fd, - const sockaddr_storage &foreign_addr ) -{ - Dbg3() << __PRETTY_FUNCTION__ << std::endl; - - constexpr int failure = -1; - constexpr int success = 1; - -#ifdef RS_PQISSL_BANLIST_DOUBLE_CHECK - /* At this point, as we are actively attempting the connection, we decide - * the address to which to connect to, banned addresses should never get - * here as the filtering for banned addresses happens much before, this - * check is therefore redundant, and if it trigger something really fishy - * must be happening (a bug somewhere else in the code). */ - uint32_t check_result; - uint32_t checking_flags = RSBANLIST_CHECKING_FLAGS_BLACKLIST; - - if (rsPeers->servicePermissionFlags(PeerId()) & RS_NODE_PERM_REQUIRE_WL) - checking_flags |= RSBANLIST_CHECKING_FLAGS_WHITELIST; - - if( RsX509Cert::getCertSslId(*SSL_get_peer_certificate(ssl)) != PeerId()) - std::cerr << "(EE) pqissl::accept_locked(): PeerId() is " << PeerId() << " but certificate ID is " << RsX509Cert::getCertSslId(*SSL_get_peer_certificate(ssl)) << std::endl; - - if(rsBanList && !rsBanList->isAddressAccepted( foreign_addr, checking_flags, check_result )) - { - RsInfo() << __PRETTY_FUNCTION__ - << " Refusing incoming SSL connection from blacklisted " - << "foreign address " << foreign_addr - << ". Reason: " << check_result << ". This should never happen " - << "at this point! Please report full log to developers!" - << std::endl; - print_stacktrace(); - - if(rsEvents) - { - X509 *x509 = SSL_get_peer_certificate(ssl); - auto ev = std::make_shared(); - ev->mSslId = RsX509Cert::getCertSslId(*x509); - ev->mLocator = RsUrl(foreign_addr); - ev->mErrorCode = RsAuthSslError::IP_IS_BLACKLISTED; - rsEvents->postEvent(ev); - } - - reset_locked(); - return failure; - } -#endif //def RS_BANLIST_REDUNDANT_CHECK - - if (waiting != WAITING_NOT) - { - RsInfo() << __PRETTY_FUNCTION__ << " Peer: " << PeerId() - << " - Two connections in progress - Shut 1 down!" - << std::endl; - - // outgoing connection in progress. - // shut this baby down. - // - // Thought I should shut down one in progress, and continue existing one! - // But the existing one might be broke.... take second. - // all we need is to never stop listening. - - switch(waiting) - { - case WAITING_SOCK_CONNECT: -#ifdef PQISSL_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " STATE = Waiting Sock Connect " - << "- close the socket" << std::endl; -#endif - break; - case WAITING_SSL_CONNECTION: -#ifdef PQISSL_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " STATE = Waiting SSL " - << "Connection - close sockfd + ssl_conn" << std::endl; -#endif - break; - case WAITING_SSL_AUTHORISE: -#ifdef PQISSL_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " STATE = Waiting SSL Authorise" - << " - close sockfd + ssl_conn" << std::endl; -#endif - break; - case WAITING_FAIL_INTERFACE: -#ifdef PQISSL_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " STATE = Failed, ignore?" - << std::endl; -#endif - break; - default: - std::cerr << __PRETTY_FUNCTION__ << " STATE = Unknown - resetting!" - << std::endl; - reset_locked(); - break; - } - } - - /* shutdown existing - in all cases use the new one */ - if ((ssl_connection) && (ssl_connection != ssl)) - { - RsInfo() << __PRETTY_FUNCTION__ - << " closing Previous/Existing ssl_connection" << std::endl; - SSL_shutdown(ssl_connection); - SSL_free (ssl_connection); - } - - if ((sockfd > -1) && (sockfd != fd)) - { - RsInfo() << __PRETTY_FUNCTION__ << " closing Previous/Existing sockfd" - << std::endl; - net_internal_close(sockfd); - } - - - // save ssl + sock. - - ssl_connection = ssl; - sockfd = fd; - - /* if we connected - then just writing the same over, - * but if from ssllistener then we need to save the address. - */ - sockaddr_storage_copy(foreign_addr, remote_addr); - - RsInfo() << __PRETTY_FUNCTION__ << " SUCCESSFUL connection to: " - << PeerId().toStdString() << " remoteaddr: " - << sockaddr_storage_iptostring(remote_addr) << std::endl; - -#ifdef PQISSL_DEBUG - { - int alg; - std::cerr << __PRETTY_FUNCTION__ << "SSL Cipher: " - << SSL_get_cipher(ssl) << std::endl << "SSL Cipher Bits: " - << SSL_get_cipher_bits(ssl, &alg) << " - " << alg - << std::endl; - } -#endif - - // make non-blocking / or check..... - int err; - if ((err = net_internal_fcntl_nonblock(sockfd)) < 0) - { - std::cerr << __PRETTY_FUNCTION__ << "Cannot make socket NON-Blocking " - << "reset!" << std::endl; - - active = false; - waiting = WAITING_FAIL_INTERFACE; // failed completely. - - reset_locked(); - return failure; - } -#ifdef PQISSL_DEBUG - else std::cerr << __PRETTY_FUNCTION__ << " Socket made non-nlocking!" - << std::endl; -#endif - - // we want to continue listening - incase this socket is crap, and they try again. - //stoplistening(); - - active = true; - waiting = WAITING_NOT; - -#ifdef PQISSL_DEBUG - std::cerr << __PRETTY_FUNCTION__ << "connection complete - notifying parent" - << std::endl; -#endif - - // Notify the pqiperson.... (Both Connect/Receive) - if (parent()) - { - // Is the copy necessary? - sockaddr_storage addr; sockaddr_storage_copy(remote_addr, addr); - parent()->notifyEvent(this, NET_CONNECT_SUCCESS, addr); - } - return success; -} - -/********** Implementation of BinInterface ************************** - * All the rest of the BinInterface. - * This functions much be Mutex protected. - * - */ - -int pqissl::senddata(void *data, int len) -{ - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - - int tmppktlen ; - - // safety check. Apparently this avoids some SIGSEGV. - // - if(ssl_connection == NULL) - return -1; - -#ifdef PQISSL_DEBUG - std::cout << "Sending data thread=" << pthread_self() << ", ssl=" << (void*)this << ", size=" << len << std::endl ; -#endif - ERR_clear_error(); - tmppktlen = SSL_write(ssl_connection, data, len) ; - - if (len != tmppktlen) - { - std::string out = "pqissl::senddata() " + PeerId().toStdString(); - rs_sprintf_append(out, " Partial Send: len: %d sent: %d ", len, tmppktlen); - - int err = SSL_get_error(ssl_connection, tmppktlen); - // incomplete operations - to repeat.... - // handled by the pqistreamer... - if (err == SSL_ERROR_SYSCALL) - { - rs_sprintf_append(out, "SSL_write() SSL_ERROR_SYSCALL SOCKET_DEAD -> calling reset() errno: %d ", errno); - out += socket_errorType(errno); - std::cerr << out << std::endl; - rslog(RSL_ALERT, pqisslzone, out); - - /* extra debugging - based on SSL_get_error() man page */ - { - int errsys = errno; - int sslerr = 0; - std::string out2; - rs_sprintf(out2, "SSL_ERROR_SYSCALL, ret == %d errno: %d %s\n", tmppktlen, errsys, socket_errorType(errsys).c_str()); - - while(0 != (sslerr = ERR_get_error())) - { - rs_sprintf_append(out2, "SSLERR:%d:", sslerr); - - char sslbuf[256] = {0}; - out2 += ERR_error_string(sslerr, sslbuf); - out2 += "\n"; - } - rslog(RSL_ALERT, pqisslzone, out2); - } - - rslog(RSL_ALERT, pqisslzone, "pqissl::senddata() -> calling reset()"); - reset_locked(); - return -1; - } - else if (err == SSL_ERROR_WANT_WRITE) - { - out += "SSL_write() SSL_ERROR_WANT_WRITE"; - rslog(RSL_WARNING, pqisslzone, out); - return -1; - } - else if (err == SSL_ERROR_WANT_READ) - { - out += "SSL_write() SSL_ERROR_WANT_READ"; - rslog(RSL_WARNING, pqisslzone, out); - //std::cerr << out << std::endl; - return -1; - } - else - { - rs_sprintf_append(out, "SSL_write() UNKNOWN ERROR: %d\n", err); - printSSLError(ssl_connection, tmppktlen, err, ERR_get_error(), out); - out += "\n\tResetting!"; - std::cerr << out << std::endl; - rslog(RSL_ALERT, pqisslzone, out); - - rslog(RSL_ALERT, pqisslzone, "pqissl::senddata() -> calling reset()"); - reset_locked(); - return -1; - } - } - return tmppktlen; -} - -int pqissl::readdata(void *data, int len) -{ - RS_STACK_MUTEX(mSslMtx); - -#ifdef PQISSL_DEBUG - std::cout << "Reading data thread=" << pthread_self() << ", ssl=" - << (void*)this << std::endl; -#endif - - // Safety check. Apparently this avoids some SIGSEGV. - if (ssl_connection == NULL) return -1; - - // There is a do, because packets can be splitted into multiple ssl buffers - // when they are larger than 16384 bytes. Such packets have to be read in - // multiple slices. - do - { - int tmppktlen; - -#ifdef PQISSL_DEBUG - std::cerr << "calling SSL_read. len=" << len << ", total_len=" - << total_len << std::endl; -#endif - ERR_clear_error(); - - tmppktlen = SSL_read(ssl_connection, - (void*)( &(((uint8_t*)data)[total_len])), - len-total_len); - -#ifdef PQISSL_DEBUG - std::cerr << "have read " << tmppktlen << " bytes" << std::endl ; - std::cerr << "data[0] = " - << (int)((uint8_t*)data)[total_len+0] << " " - << (int)((uint8_t*)data)[total_len+1] << " " - << (int)((uint8_t*)data)[total_len+2] << " " - << (int)((uint8_t*)data)[total_len+3] << " " - << (int)((uint8_t*)data)[total_len+4] << " " - << (int)((uint8_t*)data)[total_len+5] << " " - << (int)((uint8_t*)data)[total_len+6] << " " - << (int)((uint8_t*)data)[total_len+7] << std::endl ; -#endif - - // Need to catch errors..... - if (tmppktlen <= 0) // probably needs a reset. - { - std::string out; - - int error = SSL_get_error(ssl_connection, tmppktlen); - unsigned long err2 = ERR_get_error(); - - if ((error == SSL_ERROR_ZERO_RETURN) && (err2 == 0)) - { - /* this code will be called when - * (1) moretoread -> returns true. + - * (2) SSL_read fails. - * - * There are two ways this can happen: - * (1) there is a little data on the socket, but not enough - * for a full SSL record, so there legimitately is no error, and the moretoread() - * was correct, but the read fails. - * - * (2) the socket has been closed correctly. this leads to moretoread() -> true, - * and ZERO error.... we catch this case by counting how many times - * it occurs in a row (cos the other one will not). - */ - if (n_read_zero == 0) - { - /* first read_zero */ - mReadZeroTS = time(NULL); - } - - ++n_read_zero; - out += "pqissl::readdata() " + PeerId().toStdString(); - rs_sprintf_append(out, " SSL_read() SSL_ERROR_ZERO_RETURN : nReadZero: %d", n_read_zero); - - if ((PQISSL_MAX_READ_ZERO_COUNT < n_read_zero) - && (time(NULL) - mReadZeroTS > PQISSL_MAX_READ_ZERO_TIME)) - { - out += " Count passed Limit, shutting down!"; - rs_sprintf_append(out, " ReadZero Age: %ld", time(NULL) - mReadZeroTS); - - rslog(RSL_ALERT, pqisslzone, "pqissl::readdata() -> calling reset()"); - reset_locked(); - } - -#ifdef PQISSL_LOG_DEBUG2 - rslog(RSL_ALERT, pqisslzone, out); -#endif - //std::cerr << out << std::endl ; - return -1; - } - - /* the only real error we expect */ - if (error == SSL_ERROR_SYSCALL) - { - out += "pqissl::readdata() " + PeerId().toStdString(); - out += " SSL_read() SSL_ERROR_SYSCALL"; - out += " SOCKET_DEAD -> calling reset()"; - rs_sprintf_append(out, " errno: %d", errno); - out += " " + socket_errorType(errno); - rslog(RSL_ALERT, pqisslzone, out); - - /* extra debugging - based on SSL_get_error() man page */ - { - int syserr = errno; - int sslerr = 0; - std::string out2; - rs_sprintf(out2, "SSL_ERROR_SYSCALL, ret == %d errno: %d %s\n", tmppktlen, syserr, socket_errorType(syserr).c_str()); - - while(0 != (sslerr = ERR_get_error())) - { - rs_sprintf_append(out2, "SSLERR:%d : ", sslerr); - - char sslbuf[256] = {0}; - out2 += ERR_error_string(sslerr, sslbuf); - out2 += "\n"; - } - rslog(RSL_ALERT, pqisslzone, out2); - } - - rslog(RSL_ALERT, pqisslzone, "pqissl::readdata() -> calling reset()"); - reset_locked(); - std::cerr << out << std::endl ; - return -1; - } - else if (error == SSL_ERROR_WANT_WRITE) - { - out += "SSL_read() SSL_ERROR_WANT_WRITE"; - rslog(RSL_WARNING, pqisslzone, out); - std::cerr << out << std::endl ; - return -1; - } - else if (error == SSL_ERROR_WANT_READ) - { - // SSL_WANT_READ is not a crittical error. It's just a sign that - // the internal SSL buffer is not ready to accept more data. So -1 - // is returned, and the connection will be retried as is on next - // call of readdata(). - -#ifdef PQISSL_DEBUG - out += "SSL_read() SSL_ERROR_WANT_READ"; - rslog(RSL_DEBUG_BASIC, pqisslzone, out); -#endif - return -1; - } - else - { - rs_sprintf_append(out, "SSL_read() UNKNOWN ERROR: %d Resetting!", error); - rslog(RSL_ALERT, pqisslzone, out); - std::cerr << out << std::endl ; - std::cerr << ", SSL_read() output is " << tmppktlen << std::endl ; - - printSSLError(ssl_connection, tmppktlen, error, err2, out); - - rslog(RSL_ALERT, pqisslzone, "pqissl::readdata() -> calling reset()"); - reset_locked(); - return -1; - } - - rslog(RSL_ALERT, pqisslzone, out); - //exit(1); - } - else - total_len+=tmppktlen ; - } while(total_len < len) ; - -#ifdef PQISSL_DEBUG - std::cerr << "pqissl: have read data of length " << total_len << ", expected is " << len << std::endl ; -#endif - - if (len != total_len) - { - std::string out; - rs_sprintf(out, "pqissl::readdata() Full Packet Not read!\n -> Expected len(%d) actually read(%d)", len, total_len); - std::cerr << out << std::endl; - rslog(RSL_WARNING, pqisslzone, out); - } - total_len = 0 ; // reset the packet pointer as we have finished a packet. - n_read_zero = 0; - return len;//tmppktlen; -} - - -// dummy function currently. -int pqissl::netstatus() -{ - return 1; -} - -int pqissl::isactive() -{ - return active; // no need to mutex this. It's atomic. -} - -bool pqissl::moretoread(uint32_t usec) -{ - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - -#ifdef PQISSL_DEBUG - { - std::string out; - rs_sprintf(out, "pqissl::moretoread() polling socket (%d)", sockfd); - rslog(RSL_DEBUG_ALL, pqisslzone, out); - } -#endif - - if(sockfd == -1) - { - std::cerr << "pqissl::moretoread(): socket is invalid or closed." << std::endl; - return 0 ; - } - - fd_set ReadFDs, WriteFDs, ExceptFDs; - FD_ZERO(&ReadFDs); - FD_ZERO(&WriteFDs); - FD_ZERO(&ExceptFDs); - - FD_SET(sockfd, &ReadFDs); - // Dont set WriteFDs. - FD_SET(sockfd, &ExceptFDs); - - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = usec; - - if (select(sockfd + 1, &ReadFDs, &WriteFDs, &ExceptFDs, &timeout) < 0) - { - rslog(RSL_ALERT, pqisslzone, - "pqissl::moretoread() Select ERROR!"); - RS_WARN(strerror(errno)); - - if (errno == EBADF) { - // happens when SAM is shut down - rslog(RSL_ALERT, pqisslzone, "pqissl::moretoread() -> calling reset()"); - reset_locked(); - } - return 0; - } - - if (FD_ISSET(sockfd, &ExceptFDs)) - { - // error - reset socket. - rslog(RSL_ALERT, pqisslzone, - "pqissl::moretoread() Select Exception ERROR!"); - - // this is a definite bad socket!. - // reset. - rslog(RSL_ALERT, pqisslzone, "pqissl::moretoread() -> calling reset()"); - reset_locked(); - return 0; - } - - - if (FD_ISSET(sockfd, &ReadFDs)) - { -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::moretoread() Data to Read!"); -#endif - return 1; - } - else if(SSL_pending(ssl_connection) > 0) - { - return 1 ; - } - else - { -#ifdef PQISSL_DEBUG - rslog(RSL_DEBUG_ALL, pqisslzone, - "pqissl::moretoread() No Data to Read!"); -#endif - return 0; - } - -} - -bool pqissl::cansend(uint32_t usec) -{ - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - -#ifdef PQISSL_DEBUG - rslog(RSL_DEBUG_ALL, pqisslzone, - "pqissl::cansend() polling socket!"); -#endif - - if(sockfd == -1) - { - std::cerr << "pqissl::cansend(): socket is invalid or closed." << std::endl; - return 0 ; - } - - // Interestingly - This code might be portable.... - - fd_set ReadFDs, WriteFDs, ExceptFDs; - FD_ZERO(&ReadFDs); - FD_ZERO(&WriteFDs); - FD_ZERO(&ExceptFDs); - - // Dont Set ReadFDs. - FD_SET(sockfd, &WriteFDs); - FD_SET(sockfd, &ExceptFDs); - - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = usec; - - - if (select(sockfd + 1, &ReadFDs, &WriteFDs, &ExceptFDs, &timeout) < 0) - { - // select error. - rslog(RSL_ALERT, pqisslzone, - "pqissl::cansend() Select Error!"); - - return 0; - } - - if (FD_ISSET(sockfd, &ExceptFDs)) - { - // error - reset socket. - rslog(RSL_ALERT, pqisslzone, - "pqissl::cansend() Select Exception!"); - - // this is a definite bad socket!. - // reset. - rslog(RSL_ALERT, pqisslzone, "pqissl::cansend() -> calling reset()"); - reset_locked(); - return 0; - } - - if (FD_ISSET(sockfd, &WriteFDs)) - { -#ifdef PQISSL_DEBUG - // write can work. - rslog(RSL_DEBUG_ALL, pqisslzone, - "pqissl::cansend() Can Write!"); -#endif - return 1; - } - else - { -#ifdef PQISSL_DEBUG - // write can work. - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::cansend() Can *NOT* Write!"); -#endif - - return 0; - } - -} - -RsFileHash pqissl::gethash() { return RsFileHash(); } - -/********** End of Implementation of BinInterface ******************/ - - -int pqissl::net_internal_close(int fd) -{ - return unix_close(fd); -} - -int pqissl::net_internal_SSL_set_fd(SSL *ssl, int fd) -{ - return SSL_set_fd(ssl, fd); -} - -int pqissl::net_internal_fcntl_nonblock(int fd) -{ - return unix_fcntl_nonblock(fd); -} diff --git a/libretroshare/src/pqi/pqissl.h b/libretroshare/src/pqi/pqissl.h deleted file mode 100644 index 30905be5e..000000000 --- a/libretroshare/src/pqi/pqissl.h +++ /dev/null @@ -1,274 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqissl.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie * - * Copyright (C) 2015-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -// operating system specific network header. -#include "pqi/pqinetwork.h" - -#include -#include - -#include "pqi/pqi_base.h" -#include "pqi/authssl.h" - -#define RS_PQISSL_AUTH_DOUBLE_CHECK 1 - -#define RS_PQISSL_BANLIST_DOUBLE_CHECK 1 - - -#define WAITING_NOT 0 -#define WAITING_DELAY 1 -#define WAITING_SOCK_CONNECT 2 -#define WAITING_SSL_CONNECTION 3 -#define WAITING_SSL_AUTHORISE 4 -#define WAITING_FAIL_INTERFACE 5 - -#define PQISSL_PASSIVE 0x00 -#define PQISSL_ACTIVE 0x01 - -const int PQISSL_LOCAL_FLAG = 0x01; -const int PQISSL_REMOTE_FLAG = 0x02; -const int PQISSL_DNS_FLAG = 0x04; - -/* not sure about the value? */ -const int PQISSL_UDP_FLAG = 0x02; - -/* TCP buffer size for Windows systems */ -const int WINDOWS_TCP_BUFFER_SIZE = 512 * 1024; // 512 KB - - -// This is a (very) simple overview of the different state machnines. The tree includes high level funtions only. -// -// connect_parameter() is used to pass down settings, like address or timeout values -// -// tick() or connect() -// | -// +----- ConnectAttempt() -// | -// +--WAITING_NOT or WAITING_DELAY -// | | -// | +----- Delay_Connection() -// | | -// | +--WAITING_NOT -// | | - set 'waiting' to WAITING_DELAY and set delay for next connection attempt -// | | -// | +--WAITING_DELAY -// | | -// | +----- Initiate_Connection() -// | | -// | +----- setup socket -// | +----- connect -// | - on success: set "waiting" to WAITING_SOCK_CONNECT and "sockfd" to newly created socket -// | - on failure: set "waiting" to WAITING_FAIL_INTERFACE -// | -// +--WAITING_SOCK_CONNECT -// | | -// | +----- Initiate_SSL_Connection() -// | | -// | +----- Basic_Connection_Complete() -// | | | -// | | +----- CheckConnectionTimeout() -// | | | -// | | +----- ready up socket. -// | | - SOCKS, udp tou, i2p BOB intercept here -// | | - on failure: set "waiting" to WAITING_FAIL_INTERFACE and "sockfd" to -1 -// | | -// | +----- create SSL context and attach file descriptors -// | - on success:_set "waiting" to WAITING_SSL_CONNECTION -// | -// +--WAITING_SSL_CONNECTION or WAITING_SSL_AUTHORISE -// | | -// | +----- Authorise_SSL_Connection() -// | | -// | +----- SSL_Connection_Complete() -// | | | -// | | +----- performes TSL handshake -// | | - on success: set "waiting" to WAITING_SSL_AUTHORISE -// | | - on failure: set "waiting" to WAITING_FAIL_INTERFACE -// | | -// | +----- set "waiting" to WAITING_NOT -// | | -// | +----- accept_locked() -// | - add peer to the rest of RS and start pqi thread -// | -// | -// +--WAITING_FAIL_INTERFACE -// | -// +----- Failed_Connection() -// - set "waiting" to WAITING_NOT -// - - -/***************************** pqi Net SSL Interface ********************************* - * This provides the base SSL interface class, - * and handles most of the required functionality. - * - * there are a series of small fn's that can be overloaded - * to provide alternative behaviour.... - * - * Classes expected to inherit from this are: - * - * pqissllistener -> pqissllistener (tcp only) - * -> pqixpgplistener (tcp only) - * - * pqissl -> pqissltcp - * -> pqissludp - * -> pqixpgptcp - * -> pqixpgpudp - * - */ - -class pqissllistener; -class p3LinkMgr; -struct RsPeerCryptoParams; - -class pqissl: public NetBinInterface -{ -public: - pqissl(pqissllistener *l, PQInterface *parent, - p3LinkMgr *lm); -virtual ~pqissl(); - - // NetInterface -virtual int connect(const struct sockaddr_storage &raddr); -virtual int listen(); -virtual int stoplistening(); -virtual int reset(); -virtual int disconnect(); -virtual int getConnectAddress(struct sockaddr_storage &raddr); - -virtual bool connect_parameter(uint32_t /*type*/, const std::string & /*value*/) { return false; } -virtual bool connect_parameter(uint32_t type, uint32_t value); - - // BinInterface -virtual int tick(); -virtual int status(); - -virtual int senddata(void*, int); -virtual int readdata(void*, int); -virtual int netstatus(); -virtual int isactive(); -virtual bool moretoread(uint32_t usec); -virtual bool cansend(uint32_t usec); - -virtual int close(); /* BinInterface version of reset() */ -virtual RsFileHash gethash(); /* not used here */ -virtual bool bandwidthLimited() { return true ; } - -public: - -/// initiate incoming connection. -int accept(SSL *ssl, int fd, const struct sockaddr_storage &foreign_addr); - -void getCryptoParams(RsPeerCryptoParams& params) ; -bool actAsServer(); - - -protected: - - - /* no mutex protection for these ones */ - - p3LinkMgr *mLinkMgr; - pqissllistener *pqil; - - RsMutex mSslMtx; /**** MUTEX protects data and fn below ****/ - -virtual int reset_locked(); - - /// initiate incoming connection. - int accept_locked( SSL *ssl, int fd, - const sockaddr_storage& foreign_addr ); - - // A little bit of information to describe - // the SSL state, this is needed - // to allow full Non-Blocking Connect behaviour. - // This fn loops through the following fns. - // to complete an SSL. - -int ConnectAttempt(); - -virtual int Failed_Connection(); - - // Start up connection with delay... -virtual int Delay_Connection(); - - // These two fns are overloaded for udp/etc connections. -virtual int Initiate_Connection(); -virtual int Basic_Connection_Complete(); - - // These should be identical for all cases, - // differences are achieved via the net_internal_* fns. -int Initiate_SSL_Connection(); -int SSL_Connection_Complete(); -int Authorise_SSL_Connection(); - - // check connection timeout. -bool CheckConnectionTimeout(); - - - /* Do we really need this ? - * It is very specific TCP+SSL stuff and unlikely to be reused. - * In fact we are overloading them in pqissludp case where they do different things or nothing. - */ - virtual int net_internal_close(int fd); - virtual int net_internal_SSL_set_fd(SSL *ssl, int fd); - virtual int net_internal_fcntl_nonblock(int fd); - - - /* data */ - bool active; - bool certvalid; - - int waiting; - - // addition for udp (tcp version == ACTIVE). - int sslmode; - - SSL *ssl_connection; - int sockfd; - - struct sockaddr_storage remote_addr; - - void *readpkt; - int pktlen; - int total_len ; // saves the reading state accross successive calls. - - int attempt_ts; - - int n_read_zero; /* a counter to determine if the connection is really dead */ - rstime_t mReadZeroTS; /* timestamp of first READ_ZERO occurance */ - - int ssl_connect_timeout; /* timeout to ensure that we don't get stuck (can happen on udp!) */ - - uint32_t mConnectDelay; - rstime_t mConnectTS; - uint32_t mConnectTimeout; - rstime_t mTimeoutTS; - - RS_SET_CONTEXT_DEBUG_LEVEL(1) - -private: - // ssl only fns. - int connectInterface(const struct sockaddr_storage &addr); -}; diff --git a/libretroshare/src/pqi/pqissli2psam3.cpp b/libretroshare/src/pqi/pqissli2psam3.cpp deleted file mode 100644 index 1e0f5d433..000000000 --- a/libretroshare/src/pqi/pqissli2psam3.cpp +++ /dev/null @@ -1,261 +0,0 @@ -#include "pqissli2psam3.h" - -#include - -RS_SET_CONTEXT_DEBUG_LEVEL(2) - -static constexpr int pqiDone = 1; -static constexpr int pqiWait = 0; -static constexpr int pqiError = -1; - -pqissli2psam3::pqissli2psam3(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm) - : pqissl(l, parent, lm), mState(pqisslSam3State::NONE), mI2pAddrB32(), mI2pAddrLong() -{ - RS_DBG4(); - mConn = nullptr; -} - -bool pqissli2psam3::connect_parameter(uint32_t type, const std::string &value) -{ - RS_DBG4(); - - if (type == NET_PARAM_CONNECT_DOMAIN_ADDRESS) - { - RS_DBG1("got addr:", value); - RS_STACK_MUTEX(mSslMtx); - mI2pAddrB32 = value; - return true; - } - - return pqissl::connect_parameter(type, value); -} - -int pqissli2psam3::Initiate_Connection() -{ - RS_DBG4(); - - if(waiting != WAITING_DELAY) - { - RS_ERR("Already Attempt in Progress!"); - return pqiError; - } - - switch (mState) { - case(pqisslSam3State::NONE): - RS_DBG2("NONE"); - { - if(mConn) { - // how did we end up here? - RS_ERR("state is NONE but a connection is existing?!"); - } - mConn = 0; - // get SAM session - mConn = 0; - samSettings ss; - ss.session = nullptr; - rsAutoProxyMonitor::taskSync(autoProxyType::I2PSAM3, autoProxyTask::getSettings, static_cast(&ss)); - - if (!!ss.session) { - RS_DBG3("NONE->DO_LOOKUP"); - mState = pqisslSam3State::DO_LOOKUP; - } else { - RS_DBG3("NONE->DO_LOOKUP NOPE", ss.session); - } - } - break; - case(pqisslSam3State::DO_LOOKUP): - RS_DBG1("DO_LOOKUP"); - - if (!mI2pAddrLong.empty()) { - // skip lookup, it is highly unlikely/impossible for a public key to change (isn't it?) - mState = pqisslSam3State::WAIT_LOOKUP; - break; - } - - { - i2p::address *addr = new i2p::address; - addr->clear(); - addr->base32 = mI2pAddrB32; - rsAutoProxyMonitor::taskAsync(autoProxyType::I2PSAM3, autoProxyTask::lookupKey, this, static_cast(addr)); - } - mState = pqisslSam3State::WAIT_LOOKUP; - break; - case(pqisslSam3State::DO_CONNECT): - RS_DBG2("DO_CONNECT"); - - { - auto wrapper = new samEstablishConnectionWrapper(); - wrapper->address.clear(); - wrapper->address.publicKey = mI2pAddrLong; - wrapper->connection = nullptr; - - rsAutoProxyMonitor::taskAsync(autoProxyType::I2PSAM3, autoProxyTask::establishConnection, this, static_cast(wrapper)); - } - mState = pqisslSam3State::WAIT_CONNECT; - break; - case(pqisslSam3State::DONE): - RS_DBG2("DONE"); - - if (setupSocket()) - return pqiDone; - return pqiError; - - /* waiting */ - case(pqisslSam3State::WAIT_LOOKUP): - RS_DBG3("WAIT_LOOKUP"); - break; - case(pqisslSam3State::WAIT_CONNECT): - RS_DBG3("WAIT_CONNECT"); - break; - } - return pqiWait; -} - -int pqissli2psam3::net_internal_close(int fd) -{ - RS_DBG4(); - - // sanity check - if (mConn && fd != mConn->fd) { - // this should never happen! - RS_ERR("fd != mConn"); -// sam3CloseConnection(mConn); - } - - // now to the actuall closing - int ret = pqissl::net_internal_close(fd); - - rsAutoProxyMonitor::taskAsync(autoProxyType::I2PSAM3, autoProxyTask::closeConnection, this, mConn); - - // finally cleanup - mConn = 0; - mState = pqisslSam3State::NONE; - - return ret; -} - -void pqissli2psam3::taskFinished(taskTicket *&ticket) -{ - RS_DBG4(); - - switch (ticket->task) { - case autoProxyTask::lookupKey: - { - auto addr = static_cast(ticket->data); - - RS_STACK_MUTEX(mSslMtx); - if (ticket->result == autoProxyStatus::ok) { - mI2pAddrLong = addr->publicKey; - mState = pqisslSam3State::DO_CONNECT; - } else { - waiting = WAITING_FAIL_INTERFACE; - } - - delete addr; - ticket->data = nullptr; - addr = nullptr; - } - break; - case autoProxyTask::establishConnection: - { - auto wrapper = static_cast(ticket->data); - - RS_STACK_MUTEX(mSslMtx); - if (ticket->result == autoProxyStatus::ok) { - mConn = wrapper->connection; - mState = pqisslSam3State::DONE; - } else { - waiting = WAITING_FAIL_INTERFACE; - } - - delete wrapper; - ticket->data = nullptr; - wrapper = nullptr; - } - break; - case autoProxyTask::closeConnection: - // nothing to do here - break; - default: - RS_WARN("unkown task", ticket->task); - } - - // clean up! - delete ticket; - ticket = nullptr; -} - -bool pqissli2psam3::setupSocket() -{ - /* - * This function contains the generis part from pqissl::Initiate_Connection() - */ - int err; - int osock = mConn->fd; - - err = unix_fcntl_nonblock(osock); - if (err < 0) - { - RS_ERR("Cannot make socket NON-Blocking:", err); - - waiting = WAITING_FAIL_INTERFACE; - net_internal_close(osock); - return false; - } - -#ifdef WINDOWS_SYS - /* Set TCP buffer size for Windows systems */ - - int sockbufsize = 0; - int size = sizeof(int); - - err = getsockopt(osock, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, &size); -#ifdef PQISSL_DEBUG - if (err == 0) { - std::cerr << "pqissl::Initiate_Connection: Current TCP receive buffer size " << sockbufsize << std::endl; - } else { - std::cerr << "pqissl::Initiate_Connection: Error getting TCP receive buffer size. Error " << err << std::endl; - } -#endif - - sockbufsize = 0; - - err = getsockopt(osock, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, &size); -#ifdef PQISSL_DEBUG - if (err == 0) { - std::cerr << "pqissl::Initiate_Connection: Current TCP send buffer size " << sockbufsize << std::endl; - } else { - std::cerr << "pqissl::Initiate_Connection: Error getting TCP send buffer size. Error " << err << std::endl; - } -#endif - - sockbufsize = WINDOWS_TCP_BUFFER_SIZE; - - err = setsockopt(osock, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, sizeof(sockbufsize)); -#ifdef PQISSL_DEBUG - if (err == 0) { - std::cerr << "pqissl::Initiate_Connection: TCP receive buffer size set to " << sockbufsize << std::endl; - } else { - std::cerr << "pqissl::Initiate_Connection: Error setting TCP receive buffer size. Error " << err << std::endl; - } -#endif - - err = setsockopt(osock, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, sizeof(sockbufsize)); -#ifdef PQISSL_DEBUG - if (err == 0) { - std::cerr << "pqissl::Initiate_Connection: TCP send buffer size set to " << sockbufsize << std::endl; - } else { - std::cerr << "pqissl::Initiate_Connection: Error setting TCP send buffer size. Error " << err << std::endl; - } -#endif -#endif // WINDOWS_SYS - - - mTimeoutTS = time(NULL) + mConnectTimeout; - //std::cerr << "Setting Connect Timeout " << mConnectTimeout << " Seconds into Future " << std::endl; - - waiting = WAITING_SOCK_CONNECT; - sockfd = osock; - - return true; -} diff --git a/libretroshare/src/pqi/pqissli2psam3.h b/libretroshare/src/pqi/pqissli2psam3.h deleted file mode 100644 index 90fdff6e0..000000000 --- a/libretroshare/src/pqi/pqissli2psam3.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef PQISSLI2PSAM3_H -#define PQISSLI2PSAM3_H - -#include "pqi/pqissl.h" -#include "services/autoproxy/rsautoproxymonitor.h" -#include "services/autoproxy/p3i2psam3.h" - -// Use a state machine as the whole pqi code is designed around them and some operation (like lookup) might be blocking -enum class pqisslSam3State : uint8_t { - NONE = 0, - DO_LOOKUP, - WAIT_LOOKUP, - DO_CONNECT, - WAIT_CONNECT, - DONE -}; - -class pqissli2psam3 : public pqissl, public autoProxyCallback -{ -public: - pqissli2psam3(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm); - - // NetInterface interface -public: - bool connect_parameter(uint32_t type, const std::string &value); - - // pqissl interface -protected: - int Initiate_Connection(); - int net_internal_close(int fd); - - // autoProxyCallback interface -public: - void taskFinished(taskTicket *&ticket); - -private: - bool setupSocket(); - -private: - pqisslSam3State mState; - std::string mI2pAddrB32; - std::string mI2pAddrLong; - - Sam3Connection *mConn; -}; - -#endif // PQISSLI2PSAM3_H diff --git a/libretroshare/src/pqi/pqissllistener.cc b/libretroshare/src/pqi/pqissllistener.cc deleted file mode 100644 index ad2129928..000000000 --- a/libretroshare/src/pqi/pqissllistener.cc +++ /dev/null @@ -1,882 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqissllistener.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * Copyright (C) 2015-2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "pqi/pqissl.h" -#include "pqi/pqissllistener.h" -#include "pqi/pqinetwork.h" -#include "pqi/sslfns.h" -#include "pqi/p3peermgr.h" -#include "util/rsdebug.h" -#include "util/rsstring.h" -#include "retroshare/rsbanlist.h" -#include "pqi/authgpg.h" - -#include -#include -#include - -static struct RsLog::logInfo pqissllistenzoneInfo = {RsLog::Default, "p3peermgr"}; -#define pqissllistenzone &pqissllistenzoneInfo - -/* NB: This #define makes the listener open 0.0.0.0:X port instead - * of a specific port - this might help retroshare work on PCs with - * multiple interfaces or unique network setups. - * #define OPEN_UNIVERSAL_PORT 1 - */ - -//#define DEBUG_LISTENNER -#define OPEN_UNIVERSAL_PORT 1 - -/************************ PQI SSL LISTEN BASE **************************** - * - * This provides all of the basic connection stuff, - * and calls completeConnection afterwards... - * - */ - - -pqissllistenbase::pqissllistenbase(const sockaddr_storage &addr, p3PeerMgr *pm) - : mPeerMgr(pm), active(false) -{ - sockaddr_storage_copy(addr, laddr); - - if (!(AuthSSL::getAuthSSL()-> active())) - { - pqioutput(PQL_ALERT, pqissllistenzone, - "SSL-CTX-CERT-ROOT not initialised!"); - exit(1); - } - - setuplisten(); -} - -pqissllistenbase::~pqissllistenbase() -{ - if(lsock != -1) - { -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - shutdown(lsock, SHUT_RDWR); - close(lsock); -#else //WINDOWS_SYS - closesocket(lsock); -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - } -} - -int pqissllistenbase::tick() -{ - status(); - // check listen port. - acceptconnection(); - continueaccepts(); - return finaliseAccepts(); -} - -int pqissllistenbase::status() -{ - std::string out; - rs_sprintf(out, "pqissllistenbase::status(): Listening on port: %u", sockaddr_storage_port(laddr)); - pqioutput(PQL_DEBUG_ALL, pqissllistenzone, out); - return 1; -} - -int pqissllistenbase::setuplisten() -{ - int err; - if (active) return -1; - - lsock = socket(PF_INET6, SOCK_STREAM, 0); - -#ifdef IPV6_V6ONLY - int no = 0; - err = rs_setsockopt(lsock, IPPROTO_IPV6, IPV6_V6ONLY, - reinterpret_cast(&no), sizeof(no)); - if (err) std::cerr << __PRETTY_FUNCTION__ - << ": Error setting IPv6 socket dual stack" << std::endl; -#ifdef DEBUG_LISTENNER - else std::cerr << __PRETTY_FUNCTION__ - << ": Success setting IPv6 socket dual stack" << std::endl; -#endif -#endif // IPV6_V6ONLY - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - if (lsock < 0) - { - pqioutput(PQL_ALERT, pqissllistenzone, - "pqissllistenbase::setuplisten() Cannot Open Socket!"); - - return -1; - } - - err = fcntl(lsock, F_SETFL, O_NONBLOCK); - if (err < 0) - { - shutdown(lsock,SHUT_RDWR) ; - close(lsock) ; - lsock = -1 ; - - std::string out; - rs_sprintf(out, "Error: Cannot make socket NON-Blocking: %d", err); - pqioutput(PQL_ERROR, pqissllistenzone, out); - - return -1; - } - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#else //WINDOWS_SYS - if ((unsigned) lsock == INVALID_SOCKET) - { - std::string out = "pqissllistenbase::setuplisten() Cannot Open Socket!\n"; - out += "Socket Error: "+ socket_errorType(WSAGetLastError()); - pqioutput(PQL_ALERT, pqissllistenzone, out); - - return -1; - } - - // Make nonblocking. - unsigned long int on = 1; - if (0 != (err = ioctlsocket(lsock, FIONBIO, &on))) - { - closesocket(lsock) ; - lsock = -1 ; - - std::string out; - rs_sprintf(out, "pqissllistenbase::setuplisten() Error: Cannot make socket NON-Blocking: %d\n", err); - out += "Socket Error: " + socket_errorType(WSAGetLastError()); - pqioutput(PQL_ALERT, pqissllistenzone, out); - - return -1; - } -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - // setup listening address. - - { - std::string out = "pqissllistenbase::setuplisten()\n"; - out += "\t FAMILY: " + sockaddr_storage_familytostring(laddr); - out += "\t ADDRESS: " + sockaddr_storage_tostring(laddr); - - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, out); - //std::cerr << out.str() << std::endl; - } - - /* added a call to REUSEADDR, so that we can re-open an existing socket - * when we restart_listener. - */ - - { - int on = 1; - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - if (setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) -#else //WINDOWS_SYS - if (setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, (const char *) &on, sizeof(on)) < 0) -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - { - std::string out = "pqissllistenbase::setuplisten() Cannot setsockopt SO_REUSEADDR!\n"; - showSocketError(out); - pqioutput(PQL_ALERT, pqissllistenzone, out); - std::cerr << out << std::endl; - - exit(1); - } - } - - struct sockaddr_storage tmpaddr; - sockaddr_storage_copy(laddr, tmpaddr); - sockaddr_storage_ipv4_to_ipv6(tmpaddr); - if (!mPeerMgr->isHidden()) sockaddr_storage_zeroip(tmpaddr); - - if (0 != (err = rs_bind(lsock, tmpaddr))) - { - std::string out = "pqissllistenbase::setuplisten() Cannot Bind to Local Address!\n"; - showSocketError(out); - pqioutput(PQL_ALERT, pqissllistenzone, out); - std::cerr << out << std::endl - << "tmpaddr: " << sockaddr_storage_tostring(tmpaddr) - << std::endl; - print_stacktrace(); - - return -1; - } - else - { - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, - "pqissllistenbase::setuplisten() Bound to Address."); - } - -#ifdef WINDOWS_SYS - /* Set TCP buffer size for Windows systems */ - - int sockbufsize = 0; - int size = sizeof(int); - - err = getsockopt(lsock, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, &size); - if (err == 0) { - std::cerr << "pqissllistenbase::setuplisten: Current TCP receive buffer size " << sockbufsize << std::endl; - } else { - std::cerr << "pqissllistenbase::setuplisten: Error getting TCP receive buffer size. Error " << err << std::endl; - } - - sockbufsize = 0; - - err = getsockopt(lsock, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, &size); - - if (err == 0) { - std::cerr << "pqissllistenbase::setuplisten: Current TCP send buffer size " << sockbufsize << std::endl; - } else { - std::cerr << "pqissllistenbase::setuplisten: Error getting TCP send buffer size. Error " << err << std::endl; - } - - sockbufsize = WINDOWS_TCP_BUFFER_SIZE; - - err = setsockopt(lsock, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, sizeof(sockbufsize)); - - if (err == 0) { - std::cerr << "pqissllistenbase::setuplisten: TCP receive buffer size set to " << sockbufsize << std::endl; - } else { - std::cerr << "pqissllistenbase::setuplisten: Error setting TCP receive buffer size. Error " << err << std::endl; - } - - err = setsockopt(lsock, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, sizeof(sockbufsize)); - - if (err == 0) { - std::cerr << "pqissllistenbase::setuplisten: TCP send buffer size set to " << sockbufsize << std::endl; - } else { - std::cerr << "pqissllistenbase::setuplisten: Error setting TCP send buffer size. Error " << err << std::endl; - } -#endif - - if (0 != (err = listen(lsock, 100))) - { - std::string out; - rs_sprintf(out, "pqissllistenbase::setuplisten() Error: Cannot Listen to Socket: %d\n", err); - showSocketError(out); - pqioutput(PQL_ALERT, pqissllistenzone, out); - std::cerr << out << std::endl; - - exit(1); - return -1; - } - else - { - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, - "pqissllistenbase::setuplisten() Listening to Socket"); - } - active = true; - return 1; -} - -int pqissllistenbase::setListenAddr(const struct sockaddr_storage &addr) -{ - laddr = addr; - return 1; -} - -int pqissllistenbase::resetlisten() -{ - if (active) - { - // close ports etc. -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - shutdown(lsock, SHUT_RDWR); - close(lsock); -#else //WINDOWS_SYS - closesocket(lsock); -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - lsock = -1; - active = false; - return 1; - } - - return 0; -} - - -int pqissllistenbase::acceptconnection() -{ - if (!active) - return 0; - // check port for any socets... - pqioutput(PQL_DEBUG_ALL, pqissllistenzone, "pqissllistenbase::accepting()"); - - // These are local but temp variables... - // can't be arsed making them all the time. - struct sockaddr_storage remote_addr; - socklen_t addrlen = sizeof(remote_addr); - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - int fd = accept(lsock, (struct sockaddr *) &remote_addr, &addrlen); - int err = 0; - - if (fd < 0) - { - pqioutput(PQL_DEBUG_ALL, pqissllistenzone, - "pqissllistenbase::acceptconnnection() Nothing to Accept!"); - return 0; - } - - err = fcntl(fd, F_SETFL, O_NONBLOCK); - if (err < 0) - { - std::string out; - rs_sprintf(out, "pqissllistenbase::acceptconnection() Error: Cannot make socket NON-Blocking: %d", err); - pqioutput(PQL_ERROR, pqissllistenzone, out); - - close(fd); - return -1; - } - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#else //WINDOWS_SYS - SOCKET fd = accept(lsock, (struct sockaddr *) &remote_addr, &addrlen); - int err = 0; - - if (fd == INVALID_SOCKET) - { - pqioutput(PQL_DEBUG_ALL, pqissllistenzone, - "pqissllistenbase::acceptconnnection() Nothing to Accept!"); - return 0; - } - - // Make nonblocking. - unsigned long int on = 1; - if (0 != (err = ioctlsocket(fd, FIONBIO, &on))) - { - std::string out; - rs_sprintf(out, "pqissllistenbase::acceptconnection() Error: Cannot make socket NON-Blocking: %d\n", err); - out += "Socket Error:" + socket_errorType(WSAGetLastError()); - pqioutput(PQL_ALERT, pqissllistenzone, out); - - closesocket(fd); - return 0; - } -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - std::cerr << "(II) Checking incoming connection address: " << sockaddr_storage_iptostring(remote_addr) ; - if(rsBanList != NULL && !rsBanList->isAddressAccepted(remote_addr, RSBANLIST_CHECKING_FLAGS_BLACKLIST)) - { - std::cerr << " => early rejected at this point, because of blacklist." << std::endl; -#ifndef WINDOWS_SYS - close(fd); -#else - closesocket(fd); -#endif - return false ; - } - else - std::cerr << " => Accepted (i.e. whitelisted, or not blacklisted)." << std::endl; - - { - std::string out; - out += "Accepted Connection from "; - out += sockaddr_storage_tostring(remote_addr); - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, out); - } - - // Negotiate certificates. SSL stylee. - // Allow negotiations for secure transaction. - - IncomingSSLInfo incoming_connexion_info ; - - incoming_connexion_info.ssl = SSL_new(AuthSSL::getAuthSSL() -> getCTX()); - incoming_connexion_info.addr = remote_addr ; - incoming_connexion_info.gpgid.clear() ; - incoming_connexion_info.sslid.clear() ; - incoming_connexion_info.sslcn = "" ; - - SSL_set_fd(incoming_connexion_info.ssl, fd); - - return continueSSL(incoming_connexion_info, true); // continue and save if incomplete. -} - -int pqissllistenbase::continueSSL(IncomingSSLInfo& incoming_connexion_info, bool addin) -{ - // attempt the accept again. - int fd = SSL_get_fd(incoming_connexion_info.ssl); - int err = SSL_accept(incoming_connexion_info.ssl); - - if (err <= 0) - { - int ssl_err = SSL_get_error(incoming_connexion_info.ssl, err); - int err_err = ERR_get_error(); - - { - std::string out; - rs_sprintf(out, "pqissllistenbase::continueSSL() Issues with SSL Accept(%d)!\n", err); - printSSLError(incoming_connexion_info.ssl, err, ssl_err, err_err, out); - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, out); - } - - switch (ssl_err) { - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - { - std::string out = "pqissllistenbase::continueSSL() Connection Not Complete!\n"; - - if (addin) - { - out += "pqissllistenbase::continueSSL() Adding SSL to incoming!"; - - // add to incomingqueue. - incoming_ssl.push_back(incoming_connexion_info) ; - } - - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, out); - - // zero means still continuing.... - return 0; - } - break; - case SSL_ERROR_SYSCALL: - { - std::string out = "pqissllistenbase::continueSSL() Connection failed!\n"; - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, out); - - closeConnection(fd, incoming_connexion_info.ssl); - - // basic-error while connecting, no security message needed - return -1; - } - break; - } - - pqioutput(PQL_WARNING, pqissllistenzone, "Read Error on the SSL Socket\nShutting it down!"); - - // We use SSL_get_verify_result() in order to differentiate two cases: - // case 1: the incoming connection is closed because the peer is not a friend. This is already handled in authssl. - // case 2: the incoming connection is closed because no authentication info is available, in which case it returns X509_V_OK - auto vres = SSL_get_verify_result(incoming_connexion_info.ssl); - - if(vres == X509_V_OK && nullptr != rsEvents) - { - auto ev = std::make_shared(); - ev->mLocator = RsUrl(incoming_connexion_info.addr); - ev->mErrorCode = RsAuthSslError::MISSING_AUTHENTICATION_INFO; - rsEvents->postEvent(ev); - } - closeConnection(fd, incoming_connexion_info.ssl); - - // failure -1, pending 0, sucess 1. - return -1; - } - - // Now grab the connection info from the SSL itself, because the callback info might be - // tempered due to multiple connection attempts at once. - // - X509 *x509 = SSL_get_peer_certificate(incoming_connexion_info.ssl) ; - - if(x509) - { - incoming_connexion_info.gpgid = RsX509Cert::getCertIssuer(*x509); - incoming_connexion_info.sslcn = RsX509Cert::getCertName(*x509); - incoming_connexion_info.sslid = RsX509Cert::getCertSslId(*x509); - -#ifndef DEBUG_LISTENNER - std::cerr << "ContinueSSL:" << std::endl; - std::cerr << " Got PGP Id = " << incoming_connexion_info.gpgid << std::endl; - std::cerr << " Got SSL Id = " << incoming_connexion_info.sslid << std::endl; - std::cerr << " Got SSL CN = " << incoming_connexion_info.sslcn << std::endl; -#endif - } - -#ifdef DEBUG_LISTENNER - else - std::cerr << " no info." << std::endl; -#endif - - // if it succeeds - if (0 < completeConnection(fd, incoming_connexion_info)) - return 1; - - /* else we shut it down! */ - pqioutput(PQL_WARNING, pqissllistenzone, - "pqissllistenbase::completeConnection() Failed!"); - - closeConnection(fd, incoming_connexion_info.ssl) ; - - pqioutput(PQL_WARNING, pqissllistenzone, "Shutting it down!"); - - // failure -1, pending 0, sucess 1. - return -1; -} - - -int pqissllistenbase::closeConnection(int fd, SSL *ssl) -{ - /* else we shut it down! */ - pqioutput(PQL_WARNING, pqissllistenzone, "pqissllistenbase::closeConnection() Shutting it Down!"); - - // delete ssl connection. - SSL_shutdown(ssl); - - // close socket??? -/************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - shutdown(fd, SHUT_RDWR); - close(fd); -#else //WINDOWS_SYS - closesocket(fd); -#endif -/************************** WINDOWS/UNIX SPECIFIC PART ******************/ - // free connection. - SSL_free(ssl); - - return 1; -} - -int pqissllistenbase::continueaccepts() -{ - - // for each of the incoming sockets.... call continue. - - for(std::list::iterator it = incoming_ssl.begin(); it != incoming_ssl.end();) - { - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, "pqissllistenbase::continueaccepts() Continuing SSL"); - - if (0 != continueSSL( *it, false)) - { - pqioutput(PQL_DEBUG_ALERT, pqissllistenzone, - "pqissllistenbase::continueaccepts() SSL Complete/Dead!"); - - /* save and increment -> so we can delete */ - std::list::iterator itd = it++; - incoming_ssl.erase(itd); - } - else - ++it; - } - return 1; -} - -#define ACCEPT_WAIT_TIME 30 - -int pqissllistenbase::finaliseAccepts() -{ - - // for each of the incoming sockets.... call continue. - std::list::iterator it; - - rstime_t now = time(NULL); - for(it = accepted_ssl.begin(); it != accepted_ssl.end();) - { - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, - "pqissllistenbase::finalisedAccepts() Continuing SSL Accept"); - - /* check that the socket is still active - how? */ - int active = isSSLActive(it->mFd, it->mSSL); - if (active > 0) - { - pqioutput(PQL_WARNING, pqissllistenzone, - "pqissllistenbase::finaliseAccepts() SSL Connection Ok => finaliseConnection"); - - if (0 > finaliseConnection(it->mFd, it->mSSL, it->mPeerId, it->mAddr)) - { - closeConnection(it->mFd, it->mSSL); - } - it = accepted_ssl.erase(it); - } - else if (active < 0) - { - pqioutput(PQL_WARNING, pqissllistenzone, - "pqissllistenbase::finaliseAccepts() SSL Connection Dead => closeConnection"); - - closeConnection(it->mFd, it->mSSL); - it = accepted_ssl.erase(it); - } - else if (now - it->mAcceptTS > ACCEPT_WAIT_TIME) - { - pqioutput(PQL_WARNING, pqissllistenzone, - "pqissllistenbase::finaliseAccepts() SSL Connection Timed Out => closeConnection"); - closeConnection(it->mFd, it->mSSL); - it = accepted_ssl.erase(it); - } - else - { - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, - "pqissllistenbase::finaliseAccepts() SSL Connection Status Unknown"); - ++it; - } - } - return 1; -} - -int pqissllistenbase::isSSLActive(int /*fd*/, SSL *ssl) -{ - - /* can we just get error? */ - int bufsize = 8; /* just a little look */ - uint8_t buf[bufsize]; - int err = SSL_peek(ssl, buf, bufsize); - if (err <= 0) - { - int ssl_err = SSL_get_error(ssl, err); - int err_err = ERR_get_error(); - - { - std::string out; - rs_sprintf(out, "pqissllistenbase::isSSLActive() Issues with SSL_Accept(%d)!\n", err); - printSSLError(ssl, err, ssl_err, err_err, out); - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, out); - } - - if (ssl_err == SSL_ERROR_ZERO_RETURN) - { - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, "pqissllistenbase::isSSLActive() SSL_ERROR_ZERO_RETURN Connection state unknown"); - - // zero means still continuing.... - return 0; - } - if ((ssl_err == SSL_ERROR_WANT_READ) || - (ssl_err == SSL_ERROR_WANT_WRITE)) - { - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, "pqissllistenbase::isSSLActive() SSL_ERROR_WANT_READ || SSL_ERROR_WANT_WRITE Connection state unknown"); - - // zero means still continuing.... - return 0; - } - else - { - std::string out; - rs_sprintf(out, "pqissllistenbase::isSSLActive() Issues with SSL Peek(%d) Likely the Connection was killed by Peer\n", err); - printSSLError(ssl, err, ssl_err, err_err, out); - pqioutput(PQL_ALERT, pqissllistenzone, out); - - return -1; - } - } - - pqioutput(PQL_WARNING, pqissllistenzone, "pqissllistenbase::isSSLActive() Successful Peer -> Connection Okay"); - - return 1; -} - -/************************ PQI SSL LISTENER **************************** - * - * This is the standard pqissl listener interface.... - * - * this class only allows connections from - * specific certificates, which are pre specified. - * - */ - -int pqissllistener::addlistenaddr(const RsPeerId& id, pqissl *acc) -{ - std::map::iterator it; - - std::string out = "Adding to Cert Listening Addresses Id: " + id.toStdString() + "\nCurrent Certs:\n"; - for(it = listenaddr.begin(); it != listenaddr.end(); ++it) - { - out += id.toStdString() + "\n"; - if (it -> first == id) - { - out += "pqissllistener::addlistenaddr() Already listening for Certificate!\n"; - - pqioutput(PQL_DEBUG_ALERT, pqissllistenzone, out); - return -1; - } - } - - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, out); - - // not there can accept it! - listenaddr[id] = acc; - return 1; -} - -int pqissllistener::removeListenPort(const RsPeerId& id) -{ - // check where the connection is coming from. - // if in list of acceptable addresses, - // - // check if in list. - std::map::iterator it; - for(it = listenaddr.begin();it!=listenaddr.end(); ++it) - { - if (it->first == id) - { - listenaddr.erase(it); - - pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, - "pqissllisten::removeListenPort() Success!"); - return 1; - } - } - - pqioutput(PQL_WARNING, pqissllistenzone, - "pqissllistener::removeListenPort() Failed to Find a Match"); - - return -1; -} - - -int pqissllistener::status() -{ - pqissllistenbase::status(); - // print certificates we are listening for. - std::map::iterator it; - - std::string out = "pqissllistener::status(): Listening ("; - out += sockaddr_storage_tostring(laddr); - out += ") for Certs:"; - for(it = listenaddr.begin(); it != listenaddr.end(); ++it) - { - out += "\n" + it -> first.toStdString() ; - } - pqioutput(PQL_DEBUG_ALL, pqissllistenzone, out); - - return 1; -} - -int pqissllistener::completeConnection(int fd, IncomingSSLInfo& info) -{ - constexpr int failure = -1; - constexpr int success = 1; - - // Get the Peer Certificate.... - X509* peercert = SSL_get_peer_certificate(info.ssl); - if(!peercert) - { - RsFatal() << __PRETTY_FUNCTION__ << " failed to retrieve peer " - << "certificate at this point this should never happen!" - << std::endl; - print_stacktrace(); - exit(failure); - } - - RsPgpId pgpId = RsX509Cert::getCertIssuer(*peercert); - RsPeerId newPeerId = RsX509Cert::getCertSslId(*peercert); - -#ifdef RS_PQISSL_AUTH_DOUBLE_CHECK - /* At this point the actual connection authentication has already been - * performed in AuthSSL::VerifyX509Callback, any furter authentication check - * like the followings are redundant. */ - - bool isSslOnlyFriend = rsPeers->isSslOnlyFriend(newPeerId); - - uint32_t authErrCode = 0; - if( !isSslOnlyFriend && - !AuthSSL::instance().AuthX509WithGPG(peercert,false, authErrCode) ) - { - RsFatal() << __PRETTY_FUNCTION__ << " failure verifying peer " - << "certificate signature. This should never happen at this " - << "point!" << std::endl; - print_stacktrace(); - - X509_free(peercert); // not needed but just in case we change to return - exit(failure); - } - - if( !isSslOnlyFriend && pgpId != AuthPGP::getPgpOwnId() && !AuthPGP::isPGPAccepted(pgpId) ) - { - RsFatal() << __PRETTY_FUNCTION__ << " pgpId: " << pgpId - << " is not friend. It is very unlikely to happen at this " - << "point! Either the user must have been so fast to deny " - << "friendship just after VerifyX509Callback have returned " - << "success and just before this code being executed, or " - << "something really fishy is happening! Share the full log " - << "with developers." << std::endl; - print_stacktrace(); - - X509_free(peercert); // not needed but just in case we change to return - exit(failure); - } -#endif //def RS_PQISSL_AUTH_REDUNDANT_CHECK - - bool found = false; - for(auto it = listenaddr.begin(); !found && it != listenaddr.end(); ) - { - if (it -> first == newPeerId) found = true; - else ++it; - } - - if (!found) - { - Dbg1() << __PRETTY_FUNCTION__ << " got secure connection from address: " - << info.addr << " with previously unknown SSL certificate: " - << newPeerId << " signed by PGP friend: " << pgpId - << ". Adding the new location as SSL friend." << std::endl; - - mPeerMgr->addFriend(newPeerId, pgpId); - } - - // Cleanup cert. - X509_free(peercert); - - // Pushback into Accepted List. - AcceptedSSL as; - as.mFd = fd; - as.mSSL = info.ssl; - as.mPeerId = newPeerId; - as.mAddr = info.addr; - as.mAcceptTS = time(nullptr); - - accepted_ssl.push_back(as); - - Dbg1() << __PRETTY_FUNCTION__ << "Successful Connection with: " - << newPeerId << " with address: " << info.addr << std::endl; - - return success; -} - -int pqissllistener::finaliseConnection(int fd, SSL *ssl, const RsPeerId& peerId, const struct sockaddr_storage &remote_addr) -{ - std::map::iterator it; - - std::string out = "pqissllistener::finaliseConnection()\n"; - out += "checking: " + peerId.toStdString() + "\n"; - // check if cert is in the list..... - - it = listenaddr.find(peerId); - if (it == listenaddr.end()) - { - out += "No Matching Peer for Connection:"; - out += sockaddr_storage_tostring(remote_addr); - out += "\npqissllistener => Shutting Down!"; - pqioutput(PQL_WARNING, pqissllistenzone, out); - return -1; - } - - out += "Found Matching Peer for Connection:"; - out += sockaddr_storage_tostring(remote_addr); - out += "\npqissllistener => Passing to pqissl module!"; - pqioutput(PQL_WARNING, pqissllistenzone, out); - - std::cerr << "pqissllistenner::finaliseConnection() connected to " << sockaddr_storage_tostring(remote_addr) << std::endl; - - // hand off ssl conection. - pqissl *pqis = it -> second; - pqis -> accept(ssl, fd, remote_addr); - - return 1; -} diff --git a/libretroshare/src/pqi/pqissllistener.h b/libretroshare/src/pqi/pqissllistener.h deleted file mode 100644 index 800ca876b..000000000 --- a/libretroshare/src/pqi/pqissllistener.h +++ /dev/null @@ -1,193 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqissllistener.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include - -#include -#include - -#include "pqi/pqi_base.h" -#include "pqi/pqilistener.h" -#include "pqi/authssl.h" -#include "util/rsdebug.h" -#include "pqi/pqinetwork.h" - -#define RS_PQISSL_AUTH_DOUBLE_CHECK 1 - - -// This is a simple overview of how the listener is setup, ticked (calling accept) and peers added to it. -// On the highest level (RsServer) the listener lives inside the pqisslpersongrp class (variable: "pqih"). -// Inside pqisslpersongrp the listener is stored in "pqil". -// -// The listener has an internal list with incoming connections that are handled in a similar fashion to pqissl. -// (Mainly setting up the socket (non-blocking) and establisching the ssl handshake.) -// When everything went fine the connection is passed to pqissl in finaliseConnection() -// -// This is how the listener is initialized during start up: -// -// RsServer::StartupRetroShare() -// | -// +----- pqih = new pqisslpersongrp(serviceCtrl, flags, mPeerMgr); -// +----- pqih->init_listener(); -// | -// +----- pqil = locked_createListener(laddr); -// | -// +----- return new pqissllistener(laddr, mPeerMgr); -// -// -// This is how the listener is ticked to call accept: -// -// RsServer::StartupRetroShare() -// | -// +----- pqih->tick(); -// | -// +----- pqil->tick(); -// | -// +----- acceptconnection(); -// | | -// | +----- accecpt() -// | -// +----- continueaccepts(); -// +----- finaliseAccepts(); -// | -// +----- finaliseConnection() -// | -// +----- pqis->accept() -// -// -// This is how peers (their id) are registered to the listener: -// (This is only used to tell if a connection peer is known or a new one (which is then added)) -// -// pqipersongrp::addPeer() -// | -// +----- pqiperson *pqip = locked_createPerson(id, pqil); -// | | -// | +----- pqiperson *pqip = new pqiperson(id, this); -// | +----- pqissl *pqis = new pqissl((pqissllistener *) listener, pqip, mLinkMgr); -// | +----- pqiconnect *pqisc = new pqiconnect(pqip, rss, pqis); -// | +----- pqip->addChildInterface(PQI_CONNECT_TCP, pqisc); -// | | -// | +-- sets kids[type] = pqisc; -// | -// +----- pqip->reset(); -// +----- pqip->listen(); -// | -// +-- for all kids[] -// | -// +----- listen() ( of class pqiconnect ) -// | -// +----- listen() ( of class pqissl ) -// | -// +----- pqil->addlistenaddr(PeerId(), this); - - -/***************************** pqi Net SSL Interface ********************************* - */ - -class pqissl; -class p3PeerMgr; - -class AcceptedSSL -{ -public: - int mFd; - SSL *mSSL; - RsPeerId mPeerId; - - sockaddr_storage mAddr; - rstime_t mAcceptTS; -}; - - - - -class pqissllistenbase: public pqilistener -{ -public: - pqissllistenbase(const struct sockaddr_storage &addr, p3PeerMgr *pm); - virtual ~pqissllistenbase(); - - /*************************************/ - /* LISTENER INTERFACE */ - virtual int tick(); - virtual int status(); - virtual int setListenAddr(const struct sockaddr_storage &addr); - virtual int setuplisten(); - virtual int resetlisten(); - /*************************************/ - - int acceptconnection(); - int continueaccepts(); - int finaliseAccepts(); - - struct IncomingSSLInfo - { - SSL *ssl ; - sockaddr_storage addr ; - RsPgpId gpgid ; - RsPeerId sslid ; - std::string sslcn ; - }; - - // fn to get cert, anyway - int continueSSL(IncomingSSLInfo&, bool); - int closeConnection(int fd, SSL *ssl); - int isSSLActive(int fd, SSL *ssl); - - virtual int completeConnection(int sockfd, IncomingSSLInfo&) = 0; - virtual int finaliseConnection(int fd, SSL *ssl, const RsPeerId& peerId, - const sockaddr_storage &raddr) = 0; - -protected: - struct sockaddr_storage laddr; - std::list accepted_ssl; - p3PeerMgr *mPeerMgr; - -private: - - bool active; - int lsock; - std::list incoming_ssl ; -}; - - -class pqissllistener: public pqissllistenbase -{ -public: - pqissllistener(const struct sockaddr_storage &addr, p3PeerMgr *pm) : - pqissllistenbase(addr, pm) {} - virtual ~pqissllistener() {} - - int addlistenaddr(const RsPeerId& id, pqissl *acc); - int removeListenPort(const RsPeerId& id); - - virtual int status(); - virtual int completeConnection(int sockfd, IncomingSSLInfo&); - virtual int finaliseConnection(int fd, SSL *ssl, const RsPeerId& peerId, - const sockaddr_storage &raddr); - - RS_SET_CONTEXT_DEBUG_LEVEL(2) - -private: - std::map listenaddr; -}; diff --git a/libretroshare/src/pqi/pqisslpersongrp.cc b/libretroshare/src/pqi/pqisslpersongrp.cc deleted file mode 100644 index 328d64cae..000000000 --- a/libretroshare/src/pqi/pqisslpersongrp.cc +++ /dev/null @@ -1,186 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqisslpersongrp.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "serialiser/rsserializer.h" -#include "services/autoproxy/rsautoproxymonitor.h" -#include "util/rsdebug.h" - -#include "pqi/pqisslpersongrp.h" -#include "pqi/authssl.h" - -static struct RsLog::logInfo pqipersongrpzoneInfo = {RsLog::Default, "pqipersongrp"}; -#define pqipersongrpzone &pqipersongrpzoneInfo - -/**** - * #define PQI_DISABLE_UDP 1 - ***/ - -/********************************** SSL Specific features ***************************/ - -#include "pqi/pqissl.h" -#include "pqi/pqissllistener.h" -#include "pqi/p3peermgr.h" - -//#define PQISSLPERSON_DEBUG - -#ifndef PQI_DISABLE_UDP - #include "pqi/pqissludp.h" -#endif - -#include "pqi/pqisslproxy.h" -#include "pqi/pqissli2psam3.h" - -pqilistener * pqisslpersongrp::locked_createListener(const struct sockaddr_storage &laddr) -{ - pqilistener *listener = new pqissllistener(laddr, mPeerMgr); - return listener; -} - -pqiperson * pqisslpersongrp::locked_createPerson(const RsPeerId& id, pqilistener *listener) -{ -#ifdef PQISSLPERSON_DEBUG - std::cerr << "pqisslpersongrp::locked_createPerson() PeerId: " << id; - std::cerr << std::endl; -#endif - - pqioutput(PQL_DEBUG_BASIC, pqipersongrpzone, "pqipersongrp::createPerson() PeerId: " + id.toStdString()); - - pqiperson *pqip = new pqiperson(id, this); - - // If using proxy, then only create a proxy item, otherwise can use any. - // If we are a hidden node - then all connections should be via proxy. - if (mPeerMgr->isHiddenPeer(id) || mPeerMgr->isHidden()) - { -#ifdef PQISTREAMER_DEBUG - std::cerr << "pqisslpersongrp::locked_createPerson() Is Hidden Peer!"; - std::cerr << std::endl; -#endif - - // Use pqicI2P for I2P - pqiconnect *pqicSOCKSProxy, *pqicI2P; - { - pqisslproxy *pqis = new pqisslproxy((pqissllistener *) listener, pqip, mLinkMgr); - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsRawSerialiser()); - pqicSOCKSProxy = new pqiconnect(pqip, rss, pqis); - } -#ifdef RS_USE_I2P_SAM3 - if (rsAutoProxyMonitor::instance()->isEnabled(autoProxyType::I2PSAM3)) - { - pqissli2psam3 *pqis = new pqissli2psam3((pqissllistener *) listener, pqip, mLinkMgr); - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsRawSerialiser()); - - pqicI2P = new pqiconnect(pqip, rss, pqis); - } - else -#endif // def RS_USE_I2P_SAM3 - pqicI2P = pqicSOCKSProxy; - - - /* first select type based on peer */ - uint32_t typePeer = mPeerMgr->getHiddenType(id); - switch (typePeer) { - case RS_HIDDEN_TYPE_TOR: - pqip -> addChildInterface(PQI_CONNECT_HIDDEN_TOR_TCP, pqicSOCKSProxy); - break; - case RS_HIDDEN_TYPE_I2P: - pqip -> addChildInterface(PQI_CONNECT_HIDDEN_I2P_TCP, pqicI2P); - break; - default: - /* peer is not a hidden one but we are */ - /* select type based on ourselves */ - uint32_t typeOwn = mPeerMgr->getHiddenType(AuthSSL::getAuthSSL()->OwnId()); - switch (typeOwn) { - case RS_HIDDEN_TYPE_I2P: - pqip -> addChildInterface(PQI_CONNECT_HIDDEN_I2P_TCP, pqicI2P); - break; - default: - /* this case shouldn't happen! */ - std::cerr << "pqisslpersongrp::locked_createPerson WARNING INVALID HIDDEN TYPES - THIS SHOULD NOT HAPPEN!" << std::endl; - std::cerr << " - ID: " << id << std::endl; - std::cerr << " - mPeerMgr->isHidden(): " << mPeerMgr->isHidden() << std::endl; - std::cerr << " - mPeerMgr->isHiddenPeer(id): " << mPeerMgr->isHiddenPeer(id) << std::endl; - std::cerr << " - hidden types: peer=" << typePeer << " own=" << typeOwn << std::endl; - std::cerr << " --> falling back to Tor" << std::endl; - /* fallthrough */ - case RS_HIDDEN_TYPE_TOR: - pqip -> addChildInterface(PQI_CONNECT_HIDDEN_TOR_TCP, pqicSOCKSProxy); - break; - } - } - } - else - { -#ifdef PQISTREAMER_DEBUG - std::cerr << "pqisslpersongrp::locked_createPerson() Is Normal Peer!"; - std::cerr << std::endl; -#endif - - pqissl *pqis = new pqissl((pqissllistener *) listener, pqip, mLinkMgr); - - /* construct the serialiser .... - * Needs: - * * FileItem - * * FileData - * * ServiceGeneric - */ - - ssl_tunnels[id] = pqis ; // keeps for getting crypt info per peer. - - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsRawSerialiser()); - - pqiconnect *pqisc = new pqiconnect(pqip, rss, pqis); - - pqip -> addChildInterface(PQI_CONNECT_TCP, pqisc); - -#ifndef PQI_DISABLE_UDP - pqissludp *pqius = new pqissludp(pqip, mLinkMgr); - - RsSerialiser *rss2 = new RsSerialiser(); - rss2->addSerialType(new RsRawSerialiser()); - - pqiconnect *pqiusc = new pqiconnect(pqip, rss2, pqius); - - // add a ssl + proxy interface. - // Add Proxy First. - pqip -> addChildInterface(PQI_CONNECT_UDP, pqiusc); -#endif - } - - return pqip; -} - -void pqisslpersongrp::disconnectPeer(const RsPeerId &peer) -{ - std::map::iterator it = ssl_tunnels.find(peer) ; - - if(it != ssl_tunnels.end()) - it->second->disconnect() ; - else - std::cerr << "pqisslpersongrp::cannot find peer " << peer << ". cannot disconnect!" << std::endl; -} - - -/********************************** SSL Specific features ***************************/ - - diff --git a/libretroshare/src/pqi/pqisslpersongrp.h b/libretroshare/src/pqi/pqisslpersongrp.h deleted file mode 100644 index ea94e616a..000000000 --- a/libretroshare/src/pqi/pqisslpersongrp.h +++ /dev/null @@ -1,53 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqisslpersongrp.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_SSL_PERSON_HANDLER_HEADER -#define MRK_PQI_SSL_PERSON_HANDLER_HEADER - -#include "pqi/pqipersongrp.h" - -class p3PeerMgr; -struct RsPeerCryptoParams; -class pqissl ; - -class pqisslpersongrp: public pqipersongrp -{ - public: - pqisslpersongrp(p3ServiceControl *ctrl, unsigned long flags, p3PeerMgr *pm) - :pqipersongrp(ctrl, flags), mPeerMgr(pm) { return; } - - protected: - - /********* FUNCTIONS to OVERLOAD for specialisation ********/ -virtual pqilistener *locked_createListener(const struct sockaddr_storage &laddr); -virtual pqiperson *locked_createPerson(const RsPeerId& id, pqilistener *listener); - /********* FUNCTIONS to OVERLOAD for specialisation ********/ - - virtual void disconnectPeer(const RsPeerId& peer) ; - - private: - - p3PeerMgr *mPeerMgr; - std::map ssl_tunnels ; -}; - - -#endif // MRK_PQI_SSL_PERSON_HANDLER_HEADER diff --git a/libretroshare/src/pqi/pqisslproxy.cc b/libretroshare/src/pqi/pqisslproxy.cc deleted file mode 100644 index 7a64a03a8..000000000 --- a/libretroshare/src/pqi/pqisslproxy.cc +++ /dev/null @@ -1,155 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqisslproxy.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2013 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "pqi/pqisslproxy.h" -#include "pqi/pqinetwork.h" - -#include -#include - -#include - -#include "util/rsdebug.h" -#include "util/rsnet.h" - -#include "pqi/p3linkmgr.h" - -static struct RsLog::logInfo pqisslproxyzoneInfo = {RsLog::Default, "pqisslproxy"}; -#define pqisslproxyzone &pqisslproxyzoneInfo - -// #define PROXY_DEBUG 1 -// #define PROXY_DEBUG_LOG 1 - -pqisslproxy::pqisslproxy(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm) - :pqissl(l, parent, lm) -{ - sockaddr_storage_clear(remote_addr); - return; -} - - -pqisslproxy::~pqisslproxy() -{ - rslog(RSL_ALERT, pqisslproxyzone, - "pqisslproxy::~pqisslproxy -> destroying pqisslproxy"); - - stoplistening(); - reset(); - - return; -} - -int pqisslproxy::Initiate_Connection() -{ - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Initiate_Connection()"; - std::cerr << std::endl; -#endif - - rslog(RSL_DEBUG_BASIC, pqisslproxyzone, - "pqisslproxy::Initiate_Connection() Connection to Proxy"); - /* init proxy state */ - proxy_init(); - - /* call standard Init_Conn() */ - return pqissl::Initiate_Connection(); -} - - -/********* VERY DIFFERENT **********/ -int pqisslproxy::Basic_Connection_Complete() -{ - rslog(RSL_DEBUG_BASIC, pqisslproxyzone, - "pqisslproxy::Basic_Connection_Complete()..."); - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Basic_Connection_Complete() STATE: " << mProxyState; - std::cerr << std::endl; -#endif - - if (CheckConnectionTimeout()) - { - // calls reset. - return -1; - } - - int ret; - - if(proxyConnectionState() == PROXY_STATE_INIT && 1!=(ret=pqissl::Basic_Connection_Complete())) - return ret; // basic connection not complete. - - ret = proxy_negociate_connection(sockfd); - - if(ret < 0) - reset_locked(); - - return ret; -} - -bool pqisslproxy::connect_parameter(uint32_t type, const std::string &value) -{ - { - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - - if (type == NET_PARAM_CONNECT_DOMAIN_ADDRESS) - { -#ifdef PROXY_DEBUG_LOG - std::string out; - rs_sprintf(out, "pqisslproxy::connect_parameter() Peer: %s DOMAIN_ADDRESS: %s", PeerId().toStdString().c_str(), value.c_str()); - rslog(RSL_WARNING, pqisslproxyzone, out); -#endif - setRemoteAddress(value); -#ifdef PROXY_DEBUG - std::cerr << out << std::endl; -#endif - return true; - } - } - - return pqissl::connect_parameter(type, value); -} - -bool pqisslproxy::connect_parameter(uint32_t type, uint32_t value) -{ - { - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - - if (type == NET_PARAM_CONNECT_REMOTE_PORT) - { - std::string out; - rs_sprintf(out, "pqisslproxy::connect_parameter() Peer: %s REMOTE_PORT: %lu", PeerId().toStdString().c_str(), value); -#ifdef PROXY_DEBUG_LOG - rslog(RSL_WARNING, pqisslproxyzone, out); -#endif - setRemotePort(value); -#ifdef PROXY_DEBUG - std::cerr << out << std::endl; -#endif - return true; - } - } - return pqissl::connect_parameter(type, value); -} - - - - diff --git a/libretroshare/src/pqi/pqisslproxy.h b/libretroshare/src/pqi/pqisslproxy.h deleted file mode 100644 index 7071f4dfb..000000000 --- a/libretroshare/src/pqi/pqisslproxy.h +++ /dev/null @@ -1,66 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqisslproxy.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2013 by Robert Fernie. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_SSL_PROXY_HEADER -#define MRK_PQI_SSL_PROXY_HEADER - -// operating system specific network header. -#include "pqi/pqinetwork.h" -#include "pqi/pqiproxy.h" - -#include -#include - -#include "pqi/pqissl.h" - - /* pqisslproxy uses SOCKS5 proxy to hidden your own address and connect to peers. - * It uses the Domain Name interface of SOCKS5, as opposed to an IP address. - */ - -/* This provides a NetBinInterface, which is - * primarily inherited from pqissl. - * fns declared here are different -> all others are identical. - */ - -class pqisslproxy: public pqissl, public pqiproxyconnection -{ -public: - pqisslproxy(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm); - virtual ~pqisslproxy(); - - // NetInterface. Is the same. - // BinInterface. Is the same. - - virtual bool connect_parameter(uint32_t type, const std::string &value); - virtual bool connect_parameter(uint32_t type, uint32_t value); - -protected: - - //Initiate is the same - except it uses the Proxy Address rather than the Peer Address. - // minor tweaks to setup data state. - virtual int Initiate_Connection(); - - // The real overloading is done in Basic Connection Complete. - // Instead of just checking for an open socket, we need to communicate with the SOCKS5 proxy. - virtual int Basic_Connection_Complete(); -}; - -#endif // MRK_PQI_SSL_PROXY_HEADER diff --git a/libretroshare/src/pqi/pqissludp.cc b/libretroshare/src/pqi/pqissludp.cc deleted file mode 100644 index 9700f7cdc..000000000 --- a/libretroshare/src/pqi/pqissludp.cc +++ /dev/null @@ -1,622 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqissludp.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie * - * Copyright (C) 2015-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "pqi/pqissludp.h" -#include "pqi/pqinetwork.h" - -#include "tcponudp/tou.h" -#include "tcponudp/bio_tou.h" - -#include -#include - - -#include "util/rsdebug.h" -#include "util/rsnet.h" -#include "util/rstime.h" -#include "util/rsstring.h" - -#include "pqi/p3linkmgr.h" -#include - -static struct RsLog::logInfo pqissludpzoneInfo = {RsLog::Default, "pqissludp"}; -#define pqissludpzone &pqissludpzoneInfo - - /* a final timeout, to ensure this never blocks completely - * 300 secs to complete udp/tcp/ssl connection. - * This is long as the udp connect can take some time. - */ - -static const uint32_t PQI_SSLUDP_DEF_CONN_PERIOD = 300; /* 5 minutes? */ - -/********** PQI SSL UDP STUFF **************************************/ - -pqissludp::pqissludp(PQInterface *parent, p3LinkMgr *lm) : - pqissl(nullptr, parent, lm), tou_bio(nullptr), - mConnectPeriod(PQI_SSLUDP_DEF_CONN_PERIOD), mConnectFlags(0), - mConnectBandwidth(0), mConnectProxyAddr(), mConnectSrcAddr() {} - -/* - * No need to call reset() here as it will be called in the upper class, - * pqissludp::reset_locked() just reset a few members to 0 that (that will be - * deleted anyway when this destructor ends), so pqissl::reset_locked() that is - * called by in parent class destructor will do just fine. - * - * DISCLAIMER: do not double free tou_bio here, as it is implicitely freed - * by SSL_free(...) in pqissl::reset() - */ -pqissludp::~pqissludp() = default; - - -int pqissludp::reset_locked() -{ - /* reset for next time.*/ - mConnectFlags = 0; - mConnectPeriod = PQI_SSLUDP_DEF_CONN_PERIOD; - - return pqissl::reset_locked(); -} - - - /* <===================== UDP Difference *******************/ - // The Proxy Version takes a few more step - // - // connectInterface is sent via message from the proxy. - // and is set here. - /* <===================== UDP Difference *******************/ - -int pqissludp::attach() -{ - // IN THE IMPROVED TOU LIBRARY, we need to be careful with the tou_socket PARAMETERS. - // For now, this should do! - sockfd = -1; - - if (mConnectFlags & RS_CB_FLAG_MODE_UDP_DIRECT) - { - std::cerr << "pqissludp::attach() Opening DIRECT Socket"; - std::cerr << std::endl; - sockfd = tou_socket(RSUDP_TOU_RECVER_DIRECT_IDX,TOU_RECEIVER_TYPE_UDPPEER,0); - } - else if (mConnectFlags & RS_CB_FLAG_MODE_UDP_PROXY) - { - std::cerr << "pqissludp::attach() Opening PROXY Socket"; - std::cerr << std::endl; - sockfd = tou_socket(RSUDP_TOU_RECVER_PROXY_IDX,TOU_RECEIVER_TYPE_UDPPEER,0); - } - else if (mConnectFlags & RS_CB_FLAG_MODE_UDP_RELAY) - { - std::cerr << "pqissludp::attach() Opening RELAY Socket"; - std::cerr << std::endl; - sockfd = tou_socket(RSUDP_TOU_RECVER_RELAY_IDX,TOU_RECEIVER_TYPE_UDPRELAY,0); - } - else - { - std::cerr << "pqissludp::attach() ERROR unknown Connect Mode" << std::endl; - std::cerr << "pqissludp::attach() mConnectFlags: " << std::hex << mConnectFlags << std::dec; - std::cerr << std::endl; - sockfd = -1; - } - - if (0 > sockfd) - { - rslog(RSL_WARNING, pqissludpzone, - "pqissludp::attach() failed to create a socket"); - return -1; - } - - // setup remote address - rslog(RSL_WARNING, pqissludpzone, - "pqissludp::attach() Opened Local Udp Socket"); - - return 1; -} - - -// The Address determination is done centrally -int pqissludp::Initiate_Connection() -{ - int err=0; - - attach(); /* open socket */ - //remote_addr.sin_family = AF_INET; - - rslog(RSL_DEBUG_BASIC, pqissludpzone, - "pqissludp::Initiate_Connection() Attempting Outgoing Connection...."); - - /* decide if we're active or passive */ - if (mConnectFlags & RS_CB_FLAG_ORDER_ACTIVE) - { - sslmode = PQISSL_ACTIVE; - } - else if (mConnectFlags & RS_CB_FLAG_ORDER_PASSIVE) - { - sslmode = PQISSL_PASSIVE; - } - else // likely UNSPEC - use old method to decide. - { - if (PeerId() < mLinkMgr->getOwnId()) - { - sslmode = PQISSL_ACTIVE; - } - else - { - sslmode = PQISSL_PASSIVE; - } - } - - if (waiting != WAITING_DELAY) - { - rslog(RSL_WARNING, pqissludpzone, - "pqissludp::Initiate_Connection() Already Attempt in Progress!"); - return -1; - } - - if (sockfd < 0) - { - rslog(RSL_ALERT, pqissludpzone, - "pqissludp::Initiate_Connection() Socket Creation Failed!"); - waiting = WAITING_FAIL_INTERFACE; - return -1; - } - - rslog(RSL_DEBUG_BASIC, pqissludpzone, - "pqissludp::Initiate_Connection() Opening Socket"); - - { - std::string out = "pqissludp::Initiate_Connection() Connecting To: " + PeerId().toStdString(); - out += " via: "; - out += sockaddr_storage_tostring(remote_addr); - out += " "; - - if (sslmode == PQISSL_ACTIVE) - { - out += "ACTIVE Connect (SSL_Connect)"; - } - else - { - out += "PASSIVE Connect (SSL_Accept)"; - } - rslog(RSL_WARNING, pqissludpzone, out); - } - - if (sockaddr_storage_isnull(remote_addr)) - { - rslog(RSL_WARNING, pqissludpzone, "pqissludp::Initiate_Connection() Invalid (0.0.0.0) Remote Address, Aborting Connect."); - waiting = WAITING_FAIL_INTERFACE; - - reset_locked(); - return -1; - } - - if(!sockaddr_storage_ipv6_to_ipv4(remote_addr)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error: remote_addr is not " - << "valid IPv4!" << std::endl; - sockaddr_storage_dump(remote_addr); - print_stacktrace(); - return -EINVAL; - } - - mTimeoutTS = time(NULL) + mConnectTimeout; - //std::cerr << "Setting Connect Timeout " << mConnectTimeout << " Seconds into Future " << std::endl; - //std::cerr << " Connect Period is:" << mConnectPeriod << std::endl; - - /* <===================== UDP Difference *******************/ - - if (mConnectFlags & RS_CB_FLAG_MODE_UDP_DIRECT) - { - err = tou_connect(sockfd, (struct sockaddr *) &remote_addr, sizeof(remote_addr), mConnectPeriod); - } - else if (mConnectFlags & RS_CB_FLAG_MODE_UDP_PROXY) - { - err = tou_connect(sockfd, (struct sockaddr *) &remote_addr, sizeof(remote_addr), mConnectPeriod); - } - else if (mConnectFlags & RS_CB_FLAG_MODE_UDP_RELAY) - { - std::cerr << __PRETTY_FUNCTION__ << " Calling tou_connect_via_relay(" - << sockaddr_storage_tostring(mConnectSrcAddr) << "," - << sockaddr_storage_tostring(mConnectProxyAddr) << "," - << sockaddr_storage_tostring(remote_addr) << ")" << std::endl; - - if(!sockaddr_storage_ipv6_to_ipv4(mConnectSrcAddr)) - { - std::cerr << __PRETTY_FUNCTION__ << " ERROR mConnectSrcAddr is " - << "not a valid IPv4!" << std::endl; - sockaddr_storage_dump(mConnectSrcAddr); - print_stacktrace(); - return -EINVAL; - } - if(!sockaddr_storage_ipv6_to_ipv4(mConnectProxyAddr)) - { - std::cerr << __PRETTY_FUNCTION__ << " ERROR mConnectProxyAddr " - << "is not a valid IPv4!" << std::endl; - sockaddr_storage_dump(mConnectProxyAddr); - print_stacktrace(); - return -EINVAL; - - } - - err = tou_connect_via_relay( - sockfd, - reinterpret_cast(mConnectSrcAddr), - reinterpret_cast(mConnectProxyAddr), - reinterpret_cast(remote_addr) ); - -/*** It seems that the UDP Layer sees x 1.2 the traffic of the SSL layer. - * We need to compensate somewhere... we drop the maximum traffic to 75% of limit - * to allow for extra lost packets etc. - * NB: If we have a lossy UDP transmission - re-transmission could cause excessive data to - * exceed the limit... This is difficult to account for without hacking the TcpOnUdp layer. - * If it is noticed as a problem - we'll deal with it then - */ -#define UDP_RELAY_TRANSPORT_OVERHEAD_FACTOR (0.7) - - parent()->setRateCap( UDP_RELAY_TRANSPORT_OVERHEAD_FACTOR * mConnectBandwidth / 1000.0, - UDP_RELAY_TRANSPORT_OVERHEAD_FACTOR * mConnectBandwidth / 1000.0); // Set RateCap. - } - - if (0 != err) - /* <===================== UDP Difference *******************/ - { - int tou_err = tou_errno(sockfd); - - std::string out = "pqissludp::Initiate_Connection()"; - - if ((tou_err == EINPROGRESS) || (tou_err == EAGAIN)) - { - // set state to waiting..... - waiting = WAITING_SOCK_CONNECT; - - out += " EINPROGRESS Waiting for Socket Connection"; - rslog(RSL_WARNING, pqissludpzone, out); - - return 0; - } - else if ((tou_err == ENETUNREACH) || (tou_err == ETIMEDOUT)) - { - out += "ENETUNREACHABLE: cert: " + PeerId().toStdString() + "\n"; - - // Then send unreachable message. - waiting = WAITING_FAIL_INTERFACE; - } - - rs_sprintf_append(out, "Error: Connection Failed: %d - %s", tou_err, socket_errorType(tou_err).c_str()); - - rslog(RSL_WARNING, pqissludpzone, out); - - reset_locked(); - - return -1; - } - else - { - rslog(RSL_DEBUG_BASIC, pqissludpzone, - "pqissludp::Init_Connection() connect returned 0"); - } - - waiting = WAITING_SOCK_CONNECT; - - rslog(RSL_DEBUG_BASIC, pqissludpzone, - "pqissludp::Initiate_Connection() Waiting for Socket Connect"); - - return 1; -} - -/********* VERY DIFFERENT **********/ -int pqissludp::Basic_Connection_Complete() -{ - rslog(RSL_DEBUG_BASIC, pqissludpzone, - "pqissludp::Basic_Connection_Complete()..."); - - if (CheckConnectionTimeout()) - { - return -1; - } - - if (waiting != WAITING_SOCK_CONNECT) - { - rslog(RSL_DEBUG_BASIC, pqissludpzone, - "pqissludp::Basic_Connection_Complete() Wrong Mode"); - return -1; - } - - - /* new approach is to check for an error */ - /* check for an error */ - int err; - if (0 != (err = tou_errno(sockfd))) - { - if (err == EINPROGRESS) - { - rslog(RSL_DEBUG_BASIC, pqissludpzone, "pqissludp::Basic_Connection_Complete() EINPROGRESS: cert: " + PeerId().toStdString()); - } - else if ((err == ENETUNREACH) || (err == ETIMEDOUT)) - { - rslog(RSL_WARNING, pqissludpzone, "pqissludp::Basic_Connection_Complete() ENETUNREACH/ETIMEDOUT: cert: " + PeerId().toStdString()); - - /* is the second one needed? */ - std::string out = "pqissludp::Basic_Connection_Complete() "; - rs_sprintf_append(out, "Error: Connection Failed: %d - %s", err, socket_errorType(err).c_str()); - rslog(RSL_DEBUG_BASIC, pqissludpzone, out); - - reset_locked(); - - // Then send unreachable message. - waiting = WAITING_FAIL_INTERFACE; - - return -1; - } - } - - /* <===================== UDP Difference *******************/ - if (tou_connected(sockfd)) - /* <===================== UDP Difference *******************/ - { - rslog(RSL_WARNING, pqissludpzone, "pqissludp::Basic_Connection_Complete() Connection Complete: cert: " + PeerId().toStdString()); - - return 1; - } - else - { - // not ready return -1; - rslog(RSL_DEBUG_BASIC, pqissludpzone, - "pqissludp::Basic_Connection_Complete() Not Yet Ready!"); - return 0; - } - - return -1; -} - - -/* New Internal Functions required to generalise tcp/udp version - * of the programs - */ - -// used everywhere -int pqissludp::net_internal_close(int fd) -{ - rslog(RSL_ALERT, pqissludpzone, - "pqissludp::net_internal_close() -> tou_close()"); - return tou_close(fd); -} - -// install udp BIO. -int pqissludp::net_internal_SSL_set_fd(SSL *ssl, int fd) -{ - rslog(RSL_DEBUG_BASIC, pqissludpzone, - "pqissludp::net_internal_SSL_set_fd()"); - - /* create the bio's */ - tou_bio =BIO_new(BIO_s_tou_socket()); - - /* attach the fd's to the BIO's */ - BIO_set_fd(tou_bio, fd, BIO_NOCLOSE); - SSL_set_bio(ssl, tou_bio, tou_bio); - return 1; -} - -bool pqissludp::connect_parameter(uint32_t type, uint32_t value) -{ - { - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - - //std::cerr << "pqissludp::connect_parameter() type: " << type << "value: " << value << std::endl; - if (type == NET_PARAM_CONNECT_PERIOD) - { - std::string out; - rs_sprintf(out, "pqissludp::connect_parameter() Peer: %s PERIOD: %lu", PeerId().toStdString().c_str(), value); - rslog(RSL_WARNING, pqissludpzone, out); - - mConnectPeriod = value; - std::cerr << out << std::endl; - return true; - } - else if (type == NET_PARAM_CONNECT_FLAGS) - { - std::string out; - rs_sprintf(out, "pqissludp::connect_parameter() Peer: %s FLAGS: %lu", PeerId().toStdString().c_str(), value); - rslog(RSL_WARNING, pqissludpzone, out); - - mConnectFlags = value; - std::cerr << out<< std::endl; - return true; - } - else if (type == NET_PARAM_CONNECT_BANDWIDTH) - { - std::string out; - rs_sprintf(out, "pqissludp::connect_parameter() Peer: %s BANDWIDTH: %lu", PeerId().toStdString().c_str(), value); - rslog(RSL_WARNING, pqissludpzone, out); - - mConnectBandwidth = value; - std::cerr << out << std::endl; - return true; - } - } - - return pqissl::connect_parameter(type, value); -} - -bool pqissludp::connect_additional_address(uint32_t type, const struct sockaddr_storage &addr) -{ - { - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - - if (type == NET_PARAM_CONNECT_PROXY) - { - std::string out; - rs_sprintf(out, "pqissludp::connect_additional_address() Peer: %s PROXYADDR: ", PeerId().toStdString().c_str()); - out += sockaddr_storage_tostring(addr); - rslog(RSL_WARNING, pqissludpzone, out); - - mConnectProxyAddr = addr; - - std::cerr << out << std::endl; - return true; - } - else if (type == NET_PARAM_CONNECT_SOURCE) - { - std::string out; - rs_sprintf(out, "pqissludp::connect_additional_address() Peer: %s SRCADDR: ", PeerId().toStdString().c_str()); - out += sockaddr_storage_tostring(addr); - rslog(RSL_WARNING, pqissludpzone, out); - - mConnectSrcAddr = addr; - - std::cerr << out << std::endl; - return true; - } - } - return pqissl::connect_additional_address(type, addr); -} - -/********** PQI STREAMER OVERLOADING *********************************/ - -bool pqissludp::moretoread(uint32_t usec) -{ - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - - // Extra Checks to avoid crashes in v0.6 ... pqithreadstreamer calls this function - // when sockfd = -1 during the shutdown of the thread. - // NB: it should never reach here if bio->isActive() returns false. - // Some mismatch to chase down when we have a chance. - // SAME test is at cansend. - if (sockfd < 0) - { - std::cerr << "pqissludp::moretoread() INVALID sockfd PARAMETER ... bad shutdown?"; - std::cerr << std::endl; - return false; - } - - - { - std::string out = "pqissludp::moretoread()"; - rs_sprintf_append(out, " polling socket (%d)", sockfd); - rslog(RSL_DEBUG_ALL, pqissludpzone, out); - } - - if (usec) - { - //std::cerr << "pqissludp::moretoread() usec parameter: " << usec; - //std::cerr << std::endl; - - if (0 < tou_maxread(sockfd)) - { - return true; - } - rstime::rs_usleep(usec); - } - - /* check for more to read first ... if nothing... check error - */ - /* <===================== UDP Difference *******************/ - if (tou_maxread(sockfd)) - /* <===================== UDP Difference *******************/ - { - rslog(RSL_DEBUG_BASIC, pqissludpzone, - "pqissludp::moretoread() Data to Read!"); - return 1; - } - - /* else check the error */ - rslog(RSL_DEBUG_ALL, pqissludpzone, - "pqissludp::moretoread() No Data to Read!"); - - int err; - if (0 != (err = tou_errno(sockfd))) - { - if ((err == EAGAIN) || (err == EINPROGRESS)) - { - rslog(RSL_DEBUG_BASIC, pqissludpzone, "pqissludp::moretoread() EAGAIN/EINPROGRESS: cert " + PeerId().toStdString()); - return 0; - - } - else if ((err == ENETUNREACH) || (err == ETIMEDOUT)) - { - rslog(RSL_WARNING, pqissludpzone, "pqissludp::moretoread() ENETUNREACH/ETIMEDOUT: cert " + PeerId().toStdString()); - } - else if (err == EBADF) - { - rslog(RSL_WARNING, pqissludpzone, "pqissludp::moretoread() EBADF: cert " + PeerId().toStdString()); - } - else - { - std::string out = "pqissludp::moretoread() "; - rs_sprintf_append(out, " Unknown ERROR: %d: cert ", err, PeerId().toStdString().c_str()); - rslog(RSL_WARNING, pqissludpzone, out); - } - - reset_locked(); - return 0; - } - - if(SSL_pending(ssl_connection) > 0) - return 1 ; - - /* otherwise - not error - strange! */ - rslog(RSL_DEBUG_BASIC, pqissludpzone, - "pqissludp::moretoread() No Data + No Error (really nothing)"); - - return 0; - - -} - -bool pqissludp::cansend(uint32_t usec) -{ - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - - // Extra Checks to avoid crashes in v0.6 ... pqithreadstreamer calls this function - // when sockfd = -1 during the shutdown of the thread. - // NB: it should never reach here if bio->isActive() returns false. - // Some mismatch to chase down when we have a chance. - // SAME test is at can moretoread. - if (sockfd < 0) - { - std::cerr << "pqissludp::cansend() INVALID sockfd PARAMETER ... bad shutdown?"; - std::cerr << std::endl; - return false; - } - - if (usec) - { - std::cerr << "pqissludp::cansend() usec parameter: " << usec; - std::cerr << std::endl; - - if (0 < tou_maxwrite(sockfd)) - { - return true; - } - - rstime::rs_usleep(usec); - } - - rslog(RSL_DEBUG_ALL, pqissludpzone, - "pqissludp::cansend() polling socket!"); - - /* <===================== UDP Difference *******************/ - return (0 < tou_maxwrite(sockfd)); - /* <===================== UDP Difference *******************/ - -} - - - diff --git a/libretroshare/src/pqi/pqissludp.h b/libretroshare/src/pqi/pqissludp.h deleted file mode 100644 index b716efb1e..000000000 --- a/libretroshare/src/pqi/pqissludp.h +++ /dev/null @@ -1,90 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqissludp.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie * - * Copyright (C) 2015-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include - -#include "pqi/pqissl.h" -#include "pqi/pqinetwork.h" -#include "util/rsdebug.h" - - -/** - * @brief pqissludp is the special NAT traversal protocol. - * This class will implement the basics of streaming ssl over udp using a - * tcponudp library. - * It provides a NetBinInterface, which is primarily inherited from pqissl. - * Some methods are override all others are identical. - */ -class pqissludp: public pqissl -{ -public: - pqissludp(PQInterface *parent, p3LinkMgr *lm); - ~pqissludp() override; - - int listen() override { return 1; } - int stoplistening() override { return 1; } - - virtual bool connect_parameter(uint32_t type, uint32_t value); - virtual bool connect_additional_address(uint32_t type, const struct sockaddr_storage &addr); - - // BinInterface. - // These are reimplemented. - virtual bool moretoread(uint32_t usec); - virtual bool cansend(uint32_t usec); - /* UDP always through firewalls -> always bandwidth Limited */ - virtual bool bandwidthLimited() { return true; } - -protected: - - // pqissludp specific. - // called to initiate a connection; - int attach(); - - virtual int reset_locked(); - - virtual int Initiate_Connection(); - virtual int Basic_Connection_Complete(); - - /* Do we really need this ? - * It is very specific UDP+ToU+SSL stuff and unlikely to be reused. - * In fact we are overloading them here becase they are very do different of pqissl. - */ - virtual int net_internal_close(int fd); - virtual int net_internal_SSL_set_fd(SSL *ssl, int fd); - virtual int net_internal_fcntl_nonblock(int /*fd*/) { return 0; } - -private: - - BIO *tou_bio; // specific to ssludp. - - uint32_t mConnectPeriod; - uint32_t mConnectFlags; - uint32_t mConnectBandwidth; - - struct sockaddr_storage mConnectProxyAddr; - struct sockaddr_storage mConnectSrcAddr; - - RS_SET_CONTEXT_DEBUG_LEVEL(2) -}; diff --git a/libretroshare/src/pqi/pqistore.cc b/libretroshare/src/pqi/pqistore.cc deleted file mode 100644 index 090a6a794..000000000 --- a/libretroshare/src/pqi/pqistore.cc +++ /dev/null @@ -1,575 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqistore.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -/* This is dependent on the sslroot at the moment. - * -> as we need to create/restore references to the Person. - * -> and store the signatures to do this. - */ - -/******************************************************************* - * pqistore provides an store stream. - * This stores RsItem + Person Reference + Timestamp, - * - * and allows Objects to be replayed or restored, - * independently of the rest of the pqi system. - * - */ - -#include "rsitems/rsitem.h" -#include "pqi/pqistore.h" -#include "serialiser/rsserial.h" -#include -#include - -#include "util/rsdebug.h" -#include "util/rsmemory.h" -#include "util/rsstring.h" - -// -// #define PQISTORE_DEBUG -// - -static struct RsLog::logInfo pqistorezoneInfo = {RsLog::Default, "pqistore"}; -#define pqistorezone &pqistorezoneInfo - -pqistore::pqistore(RsSerialiser *rss, const RsPeerId& srcId, BinInterface *bio_in, int bio_flags_in) - :PQInterface(RsPeerId()), rsSerialiser(rss), bio_flags(bio_flags_in), - nextPkt(NULL), mSrcId(srcId), bio(bio_in) -{ - pqioutput(PQL_DEBUG_ALL, pqistorezone, "pqistore::pqistore() Initialisation!"); - - if (!bio_in) - { - pqioutput(PQL_ALERT, pqistorezone, "pqistore::pqistore() NULL bio, FATAL ERROR!"); - exit(1); - } - - bStopReading=false; - return; -} - -pqistore::~pqistore() -{ - pqioutput(PQL_DEBUG_ALL, pqistorezone, "pqistore::~pqistore() Destruction!"); - - if (bio_flags & BIN_FLAGS_NO_CLOSE) - { - pqioutput(PQL_DEBUG_ALL, pqistorezone, "pqistore::~pqistore() Not Closing BinInterface!;"); - } - else if (bio) - { - pqioutput(PQL_DEBUG_ALL, pqistorezone, "pqistore::~pqistore() Deleting BinInterface!"); - - delete bio; - } - - if (rsSerialiser) - delete rsSerialiser; - - if (nextPkt) - { - delete nextPkt; - } - return; -} - - -// Get/Send Items. -int pqistore::SendItem(RsItem *si) -{ -#ifdef PQISTORE_DEBUG - { - std::string out = "pqistore::SendItem()\n"; - si -> print(out); - pqioutput(PQL_DEBUG_BASIC, pqistorezone, out); - } -#endif - - // check if this is a writing bio. - - if (!(bio_flags & BIN_FLAGS_WRITEABLE)) - { - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete si; - return -1; - } - -// std::cerr << "SendItem: si->PeerId()=" << si->PeerId() << std::endl ; - - int ret = writePkt(si); - return ret; /* 0 - failure, 1 - success*/ -} - -RsItem *pqistore::GetItem() -{ -#ifdef PQISTORE_DEBUG - pqioutput(PQL_DEBUG_ALL, pqistorezone, "pqistore::GetItem()"); -#endif - - bStopReading=false; - // check if this is a reading bio. - if (!(bio_flags & BIN_FLAGS_READABLE)) - { - pqioutput(PQL_DEBUG_BASIC, pqistorezone, "pqistore::GetItem() Error Not Readable"); - bStopReading=true; - return NULL; - } - - // load if we dont have a packet. - if (!nextPkt) - { - if (!readPkt(&nextPkt)) - { - pqioutput(PQL_DEBUG_BASIC, pqistorezone, "pqistore::GetItem() Failed to ReadPkt"); - return NULL; - } - } - - if (!nextPkt) return NULL; - - RsItem *outPkt = nextPkt; - nextPkt = NULL; - -#ifdef PQISTORE_DEBUG - if (outPkt != NULL) - { - std::string out = "pqistore::GetItem() Returning:\n"; - outPkt -> print(out); - pqioutput(PQL_DEBUG_BASIC, pqistorezone, out); - } -#endif - return outPkt; -} - - - - -// // PQInterface -int pqistore::tick() -{ -#ifdef PQISTORE_DEBUG - std::cerr << "pqistore::tick()" << std::endl; -#endif - return 0; -} - -int pqistore::status() -{ -#ifdef PQISTORE_DEBUG - pqioutput(PQL_DEBUG_ALL, pqistorezone, "pqistore::status()"); -#endif - return 0; -} - -// -/**************** HANDLE OUTGOING TRANSLATION + TRANSMISSION ******/ - -int pqistore::writePkt(RsItem *pqi) -{ -// std::cerr << "writePkt, pqi->peerId()=" << pqi->PeerId() << std::endl ; -#ifdef PQISTORE_DEBUG - pqioutput(PQL_DEBUG_ALL, pqistorezone, "pqistore::writePkt()"); -#endif - - uint32_t pktsize = rsSerialiser->size(pqi); - - RsTemporaryMemory ptr(pktsize) ; - - if(ptr == NULL) - return 0 ; - - if (!(rsSerialiser->serialise(pqi, ptr, &pktsize))) - { -#ifdef PQISTORE_DEBUG - std::string out = "pqistore::writePkt() Null Pkt generated!\nCaused By:\n"; - pqi -> print(out); - pqioutput(PQL_ALERT, pqistorezone, out); -#endif - - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete pqi; - return 0; - } - - /* extract the extra details */ - uint32_t len = getRsItemSize(ptr); - if (len != pktsize) - { - std::string out; - rs_sprintf(out, "pqistore::writePkt() Length MisMatch: len: %u!= pktsize: %u\nCaused By:\n", len, pktsize); - pqi -> print_string(out); - pqioutput(PQL_ALERT, pqistorezone, out); - - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete pqi; - return 0; - } - - - if (!(bio->cansend(0))) - { - std::string out; - rs_sprintf(out, "pqistore::writePkt() BIO cannot write!\niscarding:\n"); - pqi -> print_string(out); - pqioutput(PQL_ALERT, pqistorezone, out); - - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete pqi; - - return 0; - } - -#ifdef PQISTORE_DEBUG - std::string out = "Writing Pkt Body"; -#endif - // write packet. - if (len != (uint32_t) bio->senddata(ptr, len)) - { -#ifdef PQISTORE_DEBUG - out += " Problems with Send Data!"; - pqioutput(PQL_ALERT, pqistorezone, out); -#endif - - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete pqi; - - return 0; - } - -#ifdef PQISTORE_DEBUG - out += " Success!"; - pqioutput(PQL_DEBUG_BASIC, pqistorezone, out); -#endif - - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete pqi; - - return 1; -} - -/* Reads a single packet from the input stream - * gets the timestamp as well. - */ - -int pqistore::readPkt(RsItem **item_out) -{ -#ifdef PQISTORE_DEBUG - pqioutput(PQL_DEBUG_ALL, pqistorezone, "pqistore::readPkt()"); -#endif - bStopReading = false ; - - if ((!(bio->isactive())) || (!(bio->moretoread(0)))) - { - bStopReading = true ; - return 0; - } - - // initial read size: basic packet. - int blen = getRsPktBaseSize(); - void *block = rs_malloc(blen); - - if(block == NULL) - return false ; - - int tmplen; - /* we have the header */ - - // read the basic block (minimum packet size) - if (blen != (tmplen = bio->readdata(block, blen))) - { - pqioutput(PQL_WARNING, pqistorezone, "pqistore::readPkt() bad read(2)"); - - free(block); - bStopReading=true; - return 0; - } - - // workout how much more to read. - int blocklength = getRsItemSize(block); - - // make sure that blocklength is not a crazy number. If so, we drop the entire stream that might be corrupted. - - if(blocklength < blen || blocklength > 1024*1024*10) - { - std::cerr << "pqistore: ERROR: trying to realloc memory for packet of length" << blocklength <<", which is either too small, or exceeds the safety limit (10 MB)" << std::endl ; - free(block) ; - bStopReading=true; - return 0 ; - } - int extralen = blocklength - blen; - - void *tmp = realloc(block, blocklength); - - if (tmp == NULL) - { - free(block); - std::cerr << "pqistore: ERROR: trying to realloc memory for packet of length" << blocklength << std::endl ; - std::cerr << "Have you got enought memory?" << std::endl ; - bStopReading=true; - return 0 ; - } - else - block = tmp; - - if (extralen > 0) - { - void *extradata = (void *) (((char *) block) + blen); - - if (extralen != (tmplen = bio->readdata(extradata, extralen))) - { - std::string out; - rs_sprintf(out, "pqistore::readPkt() Error Completing Read (read %d/%d)", tmplen, extralen); - pqioutput(PQL_ALERT, pqistorezone, out); - bStopReading=true; - - free(block); - return 0; - } - } - - // create packet, based on header. - uint32_t readbytes = extralen + blen; - - RsItem *item = rsSerialiser->deserialise(block, &readbytes); - free(block); - - if (item == NULL) - { - pqioutput(PQL_ALERT, pqistorezone, "pqistore::readPkt() Failed to create Item from store!"); - return 0; - } - - item->PeerId(mSrcId); - *item_out = item; - return 1; -} - -/**** Hashing Functions ****/ -RsFileHash pqistore::gethash() -{ - return bio->gethash(); -} - -pqiSSLstore::pqiSSLstore(RsSerialiser *rss, const RsPeerId& srcId, BinEncryptedFileInterface* bio_in, int bio_flagsin) -: pqistore(rss, srcId, bio_in, bio_flagsin), enc_bio(bio_in) -{ - bStopReading=false; - return; -} - -pqiSSLstore::~pqiSSLstore() -{ - // no need to delete member enc_bio, as it is deleted by the parent class. - return; -} - -bool pqiSSLstore::encryptedSendItems(const std::list& rsItemList) -{ - - std::list::const_iterator it; - uint32_t sizeItems = 0, sizeItem = 0; - uint32_t offset = 0; - - for(it = rsItemList.begin(); it != rsItemList.end(); ++it) - if(*it != NULL) sizeItems += rsSerialiser->size(*it); - - RsTemporaryMemory data( sizeItems ? sizeItems : 1 ); - - for(it = rsItemList.begin(); it != rsItemList.end(); ++it) - if(*it != NULL) - { - sizeItem = rsSerialiser->size(*it); - - if(rsSerialiser->serialise(*it, &data[offset],&sizeItem)) - offset += sizeItem; - else - { - std::cerr << "(EE) pqiSSLstore::encryptedSendItems(): One item did not serialize. The item is probably unknown from the serializer. Dropping the item. " << std::endl; - std::cerr << "Item content: " << std::endl; - (*it)->print(std::cerr) ; - } - - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete *it; - } - - bool result = true; - - if(sizeItems == offset) - enc_bio->senddata(data, sizeItems); - else - result = false; - - return result; -} - -bool pqiSSLstore::getEncryptedItems(std::list& rsItemList) -{ - RsItem* item; - bStopReading=false; - - do - { - if (NULL != (item = GetItem())) - rsItemList.push_back(item); - - } while (enc_bio->isactive() && enc_bio->moretoread(0) && !bStopReading); - - return true; -} - - -RsItem *pqiSSLstore::GetItem() -{ -#ifdef PQISTORE_DEBUG - pqioutput(PQL_DEBUG_ALL, pqistorezone, "pqiSSLstore::GetItem()"); -#endif - - bStopReading=false; - // check if this is a reading bio. - if (!(bio_flags & BIN_FLAGS_READABLE)) - { - pqioutput(PQL_DEBUG_BASIC, pqistorezone, "pqiSSLstore::GetItem() Error Not Readable"); - bStopReading=true; - return NULL; - } - - // load if we dont have a packet. - if (!nextPkt) - { - if (!readPkt(&nextPkt)) - { - pqioutput(PQL_DEBUG_BASIC, pqistorezone, "pqiSSLstore::GetItem() Failed to ReadPkt"); - return NULL; - } - } - - if (!nextPkt) return NULL; - - RsItem *outPkt = nextPkt; - nextPkt = NULL; - -#ifdef PQISTORE_DEBUG - if (outPkt != NULL) - { - std::string out; - rs_sprintf(out, "pqiSSLstore::GetItem() Returning:\n"); - outPkt -> print(out); - pqioutput(PQL_DEBUG_BASIC, pqistorezone, out); - } -#endif - return outPkt; -} - - -int pqiSSLstore::readPkt(RsItem **item_out) -{ - *item_out = NULL ; -#ifdef PQISTORE_DEBUG - pqioutput(PQL_DEBUG_ALL, pqistorezone, "pqistore::readPkt()"); -#endif - - bStopReading=false ; - if ((!(enc_bio->isactive())) || (!(enc_bio->moretoread(0)))) - { - bStopReading=true ; - return 0; - } - - // initial read size: basic packet. - int blen = getRsPktBaseSize(); - void *block = rs_malloc(blen); - - if(block == NULL) - return false ; - - int tmplen; - /* we have the header */ - - // read the basic block (minimum packet size) - if (blen != (tmplen = enc_bio->readdata(block, blen))) - { - pqioutput(PQL_WARNING, pqistorezone, "pqiSSLstore::readPkt() bad read(2)"); - - free(block); - bStopReading=true; - return 0; - } - - // workout how much more to read. - int blocklength = getRsItemSize(block); - - if(blocklength < blen || blocklength > 1024*1024*10) - { - free(block); - std::cerr << "pqiSSLstore: ERROR: block length has invalid value " << blocklength << " (either too small, or exceeds the safety limit of 10 MB)" << std::endl ; - bStopReading=true; - return 0 ; - } - int extralen = blocklength - blen; - - void *tmp = realloc(block, blocklength); - - if (tmp == NULL) - { - free(block); - std::cerr << "pqiSSLstore: ERROR: trying to realloc memory for packet of length" << extralen+blen << std::endl ; - std::cerr << "Have you got enought memory?" << std::endl ; - bStopReading=true; - return 0 ; - } - else - block = tmp; - - if (extralen > 0) - { - void *extradata = (void *) (((char *) block) + blen); - - if (extralen != (tmplen = enc_bio->readdata(extradata, extralen))) - { - std::string out; - rs_sprintf(out, "pqiSSLstore::readPkt() Error Completing Read (read %d/%d)", tmplen, extralen); - pqioutput(PQL_ALERT, pqistorezone, out); - - free(block); - bStopReading=true; - return 0; - } - } - - // create packet, based on header. - uint32_t readbytes = extralen + blen; - - RsItem *item = rsSerialiser->deserialise(block, &readbytes); - free(block); - - if (item == NULL) - { - pqioutput(PQL_ALERT, pqistorezone, "pqiSSLstore::readPkt() Failed to create Item from store!"); - return 0; - } - - item->PeerId(mSrcId); - *item_out = item; - return 1; -} - diff --git a/libretroshare/src/pqi/pqistore.h b/libretroshare/src/pqi/pqistore.h deleted file mode 100644 index f8a586c67..000000000 --- a/libretroshare/src/pqi/pqistore.h +++ /dev/null @@ -1,109 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqistore.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_STORE_STREAMER_HEADER -#define MRK_PQI_STORE_STREAMER_HEADER - -#include "pqi/pqibin.h" - -#include - -/******************************************************************* - * pqistore provides a stream to file. - * objects only - like pqistreamer as opposed to pqiarchive. - * - */ - -class pqistore: public PQInterface -{ -public: - pqistore(RsSerialiser *rss, const RsPeerId&srcId, BinInterface *bio_in, int bio_flagsin); -virtual ~pqistore(); - -// PQInterface -virtual int SendItem(RsItem *); -virtual RsItem *GetItem(); - -virtual int tick(); -virtual int status(); - -RsFileHash gethash(); - -bool bStopReading; - -protected: - -// Serialiser -RsSerialiser *rsSerialiser; -unsigned int bio_flags; // only BIN_NO_CLOSE at the moment. - -// Temp Storage for transient data..... -RsItem *nextPkt; -RsPeerId mSrcId; - -private: - - int writePkt(RsItem *item); - int readPkt(RsItem **item_out); - - - - // Binary Interface for IO, initialisated at startup. - BinInterface *bio; - -}; - - -/*! - * provdes an ssl encrypted stream to file storage - */ -class pqiSSLstore: public pqistore -{ - -public: - - pqiSSLstore(RsSerialiser *rss, const RsPeerId& srcId, BinEncryptedFileInterface *bio_in, int bio_flagsin); - - virtual ~pqiSSLstore(); - - /*! - * send items encrypted to file using client's ssl key - */ - bool encryptedSendItems(const std::list&); - - /*! - * retrieve encrypted file using client's ssl key - */ - bool getEncryptedItems(std::list&); - -private: - - RsItem *GetItem(); - int readPkt(RsItem **item_out); - - BinEncryptedFileInterface* enc_bio; - - //bool bStopReading; - -}; - - -#endif //MRK_PQI_STORE_STREAMER_HEADER diff --git a/libretroshare/src/pqi/pqistreamer.cc b/libretroshare/src/pqi/pqistreamer.cc deleted file mode 100644 index 7f5a42301..000000000 --- a/libretroshare/src/pqi/pqistreamer.cc +++ /dev/null @@ -1,1448 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqistreamer.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "pqi/pqistreamer.h" - -#include // for gettimeofday -#include // for free, realloc, exit -#include // for memcpy, memset, memcmp -#include "util/rstime.h" // for NULL, time, rstime_t -#include // for min -#include // for operator<<, ostream, basic_ostream -#include // for string, allocator, operator<<, oper... -#include // for pair - -#include "pqi/p3notify.h" // for p3Notify -#include "retroshare/rsids.h" // for operator<< -#include "retroshare/rsnotify.h" // for RS_SYS_WARNING -#include "rsserver/p3face.h" // for RsServer -#include "serialiser/rsserial.h" // for RsItem, RsSerialiser, getRsItemSize -#include "util/rsdebug.h" // for pqioutput, PQL_ALERT, PQL_DEBUG_ALL -#include "util/rsmemory.h" // for rs_malloc -#include "util/rsprint.h" // for BinToHex -#include "util/rsstring.h" // for rs_sprintf_append, rs_sprintf - -static struct RsLog::logInfo pqistreamerzoneInfo = {RsLog::Default, "pqistreamer"}; -#define pqistreamerzone &pqistreamerzoneInfo - -static const int PQISTREAM_ABS_MAX = 100000000; /* 100 MB/sec (actually per loop) */ -static const int PQISTREAM_AVG_PERIOD = 1; // update speed estimate every second -static const float PQISTREAM_AVG_FRAC = 0.8; // for bandpass filter over speed estimate. -static const float PQISTREAM_AVG_DT_FRAC = 0.99; // for low pass filter over elapsed time - -static const int PQISTREAM_OPTIMAL_PACKET_SIZE = 512; // It is believed that this value should be lower than TCP slices and large enough as compare to encryption padding. - // most importantly, it should be constant, so as to allow correct QoS. -static const int PQISTREAM_SLICE_FLAG_STARTS = 0x01; // -static const int PQISTREAM_SLICE_FLAG_ENDS = 0x02; // these flags should be kept in the range 0x01-0x08 -static const int PQISTREAM_SLICE_PROTOCOL_VERSION_ID_01 = 0x10; // Protocol version ID. Should hold on the 4 lower bits. -static const int PQISTREAM_PARTIAL_PACKET_HEADER_SIZE = 8; // Same size than normal header, to make the code simpler. -static const int PQISTREAM_PACKET_SLICING_PROBE_DELAY = 60; // send every 60 secs. - -// This is a probe packet, that won't deserialise (it's empty) but will not cause problems to old peers either, since they will ignore -// it. This packet however will be understood by new peers as a signal to enable packet slicing. This should go when all peers use the -// same protocol. - -static uint8_t PACKET_SLICING_PROBE_BYTES[8] = { 0x02, 0xaa, 0xbb, 0xcc, 0x00, 0x00, 0x00, 0x08 } ; - -/* Change to true to disable packet slicing and/or packet grouping, if needed */ -#define DISABLE_PACKET_SLICING false -#define DISABLE_PACKET_GROUPING false - -/* This removes the print statements (which hammer pqidebug) */ -/*** -#define RSITEM_DEBUG 1 -#define DEBUG_TRANSFERS 1 -#define DEBUG_PQISTREAMER 1 -#define DEBUG_PACKET_SLICING 1 - ***/ - -#ifdef DEBUG_TRANSFERS - #include "util/rsprint.h" -#endif - -static double getCurrentTS() -{ -#ifndef WINDOWS_SYS - struct timeval cts_tmp; - gettimeofday(&cts_tmp, NULL); - double cts = (cts_tmp.tv_sec) + ((double) cts_tmp.tv_usec) / 1000000.0; -#else - struct _timeb timebuf; - _ftime( &timebuf); - double cts = (timebuf.time) + ((double) timebuf.millitm) / 1000.0; -#endif - return cts; -} - -pqistreamer::pqistreamer(RsSerialiser *rss, const RsPeerId& id, BinInterface *bio_in, int bio_flags_in) - :PQInterface(id), mStreamerMtx("pqistreamer"), - mBio(bio_in), mBio_flags(bio_flags_in), mRsSerialiser(rss), - mPkt_wpending(NULL), mPkt_wpending_size(0), - mTotalRead(0), mTotalSent(0), - mCurrRead(0), mCurrSent(0), - mAvgReadCount(0), mAvgSentCount(0), - mAvgDtOut(0), mAvgDtIn(0) -{ - - // 100 B/s (minimal) - setMaxRate(true, 0.1); - setMaxRate(false, 0.1); - setRate(true, 0); // needs to be off-mutex - setRate(false, 0); - - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - - mAcceptsPacketSlicing = false ; // by default. Will be turned into true when everyone's ready. - mLastSentPacketSlicingProbe = 0 ; - - mAvgLastUpdate = mCurrSentTS = mCurrReadTS = getCurrentTS(); - - mIncomingSize = 0 ; - mIncomingSize_bytes = 0; - - mStatisticsTimeStamp = 0 ; - /* allocated once */ - mPkt_rpend_size = 0; - mPkt_rpending = 0; - mReading_state = reading_state_initial ; - - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, "pqistreamer::pqistreamer() Initialisation!"); - - if (!bio_in) - { - pqioutput(PQL_ALERT, pqistreamerzone, "pqistreamer::pqistreamer() NULL bio, FATAL ERROR!"); - exit(1); - } - - mFailed_read_attempts = 0; // reset failed read, as no packet is still read. - - return; -} - -pqistreamer::~pqistreamer() -{ - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ -#ifdef DEBUG_PQISTREAMER - std::cerr << "Closing pqistreamer." << std::endl; -#endif - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, "pqistreamer::~pqistreamer() Destruction!"); - - if (mBio_flags & BIN_FLAGS_NO_CLOSE) - { - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, "pqistreamer::~pqistreamer() Not Closing BinInterface!"); - } - else if (mBio) - { - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, "pqistreamer::~pqistreamer() Deleting BinInterface!"); - - delete mBio; - } - - /* clean up serialiser */ - if (mRsSerialiser) - delete mRsSerialiser; - - free_pend() ; - - // clean up incoming. - while (!mIncoming.empty()) - { - RsItem *i = mIncoming.front(); - mIncoming.pop_front() ; - --mIncomingSize; - delete i; - } - - if (mIncomingSize != 0) - std::cerr << "(EE) inconsistency after deleting pqistreamer queue. Remaining items: " << mIncomingSize << std::endl ; - return; -} - - -// Get/Send Items. -// This is the entry poing for methods willing to send items through our out queue -int pqistreamer::SendItem(RsItem *si,uint32_t& out_size) -{ -#ifdef RSITEM_DEBUG - { - std::string out = "pqistreamer::SendItem():\n"; - si -> print_string(out); - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, out); - std::cerr << out; - } -#endif - - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - - return queue_outpqi_locked(si,out_size); -} - -RsItem *pqistreamer::GetItem() -{ -#ifdef DEBUG_PQISTREAMER - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, "pqistreamer::GetItem()"); -#endif - - if(mIncoming.empty()) - return NULL; - - RsItem *osr = mIncoming.front() ; - mIncoming.pop_front() ; - --mIncomingSize; -// for future use -// mIncomingSize_bytes -= - - return osr; -} - - -float pqistreamer::getMaxRate(bool b) -{ - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - return getMaxRate_locked(b); -} - -float pqistreamer::getMaxRate_locked(bool b) -{ - return RateInterface::getMaxRate(b) ; -} - -float pqistreamer::getRate(bool b) -{ - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - return RateInterface::getRate(b) ; -} - -void pqistreamer::setMaxRate(bool b,float f) -{ - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - setMaxRate_locked(b,f); -} - -void pqistreamer::setMaxRate_locked(bool b,float f) -{ - RateInterface::setMaxRate(b,f) ; -} - -void pqistreamer::setRate(bool b,float f) -{ - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - RateInterface::setRate(b,f) ; -} - - -void pqistreamer::updateRates() -{ - // update actual rates both ways. - - double t = getCurrentTS(); // get current timestamp. - double diff = t - mAvgLastUpdate; - - if (diff > PQISTREAM_AVG_PERIOD) - { - float avgReadpSec = PQISTREAM_AVG_FRAC * getRate(true ) + (1.0 - PQISTREAM_AVG_FRAC) * mAvgReadCount/(1024.0 * diff); - float avgSentpSec = PQISTREAM_AVG_FRAC * getRate(false) + (1.0 - PQISTREAM_AVG_FRAC) * mAvgSentCount/(1024.0 * diff); - -#ifdef DEBUG_PQISTREAMER - uint64_t t_now = 1000 * getCurrentTS(); - std::cerr << std::dec << t_now << " DEBUG_PQISTREAMER pqistreamer::updateRates PeerId " << this->PeerId().toStdString() << " Current speed estimates: down " << std::dec << (int)(1024 * avgReadpSec) << " B/s / up " << (int)(1024 * avgSentpSec) << " B/s" << std::endl; -#endif - - // now store the new rates, zero meaning that we are not bandwidthLimited() - - if (mBio->bandwidthLimited()) - { - setRate(true, avgReadpSec); - setRate(false, avgSentpSec); - } - else - { - setRate(true, 0); - setRate(false, 0); - } - - mAvgLastUpdate = t; - mAvgReadCount = 0; - - { - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - mAvgSentCount = 0; - } - } -} - -int pqistreamer::tick_bio() -{ - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - mBio->tick(); - - /* short circuit everything if bio isn't active */ - if (!(mBio->isactive())) - { - return 0; - } - return 1; -} - -int pqistreamer::tick_recv(uint32_t timeout) -{ - if (mBio->moretoread(timeout)) - { - handleincoming(); - } - if(!(mBio->isactive())) - { - RsStackMutex stack(mStreamerMtx); - free_pend(); - } - return 1; -} - -int pqistreamer::tick_send(uint32_t timeout) -{ - /* short circuit everything if bio isn't active */ - if (!(mBio->isactive())) - { - RsStackMutex stack(mStreamerMtx); - free_pend(); - return 0; - } - - if (mBio->cansend(timeout)) - { - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - handleoutgoing_locked(); - } - - return 1; -} - -int pqistreamer::status() -{ - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - - -#ifdef DEBUG_PQISTREAMER - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, "pqistreamer::status()"); - - if (mBio->isactive()) - { - std::string out; - rs_sprintf(out, "Data in:%d out:%d", mTotalRead, mTotalSent); - pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, out); - } -#endif - - return 0; -} - -// this method is overloaded by pqiqosstreamer -void pqistreamer::locked_storeInOutputQueue(void *ptr,int,int) -{ - RsDbg() << "Storing packet " << std::hex << ptr << std::dec << " in outqueue."; - mOutPkts.push_back(ptr); -} - -int pqistreamer::queue_outpqi_locked(RsItem *pqi,uint32_t& pktsize) -{ - pktsize = 0 ; -#ifdef DEBUG_PQISTREAMER - std::cerr << "pqistreamer::queue_outpqi() called." << std::endl; -#endif - - /* decide which type of packet it is */ - - pktsize = mRsSerialiser->size(pqi); - void *ptr = rs_malloc(pktsize); - - if(ptr == NULL) - return 0 ; - -#ifdef DEBUG_PQISTREAMER - std::cerr << "pqistreamer::queue_outpqi() serializing packet with packet size : " << pktsize << std::endl; -#endif - - /*******************************************************************************************/ - // keep info for stats for a while. Only keep the items for the last two seconds. sec n is ongoing and second n-1 - // is a full statistics chunk that can be used in the GUI - - locked_addTrafficClue(pqi,pktsize,mCurrentStatsChunk_Out) ; - - /*******************************************************************************************/ - - if (mRsSerialiser->serialise(pqi, ptr, &pktsize)) - { - locked_storeInOutputQueue(ptr,pktsize,pqi->priority_level()) ; - - if (!(mBio_flags & BIN_FLAGS_NO_DELETE)) - { - delete pqi; - } - return 1; - } - else - { - /* cleanup serialiser */ - free(ptr); - } - - std::string out = "pqistreamer::queue_outpqi() Null Pkt generated!\nCaused By:\n"; - pqi -> print_string(out); - pqioutput(PQL_ALERT, pqistreamerzone, out); - - if (!(mBio_flags & BIN_FLAGS_NO_DELETE)) - { - delete pqi; - } - return 1; // keep error internal. -} - -int pqistreamer::handleincomingitem(RsItem *pqi,int len) -{ - -#ifdef DEBUG_PQISTREAMER - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, "pqistreamer::handleincomingitem()"); -#endif - // timestamp last received packet. - mLastIncomingTs = time(NULL); - - // Use overloaded Contact function - pqi -> PeerId(PeerId()); - - mIncoming.push_back(pqi); - ++mIncomingSize; - // for future use - // mIncomingSize_bytes += len; - - /*******************************************************************************************/ - // keep info for stats for a while. Only keep the items for the last two seconds. sec n is ongoing and second n-1 - // is a full statistics chunk that can be used in the GUI - { - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - locked_addTrafficClue(pqi,len,mCurrentStatsChunk_In) ; - } - /*******************************************************************************************/ - - return 1; -} - -void pqistreamer::locked_addTrafficClue(const RsItem *pqi,uint32_t pktsize,std::list& lst) -{ - rstime_t now = time(NULL) ; - - if(now > mStatisticsTimeStamp) // new chunk => get rid of oldest, replace old list by current list, clear current list. - { - mPreviousStatsChunk_Out = mCurrentStatsChunk_Out ; - mPreviousStatsChunk_In = mCurrentStatsChunk_In ; - mCurrentStatsChunk_Out.clear() ; - mCurrentStatsChunk_In.clear() ; - - mStatisticsTimeStamp = now ; - } - - RSTrafficClue tc ; - tc.TS = now ; - tc.size = pktsize ; - tc.priority = pqi->priority_level() ; - tc.peer_id = pqi->PeerId() ; - tc.count = 1 ; - tc.service_id = pqi->PacketService() ; - tc.service_sub_id = pqi->PacketSubType() ; - - lst.push_back(tc) ; -} - -rstime_t pqistreamer::getLastIncomingTS() -{ - // This is the only case where another thread (rs main for pqiperson) will access our data - // Still a mutex lock is not needed because the operation is atomic - return mLastIncomingTs; -} - -// Packet slicing: -// -// Old : 02 0014 03 00000026 [data, 26 bytes] => [version 1B] [service 2B][subpacket 1B] [size 4B] -// New2: pp ff xxxxxxxx ssss [data, sss bytes] => [protocol version 1B] [flags 1B] [2^32 packet count] [2^16 size] -// -// Encode protocol on 1.0 Bytes ( 8 bits) -// Encode flags on 1.0 Bytes ( 8 bits) -// 0x01 => incomplete packet continued after -// 0x02 => packet ending a previously incomplete packet -// -// Encode packet ID on 4.0 Bytes (32 bits) => packet counter = [0...2^32] -// Encode size on 2.0 Bytes (16 bits) => 65536 // max slice size = 65536 -// -// Backward compatibility: -// * send one packet with service + subpacket = aabbcc. Old peers will silently ignore such packets. Full packet header is: 02aabbcc 00000008 -// * if received, mark the peer as able to decode the new packet type -// In pqiQoS: -// - limit packet grouping to max size 512. -// - new peers need to read flux, and properly extract partial sizes, and combine packets based on packet counter. -// - on sending, RS grabs slices of max size 1024 from pqiQoS. If smaller, possibly pack them together. -// pqiQoS keeps track of sliced packets and makes sure the output is consistent: -// * when a large packet needs to be send, only takes a slice and return it, and update the remaining part -// * always consider priority when taking new slices => a newly arrived fast packet will always get through. -// -// Max slice size should be customisable, depending on bandwidth. To be tested... -// - -int pqistreamer::handleoutgoing_locked() -{ -#ifdef DEBUG_PQISTREAMER - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, "pqistreamer::handleoutgoing_locked()"); -#endif - - int maxbytes = outAllowedBytes_locked(); - int sentbytes = 0; - - // std::cerr << "pqistreamer: maxbytes=" << maxbytes<< std::endl ; - - std::list::iterator it; - - // if not connection, or cannot send anything... pause. - if (!(mBio->isactive())) - { - /* if we are not active - clear anything in the queues. */ - locked_clear_out_queue() ; -#ifdef DEBUG_PACKET_SLICING - std::cerr << "(II) Switching off packet slicing." << std::endl; -#endif - mAcceptsPacketSlicing = false ; - - /* also remove the pending packets */ - if (mPkt_wpending) - { - free(mPkt_wpending); - mPkt_wpending = NULL; - mPkt_wpending_size = 0 ; - } - - return 0; - } - - // a very simple round robin - - bool sent = true; - int nsent = 0 ; - while(sent) // catch if all items sent. - { - sent = false; - - if ((!(mBio->cansend(0))) || (maxbytes < sentbytes)) - { -#ifdef DEBUG_PQISTREAMER - if (sentbytes > maxbytes) - RsDbg() << "PQISTREAMER pqistreamer::handleoutgoing_locked() stopped sending max reached, sentbytes " << std::dec << sentbytes << " maxbytes " << maxbytes; - else - RsDbg() << "PQISTREAMER pqistreamer::handleoutgoing_locked() stopped sending bio not ready, sentbytes " << std::dec << sentbytes << " maxbytes " << maxbytes; -#endif - return 0; - } - // send a out_pkt., else send out_data. unless there is a pending packet. The strategy is to - // - grab as many packets as possible while below the optimal packet size, so as to allow some packing and decrease encryption padding overhead (suposeddly) - // - limit packets size to OPTIMAL_PACKET_SIZE when sending big packets so as to keep as much QoS as possible. - - if (!mPkt_wpending) - { - void *dta; - mPkt_wpending_size = 0 ; - int k=0; - - // Checks for inserting a packet slicing probe. We do that to send the other peer the information that packet slicing can be used. - // if so, we enable it for the session. This should be removed (because it's unnecessary) when all users have switched to the new version. - rstime_t now = time(NULL) ; - - if(now > mLastSentPacketSlicingProbe + PQISTREAM_PACKET_SLICING_PROBE_DELAY) - { -#ifdef DEBUG_PACKET_SLICING - std::cerr << "(II) Inserting packet slicing probe in traffic" << std::endl; -#endif - - mPkt_wpending_size = 8 ; - mPkt_wpending = rs_malloc(8) ; - memcpy(mPkt_wpending,PACKET_SLICING_PROBE_BYTES,8) ; - - mLastSentPacketSlicingProbe = now ; - } - - uint32_t slice_size=0; - bool slice_starts=true ; - bool slice_ends=true ; - uint32_t slice_packet_id=0 ; - - do - { - int desired_packet_size = mAcceptsPacketSlicing?PQISTREAM_OPTIMAL_PACKET_SIZE:(getRsPktMaxSize()); - - dta = locked_pop_out_data(desired_packet_size,slice_size,slice_starts,slice_ends,slice_packet_id) ; - - if(!dta) - break ; - - if(slice_starts && slice_ends) // good old method. Send the packet as is, since it's a full packet. - { -#ifdef DEBUG_PACKET_SLICING - std::cerr << "sending full slice, old style. Size=" << slice_size << std::endl; -#endif - mPkt_wpending = realloc(mPkt_wpending,slice_size+mPkt_wpending_size) ; - memcpy( &((char*)mPkt_wpending)[mPkt_wpending_size],dta,slice_size) ; - free(dta); - mPkt_wpending_size += slice_size ; - ++k ; - } - else // partial packet. We make a special header for it and insert it in the stream - { - if(slice_size > 0xffff || !mAcceptsPacketSlicing) - { - std::cerr << "(EE) protocol error in pqitreamer: slice size is too large and cannot be encoded." ; - free(mPkt_wpending) ; - mPkt_wpending_size = 0; - return -1 ; - } -#ifdef DEBUG_PACKET_SLICING - std::cerr << "sending partial slice, packet ID=" << std::hex << slice_packet_id << std::dec << ", size=" << slice_size << std::endl; -#endif - - mPkt_wpending = realloc(mPkt_wpending,slice_size+mPkt_wpending_size+PQISTREAM_PARTIAL_PACKET_HEADER_SIZE) ; - memcpy( &((char*)mPkt_wpending)[mPkt_wpending_size+PQISTREAM_PARTIAL_PACKET_HEADER_SIZE],dta,slice_size) ; - free(dta); - - // New2: pp ff xxxxxxxx ssss [data, sss bytes] => [flags 1B] [protocol version 1B] [2^32 packet count] [2^16 size] - - uint8_t partial_flags = 0 ; - if(slice_starts) partial_flags |= PQISTREAM_SLICE_FLAG_STARTS ; - if(slice_ends ) partial_flags |= PQISTREAM_SLICE_FLAG_ENDS ; - - ((char*)mPkt_wpending)[mPkt_wpending_size+0x00] = PQISTREAM_SLICE_PROTOCOL_VERSION_ID_01 ; - ((char*)mPkt_wpending)[mPkt_wpending_size+0x01] = partial_flags ; - ((char*)mPkt_wpending)[mPkt_wpending_size+0x02] = uint8_t(slice_packet_id >> 24) & 0xff ; - ((char*)mPkt_wpending)[mPkt_wpending_size+0x03] = uint8_t(slice_packet_id >> 16) & 0xff ; - ((char*)mPkt_wpending)[mPkt_wpending_size+0x04] = uint8_t(slice_packet_id >> 8) & 0xff ; - ((char*)mPkt_wpending)[mPkt_wpending_size+0x05] = uint8_t(slice_packet_id >> 0) & 0xff ; - ((char*)mPkt_wpending)[mPkt_wpending_size+0x06] = uint8_t(slice_size >> 8) & 0xff ; - ((char*)mPkt_wpending)[mPkt_wpending_size+0x07] = uint8_t(slice_size >> 0) & 0xff ; - - mPkt_wpending_size += slice_size + PQISTREAM_PARTIAL_PACKET_HEADER_SIZE; - ++k ; - } - } - while(mPkt_wpending_size < (uint32_t)maxbytes && mPkt_wpending_size < PQISTREAM_OPTIMAL_PACKET_SIZE && !DISABLE_PACKET_GROUPING) ; - -#ifdef DEBUG_PQISTREAMER - if(k > 1) - std::cerr << "Packed " << k << " packets into " << mPkt_wpending_size << " bytes." << std::endl; -#endif - } - - if (mPkt_wpending) - { - // write packet. -#ifdef DEBUG_PQISTREAMER - std::cout << "Sending Out Pkt of size " << mPkt_wpending_size << " !" << std::endl; -#endif - int ss=0; - - if (mPkt_wpending_size != (uint32_t)(ss = mBio->senddata(mPkt_wpending, mPkt_wpending_size))) - { -#ifdef DEBUG_PQISTREAMER - std::string out; - rs_sprintf(out, "Problems with Send Data! (only %d bytes sent, total pkt size=%d)", ss, mPkt_wpending_size); - // std::cerr << out << std::endl ; - pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, out); -#endif - std::cerr << PeerId() << ": sending failed. Only " << ss << " bytes sent over " << mPkt_wpending_size << std::endl; - - // pkt_wpending will kept til next time. - // ensuring exactly the same data is written (openSSL requirement). - return -1; - } -#ifdef DEBUG_PQISTREAMER - else - std::cerr << PeerId() << ": sent " << ss << " bytes " << std::endl; -#endif - - ++nsent; - - outSentBytes_locked(mPkt_wpending_size); // this is the only time where we know exactly what was sent. - -#ifdef DEBUG_TRANSFERS - std::cerr << "pqistreamer::handleoutgoing_locked() Sent Packet len: " << mPkt_wpending_size << " @ " << getCurrentTS(); - std::cerr << std::endl; -#endif - - sentbytes += mPkt_wpending_size; - - free(mPkt_wpending); - mPkt_wpending = NULL; - mPkt_wpending_size = 0 ; - - sent = true; - } - } -#ifdef DEBUG_PQISTREAMER - if(nsent > 0) - std::cerr << "nsent = " << nsent << ", total bytes=" << sentbytes << std::endl; -#endif - return 1; -} - - -/* Handles reading from input stream. - */ -int pqistreamer::handleincoming() -{ - int readbytes = 0; - static const int max_failed_read_attempts = 2000 ; - -#ifdef DEBUG_PQISTREAMER - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, "pqistreamer::handleincoming()"); -#endif - - if(!(mBio->isactive())) - { - RsStackMutex stack(mStreamerMtx); - mReading_state = reading_state_initial ; - free_pend(); - return 0; - } - else - allocate_rpend(); - - // enough space to read any packet. - uint32_t maxlen = mPkt_rpend_size; - void *block = mPkt_rpending; - - // initial read size: basic packet. - int blen = getRsPktBaseSize(); // this is valid for both packet slices and normal un-sliced packets (same header size) - - int maxin = inAllowedBytes(); - -#ifdef DEBUG_PQISTREAMER - std::cerr << "[" << (void*)pthread_self() << "] " << "reading state = " << mReading_state << std::endl ; -#endif - switch(mReading_state) - { - case reading_state_initial: /*std::cerr << "jumping to start" << std::endl; */ goto start_packet_read ; - case reading_state_packet_started: /*std::cerr << "jumping to middle" << std::endl;*/ goto continue_packet ; - } - -start_packet_read: - { // scope to ensure variable visibility - // read the basic block (minimum packet size) - int tmplen; -#ifdef DEBUG_PQISTREAMER - std::cerr << "[" << (void*)pthread_self() << "] " << "starting packet" << std::endl ; -#endif - memset(block,0,blen) ; // reset the block, to avoid uninitialized memory reads. - - if (blen != (tmplen = mBio->readdata(block, blen))) - { - pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, "pqistreamer::handleincoming() Didn't read BasePkt!"); - - // error.... (either blocked or failure) - if (tmplen == 0) - { -#ifdef DEBUG_PQISTREAMER - // most likely blocked! - pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, "pqistreamer::handleincoming() read blocked"); - std::cerr << "[" << (void*)pthread_self() << "] " << "given up 1" << std::endl ; -#endif - return 0; - } - else if (tmplen < 0) - { - // Most likely it is that the packet is pending but could not be read by pqissl because of stream flow. - // So we return without an error, and leave the machine state in 'start_read'. - // - //pqioutput(PQL_WARNING, pqistreamerzone, "pqistreamer::handleincoming() Error in bio read"); -#ifdef DEBUG_PQISTREAMER - std::cerr << "[" << (void*)pthread_self() << "] " << "given up 2, state = " << mReading_state << std::endl ; -#endif - return 0; - } - else // tmplen > 0 - { - // strange case....This should never happen as partial reads are handled by pqissl below. -#ifdef DEBUG_PQISTREAMER - std::string out = "pqistreamer::handleincoming() Incomplete "; - rs_sprintf_append(out, "(Strange) read of %d bytes", tmplen); - pqioutput(PQL_ALERT, pqistreamerzone, out); - - std::cerr << "[" << (void*)pthread_self() << "] " << "given up 3" << std::endl ; -#endif - return -1; - } - } -#ifdef DEBUG_PQISTREAMER - std::cerr << "[" << (void*)pthread_self() << "] " << "block 0 : " << RsUtil::BinToHex((unsigned char*)block,8) << std::endl; -#endif - - readbytes += blen; - mReading_state = reading_state_packet_started ; - mFailed_read_attempts = 0 ; // reset failed read, as the packet has been totally read. - - // Check for packet slicing probe (04/26/2016). To be removed when everyone uses it. - - if(!memcmp(block,PACKET_SLICING_PROBE_BYTES,8)) - { - mAcceptsPacketSlicing = !DISABLE_PACKET_SLICING; -#ifdef DEBUG_PACKET_SLICING - std::cerr << "(II) Enabling packet slicing!" << std::endl; -#endif - mReading_state = reading_state_initial ; // restart at state 1. - mFailed_read_attempts = 0 ; - return 0; - } - } -continue_packet: - { - // workout how much more to read. - - bool is_partial_packet = false ; - bool is_packet_starting = (((char*)block)[1] == PQISTREAM_SLICE_FLAG_STARTS) ; // STARTS and ENDS flags are actually never combined. - bool is_packet_ending = (((char*)block)[1] == PQISTREAM_SLICE_FLAG_ENDS) ; - bool is_packet_middle = (((char*)block)[1] == 0x00) ; - - uint32_t extralen =0; - uint32_t slice_packet_id =0; - - if( ((char*)block)[0] == PQISTREAM_SLICE_PROTOCOL_VERSION_ID_01 && ( is_packet_starting || is_packet_middle || is_packet_ending)) - { - extralen = (uint32_t(((uint8_t*)block)[6]) << 8 ) + (uint32_t(((uint8_t*)block)[7])); - slice_packet_id = (uint32_t(((uint8_t*)block)[2]) << 24) + (uint32_t(((uint8_t*)block)[3]) << 16) + (uint32_t(((uint8_t*)block)[4]) << 8) + (uint32_t(((uint8_t*)block)[5]) << 0); - -#ifdef DEBUG_PACKET_SLICING - std::cerr << "Reading partial packet from mem block " << RsUtil::BinToHex((char*)block,8) << ": packet_id=" << std::hex << slice_packet_id << std::dec << ", len=" << extralen << std::endl; -#endif - is_partial_packet = true ; - - mAcceptsPacketSlicing = !DISABLE_PACKET_SLICING; // this is needed - } - else - extralen = getRsItemSize(block) - blen; // old style packet type - -#ifdef DEBUG_PACKET_SLICING - std::cerr << "[" << (void*)pthread_self() << "] " << "continuing packet getRsItemSize(block) = " << getRsItemSize(block) << std::endl ; - std::cerr << "[" << (void*)pthread_self() << "] " << "continuing packet extralen = " << extralen << std::endl ; - - std::cerr << "[" << (void*)pthread_self() << "] " << "continuing packet state=" << mReading_state << std::endl ; - std::cerr << "[" << (void*)pthread_self() << "] " << "block 1 : " << RsUtil::BinToHex((unsigned char*)block,8) << std::endl; -#endif - if (extralen + (uint32_t)blen > maxlen) - { - pqioutput(PQL_ALERT, pqistreamerzone, "ERROR: Read Packet too Big!"); - - p3Notify *notify = RsServer::notify(); - if (notify) - { - std::string title = - "Warning: Bad Packet Read"; - - std::string msg; - msg = " **** WARNING **** \n"; - msg += "Retroshare has caught a BAD Packet Read"; - msg += "\n"; - msg += "This is normally caused by connecting to an"; - msg += " OLD version of Retroshare"; - msg += "\n"; - rs_sprintf_append(msg, "(M:%d B:%d E:%d)\n", maxlen, blen, extralen); - msg += "\n"; - msg += "block = " ; - msg += RsUtil::BinToHex((char*)block,8); - - msg += "\n"; - msg += "Please get your friends to upgrade to the latest version"; - msg += "\n"; - msg += "\n"; - msg += "If you are sure the error was not caused by an old version"; - msg += "\n"; - msg += "Please report the problem to Retroshare's developers"; - msg += "\n"; - - notify->AddLogMessage(0, RS_SYS_WARNING, title, msg); - - std::cerr << "pqistreamer::handle_incoming() ERROR: Read Packet too Big" << std::endl; - std::cerr << msg; - std::cerr << std::endl; - - } - mBio->close(); - mReading_state = reading_state_initial ; // restart at state 1. - mFailed_read_attempts = 0 ; - return -1; - - // Used to exit now! exit(1); - } - - if (extralen > 0) - { - void *extradata = (void *) (((char *) block) + blen); - int tmplen ; - - // Don't reset the block now! If pqissl is in the middle of a multiple-chunk - // packet (larger than 16384 bytes), and pqistreamer jumped directly yo - // continue_packet:, then readdata is going to write after the beginning of - // extradata, yet not exactly at start -> the start of the packet would be wiped out. - // - // so, don't do that: - // memset( extradata,0,extralen ) ; - - if (extralen != (uint32_t)(tmplen = mBio->readdata(extradata, extralen))) - { -#ifdef DEBUG_PACKET_SLICING - if(tmplen > 0) - std::cerr << "[" << (void*)pthread_self() << "] " << "Incomplete packet read ! This is a real problem ;-)" << std::endl ; -#endif - - if(++mFailed_read_attempts > max_failed_read_attempts) - { - std::string out; - rs_sprintf(out, "Error Completing Read (read %d/%d)", tmplen, extralen); - std::cerr << out << std::endl ; - pqioutput(PQL_ALERT, pqistreamerzone, out); - - p3Notify *notify = RsServer::notify(); - if (notify) - { - std::string title = "Warning: Error Completing Read"; - - std::string msgout; - msgout = " **** WARNING **** \n"; - msgout += "Retroshare has experienced an unexpected Read ERROR"; - msgout += "\n"; - rs_sprintf_append(msgout, "(M:%d B:%d E:%d R:%d)\n", maxlen, blen, extralen, tmplen); - msgout += "\n"; - msgout += "Note: this error might as well happen (rarely) when a peer disconnects in between a transmission of a large packet.\n"; - msgout += "If it happens manny time, please contact the developers, and send them these numbers:"; - msgout += "\n"; - - msgout += "block = " ; - msgout += RsUtil::BinToHex((char*)block,8) + "\n" ; - - std::cerr << msgout << std::endl; - } - - mBio->close(); - mReading_state = reading_state_initial ; // restart at state 1. - mFailed_read_attempts = 0 ; - return -1; - } - else - { -#ifdef DEBUG_PQISTREAMER - std::cerr << "[" << (void*)pthread_self() << "] " << "given up 5, state = " << mReading_state << std::endl ; -#endif - return 0 ; // this is just a SSL_WANT_READ error. Don't panic, we'll re-try the read soon. - // we assume readdata() returned either -1 or the complete read size. - } - } -#ifdef DEBUG_PACKET_SLICING - std::cerr << "[" << (void*)pthread_self() << "] " << "continuing packet state=" << mReading_state << std::endl ; - std::cerr << "[" << (void*)pthread_self() << "] " << "block 2 : " << RsUtil::BinToHex((unsigned char*)extradata,8) << std::endl; -#endif - - mFailed_read_attempts = 0 ; - readbytes += extralen; - } - - // create packet, based on header. -#ifdef DEBUG_PQISTREAMER - { - std::string out; - rs_sprintf(out, "Read Data Block -> Incoming Pkt(%d)", blen + extralen); - //std::cerr << out ; - pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, out); - } -#endif - - uint32_t pktlen = blen+extralen ; -#ifdef DEBUG_PQISTREAMER - std::cerr << "[" << (void*)pthread_self() << "] " << RsUtil::BinToHex((char*)block,8) << "...: deserializing. Size=" << pktlen << std::endl ; -#endif - RsItem *pkt ; - - if(is_partial_packet) - { -#ifdef DEBUG_PACKET_SLICING - std::cerr << "Inputing partial packet " << RsUtil::BinToHex((char*)block,8) << std::endl; -#endif - uint32_t packet_length = 0 ; - pkt = addPartialPacket(block,pktlen,slice_packet_id,is_packet_starting,is_packet_ending,packet_length) ; - - pktlen = packet_length ; - } - else - pkt = mRsSerialiser->deserialise(block, &pktlen); - - if ((pkt != NULL) && (0 < handleincomingitem(pkt,pktlen))) - { -#ifdef DEBUG_PQISTREAMER - pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, "Successfully Read a Packet!"); -#endif - inReadBytes(pktlen); // only count deserialised packets, because that's what is actually been transfered. - } - else if (!is_partial_packet) - { -#ifdef DEBUG_PQISTREAMER - pqioutput(PQL_ALERT, pqistreamerzone, "Failed to handle Packet!"); -#endif - std::cerr << "Incoming Packet could not be deserialised:" << std::endl; - std::cerr << " Incoming peer id: " << PeerId() << std::endl; - if(pktlen >= 8) - std::cerr << " Packet header : " << RsUtil::BinToHex((unsigned char*)block,8) << std::endl; - if(pktlen > 8) - std::cerr << " Packet data : " << RsUtil::BinToHex((unsigned char*)block+8,std::min(50u,pktlen-8)) << ((pktlen>58)?"...":"") << std::endl; - } - - mReading_state = reading_state_initial ; // restart at state 1. - mFailed_read_attempts = 0 ; // reset failed read, as the packet has been totally read. - } - - if(maxin > readbytes && mBio->moretoread(0)) - goto start_packet_read ; - -#ifdef DEBUG_PQISTREAMER - if (readbytes > maxin) - RsDbg() << "PQISTREAMER pqistreamer::handleincoming() stopped reading max reached, readbytes " << std::dec << readbytes << " maxin " << maxin; - else - RsDbg() << "PQISTREAMER pqistreamer::handleincoming() stopped reading no more to read, readbytes " << std::dec << readbytes << " maxin " << maxin; -#endif - - return 0; -} - -RsItem *pqistreamer::addPartialPacket(const void *block, uint32_t len, uint32_t slice_packet_id, bool is_packet_starting, bool is_packet_ending, uint32_t &total_len) -{ -#ifdef DEBUG_PACKET_SLICING - std::cerr << "Receiving partial packet. size=" << len << ", ID=" << std::hex << slice_packet_id << std::dec << ", starting:" << is_packet_starting << ", ending:" << is_packet_ending ; -#endif - - if(is_packet_starting && is_packet_ending) - { - std::cerr << " (EE) unexpected situation: both starting and ending" << std::endl; - return NULL ; - } - - uint32_t slice_length = len - PQISTREAM_PARTIAL_PACKET_HEADER_SIZE ; - unsigned char *slice_data = &((unsigned char*)block)[PQISTREAM_PARTIAL_PACKET_HEADER_SIZE] ; - - std::map::iterator it = mPartialPackets.find(slice_packet_id) ; - - if(it == mPartialPackets.end()) - { - // make sure we really have a starting packet. Otherwise this is an error. - - if(!is_packet_starting) - { - std::cerr << " (EE) non starting packet has no record. Dropping" << std::endl; - return NULL ; - } - PartialPacketRecord& rec = mPartialPackets[slice_packet_id] ; - - rec.mem = rs_malloc(slice_length) ; - - if(!rec.mem) - { - std::cerr << " (EE) Cannot allocate memory for slice of size " << slice_length << std::endl; - return NULL ; - } - - memcpy(rec.mem, slice_data, slice_length) ; ; - rec.size = slice_length ; - -#ifdef DEBUG_PACKET_SLICING - std::cerr << " => stored in new record (size=" << rec.size << std::endl; -#endif - - return NULL ; // no need to check for ending - } - else - { - PartialPacketRecord& rec = it->second ; - - if(is_packet_starting) - { - std::cerr << "(WW) dropping unfinished existing packet that gets to be replaced by new starting packet." << std::endl; - free(rec.mem); - rec.mem = NULL ; - rec.size = 0 ; - } - // make sure this is a continuing packet, otherwise this is an error. - - rec.mem = realloc(rec.mem, rec.size + slice_length) ; - memcpy( &((char*)rec.mem)[rec.size],slice_data,slice_length) ; - rec.size += slice_length ; - -#ifdef DEBUG_PACKET_SLICING - std::cerr << " => added to existing record size=" << rec.size ; -#endif - - if(is_packet_ending) - { -#ifdef DEBUG_PACKET_SLICING - std::cerr << " => deserialising: mem=" << RsUtil::BinToHex((char*)rec.mem,std::min(8u,rec.size)) << std::endl; -#endif - RsItem *item = mRsSerialiser->deserialise(rec.mem, &rec.size); - - total_len = rec.size ; - free(rec.mem) ; - mPartialPackets.erase(it) ; - return item ; - } - else - { -#ifdef DEBUG_PACKET_SLICING - std::cerr << std::endl; -#endif - return NULL ; - } - } -} - -/* BandWidth Management Assistance */ - -float pqistreamer::outTimeSlice_locked() -{ -#ifdef DEBUG_PQISTREAMER - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, "pqistreamer::outTimeSlice()"); -#endif - - //fixme("pqistreamer::outTimeSlice()", 1); - return 1; -} - -int pqistreamer::outAllowedBytes_locked() -{ - double t = getCurrentTS() ; // in sec, with high accuracy - - // allow a lot if not bandwidthLimited() - if (!mBio->bandwidthLimited()) - { - mCurrSent = 0; - mCurrSentTS = t; - return PQISTREAM_ABS_MAX; - } - - // dt is the time elapsed since the last round of sending data - double dt = t - mCurrSentTS; - - // ignore cases where dt > 1s - if (dt > 1) - dt = 1; - - // low pass filter on mAvgDtOut - mAvgDtOut = PQISTREAM_AVG_DT_FRAC * mAvgDtOut + (1 - PQISTREAM_AVG_DT_FRAC) * dt; - - double maxout = getMaxRate_locked(false) * 1024.0; - - // this is used to take into account a possible excess of data sent during the previous round - mCurrSent -= int(dt * maxout); - - // we dont allow negative value, any quota not used during the previous round is therefore lost - if (mCurrSent < 0) - mCurrSent = 0; - - mCurrSentTS = t; - - // now calculate the amount of data allowed to be sent during the next round - // we take into account the possible excess (but not deficit) of the previous round - // (this is handled differently when reading data, see below) - double quota = mAvgDtOut * maxout - mCurrSent; - -#ifdef DEBUG_PQISTREAMER - RsDbg() << "PQISTREAMER pqistreamer::outAllowedBytes_locked() dt " << std::dec << (int)(1000 * dt) << "ms, mAvgDtOut " << (int)(1000 * mAvgDtOut) << "ms, maxout " << (int)(maxout) << " bytes/s, mCurrSent " << mCurrSent << " bytes, quota " << (int)(quota) << " bytes"; -#endif - - return quota; -} - -int pqistreamer::inAllowedBytes() -{ - double t = getCurrentTS(); // in sec, with high accuracy - - // allow a lot if not bandwidthLimited() - if (!mBio->bandwidthLimited()) - { - mCurrRead = 0; - mCurrReadTS = t; - return PQISTREAM_ABS_MAX; - } - - // dt is the time elapsed since the last round of receiving data - double dt = t - mCurrReadTS; - - // limit dt to 1s - if (dt > 1) - dt = 1; - - // low pass filter on mAvgDtIn - mAvgDtIn = PQISTREAM_AVG_DT_FRAC * mAvgDtIn + (1 - PQISTREAM_AVG_DT_FRAC) * dt; - - double maxin = getMaxRate(true) * 1024.0; - - // this is used to take into account a possible excess/deficit of data received during the previous round - mCurrRead -= int(dt * maxin); - - // we allow negative value up to the average amount of data received during one round - // in that case we will use this credit during the next around - if (mCurrRead < - mAvgDtIn * maxin) - mCurrRead = - mAvgDtIn * maxin; - - mCurrReadTS = t; - - // we now calculate the max amount of data allowed to be received during the next round - // we take into account the excess/deficit of the previous round - double quota = mAvgDtIn * maxin - mCurrRead; - -#ifdef DEBUG_PQISTREAMER - RsDbg() << "PQISTREAMER pqistreamer::inAllowedBytes() dt " << std::dec << (int)(1000 * dt) << "ms, mAvgDtIn " << (int)(1000 * mAvgDtIn) << "ms, maxin " << (int)(maxin) << " bytes/s, mCurrRead " << mCurrRead << " bytes, quota " << (int)(quota) << " bytes"; -#endif - - return quota; -} - -void pqistreamer::outSentBytes_locked(uint32_t outb) -{ -#ifdef DEBUG_PQISTREAMER - { - std::string out; - rs_sprintf(out, "pqistreamer::outSentBytes(): %d@%gkB/s", outb, RateInterface::getRate(false)); - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, out); - } -#endif - - /*** One theory for the massive delays - is that the queue here is filling up ****/ -//#define DEBUG_LAG 1 -#ifdef DEBUG_LAG - -#define MIN_PKTS_FOR_MSG 100 - if (out_queue_size() > MIN_PKTS_FOR_MSG) - { - std::cerr << "pqistreamer::outSentBytes() for: " << PeerId(); - std::cerr << " End of Write and still " << out_queue_size() << " pkts left"; - std::cerr << std::endl; - } - -#endif - mTotalSent += outb; - mCurrSent += outb; - mAvgSentCount += outb; - PQInterface::traf_out += outb; - return; -} - -void pqistreamer::inReadBytes(uint32_t inb) -{ -#ifdef DEBUG_PQISTREAMER - { - std::string out; - rs_sprintf(out, "pqistreamer::inReadBytes(): %d@%gkB/s", inb, RateInterface::getRate(true)); - pqioutput(PQL_DEBUG_ALL, pqistreamerzone, out); - } -#endif - - mTotalRead += inb; - mCurrRead += inb; - mAvgReadCount += inb; - PQInterface::traf_in += inb; - return; -} - -void pqistreamer::allocate_rpend() -{ - if(mPkt_rpending) - return; - - mPkt_rpend_size = getRsPktMaxSize(); - mPkt_rpending = rs_malloc(mPkt_rpend_size); - - if(mPkt_rpending == NULL) - return ; - - // avoid uninitialized (and random) memory read. - memset(mPkt_rpending,0,mPkt_rpend_size) ; -} - -// clean everything that is half-finished, to avoid causing issues when re-connecting later on. - -int pqistreamer::reset() -{ - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ -#ifdef DEBUG_PQISTREAMER - std::cerr << "pqistreamer::reset()" << std::endl; -#endif - free_pend(); - - return 1 ; -} - -void pqistreamer::free_pend() -{ - if(mPkt_rpending) - { -#ifdef DEBUG_PQISTREAMER - std::cerr << "pqistreamer::free_pend(): pending input packet buffer" << std::endl; -#endif - free(mPkt_rpending); - mPkt_rpending = 0; - } - mPkt_rpend_size = 0; - - if (mPkt_wpending) - { -#ifdef DEBUG_PQISTREAMER - std::cerr << "pqistreamer::free_pend(): pending output packet buffer" << std::endl; -#endif - free(mPkt_wpending); - mPkt_wpending = NULL; - } - mPkt_wpending_size = 0 ; - -#ifdef DEBUG_PQISTREAMER - if(!mPartialPackets.empty()) - std::cerr << "pqistreamer::free_pend(): " << mPartialPackets.size() << " pending input partial packets" << std::endl; -#endif - // also delete any incoming partial packet - for(std::map::iterator it(mPartialPackets.begin());it!=mPartialPackets.end();++it) - free(it->second.mem) ; - - mPartialPackets.clear() ; - - // clean up outgoing. (cntrl packets) - locked_clear_out_queue() ; -} - -int pqistreamer::gatherStatistics(std::list& outqueue_lst,std::list& inqueue_lst) -{ - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - - return locked_gatherStatistics(outqueue_lst,inqueue_lst); -} - -// this method is overloaded by pqiqosstreamer -int pqistreamer::getQueueSize(bool in) -{ - if (in) -// no mutex is needed here because this is atomic - return mIncomingSize; - else - { - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - return locked_out_queue_size(); - } -} - -int pqistreamer::getQueueSize_bytes(bool in) -{ - if (in) -// no mutex is needed here because this is atomic -// for future use, mIncomingSize_bytes is not updated yet - return mIncomingSize_bytes; - else - { - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - return locked_compute_out_pkt_size(); - } -} - -void pqistreamer::getRates(RsBwRates &rates) -{ - RateInterface::getRates(rates); - -// no mutex is needed here because this is atomic - rates.mQueueIn = mIncomingSize; - - { - RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/ - rates.mQueueOut = locked_out_queue_size(); - } -} - -// this method is overloaded by pqiqosstreamer -int pqistreamer::locked_out_queue_size() const -{ - // Warning: because out_pkt is a list, calling size - // is O(n) ! Makign algorithms pretty inefficient. We should record how many - // items get stored and discarded to have a proper size value at any time - // - return mOutPkts.size() ; -} - -// this method is overloaded by pqiqosstreamer -void pqistreamer::locked_clear_out_queue() -{ - for(std::list::iterator it = mOutPkts.begin(); it != mOutPkts.end(); ) - { - free(*it); - it = mOutPkts.erase(it); -#ifdef DEBUG_PQISTREAMER - std::string out = "pqistreamer::locked_clear_out_queue() Not active -> Clearing Pkt!"; - std::cerr << out << std::endl; - pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, out); -#endif - } -} - -// this method is overloaded by pqiqosstreamer -int pqistreamer::locked_compute_out_pkt_size() const -{ - int total = 0 ; - - for(std::list::const_iterator it = mOutPkts.begin(); it != mOutPkts.end(); ++it) - total += getRsItemSize(*it); - - return total ; -} - -int pqistreamer::locked_gatherStatistics(std::list& out_lst,std::list& in_lst) -{ - out_lst = mPreviousStatsChunk_Out ; - in_lst = mPreviousStatsChunk_In ; - - return 1 ; -} - -// this method is overloaded by pqiqosstreamer -void *pqistreamer::locked_pop_out_data(uint32_t /*max_slice_size*/, uint32_t &size, bool &starts, bool &ends, uint32_t &packet_id) -{ - size = 0 ; - starts = true ; - ends = true ; - packet_id = 0 ; - - void *res = NULL ; - - if (!mOutPkts.empty()) - { - res = *(mOutPkts.begin()); - mOutPkts.pop_front(); - - // In pqistreamer, we do not split outgoing packets. For now only pqiQoSStreamer supports packet slicing. - size = getRsItemSize(res); - -#ifdef DEBUG_TRANSFERS - std::cerr << "pqistreamer::locked_pop_out_data() getting next pkt " << std::hex << res << std::dec << " from mOutPkts queue"; - std::cerr << std::endl; -#endif - } - return res ; -} - diff --git a/libretroshare/src/pqi/pqistreamer.h b/libretroshare/src/pqi/pqistreamer.h deleted file mode 100644 index 0e7f6b815..000000000 --- a/libretroshare/src/pqi/pqistreamer.h +++ /dev/null @@ -1,190 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqistreamer.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_STREAMER_HEADER -#define MRK_PQI_STREAMER_HEADER - -#include // for uint32_t -#include "util/rstime.h" // for rstime_t -#include // for operator<<, basic_ostream, cerr, endl -#include // for list -#include // for map - -#include "pqi/pqi_base.h" // for BinInterface (ptr only), PQInterface -#include "retroshare/rsconfig.h" // for RSTrafficClue -#include "retroshare/rstypes.h" // for RsPeerId -#include "util/rsthreads.h" // for RsMutex - -struct RsItem; -class RsSerialiser; - -struct PartialPacketRecord -{ - void *mem ; - uint32_t size ; -}; - -/** - * @brief Fully implements the PQInterface and communicates with peer etc via - * the BinInterface. - * The interface does not handle connection, just communication. - * Possible BIN_FLAGS: BIN_FLAGS_NO_CLOSE | BIN_FLAGS_NO_DELETE - */ -class pqistreamer: public PQInterface -{ - public: - pqistreamer(RsSerialiser *rss, const RsPeerId& peerid, BinInterface *bio_in, int bio_flagsin); - virtual ~pqistreamer(); - - // PQInterface - virtual int SendItem(RsItem *item) - { - std::cerr << "Warning pqistreamer::sendItem(RsItem*) should not be called. Plz call SendItem(RsItem *,uint32_t& serialized_size) instead." << std::endl; - uint32_t serialized_size ; - return SendItem(item,serialized_size) ; - } - virtual int SendItem(RsItem *,uint32_t& serialized_size); - virtual RsItem *GetItem(); - virtual int status(); - - rstime_t getLastIncomingTS(); // Time of last data packet, for checking a connection is alive. - virtual void getRates(RsBwRates &rates); - virtual int getQueueSize(bool in); // extracting data. - virtual int getQueueSize_bytes(bool in); // size of incoming queue in bytes - virtual int gatherStatistics(std::list& outqueue_stats,std::list& inqueue_stats); // extracting data. - - // mutex protected versions of RateInterface calls. - virtual void setRate(bool b,float f) ; - virtual void setMaxRate(bool b,float f) ; - virtual void setMaxRate_locked(bool b,float f) ; - - virtual float getRate(bool b) ; - virtual float getMaxRate(bool b) ; - virtual float getMaxRate_locked(bool b); - - protected: - virtual int reset() ; - - int tick_bio(); - int tick_send(uint32_t timeout); - int tick_recv(uint32_t timeout); - - /* Implementation */ - - // These methods are redefined in pqiQoSstreamer - // - virtual void locked_storeInOutputQueue(void *ptr, int size, int priority) ; - virtual int locked_out_queue_size() const ; - virtual void locked_clear_out_queue() ; - virtual int locked_compute_out_pkt_size() const ; - virtual void *locked_pop_out_data(uint32_t max_slice_size,uint32_t& size,bool& starts,bool& ends,uint32_t& packet_id); - virtual int locked_gatherStatistics(std::list& outqueue_stats,std::list& inqueue_stats); // extracting data. - - void updateRates() ; - - protected: - RsMutex mStreamerMtx ; // Protects data, fns below, protected so pqiqos can use it too. - - // Binary Interface for IO, initialisated at startup. - BinInterface *mBio; - unsigned int mBio_flags; // BIN_FLAGS_NO_CLOSE | BIN_FLAGS_NO_DELETE - - private: - int queue_outpqi_locked(RsItem *i,uint32_t& serialized_size); - int handleincomingitem(RsItem *i, int len); - - // ticked regularly (manages out queues and sending - // via above interfaces. - virtual int handleoutgoing_locked(); - virtual int handleincoming(); - - // Bandwidth/Streaming Management. - float outTimeSlice_locked(); - - int outAllowedBytes_locked(); - void outSentBytes_locked(uint32_t ); - - int inAllowedBytes(); - void inReadBytes(uint32_t ); - - // cleans up everything that's pending / half finished. - void free_pend(); - - // RsSerialiser - determines which packets can be serialised. - RsSerialiser *mRsSerialiser; - - void *mPkt_wpending; // storage for pending packet to write. - uint32_t mPkt_wpending_size; // ... and its size. - - void allocate_rpend(); // use these two functions to allocate/free the buffer below - - int mPkt_rpend_size; // size of pkt_rpending. - void *mPkt_rpending; // storage for read in pending packets. - - enum {reading_state_packet_started=1, reading_state_initial=0 } ; - - int mReading_state ; - int mFailed_read_attempts ; - - // Temp Storage for transient data..... - std::list mOutPkts; // Cntrl / Search / Results queue - std::list mIncoming; - - uint32_t mIncomingSize; // size of mIncoming. To avoid calling linear cost std::list::size() - uint32_t mIncomingSize_bytes; // size of Incoming in btyes - - // data for network stats. - int mTotalRead; - int mTotalSent; - - // these are representative (but not exact) - int mCurrRead; - int mCurrSent; - - double mCurrReadTS; // TS from which these are measured. - double mCurrSentTS; - - double mAvgLastUpdate; // TS from which these are measured. - uint32_t mAvgReadCount; - uint32_t mAvgSentCount; - - double mAvgDtOut; // average time diff between 2 rounds of sending data - double mAvgDtIn; // average time diff between 2 rounds of receiving data - - rstime_t mLastIncomingTs; - - // traffic statistics - - std::list mPreviousStatsChunk_In ; - std::list mPreviousStatsChunk_Out ; - std::list mCurrentStatsChunk_In ; - std::list mCurrentStatsChunk_Out ; - rstime_t mStatisticsTimeStamp ; - - bool mAcceptsPacketSlicing ; - rstime_t mLastSentPacketSlicingProbe ; - void locked_addTrafficClue(const RsItem *pqi, uint32_t pktsize, std::list &lst); - RsItem *addPartialPacket(const void *block, uint32_t len, uint32_t slice_packet_id,bool packet_starting,bool packet_ending,uint32_t& total_len); - - std::map mPartialPackets ; -}; - -#endif //MRK_PQI_STREAMER_HEADER diff --git a/libretroshare/src/pqi/pqithreadstreamer.cc b/libretroshare/src/pqi/pqithreadstreamer.cc deleted file mode 100644 index 6745dc864..000000000 --- a/libretroshare/src/pqi/pqithreadstreamer.cc +++ /dev/null @@ -1,101 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqithreadstreamer.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2013 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "util/rstime.h" -#include "pqi/pqithreadstreamer.h" -#include - -#define DEFAULT_STREAMER_TIMEOUT 10000 // 10 ms -#define DEFAULT_STREAMER_SLEEP 30000 // 30 ms -#define DEFAULT_STREAMER_IDLE_SLEEP 1000000 // 1 sec - -// #define PQISTREAMER_DEBUG - -pqithreadstreamer::pqithreadstreamer(PQInterface *parent, RsSerialiser *rss, const RsPeerId& id, BinInterface *bio_in, int bio_flags_in) -:pqistreamer(rss, id, bio_in, bio_flags_in), mParent(parent), mTimeout(0), mThreadMutex("pqithreadstreamer") -{ - mTimeout = DEFAULT_STREAMER_TIMEOUT; - mSleepPeriod = DEFAULT_STREAMER_SLEEP; -} - -bool pqithreadstreamer::RecvItem(RsItem *item) -{ - return mParent->RecvItem(item); -} - -int pqithreadstreamer::tick() -{ - // pqithreadstreamer mutex lock is not needed here - // we will only check if the connection is active, and if not we will try to establish it - tick_bio(); - - return 0; -} - -void pqithreadstreamer::threadTick() -{ - uint32_t recv_timeout = 0; - uint32_t sleep_period = 0; - bool isactive = false; - - { - RsStackMutex stack(mStreamerMtx); - recv_timeout = mTimeout; - sleep_period = mSleepPeriod; - isactive = mBio->isactive(); - } - - // update the connection rates - updateRates() ; - - // if the connection est not active, long sleep then return - if (!isactive) - { - rstime::rs_usleep(DEFAULT_STREAMER_IDLE_SLEEP); - return ; - } - - // fill incoming queue with items from SSL - { - RsStackMutex stack(mThreadMutex); - tick_recv(recv_timeout); - } - - // move items to appropriate service queue or shortcut to fast service - RsItem *incoming = NULL; - while((incoming = GetItem())) - { - RecvItem(incoming); - } - - // parse the outgoing queue and send items to SSL - { - RsStackMutex stack(mThreadMutex); - tick_send(0); - } - - // sleep - if (sleep_period) - { - rstime::rs_usleep(sleep_period); - } -} - diff --git a/libretroshare/src/pqi/pqithreadstreamer.h b/libretroshare/src/pqi/pqithreadstreamer.h deleted file mode 100644 index 5b6fa3763..000000000 --- a/libretroshare/src/pqi/pqithreadstreamer.h +++ /dev/null @@ -1,49 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqithreadstreamer.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2013 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef MRK_PQI_THREAD_STREAMER_HEADER -#define MRK_PQI_THREAD_STREAMER_HEADER - -#include "pqi/pqistreamer.h" -#include "util/rsthreads.h" - -class pqithreadstreamer: public pqistreamer, public RsTickingThread -{ -public: - pqithreadstreamer(PQInterface *parent, RsSerialiser *rss, const RsPeerId& peerid, BinInterface *bio_in, int bio_flagsin); - - // from pqistreamer - virtual bool RecvItem(RsItem *item) override; - virtual int tick() override; - -protected: - void threadTick() override; /// @see RsTickingThread - - PQInterface *mParent; - uint32_t mTimeout; - uint32_t mSleepPeriod; - -private: - /* thread variables */ - RsMutex mThreadMutex; -}; - -#endif //MRK_PQI_THREAD_STREAMER_HEADER diff --git a/libretroshare/src/pqi/rstcpsocket.cc b/libretroshare/src/pqi/rstcpsocket.cc deleted file mode 100644 index f9bf03483..000000000 --- a/libretroshare/src/pqi/rstcpsocket.cc +++ /dev/null @@ -1,100 +0,0 @@ -/******************************* BEGIN WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS -#include -#include -#include -#include -#else -#include -// Missing defines in MinGW -#ifndef MSG_WAITALL -#define MSG_WAITALL 8 -#endif -#endif -/********************************* END WINDOWS/UNIX SPECIFIC PART ******************/ -#include -#include - -#include "rstcpsocket.h" - -RsTcpSocket::RsTcpSocket(const std::string& tcp_address,uint16_t tcp_port) - :RsFdBinInterface(0, true),mState(DISCONNECTED),mConnectAddress(tcp_address),mConnectPort(tcp_port),mSocket(0) -{ -} - -RsTcpSocket::RsTcpSocket() - :RsFdBinInterface(0, true),mState(DISCONNECTED),mConnectAddress("0.0.0.0"),mConnectPort(0),mSocket(0) -{ -} - -bool RsTcpSocket::connect(const std::string& tcp_address,uint16_t tcp_port) -{ - if(mState == CONNECTED) - close(); - - mConnectPort = tcp_port; - mConnectAddress = tcp_address; - - return connect(); -} -bool RsTcpSocket::connect() -{ - int CreateSocket = 0; - char dataReceived[1024]; - struct sockaddr_in ipOfServer; - - memset(dataReceived, '0' ,sizeof(dataReceived)); - - if((CreateSocket = socket(AF_INET, SOCK_STREAM, 0))< 0) - { - printf("Socket not created \n"); - return false; - } - ipOfServer.sin_family = AF_INET; - ipOfServer.sin_port = htons(mConnectPort); - ipOfServer.sin_addr.s_addr = inet_addr(mConnectAddress.c_str()); - - if(::connect(CreateSocket, (struct sockaddr *)&ipOfServer, sizeof(ipOfServer))<0) - { - printf("Connection failed due to port and ip problems, or server is not available. Socket=%d,ConnectPort=%d,ConnectAddress=%s Errno=%d\n",mSocket,mConnectPort,mConnectAddress.c_str(),errno); - return false; - } - mState = CONNECTED; - - unix_fcntl_nonblock(CreateSocket); - setSocket(CreateSocket); - - return true; -} - -int RsTcpSocket::close() -{ - RsFdBinInterface::close(); - mState = DISCONNECTED; - - return !::close(mSocket); -} - -RsThreadedTcpSocket::RsThreadedTcpSocket(const std::string& tcp_address,uint16_t tcp_port) - : RsTcpSocket(tcp_address,tcp_port) -{ -} -RsThreadedTcpSocket::RsThreadedTcpSocket() : RsTcpSocket() -{ -} -void RsThreadedTcpSocket::run() -{ - while(!shouldStop() && connectionState() == CONNECTED) - { - tick(); - std::this_thread::sleep_for(std::chrono::milliseconds(200)); - } - RsWarn() << "Connection to " << connectAddress() << ":" << connectPort() << " is now closed."; -} - -RsThreadedTcpSocket::~RsThreadedTcpSocket() -{ - fullstop(); // fully wait for stopping. - - close(); -} diff --git a/libretroshare/src/pqi/rstcpsocket.h b/libretroshare/src/pqi/rstcpsocket.h deleted file mode 100644 index a51c400ef..000000000 --- a/libretroshare/src/pqi/rstcpsocket.h +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include "util/rsthreads.h" -#include "pqi/pqifdbin.h" - -class RsTcpSocket: public RsFdBinInterface -{ -public: - RsTcpSocket(const std::string& tcp_address,uint16_t tcp_port); - RsTcpSocket(); - virtual ~RsTcpSocket()=default; - - enum State: uint8_t { - UNKNOWN = 0x00, - DISCONNECTED = 0x01, - CONNECTED = 0x02 - }; - - // Return true when OK, false otherwise. - bool connect(); - - bool connect(const std::string& tcp_address,uint16_t tcp_port); - - // Returns 1 when OK, 0 otherwise. - int close(); - - State connectionState() const { return mState; } - const std::string& connectAddress() const { return mConnectAddress ; } - uint16_t connectPort() const { return mConnectPort ; } - -private: - State mState; - std::string mConnectAddress; - uint16_t mConnectPort; - int mSocket; -}; - -class RsThreadedTcpSocket: public RsTcpSocket, public RsThread -{ -public: - RsThreadedTcpSocket(const std::string& tcp_address,uint16_t tcp_port); - RsThreadedTcpSocket(); - virtual ~RsThreadedTcpSocket(); - - virtual void run() override; -}; - diff --git a/libretroshare/src/pqi/sslfns.cc b/libretroshare/src/pqi/sslfns.cc deleted file mode 100644 index cb799ed86..000000000 --- a/libretroshare/src/pqi/sslfns.cc +++ /dev/null @@ -1,886 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: sslfns.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -/* Functions in this file are SSL only, - * and have no dependence on SSLRoot() etc. - * might need SSL_Init() to be called - thats it! - */ - -/******************** notify of new Cert **************************/ - -#include "pqi/sslfns.h" -#include "pqi/pqi_base.h" -#include "util/rsdir.h" -#include "util/rsstring.h" -#include "pqi/authssl.h" - -#include -#include -#include -#include - -#include -#include -#include - -/**** - * #define AUTHSSL_DEBUG 1 - ***/ - -/********************************************************************************/ - -#if defined(SSLFNS_ADD_CIPHER_CTX_RAND_KEY) - -int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key) -{ - //if (ctx->cipher->flags & EVP_CIPH_RAND_KEY) - // return EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_RAND_KEY, 0, key); - if (RAND_bytes(key, ctx->key_len) <= 0) - return 0; - return 1; -} - -#endif - -/********************************************************************************/ -/********************************************************************************/ - -X509_REQ *GenerateX509Req( - std::string pkey_file, std::string passwd, - std::string name, std::string email, std::string org, - std::string loc, std::string state, std::string country, - int nbits_in, std::string &errString) -{ - /* generate request */ - X509_REQ *req=X509_REQ_new(); - - // setup output. - BIO *bio_out = BIO_new(BIO_s_file()); - BIO_set_fp(bio_out,stdout,BIO_NOCLOSE); - - EVP_PKEY *pkey = NULL; - X509_NAME *x509_name = NULL ; - RSA *rsa = NULL ; - - try - { - // first generate a key.... - if ((pkey=EVP_PKEY_new()) == NULL) - { - fprintf(stderr,"GenerateX509Req: Couldn't Create Key\n"); - throw std::runtime_error("Couldn't Create Key") ; - } - - int nbits = 2048; - unsigned long e = 0x10001; - - if ((nbits_in >= 512) && (nbits_in <= 4096)) - { - nbits = nbits_in; - } - else - { - fprintf(stderr,"GenerateX509Req: strange num of nbits: %d\n", nbits_in); - fprintf(stderr,"GenerateX509Req: reverting to %d\n", nbits); - } - - - rsa = RSA_new(); - if ((rsa == NULL) || !EVP_PKEY_assign_RSA(pkey, rsa)) - throw std::runtime_error("Couldn't generate RSA Key"); - - BIGNUM *ebn = BN_new(); - BN_set_word(ebn, e); - RSA_generate_key_ex(rsa, nbits, ebn, NULL); - - // open the file. - FILE *out; - if (NULL == (out = RsDirUtil::rs_fopen(pkey_file.c_str(), "w"))) - throw std::runtime_error("Couldn't Create Key File \"" + pkey_file + "\""); - - const EVP_CIPHER *cipher = EVP_des_ede3_cbc(); - - if (!PEM_write_PrivateKey(out,pkey,cipher, NULL,0,NULL,(void *) passwd.c_str())) - { - fclose(out) ; - throw std::runtime_error("Couldn't Save Private Key to file \""+pkey_file+"\""); - } - - fclose(out); - - // We have now created a private key.... - std::cerr << "GenerateX509Req() Saved Private Key to file \"" << pkey_file << "\"" << std::endl; - - /********** Test Loading the private Key.... ************/ - FILE *tst_in = NULL; - EVP_PKEY *tst_pkey = NULL; - - if (NULL == (tst_in = RsDirUtil::rs_fopen(pkey_file.c_str(), "rb"))) - throw std::runtime_error("GenerateX509Req() Couldn't Open Private Key file \""+pkey_file+"\"") ; - - if (NULL == (tst_pkey = PEM_read_PrivateKey(tst_in,NULL,NULL,(void *) passwd.c_str()))) - { - fclose(tst_in); - throw std::runtime_error("GenerateX509Req() Couldn't read Private Key file \""+pkey_file+"\"") ; - } - - fclose(tst_in); - EVP_PKEY_free(tst_pkey); - - /* Fill in details: fields. - req->req_info; - req->req_info->enc; - req->req_info->version; - req->req_info->subject; - req->req_info->pubkey; - ****************************/ - - long version = 0x00; - unsigned long chtype = MBSTRING_UTF8; - x509_name = X509_NAME_new(); - - // fill in the request. - - /**** X509_REQ -> Version ********************************/ - if(!X509_REQ_set_version(req,version)) /* version 1 */ - throw std::runtime_error("GenerateX509Req(): Couldn't Set SSL certificate Version!"); - - /**** X509_REQ -> Version ********************************/ - /**** X509_REQ -> Key ********************************/ - - if (!X509_REQ_set_pubkey(req,pkey)) - throw std::runtime_error("GenerateX509Req(): Couldn't Set SSL certificate PUBKEY!"); - - /**** SUBJECT ********************************/ - // create the name. - - // fields to add. - // commonName CN - // emailAddress (none) - // organizationName O - // localityName L - // stateOrProvinceName ST - // countryName C - - if (0 == strlen(name.c_str())) - throw std::runtime_error("No name! Aborting.") ; - - X509_NAME_add_entry_by_txt(x509_name, "CN", chtype, (unsigned char *) name.c_str(), -1, -1, 0); - - if (0 < strlen(email.c_str())) - X509_NAME_add_entry_by_NID(x509_name, 48, 0, (unsigned char *) email.c_str(), -1, -1, 0); - - if (0 < strlen(org.c_str())) - X509_NAME_add_entry_by_txt(x509_name, "O", chtype, (unsigned char *) org.c_str(), -1, -1, 0); - - if (0 < strlen(loc.c_str())) - X509_NAME_add_entry_by_txt(x509_name, "L", chtype, (unsigned char *) loc.c_str(), -1, -1, 0); - - if (0 < strlen(state.c_str())) - X509_NAME_add_entry_by_txt(x509_name, "ST", chtype, (unsigned char *) state.c_str(), -1, -1, 0); - - if (0 < strlen(country.c_str())) - X509_NAME_add_entry_by_txt(x509_name, "C", chtype, (unsigned char *) country.c_str(), -1, -1, 0); - - if (!X509_REQ_set_subject_name(req,x509_name)) - throw std::runtime_error("GenerateX509Req() Couldn't Set Name to Request!"); - - X509_NAME_free(x509_name); - - /**** SUBJECT ********************************/ - - if (!X509_REQ_sign(req,pkey,EVP_sha1())) - throw std::runtime_error("GenerateX509Req() Failed to sign REQ"); - - errString = "No Error"; - - return req; - } - catch(std::exception& e) - { - std::cerr << "(EE) Key creation failed: " << e.what() << std::endl; - errString = e.what() ; - req = NULL ; - } - - - if(rsa) - RSA_free(rsa); - - if(x509_name) - X509_NAME_free(x509_name); - - if(bio_out) - BIO_free_all(bio_out) ; - - if(pkey) - EVP_PKEY_free(pkey); - - return req ; -} - -#define SERIAL_RAND_BITS 64 - -#ifdef UNUSED_CODE -X509 *SignX509Certificate(X509_NAME *issuer, EVP_PKEY *privkey, X509_REQ *req, long days) -{ - const EVP_MD *digest = EVP_sha1(); - ASN1_INTEGER *serial = ASN1_INTEGER_new(); - EVP_PKEY *tmppkey; - X509 *x509 = X509_new(); - if (x509 == NULL) - return NULL; - - BIGNUM *btmp = BN_new(); - if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0)) - { - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," pseudo_rand\n"); - - return NULL; - } - if (!BN_to_ASN1_INTEGER(btmp, serial)) - { - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," int\n"); - - return NULL; - } - BN_free(btmp); - - if (!X509_set_serialNumber(x509, serial)) - { - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," serialNumber\n"); - - return NULL; - } - ASN1_INTEGER_free(serial); - - if (!X509_set_issuer_name(x509, issuer)) - { - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," issuer\n"); - - return NULL; - } - - if (!X509_gmtime_adj(x509->cert_info->validity->notBefore, 0)) - { - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," notBefore\n"); - - return NULL; - } - - //x509->cert_info->validity->notAfter - //if (!X509_gmtime_adj(X509_get_notAfter(x509), (long)60*60*24*days)) - if (!X509_gmtime_adj(x509->cert_info->validity->notAfter, (long)60*60*24*days)) - { - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," notAfter\n"); - - return NULL; - } - - if (!X509_set_subject_name(x509, X509_REQ_get_subject_name(req))) - { - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," subject_name\n"); - - return NULL; - } - - - tmppkey = X509_REQ_get_pubkey(req); - if (!tmppkey || !X509_set_pubkey(x509,tmppkey)) - { - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," pubkey\n"); - - return NULL; - } - - - /* Cleanup Algorithm part */ - - X509_ALGOR *algor1 = x509->cert_info->signature; - X509_ALGOR *algor2 = x509->sig_alg; - - X509_ALGOR *a; - - a = algor1; - ASN1_TYPE_free(a->parameter); - a->parameter=ASN1_TYPE_new(); - a->parameter->type=V_ASN1_NULL; - - ASN1_OBJECT_free(a->algorithm); - a->algorithm=OBJ_nid2obj(digest->pkey_type); - - a = algor2; - ASN1_TYPE_free(a->parameter); - a->parameter=ASN1_TYPE_new(); - a->parameter->type=V_ASN1_NULL; - - ASN1_OBJECT_free(a->algorithm); - a->algorithm=OBJ_nid2obj(digest->pkey_type); - - - if (!X509_sign(x509,privkey,digest)) - { - long e = ERR_get_error(); - - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," signing Error: %ld\n", e); - - fprintf(stderr,"ERR: %s, %s, %s\n", - ERR_lib_error_string(e), - ERR_func_error_string(e), - ERR_reason_error_string(e)); - - int inl=i2d_X509(x509,NULL); - int outl=EVP_PKEY_size(privkey); - fprintf(stderr,"Size Check: inl: %d, outl: %d\n", inl, outl); - - return NULL; - } - - fprintf(stderr,"SignX509Certificate() Success\n"); - - return x509; -} -#endif - -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ - - - /* Sign / Encrypt / Verify Data */ -bool SSL_SignDataBin(const void *data, const uint32_t len, - unsigned char *sign, unsigned int *signlen, EVP_PKEY *pkey) -{ - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - unsigned int req_signlen = EVP_PKEY_size(pkey); - if (req_signlen > *signlen) - { - /* not enough space */ - std::cerr << "SignDataBin() Not Enough Sign SpacegnInit Failure!" << std::endl; - return false; - } - - if (0 == EVP_SignInit(mdctx, EVP_sha1())) - { - std::cerr << "EVP_SignInit Failure!" << std::endl; - - EVP_MD_CTX_destroy(mdctx); - return false; - } - - if (0 == EVP_SignUpdate(mdctx, data, len)) - { - std::cerr << "EVP_SignUpdate Failure!" << std::endl; - - EVP_MD_CTX_destroy(mdctx); - return false; - } - - if (0 == EVP_SignFinal(mdctx, sign, signlen, pkey)) - { - std::cerr << "EVP_SignFinal Failure!" << std::endl; - - EVP_MD_CTX_destroy(mdctx); - return false; - } - - EVP_MD_CTX_destroy(mdctx); - return true; -} - -bool SSL_VerifySignBin(const void *data, const uint32_t len, - unsigned char *sign, unsigned int signlen, X509 *cert) -{ - - /* cert->cert_info->key->pkey is NULL.... - * but is instantiated when we call X509_get_pubkey() - */ - - EVP_PKEY *peerkey = X509_get_pubkey(cert); - - /* must free this key afterwards */ - bool ret = SSL_VerifySignBin(data, len, sign, signlen, peerkey); - - EVP_PKEY_free(peerkey); - - return ret; -} - -/* Correct form of this function ... Internal for AuthSSL's usage - */ - -bool SSL_VerifySignBin(const void *data, const uint32_t len, - unsigned char *sign, unsigned int signlen, EVP_PKEY *peerkey) -{ - if(peerkey == NULL) - { - std::cerr << "VerifySignBin: no public key available !!" << std::endl ; - return false ; - } - - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - - if (0 == EVP_VerifyInit(mdctx, EVP_sha1())) - { - std::cerr << "EVP_VerifyInit Failure!" << std::endl; - - EVP_MD_CTX_destroy(mdctx); - return false; - } - - if (0 == EVP_VerifyUpdate(mdctx, data, len)) - { - std::cerr << "EVP_VerifyUpdate Failure!" << std::endl; - - EVP_MD_CTX_destroy(mdctx); - return false; - } - - if(signlen == 0 || sign == NULL) - { - std::cerr << "AuthSSL::VerifySignBin: signlen=" << signlen << ", sign=" << (void*)sign << "!!" << std::endl ; - EVP_MD_CTX_destroy(mdctx); - return false ; - } - - if (0 == EVP_VerifyFinal(mdctx, sign, signlen, peerkey)) - { - std::cerr << "EVP_VerifyFinal Failure!" << std::endl; - - EVP_MD_CTX_destroy(mdctx); - return false; - } - - EVP_MD_CTX_destroy(mdctx); - return true; -} - -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ - -X509 *loadX509FromPEM(std::string pem) -{ -#ifdef AUTHSSL_DEBUG - std::cerr << "loadX509FromPEM()"; - std::cerr << std::endl; -#endif - - /* Put the data into a mem BIO */ - char *certstr = strdup(pem.c_str()); - - BIO *bp = BIO_new_mem_buf(certstr, -1); - - X509 *pc = PEM_read_bio_X509(bp, NULL, NULL, NULL); - - BIO_free(bp); - free(certstr); - - return pc; -} - -std::string saveX509ToPEM(X509* x509) -{ -#ifdef AUTHSSL_DEBUG - std::cerr << "saveX509ToPEM() " << std::endl; -#endif - - /* get the cert first */ - std::string certstr; - BIO *bp = BIO_new(BIO_s_mem()); - - PEM_write_bio_X509(bp, x509); - - /* translate the bp data to a string */ - char *data; - int len = BIO_get_mem_data(bp, &data); - for(int i = 0; i < len; i++) - { - certstr += data[i]; - } - - BIO_free(bp); - - return certstr; -} - - -X509 *loadX509FromDER(const uint8_t *ptr, uint32_t len) -{ -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::LoadX509FromDER()"; - std::cerr << std::endl; -#endif - - X509 *tmp = NULL; -#ifdef __APPLE__ - // This depends on which version you are compiling for... OSX10.5 doesn't have consts (old OpenSSL!) - // With the Advent of Openpgpsdk, we are forced to move to OSX10.6 for a newer OpenSSL (probably a good thing). - // So we can change this around. - //unsigned char **certptr = (unsigned char **) &ptr; - const unsigned char **certptr = (const unsigned char **) &ptr; -#else - const unsigned char **certptr = (const unsigned char **) &ptr; -#endif - - X509 *x509 = d2i_X509(&tmp, certptr, len); - - return x509; -} - -bool saveX509ToDER(X509 *x509, uint8_t **ptr, uint32_t *len) -{ -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::saveX509ToDER()"; - std::cerr << std::endl; -#endif - - int certlen = i2d_X509(x509, (unsigned char **) ptr); - if (certlen > 0) - { - *len = certlen; - return true; - } - else - { - *len = 0; - return false; - } - return false; -} - - -bool getX509id(X509 *x509, RsPeerId& xid) -{ -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::getX509id()"; - std::cerr << std::endl; -#endif - - xid.clear() ; - if (x509 == NULL) - { -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::getX509id() NULL pointer"; - std::cerr << std::endl; -#endif - return false; - } - - // get the signature from the cert, and copy to the array. -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - ASN1_BIT_STRING *signature = x509->signature; -#else - const ASN1_BIT_STRING *signature = NULL ; - const X509_ALGOR *algor ; - - X509_get0_signature(&signature,&algor,x509); -#endif - - uint32_t version_number = getX509RetroshareCertificateVersion(x509) ; - - if(version_number >= RS_CERTIFICATE_VERSION_NUMBER_06_0001) - { - // What: Computes the node id by performing a sha256 hash of the certificate's PGP signature, instead of simply picking up the last 20 bytes of it. - // - // Why: There is no real risk in forging a certificate with the same ID as the authentication is performed over the PGP signature of the certificate - // which hashes the full SSL certificate (i.e. the full serialized CERT_INFO structure). However the possibility to - // create two certificates with the same IDs is a problem, as it can be used to cause disturbance in the software. - // - // Backward compat: makes connexions impossible with non patched peers, probably because the SSL id that is computed is not the same on both side, - // and in particular unpatched peers see a cerficate with ID different (because computed with the old method) than the ID that was - // submitted when making friends. - // - // Note: the advantage of basing the ID on the signature rather than the public key is not very clear, given that the signature is based on a hash - // of the public key (and the rest of the certificate info). - // - - if(RsPeerId::SIZE_IN_BYTES > Sha256CheckSum::SIZE_IN_BYTES) - return false ; - - xid = RsPeerId(RsDirUtil::sha256sum(ASN1_STRING_data(const_cast(signature)),ASN1_STRING_length(signature)).toByteArray()) ; - } - else - { - int signlen = ASN1_STRING_length(signature); - if (signlen < CERTSIGNLEN) - { -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::getX509id() ERROR: Short Signature"; - std::cerr << std::endl; -#endif - return false; - } - - // else copy in the first CERTSIGNLEN. - unsigned char *signdata = ASN1_STRING_data(const_cast(signature)); - - /* switched to the other end of the signature. for - * more randomness - */ - -#warning csoler 2017-02-19: This is cryptographically horrible. We should hash the entire signature here! - - xid = RsPeerId(&signdata[signlen - CERTSIGNLEN]) ; - } - - return true; -} - - -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ - -int pem_passwd_cb(char *buf, int size, int rwflag, void *password) -{ - /* remove unused parameter warnings */ - (void) rwflag; - - strncpy(buf, (char *)(password), size); - buf[size - 1] = '\0'; - return(strlen(buf)); -} - -uint64_t getX509SerialNumber(X509 *cert) -{ - ASN1_INTEGER *serial = X509_get_serialNumber(cert); - - BIGNUM *btmp = ASN1_INTEGER_to_BN(serial, NULL); - - uint64_t res = BN_get_word(btmp) ; - BN_free(btmp); - - return res ; -} - -uint32_t getX509RetroshareCertificateVersion(X509 *cert) -{ - // Because the serial number was totally random before being used to identity the handshake protocol, we check if we see known version strings. If not, - // we assume v0.6-0000 - // - // We compare the uint32_t into a uint64_t on purpose,to make sure that the highest bits are 0 and not random. - - switch(getX509SerialNumber(cert)) - { - case uint64_t(RS_CERTIFICATE_VERSION_NUMBER_06_0000): return RS_CERTIFICATE_VERSION_NUMBER_06_0000 ; - case uint64_t(RS_CERTIFICATE_VERSION_NUMBER_06_0001): return RS_CERTIFICATE_VERSION_NUMBER_06_0001 ; - case uint64_t(RS_CERTIFICATE_VERSION_NUMBER_07_0001): return RS_CERTIFICATE_VERSION_NUMBER_07_0001 ; - default: - return RS_CERTIFICATE_VERSION_NUMBER_06_0000; - } -} - -std::string getX509NameString(X509_NAME *name) -{ - std::string namestr; - for(int i = 0; i < X509_NAME_entry_count(name); i++) - { - X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i); - ASN1_STRING *entry_data = X509_NAME_ENTRY_get_data(entry); - ASN1_OBJECT *entry_obj = X509_NAME_ENTRY_get_object(entry); - - namestr += "\t"; - namestr += OBJ_nid2ln(OBJ_obj2nid(entry_obj)); - namestr += " : "; - - //namestr += entry_obj -> flags; - //namestr += entry_data -> length; - //namestr += entry_data -> type; - - //namestr += entry_data -> flags; - //entry -> set; - - if (entry_data -> data != NULL) - { - namestr += (char *) entry_data -> data; - } - else - { - namestr += "NULL"; - } - - if (i + 1 < X509_NAME_entry_count(name)) - { - namestr += "\n"; - } - } - return namestr; -} - -std::string getX509CNString(X509_NAME *name) -{ - std::string namestr; - for(int i = 0; i < X509_NAME_entry_count(name); i++) - { - X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i); - ASN1_STRING *entry_data = X509_NAME_ENTRY_get_data(entry); - ASN1_OBJECT *entry_obj = X509_NAME_ENTRY_get_object(entry); - - if (0 == strncmp("CN", OBJ_nid2sn(OBJ_obj2nid(entry_obj)), 2)) - { - if (entry_data -> data != NULL) - { - // do we need to convert ASN1_STRING to utf8 (ASN1_STRING_to_UTF8)? - namestr = (char *) entry_data->data; - } - else - { - namestr = "Unknown"; - } - break; - } - } - return namestr; -} - -std::string getX509TypeString(X509_NAME *name, const char *type, int len) -{ - std::string namestr; - for(int i = 0; i < X509_NAME_entry_count(name); i++) - { - X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i); - ASN1_STRING *entry_data = X509_NAME_ENTRY_get_data(entry); - ASN1_OBJECT *entry_obj = X509_NAME_ENTRY_get_object(entry); - - if (0 == strncmp(type, OBJ_nid2sn(OBJ_obj2nid(entry_obj)), len)) - { - if (entry_data -> data != NULL) - { - // do we need to convert ASN1_STRING to utf8 (ASN1_STRING_to_UTF8)? - namestr = (char *) entry_data -> data; - } - else - { - namestr = "Unknown"; - } - break; - } - } - return namestr; -} - -std::string getX509LocString(X509_NAME *name) -{ - return getX509TypeString(name, "L", 2); -} - -std::string getX509OrgString(X509_NAME *name) -{ - return getX509TypeString(name, "O", 2); -} - -std::string getX509CountryString(X509_NAME *name) -{ - return getX509TypeString(name, "C", 2); -} - - -#ifdef AUTHSSL_DEBUG -std::string getX509Info(X509 *cert) -{ - std::string out = "X509 Certificate:\n"; - - long l; - l=X509_get_version(cert); - rs_sprintf_append(out, " Version: %ld(0x%ld)\n", l+1, l); - out += " Subject: \n"; - out += " " + getX509NameString(cert->cert_info->subject) + "\n\n"; - out += " Signatures:\n"; - return out; -} -#endif - -/********** SSL ERROR STUFF ******************************************/ - -int printSSLError( - SSL*, int retval, int err, unsigned long err2, std::string& out ) -{ - std::string reason; - - std::string mainreason = std::string("UNKNOWN ERROR CODE"); - if (err == SSL_ERROR_NONE) - { - mainreason = std::string("SSL_ERROR_NONE"); - } - else if (err == SSL_ERROR_ZERO_RETURN) - { - mainreason = std::string("SSL_ERROR_ZERO_RETURN"); - } - else if (err == SSL_ERROR_WANT_READ) - { - mainreason = std::string("SSL_ERROR_WANT_READ"); - } - else if (err == SSL_ERROR_WANT_WRITE) - { - mainreason = std::string("SSL_ERROR_WANT_WRITE"); - } - else if (err == SSL_ERROR_WANT_CONNECT) - { - mainreason = std::string("SSL_ERROR_WANT_CONNECT"); - } - else if (err == SSL_ERROR_WANT_ACCEPT) - { - mainreason = std::string("SSL_ERROR_WANT_ACCEPT"); - } - else if (err == SSL_ERROR_WANT_X509_LOOKUP) - { - mainreason = std::string("SSL_ERROR_WANT_X509_LOOKUP"); - } - else if (err == SSL_ERROR_SYSCALL) - { - mainreason = std::string("SSL_ERROR_SYSCALL"); - } - else if (err == SSL_ERROR_SSL) - { - mainreason = std::string("SSL_ERROR_SSL"); - } - rs_sprintf_append( out, - "RetVal(%d) -> SSL Error: %s\n\t + ERR Error: %s\n", - retval, mainreason.c_str(), - ERR_error_string(err2, nullptr) ); - return 1; -} - - -std::string sslErrorToString(int retval, int err, unsigned long err2) -{ - std::string ret; - // When printSSLError will be removed it's code will be moved here - printSSLError(nullptr, retval, err, err2, ret); - return ret; -} diff --git a/libretroshare/src/pqi/sslfns.h b/libretroshare/src/pqi/sslfns.h deleted file mode 100644 index c22076c51..000000000 --- a/libretroshare/src/pqi/sslfns.h +++ /dev/null @@ -1,135 +0,0 @@ -ļ»æ/******************************************************************************* - * libretroshare/src/pqi: sslfns.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -/* Functions in this file are SSL only, - * and have no dependence on SSLRoot() etc. - * might need SSL_Init() to be called - thats it! - */ - -/******************** notify of new Cert **************************/ - -#include -#include - -#include -#include - -#include "util/rsdeprecate.h" -#include "retroshare/rstypes.h" - - -/**** - * #define AUTHSSL_DEBUG 1 - ***/ - -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ - - -// IF we are compiling against ssl0.9.7 - these functions don't exist. - -#if (OPENSSL_VERSION_NUMBER & 0xfffff000) < 0x00908000 - #define SSLFNS_ADD_CIPHER_CTX_RAND_KEY 1 -#endif - -#if defined(SSLFNS_ADD_CIPHER_CTX_RAND_KEY) - -int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key); - -#endif - -// Certificates serial number is used to store the protocol version for the handshake. (*) means current version. -// -// 06_0000: < Nov.2017. -// * 06_0001: > Nov 2017. SSL id is computed by hashing the entire signature of the cert instead of simply picking up the last bytes. -// 07_0001: Signatures are performed using SHA256+RSA instead of SHA1+RSA - -static const uint32_t RS_CERTIFICATE_VERSION_NUMBER_06_0000 = 0x00060000 ; // means version RS-0.6, certificate version 0. Default version before patch. -static const uint32_t RS_CERTIFICATE_VERSION_NUMBER_06_0001 = 0x00060001 ; // means version RS-0.6, certificate version 1. -static const uint32_t RS_CERTIFICATE_VERSION_NUMBER_07_0001 = 0x00070001 ; // means version RS-0.7, certificate version 1. - -X509_REQ *GenerateX509Req( - std::string pkey_file, std::string passwd, - std::string name, std::string email, std::string org, - std::string loc, std::string state, std::string country, - int nbits_in, std::string &errString); - -X509 *SignX509Certificate(X509_NAME *issuer, EVP_PKEY *privkey, X509_REQ *req, long days); - -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ - - - /* Sign / Encrypt / Verify Data */ -bool SSL_SignDataBin(const void *data, const uint32_t len, - unsigned char *sign, unsigned int *signlen, EVP_PKEY *pkey); - -bool SSL_VerifySignBin(const void *data, const uint32_t len, - unsigned char *sign, unsigned int signlen, X509 *cert); - -bool SSL_VerifySignBin(const void *data, const uint32_t len, - unsigned char *sign, unsigned int signlen, EVP_PKEY *peerkey); - -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ - -X509 *loadX509FromPEM(std::string pem); -std::string saveX509ToPEM(X509* x509); -X509 *loadX509FromDER(const uint8_t *ptr, uint32_t len); -bool saveX509ToDER(X509 *x509, uint8_t **ptr, uint32_t *len); - -bool getX509id(X509 *x509, RsPeerId &xid); - -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ - -int pem_passwd_cb(char *buf, int size, int rwflag, void *password); - -std::string getX509NameString(X509_NAME *name); -std::string getX509CNString(X509_NAME *name); -std::string getX509TypeString(X509_NAME *name, const char *type, int len); -std::string getX509LocString(X509_NAME *name); -std::string getX509OrgString(X509_NAME *name); -std::string getX509CountryString(X509_NAME *name); -std::string getX509Info(X509 *cert); - -uint64_t getX509SerialNumber(X509 *cert); -uint32_t getX509RetroshareCertificateVersion(X509 *cert) ; - -/********** SSL ERROR STUFF ******************************************/ - -RS_DEPRECATED_FOR(sslErrorToString) -int printSSLError( - SSL* unused, int retval, int err, unsigned long err2, std::string& out); - -std::string sslErrorToString(int retval, int err, unsigned long err2); diff --git a/libretroshare/src/retroshare/rsbanlist.h b/libretroshare/src/retroshare/rsbanlist.h deleted file mode 100644 index c46ea0203..000000000 --- a/libretroshare/src/retroshare/rsbanlist.h +++ /dev/null @@ -1,157 +0,0 @@ -/******************************************************************************* - * IPv4 address filtering interface * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2015 Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include - -#include "util/rsnet.h" -#include "util/rstime.h" -#include "util/rsmemory.h" - -class RsBanList; - -/** - * Pointer to global instance of RsBanList service implementation - * @jsonapi{development} - */ -extern RsBanList* rsBanList; - -// TODO: use enum class instead of defines -#define RSBANLIST_ORIGIN_UNKNOWN 0 -#define RSBANLIST_ORIGIN_SELF 1 -#define RSBANLIST_ORIGIN_FRIEND 2 -#define RSBANLIST_ORIGIN_FOF 3 - -#define RSBANLIST_REASON_UNKNOWN 0 -#define RSBANLIST_REASON_USER 1 -#define RSBANLIST_REASON_DHT 2 -#define RSBANLIST_REASON_AUTO_RANGE 3 - -// These are flags. Can be combined. - -#define RSBANLIST_CHECKING_FLAGS_NONE 0x00 -#define RSBANLIST_CHECKING_FLAGS_BLACKLIST 0x01 -#define RSBANLIST_CHECKING_FLAGS_WHITELIST 0x02 - -// These are not flags. Cannot be combined. Used to give the reson for acceptance/denial of connections. - -#define RSBANLIST_CHECK_RESULT_UNKNOWN 0x00 -#define RSBANLIST_CHECK_RESULT_NOCHECK 0x01 -#define RSBANLIST_CHECK_RESULT_BLACKLISTED 0x02 -#define RSBANLIST_CHECK_RESULT_NOT_WHITELISTED 0x03 -#define RSBANLIST_CHECK_RESULT_ACCEPTED 0x04 - -#define RSBANLIST_TYPE_PEERLIST 1 -#define RSBANLIST_TYPE_BLACKLIST 2 -#define RSBANLIST_TYPE_WHITELIST 3 - -class RsTlvBanListEntry; - -class BanListPeer -{ -public: - BanListPeer() ; - - void toRsTlvBanListEntry(RsTlvBanListEntry& e) const ; - void fromRsTlvBanListEntry(const RsTlvBanListEntry& e) ; - - struct sockaddr_storage addr; - uint8_t masked_bytes ; // 0 = []/32. 1=[]/24, 2=[]/16 - uint32_t reason; // User, DHT - uint32_t level; // LOCAL, FRIEND, FoF. - bool state ; // true=>active, false=>just stored but inactive - int connect_attempts ; // recorded by the BanList service - rstime_t mTs; - std::string comment ; // -}; - -class RsBanList -{ -public: - /** - * @brief Enable or disable IP filtering service - * @jsonapi{development} - * @param[in] enable pass true to enable, false to disable - */ - virtual void enableIPFiltering(bool enable) = 0; - - /** - * @brief Get ip filtering service status - * @jsonapi{development} - * @return true if enabled, false if disabled - */ - virtual bool ipFilteringEnabled() = 0; - - /** - * @brief addIpRange - * @param addr full IPv4 address. Port is ignored. - * @param masked_bytes 0=full IP, 1="/24", 2="/16" - * @param list_type RSBANLIST_TYPE_WHITELIST or RSBANLIST_TYPE_BLACKLIST - * @param comment anything, user-based - * @return - */ - virtual bool addIpRange( - const sockaddr_storage& addr, int masked_bytes, uint32_t list_type, - const std::string& comment ) = 0; - - /** - * @brief removeIpRange - * @param addr full IPv4 address. Port is ignored. - * @param masked_bytes 0=full IP, 1="/24", 2="/16" - * @param list_type RSBANLIST_TYPE_WHITELIST or RSBANLIST_TYPE_BLACKLIST - * @return - */ - virtual bool removeIpRange( - const sockaddr_storage& addr, int masked_bytes, uint32_t list_type - ) = 0; - - /** - * @brief isAddressAccepted - * @param addr full IPv4 address. Port is ignored. - * @param checking_flags any combination of - * RSBANLIST_CHECKING_FLAGS_BLACKLIST and - * RSBANLIST_CHECKING_FLAGS_WHITELIST - * @param check_result returned result of the check in - * RSBANLIST_CHECK_RESULT_* - * @return true if address is accepted, false false if address is rejected. - */ - virtual bool isAddressAccepted( - const sockaddr_storage& addr, uint32_t checking_flags, - uint32_t& check_result = RS_DEFAULT_STORAGE_PARAM(uint32_t) ) = 0; - - virtual void getBannedIps(std::list& list) = 0; - virtual void getWhiteListedIps(std::list& list) = 0; - - virtual bool autoRangeEnabled() = 0; - virtual void enableAutoRange(bool b) = 0; - - virtual int autoRangeLimit() = 0; - virtual void setAutoRangeLimit(int n) = 0; - - virtual void enableIPsFromFriends(bool b) = 0; - virtual bool IPsFromFriendsEnabled() = 0; - - virtual void enableIPsFromDHT(bool b) = 0; - virtual bool iPsFromDHTEnabled() = 0; - - virtual ~RsBanList(); -}; diff --git a/libretroshare/src/retroshare/rsbroadcastdiscovery.h b/libretroshare/src/retroshare/rsbroadcastdiscovery.h deleted file mode 100644 index 92b0e5b0e..000000000 --- a/libretroshare/src/retroshare/rsbroadcastdiscovery.h +++ /dev/null @@ -1,160 +0,0 @@ -/******************************************************************************* - * RetroShare Broadcast Domain Discovery * - * * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -#include "retroshare/rsids.h" -#include "retroshare/rstypes.h" -#include "serialiser/rsserializable.h" -#include "util/rstime.h" -#include "util/rsurl.h" -#include "util/rsmemory.h" -#include "retroshare/rsevents.h" - -class RsBroadcastDiscovery; - -/** - * Pointer to global instance of RsBroadcastDiscovery service implementation - * @jsonapi{development} - * - * TODO: this should become std::weak_ptr once we have a reasonable services - * management. - */ -extern RsBroadcastDiscovery* rsBroadcastDiscovery; - - -struct RsBroadcastDiscoveryResult : RsSerializable -{ - RsPgpFingerprint mPgpFingerprint; - RsPeerId mSslId; - std::string mProfileName; - RsUrl mLocator; - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - RS_SERIAL_PROCESS(mPgpFingerprint); - RS_SERIAL_PROCESS(mSslId); - RS_SERIAL_PROCESS(mProfileName); - RS_SERIAL_PROCESS(mLocator); - } - - RsBroadcastDiscoveryResult() = default; - RsBroadcastDiscoveryResult (const RsBroadcastDiscoveryResult&) = default; - ~RsBroadcastDiscoveryResult() override; -}; - - -/** - * @brief Event emitted when a non friend new peer is found in the local network - * @see RsEvents - */ -enum class RsBroadcastDiscoveryEventType: uint32_t { - UNKNOWN = 0x00, - PEER_FOUND = 0x01 -}; - -struct RsBroadcastDiscoveryEvent : RsEvent -{ - RsBroadcastDiscoveryEvent() - : RsEvent(RsEventType::BROADCAST_DISCOVERY), - mDiscoveryEventType(RsBroadcastDiscoveryEventType::UNKNOWN) - {} - - virtual ~RsBroadcastDiscoveryEvent() override = default; - - RsBroadcastDiscoveryEventType mDiscoveryEventType; - RsBroadcastDiscoveryResult mData; - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - RsEvent::serial_process(j, ctx); - - RS_SERIAL_PROCESS(mDiscoveryEventType); - RS_SERIAL_PROCESS(mData); - } -}; - - -/** - * Announce own RetroShare instace and look friends and peers in own broadcast - * domain (aka LAN). - * Emit event @see RsBroadcastDiscoveryPeerFoundEvent when a new peer (not - * friend yet) is found. - */ -class RsBroadcastDiscovery -{ -public: - /** - * @brief Get potential peers that have been discovered up until now - * @jsonapi{development} - * @return vector containing discovered peers, may be empty. - */ - virtual std::vector getDiscoveredPeers() = 0; - - /** - * @brief Check if multicast listening is enabled - * @jsonapi{development} - * On some platforms such as Android multicast listening, which is needed - * for broadcast discovery, is not enabled by default at WiFi driver level - * @see enableMulticastListening, so this method check if it is enabled. - * On platforms that are not expected to have such a limitation this method - * always return true. - * @return true if enabled, false otherwise. - */ - virtual bool isMulticastListeningEnabled() = 0; - - /** - * @brief On platforms that need it enable low level multicast listening - * @jsonapi{development} - * On Android and potencially other mobile platforms, WiFi drivers are - * configured by default to discard any packet that is not directed to the - * unicast mac address of the interface, this way they could save some - * battery but breaks anything that is not unicast, such as broadcast - * discovery. On such platforms this method enable low level multicast - * listening so we can receive advertisement from same broadcast domain - * nodes. - * On platforms without such limitation does nothing and always return - * false. - * It is exposed as a public API so the UI can decide the right equilibrium - * between discoverability and battery saving. - * @return true if multicast listening has been enabled due to this call, - * false otherwise. - */ - virtual bool enableMulticastListening() = 0; - - /** - * @brief Disable multicast listening - * @jsonapi{development} - * The opposite of @see enableMulticastListening. - * @return true if multicast listening has been disabled due to this call, - * false otherwise. - */ - virtual bool disableMulticastListening() = 0; - - virtual ~RsBroadcastDiscovery(); -}; diff --git a/libretroshare/src/retroshare/rsconfig.h b/libretroshare/src/retroshare/rsconfig.h deleted file mode 100644 index 918372b79..000000000 --- a/libretroshare/src/retroshare/rsconfig.h +++ /dev/null @@ -1,424 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsconfig.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RETROSHARE_CONFIG_GUI_INTERFACE_H -#define RETROSHARE_CONFIG_GUI_INTERFACE_H - -#include -#include -#include -#include -#include - -/* The New Config Interface Class */ -class RsServerConfig; - -/** - * Pointer to global instance of RsServerConfig service implementation - * @jsonapi{development} - */ -extern RsServerConfig *rsConfig; - -enum class RsNetworkMode : uint8_t -{ - UNKNOWN = 1, - RESTARTING = 2, - OFFLINE = 3, - LOCALNET = 4, - BEHINDNAT = 5, - EXTERNALIP = 6 -}; - -enum class RsNatTypeMode : uint8_t -{ - NONE = 1, - UNKNOWN = 2, - SYMMETRIC = 3, - DETERM_SYM = 4, - RESTRICTED_CONE = 5, - FULL_CONE = 6, - OTHER = 7 -}; - -enum class RsNatHoleMode : uint8_t -{ - UNKNOWN = 0, - NONE = 1, - UPNP = 2, - NATPMP = 3, - FORWARDED = 4 -}; - -enum class RsConnectModes : uint16_t -{ - NONE = 0x0000, - ACCEPT_TCP = 0x0001, - OUTGOING_TCP= 0x0002, - DIRECT_UDP = 0x0100, - PROXY_UDP = 0x0200, - RELAY_UDP = 0x0400 -}; -RS_REGISTER_ENUM_FLAGS_TYPE(RsConnectModes) - -enum class RsNetState : uint8_t -{ - // BAD. (RED) - BAD_UNKNOWN = 1, - BAD_OFFLINE = 2, - BAD_NATSYM = 3, - BAD_NODHT_NAT = 4, - - // CAUTION. (ORANGE) - WARNING_RESTART = 5, - WARNING_NATTED = 6, - WARNING_NODHT = 7, - - // GOOD (GREEN) - // NAT with forwarded port, or EXT port. - GOOD = 8, - - // ADVANCED MODE (BLUE) - // If the user knows what they are doing... we cannot confirm this. - ADV_FORWARD = 9, - ADV_DARK_FORWARD= 10 -}; - - - -/************************** Indicate How experienced the RsUser is... based on Friends / Firewall status ******/ - -enum class RsConfigUserLvl : uint8_t -{ - NEW = 1, /* no friends */ - BASIC = 2, /* no connections */ - CASUAL = 3, /* firewalled */ - POWER = 4, /* good! */ - OVERRIDE= 5 /* forced to POWER level */ -}; - - - -// Must Match up with strings internal to Retroshare. -#define RS_CONFIG_ADVANCED 0x0101 - - -enum class RsOpMode : uint8_t -{ - FULL = 1, - NOTURTLE= 2, - GAMING = 3, - MINIMAL = 4 -}; - - -class RsConfigStartup -{ - public: - RsConfigStartup() - { - promptAtBoot = 1; - } - - -int promptAtBoot; /* popup the password prompt */ -}; - - -struct RsConfigDataRates : RsSerializable -{ - RsConfigDataRates() : - mRateIn(0), mRateMaxIn(0), mAllocIn(0), - mAllocTs(0), - mRateOut(0), mRateMaxOut(0), mAllowedOut(0), - mAllowedTs(0), - mQueueIn(0), mQueueOut(0) - {} - - /* all in kB/s */ - float mRateIn; - float mRateMaxIn; - float mAllocIn; - - rstime_t mAllocTs; - - float mRateOut; - float mRateMaxOut; - float mAllowedOut; - - rstime_t mAllowedTs; - - int mQueueIn; - int mQueueOut; - - // RsSerializable interface - void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) { - RS_SERIAL_PROCESS(mRateIn); - RS_SERIAL_PROCESS(mRateMaxIn); - RS_SERIAL_PROCESS(mAllocIn); - - RS_SERIAL_PROCESS(mAllocTs); - - RS_SERIAL_PROCESS(mRateOut); - RS_SERIAL_PROCESS(mRateMaxOut); - RS_SERIAL_PROCESS(mAllowedOut); - - RS_SERIAL_PROCESS(mAllowedTs); - - RS_SERIAL_PROCESS(mQueueIn); - RS_SERIAL_PROCESS(mQueueOut); - } -}; - -struct RSTrafficClue : RsSerializable -{ - rstime_t TS ; - uint32_t size ; - uint8_t priority ; - uint16_t service_id ; - uint8_t service_sub_id ; - RsPeerId peer_id ; - uint32_t count ; - - RSTrafficClue() { TS=0;size=0;service_id=0;service_sub_id=0; count=0; } - RSTrafficClue& operator+=(const RSTrafficClue& tc) { size += tc.size; count += tc.count ; return *this ;} - - // RsSerializable interface - void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) { - RS_SERIAL_PROCESS(TS); - RS_SERIAL_PROCESS(size); - RS_SERIAL_PROCESS(priority); - RS_SERIAL_PROCESS(service_id); - RS_SERIAL_PROCESS(service_sub_id); - RS_SERIAL_PROCESS(peer_id); - RS_SERIAL_PROCESS(count); - } -}; - -struct RsConfigNetStatus : RsSerializable -{ - RsConfigNetStatus() : netLocalOk(true) - { - localPort = extPort = 0 ; - firewalled = forwardPort = false ; - DHTActive = uPnPActive = netUpnpOk = netDhtOk = netStunOk = netExtAddressOk = false ; - uPnPState = 0 ; - //DHTPeers = 0 ; - netDhtNetSize = netDhtRsNetSize = 0; - } - - RsPeerId ownId; - std::string ownName; - - std::string localAddr; - int localPort; - std::string extAddr; - int extPort; - std::string extDynDns; - - bool firewalled; - bool forwardPort; - - /* older data types */ - bool DHTActive; - bool uPnPActive; - - int uPnPState; - - /* Flags for Network Status */ - RS_DEPRECATED - bool netLocalOk; /// As of today it's meaningless - bool netUpnpOk; /* upnp is enabled and active */ - bool netDhtOk; /* response from dht */ - bool netStunOk; /* recvd stun / udp packets */ - bool netExtAddressOk;/* from Dht/Stun or External IP Finder */ - - uint32_t netDhtNetSize; /* response from dht */ - uint32_t netDhtRsNetSize;/* response from dht */ - - // RsSerializable interface - void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) { - RS_SERIAL_PROCESS(ownId); - RS_SERIAL_PROCESS(ownName); - - RS_SERIAL_PROCESS(localAddr); - RS_SERIAL_PROCESS(localPort); - RS_SERIAL_PROCESS(extAddr); - RS_SERIAL_PROCESS(extPort); - RS_SERIAL_PROCESS(extDynDns); - - RS_SERIAL_PROCESS(firewalled); - RS_SERIAL_PROCESS(forwardPort); - - RS_SERIAL_PROCESS(DHTActive); - RS_SERIAL_PROCESS(uPnPActive); - - RS_SERIAL_PROCESS(uPnPState); - - RS_SERIAL_PROCESS(netLocalOk); - RS_SERIAL_PROCESS(netUpnpOk); - RS_SERIAL_PROCESS(netDhtOk); - RS_SERIAL_PROCESS(netStunOk); - RS_SERIAL_PROCESS(netExtAddressOk); - - RS_SERIAL_PROCESS(netDhtNetSize); - RS_SERIAL_PROCESS(netDhtRsNetSize); - } -}; - - -/********* - * This is a new style RsConfig Interface. - * It should contain much of the information for the Options/Config Window. - * - * To start with, I'm going to move the stuff from RsIface::RsConfig into here. - * - */ - - -class RsServerConfig -{ -public: - - RsServerConfig() {} - virtual ~RsServerConfig() {} - - /* From RsIface::RsConfig */ - // Implemented Only this one! - /** - * @brief getConfigNetStatus return the net status - * @jsonapi{development} - * @param[out] status network status - * @return returns 1 on succes and 0 otherwise - */ - virtual int getConfigNetStatus(RsConfigNetStatus &status) = 0; - - // NOT IMPLEMENTED YET! - //virtual int getConfigStartup(RsConfigStartup ¶ms) = 0; - - /** - * @brief getTotalBandwidthRates returns the current bandwidths rates - * @jsonapi{development} - * @param[out] rates - * @return returns 1 on succes and 0 otherwise - */ - virtual int getTotalBandwidthRates(RsConfigDataRates &rates) = 0; - - /** - * @brief getAllBandwidthRates get the bandwidth rates for all peers - * @jsonapi{development} - * @param[out] ratemap map with peers->rates - * @return returns 1 on succes and 0 otherwise - */ - virtual int getAllBandwidthRates(std::map &ratemap) = 0; - - /** - * @brief getTrafficInfo returns a list of all tracked traffic clues - * @jsonapi{development} - * @param[out] out_lst outgoing traffic clues - * @param[out] in_lst incomming traffic clues - * @return returns 1 on succes and 0 otherwise - */ - virtual int getTrafficInfo(std::list& out_lst,std::list& in_lst) = 0 ; - - /* From RsInit */ - - // NOT IMPLEMENTED YET! - //virtual std::string RsConfigDirectory() = 0; - //virtual std::string RsConfigKeysDirectory() = 0; - - //virtual std::string RsProfileConfigDirectory() = 0; - //virtual bool getStartMinimised() = 0; - //virtual std::string getRetroShareLink() = 0; - - //virtual bool getAutoLogin() = 0; - //virtual void setAutoLogin(bool autoLogin) = 0; - //virtual bool RsClearAutoLogin() = 0; - - //virtual std::string getRetroshareDataDirectory() = 0; - - /* New Stuff */ - - virtual RsConfigUserLvl getUserLevel() = 0; - - virtual RsNetState getNetState() = 0; - virtual RsNetworkMode getNetworkMode() = 0; - virtual RsNatTypeMode getNatTypeMode() = 0; - virtual RsNatHoleMode getNatHoleMode() = 0; - virtual RsConnectModes getConnectModes() = 0; - - virtual bool getConfigurationOption(uint32_t key, std::string &opt) = 0; - virtual bool setConfigurationOption(uint32_t key, const std::string &opt) = 0; - - - /* Operating Mode */ - /** - * @brief getOperatingMode get current operating mode - * @jsonapi{development} - * @return return the current operating mode - */ - virtual RsOpMode getOperatingMode() = 0; - - /** - * @brief setOperatingMode set the current oprating mode - * @jsonapi{development} - * @param[in] opMode new opearting mode - * @return - */ - virtual bool setOperatingMode(RsOpMode opMode) = 0; - - /** - * @brief setOperatingMode set the current operating mode from string - * @param[in] opModeStr new operating mode as string - * @return - */ - virtual bool setOperatingMode(const std::string &opModeStr) = 0; - - /* Data Rate Control - to be moved here */ - /** - * @brief SetMaxDataRates set maximum upload and download rates - * @jsonapi{development} - * @param[in] downKb download rate in kB - * @param[in] upKb upload rate in kB - * @return returns 1 on succes and 0 otherwise - */ - virtual int SetMaxDataRates( int downKb, int upKb ) = 0; - - /** - * @brief GetMaxDataRates get maximum upload and download rates - * @jsonapi{development} - * @param[out] inKb download rate in kB - * @param[out] outKb upload rate in kB - * @return returns 1 on succes and 0 otherwise - */ - virtual int GetMaxDataRates( int &inKb, int &outKb ) = 0; - - /** - * @brief GetCurrentDataRates get current upload and download rates - * @jsonapi{development} - * @param[out] inKb download rate in kB - * @param[out] outKb upload rate in kB - * @return returns 1 on succes and 0 otherwise - */ - virtual int GetCurrentDataRates( float &inKb, float &outKb ) = 0; - virtual int GetTrafficSum( uint64_t &inb, uint64_t &outb ) = 0; -}; - -#endif diff --git a/libretroshare/src/retroshare/rsdht.h b/libretroshare/src/retroshare/rsdht.h deleted file mode 100644 index f62d029eb..000000000 --- a/libretroshare/src/retroshare/rsdht.h +++ /dev/null @@ -1,230 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsdht.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RETROSHARE_DHT_GUI_INTERFACE_H -#define RETROSHARE_DHT_GUI_INTERFACE_H - -#include -#include -#include -#include -#include "util/rsnet.h" -#include "retroshare/rsflags.h" - -/* The Main Interface Class - for information about your Peers */ -class RsDht; -extern RsDht *rsDht; - -//std::ostream &operator<<(std::ostream &out, const RsPhotoShowDetails &detail); -//std::ostream &operator<<(std::ostream &out, const RsPhotoDetails &detail); - -enum class RsDhtPeerType : uint8_t -{ - ANY = 0, - OTHER = 1, - FOF = 2, - FRIEND = 3 -}; - -enum class RsDhtPeerDht : uint8_t -{ - NOT_ACTIVE = 0, - SEARCHING = 1, - FAILURE = 2, - OFFLINE = 3, - UNREACHABLE = 4, - ONLINE = 5 -}; - -enum class RsDhtPeerConnectState : uint8_t -{ - DISCONNECTED = 1, - UDP_STARTED = 2, - CONNECTED = 3 -}; - -enum class RsDhtPeerRequest : uint8_t -{ - STOPPED = 1, - RUNNING = 2 -}; - -enum class RsDhtTouMode : uint8_t -{ - NONE = 0, - DIRECT = 1, - PROXY = 2, - RELAY = 3 -}; - -enum class RsDhtRelayClass : uint8_t -{ - ALL = 0, - GENERAL = 1, - FOF = 2, - FRIENDS = 3, - - NUM_CLASS = 4 -}; - -enum class RsDhtRelayMode : uint16_t -{ - DISABLED= 0x0000, - ENABLED = 0x0001, - - MASK = 0x00f0, - OFF = 0x0010, - ON = 0x0020, - SERVER = 0x0040 -}; -RS_REGISTER_ENUM_FLAGS_TYPE(RsDhtRelayMode) - -class RsDhtPeer -{ - public: - RsDhtPeer(); - - int mBucket; - std::string mDhtId; - std::string mAddr; - rstime_t mLastSendTime; - rstime_t mLastRecvTime; - rstime_t mFoundTime; - uint32_t mPeerFlags; - uint32_t mExtraFlags; -}; - -class RsDhtNetPeer -{ - public: - RsDhtNetPeer(); - - std::string mDhtId; - RsPeerId mRsId; - - RsDhtPeerType mPeerType; - RsDhtPeerDht mDhtState; - - std::string mConnectState; // connectLogic. - - RsDhtPeerConnectState mPeerConnectState; - RsDhtTouMode mPeerConnectMode; - bool mExclusiveProxyLock; - - std::string mPeerConnectProxyId; - - RsDhtPeerRequest mPeerReqState; - std::string mCbPeerMsg; // Peer Cb Mgs. - -}; - -class RsDhtRelayEnd -{ - public: - - RsDhtRelayEnd(); - std::string mLocalAddr; - std::string mProxyAddr; - std::string mRemoteAddr; - rstime_t mCreateTS; -}; - -class RsDhtRelayProxy -{ - public: - RsDhtRelayProxy(); - - std::string mSrcAddr; - std::string mDestAddr; - - double mBandwidth; - int mRelayClass; - rstime_t mLastTS; - rstime_t mCreateTS; - - //uint32_t mDataSize; - //rstime_t mLastBandwidthTS; - -}; -class RsDhtFilteredPeer -{ -public: - struct sockaddr_in mAddr; - uint32_t mFilterFlags; /* reasons why we are filtering */ - rstime_t mFilterTS; - rstime_t mLastSeen; -}; - -class RsDht -{ - public: - - RsDht() { return; } -virtual ~RsDht() { return; } - -virtual uint32_t getNetState(uint32_t type) = 0; -virtual int getDhtPeers(int lvl, std::list &peers) = 0; -virtual int getNetPeerList(std::list &peerIds) = 0; -virtual int getNetPeerStatus(const RsPeerId& peerId, RsDhtNetPeer &status) = 0; - -virtual int getRelayEnds(std::list &relayEnds) = 0; -virtual int getRelayProxies(std::list &relayProxies) = 0; - -//virtual int getNetFailedPeer(std::string peerId, PeerStatus &status); - -virtual std::string getUdpAddressString() = 0; - -virtual void getDhtRates(float &read, float &write) = 0; -virtual void getRelayRates(float &read, float &write, float &relay) = 0; - - // Interface for controlling Relays & DHT Relay Mode -virtual int getRelayServerList(std::list &ids) = 0; -virtual int addRelayServer(std::string ids) = 0; -virtual int removeRelayServer(std::string ids) = 0; - -virtual RsDhtRelayMode getRelayMode() = 0; -virtual int setRelayMode(RsDhtRelayMode mode) = 0; - -virtual int getRelayAllowance(RsDhtRelayClass classIdx, uint32_t &count, uint32_t &bandwidth) = 0; -virtual int setRelayAllowance(RsDhtRelayClass classIdx, uint32_t count, uint32_t bandwidth) = 0; - - // So we can provide to clients. -virtual bool getOwnDhtId(std::string &ownDhtId) = 0; - -virtual bool isAddressBanned(const struct sockaddr_storage& raddr) =0; -virtual void getListOfBannedIps(std::list& lst) =0; - -#if 0 -virtual std::string getPeerStatusString(); -virtual std::string getDhtStatusString(); - -virtual int get_dht_queries(std::map &queries); -virtual int get_query_status(std::string id, bdQuerySummary &query); - -virtual int get_peer_status(std::string peerId, PeerStatus &status); - -virtual int get_net_failedpeers(std::list &peerIds); -virtual int get_failedpeer_status(std::string peerId, PeerStatus &status); -#endif - -}; - -#endif diff --git a/libretroshare/src/retroshare/rsdisc.h b/libretroshare/src/retroshare/rsdisc.h deleted file mode 100644 index 06311be6c..000000000 --- a/libretroshare/src/retroshare/rsdisc.h +++ /dev/null @@ -1,32 +0,0 @@ -/******************************************************************************* - * RetroShare gossip discovery - discovery2 retro-compatibility include * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include "retroshare/rsgossipdiscovery.h" -#include "util/rsdeprecate.h" - -#warning "Including retroshare/rsdisc.h is deprecated, \ -use retroshare/rsgossipdiscovery.h instead" - -using RsDisc RS_DEPRECATED_FOR("RsGossipDiscovery") = RsGossipDiscovery; - -#define rsDisc rsGossipDiscovery.get() diff --git a/libretroshare/src/retroshare/rsevents.h b/libretroshare/src/retroshare/rsevents.h deleted file mode 100644 index 845c43205..000000000 --- a/libretroshare/src/retroshare/rsevents.h +++ /dev/null @@ -1,263 +0,0 @@ -/******************************************************************************* - * Retroshare events service * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2019-2020 Retroshare Team * - * Copyright (C) 2019-2020 Gioacchino Mazzurco * - * Copyright (C) 2020 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -#include "util/rsmemory.h" -#include "util/rsurl.h" -#include "serialiser/rsserializable.h" -#include "serialiser/rstypeserializer.h" -#include "util/rstime.h" -#include "util/rsdebug.h" - -class RsEvents; - -/** - * Pointer to global instance of RsEvents service implementation - * @jsonapi{development} - * - * TODO: this should become std::weak_ptr once we have a reasonable services - * management. - */ -extern RsEvents* rsEvents; - -/** - * @brief Events types. - * When creating a new type of event, add a new type here and use that to - * initialize mType in the constructor of your derivative of @see RsEvent - */ -enum class RsEventType : uint32_t -{ - __NONE = 0, /// Used internally to detect invalid event type passed - - /// @see RsBroadcastDiscovery - BROADCAST_DISCOVERY = 1, - - /// @see RsDiscPendingPgpReceivedEvent - GOSSIP_DISCOVERY = 2, - - /// @see AuthSSL - AUTHSSL_CONNECTION_AUTENTICATION = 3, - - /// @see pqissl - PEER_CONNECTION = 4, - - /// @see RsGxsChanges, used also in @see RsGxsBroadcast - GXS_CHANGES = 5, - - /// Emitted when a peer state changes, @see RsPeers - PEER_STATE_CHANGED = 6, - - /// @see RsMailStatusEvent - MAIL_STATUS = 7, - - /// @see RsGxsCircleEvent - GXS_CIRCLES = 8, - - /// @see RsGxsChannelEvent - GXS_CHANNELS = 9, - - /// @see RsGxsForumEvent - GXS_FORUMS = 10, - - /// @see RsGxsPostedEvent - GXS_POSTED = 11, - - /// @see RsGxsPostedEvent - GXS_IDENTITY = 12, - - /// @see RsFiles @deprecated - SHARED_DIRECTORIES = 13, - - /// @see RsFiles - FILE_TRANSFER = 14, - - /// @see RsMsgs - CHAT_MESSAGE = 15, - - /// @see rspeers.h - NETWORK = 16, - - /// @see RsMailTagEvent - MAIL_TAG = 17, - - /** Emitted to update library clients about file hashing being completed */ - FILE_HASHING_COMPLETED = 20, - - /// @see rspeers.h - TOR_MANAGER = 21, - - __MAX /// Used internally, keep last -}; - -enum class RsEventsErrorNum : int32_t -{ - EVENT_TYPE_UNDEFINED = 3004, - EVENT_TYPE_OUT_OF_RANGE = 3005, - INVALID_HANDLER_ID = 3006, - NULL_EVENT_POINTER = 3007 -}; - -struct RsEventsErrorCategory: std::error_category -{ - const char* name() const noexcept override - { return "RetroShare Events"; } - - std::string message(int ev) const override - { - switch (static_cast(ev)) - { - case RsEventsErrorNum::EVENT_TYPE_UNDEFINED: - return "Undefined event type"; - case RsEventsErrorNum::EVENT_TYPE_OUT_OF_RANGE: - return "Event type out of range"; - case RsEventsErrorNum::INVALID_HANDLER_ID: - return "Invalid handler id"; - default: - return rsErrorNotInCategory(ev, name()); - } - } - - std::error_condition default_error_condition(int ev) const noexcept override; - - const static RsEventsErrorCategory instance; -}; - - -namespace std -{ -/** Register RsJsonApiErrorNum as an error condition enum, must be in std - * namespace */ -template<> struct is_error_condition_enum : true_type {}; -} - -/** Provide RsEventsErrorNum conversion to std::error_condition, must be in - * same namespace of RsJsonApiErrorNum */ -inline std::error_condition make_error_condition(RsEventsErrorNum e) noexcept -{ - return std::error_condition( - static_cast(e), RsEventsErrorCategory::instance ); -}; - - -/** - * This struct is not meant to be used directly, you should create events type - * deriving from it. - */ -struct RsEvent : RsSerializable -{ -protected: - explicit RsEvent(RsEventType type) : - mType(type), mTimePoint(std::chrono::system_clock::now()) {} - - RsEvent() = delete; - -public: - RsEventType mType; - std::chrono::system_clock::time_point mTimePoint; - - /** - * Derived types must call this method at beginning of their implementation - * of serial_process - * @see RsSerializable - */ - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - RS_SERIAL_PROCESS(mType); - - rstime_t mTime = std::chrono::system_clock::to_time_t(mTimePoint); - RS_SERIAL_PROCESS(mTime); - mTimePoint = std::chrono::system_clock::from_time_t(mTime); - } - - ~RsEvent() override; -}; - -typedef uint32_t RsEventsHandlerId_t; - -class RsEvents -{ -public: - /** - * @brief Post event to the event queue. - * @param[in] event - * @return Success or error details. - */ - virtual std::error_condition postEvent( - std::shared_ptr event ) = 0; - - /** - * @brief Send event directly to handlers. Blocking API - * The handlers get exectuded on the caller thread. - * @param[in] event - * @return Success or error details. - */ - virtual std::error_condition sendEvent( - std::shared_ptr event ) = 0; - - /** - * @brief Generate unique handler identifier - * @return generate Id - */ - virtual RsEventsHandlerId_t generateUniqueHandlerId() = 0; - - /** - * @brief Register events handler - * Every time an event is dispatced the registered events handlers will get - * their method handleEvent called with the event passed as paramether. - * @attention Callbacks must not fiddle internally with methods of this - * class otherwise a deadlock will happen. - * @jsonapi{development,manualwrapper} - * @param multiCallback Function that will be called each time an event - * is dispatched. - * @param[inout] hId Optional storage for handler id, useful to - * eventually unregister the handler later. The - * value may be provided to the function call but - * must habe been generated with - * @see generateUniqueHandlerId() - * @param[in] eventType Optional type of event for which the callback is - * called, if __NONE is passed multiCallback is - * called for every events without filtering. - * @return Success or error details. - */ - virtual std::error_condition registerEventsHandler( - std::function)> multiCallback, - RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0), - RsEventType eventType = RsEventType::__NONE ) = 0; - - /** - * @brief Unregister event handler - * @param[in] hId Id of the event handler to unregister - * @return Success or error details. - */ - virtual std::error_condition unregisterEventsHandler( - RsEventsHandlerId_t hId ) = 0; - - virtual ~RsEvents(); -}; diff --git a/libretroshare/src/retroshare/rsexpr.h b/libretroshare/src/retroshare/rsexpr.h deleted file mode 100644 index 562d6e342..000000000 --- a/libretroshare/src/retroshare/rsexpr.h +++ /dev/null @@ -1,407 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsexpr.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Kashif Kaleem * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include - -#include "util/rsprint.h" -#include "retroshare/rstypes.h" -#include "util/rstime.h" - -/****************************************************************************************** -Enumerations defining the Operators usable in the Boolean search expressions -******************************************************************************************/ - -namespace RsRegularExpression -{ -enum LogicalOperator{ - AndOp=0, /* exp AND exp */ - OrOp=1, /* exp OR exp */ - XorOp=2 /* exp XOR exp */ -}; - - -/* Operators for String Queries */ -enum StringOperator{ - ContainsAnyStrings = 0, /* e.g. name contains any of 'conference' 'meeting' 'presentation' */ - ContainsAllStrings = 1, /* same as above except that it contains ALL of the strings */ - EqualsString = 2 /* exactly equal*/ -}; - -/* Comparison operators ( >, <, >=, <=, == and InRange ) */ -enum RelOperator{ - Equals = 0, - GreaterEquals = 1, - Greater = 2, - SmallerEquals = 3, - Smaller = 4, - InRange = 5 /* lower limit <= value <= upper limit*/ -}; - -/******************************************************************************************** - * Helper class for further serialisation - ********************************************************************************************/ - -class StringExpression ; -class Expression ; - -class LinearizedExpression -{ -public: - std::vector _tokens ; - std::vector _ints ; - std::vector _strings ; - - typedef enum { EXPR_DATE = 0, - EXPR_POP = 1, - EXPR_SIZE = 2, - EXPR_HASH = 3, - EXPR_NAME = 4, - EXPR_PATH = 5, - EXPR_EXT = 6, - EXPR_COMP = 7, - EXPR_SIZE_MB = 8 } token ; - - static Expression *toExpr(const LinearizedExpression& e) ; - - std::string GetStrings(); - -private: - static Expression *toExpr(const LinearizedExpression& e,int&,int&,int&) ; - static void readStringExpr(const LinearizedExpression& e,int& n_ints,int& n_strings,std::list& strings,bool& b,StringOperator& op) ; -}; - - -/****************************************************************************************** -Boolean Search Expression -classes: - - Expression: The base class of all expression typest - CompoundExpression: The expression which uses a logical operator to combine - the results of two expressions - StringExpression: An expression which uses some sort of string comparison. - RelExpression: A Relational Expression where > < >= <= == make sense. - e.g. size date etc - -******************************************************************************************/ - -/*! - * \brief The ExpFileEntry class - * This is the base class the regular expressions can operate on. Derive it to fit your own needs! - */ -class ExpFileEntry -{ -public: - virtual const std::string& file_name() const =0; - virtual uint64_t file_size() const =0; - virtual rstime_t file_modtime() const =0; - virtual uint32_t file_popularity() const =0; - virtual std::string file_parent_path() const =0; - virtual const RsFileHash& file_hash() const =0; -}; - -class Expression -{ -public: - virtual bool eval (const ExpFileEntry& file) = 0; - virtual ~Expression() {}; - - virtual void linearize(LinearizedExpression& e) const = 0 ; - virtual std::string toStdString() const = 0 ; -}; - -class CompoundExpression : public Expression -{ -public: - CompoundExpression( enum LogicalOperator op, Expression * exp1, Expression *exp2) - : Lexp(exp1), Rexp(exp2), Op(op){ } - - bool eval (const ExpFileEntry& file) { - if (Lexp == NULL or Rexp == NULL) { - return false; - } - switch (Op){ - case AndOp: - return Lexp->eval(file) && Rexp->eval(file); - case OrOp: - return Lexp->eval(file) || Rexp->eval(file); - case XorOp: - return Lexp->eval(file) ^ Rexp->eval(file); - default: - return false; - } - } - virtual ~CompoundExpression(){ - delete Lexp; - delete Rexp; - } - - virtual std::string toStdString() const - { - switch(Op) - { - case AndOp: return "(" + Lexp->toStdString() + ") AND (" + Rexp->toStdString() +")" ; - case OrOp: return "(" + Lexp->toStdString() + ") OR (" + Rexp->toStdString() +")" ; - case XorOp: return "(" + Lexp->toStdString() + ") XOR (" + Rexp->toStdString() +")" ; - default: - return "" ; - } - } - - virtual void linearize(LinearizedExpression& e) const ; -private: - Expression *Lexp; - Expression *Rexp; - enum LogicalOperator Op; - -}; - -class StringExpression: public Expression -{ -public: - StringExpression(enum StringOperator op, const std::list &t, bool ic): Op(op),terms(t), IgnoreCase(ic){} - - virtual void linearize(LinearizedExpression& e) const ; - virtual std::string toStdStringWithParam(const std::string& varstr) const; -protected: - bool evalStr(const std::string &str); - - enum StringOperator Op; - std::list terms; - bool IgnoreCase; -}; - -template -class RelExpression: public Expression -{ -public: - RelExpression(enum RelOperator op, T lv, T hv): Op(op), LowerValue(lv), HigherValue(hv) {} - - virtual void linearize(LinearizedExpression& e) const ; - virtual std::string toStdStringWithParam(const std::string& typestr) const; -protected: - bool evalRel(T val); - - enum RelOperator Op; - T LowerValue; - T HigherValue; -}; - -template<> void RelExpression::linearize(LinearizedExpression& e) const ; - -template -bool RelExpression::evalRel(T val) { - switch (Op) { - case Equals: - return LowerValue == val; - case GreaterEquals: - return LowerValue >= val; - case Greater: - return LowerValue > val; - case SmallerEquals: - return LowerValue <= val; - case Smaller: - return LowerValue < val; - case InRange: - return (LowerValue <= val) && (val <= HigherValue); - default: - return false; - } -} - -template -std::string RelExpression::toStdStringWithParam(const std::string& typestr) const -{ - std::string LowerValueStr = RsUtil::NumberToString(LowerValue) ; - - switch (Op) { - case Equals: return typestr + " = " + LowerValueStr ; - case GreaterEquals: return typestr + " <= "+ LowerValueStr ; - case Greater: return typestr + " < " + LowerValueStr ; - case SmallerEquals: return typestr + " >= "+ LowerValueStr ; - case Smaller: return typestr + " > " + LowerValueStr ; - case InRange: return LowerValueStr + " <= " + typestr + " <= " + RsUtil::NumberToString(HigherValue) ; - default: - return ""; - } -} - -/****************************************************************************************** -Binary Predicate for Case Insensitive search - -******************************************************************************************/ -/*Binary predicate for case insensitive character comparison.*/ -/*TODOS: - *Factor locales in the comparison - */ -struct CompareCharIC : - public std::binary_function< char , char , bool> { - - bool operator () ( char ch1 , char ch2 ) const { - return tolower( static_cast < unsigned char > (ch1) ) - == tolower( static_cast < unsigned char > (ch2) ); - } - -}; - -/****************************************************************************************** -Some implementations of StringExpressions. - -******************************************************************************************/ - -class NameExpression: public StringExpression -{ -public: - NameExpression(enum StringOperator op, const std::list &t, bool ic): - StringExpression(op,t,ic) {} - bool eval(const ExpFileEntry& file); - - virtual std::string toStdString() const { return StringExpression::toStdStringWithParam("NAME"); } - - virtual void linearize(LinearizedExpression& e) const - { - e._tokens.push_back(LinearizedExpression::EXPR_NAME) ; - StringExpression::linearize(e) ; - } -}; - -class PathExpression: public StringExpression { -public: - PathExpression(enum StringOperator op, const std::list &t, bool ic): - StringExpression(op,t,ic) {} - bool eval(const ExpFileEntry& file); - - virtual std::string toStdString()const { return StringExpression::toStdStringWithParam("PATH"); } - - virtual void linearize(LinearizedExpression& e) const - { - e._tokens.push_back(LinearizedExpression::EXPR_PATH) ; - StringExpression::linearize(e) ; - } -}; - -class ExtExpression: public StringExpression { -public: - ExtExpression(enum StringOperator op, const std::list &t, bool ic): - StringExpression(op,t,ic) {} - bool eval(const ExpFileEntry& file); - - virtual std::string toStdString()const { return StringExpression::toStdStringWithParam("EXTENSION"); } - - virtual void linearize(LinearizedExpression& e) const - { - e._tokens.push_back(LinearizedExpression::EXPR_EXT) ; - StringExpression::linearize(e) ; - } -}; - -class HashExpression: public StringExpression { -public: - HashExpression(enum StringOperator op, const std::list &t): - StringExpression(op,t, true) {} - bool eval(const ExpFileEntry& file); - - virtual std::string toStdString() const { return StringExpression::toStdStringWithParam("HASH"); } - - virtual void linearize(LinearizedExpression& e) const - { - e._tokens.push_back(LinearizedExpression::EXPR_HASH) ; - StringExpression::linearize(e) ; - } -}; - -/****************************************************************************************** -Some implementations of Relational Expressions. - -******************************************************************************************/ - -class DateExpression: public RelExpression -{ -public: - DateExpression(enum RelOperator op, int v): RelExpression(op,v,v){} - DateExpression(enum RelOperator op, int lv, int hv): - RelExpression(op,lv,hv) {} - bool eval(const ExpFileEntry& file); - - virtual std::string toStdString() const { return RelExpression::toStdStringWithParam("DATE"); } - - virtual void linearize(LinearizedExpression& e) const - { - e._tokens.push_back(LinearizedExpression::EXPR_DATE) ; - RelExpression::linearize(e) ; - } -}; - -class SizeExpression: public RelExpression -{ -public: - SizeExpression(enum RelOperator op, int v): RelExpression(op,v,v){} - SizeExpression(enum RelOperator op, int lv, int hv): - RelExpression(op,lv,hv) {} - bool eval(const ExpFileEntry& file); - - virtual std::string toStdString() const { return RelExpression::toStdStringWithParam("SIZE"); } - - virtual void linearize(LinearizedExpression& e) const - { - e._tokens.push_back(LinearizedExpression::EXPR_SIZE) ; - RelExpression::linearize(e) ; - } -}; - -class SizeExpressionMB: public RelExpression -{ -public: - SizeExpressionMB(enum RelOperator op, int v): RelExpression(op,v,v){} - SizeExpressionMB(enum RelOperator op, int lv, int hv): - RelExpression(op,lv,hv) {} - bool eval(const ExpFileEntry& file); - - virtual std::string toStdString() const { return RelExpression::toStdStringWithParam("SIZE"); } - - virtual void linearize(LinearizedExpression& e) const - { - e._tokens.push_back(LinearizedExpression::EXPR_SIZE_MB) ; - RelExpression::linearize(e) ; - } -}; -class PopExpression: public RelExpression -{ -public: - PopExpression(enum RelOperator op, int v): RelExpression(op,v,v){} - PopExpression(enum RelOperator op, int lv, int hv): RelExpression(op,lv,hv) {} - PopExpression(const LinearizedExpression& e) ; - bool eval(const ExpFileEntry& file); - - virtual std::string toStdString() const { return RelExpression::toStdStringWithParam("POPULARITY"); } - - virtual void linearize(LinearizedExpression& e) const - { - e._tokens.push_back(LinearizedExpression::EXPR_POP) ; - RelExpression::linearize(e) ; - } -}; -} - - diff --git a/libretroshare/src/retroshare/rsfiles.h b/libretroshare/src/retroshare/rsfiles.h deleted file mode 100644 index 17b68aede..000000000 --- a/libretroshare/src/retroshare/rsfiles.h +++ /dev/null @@ -1,1022 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsfiles.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2008 Robert Fernie * - * Copyright (C) 2018-2020 Gioacchino Mazzurco * - * Copyright (C) 2019-2020 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include "rstypes.h" -#include "serialiser/rsserializable.h" -#include "rsturtle.h" -#include "util/rstime.h" -#include "retroshare/rsevents.h" -#include "util/rsmemory.h" -#include "util/rsdebug.h" - -class RsFiles; - -/** - * Pointer to global instance of RsFiles service implementation - * @jsonapi{development} - */ -extern RsFiles* rsFiles; - -enum class RsFilesErrorNum : int32_t -{ - FILES_HANDLE_NOT_FOUND = 2004, -}; - -struct RsFilesErrorCategory: std::error_category -{ - const char* name() const noexcept override - { return "RetroShare Files"; } - - std::string message(int ev) const override - { - switch (static_cast(ev)) - { - case RsFilesErrorNum::FILES_HANDLE_NOT_FOUND: - return "Files handle not found"; - default: - return rsErrorNotInCategory(ev, name()); - } - } - - std::error_condition default_error_condition(int ev) const noexcept override; - - const static RsFilesErrorCategory instance; -}; - - -namespace std -{ -/** Register RsFilesErrorNum as an error condition enum, must be in std - * namespace */ -template<> struct is_error_condition_enum : true_type {}; -} - -/** Provide RsJsonApiErrorNum conversion to std::error_condition, must be in - * same namespace of RsJsonApiErrorNum */ -inline std::error_condition make_error_condition(RsFilesErrorNum e) noexcept -{ - return std::error_condition( - static_cast(e), RsFilesErrorCategory::instance ); -}; - - -namespace RsRegularExpression { class Expression; } - -/* These are used mainly by ftController at the moment */ -const uint32_t RS_FILE_CTRL_PAUSE = 0x00000100; -const uint32_t RS_FILE_CTRL_START = 0x00000200; -const uint32_t RS_FILE_CTRL_FORCE_CHECK = 0x00000400; - -const uint32_t RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT = 0x00000001 ; -const uint32_t RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE = 0x00000002 ; - -const uint32_t RS_FILE_PERM_DIRECT_DL_YES = 0x00000001 ; -const uint32_t RS_FILE_PERM_DIRECT_DL_NO = 0x00000002 ; -const uint32_t RS_FILE_PERM_DIRECT_DL_PER_USER = 0x00000003 ; - -const uint32_t RS_FILE_RATE_TRICKLE = 0x00000001; -const uint32_t RS_FILE_RATE_SLOW = 0x00000002; -const uint32_t RS_FILE_RATE_STANDARD = 0x00000003; -const uint32_t RS_FILE_RATE_FAST = 0x00000004; -const uint32_t RS_FILE_RATE_STREAM_AUDIO = 0x00000005; -const uint32_t RS_FILE_RATE_STREAM_VIDEO = 0x00000006; - -const uint32_t RS_FILE_PEER_ONLINE = 0x00001000; -const uint32_t RS_FILE_PEER_OFFLINE = 0x00002000; - -const uint32_t RS_FILE_SHARE_FLAGS_IGNORE_PREFIXES = 0x0001 ; -const uint32_t RS_FILE_SHARE_FLAGS_IGNORE_SUFFIXES = 0x0002 ; -const uint32_t RS_FILE_SHARE_FLAGS_IGNORE_DUPLICATES = 0x0004 ; - -const uint32_t RS_FILE_SHARE_PARAMETER_DEFAULT_MAXIMUM_DEPTH = 8; - -/************************************ - * Used To indicate where to search. - * - * The Order of these is very important, - * it specifies the search order too. - * - */ - -// Flags used when requesting info about transfers, mostly to filter out the result. -// -const FileSearchFlags RS_FILE_HINTS_CACHE_deprecated ( 0x00000001 ); -const FileSearchFlags RS_FILE_HINTS_EXTRA ( 0x00000002 ); -const FileSearchFlags RS_FILE_HINTS_LOCAL ( 0x00000004 ); -const FileSearchFlags RS_FILE_HINTS_REMOTE ( 0x00000008 ); -const FileSearchFlags RS_FILE_HINTS_DOWNLOAD ( 0x00000010 ); -const FileSearchFlags RS_FILE_HINTS_UPLOAD ( 0x00000020 ); -const FileSearchFlags RS_FILE_HINTS_SPEC_ONLY ( 0x01000000 ); - -const FileSearchFlags RS_FILE_HINTS_NETWORK_WIDE ( 0x00000080 );// can be downloaded anonymously -const FileSearchFlags RS_FILE_HINTS_BROWSABLE ( 0x00000100 );// browsable by friends -const FileSearchFlags RS_FILE_HINTS_SEARCHABLE ( 0x00000200 );// can be searched anonymously -const FileSearchFlags RS_FILE_HINTS_PERMISSION_MASK ( 0x00000380 );// OR of the last tree flags. Used to filter out. - -/** Flags used when requesting a new file transfer */ -enum class FileRequestFlags: uint32_t -{ - /// Enable requesting file via turtle routing. - ANONYMOUS_ROUTING = 0x00000040, - - /// Asks (TODO: or enforce?) for end-to-end encryption of file trasfer - ENCRYPTED = 0x00000080, - - /// Asks (TODO: or enforce?) no end-to-end encryption of file trasfer - UNENCRYPTED = 0x00000100, - - /// Start trasfer very slow - SLOW = 0x00002000, - - /// Disable searching for potential direct sources - NO_DIRECT_SEARCH = 0x02000000 -}; -RS_REGISTER_ENUM_FLAGS_TYPE(FileRequestFlags) - -/// @deprecated Flags used when requesting a transfer -/// @see FileRequestFlags instead -const TransferRequestFlags RS_FILE_REQ_ANONYMOUS_ROUTING ( 0x00000040 ); // Use to ask turtle router to download the file. -const TransferRequestFlags RS_FILE_REQ_ENCRYPTED ( 0x00000080 ); // Asks for end-to-end encryption of file at the level of ftServer -const TransferRequestFlags RS_FILE_REQ_UNENCRYPTED ( 0x00000100 ); // Asks for no end-to-end encryption of file at the level of ftServer -const TransferRequestFlags RS_FILE_REQ_ASSUME_AVAILABILITY ( 0x00000200 ); // Assume full source availability. Used for cache files. -const TransferRequestFlags RS_FILE_REQ_CACHE_deprecated ( 0x00000400 ); // Old stuff used for cache files. Not used anymore. -const TransferRequestFlags RS_FILE_REQ_EXTRA ( 0x00000800 ); -const TransferRequestFlags RS_FILE_REQ_MEDIA ( 0x00001000 ); -const TransferRequestFlags RS_FILE_REQ_BACKGROUND ( 0x00002000 ); // To download slowly. -const TransferRequestFlags RS_FILE_REQ_NO_SEARCH ( 0x02000000 ); // disable searching for potential direct sources. - -// const uint32_t RS_FILE_HINTS_SHARE_FLAGS_MASK = RS_FILE_HINTS_NETWORK_WIDE_OTHERS | RS_FILE_HINTS_BROWSABLE_OTHERS -// | RS_FILE_HINTS_NETWORK_WIDE_GROUPS | RS_FILE_HINTS_BROWSABLE_GROUPS ; - -enum class RsSharedDirectoriesEventCode: uint8_t { - UNKNOWN = 0x00, - STARTING_DIRECTORY_SWEEP = 0x01, // (void) - HASHING_FILE = 0x02, // mMessage: full path and hashing speed of the file being hashed - DIRECTORY_SWEEP_ENDED = 0x03, // (void) - SAVING_FILE_INDEX = 0x04, // (void) - EXTRA_LIST_FILE_ADDED = 0x05, // (void) - EXTRA_LIST_FILE_REMOVED = 0x06, // (void) -}; - -enum class RsFileTransferEventCode: uint8_t { - UNKNOWN = 0x00, - DOWNLOAD_COMPLETE = 0x01, // mHash: hash of the complete file - COMPLETED_FILES_REMOVED = 0x02, // -}; - -struct RS_DEPRECATED_FOR("Packing arbitrary data into an std::string is bad idea") -RsSharedDirectoriesEvent: RsEvent -{ - RsSharedDirectoriesEvent() : RsEvent(RsEventType::SHARED_DIRECTORIES), mEventCode(RsSharedDirectoriesEventCode::UNKNOWN) {} - ~RsSharedDirectoriesEvent() override = default; - - ///* @see RsEvent @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) override - { - RsEvent::serial_process(j, ctx); - - RS_SERIAL_PROCESS(mEventCode); - RS_SERIAL_PROCESS(mMessage); - } - - RsSharedDirectoriesEventCode mEventCode; - std::string mMessage; -}; - -struct RsFileHashingCompletedEvent: RsEvent -{ - RsFileHashingCompletedEvent(): - RsEvent(RsEventType::FILE_HASHING_COMPLETED), mHashingSpeed(0) {} - - ///* @see RsEvent @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RsEvent::serial_process(j, ctx); - RS_SERIAL_PROCESS(mFilePath); - RS_SERIAL_PROCESS(mFileHash); - RS_SERIAL_PROCESS(mHashingSpeed); - } - - /// Complete path of the file being hashed - std::string mFilePath; - - /// File hash, null if error occurred - RsFileHash mFileHash; - - /// Hashing speed in MB/s - double mHashingSpeed; -}; - -struct RsFileTransferEvent: RsEvent -{ - RsFileTransferEvent() : RsEvent(RsEventType::FILE_TRANSFER), mFileTransferEventCode(RsFileTransferEventCode::UNKNOWN) {} - ~RsFileTransferEvent() override = default; - - ///* @see RsEvent @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) override - { - RsEvent::serial_process(j, ctx); - - RS_SERIAL_PROCESS(mFileTransferEventCode); - RS_SERIAL_PROCESS(mHash); - } - - RsFileTransferEventCode mFileTransferEventCode; - RsFileHash mHash; -}; -struct SharedDirInfo : RsSerializable -{ - static bool sameLists(const std::list& l1,const std::list& l2) - { - std::list::const_iterator it1(l1.begin()) ; - std::list::const_iterator it2(l2.begin()) ; - - for(; (it1!=l1.end() && it2!=l2.end());++it1,++it2) - if(*it1 != *it2) - return false ; - - return it1 == l1.end() && it2 == l2.end() ; - } - - std::string filename; - std::string virtualname; - - /// combnation of DIR_FLAGS_ANONYMOUS_DOWNLOAD | DIR_FLAGS_BROWSABLE | ... - FileStorageFlags shareflags; - std::list parent_groups; - - /// @see RsSerializable::serial_process - virtual void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) - { - RS_SERIAL_PROCESS(filename); - RS_SERIAL_PROCESS(virtualname); - RS_SERIAL_PROCESS(shareflags); - RS_SERIAL_PROCESS(parent_groups); - } -}; - -struct SharedDirStats -{ - uint32_t total_number_of_files ; - uint64_t total_shared_size ; -}; - -/** This class represents a tree of directories and files, only with their names - * size and hash. It is used to create collection links in the GUI and to - * transmit directory information between services. This class is independent - * from the existing FileHierarchy classes used in storage because we need a - * very copact serialization and storage size since we create links with it. - * Besides, we cannot afford to risk the leak of other local information - * by using the orignal classes. - */ -struct RsFileTree : RsSerializable -{ -public: - RsFileTree() : mTotalFiles(0), mTotalSize(0) {} - - /** - * @brief Create a RsFileTree from directory details - * @param dd directory or file details - * @param remote - * @param remove_top_dirs - * @return pointer to the created file-tree - */ - static std::unique_ptr fromDirDetails( - const DirDetails& dd, bool remote, bool remove_top_dirs = true ); - - /** - * @brief Create a RsFileTree from Base64 representation - * @param base64 base64 or base64url string representation of the file-tree - * @return pointer to the parsed file-tree on success, nullptr plus error - * details on failure - */ - static std::tuple, std::error_condition> - fromBase64(const std::string& base64); - - /** @brief Convert to base64 representetion */ - std::string toBase64() const; - - /// @see RsSerializable - virtual void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(mFiles); - RS_SERIAL_PROCESS(mDirs); - RS_SERIAL_PROCESS(mTotalFiles); - RS_SERIAL_PROCESS(mTotalSize); - } - - struct FileData: RsSerializable - { - std::string name; - uint64_t size; - RsFileHash hash; - - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override; - }; - - /// Allow browsing the hierarchy - bool getDirectoryContent( - std::string& name, std::vector& subdirs, - std::vector& subfiles, uint64_t handle = 0 ) const; - - struct DirData: RsSerializable - { - std::string name; - std::vector subdirs; - std::vector subfiles; - - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override; - }; - - static void recurs_buildFileTree( - RsFileTree& ft, uint32_t index, const DirDetails& dd, bool remote, - bool remove_top_dirs ); - - std::vector mFiles; - std::vector mDirs; - - uint32_t mTotalFiles; - uint64_t mTotalSize; - - virtual ~RsFileTree(); - - /** - * @brief Create a RsFileTree from Radix64 representation - * @deprecated kept for retrocompatibility with RetroShare-gui - * The format is not compatible with the new methods - * @param radix64_string - * @return nullptr if on failure, pointer to the created FileTree on success - */ - RS_DEPRECATED_FOR(fromBase64) - static std::unique_ptr fromRadix64( - const std::string& radix64_string ); - - /** @brief Convert to radix64 representetion - * @deprecated kept for retrocompatibility with RetroShare-gui - * The format is not compatible with the new methods - */ - RS_DEPRECATED_FOR(toBase64) - std::string toRadix64() const; - -private: - /** @deprecated kept for retrocompatibility with RetroShare-gui */ - RS_DEPRECATED_FOR(serial_process) - bool serialise(unsigned char *& data,uint32_t& data_size) const; - - /** @deprecated kept for retrocompatibility with RetroShare-gui */ - RS_DEPRECATED_FOR(serial_process) - bool deserialise(unsigned char* data, uint32_t data_size); -}; - -struct BannedFileEntry : RsSerializable -{ - BannedFileEntry() : mFilename(""), mSize(0), mBanTimeStamp(0) {} - - std::string mFilename; - uint64_t mSize; - rstime_t mBanTimeStamp; - - /// @see RsSerializable::serial_process - virtual void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) - { - RS_SERIAL_PROCESS(mFilename); - RS_SERIAL_PROCESS(mSize); - RS_SERIAL_PROCESS(mBanTimeStamp); - } -}; - -struct DeepFilesSearchResult; - -struct TurtleFileInfoV2 : RsSerializable -{ - TurtleFileInfoV2() : fSize(0), fWeight(0) {} - - explicit TurtleFileInfoV2(const TurtleFileInfo& oldInfo) : - fSize(oldInfo.size), fHash(oldInfo.hash), fName(oldInfo.name), - fWeight(0) {} - -#ifdef RS_DEEP_FILES_INDEX - explicit TurtleFileInfoV2(const DeepFilesSearchResult& dRes); -#endif // def RS_DEEP_FILES_INDEX - - uint64_t fSize; /// File size - RsFileHash fHash; /// File hash - std::string fName; /// File name - - /** @brief Xapian weight of the file which matched the search criteria - * This field is optional (its value is 0 when not specified). - * Given that Xapian weight for the same file is usually different on - * different nodes, it should not be used as an absolute refence, but just - * as an hint of how much the given file match the search criteria. - */ - float fWeight; - - /** @brief Xapian snippet of the file which matched the search criteria - * This field is optional (its value is an empty string when not specified). - */ - std::string fSnippet; - - - /// @see RsSerializable::serial_process - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(fSize); - RS_SERIAL_PROCESS(fHash); - RS_SERIAL_PROCESS(fName); - RS_SERIAL_PROCESS(fWeight); - RS_SERIAL_PROCESS(fSnippet); - } - - ~TurtleFileInfoV2() override; -}; - -class RsFiles -{ -public: - /** - * @brief Provides file data for the GUI, media streaming or API clients. - * It may return unverified chunks. This allows streaming without having to - * wait for hashes or completion of the file. - * This function returns an unspecified amount of bytes. Either as much data - * as available or a sensible maximum. Expect a block size of around 1MiB. - * To get more data, call this function repeatedly with different offsets. - * - * @jsonapi{development,manualwrapper} - * note the wrapper for this is written manually not autogenerated - * @see JsonApiServer. - * - * @param[in] hash hash of the file. The file has to be available on this node - * or it has to be in downloading state. - * @param[in] offset where the desired block starts - * @param[inout] requested_size size of pre-allocated data. Will be updated - * by the function. - * @param[out] data pre-allocated memory chunk of size 'requested_size' by the - * client - * @return Returns false in case - * - the files is not available on the local node - * - not downloading - * - the requested data was not downloaded yet - * - end of file was reached - */ - virtual bool getFileData( const RsFileHash& hash, uint64_t offset, - uint32_t& requested_size, uint8_t* data ) = 0; - - /** - * @brief Check if we already have a file - * @jsonapi{development} - * @param[in] hash file identifier - * @param[out] info storage for the possibly found file information - * @return true if the file is already present, false otherwise - */ - virtual bool alreadyHaveFile(const RsFileHash& hash, FileInfo &info) = 0; - - /** - * @brief Initiate downloading of a file - * @jsonapi{development} - * @param[in] fileName file name - * @param[in] hash file hash - * @param[in] size file size - * @param[in] destPath optional specify the destination directory - * @param[in] flags you usually want RS_FILE_REQ_ANONYMOUS_ROUTING - * @param[in] srcIds eventually specify known sources - * @return false if we already have the file, true otherwhise - */ - virtual bool FileRequest( - const std::string& fileName, const RsFileHash& hash, uint64_t size, - const std::string& destPath, TransferRequestFlags flags, - const std::list& srcIds ) = 0; - - /** - * @brief Initiate download of a files collection - * @jsonapi{development} - * An usually useful companion method of this is @see parseFilesLink() - * @param[in] collection collection of files to download - * @param[in] destPath optional base path on which to download the - * collection, if left empty the default download directory will be used - * @param[in] srcIds optional peers id known as direct source of the - * collection - * @param[in] flags optional flags to fine tune search and download - * algorithm - * @return success or error details. - */ - virtual std::error_condition requestFiles( - const RsFileTree& collection, - const std::string& destPath = "", - const std::vector& srcIds = std::vector(), - FileRequestFlags flags = FileRequestFlags::ANONYMOUS_ROUTING ) = 0; - - /** - * @brief Cancel file downloading - * @jsonapi{development} - * @param[in] hash - * @return false if the file is not in the download queue, true otherwhise - */ - virtual bool FileCancel(const RsFileHash& hash) = 0; - - /** - * @brief Set destination directory for given file - * @jsonapi{development} - * @param[in] hash file identifier - * @param[in] newPath - * @return false if some error occurred, true otherwise - */ - virtual bool setDestinationDirectory( - const RsFileHash& hash, const std::string& newPath ) = 0; - - /** - * @brief Set name for dowloaded file - * @jsonapi{development} - * @param[in] hash file identifier - * @param[in] newName - * @return false if some error occurred, true otherwise - */ - virtual bool setDestinationName( - const RsFileHash& hash, const std::string& newName ) = 0; - - /** - * @brief Set chunk strategy for file, useful to set streaming mode to be - * able of see video or other media preview while it is still downloading - * @jsonapi{development} - * @param[in] hash file identifier - * @param[in] newStrategy - * @return false if some error occurred, true otherwise - */ - virtual bool setChunkStrategy( - const RsFileHash& hash, - FileChunksInfo::ChunkStrategy newStrategy ) = 0; - - /** - * @brief Set default chunk strategy - * @jsonapi{development} - * @param[in] strategy - */ - virtual void setDefaultChunkStrategy( - FileChunksInfo::ChunkStrategy strategy ) = 0; - - /** - * @brief Get default chunk strategy - * @jsonapi{development} - * @return current default chunck strategy - */ - virtual FileChunksInfo::ChunkStrategy defaultChunkStrategy() = 0; - - /** - * @brief Get free disk space limit - * @jsonapi{development} - * @return current minimum free space on disk in MB - */ - virtual uint32_t freeDiskSpaceLimit() const = 0; - - /** - * @brief Set minimum free disk space limit - * @jsonapi{development} - * @param[in] minimumFreeMB minimum free space in MB - */ - virtual void setFreeDiskSpaceLimit(uint32_t minimumFreeMB) = 0; - - /** - * @brief Controls file transfer - * @jsonapi{development} - * @param[in] hash file identifier - * @param[in] flags action to perform. Pict into { RS_FILE_CTRL_PAUSE, RS_FILE_CTRL_START, RS_FILE_CTRL_FORCE_CHECK } } - * @return false if error occured such as unknown hash. - */ - virtual bool FileControl(const RsFileHash& hash, uint32_t flags) = 0; - - /** - * @brief Clear completed downloaded files list - * @jsonapi{development} - * @return false on error, true otherwise - */ - virtual bool FileClearCompleted() = 0; - - virtual void setDefaultEncryptionPolicy(uint32_t policy)=0; // RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT/PERMISSIVE - virtual uint32_t defaultEncryptionPolicy()=0; - virtual void setMaxUploadSlotsPerFriend(uint32_t n)=0; - virtual uint32_t getMaxUploadSlotsPerFriend()=0; - virtual void setFilePermDirectDL(uint32_t perm)=0; - virtual uint32_t filePermDirectDL()=0; - - /** - * @brief Request remote files search - * @jsonapi{development} - * @param[in] matchString string to look for in the search. If files deep - * indexing is enabled at compile time support advanced features described - * at https://xapian.org/docs/queryparser.html - * @param multiCallback function that will be called each time a search - * result is received - * @param[in] maxWait maximum wait time in seconds for search results - * @return false on error, true otherwise - */ - virtual bool turtleSearchRequest( - const std::string& matchString, - const std::function& results)>& multiCallback, - rstime_t maxWait = 300 ) = 0; - - virtual TurtleRequestId turtleSearch(const std::string& string_to_match) = 0; - virtual TurtleRequestId turtleSearch( - const RsRegularExpression::LinearizedExpression& expr) = 0; - - /*** - * Control of Downloads Priority. - ***/ - virtual uint32_t getQueueSize() = 0 ; - virtual void setQueueSize(uint32_t s) = 0 ; - virtual bool changeQueuePosition(const RsFileHash& hash, QueueMove mv) = 0; - virtual bool changeDownloadSpeed(const RsFileHash& hash, int speed) = 0; - virtual bool getDownloadSpeed(const RsFileHash& hash, int & speed) = 0; - virtual bool clearDownload(const RsFileHash& hash) = 0; - - /** - * @brief Get incoming files list - * @jsonapi{development} - * @param[out] hashs storage for files identifiers list - */ - virtual void FileDownloads(std::list& hashs) = 0; - - /** - * @brief Get outgoing files list - * @jsonapi{development} - * @param[out] hashs storage for files identifiers list - * @return false if some error occurred, true otherwise - */ - virtual bool FileUploads(std::list& hashs) = 0; - - /** - * @brief Get file details - * @jsonapi{development} - * @param[in] hash file identifier - * @param[in] hintflags filtering hint ( RS_FILE_HINTS_UPLOAD|...| - * RS_FILE_HINTS_EXTRA|RS_FILE_HINTS_LOCAL ) - * @param[out] info storage for file information - * @return true if file found, false otherwise - */ - virtual bool FileDetails( - const RsFileHash& hash, FileSearchFlags hintflags, FileInfo& info ) = 0; - - virtual bool isEncryptedSource(const RsPeerId& virtual_peer_id) =0; - - /** - * @brief Get chunk details about the downloaded file with given hash. - * @jsonapi{development} - * @param[in] hash file identifier - * @param[out] info storage for file information - * @return true if file found, false otherwise - */ - virtual bool FileDownloadChunksDetails( - const RsFileHash& hash, FileChunksInfo& info) = 0; - - /** - * @brief Get details about the upload with given hash - * @jsonapi{development} - * @param[in] hash file identifier - * @param[in] peerId peer identifier - * @param[out] map storage for chunk info - * @return true if file found, false otherwise - */ - virtual bool FileUploadChunksDetails( - const RsFileHash& hash, const RsPeerId& peerId, - CompressedChunkMap& map ) = 0; - - /** - * @brief Remove file from extra fila shared list - * @jsonapi{development} - * @param[in] hash hash of the file to remove - * @return return false on error, true otherwise - */ - virtual bool ExtraFileRemove(const RsFileHash& hash) = 0; - - /** - * @brief Add file to extra shared file list - * @jsonapi{development} - * @param[in] localpath path of the file - * @param[in] period how much time the file will be kept in extra list in - * seconds - * @param[in] flags sharing policy flags ex: RS_FILE_REQ_ANONYMOUS_ROUTING - * @return false on error, true otherwise - */ - virtual bool ExtraFileHash( - std::string localpath, rstime_t period, TransferRequestFlags flags - ) = 0; - - /** - * @brief Get extra file information - * @jsonapi{development} - * @param[in] localpath path of the file - * @param[out] info storage for the file information - * @return false on error, true otherwise - */ - virtual bool ExtraFileStatus(std::string localpath, FileInfo &info) = 0; - - virtual bool ExtraFileMove( - std::string fname, const RsFileHash& hash, uint64_t size, - std::string destpath ) = 0; - - /** - * @brief Request directory details, subsequent multiple call may be used to - * explore a whole directory tree. - * @jsonapi{development} - * @param[out] details Storage for directory details - * @param[in] handle element handle 0 for root, pass the content of - * DirDetails::child[x].ref after first call to explore deeper, be aware - * that is not a real pointer but an index used internally by RetroShare. - * @param[in] flags file search flags RS_FILE_HINTS_* - * @return false if error occurred, true otherwise - */ - virtual bool requestDirDetails( - DirDetails &details, uint64_t handle = 0, - FileSearchFlags flags = RS_FILE_HINTS_LOCAL ) = 0; - - /*** - * Directory Listing / Search Interface - */ - /** - * Kept for retrocompatibility, it was originally written for easier - * interaction with Qt. As soon as you can, you should prefer to use the - * version of this method which take `uint64_t handle` as paramether. - */ - RS_DEPRECATED_FOR(requestDirDetails) - virtual int RequestDirDetails( - void* handle, DirDetails& details, FileSearchFlags flags ) = 0; - - virtual bool findChildPointer(void *ref, int row, void *& result, FileSearchFlags flags) =0; - virtual uint32_t getType(void *ref,FileSearchFlags flags) = 0; - - virtual int SearchKeywords(std::list keywords, std::list &results,FileSearchFlags flags) = 0; - virtual int SearchKeywords(std::list keywords, std::list &results,FileSearchFlags flags,const RsPeerId& peer_id) = 0; - virtual int SearchBoolExp(RsRegularExpression::Expression * exp, std::list &results,FileSearchFlags flags) = 0; - virtual int SearchBoolExp(RsRegularExpression::Expression * exp, std::list &results,FileSearchFlags flags,const RsPeerId& peer_id) = 0; - virtual int getSharedDirStatistics(const RsPeerId& pid, SharedDirStats& stats) =0; - - /** - * @brief Ban unwanted file from being, searched and forwarded by this node - * @jsonapi{development} - * @param[in] realFileHash this is what will really enforce banning - * @param[in] filename expected name of the file, for the user to read - * @param[in] fileSize expected file size, for the user to read - * @return meaningless value - */ - virtual int banFile( const RsFileHash& realFileHash, - const std::string& filename, uint64_t fileSize ) = 0; - - /** - * @brief Remove file from unwanted list - * @jsonapi{development} - * @param[in] realFileHash hash of the file - * @return meaningless value - */ - virtual int unbanFile(const RsFileHash& realFileHash) = 0; - - /** - * @brief Get list of banned files - * @jsonapi{development} - * @param[out] bannedFiles storage for banned files information - * @return meaningless value - */ - virtual bool getPrimaryBannedFilesList( - std::map& bannedFiles ) = 0; - - /** - * @brief Check if a file is on banned list - * @jsonapi{development} - * @param[in] hash hash of the file - * @return true if the hash is on the list, false otherwise - */ - virtual bool isHashBanned(const RsFileHash& hash) = 0; - - /*** - * Utility Functions. - ***/ - virtual bool ConvertSharedFilePath(std::string path, std::string &fullpath) = 0; - - /** - * @brief Force shared directories check - * @param[in] add_safe_delay Schedule the check 20 seconds from now, to ensure to capture files written just now. - * @jsonapi{development} - */ - virtual void ForceDirectoryCheck(bool add_safe_delay=false) = 0; - - virtual void updateSinceGroupPermissionsChanged() = 0; - virtual bool InDirectoryCheck() = 0; - virtual bool copyFile(const std::string& source,const std::string& dest) = 0; - - /*** - * Directory Control - ***/ - virtual void requestDirUpdate(void *ref) =0 ; // triggers the update of the given reference. Used when browsing. - - /** - * @brief Set default complete downloads directory - * @jsonapi{development} - * @param[in] path directory path - * @return false if something failed, true otherwhise - */ - virtual bool setDownloadDirectory(const std::string& path) = 0; - - /** - * @brief Set partial downloads directory - * @jsonapi{development} - * @param[in] path directory path - * @return false if something failed, true otherwhise - */ - virtual bool setPartialsDirectory(const std::string& path) = 0; - - /** - * @brief Get default complete downloads directory - * @jsonapi{development} - * @return default completed downloads directory path - */ - virtual std::string getDownloadDirectory() = 0; - - /** - * @brief Get partial downloads directory - * @jsonapi{development} - * @return partials downloads directory path - */ - virtual std::string getPartialsDirectory() = 0; - - /** - * @brief Get list of current shared directories - * @jsonapi{development} - * @param[out] dirs storage for the list of share directories - * @return false if something failed, true otherwhise - */ - virtual bool getSharedDirectories(std::list& dirs) = 0; - - /** - * @brief Set shared directories - * @jsonapi{development} - * @param[in] dirs list of shared directories with share options - * @return false if something failed, true otherwhise - */ - virtual bool setSharedDirectories(const std::list& dirs) = 0; - - /** - * @brief Add shared directory - * @jsonapi{development} - * @param[in] dir directory to share with sharing options - * @return false if something failed, true otherwhise - */ - virtual bool addSharedDirectory(const SharedDirInfo& dir) = 0; - - /** - * @brief Updates shared directory sharing flags. - * The directory should be already shared! - * @jsonapi{development} - * @param[in] dir Shared directory with updated sharing options - * @return false if something failed, true otherwhise - */ - virtual bool updateShareFlags(const SharedDirInfo& dir) = 0; - - /** - * @brief Remove directory from shared list - * @jsonapi{development} - * @param[in] dir Path of the directory to remove from shared list - * @return false if something failed, true otherwhise - */ - virtual bool removeSharedDirectory(std::string dir) = 0; - - /// Default base URL used for files links @see exportFilesLink - static const std::string DEFAULT_FILES_BASE_URL; - - /** Link query field used to store collection files count - * @see exportFilesLink */ - static const std::string FILES_URL_COUNT_FIELD; - - /// Link query field used to store collection data @see exportFilesLink - static const std::string FILES_URL_DATA_FIELD; - - /** Link query FILES_URL_DATA_FIELD field value used to instruct the parser - * to look for the data into the link fragment - * @see exportFilesLink and parseFilesLink */ - static const std::string FILES_URL_FAGMENT_FORWARD; - - /// Link query field used to store collection name @see exportFilesLink - static const std::string FILES_URL_NAME_FIELD; - - /// Link query field used to store collection size @see exportFilesLink - static const std::string FILES_URL_SIZE_FIELD; - - /** - * @brief Export link to a collection of files - * @jsonapi{development} - * @param[out] link storage for the generated link - * @param[in] handle directory RetroShare handle - * @param[in] fragSneak when true the file data is sneaked into fragment - * instead of FILES_URL_DATA_FIELD query field, this way if using an - * http[s] link to pass around a disguised file link a misconfigured host - * attempting to visit that link with a web browser will not send the file - * data to the server thus protecting at least some of the privacy of the - * user even in a misconfiguration scenario. - * @param[in] baseUrl URL into which to sneak in the RetroShare file link - * base64, this is primarly useful to induce applications into making the - * link clickable, or to disguise the RetroShare link into a "normal" - * looking web link. If empty the collection data link will be outputted in - * plain base64 format. - * @return error information if some error occurred, 0/SUCCESS otherwise - */ - virtual std::error_condition exportCollectionLink( - std::string& link, uint64_t handle, bool fragSneak = false, - const std::string& baseUrl = RsFiles::DEFAULT_FILES_BASE_URL ) = 0; - - /** - * @brief Export link to a file - * @jsonapi{development} - * @param[out] link @see exportCollectionLink - * @param[in] fileHash hash of the file - * @param[in] fileSize size of the file - * @param[in] fileName name of the file - * @param[in] fragSneak @see exportCollectionLink - * @param[in] baseUrl @see exportCollectionLink - * @return error @see exportCollectionLink - */ - virtual std::error_condition exportFileLink( - std::string& link, const RsFileHash& fileHash, uint64_t fileSize, - const std::string& fileName, bool fragSneak = false, - const std::string& baseUrl = RsFiles::DEFAULT_FILES_BASE_URL ) = 0; - - /** - * @brief Parse RetroShare files link - * @jsonapi{development} - * Support also old RetroShare-gui file and collections links format. - * @param[in] link files link either in base64 or URL format - * @param[out] collection storage for parsed files link - * @return error information if some error occurred, 0/SUCCESS otherwise - */ - virtual std::error_condition parseFilesLink( - const std::string& link, RsFileTree& collection ) = 0; - - /** - * @brief Get list of ignored file name prefixes and suffixes - * @param[out] ignoredPrefixes storage for ingored prefixes - * @param[out] ignoredSuffixes storage for ingored suffixes - * @param flags RS_FILE_SHARE_FLAGS_IGNORE_* - * @return false if something failed, true otherwhise - */ - virtual bool getIgnoreLists( - std::list& ignoredPrefixes, - std::list& ignoredSuffixes, - uint32_t& flags ) = 0; - - virtual void setIgnoreLists(const std::list& ignored_prefixes, const std::list& ignored_suffixes,uint32_t flags) =0; - - virtual void setWatchPeriod(int minutes) =0; - virtual void setWatchEnabled(bool b) =0; - virtual int watchPeriod() const =0; - virtual bool watchEnabled() =0; - virtual bool followSymLinks() const=0; - virtual void setFollowSymLinks(bool b)=0 ; - virtual void togglePauseHashingProcess() =0; // pauses/resumes the hashing process. - virtual bool hashingProcessPaused() =0; - - virtual bool getShareDownloadDirectory() = 0; - virtual bool shareDownloadDirectory(bool share) = 0; - - virtual void setMaxShareDepth(int depth) =0; - virtual int maxShareDepth() const=0; - - virtual bool ignoreDuplicates() = 0; - virtual void setIgnoreDuplicates(bool ignore) = 0; - - virtual ~RsFiles() = default; -}; diff --git a/libretroshare/src/retroshare/rsflags.h b/libretroshare/src/retroshare/rsflags.h deleted file mode 100644 index 8775f1dfb..000000000 --- a/libretroshare/src/retroshare/rsflags.h +++ /dev/null @@ -1,250 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsflags.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012-2019 by Retroshare Team * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include - -/** Check if given type is a scoped enum */ -template -using rs_is_scoped_enum = std::integral_constant< bool, - std::is_enum::value && !std::is_convertible::value >; - -/** - * @brief Register enum class as flags type - * To use this macro define a scoped enum with your flag values, then register - * it as flags type passing it as parameter of this macro. - * The result will be type safe flags, that cannot be mixed up with flag of a - * different type, but that are very comfortable to operate like plain old - * integers. All commom operation like &, | or ! can be used. To convert - * the result of such operation to boolean use !!: -@code{.cpp} -RsConnectModes connect = rsConfig->getConnectModes(); -if (!!(connect & RsConnectModes::OUTGOING_TCP)) -@endcode - * - * This macro support flag fields of different lenght depending on what - * underlining type (usually from uint8_t up to uint64_t) has been declared for - * the enum class. - * If you plan to serialize those flags it is important to specify the - * underlining type of the enum otherwise different compilers may serialize a - * flag variable with different lenght, potentially causing interoperability - * issues between differents builds. - * - * Usage example: -@code{.cpp} -enum class RsGrouterItemFlags : uint32_t -{ - NONE = 0x0, - ENCRYPTED = 0x1, - SERVICE_UNKNOWN = 0x2 -}; -RS_REGISTER_ENUM_FLAGS_TYPE(RsGrouterItemFlags) -@endcode - */ -#define RS_REGISTER_ENUM_FLAGS_TYPE(eft) \ -template<> struct Rs__BitFlagsOps \ -{ \ - static_assert( std::is_enum::value, \ - "Are you trying to register a non-enum type as flags?" ); \ - static_assert( rs_is_scoped_enum::value, \ - "Are you trying to register an unscoped enum as flags?" ); \ - static constexpr bool enabled = true; \ -}; - -// By defaults types are not valid flags, so bit flags operators are disabled -template struct Rs__BitFlagsOps -{ static constexpr bool enabled = false; }; - -template -typename std::enable_if::enabled, EFT>::type -/*EFT*/ operator &(EFT lhs, EFT rhs) -{ - using u_t = typename std::underlying_type::type; - return static_cast(static_cast(lhs) & static_cast(rhs)); -} - -template -typename std::enable_if::enabled, EFT>::type -/*EFT*/ operator &=(EFT& lhs, EFT rhs) { lhs = lhs & rhs; return lhs; } - -template -typename std::enable_if::enabled, EFT>::type -/*EFT*/ operator |(EFT lhs, EFT rhs) -{ - using u_t = typename std::underlying_type::type; - return static_cast(static_cast(lhs) | static_cast(rhs)); -} - -template -typename std::enable_if::enabled, EFT>::type -/*EFT*/ operator |=(EFT& lhs, EFT rhs) { lhs = lhs | rhs; return lhs; } - - -template -typename std::enable_if::enabled, EFT>::type -/*EFT*/ operator ^(EFT lhs, EFT rhs) -{ - using u_t = typename std::underlying_type::type; - return static_cast(static_cast(lhs) ^ static_cast(rhs)); -} - -template -typename std::enable_if::enabled, EFT>::type -/*EFT*/ operator ^=(EFT& lhs, EFT rhs) { lhs = lhs ^ rhs; return lhs; } - -template -typename std::enable_if::enabled, EFT>::type -operator ~(EFT val) -{ - using u_t = typename std::underlying_type::type; - return static_cast(~static_cast(val)); -} - -template -typename std::enable_if::enabled, bool>::type -operator !(EFT val) -{ - using u_t = typename std::underlying_type::type; - return static_cast(val) == 0; -} - -/// Nicely print flags bits as 1 and 0 -template -typename std::enable_if::enabled, std::ostream>::type& -operator <<(std::ostream& stream, EFT flags) -{ - using u_t = typename std::underlying_type::type; - return stream << std::bitset(static_cast(flags)); -} - -#include -#include "util/rsdeprecate.h" - - -/** - * @deprecated t_RsFlags32 has been deprecated because the newer - * @see RS_REGISTER_ENUM_FLAGS_TYPE provide more convenient flags facilities. - * -// This class provides a representation for flags that can be combined with bitwise -// operations. However, because the class is templated with an id, it's not possible to -// mixup flags belonging to different classes. This avoids many bugs due to confusion of flags types -// that occur when all flags are uint32_t values. -// -// To use this class, define an ID that is different than other flags classes, and do a typedef: -// -// #define TRANSFER_INFO_FLAGS_TAG 0x8133ea -// typedef t_RsFlags32 TransferInfoFlags ; -// -// Implementation details: -// - we cannot have at the same time a implicit contructor from uint32_t and a bool operator, otherwise c++ -// mixes up operators and transforms flags into booleans before combining them further. -// -// So I decided to have: -// - an explicit constructor from uint32_t -// - an implicit bool operator, that allows test like if(flags & FLAGS_VALUE) -// -*/ -template class RS_DEPRECATED_FOR(RS_REGISTER_ENUM_FLAGS_TYPE) t_RsFlags32 -{ - public: - inline t_RsFlags32() : _bits(0) {} - inline explicit t_RsFlags32(uint32_t N) : _bits(N) {} // allows initialization from a set of uint32_t - - - inline t_RsFlags32 operator| (const t_RsFlags32& f) const { return t_RsFlags32(_bits | f._bits) ; } - inline t_RsFlags32 operator^ (const t_RsFlags32& f) const { return t_RsFlags32(_bits ^ f._bits) ; } - inline t_RsFlags32 operator* (const t_RsFlags32& f) const { return t_RsFlags32(_bits & f._bits) ; } - - inline bool operator!=(const t_RsFlags32& f) const { return _bits != f._bits ; } - inline bool operator==(const t_RsFlags32& f) const { return _bits == f._bits ; } - inline bool operator& (const t_RsFlags32& f) const { return (_bits & f._bits)>0 ; } - - inline t_RsFlags32 operator|=(const t_RsFlags32& f) { _bits |= f._bits ; return *this ;} - inline t_RsFlags32 operator^=(const t_RsFlags32& f) { _bits ^= f._bits ; return *this ;} - inline t_RsFlags32 operator&=(const t_RsFlags32& f) { _bits &= f._bits ; return *this ;} - - inline t_RsFlags32 operator~() const { return t_RsFlags32(~_bits) ; } - - //inline explicit operator bool() const { return _bits>0; } - inline uint32_t toUInt32() const { return _bits ; } - - /// Easier porting to new flag system - template inline - typename std::enable_if<(Rs__BitFlagsOps::enabled && - sizeof(EFT) >= sizeof(uint32_t) ), EFT>::type - toEFT() { return static_cast(_bits); } - - /// Easier porting to new flag system - template - static inline typename std::enable_if< - Rs__BitFlagsOps::enabled && - sizeof(EFT) <= sizeof(uint32_t), t_RsFlags32>::type - fromEFT(EFT e) { return t_RsFlags32(static_cast(e)); } - - void clear() { _bits = 0 ; } - - friend std::ostream& operator<<(std::ostream& o,const t_RsFlags32& f) // friendly print with 0 and I - { - for(int i=31;i>=0;--i) { - std::string res = f._bits&(1< TransferRequestFlags; - -// Flags for file storage. Mainly permissions like BROWSABLE/NETWORK_WIDE for groups and peers. -// -typedef t_RsFlags32 FileStorageFlags ; - -// Flags for searching in files that could be local, downloads, remote, etc. -// -typedef t_RsFlags32 FileSearchFlags ; - -// Service permissions. Will allow each user to use or not use each service. -// -typedef t_RsFlags32 ServicePermissionFlags ; - -// Flags for chat lobbies -// -typedef t_RsFlags32 ChatLobbyFlags ; - diff --git a/libretroshare/src/retroshare/rsfriendserver.h b/libretroshare/src/retroshare/rsfriendserver.h deleted file mode 100644 index 80bf2a029..000000000 --- a/libretroshare/src/retroshare/rsfriendserver.h +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include "util/rstime.h" - -// The Friend Server component of Retroshare automatically adds/removes some friends so that the -// -// The current strategy is: -// -// - if total nb of friends < S -// request new friends to the FS -// - if total nb of friends >= S -// do not request anymore (and unpublish the key), but keep the friends already here -// -// Possible states: -// - not started -// - maintain friend list -// - actively request friends -// -// The friend server internally keeps track of which friends have been added using the friend server. -// It's important to keep the ones that are already connected because they may count on us. -// Friends supplied by the FS who never connected for a few days should be removed automatically. - -class RsFriendServer -{ -public: - virtual void startServer() =0; - virtual void stopServer() =0; - - virtual void checkServerAddress_async(const std::string& addr,uint16_t, const std::function& callback) =0; - virtual void setServerAddress(const std::string&,uint16_t) =0; - virtual void setProxyAddress(const std::string&,uint16_t) =0; - virtual void setFriendsToRequest(uint32_t) =0; - - virtual uint32_t friendsToRequest() =0; - virtual uint16_t friendsServerPort() =0; - virtual std::string friendsServerAddress() =0; -}; - -extern RsFriendServer *rsFriendServer; diff --git a/libretroshare/src/retroshare/rsgossipdiscovery.h b/libretroshare/src/retroshare/rsgossipdiscovery.h deleted file mode 100644 index 9a6e2a792..000000000 --- a/libretroshare/src/retroshare/rsgossipdiscovery.h +++ /dev/null @@ -1,116 +0,0 @@ -/******************************************************************************* - * RetroShare remote peers gossip discovery * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2008 Robert Fernie * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -#include "retroshare/rstypes.h" -#include "retroshare/rsevents.h" -#include "util/rsmemory.h" - -class RsGossipDiscovery; - -/** - * Pointer to global instance of RsGossipDiscovery service implementation - * @jsonapi{development} - * - * TODO: this should become std::weak_ptr once we have a reasonable services - * management. - */ -extern std::shared_ptr rsGossipDiscovery; - -/** - * @brief Emitted when a pending PGP certificate is received - */ - -enum class RsGossipDiscoveryEventType: uint32_t { - UNKNOWN = 0x00, - FRIEND_PEER_INFO_RECEIVED = 0x01, -}; - -struct RsGossipDiscoveryEvent : RsEvent -{ - RsGossipDiscoveryEvent(): RsEvent(RsEventType::GOSSIP_DISCOVERY) {} - virtual ~RsGossipDiscoveryEvent() override {} - - RsGossipDiscoveryEventType mGossipDiscoveryEventType; - RsPeerId mFromId; - RsPeerId mAboutId; - - /// @see RsSerializable - virtual void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RsEvent::serial_process(j,ctx); - RS_SERIAL_PROCESS(mGossipDiscoveryEventType); - RS_SERIAL_PROCESS(mFromId); - RS_SERIAL_PROCESS(mAboutId); - } -}; - -class RsGossipDiscovery -{ -public: - virtual ~RsGossipDiscovery() = default; - - /** - * @brief getDiscFriends get a list of all friends of a given friend - * @jsonapi{development} - * @param[in] id peer to get the friends of - * @param[out] friends list of friends (ssl id) - * @return true on success false otherwise - */ - virtual bool getDiscFriends( const RsPeerId& id, - std::list& friends ) = 0; - - /** - * @brief getDiscPgpFriends get a list of all friends of a given friend - * @jsonapi{development} - * @param[in] pgpid peer to get the friends of - * @param[out] gpg_friends list of friends (gpg id) - * @return true on success false otherwise - */ - virtual bool getDiscPgpFriends( - const RsPgpId& pgpid, std::list& gpg_friends ) = 0; - - /** - * @brief getPeerVersion get the version string of a peer. - * @jsonapi{development} - * @param[in] id peer to get the version string of - * @param[out] version version string sent by the peer - * @return true on success false otherwise - */ - virtual bool getPeerVersion(const RsPeerId& id, std::string& version) = 0; - - /** - * @brief getWaitingDiscCount get the number of queued discovery packets. - * @jsonapi{development} - * @param[out] sendCount number of queued outgoing packets - * @param[out] recvCount number of queued incoming packets - * @return true on success false otherwise - */ - virtual bool getWaitingDiscCount(size_t& sendCount, size_t& recvCount) = 0; -}; diff --git a/libretroshare/src/retroshare/rsgrouter.h b/libretroshare/src/retroshare/rsgrouter.h deleted file mode 100644 index 84349f75e..000000000 --- a/libretroshare/src/retroshare/rsgrouter.h +++ /dev/null @@ -1,108 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgrouter.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include "util/rsdir.h" -#include "util/rsdeprecate.h" -#include "retroshare/rsids.h" -#include "retroshare/rsgxsifacetypes.h" -#include "rsitems/rsserviceids.h" - -typedef RsGxsId GRouterKeyId ; // we use SSLIds, so that it's easier in the GUI to mix up peer ids with grouter ids. -typedef uint32_t GRouterServiceId ; -typedef uint64_t GRouterMsgPropagationId ; - -class GRouterClientService ; -class RsGRouterGenericDataItem ; - -class RsGRouter -{ -public: - // This is the interface file for the global router service. - // - struct GRouterRoutingCacheInfo - { - GRouterMsgPropagationId mid ; - std::set local_origin; - GRouterKeyId destination ; - rstime_t routing_time; - rstime_t last_tunnel_attempt_time; - rstime_t last_sent_time; - bool receipt_available ; - uint32_t duplication_factor ; - uint32_t data_status ; - uint32_t tunnel_status ; - uint32_t data_size ; - Sha1CheckSum item_hash ; - }; - - struct GRouterPublishedKeyInfo - { - std::string description_string ; - RsGxsId authentication_key ; - uint32_t service_id ; - }; - - struct GRouterRoutingMatrixInfo - { - // Probabilities of reaching a given key for each friend. - // This concerns all known keys. - // - std::map > per_friend_probabilities ; - - // List of friend ids in the same order. Should roughly correspond to the friends that are currently online. - // - std::vector friend_ids ; - - // List of own published keys, with associated service ID - // - std::map published_keys ; - }; - - //===================================================// - // Debugging info // - //===================================================// - - virtual bool getRoutingCacheInfo(std::vector& infos) =0; - virtual bool getRoutingMatrixInfo(GRouterRoutingMatrixInfo& info) =0; - - // retrieve the routing probabilities - - //===================================================// - // Communication to other services. // - //===================================================// - - virtual bool sendData(const RsGxsId& destination, const GRouterServiceId& client_id, const uint8_t *data, uint32_t data_size, const RsGxsId& signing_id, GRouterMsgPropagationId& id) =0; - virtual bool cancel(GRouterMsgPropagationId mid) =0; - - virtual bool registerKey(const RsGxsId& authentication_id, const GRouterServiceId& client_id,const std::string& description_string)=0 ; - - //===================================================// - // Routage feedback from other services // - //===================================================// - - virtual void addRoutingClue(const GRouterKeyId& destination, const RsPeerId& source) =0; -}; - -// To access the GRouter from anywhere -// -extern RsGRouter *rsGRouter ; diff --git a/libretroshare/src/retroshare/rsgxschannels.h b/libretroshare/src/retroshare/rsgxschannels.h deleted file mode 100644 index 421417bdc..000000000 --- a/libretroshare/src/retroshare/rsgxschannels.h +++ /dev/null @@ -1,741 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgxschannels.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Robert Fernie * - * Copyright (C) 2018-2020 Gioacchino Mazzurco * - * Copyright (C) 2019-2020 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -#include "retroshare/rstokenservice.h" -#include "retroshare/rsgxsifacehelper.h" -#include "retroshare/rsgxscommon.h" -#include "serialiser/rsserializable.h" -#include "retroshare/rsturtle.h" -#include "util/rsdeprecate.h" -#include "retroshare/rsgxscircles.h" -#include "util/rsmemory.h" - -class RsGxsChannels; - -/** - * Pointer to global instance of RsGxsChannels service implementation - * @jsonapi{development} - */ -extern RsGxsChannels* rsGxsChannels; - - -struct RsGxsChannelGroup : RsSerializable, RsGxsGenericGroupData -{ - RsGxsChannelGroup() : mAutoDownload(false) {} - - std::string mDescription; - RsGxsImage mImage; - - bool mAutoDownload; - - /// @see RsSerializable - virtual void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(mMeta); - RS_SERIAL_PROCESS(mDescription); - RS_SERIAL_PROCESS(mImage); - RS_SERIAL_PROCESS(mAutoDownload); - } - - ~RsGxsChannelGroup() override; -}; - -struct RsGxsChannelPost : RsSerializable, RsGxsGenericMsgData -{ - RsGxsChannelPost() : mAttachmentCount(0), mCommentCount(0), mUnreadCommentCount(0), mSize(0) {} - - std::set mOlderVersions; - std::string mMsg; // UTF8 encoded. - - std::list mFiles; - uint32_t mAttachmentCount; // auto calced. - uint32_t mCommentCount; // auto calced. - uint32_t mUnreadCommentCount; // auto calced. - uint64_t mSize; // auto calced. - - RsGxsImage mThumbnail; - - /// @see RsSerializable - virtual void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(mMeta); - RS_SERIAL_PROCESS(mOlderVersions); - - RS_SERIAL_PROCESS(mMsg); - RS_SERIAL_PROCESS(mFiles); - RS_SERIAL_PROCESS(mAttachmentCount); - RS_SERIAL_PROCESS(mCommentCount); - RS_SERIAL_PROCESS(mUnreadCommentCount); - RS_SERIAL_PROCESS(mSize); - RS_SERIAL_PROCESS(mThumbnail); - } - - ~RsGxsChannelPost() override; -}; - - -enum class RsChannelEventCode: uint8_t -{ - UNKNOWN = 0x00, - NEW_CHANNEL = 0x01, // emitted when new channel is received - UPDATED_CHANNEL = 0x02, // emitted when existing channel is updated - NEW_MESSAGE = 0x03, // new message reeived in a particular channel (group and msg id) - UPDATED_MESSAGE = 0x04, // existing message has been updated in a particular channel - RECEIVED_PUBLISH_KEY = 0x05, // publish key for this channel has been received - SUBSCRIBE_STATUS_CHANGED = 0x06, // subscription for channel mChannelGroupId changed. - READ_STATUS_CHANGED = 0x07, // existing message has been read or set to unread - RECEIVED_DISTANT_SEARCH_RESULT = 0x08, // result for the given group id available for the given turtle request id - STATISTICS_CHANGED = 0x09, // stats (nb of supplier friends, how many msgs they have etc) has changed - SYNC_PARAMETERS_UPDATED = 0x0a, // sync and storage times have changed - NEW_COMMENT = 0x0b, // new comment arrived/published. mChannelThreadId gives the ID of the commented message - NEW_VOTE = 0x0c, // new vote arrived/published. mChannelThreadId gives the ID of the votes message comment - DELETED_CHANNEL = 0x0d, // channel was deleted by auto-cleaning system -}; - -struct RsGxsChannelEvent: RsEvent -{ - RsGxsChannelEvent(): RsEvent(RsEventType::GXS_CHANNELS), mChannelEventCode(RsChannelEventCode::UNKNOWN) {} - - RsChannelEventCode mChannelEventCode; - RsGxsGroupId mChannelGroupId; - RsGxsMessageId mChannelMsgId; - RsGxsMessageId mChannelThreadId; - - ///* @see RsEvent @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override - { - RsEvent::serial_process(j, ctx); - - RS_SERIAL_PROCESS(mChannelEventCode); - RS_SERIAL_PROCESS(mChannelGroupId); - RS_SERIAL_PROCESS(mChannelMsgId); - } -}; - -// This event is used to factor multiple search results notifications in a single event. - -struct RsGxsChannelSearchResultEvent: RsEvent -{ - RsGxsChannelSearchResultEvent(): - RsEvent(RsEventType::GXS_CHANNELS), - mChannelEventCode(RsChannelEventCode::RECEIVED_DISTANT_SEARCH_RESULT) {} - - RsChannelEventCode mChannelEventCode; - std::map > mSearchResultsMap; - - ///* @see RsEvent @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override - { - RsEvent::serial_process(j, ctx); - - RS_SERIAL_PROCESS(mChannelEventCode); - RS_SERIAL_PROCESS(mSearchResultsMap); - } -}; - -class RsGxsChannels: public RsGxsIfaceHelper, public RsGxsCommentService -{ -public: - explicit RsGxsChannels(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {} - - /** - * @brief Create channel. Blocking API. - * @jsonapi{development} - * @param[in] name Name of the channel - * @param[in] description Description of the channel - * @param[in] thumbnail Optional image to show as channel thumbnail. - * @param[in] authorId Optional id of the author. Leave empty for an - * anonymous channel. - * @param[in] circleType Optional visibility rule, default public. - * @param[in] circleId If the channel is not public specify the id of - * the circle who can see the channel. Depending on - * the value you pass for - * circleType this should be be an external circle - * if EXTERNAL is passed, a local friend group id - * if NODES_GROUP is passed, empty otherwise. - * @param[out] channelId Optional storage for the id of the created - * channel, meaningful only if creations succeeds. - * @param[out] errorMessage Optional storage for error messsage, meaningful - * only if creation fail. - * @return False on error, true otherwise. - */ - virtual bool createChannelV2( - const std::string& name, - const std::string& description, - const RsGxsImage& thumbnail = RsGxsImage(), - const RsGxsId& authorId = RsGxsId(), - RsGxsCircleType circleType = RsGxsCircleType::PUBLIC, - const RsGxsCircleId& circleId = RsGxsCircleId(), - RsGxsGroupId& channelId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId), - std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string) - ) = 0; - - /** - * @brief Add a comment on a post or on another comment. Blocking API. - * @jsonapi{development} - * @param[in] channelId Id of the channel in which the comment is to be - * posted - * @param[in] threadId Id of the post (that is a thread) in the channel - * where the comment is placed - * @param[in] comment UTF-8 string containing the comment itself - * @param[in] authorId Id of the author of the comment - * @param[in] parentId Id of the parent of the comment that is either a - * channel post Id or the Id of another comment. - * @param[in] origCommentId If this is supposed to replace an already - * existent comment, the id of the old post. - * If left blank a new post will be created. - * @param[out] commentMessageId Optional storage for the id of the comment - * that was created, meaningful only on success. - * @param[out] errorMessage Optional storage for error message, meaningful - * only on failure. - * @return false on error, true otherwise - */ - virtual bool createCommentV2( - const RsGxsGroupId& channelId, - const RsGxsMessageId& threadId, - const std::string& comment, - const RsGxsId& authorId, - const RsGxsMessageId& parentId = RsGxsMessageId(), - const RsGxsMessageId& origCommentId = RsGxsMessageId(), - RsGxsMessageId& commentMessageId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId), - std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string) - ) = 0; - - /** - * @brief Create channel post. Blocking API. - * @jsonapi{development} - * @param[in] channelId Id of the channel where to put the post. Beware - * you need publish rights on that channel to post. - * @param[in] title Title of the post - * @param[in] mBody Text content of the post - * @param[in] files Optional list of attached files. These are - * supposed to be already shared, - * @see ExtraFileHash() below otherwise. - * @param[in] thumbnail Optional thumbnail image for the post. - * @param[in] origPostId If this is supposed to replace an already - * existent post, the id of the old post. If left - * blank a new post will be created. - * @param[out] postId Optional storage for the id of the created post, - * meaningful only on success. - * @param[out] errorMessage Optional storage for the error message, - * meaningful only on failure. - * @return false on error, true otherwise - */ - virtual bool createPostV2( - const RsGxsGroupId& channelId, const std::string& title, - const std::string& mBody, - const std::list& files = std::list(), - const RsGxsImage& thumbnail = RsGxsImage(), - const RsGxsMessageId& origPostId = RsGxsMessageId(), - RsGxsMessageId& postId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId), - std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - /** - * @brief Create a vote - * @jsonapi{development} - * @param[in] channelId Id of the channel where to vote - * @param[in] postId Id of the channel post of which a comment is - * voted. - * @param[in] commentId Id of the comment that is voted - * @param[in] authorId Id of the author. Needs to be of an owned - * identity. - * @param[in] vote Vote value, either RsGxsVoteType::DOWN or - * RsGxsVoteType::UP - * @param[out] voteId Optional storage for the id of the created vote, - * meaningful only on success. - * @param[out] errorMessage Optional storage for error message, meaningful - * only on failure. - * @return false on error, true otherwise - */ - virtual bool createVoteV2( - const RsGxsGroupId& channelId, const RsGxsMessageId& postId, - const RsGxsMessageId& commentId, const RsGxsId& authorId, - RsGxsVoteType vote, - RsGxsMessageId& voteId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId), - std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - /** - * @brief Edit channel details. - * @jsonapi{development} - * @param[in] channel Channel data (name, description...) with modifications - * @return false on error, true otherwise - */ - virtual bool editChannel(RsGxsChannelGroup& channel) = 0; - - /** - * @brief Share extra file - * Can be used to share extra file attached to a channel post - * @jsonapi{development} - * @param[in] path file path - * @return false on error, true otherwise - */ - virtual bool ExtraFileHash(const std::string& path) = 0; - - /** - * @brief Remove extra file from shared files - * @jsonapi{development} - * @param[in] hash hash of the file to remove - * @return false on error, true otherwise - */ - virtual bool ExtraFileRemove(const RsFileHash& hash) = 0; - - /** - * @brief Get channels summaries list. Blocking API. - * @jsonapi{development} - * @param[out] channels list where to store the channels - * @return false if something failed, true otherwhise - */ - virtual bool getChannelsSummaries(std::list& channels) = 0; - - /** - * @brief Get channels information (description, thumbnail...). - * Blocking API. - * @jsonapi{development} - * @param[in] chanIds ids of the channels of which to get the informations - * @param[out] channelsInfo storage for the channels informations - * @return false if something failed, true otherwhise - */ - virtual bool getChannelsInfo( - const std::list& chanIds, - std::vector& channelsInfo ) = 0; - - /** - * @brief Get all channel messages, comments and votes in a given channel - * @note It's the client's responsibility to figure out which message (resp. comment) - * a comment (resp. vote) refers to. - * - * @jsonapi{development} - * @param[in] channelId id of the channel of which the content is requested - * @param[out] posts storage for posts - * @param[out] comments storage for the comments - * @param[out] votes storage for votes - * @return false if something failed, true otherwhise - */ - virtual bool getChannelAllContent( const RsGxsGroupId& channelId, - std::vector& posts, - std::vector& comments, - std::vector& votes ) = 0; - - /** - * @brief Get channel messages, comments and votes corresponding to the given IDs. - * @note Since comments are internally themselves messages, this function actually - * returns the data for messages, comments or votes that have the given ID. - * It *does not* automatically retrieve the comments or votes for a given message - * which Id you supplied. - * - * @jsonapi{development} - * @param[in] channelId id of the channel of which the content is requested - * @param[in] contentsIds ids of requested contents - * @param[out] posts storage for posts - * @param[out] comments storage for the comments - * @param[out] votes storage for the votes - * @return false if something failed, true otherwhise - */ - virtual bool getChannelContent( const RsGxsGroupId& channelId, - const std::set& contentsIds, - std::vector& posts, - std::vector& comments, - std::vector& votes ) = 0; - - /** - * @brief Get channel comments corresponding to the given message IDs. - * If the set is empty, nothing is returned. - * - * @jsonapi{development} - * @param[in] channelId id of the channel of which the content is requested - * @param[in] contentIds ids of requested contents - * @param[out] comments storage for the comments - * @return false if something failed, true otherwhise - */ - virtual bool getChannelComments(const RsGxsGroupId &channelId, - const std::set &contentIds, - std::vector &comments) = 0; - - /** - * @brief Get channel content summaries - * @jsonapi{development} - * @param[in] channelId id of the channel of which the content is requested - * @param[out] summaries storage for summaries - * @return false if something failed, true otherwhise - */ - virtual bool getContentSummaries( const RsGxsGroupId& channelId, - std::vector& summaries ) = 0; - - /** - * @brief Toggle post read status. Blocking API. - * @jsonapi{development} - * @param[in] postId post identifier - * @param[in] read true to mark as read, false to mark as unread - * @return false on error, true otherwise - */ - virtual bool markRead(const RsGxsGrpMsgIdPair& postId, bool read) = 0; - - /** - * @brief Share channel publishing key - * This can be used to authorize other peers to post on the channel - * @jsonapi{development} - * @param[in] channelId id of the channel - * @param[in] peers peers to share the key with - * @return false on error, true otherwise - */ - virtual bool shareChannelKeys( - const RsGxsGroupId& channelId, const std::set& peers ) = 0; - - /** - * @brief Subscrbe to a channel. Blocking API - * @jsonapi{development} - * @param[in] channelId Channel id - * @param[in] subscribe true to subscribe, false to unsubscribe - * @return false on error, true otherwise - */ - virtual bool subscribeToChannel( const RsGxsGroupId& channelId, - bool subscribe ) = 0; - - /** - * \brief Retrieve statistics about the channel service - * @jsonapi{development} - * \param[out] stat Statistics structure - * \return - */ - virtual bool getChannelServiceStatistics(GxsServiceStatistic& stat) =0; - - /** - * \brief Retrieve statistics about the given channel - * @jsonapi{development} - * \param[in] channelId Id of the channel group - * \param[out] stat Statistics structure - * \return - */ - virtual bool getChannelStatistics(const RsGxsGroupId& channelId,GxsGroupStatistic& stat) =0; - - /// default base URL used for channels links @see exportChannelLink - static const std::string DEFAULT_CHANNEL_BASE_URL; - - /// Link query field used to store channel name @see exportChannelLink - static const std::string CHANNEL_URL_NAME_FIELD; - - /// Link query field used to store channel id @see exportChannelLink - static const std::string CHANNEL_URL_ID_FIELD; - - /// Link query field used to store channel data @see exportChannelLink - static const std::string CHANNEL_URL_DATA_FIELD; - - /** Link query field used to store channel message title - * @see exportChannelLink */ - static const std::string CHANNEL_URL_MSG_TITLE_FIELD; - - /// Link query field used to store channel message id @see exportChannelLink - static const std::string CHANNEL_URL_MSG_ID_FIELD; - - /** - * @brief Get link to a channel - * @jsonapi{development} - * @param[out] link storage for the generated link - * @param[in] chanId Id of the channel of which we want to generate a link - * @param[in] includeGxsData if true include the channel GXS group data so - * the receiver can subscribe to the channel even if she hasn't received it - * through GXS yet - * @param[in] baseUrl URL into which to sneak in the RetroShare link - * radix, this is primarly useful to induce applications into making the - * link clickable, or to disguise the RetroShare link into a - * "normal" looking web link. If empty the GXS data link will be outputted - * in plain base64 format. - * @param[out] errMsg optional storage for error message, meaningful only in - * case of failure - * @return false if something failed, true otherwhise - */ - virtual bool exportChannelLink( - std::string& link, const RsGxsGroupId& chanId, - bool includeGxsData = true, - const std::string& baseUrl = RsGxsChannels::DEFAULT_CHANNEL_BASE_URL, - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - /** - * @brief Import channel from full link - * @jsonapi{development} - * @param[in] link channel link either in radix or link format - * @param[out] chanId optional storage for parsed channel id - * @param[out] errMsg optional storage for error message, meaningful only in - * case of failure - * @return false if some error occurred, true otherwise - */ - virtual bool importChannelLink( - const std::string& link, - RsGxsGroupId& chanId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId), - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - /** - * @brief Search the turtle reachable network for matching channels - * @jsonapi{development} - * An @see RsGxsChannelSearchResultEvent is emitted when matching channels - * arrives from the network - * @param[in] matchString string to search into the channels - * @return search id - */ - virtual TurtleRequestId turtleSearchRequest(const std::string& matchString)=0; - - /** - * @brief Retrieve available search results - * @jsonapi{development} - * @param[in] searchId search id - * @param[out] results storage for search results - * @return false on error, true otherwise - */ - virtual bool retrieveDistantSearchResults( - TurtleRequestId searchId, - std::map& results ) = 0; - - /** - * @brief Request distant channel details - * @jsonapi{development} - * An @see RsGxsChannelSearchResultEvent is emitted once details are - * retrieved from the network - * @param[in] groupId if of the group to request to the network - * @return search id - */ - virtual TurtleRequestId turtleGroupRequest(const RsGxsGroupId& groupId) = 0; - - /** - * @brief Retrieve previously requested distant group - * @jsonapi{development} - * @param[in] groupId if of teh group - * @param[out] distantGroup storage for group data - * @return false on error, true otherwise - */ - virtual bool getDistantSearchResultGroupData(const RsGxsGroupId& groupId, RsGxsChannelGroup& distantGroup ) = 0; - - /** - * @brief getDistantSearchStatus - * Returns the status of ongoing search: unknown (probably not even searched), known as a search result, - * data request ongoing and data available - */ - virtual DistantSearchGroupStatus getDistantSearchStatus(const RsGxsGroupId& group_id) =0; - - /** - * @brief Clear accumulated search results - * @jsonapi{development} - * @param[in] reqId search id - * @return false on error, true otherwise - */ - virtual bool clearDistantSearchResults(TurtleRequestId reqId) = 0; - - ~RsGxsChannels() override; - - //////////////////////////////////////////////////////////////////////////// - /* Following functions are deprecated and should not be considered a safe to - * use API */ - - /** - * @brief Get auto-download option value for given channel - * @jsonapi{development} - * @deprecated This feature rely on very buggy code, the returned value is - * not reliable @see setChannelAutoDownload(). - * @param[in] channelId channel id - * @param[out] enabled storage for the auto-download option value - * @return false if something failed, true otherwhise - */ - RS_DEPRECATED - virtual bool getChannelAutoDownload( - const RsGxsGroupId& channelId, bool& enabled ) = 0; - - /** - * @brief Enable or disable auto-download for given channel. Blocking API - * @jsonapi{development} - * @deprecated This feature rely on very buggy code, when enabled the - * channel service start flooding erratically log with error messages, - * apparently without more dangerous consequences. Still those messages - * hints that something out of control is happening under the hood, use at - * your own risk. A safe alternative to this method can easly implemented - * at API client level instead. - * @param[in] channelId channel id - * @param[in] enable true to enable, false to disable - * @return false if something failed, true otherwhise - */ - RS_DEPRECATED - virtual bool setChannelAutoDownload( - const RsGxsGroupId& channelId, bool enable ) = 0; - - /** - * @brief Get download directory for the given channel - * @jsonapi{development} - * @deprecated @see setChannelAutoDownload() - * @param[in] channelId id of the channel - * @param[out] directory reference to string where to store the path - * @return false on error, true otherwise - */ - RS_DEPRECATED - virtual bool getChannelDownloadDirectory( const RsGxsGroupId& channelId, - std::string& directory ) = 0; - - /** - * @brief Set download directory for the given channel. Blocking API. - * @jsonapi{development} - * @deprecated @see setChannelAutoDownload() - * @param[in] channelId id of the channel - * @param[in] directory path - * @return false on error, true otherwise - */ - RS_DEPRECATED - virtual bool setChannelDownloadDirectory( - const RsGxsGroupId& channelId, const std::string& directory) = 0; - - /** - * @brief Create channel. Blocking API. - * @jsonapi{development} - * @deprecated { substituted by createChannelV2 } - * @param[inout] channel Channel data (name, description...) - * @return false on error, true otherwise - */ - RS_DEPRECATED_FOR(createChannelV2) - virtual bool createChannel(RsGxsChannelGroup& channel) = 0; - - RS_DEPRECATED_FOR(getChannelsInfo) - virtual bool getGroupData(const uint32_t &token, std::vector &groups) = 0; - - RS_DEPRECATED_FOR(getChannelContent) - virtual bool getPostData(const uint32_t &token, std::vector &posts, std::vector &cmts, std::vector &votes) = 0; - - RS_DEPRECATED_FOR(getChannelContent) - virtual bool getPostData(const uint32_t &token, std::vector &posts, std::vector &cmts) = 0; - - RS_DEPRECATED_FOR(getChannelContent) - virtual bool getPostData(const uint32_t &token, std::vector &posts) = 0; - - /** - * @brief toggle message read status - * @deprecated - * @param[out] token GXS token queue token - * @param[in] msgId - * @param[in] read - */ - RS_DEPRECATED_FOR(markRead) - virtual void setMessageReadStatus( - uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) = 0; - - /** - * @brief Share channel publishing key - * This can be used to authorize other peers to post on the channel - * @deprecated - * @param[in] groupId Channel id - * @param[in] peers peers to which share the key - * @return false on error, true otherwise - */ - RS_DEPRECATED_FOR(shareChannelKeys) - virtual bool groupShareKeys( - const RsGxsGroupId& groupId, const std::set& peers ) = 0; - - /** - * @brief Request subscription to a group. - * The action is performed asyncronously, so it could fail in a subsequent - * phase even after returning true. - * @deprecated - * @param[out] token Storage for RsTokenService token to track request - * status. - * @param[in] groupId Channel id - * @param[in] subscribe - * @return false on error, true otherwise - */ - RS_DEPRECATED_FOR(subscribeToChannel) - virtual bool subscribeToGroup( uint32_t& token, const RsGxsGroupId &groupId, - bool subscribe ) = 0; - - /** - * @brief Request channel creation. - * The action is performed asyncronously, so it could fail in a subsequent - * phase even after returning true. - * @deprecated - * @param[out] token Storage for RsTokenService token to track request - * status. - * @param[in] group Channel data (name, description...) - * @return false on error, true otherwise - */ - RS_DEPRECATED_FOR(createChannelV2) - virtual bool createGroup(uint32_t& token, RsGxsChannelGroup& group) = 0; - - /** - * @brief Add a comment on a post or on another comment - * @jsonapi{development} - * @deprecated - * @param[inout] comment - * @return false on error, true otherwise - */ - RS_DEPRECATED_FOR(createCommentV2) - virtual bool createComment(RsGxsComment& comment) = 0; - - /** - * @brief Create channel post. Blocking API. - * @jsonapi{development} - * @deprecated - * @param[inout] post - * @return false on error, true otherwise - */ - RS_DEPRECATED_FOR(createPostV2) - virtual bool createPost(RsGxsChannelPost& post) = 0; - - /** - * @brief Request post creation. - * The action is performed asyncronously, so it could fail in a subsequent - * phase even after returning true. - * @deprecated - * @param[out] token Storage for RsTokenService token to track request - * status. - * @param[in] post - * @return false on error, true otherwise - */ - RS_DEPRECATED_FOR(createPostV2) - virtual bool createPost(uint32_t& token, RsGxsChannelPost& post) = 0; - - /** - * @brief createVote - * @jsonapi{development} - * @deprecated - * @param[inout] vote - * @return false on error, true otherwise - */ - RS_DEPRECATED_FOR(createVoteV2) - virtual bool createVote(RsGxsVote& vote) = 0; - - /** - * @brief Request channel change. - * The action is performed asyncronously, so it could fail in a subsequent - * phase even after returning true. - * @deprecated - * @param[out] token Storage for RsTokenService token to track request - * status. - * @param[in] group Channel data (name, description...) with modifications - * @return false on error, true otherwise - */ - RS_DEPRECATED_FOR(editChannel) - virtual bool updateGroup(uint32_t& token, RsGxsChannelGroup& group) = 0; -}; diff --git a/libretroshare/src/retroshare/rsgxscircles.h b/libretroshare/src/retroshare/rsgxscircles.h deleted file mode 100644 index 40916f234..000000000 --- a/libretroshare/src/retroshare/rsgxscircles.h +++ /dev/null @@ -1,526 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgxscircles.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012-2014 Robert Fernie * - * Copyright (C) 2018-2021 Gioacchino Mazzurco * - * Copyright (C) 2019-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -#include "retroshare/rstypes.h" -#include "retroshare/rstokenservice.h" -#include "retroshare/rsgxsifacehelper.h" -#include "retroshare/rsidentity.h" -#include "serialiser/rsserializable.h" -#include "util/rsmemory.h" - - -class RsGxsCircles; - -/** - * Pointer to global instance of RsGxsCircles service implementation - * @jsonapi{development} - */ -extern RsGxsCircles* rsGxsCircles; - -enum class RsGxsCircleType : uint32_t // 32 bit overkill, just for retrocompat -{ - UNKNOWN = 0, /// Used to detect uninizialized values. - PUBLIC = 1, /// Public distribution - EXTERNAL = 2, /// Restricted to an external circle, based on GxsIds - - NODES_GROUP = 3, /// Restricted to a group of friend nodes, the administrator of the circle behave as a hub for them - /// Based on PGP nodes ids. - - LOCAL = 4, /// not distributed at all - - /** Self-restricted. Used only at creation time of self-restricted circles - * when the circle id isn't known yet. Once the circle id is known the type - * is set to EXTERNAL, and the external circle id is set to the id of the - * circle itself. Based on GxsIds. - */ - EXT_SELF = 5, - - YOUR_EYES_ONLY = 6 /// distributed to nodes signed by your own PGP key only. -}; - -// TODO: convert to enum class -static const uint32_t GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST = 0x0001 ;// user is validated by circle admin -static const uint32_t GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED = 0x0002 ;// user has subscribed the group -static const uint32_t GXS_EXTERNAL_CIRCLE_FLAGS_KEY_AVAILABLE = 0x0004 ;// key is available, so we can encrypt for this circle -static const uint32_t GXS_EXTERNAL_CIRCLE_FLAGS_ALLOWED = 0x0007 ;// user is allowed. Combines all flags above. - - -struct RsGxsCircleGroup : RsSerializable -{ - RsGroupMetaData mMeta; - - std::set mLocalFriends; - std::set mInvitedMembers; - std::set mSubCircles; -#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_UNNAMED -# error "Add description, and multiple owners/administrators to circles" - // or better in general to GXS groups -#endif - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - RS_SERIAL_PROCESS(mMeta); - RS_SERIAL_PROCESS(mLocalFriends); - RS_SERIAL_PROCESS(mInvitedMembers); - RS_SERIAL_PROCESS(mSubCircles); - } - - ~RsGxsCircleGroup() override; -}; - -enum class RsGxsCircleSubscriptionType:uint8_t { - UNKNOWN = 0x00, - SUBSCRIBE = 0x01, - UNSUBSCRIBE = 0x02 -}; - -struct RsGxsCircleMsg : RsSerializable -{ - RsMsgMetaData mMeta; - -#ifdef TO_REMOVE - // This item is actually totally unused, so we can change it no problem -#ifndef V07_NON_BACKWARD_COMPATIBLE_CHANGE_UNNAMED - /* This is horrible and should be changed into yet to be defined something - * reasonable in next non-retrocompatible version */ - std::string stuff; -#endif -#endif - RsGxsCircleSubscriptionType mSubscriptionType; - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - RS_SERIAL_PROCESS(mMeta); - RS_SERIAL_PROCESS(mSubscriptionType); - } - - ~RsGxsCircleMsg() override; -}; - -struct RsGxsCircleDetails : RsSerializable -{ - RsGxsCircleDetails() : mCircleType(RsGxsCircleType::EXTERNAL), mAmIAllowed(false),mAmIAdmin(false) {} - ~RsGxsCircleDetails() override; - - // helper functions. - bool isIdInCircle(const RsGxsId& id) const { return mAllowedGxsIds.find(id) != mAllowedGxsIds.end(); } - bool isIdInInviteeList(const RsGxsId& id) const - { - auto it = mSubscriptionFlags.find(id); - return (it != mSubscriptionFlags.end()) && (it->second & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST ); - } - bool isIdRequestingMembership(const RsGxsId& id) const - { - auto it = mSubscriptionFlags.find(id); - return it != mSubscriptionFlags.end() && (it->second & GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED ); - } - bool isGxsIdBased() const { return mCircleType==RsGxsCircleType::PUBLIC || mCircleType==RsGxsCircleType::EXTERNAL || mCircleType==RsGxsCircleType::EXT_SELF; } - - // Members - - RsGxsCircleId mCircleId; - std::string mCircleName; - - RsGxsCircleType mCircleType; - RsGxsCircleId mRestrictedCircleId; - - /** true when one of load GXS ids belong to the circle allowed list (admin - * list & subscribed list). */ - bool mAmIAllowed; - - /// true when we're an administrator of the circle group, meaning that we can add/remove members from the invitee list. - bool mAmIAdmin; - - /// This crosses admin list and subscribed list - std::set mAllowedGxsIds; - std::set mAllowedNodes; - - /// subscription flags for all ids - std::map mSubscriptionFlags; - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - RS_SERIAL_PROCESS(mCircleId); - RS_SERIAL_PROCESS(mCircleName); - RS_SERIAL_PROCESS(mCircleType); - RS_SERIAL_PROCESS(mRestrictedCircleId); - RS_SERIAL_PROCESS(mAmIAllowed); - RS_SERIAL_PROCESS(mAmIAdmin); - RS_SERIAL_PROCESS(mAllowedGxsIds); - RS_SERIAL_PROCESS(mAllowedNodes); - RS_SERIAL_PROCESS(mSubscriptionFlags); - } -}; - - -enum class RsGxsCircleEventCode: uint8_t -{ - // Notifications be only have 4 different possibilities: - // - // invitee list join/leave and - // membership request / leave request - // - // From there, depending on what the client displays, it is possible to interpret these - // as "some user joined the circle", or "membership pending for that Id", etc, depending - // on whether the current node owns the circle, or the admin is or is not yours. - // - // These should be decided in the UI based on what the circle cache is displaying. - // - UNKNOWN = 0x00, - - /** - * Sent when we receive a membership request msg for a particular circle. - * - * mCircleId contains the circle id and mGxsId is the id requesting membership */ - CIRCLE_MEMBERSHIP_REQUEST = 0x01, - - /** - * Sent when the ID has been added to the circle invitee list. - * - * mCircleId is the circle that invites me, and mGxsId is my own Id that is invited */ - CIRCLE_MEMBERSHIP_ID_ADDED_TO_INVITEE_LIST = 0x02, - - /** - * Sent when a GxsId annouces its will to not be in the circle. - * - * mCircleId contains the circle id and mGxsId is the id dropping membership */ - CIRCLE_MEMBERSHIP_LEAVE = 0x03, - - /** - * Sent when the Id has been removed from the invitee list. - * - * mCircleId contains the circle id and mGxsId is the id that was revoqued * by admin */ - CIRCLE_MEMBERSHIP_ID_REMOVED_FROM_INVITEE_LIST = 0x04, - - /** - * Means a new circle has been received. - * - * mCircleId contains the circle id */ - NEW_CIRCLE = 0x05, - - /** - * Means that the circle cache has updated, and membership status that is displayed should probably be updated to. - * - * no additional information. Simply means that the info previously from the cache has changed. */ - CACHE_DATA_UPDATED = 0x06, - - /** - * The circle has been deleted by auto-cleaning. - * */ - CIRCLE_DELETED = 0x07, - - /** - * Circle has been updated (name, parent circle, type, etc) - * */ - CIRCLE_UPDATED = 0x08, -}; - -struct RsGxsCircleEvent: RsEvent -{ - RsGxsCircleEvent() - : RsEvent(RsEventType::GXS_CIRCLES), - mCircleEventType(RsGxsCircleEventCode::UNKNOWN) {} - - - RsGxsCircleEventCode mCircleEventType; - RsGxsCircleId mCircleId; - RsGxsId mGxsId; - - ///* @see RsEvent @see RsSerializable - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RsEvent::serial_process(j, ctx); - RS_SERIAL_PROCESS(mCircleEventType); - RS_SERIAL_PROCESS(mCircleId); - RS_SERIAL_PROCESS(mGxsId); - } - - ~RsGxsCircleEvent() override; -}; - -class RsGxsCircles: public RsGxsIfaceHelper -{ -public: - - RsGxsCircles(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {} - virtual ~RsGxsCircles(); - - /** - * @brief Create new circle - * @jsonapi{development} - * @param[in] circleName String containing cirlce name - * @param[in] circleType Circle type - * @param[out] circleId Optional storage to output created circle id - * @param[in] restrictedId Optional id of a pre-existent circle that see the - * created circle. Meaningful only if circleType == EXTERNAL, must be null - * in all other cases. - * @param[in] authorId Optional author of the circle. - * @param[in] gxsIdMembers GXS ids of the members of the circle. - * @param[in] localMembers PGP ids of the members if the circle. - * @return false if something failed, true otherwhise - */ - virtual bool createCircle( - const std::string& circleName, RsGxsCircleType circleType, - RsGxsCircleId& circleId = RS_DEFAULT_STORAGE_PARAM(RsGxsCircleId), - const RsGxsCircleId& restrictedId = RsGxsCircleId(), - const RsGxsId& authorId = RsGxsId(), - const std::set& gxsIdMembers = std::set(), - const std::set& localMembers = std::set() ) = 0; - -// TODO. If so, remove the other editCircle that has the same name, otherwise jsonapi will crash -// -// /** -// * @brief Edit an existing circle -// * @jsonapi{development} -// * @param[in] circleId Optional storage to output created circle id -// * @param[in] circleName String containing cirlce name -// * @param[in] circleType Circle type -// * @param[in] restrictedId Optional id of a pre-existent circle that see the -// * created circle. Meaningful only if circleType == EXTERNAL, must be null -// * in all other cases. -// * @param[in] authorId Optional author of the circle. -// * @param[in] gxsIdMembers GXS ids of the members of the circle. -// * @param[in] localMembers PGP ids of the members if the circle. -// * @return false if something failed, true otherwhise -// */ -// virtual bool editCircle( const RsGxsCircleId& circleId, const std::string& circleName, RsGxsCircleType circleType, -// const RsGxsCircleId& restrictedId, -// const RsGxsId& authorId, const std::set& gxsIdMembers, -// const std::set& localMembers ) =0; - - /** - * @brief Edit own existing circle - * @jsonapi{development} - * @param[inout] cData Circle data with modifications, storage for data - * updatedad during the operation. - * @return false if something failed, true otherwhise - */ - virtual bool editCircle(RsGxsCircleGroup& cData) = 0; - - /** - * @brief Get circle details. Memory cached - * @jsonapi{development} - * @param[in] id Id of the circle - * @param[out] details Storage for the circle details - * @return false if something failed, true otherwhise - */ - virtual bool getCircleDetails(const RsGxsCircleId& id, RsGxsCircleDetails& details ) = 0; - - /** - * @brief Get list of known external circles ids. Memory cached - * @jsonapi{development} - * @param[in] circleIds Storage for circles id list - * @return false if something failed, true otherwhise - */ - virtual bool getCircleExternalIdList(std::set& circleIds ) = 0; - - /** - * @brief Get circles summaries list. - * @jsonapi{development} - * @param[out] circles list where to store the circles summaries - * @return false if something failed, true otherwhise - */ - virtual bool getCirclesSummaries(std::list& circles) = 0; - - /** - * @brief Get circles information - * @jsonapi{development} - * @param[in] circlesIds ids of the circles of which to get the informations - * @param[out] circlesInfo storage for the circles informations - * @return false if something failed, true otherwhise - */ - virtual bool getCirclesInfo( - const std::list& circlesIds, - std::vector& circlesInfo ) = 0; - - /** - * @brief Get circle requests - * @jsonapi{development} - * @param[in] circleId id of the circle of which the requests are requested - * @param[out] requests storage for the circle requests - * @return false if something failed, true otherwhise - */ - virtual bool getCircleRequests( const RsGxsGroupId& circleId, - std::vector& requests ) = 0; - /** - * @brief Get specific circle request - * @jsonapi{development} - * @param[in] circleId id of the circle of which the requests are requested - * @param[in] msgId id of the request - * @param[out] msg storage for the circle request - * @return false if something failed, true otherwhise - */ - virtual bool getCircleRequest(const RsGxsGroupId& circleId, - const RsGxsMessageId& msgId, - RsGxsCircleMsg& msg) =0; - - /** - * @brief Invite identities to circle (admin key is required) - * @jsonapi{development} - * @param[in] identities ids of the identities to invite - * @param[in] circleId Id of the circle you own and want to invite ids in - * @return false if something failed, true otherwhise - */ - virtual bool inviteIdsToCircle( const std::set& identities, - const RsGxsCircleId& circleId ) = 0; - - /** - * @brief Remove identities from circle (admin key is required) - * @jsonapi{development} - * @param[in] identities ids of the identities to remove from the invite list - * @param[in] circleId Id of the circle you own and want to invite ids in - * @return false if something failed, true otherwhise - */ - virtual bool revokeIdsFromCircle( const std::set& identities, - const RsGxsCircleId& circleId ) = 0; - - /** - * @brief Request circle membership, or accept circle invitation - * @jsonapi{development} - * @param[in] ownGxsId Id of own identity to introduce to the circle - * @param[in] circleId Id of the circle to which ask for inclusion - * @return false if something failed, true otherwhise - */ - virtual bool requestCircleMembership( - const RsGxsId& ownGxsId, const RsGxsCircleId& circleId ) = 0; - - /** - * @brief Leave given circle - * @jsonapi{development} - * @param[in] ownGxsId Own id to remove from the circle - * @param[in] circleId Id of the circle to leave - * @return false if something failed, true otherwhise - */ - virtual bool cancelCircleMembership( - const RsGxsId& ownGxsId, const RsGxsCircleId& circleId ) = 0; - - /// default base URL used for circle links @see exportCircleLink - static const std::string DEFAULT_CIRCLE_BASE_URL; - - /// Circle link query field used to store circle name @see exportCircleLink - static const std::string CIRCLE_URL_NAME_FIELD; - - /// Circle link query field used to store circle id @see exportCircleLink - static const std::string CIRCLE_URL_ID_FIELD; - - /// Circle link query field used to store circle data @see exportCircleLink - static const std::string CIRCLE_URL_DATA_FIELD; - - /** - * @brief Get link to a circle - * @jsonapi{development} - * @param[out] link storage for the generated link - * @param[in] circleId Id of the circle of which we want to generate a link - * @param[in] includeGxsData if true include the circle GXS group data so - * the receiver can request circle membership even if the circle hasn't - * propagated through GXS to her yet - * @param[in] baseUrl URL into which to sneak in the RetroShare circle link - * radix, this is primarly useful to induce applications into making the - * link clickable, or to disguise the RetroShare circle link into a - * "normal" looking web link. If empty the circle data link will be - * outputted in plain base64 format. - * @param[out] errMsg optional storage for error message, meaningful only in - * case of failure - * @return false if something failed, true otherwhise - */ - virtual bool exportCircleLink( - std::string& link, const RsGxsCircleId& circleId, - bool includeGxsData = true, - const std::string& baseUrl = RsGxsCircles::DEFAULT_CIRCLE_BASE_URL, - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - /** - * @brief Import circle from full link - * @param[in] link circle link either in radix or link format - * @param[out] circleId optional storage for parsed circle id - * @param[out] errMsg optional storage for error message, meaningful only in - * case of failure - * @return false if some error occurred, true otherwise - */ - virtual bool importCircleLink( - const std::string& link, - RsGxsCircleId& circleId = RS_DEFAULT_STORAGE_PARAM(RsGxsCircleId), - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - RS_DEPRECATED_FOR("getCirclesSummaries getCirclesInfo") - virtual bool getGroupData( - const uint32_t& token, std::vector& groups ) = 0; - - RS_DEPRECATED_FOR(getCirclesRequests) - virtual bool getMsgData( - const uint32_t& token, std::vector& msgs ) = 0; - - /// make new group - RS_DEPRECATED_FOR(createCircle) - virtual void createGroup(uint32_t& token, RsGxsCircleGroup &group) = 0; - - /// update an existing group - RS_DEPRECATED_FOR("editCircle, inviteIdsToCircle") - virtual void updateGroup(uint32_t &token, RsGxsCircleGroup &group) = 0; -}; - - -/// @deprecated Used to detect uninizialized values. -RS_DEPRECATED_FOR("RsGxsCircleType::UNKNOWN") -static const uint32_t GXS_CIRCLE_TYPE_UNKNOWN = 0x0000; - -/// @deprecated not restricted to a circle -RS_DEPRECATED_FOR("RsGxsCircleType::PUBLIC") -static const uint32_t GXS_CIRCLE_TYPE_PUBLIC = 0x0001; - -/// @deprecated restricted to an external circle, made of RsGxsId -RS_DEPRECATED_FOR("RsGxsCircleType::EXTERNAL") -static const uint32_t GXS_CIRCLE_TYPE_EXTERNAL = 0x0002; - -/// @deprecated restricted to a subset of friend nodes of a given RS node given -/// by a RsPgpId list -RS_DEPRECATED_FOR("RsGxsCircleType::NODES_GROUP") -static const uint32_t GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY = 0x0003; - -/// @deprecated not distributed at all -RS_DEPRECATED_FOR("RsGxsCircleType::LOCAL") -static const uint32_t GXS_CIRCLE_TYPE_LOCAL = 0x0004; - -/// @deprecated self-restricted. Not used, except at creation time when the -/// circle ID isn't known yet. Set to EXTERNAL afterwards. -RS_DEPRECATED_FOR("RsGxsCircleType::EXT_SELF") -static const uint32_t GXS_CIRCLE_TYPE_EXT_SELF = 0x0005; - -/// @deprecated distributed to nodes signed by your own PGP key only. -RS_DEPRECATED_FOR("RsGxsCircleType::YOUR_EYES_ONLY") -static const uint32_t GXS_CIRCLE_TYPE_YOUR_EYES_ONLY = 0x0006; diff --git a/libretroshare/src/retroshare/rsgxscommon.h b/libretroshare/src/retroshare/rsgxscommon.h deleted file mode 100644 index c820e1999..000000000 --- a/libretroshare/src/retroshare/rsgxscommon.h +++ /dev/null @@ -1,190 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgxscommon.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include - -#include "rsgxsifacetypes.h" -#include "serialiser/rsserializable.h" - -struct RsGxsFile : RsSerializable -{ - RsGxsFile(); - std::string mName; - RsFileHash mHash; - uint64_t mSize; - - /// @see RsSerializable - virtual void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(mName); - RS_SERIAL_PROCESS(mHash); - RS_SERIAL_PROCESS(mSize); - } - - void clear() - { - mName.clear(); - mHash.clear(); - mSize = 0; - } -}; - -struct RsGxsImage : RsSerializable -{ - RsGxsImage(); - ~RsGxsImage(); - - /// Use copy constructor and duplicate memory. - RsGxsImage(const RsGxsImage& a); - - RsGxsImage &operator=(const RsGxsImage &a); // Need this as well? - - /** NB: Must make sure that we always use methods - to be consistent about - * malloc/free for this data. */ - static uint8_t *allocate(uint32_t size); - static void release(void *data); - - void take(uint8_t *data, uint32_t size); // Copies Pointer. - void copy(uint8_t *data, uint32_t size); // Allocates and Copies. - void clear(); // Frees. - void shallowClear(); // Clears Pointer. - bool empty() const; - - uint32_t mSize; - uint8_t* mData; - - /// @see RsSerializable - virtual void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RsTypeSerializer::TlvMemBlock_proxy b(mData, mSize); - RsTypeSerializer::serial_process(j, ctx, b, "mData"); - } -}; - -enum class RsGxsVoteType : uint32_t -{ - NONE = 0, /// Used to detect unset vote? - DOWN = 1, /// Negative vote - UP = 2 /// Positive vote -}; - - -// Status Flags to indicate Voting.... -// All Services that use the Comment service must not Use This space. -namespace GXS_SERV { - /* Msg Vote Status */ - static const uint32_t GXS_MSG_STATUS_GXSCOMMENT_MASK = 0x000f0000; - static const uint32_t GXS_MSG_STATUS_VOTE_MASK = 0x00030000; - - static const uint32_t GXS_MSG_STATUS_VOTE_UP = 0x00010000; - static const uint32_t GXS_MSG_STATUS_VOTE_DOWN = 0x00020000; -} - - - - -struct RsGxsVote : RsSerializable -{ - RsGxsVote(); - RsMsgMetaData mMeta; - uint32_t mVoteType; - - /// @see RsSerializable - virtual void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(mMeta); - RS_SERIAL_PROCESS(mVoteType); - } -}; - -struct RsGxsComment : RsSerializable -{ - RsGxsComment(); - RsMsgMetaData mMeta; - std::string mComment; - - // below is calculated. - uint32_t mUpVotes; - uint32_t mDownVotes; - double mScore; - - uint32_t mOwnVote; - - // This is filled in if detailed Comment Data is called. - std::list mVotes; - - /// @see RsSerializable - virtual void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(mMeta); - RS_SERIAL_PROCESS(mComment); - RS_SERIAL_PROCESS(mUpVotes); - RS_SERIAL_PROCESS(mDownVotes); - RS_SERIAL_PROCESS(mScore); - RS_SERIAL_PROCESS(mOwnVote); - RS_SERIAL_PROCESS(mVotes); - } -}; - - -struct RsGxsCommentService -{ - RsGxsCommentService() {} - virtual ~RsGxsCommentService() {} - - /** Get previously requested comment data with token */ - virtual bool getCommentData( uint32_t token, - std::vector &comments ) = 0; - virtual bool getRelatedComments( uint32_t token, - std::vector &comments ) = 0; - - virtual bool createNewComment(uint32_t &token, const RsGxsComment &comment) = 0; // async API - virtual bool createComment(RsGxsComment& comment) = 0; // blocking API. Updates comment with new metadata. - - virtual bool createNewVote(uint32_t &token, RsGxsVote &vote) = 0; - - virtual bool acknowledgeComment( - uint32_t token, - std::pair& msgId ) = 0; - - virtual bool acknowledgeVote( - uint32_t token, - std::pair& msgId ) = 0; - - virtual bool setCommentAsRead(uint32_t& token,const RsGxsGroupId& gid,const RsGxsMessageId& comment_msg_id) = 0; -}; - -/// @deprecated use RsGxsVoteType::NONE instead @see RsGxsVoteType -#define GXS_VOTE_NONE 0x0000 - -/// @deprecated use RsGxsVoteType::DOWN instead @see RsGxsVoteType -#define GXS_VOTE_DOWN 0x0001 - -/// @deprecated use RsGxsVoteType::UP instead @see RsGxsVoteType -#define GXS_VOTE_UP 0x0002 diff --git a/libretroshare/src/retroshare/rsgxsdistsync.h b/libretroshare/src/retroshare/rsgxsdistsync.h deleted file mode 100644 index d65027d58..000000000 --- a/libretroshare/src/retroshare/rsgxsdistsync.h +++ /dev/null @@ -1,91 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgxsdistsync.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#pragma once - -#include "retroshare/rsfiles.h" -#include "retroshare/rsturtle.h" - -typedef RsPeerId RsGxsNetTunnelVirtualPeerId ; - -struct RsGxsNetTunnelVirtualPeerInfo -{ - enum { RS_GXS_NET_TUNNEL_VP_STATUS_UNKNOWN = 0x00, // unknown status. - RS_GXS_NET_TUNNEL_VP_STATUS_TUNNEL_OK = 0x01, // tunnel has been established and we're waiting for virtual peer id - RS_GXS_NET_TUNNEL_VP_STATUS_ACTIVE = 0x02 // virtual peer id is known. Data can transfer. - }; - - RsGxsNetTunnelVirtualPeerInfo() : vpid_status(RS_GXS_NET_TUNNEL_VP_STATUS_UNKNOWN), last_contact(0),side(0) { memset(encryption_master_key,0,32) ; } - virtual ~RsGxsNetTunnelVirtualPeerInfo(){} - - uint8_t vpid_status ; // status of the peer - rstime_t last_contact ; // last time some data was sent/recvd - uint8_t side ; // client/server - uint8_t encryption_master_key[32]; - - TurtleVirtualPeerId turtle_virtual_peer_id ; // turtle peer to use when sending data to this vpid. - - RsGxsGroupId group_id ; // group that virtual peer is providing - uint16_t service_id ; // this is used for checkng consistency of the incoming data -}; - -struct RsGxsNetTunnelGroupInfo -{ - enum GroupStatus { - RS_GXS_NET_TUNNEL_GRP_STATUS_UNKNOWN = 0x00, // unknown status - RS_GXS_NET_TUNNEL_GRP_STATUS_IDLE = 0x01, // no virtual peers requested, just waiting - RS_GXS_NET_TUNNEL_GRP_STATUS_VPIDS_AVAILABLE = 0x02 // some virtual peers are available. Data can be read/written - }; - - enum GroupPolicy { - RS_GXS_NET_TUNNEL_GRP_POLICY_UNKNOWN = 0x00, // nothing has been set - RS_GXS_NET_TUNNEL_GRP_POLICY_PASSIVE = 0x01, // group is available for server side tunnels, but does not explicitely request tunnels - RS_GXS_NET_TUNNEL_GRP_POLICY_ACTIVE = 0x02, // group will only explicitely request tunnels if none available - RS_GXS_NET_TUNNEL_GRP_POLICY_REQUESTING = 0x03, // group explicitely requests tunnels - }; - - RsGxsNetTunnelGroupInfo() : group_policy(RS_GXS_NET_TUNNEL_GRP_POLICY_PASSIVE),group_status(RS_GXS_NET_TUNNEL_GRP_STATUS_IDLE),last_contact(0) {} - - GroupPolicy group_policy ; - GroupStatus group_status ; - rstime_t last_contact ; - RsFileHash hash ; - uint16_t service_id ; - - std::set virtual_peers ; // list of which virtual peers provide this group. Can me more than 1. -}; - -// This class is here to provide statistics about GXS dist sync internals. It -// -class RsGxsDistSync -{ - public: - virtual void getStatistics( - std::map& groups, // groups on the client and server side - std::map& virtual_peers, // current virtual peers, which group they provide, and how to talk to them through turtle - std::map& turtle_vpid_to_net_tunnel_vpid, - Bias20Bytes& bias - ) const =0; -}; - -extern RsGxsDistSync *rsGxsDistSync ; - diff --git a/libretroshare/src/retroshare/rsgxsflags.h b/libretroshare/src/retroshare/rsgxsflags.h deleted file mode 100644 index 7ef6d2c49..000000000 --- a/libretroshare/src/retroshare/rsgxsflags.h +++ /dev/null @@ -1,138 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgxsflags.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2018 by Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RSGXSFLAGS_H -#define RSGXSFLAGS_H - -#include "inttypes.h" - -/** - * The GXS_SERV namespace serves a single point of reference for definining grp and msg flags - * Declared and defined here are: - * - privacy flags which define the level of privacy that can be given \n - * to a group - * - authentication types which defined types of authentication needed for a given message to - * confirm its authenticity - * - subscription flags: This used only locally by the peer to subscription status to a \n - * a group - * - - */ -namespace GXS_SERV { - - /** START privacy **/ - - static const uint32_t FLAG_PRIVACY_MASK = 0x0000000f; - static const uint32_t FLAG_PRIVACY_PRIVATE = 0x00000001; // pub key encrypted. No-one can read unless he has the key to decrypt the publish key. - static const uint32_t FLAG_PRIVACY_RESTRICTED = 0x00000002; // publish private key needed to publish. Typical usage: channels. - static const uint32_t FLAG_PRIVACY_PUBLIC = 0x00000004; // anyone can publish, publish key pair not needed. Typical usage: forums. - - /** END privacy **/ - - /** END authentication **/ - - /** START author authentication flags **/ - static const uint32_t FLAG_AUTHOR_AUTHENTICATION_MASK = 0x0000ff00; - static const uint32_t FLAG_AUTHOR_AUTHENTICATION_NONE = 0x00000000; - static const uint32_t FLAG_AUTHOR_AUTHENTICATION_GPG = 0x00000100; // Anti-spam feature. Allows to ask higher reputation to anonymous IDs - static const uint32_t FLAG_AUTHOR_AUTHENTICATION_REQUIRED = 0x00000200; - static const uint32_t FLAG_AUTHOR_AUTHENTICATION_IFNOPUBSIGN = 0x00000400; // ??? - static const uint32_t FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES = 0x00000800; // not used anymore - static const uint32_t FLAG_AUTHOR_AUTHENTICATION_GPG_KNOWN = 0x00001000; // Anti-spam feature. Allows to ask higher reputation to unknown IDs and anonymous IDs - - static const uint32_t FLAG_GROUP_SIGN_PUBLISH_MASK = 0x000000ff; - static const uint32_t FLAG_GROUP_SIGN_PUBLISH_ENCRYPTED = 0x00000001; - static const uint32_t FLAG_GROUP_SIGN_PUBLISH_ALLSIGNED = 0x00000002; // unused - static const uint32_t FLAG_GROUP_SIGN_PUBLISH_THREADHEAD = 0x00000004; - static const uint32_t FLAG_GROUP_SIGN_PUBLISH_NONEREQ = 0x00000008; - - /** START msg authentication flags **/ - - static const uint8_t MSG_AUTHEN_MASK = 0x0f; - static const uint8_t MSG_AUTHEN_ROOT_PUBLISH_SIGN = 0x01; // means: new threads need to be signed by the publish signature of the group. Typical use: posts in channels. - static const uint8_t MSG_AUTHEN_CHILD_PUBLISH_SIGN = 0x02; // means: all messages need to be signed by the publish signature of the group. Typical use: channels were comments are restricted to the publisher. - static const uint8_t MSG_AUTHEN_ROOT_AUTHOR_SIGN = 0x04; // means: new threads need to be signed by the author of the message. Typical use: forums, since posts are signed. - static const uint8_t MSG_AUTHEN_CHILD_AUTHOR_SIGN = 0x08; // means: all messages need to be signed by the author of the message. Typical use: forums since response to posts are signed, and signed comments in channels. - - /** END msg authentication flags **/ - - /** START group options flag **/ - - static const uint8_t GRP_OPTION_AUTHEN_AUTHOR_SIGN = 0x01; // means: the group options (serialised grp data) needs to be signed by a specific author stored in GroupMeta.mAuthorId - // note that it is always signed by the *admin* (means the creator) of the group. This author signature is just an option here. - - /** END group options flag **/ - - /** START Subscription Flags. (LOCAL) **/ - - static const uint32_t GROUP_SUBSCRIBE_ADMIN = 0x01;// means: you have the admin key for this group - static const uint32_t GROUP_SUBSCRIBE_PUBLISH = 0x02;// means: you have the publish key for thiss group. Typical use: publish key in channels are shared with specific friends. - static const uint32_t GROUP_SUBSCRIBE_SUBSCRIBED = 0x04;// means: you are subscribed to a group, which makes you a source for this group to your friend nodes. - static const uint32_t GROUP_SUBSCRIBE_NOT_SUBSCRIBED = 0x08; - - /*! - * Simply defines the range of bits that deriving services - * should not use - */ - static const uint32_t GROUP_SUBSCRIBE_MASK = 0x0000000f; - - /** END Subscription Flags. (LOCAL) **/ - - /** START GXS Msg status flags **/ - - /*! - * Two lower bytes are reserved for Generic STATUS Flags listed here. - * Services are free to use the two upper bytes. (16 flags). - * - * NOTE: RsGxsCommentService uses 0x000f0000. - */ - static const uint32_t GXS_MSG_STATUS_GEN_MASK = 0x0000ffff; - static const uint32_t GXS_MSG_STATUS_UNPROCESSED = 0x00000001; // Flags to store the read/process status of group messages. - static const uint32_t GXS_MSG_STATUS_GUI_UNREAD = 0x00000002; // The actual meaning may depend on the type of service. - static const uint32_t GXS_MSG_STATUS_GUI_NEW = 0x00000004; // - static const uint32_t GXS_MSG_STATUS_KEEP_FOREVER = 0x00000008; // Do not delete message even if older then group maximum storage time - static const uint32_t GXS_MSG_STATUS_DELETE = 0x00000020; // - - /** END GXS Msg status flags **/ - - /** START GXS Grp status flags **/ - - static const uint32_t GXS_GRP_STATUS_UNPROCESSED = 0x000000100; - static const uint32_t GXS_GRP_STATUS_UNREAD = 0x000000200; - - /** END GXS Grp status flags **/ -} - - -// GENERIC GXS MACROS -#define IS_MSG_NEW(status) (status & GXS_SERV::GXS_MSG_STATUS_GUI_NEW) -#define IS_MSG_UNREAD(status) (status & GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD) -#define IS_MSG_UNPROCESSED(status) (status & GXS_SERV::GXS_MSG_STATUS_UNPROCESSED) - -#define IS_GROUP_PGP_AUTHED(signFlags) (signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG) -#define IS_GROUP_PGP_KNOWN_AUTHED(signFlags) (signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_GPG_KNOWN) -#define IS_GROUP_MESSAGE_TRACKING(signFlags) (signFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES) - -#define IS_GROUP_ADMIN(subscribeFlags) (subscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) -#define IS_GROUP_PUBLISHER(subscribeFlags) (subscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_PUBLISH) -#define IS_GROUP_SUBSCRIBED(subscribeFlags) (subscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) -#define IS_GROUP_NOT_SUBSCRIBED(subscribeFlags) (subscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_NOT_SUBSCRIBED) - -#endif // RSGXSFLAGS_H diff --git a/libretroshare/src/retroshare/rsgxsforums.h b/libretroshare/src/retroshare/rsgxsforums.h deleted file mode 100644 index ba13bd16e..000000000 --- a/libretroshare/src/retroshare/rsgxsforums.h +++ /dev/null @@ -1,502 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgxsforums.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012-2014 Robert Fernie * - * Copyright (C) 2018-2021 Gioacchino Mazzurco * - * Copyright (C) 2019-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -#include "retroshare/rstokenservice.h" -#include "retroshare/rsgxsifacehelper.h" -#include "serialiser/rstlvidset.h" -#include "serialiser/rsserializable.h" -#include "retroshare/rsgxscircles.h" - - -class RsGxsForums; - -/** - * Pointer to global instance of RsGxsForums service implementation - * @jsonapi{development} - */ -extern RsGxsForums* rsGxsForums; - - -/** Forum Service message flags, to be used in RsMsgMetaData::mMsgFlags - * Gxs imposes to use the first two bytes (lower bytes) of mMsgFlags for - * private forum flags, the upper bytes being used for internal GXS stuff. - * @todo mixing service level flags and GXS level flag into the same member is - * prone to confusion, use separated members for those things - */ -static const uint32_t RS_GXS_FORUM_MSG_FLAGS_MASK = 0x0000000f; -static const uint32_t RS_GXS_FORUM_MSG_FLAGS_MODERATED = 0x00000001; - -#define IS_FORUM_MSG_MODERATION(flags) (flags & RS_GXS_FORUM_MSG_FLAGS_MODERATED) - - -struct RsGxsForumGroup : RsSerializable, RsGxsGenericGroupData -{ - /** @brief Forum desciption */ - std::string mDescription; - - /** @brief List of forum moderators ids - * @todo run away from TLV old serializables as those types are opaque to - * JSON API! */ - RsTlvGxsIdSet mAdminList; - - /** @brief List of forum pinned posts, those are usually displayed on top - * @todo run away from TLV old serializables as those types are opaque to - * JSON API! */ - RsTlvGxsMsgIdSet mPinnedPosts; - - /// @see RsSerializable - virtual void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override; - - ~RsGxsForumGroup() override; - - /* G10h4ck: We should avoid actual methods in this contexts as they are - * invisible to JSON API */ - bool canEditPosts(const RsGxsId& id) const; -}; - -struct RsGxsForumMsg : RsSerializable -{ - /** @brief Forum post GXS metadata */ - RsMsgMetaData mMeta; - - /** @brief Forum post content */ - std::string mMsg; - - /// @see RsSerializable - virtual void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(mMeta); - RS_SERIAL_PROCESS(mMsg); - } - - ~RsGxsForumMsg() override; -}; - - -enum class RsForumEventCode: uint8_t -{ - UNKNOWN = 0x00, - NEW_FORUM = 0x01, /// emitted when new forum is received - UPDATED_FORUM = 0x02, /// emitted when existing forum is updated - NEW_MESSAGE = 0x03, /// new message reeived in a particular forum - UPDATED_MESSAGE = 0x04, /// existing message has been updated in a particular forum - SUBSCRIBE_STATUS_CHANGED = 0x05, /// forum was subscribed or unsubscribed - READ_STATUS_CHANGED = 0x06, /// msg was read or marked unread - STATISTICS_CHANGED = 0x07, /// suppliers and how many messages they have changed - MODERATOR_LIST_CHANGED = 0x08, /// forum moderation list has changed. - SYNC_PARAMETERS_UPDATED = 0x0a, /// sync and storage times have changed - PINNED_POSTS_CHANGED = 0x0b, /// some posts where pinned or un-pinned - DELETED_FORUM = 0x0c, /// forum was deleted by cleaning - DELETED_POST = 0x0d, /// Post deleted (usually by cleaning) - - /// Distant search result received - DISTANT_SEARCH_RESULT = 0x0e -}; - -struct RsGxsForumEvent: RsEvent -{ - RsGxsForumEvent() - : RsEvent(RsEventType::GXS_FORUMS), - mForumEventCode(RsForumEventCode::UNKNOWN) {} - - RsForumEventCode mForumEventCode; - RsGxsGroupId mForumGroupId; - RsGxsMessageId mForumMsgId; - std::list mModeratorsAdded; - std::list mModeratorsRemoved; - - ///* @see RsEvent @see RsSerializable - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RsEvent::serial_process(j, ctx); - RS_SERIAL_PROCESS(mForumEventCode); - RS_SERIAL_PROCESS(mForumGroupId); - RS_SERIAL_PROCESS(mForumMsgId); - RS_SERIAL_PROCESS(mModeratorsAdded); - RS_SERIAL_PROCESS(mModeratorsRemoved); - } - - ~RsGxsForumEvent() override; -}; - -/** This event is fired once distant search results are received */ -struct RsGxsForumsDistantSearchEvent: RsEvent -{ - RsGxsForumsDistantSearchEvent(): - RsEvent(RsEventType::GXS_FORUMS), - mForumEventCode(RsForumEventCode::DISTANT_SEARCH_RESULT) {} - - RsForumEventCode mForumEventCode; - TurtleRequestId mSearchId; - std::vector mSearchResults; - - ///* @see RsEvent @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RsEvent::serial_process(j, ctx); - - RS_SERIAL_PROCESS(mForumEventCode); - RS_SERIAL_PROCESS(mSearchId); - RS_SERIAL_PROCESS(mSearchResults); - } -}; - -class RsGxsForums: public RsGxsIfaceHelper -{ -public: - explicit RsGxsForums(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {} - virtual ~RsGxsForums(); - - /** - * @brief Create forum. - * @jsonapi{development} - * @param[in] name Name of the forum - * @param[in] description Optional description of the forum - * @param[in] authorId Optional id of the froum owner author - * @param[in] moderatorsIds Optional list of forum moderators - * @param[in] circleType Optional visibility rule, default public. - * @param[in] circleId If the forum is not public specify the id of - * the circle who can see the forum. Depending on - * the value you pass for circleType this should - * be a circle if EXTERNAL is passed, a local - * friends group id if NODES_GROUP is passed, - * empty otherwise. - * @param[out] forumId Optional storage for the id of the created - * forum, meaningful only if creations succeeds. - * @param[out] errorMessage Optional storage for error messsage, meaningful - * only if creation fail. - * @return False on error, true otherwise. - */ - virtual bool createForumV2( - const std::string& name, const std::string& description, - const RsGxsId& authorId = RsGxsId(), - const std::set& moderatorsIds = std::set(), - RsGxsCircleType circleType = RsGxsCircleType::PUBLIC, - const RsGxsCircleId& circleId = RsGxsCircleId(), - RsGxsGroupId& forumId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId), - std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string) - ) = 0; - - /** - * @brief Create a post on the given forum. - * @jsonapi{development} - * @param[in] forumId Id of the forum in which the post is to be - * submitted - * @param[in] title UTF-8 string containing the title of the post - * @param[in] mBody UTF-8 string containing the text of the post - * @param[in] authorId Id of the author of the comment - * @param[in] parentId Optional Id of the parent post if this post is a - * reply to another post, empty otherwise. - * @param[in] origPostId If this is supposed to replace an already - * existent post, the id of the old post. - * If left blank a new post will be created. - * @param[out] postMsgId Optional storage for the id of the created, - * meaningful only on success. - * @param[out] errorMessage Optional storage for error message, meaningful - * only on failure. - * @return false on error, true otherwise - */ - virtual bool createPost( - const RsGxsGroupId& forumId, - const std::string& title, - const std::string& mBody, - const RsGxsId& authorId, - const RsGxsMessageId& parentId = RsGxsMessageId(), - const RsGxsMessageId& origPostId = RsGxsMessageId(), - RsGxsMessageId& postMsgId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId), - std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string) - ) = 0; - - /** - * @brief Edit forum details. - * @jsonapi{development} - * @param[in] forum Forum data (name, description...) with modifications - * @return false on error, true otherwise - */ - virtual bool editForum(RsGxsForumGroup& forum) = 0; - - /** - * @brief Get forums summaries list. Blocking API. - * @jsonapi{development} - * @param[out] forums list where to store the forums summaries - * @return false if something failed, true otherwhise - */ - virtual bool getForumsSummaries(std::list& forums) = 0; - - /** - * @brief returns statistics for the forum service - * @jsonapi{development} - * @param[out] stat statistics struct - * @return false if the call fails - */ - virtual bool getForumServiceStatistics(GxsServiceStatistic& stat) =0; - - /** - * @brief returns statistics about a particular forum - * @jsonapi{development} - * @param[in] forumId Id of the forum - * @param[out] stat statistics struct - * @return false when the object doesn't exist or when the timeout is reached requesting the data - */ - virtual bool getForumStatistics(const RsGxsGroupId& forumId,GxsGroupStatistic& stat)=0; - - - /** - * @brief Get forums information (description, thumbnail...). - * Blocking API. - * @jsonapi{development} - * @param[in] forumIds ids of the forums of which to get the informations - * @param[out] forumsInfo storage for the forums informations - * @return false if something failed, true otherwhise - */ - virtual bool getForumsInfo( - const std::list& forumIds, - std::vector& forumsInfo ) = 0; - - /** - * @brief Get message metadatas for a specific forum. Blocking API - * @jsonapi{development} - * @param[in] forumId id of the forum of which the content is requested - * @param[out] msgMetas storage for the forum messages meta data - * @return false if something failed, true otherwhise - */ - virtual bool getForumMsgMetaData( const RsGxsGroupId& forumId, - std::vector& msgMetas) = 0; - - /** - * @brief Get specific list of messages from a single forum. Blocking API - * @jsonapi{development} - * @param[in] forumId id of the forum of which the content is requested - * @param[in] msgsIds list of message ids to request - * @param[out] msgs storage for the forum messages - * @return false if something failed, true otherwhise - */ - virtual bool getForumContent( - const RsGxsGroupId& forumId, - const std::set& msgsIds, - std::vector& msgs) = 0; - - /** - * @brief Toggle message read status. Blocking API. - * @jsonapi{development} - * @param[in] messageId post identifier - * @param[in] read true to mark as read, false to mark as unread - * @return false on error, true otherwise - */ - virtual bool markRead(const RsGxsGrpMsgIdPair& messageId, bool read) = 0; - - /** - * @brief Subscrbe to a forum. Blocking API - * @jsonapi{development} - * @param[in] forumId Forum id - * @param[in] subscribe true to subscribe, false to unsubscribe - * @return false on error, true otherwise - */ - virtual bool subscribeToForum( const RsGxsGroupId& forumId, - bool subscribe ) = 0; - - /// default base URL used for forums links @see exportForumLink - static const std::string DEFAULT_FORUM_BASE_URL; - - /// Link query field used to store forum name @see exportForumLink - static const std::string FORUM_URL_NAME_FIELD; - - /// Link query field used to store forum id @see exportForumLink - static const std::string FORUM_URL_ID_FIELD; - - /// Link query field used to store forum data @see exportForumLink - static const std::string FORUM_URL_DATA_FIELD; - - /** Link query field used to store forum message title - * @see exportForumLink */ - static const std::string FORUM_URL_MSG_TITLE_FIELD; - - /// Link query field used to store forum message id @see exportForumLink - static const std::string FORUM_URL_MSG_ID_FIELD; - - /** - * @brief Get link to a forum - * @jsonapi{development} - * @param[out] link storage for the generated link - * @param[in] forumId Id of the forum of which we want to generate a link - * @param[in] includeGxsData if true include the forum GXS group data so - * the receiver can subscribe to the forum even if she hasn't received it - * through GXS yet - * @param[in] baseUrl URL into which to sneak in the RetroShare link - * radix, this is primarly useful to induce applications into making the - * link clickable, or to disguise the RetroShare link into a - * "normal" looking web link. If empty the GXS data link will be outputted - * in plain base64 format. - * @param[out] errMsg optional storage for error message, meaningful only in - * case of failure - * @return false if something failed, true otherwhise - */ - virtual bool exportForumLink( - std::string& link, const RsGxsGroupId& forumId, - bool includeGxsData = true, - const std::string& baseUrl = RsGxsForums::DEFAULT_FORUM_BASE_URL, - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - /** - * @brief Import forum from full link - * @param[in] link forum link either in radix or URL format - * @param[out] forumId optional storage for parsed forum id - * @param[out] errMsg optional storage for error message, meaningful only in - * case of failure - * @return false if some error occurred, true otherwise - */ - virtual bool importForumLink( - const std::string& link, - RsGxsGroupId& forumId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId), - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - /** - * @brief Get posts related to the given post. - * If the set is empty, nothing is returned. - * @jsonapi{development} - * @param[in] forumId id of the forum of which the content is requested - * @param[in] parentId id of the post of which child posts (aka replies) - * are requested. - * @param[out] childPosts storage for the child posts - * @return Success or error details - */ - virtual std::error_condition getChildPosts( - const RsGxsGroupId& forumId, const RsGxsMessageId& parentId, - std::vector& childPosts ) = 0; - - /** - * @brief Set keep forever flag on a post so it is not deleted even if older - * then group maximum storage time - * @jsonapi{development} - * @param[in] forumId id of the forum of which the post pertain - * @param[in] postId id of the post on which to set the flag - * @param[in] keepForever true to set the flag, false to unset it - * @return Success or error details - */ - virtual std::error_condition setPostKeepForever( - const RsGxsGroupId& forumId, const RsGxsMessageId& postId, - bool keepForever ) = 0; - - /** - * @brief Get forum content summaries - * @jsonapi{development} - * @param[in] forumId id of the forum of which the content is requested - * @param[in] contentIds ids of requested contents, if empty summaries of - * all messages are reqeusted - * @param[out] summaries storage for summaries - * @return success or error details if something failed - */ - virtual std::error_condition getContentSummaries( - const RsGxsGroupId& forumId, - const std::set& contentIds, - std::vector& summaries ) = 0; - - /** - * @brief Search the whole reachable network for matching forums and - * posts - * @jsonapi{development} - * An @see RsGxsForumsDistantSearchEvent is emitted when matching results - * arrives from the network - * @param[in] matchString string to search into the forum and posts - * @param[out] searchId storage for search id, useful to track search events - * and retrieve search results - * @return success or error details - */ - virtual std::error_condition distantSearchRequest( - const std::string& matchString, TurtleRequestId& searchId ) = 0; - - /** - * @brief Search the local index for matching forums and posts - * @jsonapi{development} - * @param[in] matchString string to search into the index - * @param[out] searchResults storage for searchr esults - * @return success or error details - */ - virtual std::error_condition localSearch( - const std::string& matchString, - std::vector& searchResults ) = 0; - - /** - * @brief Request Synchronization with available peers - * Usually syncronization already happen automatically so be carefull - * to call this method only if necessary. - * It has been thinked for use cases like mobile phone where internet - * connection is intermittent and calling this may be useful when a system - * event about connection being available or about to go offline is received - * @jsonapi{development} - * @return Success or error details - */ - virtual std::error_condition requestSynchronization() = 0; - - //////////////////////////////////////////////////////////////////////////// - /* Following functions are deprecated and should not be considered a stable - * to use API */ - - /** - * @brief Create forum. Blocking API. - * @jsonapi{development} - * @param[inout] forum Forum data (name, description...) - * @return false on error, true otherwise - * @deprecated @see createForumV2 - */ - RS_DEPRECATED_FOR(createForumV2) - virtual bool createForum(RsGxsForumGroup& forum) = 0; - - /** - * @brief Create forum message. Blocking API. - * @jsonapi{development} - * @param[inout] message - * @return false on error, true otherwise - * @deprecated @see createPost - */ - RS_DEPRECATED_FOR(createPost) - virtual bool createMessage(RsGxsForumMsg& message) = 0; - - /* Specific Service Data */ - RS_DEPRECATED_FOR("getForumsSummaries, getForumsInfo") - virtual bool getGroupData(const uint32_t &token, std::vector &groups) = 0; - RS_DEPRECATED_FOR(getForumContent) - virtual bool getMsgData(const uint32_t &token, std::vector &msgs) = 0; - RS_DEPRECATED_FOR(markRead) - virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) = 0; - RS_DEPRECATED_FOR(createForum) - virtual bool createGroup(uint32_t &token, RsGxsForumGroup &group) = 0; - RS_DEPRECATED_FOR(createMessage) - virtual bool createMsg(uint32_t &token, RsGxsForumMsg &msg) = 0; - RS_DEPRECATED_FOR(editForum) - virtual bool updateGroup(uint32_t &token, const RsGxsForumGroup &group) = 0; -}; diff --git a/libretroshare/src/retroshare/rsgxsiface.h b/libretroshare/src/retroshare/rsgxsiface.h deleted file mode 100644 index eca8b009e..000000000 --- a/libretroshare/src/retroshare/rsgxsiface.h +++ /dev/null @@ -1,381 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgxsiface.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Christopher Evi-Parker * - * Copyright (C) 2019-2021 Gioacchino Mazzurco * - * Copyright (C) 2019-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include "retroshare/rsreputations.h" -#include "retroshare/rsgxsservice.h" -#include "gxs/rsgxsdata.h" -#include "retroshare/rsgxsifacetypes.h" -#include "util/rsdeprecate.h" -#include "serialiser/rsserializable.h" -#include "rsitems/rsserviceids.h" -#include "retroshare/rsevents.h" - -/*! - * This structure is used to transport GXS search results. - * It contains the group information as well as a context string to tell where - * the information was found. - * Keep it small as to make search responses as light as possible. - * It differs from RsGxsGroupSearchResults because it supports also results from - * message matches not just groups. - */ -struct RsGxsSearchResult : RsSerializable -{ - RsGxsSearchResult(): mPublishTs(0) {} - - /** Id of the group which match*/ - RsGxsGroupId mGroupId; - - /** Title of the group which match */ - std::string mGroupName; - - /** Optional message id if the search match is against a message */ - RsGxsMessageId mMsgId; - - /** Optional message title if the search match is against a message */ - std::string mMsgName; - - /** Author id of the element which matched (group or message) */ - RsGxsId mAuthorId; - - /** Publish timestamp of the element which matched (group or message) */ - rstime_t mPublishTs; - - /** A snippet of content around the exact match */ - std::string mSearchContext; - - /// @see RsSerializable::serial_process - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(mGroupId); - RS_SERIAL_PROCESS(mGroupName); - RS_SERIAL_PROCESS(mMsgId); - RS_SERIAL_PROCESS(mMsgName); - RS_SERIAL_PROCESS(mAuthorId); - RS_SERIAL_PROCESS(mPublishTs); - RS_SERIAL_PROCESS(mSearchContext); - } - - virtual ~RsGxsSearchResult() = default; -}; - -/*! - * This structure is used to transport group summary information when a GXS - * service is searched. It contains the group information as well as a context - * string to tell where the information was found. It is more compact than a - * GroupMeta object, so as to make search responses as light as possible. - */ -struct RS_DEPRECATED_FOR(RsGxsSearchResult) -RsGxsGroupSummary : RsSerializable -{ - RsGxsGroupSummary() : - mPublishTs(0), mNumberOfMessages(0),mLastMessageTs(0), - mSignFlags(0),mPopularity(0) {} - - RsGxsGroupId mGroupId; - std::string mGroupName; - RsGxsId mAuthorId; - rstime_t mPublishTs; - uint32_t mNumberOfMessages; - rstime_t mLastMessageTs; - uint32_t mSignFlags; - uint32_t mPopularity; - - std::string mSearchContext; - - /// @see RsSerializable::serial_process - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(mGroupId); - RS_SERIAL_PROCESS(mGroupName); - RS_SERIAL_PROCESS(mAuthorId); - RS_SERIAL_PROCESS(mPublishTs); - RS_SERIAL_PROCESS(mNumberOfMessages); - RS_SERIAL_PROCESS(mLastMessageTs); - RS_SERIAL_PROCESS(mSignFlags); - RS_SERIAL_PROCESS(mPopularity); - RS_SERIAL_PROCESS(mSearchContext); - } - - ~RsGxsGroupSummary(); -}; - -/*! - * This structure is used to locally store group search results for a given service. - * It contains the group information as well as a context - * strings to tell where the information was found. It is more compact than a - * GroupMeta object, so as to make search responses as light as possible. - */ -struct RS_DEPRECATED_FOR(RsGxsSearchResult) -RsGxsGroupSearchResults : RsSerializable -{ - /* TODO: This seems exactly the same as RsGxsGroupSummary + mSearchContexts - * do we really need both? */ - - RsGxsGroupSearchResults() - : mPublishTs(0), mNumberOfMessages(0),mLastMessageTs(0), mSignFlags(0),mPopularity(0) - {} - - RsGxsGroupId mGroupId; - std::string mGroupName; - RsGxsId mAuthorId; - rstime_t mPublishTs; - uint32_t mNumberOfMessages; - rstime_t mLastMessageTs; - uint32_t mSignFlags; - uint32_t mPopularity; - - std::set mSearchContexts; - - /// @see RsSerializable::serial_process - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(mGroupId); - RS_SERIAL_PROCESS(mGroupName); - RS_SERIAL_PROCESS(mAuthorId); - RS_SERIAL_PROCESS(mPublishTs); - RS_SERIAL_PROCESS(mNumberOfMessages); - RS_SERIAL_PROCESS(mLastMessageTs); - RS_SERIAL_PROCESS(mSignFlags); - RS_SERIAL_PROCESS(mPopularity); - RS_SERIAL_PROCESS(mSearchContexts); - } - - virtual ~RsGxsGroupSearchResults() = default; -}; - - -/*! - * Stores ids of changed gxs groups and messages. - * It is used to notify about GXS changes. - */ -struct RsGxsChanges : RsEvent -{ - RsGxsChanges(); - - /// Type of the service - RsServiceType mServiceType; - std::map > mMsgs; - std::map > mMsgsMeta; - std::list mGrps; - std::list mGrpsMeta; - std::list mDistantSearchReqs; - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - RsEvent::serial_process(j,ctx); - RS_SERIAL_PROCESS(mServiceType); - RS_SERIAL_PROCESS(mMsgs); - RS_SERIAL_PROCESS(mMsgsMeta); - RS_SERIAL_PROCESS(mGrps); - RS_SERIAL_PROCESS(mGrpsMeta); - RS_SERIAL_PROCESS(mDistantSearchReqs); - } - - RsTokenService* mService; /// Weak pointer, not serialized -}; - -enum class DistantSearchGroupStatus:uint8_t -{ - UNKNOWN = 0x00, // no search ongoing for this group - CAN_BE_REQUESTED = 0x01, // a search result mentions this group, so the group data can be requested - ONGOING_REQUEST = 0x02, // the group data has been requested and the request is pending - HAVE_GROUP_DATA = 0x03, // group data has been received. Group can be subscribed. -}; - -/*! - * All implementations must offer thread safety - */ -struct RsGxsIface -{ - /*! - * \brief serviceType - * \return The 16-bits service type. See @serialiser/rsserviceids.h - */ - virtual uint16_t serviceType() const =0; - -#ifdef TO_REMOVE - /*! - * Gxs services should call this for automatic handling of - * changes, send - * @param changes - */ - virtual void receiveChanges(std::vector& changes) = 0; -#endif - - /*! - * @return handle to token service for this GXS service - */ - virtual RsTokenService* getTokenService() = 0; - - /* Generic Lists */ - - /*! - * Retrieve list of group ids associated to a request token - * @param token token to be redeemed for this request - * @param groupIds the ids return for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getGroupList(const uint32_t &token, - std::list &groupIds) = 0; - - /*! - * Retrieves list of msg ids associated to a request token - * @param token token to be redeemed for this request - * @param msgIds the ids return for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getMsgList(const uint32_t &token, - GxsMsgIdResult& msgIds) = 0; - - /*! - * Retrieves list of msg related ids associated to a request token - * @param token token to be redeemed for this request - * @param msgIds the ids return for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getMsgRelatedList(const uint32_t &token, - MsgRelatedIdResult& msgIds) = 0; - - /*! - * @param token token to be redeemed for group summary request - * @param groupInfo the ids returned for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getGroupMeta(const uint32_t &token, - std::list &groupInfo) = 0; - - /*! - * @param token token to be redeemed for message summary request - * @param msgInfo the message metadata returned for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getMsgMeta(const uint32_t &token, - GxsMsgMetaMap &msgInfo) = 0; - - /*! - * @param token token to be redeemed for message related summary request - * @param msgInfo the message metadata returned for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getMsgRelatedMeta(const uint32_t &token, - GxsMsgRelatedMetaMap &msgInfo) = 0; - - /*! - * subscribes to group, and returns token which can be used - * to be acknowledged to get group Id - * @param token token to redeem for acknowledgement - * @param grpId the id of the group to subscribe to - */ - virtual bool subscribeToGroup(uint32_t& token, const RsGxsGroupId& grpId, bool subscribe) = 0; - - /*! - * This allows the client service to acknowledge that their msgs has - * been created/modified and retrieve the create/modified msg ids - * @param token the token related to modification/create request - * @param msgIds map of grpid->msgIds of message created/modified - * @return true if token exists false otherwise - */ - virtual bool acknowledgeTokenMsg(const uint32_t& token, std::pair& msgId) = 0; - - /*! - * This allows the client service to acknowledge that their grps has - * been created/modified and retrieve the create/modified grp ids - * @param token the token related to modification/create request - * @param msgIds vector of ids of groups created/modified - * @return true if token exists false otherwise - */ - virtual bool acknowledgeTokenGrp(const uint32_t& token, RsGxsGroupId& grpId) = 0; - - /*! - * Gets service statistic for a given services - * @param token value to to retrieve requested stats - * @param stats the status - * @return true if token exists false otherwise - */ - virtual bool getServiceStatistic(const uint32_t& token, GxsServiceStatistic& stats) = 0; - - /*! - * - * @param token to be redeemed - * @param stats the stats associated to token request - * @return true if token is false otherwise - */ - virtual bool getGroupStatistic(const uint32_t& token, GxsGroupStatistic& stats) = 0; - - /*! - * - * @param token value set to be redeemed with acknowledgement - * @param grpId group id for cutoff value to be set - * @param CutOff The cut off value to set - */ - virtual void setGroupReputationCutOff(uint32_t& token, const RsGxsGroupId& grpId, int CutOff) = 0; - - /*! - * @return storage/sync time of messages in secs - */ - virtual uint32_t getDefaultStoragePeriod() = 0; - virtual uint32_t getStoragePeriod(const RsGxsGroupId& grpId) = 0; - virtual void setStoragePeriod(const RsGxsGroupId& grpId,uint32_t age_in_secs) = 0; - - virtual uint32_t getDefaultSyncPeriod() = 0; - virtual uint32_t getSyncPeriod(const RsGxsGroupId& grpId) = 0; - virtual void setSyncPeriod(const RsGxsGroupId& grpId,uint32_t age_in_secs) = 0; - - virtual RsReputationLevel minReputationForForwardingMessages( - uint32_t group_sign_flags,uint32_t identity_flags ) = 0; - - /** - * @brief Export group public data in base64 format - * @jsonapi{development} - * @param[out] radix storage for the generated base64 data - * @param[in] groupId Id of the group of which to output the data - * @param[out] errMsg optional storage for error message, meaningful only in - * case of failure - * @return false if something failed, true otherwhise - */ - virtual bool exportGroupBase64( - std::string& radix, const RsGxsGroupId& groupId, - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - /** - * @brief Import group public data from base64 string - * @param[in] radix group invite in radix format - * @param[out] groupId optional storage for imported group id - * @param[out] errMsg optional storage for error message, meaningful only in - * case of failure - * @return false if some error occurred, true otherwise - */ - virtual bool importGroupBase64( - const std::string& radix, - RsGxsGroupId& groupId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId), - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - virtual ~RsGxsIface(); -}; diff --git a/libretroshare/src/retroshare/rsgxsifacehelper.h b/libretroshare/src/retroshare/rsgxsifacehelper.h deleted file mode 100644 index a6680afc6..000000000 --- a/libretroshare/src/retroshare/rsgxsifacehelper.h +++ /dev/null @@ -1,561 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgxsifacehelper.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2011 Christopher Evi-Parker * - * Copyright (C) 2018-2021 Gioacchino Mazzurco * - * Copyright (C) 2019-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include - -#include "retroshare/rsgxsiface.h" -#include "retroshare/rsservicecontrol.h" -#include "retroshare/rsreputations.h" -#include "rsgxsflags.h" -#include "util/rsdeprecate.h" -#include "util/rsdebug.h" - -/*! - * This class only make method of internal members visible tu upper level to - * offer a more friendly API. - * This is just a workaround to awkward GXS API design, do not take it as an - * example for your coding. - * To properly fix the API design many changes with the implied chain reactions - * are necessary, so at this point this workaround seems acceptable. - */ - -//================================== -// #define DEBUG_GXSIFACEHELPER 1 -//================================== - -enum class TokenRequestType: uint8_t -{ - __NONE = 0x00, /// Used to detect uninitialized - GROUP_DATA = 0x01, - GROUP_META = 0x02, - GROUP_IDS = 0x03, - POSTS = 0x04, - ALL_POSTS = 0x05, - MSG_RELATED_INFO = 0x06, - GROUP_STATISTICS = 0x07, - SERVICE_STATISTICS = 0x08, - NO_KILL_TYPE = 0x09, - __MAX /// Used to detect out of range -}; - -class RsGxsIfaceHelper -{ -public: - /*! - * @param gxs handle to RsGenExchange instance of service (Usually the - * service class itself) - */ - explicit RsGxsIfaceHelper(RsGxsIface& gxs) : - mGxs(gxs), mTokenService(*gxs.getTokenService()), mMtx("GxsIfaceHelper") - {} - - ~RsGxsIfaceHelper() = default; - -#ifdef TO_REMOVE - /*! - * Gxs services should call this for automatic handling of - * changes, send - * @param changes - */ - void receiveChanges(std::vector &changes) - { - mGxs.receiveChanges(changes); - } -#endif - - /* Generic Lists */ - - /*! - * Retrieve list of group ids associated to a request token - * @param token token to be redeemed for this request - * @param groupIds the ids return for given request token - * @return false if request token is invalid, check token status for error report - */ - bool getGroupList(const uint32_t &token, std::list &groupIds) - { - return mGxs.getGroupList(token, groupIds); - } - - /*! - * Retrieves list of msg ids associated to a request token - * @param token token to be redeemed for this request - * @param msgIds the ids return for given request token - * @return false if request token is invalid, check token status for error report - */ - bool getMsgList(const uint32_t &token, - GxsMsgIdResult& msgIds) - { - return mGxs.getMsgList(token, msgIds); - } - - /*! - * Retrieves list of msg related ids associated to a request token - * @param token token to be redeemed for this request - * @param msgIds the ids return for given request token - * @return false if request token is invalid, check token status for error report - */ - bool getMsgRelatedList(const uint32_t &token, MsgRelatedIdResult &msgIds) - { - return mGxs.getMsgRelatedList(token, msgIds); - } - - /*! - * @param token token to be redeemed for group summary request - * @param groupInfo the ids returned for given request token - * @return false if request token is invalid, check token status for error report - */ - bool getGroupSummary(const uint32_t &token, std::list &groupInfo) - { - return mGxs.getGroupMeta(token, groupInfo); - } - - /*! - * @param token token to be redeemed for message summary request - * @param msgInfo the message metadata returned for given request token - * @return false if request token is invalid, check token status for error report - */ - bool getMsgSummary(const uint32_t &token, GxsMsgMetaMap &msgInfo) - { - return mGxs.getMsgMeta(token, msgInfo); - } - - /*! - * @param token token to be redeemed for message related summary request - * @param msgInfo the message metadata returned for given request token - * @return false if request token is invalid, check token status for error report - */ - bool getMsgRelatedSummary(const uint32_t &token, GxsMsgRelatedMetaMap &msgInfo) - { - return mGxs.getMsgRelatedMeta(token, msgInfo); - } - - /*! - * subscribes to group, and returns token which can be used - * to be acknowledged to get group Id - * @param token token to redeem for acknowledgement - * @param grpId the id of the group to subscribe to - */ - bool subscribeToGroup(uint32_t& token, const RsGxsGroupId& grpId, bool subscribe) - { - return mGxs.subscribeToGroup(token, grpId, subscribe); - } - - /*! - * This allows the client service to acknowledge that their msgs has - * been created/modified and retrieve the create/modified msg ids - * @param token the token related to modification/create request - * @param msgIds map of grpid->msgIds of message created/modified - * @return true if token exists false otherwise - */ - bool acknowledgeMsg(const uint32_t& token, std::pair& msgId) - { - return mGxs.acknowledgeTokenMsg(token, msgId); - } - - /*! - * This allows the client service to acknowledge that their grps has - * been created/modified and retrieve the create/modified grp ids - * @param token the token related to modification/create request - * @param msgIds vector of ids of groups created/modified - * @return true if token exists false otherwise - */ - bool acknowledgeGrp(const uint32_t& token, RsGxsGroupId& grpId) - { - return mGxs.acknowledgeTokenGrp(token, grpId); - } - - /*! - * Gets service statistic for a given services - * @param token value to to retrieve requested stats - * @param stats the status - * @return true if token exists false otherwise - */ - bool getServiceStatistic(const uint32_t& token, GxsServiceStatistic& stats) - { - return mGxs.getServiceStatistic(token, stats); - } - - /*! - * - * @param token to be redeemed - * @param stats the stats associated to token request - * @return true if token is false otherwise - */ - bool getGroupStatistic(const uint32_t& token, GxsGroupStatistic& stats) - { - return mGxs.getGroupStatistic(token, stats); - } - - /*! - * @brief Get default maximum storage time for GXS messages - * @jsonapi{development} - * @return storage time in seconds - */ - uint32_t getDefaultStoragePeriod() - { return mGxs.getDefaultStoragePeriod(); } - - /*! - * @brief Get maximum storage time of GXS messages for the given group - * @jsonapi{development} - * @param[in] groupId Id of the group - * @return storage time in seconds - */ - uint32_t getStoragePeriod(const RsGxsGroupId& groupId) - { return mGxs.getStoragePeriod(groupId); } - - /*! - * @brief Set GXS messages maximum storage time for the given group - * @jsonapi{development} - * @param[in] groupId Id of the group - * @param[in] storageSecs storage time in seconds - */ - void setStoragePeriod(const RsGxsGroupId& groupId, uint32_t storageSecs) - { mGxs.setStoragePeriod(groupId, storageSecs); } - - /*! - * @brief Get default maximum syncronization age for GXS messages - * @jsonapi{development} - * @return age in seconds - */ - uint32_t getDefaultSyncPeriod() - { return mGxs.getDefaultSyncPeriod(); } - - /*! - * @brief Get maximum syncronization age of GXS messages for the given group - * @jsonapi{development} - * @param[in] groupId Id of the group - * @return age in seconds - */ - uint32_t getSyncPeriod(const RsGxsGroupId& groupId) - { return mGxs.getSyncPeriod(groupId); } - - /*! - * @brief Set GXS messages maximum syncronization age for the given group - * @jsonapi{development} - * @param[in] groupId Id of the group - * @param[in] syncAge age in seconds - */ - void setSyncPeriod(const RsGxsGroupId& groupId, uint32_t syncAge) - { mGxs.setSyncPeriod(groupId, syncAge); } - - /*! - * This determines the reputation threshold messages need to surpass in order - * for it to be accepted by local user from remote source - * NOTE: threshold only enforced if service require author signature - * @param token value set to be redeemed with acknowledgement - * @param grpId group id for cutoff value to be set - * @param CutOff The cut off value to set - */ - void setGroupReputationCutOff(uint32_t& token, const RsGxsGroupId& grpId, int CutOff) - { - return mGxs.setGroupReputationCutOff(token, grpId, CutOff); - } - - RsReputationLevel minReputationForForwardingMessages( - uint32_t group_sign_flags, uint32_t identity_flags ) - { - return mGxs.minReputationForForwardingMessages(group_sign_flags,identity_flags); - } - - /// @see RsTokenService::requestGroupInfo - bool requestGroupInfo( uint32_t& token, const RsTokReqOptions& opts, const std::list &groupIds, bool high_priority_request = false ) - { - TokenRequestType token_request_type; - - switch(opts.mReqType) - { - case GXS_REQUEST_TYPE_GROUP_DATA: token_request_type = TokenRequestType::GROUP_DATA; break; - case GXS_REQUEST_TYPE_GROUP_META: token_request_type = TokenRequestType::GROUP_META; break; - case GXS_REQUEST_TYPE_GROUP_IDS: token_request_type = TokenRequestType::GROUP_IDS; break; - default: - RsErr() << __PRETTY_FUNCTION__ << "(EE) Unexpected request type " << opts.mReqType << "!!" << std::endl; - return false; - } - - cancelActiveRequestTokens(token_request_type); - - if( mTokenService.requestGroupInfo(token, 0, opts, groupIds)) - { - RS_STACK_MUTEX(mMtx); - mActiveTokens[token]=high_priority_request? (TokenRequestType::NO_KILL_TYPE) : token_request_type; -#ifdef DEBUG_GXSIFACEHELPER - locked_dumpTokens(); -#endif - return true; - } - else - return false; - } - - /// @see RsTokenService::requestGroupInfo - bool requestGroupInfo(uint32_t& token, const RsTokReqOptions& opts, bool high_priority_request = false) - { - TokenRequestType token_request_type; - - switch(opts.mReqType) - { - case GXS_REQUEST_TYPE_GROUP_DATA: token_request_type = TokenRequestType::GROUP_DATA; break; - case GXS_REQUEST_TYPE_GROUP_META: token_request_type = TokenRequestType::GROUP_META; break; - case GXS_REQUEST_TYPE_GROUP_IDS: token_request_type = TokenRequestType::GROUP_IDS; break; - default: - RsErr() << __PRETTY_FUNCTION__ << "(EE) Unexpected request type " << opts.mReqType << "!!" << std::endl; - return false; - } - - cancelActiveRequestTokens(token_request_type); - - - if( mTokenService.requestGroupInfo(token, 0, opts)) - { - RS_STACK_MUTEX(mMtx); - mActiveTokens[token]=high_priority_request? (TokenRequestType::NO_KILL_TYPE) : token_request_type; -#ifdef DEBUG_GXSIFACEHELPER - locked_dumpTokens(); -#endif - return true; - } - else - return false; - } - - /// @see RsTokenService::requestMsgInfo - bool requestMsgInfo( uint32_t& token, const RsTokReqOptions& opts, const GxsMsgReq& msgIds ) - { - if(mTokenService.requestMsgInfo(token, 0, opts, msgIds)) - { - RS_STACK_MUTEX(mMtx); - - mActiveTokens[token]= (msgIds.size()==1 && msgIds.begin()->second.size()==0) ?(TokenRequestType::ALL_POSTS):(TokenRequestType::POSTS); -#ifdef DEBUG_GXSIFACEHELPER - locked_dumpTokens(); -#endif - return true; - } - else - return false; - } - - /// @see RsTokenService::requestMsgInfo - bool requestMsgInfo( uint32_t& token, const RsTokReqOptions& opts, const std::list& grpIds ) - { - if(mTokenService.requestMsgInfo(token, 0, opts, grpIds)) - { - RS_STACK_MUTEX(mMtx); - mActiveTokens[token]=TokenRequestType::ALL_POSTS; -#ifdef DEBUG_GXSIFACEHELPER - locked_dumpTokens(); -#endif - return true; - } - else - return false; - } - - /// @see RsTokenService::requestMsgRelatedInfo - bool requestMsgRelatedInfo( - uint32_t& token, const RsTokReqOptions& opts, - const std::vector& msgIds ) - { - if( mTokenService.requestMsgRelatedInfo(token, 0, opts, msgIds)) - { - RS_STACK_MUTEX(mMtx); - mActiveTokens[token]=TokenRequestType::MSG_RELATED_INFO; -#ifdef DEBUG_GXSIFACEHELPER - locked_dumpTokens(); -#endif - return true; - } - else - return false; - } - - /** - * @jsonapi{development} - * @param[in] token - */ - RsTokenService::GxsRequestStatus requestStatus(uint32_t token) - { return mTokenService.requestStatus(token); } - - /// @see RsTokenService::requestServiceStatistic - bool requestServiceStatistic(uint32_t& token) - { - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_SERVICE_STATS; - - mTokenService.requestServiceStatistic(token,opts); - - RS_STACK_MUTEX(mMtx); - mActiveTokens[token]=TokenRequestType::SERVICE_STATISTICS; - -#ifdef DEBUG_GXSIFACEHELPER - locked_dumpTokens(); -#endif - return true; - } - - /// @see RsTokenService::requestGroupStatistic - bool requestGroupStatistic(uint32_t& token, const RsGxsGroupId& grpId) - { - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_STATS; - - mTokenService.requestGroupStatistic(token, grpId,opts); - - RS_STACK_MUTEX(mMtx); - mActiveTokens[token]=TokenRequestType::GROUP_STATISTICS; -#ifdef DEBUG_GXSIFACEHELPER - locked_dumpTokens(); -#endif - return true; - } - - bool cancelActiveRequestTokens(TokenRequestType type) - { - RS_STACK_MUTEX(mMtx); - for(auto it = mActiveTokens.begin();it!=mActiveTokens.end();) - if(it->second == type) - { - mTokenService.cancelRequest(it->first); - it = mActiveTokens.erase(it); - } - else - ++it; - - return true; - } - - /// @see RsTokenService::cancelRequest - bool cancelRequest(uint32_t token) - { - { - RS_STACK_MUTEX(mMtx); - mActiveTokens.erase(token); - } - return mTokenService.cancelRequest(token); - } - - /** - * @deprecated - * Token service methods are already exposed by this helper, so you should - * not need to get token service pointer directly anymore. - */ - RS_DEPRECATED RsTokenService* getTokenService() { return &mTokenService; } - -protected: - /** - * Block caller while request is being processed. - * Useful for blocking API implementation. - * @param[in] token token associated to the request caller is waiting for - * @param[in] maxWait maximum waiting time in milliseconds - * @param[in] checkEvery time in millisecond between status checks - * @param[in] auto_delete_if_unsuccessful delete the request when it fails. This avoid leaving useless pending requests in the queue that would slow down additional calls. - */ - RsTokenService::GxsRequestStatus waitToken( - uint32_t token, - std::chrono::milliseconds maxWait = std::chrono::milliseconds(20000), - std::chrono::milliseconds checkEvery = std::chrono::milliseconds(100), - bool auto_delete_if_unsuccessful=true) - { -#if defined(__ANDROID__) && (__ANDROID_API__ < 24) - auto wkStartime = std::chrono::steady_clock::now(); - int maxWorkAroundCnt = 10; -LLwaitTokenBeginLabel: -#endif - auto timeout = std::chrono::steady_clock::now() + maxWait; - auto st = requestStatus(token); - - while( !(st == RsTokenService::FAILED || st >= RsTokenService::COMPLETE) - && std::chrono::steady_clock::now() < timeout ) - { - std::this_thread::sleep_for(checkEvery); - st = requestStatus(token); - } - if(st != RsTokenService::COMPLETE && auto_delete_if_unsuccessful) - cancelRequest(token); - -#if defined(__ANDROID__) && (__ANDROID_API__ < 24) - /* Work around for very slow/old android devices, we don't expect this - * to be necessary on newer devices. If it take unreasonably long - * something worser is already happening elsewere and we return anyway. - */ - if( st > RsTokenService::FAILED && st < RsTokenService::COMPLETE - && maxWorkAroundCnt-- > 0 ) - { - maxWait *= 10; - checkEvery *= 3; - Dbg3() << __PRETTY_FUNCTION__ << " Slow Android device " - << " workaround st: " << st - << " maxWorkAroundCnt: " << maxWorkAroundCnt - << " maxWait: " << maxWait.count() - << " checkEvery: " << checkEvery.count() << std::endl; - goto LLwaitTokenBeginLabel; - } - Dbg3() << __PRETTY_FUNCTION__ << " lasted: " - << std::chrono::duration_cast( - std::chrono::steady_clock::now() - wkStartime ).count() - << "ms" << std::endl; - -#endif - - { - RS_STACK_MUTEX(mMtx); - mActiveTokens.erase(token); - } - - return st; - } - -private: - RsGxsIface& mGxs; - RsTokenService& mTokenService; - RsMutex mMtx; - - std::map mActiveTokens; - -#ifdef DEBUG_GXSIFACEHELPER - void locked_dumpTokens() - { - const uint16_t service_id = mGxs.serviceType(); - const auto countSize = static_cast(TokenRequestType::__MAX); - uint32_t count[countSize] = {0}; - - RsDbg rsdbg; - rsdbg << __PRETTY_FUNCTION__ << " Service 0x" << std::hex << service_id - << " (" << rsServiceControl->getServiceName( - RsServiceInfo::RsServiceInfoUIn16ToFullServiceId(service_id) ) - << ") this=0x" << static_cast(this) - << ") Active tokens (per type): "; - - // let's count how many token of each type we've got. - for(auto& it: mActiveTokens) ++count[static_cast(it.second)]; - - for(uint32_t i=0; i < countSize; ++i) - rsdbg /* << i << ":" */ << count[i] << " "; - } -#endif // def DEBUG_GXSIFACEHELPER - - RS_SET_CONTEXT_DEBUG_LEVEL(1) -}; diff --git a/libretroshare/src/retroshare/rsgxsifacetypes.h b/libretroshare/src/retroshare/rsgxsifacetypes.h deleted file mode 100644 index d6232a0d6..000000000 --- a/libretroshare/src/retroshare/rsgxsifacetypes.h +++ /dev/null @@ -1,309 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgxsifacetypes.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2013 crispy * - * Copyright (C) 2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RSGXSIFACETYPES_H_ -#define RSGXSIFACETYPES_H_ - -#include -#include -#include -#include - -#include "retroshare/rstypes.h" -#include "retroshare/rsids.h" -#include "serialiser/rsserializable.h" -#include "serialiser/rstypeserializer.h" -#include "util/rstime.h" - -typedef std::map > GxsMsgIdResult; -typedef std::pair RsGxsGrpMsgIdPair; -typedef std::map > MsgRelatedIdResult; -typedef std::map > GxsMsgReq; - -struct RsMsgMetaData; - -typedef std::map > MsgMetaResult; - -enum class GxsRequestPriority { - VERY_HIGH = 0x00, - HIGH = 0x01, - NORMAL = 0x02, - LOW = 0x03, - VERY_LOW = 0x04, -}; - -class RsGxsGrpMetaData; -class RsGxsMsgMetaData; - -struct RsGroupMetaData : RsSerializable -{ - // (csoler) The correct default value to be used in mCircleType is GXS_CIRCLE_TYPE_PUBLIC, which is defined in rsgxscircles.h, - // but because of a loop in the includes, I cannot include it here. So I replaced with its current value 0x0001. - - RsGroupMetaData() : mGroupFlags(0), mSignFlags(0), mPublishTs(0), - mCircleType(0x0001), mAuthenFlags(0), mSubscribeFlags(0), mPop(0), - mVisibleMsgCount(0), mLastPost(0), mGroupStatus(0) {} - - virtual ~RsGroupMetaData() = default; - - void operator =(const RsGxsGrpMetaData& rGxsMeta); - RsGroupMetaData(const RsGxsGrpMetaData& rGxsMeta) { operator=(rGxsMeta); } - - RsGxsGroupId mGroupId; - std::string mGroupName; - uint32_t mGroupFlags; // Combination of FLAG_PRIVACY_PRIVATE | FLAG_PRIVACY_RESTRICTED | FLAG_PRIVACY_PUBLIC: diffusion - uint32_t mSignFlags; // Combination of RSGXS_GROUP_SIGN_PUBLISH_MASK & RSGXS_GROUP_SIGN_AUTHOR_MASK, i.e. what signatures are required for parent and child msgs - - rstime_t mPublishTs; // Mandatory. - RsGxsId mAuthorId; // Author of the group. Left to "000....0" if anonymous - - // for circles - RsGxsCircleId mCircleId; // Id of the circle to which the group is restricted - uint32_t mCircleType; // combination of CIRCLE_TYPE_{ PUBLIC,EXTERNAL,YOUR_FRIENDS_ONLY,LOCAL,EXT_SELF,YOUR_EYES_ONLY } - - // other stuff. - uint32_t mAuthenFlags; // Actually not used yet. - RsGxsGroupId mParentGrpId; - - // BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG. - - uint32_t mSubscribeFlags; - - uint32_t mPop; // Popularity = number of friend subscribers - uint32_t mVisibleMsgCount; // Max messages reported by friends - rstime_t mLastPost; // Timestamp for last message. Not used yet. - rstime_t mLastSeen; // Last time the group was advertised by friends. - - uint32_t mGroupStatus; - - /// Service Specific Free-Form local (non-synced) extra storage. - std::string mServiceString; - RsPeerId mOriginator; - RsGxsCircleId mInternalCircle; - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(mGroupId); - RS_SERIAL_PROCESS(mGroupName); - RS_SERIAL_PROCESS(mGroupFlags); - RS_SERIAL_PROCESS(mSignFlags); - RS_SERIAL_PROCESS(mPublishTs); - RS_SERIAL_PROCESS(mAuthorId); - RS_SERIAL_PROCESS(mCircleId); - RS_SERIAL_PROCESS(mCircleType); - RS_SERIAL_PROCESS(mAuthenFlags); - RS_SERIAL_PROCESS(mParentGrpId); - RS_SERIAL_PROCESS(mSubscribeFlags); - RS_SERIAL_PROCESS(mPop); - RS_SERIAL_PROCESS(mVisibleMsgCount); - RS_SERIAL_PROCESS(mLastPost); - RS_SERIAL_PROCESS(mGroupStatus); - RS_SERIAL_PROCESS(mServiceString); - RS_SERIAL_PROCESS(mOriginator); - RS_SERIAL_PROCESS(mInternalCircle); - } -}; - -// This is the parent class of all interface-level GXS group data. Derived classes -// will include service-specific information, such as icon, description, etc - -struct RsGxsGenericGroupData -{ - virtual ~RsGxsGenericGroupData() = default; // making the type polymorphic - - RsGroupMetaData mMeta; -}; - -struct RsMsgMetaData : RsSerializable -{ - RsMsgMetaData() : mPublishTs(0), mMsgFlags(0), mMsgStatus(0), mChildTs(0) {} - - virtual ~RsMsgMetaData() {} - - void operator =(const RsGxsMsgMetaData& rGxsMeta); - RsMsgMetaData(const RsGxsMsgMetaData& rGxsMeta) { operator=(rGxsMeta); } - - RsGxsGroupId mGroupId; - RsGxsMessageId mMsgId; - - RsGxsMessageId mThreadId; - RsGxsMessageId mParentId; - RsGxsMessageId mOrigMsgId; - - RsGxsId mAuthorId; - - std::string mMsgName; - rstime_t mPublishTs; - - /** the lower 16 bits for service, upper 16 bits for GXS - * @todo mixing service level flags and GXS level flag into the same member - * is prone to confusion, use separated members for those things, this could - * be done without breaking network retro-compatibility */ - uint32_t mMsgFlags; - - // BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG. - // normally READ / UNREAD flags. LOCAL Data. - - /** the first 16 bits for service, last 16 for GXS - * @todo mixing service level flags and GXS level flag into the same member - * is prone to confusion, use separated members for those things, this could - * be done without breaking network retro-compatibility */ - uint32_t mMsgStatus; - - rstime_t mChildTs; - std::string mServiceString; // Service Specific Free-Form extra storage. - - /// @see RsSerializable - virtual void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(mGroupId); - RS_SERIAL_PROCESS(mMsgId); - RS_SERIAL_PROCESS(mThreadId); - RS_SERIAL_PROCESS(mParentId); - RS_SERIAL_PROCESS(mOrigMsgId); - RS_SERIAL_PROCESS(mAuthorId); - RS_SERIAL_PROCESS(mMsgName); - RS_SERIAL_PROCESS(mPublishTs); - RS_SERIAL_PROCESS(mMsgFlags); - RS_SERIAL_PROCESS(mMsgStatus); - RS_SERIAL_PROCESS(mChildTs); - RS_SERIAL_PROCESS(mServiceString); - } -}; - -struct RsGxsGenericMsgData -{ - virtual ~RsGxsGenericMsgData() = default; // making the type polymorphic - - RsMsgMetaData mMeta; -}; - - -struct GxsGroupStatistic : RsSerializable -{ - GxsGroupStatistic() : - mNumMsgs(0), mTotalSizeOfMsgs(0), mNumThreadMsgsNew(0), - mNumThreadMsgsUnread(0), mNumChildMsgsNew(0), mNumChildMsgsUnread(0) {} - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(mGrpId); - RS_SERIAL_PROCESS(mNumMsgs); - RS_SERIAL_PROCESS(mTotalSizeOfMsgs); - RS_SERIAL_PROCESS(mNumThreadMsgsNew); - RS_SERIAL_PROCESS(mNumThreadMsgsUnread); - RS_SERIAL_PROCESS(mNumChildMsgsNew); - RS_SERIAL_PROCESS(mNumChildMsgsUnread); - - } - - RsGxsGroupId mGrpId; - uint32_t mNumMsgs; /// number of message, from the database - uint32_t mTotalSizeOfMsgs; - uint32_t mNumThreadMsgsNew; - uint32_t mNumThreadMsgsUnread; - uint32_t mNumChildMsgsNew; - uint32_t mNumChildMsgsUnread; - - ~GxsGroupStatistic() override; -}; - -struct GxsServiceStatistic : RsSerializable -{ - GxsServiceStatistic() : - mNumMsgs(0), mNumGrps(0), mSizeOfMsgs(0), mSizeOfGrps(0), - mNumGrpsSubscribed(0), mNumThreadMsgsNew(0), mNumThreadMsgsUnread(0), - mNumChildMsgsNew(0), mNumChildMsgsUnread(0), mSizeStore(0) {} - - uint32_t mNumMsgs; - uint32_t mNumGrps; - uint32_t mSizeOfMsgs; - uint32_t mSizeOfGrps; - uint32_t mNumGrpsSubscribed; - uint32_t mNumThreadMsgsNew; - uint32_t mNumThreadMsgsUnread; - uint32_t mNumChildMsgsNew; - uint32_t mNumChildMsgsUnread; - uint32_t mSizeStore; - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(mNumMsgs); - RS_SERIAL_PROCESS(mNumGrps); - RS_SERIAL_PROCESS(mSizeOfMsgs); - RS_SERIAL_PROCESS(mSizeOfGrps); - RS_SERIAL_PROCESS(mNumGrpsSubscribed); - RS_SERIAL_PROCESS(mNumThreadMsgsNew); - RS_SERIAL_PROCESS(mNumThreadMsgsUnread); - RS_SERIAL_PROCESS(mNumChildMsgsNew); - RS_SERIAL_PROCESS(mNumChildMsgsUnread); - RS_SERIAL_PROCESS(mSizeStore); - } - - ~GxsServiceStatistic() override; -}; - -class RS_DEPRECATED RsGxsGroupUpdateMeta -{ -public: - - // expand as support is added for other utypes - enum UpdateType { DESCRIPTION, NAME }; - - explicit RsGxsGroupUpdateMeta(const RsGxsGroupId& groupId): - mGroupId(groupId) {} - - typedef std::map GxsMetaUpdate; - - /*! - * Only one item of a utype can exist - * @param utype the type of meta update - * @param item update item containing the change value - */ - void setMetaUpdate(UpdateType utype, const std::string& update) - { - mUpdates[utype] = update; - } - - /*! - * @param utype update type to remove - * @return false if update did not exist, true if update successfully removed - */ - bool removeUpdateType(UpdateType utype){ return mUpdates.erase(utype) == 1; } - - const GxsMetaUpdate* getUpdates() const { return &mUpdates; } - const RsGxsGroupId& getGroupId() const { return mGroupId; } - -private: - - GxsMetaUpdate mUpdates; - RsGxsGroupId mGroupId; -}; - -#endif /* RSGXSIFACETYPES_H_ */ diff --git a/libretroshare/src/retroshare/rsgxsservice.h b/libretroshare/src/retroshare/rsgxsservice.h deleted file mode 100644 index 152b018c9..000000000 --- a/libretroshare/src/retroshare/rsgxsservice.h +++ /dev/null @@ -1,37 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgxsservice.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2015 Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RSGXSSERVICE_H -#define RSGXSSERVICE_H - - -#include "retroshare/rsgxsifacetypes.h" -#include "retroshare/rstokenservice.h" - -struct RsMsgMetaData ; -typedef uint32_t TurtleRequestId; - -typedef std::map > GxsMsgMetaMap; -typedef std::map > GxsMsgRelatedMetaMap; - - - -#endif // RSGXSSERVICE_H diff --git a/libretroshare/src/retroshare/rsgxstrans.h b/libretroshare/src/retroshare/rsgxstrans.h deleted file mode 100644 index 8cbb514a6..000000000 --- a/libretroshare/src/retroshare/rsgxstrans.h +++ /dev/null @@ -1,152 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgxstrans.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License version 3 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include "retroshare/rstokenservice.h" -#include "retroshare/rsgxsifacehelper.h" -#include "retroshare/rsgxscommon.h" -#include "rsitems/rsserviceids.h" - -/** Subservices identifiers (like port for TCP) - * @deprecated pay special attention fixing this as it may break - * retro-compatibility */ -enum class RS_DEPRECATED_FOR(RsServiceType) GxsTransSubServices : uint16_t -{ - UNKNOWN = 0x00, - TEST_SERVICE = 0x01, - P3_MSG_SERVICE = 0x02, - P3_CHAT_SERVICE = 0x03 -}; - -/// Values must fit into uint8_t -enum class GxsTransItemsSubtypes : uint8_t -{ - GXS_TRANS_SUBTYPE_MAIL = 0x01, - GXS_TRANS_SUBTYPE_RECEIPT = 0x02, - GXS_TRANS_SUBTYPE_GROUP = 0x03, - OUTGOING_RECORD_ITEM_deprecated = 0x04, - OUTGOING_RECORD_ITEM = 0x05 -}; - -enum class GxsTransSendStatus : uint8_t -{ - UNKNOWN = 0x00, - PENDING_PROCESSING = 0x01, - PENDING_PREFERRED_GROUP = 0x02, - PENDING_RECEIPT_CREATE = 0x03, - PENDING_RECEIPT_SIGNATURE = 0x04, - PENDING_SERIALIZATION = 0x05, - PENDING_PAYLOAD_CREATE = 0x06, - PENDING_PAYLOAD_ENCRYPT = 0x07, - PENDING_PUBLISH = 0x08, - /** This will be useful so the user can know if the mail reached at least - * some friend node, in case of internet connection interruption */ - //PENDING_TRANSFER, - PENDING_RECEIPT_RECEIVE = 0x09, - /// Records with status >= RECEIPT_RECEIVED get deleted - RECEIPT_RECEIVED = 0x0a, - FAILED_RECEIPT_SIGNATURE = 0xf0, - FAILED_ENCRYPTION = 0xf1, - FAILED_TIMED_OUT = 0xf2 -}; - -typedef uint64_t RsGxsTransId; - -class RsGxsTransGroup: public RsGxsGenericGroupData -{ -}; - -class RsGxsTransMsg -{ -public: - RsGxsTransMsg() : size(0),data(NULL) {} - virtual ~RsGxsTransMsg() { free(data) ; } - -public: - RsMsgMetaData mMeta; - - uint32_t size ; - uint8_t *data ; -}; - -struct RsGxsTransOutgoingRecord -{ - GxsTransSendStatus status; - RsGxsId recipient; - RsGxsTransId trans_id; - - GxsTransSubServices client_service; - - uint32_t data_size ; - Sha1CheckSum data_hash ; - uint32_t send_TS ; - RsGxsGroupId group_id ; -}; - -class RsGxsTransGroupStatistics: public GxsGroupStatistic -{ -public: - RsGxsTransGroupStatistics() - { - last_publish_TS = 0; - popularity = 0; - subscribed = false; - } - - void addMessageMeta(const RsGxsGroupId& grp,const RsMsgMetaData& meta) - { - messages_metas[meta.mMsgId] = meta ; - last_publish_TS = std::max(last_publish_TS,meta.mPublishTs) ; - mGrpId = grp ; - } - - bool subscribed ; - int popularity ; - - rstime_t last_publish_TS; - - std::map messages_metas ; -}; - - -/// RetroShare GxsTrans asyncronous redundant small mail trasport on top of GXS -/// -class RsGxsTrans: public RsGxsIfaceHelper -{ -public: - class GxsTransStatistics - { - public: - GxsTransStatistics() {} - - RsGxsGroupId prefered_group_id ; - std::vector outgoing_records; - }; - - RsGxsTrans(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {} - - virtual ~RsGxsTrans() {} - - virtual bool getDataStatistics(GxsTransStatistics& stats)=0; - virtual bool getGroupStatistics(std::map& stats) =0; -}; - -extern RsGxsTrans *rsGxsTrans ; diff --git a/libretroshare/src/retroshare/rsgxstunnel.h b/libretroshare/src/retroshare/rsgxstunnel.h deleted file mode 100644 index 125a7c9a9..000000000 --- a/libretroshare/src/retroshare/rsgxstunnel.h +++ /dev/null @@ -1,131 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsgxstunnel.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include "util/rsdir.h" -#include "retroshare/rsids.h" -#include "retroshare/rsturtle.h" -#include "retroshare/rsgxsifacetypes.h" - -class RsGxsTunnelService -{ -public: - enum { - RS_GXS_TUNNEL_ERROR_NO_ERROR = 0x0000, - RS_GXS_TUNNEL_ERROR_UNKNOWN_GXS_ID = 0x0001 - }; - - enum { - RS_GXS_TUNNEL_STATUS_UNKNOWN = 0x00, - RS_GXS_TUNNEL_STATUS_TUNNEL_DN = 0x01, - RS_GXS_TUNNEL_STATUS_CAN_TALK = 0x02, - RS_GXS_TUNNEL_STATUS_REMOTELY_CLOSED = 0x03 - }; - - class RsGxsTunnelClientService - { - public: - // The client should derive this in order to handle notifications from the tunnel service. - // This cannot be ignored because the client needs to know when the tunnel is active. - - virtual void notifyTunnelStatus(const RsGxsTunnelId& tunnel_id,uint32_t tunnel_status) =0; - - // Data obtained from the corresponding GXS id. The memory ownership is transferred to the client, which - // is responsible to free it using free() once used. - - virtual void receiveData(const RsGxsTunnelId& id,unsigned char *data,uint32_t data_size) =0; - - // Used by the creator of the service to supply a pointer to the GXS tunnel service for it to be able to send data etc. - - virtual void connectToGxsTunnelService(RsGxsTunnelService *tunnel_service) =0; - - // Gives feedback about type of data that is allowed in. For security reasons, this always needs to be re-derived (Clients can return true on default) - - virtual bool acceptDataFromPeer(const RsGxsId& gxs_id,const RsGxsTunnelId& tunnel_id,bool am_I_client_side) = 0 ; - }; - - class GxsTunnelInfo - { - public: - // Tunnel information - - RsGxsTunnelId tunnel_id ; - RsGxsId destination_gxs_id ; // GXS Id we're talking to - RsGxsId source_gxs_id ; // GXS Id we're using to talk - uint32_t tunnel_status ; // active, requested, DH pending, etc. - uint32_t total_size_sent ; // total bytes sent through that tunnel since openned (including management). - uint32_t total_size_received ; // total bytes received through that tunnel since openned (including management). - bool is_client_side ; // specifiec wether we are client(managing the tunnel) or server. - - // Data packets - - uint32_t pending_data_packets; // number of packets not acknowledged by other side, still on their way. Should be 0 unless something bad happens. - uint32_t total_data_packets_sent ; // total number of data packets sent (does not include tunnel management) - uint32_t total_data_packets_received ; // total number of data packets received (does not include tunnel management) - }; - - // This is the interface file for the secured tunnel service - // - //===================================================// - // Debugging info // - //===================================================// - - virtual bool getTunnelsInfo(std::vector& infos) =0; - virtual bool getTunnelInfo(const RsGxsTunnelId& tunnel_id,GxsTunnelInfo& info) =0; - - // retrieve the routing probabilities - - //===================================================// - // Communication to other services. // - //===================================================// - - // Register a new client service. The service ID needs to be unique, and it's the coder's resonsibility to use an ID that is not used elsewhere - // for the same purpose. - - virtual bool registerClientService(uint32_t service_id,RsGxsTunnelClientService *service) =0; - - // Asks for a tunnel. The service will request it to turtle router, and exchange a AES key using DH. - // When the tunnel is secured, the client---here supplied as argument---will be notified. He can - // then send data into the tunnel. The same tunnel may be used by different clients. - // The service id is passed on so that the client is notified when the tunnel is up. - - virtual bool requestSecuredTunnel(const RsGxsId& to_id,const RsGxsId& from_id,RsGxsTunnelId& tunnel_id,uint32_t service_id,uint32_t& error_code) =0 ; - - // Data is sent through the established tunnel, possibly multiple times, until reception is acknowledged. If the tunnel does not exist, the item is rejected and - // an error is issued. In any case, the memory ownership of the data is *not* transferred to the tunnel service, so the client should delete it afterwards, if needed. - - virtual bool sendData(const RsGxsTunnelId& tunnel_id, uint32_t client_service_id, const uint8_t *data, uint32_t data_size) =0; - - // Removes any established tunnel to this GXS id. This makes the tunnel refuse further data, but the tunnel will be however kept alive - // until all pending data is flushed. All clients attached to the tunnel will be notified that the tunnel gets closed. - - virtual bool closeExistingTunnel(const RsGxsTunnelId& to_id,uint32_t service_id) =0; - - //===================================================// - // Routage feedback from other services // - //===================================================// - -}; - -// To access the GRouter from anywhere -// -extern RsGxsTunnelService *rsGxsTunnel ; diff --git a/libretroshare/src/retroshare/rshistory.h b/libretroshare/src/retroshare/rshistory.h deleted file mode 100644 index faa649f2d..000000000 --- a/libretroshare/src/retroshare/rshistory.h +++ /dev/null @@ -1,161 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rshistory.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Thunder * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_HISTORY_INTERFACE_H -#define RS_HISTORY_INTERFACE_H - -class RsHistory; -class ChatId; - -extern RsHistory *rsHistory; - -#include -#include -#include -#include "retroshare/rstypes.h" - -//! data object for message history -/*! - * data object used for message history - */ -static const uint32_t RS_HISTORY_TYPE_PUBLIC = 0 ; -static const uint32_t RS_HISTORY_TYPE_PRIVATE = 1 ; -static const uint32_t RS_HISTORY_TYPE_LOBBY = 2 ; -static const uint32_t RS_HISTORY_TYPE_DISTANT = 3 ; - -class HistoryMsg: RsSerializable -{ -public: - HistoryMsg() - { - msgId = 0; - incoming = false; - sendTime = 0; - recvTime = 0; - } - - virtual void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx) override - { - RS_SERIAL_PROCESS(msgId); - RS_SERIAL_PROCESS(chatPeerId); - RS_SERIAL_PROCESS(incoming); - RS_SERIAL_PROCESS(peerId); - RS_SERIAL_PROCESS(peerName); - RS_SERIAL_PROCESS(sendTime); - RS_SERIAL_PROCESS(recvTime); - RS_SERIAL_PROCESS(message); - } - - uint32_t msgId; - RsPeerId chatPeerId; - bool incoming; - RsPeerId peerId; - std::string peerName; - uint32_t sendTime; - uint32_t recvTime; - std::string message; -}; - -//! Interface to retroshare for message history -/*! - * Provides an interface for retroshare's message history functionality - */ -class RsHistory -{ -public: - virtual bool chatIdToVirtualPeerId(const ChatId &chat_id, RsPeerId &peer_id) = 0; - - /*! - * @brief Retrieves the history of messages for a given chatId - * @jsonapi{development} - * @param[in] chatPeerId Chat Id for which the history needs to be retrieved - * @param[out] msgs retrieved messages - * @param[in] loadCount maximum number of messages to get - * @return true if messages can be retrieved, false otherwise. - */ - virtual bool getMessages(const ChatId& chatPeerId, std::list &msgs, uint32_t loadCount) = 0; - - /*! - * @brief Retrieves a specific message from the history - * @jsonapi{development} - * @param[in] msgId Id of the message to get - * @param[out] msg retrieved message - * @return true if message can be retrieved, false otherwise. - */ - virtual bool getMessage(uint32_t msgId, HistoryMsg &msg) = 0; - - /*! - * @brief Remove messages from the history - * @jsonapi{development} - * @param[in] msgIds list of messages to remove - */ - virtual void removeMessages(const std::list& msgIds) = 0; - - /*! - * @brief clears the message history for a given chat peer - * @jsonapi{development} - * @param[in] chatPeerID Id of the chat/peer for which the history needs to be wiped - */ - virtual void clear(const ChatId &chatPeerId) = 0; - - /*! - * @brief Get whether chat history is enabled or not - * @jsonapi{development} - * @param[in] chat_type Type of chat (see list of constants above) - * @return true when the information is available - */ - virtual bool getEnable(uint32_t chat_type) = 0; - - /*! - * @brief Set whether chat history is enabled or not - * @jsonapi{development} - * @param[in] chat_type Type of chat (see list of constants above) - * @param[in] enabled Desired state of the variable - */ - virtual void setEnable(uint32_t chat_type, bool enable) = 0; - - /*! - * @brief Retrieves the maximum storage time period for messages in history - * @return max storage duration of chat. - */ - virtual uint32_t getMaxStorageDuration() = 0; - /*! - * @brief Sets the maximum storage time period for messages in history - * @param[in] seconds max storage duration time in seconds - */ - virtual void setMaxStorageDuration(uint32_t seconds) = 0; - - /*! - * @brief Gets the maximum number of messages to save - * @param[in] chat_type Type of chat for that number limit - * @return maximum number of messages to save - */ - virtual uint32_t getSaveCount(uint32_t chat_type) = 0; - - /*! - * @brief Sets the maximum number of messages to save - * @param[in] chat_type Type of chat for that number limit - * @param[in] count Max umber of messages, 0 meaning indefinitly - */ - virtual void setSaveCount(uint32_t chat_type, uint32_t count) = 0; -}; - -#endif diff --git a/libretroshare/src/retroshare/rsidentity.h b/libretroshare/src/retroshare/rsidentity.h deleted file mode 100644 index 36b1f4bb8..000000000 --- a/libretroshare/src/retroshare/rsidentity.h +++ /dev/null @@ -1,656 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsidentity.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Robert Fernie * - * Copyright (C) 2019-2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -#include "retroshare/rstokenservice.h" -#include "retroshare/rsgxsifacehelper.h" -#include "retroshare/rsreputations.h" -#include "retroshare/rsids.h" -#include "serialiser/rstlvimage.h" -#include "retroshare/rsgxscommon.h" -#include "serialiser/rsserializable.h" -#include "serialiser/rstypeserializer.h" -#include "util/rsdeprecate.h" - -class RsIdentity; - -/** - * Pointer to global instance of RsIdentity service implementation - * @jsonapi{development} - */ -extern RsIdentity* rsIdentity; - - -// GroupFlags: Only one so far: - -// The deprecated flag overlaps the privacy flags for mGroupFlags. This is an error that should be fixed. For the sake of keeping some -// backward compatibility, we need to make the change step by step. - -#define RSGXSID_GROUPFLAG_REALID_kept_for_compatibility 0x0001 -#define RSGXSID_GROUPFLAG_REALID 0x0100 - -// THESE ARE FLAGS FOR INTERFACE. -#define RSID_TYPE_MASK 0xff00 -#define RSID_RELATION_MASK 0x00ff - -#define RSID_TYPE_REALID 0x0100 -#define RSID_TYPE_PSEUDONYM 0x0200 - -#define RSID_RELATION_YOURSELF 0x0001 -#define RSID_RELATION_FRIEND 0x0002 -#define RSID_RELATION_FOF 0x0004 -#define RSID_RELATION_OTHER 0x0008 -#define RSID_RELATION_UNKNOWN 0x0010 - -/// @deprecated remove toghether with RsGxsIdGroup::mRecognTags -#define RSRECOGN_MAX_TAGINFO 5 - -// Unicode symbols. NOT utf-8 bytes, because of multi byte characters -#define RSID_MAXIMUM_NICKNAME_SIZE 30 -#define RSID_MINIMUM_NICKNAME_SIZE 2 - -std::string rsIdTypeToString(uint32_t idtype); - -static const uint32_t RS_IDENTITY_FLAGS_IS_A_CONTACT = 0x0001; -static const uint32_t RS_IDENTITY_FLAGS_PGP_LINKED = 0x0002; -static const uint32_t RS_IDENTITY_FLAGS_PGP_KNOWN = 0x0004; -static const uint32_t RS_IDENTITY_FLAGS_IS_OWN_ID = 0x0008; -static const uint32_t RS_IDENTITY_FLAGS_IS_DEPRECATED= 0x0010; // used to denote keys with deprecated fingerprint format. - -struct GxsReputation : RsSerializable -{ - GxsReputation(); - - bool updateIdScore(bool pgpLinked, bool pgpKnown); - bool update(); /// checks ranges and calculates overall score. - - int32_t mOverallScore; - int32_t mIdScore; /// PGP, Known, etc. - int32_t mOwnOpinion; - int32_t mPeerOpinion; - - /// @see RsSerializable - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(mOverallScore); - RS_SERIAL_PROCESS(mIdScore); - RS_SERIAL_PROCESS(mOwnOpinion); - RS_SERIAL_PROCESS(mPeerOpinion); - } - - ~GxsReputation() override; -}; - - -struct RsGxsIdGroup : RsSerializable -{ - RsGxsIdGroup() : - mLastUsageTS(0), mPgpKnown(false), mIsAContact(false) {} - - RsGroupMetaData mMeta; - - // In GroupMetaData. - //std::string mNickname; (mGroupName) - //std::string mKeyId; (mGroupId) - //uint32_t mIdType; (mGroupFlags) - - // SHA(KeyId + Gpg Fingerprint) -> can only be IDed if GPG known. - // The length of the input must be long enough to make brute force search implausible. - - // Easy to do 1e9 SHA-1 hash computations per second on a GPU. - // We will need a minimum of 256 bits, ideally 1024 bits or 2048 bits. - - // Actually PgpIdHash is SHA1(.mMeta.mGroupId + PGPHandler->GpgFingerprint(ownId)) - // ??? 160 bits. - - Sha1CheckSum mPgpIdHash; - - /** Need a signature as proof - otherwise anyone could add others Hashes. - * This is a string, as the length is variable. - * TODO: Thing like this should actually be a byte array (pointer+size), - * using an std::string breaks the JSON serialization, as a workaround this - * field is ignored by JSON serial operations */ - std::string mPgpIdSign; - - /// Unused - RS_DEPRECATED std::list mRecognTags; - - RsGxsImage mImage; /// Avatar - rstime_t mLastUsageTS; - - bool mPgpLinked; - bool mPgpKnown; - bool mIsAContact; - RsPgpId mPgpId; - GxsReputation mReputation; - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override; - - ~RsGxsIdGroup() override; -}; - -// DATA TYPE FOR EXTERNAL INTERFACE. - -struct RS_DEPRECATED RsRecognTag -{ - RsRecognTag(uint16_t tc, uint16_t tt, bool v) : - tag_class(tc), tag_type(tt), valid(v) {} - - uint16_t tag_class; - uint16_t tag_type; - bool valid; -}; - - -struct RS_DEPRECATED RsRecognTagDetails -{ - RsRecognTagDetails() : - valid_from(0), valid_to(0), tag_class(0), tag_type(0), is_valid(false), - is_pending(false) {} - - rstime_t valid_from; - rstime_t valid_to; - uint16_t tag_class; - uint16_t tag_type; - - std::string signer; - - bool is_valid; - bool is_pending; -}; - - -struct RsIdentityParameters -{ - RsIdentityParameters() : - isPgpLinked(false) {} - - bool isPgpLinked; - std::string nickname; - RsGxsImage mImage; -}; - -struct RsIdentityUsage : RsSerializable -{ - enum UsageCode : uint8_t - { - UNKNOWN_USAGE = 0x00, - - /** These 2 are normally not normal GXS identities, but nothing prevents - * it to happen either. */ - GROUP_ADMIN_SIGNATURE_CREATION = 0x01, - GROUP_ADMIN_SIGNATURE_VALIDATION = 0x02, - - /** Not typically used, since most services do not require group author - * signatures */ - GROUP_AUTHOR_SIGNATURE_CREATION = 0x03, - GROUP_AUTHOR_SIGNATURE_VALIDATION = 0x04, - - /// most common use case. Messages are signed by authors in e.g. forums. - MESSAGE_AUTHOR_SIGNATURE_CREATION = 0x05, - MESSAGE_AUTHOR_SIGNATURE_VALIDATION = 0x06, - - /** Identities are stamped regularly by crawlign the set of messages for - * all groups. That helps keepign the useful identities in hand. */ - GROUP_AUTHOR_KEEP_ALIVE = 0x07, - MESSAGE_AUTHOR_KEEP_ALIVE = 0x08, - - /** Chat lobby msgs are signed, so each time one comes, or a chat lobby - * event comes, a signature verificaiton happens. */ - CHAT_LOBBY_MSG_VALIDATION = 0x09, - - /// Global router message validation - GLOBAL_ROUTER_SIGNATURE_CHECK = 0x0a, - - /// Global router message signature - GLOBAL_ROUTER_SIGNATURE_CREATION = 0x0b, - - GXS_TUNNEL_DH_SIGNATURE_CHECK = 0x0c, - GXS_TUNNEL_DH_SIGNATURE_CREATION = 0x0d, - - /// Identity received through GXS sync - IDENTITY_NEW_FROM_GXS_SYNC = 0x0e, - /// Group update on that identity data. Can be avatar, name, etc. - IDENTITY_NEW_FROM_DISCOVERY = 0x0f, - /// Explicit request to friend - IDENTITY_NEW_FROM_EXPLICIT_REQUEST = 0x10, - - /// Any signature verified for that identity - IDENTITY_GENERIC_SIGNATURE_CHECK = 0x11, - - /// Any signature made by that identity - IDENTITY_GENERIC_SIGNATURE_CREATION = 0x12, - - IDENTITY_GENERIC_ENCRYPTION = 0x13, - IDENTITY_GENERIC_DECRYPTION = 0x14, - CIRCLE_MEMBERSHIP_CHECK = 0x15 - } ; - - RsIdentityUsage( RsServiceType service, - RsIdentityUsage::UsageCode code, - const RsGxsGroupId& gid = RsGxsGroupId(), - const RsGxsMessageId& message_id = RsGxsMessageId(), - const RsGxsMessageId& parent_id = RsGxsMessageId(), - const RsGxsMessageId& thread_id = RsGxsMessageId(), - uint64_t additional_id=0, - const std::string& comment = std::string() ); - - /// Id of the service using that identity, as understood by rsServiceControl - RsServiceType mServiceId; - - /** Specific code to use. Will allow forming the correct translated message - * in the GUI if necessary. */ - UsageCode mUsageCode; - - /// Group ID using the identity - RsGxsGroupId mGrpId; - - /// Message ID using the identity - RsGxsMessageId mMsgId; - - /// Reference message ID. Useful for votes/comments - RsGxsMessageId mParentId; - - /// Reference message ID. Useful for votes/comments - RsGxsMessageId mThreadId; - - /// Some additional ID. Can be used for e.g. chat lobbies. - uint64_t mAdditionalId; - - /// additional comment to be used mainly for debugging, but not GUI display - std::string mComment; - - bool operator<(const RsIdentityUsage& u) const { return mHash < u.mHash; } - RsFileHash mHash; - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(mServiceId); - RS_SERIAL_PROCESS(mUsageCode); - RS_SERIAL_PROCESS(mGrpId); - RS_SERIAL_PROCESS(mMsgId); - RS_SERIAL_PROCESS(mAdditionalId); - RS_SERIAL_PROCESS(mComment); - RS_SERIAL_PROCESS(mHash); - } - - friend struct RsTypeSerializer; -private: - /** Accessible only to friend class RsTypeSerializer needed for - * deserialization */ - RsIdentityUsage(); -}; - -enum class RsGxsIdentityEventCode: uint8_t -{ - UNKNOWN = 0x00, - NEW_IDENTITY = 0x01, - DELETED_IDENTITY = 0x02, - UPDATED_IDENTITY = 0x03, -}; - -struct RsGxsIdentityEvent: public RsEvent -{ - RsGxsIdentityEvent() - : RsEvent(RsEventType::GXS_IDENTITY), - mIdentityEventCode(RsGxsIdentityEventCode::UNKNOWN) {} - - RsGxsIdentityEventCode mIdentityEventCode; - RsGxsGroupId mIdentityId; - - ///* @see RsEvent @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) override - { - RsEvent::serial_process(j, ctx); - RS_SERIAL_PROCESS(mIdentityEventCode); - RS_SERIAL_PROCESS(mIdentityId); - } - - ~RsGxsIdentityEvent() override = default; -}; - -struct RsIdentityDetails : RsSerializable -{ - RsIdentityDetails() : mFlags(0), mLastUsageTS(0) {} - - RsGxsId mId; - - std::string mNickname; - - uint32_t mFlags; - - RsPgpId mPgpId; - - /// @deprecated Recogn details. - RS_DEPRECATED std::list mRecognTags; - - /** Cyril: Reputation details. At some point we might want to merge - * information between the two into a single global score. Since the old - * reputation system is not finished yet, I leave this in place. We should - * decide what to do with it. - */ - RsReputationInfo mReputation; - - RsGxsImage mAvatar; - - rstime_t mPublishTS; - rstime_t mLastUsageTS; - - std::map mUseCases; - - /// @see RsSerializable - virtual void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(mId); - RS_SERIAL_PROCESS(mNickname); - RS_SERIAL_PROCESS(mFlags); - RS_SERIAL_PROCESS(mPgpId); - RS_SERIAL_PROCESS(mReputation); - RS_SERIAL_PROCESS(mAvatar); - RS_SERIAL_PROCESS(mPublishTS); - RS_SERIAL_PROCESS(mLastUsageTS); - RS_SERIAL_PROCESS(mUseCases); - } - - ~RsIdentityDetails() override; -}; - - - -/** The Main Interface Class for GXS people identities */ -class RsIdentity: public RsGxsIfaceHelper -{ -public: - explicit RsIdentity(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {} - - /** - * @brief Create a new identity - * @jsonapi{development} - * @param[out] id storage for the created identity Id - * @param[in] name Name of the identity - * @param[in] avatar Image associated to the identity - * @param[in] pseudonimous true for unsigned identity, false otherwise - * @param[in] pgpPassword password to unlock PGP to sign identity, - * not implemented yet - * @return false on error, true otherwise - */ - virtual bool createIdentity( - RsGxsId& id, - const std::string& name, const RsGxsImage& avatar = RsGxsImage(), - bool pseudonimous = true, const std::string& pgpPassword = "" ) = 0; - - /** - * @brief Locally delete given identity - * @jsonapi{development} - * @param[in] id Id of the identity - * @return false on error, true otherwise - */ - virtual bool deleteIdentity(RsGxsId& id) = 0; - - /** - * @brief Update identity data (name, avatar...) - * @jsonapi{development} - * @param[in] id Id of the identity - * @param[in] name New name of the identity - * @param[in] avatar New avatar for the identity - * @param[in] pseudonimous Set to true to make the identity anonymous. If set to false, updating will require the profile passphrase. - * @param[in] pgpPassword Profile passphrase, if non pseudonymous. - * @return false on error, true otherwise - */ - virtual bool updateIdentity( const RsGxsId& id, const std::string& name, const RsGxsImage& avatar, bool pseudonimous, const std::string& pgpPassword) =0; - - /** - * @brief Get identity details, from the cache - * @jsonapi{development} - * @param[in] id Id of the identity - * @param[out] details Storage for the identity details - * @return false on error, true otherwise - */ - virtual bool getIdDetails(const RsGxsId& id, RsIdentityDetails& details) = 0; - - /** - * @brief Get last seen usage time of given identity - * @jsonapi{development} - * @param[in] id Id of the identity - * @return timestamp of last seen usage - */ - virtual rstime_t getLastUsageTS(const RsGxsId& id) = 0; - - /** - * @brief Get own signed ids - * @jsonapi{development} - * @param[out] ids storage for the ids - * @return false on error, true otherwise - */ - virtual bool getOwnSignedIds(std::vector& ids) = 0; - - /** - * @brief Get own pseudonimous (unsigned) ids - * @jsonapi{development} - * @param[out] ids storage for the ids - * @return false on error, true otherwise - */ - virtual bool getOwnPseudonimousIds(std::vector& ids) = 0; - - /** - * @brief Check if an id is known - * @jsonapi{development} - * @param[in] id Id to check - * @return true if the id is known, false otherwise - */ - virtual bool isKnownId(const RsGxsId& id) = 0; - - /** - * @brief Check if an id is own - * @jsonapi{development} - * @param[in] id Id to check - * @return true if the id is own, false otherwise - */ - virtual bool isOwnId(const RsGxsId& id) = 0; - - /** - * @brief Get identities summaries list. - * @jsonapi{development} - * @param[out] ids list where to store the identities - * @return false if something failed, true otherwhise - */ - virtual bool getIdentitiesSummaries(std::list& ids) = 0; - - /** - * @brief Get identities information (name, avatar...). - * Blocking API. - * @jsonapi{development} - * @param[in] ids ids of the channels of which to get the informations - * @param[out] idsInfo storage for the identities informations - * @return false if something failed, true otherwhise - */ - virtual bool getIdentitiesInfo( - const std::set& ids, - std::vector& idsInfo ) = 0; - - /** - * @brief Check if an identity is contact - * @jsonapi{development} - * @param[in] id Id of the identity - * @return true if it is a conctact, false otherwise - */ - virtual bool isARegularContact(const RsGxsId& id) = 0; - - /** - * @brief Set/unset identity as contact - * @jsonapi{development} - * @param[in] id Id of the identity - * @param[in] isContact true to set, false to unset - * @return false on error, true otherwise - */ - virtual bool setAsRegularContact(const RsGxsId& id, bool isContact) = 0; - - /** - * @brief Toggle automatic flagging signed by friends identity as contact - * @jsonapi{development} - * @param[in] enabled true to enable, false to disable - */ - virtual void setAutoAddFriendIdsAsContact(bool enabled) = 0; - - /** - * @brief Check if automatic signed by friend identity contact flagging is - * enabled - * @jsonapi{development} - * @return true if enabled, false otherwise - */ - virtual bool autoAddFriendIdsAsContact() = 0; - - /** - * @brief Get number of days after which delete a banned identities - * @jsonapi{development} - * @return number of days - */ - virtual uint32_t deleteBannedNodesThreshold() = 0; - - /** - * @brief Set number of days after which delete a banned identities - * @jsonapi{development} - * @param[in] days number of days - */ - virtual void setDeleteBannedNodesThreshold(uint32_t days) = 0; - - /** - * @brief request details of a not yet known identity to the network - * @jsonapi{development} - * @param[in] id id of the identity to request - * @param[in] peers optional list of the peers to ask for the key, if empty - * all online peers are asked. - * @return false on error, true otherwise - */ - virtual bool requestIdentity( - const RsGxsId& id, - const std::vector& peers = std::vector() ) = 0; - - /// default base URL used for indentity links @see exportIdentityLink - static const std::string DEFAULT_IDENTITY_BASE_URL; - - /// Link query field used to store indentity name @see exportIdentityLink - static const std::string IDENTITY_URL_NAME_FIELD; - - /// Link query field used to store indentity id @see exportIdentityLink - static const std::string IDENTITY_URL_ID_FIELD; - - /// Link query field used to store indentity data @see exportIdentityLink - static const std::string IDENTITY_URL_DATA_FIELD; - - /** - * @brief Get link to a identity - * @jsonapi{development} - * @param[out] link storage for the generated link - * @param[in] id Id of the identity of which you want to generate a link - * @param[in] includeGxsData if true include the identity GXS group data so - * the receiver can make use of the identity even if she hasn't received it - * through GXS yet - * @param[in] baseUrl URL into which to sneak in the RetroShare link - * radix, this is primarly useful to induce applications into making the - * link clickable, or to disguise the RetroShare link into a - * "normal" looking web link. If empty the GXS data link will be outputted - * in plain base64 format. - * @param[out] errMsg optional storage for error message, meaningful only in - * case of failure - * @return false if something failed, true otherwhise - */ - virtual bool exportIdentityLink( - std::string& link, const RsGxsId& id, - bool includeGxsData = true, - const std::string& baseUrl = RsIdentity::DEFAULT_IDENTITY_BASE_URL, - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - /** - * @brief Import identity from full link - * @param[in] link identity link either in radix or link format - * @param[out] id optional storage for parsed identity - * @param[out] errMsg optional storage for error message, meaningful only in - * case of failure - * @return false if some error occurred, true otherwise - */ - virtual bool importIdentityLink( - const std::string& link, - RsGxsId& id = RS_DEFAULT_STORAGE_PARAM(RsGxsId), - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - RS_DEPRECATED_FOR(exportIdentityLink) - virtual bool getGroupSerializedData( - const uint32_t& token, - std::map& serialized_groups ) = 0; - - RS_DEPRECATED - virtual bool parseRecognTag( - const RsGxsId &id, const std::string& nickname, - const std::string& tag, RsRecognTagDetails& details) = 0; - - RS_DEPRECATED - virtual bool getRecognTagRequest( - const RsGxsId& id, const std::string& comment, uint16_t tag_class, - uint16_t tag_type, std::string& tag) = 0; - - RS_DEPRECATED - virtual uint32_t nbRegularContacts() =0; - - RS_DEPRECATED_FOR(exportIdentityLink) - virtual bool serialiseIdentityToMemory( const RsGxsId& id, - std::string& radix_string ) = 0; - RS_DEPRECATED_FOR(importIdentityLink) - virtual bool deserialiseIdentityFromMemory( const std::string& radix_string, - RsGxsId* id = nullptr ) = 0; - - /// Fills up list of all own ids. Returns false if ids are not yet loaded. - RS_DEPRECATED_FOR("getOwnSignedIds getOwnPseudonimousIds") - virtual bool getOwnIds( std::list &ownIds, - bool only_signed_ids = false ) = 0; - - RS_DEPRECATED - virtual bool createIdentity(uint32_t& token, RsIdentityParameters ¶ms) = 0; - - RS_DEPRECATED_FOR(RsReputations) - virtual bool submitOpinion(uint32_t& token, const RsGxsId &id, - bool absOpinion, int score) = 0; - - RS_DEPRECATED - virtual bool deleteIdentity(uint32_t& token, RsGxsIdGroup &group) = 0; - - RS_DEPRECATED_FOR("getIdentitiesSummaries getIdentitiesInfo") - virtual bool getGroupData( const uint32_t& token, - std::vector& groups) = 0; - - virtual ~RsIdentity(); -}; diff --git a/libretroshare/src/retroshare/rsids.h b/libretroshare/src/retroshare/rsids.h deleted file mode 100644 index c7fec6725..000000000 --- a/libretroshare/src/retroshare/rsids.h +++ /dev/null @@ -1,348 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsids.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2013 Cyril Soler * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "util/rsdebug.h" -#include "util/rsrandom.h" -#include "util/stacktrace.h" - -/** - * RsGenericIdType values might be random, but must be different, in order to - * make the various IDs incompatible with each other. - */ -enum class RsGenericIdType -{ - SSL, - PGP_ID, - SHA1, - PGP_FINGERPRINT, - GXS_GROUP, - GXS_ID, - GXS_MSG, - GXS_CIRCLE, - GROUTER, - GXS_TUNNEL, - DISTANT_CHAT, - NODE_GROUP, - SHA256, - BIAS_20_BYTES -}; - -/** - * This class aims at defining a generic ID type that is a list of bytes. It - * can be converted into a hexadecial string for printing, mainly) or for - * compatibility with old methods. - * - * To use this class, derive your own ID type from it. - * @see RsPpgFingerprint as an example. - * - * Take care to define and use a different @see RsGenericIdType for each ne type - * of ID you create, to avoid implicit conversion between subtypes, and - * therefore accidental ID mixup is impossible. - * - * ID Types with different lengths are not convertible even using explicit - * constructor and compilation would fail if that is attempted. - * - * Warning: never store references to a t_RsGenericIdType accross threads, since - * the cached string convertion is not thread safe. - */ -template -struct t_RsGenericIdType -{ - using Id_t = t_RsGenericIdType; - using std_list = std::list; - using std_vector = std::vector; - using std_set = std::set; - - /// by default, ids are set to null() - t_RsGenericIdType() { memset(bytes, 0, ID_SIZE_IN_BYTES); } - - /// Explicit constructor from a hexadecimal string - explicit t_RsGenericIdType(const std::string& hex_string); - - /** - * @brief Construct from a buffer of at least the size of SIZE_IN_BYTES - * This is dangerous if used without being absolutely sure of buffer size, - * nothing prevent a buffer of wrong size being passed at runtime! - * @param[in] buff pointer to the buffer - * @return empty id on failure, an id initialized from the bytes in the - * buffer - */ - static Id_t fromBufferUnsafe(const uint8_t* buff) - { - Id_t ret; - - if(!buff) - { - RsErr() << __PRETTY_FUNCTION__ << " invalid paramethers buff: " - << buff << std::endl; - print_stacktrace(); - return ret; - } - - memmove(ret.bytes, buff, SIZE_IN_BYTES); - return ret; - } - - /** - * Explicit constructor from a different type but with same size. - * - * This is used for conversions such as - * GroupId -> CircleId - * GroupId -> GxsId - */ - template - explicit t_RsGenericIdType( - const t_RsGenericIdType& - id ) - { memmove(bytes, id.toByteArray(), ID_SIZE_IN_BYTES); } - - /// Random initialization. Can be useful for testing and to generate new ids. - static Id_t random() - { - Id_t id; - RsRandom::random_bytes(id.bytes, ID_SIZE_IN_BYTES); - return id; - } - - inline void clear() { memset(bytes, 0, SIZE_IN_BYTES); } - - /// Converts to a std::string using cached value. - const uint8_t* toByteArray() const { return &bytes[0]; } - - static constexpr uint32_t SIZE_IN_BYTES = ID_SIZE_IN_BYTES; - - inline bool operator==(const Id_t& fp) const - { return !memcmp(bytes, fp.bytes, ID_SIZE_IN_BYTES); } - - inline bool operator!=(const Id_t& fp) const - { return !!memcmp(bytes, fp.bytes, ID_SIZE_IN_BYTES); } - - inline bool operator< (const Id_t& fp) const - { return (memcmp(bytes, fp.bytes, ID_SIZE_IN_BYTES) < 0); } - - inline Id_t operator~ () const - { - Id_t ret; - for(uint32_t i=0; i < ID_SIZE_IN_BYTES; ++i) - ret.bytes[i] = ~bytes[i]; - return ret; - } - - inline Id_t operator| (const Id_t& fp) const - { - Id_t ret; - for(uint32_t i=0; i < ID_SIZE_IN_BYTES; ++i) - ret.bytes[i] = bytes[i] | fp.bytes[i]; - return ret; - } - - inline Id_t operator^ (const Id_t& fp) const - { - Id_t ret; - for(uint32_t i=0; i < ID_SIZE_IN_BYTES; ++i) - ret.bytes[i] = bytes[i] ^ fp.bytes[i]; - return ret; - } - - - inline bool isNull() const - { - for(uint32_t i=0; i < SIZE_IN_BYTES; ++i) - if(bytes[i] != 0) return false; - return true; - } - - friend std::ostream& operator<<(std::ostream& out, const Id_t& id) - { - switch (UNIQUE_IDENTIFIER) - { - case RsGenericIdType::PGP_FINGERPRINT: - { - uint8_t index = 0; - for(char c : id.toStdString()) - { - out << c; - if(++index % 4 == 0 && index < id.SIZE_IN_BYTES*2) out << ' '; - } - } - break; - default: out << id.toStdString(UPPER_CASE); break; - } - - return out; - } - - inline std::string toStdString() const { return toStdString(UPPER_CASE); } - - inline static uint32_t serial_size() { return SIZE_IN_BYTES; } - - bool serialise(void* data,uint32_t pktsize,uint32_t& offset) const - { - if(offset + SIZE_IN_BYTES > pktsize) return false; - memmove( &(reinterpret_cast(data))[offset], - bytes, SIZE_IN_BYTES ); - offset += SIZE_IN_BYTES; - return true; - } - - bool deserialise(const void* data, uint32_t pktsize, uint32_t& offset) - { - if(offset + SIZE_IN_BYTES > pktsize) return false; - memmove( bytes, - &(reinterpret_cast(data))[offset], - SIZE_IN_BYTES ); - offset += SIZE_IN_BYTES; - return true; - } - - /** Explicit constructor from a byte array. The array must have size at - * least ID_SIZE_IN_BYTES - * @deprecated This is too dangerous! - * Nothing prevent a buffer of wrong size being passed at runtime! - */ - RS_DEPRECATED_FOR("fromBufferUnsafe(const uint8_t* buff)") - explicit t_RsGenericIdType(const uint8_t bytes[]); - -private: - std::string toStdString(bool upper_case) const; - uint8_t bytes[ID_SIZE_IN_BYTES]; -}; - -template -std::string t_RsGenericIdType -::toStdString(bool upper_case) const -{ - static const char outh[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' } ; - static const char outl[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' } ; - - std::string res(ID_SIZE_IN_BYTES*2,' ') ; - - for(uint32_t j = 0; j < ID_SIZE_IN_BYTES; j++) - if(upper_case) - { - res[2*j ] = outh[ (bytes[j]>>4) ] ; - res[2*j+1] = outh[ bytes[j] & 0xf ] ; - } - else - { - res[2*j ] = outl[ (bytes[j]>>4) ] ; - res[2*j+1] = outl[ bytes[j] & 0xf ] ; - } - - return res ; -} - -template -t_RsGenericIdType -::t_RsGenericIdType(const std::string& s) -{ - std::string::size_type n = 0; - if(s.length() != ID_SIZE_IN_BYTES*2) - { - if(!s.empty()) - { - RsErr() << __PRETTY_FUNCTION__ << " supplied string in constructor " - << "has wrong size. Expected ID size=" << ID_SIZE_IN_BYTES*2 - << " String=\"" << s << "\" = " << s.length() << std::endl; - print_stacktrace(); - } - clear(); - return; - } - - for(uint32_t i = 0; i < ID_SIZE_IN_BYTES; ++i) - { - bytes[i] = 0 ; - - for(int k=0;k<2;++k) - { - char b = s[n++] ; - - if(b >= 'A' && b <= 'F') - bytes[i] += (b-'A'+10) << 4*(1-k) ; - else if(b >= 'a' && b <= 'f') - bytes[i] += (b-'a'+10) << 4*(1-k) ; - else if(b >= '0' && b <= '9') - bytes[i] += (b-'0') << 4*(1-k) ; - else - { - RsErr() << __PRETTY_FUNCTION__ << "supplied string is not " - << "purely hexadecimal: s=\"" << s << "\"" << std::endl; - clear(); - return; - } - } - } -} - -template -RS_DEPRECATED_FOR("t_RsGenericIdType::fromBuffer(...)") -t_RsGenericIdType:: -t_RsGenericIdType(const uint8_t mem[]) /// @deprecated Too dangerous! -{ - if(mem == nullptr) memset(bytes, 0, ID_SIZE_IN_BYTES); - else memcpy(bytes, mem, ID_SIZE_IN_BYTES); -} - -/** - * This constants are meant to be used only inside this file. - * Use @see t_RsGenericIdType::SIZE_IN_BYTES in other places. - */ -namespace _RsIdSize -{ -constexpr uint32_t SSL_ID = 16; // = CERT_SIGN -constexpr uint32_t CERT_SIGN = 16; // = SSL_ID -constexpr uint32_t PGP_ID = 8; -constexpr uint32_t PGP_FINGERPRINT = 20; -constexpr uint32_t SHA1 = 20; -constexpr uint32_t SHA256 = 32; -} - -using RsPeerId = t_RsGenericIdType<_RsIdSize::SSL_ID , false, RsGenericIdType::SSL >; -using RsPgpId = t_RsGenericIdType<_RsIdSize::PGP_ID , true, RsGenericIdType::PGP_ID >; -using Sha1CheckSum = t_RsGenericIdType<_RsIdSize::SHA1 , false, RsGenericIdType::SHA1 >; -using Sha256CheckSum = t_RsGenericIdType<_RsIdSize::SHA256 , false, RsGenericIdType::SHA256 >; -using RsPgpFingerprint = t_RsGenericIdType<_RsIdSize::PGP_FINGERPRINT, true, RsGenericIdType::PGP_FINGERPRINT>; -using Bias20Bytes = t_RsGenericIdType<_RsIdSize::SHA1 , true, RsGenericIdType::BIAS_20_BYTES >; -using RsGxsGroupId = t_RsGenericIdType<_RsIdSize::CERT_SIGN , false, RsGenericIdType::GXS_GROUP >; -using RsGxsMessageId = t_RsGenericIdType<_RsIdSize::SHA1 , false, RsGenericIdType::GXS_MSG >; -using RsGxsId = t_RsGenericIdType<_RsIdSize::CERT_SIGN , false, RsGenericIdType::GXS_ID >; -using RsGxsCircleId = t_RsGenericIdType<_RsIdSize::CERT_SIGN , false, RsGenericIdType::GXS_CIRCLE >; -using RsGxsTunnelId = t_RsGenericIdType<_RsIdSize::SSL_ID , false, RsGenericIdType::GXS_TUNNEL >; -using DistantChatPeerId = t_RsGenericIdType<_RsIdSize::SSL_ID , false, RsGenericIdType::DISTANT_CHAT >; -using RsNodeGroupId = t_RsGenericIdType<_RsIdSize::CERT_SIGN , false, RsGenericIdType::NODE_GROUP >; - -/// @deprecated Ugly name kept temporarly only because it is used in many places -using PGPFingerprintType RS_DEPRECATED_FOR(RsPpgFingerprint) = RsPgpFingerprint; diff --git a/libretroshare/src/retroshare/rsiface.h b/libretroshare/src/retroshare/rsiface.h deleted file mode 100644 index 1f9041d3e..000000000 --- a/libretroshare/src/retroshare/rsiface.h +++ /dev/null @@ -1,93 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsiface.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include "retroshare/rsnotify.h" -#include "rstypes.h" - -#include -#include - -class RsServer; -class RsInit; -struct RsPeerCryptoParams; -class RsControl; - -/// RsInit -> Configuration Parameters for RetroShare Startup -RsInit* InitRsConfig(); - -/* extract various options for GUI */ -const char *RsConfigDirectory(RsInit *config); -bool RsConfigStartMinimised(RsInit *config); -void CleanupRsConfig(RsInit *); - - -// Called First... (handles comandline options) -int InitRetroShare(int argc, char **argv, RsInit *config); - -/** - * Pointer to global instance of RsControl needed to expose JSON API - * @jsonapi{development} - */ -extern RsControl* rsControl; - -/** The Main Interface Class - for controlling the server */ -class RsControl -{ -public: - /// TODO: This should return a reference instead of a pointer! - static RsControl* instance(); - static void earlyInitNotificationSystem() { rsControl = instance(); } - - /* Real Startup Fn */ - virtual int StartupRetroShare() = 0; - - /** - * @brief Check if core is fully ready, true only after StartupRetroShare() - * finish and before rsGlobalShutDown() begin - * @jsonapi{development} - */ - virtual bool isReady() = 0; - - virtual void ConfigFinalSave() = 0; - - /** - * @brief Turn off RetroShare - * @jsonapi{development,manualwrapper} - */ - virtual void rsGlobalShutDown() = 0; - - virtual bool getPeerCryptoDetails( - const RsPeerId& ssl_id,RsPeerCryptoParams& params ) = 0; - virtual void getLibraries(std::list &libraries) = 0; - - /** - * @brief Set shutdown callback, useful if main runlop is controlled by - * another entity such as QCoreApplication - * @param callback function to call when shutdown is almost complete - */ - virtual void setShutdownCallback(const std::function& callback) = 0; - -protected: - RsControl() {} // should not be used, hence it's private. -}; - diff --git a/libretroshare/src/retroshare/rsinit.h b/libretroshare/src/retroshare/rsinit.h deleted file mode 100644 index ba2c33765..000000000 --- a/libretroshare/src/retroshare/rsinit.h +++ /dev/null @@ -1,483 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsinit.h * - * * - * Copyright (C) 2004-2014 Robert Fernie * - * Copyright (C) 2016-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -/// @file RetroShare initialization and login API - -// Initialize ok, result >= 0 -#define RS_INIT_OK 0 // Initialize ok -#define RS_INIT_HAVE_ACCOUNT 1 // Initialize ok, have account -// Initialize failed, result < 0 -#define RS_INIT_AUTH_FAILED -1 // AuthGPG::InitAuth failed -#define RS_INIT_BASE_DIR_ERROR -2 // AuthGPG::InitAuth failed -#define RS_INIT_NO_KEYRING -3 // Keyring is empty. Need to import it. -#define RS_INIT_NO_EXECUTABLE -4 // executable path hasn't been set in config options - -#include -#include -#include -#include -#include - -#include "retroshare/rstypes.h" -#include "retroshare/rsversion.h" - - -class RsLoginHelper; - -/** - * Pointer to global instance of RsLoginHelper - * @jsonapi{development} - */ -extern RsLoginHelper* rsLoginHelper; - - -enum class RsInitErrorNum : int32_t -{ - ALREADY_LOGGED_IN = 6000, - CANT_ACQUIRE_LOCK = 6001, - INVALID_LOCATION_NAME = 6002, - PGP_NAME_OR_ID_NEEDED = 6003, - PGP_KEY_CREATION_FAILED = 6004, - SSL_KEY_CREATION_FAILED = 6005, - INVALID_SSL_ID = 6006, - LOGIN_FAILED = 6007 -}; - -struct RsInitErrorCategory: std::error_category -{ - const char* name() const noexcept override - { return "RetroShare init"; } - - std::string message(int ev) const override - { - switch (static_cast(ev)) - { - case RsInitErrorNum::ALREADY_LOGGED_IN: - return "Already logged in"; - case RsInitErrorNum::CANT_ACQUIRE_LOCK: - return "Cannot aquire lock on location data. Another instance is " - "already running with this profile?"; - case RsInitErrorNum::INVALID_LOCATION_NAME: - return "Invalid location name"; - case RsInitErrorNum::PGP_NAME_OR_ID_NEEDED: - return "Either PGP name or PGP id is needed"; - case RsInitErrorNum::PGP_KEY_CREATION_FAILED: - return "Failure creating PGP key"; - case RsInitErrorNum::SSL_KEY_CREATION_FAILED: - return "Failure creating SSL key"; - case RsInitErrorNum::INVALID_SSL_ID: - return "Invalid SSL id"; - case RsInitErrorNum::LOGIN_FAILED: - return "Generic login failure"; - default: - return rsErrorNotInCategory(ev, name()); - } - } - - const static RsInitErrorCategory instance; -}; - - -namespace std -{ -/** Register RsJsonApiErrorNum as an error condition enum, must be in std - * namespace */ -template<> struct is_error_condition_enum : true_type {}; -} - -/** Provide RsInitErrorNum conversion to std::error_condition, must be in - * same namespace of RsInitErrorNum */ -inline std::error_condition make_error_condition(RsInitErrorNum e) noexcept -{ - return std::error_condition( - static_cast(e), RsInitErrorCategory::instance ); -}; - - - -/** - * @brief The RsInitConfig struct - * This class contains common configuration options, that executables using libretroshare may want to - * set using e.g. commandline options. To be passed to RsInit::InitRetroShare(). - */ -struct RsConfigOptions -{ - RsConfigOptions(); - - // required - - std::string main_executable_path;/* this should be set to argv[0] */ - - // Optional. Only change if needed. - - bool autoLogin; /* try auto-login */ - - bool udpListenerOnly; /* only listen to udp */ - std::string forcedInetAddress; /* inet address to use.*/ - uint16_t forcedPort; /* port to listen to */ - - bool outStderr; - int debugLevel; - std::string logfname; /* output filename for log */ - - std::string opModeStr; /* operating mode. Acceptable values: "Full", "NoTurtle", "Gaming", "Minimal" */ - std::string optBaseDir; /* base directory where to find profiles, etc */ - - uint16_t jsonApiPort; /* port to use fo Json API */ - std::string jsonApiBindAddress; /* bind address for Json API */ -}; - - -/*! - * Initialisation Class (not publicly disclosed to RsIFace) - */ -class RsInit -{ -public: - enum RS_DEPRECATED_FOR(RsInitErrorNum) LoadCertificateStatus : uint8_t - { - OK, /// Everything go as expected, no error occurred - ERR_ALREADY_RUNNING, /// Another istance is running already - ERR_CANT_ACQUIRE_LOCK, /// Another istance is already running? - ERR_NO_AVAILABLE_ACCOUNT, /// Used in retroshare-service -U list when no account is available - ERR_CANNOT_CONFIGURE_TOR, /// cannot start/configure Tor for an auto-tor node - ERR_UNKNOWN /// Unkown error, maybe password is wrong? - }; - - /* reorganised RsInit system */ - - /*! - * PreLogin - * Call before init retroshare, initialises rsinitconfig's public attributes - */ - static void InitRsConfig(); - - /*! - * Should be called to load up ssl cert and private key, and intialises gpg - * this must be called before accessing rsserver (e.g. ::startupretroshare) - * @param argc passed from executable - * @param argv commandline arguments passed to executable - * @param strictCheck set to true if you want rs to continue executing if - * invalid argument passed and vice versa - * @return RS_INIT_... - */ - static int InitRetroShare(const RsConfigOptions&); - - static bool isPortable(); - static bool isWindowsXP(); - static bool collectEntropy(uint32_t bytes) ; - static bool startAutoTor(); - - /*! - * \brief lockFilePath - * \return - * full path for the lock file. Can be used to warn the user about a non deleted lock that would prevent to start. - */ - static std::string lockFilePath(); - - /* - * Setup Hidden Location; - */ - static void SetHiddenLocation(const std::string& hiddenaddress, uint16_t port, bool useI2p); - - static bool LoadPassword(const std::string& passwd) ; - - /* - * Final Certificate load. This can be called if: - * a) InitRetroshare() returns RS_INIT_HAVE_ACCOUNT -> autoLoad/password Set. - * b) or LoadPassword() - * - * This uses the preferredId from RsAccounts. - * This wrapper also locks the profile before finalising the login - */ - static LoadCertificateStatus LockAndLoadCertificates( - bool autoLoginNT, std::string& lockFilePath ); - - // Post Login Options - static bool getStartMinimised(); - - static int getSslPwdLen(); - static bool getAutoLogin(); - static void setAutoLogin(bool autoLogin); - static bool RsClearAutoLogin() ; - - static std::string executablePath() ; -private: - /** @brief Lock profile directory - * param[in] accountDir account directory to lock - * param[out] lockFilePath path of the created lock-file - */ - static LoadCertificateStatus LockConfigDirectory( - const std::string& accountDir, std::string& lockFilePath); - - /// @brief Unlock profile directory - static void UnlockConfigDirectory(); - - static int LoadCertificates(bool autoLoginNT); -}; - - - -/* Seperate static Class for dealing with Accounts */ - -class RsAccountsDetail; - -class RsAccounts -{ -public: - /// Should be called once before everything else. - static bool init(const std::string &opt_base_dir, int& error_code); - - /** - * @brief ConfigDirectory (usually ~/.retroshare) you can call this method - * even before initialisation (you can't with some other methods) - * @see RsAccountsDetail::PathBaseDirectory() - */ - static std::string ConfigDirectory(); - - /** - * @brief Get current account id. Beware that an account may be selected - * without actually logging in. - * @jsonapi{development,unauthenticated} - * @param[out] id storage for current account id - * @return false if account hasn't been selected yet, true otherwise - */ - static bool getCurrentAccountId(RsPeerId &id); - - /** - * @brief DataDirectory - * you can call this method even before initialisation (you can't with some other methods) - * @param check if set to true and directory does not exist, return empty string - * @return path where global platform independent files are stored, like bdboot.txt or webinterface files - */ - static std::string systemDataDirectory(bool check = true); - static std::string PGPDirectory(); - - /** - * @brief Get available PGP identities id list - * @jsonapi{development,unauthenticated} - * @param[out] pgpIds storage for PGP id list - * @return true on success, false otherwise - */ - static int GetPGPLogins(std::list &pgpIds); - static int GetPGPLoginDetails(const RsPgpId& id, std::string &name, std::string &email); - static bool GeneratePGPCertificate(const std::string&, const std::string& email, const std::string& passwd, RsPgpId &pgpId, const int keynumbits, std::string &errString); - - /** - * @brief Export full encrypted PGP identity to file - * @jsonapi{development} - * @param[in] filePath path of certificate file - * @param[in] pgpId PGP id to export - * @return true on success, false otherwise - */ - static bool ExportIdentity( const std::string& filePath, - const RsPgpId& pgpId ); - - /** - * @brief Import full encrypted PGP identity from file - * @jsonapi{development,unauthenticated} - * @param[in] filePath path of certificate file - * @param[out] pgpId storage for the PGP fingerprint of the imported key - * @param[out] errorMsg storage for eventual human readable error message - * @return true on success, false otherwise - */ - static bool ImportIdentity( - const std::string& filePath, RsPgpId& pgpId, std::string& errorMsg ); - - /** - * @brief Import full encrypted PGP identity from string - * @jsonapi{development,unauthenticated} - * @param[in] data certificate string - * @param[out] pgpId storage for the PGP fingerprint of the imported key - * @param[out] errorMsg storage for eventual human readable error message - * @return true on success, false otherwise - */ - static bool importIdentityFromString( - const std::string& data, RsPgpId& pgpId, - std::string& errorMsg ); - - /** - * @brief Export full encrypted PGP identity to string - * @jsonapi{development} - * @param[out] data storage for certificate string - * @param[in] pgpId PGP id to export - * @param[in] includeSignatures true to include signatures - * @param[out] errorMsg storage for eventual human readable error message - * @return true on success, false otherwise - */ - static bool exportIdentityToString( - std::string& data, const RsPgpId& pgpId, std::string& errorMsg, - bool includeSignatures = true ); - - static void GetUnsupportedKeys(std::map > &unsupported_keys); - static bool CopyGnuPGKeyrings() ; - - // Rs Accounts - static bool SelectAccount(const RsPeerId& id); - static bool GetPreferredAccountId(RsPeerId &id); - static bool GetAccountIds(std::list &ids); - - static bool GetAccountDetails(const RsPeerId &id, RsPgpId &gpgId, std::string &gpgName, std::string &gpgEmail, std::string &location); - - static bool createNewAccount( - const RsPgpId& pgp_id, const std::string& org, - const std::string& loc, const std::string& country, - bool ishiddenloc, bool is_auto_tor, const std::string& passwd, - RsPeerId &sslId, std::string &errString ); - - static void storeSelectedAccount() ; - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // All methods bellow can only be called ones SelectAccount() as been called. // - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - static bool getCurrentAccountOptions(bool& is_hidden,bool& is_tor_auto,bool& is_first_time) ; - - static bool checkCreateAccountDirectory(); // Generate the hierarchy of directories below ~/.retroshare/[SSL dir]/ - static bool isHiddenNode() ; // true if the running node is a hidden node. Used to choose which services to start. - static bool isTorAuto() ; // true if the running node is a hidden node using automated Tor management - - static std::string AccountDirectory(); // linux: ~/.retroshare/[SSL dir]/ - static std::string AccountKeysDirectory(); // linux: ~/.retroshare/[SSL dir]/keys/ - static std::string AccountPathCertFile(); // linux: ~/.retroshare/[SSL dir]/keys/user_cert.pem - static std::string AccountPathKeyFile(); // linux: ~/.retroshare/[SSL dir]/keys/user_pk.pem - static std::string AccountLocationName(); - - static bool lockPreferredAccount() ; // are these methods any useful?? - static void unlockPreferredAccount() ; - -private: - static RsAccountsDetail* rsAccountsDetails; -}; - -/** - * Pointer to global instance of RsAccounts needed to expose JSON API, as all - * the members of this class are static you should call them directly without - * using this pointer in the other parts of the code - * @jsonapi{development} - */ -extern RsAccounts* rsAccounts; - - -/** - * This helper class have been implemented because there was not reasonable way - * to login in the API that could be exposed via JSON API - */ -class RsLoginHelper -{ -public: - RsLoginHelper() = default; - - /** - * @brief Normal way to attempt login - * @jsonapi{development,unauthenticated} - * @param[in] account Id of the account to which attempt login - * @param[in] password Password for the given account - * @return RsInit::OK if login attempt success, error code otherwhise - */ - RsInit::LoadCertificateStatus attemptLogin( - const RsPeerId& account, const std::string& password ); - - /** - * @brief Feed extra entropy to the crypto libraries - * @jsonapi{development,unauthenticated} - * @param[in] bytes number to feed to the entropy pool - * @return false if error occurred, true otherwise - */ - static bool collectEntropy(uint32_t bytes); - - struct Location : RsSerializable - { - RsPeerId mLocationId; - RsPgpId mPgpId; - std::string mLocationName; - std::string mPgpName; - - /// @see RsSerializable::serial_process - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ); - }; - - /** - * @brief Get locations and associated information - * @jsonapi{development,unauthenticated} - * @param[out] locations storage for the retrived locations - */ - void getLocations(std::vector& locations); - - /** - * @brief Creates a new RetroShare location, and log in once is created - * @jsonapi{development,manualwrapper} - * @param[out] locationId storage for generated location SSL id - * @param[inout] pgpId specify PGP id to use to sign the location, if a null - * id is passed the PGP key is created too and this param is used as - * storage for its id. - * @param[in] password to protect and unlock the associated PGP key - * param[in] apiUser (JSON API only) string containing username for JSON API - * so it can be later used to authenticate JSON API calls. It is passed - * down to @see RsJsonApi::authorizeUser under the hood. - * param[in] apiPass (JSON API only) string containing password for JSON API - * so it can be later used to authenticate JSON API calls. It is passed - * down to @see RsJsonApi::authorizeUser under the hood. - * To improve security we strongly advise to not use the same as the - * password used for the PGP key. - * @return Success or error information - */ - std::error_condition createLocationV2( - RsPeerId& locationId, - RsPgpId& pgpId, - const std::string& locationName, - const std::string& pgpName, - const std::string& password - /* JSON API only - * const std::string& apiUser - * const std::string& apiPass */ ); - - /** - * @brief Check if RetroShare is already logged in, this usually return true - * after a successfull attemptLogin() and before closeSession() - * @jsonapi{development,unauthenticated} - * @return true if already logged in, false otherwise - */ - bool isLoggedIn(); - -#if !RS_VERSION_AT_LEAST(0,6,6) - /** - * @deprecated Use @see createLocationV2 instead - * @brief Creates a new RetroShare location, and log in once is created - * @jsonapi{development,manualwrapper} - * @param[inout] location provide input information to generate the location - * and storage to output the data of the generated location - * @param[in] password to protect and unlock the associated PGP key - * @param[out] errorMessage if some error occurred human readable error - * message - * @param[in] makeHidden pass true to create an hidden location. UNTESTED! - * @param[in] makeAutoTor pass true to create an automatically configured - * Tor hidden location. UNTESTED! - * @return true if success, false otherwise - */ - RS_DEPRECATED_FOR(createLocationV2) - bool createLocation( RsLoginHelper::Location& location, - const std::string& password, std::string& errorMessage, - bool makeHidden = false, bool makeAutoTor = false ); -#endif // !RS_VERSION_AT_LEAST(0,6,6) -}; diff --git a/libretroshare/src/retroshare/rsjsonapi.h b/libretroshare/src/retroshare/rsjsonapi.h deleted file mode 100644 index 38e33490e..000000000 --- a/libretroshare/src/retroshare/rsjsonapi.h +++ /dev/null @@ -1,258 +0,0 @@ -/* - * RetroShare JSON API public header - * - * Copyright (C) 2018-2020 Gioacchino Mazzurco - * Copyright (C) 2019 Cyril Soler - * Copyright (C) 2020 AsociaciĆ³n Civil Altermundi - * - * This program is free software: you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the Free - * Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - * details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see - * - * SPDX-FileCopyrightText: 2004-2019 RetroShare Team - * SPDX-License-Identifier: LGPL-3.0-or-later - */ - -#pragma once - -#include -#include -#include -#include - -#include "util/rsdebug.h" -#include "util/rsmemory.h" - -class RsJsonApi; - -/** - * Pointer to global instance of RsJsonApi service implementation - * @jsonapi{development} - */ -extern RsJsonApi* rsJsonApi; - -enum class RsJsonApiErrorNum : int32_t -{ - TOKEN_FORMAT_INVALID = 2004, - UNKNOWN_API_USER = 2005, - WRONG_API_PASSWORD = 2006, - API_USER_CONTAIN_COLON = 2007, - AUTHORIZATION_REQUEST_DENIED = 2008, - CANNOT_EXECUTE_BEFORE_RS_LOGIN = 2009, - NOT_A_MACHINE_GUN = 2010 -}; - -struct RsJsonApiErrorCategory: std::error_category -{ - const char* name() const noexcept override - { return "RetroShare JSON API"; } - - std::string message(int ev) const override - { - switch (static_cast(ev)) - { - case RsJsonApiErrorNum::TOKEN_FORMAT_INVALID: - return "Invalid token format, must be alphanumeric_user:password"; - case RsJsonApiErrorNum::UNKNOWN_API_USER: - return "Unknown API user"; - case RsJsonApiErrorNum::WRONG_API_PASSWORD: - return "Wrong API password"; - case RsJsonApiErrorNum::API_USER_CONTAIN_COLON: - return "API user cannot contain colon character"; - case RsJsonApiErrorNum::AUTHORIZATION_REQUEST_DENIED: - return "User denied new token autorization"; - case RsJsonApiErrorNum::CANNOT_EXECUTE_BEFORE_RS_LOGIN: - return "This operation cannot be executed bedore RetroShare login"; - case RsJsonApiErrorNum::NOT_A_MACHINE_GUN: - return "Method must not be called in burst"; - default: - return rsErrorNotInCategory(ev, name()); - } - } - - std::error_condition default_error_condition(int ev) const noexcept override; - - const static RsJsonApiErrorCategory instance; -}; - - -namespace std -{ -/** Register RsJsonApiErrorNum as an error condition enum, must be in std - * namespace */ -template<> struct is_error_condition_enum : true_type {}; -} - -/** Provide RsJsonApiErrorNum conversion to std::error_condition, must be in - * same namespace of RsJsonApiErrorNum */ -inline std::error_condition make_error_condition(RsJsonApiErrorNum e) noexcept -{ - return std::error_condition( - static_cast(e), RsJsonApiErrorCategory::instance ); -}; - - -class p3ConfigMgr; -class JsonApiResourceProvider; - -class RsJsonApi -{ -public: - static const uint16_t DEFAULT_PORT = 9092; - static const std::string DEFAULT_BINDING_ADDRESS; // 127.0.0.1 - - /** - * @brief Restart RsJsonApi server. - * This method is asyncronous when called from JSON API. - * @jsonapi{development,manualwrapper} - * @return Success or error details - */ - virtual std::error_condition restart() = 0; - - /** @brief Request RsJsonApi to stop and wait until it has stopped. - * Do not expose this method to JSON API as fullstop must not be called from - * the same thread of service execution. - */ - virtual void fullstop() = 0; - - /** - * @brief Request RsJsonApi to stop asynchronously. - * @jsonapi{development} - * Be expecially carefull to call this from JSON API because you will loose - * access to the API. - * If you need to wait until stopping has completed @see isRunning(). - */ - virtual void askForStop() = 0; - - /** - * @brief Get status of the json api server - * @return Returns true if the server is running - */ - virtual bool isRunning() = 0; - - /** - * Sets the binding address of the JSON API server. Will only take effect - * after the server is restarted. - * @jsonapi{development} - * @param[in] address Binding address in IPv4 or IPv6 format. - */ - virtual void setBindingAddress(const std::string& address) = 0; - - /** - * Get the binding address of the JSON API server. - * @jsonapi{development} - * @return string representing binding address - */ - virtual std::string getBindingAddress() const = 0; - - /*! - * Set port on which JSON API server will listen. Will only take effect - * after the server is restarted. - * @jsonapi{development} - * @param[in] port Must be available otherwise the binding will fail - */ - virtual void setListeningPort(uint16_t port) = 0; - - /*! - * Get port on which JSON API server will listen. - * @jsonapi{development} - */ - virtual uint16_t listeningPort() const = 0; - - /*! - * Should be called after creating the JsonAPI object so that it publishes - * itself with the proper config file. - * Since JsonAPI is created *before* login, the config manager does not - * exist at that time. - * @param cfgmgr - */ - virtual void connectToConfigManager(p3ConfigMgr& cfgmgr) = 0; - - /** - * This is used to add/remove new web services to JsonAPI. The client - * should take care of not using a path range already used by the jsonAPI - * server - */ - virtual void registerResourceProvider(const JsonApiResourceProvider&) = 0; - virtual void unregisterResourceProvider(const JsonApiResourceProvider&) = 0; - virtual bool hasResourceProvider(const JsonApiResourceProvider&) = 0; - - /** - * @brief This function should be used by JSON API clients that aren't - * authenticated yet, to ask their token to be authorized, the success or - * failure will depend on mNewAccessRequestCallback return value, and it - * will likely need human user interaction in the process. - * @jsonapi{development,unauthenticated} - * @param[in] user user name to authorize - * @param[in] password password for the new user - * @return if an error occurred details about it. - */ - virtual std::error_condition requestNewTokenAutorization( - const std::string& user, const std::string& password) = 0; - - /** Split a token in USER:PASSWORD format into user and password */ - static bool parseToken( - const std::string& clear_token, - std::string& user, std::string& passwd ); - - /** - * Add new API auth user, passwd to the authorized set. - * @jsonapi{development} - * @param[in] user user name to autorize, must not contain ':' - * @param[in] password password for the user - * @return if some error occurred return details about it - */ - virtual std::error_condition authorizeUser( - const std::string& user, const std::string& password ) = 0; - - /** - * @brief Revoke given auth token - * @jsonapi{development} - * @param[in] user user name of which to revoke authorization - * @return true if the token has been revoked, false otherwise - */ - virtual bool revokeAuthToken(const std::string& user)=0; - - /** - * @brief Get authorized tokens - * @jsonapi{development} - * @return the set of authorized encoded tokens - */ - virtual std::map getAuthorizedTokens() = 0; - - /** - * @brief Check if given JSON API auth token is authorized - * @jsonapi{development,unauthenticated} - * @param[in] token decoded - * @param[out] error optional storage for error details - * @return true if authorized, false otherwise - */ - virtual bool isAuthTokenValid( - const std::string& token, - std::error_condition& error = RS_DEFAULT_STORAGE_PARAM(std::error_condition) - ) = 0; - - /** - * @brief Write version information to given paramethers - * @jsonapi{development,unauthenticated} - * @param[out] major storage - * @param[out] minor storage - * @param[out] mini storage - * @param[out] extra storage - * @param[out] human storage - */ - static void version( uint32_t& major, uint32_t& minor, uint32_t& mini, - std::string& extra, std::string& human ); - - virtual ~RsJsonApi() = default; -}; - diff --git a/libretroshare/src/retroshare/rsmsgs.h b/libretroshare/src/retroshare/rsmsgs.h deleted file mode 100644 index 5e317d4ae..000000000 --- a/libretroshare/src/retroshare/rsmsgs.h +++ /dev/null @@ -1,1073 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsmsgs.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2007-2008 Robert Fernie * - * Copyright (C) 2016-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include -#include - -#include "retroshare/rstypes.h" -#include "retroshare/rsgxsifacetypes.h" -#include "retroshare/rsevents.h" -#include "util/rsdeprecate.h" -#include "util/rsmemory.h" - -/********************** For Messages and Channels *****************/ - -#define RS_MSG_BOXMASK 0x000f /* Mask for determining Box */ - -#define RS_MSG_OUTGOING 0x0001 /* !Inbox */ -#define RS_MSG_PENDING 0x0002 /* OutBox */ -#define RS_MSG_DRAFT 0x0004 /* Draft */ - -/* ORs of above */ -#define RS_MSG_INBOX 0x00 /* Inbox */ -#define RS_MSG_SENTBOX 0x01 /* Sentbox */ -#define RS_MSG_OUTBOX 0x03 /* Outbox */ -#define RS_MSG_DRAFTBOX 0x05 /* Draftbox */ - -#define RS_MSG_NEW 0x000010 /* New */ -#define RS_MSG_TRASH 0x000020 /* Trash */ -#define RS_MSG_UNREAD_BY_USER 0x000040 /* Unread by user */ -#define RS_MSG_REPLIED 0x000080 /* Message is replied */ -#define RS_MSG_FORWARDED 0x000100 /* Message is forwarded */ -#define RS_MSG_STAR 0x000200 /* Message is marked with a star */ -// system message -#define RS_MSG_USER_REQUEST 0x000400 /* user request */ -#define RS_MSG_FRIEND_RECOMMENDATION 0x000800 /* friend recommendation */ -#define RS_MSG_DISTANT 0x001000 /* message is distant */ -#define RS_MSG_SIGNATURE_CHECKS 0x002000 /* message was signed, and signature checked */ -#define RS_MSG_SIGNED 0x004000 /* message was signed and signature didn't check */ -#define RS_MSG_LOAD_EMBEDDED_IMAGES 0x008000 /* load embedded images */ -#define RS_MSG_PUBLISH_KEY 0x020000 /* publish key */ -#define RS_MSG_SPAM 0x040000 /* Message is marked as spam */ - -#define RS_MSG_SYSTEM (RS_MSG_USER_REQUEST | RS_MSG_FRIEND_RECOMMENDATION | RS_MSG_PUBLISH_KEY) - -#define RS_CHAT_LOBBY_EVENT_PEER_LEFT 0x01 -#define RS_CHAT_LOBBY_EVENT_PEER_STATUS 0x02 -#define RS_CHAT_LOBBY_EVENT_PEER_JOINED 0x03 -#define RS_CHAT_LOBBY_EVENT_PEER_CHANGE_NICKNAME 0x04 -#define RS_CHAT_LOBBY_EVENT_KEEP_ALIVE 0x05 - -#define RS_MSGTAGTYPE_IMPORTANT 1 -#define RS_MSGTAGTYPE_WORK 2 -#define RS_MSGTAGTYPE_PERSONAL 3 -#define RS_MSGTAGTYPE_TODO 4 -#define RS_MSGTAGTYPE_LATER 5 -#define RS_MSGTAGTYPE_USER 100 - -//#define RS_CHAT_LOBBY_PRIVACY_LEVEL_CHALLENGE 0 /* Used to accept connection challenges only. */ -//#define RS_CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC 1 /* lobby is visible by friends. Friends can connect.*/ -//#define RS_CHAT_LOBBY_PRIVACY_LEVEL_PRIVATE 2 /* lobby invisible by friends. Peers on invitation only .*/ - -#define RS_CHAT_TYPE_PUBLIC 1 -#define RS_CHAT_TYPE_PRIVATE 2 -#define RS_CHAT_TYPE_LOBBY 3 -#define RS_CHAT_TYPE_DISTANT 4 - -const ChatLobbyFlags RS_CHAT_LOBBY_FLAGS_AUTO_SUBSCRIBE( 0x00000001 ) ; -const ChatLobbyFlags RS_CHAT_LOBBY_FLAGS_deprecated ( 0x00000002 ) ; -const ChatLobbyFlags RS_CHAT_LOBBY_FLAGS_PUBLIC ( 0x00000004 ) ; -const ChatLobbyFlags RS_CHAT_LOBBY_FLAGS_CHALLENGE ( 0x00000008 ) ; -const ChatLobbyFlags RS_CHAT_LOBBY_FLAGS_PGP_SIGNED ( 0x00000010 ) ; // requires the signing ID to be PGP-linked. Avoids anonymous crap. - -typedef uint64_t ChatLobbyId ; -typedef uint64_t ChatLobbyMsgId ; -typedef std::string ChatLobbyNickName ; -typedef std::string RsMailMessageId; // TODO: rebase on t_RsGenericIdType - -/** - * Used to return a tracker id so the API user can keep track of sent mail - * status, it contains mail id, and recipient id - */ -struct RsMailIdRecipientIdPair : RsSerializable -{ - RsMailIdRecipientIdPair(RsMailMessageId mailId, RsGxsId recipientId): - mMailId(mailId), mRecipientId(recipientId) {} - - RsMailMessageId mMailId; - RsGxsId mRecipientId; - - /// @see RsSerializable - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext &ctx ) override; - - bool operator<(const RsMailIdRecipientIdPair& other) const; - bool operator==(const RsMailIdRecipientIdPair& other) const; - - RsMailIdRecipientIdPair() = default; - ~RsMailIdRecipientIdPair() override = default; -}; - -namespace Rs -{ -namespace Msgs -{ - -class MsgAddress -{ - public: - typedef enum { MSG_ADDRESS_TYPE_UNKNOWN = 0x00, - MSG_ADDRESS_TYPE_RSPEERID = 0x01, - MSG_ADDRESS_TYPE_RSGXSID = 0x02, - MSG_ADDRESS_TYPE_EMAIL = 0x03 } AddressType; - - typedef enum { MSG_ADDRESS_MODE_UNKNOWN = 0x00, - MSG_ADDRESS_MODE_TO = 0x01, - MSG_ADDRESS_MODE_CC = 0x02, - MSG_ADDRESS_MODE_BCC = 0x03 } AddressMode; - - explicit MsgAddress(const RsGxsId& gid, MsgAddress::AddressMode mmode) - : _type(MSG_ADDRESS_TYPE_RSGXSID), _mode(mmode), _addr_string(gid.toStdString()){} - - explicit MsgAddress(const RsPeerId& pid, MsgAddress::AddressMode mmode) - : _type(MSG_ADDRESS_TYPE_RSPEERID), _mode(mmode), _addr_string(pid.toStdString()){} - - explicit MsgAddress(const std::string& email, MsgAddress::AddressMode mmode) - : _type(MSG_ADDRESS_TYPE_EMAIL), _mode(mmode), _addr_string(email){} - - MsgAddress::AddressType type() { return _type ;} - MsgAddress::AddressMode mode() { return _mode ;} - - RsGxsId toGxsId() const { assert(_type==MSG_ADDRESS_TYPE_RSGXSID );return RsGxsId (_addr_string);} - RsPeerId toRsPeerId() const { assert(_type==MSG_ADDRESS_TYPE_RSPEERID);return RsPeerId(_addr_string);} - std::string toEmail() const { assert(_type==MSG_ADDRESS_TYPE_EMAIL );return _addr_string ;} - - private: - AddressType _type ; - AddressMode _mode ; - std::string _addr_string ; -}; - -struct MessageInfo : RsSerializable -{ - MessageInfo(): msgflags(0), size(0), count(0), ts(0) {} - - std::string msgId; - - RsPeerId rspeerid_srcId; - RsGxsId rsgxsid_srcId; - - unsigned int msgflags; - - // friend destinations - // - std::set rspeerid_msgto; // RsPeerId is used here for various purposes: - std::set rspeerid_msgcc; // - real peer ids which are actual friend locations - std::set rspeerid_msgbcc; // - - - // distant peers - // - std::set rsgxsid_msgto; // RsPeerId is used here for various purposes: - std::set rsgxsid_msgcc; // - real peer ids which are actual friend locations - std::set rsgxsid_msgbcc; // - - - std::string title; - std::string msg; - - std::string attach_title; - std::string attach_comment; - std::list files; - - int size; /* total of files */ - int count; /* file count */ - - int ts; - - // RsSerializable interface - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext &ctx ) override - { - RS_SERIAL_PROCESS(msgId); - - RS_SERIAL_PROCESS(rspeerid_srcId); - RS_SERIAL_PROCESS(rsgxsid_srcId); - - RS_SERIAL_PROCESS(msgflags); - - RS_SERIAL_PROCESS(rspeerid_msgto); - RS_SERIAL_PROCESS(rspeerid_msgcc); - RS_SERIAL_PROCESS(rspeerid_msgbcc); - - RS_SERIAL_PROCESS(rsgxsid_msgto); - RS_SERIAL_PROCESS(rsgxsid_msgcc); - RS_SERIAL_PROCESS(rsgxsid_msgcc); - - RS_SERIAL_PROCESS(title); - RS_SERIAL_PROCESS(msg); - - RS_SERIAL_PROCESS(attach_title); - RS_SERIAL_PROCESS(attach_comment); - RS_SERIAL_PROCESS(files); - - RS_SERIAL_PROCESS(size); - RS_SERIAL_PROCESS(count); - - RS_SERIAL_PROCESS(ts); - } - - ~MessageInfo() override; -}; - -struct MsgInfoSummary : RsSerializable -{ - MsgInfoSummary() : msgflags(0), count(0), ts(0) {} - - RsMailMessageId msgId; - RsPeerId srcId; - - uint32_t msgflags; - std::list msgtags; /// that leaves 25 bits for user-defined tags. - - std::string title; - int count; /** file count */ - rstime_t ts; - - - /// @see RsSerializable - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext &ctx) override - { - RS_SERIAL_PROCESS(msgId); - RS_SERIAL_PROCESS(srcId); - - RS_SERIAL_PROCESS(msgflags); - RS_SERIAL_PROCESS(msgtags); - - RS_SERIAL_PROCESS(title); - RS_SERIAL_PROCESS(count); - RS_SERIAL_PROCESS(ts); - } - - ~MsgInfoSummary() override; -}; - -struct MsgTagInfo : RsSerializable -{ - virtual ~MsgTagInfo() = default; - - std::string msgId; - std::list tagIds; - - // RsSerializable interface - void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) { - RS_SERIAL_PROCESS(msgId); - RS_SERIAL_PROCESS(tagIds); - } -}; - -struct MsgTagType : RsSerializable -{ - virtual ~MsgTagType() = default; - /* map containing tagId -> pair (text, rgb color) */ - std::map > types; - - // RsSerializable interface - void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) { - RS_SERIAL_PROCESS(types); - } -}; - -} //namespace Rs -} //namespace Msgs - -enum class RsMailStatusEventCode: uint8_t -{ - NEW_MESSAGE = 0x00, - MESSAGE_REMOVED = 0x01, - MESSAGE_SENT = 0x02, - - /// means the peer received the message - MESSAGE_RECEIVED_ACK = 0x03, - - /// An error occurred attempting to sign the message - SIGNATURE_FAILED = 0x04, - - MESSAGE_CHANGED = 0x05, - TAG_CHANGED = 0x06, -}; - -struct RsMailStatusEvent : RsEvent -{ - RsMailStatusEvent() : RsEvent(RsEventType::MAIL_STATUS) {} - - RsMailStatusEventCode mMailStatusEventCode; - std::set mChangedMsgIds; - - /// @see RsEvent - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - RsEvent::serial_process(j, ctx); - RS_SERIAL_PROCESS(mChangedMsgIds); - RS_SERIAL_PROCESS(mMailStatusEventCode); - } - - ~RsMailStatusEvent() override = default; -}; - -enum class RsMailTagEventCode: uint8_t -{ - TAG_ADDED = 0x00, - TAG_CHANGED = 0x01, - TAG_REMOVED = 0x02, -}; - -struct RsMailTagEvent : RsEvent -{ - RsMailTagEvent() : RsEvent(RsEventType::MAIL_TAG) {} - - RsMailTagEventCode mMailTagEventCode; - std::set mChangedMsgTagIds; - - /// @see RsEvent - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - RsEvent::serial_process(j, ctx); - RS_SERIAL_PROCESS(mChangedMsgTagIds); - RS_SERIAL_PROCESS(mMailTagEventCode); - } - - ~RsMailTagEvent() override = default; -}; - -#define RS_CHAT_PUBLIC 0x0001 -#define RS_CHAT_PRIVATE 0x0002 -#define RS_CHAT_AVATAR_AVAILABLE 0x0004 - -#define RS_DISTANT_CHAT_STATUS_UNKNOWN 0x0000 -#define RS_DISTANT_CHAT_STATUS_TUNNEL_DN 0x0001 -#define RS_DISTANT_CHAT_STATUS_CAN_TALK 0x0002 -#define RS_DISTANT_CHAT_STATUS_REMOTELY_CLOSED 0x0003 - -#define RS_DISTANT_CHAT_ERROR_NO_ERROR 0x0000 -#define RS_DISTANT_CHAT_ERROR_DECRYPTION_FAILED 0x0001 -#define RS_DISTANT_CHAT_ERROR_SIGNATURE_MISMATCH 0x0002 -#define RS_DISTANT_CHAT_ERROR_UNKNOWN_KEY 0x0003 -#define RS_DISTANT_CHAT_ERROR_UNKNOWN_HASH 0x0004 - -#define RS_DISTANT_CHAT_FLAG_SIGNED 0x0001 -#define RS_DISTANT_CHAT_FLAG_SIGNATURE_OK 0x0002 - -// flags to define who we accept to talk to. Each flag *removes* some people. - -#define RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NONE 0x0000 -#define RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NON_CONTACTS 0x0001 -#define RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_EVERYBODY 0x0002 - -#define RS_DISTANT_CHAT_CONTACT_PERMISSION_FLAG_FILTER_NONE 0x0000 -#define RS_DISTANT_CHAT_CONTACT_PERMISSION_FLAG_FILTER_NON_CONTACTS 0x0001 -#define RS_DISTANT_CHAT_CONTACT_PERMISSION_FLAG_FILTER_EVERYBODY 0x0002 - -struct DistantChatPeerInfo : RsSerializable -{ - DistantChatPeerInfo() : status(0),pending_items(0) {} - - RsGxsId to_id ; - RsGxsId own_id ; - DistantChatPeerId peer_id ; // this is the tunnel id actually - uint32_t status ; // see the values in rsmsgs.h - uint32_t pending_items; // items not sent, waiting for a tunnel - - ///* @see RsEvent @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(to_id); - RS_SERIAL_PROCESS(own_id); - RS_SERIAL_PROCESS(peer_id); - RS_SERIAL_PROCESS(status); - RS_SERIAL_PROCESS(pending_items); - } -}; - -// Identifier for an chat endpoint like -// neighbour peer, distant peer, chatlobby, broadcast -class ChatId : RsSerializable -{ -public: - ChatId(); - virtual ~ChatId() = default; - - explicit ChatId(RsPeerId id); - explicit ChatId(ChatLobbyId id); - explicit ChatId(DistantChatPeerId id); - explicit ChatId(std::string str); - static ChatId makeBroadcastId(); - - std::string toStdString() const; - bool operator<(const ChatId& other) const; - bool isSameEndpoint(const ChatId& other) const; - - bool operator==(const ChatId& other) const { return isSameEndpoint(other) ; } - - bool isNotSet() const; - bool isPeerId() const; - bool isDistantChatId() const; - bool isLobbyId() const; - bool isBroadcast() const; - - RsPeerId toPeerId() const; - ChatLobbyId toLobbyId() const; - DistantChatPeerId toDistantChatId() const; - - // for the very specific case of transfering a status string - // from the chatservice to the gui, - // this defines from which peer the status string came from - RsPeerId broadcast_status_peer_id; -private: - enum Type : uint8_t - { TYPE_NOT_SET, - TYPE_PRIVATE, // private chat with directly connected friend, peer_id is valid - TYPE_PRIVATE_DISTANT, // private chat with distant peer, gxs_id is valid - TYPE_LOBBY, // chat lobby id, lobby_id is valid - TYPE_BROADCAST // message to/from all connected peers - }; - - Type type; - RsPeerId peer_id; - DistantChatPeerId distant_chat_id; - ChatLobbyId lobby_id; - - // RsSerializable interface -public: - void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) { - RS_SERIAL_PROCESS(broadcast_status_peer_id); - RS_SERIAL_PROCESS(type); - RS_SERIAL_PROCESS(peer_id); - RS_SERIAL_PROCESS(distant_chat_id); - RS_SERIAL_PROCESS(lobby_id); - } -}; - -struct ChatMessage : RsSerializable -{ - ChatId chat_id; // id of chat endpoint - RsPeerId broadcast_peer_id; // only used for broadcast chat: source peer id - RsGxsId lobby_peer_gxs_id; // only used for lobbys: nickname of message author - std::string peer_alternate_nickname; // only used when key is unknown. - - unsigned int chatflags; - uint32_t sendTime; - uint32_t recvTime; - std::string msg; - bool incoming; - bool online; // for outgoing messages: was this message send? - //bool system_message; - - ///* @see RsEvent @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(chat_id); - RS_SERIAL_PROCESS(broadcast_peer_id); - RS_SERIAL_PROCESS(lobby_peer_gxs_id); - RS_SERIAL_PROCESS(peer_alternate_nickname); - - RS_SERIAL_PROCESS(chatflags); - RS_SERIAL_PROCESS(sendTime); - RS_SERIAL_PROCESS(recvTime); - RS_SERIAL_PROCESS(msg); - RS_SERIAL_PROCESS(incoming); - RS_SERIAL_PROCESS(online); - } -}; - -class ChatLobbyInvite : RsSerializable -{ -public: - virtual ~ChatLobbyInvite() = default; - - ChatLobbyId lobby_id ; - RsPeerId peer_id ; - std::string lobby_name ; - std::string lobby_topic ; - ChatLobbyFlags lobby_flags ; - - // RsSerializable interface -public: - void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) { - RS_SERIAL_PROCESS(lobby_id); - RS_SERIAL_PROCESS(peer_id); - RS_SERIAL_PROCESS(lobby_name); - RS_SERIAL_PROCESS(lobby_topic); - RS_SERIAL_PROCESS(lobby_flags); - } -}; - -struct VisibleChatLobbyRecord : RsSerializable -{ - VisibleChatLobbyRecord(): - lobby_id(0), total_number_of_peers(0), last_report_time(0) {} - - ChatLobbyId lobby_id ; // unique id of the lobby - std::string lobby_name ; // name to use for this lobby - std::string lobby_topic ; // topic to use for this lobby - std::set participating_friends ; // list of direct friend who participate. - - uint32_t total_number_of_peers ; // total number of particpating peers. Might not be - rstime_t last_report_time ; // last time the lobby was reported. - ChatLobbyFlags lobby_flags ; // see RS_CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC / RS_CHAT_LOBBY_PRIVACY_LEVEL_PRIVATE - - /// @see RsSerializable - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext &ctx) override - { - RS_SERIAL_PROCESS(lobby_id); - RS_SERIAL_PROCESS(lobby_name); - RS_SERIAL_PROCESS(lobby_topic); - RS_SERIAL_PROCESS(participating_friends); - - RS_SERIAL_PROCESS(total_number_of_peers); - RS_SERIAL_PROCESS(last_report_time); - RS_SERIAL_PROCESS(lobby_flags); - } - - ~VisibleChatLobbyRecord() override; -}; - -class ChatLobbyInfo : RsSerializable -{ -public: - virtual ~ChatLobbyInfo() = default; - - ChatLobbyId lobby_id ; // unique id of the lobby - std::string lobby_name ; // name to use for this lobby - std::string lobby_topic ; // topic to use for this lobby - std::set participating_friends ; // list of direct friend who participate. Used to broadcast sent messages. - RsGxsId gxs_id ; // ID to sign messages - - ChatLobbyFlags lobby_flags ; // see RS_CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC / RS_CHAT_LOBBY_PRIVACY_LEVEL_PRIVATE - std::map gxs_ids ; // list of non direct friend who participate. Used to display only. - rstime_t last_activity ; // last recorded activity. Useful for removing dead lobbies. - - virtual void clear() { gxs_ids.clear(); lobby_id = 0; lobby_name.clear(); lobby_topic.clear(); participating_friends.clear(); } - - // RsSerializable interface -public: - void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) { - RS_SERIAL_PROCESS(lobby_id); - RS_SERIAL_PROCESS(lobby_name); - RS_SERIAL_PROCESS(lobby_topic); - RS_SERIAL_PROCESS(participating_friends); - RS_SERIAL_PROCESS(gxs_id); - - RS_SERIAL_PROCESS(lobby_flags); - RS_SERIAL_PROCESS(gxs_ids); - RS_SERIAL_PROCESS(last_activity); - } -}; - - -class RsMsgs; -/** - * @brief Pointer to retroshare's message service - * @jsonapi{development} - */ -extern RsMsgs* rsMsgs; - -class RsMsgs -{ -public: - - /** - * @brief getMessageSummaries - * @jsonapi{development} - * @param[out] msgList - * @return always true - */ - virtual bool getMessageSummaries(std::list &msgList) = 0; - - /** - * @brief getMessage - * @jsonapi{development} - * @param[in] msgId message ID to lookup - * @param[out] msg - * @return true on success - */ - virtual bool getMessage(const std::string &msgId, Rs::Msgs::MessageInfo &msg) = 0; - - /** - * @brief sendMail - * @jsonapi{development} - * @param[in] from GXS id of the author - * @param[in] subject Mail subject - * @param[in] mailBody Mail body - * @param[in] to list of To: recipients - * @param[in] cc list of CC: recipients - * @param[in] bcc list of BCC: recipients - * @param[in] attachments list of suggested files - * @param[out] trackingIds storage for tracking ids for each sent mail - * @param[out] errorMsg error message if errors occurred, empty otherwise - * @return number of successfully sent mails - */ - virtual uint32_t sendMail( - const RsGxsId from, - const std::string& subject, - const std::string& mailBody, - const std::set& to = std::set(), - const std::set& cc = std::set(), - const std::set& bcc = std::set(), - const std::vector& attachments = std::vector(), - std::set& trackingIds = - RS_DEFAULT_STORAGE_PARAM(std::set), - std::string& errorMsg = - RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; - - /** - * @brief getMessageCount - * @jsonapi{development} - * @param[out] nInbox - * @param[out] nInboxNew - * @param[out] nOutbox - * @param[out] nDraftbox - * @param[out] nSentbox - * @param[out] nTrashbox - */ - virtual void getMessageCount(uint32_t &nInbox, uint32_t &nInboxNew, uint32_t &nOutbox, uint32_t &nDraftbox, uint32_t &nSentbox, uint32_t &nTrashbox) = 0; - - /** - * @brief SystemMessage - * @jsonapi{development} - * @param[in] title - * @param[in] message - * @param[in] systemFlag - * @return true on success - */ - virtual bool SystemMessage(const std::string &title, const std::string &message, uint32_t systemFlag) = 0; - - /** - * @brief MessageToDraft - * @jsonapi{development} - * @param[in] info - * @param[in] msgParentId - * @return true on success - */ - virtual bool MessageToDraft(Rs::Msgs::MessageInfo &info, const std::string &msgParentId) = 0; - - /** - * @brief MessageToTrash - * @jsonapi{development} - * @param[in] msgId Id of the message to mode to trash box - * @param[in] bTrash Move to trash if true, otherwise remove from trash - * @return true on success - */ - virtual bool MessageToTrash(const std::string &msgId, bool bTrash) = 0; - - /** - * @brief getMsgParentId - * @jsonapi{development} - * @param[in] msgId - * @param[out] msgParentId - * @return true on success - */ - virtual bool getMsgParentId(const std::string &msgId, std::string &msgParentId) = 0; - - /** - * @brief MessageDelete - * @jsonapi{development} - * @param[in] msgId - * @return true on success - */ - virtual bool MessageDelete(const std::string &msgId) = 0; - - /** - * @brief MessageRead - * @jsonapi{development} - * @param[in] msgId - * @param[in] unreadByUser - * @return true on success - */ - virtual bool MessageRead(const std::string &msgId, bool unreadByUser) = 0; - - /** - * @brief MessageReplied - * @jsonapi{development} - * @param[in] msgId - * @param[in] replied - * @return true on success - */ - virtual bool MessageReplied(const std::string &msgId, bool replied) = 0; - - /** - * @brief MessageForwarded - * @jsonapi{development} - * @param[in] msgId - * @param[in] forwarded - * @return true on success - */ - virtual bool MessageForwarded(const std::string &msgId, bool forwarded) = 0; - - /** - * @brief MessageStar - * @jsonapi{development} - * @param[in] msgId - * @param[in] mark - * @return true on success - */ - virtual bool MessageStar(const std::string &msgId, bool mark) = 0; - - /** - * @brief MessageJunk - * @jsonapi{development} - * @param[in] msgId - * @param[in] mark - * @return true on success - */ - virtual bool MessageJunk(const std::string &msgId, bool mark) = 0; - - /** - * @brief MessageLoadEmbeddedImages - * @jsonapi{development} - * @param[in] msgId - * @param[in] load - * @return true on success - */ - virtual bool MessageLoadEmbeddedImages(const std::string &msgId, bool load) = 0; - - /* message tagging */ - /** - * @brief getMessageTagTypes - * @jsonapi{development} - * @param[out] tags - * @return always true - */ - virtual bool getMessageTagTypes(Rs::Msgs::MsgTagType& tags) = 0; - - /** - * @brief setMessageTagType - * @jsonapi{development} - * @param[in] tagId - * @param[in] text - * @param[in] rgb_color - * @return true on success - */ - virtual bool setMessageTagType(uint32_t tagId, std::string& text, uint32_t rgb_color) = 0; - - /** - * @brief removeMessageTagType - * @jsonapi{development} - * @param[in] tagId - * @return true on success - */ - virtual bool removeMessageTagType(uint32_t tagId) = 0; - - /** - * @brief getMessageTag - * @jsonapi{development} - * @param[in] msgId - * @param[out] info - * @return true on success - */ - virtual bool getMessageTag(const std::string &msgId, Rs::Msgs::MsgTagInfo& info) = 0; - - /** - * @brief setMessageTag - * set == false && tagId == 0 --> remove all - * @jsonapi{development} - * @param[in] msgId - * @param[in] tagId - * @param[in] set - * @return true on success - */ - virtual bool setMessageTag(const std::string &msgId, uint32_t tagId, bool set) = 0; - - /** - * @brief resetMessageStandardTagTypes - * @jsonapi{development} - * @param[out] tags - * @return always true - */ - virtual bool resetMessageStandardTagTypes(Rs::Msgs::MsgTagType& tags) = 0; - - /****************************************/ - /* Private distant messages */ - /****************************************/ - - virtual uint32_t getDistantMessagingPermissionFlags()=0 ; - virtual void setDistantMessagingPermissionFlags(uint32_t flags)=0 ; - - /****************************************/ - /* Chat */ - /****************************************/ - // sendChat for broadcast, private, lobby and private distant chat - // note: for lobby chat, you first have to subscribe to a lobby - // for private distant chat, it is reqired to have an active distant chat session - - /** - * @brief sendChat send a chat message to a given id - * @jsonapi{development} - * @param[in] id id to send the message - * @param[in] msg message to send - * @return true on success - */ - virtual bool sendChat(ChatId id, std::string msg) = 0; - - /** - * @brief getMaxMessageSecuritySize get the maximum size of a chta message - * @jsonapi{development} - * @param[in] type chat type - * @return maximum size or zero for infinite - */ - virtual uint32_t getMaxMessageSecuritySize(int type) = 0; - - /** - * @brief sendStatusString send a status string - * @jsonapi{development} - * @param[in] id chat id to send the status string to - * @param[in] status_string status string - */ - virtual void sendStatusString(const ChatId &id, const std::string &status_string) = 0; - - /** - * @brief clearChatLobby clear a chat lobby - * @jsonapi{development} - * @param[in] id chat lobby id to clear - */ - virtual void clearChatLobby(const ChatId &id) = 0; - - /** - * @brief setCustomStateString set your custom status message - * @jsonapi{development} - * @param[in] status_string status message - */ - virtual void setCustomStateString(const std::string &status_string) = 0; - - /** - * @brief getCustomStateString get your custom status message - * @return status message - */ - virtual std::string getCustomStateString() = 0; - - /** - * @brief getCustomStateString get the custom status message from a peer - * @jsonapi{development} - * @param[in] peer_id peer id to the peer you want to get the status message from - * @return status message - */ - virtual std::string getCustomStateString(const RsPeerId &peer_id) = 0; - -// get avatar data for peer pid -virtual void getAvatarData(const RsPeerId& pid,unsigned char *& data,int& size) = 0 ; -// set own avatar data -virtual void setOwnAvatarData(const unsigned char *data,int size) = 0 ; -virtual void getOwnAvatarData(unsigned char *& data,int& size) = 0 ; - - /****************************************/ - /* Chat lobbies */ - /****************************************/ - /** - * @brief joinVisibleChatLobby join a lobby that is visible - * @jsonapi{development} - * @param[in] lobby_id lobby to join to - * @param[in] own_id chat id to use - * @return true on success - */ - virtual bool joinVisibleChatLobby(const ChatLobbyId &lobby_id, const RsGxsId &own_id) = 0 ; - - /** - * @brief getChatLobbyList get ids of subscribed lobbies - * @jsonapi{development} - * @param[out] cl_list lobby list - */ - virtual void getChatLobbyList(std::list &cl_list) = 0; - - /** - * @brief getChatLobbyInfo get lobby info of a subscribed chat lobby. Returns true if lobby id is valid. - * @jsonapi{development} - * @param[in] id id to get infos from - * @param[out] info lobby infos - * @return true on success - */ - virtual bool getChatLobbyInfo(const ChatLobbyId &id, ChatLobbyInfo &info) = 0 ; - - /** - * @brief getListOfNearbyChatLobbies get info about all lobbies, subscribed and unsubscribed - * @jsonapi{development} - * @param[out] public_lobbies list of all visible lobbies - */ - virtual void getListOfNearbyChatLobbies(std::vector &public_lobbies) = 0 ; - - /** - * @brief invitePeerToLobby invite a peer to join a lobby - * @jsonapi{development} - * @param[in] lobby_id lobby it to invite into - * @param[in] peer_id peer to invite - */ - virtual void invitePeerToLobby(const ChatLobbyId &lobby_id, const RsPeerId &peer_id) = 0; - - /** - * @brief acceptLobbyInvite accept a chat invite - * @jsonapi{development} - * @param[in] id chat lobby id you were invited into and you want to join - * @param[in] identity chat identity to use - * @return true on success - */ - virtual bool acceptLobbyInvite(const ChatLobbyId &id, const RsGxsId &identity) = 0 ; - - /** - * @brief denyLobbyInvite deny a chat lobby invite - * @jsonapi{development} - * @param[in] id chat lobby id you were invited into - * @return true on success - */ - virtual bool denyLobbyInvite(const ChatLobbyId &id) = 0 ; - - /** - * @brief getPendingChatLobbyInvites get a list of all pending chat lobby invites - * @jsonapi{development} - * @param[out] invites list of all pending chat lobby invites - */ - virtual void getPendingChatLobbyInvites(std::list &invites) = 0; - - /** - * @brief unsubscribeChatLobby leave a chat lobby - * @jsonapi{development} - * @param[in] lobby_id lobby to leave - */ - virtual void unsubscribeChatLobby(const ChatLobbyId &lobby_id) = 0; - - /** - * @brief sendLobbyStatusPeerLeaving notify friend nodes that we're leaving a subscribed lobby - * @jsonapi{development} - * @param[in] lobby_id lobby to leave - */ - virtual void sendLobbyStatusPeerLeaving(const ChatLobbyId& lobby_id) = 0; - - /** - * @brief setIdentityForChatLobby set the chat identit - * @jsonapi{development} - * @param[in] lobby_id lobby to change the chat idnetity for - * @param[in] nick new chat identity - * @return true on success - */ - virtual bool setIdentityForChatLobby(const ChatLobbyId &lobby_id, const RsGxsId &nick) = 0; - - /** - * @brief getIdentityForChatLobby - * @jsonapi{development} - * @param[in] lobby_id lobby to get the chat id from - * @param[out] nick chat identity - * @return true on success - */ - virtual bool getIdentityForChatLobby(const ChatLobbyId &lobby_id, RsGxsId &nick) = 0 ; - - /** - * @brief setDefaultIdentityForChatLobby set the default identity used for chat lobbies - * @jsonapi{development} - * @param[in] nick chat identitiy to use - * @return true on success - */ - virtual bool setDefaultIdentityForChatLobby(const RsGxsId &nick) = 0; - - /** - * @brief getDefaultIdentityForChatLobby get the default identity used for chat lobbies - * @jsonapi{development} - * @param[out] id chat identitiy to use - */ - virtual void getDefaultIdentityForChatLobby(RsGxsId &id) = 0 ; - - /** - * @brief setLobbyAutoSubscribe enable or disable auto subscribe for a chat lobby - * @jsonapi{development} - * @param[in] lobby_id lobby to auto (un)subscribe - * @param[in] autoSubscribe set value for auto subscribe - */ - virtual void setLobbyAutoSubscribe(const ChatLobbyId &lobby_id, const bool autoSubscribe) = 0 ; - - /** - * @brief getLobbyAutoSubscribe get current value of auto subscribe - * @jsonapi{development} - * @param[in] lobby_id lobby to get value from - * @return wether lobby has auto subscribe enabled or disabled - */ - virtual bool getLobbyAutoSubscribe(const ChatLobbyId &lobby_id) = 0 ; - - /** - * @brief createChatLobby create a new chat lobby - * @jsonapi{development} - * @param[in] lobby_name lobby name - * @param[in] lobby_identity chat id to use for new lobby - * @param[in] lobby_topic lobby toppic - * @param[in] invited_friends list of friends to invite - * @param[in] lobby_privacy_type flag for new chat lobby - * @return chat id of new lobby - */ - virtual ChatLobbyId createChatLobby(const std::string &lobby_name, const RsGxsId &lobby_identity, const std::string &lobby_topic, const std::set &invited_friends, ChatLobbyFlags lobby_privacy_type) = 0 ; - -/****************************************/ -/* Distant chat */ -/****************************************/ - - virtual uint32_t getDistantChatPermissionFlags()=0 ; - virtual bool setDistantChatPermissionFlags(uint32_t flags)=0 ; - - /** - * @brief initiateDistantChatConnexion initiate a connexion for a distant chat - * @jsonapi{development} - * @param[in] to_pid RsGxsId to start the connection - * @param[in] from_pid owned RsGxsId who start the connection - * @param[out] pid distant chat id - * @param[out] error_code if the connection can't be stablished - * @param[in] notify notify remote that the connection is stablished - * @return true on success. If you try to initate a connection already started it will return the pid of it. - */ - virtual bool initiateDistantChatConnexion( - const RsGxsId& to_pid, const RsGxsId& from_pid, - DistantChatPeerId& pid, uint32_t& error_code, - bool notify = true ) = 0; - - /** - * @brief getDistantChatStatus receives distant chat info to a given distant chat id - * @jsonapi{development} - * @param[in] pid distant chat id - * @param[out] info distant chat info - * @return true on success - */ - virtual bool getDistantChatStatus(const DistantChatPeerId& pid, DistantChatPeerInfo& info)=0; - - /** - * @brief closeDistantChatConnexion - * @jsonapi{development} - * @param[in] pid distant chat id to close the connection - * @return true on success - */ - virtual bool closeDistantChatConnexion(const DistantChatPeerId& pid)=0; - - /** - * @brief MessageSend - * @jsonapi{development} - * @param[in] info - * @return always true - */ - RS_DEPRECATED_FOR(sendMail) - virtual bool MessageSend(Rs::Msgs::MessageInfo &info) = 0; - - virtual ~RsMsgs(); -}; diff --git a/libretroshare/src/retroshare/rsnotify.h b/libretroshare/src/retroshare/rsnotify.h deleted file mode 100644 index aeb701066..000000000 --- a/libretroshare/src/retroshare/rsnotify.h +++ /dev/null @@ -1,246 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsnotify.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include -#include - -#include "rsturtle.h" -#include "rsgxsifacetypes.h" -#include "util/rsdeprecate.h" - -class ChatId; -class ChatMessage; -struct RsGxsChanges; - -class RsNotify; -extern RsNotify *rsNotify; - -const uint32_t RS_SYS_ERROR = 0x0001; -const uint32_t RS_SYS_WARNING = 0x0002; -const uint32_t RS_SYS_INFO = 0x0004; - -const uint32_t RS_POPUP_MSG = 0x0001; -const uint32_t RS_POPUP_CHAT = 0x0002; -//const uint32_t RS_POPUP_CALL = 0x0004; -const uint32_t RS_POPUP_CONNECT = 0x0008; -const uint32_t RS_SYSTRAY_GROUP_MSG = 0x0010; -const uint32_t RS_POPUP_DOWNLOAD = 0x0020; -const uint32_t RS_POPUP_GROUPCHAT = 0x0040; -const uint32_t RS_POPUP_CHATLOBBY = 0x0080; -const uint32_t RS_POPUP_CONNECT_ATTEMPT = 0x0100; -const uint32_t RS_POPUP_ENCRYPTED_MSG = 0x0200; - -/* CHAT flags are here - so they are in the same place as - * other Notify flags... not used by libretroshare though - */ -const uint32_t RS_CHAT_OPEN = 0x0001; -//const uint32_t free = 0x0002; -const uint32_t RS_CHAT_FOCUS = 0x0004; -const uint32_t RS_CHAT_TABBED_WINDOW = 0x0008; -const uint32_t RS_CHAT_BLINK = 0x0010; - -const uint32_t RS_FEED_TYPE_PEER = 0x0010; -const uint32_t RS_FEED_TYPE_CHANNEL = 0x0020; -const uint32_t RS_FEED_TYPE_FORUM = 0x0040; -//const uint32_t RS_FEED_TYPE_BLOG = 0x0080; -const uint32_t RS_FEED_TYPE_CHAT = 0x0100; -const uint32_t RS_FEED_TYPE_MSG = 0x0200; -const uint32_t RS_FEED_TYPE_FILES = 0x0400; -const uint32_t RS_FEED_TYPE_SECURITY = 0x0800; -const uint32_t RS_FEED_TYPE_POSTED = 0x1000; -const uint32_t RS_FEED_TYPE_SECURITY_IP = 0x2000; -const uint32_t RS_FEED_TYPE_CIRCLE = 0x4000; - -const uint32_t RS_FEED_ITEM_PEER_CONNECT = RS_FEED_TYPE_PEER | 0x0001; -const uint32_t RS_FEED_ITEM_PEER_DISCONNECT = RS_FEED_TYPE_PEER | 0x0002; -const uint32_t RS_FEED_ITEM_PEER_HELLO = RS_FEED_TYPE_PEER | 0x0003; -const uint32_t RS_FEED_ITEM_PEER_NEW = RS_FEED_TYPE_PEER | 0x0004; -const uint32_t RS_FEED_ITEM_PEER_OFFSET = RS_FEED_TYPE_PEER | 0x0005; -const uint32_t RS_FEED_ITEM_PEER_DENIES_CONNEXION = RS_FEED_TYPE_PEER | 0x0006; - -const uint32_t RS_FEED_ITEM_SEC_CONNECT_ATTEMPT = RS_FEED_TYPE_SECURITY | 0x0001; -const uint32_t RS_FEED_ITEM_SEC_AUTH_DENIED = RS_FEED_TYPE_SECURITY | 0x0002; // locally denied connection -const uint32_t RS_FEED_ITEM_SEC_UNKNOWN_IN = RS_FEED_TYPE_SECURITY | 0x0003; -const uint32_t RS_FEED_ITEM_SEC_UNKNOWN_OUT = RS_FEED_TYPE_SECURITY | 0x0004; -const uint32_t RS_FEED_ITEM_SEC_WRONG_SIGNATURE = RS_FEED_TYPE_SECURITY | 0x0005; -const uint32_t RS_FEED_ITEM_SEC_BAD_CERTIFICATE = RS_FEED_TYPE_SECURITY | 0x0006; -const uint32_t RS_FEED_ITEM_SEC_INTERNAL_ERROR = RS_FEED_TYPE_SECURITY | 0x0007; -const uint32_t RS_FEED_ITEM_SEC_MISSING_CERTIFICATE = RS_FEED_TYPE_SECURITY | 0x0008; - -const uint32_t RS_FEED_ITEM_SEC_IP_BLACKLISTED = RS_FEED_TYPE_SECURITY_IP | 0x0001; -const uint32_t RS_FEED_ITEM_SEC_IP_WRONG_EXTERNAL_IP_REPORTED = RS_FEED_TYPE_SECURITY_IP | 0x0002; - -const uint32_t RS_FEED_ITEM_CHANNEL_NEW = RS_FEED_TYPE_CHANNEL | 0x0001; -//const uint32_t RS_FEED_ITEM_CHANNEL_UPDATE = RS_FEED_TYPE_CHANNEL | 0x0002; -const uint32_t RS_FEED_ITEM_CHANNEL_MSG = RS_FEED_TYPE_CHANNEL | 0x0003; -const uint32_t RS_FEED_ITEM_CHANNEL_PUBLISHKEY = RS_FEED_TYPE_CHANNEL | 0x0004; - -const uint32_t RS_FEED_ITEM_FORUM_NEW = RS_FEED_TYPE_FORUM | 0x0001; -//const uint32_t RS_FEED_ITEM_FORUM_UPDATE = RS_FEED_TYPE_FORUM | 0x0002; -const uint32_t RS_FEED_ITEM_FORUM_MSG = RS_FEED_TYPE_FORUM | 0x0003; -const uint32_t RS_FEED_ITEM_FORUM_PUBLISHKEY = RS_FEED_TYPE_FORUM | 0x0004; - -//const uint32_t RS_FEED_ITEM_BLOG_NEW = RS_FEED_TYPE_BLOG | 0x0001; -//const uint32_t RS_FEED_ITEM_BLOG_UPDATE = RS_FEED_TYPE_BLOG | 0x0002; -//const uint32_t RS_FEED_ITEM_BLOG_MSG = RS_FEED_TYPE_BLOG | 0x0003; - -const uint32_t RS_FEED_ITEM_POSTED_NEW = RS_FEED_TYPE_POSTED | 0x0001; -//const uint32_t RS_FEED_ITEM_POSTED_UPDATE = RS_FEED_TYPE_POSTED | 0x0002; -const uint32_t RS_FEED_ITEM_POSTED_MSG = RS_FEED_TYPE_POSTED | 0x0003; - -const uint32_t RS_FEED_ITEM_CHAT_NEW = RS_FEED_TYPE_CHAT | 0x0001; -const uint32_t RS_FEED_ITEM_MESSAGE = RS_FEED_TYPE_MSG | 0x0001; -const uint32_t RS_FEED_ITEM_FILES_NEW = RS_FEED_TYPE_FILES | 0x0001; - -const uint32_t RS_FEED_ITEM_CIRCLE_MEMB_REQ = RS_FEED_TYPE_CIRCLE | 0x0001; -const uint32_t RS_FEED_ITEM_CIRCLE_INVITE_REC = RS_FEED_TYPE_CIRCLE | 0x0002; -const uint32_t RS_FEED_ITEM_CIRCLE_MEMB_LEAVE = RS_FEED_TYPE_CIRCLE | 0x0003; -const uint32_t RS_FEED_ITEM_CIRCLE_MEMB_JOIN = RS_FEED_TYPE_CIRCLE | 0x0004; -const uint32_t RS_FEED_ITEM_CIRCLE_MEMB_ACCEPTED = RS_FEED_TYPE_CIRCLE | 0x0005; -const uint32_t RS_FEED_ITEM_CIRCLE_MEMB_REVOKED = RS_FEED_TYPE_CIRCLE | 0x0006; -const uint32_t RS_FEED_ITEM_CIRCLE_INVITE_CANCELLED= RS_FEED_TYPE_CIRCLE | 0x0007; - -const uint32_t RS_MESSAGE_CONNECT_ATTEMPT = 0x0001; - -const int NOTIFY_LIST_NEIGHBOURS = 1; -const int NOTIFY_LIST_FRIENDS = 2; -const int NOTIFY_LIST_SEARCHLIST = 4; -const int NOTIFY_LIST_CHANNELLIST = 6; -const int NOTIFY_LIST_TRANSFERLIST = 7; -const int NOTIFY_LIST_CONFIG = 8; -const int NOTIFY_LIST_DIRLIST_LOCAL = 9; -const int NOTIFY_LIST_DIRLIST_FRIENDS = 10; -const int NOTIFY_LIST_FORUMLIST_LOCKED = 11; // use connect with Qt::QueuedConnection -const int NOTIFY_LIST_PUBLIC_CHAT = 13; -const int NOTIFY_LIST_PRIVATE_INCOMING_CHAT = 14; -const int NOTIFY_LIST_PRIVATE_OUTGOING_CHAT = 15; -const int NOTIFY_LIST_GROUPLIST = 16; -const int NOTIFY_LIST_CHANNELLIST_LOCKED = 17; // use connect with Qt::QueuedConnection -const int NOTIFY_LIST_CHAT_LOBBY_INVITATION = 18; -const int NOTIFY_LIST_CHAT_LOBBY_LIST = 19; - -const int NOTIFY_TYPE_SAME = 0x01; -const int NOTIFY_TYPE_MOD = 0x02; /* general purpose, check all */ -const int NOTIFY_TYPE_ADD = 0x04; /* flagged additions */ -const int NOTIFY_TYPE_DEL = 0x08; /* flagged deletions */ - -const uint32_t NOTIFY_HASHTYPE_EXAMINING_FILES = 1; /* Examining shared files */ -const uint32_t NOTIFY_HASHTYPE_FINISH = 2; /* Finish */ -const uint32_t NOTIFY_HASHTYPE_HASH_FILE = 3; /* Hashing file */ -const uint32_t NOTIFY_HASHTYPE_SAVE_FILE_INDEX = 4; /* Hashing file */ - -class RS_DEPRECATED RsFeedItem -{ - public: - RsFeedItem(uint32_t type, const std::string& id1, const std::string& id2, const std::string& id3, const std::string& id4, uint32_t result1) - :mType(type), mId1(id1), mId2(id2), mId3(id3), mId4(id4), mResult1(result1) {} - - RsFeedItem() :mType(0), mResult1(0) { return; } - - uint32_t mType; - std::string mId1, mId2, mId3, mId4; - uint32_t mResult1; -}; - -// This class implements a generic notify client. To have your own components being notified by -// the Retroshare library, sub-class NotifyClient, and overload the methods you want to make use of -// (The other methods will just ignore the call), and register your ownclient into RsNotify, as: -// -// myNotifyClient: public NotifyClient -// { -// public: -// virtual void void notifyPeerHasNewAvatar(std::string peer_id) -// { -// doMyOwnThing() ; -// } -// } -// -// myNotifyClient *client = new myNotifyClient() ; -// -// rsNotify->registerNotifyClient(client) ; -// -// This mechanism can be used in plugins, new services, etc. -// - -class RS_DEPRECATED NotifyClient; - -class RS_DEPRECATED_FOR(RsEvents) RsNotify -{ - public: - /* registration of notifies clients */ - virtual void registerNotifyClient(NotifyClient *nc) = 0; - /* returns true if NotifyClient was found */ - virtual bool unregisterNotifyClient(NotifyClient *nc) = 0; - - /* Pull methods for retroshare-gui */ - /* this should probably go into a different service. */ - - virtual bool NotifySysMessage(uint32_t &sysid, uint32_t &type, std::string &title, std::string &msg) = 0; - virtual bool NotifyPopupMessage(uint32_t &ptype, std::string &name, std::string &title, std::string &msg) = 0; - virtual bool NotifyLogMessage(uint32_t &sysid, uint32_t &type, std::string &title, std::string &msg) = 0; - - virtual bool GetFeedItem(RsFeedItem &item) = 0; - - virtual bool cachePgpPassphrase (const std::string& /* pgp_passphrase */) { return false ; } - virtual bool clearPgpPassphrase () { return false ; } - - virtual bool setDisableAskPassword (const bool /*bValue*/) { return false ; } -}; - -class RS_DEPRECATED NotifyClient -{ -public: - NotifyClient() {} - virtual ~NotifyClient() {} - - virtual void notifyListPreChange (int /* list */, int /* type */) {} - virtual void notifyListChange (int /* list */, int /* type */) {} - virtual void notifyErrorMsg (int /* list */, int /* sev */, std::string /* msg */) {} - virtual void notifyChatMessage (const ChatMessage& /* msg */) {} - virtual void notifyChatStatus (const ChatId& /* chat_id */, const std::string& /* status_string */) {} - virtual void notifyChatCleared (const ChatId& /* chat_id */) {} - virtual void notifyChatLobbyEvent (uint64_t /* lobby id */, uint32_t /* event type */ ,const RsGxsId& /* nickname */,const std::string& /* any string */) {} - virtual void notifyChatLobbyTimeShift (int /* time_shift*/) {} - virtual void notifyCustomState (const std::string& /* peer_id */, const std::string& /* status_string */) {} - virtual void notifyHashingInfo (uint32_t /* type */, const std::string& /* fileinfo */) {} - virtual void notifyTurtleSearchResult (const RsPeerId& /* pid */, uint32_t /* search_id */, const std::list& /* files */) {} - virtual void notifyPeerHasNewAvatar (std::string /* peer_id */) {} - virtual void notifyOwnAvatarChanged () {} - virtual void notifyOwnStatusMessageChanged () {} - virtual void notifyDiskFull (uint32_t /* location */, uint32_t /* size limit in MB */) {} - virtual void notifyPeerStatusChanged (const std::string& /* peer_id */, uint32_t /* status */) {} - - /* one or more peers has changed the states */ - virtual void notifyPeerStatusChangedSummary () {} - virtual void notifyDiscInfoChanged () {} - - virtual void notifyDownloadComplete (const std::string& /* fileHash */) {} - virtual void notifyDownloadCompleteCount (uint32_t /* count */) {} - virtual void notifyHistoryChanged (uint32_t /* msgId */, int /* type */) {} - - virtual bool askForPassword (const std::string& /* title */, const std::string& /* key_details */, bool /* prev_is_bad */, std::string& /* password */,bool& /* cancelled */ ) { return false ;} - virtual bool askForPluginConfirmation (const std::string& /* plugin_filename */, const std::string& /* plugin_file_hash */,bool /* first_time */) { return false ;} -}; diff --git a/libretroshare/src/retroshare/rspeers.h b/libretroshare/src/retroshare/rspeers.h deleted file mode 100644 index e00576908..000000000 --- a/libretroshare/src/retroshare/rspeers.h +++ /dev/null @@ -1,998 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rspeers.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2008 by Robert Fernie * - * Copyright (C) 2018-2020 Gioacchino Mazzurco * - * Copyright (C) 2020 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include - -#include "retroshare/rstypes.h" -#include "retroshare/rsfiles.h" -#include "retroshare/rsids.h" -#include "util/rsurl.h" -#include "util/rsdeprecate.h" -#include "util/rstime.h" -#include "retroshare/rsevents.h" - -class RsPeers; - -/** - * Pointer to global instance of RsPeers service implementation - * @jsonapi{development} - */ -extern RsPeers* rsPeers; - -/* TODO: 2015/12/31 As for type safetyness all those constant must be declared as enum! - * C++ now supports typed enum so there is no ambiguity in serialization size - */ - -/* Trust Levels. Should be the same values than what is declared in PGPHandler.h */ - -const uint32_t RS_TRUST_LVL_UNDEFINED = 0; -const uint32_t RS_TRUST_LVL_UNKNOWN = 1; -const uint32_t RS_TRUST_LVL_NEVER = 2; -const uint32_t RS_TRUST_LVL_MARGINAL = 3; -const uint32_t RS_TRUST_LVL_FULL = 4; -const uint32_t RS_TRUST_LVL_ULTIMATE = 5; - - -const uint32_t SELF_SIGNATURE_RESULT_PENDING = 0x00; -const uint32_t SELF_SIGNATURE_RESULT_SUCCESS = 0x01; -const uint32_t SELF_SIGNATURE_RESULT_FAILED = 0x02; - -/* Net Mode */ -const uint32_t RS_NETMODE_UDP = 0x0001; -const uint32_t RS_NETMODE_UPNP = 0x0002; -const uint32_t RS_NETMODE_EXT = 0x0003; -const uint32_t RS_NETMODE_HIDDEN = 0x0004; -const uint32_t RS_NETMODE_UNREACHABLE = 0x0005; - -/* Hidden Type */ -const uint32_t RS_HIDDEN_TYPE_NONE = 0x0000; -const uint32_t RS_HIDDEN_TYPE_UNKNOWN = 0x0001; -const uint32_t RS_HIDDEN_TYPE_TOR = 0x0002; -const uint32_t RS_HIDDEN_TYPE_I2P = 0x0004; -/* mask to match all valid hidden types */ -const uint32_t RS_HIDDEN_TYPE_MASK = RS_HIDDEN_TYPE_I2P | RS_HIDDEN_TYPE_TOR; - -/* Visibility parameter for discovery */ -const uint32_t RS_VS_DISC_OFF = 0x0000; -const uint32_t RS_VS_DISC_MINIMAL = 0x0001; -const uint32_t RS_VS_DISC_FULL = 0x0002; - -const uint32_t RS_VS_DHT_OFF = 0x0000; -const uint32_t RS_VS_DHT_PASSIVE = 0x0001; -const uint32_t RS_VS_DHT_FULL = 0x0002; - -/* State */ -const uint32_t RS_PEER_STATE_FRIEND = 0x0001; -const uint32_t RS_PEER_STATE_ONLINE = 0x0002; -const uint32_t RS_PEER_STATE_CONNECTED = 0x0004; -const uint32_t RS_PEER_STATE_UNREACHABLE= 0x0008; - -// Service option flags. -// -const ServicePermissionFlags RS_NODE_PERM_NONE ( 0x00000000 ) ;// 0x1, 0x2 and Ox4 are deprecated. -const ServicePermissionFlags RS_NODE_PERM_DIRECT_DL ( 0x00000008 ) ;// Accept to directly DL from this peer (breaks anonymity) -const ServicePermissionFlags RS_NODE_PERM_ALLOW_PUSH ( 0x00000010 ) ;// Auto-DL files recommended by this peer -const ServicePermissionFlags RS_NODE_PERM_REQUIRE_WL ( 0x00000020 ) ;// Require white list clearance for connection -const ServicePermissionFlags RS_NODE_PERM_DEFAULT = RS_NODE_PERM_DIRECT_DL ; -const ServicePermissionFlags RS_NODE_PERM_ALL = RS_NODE_PERM_DIRECT_DL | RS_NODE_PERM_ALLOW_PUSH | RS_NODE_PERM_REQUIRE_WL; - -// ... - -/* Connect state */ -const uint32_t RS_PEER_CONNECTSTATE_OFFLINE = 0; -const uint32_t RS_PEER_CONNECTSTATE_TRYING_TCP = 2; -const uint32_t RS_PEER_CONNECTSTATE_TRYING_UDP = 3; -const uint32_t RS_PEER_CONNECTSTATE_CONNECTED_TCP = 4; -const uint32_t RS_PEER_CONNECTSTATE_CONNECTED_UDP = 5; -const uint32_t RS_PEER_CONNECTSTATE_CONNECTED_TOR = 6; -const uint32_t RS_PEER_CONNECTSTATE_CONNECTED_I2P = 7; -const uint32_t RS_PEER_CONNECTSTATE_CONNECTED_UNKNOWN = 8; - -/* Error codes for certificate cleaning and cert parsing. Numbers should not overlap. */ - -const int RS_PEER_CERT_CLEANING_CODE_NO_ERROR = 0x00 ; -const int RS_PEER_CERT_CLEANING_CODE_UNKOWN_ERROR = 0x01 ; -const int RS_PEER_CERT_CLEANING_CODE_NO_BEGIN_TAG = 0x02 ; -const int RS_PEER_CERT_CLEANING_CODE_NO_END_TAG = 0x03 ; -const int RS_PEER_CERT_CLEANING_CODE_NO_CHECKSUM = 0x04 ; -const int RS_PEER_CERT_CLEANING_CODE_WRONG_NUMBER = 0x05 ; -const int RS_PEER_CERT_CLEANING_CODE_WRONG_RADIX_CHAR = 0x06 ; - -const uint32_t CERTIFICATE_PARSING_ERROR_NO_ERROR = 0x10 ; -const uint32_t CERTIFICATE_PARSING_ERROR_SIZE_ERROR = 0x11 ; -const uint32_t CERTIFICATE_PARSING_ERROR_INVALID_LOCATION_ID = 0x12 ; -const uint32_t CERTIFICATE_PARSING_ERROR_INVALID_EXTERNAL_IP = 0x13 ; -const uint32_t CERTIFICATE_PARSING_ERROR_INVALID_LOCAL_IP = 0x14 ; -const uint32_t CERTIFICATE_PARSING_ERROR_INVALID_CHECKSUM_SECTION = 0x15 ; -const uint32_t CERTIFICATE_PARSING_ERROR_CHECKSUM_ERROR = 0x16 ; -const uint32_t CERTIFICATE_PARSING_ERROR_UNKNOWN_SECTION_PTAG = 0x17 ; -const uint32_t CERTIFICATE_PARSING_ERROR_MISSING_CHECKSUM = 0x18 ; -const uint32_t CERTIFICATE_PARSING_ERROR_WRONG_VERSION = 0x19 ; -const uint32_t CERTIFICATE_PARSING_ERROR_MISSING_PGP_FINGERPRINT = 0x1a ; -const uint32_t CERTIFICATE_PARSING_ERROR_MISSING_LOCATION_ID = 0x1b ; - -const uint32_t PGP_KEYRING_REMOVAL_ERROR_NO_ERROR = 0x20 ; -const uint32_t PGP_KEYRING_REMOVAL_ERROR_CANT_REMOVE_SECRET_KEYS = 0x21 ; -const uint32_t PGP_KEYRING_REMOVAL_ERROR_CANNOT_CREATE_BACKUP = 0x22 ; -const uint32_t PGP_KEYRING_REMOVAL_ERROR_CANNOT_WRITE_BACKUP = 0x23 ; -const uint32_t PGP_KEYRING_REMOVAL_ERROR_DATA_INCONSISTENCY = 0x24 ; - -/* LinkType Flags */ - -// CONNECTION -const uint32_t RS_NET_CONN_TRANS_MASK = 0x0000ffff; -const uint32_t RS_NET_CONN_TRANS_TCP_MASK = 0x0000000f; -const uint32_t RS_NET_CONN_TRANS_TCP_UNKNOWN = 0x00000001; -const uint32_t RS_NET_CONN_TRANS_TCP_LOCAL = 0x00000002; -const uint32_t RS_NET_CONN_TRANS_TCP_EXTERNAL = 0x00000004; - -const uint32_t RS_NET_CONN_TRANS_UDP_MASK = 0x000000f0; -const uint32_t RS_NET_CONN_TRANS_UDP_UNKNOWN = 0x00000010; -const uint32_t RS_NET_CONN_TRANS_UDP_DIRECT = 0x00000020; -const uint32_t RS_NET_CONN_TRANS_UDP_PROXY = 0x00000040; -const uint32_t RS_NET_CONN_TRANS_UDP_RELAY = 0x00000080; - -const uint32_t RS_NET_CONN_TRANS_OTHER_MASK = 0x00000f00; - -const uint32_t RS_NET_CONN_TRANS_UNKNOWN = 0x00001000; - - -const uint32_t RS_NET_CONN_SPEED_MASK = 0x000f0000; -const uint32_t RS_NET_CONN_SPEED_UNKNOWN = 0x00000000; -const uint32_t RS_NET_CONN_SPEED_TRICKLE = 0x00010000; -const uint32_t RS_NET_CONN_SPEED_LOW = 0x00020000; -const uint32_t RS_NET_CONN_SPEED_NORMAL = 0x00040000; -const uint32_t RS_NET_CONN_SPEED_HIGH = 0x00080000; - -const uint32_t RS_NET_CONN_QUALITY_MASK = 0x00f00000; -const uint32_t RS_NET_CONN_QUALITY_UNKNOWN = 0x00000000; - -// THIS INFO MUST BE SUPPLIED BY PEERMGR.... -const uint32_t RS_NET_CONN_TYPE_MASK = 0x0f000000; -const uint32_t RS_NET_CONN_TYPE_UNKNOWN = 0x00000000; -const uint32_t RS_NET_CONN_TYPE_ACQUAINTANCE = 0x01000000; -const uint32_t RS_NET_CONN_TYPE_FRIEND = 0x02000000; -const uint32_t RS_NET_CONN_TYPE_SERVER = 0x04000000; -const uint32_t RS_NET_CONN_TYPE_CLIENT = 0x08000000; - -// working state of proxy - -const uint32_t RS_NET_PROXY_STATUS_UNKNOWN = 0x0000 ; -const uint32_t RS_NET_PROXY_STATUS_OK = 0x0001 ; - -// Potential certificate parsing errors. - - -/* Groups */ -static const RsNodeGroupId RS_GROUP_ID_FRIENDS ("00000000000000000000000000000001"); -static const RsNodeGroupId RS_GROUP_ID_FAMILY ("00000000000000000000000000000002"); -static const RsNodeGroupId RS_GROUP_ID_COWORKERS ("00000000000000000000000000000003"); -static const RsNodeGroupId RS_GROUP_ID_OTHERS ("00000000000000000000000000000004"); -static const RsNodeGroupId RS_GROUP_ID_FAVORITES ("00000000000000000000000000000005"); - -#define RS_GROUP_DEFAULT_NAME_FRIENDS "Friends" -#define RS_GROUP_DEFAULT_NAME_FAMILY "Family" -#define RS_GROUP_DEFAULT_NAME_COWORKERS "Co-Workers" -#define RS_GROUP_DEFAULT_NAME_OTHERS "Other Contacts" -#define RS_GROUP_DEFAULT_NAME_FAVORITES "Favorites" - -const uint32_t RS_GROUP_FLAG_STANDARD = 0x0001; - -/* A couple of helper functions for translating the numbers games */ - -std::string RsPeerTrustString(uint32_t trustLvl); -std::string RsPeerNetModeString(uint32_t netModel); -std::string RsPeerLastConnectString(uint32_t lastConnect); - -//===================================================================================================// -// Connexion and security events // -//===================================================================================================// - -enum class RsAuthSslError: uint8_t -{ -// NO_ERROR = 0x00, // enabling break windows build - MISSING_AUTHENTICATION_INFO = 0x01, - PGP_SIGNATURE_VALIDATION_FAILED = 0x02, - MISMATCHED_PGP_ID = 0x03, - NO_CERTIFICATE_SUPPLIED = 0x04, - NOT_A_FRIEND = 0x05, - MISSING_CERTIFICATE = 0x06, - IP_IS_BLACKLISTED = 0x07, - PEER_REFUSED_CONNECTION = 0x08, - UNKNOWN_ERROR = 0x09, -}; - -/** - * Event triggered by AuthSSL when authentication of a connection attempt either - * fail or success - */ -struct RsAuthSslConnectionAutenticationEvent : RsEvent -{ - RsAuthSslConnectionAutenticationEvent() : - RsEvent(RsEventType::AUTHSSL_CONNECTION_AUTENTICATION) {} - - RsPeerId mSslId; - std::string mSslCn; - RsPgpId mPgpId; - RsUrl mLocator; - std::string mErrorMsg; - RsAuthSslError mErrorCode; - - ///* @see RsEvent @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - RsEvent::serial_process(j, ctx); - RS_SERIAL_PROCESS(mSslId); - RS_SERIAL_PROCESS(mSslCn); - RS_SERIAL_PROCESS(mPgpId); - RS_SERIAL_PROCESS(mLocator); - RS_SERIAL_PROCESS(mErrorMsg); - RS_SERIAL_PROCESS(mErrorCode); - } - - ~RsAuthSslConnectionAutenticationEvent() override; -}; - -enum class RsConnectionEventCode: uint8_t -{ - UNKNOWN = 0x00, - PEER_CONNECTED = 0x01, - PEER_DISCONNECTED = 0x02, - PEER_TIME_SHIFT = 0x03, // mTimeShift = time shift in seconds - PEER_REPORTS_WRONG_IP = 0x04, // mPeerLocator = address reported, mOwnLocator = own address -}; - -struct RsConnectionEvent : RsEvent -{ - RsConnectionEvent() - : RsEvent(RsEventType::PEER_CONNECTION), - mConnectionInfoCode(RsConnectionEventCode::UNKNOWN), mTimeShift(0) {} - - RsConnectionEventCode mConnectionInfoCode; - RsPeerId mSslId; - RsUrl mOwnLocator; - RsUrl mReportedLocator; - - /** If there is a time shift with the peer aka - * mConnectionInfoCode == PEER_TIME_SHIFT contains the time shift value in - * seconds */ - rstime_t mTimeShift; - - ///* @see RsEvent @see RsSerializable - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RsEvent::serial_process(j, ctx); - RS_SERIAL_PROCESS(mConnectionInfoCode); - RS_SERIAL_PROCESS(mSslId); - RS_SERIAL_PROCESS(mOwnLocator); - RS_SERIAL_PROCESS(mReportedLocator); - RS_SERIAL_PROCESS(mTimeShift); - } - - ~RsConnectionEvent() override; -}; - -enum class RsNetworkEventCode: uint8_t { - UNKNOWN = 0x00, - LOCAL_IP_UPDATED = 0x01, - EXTERNAL_IP_UPDATED = 0x02, -}; - -struct RsNetworkEvent : RsEvent -{ - RsNetworkEvent() - : RsEvent(RsEventType::NETWORK), - mNetworkEventCode(RsNetworkEventCode::UNKNOWN){} - - RsNetworkEventCode mNetworkEventCode; - std::string mIPAddress; // local or external IP depending on the event type - - ///* @see RsEvent @see RsSerializable - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RsEvent::serial_process(j, ctx); - RS_SERIAL_PROCESS(mNetworkEventCode); - RS_SERIAL_PROCESS(mIPAddress); - } -}; - -//===================================================================================================// -// Peer Details // -//===================================================================================================// - -/* We should definitely split this into 2 sub-structures: - * PGP info (or profile info) with all info related to PGP keys - * peer info: all network related information - * - * Plus top level information: - * isOnlyPgpDetail (this could be obsolete if the methods to query about PGP info is a different function) - * peer Id - */ -struct RsPeerDetails : RsSerializable -{ - RsPeerDetails(); - - /* Auth details */ - bool isOnlyGPGdetail; - RsPeerId id; - RsPgpId gpg_id; - - std::string name; - std::string email; - std::string location; - std::string org; - - RsPgpId issuer; - - RsPgpFingerprint fpr; /* pgp fingerprint */ - std::string authcode; // TODO: 2015/12/31 (cyril) what is this used for ????? - std::list gpgSigners; - - uint32_t trustLvl; - uint32_t validLvl; - - bool skip_pgp_signature_validation; - bool ownsign; /* we have signed the remote peer GPG key */ - bool hasSignedMe; /* the remote peer has signed my GPG key */ - - bool accept_connection; - - /* Peer permission flags. What services the peer can use (Only valid if friend).*/ - ServicePermissionFlags service_perm_flags ; - - /* Network details (only valid if friend) */ - uint32_t state; - bool actAsServer; - - // TODO: 2015/12/31 to take advantage of multiple connection this must be - // replaced by a set of addresses - std::string connectAddr ; // current address if connected. - uint16_t connectPort ; - - // Hidden Node details. - bool isHiddenNode; - std::string hiddenNodeAddress; - uint16_t hiddenNodePort; - uint32_t hiddenType; - - // Filled in for Standard Node. - std::string localAddr; - uint16_t localPort; - std::string extAddr; - uint16_t extPort; - std::string dyndns; - std::list ipAddressList; - - uint32_t netMode; - /* vis State */ - uint16_t vs_disc; - uint16_t vs_dht; - - /* basic stats */ - uint32_t lastConnect; /* how long ago */ - uint32_t lastUsed; /* how long ago since last used: signature verif, connect attempt, etc */ - uint32_t connectState; /* RS_PEER_CONNECTSTATE_... */ - std::string connectStateString; /* Additional string like ip address */ - uint32_t connectPeriod; - bool foundDHT; - - /* have we been denied */ - bool wasDeniedConnection; - rstime_t deniedTS; - - /* linkType */ - uint32_t linkType; - - /// @see RsSerializable - virtual void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(isOnlyGPGdetail); - RS_SERIAL_PROCESS(id); - RS_SERIAL_PROCESS(gpg_id); - RS_SERIAL_PROCESS(name); - RS_SERIAL_PROCESS(email); - RS_SERIAL_PROCESS(location); - RS_SERIAL_PROCESS(org); - RS_SERIAL_PROCESS(issuer); - RS_SERIAL_PROCESS(fpr); - RS_SERIAL_PROCESS(authcode); - RS_SERIAL_PROCESS(gpgSigners); - RS_SERIAL_PROCESS(trustLvl); - RS_SERIAL_PROCESS(validLvl); - RS_SERIAL_PROCESS(ownsign); - RS_SERIAL_PROCESS(hasSignedMe); - RS_SERIAL_PROCESS(accept_connection); - RS_SERIAL_PROCESS(service_perm_flags); - RS_SERIAL_PROCESS(state); - RS_SERIAL_PROCESS(actAsServer); - RS_SERIAL_PROCESS(connectAddr); - RS_SERIAL_PROCESS(connectPort); - RS_SERIAL_PROCESS(isHiddenNode); - RS_SERIAL_PROCESS(hiddenNodeAddress); - RS_SERIAL_PROCESS(hiddenNodePort); - RS_SERIAL_PROCESS(hiddenType); - RS_SERIAL_PROCESS(localAddr); - RS_SERIAL_PROCESS(localPort); - RS_SERIAL_PROCESS(extAddr); - RS_SERIAL_PROCESS(extPort); - RS_SERIAL_PROCESS(dyndns); - RS_SERIAL_PROCESS(ipAddressList); - RS_SERIAL_PROCESS(netMode); - RS_SERIAL_PROCESS(vs_disc); - RS_SERIAL_PROCESS(vs_dht); - RS_SERIAL_PROCESS(lastConnect); - RS_SERIAL_PROCESS(lastUsed); - RS_SERIAL_PROCESS(connectState); - RS_SERIAL_PROCESS(connectStateString); - RS_SERIAL_PROCESS(connectPeriod); - RS_SERIAL_PROCESS(foundDHT); - RS_SERIAL_PROCESS(wasDeniedConnection); - RS_SERIAL_PROCESS(deniedTS); - RS_SERIAL_PROCESS(linkType); - } -}; - -// This class is used to get info about crytographic algorithms used with a -// particular peer. -struct RsPeerCryptoParams -{ - int connexion_state; - std::string cipher_name; -}; - -struct RsGroupInfo : RsSerializable -{ - RsGroupInfo(); - - RsNodeGroupId id; - std::string name; - uint32_t flag; - - std::set peerIds; - - /// @see RsSerializable - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext &ctx) - { - RS_SERIAL_PROCESS(id); - RS_SERIAL_PROCESS(name); - RS_SERIAL_PROCESS(flag); - RS_SERIAL_PROCESS(peerIds); - } -}; - -/** Event emitted when a peer change state */ -struct RsPeerStateChangedEvent : RsEvent -{ - /// @param[in] sslId is of the peer which changed state - explicit RsPeerStateChangedEvent(RsPeerId sslId); - - /// Storage fot the id of the peer that changed state - RsPeerId mSslId; - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - RsEvent::serial_process(j, ctx); - RS_SERIAL_PROCESS(mSslId); - } -}; - -enum class RetroshareInviteFlags:uint32_t { - NOTHING = 0x00, - CURRENT_IP = 0x01, - FULL_IP_HISTORY = 0x02, - DNS = 0x04, - RADIX_FORMAT = 0x08, - PGP_SIGNATURES = 0x10, -}; -RS_REGISTER_ENUM_FLAGS_TYPE(RetroshareInviteFlags) - -/** The Main Interface Class - for information about your Peers - * A peer is another RS instance, means associated with an SSL certificate - * A same GPG person can have multiple peer running with different SSL certs - * signed by the same GPG key - * Thus a peer have SSL cert details, and also the parent GPG details - */ -class RsPeers -{ -public: - - /** - * @brief Get own SSL peer id - * @return own peer id - */ - virtual const RsPeerId& getOwnId() = 0; - - virtual bool haveSecretKey(const RsPgpId& gpg_id) = 0 ; - - /** - * @brief Get trusted peers list - * @jsonapi{development} - * @param[out] sslIds storage for the trusted peers - * @return false if error occurred, true otherwise - */ - virtual bool getFriendList(std::list& sslIds) = 0; - - /** - * @brief Get trusted PGP ids list - * @jsonapi{development} - * @param[out] pgpIds storage for the trusted PGP ids - * @return false if error occurred, true otherwise - */ - virtual bool getPgpFriendList(std::vector& pgpIds) = 0; - - /** - * @brief Get connected peers list - * @jsonapi{development} - * @param[out] sslIds storage for the peers - * @return false if error occurred, true otherwise - */ - virtual bool getOnlineList(std::list &sslIds) = 0; - - /** - * @brief Get peers count - * @jsonapi{development} - * @param[out] peersCount storage for trusted peers count - * @param[out] onlinePeersCount storage for online peers count - * @param[in] countLocations true to count multiple locations of same owner - * @return false if error occurred, true otherwise - */ - virtual bool getPeersCount( - uint32_t& peersCount, uint32_t& onlinePeersCount, - bool countLocations = true ) = 0; - - RS_DEPRECATED - virtual bool getPeerCount(unsigned int *pnFriendCount, unsigned int *pnnOnlineCount, bool ssl) = 0; - - /** - * @brief Check if there is an established connection to the given peer - * @jsonapi{development} - * @param[in] sslId id of the peer to check - * @return true if the connection is establisced, false otherwise - */ - virtual bool isOnline(const RsPeerId &sslId) = 0; - - /** - * @brief Check if given peer is a trusted node - * @jsonapi{development} - * @param[in] sslId id of the peer to check - * @return true if the node is trusted, false otherwise - */ - virtual bool isFriend(const RsPeerId& sslId) = 0; - - /** - * @brief Check if given PGP id is trusted - * @jsonapi{development} - * @param[in] pgpId PGP id to check - * @return true if the PGP id is trusted, false otherwise - */ - virtual bool isPgpFriend(const RsPgpId& pgpId) = 0; - - /** - * @brief Check if given peer is a trusted SSL node pending PGP approval - * Peers added through short invite remain in this state as long as their - * PGP key is not received and verified/approved by the user. - * @jsonapi{development} - * @param[in] sslId id of the peer to check - * @return true if the node is trusted, false otherwise - */ - virtual bool isSslOnlyFriend(const RsPeerId& sslId) = 0; - - virtual std::string getPeerName(const RsPeerId &ssl_id) = 0; - virtual std::string getGPGName(const RsPgpId& gpg_id) = 0; - - /** - * @brief Get details details of the given peer - * @jsonapi{development} - * @param[in] sslId id of the peer - * @param[out] det storage for the details of the peer - * @return false if error occurred, true otherwise - */ - virtual bool getPeerDetails(const RsPeerId& sslId, RsPeerDetails& det) = 0; - - virtual bool getGPGDetails(const RsPgpId& gpg_id, RsPeerDetails &d) = 0; - - /* Using PGP Ids */ - virtual const RsPgpId& getGPGOwnId() = 0; - - /** - * @brief Get PGP id for the given peer - * @jsonapi{development} - * @param[in] sslId SSL id of the peer - * @return PGP id of the peer - */ - virtual RsPgpId getGPGId(const RsPeerId& sslId) = 0; - virtual bool isKeySupported(const RsPgpId& gpg_ids) = 0; - - RS_DEPRECATED_FOR(getPgpFriendList) - virtual bool getGPGAcceptedList(std::list &gpg_ids) = 0; - virtual bool getGPGSignedList(std::list &gpg_ids) = 0;// keys signed by our own PGP key. - virtual bool getGPGValidList(std::list &gpg_ids) = 0;// all PGP keys without filtering - virtual bool getGPGAllList(std::list &gpg_ids) = 0;// all PGP keys as well - virtual bool getAssociatedSSLIds(const RsPgpId& gpg_id, std::list& ids) = 0; - virtual bool gpgSignData(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen, std::string reason = "") = 0; - - /** - * @brief Convert PGP fingerprint to PGP id - * @jsonapi{development} - * Helper method useful while we port the whole RetroShare codebase from - * RsPgpId to RsPgpFingerprint - * @param[in] fpr PGP fingerprint to convert - * @return PGP id corresponding to the fingerprint - */ - virtual RsPgpId pgpIdFromFingerprint(const RsPgpFingerprint& fpr) = 0; - - // Note: the two methods below could be unified. The fact that one of them can take an optional RsPeerDetails struct as parameter - // seems quite inconsistent. - - /** - * @brief Add trusted node - * @jsonapi{development} - * @param[in] sslId SSL id of the node to add - * @param[in] gpgId PGP id of the node to add - * @param[in] flags service permissions flag - * @return false if error occurred, true otherwise - */ - virtual bool addFriend( - const RsPeerId& sslId, const RsPgpId& gpgId, - ServicePermissionFlags flags = RS_NODE_PERM_DEFAULT ) = 0; - - /** - * @brief Add SSL-only trusted node - * When adding an SSL-only node, it is authorized to connect. Every time a - * connection is established the user is notified about the need to verify - * the PGP fingerprint, until she does, at that point the node become a full - * SSL+PGP friend. - * @jsonapi{development} - * @param[in] sslId SSL id of the node to add - * @param[in] pgpId PGP id of the node to add. Will be used for validation when the key is available. - * @param[in] details Optional extra details known about the node to add - * @return false if error occurred, true otherwise - */ - virtual bool addSslOnlyFriend( - const RsPeerId& sslId, - const RsPgpId& pgpId, - const RsPeerDetails& details = RsPeerDetails() ) = 0; - - /** - * @brief Revoke connection trust from to node - * @jsonapi{development} - * @param[in] pgpId PGP id of the node - * @return false if error occurred, true otherwise - */ - virtual bool removeFriend(const RsPgpId& pgpId) = 0; - - /** - * @brief Remove location of a trusted node, useful to prune old unused - * locations of a trusted peer without revoking trust - * @jsonapi{development} - * @param[in] sslId SSL id of the location to remove - * @return false if error occurred, true otherwise - */ - virtual bool removeFriendLocation(const RsPeerId& sslId) = 0; - - /* keyring management */ - virtual bool removeKeysFromPGPKeyring( - const std::set& pgpIds, std::string& backupFile, - uint32_t& errorCode ) = 0; - - /* Network Stuff */ - - /** - * @brief Trigger connection attempt to given node - * @jsonapi{development} - * @param[in] sslId SSL id of the node to connect - * @return false if error occurred, true otherwise - */ - virtual bool connectAttempt(const RsPeerId& sslId) = 0; - - virtual bool setLocation(const RsPeerId &ssl_id, const std::string &location) = 0; // location is shown in the gui to differentiate ssl certs - - virtual bool setHiddenNode(const RsPeerId &id, const std::string &hidden_node_address) = 0; - virtual bool setHiddenNode(const RsPeerId &id, const std::string &address, uint16_t port) = 0; - virtual bool isHiddenNode(const RsPeerId &id) = 0; - - /** - * @brief Add URL locator for given peer - * @jsonapi{development} - * @param[in] sslId SSL id of the peer, own id is accepted too - * @param[in] locator peer url locator - * @return false if error occurred, true otherwise - */ - virtual bool addPeerLocator(const RsPeerId& sslId, const RsUrl& locator) = 0; - - /** - * @brief Set local IPv4 address for the given peer - * @jsonapi{development} - * @param[in] sslId SSL id of the peer, own id is accepted too - * @param[in] addr string representation of the local IPv4 address - * @param[in] port local listening port - * @return false if error occurred, true otherwise - */ - virtual bool setLocalAddress( - const RsPeerId& sslId, const std::string& addr, uint16_t port ) = 0; - - /** - * @brief Set external IPv4 address for given peer - * @jsonapi{development} - * @param[in] sslId SSL id of the peer, own id is accepted too - * @param[in] addr string representation of the external IPv4 address - * @param[in] port external listening port - * @return false if error occurred, true otherwise - */ - virtual bool setExtAddress( - const RsPeerId& sslId, const std::string &addr, uint16_t port ) = 0; - - /** - * @brief Set (dynamical) domain name associated to the given peer - * @jsonapi{development} - * @param[in] sslId SSL id of the peer, own id is accepted too - * @param[in] addr domain name string representation - * @return false if error occurred, true otherwise - */ - virtual bool setDynDNS(const RsPeerId& sslId, const std::string& addr) = 0; - - /** - * @brief Set network mode of the given peer - * @jsonapi{development} - * @param[in] sslId SSL id of the peer, own id is accepted too - * @param[in] netMode one of RS_NETMODE_* - * @return false if error occurred, true otherwise - */ - virtual bool setNetworkMode(const RsPeerId &sslId, uint32_t netMode) = 0; - - /** - * @brief set DHT and discovery modes - * @jsonapi{development} - * @param[in] sslId SSL id of the peer, own id is accepted too - * @param[in] vsDisc one of RS_VS_DISC_* - * @param[in] vsDht one of RS_VS_DHT_* - * @return false if error occurred, true otherwise - */ - virtual bool setVisState( const RsPeerId& sslId, - uint16_t vsDisc, uint16_t vsDht ) = 0; - - virtual bool getProxyServer(const uint32_t type, std::string &addr, uint16_t &port,uint32_t& status_flags) = 0; - virtual bool setProxyServer(const uint32_t type, const std::string &addr, const uint16_t port) = 0; - - virtual void getIPServersList(std::list& ip_servers) = 0; - virtual void getCurrentExtIPList(std::list& ip_list) = 0; - virtual void allowServerIPDetermination(bool) = 0; - virtual bool resetOwnExternalAddressList() = 0; - virtual bool getAllowServerIPDetermination() = 0 ; - - /** - * @brief Get RetroShare invite of the given peer - * @jsonapi{development} - * @param[in] sslId Id of the peer of which we want to generate an invite, - * a null id (all 0) is passed, an invite for own node is returned. - * @param[in] inviteFlags specify extra data to include in the invite - * @return invite string - */ - virtual std::string GetRetroshareInvite( - const RsPeerId& sslId = RsPeerId(), - RetroshareInviteFlags inviteFlags = - RetroshareInviteFlags::DNS | RetroshareInviteFlags::CURRENT_IP ) = 0; - - /** - * @brief Get RetroShare short invite of the given peer - * @jsonapi{development} - * @param[out] invite storage for the generated invite - * @param[in] sslId Id of the peer of which we want to generate an invite, - * a null id (all 0) is passed, an invite for own node is returned. - * @param[in] inviteFlags specify extra data to include in the invite and - * format. - * @param[in] baseUrl URL into which to sneak in the RetroShare invite - * radix, this is primarly useful to trick other applications into making - * the invite clickable, or to disguise the RetroShare invite into a - * "normal" looking web link. Used only if formatRadix is false. - * @return false if error occurred, true otherwise - */ - virtual bool getShortInvite( - std::string& invite, const RsPeerId& sslId = RsPeerId(), - RetroshareInviteFlags inviteFlags = - RetroshareInviteFlags::CURRENT_IP | RetroshareInviteFlags::DNS, - const std::string& baseUrl = "https://retroshare.me/" ) = 0; - - /** - * @brief Parse the give short invite to extract contained information - * @jsonapi{development} - * @param[in] invite string containing the short invite to parse - * @param[out] details storage for the extracted information, consider it - * @param[out] err_code storage for the error code - * @return false if error occurred, true otherwise - */ - virtual bool parseShortInvite( - const std::string& invite, RsPeerDetails& details,uint32_t& err_code ) = 0; - - /** - * @brief Add trusted node from invite - * @jsonapi{development} - * @param[in] invite invite string being it in cert or URL format - * @param[in] flags service permissions flag - * @return false if error occurred, true otherwise - */ - virtual bool acceptInvite( - const std::string& invite, - ServicePermissionFlags flags = RS_NODE_PERM_DEFAULT ) = 0; - - - RS_DEPRECATED /// This function doesn't provide meaningful error reporting - virtual std::string getPGPKey(const RsPgpId& pgp_id,bool include_signatures) = 0; - virtual bool GetPGPBase64StringAndCheckSum(const RsPgpId& gpg_id,std::string& gpg_base64_string,std::string& gpg_base64_checksum) = 0; - - /** - * @brief Import certificate into the keyring - * @jsonapi{development} - * @param[in] cert string representation of the certificate - * @param[out] sslId storage for the SSL id of the certificate - * @param[out] pgpId storage for the PGP id of the certificate - * @param[out] errorString storage for the possible error string - * @return false if error occurred, true otherwise - */ - virtual bool loadCertificateFromString( - const std::string& cert, RsPeerId& sslId, RsPgpId& pgpId, - std::string& errorString) = 0; - - /** - * @brief Examine certificate and get details without importing into - * the keyring - * @jsonapi{development} - * @param[in] cert string representation of the certificate - * @param[out] certDetails storage for the certificate details - * @param[out] errorCode storage for possible error number - * @return false if error occurred, true otherwise - */ - virtual bool loadDetailsFromStringCert( - const std::string& cert, RsPeerDetails& certDetails, - uint32_t& errorCode ) = 0; - - virtual bool loadPgpKeyFromBinaryData( const unsigned char *bin_key_data, - uint32_t bin_key_len, - RsPgpId& gpg_id, - std::string& error_string )=0; - - // Certificate utils - virtual bool cleanCertificate( - const std::string& certstr, std::string& cleanCert, - bool& is_short_format, uint32_t& error_code, RsPeerDetails& details) = 0; - virtual std::string saveCertificateToString(const RsPeerId &id) = 0; - - virtual bool signGPGCertificate(const RsPgpId &gpg_id,const std::string& gpg_passphrase) = 0; - virtual bool trustGPGCertificate(const RsPgpId &gpg_id, uint32_t trustlvl) = 0; - - /* Group Stuff */ - /** - * @brief addGroup create a new group - * @jsonapi{development} - * @param[in] groupInfo - * @return - */ - virtual bool addGroup(RsGroupInfo& groupInfo) = 0; - - /** - * @brief editGroup edit an existing group - * @jsonapi{development} - * @param[in] groupId - * @param[in] groupInfo - * @return - */ - virtual bool editGroup(const RsNodeGroupId& groupId, RsGroupInfo& groupInfo) = 0; - - /** - * @brief removeGroup remove a group - * @jsonapi{development} - * @param[in] groupId - * @return - */ - virtual bool removeGroup(const RsNodeGroupId& groupId) = 0; - - /** - * @brief getGroupInfo get group information to one group - * @jsonapi{development} - * @param[in] groupId - * @param[out] groupInfo - * @return - */ - virtual bool getGroupInfo(const RsNodeGroupId& groupId, RsGroupInfo& groupInfo) = 0; - - /** - * @brief getGroupInfoByName get group information by group name - * @jsonapi{development} - * @param[in] groupName - * @param[out] groupInfo - * @return - */ - virtual bool getGroupInfoByName(const std::string& groupName, RsGroupInfo& groupInfo) = 0; - - /** - * @brief getGroupInfoList get list of all groups - * @jsonapi{development} - * @param[out] groupInfoList - * @return - */ - virtual bool getGroupInfoList(std::list& groupInfoList) = 0; - - // groupId == "" && assign == false -> remove from all groups - /** - * @brief assignPeerToGroup add a peer to a group - * @jsonapi{development} - * @param[in] groupId - * @param[in] peerId - * @param[in] assign true to assign a peer, false to remove a peer - * @return - */ - virtual bool assignPeerToGroup(const RsNodeGroupId& groupId, const RsPgpId& peerId, bool assign) = 0; - - /** - * @brief assignPeersToGroup add a list of peers to a group - * @jsonapi{development} - * @param[in] groupId - * @param[in] peerIds - * @param[in] assign true to assign a peer, false to remove a peer - * @return - */ - virtual bool assignPeersToGroup(const RsNodeGroupId& groupId, const std::list& peerIds, bool assign) = 0; - - /* Group sharing permission */ - - // Given - // - the peer id - // - the permission flags of a given hash, e.g. a combination of - // RS_DIR_FLAGS_NETWORK_WIDE_OTHERS, RS_DIR_FLAGS_NETWORK_WIDE_GROUPS, RS_DIR_FLAGS_BROWSABLE_OTHERS and RS_DIR_FLAGS_BROWSABLE_GROUPS - // - the parent groups of the file - // - // ... computes the sharing file permission hint flags set for this peer, that is a combination of - // RS_FILE_HINTS_NETWORK_WIDE and RS_FILE_HINTS_BROWSABLE. - // - virtual FileSearchFlags computePeerPermissionFlags( - const RsPeerId& peer_id, FileStorageFlags file_sharing_flags, - const std::list& file_parent_groups) = 0; - - /* Service permission flags */ - - virtual ServicePermissionFlags servicePermissionFlags(const RsPgpId& gpg_id) = 0; - virtual ServicePermissionFlags servicePermissionFlags(const RsPeerId& ssl_id) = 0; - virtual void setServicePermissionFlags(const RsPgpId& gpg_id,const ServicePermissionFlags& flags) = 0; - - virtual bool setPeerMaximumRates(const RsPgpId& pid,uint32_t maxUploadRate,uint32_t maxDownloadRate) =0; - virtual bool getPeerMaximumRates(const RsPeerId& pid,uint32_t& maxUploadRate,uint32_t& maxDownloadRate) =0; - virtual bool getPeerMaximumRates(const RsPgpId& pid,uint32_t& maxUploadRate,uint32_t& maxDownloadRate) =0; - - RS_DEPRECATED_FOR(isPgpFriend) - virtual bool isGPGAccepted(const RsPgpId &gpg_id_is_friend) = 0; - - virtual ~RsPeers(); -}; diff --git a/libretroshare/src/retroshare/rsphoto.h b/libretroshare/src/retroshare/rsphoto.h deleted file mode 100644 index 839b28a90..000000000 --- a/libretroshare/src/retroshare/rsphoto.h +++ /dev/null @@ -1,247 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsphoto.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008-2020 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RSPHOTOV2_H -#define RSPHOTOV2_H - -#include -#include -#include -#include "retroshare/rsgxsservice.h" -#include "retroshare/rsgxscommon.h" -#include "retroshare/rsgxsifacehelper.h" - - -/* The Main Interface Class - for information about your Peers */ -class RsPhoto; -extern RsPhoto *rsPhoto; - -class RsPhotoPhoto -{ -public: - - RsMsgMetaData mMeta; - - RsPhotoPhoto(); - - // V2 PhotoMsg - keep it simple. - // mMeta.mTitle used for Photo Caption. - // mDescription optional field for addtional notes. - // mLowResImage - < 50k jpg of image. - // mPhotoFile - transfer details for original photo. - std::string mDescription; - uint32_t mOrder; - RsGxsImage mLowResImage; - RsGxsFile mPhotoFile; - - // These are not saved. - std::string mPath; // if New photo -}; - -#define RSPHOTO_SHAREMODE_LOWRESONLY (1) -#define RSPHOTO_SHAREMODE_ORIGINAL (2) -#define RSPHOTO_SHAREMODE_DUP_ORIGINAL (3) -#define RSPHOTO_SHAREMODE_DUP_200K (4) -#define RSPHOTO_SHAREMODE_DUP_1M (5) - -struct RsPhotoAlbum: RsGxsGenericGroupData -{ - RsPhotoAlbum(); - - // V2 Album - keep it simple. - // mMeta.mTitle. - uint32_t mShareMode; - - std::string mCaption; - std::string mDescription; - std::string mPhotographer; - std::string mWhere; - std::string mWhen; - - RsGxsImage mThumbnail; - - // Below is not saved. - bool mAutoDownload; -}; - -std::ostream &operator<<(std::ostream &out, const RsPhotoPhoto &photo); -std::ostream &operator<<(std::ostream &out, const RsPhotoAlbum &album); - -typedef std::map > PhotoResult; - -class RsPhoto: public RsGxsIfaceHelper, public RsGxsCommentService -{ -public: - explicit RsPhoto(RsGxsIface &gxs) : RsGxsIfaceHelper(gxs) { return; } - - virtual ~RsPhoto() { return; } - - /*! - * Use to enquire if groups or msgs have changed - * Poll regularly, particularly after a photo submission - * @return true if msgs or groups have changed - */ - virtual bool updated() = 0; - - /*! - * - * @param grpIds - */ - virtual void groupsChanged(std::list& grpIds) = 0; - - /*! - * - * @param msgs - */ - virtual void msgsChanged(GxsMsgIdResult& msgs) = 0; - - /*! - * To acquire a handle to token service handler - * needed to make requests to the service - * @return handle to token service for this gxs service - */ - virtual RsTokenService* getTokenService() = 0; - - /* Generic Lists */ - - /*! - * - * @param token token to be redeemed for this request - * @param groupIds the ids return for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getGroupList(const uint32_t &token, - std::list &groupIds) = 0; - - /*! - * @param token token to be redeemed for this request - * @param msgIds the ids return for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getMsgList(const uint32_t &token, - GxsMsgIdResult &msgIds) = 0; - - /* Generic Summary */ - - /*! - * @param token token to be redeemed for group summary request - * @param groupInfo the ids returned for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getGroupSummary(const uint32_t &token, - std::list &groupInfo) = 0; - - /*! - * @param token token to be redeemed for message summary request - * @param msgInfo the message metadata returned for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getMsgSummary(const uint32_t &token, - MsgMetaResult &msgInfo) = 0; - - /* Specific Service Data */ - - /*! - * @param token token to be redeemed for album request - * @param album the album returned for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getAlbum(const uint32_t &token, std::vector &album) = 0; - - /*! - * @param token token to be redeemed for photo request - * @param photo the photo returned for given request token - * @return false if request token is invalid, check token status for error report - */ - virtual bool getPhoto(const uint32_t &token, - PhotoResult &photo) = 0; - - /*! - * submits album, which returns a token that needs - * to be acknowledge to get album grp id - * @param token token to redeem for acknowledgement - * @param album album to be submitted - */ - virtual bool submitAlbumDetails(uint32_t& token, RsPhotoAlbum &album) = 0; - - /*! - * submits photo, which returns a token that needs - * to be acknowledged to get photo msg-grp id pair - * @param token token to redeem for acknowledgement - * @param photo photo to be submitted - */ - virtual bool submitPhoto(uint32_t& token, RsPhotoPhoto &photo) = 0; - - /*! - * subscribes to group, and returns token which can be used - * to be acknowledged to get group Id - * @param token token to redeem for acknowledgement - * @param grpId the id of the group to subscribe to - */ - virtual bool subscribeToAlbum(uint32_t& token, const RsGxsGroupId& grpId, bool subscribe) = 0; - - /*! - * This allows the client service to acknowledge that their msgs has - * been created/modified and retrieve the create/modified msg ids - * @param token the token related to modification/create request - * @param msgIds map of grpid->msgIds of message created/modified - * @return true if token exists false otherwise - */ - virtual bool acknowledgeMsg(const uint32_t& token, std::pair& msgId) = 0; - - - - /*! - * This allows the client service to acknowledge that their grps has - * been created/modified and retrieve the create/modified grp ids - * @param token the token related to modification/create request - * @param msgIds vector of ids of groups created/modified - * @return true if token exists false otherwise - */ - virtual bool acknowledgeGrp(const uint32_t& token, RsGxsGroupId& grpId) = 0; - - // Blocking versions. - /*! - * request to create a new album. Blocks until process completes. - * @param album album to be submitted - * @return true if created false otherwise - */ - virtual bool createAlbum(RsPhotoAlbum &album) = 0; - - /*! - * request to update an existing album. Blocks until process completes. - * @param album album to be submitted - * @return true if created false otherwise - */ - virtual bool updateAlbum(const RsPhotoAlbum &album) = 0; - - /*! - * retrieve albums based in groupIds. - * @param groupIds the ids to fetch. - * @param albums vector to be filled by request. - * @return true is successful, false otherwise. - */ - virtual bool getAlbums(const std::list &groupIds, - std::vector &albums) = 0; -}; - - -#endif // RSPHOTOV2_H diff --git a/libretroshare/src/retroshare/rsplugin.h b/libretroshare/src/retroshare/rsplugin.h deleted file mode 100644 index 1efa70399..000000000 --- a/libretroshare/src/retroshare/rsplugin.h +++ /dev/null @@ -1,248 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsplugin.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include "util/rstime.h" -#include -#include -#include -#include -#include "retroshare/rspeers.h" -#include "retroshare/rsfiles.h" -#include "retroshare/rsversion.h" -#include "util/rsinitedptr.h" -#include "retroshare/rsdisc.h" - -class RsPluginHandler ; -extern RsPluginHandler *rsPlugins ; - -class p3Service ; -class RsServiceControl ; -class RsReputations ; -class RsTurtle ; -class RsGxsTunnelService ; -class RsDht ; -class RsMsgs ; -class RsGxsForums; -class RsGxsChannels; -class RsNotify; -class RsServiceControl; -class p3LinkMgr ; -class MainPage ; -class QIcon ; -class QString ; -class QDialog ; -class QWidget ; -class QTranslator; -class QApplication; -class RsCacheService ; -class ftServer ; -class ConfigPage ; -class RsPQIService ; -class RsAutoUpdatePage ; -class SoundEvents; -class FeedNotify; -class ToasterNotify; -class ChatWidget; -class ChatWidgetHolder; -// for gxs based plugins -struct RsIdentity; -class RsNxsNetMgr; -class RsGxsIdExchange; -class RsGcxs; -class PgpAuxUtils; -class p3Config; - -namespace resource_api -{ - class ResourceRouter; - class StateTokenServer; -} - -// Plugin API version. Not used yet, but will be in the future the -// main value that decides for compatibility. -// -#define RS_PLUGIN_API_VERSION 0x000101 - -// Used for the status of plugins. -// -#define PLUGIN_STATUS_NO_STATUS 0x0000 -#define PLUGIN_STATUS_REJECTED_HASH 0x0001 -#define PLUGIN_STATUS_DLOPEN_ERROR 0x0002 -#define PLUGIN_STATUS_MISSING_SYMBOL 0x0003 -#define PLUGIN_STATUS_NULL_PLUGIN 0x0004 -#define PLUGIN_STATUS_LOADED 0x0005 -#define PLUGIN_STATUS_WRONG_API 0x0006 -#define PLUGIN_STATUS_MISSING_API 0x0007 -#define PLUGIN_STATUS_MISSING_SVN 0x0008 - -class RsPluginHandler; - -/*! - * - * convenience class to store gui interfaces - * - */ -class RsPlugInInterfaces { -public: - RsUtil::inited_ptr mPeers; - RsUtil::inited_ptr mFiles; - RsUtil::inited_ptr mMsgs; - RsUtil::inited_ptr mTurtle; - RsUtil::inited_ptr mDisc; - RsUtil::inited_ptr mDht; - RsUtil::inited_ptr mNotify; - RsUtil::inited_ptr mServiceControl; - RsUtil::inited_ptr mPluginHandler; - - // gxs - std::string mGxsDir; - RsUtil::inited_ptr mIdentity; - RsUtil::inited_ptr mRsNxsNetMgr; - RsUtil::inited_ptr mGxsIdService; - RsUtil::inited_ptr mGxsCirlces; - RsUtil::inited_ptr mPgpAuxUtils; - RsUtil::inited_ptr mGxsForums; - RsUtil::inited_ptr mGxsChannels; - RsUtil::inited_ptr mGxsTunnels; - RsUtil::inited_ptr mReputations; -}; - -class RsPlugin -{ - public: - RsPlugin() {} - virtual ~RsPlugin() {} - - // - //================================ Services ==================================// - // - // Cache service. Use this for providing cache-based services, such as channels, forums. - // Example plugin: LinksCloud - // - virtual RsCacheService *rs_cache_service() const { return NULL ; } - - // Peer-to-Peer service. Use this for providing a service based to friend to friend - // exchange of data, such as chat, messages, etc. - // Example plugin: VOIP - // - //virtual RsPQIService *rs_pqi_service() const { return NULL ; } - // gxs netservice is not a RsPQIService - // so have two fns which result in the same gxs netservice to be returned - virtual p3Service *p3_service() const { return NULL ; } - virtual p3Config *p3_config() const { return NULL ; } - virtual uint16_t rs_service_id() const { return 0 ; } - - - // creates a new resource api handler object. ownership is transferred to the caller. - // the caller should supply a statetokenserver, and keep it valid until destruction - // the plugin should return a entry point name. this is to make the entry point name independent from file names - virtual resource_api::ResourceRouter* new_resource_api_handler(const RsPlugInInterfaces& /* ifaces */, resource_api::StateTokenServer* /* sts */, std::string & /*entrypoint*/) const { return 0;} - - // Shutdown - virtual void stop() {} - - // Filename used for saving the specific plugin configuration. Both RsCacheService and RsPQIService - // derive from p3Config, which means that the service provided by the plugin can load/save its own - // config by deriving loadList() and saveList() from p3Config. - // - virtual std::string configurationFileName() const - { - std::cerr << "(EE) Plugin configuration file name requested in non overloaded method! Plugin code should derive configurationFileName() method!" << std::endl; - return std::string() ; - } - - // - //=================================== GUI ====================================// - // - // Derive the following methods to provide GUI additions to RetroShare's GUI. - // - // Main page: like Transfers, Channels, Forums, etc. - // - virtual MainPage *qt_page() const { return NULL ; } // The page itself - virtual QIcon *qt_icon() const { return NULL ; } // the page icon. Todo: put icon as virtual in MainPage - - virtual QWidget *qt_config_panel() const { return NULL ; } // Config panel, to appear config->plugins->[]-> - virtual QDialog *qt_about_page() const { return NULL ; } // About/Help button in plugin entry will show this up - virtual ConfigPage *qt_config_page() const { return NULL ; } // Config tab to add in config panel. - virtual RsAutoUpdatePage *qt_transfers_tab() const { return NULL ; } // Tab to add in transfers, after turtle statistics. - virtual std::string qt_transfers_tab_name()const { return "Tab" ; } // Tab name - virtual void qt_sound_events(SoundEvents &/*events*/) const { } // Sound events - - // Provide buttons for the ChatWidget - virtual ChatWidgetHolder *qt_get_chat_widget_holder(ChatWidget */*chatWidget*/) const { return NULL ; } - - virtual std::string qt_stylesheet() { return ""; } - virtual QTranslator *qt_translator(QApplication * /* app */, const QString& /* languageCode */, const QString& /* externalDir */ ) const { return NULL ; } - - // - //================================== Notify ==================================// - // - virtual FeedNotify *qt_feedNotify() { return NULL; } - virtual ToasterNotify *qt_toasterNotify() { return NULL; } - - // - //========================== Plugin Description ==============================// - // - // All these items appear in the config->plugins tab, as a description of the plugin. - // - uint32_t getSvnRevision() const { return 0; } // This is read from libretroshare/retroshare/rsversion.h - - virtual std::string getShortPluginDescription() const = 0 ; - virtual std::string getPluginName() const = 0 ; - virtual void getPluginVersion(int& major,int& minor, int& build, int& svn_rev) const = 0 ; - virtual void getLibraries(std::list & /*libraries*/) {} - - // - //========================== Plugin Interface ================================// - // - // Use these methods to access main objects from RetroShare. - // - virtual void setInterfaces(RsPlugInInterfaces& interfaces) = 0; - virtual void setPlugInHandler(RsPluginHandler* pgHandler) = 0; -}; - -class RsPluginHandler -{ - public: - // Returns the number of loaded plugins. - // - virtual int nbPlugins() const = 0 ; - virtual RsPlugin *plugin(int i) = 0 ; - virtual const std::vector& getPluginDirectories() const = 0; - virtual void getPluginStatus(int i,uint32_t& status,std::string& file_name,RsFileHash& file_hash,uint32_t& svn_revision,std::string& error_string) const = 0 ; - virtual void enablePlugin(const RsFileHash& hash) = 0; - virtual void disablePlugin(const RsFileHash& hash) = 0; - - virtual void allowAllPlugins(bool b) = 0 ; - virtual bool getAllowAllPlugins() const = 0 ; - - virtual void slowTickPlugins(rstime_t sec) = 0 ; - - virtual const std::string& getLocalCacheDir() const =0; - virtual const std::string& getRemoteCacheDir() const =0; - - virtual RsServiceControl *getServiceControl() const = 0; -}; - - - diff --git a/libretroshare/src/retroshare/rsposted.h b/libretroshare/src/retroshare/rsposted.h deleted file mode 100644 index bdcaa3798..000000000 --- a/libretroshare/src/retroshare/rsposted.h +++ /dev/null @@ -1,228 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsposted.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2008-2012 Robert Fernie, Christopher Evi-Parker * - * Copyright (C) 2020 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -#include "retroshare/rstokenservice.h" -#include "retroshare/rsgxsifacehelper.h" -#include "retroshare/rsgxscommon.h" -#include "serialiser/rsserializable.h" - -class RsPosted; - -/** - * Pointer to global instance of RsGxsChannels service implementation - * @jsonapi{development} - */ -extern RsPosted* rsPosted; - -struct RsPostedGroup: RsGxsGenericGroupData -{ - std::string mDescription; - RsGxsImage mGroupImage; -}; - -struct RsPostedPost: public RsGxsGenericMsgData -{ - RsPostedPost(): mHaveVoted(false), mUpVotes(0), mDownVotes(0), mComments(0), - mHotScore(0), mTopScore(0), mNewScore(0) {} - - bool calculateScores(rstime_t ref_time); - - std::string mLink; - std::string mNotes; - - bool mHaveVoted; - - // Calculated. - uint32_t mUpVotes; - uint32_t mDownVotes; - uint32_t mComments; - - - // and Calculated Scores:??? - double mHotScore; - double mTopScore; - double mNewScore; - - RsGxsImage mImage; - - /// @see RsSerializable - /*virtual void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(mImage); - RS_SERIAL_PROCESS(mMeta); - RS_SERIAL_PROCESS(mLink); - RS_SERIAL_PROCESS(mHaveVoted); - RS_SERIAL_PROCESS(mUpVotes); - RS_SERIAL_PROCESS(mDownVotes); - RS_SERIAL_PROCESS(mComments); - RS_SERIAL_PROCESS(mHotScore); - RS_SERIAL_PROCESS(mTopScore); - RS_SERIAL_PROCESS(mNewScore); - }*/ -}; - - -//#define RSPOSTED_MSGTYPE_POST 0x0001 -//#define RSPOSTED_MSGTYPE_VOTE 0x0002 -//#define RSPOSTED_MSGTYPE_COMMENT 0x0004 - -#define RSPOSTED_PERIOD_YEAR 1 -#define RSPOSTED_PERIOD_MONTH 2 -#define RSPOSTED_PERIOD_WEEK 3 -#define RSPOSTED_PERIOD_DAY 4 -#define RSPOSTED_PERIOD_HOUR 5 - -#define RSPOSTED_VIEWMODE_LATEST 1 -#define RSPOSTED_VIEWMODE_TOP 2 -#define RSPOSTED_VIEWMODE_HOT 3 -#define RSPOSTED_VIEWMODE_COMMENTS 4 - - -enum class RsPostedEventCode: uint8_t -{ - UNKNOWN = 0x00, - NEW_POSTED_GROUP = 0x01, - NEW_MESSAGE = 0x02, - SUBSCRIBE_STATUS_CHANGED = 0x03, - UPDATED_POSTED_GROUP = 0x04, - UPDATED_MESSAGE = 0x05, - READ_STATUS_CHANGED = 0x06, - STATISTICS_CHANGED = 0x07, - MESSAGE_VOTES_UPDATED = 0x08, - SYNC_PARAMETERS_UPDATED = 0x09, - NEW_COMMENT = 0x0a, - NEW_VOTE = 0x0b, - BOARD_DELETED = 0x0c, -}; - - -struct RsGxsPostedEvent: RsEvent -{ - RsGxsPostedEvent(): - RsEvent(RsEventType::GXS_POSTED), - mPostedEventCode(RsPostedEventCode::UNKNOWN) {} - - RsPostedEventCode mPostedEventCode; - RsGxsGroupId mPostedGroupId; - RsGxsMessageId mPostedMsgId; - RsGxsMessageId mPostedThreadId; - - ///* @see RsEvent @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override - { - RsEvent::serial_process(j, ctx); - RS_SERIAL_PROCESS(mPostedEventCode); - RS_SERIAL_PROCESS(mPostedGroupId); - RS_SERIAL_PROCESS(mPostedMsgId); - } - - ~RsGxsPostedEvent() override; -}; - -class RsPosted : public RsGxsIfaceHelper, public RsGxsCommentService -{ -public: - explicit RsPosted(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {} - - virtual bool getBoardsInfo( - const std::list& boardsIds, - std::vector& boardsInfo ) = 0; - - virtual bool getBoardsSummaries(std::list& groupInfo) =0; - - virtual bool getBoardAllContent( - const RsGxsGroupId& boardId, - std::vector& posts, - std::vector& comments, - std::vector& votes ) = 0; - - virtual bool getBoardContent( - const RsGxsGroupId& boardId, - const std::set& contentsIds, - std::vector& posts, - std::vector& comments, - std::vector& votes ) = 0; - - virtual bool editBoard(RsPostedGroup& board) =0; - - virtual bool createBoard(RsPostedGroup& board) =0; - - virtual bool getBoardStatistics(const RsGxsGroupId& boardId,GxsGroupStatistic& stat) =0; - - virtual bool getBoardsServiceStatistics(GxsServiceStatistic& stat) =0; - - virtual bool voteForPost(bool up,const RsGxsGroupId& postGrpId,const RsGxsMessageId& postMsgId,const RsGxsId& voterId) =0; - - virtual bool setPostReadStatus(const RsGxsGrpMsgIdPair& msgId, bool read) = 0; - - enum RS_DEPRECATED RankType {TopRankType, HotRankType, NewRankType }; - - RS_DEPRECATED_FOR(getBoardsInfo) - virtual bool getGroupData( const uint32_t& token, - std::vector &groups ) = 0; - - RS_DEPRECATED_FOR(getBoardsContent) - virtual bool getPostData( - const uint32_t& token, std::vector& posts, - std::vector& cmts, std::vector& vots) = 0; - - RS_DEPRECATED_FOR(getBoardsContent) - virtual bool getPostData( - const uint32_t& token, std::vector& posts, - std::vector& cmts) = 0; - - RS_DEPRECATED_FOR(getBoardsContent) - virtual bool getPostData( - const uint32_t& token, std::vector& posts) = 0; - - virtual bool setCommentAsRead(uint32_t& token,const RsGxsGroupId& gid,const RsGxsMessageId& comment_msg_id) =0; - - //Not currently used -//virtual bool getRelatedPosts(const uint32_t &token, std::vector &posts) = 0; - - /* From RsGxsCommentService */ -//virtual bool getCommentData(const uint32_t &token, std::vector &comments) = 0; -//virtual bool getRelatedComments(const uint32_t &token, std::vector &comments) = 0; -//virtual bool createNewComment(uint32_t &token, RsGxsComment &comment) = 0; -//virtual bool createNewVote(uint32_t &token, RsGxsVote &vote) = 0; - - RS_DEPRECATED_FOR(setPostReadStatus) - virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) = 0; - ////////////////////////////////////////////////////////////////////////////// - -virtual bool createGroup(uint32_t &token, RsPostedGroup &group) = 0; -virtual bool createPost(uint32_t &token, RsPostedPost &post) = 0; - -virtual bool updateGroup(uint32_t &token, RsPostedGroup &group) = 0; - - virtual bool groupShareKeys(const RsGxsGroupId& group,const std::set& peers) = 0 ; - - virtual ~RsPosted(); -}; diff --git a/libretroshare/src/retroshare/rsreputations.h b/libretroshare/src/retroshare/rsreputations.h deleted file mode 100644 index b8426e642..000000000 --- a/libretroshare/src/retroshare/rsreputations.h +++ /dev/null @@ -1,245 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsreputations.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2015 Cyril Soler * - * Copyright (C) 2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include "retroshare/rsids.h" -#include "retroshare/rsgxsifacetypes.h" -#include "serialiser/rsserializable.h" - -class RsReputations; - -/** - * Pointer to global instance of RsReputations service implementation - * @jsonapi{development} - */ -extern RsReputations* rsReputations; - - -constexpr float RS_REPUTATION_THRESHOLD_DEFAULT = 1.0f; - -enum struct RsOpinion : uint8_t -{ - NEGATIVE = 0, - NEUTRAL = 1, - POSITIVE = 2 -}; - -enum struct RsReputationLevel : uint8_t -{ - /// local opinion is negative - LOCALLY_NEGATIVE = 0x00, - - /// local opinion is neutral and friends are positive in average - REMOTELY_NEGATIVE = 0x01, - - /// no reputation information - NEUTRAL = 0x02, - - /// local opinion is neutral and friends are positive in average - REMOTELY_POSITIVE = 0x03, - - /// local opinion is positive - LOCALLY_POSITIVE = 0x04, - - /// missing info - UNKNOWN = 0x05 -}; - -struct RsReputationInfo : RsSerializable -{ - RsReputationInfo() : - mOwnOpinion(RsOpinion::NEUTRAL), mFriendsPositiveVotes(0), - mFriendsNegativeVotes(0), - mFriendAverageScore(RS_REPUTATION_THRESHOLD_DEFAULT), - mOverallReputationLevel(RsReputationLevel::NEUTRAL) {} - - RsOpinion mOwnOpinion; - - uint32_t mFriendsPositiveVotes; - uint32_t mFriendsNegativeVotes; - - float mFriendAverageScore; - - /// this should help clients in taking decisions - RsReputationLevel mOverallReputationLevel; - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(mOwnOpinion); - RS_SERIAL_PROCESS(mFriendsPositiveVotes); - RS_SERIAL_PROCESS(mFriendsNegativeVotes); - RS_SERIAL_PROCESS(mFriendAverageScore); - RS_SERIAL_PROCESS(mOverallReputationLevel); - } - - virtual ~RsReputationInfo(); -}; - - -class RsReputations -{ -public: - virtual ~RsReputations() {} - - /** - * @brief Set own opinion about the given identity - * @jsonapi{development} - * @param[in] id Id of the identity - * @param[in] op Own opinion - * @return false on error, true otherwise - */ - virtual bool setOwnOpinion(const RsGxsId& id, RsOpinion op) = 0; - - /** - * @brief Get own opition about the given identity - * @jsonapi{development} - * @param[in] id Id of the identity - * @param[out] op Own opinion - * @return false on error, true otherwise - */ - virtual bool getOwnOpinion(const RsGxsId& id, RsOpinion& op) = 0; - - /** - * @brief Get reputation data of given identity - * @jsonapi{development} - * @param[in] id Id of the identity - * @param[in] ownerNode Optiona PGP id of the signed identity, accept a null - * (all zero/noninitialized) PGP id - * @param[out] info storage for the information - * @param[in] stamp if true, timestamo the information - * @return false on error, true otherwise - */ - virtual bool getReputationInfo( - const RsGxsId& id, const RsPgpId& ownerNode, RsReputationInfo& info, - bool stamp = true ) = 0; - - /** - * @brief Get overall reputation level of given identity - * @jsonapi{development} - * @param[in] id Id of the identity - * @return the calculated reputation level based on available information - */ - virtual RsReputationLevel overallReputationLevel(const RsGxsId& id) = 0; - - /** - * @brief Enable giving automatic positive opinion when flagging as contact - * @jsonapi{development} - * @param[in] b true to enable, false to disable - */ - virtual void setAutoPositiveOpinionForContacts(bool b) = 0; - - /** - * @brief check if giving automatic positive opinion when flagging as - * contact is enbaled - * @jsonapi{development} - * @return true if enabled, false otherwise - */ - virtual bool autoPositiveOpinionForContacts() = 0; - - /** - * @brief Set threshold on remote reputation to consider it remotely - * negative - * @jsonapi{development} - * @param[in] thresh Threshold value - */ - virtual void setThresholdForRemotelyNegativeReputation(uint32_t thresh) = 0; - - /** - * * @brief Get threshold on remote reputation to consider it remotely - * negative - * @jsonapi{development} - * @return Threshold value - */ - virtual uint32_t thresholdForRemotelyNegativeReputation() = 0; - - /** - * @brief Set threshold on remote reputation to consider it remotely - * positive - * @jsonapi{development} - * @param[in] thresh Threshold value - */ - virtual void setThresholdForRemotelyPositiveReputation(uint32_t thresh) = 0; - - /** - * @brief Get threshold on remote reputation to consider it remotely - * negative - * @jsonapi{development} - * @return Threshold value - */ - virtual uint32_t thresholdForRemotelyPositiveReputation() = 0; - - /** - * @brief Get number of days to wait before deleting a banned identity from - * local storage - * @jsonapi{development} - * @return number of days to wait, 0 means never delete - */ - virtual uint32_t rememberBannedIdThreshold() = 0; - - /** - * @brief Set number of days to wait before deleting a banned identity from - * local storage - * @jsonapi{development} - * @param[in] days number of days to wait, 0 means never delete - */ - virtual void setRememberBannedIdThreshold(uint32_t days) = 0; - - /** - * @brief This method allow fast checking if a GXS identity is banned. - * @jsonapi{development} - * @param[in] id Id of the identity to check - * @return true if identity is banned, false otherwise - */ - virtual bool isIdentityBanned(const RsGxsId& id) = 0; - - /** - * @brief Check if automatic banning of all identities signed by the given - * node is enabled - * @jsonapi{development} - * @param[in] id PGP id of the node - * @return true if enabled, false otherwise - */ - virtual bool isNodeBanned(const RsPgpId& id) = 0; - - /** - * @brief Enable automatic banning of all identities signed by the given - * node - * @jsonapi{development} - * @param[in] id PGP id of the node - * @param[in] b true to enable, false to disable - */ - virtual void banNode(const RsPgpId& id, bool b) = 0; - - - /** - * @deprecated - * This returns the reputation level and also the flags of the identity - * service for that id. This is useful in order to get these flags without - * relying on the async method of p3Identity - */ - RS_DEPRECATED - virtual RsReputationLevel overallReputationLevel( - const RsGxsId& id, uint32_t* identity_flags ) = 0; -}; diff --git a/libretroshare/src/retroshare/rsrtt.h b/libretroshare/src/retroshare/rsrtt.h deleted file mode 100644 index e55220307..000000000 --- a/libretroshare/src/retroshare/rsrtt.h +++ /dev/null @@ -1,61 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsposted.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RETROSHARE_RTT_INTERFACE_H -#define RETROSHARE_RTT_INTERFACE_H - -#include -#include -#include -#include - -/* The Main Interface Class - for information about your Peers */ -class RsRtt; -extern RsRtt *rsRtt; - - -class RsRttPongResult -{ - public: - RsRttPongResult() - :mTS(0), mRTT(0), mOffset(0) { return; } - - RsRttPongResult(double ts, double rtt, double offset) - :mTS(ts), mRTT(rtt), mOffset(offset) { return; } - - double mTS; - double mRTT; - double mOffset; -}; - -class RsRtt -{ - public: - - RsRtt() { return; } -virtual ~RsRtt() { return; } - -virtual uint32_t getPongResults(const RsPeerId& id, int n, std::list &results) = 0; -virtual double getMeanOffset(const RsPeerId& id) = 0; - -}; - -#endif diff --git a/libretroshare/src/retroshare/rsservicecontrol.h b/libretroshare/src/retroshare/rsservicecontrol.h deleted file mode 100644 index 4946f5247..000000000 --- a/libretroshare/src/retroshare/rsservicecontrol.h +++ /dev/null @@ -1,200 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsservicecontrol.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014-2014 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RETROSHARE_SERVICE_CONTROL_GUI_INTERFACE_H -#define RETROSHARE_SERVICE_CONTROL_GUI_INTERFACE_H - -#include -#include -#include -#include -#include -#include - -/* The Main Interface Class - for information about your Peers */ -class RsServiceControl; - -/** - * Pointer to global instance of RsServiceControl service implementation - * @jsonapi{development} - */ -extern RsServiceControl* rsServiceControl; - -struct RsServiceInfo : RsSerializable -{ - RsServiceInfo(); - RsServiceInfo( - const uint16_t service_type, - const std::string& service_name, - const uint16_t version_major, - const uint16_t version_minor, - const uint16_t min_version_major, - const uint16_t min_version_minor); - - static unsigned int RsServiceInfoUIn16ToFullServiceId(uint16_t serviceType); - - std::string mServiceName; - uint32_t mServiceType; - // current version, we running. - uint16_t mVersionMajor; - uint16_t mVersionMinor; - // minimum version can communicate with. - uint16_t mMinVersionMajor; - uint16_t mMinVersionMinor; - - // RsSerializable interface - void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) { - RS_SERIAL_PROCESS(mServiceName); - RS_SERIAL_PROCESS(mServiceType); - RS_SERIAL_PROCESS(mVersionMajor); - RS_SERIAL_PROCESS(mVersionMinor); - RS_SERIAL_PROCESS(mMinVersionMajor); - RS_SERIAL_PROCESS(mMinVersionMinor); - } -}; - -bool ServiceInfoCompatible(const RsServiceInfo &info1, const RsServiceInfo &info2); - -/* this is what is transmitted to peers */ -struct RsPeerServiceInfo : RsSerializable -{ - RsPeerServiceInfo() : mPeerId(), mServiceList() {} - - RsPeerId mPeerId; - std::map mServiceList; - - // RsSerializable interface - void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) { - RS_SERIAL_PROCESS(mPeerId); - RS_SERIAL_PROCESS(mServiceList); - } -}; - -struct RsServicePermissions : RsSerializable -{ - RsServicePermissions(); - - bool peerHasPermission(const RsPeerId &peerId) const; - - void setPermission(const RsPeerId& peerId) ; - void resetPermission(const RsPeerId& peerId) ; - - uint32_t mServiceId; - std::string mServiceName; - - bool mDefaultAllowed; - // note only one of these is checked. - // if DefaultAllowed = true, then only PeersDenied is checked. - // if DefaultAllowed = false, then only PeersAllowed is checked. - std::set mPeersAllowed; - std::set mPeersDenied; - - // RsSerializable interface - void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) { - RS_SERIAL_PROCESS(mServiceId); - RS_SERIAL_PROCESS(mServiceName); - - RS_SERIAL_PROCESS(mDefaultAllowed); - - RS_SERIAL_PROCESS(mPeersAllowed); - RS_SERIAL_PROCESS(mPeersDenied); - } -}; - -class RsServiceControl -{ -public: - - RsServiceControl() {} - virtual ~RsServiceControl(){} - - /** - * @brief get a map off all services. - * @jsonapi{development} - * @param[out] info storage for service information - * @return always true - */ - virtual bool getOwnServices(RsPeerServiceInfo &info) = 0; - - /** - * @brief getServiceName lookup the name of a service. - * @jsonapi{development} - * @param[in] serviceId service to look up - * @return name of service - */ - virtual std::string getServiceName(uint32_t serviceId) = 0; - - /** - * @brief getServiceItemNames return a map of service item names. - * @jsonapi{development} - * @param[in] serviceId service to look up - * @param[out] names names of items - * @return true on success false otherwise - */ - virtual bool getServiceItemNames(uint32_t serviceId, std::map& names) = 0; - - /** - * @brief getServicesAllowed return a mpa with allowed service information. - * @jsonapi{development} - * @param[in] peerId peer to look up - * @param[out] info map with infomration - * @return always true - */ - virtual bool getServicesAllowed(const RsPeerId &peerId, RsPeerServiceInfo &info) = 0; - - /** - * @brief getServicesProvided return services provided by a peer. - * @jsonapi{development} - * @param[in] peerId peer to look up - * @param[out] info - * @return true on success false otherwise. - */ - virtual bool getServicesProvided(const RsPeerId &peerId, RsPeerServiceInfo &info) = 0; - - /** - * @brief getServicePermissions return permissions of one service. - * @jsonapi{development} - * @param[in] serviceId service id to look up - * @param[out] permissions - * @return true on success false otherwise. - */ - virtual bool getServicePermissions(uint32_t serviceId, RsServicePermissions &permissions) = 0; - - /** - * @brief updateServicePermissions update service permissions of one service. - * @jsonapi{development} - * @param[in] serviceId service to update - * @param[in] permissions new permissions - * @return true on success false otherwise. - */ - virtual bool updateServicePermissions(uint32_t serviceId, const RsServicePermissions &permissions) = 0; - - /** - * @brief getPeersConnected return peers using a service. - * @jsonapi{development} - * @param[in] serviceId service to look up. - * @param[out] peerSet set of peers using this service. - */ - virtual void getPeersConnected( uint32_t serviceId, - std::set& peerSet ) = 0; -}; - -#endif diff --git a/libretroshare/src/retroshare/rsstatus.h b/libretroshare/src/retroshare/rsstatus.h deleted file mode 100644 index 3173726bb..000000000 --- a/libretroshare/src/retroshare/rsstatus.h +++ /dev/null @@ -1,96 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsstatus.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Vinny Do, Chris Evi-Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_STATUS_INTERFACE_H -#define RS_STATUS_INTERFACE_H - -class RsStatus; - -extern RsStatus *rsStatus; - -#include -#include -#include -#include -#include - - -const uint32_t RS_STATUS_OFFLINE = 0x0000; -const uint32_t RS_STATUS_AWAY = 0x0001; -const uint32_t RS_STATUS_BUSY = 0x0002; -const uint32_t RS_STATUS_ONLINE = 0x0003; -const uint32_t RS_STATUS_INACTIVE = 0x0004; - -const uint32_t RS_STATUS_COUNT = 0x0005; // count of status - -//! data object for peer status information -/*! - * data object used for peer status information - */ -class StatusInfo -{ - public: - StatusInfo() : status(RS_STATUS_OFFLINE), time_stamp(0) {} - - public: - RsPeerId id; - uint32_t status; - rstime_t time_stamp; /// for owner time set, and for their peers time sent -}; - - -//! Interface to retroshare for Rs status -/*! - * Provides an interface for retroshare's status functionality - */ -class RsStatus -{ - public: - - /** - * This retrieves the own status info - * @param statusInfo is populated with own status - */ - virtual bool getOwnStatus(StatusInfo& statusInfo) = 0; - - /** - * This retrieves the status info on the client's peers - * @param statusInfo is populated with client's peer's status - */ - virtual bool getStatusList(std::list& statusInfo) = 0; - - /** - * This retrieves the status info one peer - * @param statusInfo is populated with client's peer's status - */ - virtual bool getStatus(const RsPeerId &id, StatusInfo &statusInfo) = 0; - - /** - * send the client's status to his/her peers - * @param id the peer to send the status (empty, send to all) - * @param status the status of the peers - * @return will return false if status info does not belong to client - */ - virtual bool sendStatus(const RsPeerId &id, uint32_t status) = 0; -}; - - -#endif diff --git a/libretroshare/src/retroshare/rstokenservice.h b/libretroshare/src/retroshare/rstokenservice.h deleted file mode 100644 index a0fbd7258..000000000 --- a/libretroshare/src/retroshare/rstokenservice.h +++ /dev/null @@ -1,285 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rstokenservice.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Chris Evi-Parker * - * Copyright (C) 2012 Robert Fernie * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include - -#include "retroshare/rsgxsifacetypes.h" -#include "util/rsdeprecate.h" -#include "util/rsdebug.h" - -// TODO CLEANUP: GXS_REQUEST_TYPE_* should be an inner enum of RsTokReqOptions -#define GXS_REQUEST_TYPE_GROUP_DATA 0x00010000 -#define GXS_REQUEST_TYPE_GROUP_META 0x00020000 -#define GXS_REQUEST_TYPE_GROUP_IDS 0x00040000 -#define GXS_REQUEST_TYPE_MSG_DATA 0x00080000 -#define GXS_REQUEST_TYPE_MSG_META 0x00100000 -#define GXS_REQUEST_TYPE_MSG_IDS 0x00200000 - -#define GXS_REQUEST_TYPE_MSG_RELATED_DATA 0x00400000 -#define GXS_REQUEST_TYPE_MSG_RELATED_META 0x00800000 -#define GXS_REQUEST_TYPE_MSG_RELATED_IDS 0x01000000 - -#define GXS_REQUEST_TYPE_GROUP_STATS 0x01600000 -#define GXS_REQUEST_TYPE_SERVICE_STATS 0x03200000 -#define GXS_REQUEST_TYPE_GROUP_SERIALIZED_DATA 0x04000000 - - -// TODO CLEANUP: RS_TOKREQOPT_MSG_* should be an inner enum of RsTokReqOptions -#define RS_TOKREQOPT_MSG_VERSIONS 0x0001 // MSGRELATED: Returns All MsgIds with OrigMsgId = MsgId. -#define RS_TOKREQOPT_MSG_ORIGMSG 0x0002 // MSGLIST: All Unique OrigMsgIds in a Group. -#define RS_TOKREQOPT_MSG_LATEST 0x0004 // MSGLIST: All Latest MsgIds in Group. MSGRELATED: Latest MsgIds for Input Msgs. -#define RS_TOKREQOPT_MSG_THREAD 0x0010 // MSGRELATED: All Msgs in Thread. MSGLIST: All Unique Thread Ids in Group. -#define RS_TOKREQOPT_MSG_PARENT 0x0020 // MSGRELATED: All Children Msgs. -#define RS_TOKREQOPT_MSG_AUTHOR 0x0040 // MSGLIST: Messages from this AuthorId - - -/* TODO CLEANUP: RS_TOKREQ_ANSTYPE_* values are meaningless and not used by - * RsTokenService or its implementation, and may be arbitrarly defined by each - * GXS client as they are of no usage, their use is deprecated, up until the - * definitive cleanup is done new code must use RS_DEPRECATED_TOKREQ_ANSTYPE for - * easier cleanup. */ -#ifndef RS_NO_WARN_DEPRECATED -# warning RS_TOKREQ_ANSTYPE_* macros are deprecated! -#endif -#define RS_DEPRECATED_TOKREQ_ANSTYPE 0x0000 -#define RS_TOKREQ_ANSTYPE_LIST 0x0001 -#define RS_TOKREQ_ANSTYPE_SUMMARY 0x0002 -#define RS_TOKREQ_ANSTYPE_DATA 0x0003 -#define RS_TOKREQ_ANSTYPE_ACK 0x0004 - - -/*! - * This class provides useful generic support for GXS style services. - * I expect much of this will be incorporated into the base GXS. - */ -struct RsTokReqOptions -{ - RsTokReqOptions() : mOptions(0), mStatusFilter(0), mStatusMask(0), - mMsgFlagMask(0), mMsgFlagFilter(0), mReqType(0), mSubscribeFilter(0), - mSubscribeMask(0), mBefore(0), mAfter(0),mPriority(GxsRequestPriority::NORMAL) {} - - /** - * Can be one or multiple RS_TOKREQOPT_* - * TODO: cleanup this should be made with proper flags instead of macros - */ - uint32_t mOptions; - - // Request specific matches with Group / Message Status. - // Should be usable with any Options... applied afterwards. - uint32_t mStatusFilter; - uint32_t mStatusMask; - - // use - uint32_t mMsgFlagMask, mMsgFlagFilter; - - /** - * Must be one of GXS_REQUEST_TYPE_* - * TODO: cleanup this should be made an enum instead of macros - */ - uint32_t mReqType; - - uint32_t mSubscribeFilter, mSubscribeMask; // Only for Groups. - - // Time range... again applied after Options. - rstime_t mBefore; - rstime_t mAfter; - - GxsRequestPriority mPriority; -}; - -/*! - * A proxy class for requesting generic service data for GXS - * This seperates the request mechanism from the actual retrieval of data - */ -class RsTokenService -{ -public: - - enum GxsRequestStatus : uint8_t - { - FAILED = 0, - PENDING = 1, - PARTIAL = 2, - COMPLETE = 3, - DONE = 4, /// Once all data has been retrived - CANCELLED = 5 - }; - - RsTokenService() {} - virtual ~RsTokenService() {} - - /* Data Requests */ - - /*! - * Use this to request group related information - * @param token The token returned for the request, store this value to poll for request completion - * @param ansType The type of result (e.g. group data, meta, ids) - * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - * @param groupIds group id to request info for - * @return - */ - virtual bool requestGroupInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list &groupIds) = 0; - - /*! - * Use this to request all group related info - * @param token The token returned for the request, store this value to poll for request completion - * @param ansType The type of result (e.g. group data, meta, ids) - * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - * @return - */ - virtual bool requestGroupInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts) = 0; - - /*! - * Use this to get msg related information, store this value to poll for request completion - * @param token The token returned for the request - * @param ansType The type of result wanted - * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - * @param groupIds The ids of the groups to get, second entry of map empty to query for all msgs - * @return true if request successful false otherwise - */ - virtual bool requestMsgInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const GxsMsgReq& msgIds) = 0; - - /*! - * Use this to get msg related information, store this value to poll for request completion - * @param token The token returned for the request - * @param ansType The type of result wanted - * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - * @param groupIds The ids of the groups to get, this retrieves all the msgs info for each grpId in list - * @return true if request successful false otherwise - */ - virtual bool requestMsgInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::list& grpIds) = 0; - - /*! - * For requesting msgs related to a given msg id within a group - * @param token The token returned for the request - * @param ansType The type of result wanted - * @param opts Additional option that affect outcome of request. Please see specific services, for valid values - * @param groupIds The ids of the groups to get, second entry of map empty to query for all msgs - * @return true if request successful false otherwise - */ - virtual bool requestMsgRelatedInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, const std::vector& msgIds) = 0; - - /*! - * This request statistics on amount of data held - * number of groups - * number of groups subscribed - * number of messages - * size of db store - * total size of messages - * total size of groups - * @param token - */ - virtual void requestServiceStatistic(uint32_t& token, const RsTokReqOptions &opts) = 0; - - /*! - * To request statistic on a group - * @param token set to value to be redeemed to get statistic - * @param grpId the id of the group - */ - virtual void requestGroupStatistic(uint32_t& token, const RsGxsGroupId& grpId, const RsTokReqOptions &opts) = 0; - - - /* Poll */ - - /*! - * Request the status of ongoing request. - * Please use this for polling as much cheaper - * than polling the specific service as they might - * not return intermediate status information - * @param token value of token to check status for - * @return the current status of request - */ - virtual GxsRequestStatus requestStatus(const uint32_t token) = 0; - - /*! - * @brief Cancel Request - * If this function returns false, it may be that the request has completed - * already. Useful for very expensive request. - * @param token the token of the request to cancel - * @return false if unusuccessful in cancelling request, true if successful - */ - virtual bool cancelRequest(const uint32_t &token) = 0; - -#ifdef TO_REMOVE - /** - * Block caller while request is being processed. - * Useful for blocking API implementation. - * @param[in] token token associated to the request caller is waiting for - * @param[in] maxWait maximum waiting time in milliseconds - * @param[in] checkEvery time in millisecond between status checks - */ - RsTokenService::GxsRequestStatus waitToken( - uint32_t token, - std::chrono::milliseconds maxWait = std::chrono::milliseconds(10000), - std::chrono::milliseconds checkEvery = std::chrono::milliseconds(20), - bool auto_delete_if_unsuccessful=true) - { -#if defined(__ANDROID__) && (__ANDROID_API__ < 24) - auto wkStartime = std::chrono::steady_clock::now(); - int maxWorkAroundCnt = 10; -LLwaitTokenBeginLabel: -#endif - auto timeout = std::chrono::steady_clock::now() + maxWait; - auto st = requestStatus(token); - while( !(st == RsTokenService::FAILED || st >= RsTokenService::COMPLETE) && std::chrono::steady_clock::now() < timeout ) - { - std::this_thread::sleep_for(checkEvery); - st = requestStatus(token); - } - if(st != RsTokenService::COMPLETE && auto_delete_if_unsuccessful) - cancelRequest(token); - -#if defined(__ANDROID__) && (__ANDROID_API__ < 24) - /* Work around for very slow/old android devices, we don't expect this - * to be necessary on newer devices. If it take unreasonably long - * something worser is already happening elsewere and we return anyway. - */ - if( st > RsTokenService::FAILED && st < RsTokenService::COMPLETE - && maxWorkAroundCnt-- > 0 ) - { - maxWait *= 10; - checkEvery *= 3; - Dbg3() << __PRETTY_FUNCTION__ << " Slow Android device " - << " workaround st: " << st - << " maxWorkAroundCnt: " << maxWorkAroundCnt - << " maxWait: " << maxWait.count() - << " checkEvery: " << checkEvery.count() << std::endl; - goto LLwaitTokenBeginLabel; - } - Dbg3() << __PRETTY_FUNCTION__ << " lasted: " - << std::chrono::duration_cast( - std::chrono::steady_clock::now() - wkStartime ).count() - << "ms" << std::endl; - -#endif - - return st; - } -#endif - - RS_SET_CONTEXT_DEBUG_LEVEL(2) -}; diff --git a/libretroshare/src/retroshare/rstor.h b/libretroshare/src/retroshare/rstor.h deleted file mode 100644 index 654b79938..000000000 --- a/libretroshare/src/retroshare/rstor.h +++ /dev/null @@ -1,182 +0,0 @@ -#pragma once - -// This code stands as an interface for the automatic configuration -// of Tor hidden services to be used by retroshare. -// -// The correct way to use it is to: -// -// 1 - properly set data and hidden service directories. This allowd the TorManager -// to save its keys for the hidden service, or to load one that has previously been created -// -// 2 - call setupHiddenService(). This creates/loads the hidden service. -// -// 3 - call RsTor::start() -// -// 4 - loop/wait until RsTor::getHiddenServiceStatus(service_id) -// returns RsTorHiddenServiceStatus::ONLINE -// -// 5 - call RsTor::getHiddenserviceInfo to properly setup RS internal ports and addresses: -// -// RsTor::getHiddenServiceInfo(service_id,onion_address,service_port,service_target_address,service_target_port); -// RsTor::getProxyServerInfo(proxy_server_address,proxy_server_port) ; -// -// rsPeers->setLocalAddress(rsPeers->getOwnId(), service_target_address, service_target_port); -// rsPeers->setHiddenNode(rsPeers->getOwnId(), onion_address, service_port); -// rsPeers->setProxyServer(RS_HIDDEN_TYPE_TOR, proxy_server_address,proxy_server_port) ; - -#include "retroshare/rsevents.h" - -namespace Tor { - class TorManager; -} - -enum class RsTorManagerEventCode: uint8_t -{ - UNKNOWN = 0x00, - TOR_STATUS_CHANGED = 0x01, - BOOTSTRAP_STATUS_CHANGED = 0x02, - TOR_CONNECTIVITY_CHANGED = 0x03, - TOR_MANAGER_ERROR = 0x04, - CONFIGURATION_NEEDED = 0x05, - TOR_MANAGER_STOPPED = 0x06, -}; - -// Status of the Tor hidden service setup/loaded by RS - -enum class RsTorHiddenServiceStatus: uint8_t { - ERROR = 0x00, - NOT_CREATED = 0x01, - OFFLINE = 0x02, - ONLINE = 0x03 -}; - -// Status of the connection/authentication between RS and the Tor service - -enum class RsTorConnectivityStatus: uint8_t { - ERROR = 0x00, - NOT_CONNECTED = 0x01, - CONNECTING = 0x02, - SOCKET_CONNECTED = 0x03, - AUTHENTICATING = 0x04, - AUTHENTICATED = 0x05, - HIDDEN_SERVICE_READY = 0x06, - UNKNOWN = 0x07 -}; - -// Status of the Tor service with which RS is talking. - -enum class RsTorStatus: uint8_t { - UNKNOWN = 0x00, - OFFLINE = 0x01, - READY = 0x02 -}; - -struct RsTorManagerEvent: public RsEvent -{ - RsTorManagerEvent(): RsEvent(RsEventType::TOR_MANAGER), - mTorManagerEventType(RsTorManagerEventCode::UNKNOWN) - {} - - RsTorManagerEventCode mTorManagerEventType; - - RsTorConnectivityStatus mTorConnectivityStatus; - RsTorStatus mTorStatus; - std::string mErrorMessage; - - ///* @see RsEvent @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) override - { - RsEvent::serial_process(j, ctx); - RS_SERIAL_PROCESS(mTorManagerEventType); - RS_SERIAL_PROCESS(mTorConnectivityStatus); - RS_SERIAL_PROCESS(mTorStatus); - RS_SERIAL_PROCESS(mErrorMessage); - } - - ~RsTorManagerEvent() = default; -}; - -class RsTor -{ -public: - /*! - * \brief isTorAvailable - * \return true if a Tor executble has been found. False otherwise. - */ - static bool isTorAvailable() ; - - /*! - * \brief torStatus - * \return Status of the Tor service used by RS - */ - static RsTorStatus torStatus() ; - - /*! - * \brief torConnectivityStatus - * \return Status of the connectivity/authentication between RS and Tor - */ - static RsTorConnectivityStatus torConnectivityStatus() ; - - static void setTorDataDirectory(const std::string& dir); - static void setHiddenServiceDirectory(const std::string& dir); - - static bool setupHiddenService(); - - /*! - * \brief getProxyServerInfo - * \param server_address Address of the proxy used by RS to send data in the Tor network. Usually 127.0.0.1 - * \param server_port Port of the proxy used by RS to send data in the Tor network. Usually 9050. - */ - static void getProxyServerInfo(std::string& server_address, uint16_t& server_port); - - /*! - * \brief getHiddenServiceStatus - * \param service_id onion address of the hidden service (if the service is OFFLINE or ONLINE) - * \return Status of the created/loaded hidden service. - */ - static RsTorHiddenServiceStatus getHiddenServiceStatus(std::string& service_id); - - /*! - * \brief start - * Launches the Tor management threads. - */ - static bool start(); - - /*! - * \brief stop - * Stop the Tor management threads. - */ - static void stop(); - - /*! - * \brief getHiddenServiceInfo - * Gets information about the hidden service setup by RS to run. - * \param service_id - * \param service_onion_address - * \param service_port - * \param service_target_address - * \param target_port - * \return - */ - static bool getHiddenServiceInfo(std::string& service_id, - std::string& service_onion_address, - uint16_t& service_port, - std::string& service_target_address, - uint16_t& target_port); - - /*! - * \brief bootstrapStatus - * \return Log messages of the Tor bootstrapping status. - */ - static std::map bootstrapStatus(); - static std::list logMessages(); - - static std::string socksAddress(); - static uint16_t socksPort(); - - static bool hasError(); - static std::string errorMessage(); - -private: - static Tor::TorManager *instance(); -}; diff --git a/libretroshare/src/retroshare/rsturtle.h b/libretroshare/src/retroshare/rsturtle.h deleted file mode 100644 index 76120e85b..000000000 --- a/libretroshare/src/retroshare/rsturtle.h +++ /dev/null @@ -1,170 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsturtle.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009-2018 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -#include "serialiser/rstlvbinary.h" -#include "retroshare/rstypes.h" -#include "retroshare/rsgxsifacetypes.h" -#include "serialiser/rsserializable.h" - -namespace RsRegularExpression { class LinearizedExpression ; } -class RsTurtleClientService ; - -class RsTurtle; - -/** - * Pointer to global instance of RsTurtle service implementation - */ -extern RsTurtle* rsTurtle; - -typedef uint32_t TurtleRequestId ; -typedef RsPeerId TurtleVirtualPeerId; - -struct TurtleFileInfo : RsSerializable -{ - TurtleFileInfo() : size(0) {} - - uint64_t size; /// File size - RsFileHash hash; /// File hash - std::string name; /// File name - - /// @see RsSerializable::serial_process - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { - RS_SERIAL_PROCESS(size); - RS_SERIAL_PROCESS(hash); - - // Use String TLV serial process for retrocompatibility - RsTypeSerializer::serial_process( - j, ctx, TLV_TYPE_STR_NAME, name, "name" ); - } -} RS_DEPRECATED_FOR(TurtleFileInfoV2); - -struct TurtleTunnelRequestDisplayInfo -{ - uint32_t request_id ; // Id of the request - RsPeerId source_peer_id ; // Peer that relayed the request - uint32_t age ; // Age in seconds - uint32_t depth ; // Depth of the request. Might be altered. -}; -struct TurtleSearchRequestDisplayInfo -{ - uint32_t request_id ; // Id of the request - RsPeerId source_peer_id ; // Peer that relayed the request - uint32_t age ; // Age in seconds - uint32_t depth ; // Depth of the request. Might be altered. - uint32_t hits ; - std::string keywords; -}; - -class TurtleTrafficStatisticsInfo -{ - public: - float unknown_updn_Bps ; // unknown data transit bitrate (in Bytes per sec.) - float data_up_Bps ; // upload (in Bytes per sec.) - float data_dn_Bps ; // download (in Bytes per sec.) - float tr_up_Bps ; // tunnel requests upload bitrate (in Bytes per sec.) - float tr_dn_Bps ; // tunnel requests dnload bitrate (in Bytes per sec.) - float total_up_Bps ; // turtle network management bitrate (in Bytes per sec.) - float total_dn_Bps ; // turtle network management bitrate (in Bytes per sec.) - - std::vector forward_probabilities ; // probability to forward a TR as a function of depth. -}; - -// Interface class for turtle hopping. -// -// This class mainly interacts with the turtle router, that is responsible -// for routing turtle packets between peers, accepting/forwarding search -// requests and dowloading files. -// -// As seen from here, the interface is really simple. -// -class RsTurtle -{ -public: - RsTurtle() {} - virtual ~RsTurtle() {} - - // This is saved permanently. - virtual void setEnabled(bool) = 0 ; - virtual bool enabled() const = 0 ; - - // This is temporary, used by Operating Mode. - virtual void setSessionEnabled(bool) = 0 ; - virtual bool sessionEnabled() const = 0 ; - - /** Lauches a search request through the pipes, and immediately returns - * the request id, which will be further used by client services to - * handle results as they come back. */ - virtual TurtleRequestId turtleSearch( - unsigned char *search_bin_data, uint32_t search_bin_data_len, - RsTurtleClientService* client_service ) = 0; - - // Initiates tunnel handling for the given file hash. tunnels. Launches - // an exception if an error occurs during the initialization process. The - // turtle router itself does not initiate downloads, it only maintains - // tunnels for the given hash. The download should be driven by the file - // transfer module by calling ftServer::FileRequest(). - // Aggressive mode causes the turtle router to regularly re-ask tunnels in addition to the ones already - // available without replacing them. In non aggressive mode, we wait for all tunnels to die before asking - // for new tunnels. - // - virtual void monitorTunnels(const RsFileHash& file_hash,RsTurtleClientService *client_service,bool use_aggressive_mode) = 0 ; - - // Tells the turtle router to stop handling tunnels for the given file hash. Traditionally this should - // be called after calling ftServer::fileCancel(). - // - virtual void stopMonitoringTunnels(const RsFileHash& file_hash) = 0 ; - - /// Adds a client tunnel service. This means that the service will be added - /// to the list of services that might respond to tunnel requests. - /// Example tunnel services include: - /// - /// p3ChatService: tunnels correspond to private distant chatting - /// ftServer : tunnels correspond to file data transfer - /// - virtual void registerTunnelService(RsTurtleClientService *service) = 0; - - virtual std::string getPeerNameForVirtualPeerId(const RsPeerId& virtual_peer_id) = 0; - - // Get info from the turtle router. I use std strings to hide the internal structs. - // - virtual void getInfo(std::vector >&,std::vector >&, - std::vector&,std::vector&) const = 0; - - // Get info about turtle traffic. See TurtleTrafficStatisticsInfo members for details. - // - virtual void getTrafficStatistics(TurtleTrafficStatisticsInfo& info) const = 0; - - // Convenience function. - virtual bool isTurtlePeer(const RsPeerId& peer_id) const = 0 ; - - // Hardcore handles - virtual void setMaxTRForwardRate(int max_tr_up_rate) = 0 ; - virtual int getMaxTRForwardRate() const = 0 ; -}; diff --git a/libretroshare/src/retroshare/rstypes.h b/libretroshare/src/retroshare/rstypes.h deleted file mode 100644 index 1920e665a..000000000 --- a/libretroshare/src/retroshare/rstypes.h +++ /dev/null @@ -1,545 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: rstypes.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie * - * Copyright (C) 2018-2021 Gioacchino Mazzurco * - * Copyright (C) 2020-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_TYPES_GUI_INTERFACE_H -#define RS_TYPES_GUI_INTERFACE_H - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include "util/rstime.h" - -#define USE_NEW_CHUNK_CHECKING_CODE - -typedef Sha1CheckSum RsFileHash ; - -const uint32_t FT_STATE_FAILED = 0x0000 ; -const uint32_t FT_STATE_OKAY = 0x0001 ; -const uint32_t FT_STATE_WAITING = 0x0002 ; -const uint32_t FT_STATE_DOWNLOADING = 0x0003 ; -const uint32_t FT_STATE_COMPLETE = 0x0004 ; -const uint32_t FT_STATE_QUEUED = 0x0005 ; -const uint32_t FT_STATE_PAUSED = 0x0006 ; -const uint32_t FT_STATE_CHECKING_HASH = 0x0007 ; - -// These constants are used by RsDiscSpace -// -const uint32_t RS_PARTIALS_DIRECTORY = 0x0000 ; -const uint32_t RS_DOWNLOAD_DIRECTORY = 0x0001 ; -const uint32_t RS_CONFIG_DIRECTORY = 0x0002 ; -const uint32_t RS_PGP_DIRECTORY = 0x0003 ; -const uint32_t RS_DIRECTORY_COUNT = 0x0004 ; - -struct TransferInfo : RsSerializable -{ - /**** Need Some of these Fields ****/ - RsPeerId peerId; - std::string name; /* if has alternative name? */ - double tfRate; /* kbytes */ - int status; /* FT_STATE_... */ - uint64_t transfered ; // used when no chunkmap data is available - - /// @see RsSerializable - void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) - { - RS_SERIAL_PROCESS(peerId); - RS_SERIAL_PROCESS(name); - RS_SERIAL_PROCESS(tfRate); - RS_SERIAL_PROCESS(status); - RS_SERIAL_PROCESS(transfered); - } -}; - -enum QueueMove { QUEUE_TOP = 0x00, - QUEUE_UP = 0x01, - QUEUE_DOWN = 0x02, - QUEUE_BOTTOM = 0x03 -}; - -enum DwlSpeed : uint8_t -{ - SPEED_LOW = 0x00, - SPEED_NORMAL = 0x01, - SPEED_HIGH = 0x02 -}; - - - - -/********************** For Search Interface *****************/ - -/* This is still rough, implement later! */ - - /* text based ones */ -const std::string TypeExt = "ext"; -const std::string TypeName = "name"; -const std::string TypeHash = "hash"; -const std::string TypeSize = "size"; - -const int OpContains = 0x001; -const int OpExactMatch = 0x002; -const int OpLessThan = 0x003; -const int OpGreaterThan = 0x004; - -class Condition -{ - public: - - std::string type; - int op; - double value; - std::string name; -}; - -struct PeerBandwidthLimits : RsSerializable -{ - PeerBandwidthLimits() : max_up_rate_kbs(0), max_dl_rate_kbs(0) {} - - uint32_t max_up_rate_kbs; - uint32_t max_dl_rate_kbs; - - - /// @see RsSerializable - void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) - { - RS_SERIAL_PROCESS(max_up_rate_kbs); - RS_SERIAL_PROCESS(max_dl_rate_kbs); - } -}; - -/********************** For FileCache Interface *****************/ - -/* G10h4ck: Having this kind of stuff on public headers is pretty dangerous for - * name space pollution, a C++11 enum class should be used instad ASAP */ -#define DIR_TYPE_UNKNOWN 0x00 -#define DIR_TYPE_ROOT 0x01 -#define DIR_TYPE_PERSON 0x02 -#define DIR_TYPE_DIR 0x04 -#define DIR_TYPE_FILE 0x08 -#define DIR_TYPE_EXTRA_FILE 0x10 - -/* flags for Directry request - - * two types; - * (1) Local / Remote (top byte) - * (2) Request type: Parent / Child - allows reduction in workload. - * (TODO) - */ - -const FileStorageFlags DIR_FLAGS_PARENT ( 0x0001 ); -const FileStorageFlags DIR_FLAGS_DETAILS ( 0x0002 ); // apparently unused -const FileStorageFlags DIR_FLAGS_CHILDREN ( 0x0004 ); // apparently unused - -const FileStorageFlags DIR_FLAGS_ANONYMOUS_DOWNLOAD ( 0x0080 ); // Flags for directory sharing permissions. The last -//const FileStorageFlags DIR_FLAGS_BROWSABLE_OTHERS ( 0x0100 ); // one should be the OR of the all four flags. -//const FileStorageFlags DIR_FLAGS_NETWORK_WIDE_GROUPS ( 0x0200 ); -const FileStorageFlags DIR_FLAGS_BROWSABLE ( 0x0400 ); -const FileStorageFlags DIR_FLAGS_ANONYMOUS_SEARCH ( 0x0800 ); -const FileStorageFlags DIR_FLAGS_PERMISSIONS_MASK ( DIR_FLAGS_ANONYMOUS_DOWNLOAD | /*DIR_FLAGS_BROWSABLE_OTHERS - DIR_FLAGS_NETWORK_WIDE_GROUPS*/ DIR_FLAGS_BROWSABLE | DIR_FLAGS_ANONYMOUS_SEARCH); - -const FileStorageFlags DIR_FLAGS_LOCAL ( 0x1000 ); -const FileStorageFlags DIR_FLAGS_REMOTE ( 0x2000 ); - -struct FileInfo : RsSerializable -{ - FileInfo(): - mId(0), searchId(0), size(0), avail(0), rank(0), age(0), - queue_position(0), transfered(0), tfRate(0), downloadStatus(0), - priority(SPEED_NORMAL), lastTS(0) {} - - /// Combination of the four RS_DIR_FLAGS_*. Updated when the file is a local stored file. - FileStorageFlags storage_permission_flags; - - /// various flags from RS_FILE_HINTS_* - TransferRequestFlags transfer_info_flags; - - /** allow this to be tweaked by the GUI Model - * (GUI) Model Id -> unique number - */ - mutable unsigned int mId; - - - /// 0 if none - int searchId; - - std::string path; - std::string fname; - RsFileHash hash; - - RS_DEPRECATED std::string ext; /// @deprecated unused - - uint64_t size; - uint64_t avail; /// how much we have - - double rank; - int age; - uint32_t queue_position; - - /* Transfer Stuff */ - uint64_t transfered; - double tfRate; /// in kbytes - uint32_t downloadStatus; /// FT_STATE_DOWNLOADING & co. See rstypes.h - std::vector peers; - - DwlSpeed priority; - rstime_t lastTS; - - std::list parent_groups; - - /// @see RsSerializable - void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) - { - RS_SERIAL_PROCESS(storage_permission_flags); - RS_SERIAL_PROCESS(transfer_info_flags); - RS_SERIAL_PROCESS(mId); - RS_SERIAL_PROCESS(searchId); - RS_SERIAL_PROCESS(path); - RS_SERIAL_PROCESS(fname); - RS_SERIAL_PROCESS(hash); - RS_SERIAL_PROCESS(ext); - RS_SERIAL_PROCESS(size); - RS_SERIAL_PROCESS(avail); - RS_SERIAL_PROCESS(rank); - RS_SERIAL_PROCESS(age); - RS_SERIAL_PROCESS(queue_position); - RS_SERIAL_PROCESS(transfered); - RS_SERIAL_PROCESS(tfRate); - RS_SERIAL_PROCESS(downloadStatus); - RS_SERIAL_PROCESS(peers); - RS_SERIAL_PROCESS(priority); - RS_SERIAL_PROCESS(lastTS); - RS_SERIAL_PROCESS(parent_groups); - } -}; - -/** - * Pointers in this class have no real meaning as pointers, they are used as - * indexes, internally by retroshare. - */ -struct DirStub : RsSerializable -{ - DirStub() : type(DIR_TYPE_UNKNOWN), ref(nullptr) {} - - uint8_t type; - std::string name; - - /* G10h4ck do we still need to keep this as void* instead of uint64_t for - * retroshare-gui sake? */ - void* ref; - - /// @see RsSerializable - void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) - { - RS_SERIAL_PROCESS(type); - RS_SERIAL_PROCESS(name); - - /* Enforce serialization as uint64_t because void* changes size (usually - * 4 bytes on 32bit arch and 8 bytes on 64bit archs) depending on - * architectures and make JSON API behave inconsistenly. */ - uint64_t handle = reinterpret_cast(ref); - RS_SERIAL_PROCESS(handle); - ref = reinterpret_cast(handle); - } -}; - -/** - * Pointers in this class have no real meaning as pointers, they are used as - * indexes, internally by retroshare. - */ -struct DirDetails : RsSerializable -{ - DirDetails() : parent(nullptr), prow(0), ref(nullptr), - type(DIR_TYPE_UNKNOWN), size(0), mtime(0), max_mtime(0) {} - - - /* G10h4ck do we still need to keep this as void* instead of uint64_t for - * retroshare-gui sake? */ - void* parent; - - int prow; /* parent row */ - - /* G10h4ck do we still need to keep this as void* instead of uint64_t for - * retroshare-gui sake? */ - void* ref; - - uint8_t type; - RsPeerId id; - std::string name; - RsFileHash hash; - std::string path; // full path of the parent directory, when it is a file; full path of the dir otherwise. - uint64_t size; // total size of directory, or size of the file. - uint32_t mtime; // file/directory modification time, according to what the system reports - FileStorageFlags flags; - uint32_t max_mtime ; // maximum modification time of the whole hierarchy below. - - std::vector children; - std::list parent_groups; // parent groups for the shared directory - - /// @see RsSerializable - void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - /* Enforce serialization as uint64_t because void* changes size (usually - * 4 bytes on 32bit arch and 8 bytes on 64bit archs) depending on - * architectures and make JSON API behave inconsistenly. */ - uint64_t handle = reinterpret_cast(ref); - RS_SERIAL_PROCESS(handle); - ref = reinterpret_cast(handle); - - uint64_t parentHandle = reinterpret_cast(parent); - RS_SERIAL_PROCESS(parentHandle); - parent = reinterpret_cast(parentHandle); - - RS_SERIAL_PROCESS(prow); - RS_SERIAL_PROCESS(type); - RS_SERIAL_PROCESS(id); - RS_SERIAL_PROCESS(name); - RS_SERIAL_PROCESS(hash); - RS_SERIAL_PROCESS(path); - RS_SERIAL_PROCESS(size); - RS_SERIAL_PROCESS(mtime); - RS_SERIAL_PROCESS(flags); - RS_SERIAL_PROCESS(max_mtime); - RS_SERIAL_PROCESS(children); - RS_SERIAL_PROCESS(parent_groups); - } - - ~DirDetails() override = default; -}; - -class FileDetail -{ - public: - RsPeerId id; - std::string name; - RsFileHash hash; - std::string path; - uint64_t size; - uint32_t age; - uint32_t rank; -}; - -class CompressedChunkMap ; - -struct FileChunksInfo : RsSerializable -{ - enum ChunkState : uint8_t - { - CHUNK_OUTSTANDING = 0, - CHUNK_ACTIVE = 1, - CHUNK_DONE = 2, - CHUNK_CHECKING = 3 - }; - - enum ChunkStrategy : uint8_t - { - CHUNK_STRATEGY_STREAMING, - CHUNK_STRATEGY_RANDOM, - CHUNK_STRATEGY_PROGRESSIVE - }; - - struct SliceInfo : RsSerializable - { - uint32_t start; - uint32_t size; - RsPeerId peer_id; - - /// @see RsSerializable - void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) override - { - RS_SERIAL_PROCESS(start); - RS_SERIAL_PROCESS(size); - RS_SERIAL_PROCESS(peer_id); - } - }; - - uint64_t file_size; /// real size of the file - uint32_t chunk_size; /// size of chunks - ChunkStrategy strategy; - - /// dl state of chunks. Only the last chunk may have size < chunk_size - std::vector chunks; - - /// For each source peer, gives the compressed bit map of have/don't have sate - std::map compressed_peer_availability_maps; - - /// For each chunk (by chunk number), gives the completion of the chunk. - std::vector > active_chunks; - - /// The list of pending requests, chunk per chunk (by chunk id) - std::map > pending_slices; - - /// @see RsSerializable - void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) - { - RS_SERIAL_PROCESS(file_size); - RS_SERIAL_PROCESS(chunk_size); - RS_SERIAL_PROCESS(strategy); - RS_SERIAL_PROCESS(chunks); - RS_SERIAL_PROCESS(compressed_peer_availability_maps); - RS_SERIAL_PROCESS(active_chunks); - RS_SERIAL_PROCESS(pending_slices); - } -}; - -class CompressedChunkMap : public RsSerializable -{ - public: - CompressedChunkMap() {} - - CompressedChunkMap(const std::vector& uncompressed_data) - { - _map.resize( getCompressedSize(uncompressed_data.size()),0 ) ; - - for(uint32_t i=0;i>5) + !!(size&31) ; } - - uint32_t filledChunks(uint32_t nbchks) const - { - uint32_t res = 0 ; - for(uint32_t i=0;i> 5] & (1 << (i & 31))) > 0 ; } - - inline void set(uint32_t j) { _map[j >> 5] |= (1 << (j & 31)) ; } - inline void reset(uint32_t j) { _map[j >> 5] &= ~(1 << (j & 31)) ; } - - /// compressed map, one bit per chunk - std::vector _map; - - /// @see RsSerializable - void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) - { RS_SERIAL_PROCESS(_map); } -}; - - -template class t_CRCMap -{ - public: - // Build from a file. - // - t_CRCMap(uint64_t file_size,uint32_t chunk_size) - : _crcs( file_size/chunk_size + ( (file_size%chunk_size)>0)), _ccmap(file_size/chunk_size + ( (file_size%chunk_size)>0),0) - { - } - t_CRCMap() {} - - inline void set(uint32_t i,const CRCTYPE& val) { _crcs[i] = val ; _ccmap.set(i) ; } - inline bool isSet(uint32_t i) const { return _ccmap[i] ; } - - inline const CRCTYPE& operator[](int i) const { return _crcs[i] ; } - inline uint32_t size() const { return _crcs.size() ; } - private: - std::vector _crcs; - CompressedChunkMap _ccmap ; - - friend class RsTurtleFileCrcItem ; - friend class RsFileItemSerialiser ; - friend class RsFileCRC32Map ; -}; - -//typedef t_CRCMap CRC32Map ; -typedef t_CRCMap Sha1Map ; - -/* class which encapsulates download details */ -class DwlDetails { -public: - DwlDetails() { return; } - DwlDetails(const std::string& fname, const RsFileHash& hash, int count, std::string dest, - uint32_t flags, std::list srcIds, uint32_t queue_pos) - : fname(fname), hash(hash), count(count), dest(dest), flags(flags), - srcIds(srcIds), queue_position(queue_pos), retries(0) { return; } - - /* download details */ - std::string fname; - RsFileHash hash; - int count; - std::string dest; - uint32_t flags; - std::list srcIds; - - /* internally used in download queue */ - uint32_t queue_position; - - /* how many times a failed dwl will be requeued */ - unsigned int retries; -}; - -/* class for the information about a used library */ -class RsLibraryInfo -{ -public: - RsLibraryInfo() {} - RsLibraryInfo(const std::string &name, const std::string &version) : - mName(name), mVersion(version) - {} - -public: - std::string mName; - std::string mVersion; -}; - -#endif diff --git a/libretroshare/src/retroshare/rsversion.h b/libretroshare/src/retroshare/rsversion.h deleted file mode 100644 index c16f6b9e7..000000000 --- a/libretroshare/src/retroshare/rsversion.h +++ /dev/null @@ -1,86 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsversion.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012-2018 Retroshare Team * - * Copyright (C) 2018-2020 Gioacchino Mazzurco * - * Copyright (C) 2020 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -/** - * @def RS_MINI_VERSION - * First number of RetroShare versioning scheme - * Customize it trough qmake command line @see retroshare.pri - */ -#ifndef RS_MAJOR_VERSION -# define RS_MAJOR_VERSION 0 -#endif - -/** - * @def RS_MINI_VERSION - * Second number of RetroShare versioning scheme - * Customize it trough qmake command line @see retroshare.pri - */ -#ifndef RS_MINOR_VERSION -# define RS_MINOR_VERSION 6 -#endif - -/** - * @def RS_MINI_VERSION - * Third number of RetroShare versioning scheme - * Customize it trough qmake command line @see retroshare.pri - */ -#ifndef RS_MINI_VERSION -# define RS_MINI_VERSION 6 -#endif - -/** - * @def RS_EXTRA_VERSION - * An extra string to append to the version to make it more descriptive. - * Customize it trough qmake command line @see retroshare.pri - */ -#ifndef RS_EXTRA_VERSION -# define RS_EXTRA_VERSION "" -#endif - - -/** - * Use this macro to check in your code if version of RetroShare is at least the - * specified. - */ -#define RS_VERSION_AT_LEAST(A,B,C) (RS_MAJOR_VERSION > (A) || \ - (RS_MAJOR_VERSION == (A) && \ - (RS_MINOR_VERSION > (B) || \ - (RS_MINOR_VERSION == (B) && RS_MINI_VERSION >= (C))))) - - -#define RS_PRIVATE_STRINGIFY2(X) #X -#define RS_PRIVATE_STRINGIFY(X) RS_PRIVATE_STRINGIFY2(X) - -/** - * Human readable string describing RetroShare version - */ -constexpr auto RS_HUMAN_READABLE_VERSION = - RS_PRIVATE_STRINGIFY(RS_MAJOR_VERSION) "." \ - RS_PRIVATE_STRINGIFY(RS_MINOR_VERSION) "." \ - RS_PRIVATE_STRINGIFY(RS_MINI_VERSION) RS_EXTRA_VERSION; - -/* Because RetroShare-gui include this file in gui/images/retroshare_win.rc - * including any C++ things like `#include ` will break compilation of - * RetroShare-gui on Windows. Therefore this file must be kept minimal. */ diff --git a/libretroshare/src/retroshare/rswebui.h b/libretroshare/src/retroshare/rswebui.h deleted file mode 100644 index d7166f545..000000000 --- a/libretroshare/src/retroshare/rswebui.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * RetroShare Web User Interface public header - * - * Copyright (C) 2019 Cyril Soler - * - * This program is free software: you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the Free - * Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - * details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see - * - * SPDX-FileCopyrightText: 2004-2019 RetroShare Team - * SPDX-License-Identifier: LGPL-3.0-or-later - */ - -#pragma once - -#include - -class RsWebUi; - -/** - * Pointer to global instance of RsWebUi service implementation - * jsonapi_temporarly_disabled{development} because it breaks compilation when - * webui is disabled - */ -extern RsWebUi* rsWebUi; - -class RsWebUi -{ -public: - static const std::string DEFAULT_BASE_DIRECTORY; - - /** - * @brief Restart WebUI - * @jsonapi{development} - */ - virtual bool restart() = 0; - - /** - * @brief Stop WebUI - * @jsonapi{development} - */ - virtual bool stop() = 0; - - /** - * @brief Set WebUI static files directory, need restart to apply - * @param[in] htmlDir directory path - * @jsonapi{development} - */ - virtual void setHtmlFilesDirectory(const std::string& htmlDir) = 0; - - /** - * @brief Set WebUI user password - * @param[in] password new password for WebUI - * @jsonapi{development} - */ - virtual void setUserPassword(const std::string& password) =0; - - /** - * @brief check if WebUI is running - * @jsonapi{development} - * @return true if running, false otherwise - */ - virtual bool isRunning() const = 0; - - virtual ~RsWebUi() = default; -}; diff --git a/libretroshare/src/retroshare/rswiki.h b/libretroshare/src/retroshare/rswiki.h deleted file mode 100644 index 401f2cbab..000000000 --- a/libretroshare/src/retroshare/rswiki.h +++ /dev/null @@ -1,134 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsturtle.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RETROSHARE_WIKI_GUI_INTERFACE_H -#define RETROSHARE_WIKI_GUI_INTERFACE_H - -#include -#include -#include - -#include "retroshare/rstokenservice.h" -#include "retroshare/rsgxsifacehelper.h" - -/* The Main Interface Class - for information about your Peers */ -class RsWiki; -extern RsWiki *rsWiki; - - -/* so the basic idea of Wiki is a set of Collections about subjects. - * - * Collection: RS - * - page: DHT - * - edit - * - edit - * - official revision. (new version of thread head). - * - * A collection will be moderated by it creator - important to prevent stupid changes. - * We need a way to swap out / replace / fork collections if moderator is rubbish. - * - * This should probably be done that the collection level. - * and enable all the references to be modified. - * - * Collection1 (RS DHT) - * : Turtle Link: Collection 0x54e4dafc34 - * - Page 1 - * - Page 2 - * - Link to Self:Page 1 - * - Link to Turtle:Page 1 - * - * - */ - -#define FLAG_MSG_TYPE_WIKI_SNAPSHOT 0x0001 -#define FLAG_MSG_TYPE_WIKI_COMMENT 0x0002 - -class CollectionRef -{ - public: - - std::string KeyWord; - std::string CollectionId; -}; - -struct RsWikiCollection: RsGxsGenericGroupData -{ - public: - std::string mDescription; - std::string mCategory; - - std::string mHashTags; - - // std::map linkReferences; -}; - -class RsWikiSnapshot -{ - public: - - RsMsgMetaData mMeta; - - std::string mPage; // all the text is stored here. - std::string mHashTags; -}; - - -class RsWikiComment -{ - public: - - RsMsgMetaData mMeta; - std::string mComment; -}; - -std::ostream &operator<<(std::ostream &out, const RsWikiCollection &group); -std::ostream &operator<<(std::ostream &out, const RsWikiSnapshot &shot); -std::ostream &operator<<(std::ostream &out, const RsWikiComment &comment); - - -class RsWiki: public RsGxsIfaceHelper -{ -public: - - RsWiki(RsGxsIface& gxs): RsGxsIfaceHelper(gxs) {} - virtual ~RsWiki() {} - - /* Specific Service Data */ -virtual bool getCollections(const uint32_t &token, std::vector &collections) = 0; -virtual bool getSnapshots(const uint32_t &token, std::vector &snapshots) = 0; -virtual bool getComments(const uint32_t &token, std::vector &comments) = 0; - -virtual bool getRelatedSnapshots(const uint32_t &token, std::vector &snapshots) = 0; - -virtual bool submitCollection(uint32_t &token, RsWikiCollection &collection) = 0; -virtual bool submitSnapshot(uint32_t &token, RsWikiSnapshot &snapshot) = 0; -virtual bool submitComment(uint32_t &token, RsWikiComment &comment) = 0; - -virtual bool updateCollection(uint32_t &token, RsWikiCollection &collection) = 0; - - // Blocking Interfaces. -virtual bool createCollection(RsWikiCollection &collection) = 0; -virtual bool updateCollection(const RsWikiCollection &collection) = 0; -virtual bool getCollections(const std::list groupIds, std::vector &groups) = 0; - -}; - -#endif diff --git a/libretroshare/src/retroshare/rswire.h b/libretroshare/src/retroshare/rswire.h deleted file mode 100644 index 34c953cee..000000000 --- a/libretroshare/src/retroshare/rswire.h +++ /dev/null @@ -1,250 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsturtle.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2020 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RETROSHARE_WIRE_GUI_INTERFACE_H -#define RETROSHARE_WIRE_GUI_INTERFACE_H - -#include -#include -#include - -#include "retroshare/rstokenservice.h" -#include "retroshare/rsgxsifacehelper.h" -#include "retroshare/rsgxscommon.h" - - -/* The Main Interface Class - for information about your Peers */ -class RsWire; -extern RsWire *rsWire; - -class RsWireGroup; -typedef std::shared_ptr RsWireGroupSPtr; -typedef std::shared_ptr RsWireGroupConstSPtr; - -class RsWireGroup: public RsGxsGenericGroupData -{ - public: - RsWireGroup(); - - std::string mTagline; - std::string mLocation; - - // Images max size should be enforced. - RsGxsImage mHeadshot; // max size? - RsGxsImage mMasthead; // max size? - - // Unserialised stuff --------------------- - - // These are this groups top-level msgs. - uint32_t mGroupPulses; - uint32_t mGroupRepublishes; - uint32_t mGroupLikes; - uint32_t mGroupReplies; - // how do we handle these. TODO - // uint32_t mGroupFollowing; - // uint32_t mGroupFollowers; - - // These are this groups REF / RESPONSE msgs from others. - uint32_t mRefMentions; // TODO how to handle this? - uint32_t mRefRepublishes; - uint32_t mRefLikes; - uint32_t mRefReplies; -}; - - -/*********************************************************************** - * RsWire - is intended to be a Twitter clone - but fully decentralised. - * - * From Twitter: - * twitter can be: embedded, replied to, favourited, unfavourited, - * retweeted, unretweeted and deleted - * - * See: https://dev.twitter.com/docs/platform-objects - * - * Format of message: .... - * - * #HashTags. - * @68769381495134 => ID of Sender. - * - * - ***********************************************************************/ - - - -/************************************************************************ - * Pulse comes in three flavours. - * - * - * Original Msg Pulse - * - Spontaneous msg, on your own group. - * - mPulseType = WIRE_PULSE_TYPE_ORIGINAL_MSG - * - Ref fields are empty. - * - * Reply to a Pulse (i.e Retweet), has two parts. - * as we want the retweet to reference the original, and the original to know about reply. - * This info will be duplicated in two msgs - but allow data to spread easier. - * - * Reply Msg Pulse, will be Top-Level Msg on Publisher's Group. - * - mPulseMode = WIRE_PULSE_TYPE_RESPONSE | WIRE_PULSE_TYPE_REPLY - * - Ref fields refer to Parent (InReplyTo) Msg. - * - * Reply Reference, is Child Msg of Parent Msg, on Parent Publisher's Group. - * - mPulseMode = WIRE_PULSE_TYPE_REFERENCE | WIRE_PULSE_TYPE_REPLY - * - Ref fields refer to Reply Msg. - * - NB: This Msg requires Parent Msg for complete info, while other two are self-contained. - * - * Additionally need to sort out additional relationships. - * - Mentions. - * - Followers. - * - Following. - ***********************************************************************/ - -#define WIRE_PULSE_TYPE_ORIGINAL (0x0001) -#define WIRE_PULSE_TYPE_RESPONSE (0x0002) -#define WIRE_PULSE_TYPE_REFERENCE (0x0004) - -#define WIRE_PULSE_RESPONSE_MASK (0x0f00) -#define WIRE_PULSE_TYPE_REPLY (0x0100) -#define WIRE_PULSE_TYPE_REPUBLISH (0x0200) -#define WIRE_PULSE_TYPE_LIKE (0x0400) - -#define WIRE_PULSE_SENTIMENT_NO_SENTIMENT (0x0000) -#define WIRE_PULSE_SENTIMENT_POSITIVE (0x0001) -#define WIRE_PULSE_SENTIMENT_NEUTRAL (0x0002) -#define WIRE_PULSE_SENTIMENT_NEGATIVE (0x0003) - -class RsWirePulse; - -typedef std::shared_ptr RsWirePulseSPtr; -typedef std::shared_ptr RsWirePulseConstSPtr; - -class RsWirePulse -{ - public: - - RsMsgMetaData mMeta; - - // Store actual Pulse here. - std::string mPulseText; - - uint32_t mPulseType; - uint32_t mSentiment; // sentiment can be asserted at any point. - - // These Ref to the related (parent or reply) if reply (RESPONSE set) - // Mode RESPONSE REFERENCE - RsGxsGroupId mRefGroupId; // PARENT_GrpId REPLY_GrpId - std::string mRefGroupName; // PARENT_GrpName REPLY_GrpName - RsGxsMessageId mRefOrigMsgId; // PARENT_OrigMsgId REPLY_OrigMsgId - RsGxsId mRefAuthorId; // PARENT_AuthorId REPLY_AuthorId - rstime_t mRefPublishTs; // PARENT_PublishTs REPLY_PublishTs - std::string mRefPulseText; // PARENT_PulseText REPLY_PulseText - uint32_t mRefImageCount; // PARENT_#Images REPLY_#Images - - // Additional Fields for version 2. - // Images, need to enforce 20k limit? - RsGxsImage mImage1; - RsGxsImage mImage2; - RsGxsImage mImage3; - RsGxsImage mImage4; - - // Below Here is not serialised. - // They are additional fields linking pulses together or parsing elements of msg. - - // functions. - uint32_t ImageCount(); - - // can't have self referencial list, so need to use pointers. - // using SharedPointers to automatically cleanup. - - // Pointer to WireGroups - // mRefGroupPtr is opportunistically filled in, but will often be empty. - RsWireGroupSPtr mRefGroupPtr; // ORIG: N/A, RESP: Parent, REF: Reply Group - RsWireGroupSPtr mGroupPtr; // ORIG: Own, RESP: Own, REF: Parent Group - - // These are the direct children of this message - // split into likes, replies and retweets. - std::list mReplies; - std::list mLikes; - std::list mRepublishes; - - // parsed from msg. - // do we need references..? - std::list mHashTags; - std::list mMentions; - std::list mUrls; -}; - - -std::ostream &operator<<(std::ostream &out, const RsWireGroup &group); -std::ostream &operator<<(std::ostream &out, const RsWirePulse &pulse); - - -class RsWire: public RsGxsIfaceHelper -{ - public: - - explicit RsWire(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {} - virtual ~RsWire() {} - - /*! - * To acquire a handle to token service handler - * needed to make requests to the service - * @return handle to token service for this gxs service - */ - virtual RsTokenService* getTokenService() = 0; - - /* Specific Service Data */ -virtual bool getGroupData(const uint32_t &token, std::vector &groups) = 0; -virtual bool getPulseData(const uint32_t &token, std::vector &pulses) = 0; - -virtual bool createGroup(uint32_t &token, RsWireGroup &group) = 0; -virtual bool createPulse(uint32_t &token, RsWirePulse &pulse) = 0; - - // Blocking Interfaces. -virtual bool createGroup(RsWireGroup &group) = 0; -virtual bool updateGroup(const RsWireGroup &group) = 0; -virtual bool getGroups(const std::list grpIds, - std::vector &groups) = 0; - - // New Blocking Interfaces. - // Plan to migrate all GUI calls to these, and remove old interfaces above. - // These are not single requests, but return data graphs for display. -virtual bool createOriginalPulse(const RsGxsGroupId &grpId, RsWirePulseSPtr pPulse) = 0; -virtual bool createReplyPulse(RsGxsGroupId grpId, RsGxsMessageId msgId, - RsGxsGroupId replyWith, uint32_t reply_type, - RsWirePulseSPtr pPulse) = 0; - - - // Provide Individual Group Details for display. -virtual bool getWireGroup(const RsGxsGroupId &groupId, RsWireGroupSPtr &grp) = 0; -virtual bool getWirePulse(const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, RsWirePulseSPtr &pPulse) = 0; - - // Provide list of pulses associated with groups. -virtual bool getPulsesForGroups(const std::list &groupIds, - std::list &pulsePtrs) = 0; - - // Provide pulse, and associated replies / like etc. -virtual bool getPulseFocus(const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, - int type, RsWirePulseSPtr &pPulse) = 0; - -}; - -#endif diff --git a/libretroshare/src/rs_android/AndroidManifest.xml b/libretroshare/src/rs_android/AndroidManifest.xml deleted file mode 100644 index 426c66705..000000000 --- a/libretroshare/src/rs_android/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/libretroshare/src/rs_android/LocalArray.h b/libretroshare/src/rs_android/LocalArray.h deleted file mode 100644 index 2ab708aff..000000000 --- a/libretroshare/src/rs_android/LocalArray.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef LOCAL_ARRAY_H_included -#define LOCAL_ARRAY_H_included - -#include -#include - -/** - * A fixed-size array with a size hint. That number of bytes will be allocated - * on the stack, and used if possible, but if more bytes are requested at - * construction time, a buffer will be allocated on the heap (and deallocated - * by the destructor). - * - * The API is intended to be a compatible subset of C++0x's std::array. - */ -template -class LocalArray { -public: - /** - * Allocates a new fixed-size array of the given size. If this size is - * less than or equal to the template parameter STACK_BYTE_COUNT, an - * internal on-stack buffer will be used. Otherwise a heap buffer will - * be allocated. - */ - LocalArray(size_t desiredByteCount) : mSize(desiredByteCount) { - if (desiredByteCount > STACK_BYTE_COUNT) { - mPtr = new char[mSize]; - } else { - mPtr = &mOnStackBuffer[0]; - } - } - - /** - * Frees the heap-allocated buffer, if there was one. - */ - ~LocalArray() { - if (mPtr != &mOnStackBuffer[0]) { - delete[] mPtr; - } - } - - // Capacity. - size_t size() { return mSize; } - bool empty() { return mSize == 0; } - - // Element access. - char& operator[](size_t n) { return mPtr[n]; } - const char& operator[](size_t n) const { return mPtr[n]; } - -private: - char mOnStackBuffer[STACK_BYTE_COUNT]; - char* mPtr; - size_t mSize; - - // Disallow copy and assignment. - LocalArray(const LocalArray&); - void operator=(const LocalArray&); -}; - -#endif // LOCAL_ARRAY_H_included diff --git a/libretroshare/src/rs_android/README-ifaddrs-android.adoc b/libretroshare/src/rs_android/README-ifaddrs-android.adoc deleted file mode 100644 index 0c0065f92..000000000 --- a/libretroshare/src/rs_android/README-ifaddrs-android.adoc +++ /dev/null @@ -1,49 +0,0 @@ -= README Android ifaddrs - -Android API level < 24 doesn't provide `getifaddrs` and related functions, we -have tested multiple ways to overcome this issue. - - -== Non Weorking alternative implementations - -https://github.com/kmackay/android-ifaddrs -https://github.com/morristech/android-ifaddrs -https://www.openhub.net/p/android-ifaddrs/ - -Compiles but then segfault at runtime. - - -== Qt implementation - -Using `QNetworkInterface::allAddresses()` provided by Qt works but at time of -writing (Q4 2021) on newer Android the log is flooded by warnings as we reported -here -https://bugreports.qt.io/browse/QTBUG-78659 -plus depending on Qt networking module just for this is frustrating. - -Update: the warning flood seems have been fixed in later Qt versions -https://bugreports.qt.io/browse/QTBUG-86394 - -This solution was the first working we implemented in our code it has been -removed to avoid dependency on Qt, as lighter alternatives are possible. - - -== Code copied from Android Gingerbread release - -As explained here -https://stackoverflow.com/a/57112520 - -even older Android have `getifaddrs` implementations but doesn't make them -accessible in the API, in particular the one included in Android Gingerbread - -https://android.googlesource.com/platform/libcore/+/refs/heads/gingerbread-release/luni/src/main/native/ifaddrs-android.h -https://android.googlesource.com/platform/libcore/+/refs/heads/gingerbread-release/ - -is particularly easy to include in our code base and compile. - -This solution seems the best fitting and doesn't introduce dependency on Qt. -Newer Android releases (expecially 11) have introduced multiple restrictions -on network information access so we suggest you to prepare different APK for -different API level in order to use the `getifaddrs` provided by Android NDK -which deal gracefully with those restrictions as soon as available. - diff --git a/libretroshare/src/rs_android/ScopedFd.h b/libretroshare/src/rs_android/ScopedFd.h deleted file mode 100644 index d2b7935fa..000000000 --- a/libretroshare/src/rs_android/ScopedFd.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SCOPED_FD_H_included -#define SCOPED_FD_H_included - -#include - -// A smart pointer that closes the given fd on going out of scope. -// Use this when the fd is incidental to the purpose of your function, -// but needs to be cleaned up on exit. -class ScopedFd { -public: - explicit ScopedFd(int fd) : fd(fd) { - } - - ~ScopedFd() { - close(fd); - } - - int get() const { - return fd; - } - -private: - int fd; - - // Disallow copy and assignment. - ScopedFd(const ScopedFd&); - void operator=(const ScopedFd&); -}; - -#endif // SCOPED_FD_H_included diff --git a/libretroshare/src/rs_android/androidcoutcerrcatcher.hpp b/libretroshare/src/rs_android/androidcoutcerrcatcher.hpp deleted file mode 100644 index 43cf16dd7..000000000 --- a/libretroshare/src/rs_android/androidcoutcerrcatcher.hpp +++ /dev/null @@ -1,125 +0,0 @@ -/******************************************************************************* - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016-2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -// Inspired by: https://codelab.wordpress.com/2014/11/03/how-to-use-standard-output-streams-for-logging-in-android-apps/ - -#include -#include -#include -#include // for O_NONBLOCK -#include -#include -#include - -/** - * On Android stdout and stderr of native code is discarded, instancing this - * class at the beginning of the main of your program to get them (stdout and - * stderr) on logcat output. - */ -class AndroidCoutCerrCatcher -{ -public: - AndroidCoutCerrCatcher(const std::string& dTag = "RetroShare", - android_LogPriority stdout_pri = ANDROID_LOG_INFO, - android_LogPriority stderr_pri = ANDROID_LOG_ERROR) : - tag(dTag), cout_pri(stdout_pri), cerr_pri(stderr_pri), should_stop(false) - { - // make stdout line-buffered - //setvbuf(stdout, 0, _IOLBF, 0); - - // make stdout and stderr unbuffered - setvbuf(stdout, 0, _IONBF, 0); - setvbuf(stderr, 0, _IONBF, 0); - - // create the pipes and redirect stdout and stderr - pipe2(pout_fd, O_NONBLOCK); - dup2(pout_fd[1], STDOUT_FILENO); - - pipe2(perr_fd, O_NONBLOCK); - dup2(perr_fd[1], STDERR_FILENO); - - // spawn the logging thread - pthread_create(&thr, 0, thread_func, this); - pthread_detach(thr); - } - - ~AndroidCoutCerrCatcher() - { - should_stop = true; - pthread_join(thr, nullptr); - } - -private: - const std::string tag; - const android_LogPriority cout_pri; - const android_LogPriority cerr_pri; - - int pout_fd[2]; - int perr_fd[2]; - pthread_t thr; - std::atomic should_stop; - - static void* thread_func(void* instance) - { - __android_log_write( - ANDROID_LOG_INFO, "RetroShare", - "Android standard I/O catcher start" ); - - AndroidCoutCerrCatcher &i = *static_cast(instance); - - std::string out_buf; - std::string err_buf; - - while (!i.should_stop) - { - for(char c; read(i.pout_fd[0], &c, 1) == 1;) - { - out_buf += c; - if(c == '\n') - { - __android_log_write(i.cout_pri, i.tag.c_str(), out_buf.c_str()); - out_buf.clear(); - } - } - - for(char c; read(i.perr_fd[0], &c, 1) == 1;) - { - err_buf += c; - if(c == '\n') - { - __android_log_write(i.cerr_pri, i.tag.c_str(), err_buf.c_str()); - err_buf.clear(); - } - } - - usleep(10000); - } - - __android_log_write( - ANDROID_LOG_INFO, "RetroShare", - "Android standard I/O catcher stop" ); - - return nullptr; - } -}; - diff --git a/libretroshare/src/rs_android/errorconditionwrap.cpp b/libretroshare/src/rs_android/errorconditionwrap.cpp deleted file mode 100644 index e27495878..000000000 --- a/libretroshare/src/rs_android/errorconditionwrap.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************* - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "rs_android/rsjni.hpp" - -namespace jni -{ -Local> MakeAnything( - ThingToMake, JNIEnv& env, - const std::error_condition& ec ) -{ - auto& clazz = jni::Class::Singleton(env); - - static auto method = - clazz.GetConstructor(env); - - jni::jint value = ec.value(); - auto message = jni::Make(env, ec.message()); - auto category = jni::Make(env, ec.category().name()); - - return clazz.New(env, method, value, message, category); -} -} diff --git a/libretroshare/src/rs_android/ifaddrs-android.h b/libretroshare/src/rs_android/ifaddrs-android.h deleted file mode 100644 index 446d8d2be..000000000 --- a/libretroshare/src/rs_android/ifaddrs-android.h +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef IFADDRS_ANDROID_H_included -#define IFADDRS_ANDROID_H_included - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "LocalArray.h" -#include "ScopedFd.h" - -// Android (bionic) doesn't have getifaddrs(3)/freeifaddrs(3). -// We fake it here, so java_net_NetworkInterface.cpp can use that API -// with all the non-portable code being in this file. - -// Source-compatible subset of the BSD struct. -struct ifaddrs { - // Pointer to next struct in list, or NULL at end. - ifaddrs* ifa_next; - - // Interface name. - char* ifa_name; - - // Interface flags. - unsigned int ifa_flags; - - // Interface network address. - sockaddr* ifa_addr; - - // Interface netmask. - sockaddr* ifa_netmask; - - ifaddrs(ifaddrs* next) - : ifa_next(next), ifa_name(NULL), ifa_flags(0), ifa_addr(NULL), ifa_netmask(NULL) - { - } - - ~ifaddrs() { - delete ifa_next; - delete[] ifa_name; - delete ifa_addr; - delete ifa_netmask; - } - - // Sadly, we can't keep the interface index for portability with BSD. - // We'll have to keep the name instead, and re-query the index when - // we need it later. - bool setNameAndFlagsByIndex(int interfaceIndex) { - // Get the name. - char buf[IFNAMSIZ]; - char* name = if_indextoname(interfaceIndex, buf); - if (name == NULL) { - return false; - } - ifa_name = new char[strlen(name) + 1]; - strcpy(ifa_name, name); - - // Get the flags. - ScopedFd fd(socket(AF_INET, SOCK_DGRAM, 0)); - if (fd.get() == -1) { - return false; - } - ifreq ifr; - memset(&ifr, 0, sizeof(ifr)); - strcpy(ifr.ifr_name, name); - int rc = ioctl(fd.get(), SIOCGIFFLAGS, &ifr); - if (rc == -1) { - return false; - } - ifa_flags = ifr.ifr_flags; - return true; - } - - // Netlink gives us the address family in the header, and the - // sockaddr_in or sockaddr_in6 bytes as the payload. We need to - // stitch the two bits together into the sockaddr that's part of - // our portable interface. - void setAddress(int family, void* data, size_t byteCount) { - // Set the address proper... - sockaddr_storage* ss = new sockaddr_storage; - memset(ss, 0, sizeof(*ss)); - ifa_addr = reinterpret_cast(ss); - ss->ss_family = family; - uint8_t* dst = sockaddrBytes(family, ss); - memcpy(dst, data, byteCount); - } - - // Netlink gives us the prefix length as a bit count. We need to turn - // that into a BSD-compatible netmask represented by a sockaddr*. - void setNetmask(int family, size_t prefixLength) { - // ...and work out the netmask from the prefix length. - sockaddr_storage* ss = new sockaddr_storage; - memset(ss, 0, sizeof(*ss)); - ifa_netmask = reinterpret_cast(ss); - ss->ss_family = family; - uint8_t* dst = sockaddrBytes(family, ss); - memset(dst, 0xff, prefixLength / 8); - if ((prefixLength % 8) != 0) { - dst[prefixLength/8] = (0xff << (8 - (prefixLength % 8))); - } - } - - // Returns a pointer to the first byte in the address data (which is - // stored in network byte order). - uint8_t* sockaddrBytes(int family, sockaddr_storage* ss) { - if (family == AF_INET) { - sockaddr_in* ss4 = reinterpret_cast(ss); - return reinterpret_cast(&ss4->sin_addr); - } else if (family == AF_INET6) { - sockaddr_in6* ss6 = reinterpret_cast(ss); - return reinterpret_cast(&ss6->sin6_addr); - } - return NULL; - } - -private: - // Disallow copy and assignment. - ifaddrs(const ifaddrs&); - void operator=(const ifaddrs&); -}; - -// FIXME: use iovec instead. -struct addrReq_struct { - nlmsghdr netlinkHeader; - ifaddrmsg msg; -}; - -inline bool sendNetlinkMessage(int fd, const void* data, size_t byteCount) { - ssize_t sentByteCount = TEMP_FAILURE_RETRY(send(fd, data, byteCount, 0)); - return (sentByteCount == static_cast(byteCount)); -} - -inline ssize_t recvNetlinkMessage(int fd, char* buf, size_t byteCount) { - return TEMP_FAILURE_RETRY(recv(fd, buf, byteCount, 0)); -} - -// Source-compatible with the BSD function. -inline int getifaddrs(ifaddrs** result) { - // Simplify cleanup for callers. - *result = NULL; - - // Create a netlink socket. - ScopedFd fd(socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)); - if (fd.get() < 0) { - return -1; - } - - // Ask for the address information. - addrReq_struct addrRequest; - memset(&addrRequest, 0, sizeof(addrRequest)); - addrRequest.netlinkHeader.nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH; - addrRequest.netlinkHeader.nlmsg_type = RTM_GETADDR; - addrRequest.netlinkHeader.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(addrRequest))); - addrRequest.msg.ifa_family = AF_UNSPEC; // All families. - addrRequest.msg.ifa_index = 0; // All interfaces. - if (!sendNetlinkMessage(fd.get(), &addrRequest, addrRequest.netlinkHeader.nlmsg_len)) { - return -1; - } - - // Read the responses. - LocalArray<0> buf(65536); // We don't necessarily have std::vector. - ssize_t bytesRead; - while ((bytesRead = recvNetlinkMessage(fd.get(), &buf[0], buf.size())) > 0) { - nlmsghdr* hdr = reinterpret_cast(&buf[0]); - for (; NLMSG_OK(hdr, (size_t)bytesRead); hdr = NLMSG_NEXT(hdr, bytesRead)) { - switch (hdr->nlmsg_type) { - case NLMSG_DONE: - return 0; - case NLMSG_ERROR: - return -1; - case RTM_NEWADDR: - { - ifaddrmsg* address = reinterpret_cast(NLMSG_DATA(hdr)); - rtattr* rta = IFA_RTA(address); - size_t ifaPayloadLength = IFA_PAYLOAD(hdr); - while (RTA_OK(rta, ifaPayloadLength)) { - if (rta->rta_type == IFA_LOCAL) { - int family = address->ifa_family; - if (family == AF_INET || family == AF_INET6) { - *result = new ifaddrs(*result); - if (!(*result)->setNameAndFlagsByIndex(address->ifa_index)) { - return -1; - } - (*result)->setAddress(family, RTA_DATA(rta), RTA_PAYLOAD(rta)); - (*result)->setNetmask(family, address->ifa_prefixlen); - } - } - rta = RTA_NEXT(rta, ifaPayloadLength); - } - } - break; - } - } - } - // We only get here if recv fails before we see a NLMSG_DONE. - return -1; -} - -// Source-compatible with the BSD function. -inline void freeifaddrs(ifaddrs* addresses) { - delete addresses; -} - -#endif // IFADDRS_ANDROID_H_included diff --git a/libretroshare/src/rs_android/largefile_retrocompat.hpp b/libretroshare/src/rs_android/largefile_retrocompat.hpp deleted file mode 100644 index 0140011ff..000000000 --- a/libretroshare/src/rs_android/largefile_retrocompat.hpp +++ /dev/null @@ -1,31 +0,0 @@ -/******************************************************************************* - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016-2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#ifdef __ANDROID__ -# include -# if __ANDROID_API__ < 24 -# define fopen64 fopen -# define fseeko64 fseeko -# define ftello64 ftello -# endif -#endif diff --git a/libretroshare/src/rs_android/org/retroshare/service/AssetHelper.java b/libretroshare/src/rs_android/org/retroshare/service/AssetHelper.java deleted file mode 100644 index c32aa5b5d..000000000 --- a/libretroshare/src/rs_android/org/retroshare/service/AssetHelper.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * RetroShare - * Copyright (C) 2021 Gioacchino Mazzurco - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - * SPDX-FileCopyrightText: Retroshare Team - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -package org.retroshare.service; - -import android.util.Log; -import android.content.Context; -import java.io.OutputStream; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.io.IOException; - - -public class AssetHelper -{ - public static boolean copyAsset( - Context ctx, String assetPath, String destinationFilePath ) - { - Log.d(TAG, "copyAsset " + assetPath + " -> " + destinationFilePath); - - InputStream in; - OutputStream out; - - try { in = ctx.getAssets().open(assetPath); } - catch(Exception e) - { - Log.e( - TAG, - "Failure opening asset: " + assetPath + " " + e.getMessage() ); - return false; - } - - try { out = new FileOutputStream(destinationFilePath); } - catch(Exception e) - { - Log.e( - TAG, - "Failure opening destination: " + destinationFilePath + " " + - e.getMessage() ); - return false; - } - - try - { - byte[] buf = new byte[1024]; - int len; - while ((len = in.read(buf)) > 0) out.write(buf, 0, len); - } - catch(IOException e) - { - Log.e( - TAG, - "Failure coping: " + assetPath + " -> " + destinationFilePath + - " " + e.getMessage() ); - return false; - } - - try { in.close(); } - catch(IOException e) - { - Log.e(TAG, "Failure closing: " + assetPath + " " + e.getMessage() ); - return false; - } - - try { out.close(); } - catch(IOException e) - { - Log.e( - TAG, - "Failure closing: " + destinationFilePath + " " + - e.getMessage() ); - return false; - } - - return true; - } - - private static final String TAG = "RetroShare AssetHelper.java"; -} diff --git a/libretroshare/src/rs_android/org/retroshare/service/ErrorConditionWrap.java b/libretroshare/src/rs_android/org/retroshare/service/ErrorConditionWrap.java deleted file mode 100644 index c0830f5d2..000000000 --- a/libretroshare/src/rs_android/org/retroshare/service/ErrorConditionWrap.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * RetroShare - * Copyright (C) 2021 Gioacchino Mazzurco - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - * SPDX-FileCopyrightText: Retroshare Team - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -package org.retroshare.service; - -public class ErrorConditionWrap -{ - public ErrorConditionWrap( - int value, String message, String categoryName ) - { - mValue = value; - mMessage = message; - mCategoryName = categoryName; - } - - public int value() { return mValue; } - public String message() { return mMessage; } - public String categoryName() { return mCategoryName; } - - public boolean toBool() { return mValue != 0; } - - @Override - public String toString() - { return String.format("%d", mValue)+" "+mMessage+" [" + mCategoryName+ "]"; } - - private int mValue = 0; - private String mMessage; - private String mCategoryName; -} diff --git a/libretroshare/src/rs_android/org/retroshare/service/RetroShareServiceAndroid.java b/libretroshare/src/rs_android/org/retroshare/service/RetroShareServiceAndroid.java deleted file mode 100644 index 0e3d5ced9..000000000 --- a/libretroshare/src/rs_android/org/retroshare/service/RetroShareServiceAndroid.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * RetroShare - * - * Copyright (C) 2016-2022 Gioacchino Mazzurco - * Copyright (C) 2021-2022 AsociaciĆ³n Civil Altermundi - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - * SPDX-FileCopyrightText: Retroshare Team - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -package org.retroshare.service; - -import android.app.Service; -import android.os.IBinder; -import android.os.Bundle; -import android.content.Context; -import android.content.Intent; -import android.util.Log; -import android.app.ActivityManager; - - -public class RetroShareServiceAndroid extends Service -{ - public static final int DEFAULT_JSON_API_PORT = 9092; - public static final String DEFAULT_JSON_API_BINDING_ADDRESS = "127.0.0.1"; - - static { System.loadLibrary("retroshare"); } - - public static void start( - Context ctx, int jsonApiPort, String jsonApiBindAddress ) - { - Log.d(TAG, "start"); - Intent intent = new Intent(ctx, RetroShareServiceAndroid.class); - intent.putExtra(JSON_API_PORT_KEY, jsonApiPort); - intent.putExtra(JSON_API_BIND_ADDRESS_KEY, jsonApiBindAddress); - ctx.startService(intent); - } - - public static void stop(Context ctx) - { - Log.d(TAG, "stop"); - ctx.stopService(new Intent(ctx, RetroShareServiceAndroid.class)); - } - - public static boolean isRunning(Context ctx) - { - Log.d(TAG, "isRunning"); - ActivityManager manager = - (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE); - for( ActivityManager.RunningServiceInfo service : - manager.getRunningServices(Integer.MAX_VALUE) ) - if( RetroShareServiceAndroid.class.getName() - .equals(service.service.getClassName()) ) - return true; - return false; - } - - public static Context getServiceContext() - { - if(sServiceContext == null) - { - Log.e(TAG, "getServiceContext() called before onCreate"); - throw new NullPointerException(); - } - return sServiceContext; - } - - @Override - public int onStartCommand( - Intent intent, int flags, int startId ) - { - if(intent == null) - { - Log.i(TAG, "onStartCommand called without intent"); - return Service.START_REDELIVER_INTENT; - } - - int jsonApiPort = DEFAULT_JSON_API_PORT; - String jsonApiBindAddress = DEFAULT_JSON_API_BINDING_ADDRESS; - - Bundle args = intent.getExtras(); - if(args.containsKey(JSON_API_PORT_KEY)) - jsonApiPort = args.getInt(JSON_API_PORT_KEY); - if(args.containsKey(JSON_API_BIND_ADDRESS_KEY)) - jsonApiBindAddress = - args.getString(JSON_API_BIND_ADDRESS_KEY); - - ErrorConditionWrap ec = nativeStart(jsonApiPort, jsonApiBindAddress); - if(ec.toBool()) Log.e(TAG, "onStartCommand(...) " + ec.toString()); - - return super.onStartCommand(intent, flags, startId); - } - - @Override - public void onCreate () - { - super.onCreate(); - sServiceContext = this; - } - - @Override - public void onDestroy() - { - ErrorConditionWrap ec = nativeStop(); - if(ec.toBool()) Log.e(TAG, "onDestroy() " + ec.toString()); - sServiceContext = null; - super.onDestroy(); - } - - @Override - public IBinder onBind(Intent arg0) { return null; } - - private static final String JSON_API_PORT_KEY = - RetroShareServiceAndroid.class.getCanonicalName() + - "/JSON_API_PORT_KEY"; - - private static final String JSON_API_BIND_ADDRESS_KEY = - RetroShareServiceAndroid.class.getCanonicalName() + - "/JSON_API_BIND_ADDRESS_KEY" ; - - private static final String TAG = "RetroShareServiceAndroid.java"; - - private static Context sServiceContext; - - protected static native ErrorConditionWrap nativeStart( - int jsonApiPort, String jsonApiBindAddress ); - - protected static native ErrorConditionWrap nativeStop(); -} diff --git a/libretroshare/src/rs_android/retroshareserviceandroid.cpp b/libretroshare/src/rs_android/retroshareserviceandroid.cpp deleted file mode 100644 index 6e156edca..000000000 --- a/libretroshare/src/rs_android/retroshareserviceandroid.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - * RetroShare Service Android - * Copyright (C) 2016-2021 Gioacchino Mazzurco - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - * SPDX-FileCopyrightText: Retroshare Team - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -#include -#include - -#include "util/stacktrace.h" -#include "retroshare/rsinit.h" -#include "retroshare/rsiface.h" -#include "util/rsdebug.h" - -#include "rs_android/retroshareserviceandroid.hpp" -#include "rs_android/rsjni.hpp" - - -/*static*/ std::unique_ptr -RetroShareServiceAndroid::sAndroidCoutCerrCatcher = nullptr; - -using ErrorConditionWrap = RsJni::ErrorConditionWrap; - -/*static*/ jni::Local> -RetroShareServiceAndroid::start( - JNIEnv& env, jni::Class&, - jni::jint jsonApiPort, const jni::String& jsonApiBindAddress ) -{ - if(jsonApiPort < 0 || jsonApiPort > std::numeric_limits::max()) - { - RS_ERR("Got invalid JSON API port: ", jsonApiPort); - return jni::Make(env, std::errc::invalid_argument); - } - - RsInfo() << "\n" << - "+================================================================+\n" - "| o---o o |\n" - "| \\ / - Retroshare Service Android - / \\ |\n" - "| o o---o |\n" - "+================================================================+" - << std::endl << std::endl; - - sAndroidCoutCerrCatcher = std::make_unique(); - - RsInit::InitRsConfig(); - RsControl::earlyInitNotificationSystem(); - - RsConfigOptions conf; - conf.jsonApiPort = static_cast(jsonApiPort); - conf.jsonApiBindAddress = jni::Make(env, jsonApiBindAddress); - - // Dirty workaround plugins not supported on Android ATM - conf.main_executable_path = " "; - - int initResult = RsInit::InitRetroShare(conf); - if(initResult != RS_INIT_OK) - { - RS_ERR("Retroshare core initalization failed with: ", initResult); - return jni::Make(env, std::errc::no_child_process); - } - - return jni::Make(env, std::error_condition()); -} - -jni::Local> RetroShareServiceAndroid::stop( - JNIEnv& env, jni::Class& ) -{ - if(RsControl::instance()->isReady()) - { - RsControl::instance()->rsGlobalShutDown(); - return jni::Make(env, std::error_condition()); - } - - sAndroidCoutCerrCatcher.reset(); - - return jni::Make(env, std::errc::no_such_process); -} - -jni::Local > -RetroShareServiceAndroid::getAndroidContext(JNIEnv& env) -{ - auto& clazz = jni::Class::Singleton(env); - static auto method = - clazz.GetStaticMethod()>( - env, "getServiceContext" ); - return clazz.Call(env, method); -} diff --git a/libretroshare/src/rs_android/retroshareserviceandroid.hpp b/libretroshare/src/rs_android/retroshareserviceandroid.hpp deleted file mode 100644 index bd8f88f31..000000000 --- a/libretroshare/src/rs_android/retroshareserviceandroid.hpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * RetroShare Service Android - * Copyright (C) 2016-2021 Gioacchino Mazzurco - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - * SPDX-FileCopyrightText: Retroshare Team - * SPDX-License-Identifier: AGPL-3.0-or-later - */ -#pragma once - -#include -#include - -#include - -#include "rs_android/rsjni.hpp" -#include "rs_android/androidcoutcerrcatcher.hpp" - -#include "util/stacktrace.h" - -/** Provide native methods that are registered into corresponding Java class - * to start/stop RetroShare with reasonable comfort on Android platform */ -struct RetroShareServiceAndroid -{ - static constexpr auto Name() - { return "org/retroshare/service/RetroShareServiceAndroid"; } - - using ErrorConditionWrap = RsJni::ErrorConditionWrap; - - /** - * Called from RetroShareServiceAndroid Java to init libretroshare - * @param[in] env the usual JNI parafernalia - * @param[in] jclass the usual JNI parafernalia - * @param[in] jsonApiPort port on which JSON API server will listen - * @param[in] jsonApiBindAddress binding address of the JSON API server - * @note Yeah you read it well we use a full 32 bit signed integer for JSON - * API port. This is because Java lack even the minimum decency to implement - * unsigned integral types so we need to wrap the port (16 bit unsigned - * integer everywhere reasonable) into a full integer and then check at - * runtime the value. - */ - static jni::Local> start( - JNIEnv& env, jni::Class& jclass, - jni::jint jsonApiPort, const jni::String& jsonApiBindAddress ); - - /** - * Called from RetroShareServiceAndroid Java to shutdown libretroshare - * @param[in] env the usual JNI parafernalia - * @param[in] jclass the usual JNI parafernalia - */ - static jni::Local> stop( - JNIEnv& env, jni::Class& ); - - struct Context - { - /// JNI parafernalia - static constexpr auto Name() { return "android/content/Context"; } - }; - - /// Return RetroShare Service Android Context - static jni::Local> getAndroidContext(JNIEnv& env); - -private: - /** Doesn't involve complex liftime handling stuff better let the runtime - * handle costruction (ASAP)/destruction for us */ - static CrashStackTrace CrashStackTrace; - - /** Involve threads, file descriptors etc. better handle lifetime - * explicitely */ - static std::unique_ptr sAndroidCoutCerrCatcher; -}; diff --git a/libretroshare/src/rs_android/rsjni.cpp b/libretroshare/src/rs_android/rsjni.cpp deleted file mode 100644 index c9fc2c8ed..000000000 --- a/libretroshare/src/rs_android/rsjni.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/******************************************************************************* - * RetroShare JNI utilities * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "rs_android/rsjni.hpp" -#include "rs_android/retroshareserviceandroid.hpp" - -rs_view_ptr RsJni::mJvm = nullptr; - - -extern "C" JNIEXPORT jint JNICALL JNI_OnLoad_retroshare(JavaVM* vm, void*) -{ - RS_DBG(vm); - - RsJni::mJvm = vm; - - jni::JNIEnv& env { jni::GetEnv(*vm) }; - - /** Ensure singleton refereces to our own Java classes are inizialized here - * because default Java class loader which is the one accessible by native - * threads which is not main even if attached, is not capable to find them. - * https://stackoverflow.com/questions/20752352/classnotfoundexception-when-finding-a-class-in-jni-background-thread - * https://groups.google.com/g/android-ndk/c/2gkr1mXKn_E */ - jni::Class::Singleton(env); - jni::Class::Singleton(env); - - jni::RegisterNatives( - env, *jni::Class::Singleton(env), - jni::MakeNativeMethod< - decltype(&RetroShareServiceAndroid::start), - &RetroShareServiceAndroid::start >("nativeStart"), - jni::MakeNativeMethod< - decltype(&RetroShareServiceAndroid::stop), - &RetroShareServiceAndroid::stop >("nativeStop") - ); - - return jni::Unwrap(jni::jni_version_1_2); -} - -#ifdef RS_LIBRETROSHARE_EXPORT_JNI_ONLOAD -/** If libretroshare is linked statically to other components which already - * export JNI_OnLoad then a symbol clash may happen - * if RS_LIBRETROSHARE_EXPORT_JNI_ONLOAD is defined. - * @see JNI_OnLoad_retroshare should instead be called from the exported - * JNI_OnLoad */ -extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* _reserved) -{ - RS_DBG(vm); - return JNI_OnLoad_retroshare(vm, _reserved); -} -#endif // def RS_LIBRETROSHARE_EXPORT_JNI_ONLOAD diff --git a/libretroshare/src/rs_android/rsjni.hpp b/libretroshare/src/rs_android/rsjni.hpp deleted file mode 100644 index 339dfd5c7..000000000 --- a/libretroshare/src/rs_android/rsjni.hpp +++ /dev/null @@ -1,90 +0,0 @@ -/******************************************************************************* - * RetroShare JNI utilities * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include - -#include - -#include "util/rsmemory.h" -#include "util/cxx23retrocompat.h" - - -/** Store JVM pointer safely and register native methods */ -extern "C" JNIEXPORT jint JNICALL JNI_OnLoad_retroshare(JavaVM* vm, void*); - - -/** Provide library wide JVM access with some safe measures - * The JVM pointer is set properly by @see JNI_OnLoad_retroshare - */ -class RsJni -{ -public: - static inline JavaVM& getVM() - { - if(!mJvm) // [[unlikely]] - { - RS_FATAL( "Attempt to access JVM before JNI_OnLoad_retroshare ", - std::errc::bad_address ); - print_stacktrace(); - std::exit(std::to_underlying(std::errc::bad_address)); - } - - return *mJvm; - } - - friend jint JNI_OnLoad_retroshare(JavaVM* vm, void*); - - /** Provide a comfortable way to access Android package assets like - * bdboot.txt from C++ */ - struct AssetHelper - { - static constexpr auto Name() - { return "org/retroshare/service/AssetHelper"; } - }; - - /** Provide a comfortable way to propagate C++ error_conditions to Java - * callers */ - struct ErrorConditionWrap - { - static constexpr auto Name() - { return "org/retroshare/service/ErrorConditionWrap"; } - }; - -private: - static rs_view_ptr mJvm; -}; - - -namespace jni -{ -/** Provides idiomatic way of creating instances via -@code{.cpp} - jni::Make(env, std::error_condition()); -@endcode */ -jni::Local> -MakeAnything( - jni::ThingToMake, JNIEnv& env, - const std::error_condition& ec ); -} diff --git a/libretroshare/src/rs_upnp/UPnPBase.cpp b/libretroshare/src/rs_upnp/UPnPBase.cpp deleted file mode 100644 index 353812469..000000000 --- a/libretroshare/src/rs_upnp/UPnPBase.cpp +++ /dev/null @@ -1,1755 +0,0 @@ -/******************************************************************************* - * libretroshare/src/upnp: UPnPBase.cpp * - * * - * libretroshare: retroshare core library * - * * - * Copyright (c) 2004-2009 Marcelo Roberto Jimenez ( phoenix@amule.org ) * - * Copyright (c) 2006-2009 aMule Team ( admin@amule.org / http://www.amule.org)* - * Copyright (c) 2009-2010 Retroshare Team * - * Copyright (C) 2019-2020 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#define UPNP_C - -#include "UPnPBase.h" - -#include -#include -#include // for std::istringstream -#include // For transform() - -#include "util/rsstring.h" -#include "rs_upnp/upnp18_retrocompat.h" -#include "util/rstime.h" -#include "util/rsdebug.h" - -#ifdef __GNUC__ - #if __GNUC__ >= 4 - #define REINTERPRET_CAST(x) reinterpret_cast - #endif -#endif -#ifndef REINTERPRET_CAST - // Let's hope that function pointers are equal in size to data pointers - #define REINTERPRET_CAST(x) (x) -#endif - - -/** - * Case insensitive std::string comparison - */ -bool stdStringIsEqualCI(const std::string &s1, const std::string &s2) -{ - std::string ns1(s1); - std::string ns2(s2); - std::transform(ns1.begin(), ns1.end(), ns1.begin(), tolower); - std::transform(ns2.begin(), ns2.end(), ns2.begin(), tolower); - return ns1 == ns2; -} - - -CUPnPPortMapping::CUPnPPortMapping( - int ex_port, - int in_port, - const std::string &protocol, - bool enabled, - const std::string &description) -: -m_ex_port(), -m_in_port(), -m_protocol(protocol), -m_enabled(enabled ? "1" : "0"), -m_description(description), -m_key() -{ - rs_sprintf(m_ex_port, "%d", ex_port); - rs_sprintf(m_in_port, "%d", in_port); - m_key = m_protocol + m_ex_port; -} - - -const std::string &CUPnPLib::UPNP_ROOT_DEVICE = - "upnp:rootdevice"; - -const std::string &CUPnPLib::UPNP_DEVICE_IGW = - "urn:schemas-upnp-org:device:InternetGatewayDevice:1"; -const std::string &CUPnPLib::UPNP_DEVICE_WAN = - "urn:schemas-upnp-org:device:WANDevice:1"; -const std::string &CUPnPLib::UPNP_DEVICE_WAN_CONNECTION = - "urn:schemas-upnp-org:device:WANConnectionDevice:1"; -const std::string &CUPnPLib::UPNP_DEVICE_LAN = - "urn:schemas-upnp-org:device:LANDevice:1"; - -const std::string &CUPnPLib::UPNP_SERVICE_LAYER3_FORWARDING = - "urn:schemas-upnp-org:service:Layer3Forwarding:1"; -const std::string &CUPnPLib::UPNP_SERVICE_WAN_COMMON_INTERFACE_CONFIG = - "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"; -const std::string &CUPnPLib::UPNP_SERVICE_WAN_IP_CONNECTION = - "urn:schemas-upnp-org:service:WANIPConnection:1"; -const std::string &CUPnPLib::UPNP_SERVICE_WAN_PPP_CONNECTION = - "urn:schemas-upnp-org:service:WANPPPConnection:1"; - - -CUPnPLib::CUPnPLib(CUPnPControlPoint &ctrlPoint) -: -m_ctrlPoint(ctrlPoint) -{ -} - - -std::string CUPnPLib::GetUPnPErrorMessage(int code) const -{ - return UpnpGetErrorMessage(code); -} - - -std::string CUPnPLib::processUPnPErrorMessage( - const std::string &message, - int errorCode, - const DOMString errorString, - const IXML_Document* doc) const -{ - /* remove unused parameter warnings */ - (void) message; - (void) errorCode; - (void) errorString; - (void) doc; - - std::string msg; -#ifdef UPNP_DEBUG - if (errorString == NULL || *errorString == 0) { - errorString = "Not available"; - } - if (errorCode > 0) { - std::cerr << "CUPnPLib::processUPnPErrorMessage() Error: " << - message << - ": Error code :'"; - if (doc) { - CUPnPError e(*this, doc); - std::cerr << e.getErrorCode() << - "', Error description :'" << - e.getErrorDescription() << - "'."; - } else { - std::cerr << errorCode << - "', Error description :'" << - errorString << - "'."; - } - std::cerr << std::endl; - } else { - std::cerr << "CUPnPLib::processUPnPErrorMessage() Error: " << - message << - ": UPnP SDK error: " << - GetUPnPErrorMessage(errorCode) << - " (" << errorCode << ")."; - std::cerr << std::endl; - } -#endif - return msg; -} - - -void CUPnPLib::ProcessActionResponse( - const IXML_Document* RespDoc, - const std::string &actionName) const -{ - /* remove unused parameter warnings */ - (void) actionName; - - IXML_Element *root = Element_GetRootElement(RespDoc); - IXML_Element *child = Element_GetFirstChild(root); - if (child) { - while (child) { - const DOMString childTag = Element_GetTag(child); - std::string childValue = Element_GetTextValue(child); -#ifdef UPNP_DEBUG - std::cerr << "CUPnPLib::ProcessActionResponse() \n " << - childTag << "='" << - childValue << "'"; -#endif - //add the variable to the wanservice property map - (m_ctrlPoint.m_WanService->propertyMap)[std::string(childTag)] = std::string(childValue); - child = Element_GetNextSibling(child); - } - } else { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPLib::ProcessActionResponse() \n Empty response for action '" << - actionName << "'."; -#endif - } -#ifdef UPNP_DEBUG - std::cerr << std::endl; -#endif -} - - -/*! - * \brief Returns the root node of a given document. - */ -IXML_Element *CUPnPLib::Element_GetRootElement( - const IXML_Document* doc) const -{ - IXML_Element* root = REINTERPRET_CAST(IXML_Element *)( - ixmlNode_getFirstChild( - REINTERPRET_CAST(IXML_Node *)(const_cast(doc)))); - - return root; -} - - -/*! - * \brief Returns the first child of a given element. - */ -IXML_Element *CUPnPLib::Element_GetFirstChild( - IXML_Element *parent) const -{ - IXML_Node *node = REINTERPRET_CAST(IXML_Node *)(parent); - IXML_Node *child = ixmlNode_getFirstChild(node); - - return REINTERPRET_CAST(IXML_Element *)(child); -} - - -/*! - * \brief Returns the next sibling of a given child. - */ -IXML_Element *CUPnPLib::Element_GetNextSibling( - IXML_Element *child) const -{ - IXML_Node *node = REINTERPRET_CAST(IXML_Node *)(child); - IXML_Node *sibling = ixmlNode_getNextSibling(node); - - return REINTERPRET_CAST(IXML_Element *)(sibling); -} - - -/*! - * \brief Returns the element tag (name) - */ -const DOMString CUPnPLib::Element_GetTag( - IXML_Element *element) const -{ - IXML_Node *node = REINTERPRET_CAST(IXML_Node *)(element); - const DOMString tag = ixmlNode_getNodeName(node); - - return tag; -} - - -/*! - * \brief Returns the TEXT node value of the current node. - */ -const std::string CUPnPLib::Element_GetTextValue( - IXML_Element *element) const -{ - if (!element) { - return stdEmptyString; - } - IXML_Node *text = ixmlNode_getFirstChild( - REINTERPRET_CAST(IXML_Node *)(element)); - const DOMString s = ixmlNode_getNodeValue(text); - std::string ret; - if (s) { - ret = s; - } - - return ret; -} - - -/*! - * \brief Returns the TEXT node value of the first child matching tag. - */ -const std::string CUPnPLib::Element_GetChildValueByTag( - IXML_Element *element, - const DOMString tag) const -{ - IXML_Element *child = - Element_GetFirstChildByTag(element, tag); - - return Element_GetTextValue(child); -} - - -/*! - * \brief Returns the first child element that matches the requested tag or - * NULL if not found. - */ -IXML_Element *CUPnPLib::Element_GetFirstChildByTag( - IXML_Element *element, - const DOMString tag) const -{ - if (!element || !tag) { - return NULL; - } - - IXML_Node *node = REINTERPRET_CAST(IXML_Node *)(element); - IXML_Node *child = ixmlNode_getFirstChild(node); - const DOMString childTag = ixmlNode_getNodeName(child); - while(child && childTag && strcmp(tag, childTag)) { - child = ixmlNode_getNextSibling(child); - childTag = ixmlNode_getNodeName(child); - } - - return REINTERPRET_CAST(IXML_Element *)(child); -} - - -/*! - * \brief Returns the next sibling element that matches the requested tag. Should be - * used with the return value of Element_GetFirstChildByTag(). - */ -IXML_Element *CUPnPLib::Element_GetNextSiblingByTag( - IXML_Element *element, const DOMString tag) const -{ - if (!element || !tag) { - return NULL; - } - - IXML_Node *child = REINTERPRET_CAST(IXML_Node *)(element); - const DOMString childTag = NULL; - do { - child = ixmlNode_getNextSibling(child); - childTag = ixmlNode_getNodeName(child); - } while(child && childTag && strcmp(tag, childTag)); - - return REINTERPRET_CAST(IXML_Element *)(child); -} - - -const std::string CUPnPLib::Element_GetAttributeByTag( - IXML_Element *element, const DOMString tag) const -{ - IXML_NamedNodeMap *NamedNodeMap = ixmlNode_getAttributes( - REINTERPRET_CAST(IXML_Node *)(element)); - IXML_Node *attribute = ixmlNamedNodeMap_getNamedItem(NamedNodeMap, tag); - const DOMString s = ixmlNode_getNodeValue(attribute); - std::string ret; - if (s) { - ret = s; - } - ixmlNamedNodeMap_free(NamedNodeMap); - - return ret; -} - - -CUPnPError::CUPnPError( - const CUPnPLib &upnpLib, - const IXML_Document *errorDoc) - : - m_root (upnpLib.Element_GetRootElement(errorDoc)), - m_ErrorCode (upnpLib.Element_GetChildValueByTag(m_root, "errorCode")), - m_ErrorDescription(upnpLib.Element_GetChildValueByTag(m_root, "errorDescription")) -{ -} - - -CUPnPArgument::CUPnPArgument( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *argument, - const std::string &/*SCPDURL*/) -: -m_UPnPControlPoint(upnpControlPoint), -m_name (upnpLib.Element_GetChildValueByTag(argument, "name")), -m_direction (upnpLib.Element_GetChildValueByTag(argument, "direction")), -m_retval (upnpLib.Element_GetFirstChildByTag(argument, "retval")), -m_relatedStateVariable(upnpLib.Element_GetChildValueByTag(argument, "relatedStateVariable")) -{ - -#ifdef UPNP_DEBUG - std::cerr << "CUPnPArgument::CUPnPArgument() \n Argument:" << - "\n name: " << m_name << - "\n direction: " << m_direction << - "\n retval: " << m_retval << - "\n relatedStateVariable: " << m_relatedStateVariable; - std::cerr << std::endl; -#endif -} - - -CUPnPAction::CUPnPAction( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *action, - const std::string &SCPDURL) -: -m_UPnPControlPoint(upnpControlPoint), -m_ArgumentList(upnpControlPoint, upnpLib, action, SCPDURL), -m_name(upnpLib.Element_GetChildValueByTag(action, "name")) -{ -#ifdef UPNP_DEBUG - std::cerr << "CUPnPAction::CUPnPAction() \n Action:" << - "\n name: " << m_name; - std::cerr << std::endl; -#endif -} - - -CUPnPAllowedValue::CUPnPAllowedValue( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *allowedValue, - const std::string &/*SCPDURL*/) -: -m_UPnPControlPoint(upnpControlPoint), -m_allowedValue(upnpLib.Element_GetTextValue(allowedValue)) -{ -#ifdef UPNP_DEBUG - std::cerr << "CUPnPAllowedValue::CUPnPAllowedValue() \n AllowedValue:" << - "\n allowedValue: " << m_allowedValue; - std::cerr << std::endl; -#endif -} - - -CUPnPStateVariable::CUPnPStateVariable( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *stateVariable, - const std::string &SCPDURL) -: -m_UPnPControlPoint(upnpControlPoint), -m_AllowedValueList(upnpControlPoint, upnpLib, stateVariable, SCPDURL), -m_name (upnpLib.Element_GetChildValueByTag(stateVariable, "name")), -m_dataType (upnpLib.Element_GetChildValueByTag(stateVariable, "dataType")), -m_defaultValue(upnpLib.Element_GetChildValueByTag(stateVariable, "defaultValue")), -m_sendEvents (upnpLib.Element_GetAttributeByTag (stateVariable, "sendEvents")) -{ -#ifdef UPNP_DEBUG - std::cerr << "CUPnPStateVariable::CUPnPStateVariable() \n StateVariable:" << - "\n name: " << m_name << - "\n dataType: " << m_dataType << - "\n defaultValue: " << m_defaultValue << - "\n sendEvents: " << m_sendEvents; - std::cerr << std::endl; -#endif -} - - -CUPnPSCPD::CUPnPSCPD( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *scpd, - const std::string &SCPDURL) -: -m_UPnPControlPoint(upnpControlPoint), -m_ActionList(upnpControlPoint, upnpLib, scpd, SCPDURL), -m_ServiceStateTable(upnpControlPoint, upnpLib, scpd, SCPDURL), -m_SCPDURL(SCPDURL) -{ -} - - -CUPnPArgumentValue::CUPnPArgumentValue() -: -m_argument(), -m_value() -{ -} - - -CUPnPArgumentValue::CUPnPArgumentValue( - const std::string &argument, const std::string &value) -: -m_argument(argument), -m_value(value) -{ -} - - -CUPnPService::CUPnPService( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *service, - const std::string &URLBase) -: -m_UPnPControlPoint(upnpControlPoint), -m_upnpLib(upnpLib), -m_serviceType(upnpLib.Element_GetChildValueByTag(service, "serviceType")), -m_serviceId (upnpLib.Element_GetChildValueByTag(service, "serviceId")), -m_SCPDURL (upnpLib.Element_GetChildValueByTag(service, "SCPDURL")), -m_controlURL (upnpLib.Element_GetChildValueByTag(service, "controlURL")), -m_eventSubURL(upnpLib.Element_GetChildValueByTag(service, "eventSubURL")), -m_timeout(1801), -m_SCPD(NULL) -{ - int errcode; - m_SID[0]=0; - - std::vector vscpdURL(URLBase.length() + m_SCPDURL.length() + 1); - char *scpdURL = &vscpdURL[0]; - errcode = UpnpResolveURL( - URLBase.c_str(), - m_SCPDURL.c_str(), - scpdURL); - if( errcode != UPNP_E_SUCCESS ) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::CUPnPService() Error generating scpdURL from " << - "|" << URLBase << "|" << - m_SCPDURL << "|."; - std::cerr << std::endl; -#endif - } else { - m_absSCPDURL = scpdURL; - } - - std::vector vcontrolURL( - URLBase.length() + m_controlURL.length() + 1); - char *controlURL = &vcontrolURL[0]; - errcode = UpnpResolveURL( - URLBase.c_str(), - m_controlURL.c_str(), - controlURL); - if( errcode != UPNP_E_SUCCESS ) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::CUPnPService() Error generating controlURL from " << - "|" << URLBase << "|" << - m_controlURL << "|."; - std::cerr << std::endl; -#endif - } else { - m_absControlURL = controlURL; - } - - std::vector veventURL( - URLBase.length() + m_eventSubURL.length() + 1); - char *eventURL = &veventURL[0]; - errcode = UpnpResolveURL( - URLBase.c_str(), - m_eventSubURL.c_str(), - eventURL); - if( errcode != UPNP_E_SUCCESS ) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::CUPnPService() Error generating eventURL from " << - "|" << URLBase << "|" << - m_eventSubURL << "|."; - std::cerr << std::endl; -#endif - } else { - m_absEventSubURL = eventURL; - } - -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::CUPnPService() \n Service:" << - "\n serviceType: " << m_serviceType << - "\n serviceId: " << m_serviceId << - "\n SCPDURL: " << m_SCPDURL << - "\n absSCPDURL: " << m_absSCPDURL << - "\n controlURL: " << m_controlURL << - "\n absControlURL: " << m_absControlURL << - "\n eventSubURL: " << m_eventSubURL << - "\n absEventSubURL: " << m_absEventSubURL; - std::cerr << std::endl; -#endif - - if (m_serviceType == upnpLib.UPNP_SERVICE_WAN_IP_CONNECTION || - m_serviceType == upnpLib.UPNP_SERVICE_WAN_PPP_CONNECTION) { -#if 0 - m_serviceType == upnpLib.UPNP_SERVICE_WAN_PPP_CONNECTION || - m_serviceType == upnpLib.UPNP_SERVICE_WAN_COMMON_INTERFACE_CONFIG || - m_serviceType == upnpLib.UPNP_SERVICE_LAYER3_FORWARDING) { -#endif -#if 0 -//#warning Delete this code on release. - if (!upnpLib.m_ctrlPoint.WanServiceDetected()) { - // This condition can be used to suspend the parse - // of the XML tree. -#endif -//#warning Delete this code when m_WanService is no longer used. - upnpLib.m_ctrlPoint.SetWanService(this); - // Log it -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::CUPnPService() WAN Service Detected: '" << - m_serviceType << "'."; - std::cerr << std::endl; -#endif - // Subscribe - upnpLib.m_ctrlPoint.Subscribe(*this); -#if 0 -//#warning Delete this code on release. - } else { -#ifdef UPNP_DEBUG - std::cerr << "WAN service detected again: '" << - m_serviceType << - "'. Will only use the first instance."; - std::cerr << std::endl; -#endif - } -#endif - } else { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::CUPnPService() Uninteresting service detected: '" << - m_serviceType << "'. Ignoring."; - std::cerr << std::endl; -#endif - } -} - - -CUPnPService::~CUPnPService() -{ -} - - -bool CUPnPService::Execute( - const std::string &ActionName, - const std::vector &ArgValue) const -{ -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::Execute() called." << std::endl; -#endif - if (m_SCPD.get() == NULL) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::Execute() Service without SCPD Document, cannot execute action '" << ActionName << - "' for service '" << GetServiceType() << "'."; - std::cerr << std::endl; -#endif - return false; - } -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::Execute() Sending action " << std::endl; -#endif - // Check for correct action name - ActionList::const_iterator itAction = - m_SCPD->GetActionList().find(ActionName); - if (itAction == m_SCPD->GetActionList().end()) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::Execute() invalid action name '" << ActionName << - "' for service '" << GetServiceType() << "'."; - std::cerr << std::endl; -#endif - return false; - } -#ifdef UPNP_DEBUG - std::cerr << ActionName << "("; -#endif - bool firstTime = true; - // Check for correct Argument/Value pairs - const CUPnPAction &action = *(itAction->second); - for (unsigned int i = 0; i < ArgValue.size(); ++i) { - ArgumentList::const_iterator itArg = - action.GetArgumentList().find(ArgValue[i].GetArgument()); - if (itArg == action.GetArgumentList().end()) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::Execute() Invalid argument name '" << ArgValue[i].GetArgument() << - "' for action '" << action.GetName() << - "' for service '" << GetServiceType() << "'."; - std::cerr << std::endl; -#endif - return false; - } - const CUPnPArgument &argument = *(itArg->second); - if (tolower(argument.GetDirection()[0]) != 'i' || - tolower(argument.GetDirection()[1]) != 'n') { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::Execute() Invalid direction for argument '" << - ArgValue[i].GetArgument() << - "' for action '" << action.GetName() << - "' for service '" << GetServiceType() << "'."; - std::cerr << std::endl; -#endif - return false; - } - const std::string relatedStateVariableName = - argument.GetRelatedStateVariable(); - if (!relatedStateVariableName.empty()) { - ServiceStateTable::const_iterator itSVT = - m_SCPD->GetServiceStateTable(). - find(relatedStateVariableName); - if (itSVT == m_SCPD->GetServiceStateTable().end()) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::Execute() Inconsistent Service State Table, did not find '" << - relatedStateVariableName << - "' for argument '" << argument.GetName() << - "' for action '" << action.GetName() << - "' for service '" << GetServiceType() << "'."; - std::cerr << std::endl; -#endif - return false; - } - const CUPnPStateVariable &stateVariable = *(itSVT->second); - if ( !stateVariable.GetAllowedValueList().empty() && - stateVariable.GetAllowedValueList().find(ArgValue[i].GetValue()) == - stateVariable.GetAllowedValueList().end()) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::Execute() Value not allowed '" << ArgValue[i].GetValue() << - "' for state variable '" << relatedStateVariableName << - "' for argument '" << argument.GetName() << - "' for action '" << action.GetName() << - "' for service '" << GetServiceType() << "'."; -#endif - - return false; - } - } - if (firstTime) { - firstTime = false; - } else { -#ifdef UPNP_DEBUG - std::cerr << ", "; -#endif - } -#ifdef UPNP_DEBUG - std::cerr << - ArgValue[i].GetArgument() << - "='" << - ArgValue[i].GetValue() << - "'"; -#endif - } -#ifdef UPNP_DEBUG - std::cerr << ")" << std::endl; -#endif - // Everything is ok, make the action - IXML_Document *ActionDoc = NULL; - if (ArgValue.size()) { - for (unsigned int i = 0; i < ArgValue.size(); ++i) { - int ret = UpnpAddToAction( - &ActionDoc, - action.GetName().c_str(), - GetServiceType().c_str(), - ArgValue[i].GetArgument().c_str(), - ArgValue[i].GetValue().c_str()); - if (ret != UPNP_E_SUCCESS) { - m_upnpLib.processUPnPErrorMessage( - "UpnpAddToAction", ret, NULL, NULL); - return false; - } - } - } else { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::Execute() UpnpMakeAction" << std::endl; -#endif - ActionDoc = UpnpMakeAction( - action.GetName().c_str(), - GetServiceType().c_str(), - 0, NULL); - if (!ActionDoc) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::Execute() Error: UpnpMakeAction returned NULL." << std::endl; -#endif - return false; - } - } - - // Send the action asynchronously - UpnpSendActionAsync( - m_UPnPControlPoint.GetUPnPClientHandle(), - GetAbsControlURL().c_str(), - GetServiceType().c_str(), - NULL, ActionDoc, - reinterpret_cast(&CUPnPControlPoint::Callback), - NULL); - return true; -} - - -const std::string CUPnPService::GetStateVariable( - const std::string &stateVariableName) -{ - std::map::iterator it; - it = propertyMap.find(stateVariableName); - if (it != propertyMap.end()) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::GetStateVariable(" << stateVariableName << ") = " << (*it).second << std::endl; -#endif - return (*it).second; - } else { - //property map is not populated with the specified value. - //we will try to get it with an event - - //this getvar is just to make the event happening - DOMString StVarVal; - UpnpGetServiceVarStatus( - m_UPnPControlPoint.GetUPnPClientHandle(), - GetAbsControlURL().c_str(), - stateVariableName.c_str(), - &StVarVal); - if (StVarVal != NULL) { - std::string varValue = std::string(StVarVal); -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::GetStateVariable() varValue returned by UpnpGetServiceVarStatus : " << varValue << std::endl; -#endif - return varValue; - } else { - //use event to get state variable -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::GetStateVariable() pausing in case of an UPnP event incomming."; -#endif - rstime_t begin_time = time(NULL); - while (true) { - if (time(NULL) - begin_time > 7) { - break; - } - } - } - - //propertyMap should be populated by nom - it = propertyMap.find(stateVariableName); - if (it != propertyMap.end()) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::GetStateVariable(" << stateVariableName << ") = " << (*it).second << std::endl; -#endif - return (*it).second; - } else { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPService::GetStateVariable(" << stateVariableName << ") = " << "Empty String" << std::endl; -#endif - return stdEmptyString; - } - } -} - - -CUPnPDevice::CUPnPDevice( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *device, - const std::string &URLBase) -: -m_UPnPControlPoint(upnpControlPoint), -m_DeviceList(upnpControlPoint, upnpLib, device, URLBase), -m_ServiceList(upnpControlPoint, upnpLib, device, URLBase), -m_deviceType (upnpLib.Element_GetChildValueByTag(device, "deviceType")), -m_friendlyName (upnpLib.Element_GetChildValueByTag(device, "friendlyName")), -m_manufacturer (upnpLib.Element_GetChildValueByTag(device, "manufacturer")), -m_manufacturerURL (upnpLib.Element_GetChildValueByTag(device, "manufacturerURL")), -m_modelDescription (upnpLib.Element_GetChildValueByTag(device, "modelDescription")), -m_modelName (upnpLib.Element_GetChildValueByTag(device, "modelName")), -m_modelNumber (upnpLib.Element_GetChildValueByTag(device, "modelNumber")), -m_modelURL (upnpLib.Element_GetChildValueByTag(device, "modelURL")), -m_serialNumber (upnpLib.Element_GetChildValueByTag(device, "serialNumber")), -m_UDN (upnpLib.Element_GetChildValueByTag(device, "UDN")), -m_UPC (upnpLib.Element_GetChildValueByTag(device, "UPC")), -m_presentationURL (upnpLib.Element_GetChildValueByTag(device, "presentationURL")) -{ - int presURLlen = strlen(URLBase.c_str()) + - strlen(m_presentationURL.c_str()) + 2; - std::vector vpresURL(presURLlen); - char* presURL = &vpresURL[0]; - int errcode = UpnpResolveURL( - URLBase.c_str(), - m_presentationURL.c_str(), - presURL); - if (errcode != UPNP_E_SUCCESS) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPDevice::CUPnPDevice() Error generating presentationURL from " << - "|" << URLBase << "|" << - m_presentationURL << "|."; - std::cerr << std::endl; -#endif - } else { - m_presentationURL = presURL; - } - -#ifdef UPNP_DEBUG - std::cerr << "CUPnPDevice::CUPnPDevice() \n Device: " << - "\n friendlyName: " << m_friendlyName << - "\n deviceType: " << m_deviceType << - "\n manufacturer: " << m_manufacturer << - "\n manufacturerURL: " << m_manufacturerURL << - "\n modelDescription: " << m_modelDescription << - "\n modelName: " << m_modelName << - "\n modelNumber: " << m_modelNumber << - "\n modelURL: " << m_modelURL << - "\n serialNumber: " << m_serialNumber << - "\n UDN: " << m_UDN << - "\n UPC: " << m_UPC << - "\n presentationURL: " << m_presentationURL - << std::endl; -#endif -} - - -CUPnPRootDevice::CUPnPRootDevice( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *rootDevice, - const std::string &OriginalURLBase, - const std::string &FixedURLBase, - const char *location, - int expires) -: -CUPnPDevice(upnpControlPoint, upnpLib, rootDevice, FixedURLBase), -m_UPnPControlPoint(upnpControlPoint), -m_URLBase(OriginalURLBase), -m_location(location), -m_expires(expires) -{ -#ifdef UPNP_DEBUG - std::cerr << - "CUPnPRootDevice::CUPnPRootDevice() \n Root Device: " << - "\n URLBase: " << m_URLBase << - "\n Fixed URLBase: " << FixedURLBase << - "\n location: " << m_location << - "\n expires: " << m_expires - << std::endl; -#endif -} - - -CUPnPControlPoint *CUPnPControlPoint::s_CtrlPoint = NULL; - - -CUPnPControlPoint::CUPnPControlPoint(unsigned short udpPort) -: -m_upnpLib(*this), -m_UPnPClientHandle(), -m_RootDeviceMap(), -m_ServiceMap(), -m_ActivePortMappingsMap(), -m_RootDeviceListMutex("UPnPControlPoint-RootDeviceList"), -m_IGWDeviceDetected(false), -m_WaitForSearchTimeoutMutex("UPnPControlPoint-WaitForSearchTimeout"), -m_WanService(NULL) -{ -#ifdef UPNP_DEBUG - std::cerr << "UPnPControlPoint::CUPnPControlPoint() Constructor" << std::endl; -#endif - // Pointer to self - s_CtrlPoint = this; - -#ifdef UPNP_DEBUG - int resLog = UpnpInitLog(); - std::cerr << "UPnPControlPoint::CUPnPControlPoint() Init log : " << resLog << std::endl; -#endif - -#if UPNP_VERSION < 11400 - int ret = UpnpInit(nullptr, udpPort); -#else - int ret = UpnpInit2(nullptr, udpPort); -#endif - -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint Constructor UpnpInit finished" << std::endl; -#endif - if (ret != UPNP_E_SUCCESS && ret !=UPNP_E_INIT) { -#ifdef UPNP_DEBUG - std::cerr << "UPnPControlPoint::CUPnPControlPoint() error(UpnpInit): Error code : "; -#endif - goto error; - } - - RS_INFO("bound to ", UpnpGetServerIpAddress(), ":", UpnpGetServerPort()); - - ret = UpnpRegisterClient( - reinterpret_cast(&CUPnPControlPoint::Callback), - &m_UPnPClientHandle, - &m_UPnPClientHandle); - if (ret != UPNP_E_SUCCESS) { -#ifdef UPNP_DEBUG - std::cerr << "UPnPControlPoint::CUPnPControlPoint() error(UpnpRegisterClient): Error registering callback: "; -#endif - goto error; - } - - // We could ask for just the right device here. If the root device - // contains the device we want, it will respond with the full XML doc, - // including the root device and every sub-device it has. - // - // But lets find out what we have in our network by calling UPNP_ROOT_DEVICE. - // - // We should not search twice, because this will produce two - // UPNP_DISCOVERY_SEARCH_TIMEOUT events, and we might end with problems - // on the mutex. -// UpnpSetContentLength(m_UPnPClientHandle, 5000000); -// UpnpSetMaxContentLength(5000000); - ret = UpnpSearchAsync(m_UPnPClientHandle, 20, m_upnpLib.UPNP_DEVICE_IGW.c_str(), NULL); - //ret = UpnpSearchAsync(m_UPnPClientHandle, 3, m_upnpLib.UPNP_DEVICE_IGW.c_str(), this); - //ret = UpnpSearchAsync(m_UPnPClientHandle, 3, m_upnpLib.UPNP_DEVICE_LAN.c_str(), this); - //ret = UpnpSearchAsync(m_UPnPClientHandle, 3, m_upnpLib.UPNP_DEVICE_WAN_CONNECTION.c_str(), this); - if (ret != UPNP_E_SUCCESS) { -#ifdef UPNP_DEBUG - std::cerr << "UPnPControlPoint::CUPnPControlPoint() error(UpnpSearchAsync): Error sending search request: "; -#endif - goto error; - } - - // Wait for the UPnP initialization to complete. - { - // Lock the search timeout mutex - m_WaitForSearchTimeoutMutex.lock(); - - // Lock it again, so that we block. Unlocking will only happen - // when the UPNP_DISCOVERY_SEARCH_TIMEOUT event occurs at the - // callback. -#ifdef UPNP_DEBUG - std::cerr << "UPnPControlPoint::CUPnPControlPoint() blocking m_WaitForSearchTimeoutMutex." << std::endl; -#endif - //RsMutex toto(m_WaitForSearchTimeoutMutex); - m_WaitForSearchTimeoutMutex.lock(); -#ifdef UPNP_DEBUG - std::cerr << "UPnPControlPoint::CUPnPControlPoint() m_WaitForSearchTimeoutMutex blocking finished." << std::endl; -#endif - } - - //clean the PortMappingNumberOfEntries as it is erroneus on the first event with the french neufbox - if (WanServiceDetected()) { - m_WanService->propertyMap.erase("PortMappingNumberOfEntries"); - } - -#ifdef UPNP_DEBUG - std::cerr << "UPnPControlPoint::CUPnPControlPoint() CUPnPControlPoint Constructor finished" << std::endl; -#endif - return; - - // Error processing -error: -#ifdef UPNP_DEBUG - std::cerr << ret << ": " << m_upnpLib.GetUPnPErrorMessage(ret) << "." << std::endl; -#endif - UpnpFinish(); -#ifdef UPNP_DEBUG - std::cerr << "UPnPControlPoint::CUPnPControlPoint() UpnpFinish called within CUPnPControlPoint constructor." << std::endl; -#endif -} - - -char* CUPnPControlPoint::getInternalIpAddress() -{ - char * addr = UpnpGetServerIpAddress(); - if (addr == NULL) { - addr = new char[10] ; - sprintf(addr,"%s","127.0.0.1"); - } - return addr; -} - -CUPnPControlPoint::~CUPnPControlPoint() -{ - for( RootDeviceMap::iterator it = m_RootDeviceMap.begin(); - it != m_RootDeviceMap.end(); - ++it) { - delete it->second; - } - // Remove all first - // RemoveAll(); - UpnpUnRegisterClient(m_UPnPClientHandle); -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::~CUPnPControlPoint() UpnpFinish called within CUPnPControlPoint destructor." << std::endl; -#endif - UpnpFinish(); -} - - -bool CUPnPControlPoint::AddPortMappings( - std::vector &upnpPortMapping) -{ - if (!WanServiceDetected()) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::AddPortMappings() UPnP Error: " - "CUPnPControlPoint::AddPortMapping: " - "WAN Service not detected." << std::endl; -#endif - return false; - } -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::AddPortMappings() called." << std::endl; -#endif - - int n = upnpPortMapping.size(); - bool ok = false; - - // Check the number of port mappings before - //have a little break in case we just modified the variable, so we have to wait for an event -// std::cerr << "GetStateVariable pausing in case of an UPnP event incomming."; -// rstime_t begin_time = time(NULL); -// while (true) { -// if (time(NULL) - begin_time > 7) { -// break; -// } -// } - std::istringstream OldPortMappingNumberOfEntries( - m_WanService->GetStateVariable( - "PortMappingNumberOfEntries")); - int oldNumberOfEntries; - OldPortMappingNumberOfEntries >> oldNumberOfEntries; - - // Add the enabled port mappings - for (int i = 0; i < n; ++i) { - if (upnpPortMapping[i].getEnabled() == "1") { - // Add the mapping to the control point - // active mappings list - m_ActivePortMappingsMap[upnpPortMapping[i].getKey()] = - upnpPortMapping[i]; - - // Add the port mapping - PrivateAddPortMapping(upnpPortMapping[i]); - } - } - - // Not very good, must find a better test : check the new number of port entries - //have a little break in case we just modified the variable, so we have to wait for an event -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::AddPortMappings() GetStateVariable pausing in case of an UPnP event incomming."; -#endif - rstime_t begin_time = time(NULL); - while (true) { - if (time(NULL) - begin_time > 4) { - break; - } - } - std::istringstream NewPortMappingNumberOfEntries( - m_WanService->GetStateVariable( - "PortMappingNumberOfEntries")); - int newNumberOfEntries; - NewPortMappingNumberOfEntries >> newNumberOfEntries; -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::AddPortMappings() CUPnPControlPoint::AddPortMappings() newNumberOfEntries - oldNumberOfEntries : " << (newNumberOfEntries - oldNumberOfEntries) << std::endl; -#endif - ok = newNumberOfEntries - oldNumberOfEntries >= 1; - -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::AddPortMappings() finished. Success = " << ok << std::endl; -#endif - - return ok; -} - -std::string CUPnPControlPoint::getExternalAddress() -{ - if (!WanServiceDetected()) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::getExternalAddress() UPnP Error: " - "CUPnPControlPoint::AddPortMapping: " - "WAN Service not detected." << std::endl; -#endif - return ""; - } - std::string result = m_WanService->GetStateVariable("NewExternalIPAddress"); -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::getExternalAddress() m_WanService->GetStateVariable(NewExternalIPAddress) = " << result << std::endl; -#endif - if (result == "") { - PrivateGetExternalIpAdress(); - result = m_WanService->GetStateVariable("NewExternalIPAddress"); -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::getExternalAddress() m_WanService->GetStateVariable(NewExternalIPAddress) = " << result << std::endl; -#endif - if (result == "") { - result = m_WanService->GetStateVariable("ExternalIPAddress"); -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::getExternalAddress() m_WanService->GetStateVariable(ExternalIPAddress) = " << result << std::endl; -#endif - } - } - return result; -} - -void CUPnPControlPoint::RefreshPortMappings() -{ - for ( PortMappingMap::iterator it = m_ActivePortMappingsMap.begin(); - it != m_ActivePortMappingsMap.end(); - ++it) { - PrivateAddPortMapping(it->second); - } -} - - -bool CUPnPControlPoint::PrivateAddPortMapping( - CUPnPPortMapping &upnpPortMapping) -{ - // Get an IP address. The UPnP server one must do. - std::string ipAddress(UpnpGetServerIpAddress()); - - // Start building the action - std::string actionName("AddPortMapping"); - std::vector argval(8); - - // Action parameters - argval[0].SetArgument("NewRemoteHost"); - argval[0].SetValue(""); - argval[1].SetArgument("NewExternalPort"); - argval[1].SetValue(upnpPortMapping.getExPort()); - argval[2].SetArgument("NewProtocol"); - argval[2].SetValue(upnpPortMapping.getProtocol()); - argval[3].SetArgument("NewInternalPort"); - argval[3].SetValue(upnpPortMapping.getInPort()); - argval[4].SetArgument("NewInternalClient"); - argval[4].SetValue(ipAddress); - argval[5].SetArgument("NewEnabled"); - argval[5].SetValue("1"); - argval[6].SetArgument("NewPortMappingDescription"); - argval[6].SetValue(upnpPortMapping.getDescription()); - argval[7].SetArgument("NewLeaseDuration"); - argval[7].SetValue("0"); - - // Execute - bool ret = true; - for (ServiceMap::iterator it = m_ServiceMap.begin(); - it != m_ServiceMap.end(); ++it) { - ret &= it->second->Execute(actionName, argval); - } - - return ret; -} - - -bool CUPnPControlPoint::DeletePortMappings( - std::vector &upnpPortMapping) -{ -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::DeletePortMappings() called." << std::endl; -#endif - if (!WanServiceDetected()) { -#ifdef UPNP_DEBUG - std::cerr << "UPnP Error: " - "CUPnPControlPoint::DeletePortMapping: " - "WAN Service not detected." << std::endl; -#endif - return false; - } - - int n = upnpPortMapping.size(); - - // Delete the enabled port mappings - for (int i = 0; i < n; ++i) { - if (upnpPortMapping[i].getEnabled() == "1") { - // Delete the mapping from the control point - // active mappings list - PortMappingMap::iterator it = - m_ActivePortMappingsMap.find( - upnpPortMapping[i].getKey()); - if (it != m_ActivePortMappingsMap.end()) { - m_ActivePortMappingsMap.erase(it); - } else { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::DeletePortMappings() UPnP Error: " - "CUPnPControlPoint::DeletePortMapping: " - "Mapping was not found in the active " - "mapping map." << std::endl; -#endif - } - - // Delete the port mapping - PrivateDeletePortMapping(upnpPortMapping[i]); - } - } - - return true; -} - - -bool CUPnPControlPoint::PrivateDeletePortMapping( - CUPnPPortMapping &upnpPortMapping) -{ - // Start building the action - std::string actionName("DeletePortMapping"); - std::vector argval(3); - - // Action parameters - argval[0].SetArgument("NewRemoteHost"); - argval[0].SetValue(""); - argval[1].SetArgument("NewExternalPort"); - argval[1].SetValue(upnpPortMapping.getExPort()); - argval[2].SetArgument("NewProtocol"); - argval[2].SetValue(upnpPortMapping.getProtocol()); - - // Execute - bool ret = true; - for (ServiceMap::iterator it = m_ServiceMap.begin(); - it != m_ServiceMap.end(); ++it) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::PrivateDeletePortMapping() Sending a delete port mapping action." << std::endl; -#endif - ret &= it->second->Execute(actionName, argval); -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::PrivateDeletePortMapping() Delete port mapping action finished." << std::endl; -#endif - } - - return ret; -} - -bool CUPnPControlPoint::PrivateGetExternalIpAdress() -{ - // Start building the action - std::string actionName("GetExternalIPAddress"); - std::vector argval(0); - - // Execute - bool ret = true; - for (ServiceMap::iterator it = m_ServiceMap.begin(); - it != m_ServiceMap.end(); ++it) { - ret &= it->second->Execute(actionName, argval); - } - - return ret; -} - - -// This function is static -int CUPnPControlPoint::Callback( - Upnp_EventType EventType, const void* Event, void * /*Cookie*/ ) -{ - if(!Event) return 0; - - std::string msg; - std::string msg2; - - CUPnPControlPoint* upnpCP = CUPnPControlPoint::s_CtrlPoint; - if (!upnpCP) return 0; - - switch (EventType) - { - case UPNP_DISCOVERY_ADVERTISEMENT_ALIVE: /*fallthrough*/ - case UPNP_DISCOVERY_SEARCH_RESULT: - { - const UpnpDiscovery* d_event = static_cast(Event); - - // Get the XML tree device description in doc - IXML_Document* doc = nullptr; - UpnpDownloadXmlDoc(UpnpDiscovery_get_Location_cstr(d_event), &doc); - if (!doc) break; - - IXML_Element* root = upnpCP->m_upnpLib.Element_GetRootElement(doc); - - // Extract the URLBase - const std::string urlBase = upnpCP->m_upnpLib. - Element_GetChildValueByTag(root, "URLBase"); - // Get the root device - IXML_Element *rootDevice = upnpCP->m_upnpLib. - Element_GetFirstChildByTag(root, "device"); - // Extract the deviceType - std::string devType(upnpCP->m_upnpLib. - Element_GetChildValueByTag(rootDevice, "deviceType")); - -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::Callback() EventType==UPNP_DISCOVERY_SEARCH_RESULT" << std::endl - << "urlBase:" << urlBase << std::endl - << "devType:" << devType << std::endl; -#endif - - // Only add device if it is an InternetGatewayDevice - if (stdStringIsEqualCI(devType, upnpCP->m_upnpLib.UPNP_DEVICE_IGW)) - { - // This condition can be used to auto-detect - // the UPnP device we are interested in. - // Obs.: Don't block the entry here on this - // condition! There may be more than one device, - // and the first that enters may not be the one - // we are interested in! - upnpCP->SetIGWDeviceDetected(true); - // Log it if not UPNP_DISCOVERY_ADVERTISEMENT_ALIVE, - // we don't want to spam our logs. - //if (EventType != UPNP_DISCOVERY_ADVERTISEMENT_ALIVE) { - // Add the root device to our list - upnpCP->AddRootDevice( - rootDevice, urlBase, - UpnpDiscovery_get_Location_cstr(d_event), - UpnpDiscovery_get_Expires(d_event) ); - -#if (UPNP_VERSION > 10624) && (UPNP_VERSION < 10800) - upnpCP->m_WaitForSearchTimeoutMutex.unlock(); -#endif - } - - // Free the XML doc tree - ixmlDocument_free(doc); - break; - } - case UPNP_DISCOVERY_SEARCH_TIMEOUT: - { -#if (UPNP_VERSION > 10624) && (UPNP_VERSION < 10800) - std::cerr << "********************************************************************************" << std::endl - << "*** THIS SHOULD NOT HAPPEN !!! TELL IT TO DEVS ***" << std::endl - << "*** UPnPBase.cpp CUPnPControlPoint::Callback() UPNP_DISCOVERY_SEARCH_TIMEOUT ***" << std::endl - << "********************************************************************************" << std::endl; -#endif - - // Unlock the search timeout mutex - upnpCP->m_WaitForSearchTimeoutMutex.unlock(); - break; - } - case UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE: // UPnP Device Removed - { - const UpnpDiscovery* dab_event = static_cast(Event); - if(!dab_event) break; - - std::string devType = UpnpDiscovery_get_DeviceType_cstr(dab_event); - - // Check for an InternetGatewayDevice and removes it from the list - std::transform(devType.begin(), devType.end(), devType.begin(), tolower); - if (stdStringIsEqualCI(devType, upnpCP->m_upnpLib.UPNP_DEVICE_IGW)) - upnpCP->RemoveRootDevice( - UpnpDiscovery_get_DeviceID_cstr(dab_event) ); - break; - } - case UPNP_EVENT_RECEIVED: - { - // Event reveived - const UpnpEvent* e_event = static_cast(Event); - - const std::string Sid = UpnpEvent_get_SID_cstr(e_event); - - // Parses the event - upnpCP->OnEventReceived( Sid, - UpnpEvent_get_EventKey(e_event), - UpnpEvent_get_ChangedVariables(e_event) ); - break; - } - case UPNP_EVENT_SUBSCRIBE_COMPLETE: - msg += "error(UPNP_EVENT_SUBSCRIBE_COMPLETE): "; - goto upnpEventRenewalComplete; - case UPNP_EVENT_UNSUBSCRIBE_COMPLETE: - msg += "error(UPNP_EVENT_UNSUBSCRIBE_COMPLETE): "; - goto upnpEventRenewalComplete; - case UPNP_EVENT_RENEWAL_COMPLETE: - { - msg += "error(UPNP_EVENT_RENEWAL_COMPLETE): "; -upnpEventRenewalComplete: - const UpnpEventSubscribe* es_event = - static_cast(Event); - - if (UpnpEventSubscribe_get_ErrCode(es_event) != UPNP_E_SUCCESS) - { - msg += "Error in Event Subscribe Callback"; - upnpCP->m_upnpLib.processUPnPErrorMessage( - msg, UpnpEventSubscribe_get_ErrCode(es_event), - nullptr, nullptr ); - } - - break; - } - case UPNP_EVENT_AUTORENEWAL_FAILED: - msg += "CUPnPControlPoint::Callback() error(UPNP_EVENT_AUTORENEWAL_FAILED): "; - msg2 += "UPNP_EVENT_AUTORENEWAL_FAILED: "; - goto upnpEventSubscriptionExpired; - case UPNP_EVENT_SUBSCRIPTION_EXPIRED: { - msg += "CUPnPControlPoint::Callback() error(UPNP_EVENT_SUBSCRIPTION_EXPIRED): "; - msg2 += "UPNP_EVENT_SUBSCRIPTION_EXPIRED: "; -upnpEventSubscriptionExpired: - const UpnpEventSubscribe* es_event = - static_cast(Event); - - Upnp_SID newSID; - int TimeOut = 1801; - int ret = UpnpSubscribe( - upnpCP->m_UPnPClientHandle, -#ifdef PATCHED_LIBUPNP - UpnpString_get_String(es_event->PublisherUrl), -#else - UpnpEventSubscribe_get_PublisherUrl_cstr(es_event), -#endif - &TimeOut, - newSID); - if (ret != UPNP_E_SUCCESS) - { - msg += "Error Subscribing to EventURL"; - upnpCP->m_upnpLib.processUPnPErrorMessage( - msg, UpnpEventSubscribe_get_ErrCode(es_event), - nullptr, nullptr ); - } - else - { - ServiceMap::iterator it = -#ifdef PATCHED_LIBUPNP - upnpCP->m_ServiceMap.find(UpnpString_get_String(es_event->PublisherUrl)); -#else - upnpCP->m_ServiceMap.find( - UpnpEventSubscribe_get_PublisherUrl_cstr(es_event) ); -#endif - if (it != upnpCP->m_ServiceMap.end()) { - CUPnPService &service = *(it->second); - service.SetTimeout(TimeOut); - service.SetSID(newSID); - std::cerr << "CUPnPControlPoint::Callback() Re-subscribed to EventURL '" << -#ifdef PATCHED_LIBUPNP - UpnpString_get_String(es_event->PublisherUrl) << -#else - UpnpEventSubscribe_get_PublisherUrl_cstr(es_event) << -#endif - "' with SID == '" << - newSID << "'." << std::endl; - // In principle, we should test to see if the - // service is the same. But here we only have one - // service, so... - upnpCP->RefreshPortMappings(); - } - else - { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::Callback() Error: did not find service " << - newSID << " in the service map." << std::endl; -#endif - } - } - break; - } - case UPNP_CONTROL_ACTION_COMPLETE: - { - // This is here if we choose to do this asynchronously - const UpnpActionComplete* a_event = - static_cast(Event); - if(UpnpActionComplete_get_ErrCode(a_event) != UPNP_E_SUCCESS) - { - upnpCP->m_upnpLib.processUPnPErrorMessage( - "UpnpSendActionAsync", - UpnpActionComplete_get_ErrCode(a_event), nullptr, - UpnpActionComplete_get_ActionResult(a_event) ); - } - else - { - // Check the response document - upnpCP->m_upnpLib.ProcessActionResponse( - UpnpActionComplete_get_ActionResult(a_event), - "" ); - } - /* No need for any processing here, just print out results. - * Service state table updates are handled by events. - */ - break; - } - case UPNP_CONTROL_GET_VAR_COMPLETE: - { - msg += "CUPnPControlPoint::Callback() error(UPNP_CONTROL_GET_VAR_COMPLETE): "; - const UpnpStateVarComplete* sv_event = - static_cast(Event); - if (UpnpStateVarComplete_get_ErrCode(sv_event) != UPNP_E_SUCCESS) - { - msg += "m_UpnpGetServiceVarStatusAsync"; - upnpCP->m_upnpLib.processUPnPErrorMessage( - msg, UpnpStateVarComplete_get_ErrCode(sv_event), - nullptr, nullptr ); - } - else - { - //add the variable to the wanservice property map - (upnpCP->m_WanService->propertyMap)[ - std::string( - UpnpStateVarComplete_get_StateVarName_cstr(sv_event) ) ] - = std::string(UpnpStateVarComplete_get_CurrentVal_cstr(sv_event)); - } - break; - } - // ignore these cases, since this is not a device - case UPNP_CONTROL_GET_VAR_REQUEST: - //fprintf(stderr, "Callback: UPNP_CONTROL_GET_VAR_REQUEST\n"); -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::Callback() error(UPNP_CONTROL_GET_VAR_REQUEST): "; -#endif - goto eventSubscriptionRequest; - case UPNP_CONTROL_ACTION_REQUEST: - //fprintf(stderr, "Callback: UPNP_CONTROL_ACTION_REQUEST\n"); -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::Callback() error(UPNP_CONTROL_ACTION_REQUEST): "; -#endif - goto eventSubscriptionRequest; - case UPNP_EVENT_SUBSCRIPTION_REQUEST: - //fprintf(stderr, "Callback: UPNP_EVENT_SUBSCRIPTION_REQUEST\n"); -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::Callback() error(UPNP_EVENT_SUBSCRIPTION_REQUEST): "; -#endif -eventSubscriptionRequest: -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::Callback() This is not a UPnP Device, this is a UPnP Control Point, event ignored." << std::endl; -#endif - break; - default: - // Humm, this is not good, we forgot to handle something... -#ifdef UPNP_DEBUG - fprintf(stderr, - "Callback: default... Unknown event:'%d', not good.\n", - EventType); - std::cerr << "CUPnPControlPoint::Callback() error(UPnP::Callback): Event not handled:'" << - EventType << "'." << std::endl; -#endif - // Better not throw in the callback. Who would catch it? - //throw CUPnPException(msg); - break; - } - - return 0; -} - - -void CUPnPControlPoint::OnEventReceived( - const std::string &Sid, - int EventKey, - const IXML_Document* ChangedVariablesDoc) -{ - /* remove unused parameter warnings */ - (void) EventKey; - -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::OnEventReceived() UPNP_EVENT_RECEIVED:" << - "\n SID: " << Sid << - "\n Key: " << EventKey << std::endl; - std::cerr << "CUPnPControlPoint::OnEventReceived() m_WanService->GetServiceId() : " << m_WanService->GetSID() << std::endl; -#endif - - if (m_WanService->GetSID() == Sid) { - //let's store the properties if it is an event of the wan device -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::OnEventReceived() \n Property list:"; -#endif - - IXML_Element *root = - m_upnpLib.Element_GetRootElement(ChangedVariablesDoc); - IXML_Element *child = - m_upnpLib.Element_GetFirstChild(root); - if (child) { - while (child) { - IXML_Element *child2 = - m_upnpLib.Element_GetFirstChild(child); - const DOMString childTag = - m_upnpLib.Element_GetTag(child2); - std::string childValue = - m_upnpLib.Element_GetTextValue(child2); -#ifdef UPNP_DEBUG - std::cerr << "\n " << - childTag << "='" << - childValue << "'"; -#endif - const std::string cTag(childTag); - const std::string cValue(childValue); - (m_WanService->propertyMap)[cTag] = cValue; - child = m_upnpLib.Element_GetNextSibling(child); - } - } else { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::OnEventReceived() \n Empty property list."; -#endif - } -#ifdef UPNP_DEBUG - std::cerr << std::endl; -#endif - // Freeing that doc segfaults. Probably should not be freed. - //ixmlDocument_free(ChangedVariablesDoc); - } -} - - -void CUPnPControlPoint::AddRootDevice( - IXML_Element *rootDevice, const std::string &urlBase, - const char *location, int expires) -{ - // Lock the Root Device List - RsMutex toto(m_RootDeviceListMutex); - - // Root node's URLBase - std::string OriginalURLBase(urlBase); - std::string FixedURLBase(OriginalURLBase.empty() ? - location : - OriginalURLBase); - - // Get the UDN (Unique Device Name) - std::string UDN( - m_upnpLib.Element_GetChildValueByTag(rootDevice, "UDN")); - RootDeviceMap::iterator it = m_RootDeviceMap.find(UDN); - bool alreadyAdded = it != m_RootDeviceMap.end(); - if (alreadyAdded) { - // Just set the expires field - it->second->SetExpires(expires); - } else { - // Add a new root device to the root device list - CUPnPRootDevice *upnpRootDevice = new CUPnPRootDevice( - *this, m_upnpLib, rootDevice, - OriginalURLBase, FixedURLBase, - location, expires); - m_RootDeviceMap[upnpRootDevice->GetUDN()] = upnpRootDevice; - } -} - - -void CUPnPControlPoint::RemoveRootDevice(const char *udn) -{ - // Lock the Root Device List - RsMutex toto(m_RootDeviceListMutex); - - // Remove - std::string UDN(udn); - RootDeviceMap::iterator it = m_RootDeviceMap.find(UDN); - if (it != m_RootDeviceMap.end()) { - delete it->second; - m_RootDeviceMap.erase(UDN); - } -} - - -void CUPnPControlPoint::Subscribe(CUPnPService &service) -{ - - IXML_Document *scpdDoc = NULL; - int errcode = UpnpDownloadXmlDoc( - service.GetAbsSCPDURL().c_str(), &scpdDoc); - if (errcode == UPNP_E_SUCCESS) { - // Get the root node of this service (the SCPD Document) - IXML_Element *scpdRoot = - m_upnpLib.Element_GetRootElement(scpdDoc); - CUPnPSCPD *scpd = new CUPnPSCPD(*this, m_upnpLib, - scpdRoot, service.GetAbsSCPDURL()); - service.SetSCPD(scpd); - m_ServiceMap[service.GetAbsEventSubURL()] = &service; -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::Subscribe() Successfully retrieved SCPD Document for service " << - service.GetServiceType() << ", absEventSubURL: " << - service.GetAbsEventSubURL() << "." << std::endl; -#endif - - // Now try to subscribe to this service. If the subscription - // is not successfull, we will not be notified about events, - // but it may be possible to use the service anyway. - errcode = UpnpSubscribe(m_UPnPClientHandle, - service.GetAbsEventSubURL().c_str(), - service.GetTimeoutAddr(), - service.GetSID()); - if (errcode == UPNP_E_SUCCESS) { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::Subscribe() Successfully subscribed to service " << - service.GetServiceType() << ", absEventSubURL: " << - service.GetAbsEventSubURL() << "." << std::endl; -#endif - } else { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::Subscribe() Error subscribing to service " << - service.GetServiceType() << ", absEventSubURL: " << - service.GetAbsEventSubURL() << ", error: " << - m_upnpLib.GetUPnPErrorMessage(errcode) << "."; -#endif - goto error; - } - } else { -#ifdef UPNP_DEBUG - std::cerr << "CUPnPControlPoint::Subscribe() Error getting SCPD Document from " << - service.GetAbsSCPDURL() << "." << std::endl; -#endif - } - - return; - -error: - ; -#ifdef UPNP_DEBUG - std::cerr << std::endl; -#endif -} - - -void CUPnPControlPoint::Unsubscribe(CUPnPService &service) -{ - ServiceMap::iterator it = m_ServiceMap.find(service.GetAbsEventSubURL()); - if (it != m_ServiceMap.end()) { - m_ServiceMap.erase(it); - UpnpUnSubscribe(m_UPnPClientHandle, service.GetSID()); - } -} - - -// File_checked_for_headers diff --git a/libretroshare/src/rs_upnp/UPnPBase.h b/libretroshare/src/rs_upnp/UPnPBase.h deleted file mode 100644 index e1c41fb83..000000000 --- a/libretroshare/src/rs_upnp/UPnPBase.h +++ /dev/null @@ -1,620 +0,0 @@ -/******************************************************************************* - * libretroshare/src/upnp: UPnPBase.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (c) 2004-2009 Marcelo Roberto Jimenez ( phoenix@amule.org ) * - * Copyright (c) 2006-2009 aMule Team ( admin@amule.org / http://www.amule.org)* - * Copyright (c) 2009-2010 Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "util/rsthreads.h" - -#include -#include - -#ifdef UPNP_C - std::string stdEmptyString; -#else // UPNP_C - extern std::string stdEmptyString; -#endif // UPNP_C - -//#define UPNP_DEBUG 1 - -/** - * Case insensitive std::string comparison - */ -bool stdStringIsEqualCI( - const std::string &s1, - const std::string &s2); - - -class CUPnPPortMapping -{ -private: - std::string m_ex_port; - std::string m_in_port; - std::string m_protocol; - std::string m_enabled; - std::string m_description; - std::string m_key; - -public: - CUPnPPortMapping( - int ex_port = 0, - int in_port = 0, - const std::string &protocol = stdEmptyString, - bool enabled = false, - const std::string &description = stdEmptyString); - ~CUPnPPortMapping() {} - - const std::string &getExPort() const - { return m_ex_port; } - const std::string &getInPort() const - { return m_in_port; } - const std::string &getProtocol() const - { return m_protocol; } - const std::string &getEnabled() const - { return m_enabled; } - const std::string &getDescription() const - { return m_description; } - const std::string &getKey() const - { return m_key; } -}; - - -class CUPnPControlPoint; - - -class CUPnPLib -{ -public: - static const std::string &UPNP_ROOT_DEVICE; - static const std::string &UPNP_DEVICE_IGW; - static const std::string &UPNP_DEVICE_WAN; - static const std::string &UPNP_DEVICE_WAN_CONNECTION; - static const std::string &UPNP_DEVICE_LAN; - static const std::string &UPNP_SERVICE_LAYER3_FORWARDING; - static const std::string &UPNP_SERVICE_WAN_COMMON_INTERFACE_CONFIG; - static const std::string &UPNP_SERVICE_WAN_IP_CONNECTION; - static const std::string &UPNP_SERVICE_WAN_PPP_CONNECTION; - CUPnPControlPoint &m_ctrlPoint; - -public: - explicit CUPnPLib(CUPnPControlPoint &ctrlPoint); - ~CUPnPLib() {} - - // Convenience function so we don't have to write explicit calls - // to char2unicode every time - std::string GetUPnPErrorMessage(int code) const; - - // Convenience function to avoid repetitive processing of error - // messages - std::string processUPnPErrorMessage(const std::string &messsage, - int code, - const DOMString errorString, - const IXML_Document* doc) const; - - // Processing response to actions - void ProcessActionResponse( - const IXML_Document* RespDoc, - const std::string& actionName ) const; - - // IXML_Element - IXML_Element* Element_GetRootElement(const IXML_Document* doc) const; - IXML_Element *Element_GetFirstChild( - IXML_Element *parent) const; - IXML_Element *Element_GetNextSibling( - IXML_Element *child) const; - const DOMString Element_GetTag( - IXML_Element *element) const; - const std::string Element_GetTextValue( - IXML_Element *element) const; - const std::string Element_GetChildValueByTag( - IXML_Element *element, - const DOMString tag) const; - IXML_Element *Element_GetFirstChildByTag( - IXML_Element *element, - const DOMString tag) const; - IXML_Element *Element_GetNextSiblingByTag( - IXML_Element *element, - const DOMString tag) const; - const std::string Element_GetAttributeByTag( - IXML_Element *element, - const DOMString tag) const; -}; - - -class CUPnPControlPoint; - -/* - * Even though we can retrieve the upnpLib handler from the upnpControlPoint, - * we must pass it separetly at this point, because the class CUPnPControlPoint - * must be declared after. - * - * CUPnPLib can only be removed from the constructor once we agree to link to - * UPnPLib explicitly, making this dlopen() stuff unnecessary. - */ -template -class CXML_List : public std::map -{ -public: - CXML_List( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *parent, - const std::string &url); - ~CXML_List(); -}; - - -template -CXML_List::CXML_List( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *parent, - const std::string &url) -{ - IXML_Element *elementList = - upnpLib.Element_GetFirstChildByTag(parent, XML_LIST_NAME); - unsigned int i = 0; - for ( IXML_Element *element = upnpLib.Element_GetFirstChildByTag(elementList, XML_ELEMENT_NAME); - element; - element = upnpLib.Element_GetNextSiblingByTag(element, XML_ELEMENT_NAME)) { - // Add a new element to the element list - T *upnpElement = new T(upnpControlPoint, upnpLib, element, url); - (*this)[upnpElement->GetKey()] = upnpElement; - ++i; - } - std::cerr << "\n " << XML_LIST_NAME << ": " << - i << " " << XML_ELEMENT_NAME << "s."; -} - - -template -CXML_List::~CXML_List() -{ - typename CXML_List::iterator it; - for(it = this->begin(); it != this->end(); ++it) { - delete (*it).second; - } -} - -extern const char s_argument[]; -extern const char s_argumentList[]; -extern const char s_action[]; -extern const char s_actionList[]; -extern const char s_allowedValue[]; -extern const char s_allowedValueList[]; -extern const char s_stateVariable[]; -extern const char s_serviceStateTable[]; -extern const char s_service[]; -extern const char s_serviceList[]; -extern const char s_device[]; -extern const char s_deviceList[]; - -#ifdef UPNP_C - const char s_argument[] = "argument"; - const char s_argumentList[] = "argumentList"; - const char s_action[] = "action"; - const char s_actionList[] = "actionList"; - const char s_allowedValue[] = "allowedValue"; - const char s_allowedValueList[] = "allowedValueList"; - const char s_stateVariable[] = "stateVariable"; - const char s_serviceStateTable[] = "serviceStateTable"; - const char s_service[] = "service"; - const char s_serviceList[] = "serviceList"; - const char s_device[] = "device"; - const char s_deviceList[] = "deviceList"; -#endif // UPNP_C - - -class CUPnPArgument; -typedef CXML_List ArgumentList; -class CUPnPAction; -typedef CXML_List ActionList; -class CUPnPStateVariable; -typedef CXML_List ServiceStateTable; -class CUPnPAllowedValue; -typedef CXML_List AllowedValueList; -class CUPnPService; -typedef CXML_List ServiceList; -class CUPnPDevice; -typedef CXML_List DeviceList; - - -class CUPnPError -{ -private: - IXML_Element *m_root; - const std::string m_ErrorCode; - const std::string m_ErrorDescription; -public: - CUPnPError( - const CUPnPLib &upnpLib, - const IXML_Document *errorDoc); - ~CUPnPError() {} - const std::string &getErrorCode() const - { return m_ErrorCode; } - const std::string &getErrorDescription() const - { return m_ErrorDescription; } -}; - - -class CUPnPArgument -{ -private: - const CUPnPControlPoint &m_UPnPControlPoint; - const std::string m_name; - const std::string m_direction; - bool m_retval; - const std::string m_relatedStateVariable; - -public: - CUPnPArgument( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *argument, - const std::string &SCPDURL); - ~CUPnPArgument() {} - const std::string &GetName() const - { return m_name; } - const std::string &GetDirection() const - { return m_direction; } - bool GetRetVal() const - { return m_retval; } - const std::string &GetRelatedStateVariable() const - { return m_relatedStateVariable; } - const std::string &GetKey() const - { return m_name; } -}; - - - -class CUPnPAction -{ -private: - const CUPnPControlPoint &m_UPnPControlPoint; - ArgumentList m_ArgumentList; - const std::string m_name; - -public: - CUPnPAction( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *action, - const std::string &SCPDURL); - ~CUPnPAction() {} - const std::string &GetName() const - { return m_name; } - const std::string &GetKey() const - { return m_name; } - const ArgumentList &GetArgumentList() const - { return m_ArgumentList; } -}; - - -class CUPnPAllowedValue -{ -private: - const CUPnPControlPoint &m_UPnPControlPoint; - const std::string m_allowedValue; - -public: - CUPnPAllowedValue( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *allowedValue, - const std::string &SCPDURL); - ~CUPnPAllowedValue() {} - const std::string &GetAllowedValue() const - { return m_allowedValue; } - const std::string &GetKey() const - { return m_allowedValue; } -}; - - -class CUPnPStateVariable -{ -private: - const CUPnPControlPoint &m_UPnPControlPoint; - AllowedValueList m_AllowedValueList; - const std::string m_name; - const std::string m_dataType; - const std::string m_defaultValue; - const std::string m_sendEvents; - -public: - CUPnPStateVariable( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *stateVariable, - const std::string &URLBase); - ~CUPnPStateVariable() {} - const std::string &GetNname() const - { return m_name; } - const std::string &GetDataType() const - { return m_dataType; } - const std::string &GetDefaultValue() const - { return m_defaultValue; } - const std::string &GetKey() const - { return m_name; } - const AllowedValueList &GetAllowedValueList() const - { return m_AllowedValueList; } -}; - - -class CUPnPSCPD -{ -private: - const CUPnPControlPoint &m_UPnPControlPoint; - ActionList m_ActionList; - ServiceStateTable m_ServiceStateTable; - const std::string m_SCPDURL; - -public: - CUPnPSCPD( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *scpd, - const std::string &SCPDURL); - ~CUPnPSCPD() {} - const ActionList &GetActionList() const - { return m_ActionList; } - const ServiceStateTable &GetServiceStateTable() const - { return m_ServiceStateTable; } -}; - - -class CUPnPArgumentValue -{ -private: - std::string m_argument; - std::string m_value; - -public: - CUPnPArgumentValue(); - CUPnPArgumentValue(const std::string &argument, const std::string &value); - ~CUPnPArgumentValue() {} - - const std::string &GetArgument() const { return m_argument; } - const std::string &GetValue() const { return m_value; } - const std::string &SetArgument(const std::string& argument) { return m_argument = argument; } - const std::string &SetValue(const std::string &value) { return m_value = value; } -}; - - -class CUPnPService -{ -private: - const CUPnPControlPoint &m_UPnPControlPoint; - CUPnPLib &m_upnpLib; - const std::string m_serviceType; - const std::string m_serviceId; - const std::string m_SCPDURL; - const std::string m_controlURL; - const std::string m_eventSubURL; - std::string m_absSCPDURL; - std::string m_absControlURL; - std::string m_absEventSubURL; - int m_timeout; - Upnp_SID m_SID; - std::auto_ptr m_SCPD; - -public: - std::map propertyMap; - CUPnPService( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *service, - const std::string &URLBase); - ~CUPnPService(); - - const std::string &GetServiceType() const - { return m_serviceType; } - const std::string &GetServiceId() const - { return m_serviceId; } - const std::string &GetSCPDURL() const - { return m_SCPDURL; } - const std::string &GetAbsSCPDURL() const - { return m_absSCPDURL; } - const std::string &GetControlURL() const - { return m_controlURL; } - const std::string &GetEventSubURL() const - { return m_eventSubURL; } - const std::string &GetAbsControlURL() const - { return m_absControlURL; } - const std::string &GetAbsEventSubURL() const - { return m_absEventSubURL; } - int GetTimeout() const - { return m_timeout; } - void SetTimeout(int t) - { m_timeout = t; } - int *GetTimeoutAddr() - { return &m_timeout; } - char *GetSID() - { return m_SID; } - void SetSID(const char *s) - { memcpy(m_SID, s, sizeof(Upnp_SID)); } - const std::string &GetKey() const - { return m_serviceId; } - bool IsSubscribed() const - { return m_SCPD.get() != NULL; } - void SetSCPD(CUPnPSCPD *SCPD) - { m_SCPD.reset(SCPD); } - - bool Execute( - const std::string &ActionName, - const std::vector &ArgValue) const; - const std::string GetStateVariable( - const std::string &stateVariableName); - -}; - - -class CUPnPDevice -{ -private: - const CUPnPControlPoint &m_UPnPControlPoint; - - // Please, lock these lists before use - DeviceList m_DeviceList; - ServiceList m_ServiceList; - - const std::string m_deviceType; - const std::string m_friendlyName; - const std::string m_manufacturer; - const std::string m_manufacturerURL; - const std::string m_modelDescription; - const std::string m_modelName; - const std::string m_modelNumber; - const std::string m_modelURL; - const std::string m_serialNumber; - const std::string m_UDN; - const std::string m_UPC; - std::string m_presentationURL; - -public: - CUPnPDevice( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *device, - const std::string &URLBase); - ~CUPnPDevice() {} - - const std::string &GetUDN() const - { return m_UDN; } - const std::string &GetDeviceType() const - { return m_deviceType; } - const std::string &GetFriendlyName() const - { return m_friendlyName; } - const std::string &GetPresentationURL() const - { return m_presentationURL; } - const std::string &GetKey() const - { return m_UDN; } -}; - - -class CUPnPRootDevice : public CUPnPDevice -{ -private: - const CUPnPControlPoint &m_UPnPControlPoint; - const std::string m_URLBase; - const std::string m_location; - int m_expires; - -public: - CUPnPRootDevice( - const CUPnPControlPoint &upnpControlPoint, - CUPnPLib &upnpLib, - IXML_Element *rootDevice, - const std::string &OriginalURLBase, - const std::string &FixedURLBase, - const char *location, - int expires); - ~CUPnPRootDevice() {} - - const std::string &GetURLBase() const - { return m_URLBase; } - const std::string &GetLocation() const - { return m_location; } - int GetExpires() const - { return m_expires; } - void SetExpires(int expires) - { m_expires = expires; } -}; - - -typedef std::map RootDeviceMap; -typedef std::map ServiceMap; -typedef std::map PortMappingMap; - - -class CUPnPControlPoint -{ -private: - // upnp stuff - CUPnPLib m_upnpLib; - UpnpClient_Handle m_UPnPClientHandle; - RootDeviceMap m_RootDeviceMap; - ServiceMap m_ServiceMap; - PortMappingMap m_ActivePortMappingsMap; - RsMutex m_RootDeviceListMutex; - bool m_IGWDeviceDetected; - RsMutex m_WaitForSearchTimeoutMutex; - -public: - CUPnPService *m_WanService; - std::string m_getStateVariableLastResult; - static CUPnPControlPoint *s_CtrlPoint; - explicit CUPnPControlPoint(unsigned short udpPort); - ~CUPnPControlPoint(); - char* getInternalIpAddress(); - std::string getExternalAddress(); - void Subscribe(CUPnPService &service); - void Unsubscribe(CUPnPService &service); - bool AddPortMappings( - std::vector &upnpPortMapping); - bool DeletePortMappings( - std::vector &upnpPortMapping); - - UpnpClient_Handle GetUPnPClientHandle() const - { return m_UPnPClientHandle; } - - bool GetIGWDeviceDetected() const - { return m_IGWDeviceDetected; } - void SetIGWDeviceDetected(bool b) - { m_IGWDeviceDetected = b; } - bool WanServiceDetected() const - { return !m_ServiceMap.empty(); } - void SetWanService(CUPnPService *service) - { m_WanService = service; } - - // Callback function - static int Callback( - Upnp_EventType EventType, const void* Event, void* Cookie ); - void OnEventReceived(const std::string &Sid, - int EventKey, - const IXML_Document* ChangedVariables); - -private: - void AddRootDevice( - IXML_Element *rootDevice, - const std::string &urlBase, - const char *location, - int expires); - void RemoveRootDevice( - const char *udn); - void RefreshPortMappings(); - bool PrivateAddPortMapping( - CUPnPPortMapping &upnpPortMapping); - bool PrivateDeletePortMapping( - CUPnPPortMapping &upnpPortMapping); - bool PrivateGetExternalIpAdress(); -}; - -// File_checked_for_headers diff --git a/libretroshare/src/rs_upnp/upnp18_retrocompat.h b/libretroshare/src/rs_upnp/upnp18_retrocompat.h deleted file mode 100644 index 26fb0a524..000000000 --- a/libretroshare/src/rs_upnp/upnp18_retrocompat.h +++ /dev/null @@ -1,82 +0,0 @@ -/******************************************************************************* - * libupnp-1.8.x -> libupnp-1.6.x retrocompatibility header * - * * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include - - -#if UPNP_VERSION < 10800 - -using UpnpDiscovery = Upnp_Discovery; -using UpnpEvent = Upnp_Event; -using UpnpEventSubscribe = Upnp_Event_Subscribe; -using UpnpActionComplete = Upnp_Action_Complete; -using UpnpStateVarComplete = Upnp_State_Var_Complete; - -static inline const char* UpnpStateVarComplete_get_CurrentVal_cstr( - const UpnpStateVarComplete* esvc) noexcept { return esvc->CurrentVal; } - -#endif // UPNP_VERSION < 10800 - -#if UPNP_VERSION < 10624 - -static inline int UpnpDiscovery_get_Expires(const Upnp_Discovery* disc) noexcept -{ return disc->Expires; } - -static inline const char* UpnpDiscovery_get_DeviceID_cstr( - const Upnp_Discovery* disc ) noexcept -{ return disc->DeviceId; } - -static inline const char* UpnpDiscovery_get_DeviceType_cstr( - const Upnp_Discovery* disc ) noexcept -{ return disc->DeviceType; } - -static inline const char* UpnpDiscovery_get_Location_cstr( - const Upnp_Discovery* disc ) noexcept -{ return disc->Location; } - -static inline const char* UpnpEvent_get_SID_cstr(const UpnpEvent* ev) noexcept -{ return ev->Sid; } - -static inline int UpnpEvent_get_EventKey(const UpnpEvent* ev) noexcept -{ return ev->EventKey; } - -static inline const IXML_Document* UpnpEvent_get_ChangedVariables( - const UpnpEvent* ev) noexcept { return ev->ChangedVariables; } - -static inline int UpnpEventSubscribe_get_ErrCode(const UpnpEventSubscribe* evs) -noexcept { return evs->ErrCode; } - -static inline const char* UpnpEventSubscribe_get_PublisherUrl_cstr( - const UpnpEventSubscribe* evs ) noexcept { return evs->PublisherUrl; } - -static inline int UpnpActionComplete_get_ErrCode(const UpnpActionComplete* evc) -noexcept { return evc->ErrCode; } - -static inline const IXML_Document* UpnpActionComplete_get_ActionResult( - const UpnpActionComplete* evc ) noexcept { return evc->ActionResult; } - -static inline int UpnpStateVarComplete_get_ErrCode( - const UpnpStateVarComplete* esvc) noexcept { return esvc->ErrCode; } - -static inline const char* UpnpStateVarComplete_get_StateVarName_cstr( - const UpnpStateVarComplete* esvc) noexcept { return esvc->StateVarName; } - -#endif // UPNP_VERSION < 10624 diff --git a/libretroshare/src/rs_upnp/upnphandler_libupnp.cc b/libretroshare/src/rs_upnp/upnphandler_libupnp.cc deleted file mode 100644 index 17e096a08..000000000 --- a/libretroshare/src/rs_upnp/upnphandler_libupnp.cc +++ /dev/null @@ -1,466 +0,0 @@ -/******************************************************************************* - * libretroshare/src/upnp: upnphandler_libupnp.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2018 Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} /* extern C */ -#endif -/* This stuff is actually C */ - -#include "rs_upnp/upnphandler_libupnp.h" - -#include "util/rsnet.h" - -bool upnphandler::initUPnPState() -{ - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::initUPnPState" << std::endl; - #endif - cUPnPControlPoint = new CUPnPControlPoint(2000); - - bool IGWDetected = cUPnPControlPoint->GetIGWDeviceDetected(); - - if (IGWDetected) { - /* MODIFY STATE */ - dataMtx.lock(); /* LOCK MUTEX */ - upnpState = RS_UPNP_S_READY; - - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::initUPnPState cUPnPControlPoint internal ip adress : "; - std::cerr << cUPnPControlPoint->getInternalIpAddress() << std::endl; - #endif - - //const char ipaddr = cUPnPControlPoint->getInternalIpAddress().c_str(); - inet_aton(cUPnPControlPoint->getInternalIpAddress(), &(upnp_iaddr.sin_addr)); - upnp_iaddr.sin_port = htons(iport); - - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::initUPnPState READY" << std::endl; - #endif - dataMtx.unlock(); /* UNLOCK MUTEX */ - - } else { - upnpState = RS_UPNP_S_UNAVAILABLE; - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::initUPnPState UNAVAILABLE" << std::endl; - #endif - } - - return 0; -} - -class upnpThreadData -{ - public: - upnphandler *handler; - bool start; - bool stop; -}; - - /* Thread routines */ -extern "C" void* doSetupUPnP(void* p) -{ - #ifdef UPNP_DEBUG - std::cerr << "doSetupUPnP Creating upnp thread." << std::endl; - #endif - upnpThreadData *data = (upnpThreadData *) p; - if ((!data) || (!data->handler)) - { - pthread_exit(NULL); - } - - /* publish it! */ - if (data -> stop) - { - data->handler->shutdown_upnp(); - } - - if (data -> start) - { - data->handler->initUPnPState(); - data->handler->start_upnp(); - } - - delete data; - pthread_exit(NULL); - - return NULL; -} - -bool upnphandler::background_setup_upnp(bool start, bool stop) -{ - pthread_t tid; - - /* launch thread */ - #ifdef UPNP_DEBUG - std::cerr << "background_setup_upnp Creating upnp thread." << std::endl; - #endif - upnpThreadData *data = new upnpThreadData(); - data->handler = this; - data->start = start; - data->stop = stop; - - if(! pthread_create(&tid, 0, &doSetupUPnP, (void *) data)) - { - pthread_detach(tid); /* so memory is reclaimed in linux */ - - return true; - } - else - { - delete data ; - std::cerr << "(EE) Could not start background upnp thread!" << std::endl; - return false ; - } -} - -bool upnphandler::start_upnp() -{ - if (!(upnpState >= RS_UPNP_S_READY)) - { - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::start_upnp() Not Ready" << std::endl; - #endif - return false; - } - - struct sockaddr_in localAddr; - { - RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ - - /* if we're to load -> load */ - /* select external ports */ - eport_curr = eport; - if (!eport_curr) - { - /* use local port if eport is zero */ - eport_curr = iport; - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::start_upnp() Using LocalPort for extPort." << std::endl; - #endif - } - - if (!eport_curr) - { - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::start_upnp() Invalid eport ... " << std::endl; - #endif - return false; - } - - /* our port */ - char in_addr[256]; - char in_port1[256]; - - upnp_iaddr.sin_port = htons(iport); - localAddr = upnp_iaddr; - uint32_t linaddr = ntohl(localAddr.sin_addr.s_addr); - snprintf(in_port1, 256, "%d", ntohs(localAddr.sin_port)); - snprintf(in_addr, 256, "%d.%d.%d.%d", - ((linaddr >> 24) & 0xff), - ((linaddr >> 16) & 0xff), - ((linaddr >> 8) & 0xff), - ((linaddr >> 0) & 0xff)); - - #ifdef UPNP_DEBUG - std::cerr << "Attempting Redirection: InAddr: " << in_addr; - std::cerr << " InPort: " << in_port1; - std::cerr << " ePort: " << eport_curr; - std::cerr << " eProt: " << "TCP and UDP"; - std::cerr << std::endl; - #endif - } - - //first of all, build the mappings - std::vector upnpPortMapping1; - CUPnPPortMapping cUPnPPortMapping1 = CUPnPPortMapping(eport_curr, ntohs(localAddr.sin_port), "TCP", true, "tcp retroshare redirection"); - upnpPortMapping1.push_back(cUPnPPortMapping1); - std::vector upnpPortMapping2; - CUPnPPortMapping cUPnPPortMapping2 = CUPnPPortMapping(eport_curr, ntohs(localAddr.sin_port), "UDP", true, "udp retroshare redirection"); - upnpPortMapping2.push_back(cUPnPPortMapping2); - - //attempt to remove formal port redirection rules - cUPnPControlPoint->DeletePortMappings(upnpPortMapping1); - cUPnPControlPoint->DeletePortMappings(upnpPortMapping2); - - //add new rules - bool res = cUPnPControlPoint->AddPortMappings(upnpPortMapping1); - bool res2 = cUPnPControlPoint->AddPortMappings(upnpPortMapping2); - - struct sockaddr_storage extAddr; - bool extAddrResult = getExternalAddress(extAddr); - - { - RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ - - if (extAddrResult && (res || res2)) { - upnpState = RS_UPNP_S_ACTIVE; - } else { - upnpState = RS_UPNP_S_TCP_AND_FAILED; - } - - toStart = false; - } - - return (upnpState == RS_UPNP_S_ACTIVE); - -} - -bool upnphandler::shutdown_upnp() -{ - RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ - - /* always attempt this (unless no port number) */ - if (eport_curr > 0 && eport > 0 && (upnpState >= RS_UPNP_S_ACTIVE)) - { - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::shutdown_upnp() : Attempting To Remove Redirection: port: " << eport_curr; - std::cerr << " Prot: TCP"; - std::cerr << std::endl; - #endif - - std::vector upnpPortMapping1; - CUPnPPortMapping cUPnPPortMapping1 = CUPnPPortMapping(eport_curr, 0, "TCP", true, "tcp redirection"); - upnpPortMapping1.push_back(cUPnPPortMapping1); - cUPnPControlPoint->DeletePortMappings(upnpPortMapping1); - - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::shutdown_upnp() : Attempting To Remove Redirection: port: " << eport_curr; - std::cerr << " Prot: UDP"; - std::cerr << std::endl; - #endif - - std::vector upnpPortMapping2; - CUPnPPortMapping cUPnPPortMapping2 = CUPnPPortMapping(eport_curr, 0, "UDP", true, "udp redirection"); - upnpPortMapping2.push_back(cUPnPPortMapping2); - cUPnPControlPoint->DeletePortMappings(upnpPortMapping2); - - //destroy the upnp object - cUPnPControlPoint->~CUPnPControlPoint(); - cUPnPControlPoint=NULL ; - } else { - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::shutdown_upnp() : avoid upnp connection for shutdonws because probably a net flag went down." << std::endl; - #endif - } - - //stopping os ok, set starting to true for next net reset - toStop = false; - toStart = true; - upnpState = RS_UPNP_S_UNINITIALISED; - - return true; - -} - -/************************ External Interface ***************************** - * - * - * - */ - -upnphandler::upnphandler() - : - upnpState(RS_UPNP_S_UNINITIALISED), dataMtx("upupState"), - cUPnPControlPoint(NULL), - toEnable(false), toStart(false), toStop(false), - iport(0),eport(0), eport_curr(0) -{ -} - -upnphandler::~upnphandler() -{ - return; -} - - /* RsIface */ -void upnphandler::enable(bool active) -{ - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::enable called with argument active : " << active << std::endl; - std::cerr << "toEnable : " << toEnable << std::endl; - std::cerr << "toStart : " << toStart << std::endl; - #endif - - dataMtx.lock(); /*** LOCK MUTEX ***/ - if (active != toEnable) - { - if (active) - { - toStart = true; - } - else - { - toStop = true; - } - } - toEnable = active; - - bool start = toStart; - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - if (start) - { - /* make background thread to startup UPnP */ - background_setup_upnp(true, false); - } -} - - -void upnphandler::shutdown() -{ - /* blocking call to shutdown upnp */ - - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::shutdown() called." << std::endl; - #endif - shutdown_upnp(); -} - - -void upnphandler::restart() -{ - /* non-blocking call to shutdown upnp, and startup again. */ - #ifdef UPNP_DEBUG - std::cerr << "upnphandler::restart() called." << std::endl; - #endif - background_setup_upnp(true, true); -} - - - -bool upnphandler::getEnabled() -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - - bool on = toEnable; - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - return on; -} - -bool upnphandler::getActive() -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - - #ifdef UPNP_DEBUG - std::cerr <<"upnphandler::getActive() result : " << (upnpState == RS_UPNP_S_ACTIVE) << std::endl; - #endif - - bool on = (upnpState == RS_UPNP_S_ACTIVE); - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - return on; -} - - /* the address that the listening port is on */ -void upnphandler::setInternalPort(unsigned short iport_in) -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - if (iport != iport_in) - { - iport = iport_in; - if ((toEnable) && - (upnpState == RS_UPNP_S_ACTIVE)) - { - toStop = true; - toStart = true; - } - } - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ -} - -void upnphandler::setExternalPort(unsigned short eport_in) -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - /* flag both shutdown/start -> for restart */ - if (eport != eport_in) - { - eport = eport_in; - if ((toEnable) && - (upnpState == RS_UPNP_S_ACTIVE)) - { - toStop = true; - toStart = true; - } - } - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ -} - - /* as determined by uPnP */ -bool upnphandler::getInternalAddress(struct sockaddr_storage &addr) -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - - bool valid = (upnpState >= RS_UPNP_S_ACTIVE); - - // copy to universal addr. - sockaddr_storage_clear(addr); - sockaddr_storage_setipv4(addr, &upnp_iaddr); - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - return valid; -} - -bool upnphandler::getExternalAddress(struct sockaddr_storage &addr) -{ - std::string externalAdress = cUPnPControlPoint->getExternalAddress(); - - if(!externalAdress.empty() && externalAdress != "") - { - const char* externalIPAddress = externalAdress.c_str(); - - #ifdef UPNP_DEBUG - std::cerr << " upnphandler::getExternalAddress() : " << externalIPAddress; - std::cerr << ":" << eport_curr; - std::cerr << std::endl; - #endif - - dataMtx.lock(); /*** LOCK MUTEX ***/ - sockaddr_clear(&upnp_eaddr); - inet_aton(externalIPAddress, &(upnp_eaddr.sin_addr)); - upnp_eaddr.sin_family = AF_INET; - upnp_eaddr.sin_port = htons(eport_curr); - - // copy to universal addr. - sockaddr_storage_clear(addr); - sockaddr_storage_setipv4(addr, &upnp_eaddr); - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - return true; - } - else - { - return false; - } -} - - - diff --git a/libretroshare/src/rs_upnp/upnphandler_libupnp.h b/libretroshare/src/rs_upnp/upnphandler_libupnp.h deleted file mode 100644 index bc04d6d36..000000000 --- a/libretroshare/src/rs_upnp/upnphandler_libupnp.h +++ /dev/null @@ -1,100 +0,0 @@ -/******************************************************************************* - * libretroshare/src/upnp: upnphandler_libupnp.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2018 Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include - -/* platform independent networking... */ -#include "pqi/pqinetwork.h" -#include "pqi/pqiassist.h" - -#include "util/rsthreads.h" - -#include -#include "rs_upnp/UPnPBase.h" - -#define RS_UPNP_S_UNINITIALISED 0 -#define RS_UPNP_S_UNAVAILABLE 1 -#define RS_UPNP_S_READY 2 -#define RS_UPNP_S_TCP_AND_FAILED 3 -//#define RS_UPNP_S_UDP_FAILED 4 -#define RS_UPNP_S_ACTIVE 5 - -class upnphandler: public pqiNetAssistFirewall -{ - public: - - upnphandler(); - virtual ~upnphandler(); - - /* External Interface (pqiNetAssistFirewall) */ - virtual void enable(bool active); - virtual void shutdown(); - virtual void restart(); - - virtual bool getEnabled(); - virtual bool getActive(); - - virtual void setInternalPort(unsigned short iport_in); - virtual void setExternalPort(unsigned short eport_in); - virtual bool getInternalAddress(struct sockaddr_storage &addr); - virtual bool getExternalAddress(struct sockaddr_storage &addr); - - /* TO IMPLEMENT: New Port Forward interface to support as many ports as necessary */ - virtual bool requestPortForward(const PortForwardParams & /* params */) { return false; } - virtual bool statusPortForward(const uint32_t /* fwdId */, PortForwardParams & /*params*/) { return false; } - - /* Public functions - for background thread operation, - * but effectively private from rest of RS, as in derived class - */ - unsigned int upnpState; - - bool start_upnp(); - bool shutdown_upnp(); - - bool initUPnPState(); - - /* Mutex for data below */ - RsMutex dataMtx; - - private: - - CUPnPControlPoint *cUPnPControlPoint; - - bool background_setup_upnp(bool, bool); - - - bool toEnable; /* overall on/off switch */ - bool toStart; /* if set start forwarding */ - bool toStop; /* if set stop forwarding */ - - unsigned short iport; - unsigned short eport; /* config */ - unsigned short eport_curr; /* current forwarded */ - - /* info from upnp */ - struct sockaddr_in upnp_iaddr; - struct sockaddr_in upnp_eaddr; -}; - -/* info from upnp */ -int CtrlPointCallbackEventHandler(Upnp_EventType ,void* , void*); diff --git a/libretroshare/src/rs_upnp/upnphandler_miniupnp.cc b/libretroshare/src/rs_upnp/upnphandler_miniupnp.cc deleted file mode 100644 index ca21804af..000000000 --- a/libretroshare/src/rs_upnp/upnphandler_miniupnp.cc +++ /dev/null @@ -1,677 +0,0 @@ -/******************************************************************************* - * libretroshare/src/upnp: upnphandler_miniupnp.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2018 Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -// Windows / Mac version. -/* This stuff is actually C */ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} /* extern C */ -#endif -/* This stuff is actually C */ - -#include "rs_upnp/upnphandler_miniupnp.h" -#include "rs_upnp/upnputil.h" - -class uPnPConfigData -{ - public: - struct UPNPDev * devlist; - struct UPNPUrls urls; - struct IGDdatas data; - char lanaddr[16]; /* my ip address on the LAN */ -}; - -#include - -#include "util/rsnet.h" - -bool upnphandler::initUPnPState() -{ - /* allocate memory */ - uPnPConfigData *upcd = new uPnPConfigData; -#if MINIUPNPC_API_VERSION >= 14 //1.9 2015/07/23 - /* $Id: miniupnpc.h,v 1.44 2015/07/23 20:40:10 nanard Exp $ */ - //upnpDiscover(int delay, const char * multicastif, - // const char * minissdpdsock, int sameport, - // int ipv6, unsigned char ttl, - // int * error); - unsigned char ttl = 2; /* defaulting to 2 */ - upcd->devlist = upnpDiscover(2000, NULL, - NULL, 0, - 0, ttl, - NULL); -#else -#if MINIUPNPC_API_VERSION >= 8 //1.5 2011/04/18 - /* $Id: miniupnpc.h,v 1.41 2015/05/22 10:23:48 nanard Exp $ */ - /* $Id: miniupnpc.h,v 1.23 2011/04/11 08:21:46 nanard Exp $ */ - //upnpDiscover(int delay, const char * multicastif, - // const char * minissdpdsock, int sameport, - // int ipv6, - // int * error); - upcd->devlist = upnpDiscover(2000, NULL, - NULL, 0, - 0, - NULL); -#else -#if MINIUPNPC_API_VERSION >= 6//1.5 2011/03/14 - /* $Id: miniupnpc.h,v 1.21 2011/03/14 13:37:12 nanard Exp $ */ - //upnpDiscover(int delay, const char * multicastif, - // const char * minissdpdsock, int sameport, - // int * error); - upcd->devlist = upnpDiscover(2000, NULL, - NULL, 0, - NULL); -#else -#if MINIUPNPC_API_VERSION >= -4//1.1 2008/09/25 - /* $Id: miniupnpc.h,v 1.20 2011/02/07 16:46:05 nanard Exp $ */ - /* $Id: miniupnpc.h,v 1.18 2008/09/25 18:02:50 nanard Exp $ */ - //upnpDiscover(int delay, const char * multicastif, - // const char * minissdpdsock, int sameport); - upcd->devlist = upnpDiscover(2000, NULL, - NULL, 0); -#else -#if MINIUPNPC_API_VERSION >= -5//1.0 2007/12/19 - /* $Id: miniupnpc.h,v 1.17 2007/12/19 14:58:54 nanard Exp $ */ - //upnpDiscover(int delay, const char * multicastif, - // const char * minissdpdsock); - upcd->devlist = upnpDiscover(2000, NULL, - NULL); -#else -#if MINIUPNPC_API_VERSION >= -6//1.0 2007/10/16 - /* $Id: miniupnpc.h,v 1.15 2007/10/16 15:07:32 nanard Exp $ */ - //LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif); - upcd->devlist = upnpDiscover(2000, NULL); -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - /* $Id: miniupnpc.h,v 1.14 2007/10/01 13:42:52 nanard Exp $ */ - /* $Id: miniupnpc.h,v 1.9 2006/09/04 09:30:17 nanard Exp $ */ - //struct UPNPDev * upnpDiscover(int); - upcd->devlist = upnpDiscover(2000); -#else -#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version - //2006/09/04 to 2007/10/01 => -7//Start return struct UPNPDev * for upnpDiscover - //2007/10/16 => -6 upnpDiscover - //2007/12/19 => -5 upnpDiscover - //2008/09/25 => -4 upnpDiscover - //2009/04/17 => -3 UPNP_AddPortMapping - //2010/12/09 => -2 //struct IGDdatas_service CIF; - //2011/02/15 => -1 UPNP_AddPortMapping - //2011/03/14 => 6 //Start of MINIUPNPC_API_VERSION -#endif//>=-7 -#endif//>=-6 -#endif//>=-5 -#endif//>=-4 -#endif//>=6 -#endif//>=8 -#endif//>=14 - - if(upcd->devlist) - { - struct UPNPDev * device; - printf("List of UPNP devices found on the network :\n"); - for(device=upcd->devlist;device;device=device->pNext) - { - printf("\n desc: %s\n st: %s\n", - device->descURL, device->st); - } - putchar('\n'); - if(UPNP_GetValidIGD(upcd->devlist, &(upcd->urls), - &(upcd->data), upcd->lanaddr, - sizeof(upcd->lanaddr))) - { - printf("Found valid IGD : %s\n", - upcd->urls.controlURL); - printf("Local LAN ip address : %s\n", - upcd->lanaddr); - - /* MODIFY STATE */ - dataMtx.lock(); /* LOCK MUTEX */ - - /* convert to ipaddress. */ - inet_aton(upcd->lanaddr, &(upnp_iaddr.sin_addr)); - upnp_iaddr.sin_port = htons(iport); - - upnpState = RS_UPNP_S_READY; - if (upnpConfig) - { - delete upnpConfig; - } - upnpConfig = upcd; /* */ - - dataMtx.unlock(); /* UNLOCK MUTEX */ - - - /* done -> READY */ - return 1; - - } - else - { - fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n"); - } - - - freeUPNPDevlist(upcd->devlist); - upcd->devlist = 0; - } - else - { - fprintf(stderr, "No IGD UPnP Device found on the network !\n"); - } - - /* MODIFY STATE */ - dataMtx.lock(); /* LOCK MUTEX */ - - upnpState = RS_UPNP_S_UNAVAILABLE; - delete upcd; - upnpConfig = NULL; - - dataMtx.unlock(); /* UNLOCK MUTEX */ - - /* done, FAILED -> NOT AVAILABLE */ - - return 0; -} - -bool upnphandler::printUPnPState() -{ - std::cerr << "upnphandler::printUPnPState() ... locking"; - std::cerr << std::endl; - - RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ - - std::cerr << "upnphandler::printUPnPState() ... locked"; - std::cerr << std::endl; - - uPnPConfigData *config = upnpConfig; - if ((upnpState >= RS_UPNP_S_READY) && (config)) - { - DisplayInfos(&(config -> urls), &(config->data)); - GetConnectionStatus(&(config -> urls), &(config->data)); - ListRedirections(&(config -> urls), &(config->data)); - } - else - { - std::cerr << "UPNP not Ready" << std::endl; - } - - return 1; -} - - -bool upnphandler::checkUPnPActive() -{ - RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ - - uPnPConfigData *config = upnpConfig; - if ((upnpState > RS_UPNP_S_READY) && (config)) - { - char eprot1[] = "TCP"; - char eprot2[] = "UDP"; - - char in_addr[256]; - char in_port1[256]; - char in_port2[256]; - char eport1[256]; - char eport2[256]; - - struct sockaddr_in localAddr = upnp_iaddr; - uint32_t linaddr = ntohl(localAddr.sin_addr.s_addr); - - snprintf(in_port1, 256, "%d", ntohs(localAddr.sin_port)); - snprintf(in_port2, 256, "%d", ntohs(localAddr.sin_port)); - - snprintf(in_addr, 256, "%d.%d.%d.%d", - ((linaddr >> 24) & 0xff), - ((linaddr >> 16) & 0xff), - ((linaddr >> 8) & 0xff), - ((linaddr >> 0) & 0xff)); - - snprintf(eport1, 256, "%d", eport_curr); - snprintf(eport2, 256, "%d", eport_curr); - - std::cerr << "upnphandler::checkUPnPState()"; - std::cerr << " Checking Redirection: InAddr: " << in_addr; - std::cerr << " InPort: " << in_port1; - std::cerr << " ePort: " << eport1; - std::cerr << " eProt: " << eprot1; - std::cerr << std::endl; - - - bool tcpOk = TestRedirect(&(config -> urls), &(config->data), - in_addr, in_port1, eport1, eprot1); - bool udpOk = TestRedirect(&(config -> urls), &(config->data), - in_addr, in_port2, eport2, eprot2); - - if ((!tcpOk) || (!udpOk)) - { - std::cerr << "upnphandler::checkUPnPState() ... Redirect Expired, restarting"; - std::cerr << std::endl; - - toStop = true; - toStart = true; - } - } - - return true; -} - -class upnpThreadData -{ - public: - upnphandler *handler; - bool start; - bool stop; -}; - - /* Thread routines */ -extern "C" void* doSetupUPnP(void* p) -{ - upnpThreadData *data = (upnpThreadData *) p; - if ((!data) || (!data->handler)) - { - pthread_exit(NULL); - } - - /* publish it! */ - if (data -> stop) - { - data->handler->shutdown_upnp(); - } - - if (data -> start) - { - data->handler->initUPnPState(); - data->handler->start_upnp(); - } - - data->handler->printUPnPState(); - - delete data; - pthread_exit(NULL); - - return NULL; -} - -bool upnphandler::background_setup_upnp(bool start, bool stop) -{ - pthread_t tid; - - /* launch thread */ - upnpThreadData *data = new upnpThreadData(); - data->handler = this; - data->start = start; - data->stop = stop; - - if(!pthread_create(&tid, 0, &doSetupUPnP, (void *) data)) - { - pthread_detach(tid); /* so memory is reclaimed in linux */ - return true; - } - else - { - delete data ; - std::cerr << "(EE) Failed to start upnp thread." << std::endl; - return false ; - } -} - -bool upnphandler::start_upnp() -{ - RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ - - uPnPConfigData *config = upnpConfig; - if (!((upnpState >= RS_UPNP_S_READY) && (config))) - { - std::cerr << "upnphandler::start_upnp() Not Ready"; - std::cerr << std::endl; - return false; - } - - char eprot1[] = "TCP"; - char eprot2[] = "UDP"; - - /* if we're to load -> load */ - /* select external ports */ - eport_curr = eport; - if (!eport_curr) - { - /* use local port if eport is zero */ - eport_curr = iport; - std::cerr << "Using LocalPort for extPort!"; - std::cerr << std::endl; - } - - if (!eport_curr) - { - std::cerr << "Invalid eport ... "; - std::cerr << std::endl; - return false; - } - - - /* our port */ - char in_addr[256]; - char in_port1[256]; - char in_port2[256]; - char eport1[256]; - char eport2[256]; - - upnp_iaddr.sin_port = htons(iport); - struct sockaddr_in localAddr = upnp_iaddr; - uint32_t linaddr = ntohl(localAddr.sin_addr.s_addr); - - snprintf(in_port1, 256, "%d", ntohs(localAddr.sin_port)); - snprintf(in_port2, 256, "%d", ntohs(localAddr.sin_port)); - snprintf(in_addr, 256, "%d.%d.%d.%d", - ((linaddr >> 24) & 0xff), - ((linaddr >> 16) & 0xff), - ((linaddr >> 8) & 0xff), - ((linaddr >> 0) & 0xff)); - - snprintf(eport1, 256, "%d", eport_curr); - snprintf(eport2, 256, "%d", eport_curr); - - std::cerr << "Attempting Redirection: InAddr: " << in_addr; - std::cerr << " InPort: " << in_port1; - std::cerr << " ePort: " << eport1; - std::cerr << " eProt: " << eprot1; - std::cerr << std::endl; - - if (!SetRedirectAndTest(&(config -> urls), &(config->data), - in_addr, in_port1, eport1, eprot1, - NULL /*leaseDuration*/, "RetroShare_TCP" /*description*/, - 0)) - { - upnpState = RS_UPNP_S_TCP_FAILED; - } - else if (!SetRedirectAndTest(&(config -> urls), &(config->data), - in_addr, in_port2, eport2, eprot2, - NULL /*leaseDuration*/, "RetroShare_UDP" /*description*/, - 0)) - { - upnpState = RS_UPNP_S_UDP_FAILED; - } - else - { - upnpState = RS_UPNP_S_ACTIVE; - } - - - /* now store the external address */ - char externalIPAddress[32]; - UPNP_GetExternalIPAddress(config -> urls.controlURL, -#if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09 - config->data.first.servicetype, -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - config->data.servicetype, -#else -#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version -#endif -#endif - externalIPAddress); - - sockaddr_clear(&upnp_eaddr); - - if(externalIPAddress[0]) - { - std::cerr << "Stored External address: " << externalIPAddress; - std::cerr << ":" << eport_curr; - std::cerr << std::endl; - - inet_aton(externalIPAddress, &(upnp_eaddr.sin_addr)); - upnp_eaddr.sin_family = AF_INET; - upnp_eaddr.sin_port = htons(eport_curr); - } - else - { - std::cerr << "FAILED To get external Address"; - std::cerr << std::endl; - } - - toStart = false; - - return true; - -} - -bool upnphandler::shutdown_upnp() -{ - RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ - - uPnPConfigData *config = upnpConfig; - if (!((upnpState >= RS_UPNP_S_READY) && (config))) - { - return false; - } - - char eprot1[] = "TCP"; - char eprot2[] = "UDP"; - - /* always attempt this (unless no port number) */ - if (eport_curr > 0) - { - - char eport1[256]; - char eport2[256]; - - snprintf(eport1, 256, "%d", eport_curr); - snprintf(eport2, 256, "%d", eport_curr); - - std::cerr << "Attempting To Remove Redirection: port: " << eport1; - std::cerr << " Prot: " << eprot1; - std::cerr << std::endl; - - RemoveRedirect(&(config -> urls), &(config->data), - eport1, eprot1); - - - std::cerr << "Attempting To Remove Redirection: port: " << eport2; - std::cerr << " Prot: " << eprot2; - std::cerr << std::endl; - - RemoveRedirect(&(config -> urls), &(config->data), - eport2, eprot2); - - upnpState = RS_UPNP_S_READY; - toStop = false; - } - - return true; - -} - -/************************ External Interface ***************************** - * - * - * - */ - - -upnphandler::upnphandler() - : dataMtx("upnpState"), toEnable(false), toStart(false), toStop(false), - eport(0), eport_curr(0), - upnpState(RS_UPNP_S_UNINITIALISED), - upnpConfig(NULL) -{ - return; -} - -upnphandler::~upnphandler() -{ - return; -} - - /* RsIface */ -void upnphandler::enable(bool active) -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - - if (active != toEnable) - { - if (active) - { - toStart = true; - } - else - { - toStop = true; - } - } - toEnable = active; - - bool start = toStart; - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - if (start) - { - /* make background thread to startup UPnP */ - background_setup_upnp(true, false); - } - - -} - - -void upnphandler::shutdown() -{ - /* blocking call to shutdown upnp */ - - shutdown_upnp(); -} - - -void upnphandler::restart() -{ - /* non-blocking call to shutdown upnp, and startup again. */ - background_setup_upnp(true, true); -} - - - -bool upnphandler::getEnabled() -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - - bool on = toEnable; - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - return on; -} - -bool upnphandler::getActive() -{ - dataMtx.lock(); /*** LOCK MUTEX ***/ - - bool on = (upnpState == RS_UPNP_S_ACTIVE); - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ - - return on; -} - - /* the address that the listening port is on */ -void upnphandler::setInternalPort(unsigned short iport_in) -{ -// std::cerr << "UPnPHandler::setInternalAddress() pre Lock!" << std::endl; - dataMtx.lock(); /*** LOCK MUTEX ***/ -// std::cerr << "UPnPHandler::setInternalAddress() postLock!" << std::endl; - - std::cerr << "UPnPHandler::setInternalPort(" << iport_in << ") current port: "; - std::cerr << iport << std::endl; - - if (iport != iport_in) - { - iport = iport_in; - if ((toEnable) && - (upnpState == RS_UPNP_S_ACTIVE)) - { - toStop = true; - toStart = true; - } - } - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ -} - -void upnphandler::setExternalPort(unsigned short eport_in) -{ -// std::cerr << "UPnPHandler::getExternalPort() pre Lock!" << std::endl; - dataMtx.lock(); /*** LOCK MUTEX ***/ -// std::cerr << "UPnPHandler::getExternalPort() postLock!" << std::endl; - - std::cerr << "UPnPHandler::setExternalPort(" << eport_in << ") current port: "; - std::cerr << eport << std::endl; - - /* flag both shutdown/start -> for restart */ - if (eport != eport_in) - { - eport = eport_in; - if ((toEnable) && - (upnpState == RS_UPNP_S_ACTIVE)) - { - toStop = true; - toStart = true; - } - } - - dataMtx.unlock(); /*** UNLOCK MUTEX ***/ -} - -/* as determined by uPnP */ -bool upnphandler::getInternalAddress(struct sockaddr_storage &addr) -{ - RS_STACK_MUTEX(dataMtx); - - // copy to universal addr. - sockaddr_storage_clear(addr); - sockaddr_storage_setipv4(addr, &upnp_iaddr); - - bool valid = (upnpState >= RS_UPNP_S_ACTIVE); - - Dbg2() << __PRETTY_FUNCTION__ << " valid: " << valid - << " addr: " << addr << std::endl; - - return valid; -} - -bool upnphandler::getExternalAddress(sockaddr_storage &addr) -{ - RS_STACK_MUTEX(dataMtx); - - // copy to universal addr. - sockaddr_storage_clear(addr); - sockaddr_storage_setipv4(addr, &upnp_eaddr); - - bool valid = (upnpState == RS_UPNP_S_ACTIVE); - - Dbg2() << __PRETTY_FUNCTION__ << " valid: " << valid - << " addr: " << addr << std::endl; - - return valid; -} - diff --git a/libretroshare/src/rs_upnp/upnphandler_miniupnp.h b/libretroshare/src/rs_upnp/upnphandler_miniupnp.h deleted file mode 100644 index 9449661e0..000000000 --- a/libretroshare/src/rs_upnp/upnphandler_miniupnp.h +++ /dev/null @@ -1,127 +0,0 @@ -/******************************************************************************* - * libretroshare/src/upnp: upnphandler_miniupnp.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2018 Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include - -/* platform independent networking... */ -#include "pqi/pqinetwork.h" -#include "pqi/pqiassist.h" -#include "util/rsdebug.h" -#include "util/rsthreads.h" - -class upnpentry -{ - public: - std::string name; - std::string id; - struct sockaddr_in addr; - unsigned int flags; - int status; - int lastTs; -}; - -class upnpforward -{ - public: - std::string name; - unsigned int flags; - struct sockaddr_in iaddr; - struct sockaddr_in eaddr; - int status; - int lastTs; -}; - - -#define RS_UPNP_S_UNINITIALISED 0 -#define RS_UPNP_S_UNAVAILABLE 1 -#define RS_UPNP_S_READY 2 -#define RS_UPNP_S_TCP_FAILED 3 -#define RS_UPNP_S_UDP_FAILED 4 -#define RS_UPNP_S_ACTIVE 5 - -class uPnPConfigData; - -class upnphandler: public pqiNetAssistFirewall -{ - public: - - upnphandler(); -virtual ~upnphandler(); - - /* External Interface (pqiNetAssistFirewall) */ -virtual void enable(bool active); -virtual void shutdown(); -virtual void restart(); - -virtual bool getEnabled(); -virtual bool getActive(); - -virtual void setInternalPort(unsigned short iport_in); -virtual void setExternalPort(unsigned short eport_in); -virtual bool getInternalAddress(struct sockaddr_storage &addr); -virtual bool getExternalAddress(struct sockaddr_storage &addr); - - /* TO IMPLEMENT: New Port Forward interface to support as many ports as necessary */ -virtual bool requestPortForward(const PortForwardParams &/*params*/) { return false; } -virtual bool statusPortForward(const uint32_t /*fwdId*/, PortForwardParams &/*params*/) { return false; } - -/* Public functions - for background thread operation, - * but effectively private from rest of RS, as in derived class - */ - -bool start_upnp(); -bool shutdown_upnp(); - -bool initUPnPState(); -bool printUPnPState(); - -private: - -bool background_setup_upnp(bool, bool); -bool checkUPnPActive(); - - /* Mutex for data below */ - RsMutex dataMtx; - - bool toEnable; /* overall on/off switch */ - bool toStart; /* if set start forwarding */ - bool toStop; /* if set stop forwarding */ - - unsigned short iport; - unsigned short eport; /* config */ - unsigned short eport_curr; /* current forwarded */ - - /* info from upnp */ - unsigned int upnpState; - uPnPConfigData *upnpConfig; - - struct sockaddr_in upnp_iaddr; - struct sockaddr_in upnp_eaddr; - - /* active port forwarding */ - std::list activeForwards; - - RS_SET_CONTEXT_DEBUG_LEVEL(1) -}; diff --git a/libretroshare/src/rs_upnp/upnptest.cc b/libretroshare/src/rs_upnp/upnptest.cc deleted file mode 100644 index 80d98e4e5..000000000 --- a/libretroshare/src/rs_upnp/upnptest.cc +++ /dev/null @@ -1,86 +0,0 @@ -//this file use miniupnp - -#include - - -int main(int argc, char **argv) -{ - - int id = argc % 3; - - /********* - char *fhash1 = "3509426505463458576487"; - char *hash2 = "1549879882341985914515"; - char *hash3 = "8743598543269526505434"; - - int port1 = 8754; - int port2 = 2355; - int port3 = 6621; - **********/ - - std::cerr << "Starting dhttest Id: " << id << std::endl; -/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#else - // Windows Networking Init. - WORD wVerReq = MAKEWORD(2,2); - WSADATA wsaData; - - if (0 != WSAStartup(wVerReq, &wsaData)) - { - std::cerr << "Failed to Startup Windows Networking"; - std::cerr << std::endl; - } - else - { - std::cerr << "Started Windows Networking"; - std::cerr << std::endl; - } - -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - #ifdef PTW32_STATIC_LIB - pthread_win32_process_attach_np(); - #endif - - - upnphandler upnp; - - upnp.setInternalPort(12122); - - for(int i = 0; 1; i++) - { - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - sleep(1); -#else - - Sleep(1000); -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - if (i % 120 == 10) - { - /* start up a forward */ - upnp.enable(true); - - } - - if (i % 120 == 60) - { - /* shutdown a forward */ - upnp.restart(); - } - - if (i % 120 == 100) - { - /* shutdown a forward */ - upnp.shutdown(); - } - - } -} - diff --git a/libretroshare/src/rs_upnp/upnputil.cc b/libretroshare/src/rs_upnp/upnputil.cc deleted file mode 100644 index 28b0c4de6..000000000 --- a/libretroshare/src/rs_upnp/upnputil.cc +++ /dev/null @@ -1,611 +0,0 @@ -/******************************************************************************* - * libretroshare/src/upnp: upnputil.c * - * * - * libretroshare: retroshare core library * - * From MiniUPnPc, re-licensed with permission * - * * - * Copyright (c) 2005-2016, Thomas BERNARD * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -//this file uses miniupnp -//From https://github.com/miniupnp/miniupnp/blob/master/miniupnpc/upnpc.c - -#include "rs_upnp/upnputil.h" - -#if MINIUPNPC_API_VERSION >= -4//1.0 2008/02/18 -#include "util/rstime.h" -#endif - -/* protofix() checks if protocol is "UDP" or "TCP" - * returns NULL if not */ -const char * protofix(const char * proto) -{ - static const char proto_tcp[4] = { 'T', 'C', 'P', 0}; - static const char proto_udp[4] = { 'U', 'D', 'P', 0}; - int i, b; - for(i=0, b=1; i<4; i++) - b = b && ( (proto[i] == proto_tcp[i]) - || (proto[i] == (proto_tcp[i] | 32)) ); - if(b) - return proto_tcp; - for(i=0, b=1; i<4; i++) - b = b && ( (proto[i] == proto_udp[i]) - || (proto[i] == (proto_udp[i] | 32)) ); - if(b) - return proto_udp; - return 0; -} - -void DisplayInfos(struct UPNPUrls * urls, - struct IGDdatas * data) -{ - char externalIPAddress[40]; - char connectionType[64]; - char status[64]; - char lastconnerr[64]; - unsigned int uptime; - unsigned int brUp, brDown; - time_t timenow, timestarted; // Don't use rstime_t here or ctime break on windows - int r; -#if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09 - const char * servicetype = data->first.servicetype; - const char * servicetype_CIF = data->CIF.servicetype; -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - const char * servicetype = data->servicetype; - const char * servicetype_CIF = data->servicetype_CIF; -#else -#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version -#endif//>=-7 -#endif//>=-2 - -#if MINIUPNPC_API_VERSION >= -3//1.0 2009/04/17 - if(UPNP_GetConnectionTypeInfo(urls->controlURL, - servicetype, - connectionType) != UPNPCOMMAND_SUCCESS) -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - UPNP_GetConnectionTypeInfo(urls->controlURL, servicetype, - connectionType); - if(connectionType[0]) -#endif//>=-7 -#endif//>=-3 - printf("GetConnectionTypeInfo failed.\n"); - else - printf("Connection Type : %s\n", connectionType); - -#if MINIUPNPC_API_VERSION >= -4//1.0 2008/02/18 - if(UPNP_GetStatusInfo(urls->controlURL, servicetype, - status, &uptime, lastconnerr) != UPNPCOMMAND_SUCCESS) - printf("GetStatusInfo failed.\n"); - else - printf("Status : %s, uptime=%us, LastConnectionError : %s\n", - status, uptime, lastconnerr); - timenow = time(NULL); - timestarted = timenow - uptime; - printf(" Time started : %s", ctime(×tarted)); -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - UPNP_GetStatusInfo(urls->controlURL, servicetype, - status, &uptime, lastconnerr); - printf("Status : %s, uptime=%u, LastConnectionError : %s\n", - status, uptime, lastconnerr); -#endif//>=-7 -#endif//>=-4 - -#if MINIUPNPC_API_VERSION >= -4//1.0 2008/02/18 - if(UPNP_GetLinkLayerMaxBitRates(urls->controlURL_CIF, servicetype_CIF, - &brDown, &brUp) != UPNPCOMMAND_SUCCESS) { - printf("GetLinkLayerMaxBitRates failed.\n"); - } else { - printf("MaxBitRateDown : %u bps", brDown); - if(brDown >= 1000000) { - printf(" (%u.%u Mbps)", brDown / 1000000, (brDown / 100000) % 10); - } else if(brDown >= 1000) { - printf(" (%u Kbps)", brDown / 1000); - } - printf(" MaxBitRateUp %u bps", brUp); - if(brUp >= 1000000) { - printf(" (%u.%u Mbps)", brUp / 1000000, (brUp / 100000) % 10); - } else if(brUp >= 1000) { - printf(" (%u Kbps)", brUp / 1000); - } - printf("\n"); - } -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - UPNP_GetLinkLayerMaxBitRates(urls->controlURL_CIF, - servicetype_CIF, - &brDown, &brUp); - printf("MaxBitRateDown : %u bps MaxBitRateUp %u bps\n", brDown, brUp); -#endif//>=-7 -#endif//>=-4 - -#if MINIUPNPC_API_VERSION >= -5//1.0 2007/12/19 - r = UPNP_GetExternalIPAddress(urls->controlURL, - servicetype, - externalIPAddress); - if(r != UPNPCOMMAND_SUCCESS) { - printf("GetExternalIPAddress failed. (errorcode=%d)\n", r); - } else { - printf("ExternalIPAddress = %s\n", externalIPAddress); - } -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - UPNP_GetExternalIPAddress(urls->controlURL, - servicetype, - externalIPAddress); - if(externalIPAddress[0]) - printf("ExternalIPAddress = %s\n", externalIPAddress); - else - printf("GetExternalIPAddress failed.\n"); -#endif//>=-7 -#endif//>=-4 -} - -void GetConnectionStatus(struct UPNPUrls * urls, - struct IGDdatas * data) -{ - unsigned int bytessent, bytesreceived, packetsreceived, packetssent; -#if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09 - const char * servicetype_CIF = data->CIF.servicetype; -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - const char * servicetype_CIF = data->servicetype_CIF; -#else -#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version -#endif//>=-7 -#endif//>=-2 - - DisplayInfos(urls, data); - bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, servicetype_CIF); - bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, servicetype_CIF); - packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, servicetype_CIF); - packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, servicetype_CIF); - printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived); - printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived); -} - -void ListRedirections(struct UPNPUrls * urls, - struct IGDdatas * data) -{ - int r; - int i = 0; - char index[6]; - char intClient[40]; - char intPort[6]; - char extPort[6]; - char protocol[4]; - char desc[80]; - char enabled[6]; - char rHost[64]; - char duration[16]; -#if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09 - const char * servicetype = data->first.servicetype; -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - const char * servicetype = data->servicetype; -#else -#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version -#endif//>=-7 -#endif//>=-2 - - /*unsigned int num=0; - UPNP_GetPortMappingNumberOfEntries(urls->controlURL, data->servicetype, &num); - printf("PortMappingNumberOfEntries : %u\n", num);*/ - do { - snprintf(index, 6, "%d", i); - rHost[0] = '\0'; enabled[0] = '\0'; - duration[0] = '\0'; desc[0] = '\0'; - extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0'; - r = UPNP_GetGenericPortMappingEntry(urls->controlURL, - servicetype, - index, - extPort, intClient, intPort, - protocol, desc, enabled, - rHost, duration); - if(r==0) - printf("%02d - %s %5s->%s:%-5s" - "\tenabled=%s leaseDuration=%s\n" - " desc='%s' rHost='%s'\n", - i, protocol, extPort, intClient, intPort, - enabled, duration, - desc, rHost); - else - printf("GetGenericPortMappingEntry() returned %d (%s)\n", - r, strupnperror(r)); - i++; - } while(r==0); -} - -/* Test function - * 1 - get connection type - * 2 - get extenal ip address - * 3 - Add port mapping - * 4 - get this port mapping from the IGD */ -int SetRedirectAndTest(struct UPNPUrls * urls, - struct IGDdatas * data, - const char * iaddr, - const char * iport, - const char * eport, - const char * proto, - const char * leaseDuration, - const char * description, - int addAny) -{ - char externalIPAddress[40]; - char intClient[40]; - char intPort[6]; - char reservedPort[6]; - char duration[16]; - int r; - int ok = 1; -#if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09 - const char * servicetype = data->first.servicetype; -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - const char * servicetype = data->servicetype; -#else -#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version -#endif -#endif - - if(!iaddr || !iport || !eport || !proto) - { - fprintf(stderr, "Wrong arguments\n"); - return 0; - } - proto = protofix(proto); - if(!proto) - { - fprintf(stderr, "invalid protocol\n"); - return 0; - } - -#if MINIUPNPC_API_VERSION >= -5//1.0 2007/12/19 - r = UPNP_GetExternalIPAddress(urls->controlURL, - servicetype, - externalIPAddress); - if(r != UPNPCOMMAND_SUCCESS) - printf("GetExternalIPAddress failed. (errorcode=%d)\n", r); - else - printf("ExternalIPAddress = %s\n", externalIPAddress); -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - UPNP_GetExternalIPAddress(urls->controlURL, - servicetype, - externalIPAddress); - if(externalIPAddress[0]) - printf("ExternalIPAddress = %s\n", externalIPAddress); - else - printf("GetExternalIPAddress failed.\n"); -#endif//>=-7 -#endif//>=-4 - -#if MINIUPNPC_API_VERSION >= 11 - if (addAny) { - r = UPNP_AddAnyPortMapping(urls->controlURL, data->first.servicetype, - eport, iport, iaddr, description, - proto, 0, leaseDuration, reservedPort); - if(r==UPNPCOMMAND_SUCCESS) - eport = reservedPort; - else - printf("AddAnyPortMapping(%s, %s, %s) failed with code %d (%s)\n", - eport, iport, iaddr, r, strupnperror(r)); - } else -#endif - { -#if MINIUPNPC_API_VERSION >= -1 - /* $Id: upnpcommands.h,v 1.30 2015/07/15 12:21:28 nanard Exp $ */ - /* $Id: upnpcommands.h,v 1.20 2011/02/15 11:13:22 nanard Exp $ */ - //UPNP_AddPortMapping(const char * controlURL, const char * servicetype, - // const char * extPort, - // const char * inPort, - // const char * inClient, - // const char * desc, - // const char * proto, - // const char * remoteHost, - // const char * leaseDuration); - r = UPNP_AddPortMapping(urls->controlURL, servicetype, - eport, iport, iaddr, description, proto, NULL, NULL); -#else -#if MINIUPNPC_API_VERSION >= -3 //1.0 2009/04/17 - /* $Id: upnpcommands.h,v 1.18 2010/06/09 10:59:09 nanard Exp $ */ - /* $Id: upnpcommands.h,v 1.17 2009/04/17 21:21:19 nanard Exp $ */ - //UPNP_AddPortMapping(const char * controlURL, const char * servicetype, - // const char * extPort, - // const char * inPort, - // const char * inClient, - // const char * desc, - // const char * proto, - // const char * remoteHost); - r = UPNP_AddPortMapping(urls->controlURL, servicetype, - eport, iport, iaddr, description, proto, NULL); -#else -#if MINIUPNPC_API_VERSION >= -7//Before 1.0 - /* $Id: upnpcommands.h,v 1.14 2008/09/25 18:02:50 nanard Exp $ */ - /* $Id: upnpcommands.h,v 1.7 2006/07/09 12:00:54 nanard Exp $ */ - //UPNP_AddPortMapping(const char * controlURL, const char * servicetype, - // const char * extPort, - // const char * inPort, - // const char * inClient, - // const char * desc, - // const char * proto); - r = UPNP_AddPortMapping(urls->controlURL, servicetype, - eport, iport, iaddr, description, proto); -#else -#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version -#endif//>=-7 -#endif//>=-3 -#endif//>=-1 - -#if MINIUPNPC_API_VERSION >= -5//2007/12/19 - if(r!=UPNPCOMMAND_SUCCESS){ -#else -#if MINIUPNPC_API_VERSION >= -7//Before 1.0 - if(r==0){ -#else -#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version -#endif//>=-7 -#endif//>=-5 - printf("AddPortMapping(%s, %s, %s) failed and returns %d\n", eport, iport, iaddr, r); - //this seems to trigger for unknown reasons sometimes. - //rely on Checking it afterwards... - //should check IP address then! - ok = 0; - } - } - -#if MINIUPNPC_API_VERSION >= 10//1.0 2006/09/04 - /* $Id: upnpcommands.h,v 1.30 2015/07/15 12:21:28 nanard Exp $ */ - /* $Id: upnpcommands.h,v 1.26 2014/01/31 13:18:26 nanard Exp $ */ - //UPNP_GetSpecificPortMappingEntry(const char * controlURL, - // const char * servicetype, - // const char * extPort, - // const char * proto, - // const char * remoteHost, - // char * intClient, - // char * intPort, - // char * desc, - // char * enabled, - // char * leaseDuration); - r = UPNP_GetSpecificPortMappingEntry(urls->controlURL, - data->first.servicetype, - eport, proto, NULL/*remoteHost*/, - intClient, intPort, NULL/*desc*/, - NULL/*enabled*/, duration); -#else -#if MINIUPNPC_API_VERSION >= 6//1.0 2006/09/04 - /* $Id: upnpcommands.h,v 1.24 2012/03/05 19:42:47 nanard Exp $ */ - /* $Id: upnpcommands.h,v 1.22 2011/03/14 13:36:01 nanard Exp $ */ - //UPNP_GetSpecificPortMappingEntry(const char * controlURL, - // const char * servicetype, - // const char * extPort, - // const char * proto, - // char * intClient, - // char * intPort, - // char * desc, - // char * enabled, - // char * leaseDuration); - r = UPNP_GetSpecificPortMappingEntry(urls->controlURL, - data->first.servicetype, - eport, proto, - intClient, intPort, NULL/*desc*/, - NULL/*enabled*/, duration); -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - /* $Id: upnpcommands.h,v 1.20 2011/02/15 11:13:22 nanard Exp $ */ - /* $Id: upnpcommands.h,v 1.7 2006/07/09 12:00:54 nanard Exp $ */ - //UPNP_GetSpecificPortMappingEntry(const char * controlURL, - // const char * servicetype, - // const char * extPort, - // const char * proto, - // char * intClient, - // char * intPort); - UPNP_GetSpecificPortMappingEntry(urls->controlURL, - servicetype, - eport, - proto, - intClient, - intPort); - if(intClient[0]) r = UPNPCOMMAND_SUCCESS; -#endif//>=-7 -#endif//>=6 -#endif//>=10 - - if(r!=UPNPCOMMAND_SUCCESS) { - printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n", - r, strupnperror(r)); - ok = 0; - } else if(intClient[0]) { - printf("InternalIP:Port = %s:%s\n", intClient, intPort); - printf("external %s:%s %s is redirected to internal %s:%s (duration=%s)\n", - externalIPAddress, eport, proto, intClient, intPort, duration); - } - - if ((strcmp(iaddr, intClient) != 0) || (strcmp(iport, intPort) != 0)) - { - printf("PortMappingEntry to wrong location! FAILED\n"); - printf("IP1:\"%s\"\n", iaddr); - printf("IP2:\"%s\"\n", intClient); - printf("PORT1:\"%s\"\n", iport); - printf("PORT2:\"%s\"\n", intPort); - ok = 0; - } - - if (ok) - { - printf("uPnP Forward/Mapping Succeeded\n"); - } - else - { - printf("uPnP Forward/Mapping Failed\n"); - } - - return ok; -} - -int TestRedirect(struct UPNPUrls * urls, - struct IGDdatas * data, - const char * iaddr, - const char * iport, - const char * eport, - const char * proto) -{ - char externalIPAddress[40]; - char intClient[40]; - char intPort[6]; - char duration[16]; - int r = 0; - int ok = 1; - - if(!iaddr || !iport || !eport || !proto) - { - fprintf(stderr, "Wrong arguments\n"); - return 0; - } - proto = protofix(proto); - if(!proto) - { - fprintf(stderr, "invalid protocol\n"); - return 0; - } - -#if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09 - const char * servicetype = data->first.servicetype; -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - const char * servicetype = data->servicetype; -#else -#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version -#endif -#endif - -#if MINIUPNPC_API_VERSION >= 10//1.0 2006/09/04 - /* $Id: upnpcommands.h,v 1.30 2015/07/15 12:21:28 nanard Exp $ */ - /* $Id: upnpcommands.h,v 1.26 2014/01/31 13:18:26 nanard Exp $ */ - //UPNP_GetSpecificPortMappingEntry(const char * controlURL, - // const char * servicetype, - // const char * extPort, - // const char * proto, - // const char * remoteHost, - // char * intClient, - // char * intPort, - // char * desc, - // char * enabled, - // char * leaseDuration); - r = UPNP_GetSpecificPortMappingEntry(urls->controlURL, - servicetype, - eport, proto, NULL/*remoteHost*/, - intClient, intPort, NULL/*desc*/, - NULL/*enabled*/, duration); -#else -#if MINIUPNPC_API_VERSION >= 6//1.0 2006/09/04 - /* $Id: upnpcommands.h,v 1.24 2012/03/05 19:42:47 nanard Exp $ */ - /* $Id: upnpcommands.h,v 1.22 2011/03/14 13:36:01 nanard Exp $ */ - //UPNP_GetSpecificPortMappingEntry(const char * controlURL, - // const char * servicetype, - // const char * extPort, - // const char * proto, - // char * intClient, - // char * intPort, - // char * desc, - // char * enabled, - // char * leaseDuration); - r = UPNP_GetSpecificPortMappingEntry(urls->controlURL, - servicetype, - eport, proto, - intClient, intPort, NULL/*desc*/, - NULL/*enabled*/, duration); -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - /* $Id: upnpcommands.h,v 1.20 2011/02/15 11:13:22 nanard Exp $ */ - /* $Id: upnpcommands.h,v 1.7 2006/07/09 12:00:54 nanard Exp $ */ - //UPNP_GetSpecificPortMappingEntry(const char * controlURL, - // const char * servicetype, - // const char * extPort, - // const char * proto, - // char * intClient, - // char * intPort); - UPNP_GetSpecificPortMappingEntry(urls->controlURL, - servicetype, - eport, - proto, - intClient, - intPort); - if(intClient[0]) r = UPNPCOMMAND_SUCCESS; -#endif//>=-7 -#endif//>=6 -#endif//>=10 - - if(r!=UPNPCOMMAND_SUCCESS) { - printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n", - r, strupnperror(r)); - ok = 0; - } else if(intClient[0]) { - printf("uPnP Check: InternalIP:Port = %s:%s\n", intClient, intPort); - printf("external %s:%s %s is redirected to internal %s:%s (duration=%s)\n", - externalIPAddress, eport, proto, intClient, intPort, duration); - } - - if (ok) - { - printf("uPnP Check: uPnP Forward/Mapping still Active\n"); - } - else - { - printf("uPnP Check: Forward/Mapping has been Dropped\n"); - } - - return ok; -} - -int -RemoveRedirect(struct UPNPUrls * urls, - struct IGDdatas * data, - const char * eport, - const char * proto) -{ - if(!proto || !eport) - { - fprintf(stderr, "invalid arguments\n"); - return 0; - } - proto = protofix(proto); - if(!proto) - { - fprintf(stderr, "protocol invalid\n"); - return 0; - } -#if MINIUPNPC_API_VERSION >= -2//1.4 2010/12/09 - UPNP_DeletePortMapping(urls->controlURL, data->first.servicetype, eport, proto, NULL); -#else -#if MINIUPNPC_API_VERSION >= -3//1.3 2009/04/17 - UPNP_DeletePortMapping(urls->controlURL, data->servicetype, eport, proto, NULL); -#else -#if MINIUPNPC_API_VERSION >= -7//1.0 2006/09/04 - UPNP_DeletePortMapping(urls->controlURL, data->servicetype, eport, proto); -#else -#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version -#endif//>= -7 -#endif//>= -3 -#endif//>= -2 - - return 1; -} - - -/* EOF */ diff --git a/libretroshare/src/rs_upnp/upnputil.h b/libretroshare/src/rs_upnp/upnputil.h deleted file mode 100644 index 9586418a4..000000000 --- a/libretroshare/src/rs_upnp/upnputil.h +++ /dev/null @@ -1,101 +0,0 @@ -/******************************************************************************* - * libretroshare/src/upnp: upnputil.h * - * * - * libretroshare: retroshare core library * - * From MiniUPnPc, re-licensed with permission * - * * - * Copyright (c) 2005-2016, Thomas BERNARD * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -//this file uses miniupnp - -#ifndef MINIUPNP_UTIL_H_ -#define MINIUPNP_UTIL_H_ - -#include -#include -#include -#ifdef WIN32 -#include -#define snprintf _snprintf -#endif -#include -#include -#include -#include - -//Define this variable follow the date of used MiniUPnP Library -//#define MINIUPNPC_API_VERSION -3 -#ifndef MINIUPNPC_API_VERSION -#error MINIUPNPC_API_VERSION is not defined. You may define one follow miniupnpc library version - //2006/09/04 to 2007/10/01 => -7//Start return struct UPNPDev * for upnpDiscover - //2007/10/16 => -6 upnpDiscover - //2007/12/19 => -5 upnpDiscover - //2008/09/25 => -4 upnpDiscover - //2009/04/17 => -3 UPNP_AddPortMapping - //2010/12/09 => -2 //struct IGDdatas_service CIF; - //2011/02/15 => -1 UPNP_AddPortMapping - //2011/03/14 => 6 //Start of MINIUPNPC_API_VERSION -#endif//>=-7 - -/* Ensure linking names are okay on OSX platform. (C interface) */ - -#ifdef __cplusplus -extern "C" { -#endif - - -/* protofix() checks if protocol is "UDP" or "TCP" - * returns NULL if not */ -const char * protofix(const char * proto); -void DisplayInfos(struct UPNPUrls * urls, - struct IGDdatas * data); - -void GetConnectionStatus(struct UPNPUrls * urls, - struct IGDdatas * data); - -void ListRedirections(struct UPNPUrls * urls, - struct IGDdatas * data); - -int SetRedirectAndTest(struct UPNPUrls * urls, - struct IGDdatas * data, - const char * iaddr, - const char * iport, - const char * eport, - const char * proto, - const char *leaseDuration, - const char *description, - int addAny); - -int TestRedirect(struct UPNPUrls * urls, - struct IGDdatas * data, - const char * iaddr, - const char * iport, - const char * eport, - const char * proto); - -int RemoveRedirect(struct UPNPUrls * urls, - struct IGDdatas * data, - const char * eport, - const char * proto); - -#ifdef __cplusplus -} -#endif - -/* EOF */ -#endif diff --git a/libretroshare/src/rsitems/itempriorities.h b/libretroshare/src/rsitems/itempriorities.h deleted file mode 100644 index 7c2b92cb6..000000000 --- a/libretroshare/src/rsitems/itempriorities.h +++ /dev/null @@ -1,129 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsitempriorities.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2011-2018 Cyril Soler * - * Copyright (C) 2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include - -using RsItemPriority = uint8_t; - -// This file centralises QoS priorities for all transfer RsItems -// -const uint8_t QOS_PRIORITY_UNKNOWN = 0 ; -const uint8_t QOS_PRIORITY_DEFAULT = 3 ; -const uint8_t QOS_PRIORITY_TOP = 9 ; - -// Turtle traffic -// -const uint8_t QOS_PRIORITY_RS_TURTLE_OPEN_TUNNEL = 7 ; -const uint8_t QOS_PRIORITY_RS_TURTLE_TUNNEL_OK = 7 ; - -const uint8_t QOS_PRIORITY_RS_TURTLE_SEARCH_REQUEST = 6 ; -const uint8_t QOS_PRIORITY_RS_TURTLE_FILE_REQUEST = 6 ; -const uint8_t QOS_PRIORITY_RS_TURTLE_FILE_MAP_REQUEST = 6 ; -const uint8_t QOS_PRIORITY_RS_TURTLE_FILE_CRC_REQUEST = 6 ; // unused -const uint8_t QOS_PRIORITY_RS_TURTLE_CHUNK_CRC_REQUEST = 6 ; // unused - -const uint8_t QOS_PRIORITY_RS_TURTLE_FILE_DATA = 5 ; -const uint8_t QOS_PRIORITY_RS_TURTLE_FILE_MAP = 6 ; -const uint8_t QOS_PRIORITY_RS_TURTLE_FILE_CRC = 6 ; // unused -const uint8_t QOS_PRIORITY_RS_TURTLE_CHUNK_CRC = 6 ; // unused - -const uint8_t QOS_PRIORITY_RS_TURTLE_GENERIC_FAST_DATA = 7 ; -const uint8_t QOS_PRIORITY_RS_TURTLE_SEARCH_RESULT = 6 ; -const uint8_t QOS_PRIORITY_RS_TURTLE_GENERIC_DATA = 5 ; -const uint8_t QOS_PRIORITY_RS_TURTLE_GENERIC_ITEM = 3 ; -const uint8_t QOS_PRIORITY_RS_TURTLE_FORWARD_FILE_DATA = 3 ; // unused - -// File transfer -// -const uint8_t QOS_PRIORITY_RS_FILE_REQUEST = 6 ; -const uint8_t QOS_PRIORITY_RS_FILE_MAP_REQUEST = 6 ; -const uint8_t QOS_PRIORITY_RS_FILE_CRC_REQUEST = 6 ; // unused -const uint8_t QOS_PRIORITY_RS_CHUNK_CRC_REQUEST = 6 ; - -const uint8_t QOS_PRIORITY_RS_FILE_DATA = 5 ; -const uint8_t QOS_PRIORITY_RS_FILE_MAP = 6 ; -const uint8_t QOS_PRIORITY_RS_FILE_CRC = 6 ; // unused -const uint8_t QOS_PRIORITY_RS_CHUNK_CRC = 6 ; - -const uint8_t QOS_PRIORITY_RS_CACHE_ITEM = 3 ; // unused - -// Discovery -// -const uint8_t QOS_PRIORITY_RS_DISC_HEART_BEAT = 8 ; -const uint8_t QOS_PRIORITY_RS_DISC_ASK_INFO = 2 ; -const uint8_t QOS_PRIORITY_RS_DISC_REPLY = 2 ; -const uint8_t QOS_PRIORITY_RS_DISC_VERSION = 2 ; - -const uint8_t QOS_PRIORITY_RS_DISC_CONTACT = 2 ; // CONTACT and PGPLIST must have -const uint8_t QOS_PRIORITY_RS_DISC_PGP_LIST = 2 ; // same priority -const uint8_t QOS_PRIORITY_RS_DISC_SERVICES = 2 ; -const uint8_t QOS_PRIORITY_RS_DISC_PGP_CERT = 2 ; - -// File database -// -const uint8_t QOS_PRIORITY_RS_FAST_SYNC_REQUEST = 7 ; -const uint8_t QOS_PRIORITY_RS_SLOW_SYNC_REQUEST = 3 ; - -// Heartbeat -// -const uint8_t QOS_PRIORITY_RS_HEARTBEAT_PULSE = 8 ; - -// Chat/Msgs -// -const uint8_t QOS_PRIORITY_RS_CHAT_ITEM = 7 ; -const uint8_t QOS_PRIORITY_RS_CHAT_AVATAR_ITEM = 2 ; -const uint8_t QOS_PRIORITY_RS_MSG_ITEM = 2 ; // deprecated -const uint8_t QOS_PRIORITY_RS_MAIL_ITEM = 2 ; // new mail service -const uint8_t QOS_PRIORITY_RS_STATUS_ITEM = 2 ; - -// RTT -// -const uint8_t QOS_PRIORITY_RS_RTT_PING = 9 ; - -// BanList -// -const uint8_t QOS_PRIORITY_RS_BANLIST_ITEM = 3 ; - -// Bandwidth Control -// -const uint8_t QOS_PRIORITY_RS_BWCTRL_ALLOWED_ITEM = 9 ; - -// DsDv Routing -// -const uint8_t QOS_PRIORITY_RS_DSDV_ROUTE = 4 ; -const uint8_t QOS_PRIORITY_RS_DSDV_DATA = 2 ; - -// GXS -// -const uint8_t QOS_PRIORITY_RS_GXS_NET = 6 ; - -// GXS Reputation -// -const uint8_t QOS_PRIORITY_RS_GXSREPUTATION_ITEM = 3 ; - -// Service Info / Control -// -const uint8_t QOS_PRIORITY_RS_SERVICE_INFO_ITEM = 8 ; - diff --git a/libretroshare/src/rsitems/rsbanlistitems.cc b/libretroshare/src/rsitems/rsbanlistitems.cc deleted file mode 100644 index f283f5b43..000000000 --- a/libretroshare/src/rsitems/rsbanlistitems.cc +++ /dev/null @@ -1,67 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsbanlistitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "serialiser/rsbaseserial.h" -#include "rsitems/rsbanlistitems.h" - -#include "serialiser/rstypeserializer.h" - -/*** -#define RSSERIAL_DEBUG 1 -***/ - -#include - -/*************************************************************************/ - -void RsBanListItem::clear() -{ - peerList.TlvClear(); -} - -void RsBanListItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,peerList,"peerList") ; -} - -void RsBanListConfigItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,banListType,"type") ; - RsTypeSerializer::serial_process (j,ctx,banListPeerId,"peerId") ; - RsTypeSerializer::serial_process (j,ctx,update_time,"update_time") ; - RsTypeSerializer::serial_process (j,ctx,banned_peers,"banned_peers") ; -} -RsItem *RsBanListSerialiser::create_item(uint16_t service_id,uint8_t item_sub_id) const -{ - if(service_id != RS_SERVICE_TYPE_BANLIST) - return NULL ; - - switch(item_sub_id) - { - case RS_PKT_SUBTYPE_BANLIST_CONFIG_ITEM: return new RsBanListConfigItem ; - case RS_PKT_SUBTYPE_BANLIST_ITEM: return new RsBanListItem ; - default: - std::cerr << "(EE) unknown item subtype " << (int)item_sub_id << " in RsBanListSerialiser::create_item()" << std::endl; - return NULL ; - } -} - - diff --git a/libretroshare/src/rsitems/rsbanlistitems.h b/libretroshare/src/rsitems/rsbanlistitems.h deleted file mode 100644 index 6422340af..000000000 --- a/libretroshare/src/rsitems/rsbanlistitems.h +++ /dev/null @@ -1,87 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsbanlistitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_BANLIST_ITEMS_H -#define RS_BANLIST_ITEMS_H - -#include - -#include "rsitems/rsserviceids.h" -#include "rsitems/rsitem.h" -#include "rsitems/itempriorities.h" -#include "serialiser/rstlvbanlist.h" -#include "serialiser/rsserializer.h" - -#define RS_PKT_SUBTYPE_BANLIST_ITEM_deprecated 0x01 -#define RS_PKT_SUBTYPE_BANLIST_CONFIG_ITEM_deprecated 0x02 -#define RS_PKT_SUBTYPE_BANLIST_ITEM 0x03 -#define RS_PKT_SUBTYPE_BANLIST_CONFIG_ITEM 0x04 - -/**************************************************************************/ - -class RsBanListItem: public RsItem -{ - public: - RsBanListItem() :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_BANLIST, RS_PKT_SUBTYPE_BANLIST_ITEM) - { - setPriorityLevel(QOS_PRIORITY_RS_BANLIST_ITEM); - return; - } - - virtual ~RsBanListItem(){} - virtual void clear(); - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsTlvBanList peerList; -}; - -class RsBanListConfigItem: public RsItem -{ -public: - RsBanListConfigItem() - : RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_BANLIST, RS_PKT_SUBTYPE_BANLIST_CONFIG_ITEM) - , banListType(0), update_time(0) - {} - - virtual ~RsBanListConfigItem(){} - virtual void clear() { banned_peers.TlvClear() ; } - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t banListType ; - RsPeerId banListPeerId ; - rstime_t update_time ; - RsTlvBanList banned_peers; -}; - -class RsBanListSerialiser: public RsServiceSerializer -{ -public: - RsBanListSerialiser() :RsServiceSerializer(RS_SERVICE_TYPE_BANLIST) {} - - virtual RsItem *create_item(uint16_t service_id,uint8_t item_sub_id) const ; -}; - -/**************************************************************************/ - -#endif /* RS_BANLIST_ITEMS_H */ - - diff --git a/libretroshare/src/rsitems/rsbwctrlitems.cc b/libretroshare/src/rsitems/rsbwctrlitems.cc deleted file mode 100644 index 759264aa0..000000000 --- a/libretroshare/src/rsitems/rsbwctrlitems.cc +++ /dev/null @@ -1,57 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsbwctrlitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "serialiser/rsbaseserial.h" -#include "rsitems/rsbwctrlitems.h" - -/*** -#define RSSERIAL_DEBUG 1 -***/ - -#include - -/*************************************************************************/ - -RsItem *RsBwCtrlSerialiser::create_item(uint16_t service, uint8_t item_sub_id) const -{ - if(service != RS_SERVICE_TYPE_BWCTRL) - return NULL ; - - switch(item_sub_id) - { - case RS_PKT_SUBTYPE_BWCTRL_ALLOWED_ITEM: return new RsBwCtrlAllowedItem(); - default: - return NULL; - } -} - -void RsBwCtrlAllowedItem::clear() -{ - allowedBw = 0; -} - -void RsBwCtrlAllowedItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_UINT32_BW,allowedBw,"allowedBw") ; -} - - - diff --git a/libretroshare/src/rsitems/rsbwctrlitems.h b/libretroshare/src/rsitems/rsbwctrlitems.h deleted file mode 100644 index 300bd6f54..000000000 --- a/libretroshare/src/rsitems/rsbwctrlitems.h +++ /dev/null @@ -1,68 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsbwctrlitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_BANDWIDTH_CONTROL_ITEMS_H -#define RS_BANDWIDTH_CONTROL_ITEMS_H - -#include - -#include "rsitems/rsitem.h" -#include "rsitems/rsserviceids.h" -#include "rsitems/itempriorities.h" - -#include "serialiser/rsserializer.h" -#include "serialiser/rstypeserializer.h" - -#define RS_PKT_SUBTYPE_BWCTRL_ALLOWED_ITEM 0x01 - -/**************************************************************************/ - -class RsBwCtrlAllowedItem: public RsItem -{ -public: - RsBwCtrlAllowedItem() :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_BWCTRL, RS_PKT_SUBTYPE_BWCTRL_ALLOWED_ITEM) - { - setPriorityLevel(QOS_PRIORITY_RS_BWCTRL_ALLOWED_ITEM); - return; - } - - virtual ~RsBwCtrlAllowedItem() {} - virtual void clear(); - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t allowedBw; // Units are bytes/sec => 4Gb/s; -}; - - -class RsBwCtrlSerialiser: public RsServiceSerializer -{ -public: - RsBwCtrlSerialiser() :RsServiceSerializer(RS_SERVICE_TYPE_BWCTRL) {} - virtual ~RsBwCtrlSerialiser() {} - - RsItem *create_item(uint16_t /* service */, uint8_t /* item_sub_id */) const; -}; - -/**************************************************************************/ - -#endif /* RS_BANDWIDTH_CONTROL_ITEMS_H */ - diff --git a/libretroshare/src/rsitems/rsconfigitems.cc b/libretroshare/src/rsitems/rsconfigitems.cc deleted file mode 100644 index 654d1a7f6..000000000 --- a/libretroshare/src/rsitems/rsconfigitems.cc +++ /dev/null @@ -1,239 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsconfigitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "serialiser/rsbaseserial.h" -#include "rsitems/rsconfigitems.h" -#include "retroshare/rspeers.h" // Needed for RsGroupInfo. - -#include "serialiser/rsserializable.h" -#include "serialiser/rstypeserializer.h" -/*** - * #define RSSERIAL_DEBUG 1 - * #define RSSERIAL_ERROR_DEBUG 1 - ***/ - -#define RSSERIAL_ERROR_DEBUG 1 - -#include - - -/*************************************************************************/ - -RsItem *RsFileConfigSerialiser::create_item(uint8_t item_type,uint8_t item_subtype) const -{ - if(item_type != RS_PKT_TYPE_FILE_CONFIG) - return NULL ; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_FILE_TRANSFER: return new RsFileTransfer() ; - case RS_PKT_SUBTYPE_FILE_ITEM: return new RsFileConfigItem() ; - default: - return NULL ; - } -} -void RsFileTransfer::clear() -{ - - file.TlvClear(); - allPeerIds.TlvClear(); - cPeerId.clear() ; - state = 0; - in = false; - transferred = 0; - crate = 0; - trate = 0; - lrate = 0; - ltransfer = 0; - -} - -void RsFileTransfer::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,file,"file") ; - RsTypeSerializer::serial_process(j,ctx,allPeerIds,"allPeerIds") ; - - RsTypeSerializer::serial_process (j,ctx,cPeerId,"cPeerId") ; - - RsTypeSerializer::serial_process (j,ctx,state,"state") ; - RsTypeSerializer::serial_process (j,ctx,in,"in") ; - - RsTypeSerializer::serial_process (j,ctx,transferred,"transferred") ; - - RsTypeSerializer::serial_process (j,ctx,crate,"crate") ; - RsTypeSerializer::serial_process (j,ctx,trate,"trate") ; - RsTypeSerializer::serial_process (j,ctx,lrate,"lrate") ; - RsTypeSerializer::serial_process (j,ctx,ltransfer,"ltransfer") ; - - RsTypeSerializer::serial_process (j,ctx,flags,"flags") ; - RsTypeSerializer::serial_process (j,ctx,chunk_strategy,"chunk_strategy") ; - RS_SERIAL_PROCESS(compressed_chunk_map); -} - -void RsFileConfigItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,file,"file") ; - RsTypeSerializer::serial_process (j,ctx,flags,"flags") ; - RsTypeSerializer::serial_process(j,ctx,parent_groups,"parent_groups") ; -} - -RsItem *RsGeneralConfigSerialiser::create_item(uint8_t item_type,uint8_t item_subtype) const -{ - if(item_type != RS_PKT_TYPE_GENERAL_CONFIG) - return NULL ; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_KEY_VALUE: return new RsConfigKeyValueSet(); - default: - return NULL ; - } -} - -void RsConfigKeyValueSet::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,tlvkvs,"tlvkvs") ; -} - -RsItem *RsPeerConfigSerialiser::create_item(uint8_t item_type,uint8_t item_subtype) const -{ - if(item_type != RS_PKT_TYPE_PEER_CONFIG) - return NULL ; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_PEER_NET: return new RsPeerNetItem(); - case RS_PKT_SUBTYPE_PEER_STUN: return new RsPeerStunItem(); - case RS_PKT_SUBTYPE_NODE_GROUP: return new RsNodeGroupItem() ; - case RS_PKT_SUBTYPE_PEER_PERMISSIONS: return new RsPeerServicePermissionItem(); - case RS_PKT_SUBTYPE_PEER_BANDLIMITS: return new RsPeerBandwidthLimitsItem(); - default: - return NULL ; - } -} - -void RsPeerNetItem::clear() -{ - nodePeerId.clear(); - pgpId.clear(); - location.clear(); - netMode = 0; - vs_disc = 0; - vs_dht = 0; - lastContact = 0; - - localAddrV4.TlvClear(); - extAddrV4.TlvClear(); - localAddrV6.TlvClear(); - extAddrV6.TlvClear(); - - dyndns.clear(); - - localAddrList.TlvClear(); - extAddrList.TlvClear(); - - domain_addr.clear(); - domain_port = 0; -} -void RsPeerNetItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,nodePeerId,"peerId") ; - RsTypeSerializer::serial_process(j,ctx,pgpId,"pgpId") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_LOCATION,location,"location") ; - - RsTypeSerializer::serial_process(j,ctx,netMode,"netMode") ; - RsTypeSerializer::serial_process(j,ctx,vs_disc,"vs_disc") ; - RsTypeSerializer::serial_process(j,ctx,vs_dht,"vs_dht") ; - RsTypeSerializer::serial_process(j,ctx,lastContact,"lastContact") ; - - RsTypeSerializer::serial_process(j,ctx,localAddrV4,"localAddrV4") ; - RsTypeSerializer::serial_process(j,ctx,extAddrV4,"extAddrV4") ; - RsTypeSerializer::serial_process(j,ctx,localAddrV6,"localAddrV6") ; - RsTypeSerializer::serial_process(j,ctx,extAddrV6,"extAddrV6") ; - - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DYNDNS,dyndns,"dyndns") ; - - RsTypeSerializer::serial_process(j,ctx,localAddrList,"localAddrList") ; - RsTypeSerializer::serial_process(j,ctx,extAddrList,"extAddrList") ; - - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DOMADDR,domain_addr,"domain_addr") ; - RsTypeSerializer::serial_process(j,ctx,domain_port,"domain_port") ; -} - -void RsPeerBandwidthLimitsItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,peers,"peers") ; -} - -void RsPeerStunItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,stunList,"stunList") ; -} - - -RsNodeGroupItem::RsNodeGroupItem(const RsGroupInfo& g) - :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_PEER_CONFIG, RS_PKT_SUBTYPE_NODE_GROUP) -{ - id = g.id ; - name = g.name ; - flag = g.flag ; - pgpList.ids = g.peerIds; -} - -void RsNodeGroupItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - uint32_t v=0 ; - - RsTypeSerializer::serial_process(j,ctx,v,"dummy field 0") ; - RsTypeSerializer::serial_process (j,ctx,id,"id") ; - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_NAME,name,"name") ; - RsTypeSerializer::serial_process(j,ctx,flag,"flag") ; - RsTypeSerializer::serial_process(j,ctx,pgpList,"pgpList") ; -} - -void RsPeerServicePermissionItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - // We need to hack this because of backward compatibility. The correct way to do it would be: - // - // RsTypeSerializer::serial_process(j,ctx,pgp_ids,"pgp_ids") ; - // RsTypeSerializer::serial_process(j,ctx,service_flags,"service_flags") ; - - if(j == RsGenericSerializer::DESERIALIZE) - { - uint32_t v=0 ; - RsTypeSerializer::serial_process(j,ctx,v,"pgp_ids.size()") ; - - pgp_ids.resize(v) ; - service_flags.resize(v) ; - } - else - { - uint32_t s = pgp_ids.size(); - RsTypeSerializer::serial_process(j,ctx,s,"pgp_ids.size()") ; - } - - for(uint32_t i=0;i * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_CONFIG_ITEMS_SERIALISER_H -#define RS_CONFIG_ITEMS_SERIALISER_H - -#include -#include - -#include "rsitems/rsitem.h" - -#include "retroshare/rstypes.h" -#include "serialiser/rsserial.h" - -#include "serialiser/rstlvidset.h" -#include "serialiser/rstlvfileitem.h" -#include "serialiser/rstlvkeyvalue.h" -#include "serialiser/rstlvaddrs.h" - -#include "serialiser/rsserializer.h" - -struct RsGroupInfo; - -const uint8_t RS_PKT_TYPE_GENERAL_CONFIG = 0x01; -const uint8_t RS_PKT_TYPE_PEER_CONFIG = 0x02; -const uint8_t RS_PKT_TYPE_CACHE_CONFIG = 0x03; -const uint8_t RS_PKT_TYPE_FILE_CONFIG = 0x04; -const uint8_t RS_PKT_TYPE_PLUGIN_CONFIG = 0x05; -const uint8_t RS_PKT_TYPE_HISTORY_CONFIG = 0x06; - - /* GENERAL CONFIG SUBTYPES */ -const uint8_t RS_PKT_SUBTYPE_KEY_VALUE = 0x01; - - /* PEER CONFIG SUBTYPES */ -const uint8_t RS_PKT_SUBTYPE_PEER_STUN = 0x02; -const uint8_t RS_PKT_SUBTYPE_PEER_NET = 0x03; -const uint8_t RS_PKT_SUBTYPE_PEER_GROUP_deprecated = 0x04; -const uint8_t RS_PKT_SUBTYPE_PEER_PERMISSIONS = 0x05; -const uint8_t RS_PKT_SUBTYPE_PEER_BANDLIMITS = 0x06; -const uint8_t RS_PKT_SUBTYPE_NODE_GROUP = 0x07; - - /* FILE CONFIG SUBTYPES */ -const uint8_t RS_PKT_SUBTYPE_FILE_TRANSFER = 0x01; -const uint8_t RS_PKT_SUBTYPE_FILE_ITEM_deprecated = 0x02; -const uint8_t RS_PKT_SUBTYPE_FILE_ITEM = 0x03; - -/**************************************************************************/ - -class RsPeerNetItem: public RsItem -{ -public: - RsPeerNetItem() - :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, - RS_PKT_TYPE_PEER_CONFIG, - RS_PKT_SUBTYPE_PEER_NET) - , netMode(0), vs_disc(0), vs_dht(0), lastContact(0), domain_port(0) - {} - - virtual ~RsPeerNetItem(){} - virtual void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - /* networking information */ - RsPeerId nodePeerId; /* Mandatory */ - RsPgpId pgpId; /* Mandatory */ - std::string location; /* Mandatory */ - uint32_t netMode; /* Mandatory */ - uint16_t vs_disc; /* Mandatory */ - uint16_t vs_dht; /* Mandatory */ - uint32_t lastContact; /* Mandatory */ - - RsTlvIpAddress localAddrV4; /* Mandatory */ - RsTlvIpAddress extAddrV4; /* Mandatory */ - RsTlvIpAddress localAddrV6; /* Mandatory */ - RsTlvIpAddress extAddrV6; /* Mandatory */ - - std::string dyndns; - - RsTlvIpAddrSet localAddrList; - RsTlvIpAddrSet extAddrList; - - // for proxy connection. - std::string domain_addr; - uint16_t domain_port; -}; - -// This item should be merged with the next item, but that is not backward compatible. -class RsPeerServicePermissionItem : public RsItem -{ - public: - RsPeerServicePermissionItem() : RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_PEER_CONFIG, RS_PKT_SUBTYPE_PEER_PERMISSIONS) {} - virtual ~RsPeerServicePermissionItem() {} - - virtual void clear() - { - pgp_ids.clear() ; - service_flags.clear() ; - } - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - - /* Mandatory */ - std::vector pgp_ids ; - std::vector service_flags ; -}; -class RsPeerBandwidthLimitsItem : public RsItem -{ - public: - RsPeerBandwidthLimitsItem() : RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_PEER_CONFIG, RS_PKT_SUBTYPE_PEER_BANDLIMITS) {} - virtual ~RsPeerBandwidthLimitsItem() {} - - virtual void clear() - { - peers.clear() ; - } - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - /* Mandatory */ - std::map peers ; -}; - -class RsNodeGroupItem: public RsItem -{ -public: - RsNodeGroupItem(): RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_PEER_CONFIG, RS_PKT_SUBTYPE_NODE_GROUP), flag(0) {} - virtual ~RsNodeGroupItem() {} - - virtual void clear() { pgpList.TlvClear();} - - explicit RsNodeGroupItem(const RsGroupInfo&) ; - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - // /* set data from RsGroupInfo to RsPeerGroupItem */ - // void set(RsGroupInfo &groupInfo); - // /* get data from RsGroupInfo to RsPeerGroupItem */ - // void get(RsGroupInfo &groupInfo); - - /* Mandatory */ - RsNodeGroupId id; - std::string name; - uint32_t flag; - - RsTlvPgpIdSet pgpList; -}; - -class RsPeerStunItem: public RsItem -{ -public: - RsPeerStunItem() - :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, - RS_PKT_TYPE_PEER_CONFIG, - RS_PKT_SUBTYPE_PEER_STUN) {} - virtual ~RsPeerStunItem(){} - virtual void clear() { stunList.TlvClear() ;} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsTlvPeerIdSet stunList; /* Mandatory */ -}; - -class RsPeerConfigSerialiser: public RsConfigSerializer -{ - public: - RsPeerConfigSerialiser() :RsConfigSerializer(RS_PKT_CLASS_CONFIG,RS_PKT_TYPE_PEER_CONFIG) {} - - virtual ~RsPeerConfigSerialiser(){} - - virtual RsItem *create_item(uint8_t item_type, uint8_t item_subtype) const ; -}; - -/**************************************************************************/ - -class RsFileTransfer: public RsItem -{ - public: - RsFileTransfer() :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_FILE_CONFIG, RS_PKT_SUBTYPE_FILE_TRANSFER) - { - state = 0; - in = 0; - transferred = 0; - crate = 0; - trate = 0; - lrate = 0; - ltransfer = 0; - flags = 0; - chunk_strategy = 0; - } - virtual ~RsFileTransfer(){} - virtual void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsTlvFileItem file; - RsTlvPeerIdSet allPeerIds; - - RsPeerId cPeerId; - - uint16_t state; - uint16_t in; - - uint64_t transferred; - uint32_t crate; - uint32_t trate; - - uint32_t lrate; - uint32_t ltransfer; - - // chunk information - uint32_t flags ; - uint32_t chunk_strategy ; // strategy flags for chunks - CompressedChunkMap compressed_chunk_map ; // chunk availability (bitwise) -}; - -/**************************************************************************/ - -const uint32_t RS_FILE_CONFIG_CLEANUP_DELETE = 0x0001; - -class RsFileConfigItem: public RsItem -{ -public: - RsFileConfigItem() :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_FILE_CONFIG, RS_PKT_SUBTYPE_FILE_ITEM), flags(0) {} - virtual ~RsFileConfigItem() {} - virtual void clear() { parent_groups.TlvClear(); } - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsTlvFileItem file; - uint32_t flags; - RsTlvNodeGroupIdSet parent_groups ; -}; -/**************************************************************************/ - -class RsFileConfigSerialiser: public RsConfigSerializer -{ - public: - RsFileConfigSerialiser() :RsConfigSerializer(RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_FILE_CONFIG) { } - virtual ~RsFileConfigSerialiser() {} - - virtual RsItem *create_item(uint8_t item_type, uint8_t item_subtype) const ; -}; - -/**************************************************************************/ - -/* Config items that are used generally */ - -class RsConfigKeyValueSet: public RsItem -{ -public: - RsConfigKeyValueSet() :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_GENERAL_CONFIG, RS_PKT_SUBTYPE_KEY_VALUE) {} - virtual ~RsConfigKeyValueSet(){} - virtual void clear() { tlvkvs.TlvClear();} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsTlvKeyValueSet tlvkvs; -}; - - -class RsGeneralConfigSerialiser: public RsConfigSerializer -{ - public: - RsGeneralConfigSerialiser() :RsConfigSerializer(RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_GENERAL_CONFIG) {} - - virtual RsItem *create_item(uint8_t item_type, uint8_t item_subtype) const ; -}; - -#endif /* RS_CONFIG_ITEMS_SERIALISER_H */ diff --git a/libretroshare/src/rsitems/rsfiletransferitems.cc b/libretroshare/src/rsitems/rsfiletransferitems.cc deleted file mode 100644 index 3c34acf6a..000000000 --- a/libretroshare/src/rsitems/rsfiletransferitems.cc +++ /dev/null @@ -1,109 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsfiletransferitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstlvbase.h" -#include "rsitems/rsfiletransferitems.h" - -#include "serialiser/rstypeserializer.h" - -/*** - * #define RSSERIAL_DEBUG 1 - * #define DEBUG_TRANSFERS 1 -***/ - - -#ifdef DEBUG_TRANSFERS - #include "util/rsprint.h" -#endif - -#include - -void RsFileTransferDataRequestItem::clear() -{ - file.TlvClear(); - fileoffset = 0; - chunksize = 0; -} -void RsFileTransferDataItem::clear() -{ - fd.TlvClear(); -} - -void RsFileTransferDataRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,fileoffset,"fileoffset") ; - RsTypeSerializer::serial_process (j,ctx,chunksize, "chunksize") ; - RsTypeSerializer::serial_process(j,ctx,file, "file") ; -} - -void RsFileTransferDataItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,fd,"fd") ; -} - -void RsFileTransferChunkMapRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,is_client,"is_client") ; - RsTypeSerializer::serial_process (j,ctx,hash, "hash") ; -} - -void RsFileTransferChunkMapItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,is_client, "is_client") ; - RsTypeSerializer::serial_process (j,ctx,hash, "hash") ; - RsTypeSerializer::serial_process (j,ctx,compressed_map,"compressed_map") ; -} - -void RsFileTransferSingleChunkCrcRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,hash, "hash") ; - RsTypeSerializer::serial_process(j,ctx,chunk_number,"chunk_number") ; -} - -void RsFileTransferSingleChunkCrcItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,hash, "hash") ; - RsTypeSerializer::serial_process(j,ctx,chunk_number,"chunk_number") ; - RsTypeSerializer::serial_process (j,ctx,check_sum, "check_sum") ; -} - -//===================================================================================================// -// Serializer // -//===================================================================================================// - -RsItem *RsFileTransferSerialiser::create_item(uint16_t service_type,uint8_t item_type) const -{ - if(service_type != RS_SERVICE_TYPE_FILE_TRANSFER) - return NULL ; - - switch(item_type) - { - case RS_PKT_SUBTYPE_FT_DATA_REQUEST : return new RsFileTransferDataRequestItem(); - case RS_PKT_SUBTYPE_FT_DATA : return new RsFileTransferDataItem(); - case RS_PKT_SUBTYPE_FT_CHUNK_MAP_REQUEST : return new RsFileTransferChunkMapRequestItem(); - case RS_PKT_SUBTYPE_FT_CHUNK_MAP : return new RsFileTransferChunkMapItem(); - case RS_PKT_SUBTYPE_FT_CHUNK_CRC_REQUEST : return new RsFileTransferSingleChunkCrcRequestItem(); - case RS_PKT_SUBTYPE_FT_CHUNK_CRC : return new RsFileTransferSingleChunkCrcItem() ; - default: - return NULL ; - } -} diff --git a/libretroshare/src/rsitems/rsfiletransferitems.h b/libretroshare/src/rsitems/rsfiletransferitems.h deleted file mode 100644 index 60514e41f..000000000 --- a/libretroshare/src/rsitems/rsfiletransferitems.h +++ /dev/null @@ -1,189 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsfiletransferitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include - -#include "retroshare/rstypes.h" -#include "serialiser/rsserial.h" -#include "serialiser/rstlvfileitem.h" -#include "rsitems/rsitem.h" -#include "rsitems/rsserviceids.h" -#include "rsitems/itempriorities.h" - -#include "serialiser/rsserializer.h" - -const uint8_t RS_PKT_SUBTYPE_FT_DATA_REQUEST = 0x01; -const uint8_t RS_PKT_SUBTYPE_FT_DATA = 0x02; -const uint8_t RS_PKT_SUBTYPE_FT_CHUNK_MAP_REQUEST = 0x04; -const uint8_t RS_PKT_SUBTYPE_FT_CHUNK_MAP = 0x05; -const uint8_t RS_PKT_SUBTYPE_FT_CHUNK_CRC_REQUEST = 0x08; -const uint8_t RS_PKT_SUBTYPE_FT_CHUNK_CRC = 0x09; - -const uint8_t RS_PKT_SUBTYPE_FT_CACHE_ITEM = 0x0A; -const uint8_t RS_PKT_SUBTYPE_FT_CACHE_REQUEST = 0x0B; - -//const uint8_t RS_PKT_SUBTYPE_FT_TRANSFER = 0x03; -//const uint8_t RS_PKT_SUBTYPE_FT_CRC32_MAP_REQUEST = 0x06; -//const uint8_t RS_PKT_SUBTYPE_FT_CRC32_MAP = 0x07; - -/**************************************************************************/ - -class RsFileTransferItem: public RsItem -{ - public: - RsFileTransferItem(uint8_t ft_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_FILE_TRANSFER,ft_subtype) {} - - virtual ~RsFileTransferItem() {} - - virtual void clear() = 0 ; -}; - -class RsFileTransferDataRequestItem: public RsFileTransferItem -{ - public: - RsFileTransferDataRequestItem() :RsFileTransferItem(RS_PKT_SUBTYPE_FT_DATA_REQUEST) - { - setPriorityLevel(QOS_PRIORITY_RS_FILE_REQUEST) ; - } - virtual ~RsFileTransferDataRequestItem() {} - virtual void clear(); - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - // Private data part. - // - uint64_t fileoffset; /* start of data requested */ - uint32_t chunksize; /* size of data requested */ - RsTlvFileItem file; /* file information */ -}; - -/**************************************************************************/ - -class RsFileTransferDataItem: public RsFileTransferItem -{ - public: - RsFileTransferDataItem() :RsFileTransferItem(RS_PKT_SUBTYPE_FT_DATA) - { - setPriorityLevel(QOS_PRIORITY_RS_FILE_DATA) ; - } - virtual ~RsFileTransferDataItem() { clear() ; } - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - virtual void clear(); - - // Private data part. - // - RsTlvFileData fd; -}; - -class RsFileTransferChunkMapRequestItem: public RsFileTransferItem -{ - public: - RsFileTransferChunkMapRequestItem() :RsFileTransferItem(RS_PKT_SUBTYPE_FT_CHUNK_MAP_REQUEST) - { - setPriorityLevel(QOS_PRIORITY_RS_FILE_MAP_REQUEST) ; - } - virtual ~RsFileTransferChunkMapRequestItem() {} - virtual void clear() {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - // Private data part. - // - bool is_client ; // is the request for a client, or a server ? - RsFileHash hash ; // hash of the file for which we request the chunk map -}; - -class RsFileTransferChunkMapItem: public RsFileTransferItem -{ - public: - RsFileTransferChunkMapItem() - :RsFileTransferItem(RS_PKT_SUBTYPE_FT_CHUNK_MAP) - { - setPriorityLevel(QOS_PRIORITY_RS_FILE_MAP) ; - } - virtual ~RsFileTransferChunkMapItem() {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - virtual void clear() {} - - // Private data part. - // - bool is_client ; // is the request for a client, or a server ? - RsFileHash hash ; // hash of the file for which we request the chunk map - CompressedChunkMap compressed_map ; // Chunk map of the file. -}; - -class RsFileTransferSingleChunkCrcRequestItem: public RsFileTransferItem -{ - public: - RsFileTransferSingleChunkCrcRequestItem() :RsFileTransferItem(RS_PKT_SUBTYPE_FT_CHUNK_CRC_REQUEST) - { - setPriorityLevel(QOS_PRIORITY_RS_CHUNK_CRC_REQUEST) ; - } - virtual ~RsFileTransferSingleChunkCrcRequestItem() {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - virtual void clear() {} - - // Private data part. - // - RsFileHash hash ; // hash of the file for which we request the crc - uint32_t chunk_number ; // chunk number -}; - -class RsFileTransferSingleChunkCrcItem: public RsFileTransferItem -{ - public: - RsFileTransferSingleChunkCrcItem() :RsFileTransferItem(RS_PKT_SUBTYPE_FT_CHUNK_CRC) - { - setPriorityLevel(QOS_PRIORITY_RS_CHUNK_CRC) ; - } - virtual ~RsFileTransferSingleChunkCrcItem() {} - - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - virtual void clear() {} - - // Private data part. - // - RsFileHash hash ; // hash of the file for which we request the chunk map - uint32_t chunk_number ; - Sha1CheckSum check_sum ; // CRC32 map of the file. -}; - -/**************************************************************************/ - -class RsFileTransferSerialiser: public RsServiceSerializer -{ - public: - RsFileTransferSerialiser(): RsServiceSerializer(RS_SERVICE_TYPE_FILE_TRANSFER) {} - - virtual ~RsFileTransferSerialiser() {} - - RsItem *create_item(uint16_t service_type,uint8_t item_type) const ; - -}; - -/**************************************************************************/ - diff --git a/libretroshare/src/rsitems/rsgxschannelitems.cc b/libretroshare/src/rsitems/rsgxschannelitems.cc deleted file mode 100644 index 9ef37d746..000000000 --- a/libretroshare/src/rsitems/rsgxschannelitems.cc +++ /dev/null @@ -1,169 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxschannelitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include - -#include "rsgxschannelitems.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rsbaseserial.h" - -#include "serialiser/rstypeserializer.h" - -RsItem *RsGxsChannelSerialiser::create_item(uint16_t service_id,uint8_t item_subtype) const -{ - if(service_id != RS_SERVICE_GXS_TYPE_CHANNELS) - return NULL ; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_GXSCHANNEL_GROUP_ITEM: return new RsGxsChannelGroupItem() ; - case RS_PKT_SUBTYPE_GXSCHANNEL_POST_ITEM: return new RsGxsChannelPostItem(); - default: - return RsGxsCommentSerialiser::create_item(service_id,item_subtype) ; - } -} - -void RsGxsChannelGroupItem::clear() -{ - mDescription.clear(); - mImage.TlvClear(); -} - -bool RsGxsChannelGroupItem::fromChannelGroup(RsGxsChannelGroup &group, bool moveImage) -{ - clear(); - meta = group.mMeta; - mDescription = group.mDescription; - - if (moveImage) - { - mImage.binData.bin_data = group.mImage.mData; - mImage.binData.bin_len = group.mImage.mSize; - group.mImage.shallowClear(); - } - else - { - mImage.binData.setBinData(group.mImage.mData, group.mImage.mSize); - } - return true; -} - - - -bool RsGxsChannelGroupItem::toChannelGroup(RsGxsChannelGroup &group, bool moveImage) -{ - group.mMeta = meta; - group.mDescription = mDescription; - if (moveImage) - { - group.mImage.take((uint8_t *) mImage.binData.bin_data, mImage.binData.bin_len); - // mImage doesn't have a ShallowClear at the moment! - mImage.binData.TlvShallowClear(); - } - else - { - group.mImage.copy((uint8_t *) mImage.binData.bin_data, mImage.binData.bin_len); - } - return true; -} - -void RsGxsChannelGroupItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_DESCR,mDescription,"mDescription") ; - RsTypeSerializer::serial_process(j,ctx,mImage,"mImage") ; -} - -bool RsGxsChannelPostItem::fromChannelPost(RsGxsChannelPost &post, bool moveImage) -{ - clear(); - meta = post.mMeta; - mMsg = post.mMsg; - - if (moveImage) - { - mThumbnail.binData.bin_data = post.mThumbnail.mData; - mThumbnail.binData.bin_len = post.mThumbnail.mSize; - post.mThumbnail.shallowClear(); - } - else - { - mThumbnail.binData.setBinData(post.mThumbnail.mData, post.mThumbnail.mSize); - } - - std::list::iterator fit; - for(fit = post.mFiles.begin(); fit != post.mFiles.end(); ++fit) - { - RsTlvFileItem fi; - fi.name = fit->mName; - fi.filesize = fit->mSize; - fi.hash = fit->mHash; - mAttachment.items.push_back(fi); - } - return true; -} - - - -bool RsGxsChannelPostItem::toChannelPost(RsGxsChannelPost &post, bool moveImage) -{ - post.mMeta = meta; - post.mMsg = mMsg; - if (moveImage) - { - post.mThumbnail.take((uint8_t *) mThumbnail.binData.bin_data, mThumbnail.binData.bin_len); - // mThumbnail doesn't have a ShallowClear at the moment! - mThumbnail.binData.TlvShallowClear(); - } - else - { - post.mThumbnail.copy((uint8_t *) mThumbnail.binData.bin_data, mThumbnail.binData.bin_len); - } - - post.mAttachmentCount = 0; - post.mSize = 0; - std::list::iterator fit; - for(fit = mAttachment.items.begin(); fit != mAttachment.items.end(); ++fit) - { - RsGxsFile fi; - fi.mName = RsDirUtil::getTopDir(fit->name); - fi.mSize = fit->filesize; - fi.mHash = fit->hash; - - post.mFiles.push_back(fi); - post.mAttachmentCount++; - post.mSize += fi.mSize; - } - return true; -} - -void RsGxsChannelPostItem::clear() -{ - mMsg.clear(); - mAttachment.TlvClear(); - mThumbnail.TlvClear(); -} - -void RsGxsChannelPostItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_MSG,mMsg,"mMsg") ; - RsTypeSerializer::serial_process(j,ctx,mAttachment,"mAttachment") ; - RsTypeSerializer::serial_process(j,ctx,mThumbnail,"mThumbnail") ; -} diff --git a/libretroshare/src/rsitems/rsgxschannelitems.h b/libretroshare/src/rsitems/rsgxschannelitems.h deleted file mode 100644 index fa52c8cfc..000000000 --- a/libretroshare/src/rsitems/rsgxschannelitems.h +++ /dev/null @@ -1,93 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxschannelitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_GXS_CHANNEL_ITEMS_H -#define RS_GXS_CHANNEL_ITEMS_H - -#include - -#include "rsitems/rsserviceids.h" -#include "rsitems/rsgxscommentitems.h" -#include "rsitems/rsgxsitems.h" - -#include "serialiser/rstlvfileitem.h" -#include "serialiser/rstlvimage.h" - -#include "retroshare/rsgxschannels.h" - -#include "serialiser/rsserializer.h" - -#include "util/rsdir.h" - -const uint8_t RS_PKT_SUBTYPE_GXSCHANNEL_GROUP_ITEM = 0x02; -const uint8_t RS_PKT_SUBTYPE_GXSCHANNEL_POST_ITEM = 0x03; - -class RsGxsChannelGroupItem : public RsGxsGrpItem -{ -public: - - RsGxsChannelGroupItem(): RsGxsGrpItem(RS_SERVICE_GXS_TYPE_CHANNELS, RS_PKT_SUBTYPE_GXSCHANNEL_GROUP_ITEM) {} - virtual ~RsGxsChannelGroupItem() {} - - void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - // use conversion functions to transform: - bool fromChannelGroup(RsGxsChannelGroup &group, bool moveImage); - bool toChannelGroup(RsGxsChannelGroup &group, bool moveImage); - - std::string mDescription; - RsTlvImage mImage; -}; - -class RsGxsChannelPostItem : public RsGxsMsgItem -{ -public: - - RsGxsChannelPostItem(): RsGxsMsgItem(RS_SERVICE_GXS_TYPE_CHANNELS, RS_PKT_SUBTYPE_GXSCHANNEL_POST_ITEM) {} - virtual ~RsGxsChannelPostItem() {} - void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - // Slightly unusual structure. - // use conversion functions to transform: - bool fromChannelPost(RsGxsChannelPost &post, bool moveImage); - bool toChannelPost(RsGxsChannelPost &post, bool moveImage); - - std::string mMsg; - RsTlvFileSet mAttachment; - RsTlvImage mThumbnail; -}; - - -class RsGxsChannelSerialiser : public RsGxsCommentSerialiser -{ -public: - - RsGxsChannelSerialiser() :RsGxsCommentSerialiser(RS_SERVICE_GXS_TYPE_CHANNELS) {} - virtual ~RsGxsChannelSerialiser() {} - - virtual RsItem *create_item(uint16_t service_id,uint8_t item_subtype) const ; -}; - -#endif /* RS_GXS_CHANNEL_ITEMS_H */ diff --git a/libretroshare/src/rsitems/rsgxscircleitems.cc b/libretroshare/src/rsitems/rsgxscircleitems.cc deleted file mode 100644 index f93068b5b..000000000 --- a/libretroshare/src/rsitems/rsgxscircleitems.cc +++ /dev/null @@ -1,125 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxscircleitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include - -#include "rsgxscircleitems.h" - -#include "serialiser/rstypeserializer.h" - -//#define CIRCLE_DEBUG 1 - -RsItem *RsGxsCircleSerialiser::create_item(uint16_t service, uint8_t item_sub_id) const -{ - if(service != RS_SERVICE_GXS_TYPE_GXSCIRCLE) - return NULL ; - - switch(item_sub_id) - { - case RS_PKT_SUBTYPE_GXSCIRCLE_GROUP_ITEM: return new RsGxsCircleGroupItem(); -#ifdef TO_REMOVE - case RS_PKT_SUBTYPE_GXSCIRCLE_MSG_ITEM: return new RsGxsCircleMsgItem(); -#endif - case RS_PKT_SUBTYPE_GXSCIRCLE_SUBSCRIPTION_REQUEST_ITEM: return new RsGxsCircleSubscriptionRequestItem(); - default: - return NULL ; - } -} - -void RsGxsCircleSubscriptionRequestItem::clear() -{ - time_stamp = 0 ; - time_out = 0 ; - subscription_type = RsGxsCircleSubscriptionType::UNKNOWN; -} - -#ifdef TO_REMOVE -void RsGxsCircleMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - //RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,mMsg.stuff,"mMsg.stuff") ;//Should be this but not retrocompatible... - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,mMsg.stuff,"msg.stuff") ; -} - -void RsGxsCircleMsgItem::clear() -{ - mMsg.stuff.clear(); -} -#endif - -void RsGxsCircleSubscriptionRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,time_stamp,"time_stamp") ; - RsTypeSerializer::serial_process(j,ctx,time_out ,"time_out") ; - RsTypeSerializer::serial_process (j,ctx,subscription_type ,"subscription_type") ; -} - -void RsGxsCircleGroupItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,pgpIdSet,"pgpIdSet") ; - RsTypeSerializer::serial_process(j,ctx,gxsIdSet,"gxsIdSet") ; - RsTypeSerializer::serial_process(j,ctx,subCircleSet,"subCircleSet") ; -} - -void RsGxsCircleGroupItem::clear() -{ - pgpIdSet.TlvClear(); - gxsIdSet.TlvClear(); - subCircleSet.TlvClear(); -} - -bool RsGxsCircleGroupItem::convertFrom(const RsGxsCircleGroup &group) -{ - clear(); - - meta = group.mMeta; - - // Enforce the local rules. - if (meta.mCircleType == GXS_CIRCLE_TYPE_LOCAL) - { - pgpIdSet.ids = group.mLocalFriends; - } - else - { - gxsIdSet.ids = group.mInvitedMembers; - } - - subCircleSet.ids = group.mSubCircles; - return true; -} - -bool RsGxsCircleGroupItem::convertTo(RsGxsCircleGroup &group) const -{ - group.mMeta = meta; - - // Enforce the local rules. - if (meta.mCircleType == GXS_CIRCLE_TYPE_LOCAL) - { - group.mLocalFriends = pgpIdSet.ids; - } - else - { - group.mInvitedMembers = gxsIdSet.ids; - } - - group.mSubCircles = subCircleSet.ids; - return true; -} - diff --git a/libretroshare/src/rsitems/rsgxscircleitems.h b/libretroshare/src/rsitems/rsgxscircleitems.h deleted file mode 100644 index fb720e070..000000000 --- a/libretroshare/src/rsitems/rsgxscircleitems.h +++ /dev/null @@ -1,109 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxscircleitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_GXSCIRCLE_ITEMS_H -#define RS_GXSCIRCLE_ITEMS_H - -#include - -#include "rsitems/rsserviceids.h" - -#include "serialiser/rstlvitem.h" -#include "serialiser/rstlvstring.h" -#include "serialiser/rstlvidset.h" - -#include "rsitems/rsgxsitems.h" -#include "retroshare/rsgxscircles.h" - -const uint8_t RS_PKT_SUBTYPE_GXSCIRCLE_GROUP_ITEM = 0x02; -const uint8_t RS_PKT_SUBTYPE_GXSCIRCLE_MSG_ITEM = 0x03; -const uint8_t RS_PKT_SUBTYPE_GXSCIRCLE_SUBSCRIPTION_REQUEST_ITEM = 0x04; - -const uint16_t GXSCIRCLE_PGPIDSET = 0x0001; -const uint16_t GXSCIRCLE_GXSIDSET = 0x0002; -const uint16_t GXSCIRCLE_SUBCIRCLESET = 0x0003; - -// These classes are a mess. Needs proper item serialisation etc. - -class RsGxsCircleGroupItem : public RsGxsGrpItem -{ - -public: - - RsGxsCircleGroupItem(): RsGxsGrpItem(RS_SERVICE_GXS_TYPE_GXSCIRCLE, RS_PKT_SUBTYPE_GXSCIRCLE_GROUP_ITEM) {} - virtual ~RsGxsCircleGroupItem() {} - - void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - bool convertFrom(const RsGxsCircleGroup &group); - bool convertTo(RsGxsCircleGroup &group) const; - - // DIFFERENT FROM OTHER ONES, as stupid serialisation otherwise. - RsTlvPgpIdSet pgpIdSet; // For Local Groups. - RsTlvGxsIdSet gxsIdSet; // For External Groups. - RsTlvGxsCircleIdSet subCircleSet; -}; - -#ifdef TO_REMOVE -class RsGxsCircleMsgItem : public RsGxsMsgItem -{ -public: - - RsGxsCircleMsgItem(): RsGxsMsgItem(RS_SERVICE_GXS_TYPE_GXSCIRCLE, RS_PKT_SUBTYPE_GXSCIRCLE_MSG_ITEM) {} - virtual ~RsGxsCircleMsgItem() {} - void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsGxsCircleMsg mMsg; -}; -#endif - -class RsGxsCircleSubscriptionRequestItem: public RsGxsMsgItem -{ -public: - - RsGxsCircleSubscriptionRequestItem() : RsGxsMsgItem(RS_SERVICE_GXS_TYPE_GXSCIRCLE, RS_PKT_SUBTYPE_GXSCIRCLE_SUBSCRIPTION_REQUEST_ITEM) { } - virtual ~RsGxsCircleSubscriptionRequestItem() {} - - void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t time_stamp ; - uint32_t time_out ; - RsGxsCircleSubscriptionType subscription_type ; -}; - -class RsGxsCircleSerialiser : public RsServiceSerializer -{ -public: - - RsGxsCircleSerialiser() - :RsServiceSerializer(RS_SERVICE_GXS_TYPE_GXSCIRCLE) {} - virtual ~RsGxsCircleSerialiser() {} - - virtual RsItem *create_item(uint16_t service, uint8_t item_sub_id) const; -}; - -#endif /* RS_GXSCIRCLE_ITEMS_H */ diff --git a/libretroshare/src/rsitems/rsgxscommentitems.cc b/libretroshare/src/rsitems/rsgxscommentitems.cc deleted file mode 100644 index 2386fb069..000000000 --- a/libretroshare/src/rsitems/rsgxscommentitems.cc +++ /dev/null @@ -1,55 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxscommentitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2013 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include - -#include "rsgxscommentitems.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstypeserializer.h" - -//#define GXSCOMMENT_DEBUG 1 - -RsItem *RsGxsCommentSerialiser::create_item(uint16_t service_id,uint8_t item_subtype) const -{ - if(service_id != getRsItemService(PacketId())) - return NULL ; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_GXSCOMMENT_COMMENT_ITEM: return new RsGxsCommentItem(getRsItemService(PacketId())) ; - case RS_PKT_SUBTYPE_GXSCOMMENT_VOTE_ITEM: return new RsGxsVoteItem(getRsItemService(PacketId())); - default: - return NULL ; - } -} - - -void RsGxsCommentItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,1,mMsg.mComment,"mMsg.mComment") ; -} - -void RsGxsVoteItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,mMsg.mVoteType,"mMsg.mVoteType") ; -} - diff --git a/libretroshare/src/rsitems/rsgxscommentitems.h b/libretroshare/src/rsitems/rsgxscommentitems.h deleted file mode 100644 index c35c6c2aa..000000000 --- a/libretroshare/src/rsitems/rsgxscommentitems.h +++ /dev/null @@ -1,74 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxscommentitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_GXS_COMMENT_ITEMS_H -#define RS_GXS_COMMENT_ITEMS_H - -#include - -#include "rsitems/rsserviceids.h" - -#include "rsgxsitems.h" - -#include "retroshare/rsgxscommon.h" - -const uint8_t RS_PKT_SUBTYPE_GXSCOMMENT_COMMENT_ITEM = 0xf1; -const uint8_t RS_PKT_SUBTYPE_GXSCOMMENT_VOTE_ITEM = 0xf2; - -class RsGxsCommentItem : public RsGxsMsgItem -{ -public: - - RsGxsCommentItem(uint16_t service_type): RsGxsMsgItem(service_type, RS_PKT_SUBTYPE_GXSCOMMENT_COMMENT_ITEM) {} - virtual ~RsGxsCommentItem() {} - void clear(){} - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */); - - RsGxsComment mMsg; -}; - - -class RsGxsVoteItem : public RsGxsMsgItem -{ -public: - - RsGxsVoteItem(uint16_t service_type): RsGxsMsgItem(service_type, RS_PKT_SUBTYPE_GXSCOMMENT_VOTE_ITEM) {} - virtual ~RsGxsVoteItem() {} - void clear(){} - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */); - - RsGxsVote mMsg; -}; - -class RsGxsCommentSerialiser : public RsServiceSerializer -{ -public: - - RsGxsCommentSerialiser(uint16_t service_type) :RsServiceSerializer(service_type) {} - virtual ~RsGxsCommentSerialiser() {} - - virtual RsItem *create_item(uint16_t service_id,uint8_t item_subtype) const ; -}; - -#endif /* RS_GXS_COMMENT_ITEMS_H */ - diff --git a/libretroshare/src/rsitems/rsgxsforumitems.cc b/libretroshare/src/rsitems/rsgxsforumitems.cc deleted file mode 100644 index 1918fd980..000000000 --- a/libretroshare/src/rsitems/rsgxsforumitems.cc +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxsforumitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include - -#include "rsgxsforumitems.h" - -#include "serialiser/rstypeserializer.h" - -//#define GXSFORUM_DEBUG 1 - -RsItem *RsGxsForumSerialiser::create_item(uint16_t service_id,uint8_t item_subtype) const -{ - if(service_id != RS_SERVICE_GXS_TYPE_FORUMS) - return NULL ; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_GXSFORUM_GROUP_ITEM: return new RsGxsForumGroupItem(); - case RS_PKT_SUBTYPE_GXSFORUM_MESSAGE_ITEM: return new RsGxsForumMsgItem(); - default: - return NULL ; - } -} -void RsGxsForumGroupItem::clear() -{ - mGroup.mDescription.clear(); -} - -void RsGxsForumGroupItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DESCR,mGroup.mDescription,"mGroup.Description"); - - // This is for backward compatibility: normally all members are serialized, but in the previous version, these members are missing. - - if(j == RsGenericSerializer::DESERIALIZE && ctx.mOffset == ctx.mSize) - return ; - - RsTypeSerializer::serial_process(j,ctx,mGroup.mAdminList ,"admin_list" ) ; - RsTypeSerializer::serial_process(j,ctx,mGroup.mPinnedPosts,"pinned_posts") ; -} - -void RsGxsForumMsgItem::clear() -{ - mMsg.mMsg.clear(); -} - -void RsGxsForumMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,mMsg.mMsg,"mGroup.Description"); -} - - - diff --git a/libretroshare/src/rsitems/rsgxsforumitems.h b/libretroshare/src/rsitems/rsgxsforumitems.h deleted file mode 100644 index b1f5fb629..000000000 --- a/libretroshare/src/rsitems/rsgxsforumitems.h +++ /dev/null @@ -1,125 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxsforumitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Robert Fernie * - * Copyright (C) 2018-2021 Gioacchino Mazzurco * - * Copyright (C) 2019-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include - -#include "rsitems/rsserviceids.h" -#include "rsitems/rsgxsitems.h" - -#include "serialiser/rsserializer.h" - -#include "retroshare/rsgxsforums.h" - -enum class RsGxsForumsItems : uint8_t -{ - GROUP_ITEM = 0x02, - MESSAGE_ITEM = 0x03, - SEARCH_REQUEST = 0x04, - SEARCH_REPLY = 0x05, -}; - -RS_DEPRECATED_FOR(RsGxsForumsItems) -const uint8_t RS_PKT_SUBTYPE_GXSFORUM_GROUP_ITEM = 0x02; - -RS_DEPRECATED_FOR(RsGxsForumsItems) -const uint8_t RS_PKT_SUBTYPE_GXSFORUM_MESSAGE_ITEM = 0x03; - -class RsGxsForumGroupItem : public RsGxsGrpItem -{ - -public: - - RsGxsForumGroupItem(): RsGxsGrpItem(RS_SERVICE_GXS_TYPE_FORUMS, RS_PKT_SUBTYPE_GXSFORUM_GROUP_ITEM) {} - virtual ~RsGxsForumGroupItem() {} - - void clear(); - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsGxsForumGroup mGroup; -}; - -class RsGxsForumMsgItem : public RsGxsMsgItem -{ -public: - - RsGxsForumMsgItem(): RsGxsMsgItem(RS_SERVICE_GXS_TYPE_FORUMS, RS_PKT_SUBTYPE_GXSFORUM_MESSAGE_ITEM) {} - virtual ~RsGxsForumMsgItem() {} - void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsGxsForumMsg mMsg; -}; - -struct RsGxsForumsSearchRequest : RsSerializable -{ - RsGxsForumsSearchRequest() : mType(RsGxsForumsItems::SEARCH_REQUEST) {} - - /// Just for easier back and forward compatibility - RsGxsForumsItems mType; - - /// Store search match string - std::string mQuery; - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(mType); - RS_SERIAL_PROCESS(mQuery); - } - - ~RsGxsForumsSearchRequest() override = default; -}; - -struct RsGxsForumsSearchReply : RsSerializable -{ - RsGxsForumsSearchReply() : mType(RsGxsForumsItems::SEARCH_REPLY) {} - - /// Just for easier back and forward compatibility - RsGxsForumsItems mType; - - /// Results storage - std::vector mResults; - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(mType); - RS_SERIAL_PROCESS(mResults); - } - - ~RsGxsForumsSearchReply() override = default; -}; - -class RsGxsForumSerialiser : public RsServiceSerializer -{ -public: - RsGxsForumSerialiser() :RsServiceSerializer(RS_SERVICE_GXS_TYPE_FORUMS) {} - virtual ~RsGxsForumSerialiser() {} - - virtual RsItem *create_item(uint16_t service_id,uint8_t item_subtype) const ; -}; diff --git a/libretroshare/src/rsitems/rsgxsiditems.cc b/libretroshare/src/rsitems/rsgxsiditems.cc deleted file mode 100644 index 0c37c110e..000000000 --- a/libretroshare/src/rsitems/rsgxsiditems.cc +++ /dev/null @@ -1,121 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxsiditems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include - -#include "rsgxsiditems.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstlvstring.h" -#include "util/rsstring.h" - -#include "serialiser/rstypeserializer.h" - -// #define GXSID_DEBUG 1 - -RsItem *RsGxsIdSerialiser::create_item(uint16_t service_id,uint8_t item_subtype) const -{ - if(service_id != RS_SERVICE_GXS_TYPE_GXSID) - return NULL ; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_GXSID_GROUP_ITEM : return new RsGxsIdGroupItem (); - case RS_PKT_SUBTYPE_GXSID_LOCAL_INFO_ITEM: return new RsGxsIdLocalInfoItem() ; - default: - return NULL ; - } -} -void RsGxsIdLocalInfoItem::clear() -{ - mTimeStamps.clear() ; -} -void RsGxsIdGroupItem::clear() -{ - mPgpIdHash.clear(); - mPgpIdSign.clear(); - - mRecognTags.clear(); - mImage.TlvClear(); -} -void RsGxsIdLocalInfoItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,mTimeStamps,"mTimeStamps") ; - RsTypeSerializer::serial_process(j,ctx,mContacts,"mContacts") ; -} - -void RsGxsIdGroupItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,mPgpIdHash,"mPgpIdHash") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_SIGN,mPgpIdSign,"mPgpIdSign") ; - - RsTlvStringSetRef rset(TLV_TYPE_RECOGNSET,mRecognTags) ; - - RsTypeSerializer::serial_process(j,ctx,rset,"mRecognTags") ; - - // image is optional - - if(j == RsGenericSerializer::DESERIALIZE && ctx.mOffset == ctx.mSize) - return ; - - RsTypeSerializer::serial_process(j,ctx,mImage,"mImage") ; -} - -bool RsGxsIdGroupItem::fromGxsIdGroup(RsGxsIdGroup &group, bool moveImage) -{ - clear(); - meta = group.mMeta; - mPgpIdHash = group.mPgpIdHash; - mPgpIdSign = group.mPgpIdSign; - mRecognTags = group.mRecognTags; - - if (moveImage) - { - mImage.binData.bin_data = group.mImage.mData; - mImage.binData.bin_len = group.mImage.mSize; - group.mImage.shallowClear(); - } - else - { - mImage.binData.setBinData(group.mImage.mData, group.mImage.mSize); - } - return true ; -} -bool RsGxsIdGroupItem::toGxsIdGroup(RsGxsIdGroup &group, bool moveImage) -{ - group.mMeta = meta; - group.mPgpIdHash = mPgpIdHash; - group.mPgpIdSign = mPgpIdSign; - group.mRecognTags = mRecognTags; - - if (moveImage) - { - group.mImage.take((uint8_t *) mImage.binData.bin_data, mImage.binData.bin_len); - // mImage doesn't have a ShallowClear at the moment! - mImage.binData.TlvShallowClear(); - } - else - { - group.mImage.copy((uint8_t *) mImage.binData.bin_data, mImage.binData.bin_len); - } - return true ; -} - diff --git a/libretroshare/src/rsitems/rsgxsiditems.h b/libretroshare/src/rsitems/rsgxsiditems.h deleted file mode 100644 index e18ae9759..000000000 --- a/libretroshare/src/rsitems/rsgxsiditems.h +++ /dev/null @@ -1,97 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxsiditems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Robert Fernie * - * Copyright (C) 2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include - -#include "rsitems/rsserviceids.h" -#include "serialiser/rsserial.h" - -#include "rsgxsitems.h" -#include "retroshare/rsidentity.h" - -//const uint8_t RS_PKT_SUBTYPE_GXSID_GROUP_ITEM_deprecated = 0x02; - -const uint8_t RS_PKT_SUBTYPE_GXSID_GROUP_ITEM = 0x02; -const uint8_t RS_PKT_SUBTYPE_GXSID_OPINION_ITEM = 0x03; -const uint8_t RS_PKT_SUBTYPE_GXSID_COMMENT_ITEM = 0x04; -const uint8_t RS_PKT_SUBTYPE_GXSID_LOCAL_INFO_ITEM = 0x05; - -class RsGxsIdItem: public RsGxsGrpItem -{ - public: - RsGxsIdItem(uint8_t item_subtype) : RsGxsGrpItem(RS_SERVICE_GXS_TYPE_GXSID,item_subtype) {} -}; - -class RsGxsIdGroupItem : public RsGxsIdItem -{ -public: - - RsGxsIdGroupItem(): RsGxsIdItem(RS_PKT_SUBTYPE_GXSID_GROUP_ITEM) {} - virtual ~RsGxsIdGroupItem() {} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - virtual void clear(); - - bool fromGxsIdGroup(RsGxsIdGroup &group, bool moveImage); - bool toGxsIdGroup(RsGxsIdGroup &group, bool moveImage); - - Sha1CheckSum mPgpIdHash; - - /** Need a signature as proof - otherwise anyone could add others Hashes. - * This is a string, as the length is variable. - * TODO: this should actually be a byte array (pointer+size), using an - * std::string breaks the JSON serialization. - * Be careful refactoring this as it may break retrocompatibility as this - * item is sent over the network */ - std::string mPgpIdSign; - - /// Unused - RS_DEPRECATED std::list mRecognTags; - - /// Avatar - RsTlvImage mImage; -}; - -struct RsGxsIdLocalInfoItem : public RsGxsIdItem -{ - RsGxsIdLocalInfoItem(): RsGxsIdItem(RS_PKT_SUBTYPE_GXSID_LOCAL_INFO_ITEM) {} - virtual ~RsGxsIdLocalInfoItem() {} - - virtual void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - std::map mTimeStamps ; - std::set mContacts ; -}; - -class RsGxsIdSerialiser : public RsServiceSerializer -{ -public: - RsGxsIdSerialiser() :RsServiceSerializer(RS_SERVICE_GXS_TYPE_GXSID) {} - virtual ~RsGxsIdSerialiser() {} - - virtual RsItem *create_item(uint16_t service_id,uint8_t item_subtype) const ; -}; diff --git a/libretroshare/src/rsitems/rsgxsitems.cc b/libretroshare/src/rsitems/rsgxsitems.cc deleted file mode 100644 index 22c379f9e..000000000 --- a/libretroshare/src/rsitems/rsgxsitems.cc +++ /dev/null @@ -1,126 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxsitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * Copyright 2012-2012 by Christopher Evi-Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "serialiser/rstypeserializer.h" -#include "serialiser/rsbaseserial.h" -#include "rsgxsitems.h" -#include "gxs/rsgxsdata.h" -#include - - void RsMsgMetaData::operator =(const RsGxsMsgMetaData& rGxsMeta) - { - this->mAuthorId = rGxsMeta.mAuthorId; - this->mChildTs = rGxsMeta.mChildTs; - this->mGroupId = rGxsMeta.mGroupId; - this->mMsgFlags = rGxsMeta.mMsgFlags; - this->mMsgId = rGxsMeta.mMsgId; - this->mMsgName = rGxsMeta.mMsgName; - this->mMsgStatus = rGxsMeta.mMsgStatus; - this->mOrigMsgId = rGxsMeta.mOrigMsgId; - this->mParentId = rGxsMeta.mParentId; - this->mPublishTs = rGxsMeta.mPublishTs; - this->mThreadId = rGxsMeta.mThreadId; - this->mServiceString = rGxsMeta.mServiceString; - } - - - void RsGroupMetaData::operator =(const RsGxsGrpMetaData& rGxsMeta) - { - this->mAuthorId = rGxsMeta.mAuthorId; - this->mGroupFlags = rGxsMeta.mGroupFlags; - this->mGroupId = rGxsMeta.mGroupId; - this->mGroupStatus = rGxsMeta.mGroupStatus; - this->mLastPost = rGxsMeta.mLastPost; - this->mVisibleMsgCount = rGxsMeta.mVisibleMsgCount; - this->mPop = rGxsMeta.mPop; - this->mPublishTs = rGxsMeta.mPublishTs; - this->mSubscribeFlags = rGxsMeta.mSubscribeFlags; - this->mGroupName = rGxsMeta.mGroupName; - this->mServiceString = rGxsMeta.mServiceString; - this->mSignFlags = rGxsMeta.mSignFlags; - this->mCircleId = rGxsMeta.mCircleId; - this->mCircleType = rGxsMeta.mCircleType; - this->mInternalCircle = rGxsMeta.mInternalCircle; - this->mOriginator = rGxsMeta.mOriginator; - this->mAuthenFlags = rGxsMeta.mAuthenFlags; - this->mParentGrpId = rGxsMeta.mParentGrpId; - } - -template<> uint32_t RsTypeSerializer::serial_size(const TurtleGxsInfo& i) -{ - uint32_t s = 0 ; - - s += 2 ; // service_id - s += i.group_id.SIZE_IN_BYTES ; - s += GetTlvStringSize(i.name) ; - - return s; -} - -template<> bool RsTypeSerializer::deserialize(const uint8_t data[],uint32_t size,uint32_t& offset,TurtleGxsInfo& i) -{ - uint32_t saved_offset = offset ; - bool ok = true ; - - ok &= getRawUInt16(data, size, &offset, &i.service_id); // service_id - ok &= i.group_id.deserialise(data, size, offset); // group_id - ok &= GetTlvString(data, size, &offset, TLV_TYPE_STR_NAME, i.name); // group name - - if(!ok) - offset = saved_offset ; - - return ok; -} - -template<> bool RsTypeSerializer::serialize(uint8_t data[],uint32_t size,uint32_t& offset,const TurtleGxsInfo& i) -{ - uint32_t saved_offset = offset ; - bool ok = true ; - - ok &= setRawUInt16(data, size, &offset, i.service_id); // service_id - ok &= i.group_id.serialise(data, size, offset); // group_id - ok &= SetTlvString(data, size, &offset, TLV_TYPE_STR_NAME, i.name); // group name - - if(!ok) - offset = saved_offset ; - - return ok; -} - -template<> void RsTypeSerializer::print_data(const std::string& n, const TurtleGxsInfo& i) -{ - std::cerr << " [GXS Info ] " << n << " group_id=" << i.group_id << " service=" << std::hex << i.service_id << std::dec << ", name=" << i.name << std::endl; -} - -void RsTurtleGxsSearchResultGroupSummaryItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,result,"result") ; -} -void RsTurtleGxsSearchResultGroupDataItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::TlvMemBlock_proxy prox(encrypted_nxs_group_data,encrypted_nxs_group_data_len) ; - RsTypeSerializer::serial_process(j,ctx,prox,"encrypted_nxs_data") ; -} - -RS_TYPE_SERIALIZER_FROM_JSON_NOT_IMPLEMENTED_DEF(TurtleGxsInfo) -RS_TYPE_SERIALIZER_TO_JSON_NOT_IMPLEMENTED_DEF(TurtleGxsInfo) - diff --git a/libretroshare/src/rsitems/rsgxsitems.h b/libretroshare/src/rsitems/rsgxsitems.h deleted file mode 100644 index 9b47d5d6d..000000000 --- a/libretroshare/src/rsitems/rsgxsitems.h +++ /dev/null @@ -1,134 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxsitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * Copyright 2012-2012 by Christopher Evi-Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RSGXSITEMS_H -#define RSGXSITEMS_H - -#include "rsitems/rsitem.h" -#include "rsitems/rsserviceids.h" -#include "util/rstime.h" -#include "retroshare/rsgxsifacetypes.h" - -class RsGxsGrpItem : public RsItem -{ - -public: - - RsGxsGrpItem(uint16_t service, uint8_t subtype) - : RsItem(RS_PKT_VERSION_SERVICE, service, subtype) { return; } - virtual ~RsGxsGrpItem(){} - - RsGroupMetaData meta; -}; - -class RsGxsMsgItem : public RsItem -{ - -public: - RsGxsMsgItem(uint16_t service, uint8_t subtype) - : RsItem(RS_PKT_VERSION_SERVICE, service, subtype) { return; } - virtual ~RsGxsMsgItem(){} - - RsMsgMetaData meta; -}; - -// We should make these items templates or generic classes so that each GXS service will handle them on its own. - -static const uint8_t RS_PKT_SUBTYPE_GXS_SUBSTRING_SEARCH_ITEM = 0x20 ; -static const uint8_t RS_PKT_SUBTYPE_GXS_GROUP_SEARCH_ITEM = 0x21 ; -static const uint8_t RS_PKT_SUBTYPE_GXS_GROUP_SUMMARY_ITEM = 0x22 ; -static const uint8_t RS_PKT_SUBTYPE_GXS_GROUP_DATA_ITEM = 0x23 ; - -class RsGxsTurtleSubStringSearchItem: public RsItem -{ - public: - RsGxsTurtleSubStringSearchItem(uint16_t service): RsItem(RS_PKT_VERSION_SERVICE,service,RS_PKT_SUBTYPE_GXS_SUBSTRING_SEARCH_ITEM) {} - virtual ~RsGxsTurtleSubStringSearchItem() {} - - std::string match_string ; // string to match - - std::string GetKeywords() { return match_string; } - void clear() { match_string.clear() ; } - - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -class RsGxsTurtleGroupSearchItem: public RsItem -{ - public: - RsGxsTurtleGroupSearchItem(uint16_t service): RsItem(RS_PKT_VERSION_SERVICE,service,RS_PKT_SUBTYPE_GXS_GROUP_SEARCH_ITEM) {} - virtual ~RsGxsTurtleGroupSearchItem() {} - - uint16_t service_id ; // searvice to search - Sha1CheckSum hashed_group_id ; // the group ID is hashed in order to keep it private. - - std::string GetKeywords() { return std::string("Group request for [hashed] ")+hashed_group_id.toStdString() ; } - void clear() { hashed_group_id.clear() ; } - - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -struct TurtleGxsInfo -{ - uint16_t service_id ; - RsGxsGroupId group_id ; - RsGxsId author; - std::string name ; - std::string description ; - rstime_t last_post ; - uint32_t number_of_posts ; -}; - -class RsTurtleGxsSearchResultGroupSummaryItem: public RsItem -{ - public: - RsTurtleGxsSearchResultGroupSummaryItem(uint16_t service) : RsItem(RS_PKT_VERSION_SERVICE,service,RS_PKT_SUBTYPE_GXS_GROUP_SUMMARY_ITEM){} - virtual ~RsTurtleGxsSearchResultGroupSummaryItem() {} - - std::list result ; - - void clear() { result.clear() ; } - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -class RsTurtleGxsSearchResultGroupDataItem: public RsItem -{ - public: - RsTurtleGxsSearchResultGroupDataItem(uint16_t service) : RsItem(RS_PKT_VERSION_SERVICE,service,RS_PKT_SUBTYPE_GXS_GROUP_DATA_ITEM){} - virtual ~RsTurtleGxsSearchResultGroupDataItem() {} - - unsigned char *encrypted_nxs_group_data; // data is encrypted with group ID. Only the requester, or anyone who already know the group id can decrypt. - uint32_t encrypted_nxs_group_data_len ; - - void clear() { free(encrypted_nxs_group_data); encrypted_nxs_group_data=NULL; encrypted_nxs_group_data_len=0; } - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - - - - - -#endif // RSGXSITEMS_H diff --git a/libretroshare/src/rsitems/rsgxsrecognitems.cc b/libretroshare/src/rsitems/rsgxsrecognitems.cc deleted file mode 100644 index 4113a051c..000000000 --- a/libretroshare/src/rsitems/rsgxsrecognitems.cc +++ /dev/null @@ -1,114 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxsrecogitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013-2013 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "rsitems/rsgxsrecognitems.h" -#include "serialiser/rstypeserializer.h" - -/*** -#define RSSERIAL_DEBUG 1 -***/ - -#include - -/*************************************************************************/ - -RsItem *RsGxsRecognSerialiser::create_item(uint16_t service, uint8_t item_sub_id) const -{ - if(service != RS_SERVICE_TYPE_GXS_RECOGN) - return NULL ; - - switch(item_sub_id) - { - case RS_PKT_SUBTYPE_RECOGN_REQ: return new RsGxsRecognReqItem(); - case RS_PKT_SUBTYPE_RECOGN_SIGNER: return new RsGxsRecognSignerItem(); - case RS_PKT_SUBTYPE_RECOGN_TAG: return new RsGxsRecognTagItem(); - default: - return NULL ; - } -} - -void RsGxsRecognReqItem::clear() -{ - issued_at = 0; - period = 0; - tag_class = 0; - tag_type = 0; - - identity.clear(); - nickname.clear(); - comment.clear(); - - sign.TlvClear(); - -} -void RsGxsRecognReqItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,issued_at ,"issued_at") ; - RsTypeSerializer::serial_process (j,ctx,period ,"period") ; - RsTypeSerializer::serial_process (j,ctx,tag_class ,"tag_class") ; - RsTypeSerializer::serial_process (j,ctx,tag_type ,"tag_type") ; - RsTypeSerializer::serial_process (j,ctx,identity ,"identity") ; - RsTypeSerializer::serial_process (j,ctx,1,nickname ,"nickname") ; - RsTypeSerializer::serial_process (j,ctx,1,comment ,"comment") ; - RsTypeSerializer::serial_process(j,ctx,sign ,"sign") ; -} - -void RsGxsRecognTagItem::clear() -{ - valid_from = 0; - valid_to = 0; - - tag_class = 0; - tag_type = 0; - - identity.clear(); - nickname.clear(); - - sign.TlvClear(); -} - -void RsGxsRecognTagItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,valid_from ,"valid_from") ; - RsTypeSerializer::serial_process (j,ctx,valid_to ,"valid_to") ; - RsTypeSerializer::serial_process (j,ctx,tag_class ,"tag_class") ; - RsTypeSerializer::serial_process (j,ctx,tag_type ,"tag_type") ; - RsTypeSerializer::serial_process (j,ctx,identity ,"identity"); - RsTypeSerializer::serial_process (j,ctx,1,nickname ,"nickname") ; - RsTypeSerializer::serial_process(j,ctx,sign ,"sign") ; -} - -void RsGxsRecognSignerItem::clear() -{ - signing_classes.TlvClear(); - key.TlvClear(); - sign.TlvClear(); -} - -void RsGxsRecognSignerItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,signing_classes ,"signing_classes") ; - RsTypeSerializer::serial_process(j,ctx,key ,"key"); - RsTypeSerializer::serial_process(j,ctx,sign ,"sign") ; -} - - - diff --git a/libretroshare/src/rsitems/rsgxsrecognitems.h b/libretroshare/src/rsitems/rsgxsrecognitems.h deleted file mode 100644 index 3e049f0c2..000000000 --- a/libretroshare/src/rsitems/rsgxsrecognitems.h +++ /dev/null @@ -1,136 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxsrecogitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013-2013 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_GXS_RECOG_ITEMS_H -#define RS_GXS_RECOG_ITEMS_H - -#include - -#include "rsitems/rsitem.h" -#include "rsitems/rsserviceids.h" -#include "rsitems/itempriorities.h" - -#include "serialiser/rstlvkeys.h" -#include "serialiser/rstlvidset.h" - -#if 0 -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvtypes.h" - -#endif - -#include "retroshare/rsgxsifacetypes.h" - -/**************************************************************************/ - -#define RS_PKT_SUBTYPE_RECOGN_REQ 0x01 -#define RS_PKT_SUBTYPE_RECOGN_TAG 0x02 -#define RS_PKT_SUBTYPE_RECOGN_SIGNER 0x03 - - -class RsGxsRecognReqItem: public RsItem -{ -public: - RsGxsRecognReqItem() - :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_RECOGN, RS_PKT_SUBTYPE_RECOGN_REQ) - , issued_at(0), period(0), tag_class(0), tag_type(0) - { - setPriorityLevel(QOS_PRIORITY_DEFAULT); - return; - } - virtual ~RsGxsRecognReqItem(){} - virtual void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t issued_at; - uint32_t period; - uint16_t tag_class; - uint16_t tag_type; - - RsGxsId identity; - std::string nickname; - std::string comment; - - RsTlvKeySignature sign; -}; - - -class RsGxsRecognTagItem: public RsItem -{ - public: - RsGxsRecognTagItem() - :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_RECOGN, RS_PKT_SUBTYPE_RECOGN_TAG) - , valid_from(0), valid_to(0), tag_class(0), tag_type(0) - { - setPriorityLevel(QOS_PRIORITY_DEFAULT); - return; - } - virtual ~RsGxsRecognTagItem(){} - virtual void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t valid_from; - uint32_t valid_to; - uint16_t tag_class; - uint16_t tag_type; - - RsGxsId identity; - std::string nickname; - - RsTlvKeySignature sign; -}; - - -class RsGxsRecognSignerItem: public RsItem -{ -public: - RsGxsRecognSignerItem() :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_RECOGN, RS_PKT_SUBTYPE_RECOGN_SIGNER) - { - setPriorityLevel(QOS_PRIORITY_DEFAULT); - return; - } - virtual ~RsGxsRecognSignerItem(){} - virtual void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsTlvServiceIdSet signing_classes; - RsTlvPublicRSAKey key; // has from->to, and flags. - RsTlvKeySignature sign; -}; - - -class RsGxsRecognSerialiser: public RsServiceSerializer -{ - public: - RsGxsRecognSerialiser() :RsServiceSerializer(RS_SERVICE_TYPE_GXS_RECOGN) {} - virtual ~RsGxsRecognSerialiser() {} - - virtual RsItem *create_item(uint16_t service, uint8_t item_sub_id) const; -}; - -/**************************************************************************/ - -#endif /* RS_GXS_RECOGN_ITEMS_H */ - - diff --git a/libretroshare/src/rsitems/rsgxsreputationitems.cc b/libretroshare/src/rsitems/rsgxsreputationitems.cc deleted file mode 100644 index 97d33e3d1..000000000 --- a/libretroshare/src/rsitems/rsgxsreputationitems.cc +++ /dev/null @@ -1,106 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxsreputationitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include -#include "util/rstime.h" -#include "serialiser/rsbaseserial.h" -#include "rsitems/rsgxsreputationitems.h" - -#include "serialiser/rstypeserializer.h" - -/*** -#define RSSERIAL_DEBUG 1 -***/ - -#include - -/*************************************************************************/ - -void RsGxsReputationSetItem::clear() -{ - mOpinions.clear() ; -} - -void RsGxsReputationUpdateItem::clear() -{ - mOpinions.clear() ; -} - -void RsGxsReputationBannedNodeSetItem::clear() -{ - mKnownIdentities.TlvClear(); -} - -void RsGxsReputationConfigItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,mPeerId,"mPeerId") ; - RsTypeSerializer::serial_process(j,ctx,mLatestUpdate,"mLatestUpdate") ; - RsTypeSerializer::serial_process(j,ctx,mLastQuery,"mLastQuery") ; -} - -void RsGxsReputationBannedNodeSetItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,mPgpId,"mPgpId") ; - RsTypeSerializer::serial_process (j,ctx,mLastActivityTS,"mLastActivityTS") ; - RsTypeSerializer::serial_process(j,ctx,mKnownIdentities,"mKnownIdentities") ; -} - -void RsGxsReputationSetItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,mGxsId,"mGxsId") ; - RsTypeSerializer::serial_process(j,ctx,mOwnOpinion,"mOwnOpinion") ; - RsTypeSerializer::serial_process(j,ctx,mOwnOpinionTS,"mOwnOpinionTS") ; - RsTypeSerializer::serial_process(j,ctx,mIdentityFlags,"mIdentityFlags") ; - RsTypeSerializer::serial_process(j,ctx,mLastUsedTS,"mLastUsedTS") ; - RsTypeSerializer::serial_process (j,ctx,mOwnerNodeId,"mOwnerNodeId") ; - RsTypeSerializer::serial_process (j,ctx,mOpinions,"mOpinions") ; -} - -void RsGxsReputationUpdateItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,mLatestUpdate,"mLatestUpdate") ; - RsTypeSerializer::serial_process (j,ctx,mOpinions,"mOpinions") ; -} -void RsGxsReputationRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,mLastUpdate,"mLastUpdate") ; -} - -/*************************************************************************/ - -RsItem *RsGxsReputationSerialiser::create_item(uint16_t service,uint8_t subtype) const -{ - if(service != RS_SERVICE_GXS_TYPE_REPUTATION) - return NULL ; - - switch(subtype) - { - case RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM : return new RsGxsReputationSetItem() ; - case RS_PKT_SUBTYPE_GXS_REPUTATION_BANNED_NODE_SET_ITEM : return new RsGxsReputationBannedNodeSetItem(); - case RS_PKT_SUBTYPE_GXS_REPUTATION_UPDATE_ITEM : return new RsGxsReputationUpdateItem(); - case RS_PKT_SUBTYPE_GXS_REPUTATION_REQUEST_ITEM : return new RsGxsReputationRequestItem() ; - case RS_PKT_SUBTYPE_GXS_REPUTATION_CONFIG_ITEM : return new RsGxsReputationConfigItem () ; - default: - std::cerr << "(EE) RsGxsReputationSerialiser::create_item(): unhandled item type " << subtype << std::endl; - return NULL ; - } -} - diff --git a/libretroshare/src/rsitems/rsgxsreputationitems.h b/libretroshare/src/rsitems/rsgxsreputationitems.h deleted file mode 100644 index 8028e63f1..000000000 --- a/libretroshare/src/rsitems/rsgxsreputationitems.h +++ /dev/null @@ -1,178 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxsreputationitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014-2014 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_GXSREPUTATION_ITEMS_H -#define RS_GXSREPUTATION_ITEMS_H - -#include - -#include "rsitems/rsserviceids.h" -#include "rsitems/rsitem.h" -#include "rsitems/itempriorities.h" - -#include "serialiser/rsserial.h" -#include "serialiser/rstlvidset.h" -#include "retroshare/rsgxsifacetypes.h" -#include "retroshare/rsreputations.h" - -#include "serialiser/rsserializer.h" - -#define RS_PKT_SUBTYPE_GXS_REPUTATION_CONFIG_ITEM 0x01 -#define RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM_deprecated2 0x02 -#define RS_PKT_SUBTYPE_GXS_REPUTATION_UPDATE_ITEM 0x03 -#define RS_PKT_SUBTYPE_GXS_REPUTATION_REQUEST_ITEM 0x04 -#define RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM_deprecated1 0x05 -#define RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM_deprecated3 0x06 -#define RS_PKT_SUBTYPE_GXS_REPUTATION_BANNED_NODE_SET_ITEM 0x07 -#define RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM 0x08 - -/**************************************************************************/ -class RsReputationItem: public RsItem -{ - public: - RsReputationItem(uint8_t reputation_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_GXS_TYPE_REPUTATION,reputation_subtype) - { - setPriorityLevel(QOS_PRIORITY_RS_GXSREPUTATION_ITEM); - } - - virtual ~RsReputationItem() {} - virtual void clear() = 0 ; -}; - -class RsGxsReputationConfigItem: public RsReputationItem -{ -public: - RsGxsReputationConfigItem() :RsReputationItem(RS_PKT_SUBTYPE_GXS_REPUTATION_CONFIG_ITEM) {} - - virtual ~RsGxsReputationConfigItem() {} - virtual void clear() {} - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */) ; - - RsPeerId mPeerId; - uint32_t mLatestUpdate; // timestamp they returned. - uint32_t mLastQuery; // when we sent out. -}; - -#ifdef TO_REMOVE -// This class should disappear. Deprecated since Jan 7, 2017. The class definition is actually not needed, -// that is why it's commented out. Kept here in order to explains how the deserialisation works. -// -class RsGxsReputationSetItem_deprecated3: public RsReputationItem -{ -public: - RsGxsReputationSetItem_deprecated3() :RsReputationItem(RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM_deprecated3) {} - - virtual ~RsGxsReputationSetItem_deprecated3() {} - virtual void clear() {} - - virtual void serial_process(SerializeJob /* j */,SerializeContext& /* ctx */) ; - - RsGxsId mGxsId; - uint32_t mOwnOpinion; - uint32_t mOwnOpinionTS; - uint32_t mIdentityFlags ; - RsPgpId mOwnerNodeId; - std::map mOpinions; // RsPeerId -> Opinion. -}; -#endif - -class RsGxsReputationSetItem: public RsReputationItem -{ -public: - RsGxsReputationSetItem() :RsReputationItem(RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM) - { - mOwnOpinion = static_cast(RsOpinion::NEUTRAL); - mOwnOpinionTS = 0; - mIdentityFlags = 0; - mLastUsedTS = 0; - } - - virtual ~RsGxsReputationSetItem() {} - virtual void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */) ; - - RsGxsId mGxsId; - uint32_t mOwnOpinion; - uint32_t mOwnOpinionTS; - uint32_t mIdentityFlags; - uint32_t mLastUsedTS; - RsPgpId mOwnerNodeId; - std::map mOpinions; // RsPeerId -> Opinion. -}; -class RsGxsReputationBannedNodeSetItem: public RsReputationItem -{ -public: - RsGxsReputationBannedNodeSetItem() :RsReputationItem(RS_PKT_SUBTYPE_GXS_REPUTATION_BANNED_NODE_SET_ITEM) {} - - virtual ~RsGxsReputationBannedNodeSetItem() {} - virtual void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */) ; - - RsPgpId mPgpId ; - uint32_t mLastActivityTS ; - RsTlvGxsIdSet mKnownIdentities ; -}; - -class RsGxsReputationUpdateItem: public RsReputationItem -{ -public: - RsGxsReputationUpdateItem() :RsReputationItem(RS_PKT_SUBTYPE_GXS_REPUTATION_UPDATE_ITEM) {} - - virtual ~RsGxsReputationUpdateItem() {} - virtual void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */) ; - - uint32_t mLatestUpdate; - std::map mOpinions; // GxsId -> Opinion. -}; - -class RsGxsReputationRequestItem: public RsReputationItem -{ -public: - RsGxsReputationRequestItem() :RsReputationItem(RS_PKT_SUBTYPE_GXS_REPUTATION_REQUEST_ITEM) {} - - virtual ~RsGxsReputationRequestItem() {} - virtual void clear() {} - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */) ; - - uint32_t mLastUpdate; -}; - - -class RsGxsReputationSerialiser: public RsServiceSerializer -{ -public: - RsGxsReputationSerialiser() :RsServiceSerializer(RS_SERVICE_GXS_TYPE_REPUTATION){} - virtual ~RsGxsReputationSerialiser(){} - - virtual RsItem *create_item(uint16_t service,uint8_t item_type) const; -}; - -/**************************************************************************/ - -#endif /* RS_GXSREPUTATION_ITEMS_H */ - - diff --git a/libretroshare/src/rsitems/rsgxsupdateitems.cc b/libretroshare/src/rsitems/rsgxsupdateitems.cc deleted file mode 100644 index b129dc460..000000000 --- a/libretroshare/src/rsitems/rsgxsupdateitems.cc +++ /dev/null @@ -1,133 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxsupdateitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 Christopher Evi-Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "serialiser/rstypeserializer.h" -#include "serialiser/rsbaseserial.h" - -#include "rsgxsupdateitems.h" - -/**********************************************************************************************/ -/* SERIALIZER */ -/**********************************************************************************************/ - -RsItem* RsGxsUpdateSerialiser::create_item(uint16_t service,uint8_t item_subtype) const -{ - if(service != SERVICE_TYPE) - return NULL ; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_GXS_MSG_UPDATE: return new RsGxsMsgUpdateItem(SERVICE_TYPE); - case RS_PKT_SUBTYPE_GXS_GRP_UPDATE: return new RsGxsGrpUpdateItem(SERVICE_TYPE); - case RS_PKT_SUBTYPE_GXS_SERVER_GRP_UPDATE: return new RsGxsServerGrpUpdateItem(SERVICE_TYPE); - case RS_PKT_SUBTYPE_GXS_SERVER_MSG_UPDATE: return new RsGxsServerMsgUpdateItem(SERVICE_TYPE); - case RS_PKT_SUBTYPE_GXS_GRP_CONFIG: return new RsGxsGrpConfigItem(SERVICE_TYPE); - default: - return NULL ; - } -} - -/**********************************************************************************************/ -/* CLEAR */ -/**********************************************************************************************/ - -void RsGxsGrpUpdateItem::clear() -{ - grpUpdateTS = 0; - peerID.clear(); -} - -void RsGxsMsgUpdateItem::clear() -{ - msgUpdateInfos.clear(); - peerID.clear(); -} - -void RsGxsServerMsgUpdateItem::clear() -{ - msgUpdateTS = 0; - grpId.clear(); -} - -void RsGxsServerGrpUpdateItem::clear() -{ - grpUpdateTS = 0; -} - -/**********************************************************************************************/ -/* SERIALISER */ -/**********************************************************************************************/ - -void RsGxsGrpUpdateItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,peerID,"peerID"); - RsTypeSerializer::serial_process(j,ctx,grpUpdateTS,"grpUpdateTS"); -} - -void RsGxsServerGrpUpdateItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,grpUpdateTS,"grpUpdateTS"); -} - -void RsGxsMsgUpdateItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,peerID,"peerID"); - RsTypeSerializer::serial_process(j,ctx,msgUpdateInfos,"msgUpdateInfos"); -} - -template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, const RsGxsMsgUpdateItem::MsgUpdateInfo& info) -{ - bool ok = true ; - - ok = ok && setRawUInt32(data,size,&offset,info.time_stamp); - ok = ok && setRawUInt32(data,size,&offset,info.message_count); - - return ok; -} -template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, RsGxsMsgUpdateItem::MsgUpdateInfo& info) -{ - bool ok = true ; - - ok = ok && getRawUInt32(data,size,&offset,&info.time_stamp); - ok = ok && getRawUInt32(data,size,&offset,&info.message_count); - - return ok; -} -template<> uint32_t RsTypeSerializer::serial_size(const RsGxsMsgUpdateItem::MsgUpdateInfo& /* info */) { return 8; } - -template<> void RsTypeSerializer::print_data(const std::string& name,const RsGxsMsgUpdateItem::MsgUpdateInfo& info) -{ - std::cerr << "[MsgUpdateInfo]: " << name << ": " << info.time_stamp << ", " << info.message_count << std::endl; -} - -void RsGxsServerMsgUpdateItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,grpId,"grpId"); - RsTypeSerializer::serial_process(j,ctx,msgUpdateTS,"msgUpdateTS"); -} -void RsGxsGrpConfigItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,grpId,"grpId") ; - RsTypeSerializer::serial_process(j,ctx,msg_keep_delay,"msg_keep_delay") ; - RsTypeSerializer::serial_process(j,ctx,msg_send_delay,"msg_send_delay") ; - RsTypeSerializer::serial_process(j,ctx,msg_req_delay,"msg_req_delay") ; -} - diff --git a/libretroshare/src/rsitems/rsgxsupdateitems.h b/libretroshare/src/rsitems/rsgxsupdateitems.h deleted file mode 100644 index 03bd21800..000000000 --- a/libretroshare/src/rsitems/rsgxsupdateitems.h +++ /dev/null @@ -1,219 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsgxsupdateitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 Christopher Evi-Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RSGXSUPDATEITEMS_H_ -#define RSGXSUPDATEITEMS_H_ - -#include "gxs/rsgxs.h" -#include "gxs/rsgxsdata.h" -#include "gxs/rsgxsnettunnel.h" -#include "serialiser/rstlvidset.h" -#include "serialiser/rstypeserializer.h" -#include "serialiser/rsserializable.h" - - -const uint8_t RS_PKT_SUBTYPE_GXS_GRP_UPDATE = 0x01; -const uint8_t RS_PKT_SUBTYPE_GXS_MSG_UPDATE_deprecated = 0x02; -const uint8_t RS_PKT_SUBTYPE_GXS_MSG_UPDATE = 0x03; -const uint8_t RS_PKT_SUBTYPE_GXS_SERVER_GRP_UPDATE = 0x04; -const uint8_t RS_PKT_SUBTYPE_GXS_SERVER_MSG_UPDATE = 0x08; -const uint8_t RS_PKT_SUBTYPE_GXS_GRP_CONFIG = 0x09; -const uint8_t RS_PKT_SUBTYPE_GXS_RANDOM_BIAS = 0x0a; - -class RsGxsNetServiceItem: public RsItem -{ -public: - RsGxsNetServiceItem(uint16_t serv_type,uint8_t subtype) : RsItem(RS_PKT_VERSION_SERVICE, serv_type, subtype) {} - - virtual ~RsGxsNetServiceItem() {} - virtual void clear() = 0 ; -}; - -class RsGxsGrpConfig -{ -public: - RsGxsGrpConfig() - { - msg_keep_delay = RS_GXS_DEFAULT_MSG_STORE_PERIOD ; - msg_send_delay = RS_GXS_DEFAULT_MSG_SEND_PERIOD ; - msg_req_delay = RS_GXS_DEFAULT_MSG_REQ_PERIOD ; - - max_visible_count = 0 ; - statistics_update_TS = 0 ; - last_group_modification_TS = 0 ; - } - - uint32_t msg_keep_delay ; // delay after which we discard the posts - uint32_t msg_send_delay ; // delay after which we dont send the posts anymore - uint32_t msg_req_delay ; // delay after which we dont get the posts from friends - - RsTlvPeerIdSet suppliers; // list of friends who feed this group - uint32_t max_visible_count ; // max visible count reported by contributing friends - rstime_t statistics_update_TS ; // last time the max visible count was updated. - rstime_t last_group_modification_TS ; // last time the group was modified, either in meta data or in the list of messages posted in it. -}; - -class RsGxsGrpConfigItem : public RsGxsNetServiceItem, public RsGxsGrpConfig -{ -public: - explicit RsGxsGrpConfigItem(uint16_t servType) : RsGxsNetServiceItem(servType, RS_PKT_SUBTYPE_GXS_GRP_CONFIG) {} - RsGxsGrpConfigItem(const RsGxsGrpConfig& m,uint16_t servType) : RsGxsNetServiceItem(servType, RS_PKT_SUBTYPE_GXS_GRP_CONFIG),RsGxsGrpConfig(m) {} - virtual ~RsGxsGrpConfigItem() {} - - virtual void clear() {} - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsGxsGroupId grpId ; -}; - -class RsGxsGrpUpdate -{ -public: - RsGxsGrpUpdate() { grpUpdateTS=0;} - - uint32_t grpUpdateTS; -}; - -class RsGxsGrpUpdateItem : public RsGxsNetServiceItem, public RsGxsGrpUpdate -{ -public: - explicit RsGxsGrpUpdateItem(uint16_t servType) : RsGxsNetServiceItem(servType, RS_PKT_SUBTYPE_GXS_GRP_UPDATE) {clear();} - RsGxsGrpUpdateItem(const RsGxsGrpUpdate& u,uint16_t serv_type) : RsGxsNetServiceItem(serv_type, RS_PKT_SUBTYPE_GXS_GRP_UPDATE), RsGxsGrpUpdate(u) {} - - virtual ~RsGxsGrpUpdateItem() {} - - virtual void clear(); - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsPeerId peerID; -}; - -struct RsPeerUpdateTsRecord -{ - RsPeerUpdateTsRecord() : mLastTsReceived(0), mTs(0) {} - - rstime_t mLastTsReceived; // last TS that was sent for this group by this peer ID. - rstime_t mTs; // time at which this TS was sent. -}; - -class RsGxsServerGrpUpdate -{ -public: - RsGxsServerGrpUpdate() { grpUpdateTS = 0 ; } - - uint32_t grpUpdateTS; - - std::map grpUpdateTsRecords; -}; - -class RsGxsServerGrpUpdateItem : public RsGxsNetServiceItem, public RsGxsServerGrpUpdate -{ -public: - explicit RsGxsServerGrpUpdateItem(uint16_t servType) : RsGxsNetServiceItem(servType, RS_PKT_SUBTYPE_GXS_SERVER_GRP_UPDATE) { clear();} - RsGxsServerGrpUpdateItem(const RsGxsServerGrpUpdate& u,uint16_t serv_type) : RsGxsNetServiceItem(serv_type, RS_PKT_SUBTYPE_GXS_SERVER_GRP_UPDATE), RsGxsServerGrpUpdate(u) {} - - virtual ~RsGxsServerGrpUpdateItem() {} - - virtual void clear(); - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -class RsGxsMsgUpdate -{ -public: - struct MsgUpdateInfo : RsSerializable - { - MsgUpdateInfo(): time_stamp(0), message_count(0) {} - - uint32_t time_stamp ; - uint32_t message_count ; - - /// @see RsSerializable - void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) - { - RS_SERIAL_PROCESS(time_stamp); - RS_SERIAL_PROCESS(message_count); - } - }; - - std::map msgUpdateInfos; -}; - - -class RsGxsMsgUpdateItem : public RsGxsNetServiceItem, public RsGxsMsgUpdate -{ -public: - explicit RsGxsMsgUpdateItem(uint16_t servType) : RsGxsNetServiceItem(servType, RS_PKT_SUBTYPE_GXS_MSG_UPDATE) { clear();} - RsGxsMsgUpdateItem(const RsGxsMsgUpdate& m,uint16_t servType) : RsGxsNetServiceItem(servType, RS_PKT_SUBTYPE_GXS_MSG_UPDATE), RsGxsMsgUpdate(m) {} - - virtual ~RsGxsMsgUpdateItem() {} - - virtual void clear(); - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsPeerId peerID; -}; - -class RsGxsServerMsgUpdate -{ -public: - RsGxsServerMsgUpdate() { msgUpdateTS = 0 ;} - - uint32_t msgUpdateTS; // local time stamp at which this group last received a new msg - - // Now we also store for each peer the last own TS the peer sent and when it did so. This allows to detect when transactions are stuck because of - // outqueues clogging. If that happens, we receive multiple times the same TS from the friend, in which case we do not send the list of msgs - // again until a significant amount of time has passed. These values are obviously initialized to 0. - - std::map msgUpdateTsRecords; -}; - -class RsGxsServerMsgUpdateItem : public RsGxsNetServiceItem, public RsGxsServerMsgUpdate -{ -public: - explicit RsGxsServerMsgUpdateItem(uint16_t servType) : RsGxsNetServiceItem(servType, RS_PKT_SUBTYPE_GXS_SERVER_MSG_UPDATE) { clear();} - RsGxsServerMsgUpdateItem(const RsGxsServerMsgUpdate& m,uint16_t servType) : RsGxsNetServiceItem(servType, RS_PKT_SUBTYPE_GXS_SERVER_MSG_UPDATE),RsGxsServerMsgUpdate(m) {} - virtual ~RsGxsServerMsgUpdateItem() {} - - virtual void clear(); - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsGxsGroupId grpId; -}; - -class RsGxsUpdateSerialiser : public RsServiceSerializer -{ -public: - - explicit RsGxsUpdateSerialiser(uint16_t servtype) : RsServiceSerializer(servtype), SERVICE_TYPE(servtype) {} - - virtual ~RsGxsUpdateSerialiser() {} - - virtual RsItem* create_item(uint16_t service,uint8_t item_subtype) const ; - - const uint16_t SERVICE_TYPE; -}; - - - - -#endif /* RSGXSUPDATEITEMS_H_ */ diff --git a/libretroshare/src/rsitems/rsheartbeatitems.h b/libretroshare/src/rsitems/rsheartbeatitems.h deleted file mode 100644 index b7e4f27c6..000000000 --- a/libretroshare/src/rsitems/rsheartbeatitems.h +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsheartbeatitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2013 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_HEARTBEAT_ITEMS_H -#define RS_HEARTBEAT_ITEMS_H - -#include "rsitems/rsitem.h" -#include "rsitems/rsserviceids.h" -#include "rsitems/itempriorities.h" - -const uint8_t RS_PKT_SUBTYPE_HEARTBEAT_PULSE = 0x01; - -class RsHeartbeatItem: public RsItem -{ -public: - RsHeartbeatItem() :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_HEARTBEAT, RS_PKT_SUBTYPE_HEARTBEAT_PULSE) - { - setPriorityLevel(QOS_PRIORITY_RS_HEARTBEAT_PULSE) ; - } - virtual ~RsHeartbeatItem() {} - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */) {} - - virtual void clear(){} -}; - -class RsHeartbeatSerialiser: public RsServiceSerializer -{ -public: - RsHeartbeatSerialiser() :RsServiceSerializer(RS_SERVICE_TYPE_HEARTBEAT) {} - - virtual ~RsHeartbeatSerialiser() {} - - virtual RsItem *create_item(uint16_t service,uint8_t item_subtype) const - { - if(service == RS_SERVICE_TYPE_HEARTBEAT && item_subtype == RS_PKT_SUBTYPE_HEARTBEAT_PULSE) - return new RsHeartbeatItem() ; - else - return NULL ; - } -}; - - -#endif // RS_DISC_ITEMS_H - diff --git a/libretroshare/src/rsitems/rshistoryitems.cc b/libretroshare/src/rsitems/rshistoryitems.cc deleted file mode 100644 index 4cfb04945..000000000 --- a/libretroshare/src/rsitems/rshistoryitems.cc +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rshistoryitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Thunder. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "rsitems/rshistoryitems.h" -#include "rsitems/rsconfigitems.h" - -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstlvbase.h" - -#include "serialiser/rstypeserializer.h" - -/*** -#define RSSERIAL_DEBUG 1 -***/ - -#include - -void RsHistoryMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - uint16_t version=0; - - RsTypeSerializer::serial_process(j,ctx,version,"version") ; - RsTypeSerializer::serial_process (j,ctx,chatPeerId,"chatPeerId") ; - RsTypeSerializer::serial_process (j,ctx,incoming,"incoming") ; - RsTypeSerializer::serial_process (j,ctx,msgPeerId,"peerId") ; - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_NAME,peerName,"peerName") ; - RsTypeSerializer::serial_process(j,ctx,sendTime,"sendTime") ; - RsTypeSerializer::serial_process(j,ctx,recvTime,"recvTime") ; - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_MSG,message,"message") ; -} - -RsItem *RsHistorySerialiser::create_item(uint8_t item_type,uint8_t item_subtype) const -{ - if(item_type != RS_PKT_TYPE_HISTORY_CONFIG) - return NULL ; - - if(item_subtype == RS_PKT_SUBTYPE_DEFAULT) - return new RsHistoryMsgItem(); - - return NULL ; -} - - -RsHistoryMsgItem::RsHistoryMsgItem() : RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_HISTORY_CONFIG, RS_PKT_SUBTYPE_DEFAULT) -{ - incoming = false; - sendTime = 0; - recvTime = 0; - msgId = 0; - saveToDisc = true; -} - - diff --git a/libretroshare/src/rsitems/rshistoryitems.h b/libretroshare/src/rsitems/rshistoryitems.h deleted file mode 100644 index 693817757..000000000 --- a/libretroshare/src/rsitems/rshistoryitems.h +++ /dev/null @@ -1,69 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rshistoryitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Thunder. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_HISTORY_ITEMS_H -#define RS_HISTORY_ITEMS_H - -#include "rsitems/rsserviceids.h" -#include "serialiser/rsserial.h" -#include "rsitems/rsconfigitems.h" -#include "retroshare/rstypes.h" - -#include "serialiser/rsserializer.h" - -/**************************************************************************/ - -class RsHistoryMsgItem: public RsItem -{ -public: - RsHistoryMsgItem(); - virtual ~RsHistoryMsgItem() {} - virtual void clear() {} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsPeerId chatPeerId; // empty for global chat - bool incoming; - RsPeerId msgPeerId; - std::string peerName; - uint32_t sendTime; - uint32_t recvTime; - std::string message; - - /* not serialised */ - uint32_t msgId; - bool saveToDisc; -}; - -class RsHistorySerialiser: public RsConfigSerializer -{ -public: - RsHistorySerialiser() : RsConfigSerializer(RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_HISTORY_CONFIG) {} - virtual ~RsHistorySerialiser() {} - - virtual RsItem *create_item(uint8_t item_type,uint8_t item_subtype) const ; -}; - -/**************************************************************************/ - -#endif /* RS_HISTORY_ITEMS_H */ - - diff --git a/libretroshare/src/rsitems/rsitem.h b/libretroshare/src/rsitems/rsitem.h deleted file mode 100644 index 70844f840..000000000 --- a/libretroshare/src/rsitems/rsitem.h +++ /dev/null @@ -1,142 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsitem.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2018-2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include // for typeid - -#include "util/smallobject.h" -#include "retroshare/rstypes.h" -#include "serialiser/rsserializer.h" -#include "serialiser/rsserializable.h" -#include "util/stacktrace.h" -#include "rsitems/itempriorities.h" -#include "rsitems/rsserviceids.h" - - -#include - -struct RsItem : RsMemoryManagement::SmallObject, RsSerializable -{ - explicit RsItem(uint32_t t); - RsItem(uint8_t ver, uint8_t cls, uint8_t t, uint8_t subtype); -#ifdef DO_STATISTICS - void *operator new(size_t s) ; - void operator delete(void *,size_t s) ; -#endif - - virtual ~RsItem(); - - /** TODO: Does the existence of this method make sense with the new - * serialization system? **/ - virtual void clear() - { - RS_ERR("Called without being overridden, report to developers"); - print_stacktrace(); - } - - /// @deprecated use << ostream operator instead - RS_DEPRECATED_FOR("<< ostream operator") - virtual std::ostream &print(std::ostream &out, uint16_t /* indent */ = 0) - { - RsGenericSerializer::SerializeContext ctx( - nullptr, 0, RsSerializationFlags::NONE ); - serial_process(RsGenericSerializer::PRINT,ctx); - return out; - } - - void print_string(std::string &out, uint16_t indent = 0); - - /// source / destination id - const RsPeerId& PeerId() const { return peerId; } - void PeerId(const RsPeerId& id) { peerId = id; } - - /// complete id - uint32_t PacketId() const; - - /// id parts - uint8_t PacketVersion(); - uint8_t PacketClass(); - uint8_t PacketType(); - uint8_t PacketSubType() const; - - /** For Service Packets, @deprecated use the costructor with priority - * paramether instead */ - RS_DEPRECATED RsItem(uint8_t ver, uint16_t service, uint8_t subtype); - - /// For Service Packets - RsItem( uint8_t ver, RsServiceType service, uint8_t subtype, - RsItemPriority prio ); - - uint16_t PacketService() const; /* combined Packet class/type (mid 16bits) */ - void setPacketService(uint16_t service); - - inline uint8_t priority_level() const { return _priority_level ;} - inline void setPriorityLevel(uint8_t l) { _priority_level = l ;} - -#ifdef RS_DEAD_CODE - /* - * TODO: This default implementation should be removed and childs structs - * implement ::serial_process(...) as soon as all the codebase is ported to - * the new serialization system - */ - virtual void serial_process(RsGenericSerializer::SerializeJob, - RsGenericSerializer::SerializeContext&)// = 0; - { - RS_ERR( "called by an item using new serialization system without " - "overriding Class is: ", typeid(*this).name() ); - print_stacktrace(); - } -#endif //def RS_DEAD_CODE - -protected: - uint32_t type; - RsPeerId peerId; - RsItemPriority _priority_level; -}; - -/// TODO: Do this make sense with the new serialization system? -class RsRawItem: public RsItem -{ -public: - RsRawItem(uint32_t t, uint32_t size) : RsItem(t), len(size) - { data = rs_malloc(len); } - virtual ~RsRawItem() { free(data); } - - uint32_t getRawLength() { return len; } - void * getRawData() { return data; } - -// virtual void clear() override {} - virtual std::ostream &print(std::ostream &out, uint16_t indent = 0); - - virtual void serial_process(RsGenericSerializer::SerializeJob, - RsGenericSerializer::SerializeContext&) override - { - RS_ERR( "called by an item using new serialization system ", - typeid(*this).name() ); - print_stacktrace(); - } - -private: - void *data; - uint32_t len; -}; diff --git a/libretroshare/src/rsitems/rsmsgitems.cc b/libretroshare/src/rsitems/rsmsgitems.cc deleted file mode 100644 index 8060248f4..000000000 --- a/libretroshare/src/rsitems/rsmsgitems.cc +++ /dev/null @@ -1,166 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsmsgitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include -#include "util/rstime.h" -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstlvbase.h" - -#include "rsitems/rsmsgitems.h" - -#include "serialiser/rstypeserializer.h" - -/*** -#define RSSERIAL_DEBUG 1 -***/ - -#include - - -RsItem *RsMsgSerialiser::create_item(uint16_t service,uint8_t type) const -{ - if(service != RS_SERVICE_TYPE_MSG) - return NULL ; - - switch(type) - { - case RS_PKT_SUBTYPE_DEFAULT : return new RsMsgItem() ; //= 0x01; - case RS_PKT_SUBTYPE_MSG_TAG_TYPE : return new RsMsgTagType() ; //= 0x03; - case RS_PKT_SUBTYPE_MSG_TAGS : return new RsMsgTags() ; //= 0x04; - case RS_PKT_SUBTYPE_MSG_SRC_TAG : return new RsMsgSrcId(); //= 0x05; - case RS_PKT_SUBTYPE_MSG_PARENT_TAG : return new RsMsgParentId() ; //= 0x06; - case RS_PKT_SUBTYPE_MSG_GROUTER_MAP : return new RsMsgGRouterMap(); //= 0x08; - case RS_PKT_SUBTYPE_MSG_DISTANT_MSG_MAP : return new RsMsgDistantMessagesHashMap();//= 0x09; - default: - return NULL ; - } -} - -void RsMsgItem::clear() -{ - msgId = 0; - msgFlags = 0; - sendTime = 0; - recvTime = 0; - subject.clear(); - message.clear(); - - rspeerid_msgto.TlvClear(); - rspeerid_msgcc.TlvClear(); - rspeerid_msgbcc.TlvClear(); - - rsgxsid_msgto.TlvClear(); - rsgxsid_msgcc.TlvClear(); - rsgxsid_msgbcc.TlvClear(); - - attachment.TlvClear(); -} - -void RsMsgTagType::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_NAME,text,"text") ; - RsTypeSerializer::serial_process(j,ctx,rgb_color,"rgb_color") ; - RsTypeSerializer::serial_process(j,ctx,tagId,"tagId") ; -} - -void RsMsgTags::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,msgId,"msgId") ; - -#warning this is not the correct way to serialise here. We should directly call serial_process >() but for backward compatibility, we cannot - - if(j == RsGenericSerializer::DESERIALIZE) - while(ctx.mOffset < ctx.mSize) - { - uint32_t n = 0;// No real need to initialize but otherwise the compiler complains. - RsTypeSerializer::serial_process(j,ctx,n,"tagIds element") ; - tagIds.push_back(n) ; - } - else - for(std::list::iterator it(tagIds.begin());it!=tagIds.end();++it) - RsTypeSerializer::serial_process(j,ctx,*it,"tagIds element") ; -} - -void RsMsgSrcId::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,msgId,"msgId") ; - RsTypeSerializer::serial_process (j,ctx,srcId,"srcId") ; -} - -void RsMsgGRouterMap::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,ongoing_msgs,"ongoing_msgs") ; -} - -void RsMsgGRouterMap::clear() -{ - ongoing_msgs.clear() ; - - return; -} - -void RsMsgDistantMessagesHashMap::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,hash_map,"hash_map") ; -} - -void RsMsgParentId::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,msgId,"msgId") ; - RsTypeSerializer::serial_process(j,ctx,msgParentId,"msgParentId") ; -} - -void RsMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,msgFlags,"msgFlags"); - RsTypeSerializer::serial_process(j,ctx,sendTime,"sendTime"); - RsTypeSerializer::serial_process(j,ctx,recvTime,"recvTime"); - - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_SUBJECT,subject,"subject"); - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_MSG,message,"message"); - - RsTypeSerializer::serial_process(j,ctx,rspeerid_msgto,"rspeerid_msgto"); - RsTypeSerializer::serial_process(j,ctx,rspeerid_msgcc,"rspeerid_msgcc"); - RsTypeSerializer::serial_process(j,ctx,rspeerid_msgbcc,"rspeerid_msgbcc"); - - RsTypeSerializer::serial_process(j,ctx,rsgxsid_msgto,"rsgxsid_msgto"); - RsTypeSerializer::serial_process(j,ctx,rsgxsid_msgcc,"rsgxsid_msgcc"); - RsTypeSerializer::serial_process(j,ctx,rsgxsid_msgbcc,"rsgxsid_msgbcc"); - - RsTypeSerializer::serial_process(j,ctx,attachment,"attachment"); - - if(!!(ctx.mFlags & RsSerializationFlags::CONFIG)) - RS_SERIAL_PROCESS(msgId); -} - -void RsMsgTagType::clear() -{ - text.clear(); - tagId = 0; - rgb_color = 0; -} - -void RsMsgTags::clear() -{ - msgId = 0; - tagIds.clear(); -} - diff --git a/libretroshare/src/rsitems/rsmsgitems.h b/libretroshare/src/rsitems/rsmsgitems.h deleted file mode 100644 index 27447aec0..000000000 --- a/libretroshare/src/rsitems/rsmsgitems.h +++ /dev/null @@ -1,225 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsmsgitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include - -#include "retroshare/rstypes.h" -#include "serialiser/rstlvkeys.h" -#include "rsitems/rsserviceids.h" -#include "serialiser/rsserial.h" - -#include "serialiser/rstlvidset.h" -#include "serialiser/rstlvfileitem.h" -#include "grouter/grouteritems.h" - - -/**************************************************************************/ - -// for defining tags themselves and msg tags -const uint8_t RS_PKT_SUBTYPE_MSG_TAG_TYPE = 0x03; -const uint8_t RS_PKT_SUBTYPE_MSG_TAGS = 0x04; -const uint8_t RS_PKT_SUBTYPE_MSG_SRC_TAG = 0x05; -const uint8_t RS_PKT_SUBTYPE_MSG_PARENT_TAG = 0x06; -const uint8_t RS_PKT_SUBTYPE_MSG_INVITE = 0x07; -const uint8_t RS_PKT_SUBTYPE_MSG_GROUTER_MAP = 0x08; -const uint8_t RS_PKT_SUBTYPE_MSG_DISTANT_MSG_MAP = 0x09; - - -/**************************************************************************/ - -const uint32_t RS_MSG_FLAGS_OUTGOING = 0x00000001; -const uint32_t RS_MSG_FLAGS_PENDING = 0x00000002; -const uint32_t RS_MSG_FLAGS_DRAFT = 0x00000004; -const uint32_t RS_MSG_FLAGS_NEW = 0x00000010; -const uint32_t RS_MSG_FLAGS_TRASH = 0x00000020; -const uint32_t RS_MSG_FLAGS_UNREAD_BY_USER = 0x00000040; -const uint32_t RS_MSG_FLAGS_REPLIED = 0x00000080; -const uint32_t RS_MSG_FLAGS_FORWARDED = 0x00000100; -const uint32_t RS_MSG_FLAGS_STAR = 0x00000200; -const uint32_t RS_MSG_FLAGS_PARTIAL = 0x00000400; -const uint32_t RS_MSG_FLAGS_USER_REQUEST = 0x00000800; -const uint32_t RS_MSG_FLAGS_FRIEND_RECOMMENDATION = 0x00001000; -const uint32_t RS_MSG_FLAGS_RETURN_RECEPT = 0x00002000; -const uint32_t RS_MSG_FLAGS_ENCRYPTED = 0x00004000; -const uint32_t RS_MSG_FLAGS_DISTANT = 0x00008000; -const uint32_t RS_MSG_FLAGS_SIGNATURE_CHECKS = 0x00010000; -const uint32_t RS_MSG_FLAGS_SIGNED = 0x00020000; -const uint32_t RS_MSG_FLAGS_LOAD_EMBEDDED_IMAGES = 0x00040000; -const uint32_t RS_MSG_FLAGS_DECRYPTED = 0x00080000; -const uint32_t RS_MSG_FLAGS_ROUTED = 0x00100000; -const uint32_t RS_MSG_FLAGS_PUBLISH_KEY = 0x00200000; -const uint32_t RS_MSG_FLAGS_SPAM = 0x00400000; - -const uint32_t RS_MSG_FLAGS_SYSTEM = RS_MSG_FLAGS_USER_REQUEST | RS_MSG_FLAGS_FRIEND_RECOMMENDATION | RS_MSG_FLAGS_PUBLISH_KEY; - -class RsMessageItem: public RsItem -{ - public: - RsMessageItem(uint8_t msg_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_MSG,msg_subtype) - { - setPriorityLevel(QOS_PRIORITY_RS_MSG_ITEM) ; - } - - virtual ~RsMessageItem() {} - virtual void clear() {} -}; - - -class RsMsgItem: public RsMessageItem -{ - public: - RsMsgItem() :RsMessageItem(RS_PKT_SUBTYPE_DEFAULT) {} - - virtual ~RsMsgItem() {} - virtual void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */); - - // ----------- Specific fields ------------- // - - uint32_t msgFlags; - uint32_t msgId; - - uint32_t sendTime; - uint32_t recvTime; - - std::string subject; - std::string message; - - RsTlvPeerIdSet rspeerid_msgto; - RsTlvPeerIdSet rspeerid_msgcc; - RsTlvPeerIdSet rspeerid_msgbcc; - - RsTlvGxsIdSet rsgxsid_msgto; - RsTlvGxsIdSet rsgxsid_msgcc; - RsTlvGxsIdSet rsgxsid_msgbcc; - - RsTlvFileSet attachment; -}; - -class RsMsgTagType : public RsMessageItem -{ - public: - RsMsgTagType() :RsMessageItem(RS_PKT_SUBTYPE_MSG_TAG_TYPE) {} - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */); - - virtual ~RsMsgTagType() {} - virtual void clear(); - - // ----------- Specific fields ------------- // - // - std::string text; - uint32_t rgb_color; - uint32_t tagId; -}; - -class RsMsgTags : public RsMessageItem -{ -public: - RsMsgTags() - :RsMessageItem(RS_PKT_SUBTYPE_MSG_TAGS) {} - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */); - - virtual ~RsMsgTags() {} - virtual void clear(); - - // ----------- Specific fields ------------- // - // - uint32_t msgId; - std::list tagIds; -}; - -class RsMsgSrcId : public RsMessageItem -{ - public: - RsMsgSrcId() : RsMessageItem(RS_PKT_SUBTYPE_MSG_SRC_TAG) {} - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */); - - virtual ~RsMsgSrcId() {} - virtual void clear(){} - - // ----------- Specific fields ------------- // - // - - uint32_t msgId; - RsPeerId srcId; -}; - -class RsMsgGRouterMap : public RsMessageItem -{ - public: - RsMsgGRouterMap() : RsMessageItem(RS_PKT_SUBTYPE_MSG_GROUTER_MAP) {} - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */); - - virtual ~RsMsgGRouterMap() {} - virtual void clear(); - - // ----------- Specific fields ------------- // - // - std::map ongoing_msgs ; -}; -class RsMsgDistantMessagesHashMap : public RsMessageItem -{ - public: - RsMsgDistantMessagesHashMap() : RsMessageItem(RS_PKT_SUBTYPE_MSG_DISTANT_MSG_MAP) {} - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */); - - virtual ~RsMsgDistantMessagesHashMap() {} - virtual void clear() { hash_map.clear() ;} - - // ----------- Specific fields ------------- // - // - std::map hash_map ; -}; -class RsMsgParentId : public RsMessageItem -{ - public: - RsMsgParentId() : RsMessageItem(RS_PKT_SUBTYPE_MSG_PARENT_TAG) {} - - virtual void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */); - - virtual ~RsMsgParentId() {} - virtual void clear(){} - - // ----------- Specific fields ------------- // - // - uint32_t msgId; - uint32_t msgParentId; -}; - -class RsMsgSerialiser: public RsServiceSerializer -{ -public: - RsMsgSerialiser( - RsSerializationFlags flags = RsSerializationFlags::NONE ): - RsServiceSerializer(RS_SERVICE_TYPE_MSG, flags){} - - RsItem* create_item(uint16_t service,uint8_t type) const override; - - ~RsMsgSerialiser() override = default; -}; diff --git a/libretroshare/src/rsitems/rsnxsitems.cc b/libretroshare/src/rsitems/rsnxsitems.cc deleted file mode 100644 index dbed0d967..000000000 --- a/libretroshare/src/rsitems/rsnxsitems.cc +++ /dev/null @@ -1,254 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsnxsitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 Christopher Evi-Parker,Robert Fernie* - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "rsnxsitems.h" -#include "util/rsprint.h" -#include - -#include "serialiser/rstypeserializer.h" - -/*** - * #define RSSERIAL_DEBUG 1 - ***/ - -const uint8_t RsNxsSyncGrpItem::FLAG_REQUEST = 0x001; -const uint8_t RsNxsSyncGrpItem::FLAG_RESPONSE = 0x002; - -const uint8_t RsNxsSyncMsgItem::FLAG_REQUEST = 0x001; -const uint8_t RsNxsSyncMsgItem::FLAG_RESPONSE = 0x002; - -const uint8_t RsNxsSyncGrpItem::FLAG_USE_SYNC_HASH = 0x0001; -const uint8_t RsNxsSyncMsgItem::FLAG_USE_SYNC_HASH = 0x0001; - -const uint8_t RsNxsSyncMsgReqItem::FLAG_USE_HASHED_GROUP_ID = 0x02; - -/** transaction state **/ -const uint16_t RsNxsTransacItem::FLAG_BEGIN_P1 = 0x0001; -const uint16_t RsNxsTransacItem::FLAG_BEGIN_P2 = 0x0002; -const uint16_t RsNxsTransacItem::FLAG_END_SUCCESS = 0x0004; -const uint16_t RsNxsTransacItem::FLAG_CANCEL = 0x0008; -const uint16_t RsNxsTransacItem::FLAG_END_FAIL_NUM = 0x0010; -const uint16_t RsNxsTransacItem::FLAG_END_FAIL_TIMEOUT = 0x0020; -const uint16_t RsNxsTransacItem::FLAG_END_FAIL_FULL = 0x0040; - - -/** transaction type **/ -const uint16_t RsNxsTransacItem::FLAG_TYPE_GRP_LIST_RESP = 0x0100; -const uint16_t RsNxsTransacItem::FLAG_TYPE_MSG_LIST_RESP = 0x0200; -const uint16_t RsNxsTransacItem::FLAG_TYPE_GRP_LIST_REQ = 0x0400; -const uint16_t RsNxsTransacItem::FLAG_TYPE_MSG_LIST_REQ = 0x0800; -const uint16_t RsNxsTransacItem::FLAG_TYPE_GRPS = 0x1000; -const uint16_t RsNxsTransacItem::FLAG_TYPE_MSGS = 0x2000; -const uint16_t RsNxsTransacItem::FLAG_TYPE_ENCRYPTED_DATA = 0x4000; - -RsItem *RsNxsSerialiser::create_item(uint16_t service_id,uint8_t item_subtype) const -{ - if(service_id != SERVICE_TYPE) - return NULL ; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_NXS_SYNC_GRP_REQ_ITEM: return new RsNxsSyncGrpReqItem(SERVICE_TYPE) ; - case RS_PKT_SUBTYPE_NXS_SYNC_GRP_ITEM: return new RsNxsSyncGrpItem(SERVICE_TYPE) ; - case RS_PKT_SUBTYPE_NXS_SYNC_MSG_REQ_ITEM: return new RsNxsSyncMsgReqItem(SERVICE_TYPE) ; - case RS_PKT_SUBTYPE_NXS_SYNC_MSG_ITEM: return new RsNxsSyncMsgItem(SERVICE_TYPE) ; - case RS_PKT_SUBTYPE_NXS_GRP_ITEM: return new RsNxsGrp(SERVICE_TYPE) ; - case RS_PKT_SUBTYPE_NXS_MSG_ITEM: return new RsNxsMsg(SERVICE_TYPE) ; - case RS_PKT_SUBTYPE_NXS_TRANSAC_ITEM: return new RsNxsTransacItem(SERVICE_TYPE) ; - case RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY_ITEM:return new RsNxsGroupPublishKeyItem(SERVICE_TYPE) ; - case RS_PKT_SUBTYPE_NXS_ENCRYPTED_DATA_ITEM: return new RsNxsEncryptedDataItem(SERVICE_TYPE) ; - case RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS_ITEM: return new RsNxsSyncGrpStatsItem(SERVICE_TYPE) ; - case RS_PKT_SUBTYPE_NXS_SYNC_PULL_REQUEST_ITEM: return new RsNxsPullRequestItem(SERVICE_TYPE) ; - - default: - return NULL; - } -} - -void RsNxsSyncMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,transactionNumber,"transactionNumber") ; - RsTypeSerializer::serial_process (j,ctx,flag ,"flag") ; - RsTypeSerializer::serial_process (j,ctx,grpId ,"grpId") ; - RsTypeSerializer::serial_process (j,ctx,msgId ,"msgId") ; - RsTypeSerializer::serial_process (j,ctx,authorId ,"authorId") ; -} - -void RsNxsMsg::serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - RS_SERIAL_PROCESS(transactionNumber); - RS_SERIAL_PROCESS(pos); - RS_SERIAL_PROCESS(msgId); - RS_SERIAL_PROCESS(grpId); - RS_SERIAL_PROCESS(msg); - RS_SERIAL_PROCESS(meta); -} - -void RsNxsGrp::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,transactionNumber,"transactionNumber") ; - RsTypeSerializer::serial_process (j,ctx,pos ,"pos") ; - RsTypeSerializer::serial_process (j,ctx,grpId ,"grpId") ; - RsTypeSerializer::serial_process(j,ctx,grp ,"grp") ; - RsTypeSerializer::serial_process(j,ctx,meta ,"meta") ; -} - -void RsNxsSyncGrpStatsItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,request_type ,"request_type") ; - RsTypeSerializer::serial_process (j,ctx,grpId ,"grpId") ; - RsTypeSerializer::serial_process (j,ctx,number_of_posts,"number_of_posts") ; - RsTypeSerializer::serial_process (j,ctx,last_post_TS ,"last_post_TS") ; -} - -void RsNxsSyncGrpReqItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,transactionNumber,"transactionNumber") ; - RsTypeSerializer::serial_process (j,ctx,flag ,"flag") ; - RsTypeSerializer::serial_process(j,ctx,createdSince ,"createdSince") ; - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_HASH_SHA1,syncHash,"syncHash") ; - RsTypeSerializer::serial_process(j,ctx,updateTS ,"updateTS") ; -} - -void RsNxsTransacItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,transactionNumber,"transactionNumber") ; - RsTypeSerializer::serial_process(j,ctx,transactFlag ,"transactFlag") ; - RsTypeSerializer::serial_process(j,ctx,nItems ,"nItems") ; - RsTypeSerializer::serial_process(j,ctx,updateTS ,"updateTS") ; -} -void RsNxsSyncGrpItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,transactionNumber,"transactionNumber") ; - RsTypeSerializer::serial_process (j,ctx,flag ,"flag") ; - RsTypeSerializer::serial_process (j,ctx,grpId ,"grpId") ; - RsTypeSerializer::serial_process(j,ctx,publishTs ,"publishTs") ; - RsTypeSerializer::serial_process (j,ctx,authorId ,"authorId") ; -} -void RsNxsSyncMsgReqItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,transactionNumber,"transactionNumber") ; - RsTypeSerializer::serial_process (j,ctx,flag ,"flag") ; - RsTypeSerializer::serial_process(j,ctx,createdSinceTS ,"createdSinceTS") ; - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_HASH_SHA1,syncHash,"syncHash") ; - RsTypeSerializer::serial_process (j,ctx,grpId ,"grpId") ; - RsTypeSerializer::serial_process(j,ctx,updateTS ,"updateTS") ; -} -void RsNxsGroupPublishKeyItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,grpId ,"grpId") ; - RsTypeSerializer::serial_process(j,ctx,private_key ,"private_key") ; -} -void RsNxsEncryptedDataItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,transactionNumber,"transactionNumber") ; - RsTypeSerializer::serial_process(j,ctx,encrypted_data, "encrypted_data") ; -} - -int RsNxsGrp::refcount = 0; -int RsNxsMsg::refcount = 0; - -/** print and clear functions **/ -void RsNxsMsg::clear() -{ - - msg.TlvClear(); - meta.TlvClear(); -} - -void RsNxsGrp::clear() -{ - grpId.clear(); - grp.TlvClear(); - meta.TlvClear(); -} - -RsNxsGrp* RsNxsGrp::clone() const { - RsNxsGrp* grp = new RsNxsGrp(this->grp.tlvtype); - *grp = *this; - - if(this->metaData) - { - grp->metaData = new RsGxsGrpMetaData(); - *(grp->metaData) = *(this->metaData); - } - - return grp; -} - -void RsNxsSyncGrpReqItem::clear() -{ - flag = 0; - createdSince = 0; - updateTS = 0; - syncHash.clear(); -} -void RsNxsGroupPublishKeyItem::clear() -{ - private_key.TlvClear(); -} -void RsNxsSyncMsgReqItem::clear() -{ - grpId.clear(); - flag = 0; - createdSinceTS = 0; - updateTS = 0; - syncHash.clear(); -} -void RsNxsSyncGrpItem::clear() -{ - flag = 0; - publishTs = 0; - grpId.clear(); - authorId.clear(); -} - -void RsNxsSyncMsgItem::clear() -{ - flag = 0; - grpId.clear(); - msgId.clear(); - authorId.clear(); -} - -void RsNxsTransacItem::clear(){ - transactFlag = 0; - nItems = 0; - updateTS = 0; - timestamp = 0; - transactionNumber = 0; -} -void RsNxsEncryptedDataItem::clear(){ - encrypted_data.TlvClear() ; -} - -#ifdef SUSPENDED_CODE_27042017 -void RsNxsSessionKeyItem::clear() -{ - for(std::map::iterator it(encrypted_session_keys.begin());it!=encrypted_session_keys.end();++it) - it->second.TlvClear() ; - - encrypted_session_keys.clear() ; -} -#endif - - diff --git a/libretroshare/src/rsitems/rsnxsitems.h b/libretroshare/src/rsitems/rsnxsitems.h deleted file mode 100644 index 3cd941bdc..000000000 --- a/libretroshare/src/rsitems/rsnxsitems.h +++ /dev/null @@ -1,530 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsnxsitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Christopher Evi-Parker * - * Copyright (C) 2012 Robert Fernie * - * Copyright (C) 2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include - -#include "rsitems/rsserviceids.h" -#include "rsitems/itempriorities.h" -#include "serialiser/rsserial.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvitem.h" -#include "serialiser/rstlvkeys.h" -#include "gxs/rsgxsdata.h" - -// These items have "flag type" numbers, but this is not used. -// TODO: refactor as C++11 enum class -const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_GRP_REQ_ITEM = 0x01; -const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_GRP_ITEM = 0x02; -const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS_ITEM = 0x03; -const uint8_t RS_PKT_SUBTYPE_NXS_GRP_ITEM = 0x04; -const uint8_t RS_PKT_SUBTYPE_NXS_ENCRYPTED_DATA_ITEM = 0x05; -const uint8_t RS_PKT_SUBTYPE_NXS_SESSION_KEY_ITEM = 0x06; -const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_MSG_ITEM = 0x08; -const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_MSG_REQ_ITEM = 0x10; -const uint8_t RS_PKT_SUBTYPE_NXS_MSG_ITEM = 0x20; -const uint8_t RS_PKT_SUBTYPE_NXS_TRANSAC_ITEM = 0x40; -const uint8_t RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY_ITEM = 0x80; -const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_PULL_REQUEST_ITEM = 0x90; - - -#ifdef RS_DEAD_CODE -// possibility create second service to deal with this functionality -const uint8_t RS_PKT_SUBTYPE_EXT_SEARCH_GRP = 0x0001; -const uint8_t RS_PKT_SUBTYPE_EXT_SEARCH_MSG = 0x0002; -const uint8_t RS_PKT_SUBTYPE_EXT_DELETE_GRP = 0x0004; -const uint8_t RS_PKT_SUBTYPE_EXT_DELETE_MSG = 0x0008; -const uint8_t RS_PKT_SUBTYPE_EXT_SEARCH_REQ = 0x0010; -#endif // def RS_DEAD_CODE - -/*! - * Base class for Network exchange service - * Main purpose is for rtti based routing used in the - * serialisation and deserialisation of NXS packets - * - * Service type is set by plugin service - */ -class RsNxsItem : public RsItem -{ -public: - RsNxsItem(uint16_t servtype, uint8_t subtype): - RsItem(RS_PKT_VERSION_SERVICE, servtype, subtype), transactionNumber(0) - { setPriorityLevel(QOS_PRIORITY_RS_GXS_NET); } - - virtual ~RsNxsItem() = default; - - uint32_t transactionNumber; // set to zero if this is not a transaction item -}; - - -/*! - * Use to request grp list from peer - * Server may advise client peer to use sync file - * while serving his request. This results - */ -class RsNxsSyncGrpReqItem : public RsNxsItem -{ -public: - - static const uint8_t FLAG_USE_SYNC_HASH; - static const uint8_t FLAG_ONLY_CURRENT; // only send most current version of grps / ignores sync hash - - explicit RsNxsSyncGrpReqItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SYNC_GRP_REQ_ITEM) { clear();} - virtual void clear() override; - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override; - - uint8_t flag; // advises whether to use sync hash - uint32_t createdSince; // how far back to sync data - uint32_t updateTS; // time of last group update - std::string syncHash; // use to determine if changes that have occured since last hash -}; - -/*! - * Use to request statistics about a particular group - */ -class RsNxsSyncGrpStatsItem : public RsNxsItem -{ -public: - - explicit RsNxsSyncGrpStatsItem(uint16_t servtype) - : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS_ITEM) - , request_type(0), number_of_posts(0), last_post_TS(0) - {} - - virtual void clear() override {} - - static const uint8_t GROUP_INFO_TYPE_REQUEST = 0x01; - static const uint8_t GROUP_INFO_TYPE_RESPONSE = 0x02; - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override; - - uint32_t request_type; // used to determine the type of request - RsGxsGroupId grpId; // id of the group - uint32_t number_of_posts; // number of posts in that group - uint32_t last_post_TS; // time_stamp of last post -}; - -/*! - * Use to request grp list from peer - * Server may advise client peer to use sync file - * while serving his request. This results - */ -class RsNxsGroupPublishKeyItem : public RsNxsItem -{ -public: - explicit RsNxsGroupPublishKeyItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY_ITEM) { clear(); } - - virtual void clear() override; - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override; - - RsGxsGroupId grpId ; - RsTlvPrivateRSAKey private_key ; -}; - - - -/*! - * This RsNxsItem is for use in enabling transactions - * in order to guaranttee a collection of item have been - * received - */ -class RsNxsTransacItem: public RsNxsItem { - -public: - - static const uint16_t FLAG_STATE_MASK = 0xff; - static const uint16_t FLAG_TYPE_MASK = 0xff00; - - /** transaction state **/ - static const uint16_t FLAG_BEGIN_P1; - static const uint16_t FLAG_BEGIN_P2; - static const uint16_t FLAG_END_SUCCESS; - static const uint16_t FLAG_CANCEL; - static const uint16_t FLAG_END_FAIL_NUM; - static const uint16_t FLAG_END_FAIL_TIMEOUT; - static const uint16_t FLAG_END_FAIL_FULL; - - - /** transaction type **/ - static const uint16_t FLAG_TYPE_GRP_LIST_RESP; - static const uint16_t FLAG_TYPE_MSG_LIST_RESP; - static const uint16_t FLAG_TYPE_GRP_LIST_REQ; - static const uint16_t FLAG_TYPE_MSG_LIST_REQ; - static const uint16_t FLAG_TYPE_GRPS; - static const uint16_t FLAG_TYPE_MSGS; - static const uint16_t FLAG_TYPE_ENCRYPTED_DATA; - - explicit RsNxsTransacItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_TRANSAC_ITEM) { clear(); } - virtual ~RsNxsTransacItem() {} - - virtual void clear() override; - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override; - - uint16_t transactFlag; - uint32_t nItems; - uint32_t updateTS; - - // not serialised - uint32_t timestamp; -}; - -/*! - * Use to send to peer list of grps - * held by server peer - */ -class RsNxsSyncGrpItem: public RsNxsItem -{ - -public: - - static const uint8_t FLAG_REQUEST; - static const uint8_t FLAG_RESPONSE; - static const uint8_t FLAG_USE_SYNC_HASH; - - explicit RsNxsSyncGrpItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SYNC_GRP_ITEM) { clear();} - virtual ~RsNxsSyncGrpItem() {} - - virtual void clear() override; - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override; - - uint8_t flag; // request or response - uint32_t publishTs; // to compare to Ts of receiving peer's grp of same id - - /// grpId of grp held by sending peer - RsGxsGroupId grpId; - RsGxsId authorId; - -}; - -#ifdef SUSPENDED_CODE_27042017 -/*! - * Use to send to peer list of grps - * held by server peer - */ -class RsNxsSessionKeyItem : public RsNxsItem -{ - -public: - - explicit RsNxsSessionKeyItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SESSION_KEY_ITEM) { clear(); } - virtual ~RsNxsSessionKeyItem() {} - - virtual void clear() override; - - /// Session key encrypted for the whole group - /// - uint8_t iv[EVP_MAX_IV_LENGTH] ; // initialisation vector - std::map encrypted_session_keys; // encrypted session keys -}; -#endif -/*! - * Use to send to peer list of grps - * held by server peer - */ -class RsNxsEncryptedDataItem : public RsNxsItem -{ - -public: - - explicit RsNxsEncryptedDataItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_ENCRYPTED_DATA_ITEM),encrypted_data(servtype) - { - encrypted_data.tlvtype = TLV_TYPE_BIN_ENCRYPTED ; - clear(); - } - virtual ~RsNxsEncryptedDataItem() {} - virtual void clear() override; - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override; - - /// grpId of grp held by sending peer - /// - RsTlvBinaryData encrypted_data ; -}; - - -/*! - * Contains serialised group items - * Each item corresponds to a group which needs to be - * deserialised - */ -class RsNxsGrp : public RsNxsItem -{ - -public: - - explicit RsNxsGrp(uint16_t servtype) - : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_GRP_ITEM) - , pos(0), count(0), meta(servtype), grp(servtype), metaData(NULL) - { clear(); } - virtual ~RsNxsGrp() { delete metaData; } - - RsNxsGrp* clone() const; - - virtual void clear() override; - - virtual void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override; - - uint8_t pos; /// used for splitting up grp - uint8_t count; /// number of split up messages - RsGxsGroupId grpId; /// group Id, needed to complete version Id (ncvi) - static int refcount; - - /*! - * This should contains all data - * which is not specific to the Gxs service data - */ - // This is the binary data for the group meta that is sent to friends. It *should not* contain any private - // key parts. This is ensured in RsGenExchange - - RsTlvBinaryData meta; - - RsTlvBinaryData grp; /// actual group data - - // Deserialised metaData, this is not serialised by the serialize() method. So it may contain private key parts in some cases. - RsGxsGrpMetaData* metaData; -}; - -/*! - * Use to request list of msg held by peer - * for a given group - */ -class RsNxsSyncMsgReqItem : public RsNxsItem -{ - -public: - -#ifdef UNUSED_CODE - static const uint8_t FLAG_USE_SYNC_HASH; -#endif - static const uint8_t FLAG_USE_HASHED_GROUP_ID; - - explicit RsNxsSyncMsgReqItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SYNC_MSG_REQ_ITEM) { clear(); } - - virtual void clear() override; - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override; - - RsGxsGroupId grpId; - uint8_t flag; - uint32_t createdSinceTS; - uint32_t updateTS; // time of last update - std::string syncHash; -}; - -/*! - * Use to send list msgs for a group held by - * a peer - */ -class RsNxsSyncMsgItem : public RsNxsItem -{ -public: - - static const uint8_t FLAG_REQUEST; - static const uint8_t FLAG_RESPONSE; - static const uint8_t FLAG_USE_SYNC_HASH; - explicit RsNxsSyncMsgItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SYNC_MSG_ITEM) { clear(); } - - virtual void clear() override; - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override; - - uint8_t flag; // response/req - RsGxsGroupId grpId; - RsGxsMessageId msgId; - RsGxsId authorId; - -}; - -/*! - * Used to request to a peer pull updates from us ASAP without waiting GXS sync - * timer */ -class RsNxsPullRequestItem: public RsNxsItem -{ -public: - explicit RsNxsPullRequestItem(uint16_t servtype): RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SYNC_PULL_REQUEST_ITEM) {} - - /// @see RsSerializable - void serial_process( RsGenericSerializer::SerializeJob, - RsGenericSerializer::SerializeContext& ) override {} -}; - - -/*! - * Used to respond to a RsGrpMsgsReq - * with message items satisfying request - */ -class RsNxsMsg : public RsNxsItem -{ -public: - explicit RsNxsMsg(uint16_t servtype) - : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_MSG_ITEM) - , pos(0), count(0), meta(servtype), msg(servtype), metaData(NULL) - { clear(); } - virtual ~RsNxsMsg() { delete metaData; } - - virtual void clear() override; - - virtual void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override; - - uint8_t pos; /// used for splitting up msg - uint8_t count; /// number of split up messages - RsGxsGroupId grpId; /// group id, forms part of version id - RsGxsMessageId msgId; /// msg id - static int refcount; - - /*! - * This should contains all the data - * which is not specific to the Gxs service data - */ - RsTlvBinaryData meta; - - /*! - * This contains Gxs specific data - * only client of API knows how to decode this - */ - RsTlvBinaryData msg; - - RsGxsMsgMetaData* metaData; -}; - -#ifdef RS_DEAD_CODE -/*! - * Used to request a search of user data - */ -class RsNxsSearchReqItem : public RsNxsItem -{ -public: - - explicit RsNxsSearchReqItem(uint16_t servtype) - : RsNxsItem(servtype, RS_PKT_SUBTYPE_EXT_SEARCH_REQ) - , nHops(0), token(0), serviceSearchItem(servtype), expiration(0) - {} - virtual ~RsNxsSearchReqItem() {} - virtual void clear() override {} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override; - - uint8_t nHops; /// how many peers to jump to - uint32_t token; // search token - RsTlvBinaryData serviceSearchItem; // service aware of item class - uint32_t expiration; // expiration date -}; -#endif //def RS_DEAD_CODE - -#ifdef UNUSED_CODE - -/*! - * Used to respond to a RsGrpSearchReq - * with grpId/MsgIds that satisfy search request - */ -class RsNxsSearchResultMsgItem -{ -public: - - RsNxsSearchResultMsgItem() - : token(0), context(0), expiration(0) - {} - - void clear() {} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t token; // search token to be redeemed - RsTlvBinaryData context; // used by client service - std::string msgId; - std::string grpId; - RsTlvKeySignature idSign; - - uint32_t expiration; // expiration date -}; - -/*! - * Used to respond to a RsGrpSearchReq - * with grpId/MsgIds that satisfy search request - */ -class RsNxsSearchResultGrpItem -{ -public: - - RsNxsSearchResultGrpItem(); - - void clear() {} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t token; // search token to be redeemed - RsTlvBinaryData context; // used by client service - - std::string grpId; - RsTlvKeySignature adminSign; - - uint32_t expiration; // expiration date -}; - -class RsNxsDeleteMsg -{ -public: - - RsNxsDeleteMsg() { return; } - - std::string msgId; - std::string grpId; - RsTlvKeySignature deleteSign; // ( msgId + grpId + msg data ) sign //TODO: add warning not to place msgId+grpId in msg! - -}; - -class RsNxsDeleteGrp -{ -public: - - RsNxsDeleteGrp() { return;} - - std::string grpId; - RsTlvKeySignature idSign; - RsTlvKeySignature deleteSign; // (grpId + grp data) sign // TODO: add warning not to place grpId in msg -}; -#endif - - -class RsNxsSerialiser : public RsServiceSerializer -{ -public: - - explicit RsNxsSerialiser(uint16_t servtype): - RsServiceSerializer(servtype), SERVICE_TYPE(servtype) {} - virtual ~RsNxsSerialiser() = default; - - - virtual RsItem *create_item(uint16_t service_id,uint8_t item_subtype) const ; -protected: - const uint16_t SERVICE_TYPE; -}; diff --git a/libretroshare/src/rsitems/rsphotoitems.cc b/libretroshare/src/rsitems/rsphotoitems.cc deleted file mode 100644 index f9200a83c..000000000 --- a/libretroshare/src/rsitems/rsphotoitems.cc +++ /dev/null @@ -1,85 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsphotoitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 Christopher Evi-Parker,Robert Fernie* - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include - -#include "rsitems/rsphotoitems.h" - -#include "serialiser/rstlvbinary.h" -#include "serialiser/rstypeserializer.h" - -RsItem *RsGxsPhotoSerialiser::create_item(uint16_t service, uint8_t item_sub_id) const -{ - if(service != RS_SERVICE_GXS_TYPE_PHOTO) - return NULL ; - - switch(item_sub_id) - { - case RS_PKT_SUBTYPE_PHOTO_SHOW_ITEM: return new RsGxsPhotoPhotoItem() ; - case RS_PKT_SUBTYPE_PHOTO_ITEM: return new RsGxsPhotoAlbumItem() ; - default: - return RsGxsCommentSerialiser::create_item(service,item_sub_id) ; - } -} - -void RsGxsPhotoAlbumItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_UINT32_PARAM,album.mShareMode,"mShareMode"); - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_CAPTION, album.mCaption, "mCaption"); - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DESCR, album.mDescription, "mDescription"); - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_NAME, album.mPhotographer, "mPhotographer"); - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_LOCATION, album.mWhere, "mWhere"); - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DATE, album.mWhen, "mWhen"); - - album.mThumbnail.serial_process(j, ctx); -} -void RsGxsPhotoPhotoItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DESCR, photo.mDescription, "mDescription"); - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_UINT32_PARAM,photo.mOrder,"mOrder"); - photo.mLowResImage.serial_process(j, ctx); - photo.mPhotoFile.serial_process(j, ctx); -} - -void RsGxsPhotoAlbumItem::clear() -{ - album.mShareMode = RSPHOTO_SHAREMODE_LOWRESONLY; - album.mCaption.clear(); - album.mDescription.clear(); - album.mPhotographer.clear(); - album.mWhere.clear(); - album.mWhen.clear(); - album.mThumbnail.clear(); - - // not saved - album.mAutoDownload = false; -} - -void RsGxsPhotoPhotoItem::clear() -{ - photo.mDescription.clear(); - photo.mOrder = 0; - photo.mLowResImage.clear(); - photo.mPhotoFile.clear(); - - // not saved - photo.mPath.clear(); -} diff --git a/libretroshare/src/rsitems/rsphotoitems.h b/libretroshare/src/rsitems/rsphotoitems.h deleted file mode 100644 index a504ae29b..000000000 --- a/libretroshare/src/rsitems/rsphotoitems.h +++ /dev/null @@ -1,79 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsphotoitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 Christopher Evi-Parker,Robert Fernie* - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RSPHOTOV2ITEMS_H_ -#define RSPHOTOV2ITEMS_H_ - -#include - -#include "rsitems/rsserviceids.h" -#include "rsitems/rsgxsitems.h" -#include "rsitems/rsgxscommentitems.h" - -#include "serialiser/rsserial.h" -#include "serialiser/rsserializer.h" - -#include "retroshare/rsphoto.h" - -const uint8_t RS_PKT_SUBTYPE_PHOTO_ITEM = 0x02; -const uint8_t RS_PKT_SUBTYPE_PHOTO_SHOW_ITEM = 0x03; - -class RsGxsPhotoAlbumItem : public RsGxsGrpItem -{ - -public: - - RsGxsPhotoAlbumItem(): RsGxsGrpItem(RS_SERVICE_GXS_TYPE_PHOTO, - RS_PKT_SUBTYPE_PHOTO_ITEM) { return;} - virtual ~RsGxsPhotoAlbumItem() { return;} - - void clear(); -// std::ostream &print(std::ostream &out, uint16_t indent = 0); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsPhotoAlbum album; -}; - -class RsGxsPhotoPhotoItem : public RsGxsMsgItem -{ -public: - - RsGxsPhotoPhotoItem(): RsGxsMsgItem(RS_SERVICE_GXS_TYPE_PHOTO, RS_PKT_SUBTYPE_PHOTO_SHOW_ITEM) {} - virtual ~RsGxsPhotoPhotoItem() {} - void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsPhotoPhoto photo; -}; - -class RsGxsPhotoSerialiser : public RsGxsCommentSerialiser -{ -public: - - RsGxsPhotoSerialiser() :RsGxsCommentSerialiser(RS_SERVICE_GXS_TYPE_PHOTO) {} - virtual ~RsGxsPhotoSerialiser() {} - - virtual RsItem *create_item(uint16_t service, uint8_t item_sub_id) const; -}; - -#endif /* RSPHOTOV2ITEMS_H_ */ diff --git a/libretroshare/src/rsitems/rspluginitems.h b/libretroshare/src/rsitems/rspluginitems.h deleted file mode 100644 index 29069815d..000000000 --- a/libretroshare/src/rsitems/rspluginitems.h +++ /dev/null @@ -1,68 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rspluginitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include "rsitems/rsitem.h" -#include "rsitems/rsconfigitems.h" - -#include "serialiser/rstypeserializer.h" - -const uint8_t RS_PKT_CLASS_PLUGIN_SUBTYPE_HASHSET = 0x01 ; - -class RsPluginItem: public RsItem -{ - public: - explicit RsPluginItem(uint8_t plugin_item_subtype): RsItem(RS_PKT_VERSION1,RS_PKT_CLASS_CONFIG,RS_PKT_TYPE_PLUGIN_CONFIG,plugin_item_subtype) {} - virtual ~RsPluginItem() {} - - virtual void clear() {} -}; - -class RsPluginHashSetItem: public RsPluginItem -{ - public: - RsPluginHashSetItem() : RsPluginItem(RS_PKT_CLASS_PLUGIN_SUBTYPE_HASHSET) {} - RsPluginHashSetItem(void *data,uint32_t size) ; - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) - { - RsTypeSerializer::serial_process(j,ctx,hashes,"hashes"); - } - - RsTlvHashSet hashes ; -}; - -class RsPluginSerialiser: public RsConfigSerializer -{ - public: - RsPluginSerialiser() : RsConfigSerializer(RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_PLUGIN_CONFIG) {} - - virtual RsItem *create_item(uint8_t class_type, uint8_t item_type) const - { - if(class_type == RS_PKT_TYPE_PLUGIN_CONFIG && item_type == RS_PKT_CLASS_PLUGIN_SUBTYPE_HASHSET) - return new RsPluginHashSetItem() ; - - return NULL ; - } -}; - - diff --git a/libretroshare/src/rsitems/rsposteditems.cc b/libretroshare/src/rsitems/rsposteditems.cc deleted file mode 100644 index 3c16ff5bd..000000000 --- a/libretroshare/src/rsitems/rsposteditems.cc +++ /dev/null @@ -1,158 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsposteditems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "rsitems/rsposteditems.h" -#include "serialiser/rstypeserializer.h" - - - -void RsGxsPostedPostItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_LINK,mPost.mLink,"mPost.mLink") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG ,mPost.mNotes,"mPost.mNotes") ; - - // Do not serialize mImage member if it is empty (keeps compatibility of new posts without image toward older RS) - // and do not expect to deserialize mImage member if the data block has been consummed entirely (keeps compatibility - // of new RS with older posts. - - if(j == RsGenericSerializer::DESERIALIZE && ctx.mOffset == ctx.mSize) - return ; - - if((j == RsGenericSerializer::SIZE_ESTIMATE || j == RsGenericSerializer::SERIALIZE) && mImage.empty()) - return ; - - RsTypeSerializer::serial_process(j,ctx,mImage,"mImage") ; -} - -void RsGxsPostedGroupItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DESCR ,mDescription,"mDescription") ; - - if(j == RsGenericSerializer::DESERIALIZE && ctx.mOffset == ctx.mSize) - return ; - - if((j == RsGenericSerializer::SIZE_ESTIMATE || j == RsGenericSerializer::SERIALIZE) && mGroupImage.empty()) - return ; - - RsTypeSerializer::serial_process(j,ctx,mGroupImage,"mGroupImage") ; -} - -RsItem *RsGxsPostedSerialiser::create_item(uint16_t service_id,uint8_t item_subtype) const -{ - if(service_id != RS_SERVICE_GXS_TYPE_POSTED) - return NULL ; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_POSTED_GRP_ITEM: return new RsGxsPostedGroupItem() ; - case RS_PKT_SUBTYPE_POSTED_POST_ITEM: return new RsGxsPostedPostItem() ; - default: - return RsGxsCommentSerialiser::create_item(service_id,item_subtype) ; - } -} - -bool RsGxsPostedPostItem::fromPostedPost(RsPostedPost &post, bool moveImage) -{ - clear(); - - mPost = post; - meta = post.mMeta; - - if (moveImage) - { - mImage.binData.bin_data = post.mImage.mData; - mImage.binData.bin_len = post.mImage.mSize; - post.mImage.shallowClear(); - } - else - { - mImage.binData.setBinData(post.mImage.mData, post.mImage.mSize); - } - - return true; -} - -bool RsGxsPostedPostItem::toPostedPost(RsPostedPost &post, bool moveImage) -{ - post = mPost; - post.mMeta = meta; - - if (moveImage) - { - post.mImage.take((uint8_t *) mImage.binData.bin_data, mImage.binData.bin_len); - // mImage doesn't have a ShallowClear at the moment! - mImage.binData.TlvShallowClear(); - } - else - { - post.mImage.copy((uint8_t *) mImage.binData.bin_data, mImage.binData.bin_len); - } - - return true; -} - -void RsGxsPostedPostItem::clear() -{ - mPost.mLink.clear(); - mPost.mNotes.clear(); - mImage.TlvClear(); -} -void RsGxsPostedGroupItem::clear() -{ - mDescription.clear(); - mGroupImage.TlvClear(); -} - -bool RsGxsPostedGroupItem::fromPostedGroup(RsPostedGroup &group, bool moveImage) -{ - clear(); - meta = group.mMeta; - mDescription = group.mDescription; - - if (moveImage) - { - mGroupImage.binData.bin_data = group.mGroupImage.mData; - mGroupImage.binData.bin_len = group.mGroupImage.mSize; - group.mGroupImage.shallowClear(); - } - else - { - mGroupImage.binData.setBinData(group.mGroupImage.mData, group.mGroupImage.mSize); - } - return true; -} - -bool RsGxsPostedGroupItem::toPostedGroup(RsPostedGroup &group, bool moveImage) -{ - group.mMeta = meta; - group.mDescription = mDescription; - if (moveImage) - { - group.mGroupImage.take((uint8_t *) mGroupImage.binData.bin_data, mGroupImage.binData.bin_len); - // mGroupImage doesn't have a ShallowClear at the moment! - mGroupImage.binData.TlvShallowClear(); - } - else - { - group.mGroupImage.copy((uint8_t *) mGroupImage.binData.bin_data, mGroupImage.binData.bin_len); - } - return true; -} diff --git a/libretroshare/src/rsitems/rsposteditems.h b/libretroshare/src/rsitems/rsposteditems.h deleted file mode 100644 index 910471c19..000000000 --- a/libretroshare/src/rsitems/rsposteditems.h +++ /dev/null @@ -1,84 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsposteditems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RSPOSTEDITEMS_H -#define RSPOSTEDITEMS_H - -#include "rsitems/rsserviceids.h" -#include "rsitems/rsgxscommentitems.h" -#include "rsitems/rsgxsitems.h" -#include "serialiser/rstlvimage.h" - -#include "retroshare/rsposted.h" - -const uint8_t RS_PKT_SUBTYPE_POSTED_GRP_ITEM = 0x02; -const uint8_t RS_PKT_SUBTYPE_POSTED_POST_ITEM = 0x03; - -class RsGxsPostedGroupItem : public RsGxsGrpItem -{ -public: - RsGxsPostedGroupItem() : RsGxsGrpItem(RS_SERVICE_GXS_TYPE_POSTED, RS_PKT_SUBTYPE_POSTED_GRP_ITEM) {} - virtual ~RsGxsPostedGroupItem() {} - - void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - // use conversion functions to transform: - bool fromPostedGroup(RsPostedGroup &group, bool moveImage); - bool toPostedGroup(RsPostedGroup &group, bool moveImage); - - std::string mDescription; - RsTlvImage mGroupImage; - -}; - -class RsGxsPostedPostItem : public RsGxsMsgItem -{ -public: - RsGxsPostedPostItem() : RsGxsMsgItem(RS_SERVICE_GXS_TYPE_POSTED, RS_PKT_SUBTYPE_POSTED_POST_ITEM) {} - virtual ~RsGxsPostedPostItem() {} - - void clear(); - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - // Slightly unusual structure. - // use conversion functions to transform: - bool fromPostedPost(RsPostedPost &post, bool moveImage); - bool toPostedPost(RsPostedPost &post, bool moveImage); - - RsPostedPost mPost; - RsTlvImage mImage; -}; - -class RsGxsPostedSerialiser : public RsGxsCommentSerialiser -{ -public: - - RsGxsPostedSerialiser() :RsGxsCommentSerialiser(RS_SERVICE_GXS_TYPE_POSTED) {} - - virtual ~RsGxsPostedSerialiser() {} - - virtual RsItem *create_item(uint16_t service_id,uint8_t item_subtype) const ; -}; - - -#endif // RSPOSTEDITEMS_H diff --git a/libretroshare/src/rsitems/rsrttitems.cc b/libretroshare/src/rsitems/rsrttitems.cc deleted file mode 100644 index 739f1c06d..000000000 --- a/libretroshare/src/rsitems/rsrttitems.cc +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsrttitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2013 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "rsitems/rsrttitems.h" - -/*** -#define RSSERIAL_DEBUG 1 -***/ - -#include - -#include "serialiser/rstypeserializer.h" - -/*************************************************************************/ - -RsItem *RsRttSerialiser::create_item(uint16_t service,uint8_t type) const -{ - if(service != RS_SERVICE_TYPE_RTT) - return NULL ; - - switch(type) - { - case RS_PKT_SUBTYPE_RTT_PING: return new RsRttPingItem() ; //= 0x01; - case RS_PKT_SUBTYPE_RTT_PONG: return new RsRttPongItem() ; // = 0x02; - default: - return NULL ; - } -} - -void RsRttPingItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,mSeqNo,"mSeqNo") ; - RsTypeSerializer::serial_process(j,ctx,mPingTS,"mPingTS") ; -} - -void RsRttPongItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,mSeqNo,"mSeqNo") ; - RsTypeSerializer::serial_process(j,ctx,mPingTS,"mPingTS") ; - RsTypeSerializer::serial_process(j,ctx,mPongTS,"mPongTS") ; -} - - - diff --git a/libretroshare/src/rsitems/rsrttitems.h b/libretroshare/src/rsitems/rsrttitems.h deleted file mode 100644 index 54f612ee6..000000000 --- a/libretroshare/src/rsitems/rsrttitems.h +++ /dev/null @@ -1,99 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsrttitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2013 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_RTT_ITEMS_H -#define RS_RTT_ITEMS_H - -#include - -#include "rsitems/rsitem.h" -#include "rsitems/rsserviceids.h" -#include "rsitems/itempriorities.h" -#include "serialiser/rsserial.h" - -#include "serialiser/rsserializer.h" - -/**************************************************************************/ - -const uint8_t RS_PKT_SUBTYPE_RTT_PING = 0x01; -const uint8_t RS_PKT_SUBTYPE_RTT_PONG = 0x02; - -class RsRttItem: public RsItem -{ - public: - explicit RsRttItem(uint8_t subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_RTT,subtype) - { setPriorityLevel(QOS_PRIORITY_RS_RTT_PING) ;} // should be refined later. - - virtual ~RsRttItem() {} - virtual void clear() {} -}; - -class RsRttPingItem: public RsRttItem -{ - public: - RsRttPingItem() - : RsRttItem(RS_PKT_SUBTYPE_RTT_PING) - , mSeqNo(0), mPingTS(0) - {} - - virtual ~RsRttPingItem(){} - virtual void clear(){} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t mSeqNo; - uint64_t mPingTS; -}; - -class RsRttPongItem: public RsRttItem -{ - public: - RsRttPongItem() - : RsRttItem(RS_PKT_SUBTYPE_RTT_PONG) - , mSeqNo(0), mPingTS(0), mPongTS(0) - {} - - virtual ~RsRttPongItem(){} - virtual void clear(){} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t mSeqNo; - uint64_t mPingTS; - uint64_t mPongTS; -}; - - -class RsRttSerialiser: public RsServiceSerializer -{ - public: - RsRttSerialiser() :RsServiceSerializer(RS_SERVICE_TYPE_RTT) {} - - virtual ~RsRttSerialiser(){} - - virtual RsItem *create_item(uint16_t service,uint8_t type) const; -}; - -/**************************************************************************/ - -#endif /* RS_RTT_ITEMS_H */ - - diff --git a/libretroshare/src/rsitems/rsserviceids.h b/libretroshare/src/rsitems/rsserviceids.h deleted file mode 100644 index a80931aca..000000000 --- a/libretroshare/src/rsitems/rsserviceids.h +++ /dev/null @@ -1,161 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsserviceids.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2007-2008 Robert Fernie * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include "util/rsdeprecate.h" - -#include - -enum class RsServiceType : uint16_t -{ - /// To detect non-initialized items - NONE = 0, - - GOSSIP_DISCOVERY = 0x0011, - CHAT = 0x0012, - MSG = 0x0013, - TURTLE = 0x0014, - TUNNEL = 0x0015, - HEARTBEAT = 0x0016, - FILE_TRANSFER = 0x0017, - GROUTER = 0x0018, - FILE_DATABASE = 0x0019, - SERVICEINFO = 0x0020, - BANDWIDTH_CONTROL = 0x0021, - MAIL = 0x0022, - DIRECT_MAIL = 0x0023, - DISTANT_MAIL = 0x0024, - GWEMAIL_MAIL = 0x0025, - SERVICE_CONTROL = 0x0026, - DISTANT_CHAT = 0x0027, - - /// For GXS identity authenticated tunnels, do not confuse with @GXS_DISTANT - GXS_TUNNEL = 0x0028, - - BANLIST = 0x0101, - STATUS = 0x0102, - FRIEND_SERVER = 0x0103, - NXS = 0x0200, - GXSID = 0x0211, - PHOTO = 0x0212, - WIKI = 0x0213, - WIRE = 0x0214, - FORUMS = 0x0215, - POSTED = 0x0216, - CHANNELS = 0x0217, - GXSCIRCLE = 0x0218, - - /// not gxs, but used with identities. - REPUTATION = 0x0219, - GXS_RECOGN = 0x0220, - GXS_TRANS = 0x0230, - JSONAPI = 0x0240, - FORUMS_CONFIG = 0x0315, - POSTED_CONFIG = 0x0316, - CHANNELS_CONFIG = 0x0317, - RTT = 0x1011, /// Round Trip Time - - PLUGIN_ARADO_ID = 0x2001, - PLUGIN_QCHESS_ID = 0x2002, - PLUGIN_FEEDREADER = 0x2003, - - /// GXS distant sync and search do not confuse with @see GXS_TUNNEL - GXS_DISTANT = 0x2233, - - /// Reserved for packet slicing probes. - PACKET_SLICING_PROBE = 0xAABB, - - // Nabu's experimental services. - PLUGIN_FIDO_GW = 0xF1D0, - PLUGIN_ZERORESERVE = 0xBEEF -}; - - - -// TODO: Port all services types to RsServiceType - -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_FILE_INDEX = 0x0001; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_DISC = 0x0011; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_CHAT = 0x0012; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_MSG = 0x0013; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_TURTLE = 0x0014; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_TUNNEL = 0x0015; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_HEARTBEAT = 0x0016; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_FILE_TRANSFER = 0x0017; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_GROUTER = 0x0018; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_FILE_DATABASE = 0x0019; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_SERVICEINFO = 0x0020; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_BWCTRL = 0x0021; /// Bandwidth Control -/// New Mail Service (replace old Msg Service) -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_MAIL = 0x0022; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_DIRECT_MAIL = 0x0023; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_DISTANT_MAIL = 0x0024; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_GWEMAIL_MAIL = 0x0025; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_SERVICE_CONTROL= 0x0026; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_DISTANT_CHAT = 0x0027; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_GXS_TUNNEL = 0x0028; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_BANLIST = 0x0101; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_STATUS = 0x0102; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_FRIEND_SERVER = 0x0103; - -/// Rs Network Exchange Service -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_NXS = 0x0200; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_GXSID = 0x0211; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_PHOTO = 0x0212; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_WIKI = 0x0213; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_WIRE = 0x0214; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_FORUMS = 0x0215; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_POSTED = 0x0216; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_CHANNELS = 0x0217; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_GXSCIRCLE = 0x0218; -/// not gxs, but used with identities. -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_REPUTATION = 0x0219; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_GXS_RECOGN = 0x0220; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_GXS_TRANS = 0x0230; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_JSONAPI = 0x0240; -/// used to save notification records in GXS and possible other service-based configuration -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_FORUMS_CONFIG = 0x0315; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_POSTED_CONFIG = 0x0316; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_CHANNELS_CONFIG = 0x0317; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_CIRCLES_CONFIG = 0x0318; - -// Experimental Services. -/* DSDV Testing at the moment - Service Only */ -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_DSDV = 0x1010; -/* Latency RTT Measurements */ -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_RTT = 0x1011; - - -/***************** IDS ALLOCATED FOR PLUGINS ******************/ -// 2000+ - -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_PLUGIN_ARADO_ID = 0x2001; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_PLUGIN_QCHESS_ID = 0x2002; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_PLUGIN_FEEDREADER = 0x2003; - -// Reserved for packet slicing probes. -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_PACKET_SLICING_PROBE = 0xAABB; - -// Nabu's services. -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_PLUGIN_FIDO_GW = 0xF1D0; -RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_PLUGIN_ZERORESERVE = 0xBEEF; diff --git a/libretroshare/src/rsitems/rsserviceinfoitems.cc b/libretroshare/src/rsitems/rsserviceinfoitems.cc deleted file mode 100644 index 8d007941d..000000000 --- a/libretroshare/src/rsitems/rsserviceinfoitems.cc +++ /dev/null @@ -1,169 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsserviceinfoitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstypeserializer.h" -#include "rsitems/rsserviceinfoitems.h" - -/*** -#define RSSERIAL_DEBUG 1 -***/ - -#include - -/*************************************************************************/ -/***** RsServiceInfo ****/ -/*************************************************************************/ - -void RsServiceInfoListItem::clear() -{ - mServiceInfo.clear(); -} - -void RsServiceInfoListItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTlvServiceInfoMapRef map(mServiceInfo); - - RsTypeSerializer::serial_process(j,ctx,map,"map") ; -} - -void RsServiceInfoPermissionsItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,allowedBw,"allowedBw") ; -} - -RsItem *RsServiceInfoSerialiser::create_item(uint16_t service, uint8_t item_sub_id) const -{ - if(service != RS_SERVICE_TYPE_SERVICEINFO) - return NULL ; - - switch(item_sub_id) - { - case RS_PKT_SUBTYPE_SERVICELIST_ITEM: return new RsServiceInfoListItem() ; - case RS_PKT_SUBTYPE_SERVICEPERMISSIONS_ITEM: return new RsServiceInfoPermissionsItem() ; - default: - return NULL ; - } -} - - - - -template<> std::ostream& RsTlvParamRef::print(std::ostream &out, uint16_t /*indent*/) const -{ - out << "RsServiceInfo: " << mParam.mServiceType << " name " << mParam.mServiceName; - out << std::endl; - out << "Version(" << mParam.mVersionMajor << "," << mParam.mVersionMinor << ")"; - out << " MinVersion(" << mParam.mMinVersionMajor << "," << mParam.mMinVersionMinor << ")"; - out << std::endl; - return out; -} - -template<> -uint32_t RsTlvParamRef::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header + 4 for size */ - - s += getRawStringSize(mParam.mServiceName); - s += 4; // type. - s += 4; // version. - s += 4; // min version. - return s; -} - -template<> -void RsTlvParamRef::TlvClear() -{ - mParam = RsServiceInfo(); - mParam.mServiceName.clear(); -} - -template<> -bool RsTlvParamRef::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - { - return false; /* not enough space */ - } - - bool ok = true; - - ok &= SetTlvBase(data, tlvend, offset, mParamType, tlvsize); - ok &= setRawString(data, tlvend, offset, mParam.mServiceName); - ok &= setRawUInt32(data, tlvend, offset, mParam.mServiceType); - ok &= setRawUInt16(data, tlvend, offset, mParam.mVersionMajor); - ok &= setRawUInt16(data, tlvend, offset, mParam.mVersionMinor); - ok &= setRawUInt16(data, tlvend, offset, mParam.mMinVersionMajor); - ok &= setRawUInt16(data, tlvend, offset, mParam.mMinVersionMinor); - - if (!ok) - { - std::cerr << "RsTlvParamRef::SetTlv() Failed"; - std::cerr << std::endl; - } - - return ok; -} - -template<> -bool RsTlvParamRef::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - { - return false; /* not enough space */ - } - - if (tlvtype != mParamType) /* check type */ - { - return false; - } - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - ok &= getRawString(data, tlvend, offset, mParam.mServiceName); - ok &= getRawUInt32(data, tlvend, offset, &(mParam.mServiceType)); - ok &= getRawUInt16(data, tlvend, offset, &(mParam.mVersionMajor)); - ok &= getRawUInt16(data, tlvend, offset, &(mParam.mVersionMinor)); - ok &= getRawUInt16(data, tlvend, offset, &(mParam.mMinVersionMajor)); - ok &= getRawUInt16(data, tlvend, offset, &(mParam.mMinVersionMinor)); - - return ok; -} - -template class RsTlvParamRef; - diff --git a/libretroshare/src/rsitems/rsserviceinfoitems.h b/libretroshare/src/rsitems/rsserviceinfoitems.h deleted file mode 100644 index e3d04b3c8..000000000 --- a/libretroshare/src/rsitems/rsserviceinfoitems.h +++ /dev/null @@ -1,105 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsserviceinfoitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_SERVICE_INFO_ITEMS_H -#define RS_SERVICE_INFO_ITEMS_H - -// Provides serialiser for p3ServiceControl & p3ServiceInfo. - -#include - -#include "rsitems/rsserviceids.h" -#include "rsitems/rsitem.h" -#include "rsitems/itempriorities.h" - -#include "serialiser/rstlvgenericmap.h" -#include "retroshare/rsservicecontrol.h" - -#define RS_PKT_SUBTYPE_SERVICELIST_ITEM 0x01 -#define RS_PKT_SUBTYPE_SERVICEPERMISSIONS_ITEM 0x02 - -/**************************************************************************/ -#define SERVICE_INFO_MAP 0x01 -#define SERVICE_INFO_KEY 0x01 -#define SERVICE_ID 0x01 -#define SERVICE_INFO 0x01 - -class RsTlvServiceInfoMapRef: public RsTlvGenericMapRef -{ -public: - RsTlvServiceInfoMapRef(std::map &refmap) - :RsTlvGenericMapRef( - SERVICE_INFO_MAP, - SERVICE_INFO_KEY, - SERVICE_ID, - SERVICE_INFO, - refmap) - { - return; - } -}; - -class RsServiceInfoListItem: public RsItem -{ - public: - RsServiceInfoListItem() :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_SERVICEINFO, RS_PKT_SUBTYPE_SERVICELIST_ITEM) - { - setPriorityLevel(QOS_PRIORITY_RS_SERVICE_INFO_ITEM); - return; - } - - virtual ~RsServiceInfoListItem(){} - virtual void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - std::map mServiceInfo; -}; - -class RsServiceInfoPermissionsItem: public RsItem -{ - public: - RsServiceInfoPermissionsItem() :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_SERVICEINFO, RS_PKT_SUBTYPE_SERVICEPERMISSIONS_ITEM) - { - setPriorityLevel(QOS_PRIORITY_RS_SERVICE_INFO_ITEM); - return; - } - - virtual ~RsServiceInfoPermissionsItem(){} - virtual void clear(){} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - uint32_t allowedBw; // Units are bytes/sec => 4Gb/s; -}; - -class RsServiceInfoSerialiser: public RsServiceSerializer -{ - public: - RsServiceInfoSerialiser() :RsServiceSerializer(RS_SERVICE_TYPE_SERVICEINFO) {} - virtual ~RsServiceInfoSerialiser() {} - - virtual RsItem *create_item(uint16_t /* service */, uint8_t /* item_sub_id */) const; -}; - -/**************************************************************************/ - -#endif /* RS_SERVICE_INFO_ITEMS_H */ diff --git a/libretroshare/src/rsitems/rsstatusitems.h b/libretroshare/src/rsitems/rsstatusitems.h deleted file mode 100644 index e92db7816..000000000 --- a/libretroshare/src/rsitems/rsstatusitems.h +++ /dev/null @@ -1,75 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rsstatusitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Vinny Do. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_STATUS_ITEMS_H -#define RS_STATUS_ITEMS_H - -#include "rsitems/rsserviceids.h" -#include "rsitems/itempriorities.h" -#include "rsitems/rsitem.h" - -#include "serialiser/rstypeserializer.h" - -/**************************************************************************/ - -class RsStatusItem: public RsItem -{ -public: - RsStatusItem() :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_STATUS, RS_PKT_SUBTYPE_DEFAULT) - { - setPriorityLevel(QOS_PRIORITY_RS_STATUS_ITEM); - } - virtual ~RsStatusItem() {} - virtual void clear() {} - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) - { - RsTypeSerializer::serial_process(j,ctx,sendTime,"sendTime") ; - RsTypeSerializer::serial_process(j,ctx,status ,"status") ; - } - - uint32_t sendTime; - uint32_t status; - - /* not serialised */ - uint32_t recvTime; -}; - -class RsStatusSerialiser: public RsServiceSerializer -{ -public: - RsStatusSerialiser() :RsServiceSerializer(RS_SERVICE_TYPE_STATUS) {} - virtual ~RsStatusSerialiser() {} - - virtual RsItem *create_item(uint16_t service,uint8_t item_subtype) const - { - if(service == RS_SERVICE_TYPE_STATUS && item_subtype == RS_PKT_SUBTYPE_DEFAULT) - return new RsStatusItem(); - else - return NULL ; - } -}; - -/**************************************************************************/ - -#endif /* RS_STATUS_ITEMS_H */ - - diff --git a/libretroshare/src/rsitems/rswikiitems.cc b/libretroshare/src/rsitems/rswikiitems.cc deleted file mode 100644 index e7ffa8508..000000000 --- a/libretroshare/src/rsitems/rswikiitems.cc +++ /dev/null @@ -1,80 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rswikiitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include - -#include "rsitems/rswikiitems.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rstypeserializer.h" - -#define GXSID_DEBUG 1 - -RsItem *RsGxsWikiSerialiser::create_item(uint16_t service, uint8_t item_sub_id) const -{ - if(service != RS_SERVICE_GXS_TYPE_WIKI) - return NULL ; - - switch(item_sub_id) - { - case RS_PKT_SUBTYPE_WIKI_COLLECTION_ITEM: return new RsGxsWikiCollectionItem(); - case RS_PKT_SUBTYPE_WIKI_COMMENT_ITEM: return new RsGxsWikiCommentItem(); - case RS_PKT_SUBTYPE_WIKI_SNAPSHOT_ITEM: return new RsGxsWikiSnapshotItem(); - default: - return NULL ; - } -} - -void RsGxsWikiCollectionItem::clear() -{ - collection.mDescription.clear(); - collection.mCategory.clear(); - collection.mHashTags.clear(); -} - -void RsGxsWikiCollectionItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DESCR ,collection.mDescription,"collection.mDescription") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_CATEGORY,collection.mCategory ,"collection.mCategory") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_HASH_TAG,collection.mHashTags ,"collection.mHashTags") ; -} - -void RsGxsWikiSnapshotItem::clear() -{ - snapshot.mPage.clear(); - snapshot.mHashTags.clear(); -} - -void RsGxsWikiSnapshotItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_WIKI_PAGE,snapshot.mPage,"snapshot.mPage") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_HASH_TAG ,snapshot.mPage,"snapshot.mHashTags") ; -} - -void RsGxsWikiCommentItem::clear() -{ - comment.mComment.clear(); -} - -void RsGxsWikiCommentItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_COMMENT,comment.mComment,"comment.mComment") ; -} - diff --git a/libretroshare/src/rsitems/rswikiitems.h b/libretroshare/src/rsitems/rswikiitems.h deleted file mode 100644 index fa5cf1533..000000000 --- a/libretroshare/src/rsitems/rswikiitems.h +++ /dev/null @@ -1,87 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rswikiitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef RS_WIKI_ITEMS_H -#define RS_WIKI_ITEMS_H - -#include - -#include "rsitems/rsserviceids.h" -#include "rsitems/rsitem.h" -#include "rsitems/rsgxsitems.h" - -#include "retroshare/rswiki.h" - -const uint8_t RS_PKT_SUBTYPE_WIKI_COLLECTION_ITEM = 0x02; -const uint8_t RS_PKT_SUBTYPE_WIKI_SNAPSHOT_ITEM = 0x03; -const uint8_t RS_PKT_SUBTYPE_WIKI_COMMENT_ITEM = 0x04; - -class RsGxsWikiCollectionItem : public RsGxsGrpItem -{ -public: - RsGxsWikiCollectionItem(): RsGxsGrpItem(RS_SERVICE_GXS_TYPE_WIKI, RS_PKT_SUBTYPE_WIKI_COLLECTION_ITEM) {} - virtual ~RsGxsWikiCollectionItem() {} - - void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsWikiCollection collection; -}; - -class RsGxsWikiSnapshotItem : public RsGxsMsgItem -{ -public: - - RsGxsWikiSnapshotItem(): RsGxsMsgItem(RS_SERVICE_GXS_TYPE_WIKI, RS_PKT_SUBTYPE_WIKI_SNAPSHOT_ITEM) {} - virtual ~RsGxsWikiSnapshotItem() {} - void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsWikiSnapshot snapshot; -}; - -class RsGxsWikiCommentItem : public RsGxsMsgItem -{ -public: - - RsGxsWikiCommentItem(): RsGxsMsgItem(RS_SERVICE_GXS_TYPE_WIKI, RS_PKT_SUBTYPE_WIKI_COMMENT_ITEM) {} - virtual ~RsGxsWikiCommentItem() {} - void clear(); - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsWikiComment comment; - -}; - -class RsGxsWikiSerialiser : public RsServiceSerializer -{ -public: - - RsGxsWikiSerialiser() :RsServiceSerializer(RS_SERVICE_GXS_TYPE_WIKI) {} - virtual ~RsGxsWikiSerialiser() {} - - virtual RsItem *create_item(uint16_t /* service */, uint8_t /* item_sub_id */) const; -}; - -#endif /* RS_WIKI_ITEMS_H */ diff --git a/libretroshare/src/rsitems/rswireitems.cc b/libretroshare/src/rsitems/rswireitems.cc deleted file mode 100644 index a618336f7..000000000 --- a/libretroshare/src/rsitems/rswireitems.cc +++ /dev/null @@ -1,97 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rswireitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include - -#include "rswireitems.h" -#include "serialiser/rstypeserializer.h" - -#define WIRE_DEBUG 1 - - -RsItem *RsGxsWireSerialiser::create_item(uint16_t service,uint8_t item_subtype) const -{ - if(service != RS_SERVICE_GXS_TYPE_WIRE) - return NULL ; - - switch(item_subtype) - { - case RS_PKT_SUBTYPE_WIRE_GROUP_ITEM: return new RsGxsWireGroupItem(); - case RS_PKT_SUBTYPE_WIRE_PULSE_ITEM: return new RsGxsWirePulseItem(); - default: - return NULL ; - } -} - -void RsGxsWireGroupItem::clear() -{ - group.mTagline.clear(); - group.mLocation.clear(); - group.mHeadshot.clear(); - group.mMasthead.clear(); -} - -void RsGxsWireGroupItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DESCR,group.mTagline,"group.mTagline") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_LOCATION,group.mLocation,"group.mLocation") ; - group.mHeadshot.serial_process(j, ctx); - group.mMasthead.serial_process(j, ctx); -} - -void RsGxsWirePulseItem::clear() -{ - pulse.mPulseText.clear(); - pulse.mPulseType = 0; - pulse.mSentiment = 0; - pulse.mRefGroupId.clear(); - pulse.mRefGroupName.clear(); - pulse.mRefOrigMsgId.clear(); - pulse.mRefAuthorId.clear(); - pulse.mRefPublishTs = 0; - pulse.mRefPulseText.clear(); - pulse.mRefImageCount = 0; - - pulse.mImage1.clear(); - pulse.mImage2.clear(); - pulse.mImage3.clear(); - pulse.mImage4.clear(); -} - -void RsGxsWirePulseItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,pulse.mPulseText,"pulse.mPulseText") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_UINT32_PARAM,pulse.mPulseType,"pulse.mPulseType") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_UINT32_PARAM,pulse.mSentiment,"pulse.mSentiment") ; - RsTypeSerializer::serial_process(j,ctx,pulse.mRefGroupId,"pulse.mRefGroupId") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_NAME,pulse.mRefGroupName,"pulse.mRefGroupName") ; - RsTypeSerializer::serial_process(j,ctx,pulse.mRefOrigMsgId,"pulse.mRefOrigMsgId") ; - RsTypeSerializer::serial_process(j,ctx,pulse.mRefAuthorId,"pulse.mRefAuthorId") ; - RsTypeSerializer::serial_process(j,ctx,pulse.mRefPublishTs,"pulse.mRefPublishTs") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,pulse.mRefPulseText,"pulse.mRefPulseText") ; - RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_UINT32_PARAM,pulse.mRefImageCount,"pulse.mRefImageCount") ; - - pulse.mImage1.serial_process(j, ctx); - pulse.mImage2.serial_process(j, ctx); - pulse.mImage3.serial_process(j, ctx); - pulse.mImage4.serial_process(j, ctx); -} - diff --git a/libretroshare/src/rsitems/rswireitems.h b/libretroshare/src/rsitems/rswireitems.h deleted file mode 100644 index 4db5f3d25..000000000 --- a/libretroshare/src/rsitems/rswireitems.h +++ /dev/null @@ -1,76 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsitems: rswireitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef RS_WIRE_ITEMS_H -#define RS_WIRE_ITEMS_H - -#include - -#include "rsitems/rsserviceids.h" -#include "serialiser/rsserial.h" -//#include "serialiser/rstlvtypes.h" - -#include "rsgxsitems.h" -#include "retroshare/rswire.h" - -const uint8_t RS_PKT_SUBTYPE_WIRE_GROUP_ITEM = 0x02; -const uint8_t RS_PKT_SUBTYPE_WIRE_PULSE_ITEM = 0x03; - -class RsGxsWireGroupItem : public RsGxsGrpItem -{ - -public: - - RsGxsWireGroupItem(): RsGxsGrpItem(RS_SERVICE_GXS_TYPE_WIRE, RS_PKT_SUBTYPE_WIRE_GROUP_ITEM) {} - virtual ~RsGxsWireGroupItem() {} - - void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsWireGroup group; -}; - -class RsGxsWirePulseItem : public RsGxsMsgItem -{ -public: - - RsGxsWirePulseItem(): RsGxsMsgItem(RS_SERVICE_GXS_TYPE_WIRE, RS_PKT_SUBTYPE_WIRE_PULSE_ITEM) {} - virtual ~RsGxsWirePulseItem() {} - void clear(); - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - RsWirePulse pulse; -}; - -class RsGxsWireSerialiser : public RsServiceSerializer -{ -public: - - RsGxsWireSerialiser() :RsServiceSerializer(RS_SERVICE_GXS_TYPE_WIRE) {} - virtual ~RsGxsWireSerialiser() {} - - virtual RsItem *create_item(uint16_t service,uint8_t item_subtype) const ; -}; - -#endif /* RS_WIKI_ITEMS_H */ diff --git a/libretroshare/src/rsserver/p3face-config.cc b/libretroshare/src/rsserver/p3face-config.cc deleted file mode 100644 index 62c60815b..000000000 --- a/libretroshare/src/rsserver/p3face-config.cc +++ /dev/null @@ -1,124 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3face-config.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "rsserver/p3face.h" - -#include -#include "pqi/authssl.h" -#include "pqi/authgpg.h" -#include "retroshare/rsinit.h" -#include "plugins/pluginmanager.h" -#include "util/rsdebug.h" - -#ifdef RS_JSONAPI -# include "jsonapi/jsonapi.h" -#endif // ifdef RS_JSONAPI - -#include -#include "util/rstime.h" - -#include "pqi/p3peermgr.h" -#include "pqi/p3netmgr.h" - - -// TO SHUTDOWN THREADS. -#ifdef RS_ENABLE_GXS - -#include "services/autoproxy/rsautoproxymonitor.h" - -#include "services/p3idservice.h" -#include "services/p3gxscircles.h" -#include "services/p3wiki.h" -#include "services/p3posted.h" -#include "services/p3photoservice.h" -#include "services/p3gxsforums.h" -#include "services/p3gxschannels.h" -#include "services/p3wire.h" - -#endif - -/****************************************/ -/* RsIface Config */ -/* Config */ - -void RsServer::ConfigFinalSave() -{ - //TODO: force saving of transfers - //ftserver->saveFileTransferStatus(); - -#ifdef RS_AUTOLOGIN - if(!RsInit::getAutoLogin()) RsInit::RsClearAutoLogin(); -#endif // RS_AUTOLOGIN - - //AuthSSL::getAuthSSL()->FinalSaveCertificates(); - mConfigMgr->completeConfiguration(); -} - -void RsServer::startServiceThread(RsTickingThread *t, const std::string &threadName) -{ - t->start(threadName) ; - mRegisteredServiceThreads.push_back(t) ; -} - -void RsServer::rsGlobalShutDown() -{ - coreReady = false; - // TODO: cache should also clean up old files - - ConfigFinalSave(); // save configuration before exit - - mPluginsManager->stopPlugins(pqih); - - mNetMgr->shutdown(); /* Handles UPnP */ - -#ifdef RS_JSONAPI - rsJsonApi->fullstop(); -#endif - - rsAutoProxyMonitor::instance()->stopAllRSShutdown(); - - fullstop() ; - - // kill all registered service threads - - for(std::list::iterator it= mRegisteredServiceThreads.begin();it!=mRegisteredServiceThreads.end();++it) - { - (*it)->fullstop() ; - } -// #ifdef RS_ENABLE_GXS -// // We should automate this. -// // -// if(mGxsCircles) mGxsCircles->join(); -// if(mGxsForums) mGxsForums->join(); -// if(mGxsChannels) mGxsChannels->join(); -// if(mGxsIdService) mGxsIdService->join(); -// if(mPosted) mPosted->join(); -// if(mWiki) mWiki->join(); -// if(mGxsNetService) mGxsNetService->join(); -// if(mPhoto) mPhoto->join(); -// if(mWire) mWire->join(); -// #endif - - AuthPGP::exit(); - - mShutdownCallback(0); -} diff --git a/libretroshare/src/rsserver/p3face-info.cc b/libretroshare/src/rsserver/p3face-info.cc deleted file mode 100644 index 18fdc40aa..000000000 --- a/libretroshare/src/rsserver/p3face-info.cc +++ /dev/null @@ -1,97 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3face-info.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2015 by RetroShare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "rsserver/p3face.h" -#include -#include -#include - -#ifdef NO_SQLCIPHER -# include -#else -# include -#endif - -#ifdef RS_USE_LIBUPNP -# include -#elif defined(RS_USE_LIBMINIUPNPC) -# include -#endif // def RS_USE_LIBUPNP - -std::string RsServer::getSQLCipherVersion() -{ - sqlite3* mDb; - std::string versionstring(""); - const char* version; - int rc = sqlite3_open_v2("", &mDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE , NULL); //create DB in a temp file - - if(rc){ - std::cerr << "Can't open database, Error code: " << sqlite3_errmsg(mDb) - << std::endl; - sqlite3_close(mDb); - mDb = NULL; - return ""; - } - - std::string sqlQuery = "PRAGMA cipher_version;"; - sqlite3_stmt* stmt = NULL; - rc = sqlite3_prepare_v2(mDb, sqlQuery.c_str(), sqlQuery.length(), &stmt, NULL); - if (rc == SQLITE_OK) { - rc = sqlite3_step(stmt); - switch (rc) { - case SQLITE_ROW: - version = (const char *)sqlite3_column_text(stmt, 0); //not needed to free - versionstring.append(version); - break; - case SQLITE_DONE: - break; - default: - std::cerr << "RetroDb::tableExists(): Error executing statement (code: " << rc << ")" - << std::endl; - break; - } - } - - if (stmt) { - sqlite3_finalize(stmt); - } - sqlite3_close(mDb); // no-op if mDb is NULL (https://www.sqlite.org/c3ref/close.html) - return versionstring; -} - -void RsServer::getLibraries(std::list &libraries) -{ - libraries.push_back(RsLibraryInfo("bzip2", BZ2_bzlibVersion())); - libraries.push_back(RsLibraryInfo("OpenSSL", SSLeay_version(SSLEAY_VERSION))); - libraries.push_back(RsLibraryInfo("SQLite", SQLITE_VERSION)); -#ifndef NO_SQLCIPHER - libraries.push_back(RsLibraryInfo("SQLCipher", getSQLCipherVersion())); -#endif - -#ifdef RS_USE_LIBUPNP - libraries.push_back(RsLibraryInfo("UPnP (libupnp)", UPNP_VERSION_STRING)); -#elif defined(RS_USE_LIBMINIUPNPC) - libraries.push_back(RsLibraryInfo("UPnP (MiniUPnP)", MINIUPNPC_VERSION)); -#endif // def RS_USE_LIBUPNP - - libraries.push_back(RsLibraryInfo("Zlib", ZLIB_VERSION)); -} diff --git a/libretroshare/src/rsserver/p3face-server.cc b/libretroshare/src/rsserver/p3face-server.cc deleted file mode 100644 index 8642860b8..000000000 --- a/libretroshare/src/rsserver/p3face-server.cc +++ /dev/null @@ -1,275 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3face-server.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2015 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "util/rstime.h" -#include "rsserver/p3face.h" -#include "retroshare/rsplugin.h" - -#include "tcponudp/tou.h" -#include - -#include "pqi/authssl.h" -#include -#include "util/rstime.h" - -#include "pqi/p3peermgr.h" -#include "pqi/p3linkmgr.h" -#include "pqi/p3netmgr.h" - -#include "util/rsdebug.h" - -#include "retroshare/rsevents.h" -#include "services/rseventsservice.h" - -/******************* -#define TICK_DEBUG 1 -*******************/ - -#define WARN_BIG_CYCLE_TIME (0.2) - -#ifdef WINDOWS_SYS -#include "util/rstime.h" -#include -#endif - - -/*extern*/ RsControl* rsControl = nullptr; - -static double getCurrentTS() -{ - -#ifndef WINDOWS_SYS - struct timeval cts_tmp; - gettimeofday(&cts_tmp, NULL); - double cts = (cts_tmp.tv_sec) + ((double) cts_tmp.tv_usec) / 1000000.0; -#else - struct _timeb timebuf; - _ftime( &timebuf); - double cts = (timebuf.time) + ((double) timebuf.millitm) / 1000.0; -#endif - return cts; -} - -// These values should be tunable from the GUI, to offer a compromise between speed and CPU use. -// In some cases (VOIP) it's likely that we will need to set them temporarily to a very low -// value, in order to favor a fast feedback - -const double RsServer::minTickInterval = 0.05; -const double RsServer::maxTickInterval = 0.2; - - -RsServer::RsServer() : - coreMutex("RsServer"), mShutdownCallback([](int){}), - coreReady(false) -{ - { - RsEventsService* tmpRsEvtPtr = new RsEventsService(); - rsEvents = tmpRsEvtPtr; - startServiceThread(tmpRsEvtPtr, "RsEventsService"); - } - - // This is needed asap. - // - mNotify = new p3Notify() ; - rsNotify = mNotify ; - - mPeerMgr = NULL; - mLinkMgr = NULL; - mNetMgr = NULL; - mHistoryMgr = NULL; - - pqih = NULL; - - mPluginsManager = NULL; - - /* services */ - mHeart = NULL; - mDisc = NULL; - msgSrv = NULL; - chatSrv = NULL; - mStatusSrv = NULL; - mGxsTunnels = NULL; - - /* timers */ - mLastts = getCurrentTS(); - mTickInterval = maxTickInterval ; - mAvgRunDuration = 0; - mLastRunDuration = 0; - mCycle1 = mLastts; - mCycle2 = mLastts; - mCycle3 = mLastts; - mCycle4 = mLastts; - - /* caches (that need ticking) */ - - /* config */ - mConfigMgr = NULL; - mGeneralConfig = NULL; -} - -RsServer::~RsServer() -{ - delete mGxsTrans; -} - -// General Internal Helper Functions ----> MUST BE LOCKED! - -void RsServer::threadTick() -{ -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG ticking interval " << std::dec << (int) (1000 * mTickInterval) << " ms"; -#endif - -// we try to tick at a regular interval depending on the load -// if there is time left, we sleep - double timeToSleep = mTickInterval - mAvgRunDuration; - -// never sleep less than 50 ms - if (timeToSleep < 0.050) - timeToSleep = 0.050; - -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG will sleep " << std::dec << (int) (1000 * timeToSleep) << " ms"; -#endif - rstime::rs_usleep(timeToSleep * 1000000); - - double ts = getCurrentTS(); - mLastts = ts; - -// stuff we do always - // tick the core -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG ticking RS core"; -#endif - lockRsCore(); - int moreToTick = pqih->tick(); - unlockRsCore(); - // tick the managers -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG ticking mPeerMgr"; -#endif - mPeerMgr->tick(); -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG ticking mLinkMgr"; -#endif - mLinkMgr->tick(); -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG ticking mNetMgr"; -#endif - mNetMgr->tick(); - - -// stuff we do every second - if (ts - mCycle1 > 1) - { -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG every second"; -#endif - // slow services - if (rsPlugins) - { -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG ticking slow tick plugins"; -#endif - rsPlugins->slowTickPlugins((rstime_t)ts); - } - // UDP keepalive - // tou_tick_stunkeepalive(); - // other stuff to tick - // update(); - mCycle1 = ts; - } - -// stuff we do every five seconds - if (ts - mCycle2 > 5) - { -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG every 5 seconds"; -#endif - mCycle2 = ts; - } - -// stuff we do every minute - if (ts - mCycle3 > 60) - { -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG every 60 seconds"; -#endif - // force saving FileTransferStatus TODO - // ftserver->saveFileTransferStatus(); - // see if we need to resave certs - // AuthSSL::getAuthSSL()->CheckSaveCertificates(); - mCycle3 = ts; - } - -// stuff we do every hour - if (ts - mCycle4 > 3600) - { -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG every hour"; -#endif - // save configuration files -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG ticking mConfigMgr"; -#endif - mConfigMgr->tick(); - mCycle4 = ts; - } - -// ticking is done, now compute new values of mLastRunDuration, mAvgRunDuration and mTickInterval - ts = getCurrentTS(); - mLastRunDuration = ts - mLastts; - -// low-pass filter and don't let mAvgRunDuration exceeds maxTickInterval - mAvgRunDuration = 0.1 * mLastRunDuration + 0.9 * mAvgRunDuration; - if (mAvgRunDuration > maxTickInterval) - mAvgRunDuration = maxTickInterval; - -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG mLastRunDuration " << std::dec << (int) (1000 * mLastRunDuration) << " ms, mAvgRunDuration " << (int) (1000 * mAvgRunDuration) << " ms"; - if (mLastRunDuration > WARN_BIG_CYCLE_TIME) - RsDbg() << "TICK_DEBUG excessively long cycle time " << std::dec << (int) (1000 * mLastRunDuration) << " ms"; -#endif - -// if the core has returned that there is more to tick we decrease the ticking interval, else we increase it -// TODO: this should be investigated as it seems that the core never returns 1 -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG moreToTick " << moreToTick; -#endif - if (moreToTick == 1) - mTickInterval = 0.9 * mTickInterval; - else - mTickInterval = 1.1 * mTickInterval; -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG new tick interval " << std::dec << (int) (1000 * mTickInterval) << " ms"; -#endif - -// keep the tick interval target within allowed limits - if (mTickInterval < minTickInterval) - mTickInterval = minTickInterval; - else if (mTickInterval > maxTickInterval) - mTickInterval = maxTickInterval; -#ifdef TICK_DEBUG - RsDbg() << "TICK_DEBUG new tick interval after limiter " << std::dec << (int) (1000 * mTickInterval) << " ms"; -#endif -} - diff --git a/libretroshare/src/rsserver/p3face.h b/libretroshare/src/rsserver/p3face.h deleted file mode 100644 index 648e39123..000000000 --- a/libretroshare/src/rsserver/p3face.h +++ /dev/null @@ -1,215 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3face.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include - -//#include "server/filedexserver.h" -#include "ft/ftserver.h" -//#include "pqi/pqissl.h" - -#include "pqi/p3cfgmgr.h" -#include "pqi/p3notify.h" -#include "pqi/pqipersongrp.h" - -#include "retroshare/rsiface.h" -#include "retroshare/rstypes.h" -#include "util/rsthreads.h" - -#include "chat/p3chatservice.h" -#include "gxstunnel/p3gxstunnel.h" - -#include "services/p3msgservice.h" -#include "services/p3statusservice.h" - -class p3heartbeat; -class p3discovery2; -class p3I2pSam3; - -/* GXS Classes - just declare the classes. - so we don't have to totally recompile to switch */ - -class p3IdService; -class p3GxsCircles; -class p3GxsForums; -class p3GxsChannels; -class p3Wiki; -class p3Posted; -class p3PhotoService; -class p3Wire; - - -class p3PeerMgrIMPL; -class p3LinkMgrIMPL; -class p3NetMgrIMPL; -class p3HistoryMgr; -class RsPluginManager; - -/* The Main Interface Class - for controlling the server */ - -/* The init functions are actually Defined in p3face-startup.cc - */ -//RsInit *InitRsConfig(); -//void CleanupRsConfig(RsInit *); -//int InitRetroShare(int argc, char **argv, RsInit *config); -//int LoadCertificates(RsInit *config); - -class RsServer: public RsControl, public RsTickingThread -{ -public: - RsServer(); - virtual ~RsServer(); - - virtual int StartupRetroShare(); - - /// @see RsControl::isReady() - virtual bool isReady() { return coreReady; } - - /// @see RsControl::setShutdownCallback - void setShutdownCallback(const std::function& callback) - { mShutdownCallback = callback; } - - void threadTick() override; /// @see RsTickingThread - - /* locking stuff */ - void lockRsCore() - { - // std::cerr << "RsServer::lockRsCore()" << std::endl; - coreMutex.lock(); - } - - void unlockRsCore() - { - // std::cerr << "RsServer::unlockRsCore()" << std::endl; - coreMutex.unlock(); - } - - static p3Notify *notify() { return dynamic_cast(instance())->mNotify ; } - - private: - - /* mutex */ - RsMutex coreMutex; - - private: - - /****************************************/ - /****************************************/ - /****************************************/ - /****************************************/ - public: - /* Config */ - - virtual void ConfigFinalSave( ); - virtual void startServiceThread(RsTickingThread *t, const std::string &threadName) ; - - /************* Rs shut down function: in upnp 'port lease time' bug *****************/ - - /** - * This function is responsible for ensuring Retroshare exits in a legal state: - * i.e. releases all held resources and saves current configuration - */ - virtual void rsGlobalShutDown(); - - /****************************************/ - - public: - virtual bool getPeerCryptoDetails(const RsPeerId& ssl_id,RsPeerCryptoParams& params) { return pqih->getCryptoParams(ssl_id,params); } - virtual void getLibraries(std::list &libraries); - - private: - - std::string getSQLCipherVersion(); // TODO: move to rsversion.h - - // The real Server Parts. - - //filedexserver *server; - //ftServer *ftserver; - - p3PeerMgrIMPL *mPeerMgr; - p3LinkMgrIMPL *mLinkMgr; - p3NetMgrIMPL *mNetMgr; - p3HistoryMgr *mHistoryMgr; - - pqipersongrp *pqih; - - RsPluginManager *mPluginsManager; - - /* services */ - p3heartbeat *mHeart; - p3discovery2 *mDisc; - p3MsgService *msgSrv; - p3ChatService *chatSrv; - p3StatusService *mStatusSrv; - p3GxsTunnelService *mGxsTunnels; -#ifdef RS_USE_I2P_SAM3 - p3I2pSam3 *mI2pSam3; -#endif - - // This list contains all threaded services. It will be used to shut them down properly. - - std::list mRegisteredServiceThreads ; - - /* GXS */ -// p3Wiki *mWiki; -// p3Posted *mPosted; -// p3PhotoService *mPhoto; -// p3GxsCircles *mGxsCircles; -// p3GxsNetService *mGxsNetService; -// p3IdService *mGxsIdService; -// p3GxsForums *mGxsForums; -// p3GxsChannels *mGxsChannels; -// p3Wire *mWire; - p3GxsTrans* mGxsTrans; - - /* Config */ - p3ConfigMgr *mConfigMgr; - p3GeneralConfig *mGeneralConfig; - - // notify - p3Notify *mNotify ; - - // Worker Data..... - - double mLastts; - double mTickInterval; - double mLastRunDuration; - double mAvgRunDuration; - double mCycle1, mCycle2, mCycle3, mCycle4; - - static const double minTickInterval; - static const double maxTickInterval; - - /// @see RsControl::setShutdownCallback - std::function mShutdownCallback; - - /** Keep track of the core being fully ready, true only after - * StartupRetroShare() finish and before rsGlobalShutDown() begin - */ - bool coreReady; -}; - -/* Helper function to convert windows paths - * into unix (ie switch \ to /) for FLTK's file chooser - */ - -std::string make_path_unix(std::string winpath); diff --git a/libretroshare/src/rsserver/p3history.cc b/libretroshare/src/rsserver/p3history.cc deleted file mode 100644 index 2818d9339..000000000 --- a/libretroshare/src/rsserver/p3history.cc +++ /dev/null @@ -1,85 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3history.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Thunder. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "p3history.h" -#include "pqi/p3historymgr.h" - -p3History::p3History(p3HistoryMgr* historyMgr) - : mHistoryMgr(historyMgr) -{ -} - -p3History::~p3History() -{ -} - -bool p3History::chatIdToVirtualPeerId(const ChatId &chat_id, RsPeerId &peer_id) -{ - return mHistoryMgr->chatIdToVirtualPeerId(chat_id, peer_id); -} - -void p3History::setMaxStorageDuration(uint32_t seconds) -{ - mHistoryMgr->setMaxStorageDuration(seconds) ; -} -uint32_t p3History::getMaxStorageDuration() -{ - return mHistoryMgr->getMaxStorageDuration() ; -} -bool p3History::getMessages(const ChatId &chatPeerId, std::list &msgs, const uint32_t loadCount) -{ - return mHistoryMgr->getMessages(chatPeerId, msgs, loadCount); -} - -bool p3History::getMessage(uint32_t msgId, HistoryMsg &msg) -{ - return mHistoryMgr->getMessage(msgId, msg); -} - -void p3History::removeMessages(const std::list &msgIds) -{ - mHistoryMgr->removeMessages(msgIds); -} - -void p3History::clear(const ChatId &chatPeerId) -{ - mHistoryMgr->clear(chatPeerId); -} - -bool p3History::getEnable(uint32_t chat_type) -{ - return mHistoryMgr->getEnable(chat_type); -} - -void p3History::setEnable(uint32_t chat_type, bool enable) -{ - mHistoryMgr->setEnable(chat_type, enable); -} - -uint32_t p3History::getSaveCount(uint32_t chat_type) -{ - return mHistoryMgr->getSaveCount(chat_type); -} - -void p3History::setSaveCount(uint32_t chat_type, uint32_t count) -{ - mHistoryMgr->setSaveCount(chat_type, count); -} diff --git a/libretroshare/src/rsserver/p3history.h b/libretroshare/src/rsserver/p3history.h deleted file mode 100644 index 2a75d328d..000000000 --- a/libretroshare/src/rsserver/p3history.h +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3history.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Thunder. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_P3HISTORY_INTERFACE_H -#define RS_P3HISTORY_INTERFACE_H - -#include "retroshare/rshistory.h" - -class p3HistoryMgr; - -//! Implements abstract interface rsHistory -/*! - * Interfaces with p3HistoryMsg - */ -class p3History : public RsHistory -{ -public: - - p3History(p3HistoryMgr* historyMgr); - virtual ~p3History(); - - virtual bool chatIdToVirtualPeerId(const ChatId &chat_id, RsPeerId &peer_id); - virtual bool getMessages(const ChatId &chatPeerId, std::list &msgs, uint32_t loadCount); - virtual bool getMessage(uint32_t msgId, HistoryMsg &msg); - virtual void removeMessages(const std::list &msgIds); - virtual void clear(const ChatId &chatPeerId); - - virtual bool getEnable(uint32_t chat_type); - virtual void setEnable(uint32_t chat_type, bool enable); - - virtual uint32_t getMaxStorageDuration(); - virtual void setMaxStorageDuration(uint32_t seconds); - - // 0 = no limit, >0 count of saved messages - virtual uint32_t getSaveCount(uint32_t chat_type); - virtual void setSaveCount(uint32_t chat_type, uint32_t count); - -private: - p3HistoryMgr* mHistoryMgr; -}; - -#endif /* RS_P3HISTORY_INTERFACE_H */ diff --git a/libretroshare/src/rsserver/p3msgs.cc b/libretroshare/src/rsserver/p3msgs.cc deleted file mode 100644 index a89e1ae04..000000000 --- a/libretroshare/src/rsserver/p3msgs.cc +++ /dev/null @@ -1,587 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3msgs.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie * - * Copyright (C) 2016-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include -#include - -#include "util/rsdir.h" -#include "util/rsdebug.h" -//const int p3facemsgzone = 11453; - -#include -#include "util/rstime.h" - -#include "retroshare/rstypes.h" -#include "rsserver/p3msgs.h" - -#include "services/p3msgservice.h" -#include "chat/p3chatservice.h" - -#include "pqi/authgpg.h" - -using namespace Rs::Msgs; - -/*extern*/ RsMsgs* rsMsgs = nullptr; - -/****************************************/ -/****************************************/ - -ChatId::ChatId(): - type(TYPE_NOT_SET), - lobby_id(0) -{ - -} - -ChatId::ChatId(RsPeerId id): - lobby_id(0) -{ - type = TYPE_PRIVATE; - peer_id = id; -} - -ChatId::ChatId(DistantChatPeerId id): - lobby_id(0) -{ - type = TYPE_PRIVATE_DISTANT; - distant_chat_id = id; -} - -ChatId::ChatId(ChatLobbyId id): - lobby_id(0) -{ - type = TYPE_LOBBY; - lobby_id = id; -} - -ChatId::ChatId(std::string str) : lobby_id(0) -{ - type = TYPE_NOT_SET; - if(str.empty()) return; - - if(str[0] == 'P') - { - type = TYPE_PRIVATE; - peer_id = RsPeerId(str.substr(1)); - } - else if(str[0] == 'D') - { - type = TYPE_PRIVATE_DISTANT; - distant_chat_id = DistantChatPeerId(str.substr(1)); - } - else if(str[0] == 'L') - { - if(sizeof(ChatLobbyId) != 8) - { - std::cerr << "ChatId::ChatId(std::string) Error: sizeof(ChatLobbyId) != 8. please report this" << std::endl; - return; - } - str = str.substr(1); - if(str.size() != 16) - return; - ChatLobbyId id = 0; - for(int i = 0; i<16; i++) - { - uint8_t c = str[i]; - if(c <= '9') - c -= '0'; - else - c -= 'A' - 10; - id = id << 4; - id |= c; - } - type = TYPE_LOBBY; - lobby_id = id; - } - else if(str[0] == 'B') - { - type = TYPE_BROADCAST; - } -} - -ChatId ChatId::makeBroadcastId() -{ - ChatId id; - id.type = TYPE_BROADCAST; - return id; -} - -std::string ChatId::toStdString() const -{ - std::string str; - if(type == TYPE_PRIVATE) - { - str += "P"; - str += peer_id.toStdString(); - } - else if(type == TYPE_PRIVATE_DISTANT) - { - str += "D"; - str += distant_chat_id.toStdString(); - } - else if(type == TYPE_LOBBY) - { - if(sizeof(ChatLobbyId) != 8) - { - std::cerr << "ChatId::toStdString() Error: sizeof(ChatLobbyId) != 8. please report this" << std::endl; - return ""; - } - str += "L"; - - ChatLobbyId id = lobby_id; - for(int i = 0; i<16; i++) - { - uint8_t c = id >>(64-4); - if(c > 9) - c += 'A' - 10; - else - c += '0'; - str += c; - id = id << 4; - } - } - else if(type == TYPE_BROADCAST) - { - str += "B"; - } - return str; -} - -bool ChatId::operator <(const ChatId& other) const -{ - if(type != other.type) - return type < other.type; - else - { - switch(type) - { - case TYPE_NOT_SET: - return false; - case TYPE_PRIVATE: - return peer_id < other.peer_id; - case TYPE_PRIVATE_DISTANT: - return distant_chat_id < other.distant_chat_id; - case TYPE_LOBBY: - return lobby_id < other.lobby_id; - case TYPE_BROADCAST: - return false; - default: - return false; - } - } -} - -bool ChatId::isSameEndpoint(const ChatId &other) const -{ - if(type != other.type) - return false; - else - { - switch(type) - { - case TYPE_NOT_SET: - return false; - case TYPE_PRIVATE: - return peer_id == other.peer_id; - case TYPE_PRIVATE_DISTANT: - return distant_chat_id == other.distant_chat_id; - case TYPE_LOBBY: - return lobby_id == other.lobby_id; - case TYPE_BROADCAST: - return true; - default: - return false; - } - } -} - -bool ChatId::isNotSet() const -{ - return type == TYPE_NOT_SET; -} -bool ChatId::isPeerId() const -{ - return type == TYPE_PRIVATE; -} -bool ChatId::isDistantChatId() const -{ - return type == TYPE_PRIVATE_DISTANT; -} -bool ChatId::isLobbyId() const -{ - return type == TYPE_LOBBY; -} -bool ChatId::isBroadcast() const -{ - return type == TYPE_BROADCAST; -} -RsPeerId ChatId::toPeerId() const -{ - if(type == TYPE_PRIVATE) - return peer_id; - else - { - std::cerr << "ChatId Warning: conversation to RsPeerId requested, but type is different. Current value=\"" << toStdString() << "\"" << std::endl; - return RsPeerId(); - } -} - -DistantChatPeerId ChatId::toDistantChatId() const -{ - if(type == TYPE_PRIVATE_DISTANT) - return distant_chat_id; - else - { - std::cerr << "ChatId Warning: conversation to DistantChatPeerId requested, but type is different. Current value=\"" << toStdString() << "\"" << std::endl; - return DistantChatPeerId(); - } -} -ChatLobbyId ChatId::toLobbyId() const -{ - if(type == TYPE_LOBBY) - return lobby_id; - else - { - std::cerr << "ChatId Warning: conversation to ChatLobbyId requested, but type is different. Current value=\"" << toStdString() << "\"" << std::endl; - return 0; - } -} - -bool p3Msgs::getMessageSummaries(std::list &msgList) -{ - return mMsgSrv->getMessageSummaries(msgList); -} - - -uint32_t p3Msgs::getDistantMessagingPermissionFlags() -{ - return mMsgSrv->getDistantMessagingPermissionFlags(); -} - -void p3Msgs::setDistantMessagingPermissionFlags(uint32_t flags) -{ - return mMsgSrv->setDistantMessagingPermissionFlags(flags); -} - - -bool p3Msgs::getMessage(const std::string &mid, MessageInfo &msg) -{ - return mMsgSrv->getMessage(mid, msg); -} - -void p3Msgs::getMessageCount(uint32_t &nInbox, uint32_t &nInboxNew, uint32_t &nOutbox, uint32_t &nDraftbox, uint32_t &nSentbox, uint32_t &nTrashbox) -{ - mMsgSrv->getMessageCount(nInbox, nInboxNew, nOutbox, nDraftbox, nSentbox, nTrashbox); -} - -/****************************************/ -/****************************************/ - /* Message Items */ -bool p3Msgs::MessageSend(MessageInfo &info) -{ - return mMsgSrv->MessageSend(info); -} - -uint32_t p3Msgs::sendMail( - const RsGxsId from, - const std::string& subject, - const std::string& body, - const std::set& to, - const std::set& cc, - const std::set& bcc, - const std::vector& attachments, - std::set& trackingIds, - std::string& errorMsg ) -{ - return mMsgSrv->sendMail( - from, subject, body, to, cc, bcc, attachments, - trackingIds, errorMsg ); -} - -bool p3Msgs::SystemMessage(const std::string &title, const std::string &message, uint32_t systemFlag) -{ - return mMsgSrv->SystemMessage(title, message, systemFlag); -} - -bool p3Msgs::MessageToDraft(MessageInfo &info, const std::string &msgParentId) -{ - return mMsgSrv->MessageToDraft(info, msgParentId); -} - -bool p3Msgs::MessageToTrash(const std::string &mid, bool bTrash) -{ - return mMsgSrv->MessageToTrash(mid, bTrash); -} - -bool p3Msgs::getMsgParentId(const std::string &msgId, std::string &msgParentId) -{ - return mMsgSrv->getMsgParentId(msgId, msgParentId); -} - -/****************************************/ -/****************************************/ -bool p3Msgs::MessageDelete(const std::string &mid) -{ - //std::cerr << "p3Msgs::MessageDelete() "; - //std::cerr << "mid: " << mid << std::endl; - - return mMsgSrv -> removeMsgId(mid); -} - -bool p3Msgs::MessageRead(const std::string &mid, bool unreadByUser) -{ - //std::cerr << "p3Msgs::MessageRead() "; - //std::cerr << "mid: " << mid << std::endl; - - return mMsgSrv -> markMsgIdRead(mid, unreadByUser); -} - -bool p3Msgs::MessageReplied(const std::string &mid, bool replied) -{ - return mMsgSrv->setMsgFlag(mid, replied ? RS_MSG_FLAGS_REPLIED : 0, RS_MSG_FLAGS_REPLIED); -} - -bool p3Msgs::MessageForwarded(const std::string &mid, bool forwarded) -{ - return mMsgSrv->setMsgFlag(mid, forwarded ? RS_MSG_FLAGS_FORWARDED : 0, RS_MSG_FLAGS_FORWARDED); -} - -bool p3Msgs::MessageLoadEmbeddedImages(const std::string &mid, bool load) -{ - return mMsgSrv->setMsgFlag(mid, load ? RS_MSG_FLAGS_LOAD_EMBEDDED_IMAGES : 0, RS_MSG_FLAGS_LOAD_EMBEDDED_IMAGES); -} - -bool p3Msgs::getMessageTagTypes(MsgTagType& tags) -{ - return mMsgSrv->getMessageTagTypes(tags); -} - -bool p3Msgs::MessageStar(const std::string &mid, bool star) -{ - return mMsgSrv->setMsgFlag(mid, star ? RS_MSG_FLAGS_STAR : 0, RS_MSG_FLAGS_STAR); -} - -bool p3Msgs::MessageJunk(const std::string &mid, bool junk) -{ - return mMsgSrv->setMsgFlag(mid, junk ? RS_MSG_FLAGS_SPAM : 0, RS_MSG_FLAGS_SPAM); -} - -bool p3Msgs::setMessageTagType(uint32_t tagId, std::string& text, uint32_t rgb_color) -{ - return mMsgSrv->setMessageTagType(tagId, text, rgb_color); -} - -bool p3Msgs::removeMessageTagType(uint32_t tagId) -{ - return mMsgSrv->removeMessageTagType(tagId); -} - -bool p3Msgs::getMessageTag(const std::string &msgId, MsgTagInfo& info) -{ - return mMsgSrv->getMessageTag(msgId, info); -} - -bool p3Msgs::setMessageTag(const std::string &msgId, uint32_t tagId, bool set) -{ - return mMsgSrv->setMessageTag(msgId, tagId, set); -} - -bool p3Msgs::resetMessageStandardTagTypes(MsgTagType& tags) -{ - return mMsgSrv->resetMessageStandardTagTypes(tags); -} - -/****************************************/ -/****************************************/ -bool p3Msgs::sendChat(ChatId destination, std::string msg) -{ - return mChatSrv->sendChat(destination, msg); -} - -uint32_t p3Msgs::getMaxMessageSecuritySize(int type) -{ - return mChatSrv->getMaxMessageSecuritySize(type); -} - -void p3Msgs::sendStatusString(const ChatId& id, const std::string& status_string) -{ - mChatSrv->sendStatusString(id, status_string); -} - -void p3Msgs::clearChatLobby(const ChatId &id) -{ - mChatSrv->clearChatLobby(id); -} - -void p3Msgs::getOwnAvatarData(unsigned char *& data,int& size) -{ - mChatSrv->getOwnAvatarJpegData(data,size) ; -} - -void p3Msgs::setOwnAvatarData(const unsigned char *data,int size) -{ - mChatSrv->setOwnAvatarJpegData(data,size) ; -} - -void p3Msgs::getAvatarData(const RsPeerId& pid,unsigned char *& data,int& size) -{ - mChatSrv->getAvatarJpegData(pid,data,size) ; -} - -std::string p3Msgs::getCustomStateString(const RsPeerId& peer_id) -{ - return mChatSrv->getCustomStateString(peer_id) ; -} - -std::string p3Msgs::getCustomStateString() -{ - return mChatSrv->getOwnCustomStateString() ; -} - -void p3Msgs::setCustomStateString(const std::string& state_string) -{ - mChatSrv->setOwnCustomStateString(state_string) ; -} - -bool p3Msgs::getChatLobbyInfo(const ChatLobbyId& id,ChatLobbyInfo& linfo) -{ - return mChatSrv->getChatLobbyInfo(id,linfo) ; -} -void p3Msgs::getChatLobbyList(std::list& lids) -{ - mChatSrv->getChatLobbyList(lids) ; -} -void p3Msgs::invitePeerToLobby(const ChatLobbyId& lobby_id, const RsPeerId& peer_id) -{ - mChatSrv->invitePeerToLobby(lobby_id,peer_id) ; -} -void p3Msgs::sendLobbyStatusPeerLeaving(const ChatLobbyId& lobby_id) -{ - mChatSrv->sendLobbyStatusPeerLeaving(lobby_id) ; -} -void p3Msgs::unsubscribeChatLobby(const ChatLobbyId& lobby_id) -{ - mChatSrv->unsubscribeChatLobby(lobby_id) ; -} -bool p3Msgs::setDefaultIdentityForChatLobby(const RsGxsId& nick) -{ - return mChatSrv->setDefaultIdentityForChatLobby(nick) ; -} -void p3Msgs::getDefaultIdentityForChatLobby(RsGxsId& nick_name) -{ - mChatSrv->getDefaultIdentityForChatLobby(nick_name) ; -} - -bool p3Msgs::setIdentityForChatLobby(const ChatLobbyId& lobby_id,const RsGxsId& nick) -{ - return mChatSrv->setIdentityForChatLobby(lobby_id,nick) ; -} -bool p3Msgs::getIdentityForChatLobby(const ChatLobbyId& lobby_id,RsGxsId& nick_name) -{ - return mChatSrv->getIdentityForChatLobby(lobby_id,nick_name) ; -} - -bool p3Msgs::joinVisibleChatLobby(const ChatLobbyId& lobby_id,const RsGxsId& own_id) -{ - return mChatSrv->joinVisibleChatLobby(lobby_id,own_id) ; -} - -void p3Msgs::getListOfNearbyChatLobbies(std::vector& public_lobbies) -{ - mChatSrv->getListOfNearbyChatLobbies(public_lobbies) ; -} - -ChatLobbyId p3Msgs::createChatLobby(const std::string& lobby_name,const RsGxsId& lobby_identity,const std::string& lobby_topic,const std::set& invited_friends,ChatLobbyFlags privacy_type) -{ - return mChatSrv->createChatLobby(lobby_name,lobby_identity,lobby_topic,invited_friends,privacy_type) ; -} - -void p3Msgs::setLobbyAutoSubscribe(const ChatLobbyId& lobby_id, const bool autoSubscribe) -{ - mChatSrv->setLobbyAutoSubscribe(lobby_id, autoSubscribe); -} - -bool p3Msgs::getLobbyAutoSubscribe(const ChatLobbyId& lobby_id) -{ - return mChatSrv->getLobbyAutoSubscribe(lobby_id); -} - - -bool p3Msgs::acceptLobbyInvite(const ChatLobbyId& id,const RsGxsId& gxs_id) -{ - return mChatSrv->acceptLobbyInvite(id,gxs_id) ; -} -bool p3Msgs::denyLobbyInvite(const ChatLobbyId& id) -{ - return mChatSrv->denyLobbyInvite(id) ; -} -void p3Msgs::getPendingChatLobbyInvites(std::list& invites) -{ - mChatSrv->getPendingChatLobbyInvites(invites) ; -} -bool p3Msgs::initiateDistantChatConnexion( - const RsGxsId& to_gxs_id, const RsGxsId& from_gxs_id, - DistantChatPeerId& pid, uint32_t& error_code, bool notify ) -{ - return mChatSrv->initiateDistantChatConnexion( to_gxs_id, from_gxs_id, pid, error_code, notify ); -} -bool p3Msgs::getDistantChatStatus(const DistantChatPeerId& pid,DistantChatPeerInfo& info) -{ - return mChatSrv->getDistantChatStatus(pid,info) ; -} -bool p3Msgs::closeDistantChatConnexion(const DistantChatPeerId &pid) -{ - return mChatSrv->closeDistantChatConnexion(pid) ; -} -bool p3Msgs::setDistantChatPermissionFlags(uint32_t flags) -{ - return mChatSrv->setDistantChatPermissionFlags(flags) ; -} -uint32_t p3Msgs::getDistantChatPermissionFlags() -{ - return mChatSrv->getDistantChatPermissionFlags() ; -} - -RsMsgs::~RsMsgs() = default; -Rs::Msgs::MessageInfo::~MessageInfo() = default; -MsgInfoSummary::~MsgInfoSummary() = default; -VisibleChatLobbyRecord::~VisibleChatLobbyRecord() = default; - -void RsMailIdRecipientIdPair::serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - RS_SERIAL_PROCESS(mMailId); - RS_SERIAL_PROCESS(mRecipientId); -} - -bool RsMailIdRecipientIdPair::operator<(const RsMailIdRecipientIdPair& o) const -{ - return std::tie( mMailId, mRecipientId) < - std::tie(o.mMailId, o.mRecipientId); -} - -bool RsMailIdRecipientIdPair::operator==(const RsMailIdRecipientIdPair& o) const -{ - return std::tie( mMailId, mRecipientId) == - std::tie(o.mMailId, o.mRecipientId); -} diff --git a/libretroshare/src/rsserver/p3msgs.h b/libretroshare/src/rsserver/p3msgs.h deleted file mode 100644 index f30ebe5aa..000000000 --- a/libretroshare/src/rsserver/p3msgs.h +++ /dev/null @@ -1,190 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3msgs.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2007-2008 Robert Fernie * - * Copyright (C) 2016-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include "retroshare/rsmsgs.h" -#include "retroshare/rsgxsifacetypes.h" - -class p3MsgService; -class p3ChatService; - -class RsChatMsgItem; - -//! provides retroshares chatservice and messaging service -/*! - * Provides rs with the ability to send/receive messages, immediate status, - * custom status, avatar and - * chats (public(group) and private) to peers - */ -class p3Msgs: public RsMsgs -{ -public: - - p3Msgs(p3MsgService *p3m, p3ChatService *p3c) : - mMsgSrv(p3m), mChatSrv(p3c) {} - ~p3Msgs() override = default; - - /// @see RsMsgs - uint32_t sendMail( - const RsGxsId from, - const std::string& subject, - const std::string& body, - const std::set& to = std::set(), - const std::set& cc = std::set(), - const std::set& bcc = std::set(), - const std::vector& attachments = std::vector(), - std::set& trackingIds = - RS_DEFAULT_STORAGE_PARAM(std::set), - std::string& errorMsg = - RS_DEFAULT_STORAGE_PARAM(std::string) ) override; - - /****************************************/ - /* Message Items */ - - /*! - * @param msgList ref to list summarising client's msgs - */ - virtual bool getMessageSummaries(std::list &msgList)override ; - virtual bool getMessage(const std::string &mId, Rs::Msgs::MessageInfo &msg)override ; - virtual void getMessageCount(uint32_t &nInbox, uint32_t &nInboxNew, uint32_t &nOutbox, uint32_t &nDraftbox, uint32_t &nSentbox, uint32_t &nTrashbox)override ; - - RS_DEPRECATED_FOR(sendMail) - virtual bool MessageSend(Rs::Msgs::MessageInfo &info)override ; - virtual bool SystemMessage(const std::string &title, const std::string &message, uint32_t systemFlag)override ; - virtual bool MessageToDraft(Rs::Msgs::MessageInfo &info, const std::string &msgParentId)override ; - virtual bool MessageToTrash(const std::string &mid, bool bTrash)override ; - virtual bool MessageDelete(const std::string &mid)override ; - virtual bool MessageRead(const std::string &mid, bool unreadByUser)override ; - virtual bool MessageReplied(const std::string &mid, bool replied)override ; - virtual bool MessageForwarded(const std::string &mid, bool forwarded)override ; - virtual bool MessageStar(const std::string &mid, bool star)override ; - virtual bool MessageJunk(const std::string &mid, bool junk)override ; - virtual bool MessageLoadEmbeddedImages(const std::string &mid, bool load)override ; - virtual bool getMsgParentId(const std::string &msgId, std::string &msgParentId)override ; - - virtual bool getMessageTagTypes(Rs::Msgs::MsgTagType& tags)override ; - virtual bool setMessageTagType(uint32_t tagId, std::string& text, uint32_t rgb_color)override ; - virtual bool removeMessageTagType(uint32_t tagId)override ; - - virtual bool getMessageTag(const std::string &msgId, Rs::Msgs::MsgTagInfo& info)override ; - /* set == false && tagId == 0 --> remove all */ - virtual bool setMessageTag(const std::string &msgId, uint32_t tagId, bool set)override ; - - virtual bool resetMessageStandardTagTypes(Rs::Msgs::MsgTagType& tags)override ; - - virtual uint32_t getDistantMessagingPermissionFlags() override ; - virtual void setDistantMessagingPermissionFlags(uint32_t flags) override ; - - /*! - * gets avatar from peer, image data in jpeg format - */ - virtual void getAvatarData(const RsPeerId& pid,unsigned char *& data,int& size)override ; - - /*! - * sets clients avatar, image data should be in jpeg format - */ - virtual void setOwnAvatarData(const unsigned char *data,int size)override ; - - /*! - * retrieve clients avatar, image data in jpeg format - */ - virtual void getOwnAvatarData(unsigned char *& data,int& size)override ; - - /*! - * sets clients custom status (e.g. "i'm tired") - */ - virtual void setCustomStateString(const std::string& status_string) override ; - - /*! - * retrieves client's custom status - */ - virtual std::string getCustomStateString() override ; - - /*! - * retrieves peer's custom status - */ - virtual std::string getCustomStateString(const RsPeerId& peer_id) override ; - - - /*! - * Send a chat message. - * @param destination where to send the chat message - * @param msg the message - * @see ChatId - */ - virtual bool sendChat(ChatId destination, std::string msg) override ; - - /*! - * Return the max message size for security forwarding - */ - virtual uint32_t getMaxMessageSecuritySize(int type)override ; - - /*! - * sends immediate status string to a specific peer, e.g. in a private chat - * @param chat_id chat id to send status string to - * @param status_string immediate status to send - */ - virtual void sendStatusString(const ChatId& id, const std::string& status_string) override ; - - /** - * @brief clearChatLobby: Signal chat was cleared by GUI. - * @param id: Chat id cleared. - */ - virtual void clearChatLobby(const ChatId &id)override ; - - /****************************************/ - - virtual bool joinVisibleChatLobby(const ChatLobbyId& id, const RsGxsId &own_id) override ; - virtual void getListOfNearbyChatLobbies(std::vector& public_lobbies) override ; - virtual void getChatLobbyList(std::list& cl_list) override ; - virtual bool getChatLobbyInfo(const ChatLobbyId& id,ChatLobbyInfo& info) override ; - virtual void invitePeerToLobby(const ChatLobbyId&, const RsPeerId&) override ; - virtual bool acceptLobbyInvite(const ChatLobbyId& id, const RsGxsId &gxs_id) override ; - virtual bool denyLobbyInvite(const ChatLobbyId& id) override ; - virtual void getPendingChatLobbyInvites(std::list& invites) override ; - virtual void unsubscribeChatLobby(const ChatLobbyId& lobby_id) override ; - virtual void sendLobbyStatusPeerLeaving(const ChatLobbyId& lobby_id)override ; - virtual bool setIdentityForChatLobby(const ChatLobbyId& lobby_id,const RsGxsId&) override ; - virtual bool getIdentityForChatLobby(const ChatLobbyId&,RsGxsId& nick) override ; - virtual bool setDefaultIdentityForChatLobby(const RsGxsId&) override ; - virtual void getDefaultIdentityForChatLobby(RsGxsId& nick) override ; - virtual void setLobbyAutoSubscribe(const ChatLobbyId& lobby_id, const bool autoSubscribe)override ; - virtual bool getLobbyAutoSubscribe(const ChatLobbyId& lobby_id)override ; - virtual ChatLobbyId createChatLobby(const std::string& lobby_name,const RsGxsId& lobby_identity,const std::string& lobby_topic,const std::set& invited_friends,ChatLobbyFlags privacy_type) override ; - - virtual bool initiateDistantChatConnexion( - const RsGxsId& to_gxs_id, const RsGxsId& from_gxs_id, - DistantChatPeerId &pid, uint32_t& error_code, - bool notify = true )override ; - - virtual bool getDistantChatStatus(const DistantChatPeerId& gxs_id,DistantChatPeerInfo& info)override ; - virtual bool closeDistantChatConnexion(const DistantChatPeerId &pid) override ; - - virtual uint32_t getDistantChatPermissionFlags() override ; - virtual bool setDistantChatPermissionFlags(uint32_t flags) override ; - - private: - - p3MsgService *mMsgSrv; - p3ChatService *mChatSrv; -}; diff --git a/libretroshare/src/rsserver/p3peers.cc b/libretroshare/src/rsserver/p3peers.cc deleted file mode 100644 index 53cd3b5d7..000000000 --- a/libretroshare/src/rsserver/p3peers.cc +++ /dev/null @@ -1,1833 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3peers.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2008 Robert Fernie * - * Copyright (C) 2015-2020 Gioacchino Mazzurco * - * Copyright (C) 2020 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "pgp/pgpkeyutil.h" - -#include "rsserver/p3peers.h" -#include "rsserver/p3face.h" - -#include "pqi/p3linkmgr.h" -#include "pqi/p3peermgr.h" -#include "pqi/p3netmgr.h" - -#include "pqi/authssl.h" -#include "pqi/authgpg.h" -#include "retroshare/rsinit.h" -#include "retroshare/rsnotify.h" -#include "retroshare/rsfiles.h" -#include "util/rsurl.h" -#include "util/radix64.h" -#include "util/rsbase64.h" -#include "pgp/rscertificate.h" - -#include -#include - -//static const int MAX_TIME_KEEP_LOCATION_WITHOUT_CONTACT = 30*24*3600 ; // 30 days. - -#include "pqi/authssl.h" - -typedef RsCertificate::RsShortInviteFieldType RsShortInviteFieldType; // locally in this file to avoid renaming everything. - -RsPeers *rsPeers = NULL; - -/******* - * #define P3PEERS_DEBUG 1 - *******/ - -//int ensureExtension(std::string &name, std::string def_ext); - -std::string RsPeerTrustString(uint32_t trustLvl) -{ - std::string str; - - switch(trustLvl) - { - default: - case RS_TRUST_LVL_UNKNOWN: - str = "VALIDITY_UNKNOWN"; - break; - case RS_TRUST_LVL_UNDEFINED: - str = "VALIDITY_UNDEFINED"; - break; - case RS_TRUST_LVL_NEVER: - str = "VALIDITY_NEVER"; - break; - case RS_TRUST_LVL_MARGINAL: - str = "VALIDITY_MARGINAL"; - break; - case RS_TRUST_LVL_FULL: - str = "VALIDITY_FULL"; - break; - case RS_TRUST_LVL_ULTIMATE: - str = "VALIDITY_ULTIMATE"; - break; - } - return str; -} - -std::string RsPeerNetModeString(uint32_t netModel) -{ - std::string str; - if (netModel == RS_NETMODE_EXT) - { - str = "External Port"; - } - else if (netModel == RS_NETMODE_UPNP) - { - str = "Ext (UPnP)"; - } - else if (netModel == RS_NETMODE_UDP) - { - str = "UDP Mode"; - } - else if (netModel == RS_NETMODE_HIDDEN) - { - str = "Hidden"; - } - else if (netModel == RS_NETMODE_UNREACHABLE) - { - str = "UDP Mode (Unreachable)"; - } - else - { - str = "Unknown NetMode"; - } - return str; -} - - -p3Peers::p3Peers(p3LinkMgr *lm, p3PeerMgr *pm, p3NetMgr *nm) - :mLinkMgr(lm), mPeerMgr(pm), mNetMgr(nm) {} - - /* Updates ... */ -bool p3Peers::FriendsChanged(const RsPeerId& pid,bool add) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::FriendsChanged()" << std::endl; -#endif - if(rsEvents) - { - auto ev = std::make_shared(pid); - rsEvents->postEvent(ev); - } - RsServer::notify()->notifyListChange(NOTIFY_LIST_FRIENDS, add? NOTIFY_TYPE_ADD : NOTIFY_TYPE_DEL); // this is meant to disappear - - /* TODO */ - return false; -} - -bool p3Peers::OthersChanged() -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::OthersChanged()" << std::endl; -#endif - - /* TODO */ - return false; -} - - /* Peer Details (Net & Auth) */ -const RsPeerId& p3Peers::getOwnId() -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getOwnId()" << std::endl; -#endif - - return AuthSSL::getAuthSSL()->OwnId(); -} - -bool p3Peers::getOnlineList(std::list &ids) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getOnlineList()" << std::endl; -#endif - - /* get from mConnectMgr */ - mLinkMgr->getOnlineList(ids); - return true; -} - -bool p3Peers::getFriendList(std::list &ids) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getFriendList()" << std::endl; -#endif - - /* get from mConnectMgr */ - mLinkMgr->getFriendList(ids); - return true; -} - -//bool p3Peers::getOthersList(std::list &ids) -//{ -//#ifdef P3PEERS_DEBUG -// std::cerr << "p3Peers::getOthersList()"; -// std::cerr << std::endl; -//#endif -// -// /* get from mAuthMgr */ -// AuthSSL::getAuthSSL()->getAllList(ids); -// return true; -//} - -bool p3Peers::getPeersCount( - uint32_t& peersCount, uint32_t& onlinePeersCount, - bool countLocations ) -{ - peersCount = mPeerMgr->getFriendCount(countLocations, false); - onlinePeersCount = mPeerMgr->getFriendCount(countLocations, true); - return true; -} - -bool p3Peers::getPeerCount (unsigned int *friendCount, unsigned int *onlineCount, bool ssl) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getPeerCount()" << std::endl; -#endif - - if (friendCount) *friendCount = mPeerMgr->getFriendCount(ssl, false); - if (onlineCount) *onlineCount = mPeerMgr->getFriendCount(ssl, true); - - return true; -} - -bool p3Peers::isOnline(const RsPeerId &id) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::isOnline() " << id << std::endl; -#endif - - /* get from mConnectMgr */ - peerConnectState state; - if (mLinkMgr->getFriendNetStatus(id, state) && - (state.state & RS_PEER_S_CONNECTED)) - { - return true; - } - return false; -} - -bool p3Peers::isFriend(const RsPeerId &ssl_id) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::isFriend() " << ssl_id << std::endl; -#endif - - /* get from mConnectMgr */ - return mPeerMgr->isFriend(ssl_id); -} - -bool p3Peers::getPeerMaximumRates(const RsPeerId& pid,uint32_t& maxUploadRate,uint32_t& maxDownloadRate) -{ - return mPeerMgr->getMaxRates(pid,maxUploadRate,maxDownloadRate) ; -} -bool p3Peers::getPeerMaximumRates(const RsPgpId& pid,uint32_t& maxUploadRate,uint32_t& maxDownloadRate) -{ - return mPeerMgr->getMaxRates(pid,maxUploadRate,maxDownloadRate) ; -} - -bool p3Peers::setPeerMaximumRates(const RsPgpId& pid,uint32_t maxUploadRate,uint32_t maxDownloadRate) -{ - return mPeerMgr->setMaxRates(pid,maxUploadRate,maxDownloadRate) ; -} - -bool p3Peers::haveSecretKey(const RsPgpId& id) -{ - return AuthPGP::haveSecretKey(id); -} - -/* There are too many dependancies of this function - * to shift it immeidately - */ - -bool p3Peers::getPeerDetails(const RsPeerId& id, RsPeerDetails &d) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getPeerDetails() called for id : " << id << std::endl; -#endif - - RsPeerId sOwnId = AuthSSL::getAuthSSL()->OwnId(); - peerState ps; - - if (id == sOwnId) - { - mPeerMgr->getOwnNetStatus(ps); - ps.gpg_id = AuthPGP::getPgpOwnId(); - } - else if (!mPeerMgr->getFriendNetStatus(id, ps)) - { -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getPeerDetails() ERROR not an SSL Id: " << id << std::endl; -#endif - return false; - } - - /* get from gpg (first), to fill in the sign and trust details */ - /* don't return now, we've got fill in the ssl and connection info */ - - if(!getGPGDetails(ps.gpg_id, d)) - { - if(!ps.skip_pgp_signature_validation) - return false; - - d.gpg_id = ps.gpg_id ; - d.skip_pgp_signature_validation = true; - } - else - d.skip_pgp_signature_validation = false; - - d.isOnlyGPGdetail = false; - - //get the ssl details - d.id = id; - d.location = ps.location; - - d.service_perm_flags = mPeerMgr->servicePermissionFlags(ps.gpg_id); - - /* generate */ - d.authcode = "AUTHCODE"; - - /* fill from pcs */ - d.lastConnect = ps.lastcontact; - d.connectPeriod = 0; - - if (ps.hiddenNode) - { - d.isHiddenNode = true; - d.hiddenNodeAddress = ps.hiddenDomain; - d.hiddenNodePort = ps.hiddenPort; - d.hiddenType = ps.hiddenType; - - if(sockaddr_storage_isnull(ps.localaddr)) // that happens if the address is not initialised. - { - d.localAddr = "INVALID_IP"; - d.localPort = 0 ; - } - else - { - d.localAddr = sockaddr_storage_iptostring(ps.localaddr); - d.localPort = sockaddr_storage_port(ps.localaddr); - } - d.extAddr = "hidden"; - d.extPort = 0; - d.dyndns = ""; - } - else - { - d.isHiddenNode = false; - d.hiddenNodeAddress = ""; - d.hiddenNodePort = 0; - d.hiddenType = RS_HIDDEN_TYPE_NONE; - - if(!sockaddr_storage_isnull(ps.localaddr)) - { - sockaddr_storage_ipv6_to_ipv4(ps.localaddr); - d.localAddr = sockaddr_storage_iptostring(ps.localaddr); - d.localPort = sockaddr_storage_port(ps.localaddr); - } - else - { - d.localAddr = "INVALID_IP"; - d.localPort = 0; - } - - if(!sockaddr_storage_isnull(ps.serveraddr)) - { - sockaddr_storage_ipv6_to_ipv4(ps.serveraddr); - d.extAddr = sockaddr_storage_iptostring(ps.serveraddr); - d.extPort = sockaddr_storage_port(ps.serveraddr); - } - else - { - d.extAddr = "INVALID_IP"; - d.extPort = 0; - } - - d.dyndns = ps.dyndns; - - std::list::iterator it; - for(it = ps.ipAddrs.mLocal.mAddrs.begin(); - it != ps.ipAddrs.mLocal.mAddrs.end(); ++it) - { - sockaddr_storage_ipv6_to_ipv4(it->mAddr); - std::string toto; - toto += sockaddr_storage_tostring(it->mAddr); - rs_sprintf_append(toto, " %ld sec loc", time(NULL) - it->mSeenTime); - d.ipAddressList.push_back(toto); - } - for(it = ps.ipAddrs.mExt.mAddrs.begin(); it != ps.ipAddrs.mExt.mAddrs.end(); ++it) - { - sockaddr_storage_ipv6_to_ipv4(it->mAddr); - std::string toto; - toto += sockaddr_storage_tostring(it->mAddr); - rs_sprintf_append(toto, " %ld sec ext", time(NULL) - it->mSeenTime); - d.ipAddressList.push_back(toto); - } - } - - - switch(ps.netMode & RS_NET_MODE_ACTUAL) - { - case RS_NET_MODE_EXT: - d.netMode = RS_NETMODE_EXT; - break; - case RS_NET_MODE_UPNP: - d.netMode = RS_NETMODE_UPNP; - break; - case RS_NET_MODE_UDP: - d.netMode = RS_NETMODE_UDP; - break; - case RS_NET_MODE_HIDDEN: - d.netMode = RS_NETMODE_HIDDEN; - break; - case RS_NET_MODE_UNREACHABLE: - case RS_NET_MODE_UNKNOWN: - default: - d.netMode = RS_NETMODE_UNREACHABLE; - break; - } - - d.vs_disc = ps.vs_disc; - d.vs_dht = ps.vs_dht; - - /* Translate */ - peerConnectState pcs; - if (!mLinkMgr->getFriendNetStatus(id, pcs)) - { - if(id != sOwnId) - std::cerr << "p3Peers::getPeerDetails() ERROR No Link Information : " << id << std::endl; - return true; - } - -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getPeerDetails() got a SSL id and is returning SSL and GPG details for id : " << id << std::endl; -#endif - - if (pcs.state & RS_PEER_S_CONNECTED) - { - sockaddr_storage_ipv6_to_ipv4(pcs.connectaddr); - d.connectAddr = sockaddr_storage_iptostring(pcs.connectaddr); - d.connectPort = sockaddr_storage_port(pcs.connectaddr); - } - else - { - d.connectAddr = ""; - d.connectPort = 0 ; - } - - d.state = 0; - if (pcs.state & RS_PEER_S_FRIEND) d.state |= RS_PEER_STATE_FRIEND; - if (pcs.state & RS_PEER_S_ONLINE) d.state |= RS_PEER_STATE_ONLINE; - if (pcs.state & RS_PEER_S_CONNECTED) d.state |= RS_PEER_STATE_CONNECTED; - if (pcs.state & RS_PEER_S_UNREACHABLE) d.state |= RS_PEER_STATE_UNREACHABLE; - - d.actAsServer = pcs.actAsServer; - - d.linkType = pcs.linkType; - - /* Finally determine AutoConnect Status */ - d.foundDHT = pcs.dht.found; - - d.connectState = RS_PEER_CONNECTSTATE_OFFLINE; - d.connectStateString.clear(); - - if (pcs.inConnAttempt) - { - if (pcs.currentConnAddrAttempt.type & RS_NET_CONN_TCP_ALL) { - d.connectState = RS_PEER_CONNECTSTATE_TRYING_TCP; - d.connectStateString = sockaddr_storage_tostring(pcs.currentConnAddrAttempt.addr); - } else if (pcs.currentConnAddrAttempt.type & RS_NET_CONN_UDP_ALL) { - d.connectState = RS_PEER_CONNECTSTATE_TRYING_UDP; - d.connectStateString = sockaddr_storage_tostring(pcs.currentConnAddrAttempt.addr); - } - } - else if (pcs.state & RS_PEER_S_CONNECTED) - { - /* peer is connected - determine how and set proper connectState */ - if(mPeerMgr->isHidden()) - { - uint32_t type; - /* hidden location */ - /* use connection direction to determine connection type */ - if(pcs.actAsServer) - { - /* incoming connection */ - /* use own type to set connectState */ - type = mPeerMgr->getHiddenType(AuthSSL::getAuthSSL()->OwnId()); - switch (type) { - case RS_HIDDEN_TYPE_TOR: - d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_TOR; - break; - case RS_HIDDEN_TYPE_I2P: - d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_I2P; - break; - default: - d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_UNKNOWN; - break; - } - } - else - { - /* outgoing connection */ - /* use peer hidden type to set connectState */ - switch (ps.hiddenType) { - case RS_HIDDEN_TYPE_TOR: - d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_TOR; - break; - case RS_HIDDEN_TYPE_I2P: - d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_I2P; - break; - default: - d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_UNKNOWN; - break; - } - } - } - else if (ps.hiddenType & RS_HIDDEN_TYPE_MASK) - { - /* hidden peer */ - /* use hidden type to set connectState */ - switch (ps.hiddenType) { - case RS_HIDDEN_TYPE_TOR: - d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_TOR; - break; - case RS_HIDDEN_TYPE_I2P: - d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_I2P; - break; - default: - d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_UNKNOWN; - break; - } - } - else - { - /* peer and we are normal nodes */ - /* use normal detection to set connectState */ - if (pcs.connecttype == RS_NET_CONN_TCP_ALL) - { - d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_TCP; - } - else if (pcs.connecttype == RS_NET_CONN_UDP_ALL) - { - d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_UDP; - } - else - { - d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_UNKNOWN; - } - } - } - - d.wasDeniedConnection = pcs.wasDeniedConnection; - d.deniedTS = pcs.deniedTS; - - return true; -} - -bool p3Peers::isProxyAddress(const uint32_t type, const sockaddr_storage& addr) -{ - uint16_t port ; - std::string string_addr; - uint32_t status ; - - if(!getProxyServer(type, string_addr, port, status)) - return false ; - - return sockaddr_storage_iptostring(addr)==string_addr && sockaddr_storage_port(addr)==port ; -} - -bool p3Peers::isKeySupported(const RsPgpId& id) -{ - return AuthPGP::isKeySupported(id); -} - -std::string p3Peers::getGPGName(const RsPgpId &gpg_id) -{ - /* get from mAuthMgr as it should have more peers? */ - return AuthPGP::getPgpName(gpg_id); -} - -bool p3Peers::isPgpFriend(const RsPgpId& pgpId) -{ return AuthPGP::isPGPAccepted(pgpId); } - -bool p3Peers::isSslOnlyFriend(const RsPeerId& sslId) -{ - bool has_ssl_only_flag = mPeerMgr->isSslOnlyFriend(sslId) ; - - if(has_ssl_only_flag) - { - if(isPgpFriend(getGPGId(sslId))) - { - RsErr() << __PRETTY_FUNCTION__ << ": Peer " << sslId << " has SSL-friend-only flag but his PGP id is in the list of friends. This is inconsistent (Bug in the code). Returning false for security reasons." << std::endl; - return false; - } - return true; - } - return false; -} - -bool p3Peers::isGPGAccepted(const RsPgpId &gpg_id_is_friend) -{ return isPgpFriend(gpg_id_is_friend); } - -std::string p3Peers::getPeerName(const RsPeerId& ssl) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getPeerName() " << ssl_or_gpg_id << std::endl; -#endif - std::string name; - if (ssl == AuthSSL::getAuthSSL()->OwnId()) - return AuthPGP::getPgpOwnName(); - - if (mPeerMgr->getPeerName(ssl, name)) - { -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getPeerName() got a ssl id. Name is : " << name << std::endl; -#endif - return name; - } - return std::string() ; -} - - -bool p3Peers::getGPGAllList(std::list &ids) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getGPGAllList()" << std::endl; -#endif - - /* get from mAuthMgr */ - AuthPGP::getPgpAllList(ids); - return true; -} - -bool p3Peers::getGPGValidList(std::list &ids) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getPGPOthersList()" << std::endl; -#endif - - /* get from mAuthMgr */ - AuthPGP::getPgpValidList(ids); - return true; -} - -bool p3Peers::getGPGSignedList(std::list &ids) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getPGPOthersList()" << std::endl; -#endif - - /* get from mAuthMgr */ - AuthPGP::getPgpSignedList(ids); - return true; -} - -bool p3Peers::getPgpFriendList(std::vector& pgpIds) -{ - std::list ids; - if(AuthPGP::getPgpAcceptedList(ids)) - { - pgpIds.clear(); - std::copy(ids.begin(), ids.end(), std::back_inserter(pgpIds)); - return true; - } - return false; -} - -bool p3Peers::getGPGAcceptedList(std::list &ids) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getGPGAcceptedList()" << std::endl; -#endif - AuthPGP::getPgpAcceptedList(ids); - return true; -} - - -bool p3Peers::getAssociatedSSLIds(const RsPgpId &gpg_id, std::list &ids) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getAssociatedSSLIds() for id : " << gpg_id << std::endl; -#endif - - return mPeerMgr->getAssociatedPeers(gpg_id, ids); -} - -bool p3Peers::gpgSignData(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen, std::string reason /* = "" */) -{ - return AuthPGP::SignDataBin(data,len,sign,signlen, reason); -} - -RsPgpId p3Peers::pgpIdFromFingerprint(const RsPgpFingerprint& fpr) -{ - return PGPHandler::pgpIdFromFingerprint(fpr); -} - -bool p3Peers::getGPGDetails(const RsPgpId &pgp_id, RsPeerDetails &d) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getPgpDetails() called for id : " << pgp_id << std::endl; -#endif - - /* get from mAuthMgr */ - bool res = AuthPGP::getPgpDetails(pgp_id, d); - - d.isOnlyGPGdetail = true ; - d.service_perm_flags = mPeerMgr->servicePermissionFlags(pgp_id) ; - - return res ; -} - -const RsPgpId& p3Peers::getGPGOwnId() -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getPGPOwnId()" << std::endl; -#endif - - /* get from mAuthMgr */ - return AuthPGP::getPgpOwnId(); -} - -RsPgpId p3Peers::getGPGId(const RsPeerId& sslid) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getPGPId()" << std::endl; -#endif - - /* get from mAuthMgr */ - if (sslid == AuthSSL::getAuthSSL()->OwnId()) - { - return AuthPGP::getPgpOwnId(); - } - peerState pcs; - if (mPeerMgr->getFriendNetStatus(sslid, pcs)) - return pcs.gpg_id; - - return RsPgpId(); -} - - - /* These Functions are now the only way to authorize a new gpg user... - * if we are passed a ssl_id, then use it... otherwise just auth gpg_id - */ - - /* Add/Remove Friends */ -bool p3Peers::addFriend(const RsPeerId &ssl_id, const RsPgpId &gpg_id,ServicePermissionFlags perm_flags) -{ - -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::addFriend() with : id : " << id << "; gpg_id : " << gpg_id << std::endl; -#endif - if(AuthPGP::isPGPId(gpg_id)) - { -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::addFriend() Authorising GPG Id: " << gpg_id << std::endl; -#endif - if (AuthPGP::AllowConnection(gpg_id, true)) - { -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::addFriend() Authorization OK." << std::endl; -#endif - } - else - { -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::addFriend() Authorization FAILED." << std::endl; -#endif - return false; - } - } - else - { -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::addFriend() Bad gpg_id : " << gpg_id << std::endl; -#endif - return false; - } - - if(ssl_id.isNull()) - { -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::addFriend() WARNING id is NULL or gpgId" << std::endl; -#endif - return true; - } - - FriendsChanged(ssl_id,true); - - /* otherwise - we install as ssl_id..... - * If we are adding an SSL certificate. we flag lastcontact as now. - * This will cause the SSL certificate to be retained for 30 days... and give the person a chance to connect! - * */ - rstime_t now = time(NULL); - return mPeerMgr->addFriend(ssl_id, gpg_id, RS_NET_MODE_UDP, RS_VS_DISC_FULL, RS_VS_DHT_FULL, now, perm_flags); -} - -bool p3Peers::addSslOnlyFriend( const RsPeerId& sslId, const RsPgpId& pgp_id,const RsPeerDetails& details ) -{ - if( mPeerMgr->addSslOnlyFriend(sslId, pgp_id,details)) - { - FriendsChanged(sslId,true); - return true; - } - else - return false; -} - -bool p3Peers::removeKeysFromPGPKeyring(const std::set& pgp_ids,std::string& backup_file,uint32_t& error_code) -{ - return AuthPGP::removeKeysFromPGPKeyring(pgp_ids,backup_file,error_code) ; -} - -bool p3Peers::removeFriendLocation(const RsPeerId &sslId) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::removeFriendLocation() " << sslId << std::endl; -#endif - //will remove if it's a ssl id - mPeerMgr->removeFriend(sslId, false); - - FriendsChanged(sslId,false); - return true; -} - -bool p3Peers::removeFriend(const RsPgpId& gpgId) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::removeFriend() " << gpgId << std::endl; -#endif - if (gpgId == AuthPGP::getPgpOwnId()) { - std::cerr << "p3Peers::removeFriend() ERROR we're not going to remove our own GPG id." << std::endl; - return false; - } - -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::removeFriend() Removing GPG Id: " << gpgId << std::endl; -#endif - if (AuthPGP::AllowConnection(gpgId, false)) - { -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::removeFriend() OK." << std::endl; -#endif - mPeerMgr->removeAllFriendLocations(gpgId); - return true; - } - else - { -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::removeFriend() FAILED." << std::endl; -#endif - mPeerMgr->removeAllFriendLocations(gpgId); - return false; - } -} - - - - /* Network Stuff */ -bool p3Peers::connectAttempt(const RsPeerId &id) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::connectAttempt() " << id << std::endl; -#endif - - return mLinkMgr->retryConnect(id); -} - -void p3Peers::getIPServersList(std::list& ip_servers) -{ - mNetMgr->getIPServersList(ip_servers) ; -} -void p3Peers::getCurrentExtIPList(std::list& ip_list) -{ - mNetMgr->getCurrentExtIPList(ip_list) ; -} -bool p3Peers::resetOwnExternalAddressList() -{ - //TODO Phenom 2021-10-30: Need to call something like mNetMgr->netReset(); - // to update this addresslist. - return mPeerMgr->resetOwnExternalAddressList(); -} -void p3Peers::allowServerIPDetermination(bool b) -{ - mNetMgr->setIPServersEnabled(b) ; -} - -bool p3Peers::getAllowServerIPDetermination() -{ - return mNetMgr->getIPServersEnabled() ; -} - -bool p3Peers::setLocation(const RsPeerId &ssl_id, const std::string &location) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::setLocation() " << ssl_id << std::endl; -#endif - - return mPeerMgr->setLocation(ssl_id, location); -} - - -bool splitAddressString(const std::string &addr, std::string &domain, uint16_t &port) -{ - std::cerr << "splitAddressString() Input: " << addr << std::endl; - - size_t cpos = addr.rfind(':'); - if (cpos == std::string::npos) - { - std::cerr << "splitAddressString Failed to parse (:)"; - std::cerr << std::endl; - return false; - } - - int lenport = addr.length() - (cpos + 1); // +1 to skip over : char. - if (lenport <= 0) - { - std::cerr << "splitAddressString() Missing Port "; - std::cerr << std::endl; - return false; - } - - domain = addr.substr(0, cpos); - std::string portstr = addr.substr(cpos + 1, std::string::npos); - int portint = atoi(portstr.c_str()); - - if ((portint < 0) || (portint > 65535)) - { - std::cerr << "splitAddressString() Invalid Port"; - std::cerr << std::endl; - return false; - } - port = portint; - - std::cerr << "splitAddressString() Domain: " << domain << " Port: " << port; - std::cerr << std::endl; - return true; -} - - -bool p3Peers::setHiddenNode(const RsPeerId &id, const std::string &hidden_node_address) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::setHiddenNode() " << id << std::endl; -#endif - - std::string domain; - uint16_t port; - if (!splitAddressString(hidden_node_address, domain, port)) - { - return false; - } - mPeerMgr->setNetworkMode(id, RS_NET_MODE_HIDDEN); - mPeerMgr->setHiddenDomainPort(id, domain, port); - return true; -} - - -bool p3Peers::isHiddenNode(const RsPeerId &id) -{ - return mPeerMgr->isHiddenNode(id) ; -} - -bool p3Peers::setHiddenNode(const RsPeerId &id, const std::string &address, uint16_t port) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::setHiddenNode() " << id << std::endl; -#endif - std::cerr << "p3Peers::setHiddenNode() Domain: " << address << " Port: " << port; - std::cerr << std::endl; - - mPeerMgr->setNetworkMode(id, RS_NET_MODE_HIDDEN); - mPeerMgr->setHiddenDomainPort(id, address, port); - return true; -} - -bool p3Peers::addPeerLocator(const RsPeerId &ssl_id, const RsUrl& locator) -{ return mPeerMgr->addPeerLocator(ssl_id, locator); } - -bool p3Peers::setLocalAddress(const RsPeerId &id, - const std::string &addr_str, uint16_t port) -{ -#ifdef P3PEERS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " " << id << " " << addr_str << " " - << port << std::endl; -#endif - - sockaddr_storage addr; - if (sockaddr_storage_inet_pton(addr, addr_str)) - if (sockaddr_storage_setport(addr, port)) - return mPeerMgr->setLocalAddress(id, addr); - return false; -} - -bool p3Peers::setExtAddress(const RsPeerId &id, - const std::string &addr_str, uint16_t port) -{ -#ifdef P3PEERS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " " << id << " " << addr_str << " " - << port << std::endl; -#endif - - sockaddr_storage addr; - if (sockaddr_storage_inet_pton(addr, addr_str)) - if (sockaddr_storage_setport(addr, port)) - return mPeerMgr->setExtAddress(id, addr); - return false; -} - -bool p3Peers::setDynDNS(const RsPeerId &id, const std::string &dyndns) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::setDynDNS() called with id: " << id << " dyndns: " << dyndns <setDynDNS(id, dyndns); -} - -bool p3Peers::setNetworkMode(const RsPeerId &id, uint32_t extNetMode) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::setNetworkMode() " << id << std::endl; -#endif - - /* translate */ - uint32_t netMode = 0; - switch(extNetMode) - { - case RS_NETMODE_EXT: - netMode = RS_NET_MODE_EXT; - break; - case RS_NETMODE_UPNP: - netMode = RS_NET_MODE_UPNP; - break; - case RS_NETMODE_UDP: - netMode = RS_NET_MODE_UDP; - break; - case RS_NETMODE_HIDDEN: - netMode = RS_NET_MODE_HIDDEN; - break; - case RS_NETMODE_UNREACHABLE: - netMode = RS_NET_MODE_UNREACHABLE; - break; - default: - break; - } - - return mPeerMgr->setNetworkMode(id, netMode); -} - - -bool p3Peers::setVisState(const RsPeerId &id, uint16_t vs_disc, uint16_t vs_dht) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::setVisState() " << id << std::endl; -#endif - std::cerr << "p3Peers::setVisState() " << id << " DISC: " << vs_disc; - std::cerr << " DHT: " << vs_dht << std::endl; - - return mPeerMgr->setVisState(id, vs_disc, vs_dht); -} - -bool p3Peers::getProxyServer(const uint32_t type, std::string &addr, uint16_t &port, uint32_t &status) -{ - #ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getProxyServer()" << std::endl; - #endif - - struct sockaddr_storage proxy_addr; - mPeerMgr->getProxyServerAddress(type, proxy_addr); - addr = sockaddr_storage_iptostring(proxy_addr); - port = sockaddr_storage_port(proxy_addr); - mPeerMgr->getProxyServerStatus(type, status); - return true; -} - -bool p3Peers::setProxyServer(const uint32_t type, const std::string &addr_str, const uint16_t port) -{ - #ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::setProxyServer() " << std::endl; - #endif - - if(port < 1024) - { - std::cerr << "(EE) attempt to set proxy server address to something not allowed: " << addr_str << ":" << port << std::endl; - return false ; - } - - std::cerr << "Settign proxy server address to " << addr_str << ":" << port << std::endl; - - struct sockaddr_storage addr; - struct sockaddr_in *addrv4p = (struct sockaddr_in *) &addr; - addrv4p->sin_family = AF_INET; - addrv4p->sin_port = htons(port); - - int ret = 1; -/********************************** WINDOWS/UNIX SPECIFIC PART *******************/ -#ifndef WINDOWS_SYS - if (ret && (0 != inet_aton(addr_str.c_str(), &(addrv4p->sin_addr)))) -#else - addrv4p->sin_addr.s_addr = inet_addr(addr_str.c_str()); - if (ret) -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART *******************/ - { - return mPeerMgr->setProxyServerAddress(type, addr); - } - else - { - std::cerr << "p3Peers::setProxyServer() Failed to Parse Address" << std::endl; - } - - return false; -} - - - - - -//=========================================================================== - /* Auth Stuff */ - -std::string p3Peers::getPGPKey(const RsPgpId& pgp_id,bool include_signatures) -{ - rs_owner_ptr mem_block = nullptr; - size_t mem_block_size = 0; - - if( !AuthPGP::exportPublicKey( RsPgpId(pgp_id), mem_block, mem_block_size, false, include_signatures ) ) - { - RsErr() << __PRETTY_FUNCTION__ - << " Failure retriving certificate for id " << pgp_id - << std::endl; - return ""; - } - - RsPeerDetails details; - if(!getGPGDetails(pgp_id, details)) return ""; - - auto certPtr = - RsCertificate::fromMemoryBlock(details, mem_block, mem_block_size); - - free(mem_block); - - if(certPtr) return certPtr->armouredPGPKey(); - - return ""; -} - - -bool p3Peers::GetPGPBase64StringAndCheckSum( - const RsPgpId& gpg_id, - std::string& gpg_base64_string, std::string& gpg_base64_checksum ) -{ - gpg_base64_string = "" ; - gpg_base64_checksum = "" ; - - rs_owner_ptr mem_block = nullptr; - size_t mem_block_size = 0; - if(!AuthPGP::exportPublicKey( gpg_id,mem_block,mem_block_size,false,false )) - return false; - - RsBase64::encode(mem_block, mem_block_size, gpg_base64_string, true, false); - - uint32_t crc = PGPKeyManagement::compute24bitsCRC(mem_block,mem_block_size); - - free(mem_block); - - unsigned char tmp[3] = { - uint8_t((crc >> 16) & 0xff), - uint8_t((crc >> 8) & 0xff), - uint8_t(crc & 0xff) } ; - RsBase64::encode(tmp, 3, gpg_base64_checksum, true, false); - - return true; -} - -static void addPacketHeader(RsShortInviteFieldType ptag, size_t size, unsigned char *& buf, uint32_t& offset, uint32_t& buf_size) -{ - // Check that the buffer has sufficient size. If not, increase it. - - while(offset + size + 6 >= buf_size) - { - unsigned char *newbuf = new unsigned char[2*buf_size] ; - - memcpy(newbuf, buf, buf_size) ; - buf_size *= 2 ; - delete[] buf ; - buf = newbuf ; - } - - // Write ptag and size - - buf[offset] = static_cast(ptag) ; - offset += 1 ; - - offset += PGPKeyParser::write_125Size(&buf[offset],size) ; -} - -bool p3Peers::getShortInvite(std::string& invite, const RsPeerId& _sslId, RetroshareInviteFlags invite_flags, const std::string& baseUrl ) -{ - RsPeerId sslId = _sslId; - if(sslId.isNull()) sslId = getOwnId(); - - RsPeerDetails tDetails; - if(!getPeerDetails(sslId, tDetails)) return false; - - uint32_t buf_size = 100; - uint32_t offset = 0; - unsigned char *buf = (unsigned char*)malloc(buf_size); - - addPacketHeader(RsShortInviteFieldType::SSL_ID,RsPeerId::SIZE_IN_BYTES,buf,offset,buf_size); - sslId.serialise(buf,buf_size,offset); - - addPacketHeader(RsShortInviteFieldType::PGP_FINGERPRINT,RsPgpFingerprint::SIZE_IN_BYTES,buf,offset,buf_size); - tDetails.fpr.serialise(buf,buf_size,offset); - - addPacketHeader(RsShortInviteFieldType::PEER_NAME,tDetails.name.size(),buf,offset,buf_size); - memcpy(&buf[offset],tDetails.name.c_str(),tDetails.name.size()); - offset += tDetails.name.size(); - - /* If it is a hidden node, always use hidden address and port as locator */ - - if(tDetails.isHiddenNode) - { - addPacketHeader(RsShortInviteFieldType::HIDDEN_LOCATOR,4 + 2 + tDetails.hiddenNodeAddress.size(),buf,offset,buf_size); - - buf[offset+0] = (uint8_t)((tDetails.hiddenType >> 24) & 0xff); - buf[offset+1] = (uint8_t)((tDetails.hiddenType >> 16) & 0xff); - buf[offset+2] = (uint8_t)((tDetails.hiddenType >> 8) & 0xff); - buf[offset+3] = (uint8_t)((tDetails.hiddenType ) & 0xff); - - buf[offset+4] = (uint8_t)((tDetails.hiddenNodePort >> 8) & 0xff); - buf[offset+5] = (uint8_t)((tDetails.hiddenNodePort ) & 0xff); - - memcpy(&buf[offset+6],tDetails.hiddenNodeAddress.c_str(),tDetails.hiddenNodeAddress.size()); - offset += 4 + 2 + tDetails.hiddenNodeAddress.size(); - } - - if( !!(invite_flags & RetroshareInviteFlags::DNS) && !tDetails.dyndns.empty() && (tDetails.extPort || tDetails.localPort)) - { - uint16_t tPort = tDetails.extPort ? tDetails.extPort : tDetails.localPort; - - addPacketHeader(RsShortInviteFieldType::DNS_LOCATOR, 2 + tDetails.dyndns.size(),buf,offset,buf_size); - - buf[offset+0] = (uint8_t)((tPort >> 8) & 0xff); - buf[offset+1] = (uint8_t)((tPort ) & 0xff); - - memcpy(&buf[offset+2],tDetails.dyndns.c_str(),tDetails.dyndns.size()); - offset += 2 + tDetails.dyndns.size(); - } - - if( !!(invite_flags & RetroshareInviteFlags::FULL_IP_HISTORY) && (!tDetails.ipAddressList.empty())) - for(auto& s: tDetails.ipAddressList) - { - const std::string& tLc = s; - std::string tLocator = tLc.substr(0, tLc.find_first_of(" ")-1); - - addPacketHeader(RsShortInviteFieldType::LOCATOR, tLocator.size(),buf,offset,buf_size); - memcpy(&buf[offset],tLocator.c_str(),tLocator.size()); - - offset += tLocator.size(); - } - else if( !!(invite_flags & RetroshareInviteFlags::CURRENT_IP) ) // only add at least the local and external IPs - { -#ifdef USE_NEW_LOCATOR_SYSTEM - // This new locator system as some advantages, but here it also has major drawbacks: (1) it cannot differentiate local and external addresses, - // and (2) it's quite larger than the old system, which tends to make certificates more than 1 line long. - - sockaddr_storage tLocal; - - if(sockaddr_storage_inet_pton(tLocal, tDetails.localAddr) && sockaddr_storage_isValidNet(tLocal) && tDetails.localPort ) - { - addPacketHeader(RsShortInviteFieldType::LOCATOR, tDetails.localAddr.size(),buf,offset,buf_size); - memcpy(&buf[offset],tDetails.localAddr.c_str(),tDetails.localAddr.size()); - - offset += tDetails.localAddr.size(); - } - sockaddr_storage tExt; - - if(sockaddr_storage_inet_pton(tExt, tDetails.extAddr) && sockaddr_storage_isValidNet(tExt) && tDetails.extPort ) - { - addPacketHeader(RsShortInviteFieldType::LOCATOR, tDetails.extAddr.size(),buf,offset,buf_size); - memcpy(&buf[offset],tDetails.extAddr.c_str(),tDetails.extAddr.size()); - - offset += tDetails.extAddr.size(); - } -#else - sockaddr_storage tLocal; - bool validLoc = sockaddr_storage_inet_pton(tLocal, tDetails.localAddr) - && sockaddr_storage_isValidNet(tLocal) - && tDetails.localPort; - bool isLocIpv4 = sockaddr_storage_ipv6_to_ipv4(tLocal); - if(validLoc && isLocIpv4) - { - uint32_t t4Addr = reinterpret_cast(tLocal).sin_addr.s_addr; - - addPacketHeader(RsShortInviteFieldType::LOC4_LOCATOR, 4 + 2,buf,offset,buf_size); - - buf[offset+0] = (uint8_t)((t4Addr >> 24) & 0xff); - buf[offset+1] = (uint8_t)((t4Addr >> 16) & 0xff); - buf[offset+2] = (uint8_t)((t4Addr >> 8) & 0xff); - buf[offset+3] = (uint8_t)((t4Addr ) & 0xff); - - buf[offset+4] = (uint8_t)((tDetails.localPort >> 8) & 0xff); - buf[offset+5] = (uint8_t)((tDetails.localPort ) & 0xff); - - offset += 4+2; - } - - sockaddr_storage tExt; - bool validExt = sockaddr_storage_inet_pton(tExt, tDetails.extAddr) - && sockaddr_storage_isValidNet(tExt) - && tDetails.extPort; - bool isExtIpv4 = sockaddr_storage_ipv6_to_ipv4(tExt); - if(validExt && isExtIpv4) - { - uint32_t t4Addr = reinterpret_cast(tExt).sin_addr.s_addr; - - addPacketHeader(RsShortInviteFieldType::EXT4_LOCATOR, 4 + 2,buf,offset,buf_size); - - buf[offset+0] = (uint8_t)((t4Addr >> 24) & 0xff); - buf[offset+1] = (uint8_t)((t4Addr >> 16) & 0xff); - buf[offset+2] = (uint8_t)((t4Addr >> 8) & 0xff); - buf[offset+3] = (uint8_t)((t4Addr ) & 0xff); - - buf[offset+4] = (uint8_t)((tDetails.extPort >> 8) & 0xff); - buf[offset+5] = (uint8_t)((tDetails.extPort ) & 0xff); - - offset += 4+2; - } - else if(validExt && !isExtIpv4) - { - // External address is IPv6, save it on LOCATOR - sockaddr_storage_setport(tExt,tDetails.extPort); - std::string tLocator = sockaddr_storage_tostring(tExt); - - addPacketHeader(RsShortInviteFieldType::LOCATOR, tLocator.size(),buf,offset,buf_size); - memcpy(&buf[offset],tLocator.c_str(),tLocator.size()); - - offset += tLocator.size(); - } -#endif - - } - - uint32_t computed_crc = PGPKeyManagement::compute24bitsCRC(buf,offset) ; - - // handle endian issues. - unsigned char mem[3] ; - mem[0] = computed_crc & 0xff ; - mem[1] = (computed_crc >> 8 ) & 0xff ; - mem[2] = (computed_crc >> 16) & 0xff ; - - addPacketHeader( RsShortInviteFieldType::CHECKSUM,3,buf,offset,buf_size); - memcpy(&buf[offset],mem,3); - offset += 3; - - Radix64::encode(buf, static_cast(offset), invite); - - if(!(invite_flags & RetroshareInviteFlags::RADIX_FORMAT)) - { - RsUrl inviteUrl(baseUrl); - inviteUrl.setQueryKV("rsInvite", invite); - invite = inviteUrl.toString(); - } - - return true; -} - -bool p3Peers::parseShortInvite(const std::string& inviteStrUrl, RsPeerDetails& details, uint32_t &err_code ) -{ - if(inviteStrUrl.empty()) - { - RsErr() << __PRETTY_FUNCTION__ << " can't parse empty invite" - << std::endl; - return false; - } - std::string rsInvite = inviteStrUrl; - - RsUrl inviteUrl(inviteStrUrl); - - if(inviteUrl.hasQueryK("rsInvite")) - rsInvite = *inviteUrl.getQueryV("rsInvite"); - - if(!RsCertificate::decodeRadix64ShortInvite(rsInvite, details, err_code)) - return false; - - // Also check if the PGP key is available. If so, add it in the PeerDetails: - - RsPeerDetails pgp_det ; - if(getGPGDetails(PGPHandler::pgpIdFromFingerprint(details.fpr),pgp_det) && pgp_det.fpr == details.fpr) - { - details.issuer = pgp_det.issuer; - details.gpg_id = pgp_det.gpg_id; - details.gpgSigners = pgp_det.gpgSigners; - details.trustLvl = pgp_det.trustLvl; - details.validLvl = pgp_det.validLvl; - details.ownsign = pgp_det.ownsign; - details.hasSignedMe = pgp_det.hasSignedMe; - details.accept_connection = pgp_det.accept_connection; - } - else - details.skip_pgp_signature_validation = true; - - if(details.gpg_id.isNull()) - { - err_code = CERTIFICATE_PARSING_ERROR_MISSING_PGP_FINGERPRINT; - return false; - } - err_code = CERTIFICATE_PARSING_ERROR_NO_ERROR; - return true; -} - -bool p3Peers::acceptInvite( const std::string& invite, - ServicePermissionFlags flags ) -{ - if(invite.empty()) return false; - - const std::string* radixPtr(&invite); - - RsUrl url(invite); - std::map query(url.query()); - - if(query.find("radix") != query.end()) - radixPtr = &query["radix"]; - - const std::string& radix(*radixPtr); - if(radix.empty()) return false; - - RsPgpId pgpId; - RsPeerId sslId; - std::string errorString; - - if(!loadCertificateFromString(radix, sslId, pgpId, errorString)) - return false; - - RsPeerDetails peerDetails; - uint32_t errorCode; - - if(!loadDetailsFromStringCert(radix, peerDetails, errorCode)) - return false; - - if(peerDetails.gpg_id.isNull()) - return false; - - addFriend(peerDetails.id, peerDetails.gpg_id, flags); - - if (!peerDetails.location.empty()) - setLocation(peerDetails.id, peerDetails.location); - - // Update new address even the peer already existed. - if (peerDetails.isHiddenNode) - { - setHiddenNode( peerDetails.id, - peerDetails.hiddenNodeAddress, - peerDetails.hiddenNodePort ); - } - else - { - //let's check if there is ip adresses in the certificate. - if (!peerDetails.extAddr.empty() && peerDetails.extPort) - setExtAddress( peerDetails.id, - peerDetails.extAddr, - peerDetails.extPort ); - if (!peerDetails.localAddr.empty() && peerDetails.localPort) - setLocalAddress( peerDetails.id, - peerDetails.localAddr, - peerDetails.localPort ); - if (!peerDetails.dyndns.empty()) - setDynDNS(peerDetails.id, peerDetails.dyndns); - for(auto&& ipr : peerDetails.ipAddressList) - addPeerLocator( - peerDetails.id, - RsUrl(ipr.substr(0, ipr.find(' '))) ); - } - - return true; -} - -std::string p3Peers::GetRetroshareInvite( const RsPeerId& sslId, RetroshareInviteFlags invite_flags) -{ -#ifdef P3PEERS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << std::endl; -#endif - const RsPeerId& ssl_id(sslId.isNull() ? getOwnId() : sslId); - - //add the sslid, location, ip local and external address after the signature - RsPeerDetails detail; - std::string invite; - - if (getPeerDetails(ssl_id, detail)) - { - if( !(invite_flags & RetroshareInviteFlags::FULL_IP_HISTORY) - || detail.isHiddenNode) - detail.ipAddressList.clear(); - - //Check if external address is IPv6, then move it to ipAddressList as RsCertificate only allow 4 numbers. - sockaddr_storage tExt; - bool validExt = sockaddr_storage_inet_pton(tExt, detail.extAddr) - && sockaddr_storage_isValidNet(tExt) - && detail.extPort; - bool isExtIpv4 = sockaddr_storage_ipv6_to_ipv4(tExt); - - if( !(invite_flags & RetroshareInviteFlags::FULL_IP_HISTORY) - && !detail.isHiddenNode - && validExt && !isExtIpv4) - { - sockaddr_storage_setport(tExt,detail.extPort); - detail.ipAddressList.push_front(sockaddr_storage_tostring(tExt) + " "); // Space needed to later parse. - detail.extAddr = ""; //Clear it to not trigg error. - detail.extPort = 0; - } - - unsigned char *mem_block = nullptr; - size_t mem_block_size = 0; - - if(!AuthPGP::exportPublicKey( RsPgpId(detail.gpg_id), mem_block, mem_block_size, false, !!(invite_flags & RetroshareInviteFlags::PGP_SIGNATURES) )) - { - std::cerr << "Cannot output certificate for id \"" << detail.gpg_id - << "\". Sorry." << std::endl; - return ""; - } - - RsCertificate cert(detail, mem_block, mem_block_size); - free(mem_block); - - return cert.toStdString(); - } - -#ifdef P3PEERS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " returns : \n" << invite << std::endl; -#endif - return invite; -} - -//=========================================================================== - -bool p3Peers::loadCertificateFromString( - const std::string& cert, RsPeerId& ssl_id, - RsPgpId& gpg_id, std::string& error_string ) -{ - uint32_t errNum = 0; - auto crt = RsCertificate::fromString(cert, errNum); - - if(!crt) - { - error_string = "RsCertificate failed with errno: " - + std::to_string(errNum) + " parsing: " + cert; - return false; - } - - RsPgpId gpgid; - bool res = AuthPGP::LoadCertificateFromString( crt->armouredPGPKey(), gpgid, error_string ); - - gpg_id = gpgid; - ssl_id = crt->sslid(); - - // now get all friends who declare this key ID to be the one needed to check connections, and clear their "skip_pgp_signature_validation" flag - - if(res) - { - mPeerMgr->notifyPgpKeyReceived(gpgid); - FriendsChanged(ssl_id,true); - } - - return res; -} -bool p3Peers::loadPgpKeyFromBinaryData( const unsigned char *bin_key_data,uint32_t bin_key_len, RsPgpId& gpg_id, std::string& error_string ) -{ - bool res = AuthPGP::LoadPGPKeyFromBinaryData( bin_key_data,bin_key_len, gpg_id, error_string ); - - if(res) - mPeerMgr->notifyPgpKeyReceived(gpg_id); - - return res; -} - -bool p3Peers::loadDetailsFromStringCert( const std::string &certstr, - RsPeerDetails &pd, - uint32_t& error_code ) -{ - Dbg3() << __PRETTY_FUNCTION__ << std::endl; - - auto certPtr = RsCertificate::fromString(certstr, error_code); - if(!certPtr) return false; - - RsCertificate& cert = *certPtr; - - if(!AuthPGP::getPgpDetailsFromBinaryBlock( cert.pgp_key(), cert.pgp_key_size(), pd.gpg_id, pd.name, pd.gpgSigners )) - return false; - - Dbg4() << __PRETTY_FUNCTION__ << " Parsing cert for sslid, location, ext " - << " and local address details. : " << certstr << std::endl; - - pd.id = cert.sslid(); - pd.location = cert.location_name_string(); - - pd.isOnlyGPGdetail = pd.id.isNull(); - pd.service_perm_flags = RS_NODE_PERM_DEFAULT; - - if (!cert.hidden_node_string().empty()) - { - pd.isHiddenNode = true; - - std::string domain; - uint16_t port; - if (splitAddressString(cert.hidden_node_string(), domain, port)) - { - pd.hiddenNodeAddress = domain; - pd.hiddenNodePort = port; - pd.hiddenType = mPeerMgr->hiddenDomainToHiddenType(domain); - } - } - else - { - pd.isHiddenNode = false; - pd.localAddr = cert.loc_ip_string(); - pd.localPort = cert.loc_port_us(); - pd.extAddr = cert.ext_ip_string(); - pd.extPort = cert.ext_port_us(); - pd.dyndns = cert.dns_string(); - for(const RsUrl& locator : cert.locators()) - pd.ipAddressList.push_back(locator.toString()); - } - - return true; -} - -bool p3Peers::cleanCertificate(const std::string &certstr, std::string &cleanCert,bool& is_short_format,uint32_t& error_code,RsPeerDetails& details) -{ - RsCertificate::Format format ; - - bool res = RsCertificate::cleanCertificate(certstr,cleanCert,format,error_code,true,details) ; - - if(format == RsCertificate::RS_CERTIFICATE_RADIX) - is_short_format = false; - else if(format == RsCertificate::RS_CERTIFICATE_SHORT_RADIX) - is_short_format = true; - else - return false ; - - return res; -} - -std::string p3Peers::saveCertificateToString(const RsPeerId &id) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::SaveCertificateToString() " << id; - std::cerr << std::endl; -#endif - if (id == AuthSSL::getAuthSSL()->OwnId()) { - return AuthSSL::getAuthSSL()->SaveOwnCertificateToString(); - } else { - return ""; - } -} - -bool p3Peers::signGPGCertificate(const RsPgpId &id, const std::string &gpg_passphrase) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::SignCertificate() " << id; - std::cerr << std::endl; -#endif - rsNotify->cachePgpPassphrase(gpg_passphrase); - rsNotify->setDisableAskPassword(true); - - bool res = AuthPGP::SignCertificateLevel0(id); - - rsNotify->clearPgpPassphrase(); - rsNotify->setDisableAskPassword(false); - - return res; -} - -bool p3Peers::trustGPGCertificate(const RsPgpId &id, uint32_t trustlvl) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::TrustCertificate() " << id; - std::cerr << std::endl; -#endif - return AuthPGP::TrustCertificate(id, trustlvl); -} - - /* Group Stuff */ -bool p3Peers::addGroup(RsGroupInfo &groupInfo) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::addGroup()" << std::endl; -#endif - - bool res = mPeerMgr->addGroup(groupInfo); - rsFiles->updateSinceGroupPermissionsChanged() ; - return res ; -} - -bool p3Peers::editGroup(const RsNodeGroupId &groupId, RsGroupInfo &groupInfo) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::editGroup()" << std::endl; -#endif - - bool res = mPeerMgr->editGroup(groupId, groupInfo); - rsFiles->updateSinceGroupPermissionsChanged() ; - - return res ; -} - -bool p3Peers::removeGroup(const RsNodeGroupId &groupId) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::removeGroup()" << std::endl; -#endif - - bool res = mPeerMgr->removeGroup(groupId); - rsFiles->updateSinceGroupPermissionsChanged() ; - return res ; -} - -bool p3Peers::getGroupInfoByName(const std::string& groupName, RsGroupInfo &groupInfo) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getGroupInfo()" << std::endl; -#endif - - return mPeerMgr->getGroupInfoByName(groupName, groupInfo); -} -bool p3Peers::getGroupInfo(const RsNodeGroupId &groupId, RsGroupInfo &groupInfo) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getGroupInfo()" << std::endl; -#endif - - return mPeerMgr->getGroupInfo(groupId, groupInfo); -} - -bool p3Peers::getGroupInfoList(std::list &groupInfoList) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::getGroupInfoList()" << std::endl; -#endif - - return mPeerMgr->getGroupInfoList(groupInfoList); -} - -bool p3Peers::assignPeerToGroup(const RsNodeGroupId &groupId, const RsPgpId& peerId, bool assign) -{ - std::list peerIds; - peerIds.push_back(peerId); - - return assignPeersToGroup(groupId, peerIds, assign); -} - -bool p3Peers::assignPeersToGroup(const RsNodeGroupId &groupId, const std::list &peerIds, bool assign) -{ -#ifdef P3PEERS_DEBUG - std::cerr << "p3Peers::assignPeersToGroup()" << std::endl; -#endif - - bool res = mPeerMgr->assignPeersToGroup(groupId, peerIds, assign); - rsFiles->updateSinceGroupPermissionsChanged() ; - - return res ; -} - -FileSearchFlags p3Peers::computePeerPermissionFlags(const RsPeerId& peer_ssl_id, - FileStorageFlags share_flags, - const std::list& directory_parent_groups) -{ - // We should be able to do that in O(1), using groups based on packs of bits. - // - // But for now, because the implementation of groups is not totally decided yet, we revert to this - // very simple algorithm. - // - - bool found = directory_parent_groups.empty() ; // by default, empty list means browsable by everyone. - RsPgpId pgp_id = getGPGId(peer_ssl_id) ; - - for(std::list::const_iterator it(directory_parent_groups.begin());it!=directory_parent_groups.end() && !found;++it) - { - RsGroupInfo info ; - if(!getGroupInfo(*it,info)) - { - std::cerr << "(EE) p3Peers::computePeerPermissionFlags: no group named " << *it << ": cannot get info." << std::endl; - continue ; - } - - found = found || (info.peerIds.find(pgp_id) != info.peerIds.end()) ; - - //for(std::set::const_iterator it2(info.peerIds.begin());it2!=info.peerIds.end() && !found;++it2) - // if(*it2 == pgp_id) - // found = true ; - } - - bool network_wide = (share_flags & DIR_FLAGS_ANONYMOUS_DOWNLOAD) ;//|| ( (share_flags & DIR_FLAGS_NETWORK_WIDE_GROUPS) && found) ; - bool browsable = (share_flags & DIR_FLAGS_BROWSABLE) && found ; - bool searchable = (share_flags & DIR_FLAGS_ANONYMOUS_SEARCH) ; - - FileSearchFlags final_flags ; - - if(network_wide) final_flags |= RS_FILE_HINTS_NETWORK_WIDE ; - if(browsable ) final_flags |= RS_FILE_HINTS_BROWSABLE ; - if(searchable ) final_flags |= RS_FILE_HINTS_SEARCHABLE ; - - return final_flags ; -} - -RsPeerDetails::RsPeerDetails() - :isOnlyGPGdetail(false), - name(""),email(""),location(""), - org(""),authcode(""), - trustLvl(0), validLvl(0),skip_pgp_signature_validation(false),ownsign(false), - hasSignedMe(false),accept_connection(false), - state(0),actAsServer(false), - connectPort(0), - isHiddenNode(false), - hiddenNodePort(0), - hiddenType(RS_HIDDEN_TYPE_NONE), - localAddr(""),localPort(0),extAddr(""),extPort(0),netMode(0),vs_disc(0), vs_dht(0), - lastConnect(0),lastUsed(0),connectState(0),connectStateString(""), - connectPeriod(0), - foundDHT(false), wasDeniedConnection(false), deniedTS(0), - linkType ( RS_NET_CONN_TRANS_TCP_UNKNOWN) {} - -RsGroupInfo::RsGroupInfo() : flag(0) {} - -ServicePermissionFlags p3Peers::servicePermissionFlags(const RsPeerId& ssl_id) -{ - return mPeerMgr->servicePermissionFlags(ssl_id) ; -} -ServicePermissionFlags p3Peers::servicePermissionFlags(const RsPgpId& gpg_id) -{ - return mPeerMgr->servicePermissionFlags(gpg_id) ; -} -void p3Peers::setServicePermissionFlags(const RsPgpId& gpg_id,const ServicePermissionFlags& flags) -{ - mPeerMgr->setServicePermissionFlags(gpg_id,flags) ; -} - -RsPeerStateChangedEvent::RsPeerStateChangedEvent(RsPeerId sslId) : - RsEvent(RsEventType::PEER_STATE_CHANGED), mSslId(sslId) {} - -RsPeers::~RsPeers() = default; -RsAuthSslConnectionAutenticationEvent::~RsAuthSslConnectionAutenticationEvent() = default; -RsConnectionEvent::~RsConnectionEvent() = default; diff --git a/libretroshare/src/rsserver/p3peers.h b/libretroshare/src/rsserver/p3peers.h deleted file mode 100644 index 91630e12d..000000000 --- a/libretroshare/src/rsserver/p3peers.h +++ /dev/null @@ -1,202 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3peers.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RETROSHARE_P3_PEER_INTERFACE_H -#define RETROSHARE_P3_PEER_INTERFACE_H -/* get OS-specific definitions for: - * struct sockaddr_storage - */ -#ifndef WINDOWS_SYS - #include -#else - #include -#endif - -#include "retroshare/rspeers.h" -#include "util/rsurl.h" -#include "util/rsdeprecate.h" -#include "util/rsdebug.h" - -class p3LinkMgr; -class p3PeerMgr; -class p3NetMgr; - - -class p3Peers: public RsPeers -{ -public: - - p3Peers(p3LinkMgr *lm, p3PeerMgr *pm, p3NetMgr *nm); - virtual ~p3Peers() {} - - /* Updates ... */ - virtual bool FriendsChanged(const RsPeerId &pid, bool add); - virtual bool OthersChanged(); - - /* Peer Details (Net & Auth) */ - virtual const RsPeerId& getOwnId() override; - - virtual bool haveSecretKey(const RsPgpId& gpg_id) override; - - virtual bool getOnlineList(std::list &ids) override; - virtual bool getFriendList(std::list &ids) override; - virtual bool getPeersCount( - uint32_t& peersCount, uint32_t& onlinePeersCount, - bool countLocations ) override; - - RS_DEPRECATED - virtual bool getPeerCount (unsigned int *friendCount, unsigned int *onlineCount, bool ssl) override; - - virtual bool isOnline(const RsPeerId &id) override; - virtual bool isFriend(const RsPeerId &id) override; - virtual bool isPgpFriend(const RsPgpId& pgpId) override; - - /// @see RsPeers - bool isSslOnlyFriend(const RsPeerId& sslId) override; - - RS_DEPRECATED_FOR(isPgpFriend) - virtual bool isGPGAccepted(const RsPgpId &gpg_id_is_friend) override; - - virtual std::string getGPGName(const RsPgpId &gpg_id) override; - virtual std::string getPeerName(const RsPeerId& ssl_or_gpg_id) override; - virtual bool getPeerDetails(const RsPeerId& ssl_or_gpg_id, RsPeerDetails &d) override; - - /* Using PGP Ids */ - virtual const RsPgpId& getGPGOwnId() override; - virtual RsPgpId getGPGId(const RsPeerId &ssl_id) override; - virtual bool isKeySupported(const RsPgpId& ids) override; - - /// @see RsPeers - bool getPgpFriendList(std::vector& pgpIds) override; - - RS_DEPRECATED_FOR(getPgpFriendList) - virtual bool getGPGAcceptedList(std::list &ids) override; - virtual bool getGPGSignedList(std::list &ids) override; - virtual bool getGPGValidList(std::list &ids) override; - virtual bool getGPGAllList(std::list &ids) override; - virtual bool getGPGDetails(const RsPgpId &id, RsPeerDetails &d) override; - virtual bool getAssociatedSSLIds(const RsPgpId& gpg_id, std::list &ids) override; - virtual bool gpgSignData(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen, std::string reason = "") override; - - virtual RsPgpId pgpIdFromFingerprint(const RsPgpFingerprint& fpr) override; - - /* Add/Remove Friends */ - virtual bool addFriend(const RsPeerId &ssl_id, const RsPgpId &gpg_id,ServicePermissionFlags flags = RS_NODE_PERM_DEFAULT) override; - - /// @see RsPeers - bool addSslOnlyFriend( - const RsPeerId& sslId, - const RsPgpId& pgp_id, - const RsPeerDetails& details = RsPeerDetails() ) override; - - virtual bool removeFriend(const RsPgpId& gpgid) override; - virtual bool removeFriendLocation(const RsPeerId& sslId) override; - - /* keyring management */ - virtual bool removeKeysFromPGPKeyring(const std::set &pgp_ids,std::string& backup_file,uint32_t& error_code) override; - - /* Network Stuff */ - virtual bool connectAttempt(const RsPeerId &id) override; - virtual bool setLocation(const RsPeerId &ssl_id, const std::string &location) override;//location is shown in the gui to differentiate ssl certs - virtual bool setHiddenNode(const RsPeerId &id, const std::string &hidden_node_address) override; - virtual bool setHiddenNode(const RsPeerId &id, const std::string &address, uint16_t port) override; - virtual bool isHiddenNode(const RsPeerId &id) override; - - virtual bool addPeerLocator(const RsPeerId &ssl_id, const RsUrl& locator) override; - virtual bool setLocalAddress(const RsPeerId &id, const std::string &addr, uint16_t port) override; - virtual bool setExtAddress(const RsPeerId &id, const std::string &addr, uint16_t port) override; - virtual bool setDynDNS(const RsPeerId &id, const std::string &dyndns) override; - virtual bool setNetworkMode(const RsPeerId &id, uint32_t netMode) override; - virtual bool setVisState(const RsPeerId &id, uint16_t vs_disc, uint16_t vs_dht) override; - - virtual bool getProxyServer(const uint32_t type, std::string &addr, uint16_t &port,uint32_t& status) override; - virtual bool setProxyServer(const uint32_t type, const std::string &addr, const uint16_t port) override; - virtual bool isProxyAddress(const uint32_t type, const sockaddr_storage &addr); - - virtual void getIPServersList(std::list& ip_servers) override; - virtual void getCurrentExtIPList(std::list& ip_list) override; - virtual void allowServerIPDetermination(bool) override; - virtual bool getAllowServerIPDetermination() override; - virtual bool resetOwnExternalAddressList() override; - - /* Auth Stuff */ - // Get the invitation (GPG cert + local/ext address + SSL id for the given peer) - virtual std::string GetRetroshareInvite(const RsPeerId& ssl_id = RsPeerId(), RetroshareInviteFlags invite_flags = RetroshareInviteFlags::DNS | RetroshareInviteFlags::CURRENT_IP ) override; - - RS_DEPRECATED /// @see RsPeers - std::string getPGPKey(const RsPgpId& pgp_id,bool include_signatures) override; - - virtual bool GetPGPBase64StringAndCheckSum(const RsPgpId& gpg_id,std::string& gpg_base64_string,std::string& gpg_base64_checksum); - - /// @see RsPeers - bool getShortInvite(std::string& invite, const RsPeerId& sslId = RsPeerId(), - RetroshareInviteFlags invite_flags = RetroshareInviteFlags::CURRENT_IP | RetroshareInviteFlags::DNS, - const std::string& baseUrl = "https://retroshare.me/" ) override; - - /// @see RsPeers - bool parseShortInvite(const std::string& invite, RsPeerDetails& details, uint32_t &err_code ) override; - - /// @see RsPeers::acceptInvite - virtual bool acceptInvite( - const std::string& invite, - ServicePermissionFlags flags = RS_NODE_PERM_DEFAULT ) override; - - virtual bool loadCertificateFromString(const std::string& cert, RsPeerId& ssl_id,RsPgpId& pgp_id, std::string& error_string) override; - virtual bool loadPgpKeyFromBinaryData( const unsigned char *bin_key_data,uint32_t bin_key_len, RsPgpId& gpg_id, std::string& error_string ) override; - virtual bool loadDetailsFromStringCert(const std::string &cert, RsPeerDetails &pd, uint32_t& error_code) override; - - virtual bool cleanCertificate(const std::string &certstr, std::string &cleanCert, bool &is_short_format, uint32_t& error_code, RsPeerDetails& details) override; - virtual std::string saveCertificateToString(const RsPeerId &id) override; - - virtual bool signGPGCertificate(const RsPgpId &id,const std::string& gpg_passphrase) override; - virtual bool trustGPGCertificate(const RsPgpId &id, uint32_t trustlvl) override; - - /* Group Stuff */ - virtual bool addGroup(RsGroupInfo &groupInfo) override; - virtual bool editGroup(const RsNodeGroupId &groupId, RsGroupInfo &groupInfo) override; - virtual bool removeGroup(const RsNodeGroupId &groupId) override; - virtual bool getGroupInfo(const RsNodeGroupId &groupId, RsGroupInfo &groupInfo) override; - virtual bool getGroupInfoByName(const std::string& groupName, RsGroupInfo& groupInfo) override; - virtual bool getGroupInfoList(std::list &groupInfoList) override; - virtual bool assignPeerToGroup(const RsNodeGroupId &groupId, const RsPgpId &peerId, bool assign) override; - virtual bool assignPeersToGroup(const RsNodeGroupId &groupId, const std::list& peerIds, bool assign) override; - - virtual FileSearchFlags computePeerPermissionFlags(const RsPeerId& peer_id, FileStorageFlags share_flags, const std::list &parent_groups) override; - - // service permission stuff - - virtual ServicePermissionFlags servicePermissionFlags(const RsPgpId& gpg_id) override; - virtual ServicePermissionFlags servicePermissionFlags(const RsPeerId & ssl_id) override; - virtual void setServicePermissionFlags(const RsPgpId& gpg_id,const ServicePermissionFlags& flags) override; - - virtual bool setPeerMaximumRates(const RsPgpId& pid,uint32_t maxUploadRate,uint32_t maxDownloadRate) override; - virtual bool getPeerMaximumRates(const RsPgpId& pid,uint32_t& maxUploadRate,uint32_t& maxDownloadRate) override; - virtual bool getPeerMaximumRates(const RsPeerId& pid,uint32_t& maxUploadRate,uint32_t& maxDownloadRate) override; -private: - - p3LinkMgr *mLinkMgr; - p3PeerMgr *mPeerMgr; - p3NetMgr *mNetMgr; - - RS_SET_CONTEXT_DEBUG_LEVEL(1) -}; - -#endif diff --git a/libretroshare/src/rsserver/p3serverconfig.cc b/libretroshare/src/rsserver/p3serverconfig.cc deleted file mode 100644 index c50eb2c89..000000000 --- a/libretroshare/src/rsserver/p3serverconfig.cc +++ /dev/null @@ -1,566 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3serverconfig.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include -#include "rsserver/p3serverconfig.h" -#include "services/p3bwctrl.h" - -#include "pqi/authgpg.h" -#include "pqi/authssl.h" - -RsServerConfig *rsConfig = NULL; - -static const std::string pqih_ftr("PQIH_FTR"); - -#define DEFAULT_DOWNLOAD_KB_RATE (10000.0) -#define DEFAULT_UPLOAD_KB_RATE (10000.0) - -#define MIN_MINIMAL_RATE (5.0) - - -p3ServerConfig::p3ServerConfig(p3PeerMgr *peerMgr, p3LinkMgr *linkMgr, p3NetMgr *netMgr, pqihandler *pqih, p3GeneralConfig *genCfg) -:configMtx("p3ServerConfig") -{ - mPeerMgr = peerMgr; - mLinkMgr = linkMgr; - mNetMgr = netMgr; - mPqiHandler = pqih; - - mGeneralConfig = genCfg; - - RsStackMutex stack(configMtx); /******* LOCKED MUTEX *****/ - - mUserLevel = RsConfigUserLvl::NEW; /* START LEVEL */ - mRateDownload = DEFAULT_DOWNLOAD_KB_RATE; - mRateUpload = DEFAULT_UPLOAD_KB_RATE; - - mOpMode = RsOpMode::FULL; - - rsConfig = this; -} - - -p3ServerConfig::~p3ServerConfig() -{ - return; -} - - -void p3ServerConfig::load_config() -{ - /* get the real bandwidth setting from GeneralConfig */ - std::string rates = mGeneralConfig -> getSetting(pqih_ftr); - - float mri, mro; - if (2 == sscanf(rates.c_str(), "%f %f", &mri, &mro)) - { - RsStackMutex stack(configMtx); /******* LOCKED MUTEX *****/ - - mRateDownload = mri; - mRateUpload = mro; - } - else - { - RsStackMutex stack(configMtx); /******* LOCKED MUTEX *****/ - - mRateDownload = DEFAULT_DOWNLOAD_KB_RATE; - mRateUpload = DEFAULT_UPLOAD_KB_RATE; - } - - /* enable operating mode */ - RsOpMode opMode = getOperatingMode(); - switchToOperatingMode(opMode); -} - - -#define RS_CONFIG_ADVANCED_STRING "AdvMode" - -bool p3ServerConfig::findConfigurationOption(uint32_t key, std::string &keystr) -{ - bool found = false; - switch(key) - { - case RS_CONFIG_ADVANCED: - keystr = RS_CONFIG_ADVANCED_STRING; - found = true; - break; - } - return found; -} - - -bool p3ServerConfig::getConfigurationOption(uint32_t key, std::string &opt) -{ - std::string strkey; - if (!findConfigurationOption(key, strkey)) - { - std::cerr << "p3ServerConfig::getConfigurationOption() OPTION NOT VALID: " << key; - std::cerr << std::endl; - return false; - } - - opt = mGeneralConfig->getSetting(strkey); - return true; -} - - -bool p3ServerConfig::setConfigurationOption(uint32_t key, const std::string &opt) -{ - std::string strkey; - if (!findConfigurationOption(key, strkey)) - { - std::cerr << "p3ServerConfig::setConfigurationOption() OPTION NOT VALID: " << key; - std::cerr << std::endl; - return false; - } - - mGeneralConfig->setSetting(strkey, opt); - return true; -} - - /* From RsIface::RsConfig */ -int p3ServerConfig::getConfigNetStatus(RsConfigNetStatus &status) -{ - status.ownId = AuthSSL::getAuthSSL()->OwnId(); - status.ownName = AuthPGP::getPgpOwnName(); - - // Details from PeerMgr. - peerState pstate; - mPeerMgr->getOwnNetStatus(pstate); - - status.localAddr = sockaddr_storage_iptostring(pstate.localaddr); - status.localPort = sockaddr_storage_port(pstate.localaddr); - - status.extAddr = sockaddr_storage_iptostring(pstate.serveraddr); - status.extPort = sockaddr_storage_port(pstate.serveraddr); - status.extDynDns = pstate.dyndns; - - status.firewalled = true; - status.forwardPort = true; - - /* update network configuration */ - pqiNetStatus nstatus; - mNetMgr->getNetStatus(nstatus); - - status.netUpnpOk = nstatus.mUpnpOk; - status.netStunOk = false; - status.netExtAddressOk = nstatus.mExtAddrOk; - - status.netDhtOk = nstatus.mDhtOk; - status.netDhtNetSize = nstatus.mDhtNetworkSize; - status.netDhtRsNetSize = nstatus.mDhtRsNetworkSize; - - /* update DHT/UPnP status */ - status.uPnPState = mNetMgr->getUPnPState(); - status.uPnPActive = mNetMgr->getUPnPEnabled(); - status.DHTActive = mNetMgr->getDHTEnabled(); - - return 1; -} - -int p3ServerConfig::getConfigStartup(RsConfigStartup &/*params*/) -{ - //status.promptAtBoot = true; /* popup the password prompt */ - return 0; -} - -/***** for RsConfig -> p3BandwidthControl ****/ - -int p3ServerConfig::getTrafficInfo(std::list& out_lst,std::list& in_lst) -{ - - if (rsBandwidthControl) - return rsBandwidthControl->ExtractTrafficInfo(out_lst,in_lst); - else - return 0 ; -} - -int p3ServerConfig::getTotalBandwidthRates(RsConfigDataRates &rates) -{ - if (rsBandwidthControl) - { - return rsBandwidthControl->getTotalBandwidthRates(rates); - } - return 0; -} - -int p3ServerConfig::getAllBandwidthRates(std::map &ratemap) -{ - if (rsBandwidthControl) - { - return rsBandwidthControl->getAllBandwidthRates(ratemap); - } - return 0; -} - - - /* From RsInit */ - -std::string p3ServerConfig::RsConfigDirectory() -{ - return std::string(); -} - -std::string p3ServerConfig::RsConfigKeysDirectory() -{ - return std::string(); -} - - -std::string p3ServerConfig::RsProfileConfigDirectory() -{ - return std::string(); -} - -bool p3ServerConfig::getStartMinimised() -{ - return 0; -} - -std::string p3ServerConfig::getRetroShareLink() -{ - return std::string(); -} - - -bool p3ServerConfig::getAutoLogin() -{ - return 0; -} - -void p3ServerConfig::setAutoLogin(bool /*autoLogin*/) -{ - return; -} - -bool p3ServerConfig::RsClearAutoLogin() -{ - return 0; -} - - -std::string p3ServerConfig::getRetroshareDataDirectory() -{ - return std::string(); -} - - /* New Stuff */ - -RsConfigUserLvl p3ServerConfig::getUserLevel() -{ - RsConfigUserLvl userLevel = RsConfigUserLvl::NEW; - { - RsStackMutex stack(configMtx); /******* LOCKED MUTEX *****/ - userLevel = mUserLevel; - } - - switch(userLevel) - { - case RsConfigUserLvl::OVERRIDE: - break; - -#define MIN_BASIC_FRIENDS 2 - - // FALL THROUGH EVERYTHING. - default: - case RsConfigUserLvl::NEW: - { - - if (mPeerMgr->getFriendCount(true, false) > MIN_BASIC_FRIENDS) - { - userLevel = RsConfigUserLvl::BASIC; - } - } - /* fallthrough */ - case RsConfigUserLvl::BASIC: - { - /* check that we have some lastConnect > 0 */ - if (mPeerMgr->haveOnceConnected()) - { - userLevel = RsConfigUserLvl::CASUAL; - } - } - /* fallthrough */ - case RsConfigUserLvl::CASUAL: - case RsConfigUserLvl::POWER: - - { - /* check that the firewall is open */ - - RsNetworkMode netMode = mNetMgr->getNetworkMode(); - RsNatHoleMode firewallMode = mNetMgr->getNatHoleMode(); - - if ((RsNetworkMode::EXTERNALIP == netMode) || - ((RsNetworkMode::BEHINDNAT == netMode) && - (RsNatHoleMode::UPNP == firewallMode || - (RsNatHoleMode::NATPMP == firewallMode) || - (RsNatHoleMode::FORWARDED == firewallMode)))) - { - userLevel = RsConfigUserLvl::POWER; - } - } - break; /* for all */ - } - - { - RsStackMutex stack(configMtx); /******* LOCKED MUTEX *****/ - mUserLevel = userLevel; - } - - return userLevel; -} - - -RsNetState p3ServerConfig::getNetState() -{ - return mNetMgr->getNetStateMode(); -} - -RsNetworkMode p3ServerConfig::getNetworkMode() -{ - return mNetMgr->getNetworkMode(); -} - -RsNatTypeMode p3ServerConfig::getNatTypeMode() -{ - return mNetMgr->getNatTypeMode(); -} - -RsNatHoleMode p3ServerConfig::getNatHoleMode() -{ - return mNetMgr->getNatHoleMode(); -} - -RsConnectModes p3ServerConfig::getConnectModes() -{ - return mNetMgr->getConnectModes(); -} - - /* Operating Mode */ -#define RS_CONFIG_OPERATING_STRING "OperatingMode" - -RsOpMode p3ServerConfig::getOperatingMode() -{ -#ifdef SAVE_OPERATING_MODE - std::string modestr = mGeneralConfig->getSetting(RS_CONFIG_OPERATING_STRING); - uint32_t mode = RsOpMode::FULL; - - if (modestr == "FULL") - { - mode = RsOpMode::FULL; - } - else if (modestr == "NOTURTLE") - { - mode = RsOpMode::NOTURTLE; - } - else if (modestr == "GAMING") - { - mode = RsOpMode::GAMING; - } - else if (modestr == "MINIMAL") - { - mode = RsOpMode::MINIMAL; - } - return mode; -#else - RsStackMutex stack(configMtx); /******* LOCKED MUTEX *****/ - return mOpMode; -#endif -} - - -bool p3ServerConfig::setOperatingMode(RsOpMode opMode) -{ -#ifdef SAVE_OPERATING_MODE - std::string modestr = "FULL"; - switch(opMode) - { - case RsOpMode::FULL: - modestr = "FULL"; - break; - case RsOpMode::NOTURTLE: - modestr = "NOTURTLE"; - - break; - case RsOpMode::GAMING: - modestr = "GAMING"; - - break; - case RsOpMode::MINIMAL: - modestr = "MINIMAL"; - break; - } - mGeneralConfig->setSetting(RS_CONFIG_OPERATING_STRING, modestr); -#else - { - RsStackMutex stack(configMtx); /******* LOCKED MUTEX *****/ - mOpMode = opMode; - } -#endif - return switchToOperatingMode(opMode); -} - -bool p3ServerConfig::setOperatingMode(const std::string &opModeStr) -{ - RsOpMode opMode = RsOpMode::FULL; - std::string upper; - stringToUpperCase(opModeStr, upper); - - if (upper == "NOTURTLE") - { - opMode = RsOpMode::NOTURTLE; - } - else if (upper == "GAMING") - { - opMode = RsOpMode::GAMING; - } - else if (upper == "MINIMAL") - { - opMode = RsOpMode::MINIMAL; - } - else // "FULL" by default - { - opMode = RsOpMode::FULL; - } - - return setOperatingMode(opMode); -} - -bool p3ServerConfig::switchToOperatingMode(RsOpMode opMode) -{ - float dl_rate = 0; - float ul_rate = 0; - bool turtle_enabled = true; - - { - RsStackMutex stack(configMtx); /******* LOCKED MUTEX *****/ - dl_rate = mRateDownload; - ul_rate = mRateUpload; - } - - std::cerr << "p3ServerConfig::switchToOperatingMode(" << static_cast::type>(opMode) << ")"; - std::cerr << std::endl; - - switch (opMode) - { - default: - case RsOpMode::FULL: - /* switch on all transfers */ - /* 100% bandwidth */ - /* switch on popups, enable hashing */ - //setMaxRate(true, mri); // In / Download - //setMaxRate(false, mro); // Out / Upload. - turtle_enabled = true; - break; - case RsOpMode::NOTURTLE: - /* switch on all transfers - except turtle, enable hashing */ - /* 100% bandwidth */ - /* switch on popups, enable hashing */ - turtle_enabled = false; - - break; - case RsOpMode::GAMING: - /* switch on all transfers */ - /* reduce bandwidth to 25% */ - /* switch off popups, enable hashing */ - turtle_enabled = true; - - dl_rate *= 0.25; - ul_rate *= 0.25; - break; - case RsOpMode::MINIMAL: - /* switch off all transfers */ - /* reduce bandwidth to 10%, but make sure there is enough for VoIP */ - /* switch on popups, enable hashing */ - - turtle_enabled = false; - - dl_rate *= 0.10; - ul_rate *= 0.10; - if (dl_rate < MIN_MINIMAL_RATE) - { - dl_rate = MIN_MINIMAL_RATE; - } - if (ul_rate < MIN_MINIMAL_RATE) - { - ul_rate = MIN_MINIMAL_RATE; - } - - break; - } - - if (mPqiHandler) - { - mPqiHandler -> setMaxRate(true, dl_rate); - mPqiHandler -> setMaxRate(false, ul_rate); - - std::cerr << "p3ServerConfig::switchToOperatingMode() D/L: " << dl_rate << " U/L: " << ul_rate; - std::cerr << std::endl; - - } - - std::cerr << "p3ServerConfig::switchToOperatingMode() Turtle Mode: " << turtle_enabled; - std::cerr << std::endl; - - rsTurtle->setSessionEnabled(turtle_enabled); - return true; -} - -/* handle data rates. - * Mutex must be handled at the lower levels: TODO */ - -int p3ServerConfig::SetMaxDataRates( int downKb, int upKb ) /* in kbrates */ -{ - char line[512]; - - { - RsStackMutex stack(configMtx); /******* LOCKED MUTEX *****/ - mRateDownload = downKb; - mRateUpload = upKb; - sprintf(line, "%f %f", mRateDownload, mRateUpload); - } - mGeneralConfig->setSetting(pqih_ftr, std::string(line)); - - load_config(); // load and setup everything. - return 1; -} - - -int p3ServerConfig::GetMaxDataRates( int &inKb, int &outKb ) /* in kbrates */ -{ - RsStackMutex stack(configMtx); /******* LOCKED MUTEX *****/ - - inKb = mRateDownload; - outKb = mRateUpload; - return 1; -} - -int p3ServerConfig::GetCurrentDataRates( float &inKb, float &outKb ) -{ - mPqiHandler->getCurrentRates(inKb, outKb); - return 1; -} - -int p3ServerConfig::GetTrafficSum(uint64_t &inb, uint64_t &outb ) -{ - mPqiHandler->GetTraffic(inb, outb); - return 1; -} diff --git a/libretroshare/src/rsserver/p3serverconfig.h b/libretroshare/src/rsserver/p3serverconfig.h deleted file mode 100644 index c197aa1b0..000000000 --- a/libretroshare/src/rsserver/p3serverconfig.h +++ /dev/null @@ -1,118 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3serverconfig.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef LIBRETROSHARE_CONFIG_IMPLEMENTATION_H -#define LIBRETROSHARE_CONFIG_IMPLEMENTATION_H - -#include "retroshare/rsconfig.h" -#include "pqi/p3peermgr.h" -#include "pqi/p3linkmgr.h" -#include "pqi/p3netmgr.h" -#include "pqi/p3cfgmgr.h" -#include "pqi/pqihandler.h" - - -#define RS_CONFIG_ADVANCED_STRING "AdvMode" - - - -class p3ServerConfig: public RsServerConfig -{ - public: - - p3ServerConfig(p3PeerMgr *peerMgr, p3LinkMgr *linkMgr, p3NetMgr *netMgr, pqihandler *pqih, p3GeneralConfig *genCfg); -virtual ~p3ServerConfig(); - - void load_config(); - - /* From RsIface::RsConfig */ - -virtual int getConfigNetStatus(RsConfigNetStatus &status); -virtual int getConfigStartup(RsConfigStartup ¶ms); -//virtual int getConfigDataRates(RsConfigDataRates ¶ms); - - /***** for RsConfig -> p3BandwidthControl ****/ - -virtual int getTotalBandwidthRates(RsConfigDataRates &rates); -virtual int getAllBandwidthRates(std::map &ratemap); - virtual int getTrafficInfo(std::list& out_lst, std::list &in_lst) ; - - /* From RsInit */ - -virtual std::string RsConfigDirectory(); -virtual std::string RsConfigKeysDirectory(); - -virtual std::string RsProfileConfigDirectory(); -virtual bool getStartMinimised(); -virtual std::string getRetroShareLink(); - -virtual bool getAutoLogin(); -virtual void setAutoLogin(bool autoLogin); -virtual bool RsClearAutoLogin(); - -virtual std::string getRetroshareDataDirectory(); - - /* New Stuff */ - -virtual RsConfigUserLvl getUserLevel(); - -virtual RsNetState getNetState(); -virtual RsNetworkMode getNetworkMode(); -virtual RsNatTypeMode getNatTypeMode(); -virtual RsNatHoleMode getNatHoleMode(); -virtual RsConnectModes getConnectModes(); - -virtual bool getConfigurationOption(uint32_t key, std::string &opt); -virtual bool setConfigurationOption(uint32_t key, const std::string &opt); - - /* Operating Mode */ -virtual RsOpMode getOperatingMode(); -virtual bool setOperatingMode(RsOpMode opMode); -virtual bool setOperatingMode(const std::string &opModeStr); - -virtual int SetMaxDataRates( int downKb, int upKb ); -virtual int GetMaxDataRates( int &downKb, int &upKb ); -virtual int GetCurrentDataRates( float &inKb, float &outKb ); -virtual int GetTrafficSum( uint64_t &inb, uint64_t &outb ); - -/********************* ABOVE is RsConfig Interface *******/ - - private: - -bool switchToOperatingMode(RsOpMode opMode); - -bool findConfigurationOption(uint32_t key, std::string &keystr); - - p3PeerMgr *mPeerMgr; - p3LinkMgr *mLinkMgr; - p3NetMgr *mNetMgr; - pqihandler *mPqiHandler; - p3GeneralConfig *mGeneralConfig; - - RsMutex configMtx; - RsConfigUserLvl mUserLevel; // store last one... will later be a config Item too. - float mRateDownload; - float mRateUpload; - - RsOpMode mOpMode; -}; - -#endif diff --git a/libretroshare/src/rsserver/p3status.cc b/libretroshare/src/rsserver/p3status.cc deleted file mode 100644 index 4185e6802..000000000 --- a/libretroshare/src/rsserver/p3status.cc +++ /dev/null @@ -1,53 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3status.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Chris Evi-Parker. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "p3status.h" -#include "services/p3statusservice.h" - -p3Status::p3Status(p3StatusService* statusSrv) - : mStatusSrv(statusSrv) { - - -} - -p3Status::~p3Status(){ - return; -} - -bool p3Status::getOwnStatus(StatusInfo& statusInfo){ - - return mStatusSrv->getOwnStatus(statusInfo); -} - -bool p3Status::getStatusList(std::list& statusInfo){ - - return mStatusSrv->getStatusList(statusInfo); -} - -bool p3Status::getStatus(const RsPeerId &id, StatusInfo &statusInfo) -{ - return mStatusSrv->getStatus(id, statusInfo); -} - -bool p3Status::sendStatus(const RsPeerId &id, uint32_t status){ - - return mStatusSrv->sendStatus(id, status); -} diff --git a/libretroshare/src/rsserver/p3status.h b/libretroshare/src/rsserver/p3status.h deleted file mode 100644 index a6ae941f0..000000000 --- a/libretroshare/src/rsserver/p3status.h +++ /dev/null @@ -1,53 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: p3status.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Chris Evi-Parker. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_P3STATUS_INTERFACE_H -#define RS_P3STATUS_INTERFACE_H - -#include "retroshare/rsstatus.h" - - -class p3StatusService; - -//! Implements abstract interface rsStatus -/*! - * Interfaces with p3StatusService - */ -class p3Status : public RsStatus -{ -public: - - explicit p3Status(p3StatusService* statusSrv); - virtual ~p3Status(); - - - virtual bool getOwnStatus(StatusInfo& statusInfo); - virtual bool getStatusList(std::list& statusInfo); - virtual bool getStatus(const RsPeerId &id, StatusInfo &statusInfo); - virtual bool sendStatus(const RsPeerId &id, uint32_t status); - -private: - - p3StatusService* mStatusSrv; - -}; - -#endif /* RS_P3STATUS_INTERFACE_H */ diff --git a/libretroshare/src/rsserver/rsaccounts.cc b/libretroshare/src/rsserver/rsaccounts.cc deleted file mode 100644 index 5d848571a..000000000 --- a/libretroshare/src/rsserver/rsaccounts.cc +++ /dev/null @@ -1,1487 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: rsaccounts.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013-2014 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -/********************************************************************* - * Libretroshare interface declared in rsaccounts.h. - * external interface in rsinit.h RsAccounts namespace. - * - */ - -#ifdef WINDOWS_SYS -#include "util/rswin.h" -#endif // WINDOWS_SYS - -#include -#include -#include -#include - -#include "retroshare/rsinit.h" -#include "rsaccounts.h" -#include "util/rsdebug.h" -#include "util/rsdir.h" -#include "util/rsstring.h" -#include "util/folderiterator.h" - -#include "pqi/authssl.h" -#include "pqi/sslfns.h" -#include "pqi/authgpg.h" - -#include - -#ifdef __ANDROID__ -# include "rs_android/rsjni.hpp" -# include "rs_android/retroshareserviceandroid.hpp" -#endif - -// Global singleton declaration of data. -RsAccountsDetail* RsAccounts::rsAccountsDetails = nullptr; - -/* Uses private class - so must be hidden */ -static bool checkAccount(const std::string &accountdir, AccountDetails &account,std::map >& unsupported_keys); - -AccountDetails::AccountDetails() - :mSslId(""), mAccountDir(""), mPgpId(""), mPgpName(""), mPgpEmail(""), - mLocation(""), mIsHiddenLoc(false), mFirstRun(false) -{ - return; -} - -RsAccountsDetail::RsAccountsDetail() : mAccountsLocked(false), mPreferredId("") -{} - -bool RsAccountsDetail::loadAccounts() -{ - int failing_accounts ; -#warning we might need some switch here for hidden nodes only - getAvailableAccounts(mAccounts,failing_accounts,mUnsupportedKeys,false); - - loadPreferredAccount(); - checkPreferredId(); - - if(failing_accounts > 0 && mAccounts.empty()) - return false; - - return true; -} - -bool RsAccountsDetail::lockPreferredAccount() -{ - if (checkPreferredId()) - { - mAccountsLocked = true; - return true; - } - - return false; -} - -void RsAccountsDetail::unlockPreferredAccount() -{ - mAccountsLocked = false; -} - -bool RsAccountsDetail::checkAccountDirectory() -{ - if (!checkPreferredId()) - { - return false; - } - - return setupAccount(getCurrentAccountPathAccountDirectory()); -} - -#warning we need to clean that up. Login should only ask for a SSL id, instead of a std::string. - -bool RsAccountsDetail::selectAccountByString(const std::string &prefUserString) -{ - if (mAccountsLocked) - { - std::cerr << "RsAccountsDetail::selectAccountByString() ERROR Accounts Locked"; - std::cerr << std::endl; - return false; - } - - // try both. - // - RsPeerId ssl_id(prefUserString) ; - RsPgpId pgp_id(prefUserString) ; - - std::cerr << "RsAccountsDetail::selectAccountByString(" << prefUserString << ")" << std::endl; - - //bool pgpNameFound = false; - std::map::const_iterator it; - for(it = mAccounts.begin() ; it!= mAccounts.end() ; ++it) - { - std::cerr << "\tChecking account (pgpid = " << it->second.mPgpId; - std::cerr << ", name=" << it->second.mPgpName << ", sslId="; - std::cerr << it->second.mSslId << ")" << std::endl; - - if(prefUserString == it->second.mPgpName || pgp_id == it->second.mPgpId || ssl_id == it->second.mSslId) - { - mPreferredId = it->second.mSslId; - //pgpNameFound = true; - - std::cerr << "Account selected: " << ssl_id << std::endl; - - return true; - } - } - std::cerr << "No suitable candidate found." << std::endl; - return false; -} - - -bool RsAccountsDetail::selectId(const RsPeerId& preferredId) -{ - - if (mAccountsLocked) - { - std::cerr << "RsAccountsDetail::selectId() ERROR Accounts Locked"; - std::cerr << std::endl; - return false; - } - - std::map::const_iterator it; - it = mAccounts.find(preferredId); - - if (it != mAccounts.end()) - { - mPreferredId = preferredId; - return true; - } - else - { - return false; - } -} - - -bool RsAccountsDetail::checkPreferredId() -{ - std::map::const_iterator it; - it = mAccounts.find(mPreferredId); - - if (it != mAccounts.end()) - { - return true; - } - else - { - mPreferredId.clear(); - return false; - } -} - -// initial configuration bootstrapping... - -const std::string kPathPGPDirectory = "pgp"; -const std::string kPathKeyDirectory = "keys"; -const std::string kPathConfigDirectory = "config"; - -const std::string kFilenamePreferredAccount = "default_cert_06.txt"; -const std::string kFilenameKey = "user_pk.pem"; -const std::string kFilenameCert = "user_cert.pem"; -const std::string kFilenameLocation = "location_name.txt"; - - -/********************************************************************* - * Directories... based on current PreferredId. - */ - -std::string RsAccountsDetail::PathPGPDirectory() -{ - return mBaseDirectory + "/" + kPathPGPDirectory; -} - - -std::string RsAccountsDetail::PathBaseDirectory() -{ - if(mBaseDirectory.empty()) defaultBaseDirectory(); - return mBaseDirectory; -} - - -std::string RsAccountsDetail::getCurrentAccountPathAccountDirectory() -{ - std::string path; - - std::map::const_iterator it; - it = mAccounts.find(mPreferredId); - if (it == mAccounts.end()) - { - return path; - } - - path = mBaseDirectory + "/"; - path += it->second.mAccountDir; - return path; -} - -std::string RsAccountsDetail::getCurrentAccountPathAccountKeysDirectory() -{ - std::string path = getCurrentAccountPathAccountDirectory(); - if (path.empty()) - { - return path; - } - - path += "/" + kPathKeyDirectory; - return path; -} - -std::string RsAccountsDetail::getCurrentAccountPathKeyFile() -{ - std::string path = getCurrentAccountPathAccountKeysDirectory(); - if (path.empty()) - { - return path; - } - - path += "/" + kFilenameKey; - return path; -} - -std::string RsAccountsDetail::getCurrentAccountPathCertFile() -{ - std::string path = getCurrentAccountPathAccountKeysDirectory(); - if (path.empty()) - { - return path; - } - path += "/" + kFilenameCert; - return path; -} - -std::string RsAccountsDetail::getCurrentAccountLocationName() -{ - std::map::const_iterator it; - it = mAccounts.find(mPreferredId); - if (it == mAccounts.end()) - { - return ""; - } - return it->second.mLocation; -} - - -/********************************************************************* - * Setup Base Directories. - * - */ - -bool RsAccountsDetail::setupBaseDirectory(std::string alt_basedir) -{ - if (alt_basedir.empty()) - { - if (!defaultBaseDirectory()) - { - std::cerr << "RsAccounts::setupBaseDirectory() Cannot find defaultBaseDirectory"; - std::cerr << std::endl; - return false; - } - } - else - { - mBaseDirectory = alt_basedir; - } - - /* Check for trailing '/' */ - if (!mBaseDirectory.empty()) - { - char lastChar = *mBaseDirectory.rbegin(); - if (lastChar == '/' -#ifdef WINDOWS_SYS - || lastChar == '\\' -#endif - ) - { - mBaseDirectory.erase(mBaseDirectory.end() - 1); - } - } - - if (!RsDirUtil::checkCreateDirectory(mBaseDirectory)) - { - std::cerr << "RsAccounts::setupBaseDirectory() Cannot Create BaseConfig Dir:" << mBaseDirectory; - std::cerr << std::endl; - return false ; - } - return true ; -} - - -bool RsAccountsDetail::defaultBaseDirectory() -{ - std::string basedir; - -#ifdef WINDOWS_SYS - if (RsInit::isPortable()) - { - // use directory "Data" in portable version - basedir = "Data"; - } - else - { - wchar_t *wh = _wgetenv(L"APPDATA"); - std::string h; - librs::util::ConvertUtf16ToUtf8(std::wstring(wh), h); - if (h.empty()) - { - // generating default - std::cerr << "defaultBaseDirectory() Error: "; - std::cerr << " getEnv Error --Win95/98?"; - std::cerr << std::endl; - basedir="C:\\Retro"; - } - else - { - basedir = h; - } - - if (!RsDirUtil::checkCreateDirectory(basedir)) - { - std::cerr << "defaultBaseDirectory() Error: "; - std::cerr << "Cannot Create BaseConfig Dir : " << basedir << std::endl; - return false ; - } - basedir += "\\RetroShare"; - } -#elif defined (__ANDROID__) // def WINDOWS_SYS - - struct ApplicationInfo - { - static constexpr auto Name() - { return "android/content/pm/ApplicationInfo"; } - }; - - auto uenv = jni::GetAttachedEnv(RsJni::getVM()); - JNIEnv& env = *uenv; - auto androidContext = RetroShareServiceAndroid::getAndroidContext(env); - auto& contextClass = - jni::Class::Singleton(env); - - auto& applicationInfoClass = jni::Class::Singleton(env); - - auto getApplicationInfo = - contextClass.GetMethod ()>( - env, "getApplicationInfo" ); - - auto applicationInfo = androidContext.Call(env, getApplicationInfo); - - auto dataDirField = jni::Field( - env, applicationInfoClass, "dataDir" ); - - jni::Local dataDir = applicationInfo.Get( - env, dataDirField ); - - basedir = jni::Make(env, dataDir) + "/.retroshare/"; - -#else // def WINDOWS_SYS, if defined (__ANDROID__) - // unix: homedir + /.retroshare - char* h = getenv("HOME"); - if(h == nullptr) - { - RS_ERR("cannot determine $HOME dir"); - return false ; - } - - basedir = h; - basedir += "/.retroshare"; -#endif // def WINDOWS_SYS - - /* store to class variable */ - mBaseDirectory = basedir; - - RS_INFO(mBaseDirectory); - return true; -} - - -bool RsAccountsDetail::loadPreferredAccount() -{ - std::string initfile = mBaseDirectory + "/"; - initfile += kFilenamePreferredAccount; - - // open and read in the lines. - FILE *ifd = RsDirUtil::rs_fopen(initfile.c_str(), "r"); - char path[1024]; - int i; - - if (ifd != NULL) - { - if (NULL != fgets(path, 1024, ifd)) - { - for(i = 0; (path[i] != '\0') && (path[i] != '\n'); i++) ; - path[i] = '\0'; - - // Store PreferredId. - mPreferredId = RsPeerId(std::string(path)); - - if(mPreferredId.isNull()) - { - fclose(ifd); - return false ; - } - } - fclose(ifd); - return true; - } - return false; -} - -bool RsAccountsDetail::storePreferredAccount() -{ - // Check for config file. - std::string initfile = mBaseDirectory + "/"; - initfile += kFilenamePreferredAccount; - - // open and read in the lines. - FILE *ifd = RsDirUtil::rs_fopen(initfile.c_str(), "w"); - - if (ifd != NULL) - { - fprintf(ifd, "%s\n", mPreferredId.toStdString().c_str()); - fclose(ifd); - - std::cerr << "Creating Init File: " << initfile << std::endl; - std::cerr << "\tId: " << mPreferredId << std::endl; - - return true; - } - std::cerr << "Failed To Create Init File: " << initfile << std::endl; - return false; -} - - -/********************************************************************* - * Accounts - * - */ - -bool RsAccountsDetail::getCurrentAccountId(RsPeerId &id) -{ - id = mPreferredId; - return (!mPreferredId.isNull()); -} - -bool RsAccountsDetail::getAccountIds(std::list &ids) -{ - std::map::iterator it; -#ifdef DEBUG_ACCOUNTS - std::cerr << "getAccountIds:" << std::endl; -#endif - - for(it = mAccounts.begin(); it != mAccounts.end(); ++it) - { -#ifdef DEBUG_ACCOUNTS - std::cerr << "SSL Id: " << it->second.mSslId << " PGP Id " << it->second.mPgpId; - std::cerr << " PGP Name: " << it->second.mPgpName; - std::cerr << " PGP Email: " << it->second.mPgpEmail; - std::cerr << " Location: " << it->second.mLocation; - std::cerr << std::endl; -#endif - - ids.push_back(it->first); - } - return true; -} - - -bool RsAccountsDetail::getCurrentAccountDetails(const RsPeerId &id, - RsPgpId &gpgId, std::string &gpgName, - std::string &gpgEmail, std::string &location) -{ - std::map::iterator it; - it = mAccounts.find(id); - if (it != mAccounts.end()) - { - gpgId = it->second.mPgpId; - gpgName = it->second.mPgpName; - gpgEmail = it->second.mPgpEmail; - location = it->second.mLocation; - return true; - } - return false; -} - -bool RsAccountsDetail::getCurrentAccountOptions(bool &ishidden,bool& isautotor, bool &isFirstTimeRun) -{ - std::map::iterator it; - it = mAccounts.find(mPreferredId); - if (it != mAccounts.end()) - { - ishidden = it->second.mIsHiddenLoc; - isFirstTimeRun = it->second.mFirstRun; - isautotor = it->second.mIsAutoTor; - - return true; - } - return false; -} - - -/* directories with valid certificates in the expected location */ -bool RsAccountsDetail::getAvailableAccounts(std::map &accounts,int& failing_accounts,std::map >& unsupported_keys,bool hidden_only) -{ - failing_accounts = 0 ; - /* get the directories */ - std::list directories; - std::list::iterator it; - - std::cerr << "RsAccounts::getAvailableAccounts()"; - std::cerr << std::endl; - - /* now iterate through the directory... - * directories - flags as old, - * files checked to see if they have changed. (rehashed) - */ - - /* check for the dir existance */ - librs::util::FolderIterator dirIt(mBaseDirectory,false); - - if (!dirIt.isValid()) - { - std::cerr << "Cannot Open Base Dir - No Available Accounts" << std::endl; - return false ; - } - - struct stat64 buf; - - for(;dirIt.isValid();dirIt.next()) - { - /* check entry type */ - std::string fname = dirIt.file_name(); - std::string fullname = mBaseDirectory + "/" + fname; -#ifdef FIM_DEBUG - std::cerr << "calling stats on " << fullname <length() != 32 + 6) - { - std::cerr << "getAvailableAccounts() Skipping Invalid sized dir: " << *it << std::endl; - continue; - } - - std::string prefix = (*it).substr(0, 6); - std::string lochex = (*it).substr(6); // rest of string. - - bool hidden_location = false; - bool auto_tor = false; - bool valid_prefix = false; - - if (prefix == "LOC06_") - { - valid_prefix = true; - } - else if (prefix == "HID06_") - { - valid_prefix = true; - hidden_location = true; - - auto_tor = RsDirUtil::checkDirectory(mBaseDirectory+"/"+*it+"/hidden_service"); - } - else - { - std::cerr << "getAvailableAccounts() Skipping Invalid Prefix dir: " << *it << std::endl; - continue; - } - - if(hidden_only && !hidden_location) - continue ; - - if(valid_prefix && isHexaString(lochex) && (lochex).length() == 32) - { - std::string accountdir = mBaseDirectory + "/" + *it; -#ifdef GPG_DEBUG - std::cerr << "getAvailableAccounts() Checking: " << *it << std::endl; -#endif - - AccountDetails tmpId; - tmpId.mIsHiddenLoc = hidden_location; - tmpId.mIsAutoTor = auto_tor; - tmpId.mAccountDir = *it; - - if (checkAccount(accountdir, tmpId,unsupported_keys)) - { -#ifdef GPG_DEBUG - std::cerr << "getAvailableAccounts() Accepted: " << *it << std::endl; -#endif - - std::map::iterator ait; - ait = accounts.find(tmpId.mSslId); - if (ait != accounts.end()) - { - std::cerr << "getAvailableAccounts() ERROR Duplicate SSLIDs"; - std::cerr << " - only one will be available"; - std::cerr << std::endl; - std::cerr << " ID1 (overridden) : " << ait->first << " Directory: " << ait->second.mAccountDir; - std::cerr << std::endl; - std::cerr << " ID2 (available) : " << tmpId.mSslId << " Directory: " << tmpId.mAccountDir; - std::cerr << std::endl; - - } - - accounts[tmpId.mSslId] = tmpId; - } - else - ++failing_accounts ; - } -#ifdef GPG_DEBUG - else - std::cerr << "Skipped non SSLid directory " << *it << std::endl; -#endif - } - return true; -} - - - -static bool checkAccount(const std::string &accountdir, AccountDetails &account,std::map >& unsupported_keys) -{ - /* check if the cert/key file exists */ - - // Create the filename. - // TODO: use kFilenameKey - std::string basename = accountdir + "/"; - basename += kPathKeyDirectory + "/"; - basename += "user"; - - std::string cert_name = basename + "_cert.pem"; - //std::string userName; - -#ifdef AUTHSSL_DEBUG - std::cerr << "checkAccount() dir: " << accountdir << std::endl; -#endif - bool ret = false; - - /* check against authmanagers private keys */ - if(AuthSSL::instance().parseX509DetailsFromFile( - cert_name, account.mSslId, account.mPgpId, account.mLocation )) - { - // new locations store the name in an extra file - if(account.mLocation == "") - RsDirUtil::loadStringFromFile(accountdir + "/" + kPathKeyDirectory + "/" + kFilenameLocation, - account.mLocation); -#ifdef AUTHSSL_DEBUG - std::cerr << "location: " << account.mLocation << " id: " << account.mSslId << std::endl; - std::cerr << "issuerName: " << account.mPgpId << " id: " << account.mSslId << std::endl; -#endif - - if(! RsAccounts::GetPGPLoginDetails(account.mPgpId, account.mPgpName, account.mPgpEmail)) - return false ; - - if(!AuthPGP::haveSecretKey(account.mPgpId)) - return false ; - - if(!AuthPGP::isKeySupported(account.mPgpId)) - { - std::string keystring = account.mPgpId.toStdString() + " " + account.mPgpName + "<" + account.mPgpEmail ; - unsupported_keys[keystring].push_back("Location: " + account.mLocation + "  (" + account.mSslId.toStdString() + ")") ; - return false ; - } - -#ifdef GPG_DEBUG - std::cerr << "PGPLoginDetails: " << account.mPgpId << " name: " << account.mPgpName; - std::cerr << " email: " << account.mPgpEmail << std::endl; -#endif - ret = true; - } - else - { - std::cerr << "GetIssuerName FAILED!" << std::endl; - ret = false; - } - - return ret; -} - - - - - -/**************************** Access Functions for Init Data **************************/ -/**************************** Private Functions for InitRetroshare ********************/ -/**************************** Private Functions for InitRetroshare ********************/ - - -/*********************************************************** - * This Directory is used to store data and "template" file that Retroshare requires. - * These files will either be copied into Retroshare's configuration directory, - * if they are to be modified. Or used directly, if read-only. - * - * This will initially be used for the DHT bootstrap file. - * - * Please modify the code below to suit your platform! - * - * WINDOWS: - * WINDOWS PORTABLE: - * Linux: - * OSX: - - ***********/ - -#ifdef __APPLE__ - /* needs CoreFoundation Framework */ - #include - //#include - //#include -#endif - -/*static*/ std::string RsAccountsDetail::PathDataDirectory(bool check) -{ - std::string dataDirectory; - -#ifdef __APPLE__ - /* NOTE: OSX also qualifies as BSD... so this #ifdef must be before the BSD check. */ - - /* For OSX, applications are Bundled in a directory... - * need to get the path to the executable Bundle. - * - * Code nicely supplied by Qt! - */ - - CFURLRef pluginRef = CFBundleCopyBundleURL(CFBundleGetMainBundle()); - CFStringRef macPath = CFURLCopyFileSystemPath(pluginRef, - kCFURLPOSIXPathStyle); - const char *pathPtr = CFStringGetCStringPtr(macPath, - CFStringGetSystemEncoding()); - dataDirectory = pathPtr; - CFRelease(pluginRef); - CFRelease(macPath); - - dataDirectory += "/Contents/Resources"; - std::cerr << "getRetroshareDataDirectory() OSX: " << dataDirectory; - -#elif (defined(BSD) && (BSD >= 199103)) - /* For BSD, the default is LOCALBASE which will be set - * before compilation via the ports/pkg-src mechanisms. - * For compilation without ports/pkg-src it is set to - * /usr/local (default on Open and Free; Net has /usr/pkg) - */ - dataDirectory = "/usr/local/share/retroshare"; - std::cerr << "getRetroshareDataDirectory() BSD: " << dataDirectory; -#elif defined(WINDOWS_SYS) -// if (RsInitConfig::portable) -// { -// /* For Windows Portable, files must be in the data directory */ -// dataDirectory = "Data"; -// std::cerr << "getRetroshareDataDirectory() WINDOWS PORTABLE: " << dataDirectory; -// std::cerr << std::endl; -// } -// else -// { -// /* For Windows: environment variable APPDATA should be suitable */ -// dataDirectory = getenv("APPDATA"); -// dataDirectory += "\\RetroShare"; -// -// std::cerr << "getRetroshareDataDirectory() WINDOWS: " << dataDirectory; -// std::cerr << std::endl; -// } - - /* Use RetroShare's exe dir */ - dataDirectory = "."; -#elif defined(__ANDROID__) - // TODO: This is probably not really used on Android - dataDirectory = PathBaseDirectory()+"/usr/share/retroshare"; -#elif defined(RS_DATA_DIR) - // cppcheck-suppress ConfigurationNotChecked - dataDirectory = RS_DATA_DIR; - // For all other OS the data directory must be set in libretroshare.pro -#else -# error "For your target OS automatic data dir discovery is not supported, cannot compile if RS_DATA_DIR variable not set." -#endif - - if (!check) - { - std::cerr << "getRetroshareDataDirectory() unckecked: " << dataDirectory << std::endl; - return dataDirectory; - } - - /* Make sure the directory exists, else return emptyString */ - if (!RsDirUtil::checkDirectory(dataDirectory)) - { - std::cerr << "getRetroshareDataDirectory() not found: " << dataDirectory << std::endl; - dataDirectory = ""; - } - else - { - std::cerr << "getRetroshareDataDirectory() found: " << dataDirectory << std::endl; - } - - return dataDirectory; -} - - - -/*****************************************************************************/ -/*****************************************************************************/ -/************************* Generating Certificates ***************************/ -/*****************************************************************************/ -/*****************************************************************************/ - - - /* Generating GPGme Account */ -int RsAccountsDetail::GetPGPLogins(std::list& pgpIds) -{ - AuthPGP::availablePgpCertificatesWithPrivateKeys(pgpIds); - return 1; -} - -int RsAccountsDetail::GetPGPLoginDetails(const RsPgpId& id, std::string &name, std::string &email) -{ - #ifdef GPG_DEBUG - std::cerr << "RsInit::GetPGPLoginDetails for \"" << id << "\"" << std::endl; - #endif - - bool ok = true ; - name = AuthPGP::getPgpName(id,&ok); - if(!ok) - return 0 ; - email = AuthPGP::getPgpEmail(id,&ok); - if(!ok) - return 0 ; - - if (name != "") { - return 1; - } else { - return 0; - } -} - - - -/* Before any SSL stuff can be loaded, the correct PGP must be selected / generated: - **/ - -bool RsAccountsDetail::SelectPGPAccount(const RsPgpId& pgpId) -{ - bool retVal = false; - - if (0 < AuthPGP::PgpInit(pgpId)) - { - retVal = true; -#ifdef DEBUG_ACCOUNTS - std::cerr << "PGP Auth Success!"; -#endif - } - else - std::cerr << "PGP Auth Failed!"; - -#ifdef DEBUG_ACCOUNTS - std::cerr << " ID: " << pgpId << std::endl; -#endif - - return retVal; -} - - -bool RsAccountsDetail::GeneratePGPCertificate(const std::string& name, const std::string& email, const std::string& passwd, RsPgpId &pgpId, const int keynumbits, std::string &errString) -{ - return AuthPGP::GeneratePgpCertificate(name, email, passwd, pgpId, keynumbits, errString); -} - - // PGP Support Functions. -void RsAccountsDetail::getUnsupportedKeys(std::map > &unsupported_keys) -{ - unsupported_keys = mUnsupportedKeys; - return; -} - -bool RsAccountsDetail::exportIdentity(const std::string& fname,const RsPgpId& id) -{ - return AuthPGP::exportProfile(fname,id); -} - -bool RsAccountsDetail::importIdentity(const std::string& fname,RsPgpId& id,std::string& import_error) -{ - return AuthPGP::importProfile(fname,id,import_error); -} - -bool RsAccountsDetail::importIdentityFromString(const std::string &data, RsPgpId &imported_pgp_id, std::string &import_error) -{ - return AuthPGP::importProfileFromString(data, imported_pgp_id, import_error); -} - -bool RsAccountsDetail::exportIdentityToString( - std::string& data, const RsPgpId& pgpId, bool includeSignatures, - std::string& errorMsg ) -{ - return AuthPGP::exportIdentityToString( - data, pgpId, includeSignatures, errorMsg ); -} - -bool RsAccountsDetail::copyGnuPGKeyrings() -{ -#ifdef __ANDROID__ - RS_ERR(std::errc::not_supported); - print_stacktrace(); - return false; -#else - std::string pgp_dir = PathPGPDirectory() ; - - if(!RsDirUtil::checkCreateDirectory(pgp_dir)) - throw std::runtime_error("Cannot create pgp directory " + pgp_dir) ; - - std::string source_public_keyring; - std::string source_secret_keyring; - -#ifdef WINDOWS_SYS - source_public_keyring = mBaseDirectory + "/gnupg/pubring.gpg"; - source_secret_keyring = mBaseDirectory + "/gnupg/secring.gpg" ; -#else - char *env_gnupghome = getenv("GNUPGHOME") ; - - if(env_gnupghome != NULL) - { - std::cerr << "looking into $GNUPGHOME/" << std::endl; - - source_public_keyring = std::string(env_gnupghome) + "/pubring.gpg" ; - source_secret_keyring = std::string(env_gnupghome) + "/secring.gpg" ; - } - else - { - char *env_homedir = getenv("HOME") ; - - if(env_homedir != NULL) - { - std::cerr << "looking into $HOME/.gnupg/" << std::endl; - std::string home_dir(env_homedir) ; - - // We need a specific part for MacOS and Linux as well - source_public_keyring = home_dir + "/.gnupg/pubring.gpg" ; - source_secret_keyring = home_dir + "/.gnupg/secring.gpg" ; - } - else - return false ; - } -#endif - - if(!RsDirUtil::copyFile(source_public_keyring,pgp_dir + "/retroshare_public_keyring.gpg")) - { - std::cerr << "Cannot copy pub keyring " << source_public_keyring << " to destination file " << pgp_dir + "/retroshare_public_keyring.gpg. If you believe your keyring is in a different place, please make the copy yourself." << std::endl; - return false ; - } - if(!RsDirUtil::copyFile(source_secret_keyring,pgp_dir + "/retroshare_secret_keyring.gpg")) - { - std::cerr << "Cannot copy sec keyring " << source_secret_keyring << " to destination file " << pgp_dir + "/retroshare_secret_keyring.gpg. your keyring is in a different place, please make the copy yourself." << std::endl; - return false ; - } - - return true ; -#endif // def __ANDROID__ -} - - - - /* Create SSL Certificates */ -bool RsAccountsDetail::GenerateSSLCertificate(const RsPgpId& pgp_id, const std::string& org, const std::string& loc, const std::string& country, bool ishiddenloc,bool isautotor, const std::string& passwd, RsPeerId &sslId, std::string &errString) -{ - /* select the PGP Identity first */ - if (!SelectPGPAccount(pgp_id)) - { - errString = "Invalid PGP Identity"; - return false; - } - - // generate the private_key / certificate. - // save to file. - // - // then load as if they had entered a passwd. - - // check password. - if (passwd.length() < 4) - { - errString = "Password is Unsatisfactory (must be 4+ chars)"; - return false; - } - - int nbits = 4096; - - //std::string pgp_name = AuthGPG::getGPGName(pgp_id); - - // Create the filename ..... - // Temporary Directory for creating files.... - std::string tmpdir = "TMPCFG"; - - std::string tmpbase = mBaseDirectory + "/" + tmpdir + "/"; - - if(!setupAccount(tmpbase)) - return false ; - - /* create directory structure */ - std::string keypath = tmpbase + kPathKeyDirectory + "/"; - std::string key_name = keypath + kFilenameKey; - std::string cert_name = keypath + kFilenameCert; - - /* Extra step required for SSL + PGP, user must have selected - * or generated a suitable key so the signing can happen. - */ - - X509_REQ *req = GenerateX509Req( - key_name.c_str(), - passwd.c_str(), - "-", //pgp_name.c_str(), // does not allow empty name, set to constant instead - "", //ui -> gen_email -> value(), - org.c_str(), - "", //loc.c_str(), - "", //ui -> gen_state -> value(), - country.c_str(), - nbits, errString); - - if (req == NULL) - { - fprintf(stderr,"RsGenerateCert() Couldn't create Request. Reason: %s\n", errString.c_str()); - return false; - } - - long days = 3000; - X509 *x509 = AuthSSL::getAuthSSL()->SignX509ReqWithGPG(req, days); - - X509_REQ_free(req); - if (x509 == NULL) { - fprintf(stderr,"RsGenerateCert() Couldn't sign ssl certificate. Probably PGP password is wrong.\n"); - return false; - } - - /* save to file */ - - bool gen_ok = true; - - /* Print the signed Certificate! */ - BIO *bio_out = BIO_new(BIO_s_file()); - BIO_set_fp(bio_out,stdout,BIO_NOCLOSE); - - /* Print it out */ - int nmflag = 0; - int reqflag = 0; - - X509_print_ex(bio_out, x509, nmflag, reqflag); - - (void) BIO_flush(bio_out); - BIO_free(bio_out); - - /* Save cert to file */ - // open the file. - FILE *out = NULL; - if (NULL == (out = RsDirUtil::rs_fopen(cert_name.c_str(), "w"))) - { - fprintf(stderr,"RsGenerateCert() Couldn't create Cert File"); - fprintf(stderr," : %s\n", cert_name.c_str()); - gen_ok = false; - } - - if (!PEM_write_X509(out,x509)) - { - fprintf(stderr,"RsGenerateCert() Couldn't Save Cert"); - fprintf(stderr," : %s\n", cert_name.c_str()); - gen_ok = false; - } - - fclose(out); - X509_free(x509); - - // store location name in a file - if(!RsDirUtil::saveStringToFile(keypath + kFilenameLocation, loc)) - std::cerr << "RsInit::GenerateSSLCertificate() failed to save location name to into file." << std::endl; - - if (!gen_ok) - { - errString = "Generation of Certificate Failed"; - return false; - } - - /* try to load it, and get Id */ - - std::string location; - RsPgpId pgpid_retrieved; - - if(!AuthSSL::instance().parseX509DetailsFromFile( - cert_name, sslId, pgpid_retrieved, location )) - { - RsErr() << __PRETTY_FUNCTION__ << " Cannot check own signature, maybe " - << "the files are corrupted." << std::endl; - return false; - } - - /* Move directory to correct id */ - std::string accountdir; - if (ishiddenloc) - accountdir = "HID06_" + sslId.toStdString(); - else - accountdir = "LOC06_" + sslId.toStdString(); - - std::string fullAccountDir = mBaseDirectory + "/" + accountdir; - std::string finalbase = fullAccountDir + "/"; - - /* Rename Directory */ - std::cerr << "Mv Config Dir from: " << tmpbase << " to: " << finalbase; - std::cerr << std::endl; - - if (!RsDirUtil::renameFile(tmpbase, finalbase)) - { - std::cerr << "rename FAILED" << std::endl; - } - - AccountDetails newAccount; - - newAccount.mSslId = sslId; - newAccount.mAccountDir = accountdir; - newAccount.mPgpId = pgp_id; - - newAccount.mLocation = loc; - newAccount.mIsHiddenLoc = ishiddenloc; - newAccount.mIsAutoTor = isautotor; - - newAccount.mFirstRun = true; - - // rest of newAccount pgp filled in checkAccount. - if (!checkAccount(fullAccountDir, newAccount, mUnsupportedKeys)) - { - std::cerr << "RsInit::GenerateSSLCertificate() Cannot check own signature, maybe the files are corrupted." << std::endl; - return false; - } - - mAccounts[newAccount.mSslId] = newAccount; - mPreferredId = newAccount.mSslId; - - std::cerr << "RetroShare has Successfully generated a Certficate/Key" << std::endl; - std::cerr << "\tCert Located: " << cert_name << std::endl; - std::cerr << "\tLocated: " << key_name << std::endl; - - return true; -} - - -/******************* PRIVATE FNS TO HELP with GEN **************/ -bool RsAccountsDetail::setupAccount(const std::string& accountdir) -{ - /* actual config directory isd */ - - std::string subdir1 = accountdir + "/"; - subdir1 += kPathKeyDirectory; - - std::string subdir2 = accountdir + "/"; - subdir2 += kPathConfigDirectory; - - std::string subdir3 = accountdir + "/"; - subdir3 += "cache"; - - std::string subdir4 = subdir3 + "/"; - std::string subdir5 = subdir3 + "/"; - subdir4 += "local"; - subdir5 += "remote"; - - // fatal if cannot find/create. - std::cerr << "Checking For Directories" << std::endl; - if (!RsDirUtil::checkCreateDirectory(accountdir)) - { - std::cerr << "Cannot Create BaseConfig Dir" << std::endl; - return false ; - } - if (!RsDirUtil::checkCreateDirectory(subdir1)) - { - std::cerr << "Cannot Create Key Directory" << std::endl; - return false ; - } - if (!RsDirUtil::checkCreateDirectory(subdir2)) - { - std::cerr << "Cannot Create Config Directory" << std::endl; - return false ; - } - if (!RsDirUtil::checkCreateDirectory(subdir3)) - { - std::cerr << "Cannot Create Config/Cache Dir" << std::endl; - return false ; - } - if (!RsDirUtil::checkCreateDirectory(subdir4)) - { - std::cerr << "Cannot Create Config/Cache/local Dir" << std::endl; - return false ; - } - if (!RsDirUtil::checkCreateDirectory(subdir5)) - { - std::cerr << "Cannot Create Config/Cache/remote Dir" << std::endl; - return false ; - } - - return true; -} - - - - - - -/***************************** FINAL LOADING OF SETUP *************************/ - -#if 0 - /* Login SSL */ -bool RsInit::LoadPassword(const std::string& id, const std::string& inPwd) -{ - /* select configDir */ - - RsInitConfig::preferredId = id; - - std::map::iterator it = RsInitConfig::accountIds.find(id); - if (it == RsInitConfig::accountIds.end()) - { - std::cerr << "RsInit::LoadPassword() Cannot Locate Identity: " << id; - std::cerr << std::endl; - exit(1); - } - - std::string accountdir = it->second.accountDir; - - RsInitConfig::configDir = RsInitConfig::basedir + "/" + accountdir; - RsInitConfig::passwd = inPwd; - - // if(inPwd != "") - // RsInitConfig::havePasswd = true; - - // Create the filename. - std::string basename = RsInitConfig::configDir + "/"; - basename += configKeyDir + "/"; - basename += "user"; - - RsInitConfig::load_key = basename + "_pk.pem"; - RsInitConfig::load_cert = basename + "_cert.pem"; - - return true; -} -#endif - -/********************************************************************************* - * PUBLIC INTERFACE FUNCTIONS - ********************************************************************************/ - -bool RsAccounts::init(const std::string& opt_base_dir,int& error_code) -{ - rsAccountsDetails = new RsAccountsDetail; - rsAccounts = new RsAccounts; - - // first check config directories, and set bootstrap values. - if(!rsAccountsDetails->setupBaseDirectory(opt_base_dir)) - { - error_code = RS_INIT_BASE_DIR_ERROR ; - return false ; - } - - // Setup PGP stuff. - std::string pgp_dir = rsAccountsDetails->PathPGPDirectory(); - - if(!RsDirUtil::checkCreateDirectory(pgp_dir)) - throw std::runtime_error("Cannot create pgp directory " + pgp_dir) ; - - AuthPGP::init( pgp_dir + "/retroshare_public_keyring.gpg", - pgp_dir + "/retroshare_secret_keyring.gpg", - pgp_dir + "/retroshare_trustdb.gpg", - pgp_dir + "/lock"); - - // load Accounts. - if (!rsAccountsDetails->loadAccounts()) - { - error_code = RS_INIT_NO_KEYRING ; - return false ; - } - return true; -} - - // Directories. -std::string RsAccounts::ConfigDirectory() { return RsAccountsDetail::PathBaseDirectory(); } -std::string RsAccounts::systemDataDirectory(bool check) { return RsAccountsDetail::PathDataDirectory(check); } -std::string RsAccounts::PGPDirectory() { return rsAccountsDetails->PathPGPDirectory(); } -std::string RsAccounts::AccountDirectory() { return rsAccountsDetails->getCurrentAccountPathAccountDirectory(); } -std::string RsAccounts::AccountKeysDirectory() { return rsAccountsDetails->getCurrentAccountPathAccountKeysDirectory(); } -std::string RsAccounts::AccountPathCertFile() { return rsAccountsDetails->getCurrentAccountPathCertFile(); } -std::string RsAccounts::AccountPathKeyFile() { return rsAccountsDetails->getCurrentAccountPathKeyFile(); } -std::string RsAccounts::AccountLocationName() { return rsAccountsDetails->getCurrentAccountLocationName(); } - -bool RsAccounts::lockPreferredAccount() { return rsAccountsDetails->lockPreferredAccount();} // are these methods any useful?? -void RsAccounts::unlockPreferredAccount() { rsAccountsDetails->unlockPreferredAccount(); } - -bool RsAccounts::checkCreateAccountDirectory() { return rsAccountsDetails->checkAccountDirectory(); } - -// PGP Accounts. -int RsAccounts::GetPGPLogins(std::list &pgpIds) -{ - return rsAccountsDetails->GetPGPLogins(pgpIds); -} - -int RsAccounts::GetPGPLoginDetails(const RsPgpId& id, std::string &name, std::string &email) -{ - return rsAccountsDetails->GetPGPLoginDetails(id, name, email); -} - -bool RsAccounts::GeneratePGPCertificate(const std::string &name, const std::string& email, const std::string& passwd, RsPgpId &pgpId, const int keynumbits, std::string &errString) -{ - return rsAccountsDetails->GeneratePGPCertificate(name, email, passwd, pgpId, keynumbits, errString); -} - -// PGP Support Functions. -bool RsAccounts::ExportIdentity(const std::string& fname,const RsPgpId& pgp_id) -{ - return rsAccountsDetails->exportIdentity(fname,pgp_id); -} - -bool RsAccounts::ImportIdentity(const std::string& fname,RsPgpId& imported_pgp_id,std::string& import_error) -{ - return rsAccountsDetails->importIdentity(fname,imported_pgp_id,import_error); -} - -bool RsAccounts::importIdentityFromString( - const std::string& data, RsPgpId& imported_pgp_id, - std::string& import_error ) -{ - return rsAccountsDetails-> - importIdentityFromString(data, imported_pgp_id, import_error); -} - -/*static*/ bool RsAccounts::exportIdentityToString( - std::string& data, const RsPgpId& pgpId, std::string& errorMsg, - bool includeSignatures ) -{ - return rsAccountsDetails->exportIdentityToString( - data, pgpId, includeSignatures, errorMsg); -} - -void RsAccounts::GetUnsupportedKeys(std::map > &unsupported_keys) -{ - return rsAccountsDetails->getUnsupportedKeys(unsupported_keys); -} - -bool RsAccounts::CopyGnuPGKeyrings() -{ - return rsAccountsDetails->copyGnuPGKeyrings(); -} - -void RsAccounts::storeSelectedAccount() { rsAccountsDetails->storePreferredAccount() ;} -// Rs Accounts -bool RsAccounts::SelectAccount(const RsPeerId &id) -{ - return rsAccountsDetails->selectId(id); -} - -bool RsAccounts::GetPreferredAccountId(RsPeerId &id) -{ - return rsAccountsDetails->getCurrentAccountId(id); -} - -bool RsAccounts::getCurrentAccountOptions(bool& is_hidden,bool& is_tor_auto,bool& is_first_time) -{ - return rsAccountsDetails->getCurrentAccountOptions(is_hidden,is_tor_auto,is_first_time); -} -bool RsAccounts::isHiddenNode() -{ - bool hidden = false ; - bool is_tor_only = false ; - bool is_first_time = false ; - - if(!getCurrentAccountOptions(hidden,is_tor_only,is_first_time)) - { - std::cerr << "(EE) Critical problem: RsAccounts::getCurrentAccountOptions() called but no account chosen!" << std::endl; - throw std::runtime_error("inconsistent configuration") ; - } - - return hidden ; -} -bool RsAccounts::isTorAuto() -{ - bool hidden = false ; - bool is_tor_only = false ; - bool is_first_time = false ; - - if(!getCurrentAccountOptions(hidden,is_tor_only,is_first_time)) - { - std::cerr << "(EE) Critical problem: RsAccounts::getCurrentAccountOptions() called but no account chosen!" << std::endl; - throw std::runtime_error("inconsistent configuration") ; - } - - return is_tor_only ; -} - -bool RsAccounts::GetAccountIds(std::list &ids) -{ - return rsAccountsDetails->getAccountIds(ids); -} - -bool RsAccounts::GetAccountDetails(const RsPeerId &id, - RsPgpId &pgpId, std::string &pgpName, - std::string &pgpEmail, std::string &location) -{ - return rsAccountsDetails->getCurrentAccountDetails(id, pgpId, pgpName, pgpEmail, location); -} - -bool RsAccounts::createNewAccount( - const RsPgpId& pgp_id, const std::string& org, const std::string& loc, - const std::string& country, bool ishiddenloc, bool isautotor, - const std::string& passwd, RsPeerId &sslId, std::string &errString ) -{ - return rsAccountsDetails->GenerateSSLCertificate(pgp_id, org, loc, country, ishiddenloc, isautotor, passwd, sslId, errString); -} - -/********************************************************************************* - * END OF: PUBLIC INTERFACE FUNCTIONS - ********************************************************************************/ - -std::string RsAccountsDetail::mBaseDirectory; diff --git a/libretroshare/src/rsserver/rsaccounts.h b/libretroshare/src/rsserver/rsaccounts.h deleted file mode 100644 index 2db4552a7..000000000 --- a/libretroshare/src/rsserver/rsaccounts.h +++ /dev/null @@ -1,150 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: rsaccounts.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013-2014 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -/********************************************************************* - * Header providing interface for libretroshare access to RsAccounts stuff. - * External access must be through rsinit.g where a RsAccounts namespace + fns - * are available. - * - */ - -#pragma once - -#include -#include -#include -#include "retroshare/rstypes.h" - -class AccountDetails -{ - public: - AccountDetails(); - - RsPeerId mSslId; - std::string mAccountDir; - - RsPgpId mPgpId; - std::string mPgpName; - std::string mPgpEmail; - - std::string mLocation; - bool mIsHiddenLoc; - bool mFirstRun; - bool mIsAutoTor; - -}; - -class RsAccountsDetail -{ - public: - RsAccountsDetail(); - - // These functions are externally accessible via RsAccounts namespace. - // These functions are accessible from inside libretroshare. - - bool setupBaseDirectory(std::string alt_basedir); - bool loadAccounts(); - bool lockPreferredAccount(); - void unlockPreferredAccount(); - bool checkAccountDirectory(); - - // Paths. - /** - * @brief PathDataDirectory - * @param check if set to true and directory does not exist, return empty string - * @return path where global platform independent files are stored, like bdboot.txt or webinterface files - */ - static std::string PathDataDirectory(bool check = true); - - /** - * @brief PathBaseDirectory - * @return path where user data is stored ( on Linux and similar - * systems it is usually something like /home/USERNAME/.retroshare ). - */ - static std::string PathBaseDirectory(); - - // PGP Path is only dependent on BaseDirectory. - std::string PathPGPDirectory(); - - // Generate a new account based on a given PGP key returns its SSL id and sets it to be the preferred account. - - bool GenerateSSLCertificate(const RsPgpId& gpg_id, const std::string& org, const std::string& loc, const std::string& country, bool ishiddenloc, bool is_auto_tor,const std::string& passwd, RsPeerId &sslId, std::string &errString); - - // PGP Accounts. - - int GetPGPLogins(std::list &pgpIds); - int GetPGPLoginDetails(const RsPgpId& id, std::string &name, std::string &email); - bool GeneratePGPCertificate(const std::string&, const std::string& email, const std::string& passwd, RsPgpId &pgpId, const int keynumbits, std::string &errString); - bool SelectPGPAccount(const RsPgpId& pgpId); - - // PGP Support Functions. - bool exportIdentity(const std::string& fname,const RsPgpId& pgp_id) ; - bool importIdentity(const std::string& fname,RsPgpId& imported_pgp_id,std::string& import_error) ; - bool exportIdentityToString( - std::string& data, const RsPgpId& pgpId, bool includeSignatures, - std::string& errorMsg ); - bool importIdentityFromString(const std::string& data,RsPgpId& imported_pgp_id,std::string& import_error) ; - void getUnsupportedKeys(std::map > &unsupported_keys); - bool copyGnuPGKeyrings() ; - - // Selecting Rs Account. - bool getAccountIds(std::list &ids); - bool selectAccountByString(const std::string &prefUserString); - bool selectId(const RsPeerId& preferredId); - bool storePreferredAccount(); - bool loadPreferredAccount(); - - // Details of current Rs Account. - bool getCurrentAccountId(RsPeerId &id); - bool getCurrentAccountDetails(const RsPeerId &id, RsPgpId& gpgId, std::string &gpgName, std::string &gpgEmail, std::string &location); - bool getCurrentAccountOptions(bool &ishidden, bool &isautotor, bool &isFirstTimeRun); - - std::string getCurrentAccountPathAccountDirectory(); - std::string getCurrentAccountPathAccountKeysDirectory(); - std::string getCurrentAccountPathKeyFile(); - std::string getCurrentAccountPathCertFile(); - std::string getCurrentAccountLocationName(); - - - private: - bool checkPreferredId(); - - static bool defaultBaseDirectory(); - - bool getAvailableAccounts(std::map &accounts, - int& failing_accounts, - std::map >& unsupported_keys, bool hidden_only=false); - - bool setupAccount(const std::string& accountdir); - - private: - - bool mAccountsLocked; - - std::map mAccounts; - RsPeerId mPreferredId; - static std::string mBaseDirectory; - - std::map > mUnsupportedKeys ; -}; - - diff --git a/libretroshare/src/rsserver/rsinit.cc b/libretroshare/src/rsserver/rsinit.cc deleted file mode 100644 index 5729b552c..000000000 --- a/libretroshare/src/rsserver/rsinit.cc +++ /dev/null @@ -1,2155 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsinit.cc * - * * - * Copyright (C) 2004-2014 Robert Fernie * - * Copyright (C) 2016-2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -/// RetroShare initialization and login API implementation - -#include - -#ifndef WINDOWS_SYS -// for locking instances -#include -#else -#include "util/rswin.h" -#endif - -#ifdef __ANDROID__ -# include -# include "rs_android/rsjni.hpp" -# include "rs_android/retroshareserviceandroid.hpp" -#endif - -#include "util/argstream.h" -#include "util/rsdebug.h" -#include "util/rsdir.h" -#include "util/rsrandom.h" -#include "util/folderiterator.h" -#include "util/rsstring.h" -#include "retroshare/rsinit.h" -#include "retroshare/rstor.h" -#include "retroshare/rsnotify.h" -#include "retroshare/rsiface.h" -#include "plugins/pluginmanager.h" -#include "retroshare/rsversion.h" -#include "rsserver/rsloginhandler.h" -#include "rsserver/rsaccounts.h" - -#ifdef RS_EMBEDED_FRIEND_SERVER -#include "friend_server/fsmanager.h" -#endif - -#include -#include - -#include -#include -#include -#include -#include - -#include "gxstunnel/p3gxstunnel.h" -#include "retroshare/rsgxsdistsync.h" -#include "file_sharing/p3filelists.h" - -#define ENABLE_GROUTER - -#if (defined(__unix__) || defined(unix)) && !defined(USG) -#include -#endif - -// This needs to be defined here, because when USE_BITDHT is unset, the variable, that is defined in libbitdht (not compiled!) will be missing. -#ifndef RS_USE_BITDHT -RsDht *rsDht = NULL ; -#endif - -// for blocking signals -#include - -#include - -#include "pqi/authssl.h" -#include "pqi/sslfns.h" -#include "pqi/authgpg.h" - -#ifdef ENABLE_GROUTER -#include "grouter/p3grouter.h" -#endif - -#ifdef RS_USE_DHT_STUNNER -#include "tcponudp/udpstunner.h" -#endif // RS_USE_DHT_STUNNER - -#ifdef RS_GXS_TRANS -# include "gxstrans/p3gxstrans.h" -#endif - -#ifdef RS_JSONAPI -# include "jsonapi/jsonapi.h" -#endif - -#ifdef RS_BROADCAST_DISCOVERY -# include "retroshare/rsbroadcastdiscovery.h" -# include "services/broadcastdiscoveryservice.h" -#endif // def RS_BROADCAST_DISCOVERY - -// #define GPG_DEBUG -// #define AUTHSSL_DEBUG -// #define FIM_DEBUG -// #define DEBUG_RSINIT - -//std::map > RsInit::unsupported_keys ; - -RsLoginHelper* rsLoginHelper = nullptr; - -RsAccounts* rsAccounts = nullptr; - -const RsInitErrorCategory RsInitErrorCategory::instance; - -RsConfigOptions::RsConfigOptions() - : - autoLogin(false), - udpListenerOnly(false), - forcedInetAddress("127.0.0.1"), /* inet address to use.*/ - forcedPort(0), - outStderr(false), - debugLevel(5) -#ifdef RS_JSONAPI - ,jsonApiPort(0) // JSonAPI server is enabled in each main() - ,jsonApiBindAddress("127.0.0.1") -#endif -{ -} - - -struct RsInitConfig -{ - RsInitConfig() -#ifdef RS_JSONAPI - : jsonApiPort(JsonApiServer::DEFAULT_PORT), - jsonApiBindAddress("127.0.0.1") -#endif - {} - - RsFileHash main_executable_hash; - std::string mainExecutablePath; - -#ifdef WINDOWS_SYS - bool portable; - bool isWindowsXP; -#endif - rs_lock_handle_t lockHandle; - - std::string passwd; - std::string gxs_passwd; - - bool autoLogin; /* autoLogin allowed */ - bool startMinimised; /* Icon or Full Window */ - - /* Key Parameters that must be set before - * RetroShare will start up: - */ - - /* Listening Port */ - bool forceExtPort; - bool forceLocalAddr; - unsigned short port; - std::string inet ; - - /* v0.6 features */ - bool hiddenNodeSet; - std::string hiddenNodeAddress; - uint16_t hiddenNodePort; - - bool hiddenNodeI2P; - - /* Logging */ - bool haveLogFile; - bool outStderr; - int debugLevel; - std::string logfname; - - bool udpListenerOnly; - std::string opModeStr; - std::string optBaseDir; - - uint16_t jsonApiPort; - std::string jsonApiBindAddress; -}; - -static RsInitConfig* rsInitConfig = nullptr; - -static const std::string configLogFileName = "retro.log"; -static const int SSLPWD_LEN = 64; - -void RsInit::InitRsConfig() -{ - RsInfo() << "libretroshare version: " << RS_HUMAN_READABLE_VERSION - << std::endl; - - rsInitConfig = new RsInitConfig; - - - /* TODO almost all of this should be moved to RsInitConfig::RsInitConfig - * initializers */ - - /* Directories */ -#ifdef WINDOWS_SYS - rsInitConfig->portable = false; - rsInitConfig->isWindowsXP = false; -#endif - /* v0.6 features */ - rsInitConfig->hiddenNodeSet = false; - - - // This doesn't seems a configuration... -#ifndef WINDOWS_SYS - rsInitConfig->lockHandle = -1; -#else - rsInitConfig->lockHandle = NULL; -#endif - - rsInitConfig->port = 0 ; - rsInitConfig->forceLocalAddr = false; - rsInitConfig->haveLogFile = false; - rsInitConfig->outStderr = false; - rsInitConfig->forceExtPort = false; - - rsInitConfig->inet = std::string("127.0.0.1"); - - rsInitConfig->autoLogin = false; // . - rsInitConfig->startMinimised = false; - rsInitConfig->passwd = ""; - rsInitConfig->debugLevel = PQL_WARNING; - rsInitConfig->udpListenerOnly = false; - rsInitConfig->opModeStr = std::string(""); - -#ifdef WINDOWS_SYS - // test for portable version - if (GetFileAttributes(L"portable") != (DWORD) -1) { - // use portable version - rsInitConfig->portable = true; - } - - // test for Windows XP - OSVERSIONINFOEX osvi; - memset(&osvi, 0, sizeof(osvi)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - - if (GetVersionEx((OSVERSIONINFO*) &osvi)) { - if (osvi.dwMajorVersion == 5) { - if (osvi.dwMinorVersion == 1) { - /* Windows XP */ - rsInitConfig->isWindowsXP = true; - } else if (osvi.dwMinorVersion == 2) { - SYSTEM_INFO si; - memset(&si, 0, sizeof(si)); - GetSystemInfo(&si); - if (osvi.wProductType == VER_NT_WORKSTATION && si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64) { - /* Windows XP Professional x64 Edition */ - rsInitConfig->isWindowsXP = true; - } - } - } - } - - if (rsInitConfig->isWindowsXP) { - std::cerr << "Running Windows XP" << std::endl; - } else { - std::cerr << "Not running Windows XP" << std::endl; - } -#endif - - setOutputLevel(RsLog::Warning); -} - -#ifdef LOCALNET_TESTING - -std::string portRestrictions; -bool doPortRestrictions = false; - -#endif - -#ifdef WINDOWS_SYS -#ifdef PTW32_STATIC_LIB -#include -#endif -#endif - -/******** - * LOCALNET_TESTING - allows port restrictions - * - * #define LOCALNET_TESTING 1 - * - ********/ -int RsInit::InitRetroShare(const RsConfigOptions& conf) -{ - rsInitConfig->autoLogin = conf.autoLogin; - rsInitConfig->outStderr = conf.outStderr; - rsInitConfig->logfname = conf.logfname ; - rsInitConfig->inet = conf.forcedInetAddress ; - rsInitConfig->port = conf.forcedPort ; - rsInitConfig->debugLevel = conf.debugLevel; - rsInitConfig->udpListenerOnly = conf.udpListenerOnly; - rsInitConfig->optBaseDir = conf.optBaseDir; - rsInitConfig->jsonApiPort = conf.jsonApiPort; - rsInitConfig->jsonApiBindAddress = conf.jsonApiBindAddress; - rsInitConfig->mainExecutablePath = conf.main_executable_path; - -#ifdef PTW32_STATIC_LIB - // for static PThreads under windows... we need to init the library... - pthread_win32_process_attach_np(); -#endif - if( rsInitConfig->autoLogin) rsInitConfig->startMinimised = true ; - if( rsInitConfig->outStderr) rsInitConfig->haveLogFile = false ; - if(!rsInitConfig->logfname.empty()) rsInitConfig->haveLogFile = true; - if( rsInitConfig->inet != "127.0.0.1") rsInitConfig->forceLocalAddr = true; - if( rsInitConfig->port != 0) rsInitConfig->forceLocalAddr = true; // previously forceExtPort, which means nothing in this case -#ifdef LOCALNET_TESTING - if(!portRestrictions.empty()) doPortRestrictions = true; -#endif - - setOutputLevel((RsLog::logLvl)rsInitConfig->debugLevel); - - // set the debug file. - if (rsInitConfig->haveLogFile) - setDebugFile(rsInitConfig->logfname.c_str()); - - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - /********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#else - // Windows Networking Init. - WORD wVerReq = MAKEWORD(2,2); - WSADATA wsaData; - - if (0 != WSAStartup(wVerReq, &wsaData)) - { - std::cerr << "Failed to Startup Windows Networking"; - std::cerr << std::endl; - } - else - { - std::cerr << "Started Windows Networking"; - std::cerr << std::endl; - } - -#endif - /********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - // SWITCH off the SIGPIPE - kills process on Linux. - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - struct sigaction sigact; - sigact.sa_handler = SIG_IGN; - sigact.sa_flags = 0; - - sigset_t set; - sigemptyset(&set); - //sigaddset(&set, SIGINT); // or whatever other signal - sigact.sa_mask = set; - - if (0 == sigaction(SIGPIPE, &sigact, NULL)) - { - std::cerr << "RetroShare:: Successfully installed the SIGPIPE Block" << std::endl; - } - else - { - std::cerr << "RetroShare:: Failed to install the SIGPIPE Block" << std::endl; - } -#endif - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - // Hash the main executable. - - uint64_t tmp_size ; - - if(conf.main_executable_path.empty()) - { - std::cerr << "Executable path is unknown. It should normally have been set in passed RsConfigOptions structure" << std::endl; - return 1; - } - if(!RsDirUtil::getFileHash(conf.main_executable_path,rsInitConfig->main_executable_hash,tmp_size,NULL)) - std::cerr << "Cannot hash executable! Plugins will not be loaded correctly." << std::endl; - else - std::cerr << "Hashed main executable: " << rsInitConfig->main_executable_hash << std::endl; - - /* At this point we want to. - * 1) Load up Dase Directory. - * 3) Get Prefered Id. - * 2) Get List of Available Accounts. - * 4) Get List of GPG Accounts. - */ - /* Initialize AuthSSL */ - AuthSSL::instance().InitAuth(nullptr, nullptr, nullptr, ""); - - rsLoginHelper = new RsLoginHelper; - - int error_code ; - - if(!RsAccounts::init(rsInitConfig->optBaseDir,error_code)) - return error_code ; - -#ifdef RS_JSONAPI - // We create the JsonApiServer this early, because it is needed *before* login - RsDbg() << __PRETTY_FUNCTION__ - << " Allocating JSON API server (not launched yet)" << std::endl; - JsonApiServer* jas = new JsonApiServer(); - jas->setListeningPort(conf.jsonApiPort); - jas->setBindingAddress(conf.jsonApiBindAddress); - - if(conf.jsonApiPort != 0) jas->restart(); - - rsJsonApi = jas; -#endif - -#ifdef RS_AUTOLOGIN - /* check that we have selected someone */ - RsPeerId preferredId; - bool existingUser = RsAccounts::GetPreferredAccountId(preferredId); - - if (existingUser) - { - if(RsLoginHandler::getSSLPassword(preferredId,false,rsInitConfig->passwd)) - { - RsInit::setAutoLogin(true); - std::cerr << "Autologin has succeeded" << std::endl; - return RS_INIT_HAVE_ACCOUNT; - } - } -#endif - - return RS_INIT_OK; -} - - -/* - * To prevent several running instances from using the same directory - * simultaneously we have to use a global lock. - * We use a lock file on Unix systems. - * - * Return value: - * 0 : Success - * 1 : Another instance already has the lock - * 2 : Unexpected error - */ -RsInit::LoadCertificateStatus RsInit::LockConfigDirectory( - const std::string& accountDir, std::string& lockFilePath ) -{ - const std::string lockFile = accountDir + "/" + "lock"; - lockFilePath = lockFile; - - int rt = RsDirUtil::createLockFile(lockFile,rsInitConfig->lockHandle); - - switch (rt) - { - case 0: return RsInit::OK; - case 1: return RsInit::ERR_ALREADY_RUNNING; - case 2: return RsInit::ERR_CANT_ACQUIRE_LOCK; - default: return RsInit::ERR_UNKNOWN; - } -} - -/* - * Unlock the currently locked profile, if there is one. - * For Unix systems we simply close the handle of the lock file. - */ -void RsInit::UnlockConfigDirectory() -{ - RsDirUtil::releaseLockFile(rsInitConfig->lockHandle) ; -} - - - - -bool RsInit::collectEntropy(uint32_t n) -{ - RAND_seed(&n,4) ; - - return true ; -} - -/***************************** FINAL LOADING OF SETUP *************************/ - - - /* Login SSL */ -bool RsInit::LoadPassword(const std::string& inPwd) -{ - rsInitConfig->passwd = inPwd; - return true; -} - -std::string RsInit::lockFilePath() -{ - return RsAccounts::AccountDirectory() + "/lock" ; -} - -RsInit::LoadCertificateStatus RsInit::LockAndLoadCertificates( - bool autoLoginNT, std::string& lockFilePath ) -{ - try - { - if (!RsAccounts::lockPreferredAccount()) - throw RsInit::ERR_UNKNOWN; // invalid PreferredAccount. - - // Logic that used to be external to RsInit... - RsPeerId accountId; - if (!RsAccounts::GetPreferredAccountId(accountId)) - throw RsInit::ERR_UNKNOWN; // invalid PreferredAccount; - - RsPgpId pgpId; - std::string pgpName, pgpEmail, location; - - if(!RsAccounts::GetAccountDetails(accountId, pgpId, pgpName, pgpEmail, location)) - throw RsInit::ERR_UNKNOWN; // invalid PreferredAccount; - - if(0 == AuthPGP::PgpInit(pgpId)) - throw RsInit::ERR_UNKNOWN; // PGP Error. - - LoadCertificateStatus retVal = - LockConfigDirectory(RsAccounts::AccountDirectory(), lockFilePath); - - if(retVal > 0) - throw retVal ; - - if(LoadCertificates(autoLoginNT) != 1) - { - UnlockConfigDirectory(); - throw RsInit::ERR_UNKNOWN; - } - - return RsInit::OK; - } - catch(LoadCertificateStatus retVal) - { - RsAccounts::unlockPreferredAccount(); - return retVal ; - } -} - - -/** *************************** FINAL LOADING OF SETUP ************************* - * Requires: - * PGPid to be selected (Password not required). - * CertId to be selected (Password Required). - * - * Return value: - * 0 : unexpected error - * 1 : success - */ -int RsInit::LoadCertificates(bool autoLoginNT) -{ - RsPeerId preferredId; - if (!RsAccounts::GetPreferredAccountId(preferredId)) - { - std::cerr << "No Account Selected" << std::endl; - return 0; - } - - - if (RsAccounts::AccountPathCertFile() == "") - { - std::cerr << "RetroShare needs a certificate" << std::endl; - return 0; - } - - if (RsAccounts::AccountPathKeyFile() == "") - { - std::cerr << "RetroShare needs a key" << std::endl; - return 0; - } - - //check if password is already in memory - - if(rsInitConfig->passwd == "") { - if (RsLoginHandler::getSSLPassword(preferredId,true,rsInitConfig->passwd) == false) { -#ifdef DEBUG_RSINIT - std::cerr << "RsLoginHandler::getSSLPassword() Failed!"; -#endif - return 0 ; - } - } else { - if (RsLoginHandler::checkAndStoreSSLPasswdIntoGPGFile(preferredId,rsInitConfig->passwd) == false) { - std::cerr << "RsLoginHandler::checkAndStoreSSLPasswdIntoGPGFile() Failed!"; - return 0; - } - } - - std::cerr << "rsAccounts->PathKeyFile() : " << RsAccounts::AccountPathKeyFile() << std::endl; - - if(0 == AuthSSL::getAuthSSL() -> InitAuth(RsAccounts::AccountPathCertFile().c_str(), RsAccounts::AccountPathKeyFile().c_str(), rsInitConfig->passwd.c_str(), - RsAccounts::AccountLocationName())) - { - std::cerr << "SSL Auth Failed!"; - return 0 ; - } - -#ifdef RS_AUTOLOGIN - if(autoLoginNT) - { - std::cerr << "RetroShare will AutoLogin next time" << std::endl; - - RsLoginHandler::enableAutoLogin(preferredId,rsInitConfig->passwd); - rsInitConfig->autoLogin = true ; - } -#else - (void) autoLoginNT; -#endif // RS_AUTOLOGIN - - /* wipe out password */ - - // store pword to allow gxs use it to services' key their databases - // ideally gxs should have its own password - rsInitConfig->gxs_passwd = rsInitConfig->passwd; - rsInitConfig->passwd = ""; - - RsAccounts::storeSelectedAccount(); - return 1; -} - -#ifdef RS_AUTOLOGIN -bool RsInit::RsClearAutoLogin() -{ - RsPeerId preferredId; - if (!RsAccounts::GetPreferredAccountId(preferredId)) - { - std::cerr << "RsInit::RsClearAutoLogin() No Account Selected" << std::endl; - return 0; - } - return RsLoginHandler::clearAutoLogin(preferredId); -} -#endif // RS_AUTOLOGIN - - -bool RsInit::isPortable() -{ -#ifdef WINDOWS_SYS - return rsInitConfig->portable; -#else - return false; -#endif -} - -bool RsInit::isWindowsXP() -{ -#ifdef WINDOWS_SYS - return rsInitConfig->isWindowsXP; -#else - return false; -#endif -} - -bool RsInit::getStartMinimised() -{ - return rsInitConfig->startMinimised; -} - -int RsInit::getSslPwdLen(){ - return SSLPWD_LEN; -} - -bool RsInit::getAutoLogin(){ - return rsInitConfig->autoLogin; -} - -void RsInit::setAutoLogin(bool autoLogin){ - rsInitConfig->autoLogin = autoLogin; -} - -/* Setup Hidden Location; */ -void RsInit::SetHiddenLocation(const std::string& hiddenaddress, uint16_t port, bool useI2p) -{ - /* parse the bugger (todo) */ - rsInitConfig->hiddenNodeSet = true; - rsInitConfig->hiddenNodeAddress = hiddenaddress; - rsInitConfig->hiddenNodePort = port; - rsInitConfig->hiddenNodeI2P = useI2p; -} - - -/* - * - * Init Part of RsServer... needs the private - * variables so in the same file. - * - */ - -#include -//#include - -#include "ft/ftserver.h" -#include "ft/ftcontroller.h" - -#include "retroshare/rsiface.h" -#include "retroshare/rsturtle.h" - -/* global variable now points straight to - * ft/ code so variable defined here. - */ - -RsFiles *rsFiles = NULL; -RsTurtle *rsTurtle = NULL ; -RsReputations *rsReputations = NULL ; -#ifdef ENABLE_GROUTER -RsGRouter *rsGRouter = NULL ; -#endif - -#include "pqi/pqipersongrp.h" -#include "pqi/pqisslpersongrp.h" -#include "pqi/pqiloopback.h" -#include "pqi/p3cfgmgr.h" -#include "pqi/p3historymgr.h" - -#include "util/rsdebug.h" -#include "util/rsdir.h" -#include "util/rsrandom.h" - -#ifdef RS_USE_LIBUPNP -# include "rs_upnp/upnphandler_libupnp.h" -#else // def RS_USE_LIBUPNP -# include "rs_upnp/upnphandler_miniupnp.h" -#endif // def RS_USE_LIBUPNP - -#include "services/autoproxy/p3i2psam3.h" -#include "services/autoproxy/rsautoproxymonitor.h" - -#include "services/p3gxsreputation.h" -#include "services/p3serviceinfo.h" -#include "services/p3heartbeat.h" -#include "gossipdiscovery/p3gossipdiscovery.h" -#include "services/p3msgservice.h" -#include "services/p3statusservice.h" - -#include "turtle/p3turtle.h" -#include "chat/p3chatservice.h" - -#ifdef RS_ENABLE_GXS -// NEW GXS SYSTEMS. -#include "gxs/rsdataservice.h" -#include "gxs/rsgxsnetservice.h" -#include "retroshare/rsgxsflags.h" - -#include "pgp/pgpauxutils.h" -#include "services/p3idservice.h" -#include "services/p3gxscircles.h" -#include "services/p3posted.h" -#include "services/p3gxsforums.h" -#include "services/p3gxschannels.h" - -#include "services/p3wiki.h" -#include "services/p3wire.h" -#include "services/p3photoservice.h" - -#endif // RS_ENABLE_GXS - - -#include -#include - -// for blocking signals -#include - -/* Implemented Rs Interfaces */ -#include "rsserver/p3face.h" -#include "rsserver/p3peers.h" -#include "rsserver/p3msgs.h" -#include "rsserver/p3status.h" -#include "rsserver/p3history.h" -#include "rsserver/p3serverconfig.h" - - -#include "pqi/p3notify.h" // HACK - moved to pqi for compilation order. - -#include "pqi/p3peermgr.h" -#include "pqi/p3linkmgr.h" -#include "pqi/p3netmgr.h" - -#include "tcponudp/tou.h" -#include "tcponudp/rsudpstack.h" - -#ifdef RS_USE_BITDHT -#include "dht/p3bitdht.h" -#ifdef RS_USE_DHT_STUNNER -#include "dht/stunaddrassist.h" -#endif // RS_USE_DHT_STUNNER - -#include "udp/udpstack.h" -#include "tcponudp/udppeer.h" -#include "tcponudp/udprelay.h" -#endif - -/**** - * #define RS_RELEASE 1 - * #define RS_RTT 1 -****/ - -#define RS_RELEASE 1 -#define RS_RTT 1 - - -#ifdef RS_RTT -#include "services/p3rtt.h" -#endif - - -#include "services/p3banlist.h" -#include "services/p3bwctrl.h" - -#ifdef SERVICES_DSDV -#include "services/p3dsdv.h" -#endif - -RsControl *RsControl::instance() -{ - static RsServer rsicontrol; - return &rsicontrol; -} - - -/* - * The Real RetroShare Startup Function. - */ - -int RsServer::StartupRetroShare() -{ - RsPeerId ownId = AuthSSL::getAuthSSL()->OwnId(); - - std::cerr << "========================================================================" << std::endl; - std::cerr << "== RsInit:: starting up Retroshare core ==" << std::endl; - std::cerr << "== ==" << std::endl; - std::cerr << "== Account/SSL ID : " << ownId << " ==" << std::endl; - std::cerr << "== Node type : " << (RsAccounts::isHiddenNode()?"Hidden":"Normal") << " ==" << std::endl; - if(RsAccounts::isHiddenNode()) - std::cerr << "== Tor/I2P configuration : " << (RsAccounts::isTorAuto()?"Tor Auto":"Manual ") << " ==" << std::endl; - std::cerr << "========================================================================" << std::endl; - - /**************************************************************************/ - /* STARTUP procedure */ - /**************************************************************************/ - /**************************************************************************/ - /* (1) Load up own certificate (DONE ALREADY) - just CHECK */ - /**************************************************************************/ - - if (1 != AuthSSL::getAuthSSL() -> InitAuth(NULL, NULL, NULL, "")) - { - std::cerr << "main() - Fatal Error....." << std::endl; - std::cerr << "Invalid Certificate configuration!" << std::endl; - std::cerr << std::endl; - return false ; - } - - /**************************************************************************/ - /* Any Initial Configuration (Commandline Options) */ - /**************************************************************************/ - - /* set the debugging to crashMode */ - std::cerr << "set the debugging to crashMode." << std::endl; - if ((!rsInitConfig->haveLogFile) && (!rsInitConfig->outStderr)) - { - std::string crashfile = RsAccounts::AccountDirectory(); - crashfile += "/" + configLogFileName; - setDebugCrashMode(crashfile.c_str()); - } - - unsigned long flags = 0; - if (rsInitConfig->udpListenerOnly) - { - flags |= PQIPERSON_NO_LISTENER; - } - - /* check account directory */ - if (!RsAccounts::checkCreateAccountDirectory()) - { - std::cerr << "RsServer::StartupRetroShare() - Fatal Error....." << std::endl; - std::cerr << "checkAccount failed!" << std::endl; - std::cerr << std::endl; - return 0; - } - - /**************************************************************************/ - // Load up Certificates, and Old Configuration (if present) - std::cerr << "Load up Certificates, and Old Configuration (if present)." << std::endl; - - std::string emergencySaveDir = RsAccounts::AccountDirectory(); - std::string emergencyPartialsDir = RsAccounts::AccountDirectory(); - if (emergencySaveDir != "") - { - emergencySaveDir += "/"; - emergencyPartialsDir += "/"; - } - emergencySaveDir += "Downloads"; - emergencyPartialsDir += "Partials"; - - /**************************************************************************/ - /* setup Configuration */ - /**************************************************************************/ - std::cerr << "Load Configuration" << std::endl; - - mConfigMgr = new p3ConfigMgr(RsAccounts::AccountDirectory()); - mGeneralConfig = new p3GeneralConfig(); - - // Get configuration options from rsAccounts. - bool isHiddenNode = false; - bool isFirstTimeRun = false; - bool isTorAuto = false; - - RsAccounts::getCurrentAccountOptions(isHiddenNode,isTorAuto, isFirstTimeRun); - - /**************************************************************************/ - /* setup classes / structures */ - /**************************************************************************/ - std::cerr << "setup classes / structures" << std::endl; - - /* History Manager */ - mHistoryMgr = new p3HistoryMgr(); - mPeerMgr = new p3PeerMgrIMPL( AuthSSL::getAuthSSL()->OwnId(), - AuthPGP::getPgpOwnId(), - AuthPGP::getPgpOwnName(), - AuthSSL::getAuthSSL()->getOwnLocation()); - mNetMgr = new p3NetMgrIMPL(); - mLinkMgr = new p3LinkMgrIMPL(mPeerMgr, mNetMgr); - - /* Setup Notify Early - So we can use it. */ - rsPeers = new p3Peers(mLinkMgr, mPeerMgr, mNetMgr); - - mPeerMgr->setManagers(mLinkMgr, mNetMgr); - mNetMgr->setManagers(mPeerMgr, mLinkMgr); - - rsAutoProxyMonitor *autoProxy = rsAutoProxyMonitor::instance(); -#ifdef RS_USE_I2P_SAM3 - mI2pSam3 = new p3I2pSam3(mPeerMgr); - autoProxy->addProxy(autoProxyType::I2PSAM3, mI2pSam3); -#endif - - //load all the SSL certs as friends - // std::list sslIds; - // AuthSSL::getAuthSSL()->getAuthenticatedList(sslIds); - // for (std::list::iterator sslIdsIt = sslIds.begin(); sslIdsIt != sslIds.end(); ++sslIdsIt) { - // mConnMgr->addFriend(*sslIdsIt); - // } - //p3DhtMgr *mDhtMgr = new OpenDHTMgr(ownId, mConnMgr, rsInitConfig->configDir); - /**************************** BITDHT ***********************************/ - - // Make up an address. XXX - - struct sockaddr_in tmpladdr; - sockaddr_clear(&tmpladdr); - tmpladdr.sin_port = htons(rsInitConfig->port); - - rsUdpStack *mDhtStack = NULL ; - - if(!RsAccounts::isHiddenNode()) - { -#ifdef LOCALNET_TESTING - - mDhtStack = new rsUdpStack(UDP_TEST_RESTRICTED_LAYER, tmpladdr); - - /* parse portRestrictions */ - unsigned int lport, uport; - - if (doPortRestrictions) - { - if (2 == sscanf(portRestrictions.c_str(), "%u-%u", &lport, &uport)) - { - std::cerr << "Adding Port Restriction (" << lport << "-" << uport << ")"; - std::cerr << std::endl; - } - else - { - std::cerr << "Failed to parse Port Restrictions ... exiting"; - std::cerr << std::endl; - exit(1); - } - - RestrictedUdpLayer *url = (RestrictedUdpLayer *) mDhtStack->getUdpLayer(); - url->addRestrictedPortRange(lport, uport); - } -#else //LOCALNET_TESTING -#ifdef RS_USE_BITDHT - mDhtStack = new rsUdpStack(tmpladdr); -#endif -#endif //LOCALNET_TESTING - } - -#ifdef RS_USE_BITDHT - -#define BITDHT_BOOTSTRAP_FILENAME "bdboot.txt" -#define BITDHT_FILTERED_IP_FILENAME "bdfilter.txt" - - - std::string bootstrapfile = RsAccounts::AccountDirectory(); - if (bootstrapfile != "") - bootstrapfile += "/"; - bootstrapfile += BITDHT_BOOTSTRAP_FILENAME; - - std::string installfile = ""; -#ifndef __ANDROID__ - installfile = RsAccounts::systemDataDirectory(); - installfile += "/"; - installfile += BITDHT_BOOTSTRAP_FILENAME; -#endif - - std::string filteredipfile = RsAccounts::AccountDirectory(); - if (filteredipfile != "") - filteredipfile += "/"; - filteredipfile += BITDHT_FILTERED_IP_FILENAME; - - std::cerr << "Checking for DHT bootstrap file: " << bootstrapfile << std::endl; - - /* check if bootstrap file exists... - * if not... copy from dataDirectory - */ - - uint64_t tmp_size ; - if (!RsDirUtil::checkFile(bootstrapfile,tmp_size,true)) - { - RS_INFO("DHT bootstrap file not in ConfigDir: ", bootstrapfile); - -#ifdef __ANDROID__ - auto uenv = jni::GetAttachedEnv(RsJni::getVM()); - JNIEnv& env = *uenv; - - using AContext = RetroShareServiceAndroid::Context; - - auto& assetHelperClass = jni::Class::Singleton(env); - - static auto copyAsset = - assetHelperClass.GetStaticMethod< - jni::jboolean(jni::Object, jni::String, jni::String)>( - env, "copyAsset" ); - - auto androidContext = RetroShareServiceAndroid::getAndroidContext(env); - - jni::jboolean result = assetHelperClass.Call( - env, copyAsset, - androidContext, - jni::Make(env, "values/bdboot.txt"), - jni::Make(env, bootstrapfile) ); - - if(!result) RS_ERR("Failure installing ", bootstrapfile); - -#else // def __ANDROID__ - std::cerr << "Checking for Installation DHT bootstrap file " << installfile << std::endl; - if ((installfile != "") && (RsDirUtil::checkFile(installfile,tmp_size))) - { - std::cerr << "Copying Installation DHT bootstrap file..." << std::endl; - if (RsDirUtil::copyFile(installfile, bootstrapfile)) - { - std::cerr << "Installed DHT bootstrap file in configDir" << std::endl; - } - else - { - std::cerr << "Failed Installation DHT bootstrap file..." << std::endl; - } - } - else - { - std::cerr << "No Installation DHT bootstrap file to copy" << std::endl; - } -#endif // def __ANDROID__ - } - - /* construct the rest of the stack, important to build them in the correct order! */ - /* MOST OF THIS IS COMMENTED OUT UNTIL THE REST OF libretroshare IS READY FOR IT! */ - - p3BitDht *mBitDht = NULL ; - rsDht = NULL ; - rsFixedUdpStack *mProxyStack = NULL ; - - if(!RsAccounts::isHiddenNode()) - { - UdpSubReceiver *udpReceivers[RSUDP_NUM_TOU_RECVERS]; - int udpTypes[RSUDP_NUM_TOU_RECVERS]; - -#ifdef RS_USE_DHT_STUNNER - // FIRST DHT STUNNER. - UdpStunner *mDhtStunner = new UdpStunner(mDhtStack); - mDhtStunner->setTargetStunPeriod(300); /* slow (5mins) */ - mDhtStack->addReceiver(mDhtStunner); - -#ifdef LOCALNET_TESTING - mDhtStunner->SetAcceptLocalNet(); -#endif -#endif // RS_USE_DHT_STUNNER - - - // NEXT BITDHT. - - - mBitDht = new p3BitDht(ownId, mLinkMgr, mNetMgr, mDhtStack, bootstrapfile, installfile, filteredipfile); - - // NEXT THE RELAY (NEED to keep a reference for installing RELAYS) - UdpRelayReceiver *mRelay = new UdpRelayReceiver(mDhtStack); - udpReceivers[RSUDP_TOU_RECVER_RELAY_IDX] = mRelay; /* RELAY Connections (DHT Port) */ - udpTypes[RSUDP_TOU_RECVER_RELAY_IDX] = TOU_RECEIVER_TYPE_UDPRELAY; - mDhtStack->addReceiver(udpReceivers[RSUDP_TOU_RECVER_RELAY_IDX]); - - // LAST ON THIS STACK IS STANDARD DIRECT TOU - udpReceivers[RSUDP_TOU_RECVER_DIRECT_IDX] = new UdpPeerReceiver(mDhtStack); /* standard DIRECT Connections (DHT Port) */ - udpTypes[RSUDP_TOU_RECVER_DIRECT_IDX] = TOU_RECEIVER_TYPE_UDPPEER; - mDhtStack->addReceiver(udpReceivers[RSUDP_TOU_RECVER_DIRECT_IDX]); - - /* install external Pointer for Interface */ - rsDht = mBitDht; - - // NOW WE BUILD THE SECOND STACK. - // Create the Second UdpStack... Port should be random (but openable!). - // We do this by binding to xx.xx.xx.xx:0 which which gives us a random port. - - struct sockaddr_in sndladdr; - sockaddr_clear(&sndladdr); - -#ifdef LOCALNET_TESTING - - // // HACK Proxy Port near Dht Port - For Relay Testing. - // uint16_t rndport = rsInitConfig->port + 3; - // sndladdr.sin_port = htons(rndport); - - mProxyStack = new rsFixedUdpStack(UDP_TEST_RESTRICTED_LAYER, sndladdr); - - /* portRestrictions already parsed */ - if (doPortRestrictions) - { - RestrictedUdpLayer *url = (RestrictedUdpLayer *) mProxyStack->getUdpLayer(); - url->addRestrictedPortRange(lport, uport); - } -#else - mProxyStack = new rsFixedUdpStack(sndladdr); -#endif - -#ifdef RS_USE_DHT_STUNNER - // FIRSTLY THE PROXY STUNNER. - UdpStunner *mProxyStunner = new UdpStunner(mProxyStack); - mProxyStunner->setTargetStunPeriod(300); /* slow (5mins) */ - mProxyStack->addReceiver(mProxyStunner); - -#ifdef LOCALNET_TESTING - mProxyStunner->SetAcceptLocalNet(); -#endif -#endif // RS_USE_DHT_STUNNER - - - // FINALLY THE PROXY UDP CONNECTIONS - udpReceivers[RSUDP_TOU_RECVER_PROXY_IDX] = new UdpPeerReceiver(mProxyStack); /* PROXY Connections (Alt UDP Port) */ - udpTypes[RSUDP_TOU_RECVER_PROXY_IDX] = TOU_RECEIVER_TYPE_UDPPEER; - mProxyStack->addReceiver(udpReceivers[RSUDP_TOU_RECVER_PROXY_IDX]); - - // REAL INITIALISATION - WITH THREE MODES - tou_init((void **) udpReceivers, udpTypes, RSUDP_NUM_TOU_RECVERS); - -#ifdef RS_USE_DHT_STUNNER - mBitDht->setupConnectBits(mDhtStunner, mProxyStunner, mRelay); -#else // RS_USE_DHT_STUNNER - mBitDht->setupConnectBits(mRelay); -#endif // RS_USE_DHT_STUNNER - -#ifdef RS_USE_DHT_STUNNER - mNetMgr->setAddrAssist(new stunAddrAssist(mDhtStunner), new stunAddrAssist(mProxyStunner)); -#endif // RS_USE_DHT_STUNNER - // #else //RS_USE_BITDHT - // /* install NULL Pointer for rsDht Interface */ - // rsDht = NULL; -#endif //RS_USE_BITDHT - } - - - /**************************** BITDHT ***********************************/ - - p3ServiceControl *serviceCtrl = new p3ServiceControl(mLinkMgr); - rsServiceControl = serviceCtrl; - - pqih = new pqisslpersongrp(serviceCtrl, flags, mPeerMgr); - //pqih = new pqipersongrpDummy(none, flags); - - serviceCtrl->setServiceServer(pqih) ; - -#ifdef RS_EMBEDED_FRIEND_SERVER - // setup friend server - rsFriendServer = new FriendServerManager(); -#endif - - /****** New Ft Server **** !!! */ - ftServer *ftserver = new ftServer(mPeerMgr, serviceCtrl); - ftserver->setConfigDirectory(RsAccounts::AccountDirectory()); - - ftserver->SetupFtServer() ; - - /* setup any extra bits (Default Paths) */ - ftserver->setPartialsDirectory(emergencyPartialsDir); - ftserver->setDownloadDirectory(emergencySaveDir); - - /* This should be set by config ... there is no default */ - //ftserver->setSharedDirectories(fileList); - - rsFiles = ftserver; - - std::vector plugins_directories ; - -#ifdef __APPLE__ - plugins_directories.push_back(RsAccounts::systemDataDirectory()) ; -#endif -#if !defined(WINDOWS_SYS) && defined(PLUGIN_DIR) - plugins_directories.push_back(std::string(PLUGIN_DIR)) ; -#endif - std::string extensions_dir = RsAccounts::ConfigDirectory() + "/extensions6/" ; - plugins_directories.push_back(extensions_dir) ; - - if(!RsDirUtil::checkCreateDirectory(extensions_dir)) - std::cerr << "(EE) Cannot create extensions directory " << extensions_dir - << ". This is not mandatory, but you probably have a permission problem." << std::endl; - -#ifdef DEBUG_PLUGIN_SYSTEM - plugins_directories.push_back(".") ; // this list should be saved/set to some correct value. - // possible entries include: /usr/lib/retroshare, ~/.retroshare/extensions/, etc. -#endif - - mPluginsManager = new RsPluginManager(rsInitConfig->main_executable_hash) ; - rsPlugins = mPluginsManager ; - mConfigMgr->addConfiguration("plugins.cfg", mPluginsManager); - mPluginsManager->loadConfiguration() ; - - // These are needed to load plugins: plugin devs might want to know the place of - // cache directories, get pointers to cache strapper, or access ownId() - // - mPluginsManager->setServiceControl(serviceCtrl) ; - - // Now load the plugins. This parses the available SO/DLL files for known symbols. - // - mPluginsManager->loadPlugins(plugins_directories) ; - - // Also load some plugins explicitly. This is helpful for - // - developping plugins - // - std::vector programatically_inserted_plugins ; - - // Push your own plugins into this list, before the call: - // - // programatically_inserted_plugins.push_back(myCoolPlugin) ; - // - mPluginsManager->loadPlugins(programatically_inserted_plugins) ; - -#ifdef RS_JSONAPI - // add jsonapi server to config manager so that it can save/load its tokens - if(rsJsonApi) rsJsonApi->connectToConfigManager(*mConfigMgr); -#endif - - /**** Reputation system ****/ - - p3GxsReputation *mReputations = new p3GxsReputation(mLinkMgr) ; - rsReputations = mReputations ; - -#ifdef RS_ENABLE_GXS - - std::string currGxsDir = RsAccounts::AccountDirectory() + "/gxs"; - RsDirUtil::checkCreateDirectory(currGxsDir); - - RsNxsNetMgr* nxsMgr = new RsNxsNetMgrImpl(serviceCtrl); - - /**** GXS Dist sync service ****/ - -#ifdef RS_USE_GXS_DISTANT_SYNC - RsGxsNetTunnelService *mGxsNetTunnel = new RsGxsNetTunnelService ; - rsGxsDistSync = mGxsNetTunnel ; -#else - RsGxsNetTunnelService *mGxsNetTunnel = NULL ; -#endif - - /**** Identity service ****/ - - RsGeneralDataService* gxsid_ds = new RsDataService(currGxsDir + "/", "gxsid_db", - RS_SERVICE_GXS_TYPE_GXSID, NULL, rsInitConfig->gxs_passwd); - - // init gxs services - PgpAuxUtils *pgpAuxUtils = new PgpAuxUtilsImpl(); - p3IdService *mGxsIdService = new p3IdService(gxsid_ds, NULL, pgpAuxUtils); - - // circles created here, as needed by Ids. - RsGeneralDataService* gxscircles_ds = new RsDataService(currGxsDir + "/", "gxscircles_db", - RS_SERVICE_GXS_TYPE_GXSCIRCLE, NULL, rsInitConfig->gxs_passwd); - - // create GxsCircles - early, as IDs need it. - p3GxsCircles *mGxsCircles = new p3GxsCircles(gxscircles_ds, NULL, mGxsIdService, pgpAuxUtils); - - // create GXS ID service - RsGxsNetService* gxsid_ns = new RsGxsNetService( - RS_SERVICE_GXS_TYPE_GXSID, gxsid_ds, nxsMgr, - mGxsIdService, mGxsIdService->getServiceInfo(), - mReputations, mGxsCircles,mGxsIdService, - pgpAuxUtils,mGxsNetTunnel, - false,false,true); // don't synchronise group automatic (need explicit group request) - // don't sync messages at all. - // allow distsync, so that we can grab GXS id requests for other services - - // Normally we wouldn't need this (we do in other service): - // mGxsIdService->setNetworkExchangeService(gxsid_ns) ; - // ...since GxsIds are propagated manually. But that requires the gen exchange of GXSids to - // constantly test that mNetService is not null. The call below is to make the service aware of the - // netService so that it can request the missing ids. We'll need to fix this. - - mGxsIdService->setNes(gxsid_ns); - - /**** GxsCircle service ****/ - - // create GXS Circle service - RsGxsNetService* gxscircles_ns = new RsGxsNetService( - RS_SERVICE_GXS_TYPE_GXSCIRCLE, gxscircles_ds, nxsMgr, - mGxsCircles, mGxsCircles->getServiceInfo(), - mReputations, mGxsCircles,mGxsIdService, - pgpAuxUtils); - - mGxsCircles->setNetworkExchangeService(gxscircles_ns) ; - - /**** Posted GXS service ****/ - - RsGeneralDataService* posted_ds = new RsDataService(currGxsDir + "/", "posted_db", - RS_SERVICE_GXS_TYPE_POSTED, - NULL, rsInitConfig->gxs_passwd); - - p3Posted *mPosted = new p3Posted(posted_ds, NULL, mGxsIdService); - - // create GXS photo service - RsGxsNetService* posted_ns = new RsGxsNetService( - RS_SERVICE_GXS_TYPE_POSTED, posted_ds, nxsMgr, - mPosted, mPosted->getServiceInfo(), - mReputations, mGxsCircles,mGxsIdService, - pgpAuxUtils); - - mPosted->setNetworkExchangeService(posted_ns) ; - - /**** Wiki GXS service ****/ - -#ifdef RS_USE_WIKI - RsGeneralDataService* wiki_ds = new RsDataService(currGxsDir + "/", "wiki_db", - RS_SERVICE_GXS_TYPE_WIKI, - NULL, rsInitConfig->gxs_passwd); - - p3Wiki *mWiki = new p3Wiki(wiki_ds, NULL, mGxsIdService); - // create GXS wiki service - RsGxsNetService* wiki_ns = new RsGxsNetService( - RS_SERVICE_GXS_TYPE_WIKI, wiki_ds, nxsMgr, - mWiki, mWiki->getServiceInfo(), - mReputations, mGxsCircles, mGxsIdService, - pgpAuxUtils); - - mWiki->setNetworkExchangeService(wiki_ns) ; -#endif - - /************************* Forum GXS service ******************************/ - - RsGeneralDataService* gxsforums_ds = new RsDataService( - currGxsDir + "/", "gxsforums_db", RS_SERVICE_GXS_TYPE_FORUMS, - nullptr, rsInitConfig->gxs_passwd ); - - p3GxsForums* mGxsForums = new p3GxsForums( - gxsforums_ds, nullptr, mGxsIdService ); - - RsGxsNetTunnelService* gxsForumsTunnelService = nullptr; -#ifdef RS_DEEP_FORUMS_INDEX - gxsForumsTunnelService = mGxsNetTunnel; -#endif - - RsGxsNetService* gxsforums_ns = new RsGxsNetService( - RS_SERVICE_GXS_TYPE_FORUMS, gxsforums_ds, nxsMgr, mGxsForums, - mGxsForums->getServiceInfo(), mReputations, mGxsCircles, - mGxsIdService, pgpAuxUtils, gxsForumsTunnelService ); - mGxsForums->setNetworkExchangeService(gxsforums_ns); - - - /**** Channel GXS service ****/ - - RsGeneralDataService* gxschannels_ds = new RsDataService(currGxsDir + "/", "gxschannels_db", - RS_SERVICE_GXS_TYPE_CHANNELS, NULL, rsInitConfig->gxs_passwd); - - p3GxsChannels *mGxsChannels = new p3GxsChannels(gxschannels_ds, NULL, mGxsIdService); - - // create GXS photo service - RsGxsNetService* gxschannels_ns = new RsGxsNetService( - RS_SERVICE_GXS_TYPE_CHANNELS, gxschannels_ds, nxsMgr, - mGxsChannels, mGxsChannels->getServiceInfo(), - mReputations, mGxsCircles,mGxsIdService, - pgpAuxUtils,mGxsNetTunnel,true,true,true); - - mGxsChannels->setNetworkExchangeService(gxschannels_ns) ; - -#ifdef RS_USE_PHOTO - /**** Photo service ****/ - RsGeneralDataService* photo_ds = new RsDataService(currGxsDir + "/", "photoV2_db", - RS_SERVICE_GXS_TYPE_PHOTO, NULL, rsInitConfig->gxs_passwd); - - // init gxs services - p3PhotoService *mPhoto = new p3PhotoService(photo_ds, NULL, mGxsIdService); - - // create GXS photo service - RsGxsNetService* photo_ns = new RsGxsNetService( - RS_SERVICE_GXS_TYPE_PHOTO, photo_ds, nxsMgr, - mPhoto, mPhoto->getServiceInfo(), - mReputations, mGxsCircles,mGxsIdService, - pgpAuxUtils); - - mPhoto->setNetworkExchangeService(photo_ns); -#endif - -#ifdef RS_USE_WIRE - /**** Wire GXS service ****/ - RsGeneralDataService* wire_ds = new RsDataService(currGxsDir + "/", "wire_db", - RS_SERVICE_GXS_TYPE_WIRE, NULL, rsInitConfig->gxs_passwd); - - p3Wire *mWire = new p3Wire(wire_ds, NULL, mGxsIdService); - - // create GXS photo service - RsGxsNetService* wire_ns = new RsGxsNetService( - RS_SERVICE_GXS_TYPE_WIRE, wire_ds, nxsMgr, - mWire, mWire->getServiceInfo(), - mReputations, mGxsCircles,mGxsIdService, - pgpAuxUtils); - - mWire->setNetworkExchangeService(wire_ns); -#endif - // now add to p3service - pqih->addService(gxsid_ns, true); - pqih->addService(gxscircles_ns, true); - pqih->addService(posted_ns, true); -#ifdef RS_USE_WIKI - pqih->addService(wiki_ns, true); -#endif - pqih->addService(gxsforums_ns, true); - pqih->addService(gxschannels_ns, true); -#ifdef RS_USE_PHOTO - pqih->addService(photo_ns, true); -#endif -#ifdef RS_USE_WIRE - pqih->addService(wire_ns, true); -#endif - -# ifdef RS_GXS_TRANS - RsGeneralDataService* gxstrans_ds = new RsDataService( - currGxsDir + "/", "gxstrans_db", RS_SERVICE_TYPE_GXS_TRANS, - NULL, rsInitConfig->gxs_passwd ); - mGxsTrans = new p3GxsTrans(gxstrans_ds, NULL, *mGxsIdService); - - RsGxsNetService* gxstrans_ns = new RsGxsNetService( - RS_SERVICE_TYPE_GXS_TRANS, gxstrans_ds, nxsMgr, mGxsTrans, - mGxsTrans->getServiceInfo(), mReputations, mGxsCircles, - mGxsIdService, pgpAuxUtils,NULL,true,true,false,p3GxsTrans::GXS_STORAGE_PERIOD,p3GxsTrans::GXS_SYNC_PERIOD); - - mGxsTrans->setNetworkExchangeService(gxstrans_ns); - pqih->addService(gxstrans_ns, true); -# endif // RS_GXS_TRANS - - // remove pword from memory - rsInitConfig->gxs_passwd = ""; - -#endif // RS_ENABLE_GXS. - - /* create Services */ - p3ServiceInfo *serviceInfo = new p3ServiceInfo(serviceCtrl); - mDisc = new p3discovery2(mPeerMgr, mLinkMgr, mNetMgr, serviceCtrl,mGxsIdService); - mHeart = new p3heartbeat(serviceCtrl, pqih); - msgSrv = new p3MsgService( serviceCtrl, mGxsIdService, *mGxsTrans ); - chatSrv = new p3ChatService( serviceCtrl,mGxsIdService, mLinkMgr, - mHistoryMgr, *mGxsTrans ); - mStatusSrv = new p3StatusService(serviceCtrl); - -#ifdef RS_BROADCAST_DISCOVERY - BroadcastDiscoveryService* broadcastDiscoveryService = - new BroadcastDiscoveryService(*rsPeers); - rsBroadcastDiscovery = broadcastDiscoveryService; -#endif // def RS_BROADCAST_DISCOVERY - -#ifdef ENABLE_GROUTER - p3GRouter *gr = new p3GRouter(serviceCtrl,mGxsIdService) ; - rsGRouter = gr ; - pqih->addService(gr,true) ; -#endif - - p3FileDatabase *fdb = new p3FileDatabase(serviceCtrl) ; - p3turtle *tr = new p3turtle(serviceCtrl,mLinkMgr) ; - rsTurtle = tr ; - pqih -> addService(tr,true); - pqih -> addService(fdb,true); - pqih -> addService(ftserver,true); - - mGxsTunnels = new p3GxsTunnelService(mGxsIdService) ; - mGxsTunnels->connectToTurtleRouter(tr) ; - rsGxsTunnel = mGxsTunnels; - - mGxsNetTunnel->connectToTurtleRouter(tr) ; - - rsGossipDiscovery.reset(mDisc); - rsMsgs = new p3Msgs(msgSrv, chatSrv); - - // connect components to turtle router. - - ftserver->connectToTurtleRouter(tr) ; - ftserver->connectToFileDatabase(fdb) ; - chatSrv->connectToGxsTunnelService(mGxsTunnels) ; - gr->connectToTurtleRouter(tr) ; -#ifdef ENABLE_GROUTER - msgSrv->connectToGlobalRouter(gr) ; -#endif - - pqih -> addService(serviceInfo,true); - pqih -> addService(mHeart,true); - pqih -> addService(mDisc,true); - pqih -> addService(msgSrv,true); - pqih -> addService(chatSrv,true); - pqih -> addService(mStatusSrv,true); - pqih -> addService(mGxsTunnels,true); - pqih -> addService(mReputations,true); - - // set interfaces for plugins - // - RsPlugInInterfaces interfaces; - interfaces.mFiles = rsFiles; - interfaces.mPeers = rsPeers; - interfaces.mMsgs = rsMsgs; - interfaces.mTurtle = rsTurtle; - interfaces.mDisc = rsDisc; -#ifdef RS_USE_BITDHT - interfaces.mDht = rsDht; -#else - interfaces.mDht = NULL; -#endif - interfaces.mNotify = mNotify; - interfaces.mServiceControl = serviceCtrl; - interfaces.mPluginHandler = mPluginsManager; - // gxs - interfaces.mGxsDir = currGxsDir; - interfaces.mIdentity = mGxsIdService; - interfaces.mRsNxsNetMgr = nxsMgr; - interfaces.mGxsIdService = mGxsIdService; - interfaces.mGxsCirlces = mGxsCircles; - interfaces.mPgpAuxUtils = pgpAuxUtils; - interfaces.mGxsForums = mGxsForums; - interfaces.mGxsChannels = mGxsChannels; - interfaces.mGxsTunnels = mGxsTunnels; - interfaces.mReputations = mReputations; - - mPluginsManager->setInterfaces(interfaces); - - // now add plugin objects inside the loop: - // - client services provided by plugins. - // - cache services provided by plugins. - // - mPluginsManager->registerClientServices(pqih) ; - mPluginsManager->registerCacheServices() ; - - - -#ifdef RS_RTT - p3rtt *mRtt = new p3rtt(serviceCtrl); - pqih -> addService(mRtt, true); - rsRtt = mRtt; -#endif - - // new services to test. - - p3BanList *mBanList = NULL; - - if(!RsAccounts::isHiddenNode()) - { - mBanList = new p3BanList(serviceCtrl, mNetMgr); - rsBanList = mBanList ; - pqih -> addService(mBanList, true); - } - else - rsBanList = NULL ; - - p3BandwidthControl *mBwCtrl = new p3BandwidthControl(pqih); - pqih -> addService(mBwCtrl, true); - -#ifdef SERVICES_DSDV - p3Dsdv *mDsdv = new p3Dsdv(serviceCtrl); - pqih -> addService(mDsdv, true); - rsDsdv = mDsdv; - mDsdv->addTestService(); -#endif - - /**************************************************************************/ - - if(!RsAccounts::isHiddenNode()) - { -#ifdef RS_USE_BITDHT - mBitDht->setupPeerSharer(mBanList); - - mNetMgr->addNetAssistConnect(1, mBitDht); - mNetMgr->addNetListener(mDhtStack); - mNetMgr->addNetListener(mProxyStack); -#endif - -#if defined(RS_USE_LIBMINIUPNPC) || defined(RS_USE_LIBUPNP) - // Original UPnP Interface. - pqiNetAssistFirewall *mUpnpMgr = new upnphandler(); - mNetMgr->addNetAssistFirewall(1, mUpnpMgr); -#endif // defined(RS_USE_LIBMINIUPNPC) || defined(RS_USE_LIBUPNP) - } - - /**************************************************************************/ - /* need to Monitor too! */ - mLinkMgr->addMonitor(pqih); - mLinkMgr->addMonitor(serviceCtrl); - mLinkMgr->addMonitor(serviceInfo); - - // Services that have been changed to pqiServiceMonitor - serviceCtrl->registerServiceMonitor(msgSrv, msgSrv->getServiceInfo().mServiceType); - serviceCtrl->registerServiceMonitor(mDisc, mDisc->getServiceInfo().mServiceType); - serviceCtrl->registerServiceMonitor(mStatusSrv, mStatusSrv->getServiceInfo().mServiceType); - serviceCtrl->registerServiceMonitor(chatSrv, chatSrv->getServiceInfo().mServiceType); - serviceCtrl->registerServiceMonitor(mBwCtrl, mBwCtrl->getServiceInfo().mServiceType); - - /**************************************************************************/ - // Turtle search for GXS services - - mGxsNetTunnel->registerSearchableService(gxschannels_ns); -#ifdef RS_DEEP_FORUMS_INDEX - mGxsNetTunnel->registerSearchableService(gxsforums_ns); -#endif - - /**************************************************************************/ - - //mConfigMgr->addConfiguration("ftserver.cfg", ftserver); - // - AuthPGP::registerToConfigMgr(std::string("gpg_prefs.cfg"),mConfigMgr); - - mConfigMgr->addConfiguration("gxsnettunnel.cfg", mGxsNetTunnel); - mConfigMgr->addConfiguration("peers.cfg" , mPeerMgr); - mConfigMgr->addConfiguration("general.cfg" , mGeneralConfig); - mConfigMgr->addConfiguration("msgs.cfg" , msgSrv); - mConfigMgr->addConfiguration("chat.cfg" , chatSrv); - mConfigMgr->addConfiguration("p3History.cfg" , mHistoryMgr); - mConfigMgr->addConfiguration("p3Status.cfg" , mStatusSrv); - mConfigMgr->addConfiguration("turtle.cfg" , tr); - - if(mBanList != NULL) - mConfigMgr->addConfiguration("banlist.cfg" , mBanList); - - mConfigMgr->addConfiguration("servicecontrol.cfg", serviceCtrl); - mConfigMgr->addConfiguration("reputations.cfg" , mReputations); -#ifdef ENABLE_GROUTER - mConfigMgr->addConfiguration("grouter.cfg" , gr); -#endif - -#ifdef RS_USE_BITDHT - if(mBitDht != NULL) - mConfigMgr->addConfiguration("bitdht.cfg" , mBitDht); -#endif - -#ifdef RS_ENABLE_GXS - -# ifdef RS_GXS_TRANS - mConfigMgr->addConfiguration("gxs_trans_ns.cfg", gxstrans_ns); - mConfigMgr->addConfiguration("gxs_trans.cfg" , mGxsTrans); -# endif // RS_GXS_TRANS - - mConfigMgr->addConfiguration("p3identity.cfg" , mGxsIdService); - mConfigMgr->addConfiguration("identity.cfg" , gxsid_ns); - mConfigMgr->addConfiguration("gxsforums.cfg" , gxsforums_ns); - mConfigMgr->addConfiguration("gxsforums_srv.cfg" , mGxsForums); - mConfigMgr->addConfiguration("gxschannels.cfg" , gxschannels_ns); - mConfigMgr->addConfiguration("gxschannels_srv.cfg", mGxsChannels); - mConfigMgr->addConfiguration("gxscircles.cfg" , gxscircles_ns); - mConfigMgr->addConfiguration("gxscircles_srv.cfg" , mGxsCircles); - mConfigMgr->addConfiguration("posted.cfg" , posted_ns); - mConfigMgr->addConfiguration("gxsposted_srv.cfg" , mPosted); -#ifdef RS_USE_WIKI - mConfigMgr->addConfiguration("wiki.cfg", wiki_ns); -#endif -#ifdef RS_USE_PHOTO - mConfigMgr->addConfiguration("photo.cfg", photo_ns); -#endif -#ifdef RS_USE_WIRE - mConfigMgr->addConfiguration("wire.cfg", wire_ns); -#endif -#endif //RS_ENABLE_GXS -#ifdef RS_USE_I2P_SAM3 - // to make migration easiert, SAM will use BOBs configuration, as they are compatible / the same. - mConfigMgr->addConfiguration("I2PBOB.cfg", mI2pSam3); -#endif - - mPluginsManager->addConfigurations(mConfigMgr) ; - - ftserver->addConfiguration(mConfigMgr); - - /**************************************************************************/ - /* (2) Load configuration files */ - /**************************************************************************/ - std::cerr << "(2) Load configuration files" << std::endl; - - mConfigMgr->loadConfiguration(); - - /**************************************************************************/ - /* trigger generalConfig loading for classes that require it */ - /**************************************************************************/ - p3ServerConfig *serverConfig = new p3ServerConfig(mPeerMgr, mLinkMgr, mNetMgr, pqih, mGeneralConfig); - serverConfig->load_config(); - - /**************************************************************************/ - /* Force Any Configuration before Startup (After Load) */ - /**************************************************************************/ - std::cerr << "Force Any Configuration before Startup (After Load)" << std::endl; - - if (rsInitConfig->forceLocalAddr) - { - struct sockaddr_storage laddr; - - /* clean sockaddr before setting values (MaxOSX) */ - sockaddr_storage_clear(laddr); - - struct sockaddr_in *lap = (struct sockaddr_in *) &laddr; - - lap->sin_family = AF_INET; - lap->sin_port = htons(rsInitConfig->port); - - // universal - lap->sin_addr.s_addr = inet_addr(rsInitConfig->inet.c_str()); - - mPeerMgr->setLocalAddress(ownId, laddr); - } - - if (rsInitConfig->forceExtPort) - { - mPeerMgr->setOwnNetworkMode(RS_NET_MODE_EXT); - mPeerMgr->setOwnVisState(RS_VS_DISC_FULL, RS_VS_DHT_FULL); - } - - if (rsInitConfig->hiddenNodeSet) - { - std::cout << "RsServer::StartupRetroShare setting up hidden locations" << std::endl; - - if (rsInitConfig->hiddenNodeI2P) { - std::cout << "RsServer::StartupRetroShare setting up SAMv3" << std::endl; - - // we need a local port! - mNetMgr->checkNetAddress(); - - // add i2p proxy - sockaddr_storage i2pInstance; - sockaddr_storage_ipv4_aton(i2pInstance, rsInitConfig->hiddenNodeAddress.c_str()); - mPeerMgr->setProxyServerAddress(RS_HIDDEN_TYPE_I2P, i2pInstance); - - std::string addr; // will be set by auto proxy service - uint16_t port; // unused by SAM - - bool r = autoProxy->initialSetup(autoProxyType::I2PSAM3, addr, port); - - if (r && !addr.empty()) { - mPeerMgr->setupHiddenNode(addr, port); - - // now enable SAM - samSettings ss; - autoProxy->taskSync(autoProxyType::I2PSAM3, autoProxyTask::getSettings, &ss); - ss.enable = true; - autoProxy->taskSync(autoProxyType::I2PSAM3, autoProxyTask::setSettings, &ss); - } else { - std::cerr << "RsServer::StartupRetroShare failed to receive keys" << std::endl; - /// TODO add notify for failed i2p setup - } - } else { - mPeerMgr->setupHiddenNode(rsInitConfig->hiddenNodeAddress, rsInitConfig->hiddenNodePort); - } - - std::cout << "RsServer::StartupRetroShare hidden location set up" << std::endl; - } - else if (isHiddenNode) - { - mPeerMgr->forceHiddenNode(); - } - - if (!rsInitConfig->opModeStr.empty()) - { - rsConfig->setOperatingMode(rsInitConfig->opModeStr); - } - mNetMgr -> checkNetAddress(); - - if (rsInitConfig->hiddenNodeSet) { - // newly created location - // mNetMgr->checkNetAddress() will setup ports for us - -#if 0 // this was used for BOB but is not requires for SAMv3 - // trigger updates for auto proxy services - std::vector types; - rsAutoProxyMonitor::taskSync(types, autoProxyTask::reloadConfig); -#endif - } - - /**************************************************************************/ - /* startup (stuff dependent on Ids/peers is after this point) */ - /**************************************************************************/ - autoProxy->startAll(); - - pqih->init_listener(); - mNetMgr->addNetListener(pqih); /* add listener so we can reset all sockets later */ - - /**************************************************************************/ - /* load caches and secondary data */ - /**************************************************************************/ - - // Clear the News Feeds that are generated by Initial Cache Loading. - - /* Peer stuff is up to date */ - - //getPqiNotify()->ClearFeedItems(RS_FEED_ITEM_CHAT_NEW); - mNotify->ClearFeedItems(RS_FEED_ITEM_MESSAGE); - //getPqiNotify()->ClearFeedItems(RS_FEED_ITEM_FILES_NEW); - - /**************************************************************************/ - /* Add AuthGPG services */ - /**************************************************************************/ - - //AuthGPG::addService(mDisc); - - /**************************************************************************/ - /* Force Any Last Configuration Options */ - /**************************************************************************/ - - /**************************************************************************/ - /* Start up Threads */ - /**************************************************************************/ - - // auto proxy threads -#ifdef RS_USE_I2P_SAM3 - startServiceThread(mI2pSam3, "I2P-SAM3"); -#endif - -#ifdef RS_ENABLE_GXS - // Must Set the GXS pointers before starting threads. - rsIdentity = mGxsIdService; - rsGxsCircles = mGxsCircles; -#if RS_USE_WIKI - rsWiki = mWiki; -#endif - rsPosted = mPosted; - rsGxsForums = mGxsForums; - rsGxsChannels = mGxsChannels; - rsGxsTrans = mGxsTrans; - -#if RS_USE_PHOTO - rsPhoto = mPhoto; -#endif -#if RS_USE_WIRE - rsWire = mWire; -#endif - - /*** start up GXS core runner ***/ - - startServiceThread(mGxsNetTunnel, "gxs net tunnel"); - startServiceThread(mGxsIdService, "gxs id"); - startServiceThread(mGxsCircles, "gxs circle"); - startServiceThread(mPosted, "gxs posted"); -#if RS_USE_WIKI - startServiceThread(mWiki, "gxs wiki"); -#endif - startServiceThread(mGxsForums, "gxs forums"); - startServiceThread(mGxsChannels, "gxs channels"); - -#if RS_USE_PHOTO - startServiceThread(mPhoto, "gxs photo"); -#endif -#if RS_USE_WIRE - startServiceThread(mWire, "gxs wire"); -#endif - - // cores ready start up GXS net servers - startServiceThread(gxsid_ns, "gxs id ns"); - startServiceThread(gxscircles_ns, "gxs circle ns"); - startServiceThread(posted_ns, "gxs posted ns"); -#if RS_USE_WIKI - startServiceThread(wiki_ns, "gxs wiki ns"); -#endif - startServiceThread(gxsforums_ns, "gxs forums ns"); - startServiceThread(gxschannels_ns, "gxs channels ns"); - -#if RS_USE_PHOTO - startServiceThread(photo_ns, "gxs photo ns"); -#endif -#if RS_USE_WIRE - startServiceThread(wire_ns, "gxs wire ns"); -#endif - -# ifdef RS_GXS_TRANS - startServiceThread(mGxsTrans, "gxs trans"); - startServiceThread(gxstrans_ns, "gxs trans ns"); -# endif // def RS_GXS_TRANS - -#endif // RS_ENABLE_GXS - -#ifdef RS_BROADCAST_DISCOVERY - startServiceThread(broadcastDiscoveryService, "Broadcast Discovery"); -#endif // def RS_BROADCAST_DISCOVERY - - ftserver->StartupThreads(); - ftserver->ResumeTransfers(); - - //mDhtMgr->start(); -#ifdef RS_USE_BITDHT - if(mBitDht != NULL) - mBitDht->start(); -#endif - - /**************************************************************************/ - - // create loopback device, and add to pqisslgrp. - - SearchModule *mod = new SearchModule(); - pqiloopback *ploop = new pqiloopback(ownId); - - mod -> peerid = ownId; - mod -> pqi = ploop; - - pqih->AddSearchModule(mod); - - /* Setup GUI Interfaces. */ - - // rsDisc & RsMsgs done already. - rsBandwidthControl = mBwCtrl; - rsConfig = serverConfig; - - - rsStatus = new p3Status(mStatusSrv); - rsHistory = new p3History(mHistoryMgr); - - /* put a welcome message in! */ - if (isFirstTimeRun) - { - msgSrv->loadWelcomeMsg(); - ftserver->shareDownloadDirectory(true); - mGeneralConfig->saveConfiguration(); - } - - /* Startup this thread! */ - start("rs main") ; - - std::cerr << "========================================================================" << std::endl; - std::cerr << "== RsInit:: Retroshare core started ==" << std::endl; - std::cerr << "========================================================================" << std::endl; - - coreReady = true; - return 1; -} - -std::string RsInit::executablePath() -{ - if(rsInitConfig->mainExecutablePath.empty()) - { - RsErr() << "Main executable path not set! Plz call RsInit::InitRetroShare(conf) with conf.main_executable_path = argv[0]"; - assert(false); - } - - return rsInitConfig->mainExecutablePath; -} -bool RsInit::startAutoTor() -{ - std::cerr << "(II) node is an automated Tor node => launching Tor auto-configuration." << std::endl; - // Now that we know the Tor service running, and we know the SSL id, we can make sure it provides a viable hidden service - - std::string tor_hidden_service_dir = RsAccounts::AccountDirectory() + "/hidden_service/" ; - - RsTor::setTorDataDirectory(RsAccounts::ConfigDirectory() + "/tor/"); - RsTor::setHiddenServiceDirectory(tor_hidden_service_dir); // re-set it, because now it's changed to the specific location that is run - - RsDirUtil::checkCreateDirectory(std::string(tor_hidden_service_dir)) ; - - if(! RsTor::start() || RsTor::hasError()) - { - std::cerr << "(EE) Tor cannot be started on your system: "+RsTor::errorMessage() << std::endl ; - return false ; - } - std::cerr << "(II) Tor has been started." << std::endl; - - // now start/create the hidden service as needed. - - std::string service_id; - RsTor::setupHiddenService(); - - while(RsTor::torStatus() != RsTorStatus::READY && RsTor::getHiddenServiceStatus(service_id) != RsTorHiddenServiceStatus::ONLINE) // runs until some status is reached: either tor works, or it fails. - { - rstime::rs_usleep(0.5*1000*1000) ; - - std::cerr << "(II) Hidden service ID: " << service_id << ", status: " << (int)RsTor::getHiddenServiceStatus(service_id) << std::endl; - if(RsTor::hasError()) - { - std::string error_msg = RsTor::errorMessage(); - - std::cerr << "(EE) Tor hidden service cannot be started: " << error_msg << std::endl; - return false; - } - // process Qt event loop to deal with messages of online/offline info - // QCoreApplication::processEvents(); - } - return true; -} - -RsInit::LoadCertificateStatus RsLoginHelper::attemptLogin(const RsPeerId& account, const std::string& password) -{ - if(isLoggedIn()) return RsInit::ERR_ALREADY_RUNNING; - - { - if(!RsAccounts::SelectAccount(account)) - return RsInit::ERR_UNKNOWN; - - if(!password.empty()) - { - rsNotify->cachePgpPassphrase(password); - rsNotify->setDisableAskPassword(true); - } - std::string _ignore_lockFilePath; - RsInit::LoadCertificateStatus ret = RsInit::LockAndLoadCertificates(false, _ignore_lockFilePath); - - rsNotify->setDisableAskPassword(false) ; - rsNotify->clearPgpPassphrase() ; - - bool is_hidden_node = false; - bool is_auto_tor = false ; - bool is_first_time = false ; - - RsAccounts::getCurrentAccountOptions(is_hidden_node,is_auto_tor,is_first_time); - - if(is_auto_tor) - if(!RsInit::startAutoTor()) - return RsInit::ERR_CANNOT_CONFIGURE_TOR; - - if(ret == RsInit::OK && RsControl::instance()->StartupRetroShare() == 1) - return RsInit::OK; - - return ret; - } -} - -/*static*/ bool RsLoginHelper::collectEntropy(uint32_t bytes) -{ return RsInit::collectEntropy(bytes); } - -void RsLoginHelper::getLocations(std::vector& store) -{ - std::list locIds; - RsAccounts::GetAccountIds(locIds); - store.clear(); - - for(const RsPeerId& locId : locIds ) - { - Location l; l.mLocationId = locId; - std::string discardPgpMail; - RsAccounts::GetAccountDetails( locId, l.mPgpId, l.mPgpName, - discardPgpMail, l.mLocationName ); - store.push_back(l); - } -} - -std::error_condition RsLoginHelper::createLocationV2( - RsPeerId& locationId, RsPgpId& pgpId, - const std::string& locationName, const std::string& pgpName, - const std::string& password ) -{ - if(isLoggedIn()) return RsInitErrorNum::ALREADY_LOGGED_IN; - if(locationName.empty()) return RsInitErrorNum::INVALID_LOCATION_NAME; - if(pgpId.isNull() && pgpName.empty()) - return RsInitErrorNum::PGP_NAME_OR_ID_NEEDED; - - std::string errorMessage; - if(pgpId.isNull() && !RsAccounts::GeneratePGPCertificate( - pgpName, "", password, pgpId, 4096, errorMessage ) ) - { - RS_ERR("Failure creating PGP key: ", errorMessage); - return RsInitErrorNum::PGP_KEY_CREATION_FAILED; - } - - std::string sslPassword = - RsRandom::random_alphaNumericString(RsInit::getSslPwdLen()); - - rsNotify->cachePgpPassphrase(password); - rsNotify->setDisableAskPassword(true); - - bool ret = RsAccounts::createNewAccount( - pgpId, "", locationName, "", false, false, sslPassword, - locationId, errorMessage ); - if(!ret) - { - RS_ERR("Failure creating SSL key: ", errorMessage); - return RsInitErrorNum::SSL_KEY_CREATION_FAILED; - } - - RsInit::LoadPassword(sslPassword); - ret = (RsInit::OK == attemptLogin(locationId, password)); - rsNotify->setDisableAskPassword(false); - - return (ret ? std::error_condition() : RsInitErrorNum::LOGIN_FAILED); -} - -#if !RS_VERSION_AT_LEAST(0,6,6) -bool RsLoginHelper::createLocation( - RsLoginHelper::Location& l, const std::string& password, - std::string& errorMessage, bool makeHidden, bool makeAutoTor ) -{ - if(isLoggedIn()) return (errorMessage="Already Running", false); - - if(l.mLocationName.empty()) - { - errorMessage = "Location name is needed"; - return false; - } - - if(l.mPgpId.isNull() && l.mPgpName.empty()) - { - errorMessage = "Either PGP name or PGP id is needed"; - return false; - } - - if(l.mPgpId.isNull() && !RsAccounts::GeneratePGPCertificate( - l.mPgpName, "", password, l.mPgpId, 4096, errorMessage) ) - { - errorMessage = "Failure creating PGP key: " + errorMessage; - return false; - } - - std::string sslPassword = - RSRandom::random_alphaNumericString(RsInit::getSslPwdLen()); - - if(!rsNotify->cachePgpPassphrase(password)) return false; - if(!rsNotify->setDisableAskPassword(true)) return false; - - bool ret = RsAccounts::createNewAccount( - l.mPgpId, "", l.mLocationName, "", makeHidden, makeAutoTor, - sslPassword, l.mLocationId, errorMessage ); - - ret = ret && RsInit::LoadPassword(sslPassword); - ret = ret && RsInit::OK == attemptLogin(l.mLocationId, password); - - rsNotify->setDisableAskPassword(false); - return ret; -} -#endif // !RS_VERSION_AT_LEAST(0,6,6) - -bool RsLoginHelper::isLoggedIn() -{ - return RsControl::instance()->isReady(); -} - -void RsLoginHelper::Location::serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - RS_SERIAL_PROCESS(mLocationId); - RS_SERIAL_PROCESS(mPgpId); - RS_SERIAL_PROCESS(mLocationName); - RS_SERIAL_PROCESS(mPgpName); -} - -/*static*/ bool RsAccounts::getCurrentAccountId(RsPeerId& id) -{ - return rsAccountsDetails->getCurrentAccountId(id); -} diff --git a/libretroshare/src/rsserver/rsloginhandler.cc b/libretroshare/src/rsserver/rsloginhandler.cc deleted file mode 100644 index a0834b0af..000000000 --- a/libretroshare/src/rsserver/rsloginhandler.cc +++ /dev/null @@ -1,791 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: rsloginhandler.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 retroshare team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include -#include -#include -#include "rsloginhandler.h" -#include "util/rsdir.h" -#include "retroshare/rsinit.h" -#include "util/rsdebug.h" - -//#define DEBUG_RSLOGINHANDLER 1 - -bool RsLoginHandler::getSSLPassword( const RsPeerId& ssl_id, - bool enable_gpg_ask_passwd, - std::string& ssl_passwd ) -{ - -#ifdef RS_AUTOLOGIN - // First, see if autologin is available - if(tryAutoLogin(ssl_id,ssl_passwd)) return true; -#endif // RS_AUTOLOGIN - - // If we're not expecting to enter a passwd (e.g. test for autologin before - // display of the login window), safely respond false. - if(!enable_gpg_ask_passwd) return false; - - return getSSLPasswdFromGPGFile(ssl_id,ssl_passwd); -} - -bool RsLoginHandler::checkAndStoreSSLPasswdIntoGPGFile( - const RsPeerId& ssl_id, const std::string& ssl_passwd ) -{ - // We want to pursue login with gpg passwd. Let's do it: - FILE *sslPassphraseFile = RsDirUtil::rs_fopen( - getSSLPasswdFileName(ssl_id).c_str(), "r"); - - if(sslPassphraseFile) // already have it. - { - fclose(sslPassphraseFile); - return true ; - } - - bool ok = AuthPGP::encryptTextToFile( ssl_passwd, getSSLPasswdFileName(ssl_id)); - - if (!ok) std::cerr << "Encrypting went wrong !" << std::endl; - - return ok; -} - -bool RsLoginHandler::getSSLPasswdFromGPGFile(const RsPeerId& ssl_id,std::string& sslPassword) -{ - /* Let's read the password from an encrypted file, before check if there's - * an ssl_passpharese_file that we can decrypt with PGP */ - FILE *sslPassphraseFile = RsDirUtil::rs_fopen( - getSSLPasswdFileName(ssl_id).c_str(), "r"); - - if (!sslPassphraseFile) - { - std::cerr << "No password provided, and no sslPassphraseFile : " - << getSSLPasswdFileName(ssl_id).c_str() << std::endl; - return 0; - } - - fclose(sslPassphraseFile); - -#ifdef DEBUG_RSLOGINHANDLER - std::cerr << "opening sslPassphraseFile : " - << getSSLPasswdFileName(ssl_id).c_str() << std::endl; -#endif - - std::string plain; - if ( AuthPGP::decryptTextFromFile( plain, getSSLPasswdFileName(ssl_id)) ) - { - sslPassword = plain; -#ifdef DEBUG_RSLOGINHANDLER - if(sslPassword.length() > 0) - std::cerr << "Decrypting went ok !" << std::endl; - else - std::cerr << "Passphrase is empty!" << std::endl; -#endif - - return sslPassword.length() > 0 ; - } - else - { - sslPassword = ""; - std::cerr << "Error : decrypting went wrong !" << std::endl; - - return false; - } -} - - -std::string RsLoginHandler::getSSLPasswdFileName(const RsPeerId& /*ssl_id*/) -{ - return RsAccounts::AccountKeysDirectory() + "/" + "ssl_passphrase.pgp"; -} - -#ifdef RS_AUTOLOGIN - -#if defined(HAS_GNOME_KEYRING) || defined(__FreeBSD__) || defined(__OpenBSD__) -# include - -GnomeKeyringPasswordSchema my_schema = { - GNOME_KEYRING_ITEM_ENCRYPTION_KEY_PASSWORD, - { - { "RetroShare SSL Id", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, - { NULL, (GnomeKeyringAttributeType)0 } - }, - NULL, - NULL, - NULL -}; -#elif defined(HAS_LIBSECRET) -#include -const SecretSchema *libsecret_get_schema(void) -{ - static const SecretSchema the_schema = { - "org.Retroshare.Password", SECRET_SCHEMA_NONE, - { - { "RetroShare SSL Id", SECRET_SCHEMA_ATTRIBUTE_STRING }, - { "NULL", static_cast(0) }, - }, - 0,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr - }; - return &the_schema; -} -#endif - - -#ifdef __APPLE__ - /* OSX Headers */ - -#include -#include - -#endif - -/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -/* WINDOWS STRUCTURES FOR DPAPI */ - -#ifndef WINDOWS_SYS /* UNIX */ - -#include - -#else -/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - -#include -#include -#include - -/* -class CRYPTPROTECT_PROMPTSTRUCT; -*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef WINDOWS_SYS -#if defined(__CYGWIN__) - -typedef struct _CRYPTPROTECT_PROMPTSTRUCT { - DWORD cbSize; - DWORD dwPromptFlags; - HWND hwndApp; - LPCWSTR szPrompt; -} CRYPTPROTECT_PROMPTSTRUCT, - *PCRYPTPROTECT_PROMPTSTRUCT; - -#endif -#endif - -/* definitions for the two functions */ -__declspec (dllimport) -extern BOOL WINAPI CryptProtectData( - DATA_BLOB* pDataIn, - LPCWSTR szDataDescr, - DATA_BLOB* pOptionalEntropy, - PVOID pvReserved, - /* PVOID prompt, */ - /* CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, */ - CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, - DWORD dwFlags, - DATA_BLOB* pDataOut -); - -__declspec (dllimport) -extern BOOL WINAPI CryptUnprotectData( - DATA_BLOB* pDataIn, - LPWSTR* ppszDataDescr, - DATA_BLOB* pOptionalEntropy, - PVOID pvReserved, - /* PVOID prompt, */ - /* CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, */ - CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, - DWORD dwFlags, - DATA_BLOB* pDataOut -); - -#ifdef __cplusplus -} -#endif - -#endif - - -bool RsLoginHandler::tryAutoLogin(const RsPeerId& ssl_id,std::string& ssl_passwd) -{ -#ifdef DEBUG_RSLOGINHANDLER - std::cerr << "RsTryAutoLogin()" << std::endl; -#endif - - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef __HAIKU__ -#ifndef WINDOWS_SYS /* UNIX */ -#if defined(HAS_GNOME_KEYRING) || defined(__FreeBSD__) || defined(__OpenBSD__) - - gchar *passwd = NULL; - -#ifdef DEBUG_RSLOGINHANDLER - std::cerr << "Using attribute: " << ssl_id << std::endl; -#endif - if( gnome_keyring_find_password_sync(&my_schema, &passwd,"RetroShare SSL Id",ssl_id.toStdString().c_str(),NULL) == GNOME_KEYRING_RESULT_OK ) - { - std::cout << "Got SSL passwd ********************" /*<< passwd*/ << " from gnome keyring" << std::endl; - ssl_passwd = std::string(passwd); - return true ; - } - else - { -#ifdef DEBUG_RSLOGINHANDLER - std::cerr << "Could not get passwd from gnome keyring" << std::endl; -#endif - return false ; - } -#elif defined(HAS_LIBSECRET) - // do synchronous lookup - -#ifdef DEBUG_RSLOGINHANDLER - std::cerr << "Using attribute: " << ssl_id << std::endl; -#endif - - GError *error = nullptr; - gchar *password = secret_password_lookup_sync (libsecret_get_schema(), nullptr, &error, - "RetroShare SSL Id", ssl_id.toStdString().c_str(), - NULL); - - if (error) { - g_error_free (error); -#ifdef DEBUG_RSLOGINHANDLER - std::cerr << "Could not get passwd using libsecret: error" << std::endl; -#endif - return false; - } else if (!password) { - /* password will be null, if no matching password found */ -#ifdef DEBUG_RSLOGINHANDLER - std::cerr << "Could not get passwd using libsecret: not found" << std::endl; -#endif - return false; - } else { - std::cout << "Got SSL passwd ********************" /*<< passwd*/ << " using libsecret" << std::endl; - ssl_passwd = std::string(password); - - secret_password_free (password); - return true; - } -#ifdef DEBUG_RSLOGINHANDLER - std::cerr << "Could not get passwd from gnome keyring: unknown" << std::endl; -#endif - //return false; //Never used returned before -#else - /******************** OSX KeyChain stuff *****************************/ -#ifdef __APPLE__ - - std::cerr << "RsTryAutoLogin() OSX Version" << std::endl; - //Call SecKeychainFindGenericPassword to get a password from the keychain: - - void *passwordData = NULL; - UInt32 passwordLength = 0; - std::string idtemp = ssl_id.toStdString(); - const char *userId = idtemp.c_str(); - UInt32 uidLength = strlen(userId); - SecKeychainItemRef itemRef = NULL; - - OSStatus status = SecKeychainFindGenericPassword ( - NULL, // default keychain - 10, // length of service name - "Retroshare", // service name - uidLength, // length of account name - userId, // account name - &passwordLength, // length of password - &passwordData, // pointer to password data - &itemRef // the item reference - ); - - std::cerr << "RsTryAutoLogin() SecKeychainFindGenericPassword returned: " << status << std::endl; - - if (status != 0) - { - std::cerr << "RsTryAutoLogin() Error " << std::endl; - - /* error */ - if (status == errSecItemNotFound) - { - //Is password on keychain? - std::cerr << "RsTryAutoLogin() Error - Looks like password is not in KeyChain " << std::endl; - } - } - else - { - std::cerr << "RsTryAutoLogin() Password found on KeyChain! " << std::endl; - - /* load up password to correct location */ - ssl_passwd.clear(); - ssl_passwd.insert(0, (char*)passwordData, passwordLength); - } - - //Free the data allocated by SecKeychainFindGenericPassword: - - SecKeychainItemFreeContent ( - NULL, //No attribute data to release - passwordData //Release data buffer allocated by SecKeychainFindGenericPassword - ); - - if (itemRef) CFRelease(itemRef); - - return (status == 0); - - /******************** OSX KeyChain stuff *****************************/ -#endif // APPLE -#endif // HAS_GNOME_KEYRING / HAS_LIBSECRET -#else /******* WINDOWS BELOW *****/ - - /* try to load from file */ - std::string entropy = getSSLPasswdFileName(ssl_id); - /* get the data out */ - - DATA_BLOB DataIn; - DATA_BLOB DataEnt; - DATA_BLOB DataOut; - - BYTE *pbDataEnt =(BYTE *) strdup(entropy.c_str()); - DWORD cbDataEnt = strlen((char *)pbDataEnt)+1; - DataEnt.pbData = pbDataEnt; - DataEnt.cbData = cbDataEnt; - - char *dataptr = NULL; - int datalen = 0; - - /* open the data to the file */ - FILE *fp = RsDirUtil::rs_fopen(getAutologinFileName(ssl_id).c_str(), "rb"); - if (fp != NULL) - { - fseek(fp, 0, SEEK_END); - datalen = ftell(fp); - fseek(fp, 0, SEEK_SET); - dataptr = (char *) rs_malloc(datalen); - - if(dataptr == NULL) - { - fclose(fp); - return false; - } - fread(dataptr, 1, datalen, fp); - fclose(fp); - - /***** - std::cerr << "Data loaded from: " << passwdfile; - std::cerr << std::endl; - - std::cerr << "Size :"; - std::cerr << datalen << std::endl; - - for(unsigned int i = 0; i < datalen; i++) - { - std::cerr << std::setw(2) << (int) dataptr[i]; - std::cerr << " "; - } - std::cerr << std::endl; - *****/ - } - else - { - return false; - } - - BYTE *pbDataInput =(BYTE *) dataptr; - DWORD cbDataInput = datalen; - DataIn.pbData = pbDataInput; - DataIn.cbData = cbDataInput; - - - CRYPTPROTECT_PROMPTSTRUCT prom; - - prom.cbSize = sizeof(prom); - prom.dwPromptFlags = 0; - - - bool isDecrypt = CryptUnprotectData( - &DataIn, - NULL, - &DataEnt, /* entropy.c_str(), */ - NULL, // Reserved - &prom, // Opt. Prompt - 0, - &DataOut); - - if (isDecrypt) - { - //std::cerr << "Decrypted size: " << DataOut.cbData; - //std::cerr << std::endl; - if (DataOut.pbData[DataOut.cbData - 1] != '\0') - { - std::cerr << "Error: Decrypted Data not a string..."; - std::cerr << std::endl; - isDecrypt = false; - } - else - { - //std::cerr << "The decrypted data is: " << DataOut.pbData; - //std::cerr << std::endl; - ssl_passwd = (char *) DataOut.pbData; - } - } - else - { - std::cerr << "Decryption error!"; - std::cerr << std::endl; - } - - /* strings to be freed */ - free(pbDataInput); - free(pbDataEnt); - - /* generated data space */ - LocalFree(DataOut.pbData); - - return isDecrypt; -#endif -#endif - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - //return false; //never used -} - - -bool RsLoginHandler::enableAutoLogin(const RsPeerId& ssl_id,const std::string& ssl_passwd) -{ - std::cerr << "RsStoreAutoLogin()" << std::endl; - - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef __HAIKU__ -#ifndef WINDOWS_SYS /* UNIX */ -#if defined(HAS_GNOME_KEYRING) || defined(__FreeBSD__) || defined(__OpenBSD__) - if(GNOME_KEYRING_RESULT_OK == gnome_keyring_store_password_sync(&my_schema, NULL, (gchar*)("RetroShare password for SSL Id "+ssl_id.toStdString()).c_str(),(gchar*)ssl_passwd.c_str(),"RetroShare SSL Id",ssl_id.toStdString().c_str(),NULL)) - { - std::cout << "Stored passwd " << "************************" << " into gnome keyring" << std::endl; - return true ; - } - else - { - std::cerr << "Could not store passwd into gnome keyring" << std::endl; - return false ; - } -#elif defined(HAS_LIBSECRET) - // do synchronous store - - GError *error = nullptr; - secret_password_store_sync (libsecret_get_schema(), SECRET_COLLECTION_DEFAULT, - static_cast(("RetroShare password for SSL Id " + ssl_id.toStdString()).c_str()), - static_cast(ssl_passwd.c_str()), - nullptr, &error, - "RetroShare SSL Id", ssl_id.toStdString().c_str(), - NULL); - - if (error) { - RsErr() << __PRETTY_FUNCTION__ - << " Could not store passwd using libsecret with" - << " error.code=" << error->code - << " error.domain=" << error->domain - << " error.message=\"" << error->message << "\"" << std::endl; - if (error->code == 2) - RsErr() << "Do have a key wallet installed?" << std::endl - << "Like gnome-keyring or other using \"Secret Service\" by DBus." << std::endl; - g_error_free (error); - return false; - } - std::cout << "Stored passwd " << "************************" << " using libsecret" << std::endl; - return true; -#else -#ifdef __APPLE__ - /***************** OSX KEYCHAIN ****************/ - //Call SecKeychainAddGenericPassword to add a new password to the keychain: - - std::cerr << "RsStoreAutoLogin() OSX Version!" << std::endl; - - const void *password = ssl_passwd.c_str(); - UInt32 passwordLength = strlen(ssl_passwd.c_str()); - std::string idtemp = ssl_id.toStdString(); - const char *userid = idtemp.c_str(); - UInt32 uidLength = strlen(userid); - - OSStatus status = SecKeychainAddGenericPassword ( - NULL, // default keychain - 10, // length of service name - "Retroshare", // service name - uidLength, // length of account name - userid, // account name - passwordLength, // length of password - password, // pointer to password data - NULL // the item reference - ); - - std::cerr << "RsStoreAutoLogin() Call to SecKeychainAddGenericPassword returned: " << status << std::endl; - - if (status != 0) - { - std::cerr << "RsStoreAutoLogin() SecKeychainAddGenericPassword Failed" << std::endl; - return false; - } - return true; - - /***************** OSX KEYCHAIN ****************/ -#else -#ifdef TODO_CODE_ROTTEN - - /* WARNING: Autologin is inherently unsafe */ - FILE* helpFile = RsDirUtil::rs_fopen(getAutologinFileName.c_str(), "w"); - - if(helpFile == NULL){ - std::cerr << "\nRsStoreAutoLogin(): Failed to open help file\n" << std::endl; - return false; - } - - /* encrypt help */ - - const int DAT_LEN = ssl_passwd.length(); - const int KEY_DAT_LEN = RsInitConfig::load_cert.length(); - unsigned char* key_data = (unsigned char*)RsInitConfig::load_cert.c_str(); - unsigned char* indata = (unsigned char*)ssl_passwd.c_str(); - unsigned char* outdata = new unsigned char[DAT_LEN]; - - RC4_KEY* key = new RC4_KEY; - RC4_set_key(key, KEY_DAT_LEN, key_data); - - RC4(key, DAT_LEN, indata, outdata); - - - fprintf(helpFile, "%s", outdata); - fclose(helpFile); - - delete key; - delete[] outdata; - - - return true; -#endif // TODO_CODE_ROTTEN -#endif // __APPLE__ -#endif // HAS_GNOME_KEYRING / HAS_LIBSECRET -#else /* windows */ - - /* store password encrypted in a file */ - std::string entropy = getSSLPasswdFileName(ssl_id); - - DATA_BLOB DataIn; - DATA_BLOB DataEnt; - DATA_BLOB DataOut; - BYTE *pbDataInput = (BYTE *) strdup(ssl_passwd.c_str()); - DWORD cbDataInput = strlen((char *)pbDataInput)+1; - BYTE *pbDataEnt =(BYTE *) strdup(entropy.c_str()); - DWORD cbDataEnt = strlen((char *)pbDataEnt)+1; - DataIn.pbData = pbDataInput; - DataIn.cbData = cbDataInput; - DataEnt.pbData = pbDataEnt; - DataEnt.cbData = cbDataEnt; - - CRYPTPROTECT_PROMPTSTRUCT prom; - - prom.cbSize = sizeof(prom); - prom.dwPromptFlags = 0; - - /********* - std::cerr << "Password (" << cbDataInput << "):"; - std::cerr << pbDataInput << std::endl; - std::cerr << "Entropy (" << cbDataEnt << "):"; - std::cerr << pbDataEnt << std::endl; - *********/ - - if(CryptProtectData( - &DataIn, - NULL, - &DataEnt, /* entropy.c_str(), */ - NULL, // Reserved. - &prom, - 0, - &DataOut)) - { - - /********** - std::cerr << "The encryption phase worked. ("; - std::cerr << DataOut.cbData << ")" << std::endl; - - for(unsigned int i = 0; i < DataOut.cbData; i++) - { - std::cerr << std::setw(2) << (int) DataOut.pbData[i]; - std::cerr << " "; - } - std::cerr << std::endl; - **********/ - - //std::cerr << "Save to: " << passwdfile; - //std::cerr << std::endl; - - /* save the data to the file */ - FILE *fp = RsDirUtil::rs_fopen(getAutologinFileName(ssl_id).c_str(), "wb"); - if (fp != NULL) - { - fwrite(DataOut.pbData, 1, DataOut.cbData, fp); - fclose(fp); - - std::cerr << "AutoLogin Data saved: "; - std::cerr << std::endl; - } - } - else - { - std::cerr << "Encryption Failed"; - std::cerr << std::endl; - } - - free(pbDataInput); - free(pbDataEnt); - LocalFree(DataOut.pbData); - return false; -#endif - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ - -#endif -} - -bool RsLoginHandler::clearAutoLogin(const RsPeerId& ssl_id) -{ -#ifdef HAS_GNOME_KEYRING - if(GNOME_KEYRING_RESULT_OK == gnome_keyring_delete_password_sync(&my_schema,"RetroShare SSL Id", ssl_id.toStdString().c_str(),NULL)) - { - std::cout << "Successfully Cleared gnome keyring passwd for SSLID " << ssl_id << std::endl; - return true ; - } - else - { - std::cerr << "Could not clear gnome keyring passwd for SSLID " << ssl_id << std::endl; - return false ; - } -#elif defined(HAS_LIBSECRET) - // do synchronous clear - - GError *error = nullptr; - gboolean removed = secret_password_clear_sync (libsecret_get_schema(), nullptr, &error, - "RetroShare SSL Id", ssl_id.toStdString().c_str(), - NULL); - - if (error) { - g_error_free (error); - std::cerr << "Could not clearpasswd for SSLID " << ssl_id << " using libsecret: error" << std::endl; - return false ; - } else if (removed == FALSE) { - std::cerr << "Could not clearpasswd for SSLID " << ssl_id << " using libsecret: false" << std::endl; - return false ; - } - - std::cout << "Successfully Cleared passwd for SSLID " << ssl_id << " using libsecret" << std::endl; - return true ; -#else // HAS_GNOME_KEYRING / HAS_LIBSECRET - #ifdef __APPLE__ - - std::cerr << "clearAutoLogin() OSX Version" << std::endl; - //Call SecKeychainFindGenericPassword to get a password from the keychain: - - void *passwordData = NULL; - UInt32 passwordLength = 0; - std::string idtemp = ssl_id.toStdString(); - const char *userId = idtemp.c_str(); - UInt32 uidLength = strlen(userId); - SecKeychainItemRef itemRef = NULL; - - OSStatus status = SecKeychainFindGenericPassword ( - NULL, // default keychain - 10, // length of service name - "Retroshare", // service name - uidLength, // length of account name - userId, // account name - &passwordLength, // length of password - &passwordData, // pointer to password data - &itemRef // the item reference - ); - - std::cerr << "RsTryAutoLogin() SecKeychainFindGenericPassword returned: " << status << std::endl; - - if (status != 0) - { - std::cerr << "clearAutoLogin() Error Finding password " << std::endl; - - /* error */ - if (status == errSecItemNotFound) - { - //Is password on keychain? - std::cerr << "RsTryAutoLogin() Error - Looks like password is not in KeyChain " << std::endl; - } - } - else - { - std::cerr << "clearAutoLogin() Password found on KeyChain! " << std::endl; - - OSStatus deleteStatus = SecKeychainItemDelete (itemRef); - if (status != 0) - { - std::cerr << "clearAutoLogin() Failed to Delete Password status: " << deleteStatus << std::endl; - } - else - { - std::cerr << "clearAutoLogin() Deleted Password" << std::endl; - } - } - - //Free the data allocated by SecKeychainFindGenericPassword: - - SecKeychainItemFreeContent ( - NULL, //No attribute data to release - passwordData //Release data buffer allocated by SecKeychainFindGenericPassword - ); - - if (itemRef) CFRelease(itemRef); - - return (status == 0); - - /******************** OSX KeyChain stuff *****************************/ - - #else // WINDOWS / Generic Linux. - - std::string passwdfile = getAutologinFileName(ssl_id) ; - - FILE *fp = RsDirUtil::rs_fopen(passwdfile.c_str(), "wb"); - - if (fp != NULL) - { - fwrite(" ", 1, 1, fp); - fclose(fp); - bool removed = remove(passwdfile.c_str()); - - if(removed != 0) - std::cerr << "RsLoginHandler::clearAutoLogin(): Failed to Removed help file" << std::endl; - - std::cerr << "AutoLogin Data cleared "; - std::cerr << std::endl; - return true; - } - - return false; - #endif -#endif -} - -std::string RsLoginHandler::getAutologinFileName(const RsPeerId& /*ssl_id*/) -{ - return RsAccounts::AccountKeysDirectory() + "/" + "help.dta" ; -} - -#endif // RS_AUTOLOGIN diff --git a/libretroshare/src/rsserver/rsloginhandler.h b/libretroshare/src/rsserver/rsloginhandler.h deleted file mode 100644 index 1c95a741b..000000000 --- a/libretroshare/src/rsserver/rsloginhandler.h +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************************* - * libretroshare/src/rsserver: rsloginhandler.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2018 retroshare team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#pragma once - -#include - -/** - * This class handles login, meaning that it retrieves the SSL password from - * either the keyring or help.dta file, if autologin is enabled, or from the - * ssl_passphrase.pgp file, asking for the GPG password to decrypt it. - * - * This class should handle the following scenario: - * - * Normal login: - * - SSL key is stored -> do autologin - * - SSL key is not stored - * - if we're actually in the login process, ask for the gpg passwd, and - * decrypt the key file - * - if we're just trying for autologin, don't ask for the gpg passwd and - * return null - * - * Key creation: - * - the key should be stored in the gpg file. - */ -class RsLoginHandler -{ -public: - /** - * Gets the SSL passwd by any means: try autologin, and look into gpg file - * if enable_gpg_key_callback==true - */ - static bool getSSLPassword( const RsPeerId& ssl_id, - bool enable_gpg_key_callback, - std::string& ssl_password); - - /** - * Checks whether the ssl passwd is already in the gpg file. If the file's - * not here, the passwd is stored there, encrypted with the current GPG key. - */ - static bool checkAndStoreSSLPasswdIntoGPGFile( - const RsPeerId& ssl_id, const std::string& ssl_passwd ); - -#ifdef RS_AUTOLOGIN - /** - * Stores the given ssl_id/passwd pair into the keyring, or by default into - * a file in /[ssl_id]/keys/help.dta - */ - static bool enableAutoLogin(const RsPeerId& ssl_id,const std::string& passwd) ; - - /// Clears autologin entry. - static bool clearAutoLogin(const RsPeerId& ssl_id) ; -#endif // RS_AUTOLOGIN - -private: - static bool getSSLPasswdFromGPGFile(const RsPeerId& ssl_id,std::string& sslPassword); - static std::string getSSLPasswdFileName(const RsPeerId& ssl_id); - -#ifdef RS_AUTOLOGIN - static bool tryAutoLogin(const RsPeerId& ssl_id,std::string& ssl_passwd); - static std::string getAutologinFileName(const RsPeerId& ssl_id); -#endif // RS_AUTOLOGIN -}; - diff --git a/libretroshare/src/scripts/checks.mk b/libretroshare/src/scripts/checks.mk deleted file mode 100644 index 61d242ef0..000000000 --- a/libretroshare/src/scripts/checks.mk +++ /dev/null @@ -1,25 +0,0 @@ -#Basic checks - -ifndef RS_TOP_DIR -dummy: - echo "RS_TOP_DIR is not defined in your makefile" -endif - -ifndef SSL_DIR -dummy: - echo "you must define SSL_DIR before you can compile" - -endif - -ifneq ($(OS),Linux) - ifneq ($(OS),MacOSX) - ifndef PTHREADS_DIR -dummy: - echo "you must define PTHREADS_DIR before you can compile" - - endif - endif -endif - - - diff --git a/libretroshare/src/scripts/config-cygwin.mk b/libretroshare/src/scripts/config-cygwin.mk deleted file mode 100644 index ec4518f68..000000000 --- a/libretroshare/src/scripts/config-cygwin.mk +++ /dev/null @@ -1,118 +0,0 @@ -ifneq ($(OS),Cygwin) -dummy: - echo "ERROR Cygwin configuration file included, but (OS != Cygwin) - -endif - -############ LINUX CONFIGURATION ######################## - -# flags for components.... -PQI_USE_XPGP = 1 -#PQI_USE_PROXY = 1 -#PQI_USE_CHANNELS = 1 -#USE_FILELOOK = 1 - -########################################################################### - -#### DrBobs Versions.... Please Don't Delete. -### Comment out if needed. -ALT_SRC_ROOT=/cygdrive/c/home/rmfern/prog/MinGW -SRC_ROOT=../../../.. - -PTHREADS_DIR=$(ALT_SRC_ROOT)/pthreads/pthreads.2 - -################### - -#ALT_SRC_ROOT=/cygdrive/c/RetroShareBuild/src -#SRC_ROOT=/cygdrive/c/RetroShareBuild/src - -#PTHREADS_DIR=$(ALT_SRC_ROOT)/pthreads-w32-2-8-0-release - -################### - -ZLIB_DIR=$(ALT_SRC_ROOT)/zlib-1.2.3 - -SSL_DIR=$(SRC_ROOT)/openssl-0.9.7g-xpgp-0.1c -UPNPC_DIR=$(SRC_ROOT)/miniupnpc-1.0 - -include $(RS_TOP_DIR)/scripts/checks.mk - -############ ENFORCE DIRECTORY NAMING ######################## - -CC = g++ -RM = /bin/rm -RANLIB = ranlib -LIBDIR = $(RS_TOP_DIR)/lib -LIBRS = $(LIBDIR)/libretroshare.a - -# Unix: Linux/Cygwin -INCLUDE = -I $(RS_TOP_DIR) - -ifdef PQI_DEBUG - CFLAGS = -Wall -g $(INCLUDE) -else - CFLAGS = -Wall -O2 $(INCLUDE) -endif - -ifdef PQI_USE_XPGP - INCLUDE += -I $(SSL_DIR)/include -endif - -ifdef PQI_USE_XPGP - CFLAGS += -DPQI_USE_XPGP -endif - -ifdef PQI_USE_PROXY - CFLAGS += -DPQI_USE_PROXY -endif - -ifdef PQI_USE_CHANNELS - CFLAGS += -DPQI_USE_CHANNELS -endif - -ifdef USE_FILELOOK - CFLAGS += -DUSE_FILELOOK -endif - - -RSCFLAGS = -Wall -g $(INCLUDE) - -######################################################################### -# OS Compile Options -######################################################################### - -# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) -BIOCC = gcc - -# Cygwin - ?same? as Linux flags -BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -m486 -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM - -######################################################################### -# OS specific Linking. -######################################################################### - -# for static pthread libs.... -WININC += -DPTW32_STATIC_LIB -WININC += -mno-cygwin -mwindows -fno-exceptions -WININC += -DWINDOWS_SYS - -WINLIB = -lws2_32 -luuid -lole32 -liphlpapi -WINLIB += -lcrypt32 -lwinmm - -CFLAGS += -I$(PTHREADS_DIR) $(WININC) -CFLAGS += -I$(ZLIB_DIR) - -LIBS = -L$(LIBDIR) -lretroshare -ifdef PQI_USE_XPGP - LIBS += -L$(SSL_DIR) -endif - -LIBS += -lssl -lcrypto -LIBS += -L$(UPNPC_DIR) -lminiupnpc -LIBS += -L$(ZLIB_DIR) -lz -LIBS += -L$(PTHREADS_DIR) -lpthreadGC2d -LIBS += $(WINLIB) - -RSCFLAGS += $(WININC) - - diff --git a/libretroshare/src/scripts/config-linux.mk b/libretroshare/src/scripts/config-linux.mk deleted file mode 100644 index e82e903c2..000000000 --- a/libretroshare/src/scripts/config-linux.mk +++ /dev/null @@ -1,98 +0,0 @@ - -ifneq ($(OS),Linux) -dummy: - echo "ERROR Linux configuration file included, but (OS != Linux) - -endif - -############ LINUX CONFIGURATION ######################## - -# flags for components.... -#PQI_USE_SSLONLY = 1 -#PQI_USE_XPGP = 1 - - -#PQI_USE_PROXY = 1 -#PQI_USE_CHANNELS = 1 -#USE_FILELOOK = 1 - -SSL_DIR=../../../../openssl-0.9.7g-xpgp-0.1c -UPNPC_DIR=../../../../miniupnpc-1.0 - -# Need to define miniupnpc version because API changed a little between v1.0 and 1.2 -# put 10 for 1.0 and 12 for 1.2 -DEFINES += -DMINIUPNPC_VERSION=10 - -include $(RS_TOP_DIR)/scripts/checks.mk - -############ ENFORCE DIRECTORY NAMING ######################## - -CC = g++ -RM = /bin/rm -RANLIB = ranlib -LIBDIR = $(RS_TOP_DIR)/lib -LIBRS = $(LIBDIR)/libretroshare.a - -# Unix: Linux/Cygwin -INCLUDE = -I $(RS_TOP_DIR) -#-I$(KADC_DIR) -CFLAGS = -Wall -g $(INCLUDE) -CFLAGS += ${DEFINES} - -ifdef PQI_USE_XPGP - INCLUDE += -I $(SSL_DIR)/include -endif - -ifdef PQI_USE_XPGP - CFLAGS += -DPQI_USE_XPGP -endif - -ifdef PQI_USE_SSLONLY - CFLAGS += -DPQI_USE_SSLONLY -endif - -ifdef PQI_USE_PROXY - CFLAGS += -DPQI_USE_PROXY -endif - -ifdef PQI_USE_CHANNELS - CFLAGS += -DPQI_USE_CHANNELS -endif - -ifdef USE_FILELOOK - CFLAGS += -DUSE_FILELOOK -endif - - -RSCFLAGS = -Wall -g $(INCLUDE) -######################################################################### -# OS Compile Options -######################################################################### - -# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) -BIOCC = gcc - -# march=i686 causes problems while 64Bit compiling, GCC tries to generate Output for a m64 machine, but the marchi686 -# doesnt allow the instructionfs for that. -# -# gcc docu: http://gcc.gnu.org/onlinedocs/gcc-4.0.3/gcc/i386-and-x86_002d64-Options.html#i386-and-x86_002d64-Options - -# Linux flags -BIOCFLAGS = -I $(SSL_DIR)/include ${DEFINES} -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM - -######################################################################### -# OS specific Linking. -######################################################################### - -LIBS = -L$(LIBDIR) -lretroshare -ifdef PQI_USE_XPGP - LIBS += -L$(SSL_DIR) - endif -LIBS += -lssl -lcrypto -lpthread -LIBS += -L$(UPNPC_DIR) -lminiupnpc -LIBS += $(XLIB) -ldl -lz -LIBS += -lgpgme - -RSLIBS = $(LIBS) - - diff --git a/libretroshare/src/scripts/config-macosx.mk b/libretroshare/src/scripts/config-macosx.mk deleted file mode 100644 index 7aa56d361..000000000 --- a/libretroshare/src/scripts/config-macosx.mk +++ /dev/null @@ -1,152 +0,0 @@ - -ifneq ($(OS),MacOSX) -dummy: - echo "ERROR MacOSX configuration file included, but (OS != MacOSX) - -endif - -############ LINUX CONFIGURATION ######################## - - -# FLAGS to decide if we want i386 Build or ppc Build -# -# - -# PPC is default -# Could define both for combined compilation... -# except might not work for bio_tou.c file! -# -# MAC_I386_BUILD = 1 -# MAC_PPC_BUILD = 1 - -#MAC_I386_BUILD = 1 -#MAC_PPC_BUILD = 1 - -ifndef MAC_I386_BUILD - MAC_PPC_BUILD = 1 -endif - -# flags for components.... -#PQI_USE_SSLONLY = 1 -#PQI_USE_XPGP = 1 - -#PQI_USE_PROXY = 1 -#PQI_USE_CHANNELS = 1 -#USE_FILELOOK = 1 - -SSL_DIR=../../../../../src/openssl-0.9.7g-xpgp-0.1c -UPNPC_DIR=../../../../../src/miniupnpc-1.0 - -include $(RS_TOP_DIR)/scripts/checks.mk - -############ ENFORCE DIRECTORY NAMING ######################## - -CC = g++ -RM = /bin/rm - -RANLIB = ranlib - -# Dummy ranlib -> can't do it until afterwards with universal binaries. -# RANLIB = ls -l - -LIBDIR = $(RS_TOP_DIR)/lib -LIBRS = $(LIBDIR)/libretroshare.a - -OPT_DIR = /opt/local -OPT_INCLUDE = $(OPT_DIR)/include -OPT_LIBS = $(OPT_DIR)/lib - -INCLUDE = -I $(RS_TOP_DIR) -I $(OPT_INCLUDE) -#CFLAGS = -Wall -O3 -CFLAGS = -Wall -g - -# Flags for architecture builds. -ifdef MAC_I386_BUILD - CFLAGS += -arch i386 -endif - -ifdef MAC_PPC_BUILD - CFLAGS += -arch ppc -endif - -CFLAGS += $(INCLUDE) - -# This Line is for Universal BUILD for 10.4 + 10.5 -# (but unlikely to work unless Qt Libraries are build properly) -# CFLAGS += -isysroot /Developer/SDKs/MacOSX10.4u.sdk - -ifdef PQI_USE_XPGP - INCLUDE += -I $(SSL_DIR)/include - CFLAGS += -DPQI_USE_XPGP -endif - -ifdef PQI_USE_SSLONLY - CFLAGS += -DPQI_USE_SSLONLY -endif - -ifdef PQI_USE_PROXY - CFLAGS += -DPQI_USE_PROXY -endif - -ifdef PQI_USE_CHANNELS - CFLAGS += -DPQI_USE_CHANNELS -endif - -ifdef USE_FILELOOK - CFLAGS += -DUSE_FILELOOK -endif - - -# RSCFLAGS = -Wall -O3 $(INCLUDE) - -######################################################################### -# OS Compile Options -######################################################################### - -# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) -BIOCC = gcc - - -# Flags for architecture builds. -ifdef MAC_I386_BUILD - BIOCFLAGS = -arch i386 -I $(SSL_DIR)/include -DOPENSSL_SYSNAME_MACOSX -DOPENSSL_THREADS -D_REENTRANT -DOPENSSL_NO_KRB5 -O3 -fomit-frame-pointer -fno-common -endif - -ifdef MAC_PPC_BUILD - BIOCFLAGS = -arch ppc -I $(SSL_DIR)/include -DOPENSSL_SYSNAME_MACOSX -DOPENSSL_THREADS -D_REENTRANT -DOPENSSL_NO_KRB5 -O3 -fomit-frame-pointer -fno-common -DB_ENDIAN -endif - - - -# MacOSX flags -# BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_SYSNAME_MACOSX -DOPENSSL_THREADS -D_REENTRANT -DOPENSSL_NO_KRB5 -O3 -fomit-frame-pointer -fno-common -DB_ENDIAN - -# This is for the Universal Build... -# but is unlikely to work... as options are PPC specific.... -# -# BIOCFLAGS = -arch ppc -arch i386 -I $(SSL_DIR)/include -DOPENSSL_SYSNAME_MACOSX -DOPENSSL_THREADS -D_REENTRANT -DOPENSSL_NO_KRB5 -O3 -fomit-frame-pointer -fno-common -DB_ENDIAN - - -######################################################################### -# OS specific Linking. -######################################################################### - -LIBS = -Wl,-search_paths_first - -# for Univeral BUILD -# LIBS += -arch ppc -arch i386 -# LIBS += -Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk -arch ppc -arch i386 - -LIBS += -L$(LIBDIR) -lretroshare -ifdef PQI_USE_XPGP - LIBS += -L$(SSL_DIR) - endif -LIBS += -lssl -lcrypto -lpthread -LIBS += -L$(OPT_LIBS) -LIBS += -lgpgme -lgpg-error -LIBS += -L$(UPNPC_DIR) -lminiupnpc -LIBS += $(XLIB) -ldl -lz - -RSLIBS = $(LIBS) - - diff --git a/libretroshare/src/scripts/config-mingw.mk b/libretroshare/src/scripts/config-mingw.mk deleted file mode 100644 index c0040ac4e..000000000 --- a/libretroshare/src/scripts/config-mingw.mk +++ /dev/null @@ -1,138 +0,0 @@ -#ifneq ($(OS),"Win ") -#dummy: -# echo "ERROR OS = $(OS)" -# echo "ERROR MinGW configuration file included, but (OS != Win) -# -#endif - -############ LINUX CONFIGURATION ######################## - -# flags for components.... -#PQI_USE_XPGP = 1 -#PQI_USE_PROXY = 1 -#PQI_USE_CHANNELS = 1 -#USE_FILELOOK = 1 - -########################################################################### - -#### DrBobs Versions.... Please Don't Delete. -### Comment out if needed. -SRC_ROOT_PKG=/home/Mark/prog/retroshare/package/rs-win-v0.5.0/src -SRC_ROOT_GPG=/local - -#ALT_SRC_ROOT=/cygdrive/c/home/rmfern/prog/MinGW -#SRC_ROOT=../../../.. - -PTHREADS_DIR=$(SRC_ROOT_PKG)/pthreads-w32-2-8-0/Pre-built.2 -ZLIB_DIR=$(SRC_ROOT_PKG)/zlib-1.2.3 -SSL_DIR=$(SRC_ROOT_PKG)/openssl-tmp -UPNPC_DIR=$(SRC_ROOT_PKG)/miniupnpc-1.3 - -########################################################################### - -#### Enable this section for compiling with MSYS/MINGW compile -#SRC_ROOT=/home/linux - -#SSL_DIR=$(SRC_ROOT)/OpenSSL -#GPGME_DIR=$(SRC_ROOT)/gpgme-1.1.8 -#GPG_ERROR_DIR=$(SRC_ROOT)/libgpg-error-1.7 - -#ZLIB_DIR=$(SRC_ROOT)/zlib-1.2.3 -#UPNPC_DIR=$(SRC_ROOT)/miniupnpc-1.0 -#PTHREADS_DIR=$(SRC_ROOT)/pthreads-w32-2-8-0-release - -include $(RS_TOP_DIR)/scripts/checks.mk - -############ ENFORCE DIRECTORY NAMING ####################################### - -CC = g++ -RM = /bin/rm -RANLIB = ranlib -LIBDIR = $(RS_TOP_DIR)/lib -LIBRS = $(LIBDIR)/libretroshare.a - -# Unix: Linux/Cygwin -INCLUDE = -I $(RS_TOP_DIR) - -ifdef PQI_DEBUG - CFLAGS = -Wall -g $(INCLUDE) -else - CFLAGS = -Wall -O2 $(INCLUDE) -endif - -# These aren't used anymore.... really. -ifdef PQI_USE_XPGP - CFLAGS += -DPQI_USE_XPGP -endif - -ifdef PQI_USE_PROXY - CFLAGS += -DPQI_USE_PROXY -endif - -ifdef PQI_USE_CHANNELS - CFLAGS += -DPQI_USE_CHANNELS -endif - -ifdef USE_FILELOOK - CFLAGS += -DUSE_FILELOOK -endif - - -# SSL / pthreads / Zlib -# included by default for Windows compilation. -INCLUDE += -I $(SSL_DIR)/include -INCLUDE += -I$(PTHREADS_DIR) -INCLUDE += -I$(ZLIB_DIR) - - -######################################################################### -# OS Compile Options -######################################################################### - -# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) -BIOCC = gcc - -# Cygwin - ?same? as Linux flags -BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -m486 -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM -BIOCFLAGS += -DWINDOWS_SYS - -######################################################################### -# OS specific Linking. -######################################################################### - -# for static pthread libs.... -#WININC += -DPTW32_STATIC_LIB -#WININC += -mno-cygwin -mwindows -fno-exceptions - -WININC += -DWINDOWS_SYS - -WINLIB = -lws2_32 -luuid -lole32 -liphlpapi -WINLIB += -lcrypt32 -lwinmm - -CFLAGS += -I$(SSL_DIR)/include -CFLAGS += -I$(PTHREADS_DIR)/include -CFLAGS += -I$(ZLIB_DIR) -CFLAGS += -I$(SRC_ROOT_GPG)/include - -### Enable this for GPGME and GPG ERROR dirs -#CFLAGS += -I$(GPGME_DIR)/src -#CFLAGS += -I$(GPG_ERROR_DIR)/src - -CFLAGS += $(WININC) - - - -LIBS = -L$(LIBDIR) -lretroshare - -LIBS += -L$(SSL_DIR) - -LIBS += -lssl -lcrypto -LIBS += -L$(UPNPC_DIR) -lminiupnpc -LIBS += -L$(ZLIB_DIR) -lz -LIBS += -L$(PTHREADS_DIR) -lpthreadGC2d -LIBS += $(WINLIB) - -#RSCFLAGS = -Wall -g $(INCLUDE) -#RSCFLAGS += $(WININC) - - diff --git a/libretroshare/src/scripts/config.mk b/libretroshare/src/scripts/config.mk deleted file mode 100644 index 9f22fa363..000000000 --- a/libretroshare/src/scripts/config.mk +++ /dev/null @@ -1,27 +0,0 @@ - -# determine which operating system -# -########################################################################### -#Define OS. -# -OS = Linux -#OS = MacOSX -#OS = Cygwin -#OS = Win # MinGw. -########################################################################### - -ifeq ($(OS),Linux) - include $(RS_TOP_DIR)/scripts/config-linux.mk -else - ifeq ($(OS),MacOSX) - include $(RS_TOP_DIR)/scripts/config-macosx.mk - else - ifeq ($(OS),Cygwin) - include $(RS_TOP_DIR)/scripts/config-cygwin.mk - else - include $(RS_TOP_DIR)/scripts/config-mingw.mk - endif - endif -endif - -########################################################################### diff --git a/libretroshare/src/scripts/documentation-script b/libretroshare/src/scripts/documentation-script deleted file mode 100755 index 0d47217bc..000000000 --- a/libretroshare/src/scripts/documentation-script +++ /dev/null @@ -1,16 +0,0 @@ - -#!/bin/bash -# This script creates a doxygen documentation of retroshare -# you need to install doxygen and graph-viz(dot tool) for script to work - - -echo "doxygen and graph viz must be installed" - -# create documentation -doxygen rsDocumentation || exit - -#indicate finshed -echo "complete" - - - diff --git a/libretroshare/src/scripts/makeMacUniversalLibrary.sh b/libretroshare/src/scripts/makeMacUniversalLibrary.sh deleted file mode 100755 index b1222d049..000000000 --- a/libretroshare/src/scripts/makeMacUniversalLibrary.sh +++ /dev/null @@ -1,35 +0,0 @@ -# -## clean up all bits of libretroshare -echo make clobber -make clobber -# -## make the standard version (PPC) -echo make librs -make librs -# -LIB=libretroshare.a -LIB_PPC=libretroshare_ppc.a -LIB_X86=libretroshare_x86.a - -MAC_SCRIPT="./scripts/config-macosx.mk" - -echo cp lib/$LIB lib/$LIB_PPC -cp lib/$LIB lib/$LIB_PPC - -echo make clobber -make clobber - -echo make "MAC_I386_BUILD=1" librs -make "MAC_I386_BUILD=1" librs - -echo cp lib/$LIB lib/$LIB_X86 -cp lib/$LIB lib/$LIB_X86 - -# magic combine trick. -echo cd lib -cd lib - -echo lipo -create libretroshare_*.a -output $LIB -lipo -create libretroshare_*.a -output $LIB - - diff --git a/libretroshare/src/scripts/regress.mk b/libretroshare/src/scripts/regress.mk deleted file mode 100644 index f80b48451..000000000 --- a/libretroshare/src/scripts/regress.mk +++ /dev/null @@ -1,25 +0,0 @@ - -testoutputfiles = $(foreach tt,$(1),$(tt).tstout) - -%.tstout : %.sh - -sh ./$< > $@ 2>&1 - -%.tstout : % - -./$< > $@ 2>&1 - -TESTOUT = $(call testoutputfiles,$(TESTS)) - -.phony : tests regress retest clobber - -tests: $(TESTS) - -regress: $(TESTOUT) - @-echo "--------------- SUCCESS (count):" - @-grep -c SUCCESS $(TESTOUT) - @-echo "--------------- FAILURE REPORTS:" - @-grep FAILURE $(TESTOUT) || echo no failures - @-echo "--------------- end" - -retest: - -/bin/rm $(TESTOUT) - diff --git a/libretroshare/src/scripts/rsDocumentation b/libretroshare/src/scripts/rsDocumentation deleted file mode 100644 index d21dfaa1c..000000000 --- a/libretroshare/src/scripts/rsDocumentation +++ /dev/null @@ -1,281 +0,0 @@ -# Doxyfile 1.5.3 - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- -DOXYFILE_ENCODING = UTF-8 -PROJECT_NAME = retroshare -PROJECT_NUMBER = 1.0 -OUTPUT_DIRECTORY = ../ -CREATE_SUBDIRS = YES -OUTPUT_LANGUAGE = English -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = YES -ABBREVIATE_BRIEF = "The $name class " \ - "The $name widget " \ - "The $name file " \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the -ALWAYS_DETAILED_SEC = NO -INLINE_INHERITED_MEMB = NO -FULL_PATH_NAMES = YES -STRIP_FROM_PATH = ../ -STRIP_FROM_INC_PATH = -SHORT_NAMES = NO -JAVADOC_AUTOBRIEF = NO -QT_AUTOBRIEF = NO -MULTILINE_CPP_IS_BRIEF = NO -DETAILS_AT_TOP = NO -INHERIT_DOCS = YES -SEPARATE_MEMBER_PAGES = NO -TAB_SIZE = 8 -ALIASES = -OPTIMIZE_OUTPUT_FOR_C = NO -OPTIMIZE_OUTPUT_JAVA = NO -BUILTIN_STL_SUPPORT = NO -CPP_CLI_SUPPORT = NO -DISTRIBUTE_GROUP_DOC = NO -SUBGROUPING = YES -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- -EXTRACT_ALL = YES -EXTRACT_PRIVATE = YES -EXTRACT_STATIC = YES -EXTRACT_LOCAL_CLASSES = YES -EXTRACT_LOCAL_METHODS = NO -EXTRACT_ANON_NSPACES = NO -HIDE_UNDOC_MEMBERS = NO -HIDE_UNDOC_CLASSES = NO -HIDE_FRIEND_COMPOUNDS = NO -HIDE_IN_BODY_DOCS = NO -INTERNAL_DOCS = NO -CASE_SENSE_NAMES = YES -HIDE_SCOPE_NAMES = NO -SHOW_INCLUDE_FILES = YES -INLINE_INFO = YES -SORT_MEMBER_DOCS = YES -SORT_BRIEF_DOCS = NO -SORT_BY_SCOPE_NAME = NO -GENERATE_TODOLIST = YES -GENERATE_TESTLIST = YES -GENERATE_BUGLIST = YES -GENERATE_DEPRECATEDLIST= YES -ENABLED_SECTIONS = -MAX_INITIALIZER_LINES = 30 -SHOW_USED_FILES = YES -SHOW_DIRECTORIES = NO -FILE_VERSION_FILTER = -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- -QUIET = NO -WARNINGS = YES -WARN_IF_UNDOCUMENTED = YES -WARN_IF_DOC_ERROR = YES -WARN_NO_PARAMDOC = NO -WARN_FORMAT = "$file:$line: $text " -WARN_LOGFILE = -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = ../ -INPUT_ENCODING = UTF-8 -FILE_PATTERNS = *.c \ - *.cc \ - *.cxx \ - *.cpp \ - *.c++ \ - *.d \ - *.java \ - *.ii \ - *.ixx \ - *.ipp \ - *.i++ \ - *.inl \ - *.h \ - *.hh \ - *.hxx \ - *.hpp \ - *.h++ \ - *.idl \ - *.odl \ - *.cs \ - *.php \ - *.php3 \ - *.inc \ - *.m \ - *.mm \ - *.dox \ - *.py \ - *.C \ - *.CC \ - *.C++ \ - *.II \ - *.I++ \ - *.H \ - *.HH \ - *.H++ \ - *.CS \ - *.PHP \ - *.PHP3 \ - *.M \ - *.MM \ - *.PY -RECURSIVE = YES -EXCLUDE = -EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = -EXCLUDE_SYMBOLS = -EXAMPLE_PATH = -EXAMPLE_PATTERNS = * -EXAMPLE_RECURSIVE = NO -IMAGE_PATH = -INPUT_FILTER = -FILTER_PATTERNS = -FILTER_SOURCE_FILES = NO -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- -SOURCE_BROWSER = NO -INLINE_SOURCES = NO -STRIP_CODE_COMMENTS = YES -REFERENCED_BY_RELATION = NO -REFERENCES_RELATION = NO -REFERENCES_LINK_SOURCE = YES -USE_HTAGS = NO -VERBATIM_HEADERS = NO -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- -ALPHABETICAL_INDEX = NO -COLS_IN_ALPHA_INDEX = 5 -IGNORE_PREFIX = -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- -GENERATE_HTML = YES -HTML_OUTPUT = html -HTML_FILE_EXTENSION = .html -HTML_HEADER = -HTML_FOOTER = -HTML_STYLESHEET = -HTML_ALIGN_MEMBERS = YES -GENERATE_HTMLHELP = NO -HTML_DYNAMIC_SECTIONS = NO -CHM_FILE = -HHC_LOCATION = -GENERATE_CHI = NO -BINARY_TOC = NO -TOC_EXPAND = NO -DISABLE_INDEX = NO -ENUM_VALUES_PER_LINE = 4 -GENERATE_TREEVIEW = YES -TREEVIEW_WIDTH = 250 -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- -GENERATE_LATEX = NO -LATEX_OUTPUT = latex -LATEX_CMD_NAME = latex -MAKEINDEX_CMD_NAME = makeindex -COMPACT_LATEX = NO -PAPER_TYPE = a4wide -EXTRA_PACKAGES = -LATEX_HEADER = -PDF_HYPERLINKS = NO -USE_PDFLATEX = NO -LATEX_BATCHMODE = NO -LATEX_HIDE_INDICES = NO -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- -GENERATE_RTF = NO -RTF_OUTPUT = rtf -COMPACT_RTF = NO -RTF_HYPERLINKS = NO -RTF_STYLESHEET_FILE = -RTF_EXTENSIONS_FILE = -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- -GENERATE_MAN = NO -MAN_OUTPUT = man -MAN_EXTENSION = .3 -MAN_LINKS = NO -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- -GENERATE_XML = NO -XML_OUTPUT = xml -XML_SCHEMA = -XML_DTD = -XML_PROGRAMLISTING = YES -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- -GENERATE_AUTOGEN_DEF = NO -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- -GENERATE_PERLMOD = NO -PERLMOD_LATEX = NO -PERLMOD_PRETTY = YES -PERLMOD_MAKEVAR_PREFIX = -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- -ENABLE_PREPROCESSING = YES -MACRO_EXPANSION = NO -EXPAND_ONLY_PREDEF = NO -SEARCH_INCLUDES = YES -INCLUDE_PATH = -INCLUDE_FILE_PATTERNS = -PREDEFINED = -EXPAND_AS_DEFINED = -SKIP_FUNCTION_MACROS = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- -TAGFILES = -GENERATE_TAGFILE = -ALLEXTERNALS = NO -EXTERNAL_GROUPS = YES -PERL_PATH = /usr/bin/perl -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- -CLASS_DIAGRAMS = NO -MSCGEN_PATH = -HIDE_UNDOC_RELATIONS = YES -HAVE_DOT = YES -CLASS_GRAPH = YES -COLLABORATION_GRAPH = YES -GROUP_GRAPHS = YES -UML_LOOK = NO -TEMPLATE_RELATIONS = NO -INCLUDE_GRAPH = YES -INCLUDED_BY_GRAPH = YES -CALL_GRAPH = NO -CALLER_GRAPH = NO -GRAPHICAL_HIERARCHY = YES -DIRECTORY_GRAPH = YES -DOT_IMAGE_FORMAT = png -DOT_PATH = -DOTFILE_DIRS = -DOT_GRAPH_MAX_NODES = 50 -MAX_DOT_GRAPH_DEPTH = 1000 -DOT_TRANSPARENT = NO -DOT_MULTI_TARGETS = NO -GENERATE_LEGEND = YES -DOT_CLEANUP = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- -SEARCHENGINE = NO diff --git a/libretroshare/src/scripts/rules.mk b/libretroshare/src/scripts/rules.mk deleted file mode 100644 index f8d75c21f..000000000 --- a/libretroshare/src/scripts/rules.mk +++ /dev/null @@ -1,23 +0,0 @@ - -# defines required / used. -# -# CFLAGS -# -# - -librs: $(RSOBJ) - $(AR) r $(LIBRS) $(RSOBJ) - $(RANLIB) $(LIBRS) - -.cc.o: - $(CC) $(CFLAGS) -c $< - -clean: - -/bin/rm $(RSOBJ) $(EXECOBJ) $(TESTOBJ) - -clobber: clean retest - -/bin/rm $(EXEC) $(TESTS) - - -include $(RS_TOP_DIR)/scripts/regress.mk - diff --git a/libretroshare/src/serialiser/rsbaseserial.cc b/libretroshare/src/serialiser/rsbaseserial.cc deleted file mode 100644 index 276872364..000000000 --- a/libretroshare/src/serialiser/rsbaseserial.cc +++ /dev/null @@ -1,311 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rsbaseserial.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include /* Included because GCC4.4 wants it */ -#include /* Included because GCC4.4 wants it */ - -#include "retroshare/rstypes.h" -#include "serialiser/rsbaseserial.h" -#include "util/rsnet.h" -#include "util/rstime.h" - -#include -#include - -/* UInt8 get/set */ - -bool getRawUInt8(const void *data, uint32_t size, uint32_t *offset, uint8_t *out) -{ - /* first check there is space */ - if (size < *offset + 1) - { - std::cerr << "(EE) Cannot deserialise uint8_t: not enough size." << std::endl; - return false; - } - void *buf = (void *) &(((uint8_t *) data)[*offset]); - - /* extract the data */ - memcpy(out, buf, sizeof(uint8_t)); - (*offset) += 1; - - return true; -} - -bool setRawUInt8(void *data, uint32_t size, uint32_t *offset, uint8_t in) -{ - /* first check there is space */ - if (size < *offset + 1) - { - std::cerr << "(EE) Cannot serialise uint8_t: not enough size." << std::endl; - return false; - } - - void *buf = (void *) &(((uint8_t *) data)[*offset]); - - /* pack it in */ - memcpy(buf, &in, sizeof(uint8_t)); - - (*offset) += 1; - return true; -} -/* UInt16 get/set */ - -bool getRawUInt16(const void *data, uint32_t size, uint32_t *offset, uint16_t *out) -{ - /* first check there is space */ - if (size < *offset + 2) - { - std::cerr << "(EE) Cannot deserialise uint16_t: not enough size." << std::endl; - return false; - } - void *buf = (void *) &(((uint8_t *) data)[*offset]); - - /* extract the data */ - uint16_t netorder_num; - memcpy(&netorder_num, buf, sizeof(uint16_t)); - - (*out) = ntohs(netorder_num); - (*offset) += 2; - return true; -} - -bool setRawUInt16(void *data, uint32_t size, uint32_t *offset, uint16_t in) -{ - /* first check there is space */ - if (size < *offset + 2) - { - std::cerr << "(EE) Cannot serialise uint16_t: not enough size." << std::endl; - return false; - } - - void *buf = (void *) &(((uint8_t *) data)[*offset]); - - /* convert the data to the right format */ - uint16_t netorder_num = htons(in); - - /* pack it in */ - memcpy(buf, &netorder_num, sizeof(uint16_t)); - - (*offset) += 2; - return true; -} - -/* UInt32 get/set */ - -bool getRawUInt32(const void *data, uint32_t size, uint32_t *offset, uint32_t *out) -{ - /* first check there is space */ - if (size < *offset + 4) - { - std::cerr << "(EE) Cannot deserialise uint32_t: not enough size." << std::endl; - return false; - } - void *buf = (void *) &(((uint8_t *) data)[*offset]); - - /* extract the data */ - uint32_t netorder_num; - memcpy(&netorder_num, buf, sizeof(uint32_t)); - - (*out) = ntohl(netorder_num); - (*offset) += 4; - return true; -} - -bool setRawUInt32(void *data, uint32_t size, uint32_t *offset, uint32_t in) -{ - /* first check there is space */ - if (size < *offset + 4) - { - std::cerr << "(EE) Cannot serialise uint32_t: not enough size." << std::endl; - return false; - } - - void *buf = (void *) &(((uint8_t *) data)[*offset]); - - /* convert the data to the right format */ - uint32_t netorder_num = htonl(in); - - /* pack it in */ - memcpy(buf, &netorder_num, sizeof(uint32_t)); - - (*offset) += 4; - return true; -} - -/* UInt64 get/set */ - -bool getRawUInt64(const void *data, uint32_t size, uint32_t *offset, uint64_t *out) -{ - /* first check there is space */ - if (size < *offset + 8) - { - std::cerr << "(EE) Cannot deserialise uint64_t: not enough size." << std::endl; - return false; - } - void *buf = (void *) &(((uint8_t *) data)[*offset]); - - /* extract the data */ - uint64_t netorder_num; - memcpy(&netorder_num, buf, sizeof(uint64_t)); - - (*out) = ntohll(netorder_num); - (*offset) += 8; - return true; -} - -bool setRawUInt64(void *data, uint32_t size, uint32_t *offset, uint64_t in) -{ - /* first check there is space */ - if (size < *offset + 8) - { - std::cerr << "(EE) Cannot serialise uint64_t: not enough size." << std::endl; - return false; - } - - void *buf = (void *) &(((uint8_t *) data)[*offset]); - - /* convert the data to the right format */ - uint64_t netorder_num = htonll(in); - - /* pack it in */ - memcpy(buf, &netorder_num, sizeof(uint64_t)); - - (*offset) += 8; - return true; -} - -bool getRawUFloat32(const void *data, uint32_t size, uint32_t *offset, float& f) -{ - uint32_t n ; - if(!getRawUInt32(data, size, offset, &n) ) - return false ; - - f = 1.0f/ ( n/(float)(~(uint32_t)0)) - 1.0f ; - - return true ; -} - -bool setRawUFloat32(void *data,uint32_t size,uint32_t *offset,float f) -{ - uint32_t sz = 4; - - if ( !data || size <= *offset || size < sz + *offset ) - { - std::cerr << "(EE) not enough room. SIZE+offset=" << sz+*offset << " and size is only " << size << std::endl; - return false; - } - if(f < 0.0f) - { - std::cerr << "(EE) Cannot serialise invalid negative float value " << f << " in " << __PRETTY_FUNCTION__ << std::endl; - return false ; - } - - // This serialisation is quite accurate. The max relative error is approx. - // 0.01% and most of the time less than 1e-05% The error is well distributed - // over numbers also. - // - uint32_t n = (f < 1e-7)?(~(uint32_t)0): ((uint32_t)( (1.0f/(1.0f+f) * (~(uint32_t)0)))) ; - - return setRawUInt32(data, size, offset, n); -} - - -uint32_t getRawStringSize(const std::string &outStr) -{ - return outStr.length() + 4; -} - -bool getRawString(const void *data, uint32_t size, uint32_t *offset, std::string &outStr) -{ - outStr.clear(); - - uint32_t len = 0; - if (!getRawUInt32(data, size, offset, &len)) - { - std::cerr << "getRawString() get size failed" << std::endl; - return false; - } - - /* check there is space for string */ - if(len > size || size-len < *offset) // better than if(size < *offset + len) because it avoids integer overflow - { - std::cerr << "getRawString() not enough size" << std::endl; - print_stacktrace(); - return false; - } - uint8_t *buf = &(((uint8_t *) data)[*offset]); - - for (uint32_t i = 0; i < len; i++) - { - outStr += buf[i]; - } - - (*offset) += len; - return true; -} - -bool setRawString(void *data, uint32_t size, uint32_t *offset, const std::string &inStr) -{ - uint32_t len = inStr.length(); - /* first check there is space */ - - if(size < 4 || len > size-4 || size-len-4 < *offset) // better than if(size < *offset + len + 4) because it avoids integer overflow - { - std::cerr << "setRawString() Not enough size" << std::endl; - return false; - } - - if (!setRawUInt32(data, size, offset, len)) - { - std::cerr << "setRawString() set size failed" << std::endl; - return false; - } - - void *buf = (void *) &(((uint8_t *) data)[*offset]); - - /* pack it in */ - memcpy(buf, inStr.c_str(), len); - - (*offset) += len; - return true; -} - -bool getRawTimeT(const void *data,uint32_t size,uint32_t *offset,rstime_t& t) -{ - uint64_t T; - bool res = getRawUInt64(data,size,offset,&T); - t = T; - - if(t < 0) // [[unlikely]] - std::cerr << __PRETTY_FUNCTION__ << " got a negative time: " << t - << " this seems fishy, report to the developers!" << std::endl; - - return res; -} -bool setRawTimeT(void *data, uint32_t size, uint32_t *offset, const rstime_t& t) -{ - if(t < 0) // [[unlikely]] - std::cerr << __PRETTY_FUNCTION__ << " got a negative time: " << t - << " this seems fishy, report to the developers!" << std::endl; - - return setRawUInt64(data,size,offset,t) ; -} diff --git a/libretroshare/src/serialiser/rsbaseserial.h b/libretroshare/src/serialiser/rsbaseserial.h deleted file mode 100644 index 839932927..000000000 --- a/libretroshare/src/serialiser/rsbaseserial.h +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rsbaseserial.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_BASE_PACKING_H -#define RS_BASE_PACKING_H - -#include -#include -#include - -#include "retroshare/rsids.h" -#include "util/rstime.h" - -/******************************************************************* - * This is at the lowlevel packing routines. They are usually - * created in pairs - one to pack the data, the other to unpack. - * - * getRawXXX(void *data, uint32_t size, uint32_t *offset, XXX *out); - * setRawXXX(void *data, uint32_t size, uint32_t *offset, XXX *in); - * - * - * data - the base pointer to the serialised data. - * size - size of the memory pointed to by data. - * *offset - where we want to (un)pack the data. - * This is incremented by the datasize. - * - * *in / *out - the data to (un)pack. - * - ******************************************************************/ - -bool getRawUInt8(const void *data, uint32_t size, uint32_t *offset, uint8_t *out); -bool setRawUInt8(void *data, uint32_t size, uint32_t *offset, uint8_t in); - -bool getRawUInt16(const void *data, uint32_t size, uint32_t *offset, uint16_t *out); -bool setRawUInt16(void *data, uint32_t size, uint32_t *offset, uint16_t in); - -bool getRawUInt32(const void *data, uint32_t size, uint32_t *offset, uint32_t *out); -bool setRawUInt32(void *data, uint32_t size, uint32_t *offset, uint32_t in); - -bool getRawUInt64(const void *data, uint32_t size, uint32_t *offset, uint64_t *out); -bool setRawUInt64(void *data, uint32_t size, uint32_t *offset, uint64_t in); - -bool getRawUFloat32(const void *data, uint32_t size, uint32_t *offset, float& out); -bool setRawUFloat32(void *data, uint32_t size, uint32_t *offset, float in); - -uint32_t getRawStringSize(const std::string &outStr); -bool getRawString(const void *data, uint32_t size, uint32_t *offset, std::string &outStr); -bool setRawString(void *data, uint32_t size, uint32_t *offset, const std::string &inStr); - -bool getRawTimeT(const void *data, uint32_t size, uint32_t *offset, rstime_t& outTime); -bool setRawTimeT(void *data, uint32_t size, uint32_t *offset, const rstime_t& inTime); - -#endif - diff --git a/libretroshare/src/serialiser/rsserial.cc b/libretroshare/src/serialiser/rsserial.cc deleted file mode 100644 index 4d3cda811..000000000 --- a/libretroshare/src/serialiser/rsserial.cc +++ /dev/null @@ -1,570 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rsserial.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2007-2008 Robert Fernie * - * Copyright (C) 2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include -#include -#include -#include -#include - -#include "serialiser/rsbaseserial.h" -#include "util/cxx23retrocompat.h" -#include "util/rsthreads.h" -#include "util/rsstring.h" -#include "util/rsprint.h" -#include "rsitems/rsitem.h" -#include "rsitems/itempriorities.h" - - -/*** - * #define RSSERIAL_DEBUG 1 - * #define RSSERIAL_ERROR_DEBUG 1 -***/ - -// As these represent SERIOUS ERRORs, this debug should be left one. -#define RSSERIAL_ERROR_DEBUG 1 - - -#if defined(RSSERIAL_DEBUG) || defined(RSSERIAL_ERROR_DEBUG) - #include -#endif - -RsItem::RsItem(uint32_t t) -:type(t) -{ - _priority_level = QOS_PRIORITY_UNKNOWN ; // This value triggers PQIInterface to complain about undefined priorities -} - - -#ifdef DO_STATISTICS -class Counter -{ - public: - Counter(int i): _i(i) {} - Counter(): _i(0) {} - - int v() const { return _i ; } - int& v() { return _i ; } - private: - int _i ; -}; - - static RsMutex smtx ; - static std::map size_hits ; - static int nb_rsitem_creations = 0 ; - static int total_rsitem_mallocs = 0 ; - static int total_rsitem_frees = 0 ; - static int total_rsitem_freed = 0 ; - static rstime_t last_time = 0 ; - -void *RsItem::operator new(size_t s) -{ -// std::cerr << "New RsItem: s=" << s << std::endl; - - RsStackMutex m(smtx) ; - - ++size_hits[ s ].v() ; - - rstime_t now = time(NULL); - ++nb_rsitem_creations ; - total_rsitem_mallocs += s ; - - if(last_time + 20 < now) - { - std::cerr << "Memory statistics:" << std::endl; - std::cerr << " Total RsItem memory: " << total_rsitem_mallocs << std::endl; - std::cerr << " Total RsItem creations: " << nb_rsitem_creations << std::endl; - std::cerr << " Total RsItem freed memory: " << total_rsitem_freed << std::endl; - std::cerr << " Total RsItem deletions: " << total_rsitem_frees << std::endl; - std::cerr << "Now printing histogram:" << std::endl; - - for(std::map::const_iterator it(size_hits.begin());it!=size_hits.end();++it) - std::cerr << it->first << " " << it->second.v() << std::endl; - last_time = now ; - } - - RsItem *a = static_cast(::operator new(s)) ; - return a ; -} -void RsItem::operator delete(void *p,size_t s) -{ -// std::cerr << "Delete RsItem: s=" << s << std::endl; - - RsStackMutex m(smtx) ; - total_rsitem_freed += s ; - ++total_rsitem_frees ; - - ::operator delete(p) ; -} -#endif - -RsItem::RsItem(uint8_t ver, uint8_t cls, uint8_t t, uint8_t subtype) -{ - _priority_level = QOS_PRIORITY_UNKNOWN ; // This value triggers PQIInterface to complain about undefined priorities - - type = (ver << 24) + (cls << 16) + (t << 8) + subtype; -} - -RsItem::~RsItem() = default; - -void RsItem::print_string(std::string &out, uint16_t indent) -{ - std::ostringstream stream; - print(stream, indent); - - out += stream.str(); -} -uint32_t RsItem::PacketId() const -{ - return type; -} - -uint8_t RsItem::PacketVersion() -{ - return (type >> 24); -} - - -uint8_t RsItem::PacketClass() -{ - return (type >> 16) & 0xFF; -} - - -uint8_t RsItem::PacketType() -{ - return (type >> 8) & 0xFF; -} - - -uint8_t RsItem::PacketSubType() const -{ - return (type & 0xFF); -} - - - /* For Service Packets */ -RsItem::RsItem(uint8_t ver, uint16_t service, uint8_t subtype) -{ - // This value triggers PQIInterface to complain about undefined priorities - _priority_level = QOS_PRIORITY_UNKNOWN; - type = (ver << 24) + (service << 8) + subtype; -} - -RsItem::RsItem( uint8_t ver, RsServiceType service, uint8_t subtype, - RsItemPriority prio ): - type(static_cast( - (ver << 24) + (std::to_underlying(service) << 8) + subtype )), - _priority_level(prio) {} - -uint16_t RsItem::PacketService() const -{ - return (type >> 8) & 0xFFFF; -} - -void RsItem::setPacketService(uint16_t service) -{ - type &= 0xFF0000FF; - type |= (uint32_t) (service << 8); -} - - -RsSerialType::RsSerialType(uint32_t t) - :type(t & 0xFFFFFF00) -{ - return; -} - -RsSerialType::RsSerialType(uint8_t ver, uint8_t cls, uint8_t t) -{ - type = (ver << 24) + (cls << 16) + (t << 8); - return; -} - -RsSerialType::RsSerialType(uint8_t ver, uint16_t service) -{ - type = (ver << 24) + (service << 8); - return; -} - -RsSerialType::~RsSerialType() -{ - return; -} - -uint32_t RsSerialType::size(RsItem *) -{ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsSerialType::size()" << std::endl; -#endif - - /* base size: type + length */ - return 8; -} - -bool RsSerialType::serialise(RsItem */*item*/, void */*data*/, uint32_t */*size*/) -{ - std::cerr << "(EE) Empty method called for missing serialize() method in serializer class " << typeid(this).name() << std::endl; -#ifdef RSSERIAL_DEBUG - std::cerr << "RsSerialType::serialise()" << std::endl; -#endif - return false; -} - -RsItem * RsSerialType::deserialise(void */*data*/, uint32_t */*size*/) -{ -#ifdef RSSERIAL_DEBUG - std::cerr << "RsSerialType::deserialise()" << std::endl; -#endif - return NULL; -} - -uint32_t RsSerialType::PacketId() const -{ - return type; -} - - - - -RsSerialiser::RsSerialiser() = default; - - -RsSerialiser::~RsSerialiser() -{ - /* clean up the map */ - std::map::iterator it; - for(it = serialisers.begin(); it != serialisers.end(); ++it) - { - delete (it->second); - } - serialisers.clear(); - return; -} - - - -bool RsSerialiser::addSerialType(RsSerialType *serialiser) -{ - uint32_t type = (serialiser->PacketId() & 0xFFFFFF00); - std::map::iterator it; - if (serialisers.end() != (it = serialisers.find(type))) - { -#ifdef RSSERIAL_DEBUG - std::cerr << "RsSerialiser::addSerialType() Error Serialiser already exists!"; - std::cerr << std::endl; -#endif - return false; - } - - serialisers[type] = serialiser; - return true; -} - - - -uint32_t RsSerialiser::size(RsItem *item) -{ - /* find the type */ - uint32_t type = (item->PacketId() & 0xFFFFFF00); - std::map::iterator it; - - if (serialisers.end() == (it = serialisers.find(type))) - { - /* remove 8 more bits -> try again */ - type &= 0xFFFF0000; - if (serialisers.end() == (it = serialisers.find(type))) - { - /* one more try */ - type &= 0xFF000000; - if (serialisers.end() == (it = serialisers.find(type))) - { - -#ifdef RSSERIAL_ERROR_DEBUG - std::cerr << "RsSerialiser::size() ERROR serialiser missing!" << std::endl; - - std::string out; - rs_sprintf(out, "%x", item->PacketId()); - - std::cerr << "RsSerialiser::size() PacketId: "; - std::cerr << out; - std::cerr << std::endl; -#endif - return 0; - } - } - } - -#ifdef RSSERIAL_DEBUG - std::string out; - rs_sprintf(out, "RsSerialiser::size() Item->PacketId(): %x matched to Serialiser Type: %lu", item->PacketId(), type); - std::cerr << out << std::endl; -#endif - - return (it->second)->size(item); -} - -bool RsSerialiser::serialise (RsItem *item, void *data, uint32_t *size) -{ - /* find the type */ - uint32_t type = (item->PacketId() & 0xFFFFFF00); - std::map::iterator it; - - if (serialisers.end() == (it = serialisers.find(type))) - { - /* remove 8 more bits -> try again */ - type &= 0xFFFF0000; - if (serialisers.end() == (it = serialisers.find(type))) - { - /* one more try */ - type &= 0xFF000000; - if (serialisers.end() == (it = serialisers.find(type))) - { - -#ifdef RSSERIAL_ERROR_DEBUG - std::cerr << "RsSerialiser::serialise() ERROR serialiser missing!"; - std::string out; - rs_sprintf(out, "%x", item->PacketId()); - - std::cerr << "RsSerialiser::serialise() PacketId: "; - std::cerr << out; - std::cerr << std::endl; -#endif - return false; - } - } - } - -#ifdef RSSERIAL_DEBUG - std::string out; - rs_sprintf(out, "RsSerialiser::serialise() Item->PacketId(): %x matched to Serialiser Type: %lu", item->PacketId(), type); - std::cerr << out << std::endl; -#endif - - return (it->second)->serialise(item, data, size); -} - - - -RsItem * RsSerialiser::deserialise(void *data, uint32_t *size) -{ - /* find the type */ - if (*size < 8) - { -#ifdef RSSERIAL_ERROR_DEBUG - std::cerr << "RsSerialiser::deserialise() ERROR Not Enough Data(1)"; - std::cerr << std::endl; -#endif - return NULL; - } - - uint32_t type = (getRsItemId(data) & 0xFFFFFF00); - uint32_t pkt_size = getRsItemSize(data); - - //std::cerr << "RsSerialiser::deserialise() RsItem Type: " << std::hex << getRsItemId(data) << " Size: " << pkt_size; - //std::cerr << std::endl; - - if (pkt_size > *size) - { -#ifdef RSSERIAL_ERROR_DEBUG - std::cerr << "RsSerialiser::deserialise() ERROR Size mismatch(2)"; - std::cerr << std::endl; -#endif - return NULL; - } - if(pkt_size > getRsPktMaxSize()) - { - std::cerr << "(EE) trying to deserialise a packet with absurdely large size " << pkt_size << ". This means there's a bug upward or packet corruption. Packet content: " << RsUtil::BinToHex((unsigned char*)data,std::min(300u,pkt_size)) ; - return NULL ; - } - - /* store the packet size to return the amount we should use up */ - *size = pkt_size; - - std::map::iterator it; - if (serialisers.end() == (it = serialisers.find(type))) - { - /* remove 8 more bits -> try again */ - type &= 0xFFFF0000; - if (serialisers.end() == (it = serialisers.find(type))) - { - /* one more try */ - type &= 0xFF000000; - if (serialisers.end() == (it = serialisers.find(type))) - { - -#ifdef RSSERIAL_ERROR_DEBUG - std::cerr << "RsSerialiser::deserialise() ERROR deserialiser missing!"; - std::string out; - rs_sprintf(out, "%x", getRsItemId(data)); - - std::cerr << "RsSerialiser::deserialise() PacketId: "; - std::cerr << out << std::endl; -#endif - return NULL; - } - } - } - - RsItem *item = (it->second)->deserialise(data, &pkt_size); - if (!item) - { -#ifdef RSSERIAL_ERROR_DEBUG - std::cerr << "RsSerialiser::deserialise() ERROR Failed!"; - std::cerr << std::endl; - std::cerr << "RsSerialiser::deserialise() pkt_size: " << pkt_size << " vs *size: " << *size; - std::cerr << std::endl; - - //RsItem *item2 = (it->second)->deserialise(data, &pkt_size); - - uint32_t failedtype = getRsItemId(data); - std::cerr << "RsSerialiser::deserialise() FAILED PACKET Size: "; - std::cerr << getRsItemSize(data) << " ID: "; - std::cerr << std::hex << failedtype << std::endl; - std::cerr << "RsSerialiser::deserialise() FAILED PACKET: "; - std::cerr << " Version: " << std::hex << (uint32_t) getRsItemVersion(failedtype) << std::dec; - std::cerr << " Class: " << std::hex << (uint32_t) getRsItemClass(failedtype) << std::dec; - std::cerr << " Type: " << std::hex << (uint32_t) getRsItemType(failedtype) << std::dec; - std::cerr << " SubType: " << std::hex << (uint32_t) getRsItemSubType(failedtype) << std::dec; - std::cerr << " Data: " << RsUtil::BinToHex((char*)data,pkt_size).substr(0,300) << std::endl; - std::cerr << std::endl; -#endif - return NULL; - } - - if (pkt_size != *size) - { -#ifdef RSSERIAL_ERROR_DEBUG - std::cerr << "RsSerialiser::deserialise() ERROR: size mismatch!"; - std::cerr << std::endl; - std::cerr << "RsSerialiser::deserialise() pkt_size: " << pkt_size << " vs *size: " << *size; - std::cerr << std::endl; - - uint32_t failedtype = getRsItemId(data); - std::cerr << "RsSerialiser::deserialise() FAILED PACKET Size: "; - std::cerr << getRsItemSize(data) << " ID: "; - std::cerr << std::hex << failedtype << std::dec; - std::cerr << "RsSerialiser::deserialise() FAILED PACKET: "; - std::cerr << " Version: " << std::hex << (uint32_t) getRsItemVersion(failedtype) << std::dec; - std::cerr << " Class: " << std::hex << (uint32_t) getRsItemClass(failedtype) << std::dec; - std::cerr << " Type: " << std::hex << (uint32_t) getRsItemType(failedtype) << std::dec; - std::cerr << " SubType: " << std::hex << (uint32_t) getRsItemSubType(failedtype) << std::dec; - std::cerr << " Data: " << RsUtil::BinToHex((char*)data,pkt_size).substr(0,300) << std::endl; - std::cerr << std::endl; -#endif - } - return item; -} - - -bool setRsItemHeader(void *data, uint32_t size, uint32_t type, uint32_t pktsize) -{ - if (size < 8) - return false; - - uint32_t offset = 0; - bool ok = true; - ok &= setRawUInt32(data, 8, &offset, type); - ok &= setRawUInt32(data, 8, &offset, pktsize); - - return ok; -} - - - -uint32_t getRsItemId(void *data) -{ - uint32_t type = 0; - uint32_t offset = 0; - getRawUInt32(data, 4, &offset, &type); - return type; -} - - -uint32_t getRsItemSize(void *data) -{ - uint32_t size = 0; - uint32_t offset = 4; - getRawUInt32(data, 8, &offset, &size); - return size; -} - -uint8_t getRsItemVersion(uint32_t type) -{ - return (type >> 24); -} - -uint8_t getRsItemClass(uint32_t type) -{ - return (type >> 16) & 0xFF; -} - -uint8_t getRsItemType(uint32_t type) -{ - return (type >> 8) & 0xFF; -} - -uint8_t getRsItemSubType(uint32_t type) -{ - return (type & 0xFF); -} - -uint16_t getRsItemService(uint32_t type) -{ - return (type >> 8) & 0xFFFF; -} - - -std::ostream &printRsItemBase(std::ostream &out, std::string clsName, uint16_t indent) -{ - printIndent(out, indent); - out << "RsItem: " << clsName << " ####################################"; - out << std::endl; - return out; -} - -std::ostream &printRsItemEnd(std::ostream &out, std::string clsName, uint16_t indent) -{ - printIndent(out, indent); - out << "###################### " << clsName << " #####################"; - out << std::endl; - return out; -} - -std::ostream &RsRawItem::print(std::ostream &out, uint16_t indent) -{ - printRsItemBase(out, "RsRawItem", indent); - printIndent(out, indent); - out << "Size: " << len << std::endl; - printRsItemEnd(out, "RsRawItem", indent); - return out; -} - -uint32_t getRsPktMaxSize() { return RsSerialiser::MAX_SERIAL_SIZE; } - -uint32_t getRsPktBaseSize() -{ - return 8; /* 4 + 4 */ -} - diff --git a/libretroshare/src/serialiser/rsserial.h b/libretroshare/src/serialiser/rsserial.h deleted file mode 100644 index 168db8d75..000000000 --- a/libretroshare/src/serialiser/rsserial.h +++ /dev/null @@ -1,114 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rsserial.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include "util/rsdeprecate.h" - -/******************************************************************* - * This is the Top-Level serialiser/deserialise, - * - * Data is Serialised into the following format - * - * ----------------------------------------- - * | TYPE (4 bytes) | Size (4 bytes) | - * ----------------------------------------- - * | | - * | Data .... | - * | | - * ----------------------------------------- - * - * Size is the total size of the packet (including the 8 byte header) - * Type is composed of: - * - * 8 bits: Version (0x01) - * 8 bits: Class - * 8 bits: Type - * 8 bits: SubType - ******************************************************************/ - -const uint8_t RS_PKT_VERSION1 = 0x01; -const uint8_t RS_PKT_VERSION_SERVICE = 0x02; - -const uint8_t RS_PKT_CLASS_BASE = 0x01; -const uint8_t RS_PKT_CLASS_CONFIG = 0x02; - -const uint8_t RS_PKT_SUBTYPE_DEFAULT = 0x01; /* if only one subtype */ - -struct RsItem; -class RsSerialType ; - - -class RsSerialiser -{ -public: - /** Remember that every pqistreamer allocates an input buffer of this size! - * So don't make it too big! */ - static constexpr uint32_t MAX_SERIAL_SIZE = 262143; /* 2^18 -1 */ - - RsSerialiser(); - ~RsSerialiser(); - bool addSerialType(RsSerialType *type); - - uint32_t size(RsItem *); - bool serialise (RsItem *item, void *data, uint32_t *size); - RsItem * deserialise(void *data, uint32_t *size); - - -private: - std::map serialisers; -}; - -bool setRsItemHeader(void *data, uint32_t size, uint32_t type, uint32_t pktsize); - -/* Extract Header Information from Packet */ -uint32_t getRsItemId(void *data); -uint32_t getRsItemSize(void *data); - -uint8_t getRsItemVersion(uint32_t type); -uint8_t getRsItemClass(uint32_t type); -uint8_t getRsItemType(uint32_t type); -uint8_t getRsItemSubType(uint32_t type); - -uint16_t getRsItemService(uint32_t type); - -/* size constants */ -uint32_t getRsPktBaseSize(); - -RS_DEPRECATED_FOR(RsSerialiser::MAX_SERIAL_SIZE) -uint32_t getRsPktMaxSize(); - - - -/* helper fns for printing */ -std::ostream &printRsItemBase(std::ostream &o, std::string n, uint16_t i); -std::ostream &printRsItemEnd(std::ostream &o, std::string n, uint16_t i); - -/* defined in rstlvtypes.cc - redeclared here for ease */ -std::ostream &printIndent(std::ostream &out, uint16_t indent); -/* Wrapper class for data that is serialised somewhere else */ diff --git a/libretroshare/src/serialiser/rsserializable.cc b/libretroshare/src/serialiser/rsserializable.cc deleted file mode 100644 index a5a329e6d..000000000 --- a/libretroshare/src/serialiser/rsserializable.cc +++ /dev/null @@ -1,31 +0,0 @@ -/******************************************************************************* - * libretroshare: retroshare core library * - * * - * Copyright (C) 2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "serialiser/rsserializable.h" - -#include - -std::ostream& operator<<(std::ostream& out, const RsSerializable& serializable) -{ - RsGenericSerializer::SerializeContext ctx; - const_cast(serializable) // safe with TO_JSON - .serial_process(RsGenericSerializer::TO_JSON, ctx); - return out << ctx.mJson; -} diff --git a/libretroshare/src/serialiser/rsserializable.h b/libretroshare/src/serialiser/rsserializable.h deleted file mode 100644 index 5e115e673..000000000 --- a/libretroshare/src/serialiser/rsserializable.h +++ /dev/null @@ -1,58 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rsserializable.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016-2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include "serialiser/rsserializer.h" - -#include - - -/** @brief Minimal ancestor for all serializable structs in RetroShare. - * If you want your struct to be easly serializable you should inherit from this - * struct. - */ -struct RsSerializable -{ - /** Process struct members to serialize in this method taking advantage of - * the helper macro @see RS_SERIAL_PROCESS(I) - */ - virtual void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx) = 0; - - virtual ~RsSerializable() = default; -}; - -/** @def RS_SERIAL_PROCESS(I) - * Use this macro to process the members of `YourSerializable` for serial - * processing inside `YourSerializable::serial_process(j, ctx)` - * - * Pay special attention for member of enum type which must be declared - * specifying the underlying type otherwise the serialization format may differ - * in an uncompatible way depending on the compiler/platform. - * - * Inspired by http://stackoverflow.com/a/39345864 - */ -#define RS_SERIAL_PROCESS(I) do { \ - RsTypeSerializer::serial_process(j, ctx, I, #I ); \ - } while(0) - -std::ostream &operator<<(std::ostream& out, const RsSerializable& serializable); diff --git a/libretroshare/src/serialiser/rsserializer.cc b/libretroshare/src/serialiser/rsserializer.cc deleted file mode 100644 index 1a029ee2e..000000000 --- a/libretroshare/src/serialiser/rsserializer.cc +++ /dev/null @@ -1,289 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rsserializer.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016 Cyril Soler * - * Copyright (C) 2020 Gioacchino Mazzurco * - * Copyright (C) 2020 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - ******************************************************************************/ - -#include - -#include "rsitems/rsitem.h" -#include "util/rsprint.h" -#include "serialiser/rsserializer.h" -#include "serialiser/rstypeserializer.h" -#include "util/stacktrace.h" -#include "util/rsdebug.h" - -RsItem *RsServiceSerializer::deserialise(void *data, uint32_t *size) -{ - if(!data || !size || *size < 8) - { - RsErr() << __PRETTY_FUNCTION__ << " Called with inconsistent parameters data: " << std::endl; - if(data) - RsErr() << "Data is: " << RsUtil::BinToHex(static_cast(data),std::min(50u,*size)) << ((*size>50)?"...":"") << std::endl; - else - RsErr() << "Null Data" << std::endl; - - RsErr() << " size: " << static_cast(size) << " *size: " << (size ? *size : 0) << std::endl - << " this should never happen!" - << std::endl; - print_stacktrace(); - return nullptr; - } - - if(!!(mFlags & RsSerializationFlags::SKIP_HEADER)) - { - RsErr() << __PRETTY_FUNCTION__ << " Cannot deserialise item with flag " - << "SKIP_HEADER. Check your code!" << std::endl; - print_stacktrace(); - return nullptr; - } - - uint32_t rstype = getRsItemId(const_cast((const void*)data)) ; - - RsItem *item = create_item(getRsItemService(rstype),getRsItemSubType(rstype)) ; - - if(!item) - { - std::cerr << "(EE) " << typeid(*this).name() << ": cannot deserialise unknown item subtype " << std::hex << (int)getRsItemSubType(rstype) << std::dec << std::endl; - std::cerr << "(EE) Data is: " << RsUtil::BinToHex(static_cast(data),std::min(50u,*size)) << ((*size>50)?"...":"") << std::endl; - return NULL ; - } - - SerializeContext ctx( - const_cast(static_cast(data)), *size, - mFlags ); - ctx.mOffset = 8 ; - - item->serial_process(RsGenericSerializer::DESERIALIZE, ctx) ; - - if(ctx.mSize < ctx.mOffset) - { - std::cerr << "RsSerializer::deserialise(): ERROR. offset does not match expected size!" << std::endl; - delete item ; - return NULL ; - } - *size = ctx.mOffset ; - - if(ctx.mOk) - return item ; - - delete item ; - return NULL ; -} -RsItem *RsConfigSerializer::deserialise(void *data, uint32_t *size) -{ - if(!!(mFlags & RsSerializationFlags::SKIP_HEADER)) - { - RsErr() << __PRETTY_FUNCTION__ << " Cannot deserialise item with flag " - << "SKIP_HEADER. Check your code!" << std::endl; - print_stacktrace(); - return nullptr; - } - - uint32_t rstype = getRsItemId(const_cast((const void*)data)) ; - - RsItem *item = create_item(getRsItemType(rstype),getRsItemSubType(rstype)) ; - - if(!item) - { - std::cerr << "(EE) " << typeid(*this).name() << ": cannot deserialise unknown item subtype " << std::hex << (int)getRsItemSubType(rstype) << std::dec << std::endl; - std::cerr << "(EE) Data is: " << RsUtil::BinToHex(static_cast(data),std::min(50u,*size)) << ((*size>50)?"...":"") << std::endl; - return NULL ; - } - - SerializeContext ctx( - const_cast(static_cast(data)), *size, - mFlags ); - ctx.mOffset = 8 ; - - item->serial_process(DESERIALIZE, ctx) ; - - if(ctx.mSize < ctx.mOffset) - { - std::cerr << "RsSerializer::deserialise(): ERROR. offset does not match expected size!" << std::endl; - delete item ; - return NULL ; - } - *size = ctx.mOffset ; - - if(ctx.mOk) - return item ; - - delete item ; - return NULL ; -} - -bool RsGenericSerializer::serialise(RsItem* item, void* data, uint32_t* size) -{ - uint32_t tlvsize = this->size(item); - - constexpr auto fName = __PRETTY_FUNCTION__; - const auto failure = [=](std::error_condition ec) - { - RsErr() << fName << " " << ec << std::endl; - print_stacktrace(); - return false; - }; - - if(tlvsize > *size) return failure(std::errc::no_buffer_space); - - SerializeContext ctx(static_cast(data), tlvsize, mFlags); - - if(!(mFlags & RsSerializationFlags::SKIP_HEADER)) - { - if(!setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize)) - return failure(std::errc::no_buffer_space); - ctx.mOffset = 8; - } - - item->serial_process(RsGenericSerializer::SERIALIZE,ctx); - - if(ctx.mSize != ctx.mOffset) return failure(std::errc::message_size); - - *size = ctx.mOffset; - return true; -} - -uint32_t RsGenericSerializer::size(RsItem *item) -{ - SerializeContext ctx(nullptr, 0, mFlags); - - if(!!(mFlags & RsSerializationFlags::SKIP_HEADER)) ctx.mOffset = 0; - else ctx.mOffset = 8; // header size - item->serial_process(SIZE_ESTIMATE, ctx) ; - - return ctx.mOffset ; -} - -void RsGenericSerializer::print(RsItem *item) -{ - SerializeContext ctx(nullptr, 0, mFlags); - - std::cerr << "***** RsItem class: \"" << typeid(*item).name() << "\" *****" << std::endl; - item->serial_process(PRINT, ctx) ; - std::cerr << "******************************" << std::endl; -} - -uint32_t RsRawSerialiser::size(RsItem *i) -{ - RsRawItem *item = dynamic_cast(i); - - if (item) - { - return item->getRawLength(); - } - return 0; -} - -/* serialise the data to the buffer */ -bool RsRawSerialiser::serialise(RsItem *i, void *data, uint32_t *pktsize) -{ - RsRawItem *item = dynamic_cast(i); - if (!item) - { - return false; - } - - #ifdef RSSERIAL_DEBUG - std::cerr << "RsRawSerialiser::serialise() serializing raw item. pktsize : " << *pktsize; - #endif - - uint32_t tlvsize = item->getRawLength(); - #ifdef RSSERIAL_DEBUG - std::cerr << "tlvsize : " << tlvsize << std::endl; - #endif - - if (*pktsize < tlvsize) - return false; /* not enough space */ - - if (tlvsize > getRsPktMaxSize()) - { - std::cerr << "(EE) Serialised packet is too big. Maximum allowed size is " << getRsPktMaxSize() << ". Serialised size is " << tlvsize << ". Please tune your service to correctly split packets" << std::endl; - return false; /* packet too big */ - } - - *pktsize = tlvsize; - - /* its serialised already!!! */ - memcpy(data, item->getRawData(), tlvsize); - - return true; -} - -RsItem *RsRawSerialiser::deserialise(void *data, uint32_t *pktsize) -{ - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t rssize = getRsItemSize(data); - - if (RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) - { - return NULL; /* wrong type */ - } - - if (*pktsize < rssize) /* check size */ - return NULL; /* not enough data */ - - if (rssize > getRsPktMaxSize()) - return NULL; /* packet too big */ - - /* set the packet length */ - *pktsize = rssize; - - RsRawItem *item = new RsRawItem(rstype, rssize); - void *item_data = item->getRawData(); - - memcpy(item_data, data, rssize); - - return item; -} - - -RsGenericSerializer::SerializeContext::SerializeContext( - uint8_t* data, uint32_t size, RsSerializationFlags flags, - RsJson::AllocatorType* allocator ) : - mData(data), mSize(size), mOffset(0), mOk(true), mFlags(flags), - mJson(rapidjson::kObjectType, allocator) -{ - if(data) - { - if(size == 0) - { - RsFatal() << __PRETTY_FUNCTION__ << " data passed without " - << "size! This make no sense report to developers!" - << std::endl; - print_stacktrace(); - exit(-EINVAL); - } - - if(!!(flags & RsSerializationFlags::YIELDING)) - { - RsFatal() << __PRETTY_FUNCTION__ - << " Attempt to create a " - << "binary serialization context with " - << "SERIALIZATION_FLAG_YIELDING! " - << "This make no sense report to developers!" - << std::endl; - print_stacktrace(); - exit(-EINVAL); - } - } -} diff --git a/libretroshare/src/serialiser/rsserializer.h b/libretroshare/src/serialiser/rsserializer.h deleted file mode 100644 index 1b67e2675..000000000 --- a/libretroshare/src/serialiser/rsserializer.h +++ /dev/null @@ -1,319 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rsserializer.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016 Cyril Soler * - * Copyright (C) 2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Retroshare Serialization code // -/////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Classes -// ======= -// -// RsSerialiser ----------------+ std::map -// -// RsSerialType -// | -// +----------- RsRawSerializer -// | -// +----------- RsGenericSerializer -// | -// +----------- RsConfigSerializer -// | | -// | +----------- Specific config serializers -// | +----------- ... -// | -// +----------- RsServiceSerializer -// | -// +----------- Specific service serializers -// +----------- ... -// +----------- ... -// -// -// Steps to derive a serializer for a new service: -// ============================================== -// -// 1 - create a serializer class, and overload create_item() to create a new item of your own service for each item type constant: -// -// class MyServiceSerializer: public RsServiceSerializer -// { -// MyServiceSerializer() : RsServiceSerializer(MY_SERVICE_IDENTIFIER) {} -// -// RsItem *create_item(uint16_t service,uint8_t item_subtype) const // mind the "const"! -// { -// if(service != MY_SERVICE_IDENTIFIER) return NULL ; -// -// switch(item_subtype) -// { -// case MY_ITEM_SUBTYPE_01: return new MyServiceItem(); -// default: -// return NULL ; -// } -// } -// } -// -// 2 - create your own items, and overload serial_process in order to define the serialized structure: -// -// class MyServiceItem: public RsItem -// { -// virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -// { -// RsTypeSerializer::serial_process (j,ctx,count,"count") ; // uint32_t is not really needed here, except for explicitly avoiding int types convertion -// RsTypeSerializer::serial_process (j,ctx,update_times,"update_times") ; // will serialize the map and its content -// RsTypeSerializer::serial_process(j,ctx,key,"key") ; // note the explicit call to TlvItem -// RsTypeSerializer::serial_process (j,ctx,dh_key,"dh_key") ; // template will automatically require serialise/deserialise/size/print_data for your type -// } -// -// private: -// uint32_t count ; // example of an int type. All int sizes are supported -// std::map update_times ; // example of a std::map. All std containers are supported. -// RsTlvSecurityKey key ; // example of a TlvItem class. -// BIGNUM *dh_key; // example of a class that needs its own serializer (see below) -// }; -// -// Some types may not be already handled by RsTypeSerializer, so in this case, you need to specialise the template for your own type. But this is quite unlikely to -// happen. In most cases, for instance in your structure types, serialization is directly done by calling RsTypeSerializer::serial_process() on each member of the type. -// In case you really need a specific serialization for soe particular type, here is how to do it, with the example of BIGNUM* (a crypto primitive): -// -// template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset, BIGNUM * const & member) -// { -// uint32_t s = BN_num_bytes(member) ; -// -// if(size < offset + 4 + s) -// return false ; -// -// bool ok = true ; -// ok &= setRawUInt32(data, size, &offset, s); -// -// BN_bn2bin(member,&((unsigned char *)data)[offset]) ; -// offset += s ; -// -// return ok; -// } -// template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, BIGNUM *& member) -// { -// uint32_t s=0 ; -// bool ok = true ; -// ok &= getRawUInt32(data, size, &offset, &s); -// -// if(s > size || size - s < offset) -// return false ; -// -// member = BN_bin2bn(&((unsigned char *)data)[offset],s,NULL) ; -// offset += s ; -// -// return ok; -// } -// template<> uint32_t RsTypeSerializer::serial_size(BIGNUM * const & member) -// { -// return 4 + BN_num_bytes(member) ; -// } -// template<> void RsTypeSerializer::print_data(const std::string& name,BIGNUM * const & /* member */) -// { -// std::cerr << "[BIGNUM] : " << name << std::endl; -// } -// -// 3 - in your service, overload the serialiser declaration to add your own: -// -// MyService::MyService() -// { -// addSerialType(new MyServiceSerializer()) ; -// } -// -// If needed, you may serialize your own items by calling: -// -// uint32_t size = MySerializer().size(item) ; -// uint8_t *data = (uint8_t*)malloc(size); -// MySerializer().serialise(item,data,size) ; -// -// 4 - in your service, receive and send items by calling recvItem() and sendItem() respectively. -// -#include -#include -#include -#include - -#include "retroshare/rsflags.h" -#include "serialiser/rsserial.h" -#include "util/rsdeprecate.h" -#include "util/rsjson.h" - -struct RsItem; - -// This is the base class for serializers. - -class RsSerialType -{ -public: - RsSerialType(uint32_t t); /* only uses top 24bits */ - RsSerialType(uint8_t ver, uint8_t cls, uint8_t t); - RsSerialType(uint8_t ver, uint16_t service); - - virtual ~RsSerialType(); - - virtual uint32_t size(RsItem *)=0; - virtual bool serialise (RsItem *item, void *data, uint32_t *size)=0; - virtual RsItem * deserialise(void *data, uint32_t *size)=0; - - uint32_t PacketId() const; -private: - uint32_t type; -}; - -// This class is only used internally to p3service. It should not be used explicitely otherwise. - -class RsRawSerialiser: public RsSerialType -{ - public: - RsRawSerialiser() :RsSerialType(RS_PKT_VERSION_SERVICE, 0, 0) {} - virtual ~RsRawSerialiser() { } - - virtual uint32_t size(RsItem *); - virtual bool serialise (RsItem *item, void *data, uint32_t *size); - virtual RsItem * deserialise(void *data, uint32_t *size); -}; - -/** These are convenience flags to be used by the items when processing the - * data. The names of the flags are not very important. What matters is that - * the serial_process() method of each item correctly deals with the data - * when it sees the flags, if the serialiser sets them. - * By default the flags are not set and shouldn't be handled. - * When deriving a new serializer, the user can set his own flags, using - * compatible values - */ -enum class RsSerializationFlags -{ - NONE = 0, - CONFIG = 1, - SIGNATURE = 2, - SKIP_HEADER = 4, - - /** Used for JSON deserialization in JSON API, it causes the deserialization - * to continue even if some field is missing (or incorrect), this way the - * API is more user friendly as some methods need just part of the structs - * they take as parameters. */ - YIELDING = 8, - - /** When set integers typer are serialized/deserialized in Variable Length - * Quantity mode - * @see https://en.wikipedia.org/wiki/Variable-length_quantity - * This type of encoding is efficent when absoulte value is usually much - * smaller then the maximum representable with the original type. - * This encoding is also capable of representing big values at expences of a - * one more byte used. - */ - INTEGER_VLQ = 16 -}; -RS_REGISTER_ENUM_FLAGS_TYPE(RsSerializationFlags); - -/// Top class for all services and config serializers. -struct RsGenericSerializer : RsSerialType -{ - typedef enum - { - SIZE_ESTIMATE = 0x01, - SERIALIZE = 0x02, - DESERIALIZE = 0x03, - PRINT = 0x04, /// @deprecated use rsdebug.h << operator instead - TO_JSON, - FROM_JSON - } SerializeJob; - - struct SerializeContext - { - /** Allow shared allocator usage to avoid costly JSON deepcopy for - * nested RsSerializable */ - SerializeContext( - uint8_t* data = nullptr, uint32_t size = 0, - RsSerializationFlags flags = RsSerializationFlags::NONE, - RsJson::AllocatorType* allocator = nullptr); - - unsigned char *mData; - uint32_t mSize; - uint32_t mOffset; - bool mOk; - RsSerializationFlags mFlags; - RsJson mJson; - }; - - /** - * The following functions overload RsSerialType. - * They *should not* need to be further overloaded. - */ - RsItem *deserialise(void *data,uint32_t *size) = 0; - bool serialise(RsItem *item,void *data,uint32_t *size); - uint32_t size(RsItem *item); - void print(RsItem *item); - -protected: - RsGenericSerializer( - uint8_t serial_class, uint8_t serial_type, - RsSerializationFlags flags ): - RsSerialType( RS_PKT_VERSION1, serial_class, serial_type), - mFlags(flags) {} - - RsGenericSerializer( - uint16_t service, RsSerializationFlags flags ): - RsSerialType( RS_PKT_VERSION_SERVICE, service ), mFlags(flags) {} - - RsSerializationFlags mFlags; -}; - - -/** Top class for service serializers. - * Derive your on service serializer from this class and overload creat_item(). - */ -struct RsServiceSerializer : RsGenericSerializer -{ - RsServiceSerializer( - uint16_t service_id, - RsSerializationFlags flags = RsSerializationFlags::NONE ) : - RsGenericSerializer(service_id, flags) {} - - /*! should be overloaded to create the correct type of item depending on the - * data */ - virtual RsItem *create_item( uint16_t /* service */, - uint8_t /* item_sub_id */ ) const = 0; - - RsItem *deserialise(void *data, uint32_t *size); -}; - - -/** Top class for config serializers. - * Config serializers are only used internally by RS core. - * The development of new services or plugins do not need this. - */ -struct RsConfigSerializer : RsGenericSerializer -{ - RsConfigSerializer( - uint8_t config_class, uint8_t config_type, - RsSerializationFlags flags = RsSerializationFlags::NONE ) : - RsGenericSerializer(config_class, config_type, flags) {} - - /*! should be overloaded to create the correct type of item depending on the - * data */ - virtual RsItem *create_item(uint8_t /* item_type */, - uint8_t /* item_sub_type */) const = 0; - - RsItem *deserialise(void *data,uint32_t *size); -}; - diff --git a/libretroshare/src/serialiser/rstlvaddrs.cc b/libretroshare/src/serialiser/rstlvaddrs.cc deleted file mode 100644 index 5f9a06390..000000000 --- a/libretroshare/src/serialiser/rstlvaddrs.cc +++ /dev/null @@ -1,434 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvaddr.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvaddrs.h" -#include "serialiser/rsbaseserial.h" - -/************************************* RsTlvIpAddress ************************************/ - -RsTlvIpAddress::RsTlvIpAddress() - :RsTlvItem() -{ - sockaddr_storage_clear(addr); - return; -} - -void RsTlvIpAddress::TlvClear() -{ - sockaddr_storage_clear(addr); -} - -uint32_t RsTlvIpAddress::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; - switch(addr.ss_family) - { - default: - case 0: - break; - case AF_INET: - s += GetTlvIpAddrPortV4Size(); - break; - case AF_INET6: - s += GetTlvIpAddrPortV6Size(); - break; - } - return s; -} - -bool RsTlvIpAddress::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - /* add mandatory parts first */ - - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_ADDRESS, tlvsize); - - switch(addr.ss_family) - { - default: - case 0: - break; - case AF_INET: - ok &= SetTlvIpAddrPortV4(data, tlvend, offset, TLV_TYPE_IPV4, (struct sockaddr_in *) &addr); - break; - - case AF_INET6: - ok &= SetTlvIpAddrPortV6(data, tlvend, offset, TLV_TYPE_IPV6, (struct sockaddr_in6 *) &addr); - break; - } - return ok; - -} - - -bool RsTlvIpAddress::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_ADDRESS) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - if (*offset == tlvend) - { - /* empty address */ - return ok; - } - - uint16_t iptype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - switch(iptype) - { - case TLV_TYPE_IPV4: - ok &= GetTlvIpAddrPortV4(data, tlvend, offset, TLV_TYPE_IPV4, (struct sockaddr_in *) &addr); - break; - case TLV_TYPE_IPV6: - ok &= GetTlvIpAddrPortV6(data, tlvend, offset, TLV_TYPE_IPV6, (struct sockaddr_in6 *) &addr); - break; - default: - break; - } - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvIpAddress::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; - -} - - -std::ostream &RsTlvIpAddress::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvIpAddress", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - out << "Address:" << sockaddr_storage_tostring(addr) << std::endl; - - printEnd(out, "RsTlvIpAddress", indent); - return out; -} - - - - -/************************************* RsTlvIpAddressInfo ************************************/ - -RsTlvIpAddressInfo::RsTlvIpAddressInfo() - :RsTlvItem(), seenTime(0), source(0) -{ - addr.TlvClear(); - return; -} - -void RsTlvIpAddressInfo::TlvClear() -{ - addr.TlvClear(); - seenTime = 0; - source = 0; -} - -uint32_t RsTlvIpAddressInfo::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header + IpAddr + 8 for time & 4 for size */ - - s += addr.TlvSize(); - s += 8; // seenTime - s += 4; // source - - return s; - -} - -bool RsTlvIpAddressInfo::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - /* add mandatory parts first */ - - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_ADDRESS_INFO, tlvsize); - - ok &= addr.SetTlv(data, tlvend, offset); - ok &= setRawUInt64(data, tlvend, offset, seenTime); - ok &= setRawUInt32(data, tlvend, offset, source); - - return ok; - -} - - -bool RsTlvIpAddressInfo::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_ADDRESS_INFO) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - ok &= addr.GetTlv(data, tlvend, offset); - ok &= getRawUInt64(data, tlvend, offset, &(seenTime)); - ok &= getRawUInt32(data, tlvend, offset, &(source)); - - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvIpAddressInfo::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; - -} - - -std::ostream &RsTlvIpAddressInfo::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvIpAddressInfo", indent); - uint16_t int_Indent = indent + 2; - - addr.print(out, int_Indent); - - printIndent(out, int_Indent); - out << "SeenTime:" << seenTime; - out << std::endl; - - printIndent(out, int_Indent); - out << "Source:" << source; - out << std::endl; - - printEnd(out, "RsTlvIpAddressInfo", indent); - return out; -} - - - -#if 0 -/************************************* RsTlvIpAddrSet ************************************/ - -void RsTlvIpAddrSet::TlvClear() -{ - addrs.clear(); -} - -uint32_t RsTlvIpAddrSet::TlvSize() const -{ - - uint32_t s = TLV_HEADER_SIZE; /* header */ - - std::list::iterator it; - - - if(!addrs.empty()) - { - - for(it = addrs.begin(); it != addrs.end() ; ++it) - s += it->TlvSize(); - - } - - return s; -} - -bool RsTlvIpAddrSet::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_ADDRESS_SET , tlvsize); - - if(!addrs.empty()) - { - std::list::iterator it; - - for(it = addrs.begin(); it != addrs.end() ; ++it) - ok &= it->SetTlv(data, size, offset); - } - - -return ok; - -} - - -bool RsTlvIpAddrSet::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_ADDRESS_SET) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - /* while there is TLV */ - while((*offset) + 2 < tlvend) - { - /* get the next type */ - uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - - switch(tlvsubtype) - { - case TLV_TYPE_ADDRESS_INFO: - { - RsTlvIpAddressInfo addr; - ok &= addr.GetTlv(data, size, offset); - if (ok) - { - addrs.push_back(addr); - } - } - break; - default: - ok &= SkipUnknownTlv(data, tlvend, offset); - break; - - } - - if (!ok) - break; - } - - - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvIpAddrSet::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; -} - -// prints out contents of RsTlvIpAddrSet -std::ostream &RsTlvIpAddrSet::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvIpAddrSet", indent); - uint16_t int_Indent = indent + 2; - - std::list::iterator it; - for(it = addrs.begin(); it != addrs.end() ; ++it) - it->print(out, int_Indent); - - printEnd(out, "RsTlvIpAddrSet", indent); - return out; -} - - -/************************************* RsTlvIpAddressInfo ************************************/ - -#endif diff --git a/libretroshare/src/serialiser/rstlvaddrs.h b/libretroshare/src/serialiser/rstlvaddrs.h deleted file mode 100644 index 07b668559..000000000 --- a/libretroshare/src/serialiser/rstlvaddrs.h +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvaddr.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -/******************************************************************* - * These are the Compound TLV structures that must be (un)packed. - ******************************************************************/ - -#include "serialiser/rstlvitem.h" -#include "util/rsnet.h" -#include - -#include "serialiser/rstlvlist.h" - -class RsTlvIpAddress: public RsTlvItem -{ - public: - RsTlvIpAddress(); -virtual ~RsTlvIpAddress() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - struct sockaddr_storage addr; // Mandatory : -}; - - -class RsTlvIpAddressInfo: public RsTlvItem -{ - public: - RsTlvIpAddressInfo(); -virtual ~RsTlvIpAddressInfo() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - RsTlvIpAddress addr; // Mandatory : - uint64_t seenTime; // Mandatory : - uint32_t source; // Mandatory : -}; - -typedef t_RsTlvList RsTlvIpAddrSet; - -#if 0 -class RsTlvIpAddrSet: public RsTlvItem -{ - public: - RsTlvIpAddrSet() { return; } -virtual ~RsTlvIpAddrSet() { return; } -virtual uint32_t TlvSize(); -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset); /* serialise */ -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); /* deserialise */ -virtual std::ostream &print(std::ostream &out, uint16_t indent); - - std::list addrs; // Mandatory : -}; -#endif - - diff --git a/libretroshare/src/serialiser/rstlvbanlist.cc b/libretroshare/src/serialiser/rstlvbanlist.cc deleted file mode 100644 index 92bd3a6d2..000000000 --- a/libretroshare/src/serialiser/rstlvbanlist.cc +++ /dev/null @@ -1,172 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvbanlist.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "serialiser/rstlvbanlist.h" -#include "serialiser/rstlvbase.h" - -#include "serialiser/rsbaseserial.h" - - -/************************************* RsTlvBanListEntry ************************************/ - -RsTlvBanListEntry::RsTlvBanListEntry() - :RsTlvItem(), level(0), reason(0), age(0) -{ - return; -} - -void RsTlvBanListEntry::TlvClear() -{ - addr.TlvClear(); - level = 0; - reason = 0; - age = 0; - comment.clear(); - masked_bytes = 0; -} - -uint32_t RsTlvBanListEntry::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; - - s += addr.TlvSize(); - s += 4; // level; - s += 4; // reason; - s += 4; // age; - s += 1; // masked_bytes; - s += GetTlvStringSize(comment) ; - - return s; - -} - -bool RsTlvBanListEntry::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - /* add mandatory parts first */ - - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_BAN_ENTRY, tlvsize); - - ok &= addr.SetTlv(data, tlvend, offset); - ok &= setRawUInt32(data, tlvend, offset, level); - ok &= setRawUInt32(data, tlvend, offset, reason); - ok &= setRawUInt32(data, tlvend, offset, age); - ok &= setRawUInt8(data, tlvend, offset, masked_bytes); - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_COMMENT, comment); - - return ok; - -} - - -bool RsTlvBanListEntry::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_BAN_ENTRY) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - ok &= addr.GetTlv(data, tlvend, offset); - ok &= getRawUInt32(data, tlvend, offset, &(level)); - ok &= getRawUInt32(data, tlvend, offset, &(reason)); - ok &= getRawUInt32(data, tlvend, offset, &(age)); - - uint8_t tmp ; - ok &= getRawUInt8(data, tlvend, offset, &(tmp)); - masked_bytes = tmp ; - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_COMMENT, comment); - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvBanListEntry::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; - -} - - -std::ostream &RsTlvBanListEntry::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvBanListEntry", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - out << "addr:" << std::endl; - addr.print(out, int_Indent); - - printIndent(out, int_Indent); - out << "level:" << level; - out << std::endl; - - printIndent(out, int_Indent); - out << "reason:" << reason; - out << std::endl; - - printIndent(out, int_Indent); - out << "age:" << age; - out << std::endl; - - printIndent(out, int_Indent); - out << "masked bytes:" << masked_bytes; - out << std::endl; - - printEnd(out, "RsTlvBanListEntry", indent); - return out; -} - - - diff --git a/libretroshare/src/serialiser/rstlvbanlist.h b/libretroshare/src/serialiser/rstlvbanlist.h deleted file mode 100644 index a08f92a7a..000000000 --- a/libretroshare/src/serialiser/rstlvbanlist.h +++ /dev/null @@ -1,57 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvbanlist.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -/******************************************************************* - * These are the Compound TLV structures that must be (un)packed. - ******************************************************************/ - -#include "serialiser/rstlvitem.h" -#include "serialiser/rstlvaddrs.h" -#include "serialiser/rstlvlist.h" -#include "serialiser/rstlvbase.h" - -#define RSDSDV_MAX_ROUTE_TABLE 1000 - -class RsTlvBanListEntry: public RsTlvItem -{ - public: - RsTlvBanListEntry(); -virtual ~RsTlvBanListEntry() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - RsTlvIpAddress addr; - uint32_t level; - uint32_t reason; - uint32_t age; - uint8_t masked_bytes ; - std::string comment ; -}; - -typedef t_RsTlvList RsTlvBanList; - - - diff --git a/libretroshare/src/serialiser/rstlvbase.cc b/libretroshare/src/serialiser/rstlvbase.cc deleted file mode 100644 index 9cf713193..000000000 --- a/libretroshare/src/serialiser/rstlvbase.cc +++ /dev/null @@ -1,1007 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvbase.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie, Horatio, Chris Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include - -#include "serialiser/rstlvbase.h" -#include "serialiser/rsbaseserial.h" - -//********************* - -// A facility func -inline void* right_shift_void_pointer(const void* p, uint32_t len) { - - return (void*)( (uint8_t*)p + len); -} -//********************* - -//#define TLV_BASE_DEBUG 1 - -/**** Basic TLV Functions ****/ -uint32_t GetTlvSize(void *data) { - if (!data) - return 0; - - uint32_t len; - - void * from =right_shift_void_pointer(data, TLV_HEADER_TYPE_SIZE); - - memcpy((void *)&len, from , TLV_HEADER_LEN_SIZE); - - len = ntohl(len); - - return len; -} - -uint16_t GetTlvType(void *data) { - if (!data) - return 0; - - uint16_t type; - - memcpy((void*)&type, data, TLV_HEADER_TYPE_SIZE); - - type = ntohs(type); - - return type; - -} - -//tested -bool SetTlvBase(void *data, uint32_t size, uint32_t *offset, uint16_t type, - uint32_t len) { - if (!data) - return false; - if (!offset) - return false; - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t type_n = htons(type); - - //copy type_n to (data+*offset) - void* to = right_shift_void_pointer(data, *offset); - memcpy(to , (void*)&type_n, TLV_HEADER_TYPE_SIZE); - - uint32_t len_n =htonl(len); - //copy len_n to (data + *offset +2) - to = right_shift_void_pointer(to, TLV_HEADER_TYPE_SIZE); - memcpy((void *)to, (void*)&len_n, TLV_HEADER_LEN_SIZE); - - *offset += TLV_HEADER_SIZE; - - return true; -} - -bool SetTlvType(void *data, uint32_t size, uint16_t type) -{ - if (!data) - return false; - - if(size < TLV_HEADER_SIZE ) - return false; - - uint16_t type_n = htons(type); - memcpy(data , (void*)&type_n, TLV_HEADER_TYPE_SIZE); - return true; -} - -//tested -bool SetTlvSize(void *data, uint32_t size, uint32_t len) { - if (!data) - return false; - - if(size < TLV_HEADER_SIZE ) - return false; - - uint32_t len_n = htonl(len); - - void * to = (void*)((uint8_t *) data + TLV_HEADER_TYPE_SIZE); - - memcpy(to, (void*) &len_n, TLV_HEADER_LEN_SIZE); - - return true; - -} - -/* Step past unknown TLV TYPE */ -bool SkipUnknownTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (!data) - return false; - - if (size < *offset + TLV_HEADER_SIZE) - return false; - - /* extract the type and size */ - void *tlvstart = right_shift_void_pointer(data, *offset); - //uint16_t tlvtype = GetTlvType(tlvstart); - uint32_t tlvsize = GetTlvSize(tlvstart); - - /* check that there is size */ - uint32_t tlvend = *offset + tlvsize; - if (size < tlvend) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "SkipUnknownTlv() FAILED - not enough space." << std::endl; - std::cerr << "SkipUnknownTlv() size: " << size << std::endl; - std::cerr << "SkipUnknownTlv() tlvsize: " << tlvsize << std::endl; - std::cerr << "SkipUnknownTlv() tlvend: " << tlvend << std::endl; -#endif - return false; - } - - bool ok = true; - /* step past this tlv item */ - *offset = tlvend; - return ok; -} - - -/**** Generic TLV Functions **** - * This have the same data (int or string for example), - * but they can have different types eg. a string could represent a name or a path, - * so we include a type parameter in the arguments - */ -//tested -bool SetTlvUInt32(void *data, uint32_t size, uint32_t *offset, uint16_t type, - uint32_t out) -{ - if (!data) - return false; - uint32_t tlvsize = GetTlvUInt32Size(); /* this will always be 8 bytes */ - uint32_t tlvend = *offset + tlvsize; /* where the data will extend to */ - if (size < tlvend) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "SetTlvUInt32() FAILED - not enough space. (or earlier)" << std::endl; - std::cerr << "SetTlvUInt32() size: " << size << std::endl; - std::cerr << "SetTlvUInt32() tlvsize: " << tlvsize << std::endl; - std::cerr << "SetTlvUInt32() tlvend: " << tlvend << std::endl; -#endif - return false; - } - - bool ok = true; - - /* Now use the function we got to set the TlvHeader */ - /* function shifts offset to the new start for the next data */ - ok &= SetTlvBase(data, tlvend, offset, type, tlvsize); - -#ifdef TLV_BASE_DEBUG - if (!ok) - { - std::cerr << "SetTlvUInt32() SetTlvBase FAILED (or earlier)" << std::endl; - } -#endif - - /* now set the UInt32 ( in rsbaseserial.h???) */ - ok &= setRawUInt32(data, tlvend, offset, out); - -#ifdef TLV_BASE_DEBUG - if (!ok) - { - std::cerr << "SetTlvUInt32() setRawUInt32 FAILED (or earlier)" << std::endl; - } -#endif - - - return ok; - -} - -//tested -bool GetTlvUInt32(void *data, uint32_t size, uint32_t *offset, - uint16_t type, uint32_t *in) -{ - if (!data) - return false; - - if (size < *offset + TLV_HEADER_SIZE) - return false; - - /* extract the type and size */ - void *tlvstart = right_shift_void_pointer(data, *offset); - uint16_t tlvtype = GetTlvType(tlvstart); - uint32_t tlvsize = GetTlvSize(tlvstart); - - /* check that there is size */ - uint32_t tlvend = *offset + tlvsize; - if (size < tlvend) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "GetTlvUInt32() FAILED - not enough space." << std::endl; - std::cerr << "GetTlvUInt32() size: " << size << std::endl; - std::cerr << "GetTlvUInt32() tlvsize: " << tlvsize << std::endl; - std::cerr << "GetTlvUInt32() tlvend: " << tlvend << std::endl; -#endif - return false; - } - - if (type != tlvtype) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "GetTlvUInt32() FAILED - Type mismatch" << std::endl; - std::cerr << "GetTlvUInt32() type: " << type << std::endl; - std::cerr << "GetTlvUInt32() tlvtype: " << tlvtype << std::endl; -#endif - return false; - } - - *offset += TLV_HEADER_SIZE; /* step past header */ - - bool ok = true; - ok &= getRawUInt32(data, tlvend, offset, in); - - return ok; -} - -// UInt16 -bool SetTlvUInt16(void *data, uint32_t size, uint32_t *offset, uint16_t type, - uint16_t out) -{ - if (!data) - return false; - uint32_t tlvsize = GetTlvUInt16Size(); /* this will always be 8 bytes */ - uint32_t tlvend = *offset + tlvsize; /* where the data will extend to */ - if (size < tlvend) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "SetTlvUInt16() FAILED - not enough space. (or earlier)" << std::endl; - std::cerr << "SetTlvUInt16() size: " << size << std::endl; - std::cerr << "SetTlvUInt16() tlvsize: " << tlvsize << std::endl; - std::cerr << "SetTlvUInt16() tlvend: " << tlvend << std::endl; -#endif - return false; - } - - bool ok = true; - - /* Now use the function we got to set the TlvHeader */ - /* function shifts offset to the new start for the next data */ - ok &= SetTlvBase(data, tlvend, offset, type, tlvsize); - -#ifdef TLV_BASE_DEBUG - if (!ok) - { - std::cerr << "SetTlvUInt16() SetTlvBase FAILED (or earlier)" << std::endl; - } -#endif - - /* now set the UInt16 ( in rsbaseserial.h???) */ - ok &= setRawUInt16(data, tlvend, offset, out); - -#ifdef TLV_BASE_DEBUG - if (!ok) - { - std::cerr << "SetTlvUInt16() setRawUInt16 FAILED (or earlier)" << std::endl; - } -#endif - - - return ok; - -} - -bool GetTlvUInt16(void *data, uint32_t size, uint32_t *offset, - uint16_t type, uint16_t *in) -{ - if (!data) - return false; - - if (size < *offset + TLV_HEADER_SIZE) - return false; - - /* extract the type and size */ - void *tlvstart = right_shift_void_pointer(data, *offset); - uint16_t tlvtype = GetTlvType(tlvstart); - uint32_t tlvsize = GetTlvSize(tlvstart); - - /* check that there is size */ - uint32_t tlvend = *offset + tlvsize; - if (size < tlvend) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "GetTlvUInt16() FAILED - not enough space." << std::endl; - std::cerr << "GetTlvUInt16() size: " << size << std::endl; - std::cerr << "GetTlvUInt16() tlvsize: " << tlvsize << std::endl; - std::cerr << "GetTlvUInt16() tlvend: " << tlvend << std::endl; -#endif - return false; - } - - if (type != tlvtype) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "GetTlvUInt16() FAILED - Type mismatch" << std::endl; - std::cerr << "GetTlvUInt16() type: " << type << std::endl; - std::cerr << "GetTlvUInt16() tlvtype: " << tlvtype << std::endl; -#endif - return false; - } - - *offset += TLV_HEADER_SIZE; /* step past header */ - - bool ok = true; - ok &= getRawUInt16(data, tlvend, offset, in); - - return ok; -} - - -uint32_t GetTlvUInt64Size() { - return TLV_HEADER_SIZE + 8; -} - -uint32_t GetTlvUInt32Size() { - return TLV_HEADER_SIZE + 4; -} - -uint32_t GetTlvUInt16Size() { - return TLV_HEADER_SIZE + sizeof(uint16_t); - -} - -uint32_t GetTlvUInt8Size() { - return TLV_HEADER_SIZE + sizeof(uint8_t); - -} - - -bool SetTlvUInt64(void *data, uint32_t size, uint32_t *offset, uint16_t type, - uint64_t out) -{ - if (!data) - return false; - uint32_t tlvsize = GetTlvUInt64Size(); - uint32_t tlvend = *offset + tlvsize; - if (size < tlvend) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "SetTlvUInt64() FAILED - not enough space. (or earlier)" << std::endl; - std::cerr << "SetTlvUInt64() size: " << size << std::endl; - std::cerr << "SetTlvUInt64() tlvsize: " << tlvsize << std::endl; - std::cerr << "SetTlvUInt64() tlvend: " << tlvend << std::endl; -#endif - return false; - } - - bool ok = true; - - /* Now use the function we got to set the TlvHeader */ - /* function shifts offset to the new start for the next data */ - ok &= SetTlvBase(data, tlvend, offset, type, tlvsize); - -#ifdef TLV_BASE_DEBUG - if (!ok) - { - std::cerr << "SetTlvUInt64() SetTlvBase FAILED (or earlier)" << std::endl; - } -#endif - - /* now set the UInt64 ( in rsbaseserial.h???) */ - ok &= setRawUInt64(data, tlvend, offset, out); - -#ifdef TLV_BASE_DEBUG - if (!ok) - { - std::cerr << "SetTlvUInt64() setRawUInt64 FAILED (or earlier)" << std::endl; - } -#endif - - return ok; - -} - -bool GetTlvUInt64(void *data, uint32_t size, uint32_t *offset, - uint16_t type, uint64_t *in) -{ - if (!data) - return false; - - if (size < *offset + TLV_HEADER_SIZE) - return false; - - /* extract the type and size */ - void *tlvstart = right_shift_void_pointer(data, *offset); - uint16_t tlvtype = GetTlvType(tlvstart); - uint32_t tlvsize = GetTlvSize(tlvstart); - - /* check that there is size */ - uint32_t tlvend = *offset + tlvsize; - if (size < tlvend) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "GetTlvUInt64() FAILED - not enough space." << std::endl; - std::cerr << "GetTlvUInt64() size: " << size << std::endl; - std::cerr << "GetTlvUInt64() tlvsize: " << tlvsize << std::endl; - std::cerr << "GetTlvUInt64() tlvend: " << tlvend << std::endl; -#endif - return false; - } - - if (type != tlvtype) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "GetTlvUInt64() FAILED - Type mismatch" << std::endl; - std::cerr << "GetTlvUInt64() type: " << type << std::endl; - std::cerr << "GetTlvUInt64() tlvtype: " << tlvtype << std::endl; -#endif - return false; - } - - *offset += TLV_HEADER_SIZE; /* step past header */ - - bool ok = true; - ok &= getRawUInt64(data, tlvend, offset, in); - - return ok; -} - - -bool SetTlvString(void *data, uint32_t size, uint32_t *offset, - uint16_t type, std::string out) -{ - if (!data) - return false; - uint32_t tlvsize = GetTlvStringSize(out); - uint32_t tlvend = *offset + tlvsize; /* where the data will extend to */ - - if (size < tlvend) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "SetTlvString() FAILED - not enough space" << std::endl; - std::cerr << "SetTlvString() size: " << size << std::endl; - std::cerr << "SetTlvString() tlvsize: " << tlvsize << std::endl; - std::cerr << "SetTlvString() tlvend: " << tlvend << std::endl; -#endif - return false; - } - - bool ok = true; - ok &= SetTlvBase(data, tlvend, offset, type, tlvsize); - - void * to = right_shift_void_pointer(data, *offset); - - uint32_t strlen = tlvsize - TLV_HEADER_SIZE; - memcpy(to, out.c_str(), strlen); - - *offset += strlen; - - return ok; -} - -static bool readHex(char s1,char s2,uint8_t& v) -{ - v=0 ; - - if(s1 >= 'a' && s1 <= 'f') - v += (s1-'a')+10; - else if(s1 >= 'A' && s1 <= 'F') - v += (s1-'A')+10; - else if(s1 >= '0' && s1 <= '9') - v += s1 - '0' ; - else - return false ; - - v = v << 4; - - if(s2 >= 'a' && s2 <= 'f') - v += (s2-'a')+10; - else if(s2 >= 'A' && s2 <= 'F') - v += (s2-'A')+10; - else if(s2 >= '0' && s2 <= '9') - v += s2 - '0' ; - else - return false ; - - return true ; -} - -static bool find_decoded_string(const std::string& in,const std::string& suspicious_string) -{ - uint32_t ss_pointer = 0 ; - - for(uint32_t i=0;i 0x7f. - // We do this for strings that should not contain some - // special characters by design. - - if( type == 0 // this is used for mGroupName and mMsgName - || type == TLV_TYPE_STR_PEERID - || type == TLV_TYPE_STR_NAME - || type == TLV_TYPE_STR_PATH - || type == TLV_TYPE_STR_TITLE - || type == TLV_TYPE_STR_SUBJECT - || type == TLV_TYPE_STR_LOCATION - || type == TLV_TYPE_STR_VERSION ) - { - bool modified = false ; - for(uint32_t i=0;i 0) - { - modified = true ; - in[i] = 0x20 ; - } - - if(modified) - std::cerr << "(WW) De-serialised string of type " << type << " contains forbidden characters. They have been replaced by spaces. New string: \"" << in << "\"" << std::endl; - } - - *offset += tlvsize; /* step along */ - return true; -} - -uint32_t GetTlvStringSize(const std::string &in) { - return TLV_HEADER_SIZE + in.size(); -} - - -#ifdef REMOVED_CODE -/* We must use a consistent wchar size for cross platform ness. - * As unix uses 4bytes, and windows 2bytes? we'll go with 4bytes for maximum flexibility - */ - -const uint32_t RS_WCHAR_SIZE = 4; - -bool SetTlvWideString(void *data, uint32_t size, uint32_t *offset, - uint16_t type, std::wstring out) -{ - if (!data) - return false; - uint32_t tlvsize = GetTlvWideStringSize(out); - uint32_t tlvend = *offset + tlvsize; /* where the data will extend to */ - - if (size < tlvend) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "SetTlvWideString() FAILED - not enough space" << std::endl; - std::cerr << "SetTlvWideString() size: " << size << std::endl; - std::cerr << "SetTlvWideString() tlvsize: " << tlvsize << std::endl; - std::cerr << "SetTlvWideString() tlvend: " << tlvend << std::endl; -#endif - return false; - } - - bool ok = true; - ok &= SetTlvBase(data, tlvend, offset, type, tlvsize); - - uint32_t strlen = out.length(); - - /* Must convert manually to ensure its always the same! */ - for(uint32_t i = 0; i < strlen; i++) - { - uint32_t widechar = out[i]; - ok &= setRawUInt32(data, tlvend, offset, widechar); - } - return ok; -} - -//tested -bool GetTlvWideString(void *data, uint32_t size, uint32_t *offset, - uint16_t type, std::wstring &in) -{ - if (!data) - return false; - - if (size < *offset + TLV_HEADER_SIZE) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "GetTlvWideString() FAILED - not enough space" << std::endl; - std::cerr << "GetTlvWideString() size: " << size << std::endl; - std::cerr << "GetTlvWideString() *offset: " << *offset << std::endl; -#endif - return false; - } - - /* extract the type and size */ - void *tlvstart = right_shift_void_pointer(data, *offset); - uint16_t tlvtype = GetTlvType(tlvstart); - uint32_t tlvsize = GetTlvSize(tlvstart); - - /* check that there is size */ - uint32_t tlvend = *offset + tlvsize; - if (size < tlvend) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "GetTlvWideString() FAILED - not enough space" << std::endl; - std::cerr << "GetTlvWideString() size: " << size << std::endl; - std::cerr << "GetTlvWideString() tlvsize: " << tlvsize << std::endl; - std::cerr << "GetTlvWideString() tlvend: " << tlvend << std::endl; -#endif - return false; - } - - if (type != tlvtype) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "GetTlvWideString() FAILED - invalid type" << std::endl; - std::cerr << "GetTlvWideString() type: " << type << std::endl; - std::cerr << "GetTlvWideString() tlvtype: " << tlvtype << std::endl; -#endif - return false; - } - - - bool ok = true; - /* remove the header, calc string length */ - *offset += TLV_HEADER_SIZE; - uint32_t strlen = (tlvsize - TLV_HEADER_SIZE) / RS_WCHAR_SIZE; - - /* Must convert manually to ensure its always the same! */ - for(uint32_t i = 0; i < strlen; i++) - { - uint32_t widechar; - ok &= getRawUInt32(data, tlvend, offset, &widechar); - in += widechar; - } - - // Check for message content. We want to avoid possible lol bombs as soon as possible. - - static const int number_of_suspiscious_strings = 4 ; - static const std::wstring err_in = L"**** String removed (SVG bomb?) ****" ; - static std::wstring suspiscious_strings[number_of_suspiscious_strings] = { L"sin_family = AF_INET; /* set FAMILY */ - in->sin_addr.s_addr = ipaddr; - - uint16_t port; - ok &= getRawUInt16(data, tlvend, offset, &port); - in->sin_port = port; - - return ok; -} - -uint32_t GetTlvIpAddrPortV4Size() { - return TLV_HEADER_SIZE + 4 + 2; /* header + 4 (IP) + 2 (Port) */ -} - - -bool SetTlvIpAddrPortV6(void *data, uint32_t size, uint32_t *offset, - uint16_t type, struct sockaddr_in6 *out) { - if (!data) - return false; - - uint32_t tlvsize = GetTlvIpAddrPortV6Size(); - uint32_t tlvend = *offset + tlvsize; /* where the data will extend to */ - - if (size < tlvend) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "SetTlvIpAddrPortV6() FAILED - not enough space" << std::endl; - std::cerr << "SetTlvIpAddrPortV6() size: " << size << std::endl; - std::cerr << "SetTlvIpAddrPortV6() tlvsize: " << tlvsize << std::endl; - std::cerr << "SetTlvIpAddrPortV6() tlvend: " << tlvend << std::endl; -#endif - return false; - } - - bool ok = true; - ok &= SetTlvBase(data, tlvend, offset, type, tlvsize); - - /* now add the data (keep in network order) */ - uint32_t *ip6addr = (uint32_t *) out->sin6_addr.s6_addr; - for(int i = 0; i < 4; i++) - { - ok &= setRawUInt32(data, tlvend, offset, ip6addr[i]); - } - ok &= setRawUInt16(data, tlvend, offset, out->sin6_port); - return ok; -} - -bool GetTlvIpAddrPortV6(void *data, uint32_t size, uint32_t *offset, - uint16_t type, struct sockaddr_in6 *in) { - if (!data) - return false; - - if (size < *offset + TLV_HEADER_SIZE) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "GetIpAddrPortV6() FAILED - not enough space" << std::endl; - std::cerr << "GetIpAddrPortV6() size: " << size << std::endl; - std::cerr << "GetIpAddrPortV6() *offset: " << *offset << std::endl; -#endif - return false; - } - - /* extract the type and size */ - void *tlvstart = right_shift_void_pointer(data, *offset); - uint16_t tlvtype = GetTlvType(tlvstart); - uint32_t tlvsize = GetTlvSize(tlvstart); - - /* check that there is size */ - uint32_t tlvend = *offset + tlvsize; - if (size < tlvend) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "GetIpAddrPortV6() FAILED - not enough space" << std::endl; - std::cerr << "GetIpAddrPortV6() size: " << size << std::endl; - std::cerr << "GetIpAddrPortV6() tlvsize: " << tlvsize << std::endl; - std::cerr << "GetIpAddrPortV6() tlvend: " << tlvend << std::endl; -#endif - return false; - } - - if (type != tlvtype) - { -#ifdef TLV_BASE_DEBUG - std::cerr << "GetIpAddrPortV6() FAILED - invalid type" << std::endl; - std::cerr << "GetIpAddrPortV6() type: " << type << std::endl; - std::cerr << "GetIpAddrPortV6() tlvtype: " << tlvtype << std::endl; -#endif - return false; - } - - *offset += TLV_HEADER_SIZE; /* skip header */ - - bool ok = true; - - /* now get the data (keep in network order) */ - uint32_t *ip6addr = (uint32_t *) in->sin6_addr.s6_addr; - for(int i = 0; i < 4; i++) - { - ok &= getRawUInt32(data, tlvend, offset, &(ip6addr[i])); - } - - in->sin6_family = AF_INET6; /* set FAMILY */ - ok &= getRawUInt16(data, tlvend, offset, &(in->sin6_port)); - - return ok; -} - -uint32_t GetTlvIpAddrPortV6Size() { - return TLV_HEADER_SIZE + 16 + 2; /* header + 16 (IP) + 2 (Port) */ -} - diff --git a/libretroshare/src/serialiser/rstlvbase.h b/libretroshare/src/serialiser/rstlvbase.h deleted file mode 100644 index e153f1797..000000000 --- a/libretroshare/src/serialiser/rstlvbase.h +++ /dev/null @@ -1,299 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvbase.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie, Horatio, Chris Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -/******************************************************************* - * These are the general TLV (un)packing routines. - * - * Data is Serialised into the following format - * - * ----------------------------------------- - * | TLV TYPE (2 bytes) | TLV LEN (4 bytes)| - * ----------------------------------------- - * | | - * | Data .... | - * | | - * ----------------------------------------- - * - * Originally TLV TYPE = 2 bytes, and TLV LEN = 2 bytes. - * However with HTML and WSTRINGS the 64K Limit becomes limiting. - * The TLV LEN = 4 bytes now! - * - * Size is the total size of the TLV Field (including the 4 byte header) - * - * Like the lowlevel packing routines. They are usually - * created in pairs - one to pack the data, the other to unpack. - * - * GetTlvXXX(void *data, uint32_t size, uint32_t *offset, XXX *out); - * SetTlvXXX(void *data, uint32_t size, uint32_t *offset, XXX *in); - * - * - * data - the base pointer to the serialised data. - * size - size of the memory pointed to by data. - * *offset - where we want to (un)pack the data. - * This is incremented by the datasize. - * - * *in / *out - the data to (un)pack. - * - ******************************************************************/ - -#include -#include -#include "util/rsnet.h" - - -/* 0b 0000 0000 0001 XXXX UInt8 */ -/* 0b 0000 0000 0010 XXXX UInt16 */ -/* 0b 0000 0000 0011 XXXX UInt32 */ -/* 0b 0000 0000 0100 XXXX UInt64 */ -/* 0b 0000 0000 0101 XXXX String */ -/* 0b 0000 0000 0110 XXXX Wide String */ -/* 0b 0000 0000 0111 XXXX Hashes */ -/* 0b 0000 0000 1000 XXXX IP:Port V4 */ - -/******* BINARY TYPES *****************/ -/* 0b 0000 0001 0000 XXXX CERT */ -/* 0b 0000 0001 0001 XXXX Priv Key */ -/* 0b 0000 0001 0010 XXXX Pub Key */ -/* 0b 0000 0001 0011 XXXX Signature */ - -/******* COMPOUND TYPES ***************/ -/* 0b 0001 XXXX XXXX XXXX Compound */ -/* 0b 0001 0000 0000 XXXX FILE */ -/* 0b 0001 0000 0001 XXXX KEY VALUE */ -/* 0b 0001 0000 0010 XXXX PEERS */ -/* 0b 0001 0000 0011 XXXX SERVICES */ - -/******* BIG LEN TYPES ***************/ - -/* 0b 1000 XXXX XXXX XXXX BIG LEN */ -/* 0b 1000 0000 0001 XXXX STRINGS */ -/* 0b 1000 0000 0010 XXXX WSTRINGS */ -/* 0b 1000 0000 0011 XXXX BINARY */ - -/* 0b 1001 XXXX XXXX XXXX Compound */ - - -/* TLV HEADER SIZE (Reference) *******************************/ -const uint32_t TLV_HEADER_TYPE_SIZE = 2; -const uint32_t TLV_HEADER_LEN_SIZE = 4; -const uint32_t TLV_HEADER_SIZE = TLV_HEADER_TYPE_SIZE + TLV_HEADER_LEN_SIZE; -/* TLV HEADER SIZE (Reference) *******************************/ - -const uint16_t TLV_TYPE_UINT32_SIZE = 0x0030; -const uint16_t TLV_TYPE_UINT32_POP = 0x0031; -const uint16_t TLV_TYPE_UINT32_AGE = 0x0032; -const uint16_t TLV_TYPE_UINT32_OFFSET = 0x0033; -const uint16_t TLV_TYPE_UINT32_SERID = 0x0034; -const uint16_t TLV_TYPE_UINT32_BW = 0x0035; -const uint16_t TLV_TYPE_UINT32_PARAM = 0x0030; - -const uint16_t TLV_TYPE_UINT64_SIZE = 0x0040; -const uint16_t TLV_TYPE_UINT64_OFFSET = 0x0041; - -const uint16_t TLV_TYPE_STR_PEERID = 0x0050; -const uint16_t TLV_TYPE_STR_NAME = 0x0051; -const uint16_t TLV_TYPE_STR_PATH = 0x0052; -const uint16_t TLV_TYPE_STR_KEY = 0x0053; -const uint16_t TLV_TYPE_STR_VALUE = 0x0054; -const uint16_t TLV_TYPE_STR_COMMENT = 0x0055; -const uint16_t TLV_TYPE_STR_TITLE = 0x0056; -const uint16_t TLV_TYPE_STR_MSG = 0x0057; -const uint16_t TLV_TYPE_STR_SUBJECT = 0x0058; -const uint16_t TLV_TYPE_STR_LINK = 0x0059; -const uint16_t TLV_TYPE_STR_GENID = 0x005a; -const uint16_t TLV_TYPE_STR_GPGID = 0x005b; /* depreciated */ -const uint16_t TLV_TYPE_STR_PGPID = 0x005b; /* same as GPG */ -const uint16_t TLV_TYPE_STR_LOCATION = 0x005c; -const uint16_t TLV_TYPE_STR_CERT_GPG = 0x005d; -const uint16_t TLV_TYPE_STR_PGPCERT = 0x005d; /* same as CERT_GPG */ -const uint16_t TLV_TYPE_STR_CERT_SSL = 0x005e; -const uint16_t TLV_TYPE_STR_VERSION = 0x005f; -const uint16_t TLV_TYPE_STR_PARAM = 0x0054; /* same as VALUE ---- TO FIX */ - -/* Hashs are always strings */ -const uint16_t TLV_TYPE_STR_HASH_SHA1 = 0x0070; -const uint16_t TLV_TYPE_STR_HASH_ED2K = 0x0071; - -const uint16_t TLV_TYPE_IPV4_LOCAL = 0x0080; -const uint16_t TLV_TYPE_IPV4_REMOTE = 0x0081; -const uint16_t TLV_TYPE_IPV4_LAST = 0x0082; -const uint16_t TLV_TYPE_STR_DYNDNS = 0x0083; -const uint16_t TLV_TYPE_STR_DOMADDR = 0x0084; - -// rearrange these in the future. -const uint16_t TLV_TYPE_IPV4 = 0x0085; -const uint16_t TLV_TYPE_IPV6 = 0x0086; - -/*** MORE STRING IDS ****/ -const uint16_t TLV_TYPE_STR_GROUPID = 0x00a0; -const uint16_t TLV_TYPE_STR_MSGID = 0x00a1; -const uint16_t TLV_TYPE_STR_PARENTID = 0x00a2; -const uint16_t TLV_TYPE_STR_THREADID = 0x00a3; -const uint16_t TLV_TYPE_STR_KEYID = 0x00a4; - -/* even MORE string Ids for GXS services */ - -const uint16_t TLV_TYPE_STR_CAPTION = 0x00b1; -const uint16_t TLV_TYPE_STR_CATEGORY = 0x00b2; -const uint16_t TLV_TYPE_STR_DESCR = 0x00b3; -const uint16_t TLV_TYPE_STR_SIGN = 0x00b4; -const uint16_t TLV_TYPE_STR_HASH_TAG = 0x00b5; -const uint16_t TLV_TYPE_STR_WIKI_PAGE = 0x00b6; -const uint16_t TLV_TYPE_STR_DATE = 0x00b7; -const uint16_t TLV_TYPE_STR_PIC_TYPE = 0x00b8; -const uint16_t TLV_TYPE_STR_PIC_AUTH = 0x00b9; -const uint16_t TLV_TYPE_STR_GXS_ID = 0x00ba; - - - /**** Binary Types ****/ -const uint16_t TLV_TYPE_CERT_XPGP_DER = 0x0100; -const uint16_t TLV_TYPE_CERT_X509 = 0x0101; -const uint16_t TLV_TYPE_CERT_OPENPGP = 0x0102; - -const uint16_t TLV_TYPE_KEY_EVP_PKEY = 0x0110; /* Used (Generic - Distrib) */ -const uint16_t TLV_TYPE_KEY_PRIV_RSA = 0x0111; /* not used yet */ -const uint16_t TLV_TYPE_KEY_PUB_RSA = 0x0112; /* not used yet */ - -const uint16_t TLV_TYPE_SIGN_RSA_SHA1 = 0x0120; /* Used (Distrib/Forums) */ - -const uint16_t TLV_TYPE_BIN_IMAGE = 0x0130; /* Used (Generic - Forums) */ -const uint16_t TLV_TYPE_BIN_FILEDATA = 0x0140; /* Used - ACTIVE! */ -const uint16_t TLV_TYPE_BIN_SERIALISE = 0x0150; /* Used (Generic - Distrib) */ -const uint16_t TLV_TYPE_BIN_GENERIC = 0x0160; /* Used (DSDV Data) */ -const uint16_t TLV_TYPE_BIN_ENCRYPTED = 0x0170; /* Encrypted data */ - - - /**** Compound Types ****/ -const uint16_t TLV_TYPE_FILEITEM = 0x1000; -const uint16_t TLV_TYPE_FILESET = 0x1001; -const uint16_t TLV_TYPE_FILEDATA = 0x1002; - -const uint16_t TLV_TYPE_KEYVALUE = 0x1010; -const uint16_t TLV_TYPE_KEYVALUESET = 0x1011; - -const uint16_t TLV_TYPE_STRINGSET = 0x1020; /* dummy non-existant */ -const uint16_t TLV_TYPE_PEERSET = 0x1021; -const uint16_t TLV_TYPE_HASHSET = 0x1022; - -const uint16_t TLV_TYPE_PGPIDSET = 0x1023; -const uint16_t TLV_TYPE_RECOGNSET = 0x1024; -const uint16_t TLV_TYPE_GXSIDSET = 0x1025; -const uint16_t TLV_TYPE_GXSCIRCLEIDSET= 0x1026; -const uint16_t TLV_TYPE_NODEGROUPIDSET= 0x1027; -const uint16_t TLV_TYPE_GXSMSGIDSET = 0x1028; - -const uint16_t TLV_TYPE_SERVICESET = 0x1030; - -// *_deprectate should not be used anymore!! -// We use 1040 for both public and private keys, so that transmitting them still works (backward compatibility), and so that -// signatures are kept. But the two different classes will check that the flags are correct when deserialising. - -const uint16_t TLV_TYPE_SECURITY_KEY = 0x1040; -const uint16_t TLV_TYPE_SECURITYKEYSET = 0x1041; - -const uint16_t TLV_TYPE_KEYSIGNATURE = 0x1050; -const uint16_t TLV_TYPE_KEYSIGNATURESET = 0x1051; -const uint16_t TLV_TYPE_KEYSIGNATURETYPE = 0x1052; - -const uint16_t TLV_TYPE_IMAGE = 0x1060; - -const uint16_t TLV_TYPE_ADDRESS_INFO = 0x1070; -const uint16_t TLV_TYPE_ADDRESS_SET = 0x1071; -const uint16_t TLV_TYPE_ADDRESS = 0x1072; - -const uint16_t TLV_TYPE_DSDV_ENDPOINT = 0x1080; -const uint16_t TLV_TYPE_DSDV_ENTRY = 0x1081; -const uint16_t TLV_TYPE_DSDV_ENTRY_SET= 0x1082; - -const uint16_t TLV_TYPE_BAN_ENTRY_dep = 0x1090; -const uint16_t TLV_TYPE_BAN_ENTRY = 0x1092; -const uint16_t TLV_TYPE_BAN_LIST = 0x1091; - -const uint16_t TLV_TYPE_MSG_ADDRESS = 0x10A0; -const uint16_t TLV_TYPE_MSG_ID = 0x10A1; - - -const uint32_t RSTLV_IMAGE_TYPE_PNG = 0x0001; -const uint32_t RSTLV_IMAGE_TYPE_JPG = 0x0002; - -/**** Basic TLV Functions ****/ -uint32_t GetTlvSize(void *data); -uint16_t GetTlvType(void *data); -bool SetTlvBase(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint32_t len); -bool SetTlvSize(void *data, uint32_t size, uint32_t len); -bool SetTlvType(void *data, uint32_t size, uint16_t type); - -/* skip past the unknown tlv elements */ -bool SkipUnknownTlv(void *data, uint32_t size, uint32_t *offset); - -/**** Generic TLV Functions **** - * This have the same data (int or string for example), - * but they can have different types eg. a string could represent a name or a path, - * so we include a type parameter in the arguments - */ - -bool SetTlvUInt8(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint8_t out); -bool GetTlvUInt8(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint8_t *in); - -bool SetTlvUInt16(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint16_t out); -bool GetTlvUInt16(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint16_t *in); - -bool SetTlvUInt32(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint32_t out); -bool GetTlvUInt32(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint32_t *in); - -bool SetTlvUInt64(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint64_t out); -bool GetTlvUInt64(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint64_t *in); - -uint32_t GetTlvUInt8Size(); -uint32_t GetTlvUInt16Size(); -uint32_t GetTlvUInt32Size(); -uint32_t GetTlvUInt64Size(); - - -bool SetTlvString(void *data, uint32_t size, uint32_t *offset, uint16_t type, std::string out); -bool GetTlvString(const void *data, uint32_t size, uint32_t *offset, uint16_t type, std::string &in); -uint32_t GetTlvStringSize(const std::string &in); - -#ifdef REMOVED_CODE -bool SetTlvWideString(void *data, uint32_t size, uint32_t *offset, uint16_t type, std::wstring out); -bool GetTlvWideString(void *data, uint32_t size, uint32_t *offset, uint16_t type, std::wstring &in); -uint32_t GetTlvWideStringSize(std::wstring &in); -#endif - -bool SetTlvIpAddrPortV4(void *data, uint32_t size, uint32_t *offset, uint16_t type, struct sockaddr_in *out); -bool GetTlvIpAddrPortV4(void *data, uint32_t size, uint32_t *offset, uint16_t type, struct sockaddr_in *in); -uint32_t GetTlvIpAddrPortV4Size(); - -bool SetTlvIpAddrPortV6(void *data, uint32_t size, uint32_t *offset, uint16_t type, struct sockaddr_in6 *out); -bool GetTlvIpAddrPortV6(void *data, uint32_t size, uint32_t *offset, uint16_t type, struct sockaddr_in6 *in); -uint32_t GetTlvIpAddrPortV6Size(); - -/* additional function to be added - -bool SetTlvBinData(void* data, uint32_t size, uint32_t* offset, uint16_t type, void* data_bin, uint32_t len_tlv) - -above(SetTlvbinData) is partially implemented - -bool GetTlvBinData(void* data, uint32_t size, uint32_t* offset, uint16_t type, void* data_bin, uint32_t len_tlv) - -*************************************/ diff --git a/libretroshare/src/serialiser/rstlvbinary.cc b/libretroshare/src/serialiser/rstlvbinary.cc deleted file mode 100644 index 7eabf74d9..000000000 --- a/libretroshare/src/serialiser/rstlvbinary.cc +++ /dev/null @@ -1,326 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvbinary.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie,Chris Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "util/rsmemory.h" -#include "serialiser/rstlvbinary.h" - -#include "serialiser/rstlvbase.h" -#include -#include -#include - -// #define TLV_DEBUG 1 - -/*!********************************** RsTlvFileBinaryData **********************************/ - - -RsTlvBinaryData::RsTlvBinaryData() - :tlvtype(0), bin_len(0), bin_data(NULL) -{ -} - -RsTlvBinaryData::RsTlvBinaryData(uint16_t t) - :tlvtype(t), bin_len(0), bin_data(NULL) -{ -} - -RsTlvBinaryData::RsTlvBinaryData(const RsTlvBinaryData &b) - : tlvtype(b.tlvtype), bin_len(0) , bin_data(NULL) { - - setBinData(b.bin_data, b.bin_len); -} - -RsTlvBinaryData::~RsTlvBinaryData() -{ - TlvClear(); -} - -void RsTlvBinaryData::operator =(const RsTlvBinaryData& b){ - - setBinData(b.bin_data, b.bin_len); - tlvtype = b.tlvtype; -} - -/// used to allocate memory andinitialize binary data member -bool RsTlvBinaryData::setBinData(const void *data, uint32_t size) -{ - /* ready to load */ - TlvClear(); - - /* get mandatory */ - /* the rest of the TLV size binary data */ - bin_len = size; - if (bin_len == 0) - { - bin_data = NULL; - return true; - } - - bin_data = rs_malloc(bin_len); - - if(bin_data == NULL) - return false ; - - memcpy(bin_data, data, bin_len); - return true; -} - -void RsTlvBinaryData::TlvClear() -{ - free(bin_data); - TlvShallowClear(); -} - -void RsTlvBinaryData::TlvShallowClear() -{ - bin_data = NULL; - bin_len = 0; -} - -uint32_t RsTlvBinaryData::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header */ - - if (bin_data != NULL) - s += bin_len; // len is the size of data - - return s; -} - - -bool RsTlvBinaryData::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, tlvtype, tlvsize); - - /* add mandatory data */ - - // Warning: this is actually not an error if bin_len=0, as it does not - // corrupt the packet structure. We thus still return true in this case. - // - if (bin_data != NULL && bin_len > 0) - { - memcpy(&(((uint8_t *) data)[*offset]), bin_data, bin_len); - *offset += bin_len; - } - return ok; -} - - - -bool RsTlvBinaryData::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - { - return false; /* not enough space to get the header */ - } - - uint16_t tlvtype_in = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvsize < TLV_HEADER_SIZE) - { - return false; /* bad tlv size */ - } - - if (tlvtype != tlvtype_in) /* check type */ - return false; - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - bool ok = setBinData(&(((uint8_t *) data)[*offset]), tlvsize - TLV_HEADER_SIZE); - (*offset) += bin_len; - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvBinaryData::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; -} -std::ostream &RsTlvBinaryDataRef::print(std::ostream &out, uint16_t indent) const -{ - uint16_t int_Indent = indent + 2; - - uint32_t i; - std::ostringstream sout; - printIndent(sout, indent); - sout << "RsTlvBinaryData: Type: " << tlvtype << " Size: " << mSizeRef; - sout << std::hex; - - for(i = 0; i < mSizeRef; i++) - { - if (i % 16 == 0) - { - sout << std::endl; - printIndent(sout, int_Indent); - } - sout << std::setw(2) << std::setfill('0') - << (int) (((unsigned char *) mDataRef)[i]) << ":"; - } - - sout << std::endl; - out << sout.str(); - - printEnd(out, "RsTlvBinaryData", indent); - return out; - -} - -std::ostream &RsTlvBinaryData::print(std::ostream &out, uint16_t indent) const -{ - uint16_t int_Indent = indent + 2; - - uint32_t i; - std::ostringstream sout; - printIndent(sout, indent); - sout << "RsTlvBinaryData: Type: " << tlvtype << " Size: " << bin_len; - sout << std::hex; - - for(i = 0; i < bin_len; i++) - { - if (i % 16 == 0) - { - sout << std::endl; - printIndent(sout, int_Indent); - } - sout << std::setw(2) << std::setfill('0') - << (int) (((unsigned char *) bin_data)[i]) << ":"; - } - - sout << std::endl; - out << sout.str(); - - printEnd(out, "RsTlvBinaryData", indent); - return out; - -} - -bool RsTlvBinaryDataRef::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, tlvtype, tlvsize); - - /* add mandatory data */ - - // Warning: this is actually not an error if bin_len=0, as it does not - // corrupt the packet structure. We thus still return true in this case. - // - if (mDataRef != NULL && mSizeRef > 0) - { - memcpy(&(((uint8_t *) data)[*offset]), mDataRef, mSizeRef); - *offset += mSizeRef; - } - return ok; -} -bool RsTlvBinaryDataRef::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - { - return false; /* not enough space to get the header */ - } - - uint16_t tlvtype_in = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvsize < TLV_HEADER_SIZE) - return false; /* bad tlv size */ - - if (tlvtype != tlvtype_in) /* check type */ - return false; - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - mDataRef = (uint8_t*)rs_malloc(tlvsize - TLV_HEADER_SIZE) ; - - if(mDataRef == NULL) - return false ; - - mSizeRef = tlvsize - TLV_HEADER_SIZE; - - memcpy(mDataRef,&(((uint8_t *) data)[*offset]), tlvsize - TLV_HEADER_SIZE); - *offset += mSizeRef; - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvBinaryData::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return true; -} - -uint32_t RsTlvBinaryDataRef::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header */ - - if (mDataRef != NULL) - s += mSizeRef; // len is the size of data - - return s; -} diff --git a/libretroshare/src/serialiser/rstlvbinary.h b/libretroshare/src/serialiser/rstlvbinary.h deleted file mode 100644 index 3d41d5402..000000000 --- a/libretroshare/src/serialiser/rstlvbinary.h +++ /dev/null @@ -1,84 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvbinary.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie,Chris Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -/******************************************************************* - * These are the Compound TLV structures that must be (un)packed. - * - ******************************************************************/ - -#include "serialiser/rstlvitem.h" - - -class RsTlvBinaryData: public RsTlvItem -{ -public: - RsTlvBinaryData(); - RsTlvBinaryData(uint16_t t); - RsTlvBinaryData(const RsTlvBinaryData& b); // as per rule of three - void operator=(const RsTlvBinaryData& b); // as per rule of three - - virtual ~RsTlvBinaryData(); // as per rule of three - - virtual uint32_t TlvSize() const; - virtual void TlvClear(); /*! Initialize fields to empty legal values ( "0", "", etc) */ - virtual void TlvShallowClear(); /*! Don't delete the binary data */ - - /// Serialise. - /*! Serialise Tlv to buffer(*data) of 'size' bytes starting at *offset */ - virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; - - /// Deserialise. - /*! Deserialise Tlv buffer(*data) of 'size' bytes starting at *offset */ - virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); - virtual std::ostream &print(std::ostream &out, uint16_t indent) const; /*! Error/Debug util function */ - - // mallocs the necessary size, and copies data into the allocated buffer in bin_data - bool setBinData(const void *data, uint32_t size); - - uint16_t tlvtype; /// set/checked against TLV input - uint32_t bin_len; /// size of malloc'ed data (not serialised) - void *bin_data; /// mandatory -}; - -// This class is mainly used for on-the-fly serialization - -class RsTlvBinaryDataRef: public RsTlvItem -{ -public: - RsTlvBinaryDataRef(uint16_t type,uint8_t *& data_ref,uint32_t& size_ref) : mDataRef(data_ref),mSizeRef(size_ref),tlvtype(type) {} - virtual ~RsTlvBinaryDataRef() {} - - virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - virtual uint32_t TlvSize() const; - virtual void TlvClear(){} - virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; - virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); - - uint8_t *& mDataRef ; - uint32_t & mSizeRef ; - uint16_t tlvtype ; -}; - - - diff --git a/libretroshare/src/serialiser/rstlvfileitem.cc b/libretroshare/src/serialiser/rstlvfileitem.cc deleted file mode 100644 index 098b8de6f..000000000 --- a/libretroshare/src/serialiser/rstlvfileitem.cc +++ /dev/null @@ -1,703 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvfileitem.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie,Chris Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "serialiser/rstlvfileitem.h" -#include "serialiser/rsbaseserial.h" - -#if 0 -#include - -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvtypes.h" -#endif - -/*** - * #define TLV_FI_DEBUG 1 - **/ - - -RsTlvFileItem::RsTlvFileItem() -{ - TlvClear(); -} - -void RsTlvFileItem::TlvClear() -{ - filesize = 0; - hash.clear() ; - name.clear(); - path.clear(); - pop = 0; - age = 0; - piecesize = 0; - hashset.TlvClear(); -} - -uint32_t RsTlvFileItem::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header */ - s += 8; /* filesize */ - s += hash.serial_size() ; -#ifdef TLV_FI_DEBUG - std::cerr << "RsTlvFileItem::TlvSize() 8 + Hash: " << s << std::endl; -#endif - - - /* now optional ones */ - if (name.length() > 0) - { - s += GetTlvStringSize(name); -#ifdef TLV_FI_DEBUG - std::cerr << "RsTlvFileItem::TlvSize() + Name: " << s << std::endl; -#endif - } - - if (path.length() > 0) - { - s += GetTlvStringSize(path); -#ifdef TLV_FI_DEBUG - std::cerr << "RsTlvFileItem::TlvSize() + Path: " << s << std::endl; -#endif - } - - if (pop != 0) - { - s += GetTlvUInt32Size(); -#ifdef TLV_FI_DEBUG - std::cerr << "RsTlvFileItem::TlvSize() + Pop: " << s << std::endl; -#endif - } - - if (age != 0) - { - s += GetTlvUInt32Size(); -#ifdef TLV_FI_DEBUG - std::cerr << "RsTlvFileItem::TlvSize() 4 + Age: " << s << std::endl; -#endif - } - - if (piecesize != 0) - { - s += GetTlvUInt32Size(); -#ifdef TLV_FI_DEBUG - std::cerr << "RsTlvFileItem::TlvSize() 4 + PieceSize: " << s << std::endl; -#endif - } - - if (hashset.ids.size() != 0) - { - s += hashset.TlvSize(); -#ifdef TLV_FI_DEBUG - std::cerr << "RsTlvFileItem::TlvSize() 4 + HashSet: " << s << std::endl; -#endif - } - -#ifdef TLV_FI_DEBUG - std::cerr << "RsTlvFileItem::TlvSize() Total: " << s << std::endl; -#endif - - return s; -} - -/* serialise the data to the buffer */ -bool RsTlvFileItem::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - { -#ifdef TLV_FI_DEBUG - std::cerr << "RsTlvFileItem::SetTlv() Failed size (" << size; - std::cerr << ") < tlvend (" << tlvend << ")" << std::endl; -#endif - return false; /* not enough space */ - } - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_FILEITEM, tlvsize); - -#ifdef TLV_FI_DEBUG - if (!ok) - { - std::cerr << "RsTlvFileItem::SetTlv() SetTlvBase Failed (or earlier)" << std::endl; - } - std::cerr << "RsTlvFileItem::SetTlv() PostBase:" << std::endl; - std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; - std::cerr << std::endl; -#endif - - - /* add mandatory parts first */ - ok &= setRawUInt64(data, tlvend, offset, filesize); - -#ifdef TLV_FI_DEBUG - if (!ok) - { - std::cerr << "RsTlvFileItem::SetTlv() SetRawUInt32(FILESIZE) Failed (or earlier)" << std::endl; - } - std::cerr << "RsTlvFileItem::SetTlv() PostSize:" << std::endl; - std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; - std::cerr << std::endl; -#endif - - ok &= hash.serialise(data, tlvend, *offset) ; - - -#ifdef TLV_FI_DEBUG - if (!ok) - { - std::cerr << "RsTlvFileItem::SetTlv() SetTlvString(HASH) Failed (or earlier)" << std::endl; - } - std::cerr << "RsTlvFileItem::SetTlv() PostHash:" << std::endl; - std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; - std::cerr << std::endl; -#endif - - /* now optional ones */ - if (name.length() > 0) - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_NAME, name); -#ifdef TLV_FI_DEBUG - if (!ok) - { - std::cerr << "RsTlvFileItem::SetTlv() Setting Option:Name Failed (or earlier)" << std::endl; - } - std::cerr << "RsTlvFileItem::SetTlv() PostName:" << std::endl; - std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; - std::cerr << std::endl; -#endif - - if (path.length() > 0) - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_PATH, path); -#ifdef TLV_FI_DEBUG - if (!ok) - { - std::cerr << "RsTlvFileItem::SetTlv() Setting Option:Path Failed (or earlier)" << std::endl; - } - std::cerr << "RsTlvFileItem::SetTlv() Pre Pop:" << std::endl; - std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; - std::cerr << " type: " << TLV_TYPE_UINT32_POP << " value: " << pop; - std::cerr << std::endl; -#endif - - if (pop != 0) - ok &= SetTlvUInt32(data, tlvend, offset, TLV_TYPE_UINT32_POP, pop); -#ifdef TLV_FI_DEBUG - if (!ok) - { - std::cerr << "RsTlvFileItem::SetTlv() Setting Option:Pop Failed (or earlier)" << std::endl; - } - std::cerr << "RsTlvFileItem::SetTlv() Post Pop/Pre Age:" << std::endl; - std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; - std::cerr << " type: " << TLV_TYPE_UINT32_AGE << " value: " << age; - std::cerr << std::endl; -#endif - - if (age != 0) - ok &= SetTlvUInt32(data, tlvend, offset, TLV_TYPE_UINT32_AGE, age); -#ifdef TLV_FI_DEBUG - if (!ok) - { - std::cerr << "RsTlvFileItem::SetTlv() Setting Option:Age Failed (or earlier)" << std::endl; - } - std::cerr << "RsTlvFileItem::SetTlv() Post Age:" << std::endl; - std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; - std::cerr << std::endl; -#endif - - if (piecesize != 0) - ok &= SetTlvUInt32(data, tlvend, offset, TLV_TYPE_UINT32_SIZE, piecesize); -#ifdef TLV_FI_DEBUG - if (!ok) - { - std::cerr << "RsTlvFileItem::SetTlv() Setting Option:piecesize Failed (or earlier)" << std::endl; - } - std::cerr << "RsTlvFileItem::SetTlv() Post PieceSize:" << std::endl; - std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; - std::cerr << std::endl; -#endif - - if (hashset.ids.size() != 0) - ok &= hashset.SetTlv(data, tlvend, offset); -#ifdef TLV_FI_DEBUG - if (!ok) - { - std::cerr << "RsTlvFileItem::SetTlv() Setting Option:hashset Failed (or earlier)" << std::endl; - } - std::cerr << "RsTlvFileItem::SetTlv() Post HashSet:" << std::endl; - std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; - std::cerr << std::endl; -#endif - - - -#ifdef TLV_FI_DEBUG - if (!ok) - { - std::cerr << "RsTlvFileItem::SetTlv() Setting Options Failed (or earlier)" << std::endl; - } -#endif - - return ok; -} - -bool RsTlvFileItem::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_FILEITEM) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - /* get mandatory parts first */ - ok &= getRawUInt64(data, tlvend, offset, &filesize); - ok &= hash.deserialise(data, tlvend, *offset) ; - - /* while there is more TLV (optional part) */ - while((*offset) + 2 < tlvend) - { - /* get the next type */ - uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - switch(tlvsubtype) - { - case TLV_TYPE_STR_NAME: - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_NAME, name); - break; - case TLV_TYPE_STR_PATH: - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_PATH, path); - break; - case TLV_TYPE_UINT32_POP: - ok &= GetTlvUInt32(data, tlvend, offset, TLV_TYPE_UINT32_POP, &pop); - break; - case TLV_TYPE_UINT32_AGE: - ok &= GetTlvUInt32(data, tlvend, offset, TLV_TYPE_UINT32_AGE, &age); - break; - case TLV_TYPE_UINT32_SIZE: - ok &= GetTlvUInt32(data, tlvend, offset, TLV_TYPE_UINT32_SIZE, &piecesize); - break; - case TLV_TYPE_HASHSET: - ok &= hashset.GetTlv(data, tlvend, offset); - break; - default: - ok &= SkipUnknownTlv(data, tlvend, offset); - break; - } - if (!ok) - { - break; - } - } - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvFileItem::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; -} - - -/* print it out */ -std::ostream &RsTlvFileItem::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvFileItem", indent); - uint16_t int_Indent = indent + 2; - - - printIndent(out, int_Indent); - out << "Mandatory: FileSize: " << filesize << " Hash: " << hash; - out << std::endl; - - printIndent(out, int_Indent); - out << "Optional:" << std::endl; - - /* now optional ones */ - if (name.length() > 0) - { - printIndent(out, int_Indent); - out << "Name : " << name << std::endl; - } - if (path.length() > 0) - { - printIndent(out, int_Indent); - out << "Path : " << path << std::endl; - } - if (pop != 0) - { - printIndent(out, int_Indent); - out << "Pop: " << pop << std::endl; - } - if (age != 0) - { - printIndent(out, int_Indent); - out << "Age: " << age << std::endl; - } - if (piecesize != 0) - { - printIndent(out, int_Indent); - out << "PieceSize: " << piecesize << std::endl; - } - if (hashset.ids.size() != 0) - { - hashset.print(out, int_Indent); - } - - printEnd(out, "RsTlvFileItem", indent); - - return out; -} - - -/************************************* RsTlvFileSet ************************************/ - -void RsTlvFileSet::TlvClear() -{ - title.clear(); - comment.clear(); - items.clear(); -} - -uint32_t RsTlvFileSet::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header */ - - /* first determine the total size of RstlvFileItems in list */ - - std::list::const_iterator it; - - for(it = items.begin(); it != items.end() ; ++it) - { - s += (*it).TlvSize(); - } - - /* now add comment and title length of this tlv object */ - - if (title.length() > 0) - s += GetTlvStringSize(title); - if (comment.length() > 0) - s += GetTlvStringSize(comment); - - return s; -} - - -/* serialize data to the buffer */ - -bool RsTlvFileSet::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_FILESET, tlvsize); - - /* add mandatory parts first */ - std::list::const_iterator it; - - for(it = items.begin(); it != items.end() ; ++it) - { - ok &= (*it).SetTlv(data, size, offset); - /* drop out if fails */ - if (!ok) - return false; - } - - /* now optional ones */ - if (title.length() > 0) - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_TITLE, title); - if (comment.length() > 0) - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_COMMENT, comment); - - return ok; - -} - - -bool RsTlvFileSet::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_FILESET) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - /* while there is more TLV */ - while((*offset) + 2 < tlvend) - { - /* get the next type */ - uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - if (tlvsubtype == TLV_TYPE_FILEITEM) - { - RsTlvFileItem newitem; - ok &= newitem.GetTlv(data, size, offset); - if (ok) - { - items.push_back(newitem); - } - } - else if (tlvsubtype == TLV_TYPE_STR_TITLE) - { - ok &= GetTlvString(data, tlvend, offset, - TLV_TYPE_STR_TITLE, title); - } - else if (tlvsubtype == TLV_TYPE_STR_COMMENT) - { - ok &= GetTlvString(data, tlvend, offset, - TLV_TYPE_STR_COMMENT, comment); - } - else - { - /* unknown subtype -> error */ - ok &= SkipUnknownTlv(data, tlvend, offset); - } - - if (!ok) - { - break; - } - } - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvFileSet::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; -} - -/* print it out */ - -std::ostream &RsTlvFileSet::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvFileSet", indent); - uint16_t int_Indent = indent + 2; - - - printIndent(out, int_Indent); - out << "Mandatory:" << std::endl; - std::list::const_iterator it; - - for(it = items.begin(); it != items.end() ; ++it) - { - it->print(out, int_Indent); - } - printIndent(out, int_Indent); - out << "Optional:" << std::endl; - - /* now optional ones */ - if (title.length() > 0) - { - printIndent(out, int_Indent); - std::string cnv_title(title.begin(), title.end()); - out << "Title: " << cnv_title << std::endl; - } - if (comment.length() > 0) - { - printIndent(out, int_Indent); - std::string cnv_comment(comment.begin(), comment.end()); - out << "Comment: " << cnv_comment << std::endl; - } - - printEnd(out, "RsTlvFileSet", indent); - - return out; -} - - -/************************************* RsTlvFileData ************************************/ - -RsTlvFileData::RsTlvFileData() - :RsTlvItem(), file_offset(0), binData(TLV_TYPE_BIN_FILEDATA) -{ - return; -} - -void RsTlvFileData::TlvClear() -{ - file.TlvClear(); - binData.TlvClear(); - file_offset = 0; -} - - -uint32_t RsTlvFileData::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header */ - - /* collect sizes for both uInts and data length */ - s+= file.TlvSize(); - s+= GetTlvUInt64Size(); - s+= binData.TlvSize(); - - return s; -} - - -bool RsTlvFileData::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_FILEDATA , tlvsize); - - /* add mandatory part */ - ok &= file.SetTlv(data, size, offset); - ok &= SetTlvUInt64(data,size,offset, - TLV_TYPE_UINT64_OFFSET,file_offset); - ok &= binData.SetTlv(data, size, offset); - - return ok; - - -} - -bool RsTlvFileData::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - { - return false; - } - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_FILEDATA) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - ok &= file.GetTlv(data, size, offset); - ok &= GetTlvUInt64(data,size,offset, - TLV_TYPE_UINT64_OFFSET,&file_offset); - ok &= binData.GetTlv(data, size, offset); - - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvFileData::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; - -} - -/* print it out */ -std::ostream &RsTlvFileData::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvFileData", indent); - uint16_t int_Indent = indent + 2; - - file.print(out, int_Indent); - - printIndent(out, int_Indent); - out << "FileOffset: " << file_offset; - out << std::endl; - - binData.print(out, int_Indent); - - printEnd(out, "RsTlvFileData", indent); - return out; - -} - diff --git a/libretroshare/src/serialiser/rstlvfileitem.h b/libretroshare/src/serialiser/rstlvfileitem.h deleted file mode 100644 index 174753364..000000000 --- a/libretroshare/src/serialiser/rstlvfileitem.h +++ /dev/null @@ -1,89 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvfileitem.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie,Chris Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -/******************************************************************* - * These are the Compound TLV structures that must be (un)packed. - * - ******************************************************************/ - -#include "serialiser/rstlvitem.h" -#include "serialiser/rstlvidset.h" -#include "serialiser/rstlvbinary.h" - -class RsTlvFileItem: public RsTlvItem -{ - public: - RsTlvFileItem(); -virtual ~RsTlvFileItem() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - uint64_t filesize; /// Mandatory: size of file to be downloaded - RsFileHash hash; /// Mandatory: to find file - std::string name; /// Optional: name of file - std::string path; /// Optional: path on host computer - uint32_t pop; /// Optional: Popularity of file - uint32_t age; /// Optional: age of file - // For chunk hashing. - uint32_t piecesize; /// Optional: bytes/piece for hashset. - RsTlvHashSet hashset; /// Optional: chunk hashes. - -}; - -class RsTlvFileSet: public RsTlvItem -{ - public: - RsTlvFileSet() { return; } -virtual ~RsTlvFileSet() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - std::list items; /// Mandatory - std::string title; /// Optional: title of file set - std::string comment; /// Optional: comments for file -}; - - -class RsTlvFileData: public RsTlvItem -{ - public: - RsTlvFileData(); - virtual ~RsTlvFileData() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - RsTlvFileItem file; /// Mandatory: file information - uint64_t file_offset; /// Mandatory: where to start in bin data - RsTlvBinaryData binData; /// Mandatory: serialised file info -}; - - diff --git a/libretroshare/src/serialiser/rstlvgenericmap.h b/libretroshare/src/serialiser/rstlvgenericmap.h deleted file mode 100644 index 0cc4a3a88..000000000 --- a/libretroshare/src/serialiser/rstlvgenericmap.h +++ /dev/null @@ -1,91 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvgenericmap.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_TLV_GENERIC_MAP_H -#define RS_TLV_GENERIC_MAP_H - -#include "serialiser/rstlvitem.h" -#include "serialiser/rstlvgenericparam.h" - -#if 0 -#include - -#include -#include - -#endif - -/*********************************** RsTlvGenericPairRef ***********************************/ - -template -class RsTlvGenericPairRef: public RsTlvItem -{ - public: - RsTlvGenericPairRef(uint16_t pair_type, - uint16_t key_type, uint16_t value_type, K &k, V &v) - :mPairType(pair_type), mKeyType(key_type), - mValueType(value_type), mKey(k), mValue(v) { return; } - -virtual ~RsTlvGenericPairRef() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - uint16_t mPairType; - uint16_t mKeyType; - uint16_t mValueType; - K &mKey; - V &mValue; -}; - - -/************************************ RsTlvGenericMapRef ***********************************/ - -template -class RsTlvGenericMapRef: public RsTlvItem -{ - public: - RsTlvGenericMapRef(uint16_t map_type, uint16_t pair_type, - uint16_t key_type, uint16_t value_type, std::map &refmap) - :mMapType(map_type), mPairType(pair_type), - mKeyType(key_type), mValueType(value_type), mRefMap(refmap) { return; } - -virtual ~RsTlvGenericMapRef() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - uint16_t mMapType; - uint16_t mPairType; - uint16_t mKeyType; - uint16_t mValueType; - std::map &mRefMap; -}; - - -#include "rstlvgenericmap.inl" - -#endif - diff --git a/libretroshare/src/serialiser/rstlvgenericmap.inl b/libretroshare/src/serialiser/rstlvgenericmap.inl deleted file mode 100644 index b5239d2f7..000000000 --- a/libretroshare/src/serialiser/rstlvgenericmap.inl +++ /dev/null @@ -1,306 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvgenericmap.inl * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "serialiser/rstlvbase.h" - -// Must be different - as this is inline in headers. -//#define TLV_GENERICMAP_DEBUG 1 - -/*********************************** RsTlvGenericPairRef ***********************************/ - -template -void RsTlvGenericPairRef::TlvClear() -{ - RsTlvParamRef key(mKeyType, mKey); - RsTlvParamRef value(mValueType, mValue); - key.TlvClear(); - value.TlvClear(); -} - -template -uint32_t RsTlvGenericPairRef::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header */ - RsTlvParamRef key(mKeyType, mKey); - RsTlvParamRef value(mValueType, mValue); - - s += key.TlvSize(); - s += value.TlvSize(); - return s; - -} - -template -bool RsTlvGenericPairRef::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, mPairType, tlvsize); - - RsTlvParamRef key(mKeyType, mKey); - RsTlvParamRef value(mValueType, mValue); - ok &= key.SetTlv(data, tlvend, offset); - ok &= value.SetTlv(data, tlvend, offset); - - if (!ok) - { - std::cerr << "RsTlvGenericPairRef<>::SetTlv() Failed"; - std::cerr << std::endl; - } -#ifdef TLV_GENERICMAP_DEBUG - else - { - std::cerr << "RsTlvGenericPairRef<>::SetTlv() Ok"; - std::cerr << std::endl; - } -#endif - return ok; -} - -template -bool RsTlvGenericPairRef::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != mPairType) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - RsTlvParamRef key(mKeyType, mKey); - RsTlvParamRef value(mValueType, mValue); - ok &= key.GetTlv(data, tlvend, offset); - ok &= value.GetTlv(data, tlvend, offset); - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_GENERICMAP_DEBUG - std::cerr << "RsTlvGenericPairRef::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - return ok; - -} - -template -std::ostream &RsTlvGenericPairRef::print(std::ostream &out, uint16_t indent) const -{ - //printBase(out, "RsTlvGenericPairRef", indent); - uint16_t int_Indent = indent + 2; - - RsTlvParamRef key(mKeyType, mKey); - RsTlvParamRef value(mValueType, mValue); - - printIndent(out, int_Indent); - out << "Key:"; - key.print(out, 0); - out << std::endl; - - printIndent(out, int_Indent); - out << "Value:"; - value.print(out, 0); - out << std::endl; - - //printEnd(out, "RsTlvGenericPairRef", indent); - return out; -} - -// declare likely combinations. -//template<> class RsTlvGenericPairRef; -//template<> class RsTlvGenericPairRef; -//template<> class RsTlvGenericPairRef; -//template<> class RsTlvGenericPairRef; - -/************************************ RsTlvGenericMapRef ***********************************/ - -template -void RsTlvGenericMapRef::TlvClear() -{ - mRefMap.clear(); //empty list -} - -template -uint32_t RsTlvGenericMapRef::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header */ - - typename std::map::iterator it; - for(it = mRefMap.begin(); it != mRefMap.end(); ++it) - { - RsTlvGenericPairRef pair(mPairType, mKeyType, mValueType, it->first, it->second); - s += pair.TlvSize(); - } - - return s; -} - -template -bool RsTlvGenericMapRef::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, mMapType, tlvsize); - - - typename std::map::iterator it; - for(it = mRefMap.begin(); it != mRefMap.end(); ++it) - { - RsTlvGenericPairRef pair(mPairType, mKeyType, mValueType, it->first, it->second); - ok &= pair.SetTlv(data, size, offset); - } - - if (!ok) - { - std::cerr << "RsTlvGenericMapRef<>::SetTlv() Failed"; - std::cerr << std::endl; - } - - return ok; -} - -template -bool RsTlvGenericMapRef::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != mMapType) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - /* while there is TLV */ - while((*offset) + 2 < tlvend) - { - /* get the next type */ - uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - - if (tlvsubtype == mPairType) - { - K k; - V v; - RsTlvGenericPairRef pair(mPairType, mKeyType, mValueType, k, v); - ok &= pair.GetTlv(data, size, offset); - if (ok) - { - mRefMap[k] = v; - } - } - else - { - ok &= SkipUnknownTlv(data, tlvend, offset); - ok = false; - } - - if (!ok) - break; - } - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_GENERICMAP_DEBUG - std::cerr << "RsTlvGenericMapRef::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; -} - -template -std::ostream &RsTlvGenericMapRef::print(std::ostream &out, uint16_t indent) const -{ - //printBase(out, "RsTlvGenericMapRef", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - out << "MapType:" << mMapType << std::endl; - - typename std::map::iterator it; - for(it = mRefMap.begin(); it != mRefMap.end() ; ++it) - { - RsTlvGenericPairRef pair(mPairType, mKeyType, mValueType, it->first, it->second); - pair.print(out, int_Indent); - } - - //printEnd(out, "RsTlvGenericMapRef", indent); - return out; -} - diff --git a/libretroshare/src/serialiser/rstlvgenericparam.cc b/libretroshare/src/serialiser/rstlvgenericparam.cc deleted file mode 100644 index ef3610813..000000000 --- a/libretroshare/src/serialiser/rstlvgenericparam.cc +++ /dev/null @@ -1,222 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvgenericparam.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "serialiser/rstlvgenericparam.h" -#include "serialiser/rstlvbase.h" -#include - -// #define TLV_DEBUG 1 - -/* generic print */ -template -std::ostream & RsTlvParamRef::print(std::ostream &out, uint16_t indent) const -{ - printIndent(out, indent); - out << "Type: " << mParamType << " Param: " << mParam; - return out; -} - - -/***** uint16_t ****/ -template<> -uint32_t RsTlvParamRef::TlvSize() const -{ - return GetTlvUInt16Size(); -} - -template<> -void RsTlvParamRef::TlvClear() -{ - mParam = 0; -} - -template<> -bool RsTlvParamRef::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - return SetTlvUInt16(data, size, offset, mParamType, mParam); -} - -template<> -bool RsTlvParamRef::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - uint16_t param; - bool retval = GetTlvUInt16(data, size, offset, mParamType, ¶m); - mParam = param; - return retval; -} - -template<> -std::ostream & RsTlvParamRef::print(std::ostream &out, uint16_t indent) const -{ - printIndent(out, indent); - out << "Type: " << mParamType << "Param: " << mParam; - return out; -} - - -/***** const uint16_t ****/ - -template<> -uint32_t RsTlvParamRef::TlvSize() const -{ - return GetTlvUInt16Size(); -} - -template<> -void RsTlvParamRef::TlvClear() -{ - //mParam = 0; -} - - -template<> -bool RsTlvParamRef::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - return SetTlvUInt16(data, size, offset, mParamType, mParam); -} - -template<> -bool RsTlvParamRef::GetTlv(void */*data*/, uint32_t /*size*/, uint32_t */*offset*/) -{ - return false; //GetTlvUInt16(data, size, offset, mParamType, &mParam); -} - - -template<> -std::ostream & RsTlvParamRef::print(std::ostream &out, uint16_t indent) const -{ - printIndent(out, indent); - out << "Type: " << mParamType << "Param: " << mParam; - return out; -} - -/***** uint32_t ****/ -template<> -uint32_t RsTlvParamRef::TlvSize() const -{ - return GetTlvUInt32Size(); -} - -template<> -void RsTlvParamRef::TlvClear() -{ - mParam = 0; -} - -template<> -bool RsTlvParamRef::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - return SetTlvUInt32(data, size, offset, mParamType, mParam); -} - -template<> -bool RsTlvParamRef::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - return GetTlvUInt32(data, size, offset, mParamType, &mParam); -} - -template<> -std::ostream & RsTlvParamRef::print(std::ostream &out, uint16_t indent) const -{ - printIndent(out, indent); - out << "Type: " << mParamType << "Param: " << mParam; - return out; -} - - - -/***** const uint32_t ****/ -template<> -uint32_t RsTlvParamRef::TlvSize() const -{ - return GetTlvUInt32Size(); -} - -template<> -void RsTlvParamRef::TlvClear() -{ - //mParam = 0; -} - -template<> -bool RsTlvParamRef::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - return SetTlvUInt32(data, size, offset, mParamType, mParam); -} - -template<> -bool RsTlvParamRef::GetTlv(void */*data*/, uint32_t /*size*/, uint32_t */*offset*/) -{ - return false; - //GetTlvUInt32(data, size, offset, mParamType, &mParam); -} - -template<> -std::ostream & RsTlvParamRef::print(std::ostream &out, uint16_t indent) const -{ - printIndent(out, indent); - out << "Type: " << mParamType << "Param: " << mParam; - return out; -} - - -/***** std::string ****/ -template<> -uint32_t RsTlvParamRef::TlvSize() const -{ - return GetTlvStringSize(mParam); -} - -template<> -void RsTlvParamRef::TlvClear() -{ - mParam.clear(); -} - -template<> -bool RsTlvParamRef::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - return SetTlvString(data, size, offset, mParamType, mParam); -} - -template<> -bool RsTlvParamRef::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - return GetTlvString(data, size, offset, mParamType, mParam); -} - -template<> -std::ostream & RsTlvParamRef::print(std::ostream &out, uint16_t indent) const -{ - printIndent(out, indent); - out << "Type: " << mParamType << "Param: " << mParam; - return out; -} - -// declare likely combinations. -//template class RsTlvParamRef; -//template class RsTlvParamRef; -//template class RsTlvParamRef; - -//template class RsTlvParamRef; -//template class RsTlvParamRef; -//template class RsTlvParamRef; - diff --git a/libretroshare/src/serialiser/rstlvgenericparam.h b/libretroshare/src/serialiser/rstlvgenericparam.h deleted file mode 100644 index b1b6417a7..000000000 --- a/libretroshare/src/serialiser/rstlvgenericparam.h +++ /dev/null @@ -1,58 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvgenericparam.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_TLV_GENERIC_PARAM_H -#define RS_TLV_GENERIC_PARAM_H - -#include "serialiser/rstlvitem.h" - -#if 0 -#include - -#include -#include -#endif - - -/**** TLV ***** - * Generic Parameters / Maps. - */ - - -template -class RsTlvParamRef: public RsTlvItem -{ - public: - RsTlvParamRef(uint16_t param_type, T &p): mParamType(param_type), mParam(p) {} -virtual ~RsTlvParamRef() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - uint16_t mParamType; - T &mParam; -}; - - -#endif - diff --git a/libretroshare/src/serialiser/rstlvidset.cc b/libretroshare/src/serialiser/rstlvidset.cc deleted file mode 100644 index ef60aca36..000000000 --- a/libretroshare/src/serialiser/rstlvidset.cc +++ /dev/null @@ -1,166 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvidset.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie,Chris Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "rstlvidset.h" - -// #define TLV_DEBUG 1 - -/************************************* Service Id Set ************************************/ - -void RsTlvServiceIdSet::TlvClear() -{ - ids.clear(); - -} - -uint32_t RsTlvServiceIdSet::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header */ - - /* determine the total size of ids strings in list */ - std::list::const_iterator it; - for(it = ids.begin(); it != ids.end() ; ++it) - { - if (*it > 0) - s += GetTlvUInt32Size(); - } - - return s; -} - -bool RsTlvServiceIdSet::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_SERVICESET , tlvsize); - - /* determine the total size of ids strings in list */ - std::list::const_iterator it; - for(it = ids.begin(); it != ids.end() ; ++it) - { - if (*it > 0) - ok &= SetTlvUInt32(data, tlvend, offset, TLV_TYPE_UINT32_SERID, *it); - } - - return ok; - -} - -bool RsTlvServiceIdSet::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_SERVICESET) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - -/* while there is TLV */ - while((*offset) + 2 < tlvend) - { - /* get the next type */ - uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - - if (tlvsubtype == TLV_TYPE_UINT32_SERID) - { - uint32_t newIds; - ok &= GetTlvUInt32(data, tlvend, offset, TLV_TYPE_UINT32_SERID, &newIds); - if(ok) - { - ids.push_back(newIds); - - } - } - else - { - /* Step past unknown TLV TYPE */ - ok &= SkipUnknownTlv(data, tlvend, offset); - } - - if (!ok) - { - break; - } - } - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvServiceIdSet::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - - return ok; -} - -/// print to screen RsTlvServiceSet contents -std::ostream &RsTlvServiceIdSet::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvServiceIdSet", indent); - uint16_t int_Indent = indent + 2; - - std::list::const_iterator it; - for(it = ids.begin(); it != ids.end() ; ++it) - { - printIndent(out, int_Indent); - out << "id:" << *it; - out << std::endl; - } - - printEnd(out, "RsTlvServiceIdSet", indent); - return out; - -} - - - diff --git a/libretroshare/src/serialiser/rstlvidset.h b/libretroshare/src/serialiser/rstlvidset.h deleted file mode 100644 index 2e8a3f882..000000000 --- a/libretroshare/src/serialiser/rstlvidset.h +++ /dev/null @@ -1,145 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvidset.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie,Chris Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -/******************************************************************* - * These are the Compound TLV structures that must be (un)packed. - * - ******************************************************************/ - -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvitem.h" -#include "util/rsdeprecate.h" -#include -#include - -#include - -/// @deprecated use plain std::set<> instead -template class RS_DEPRECATED_FOR(std::set<>) t_RsTlvIdSet - : public RsTlvItem -{ - public: - t_RsTlvIdSet() {} - virtual ~t_RsTlvIdSet() {} - - virtual uint32_t TlvSize() const { return ID_CLASS::SIZE_IN_BYTES * ids.size() + TLV_HEADER_SIZE; } - virtual void TlvClear(){ ids.clear() ; } - virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const - { /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - ok = ok && SetTlvBase(data, tlvend, offset, TLV_TYPE, tlvsize); - - for(typename std::set::const_iterator it(ids.begin());it!=ids.end();++it) - ok = ok && (*it).serialise(data,tlvend,*offset) ; - - return ok ; - } - virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset) - { - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - while(*offset + ID_CLASS::SIZE_IN_BYTES <= tlvend) - { - ID_CLASS id ; - ok = ok && id.deserialise(data,tlvend,*offset) ; - ids.insert(id) ; - } - if(*offset != tlvend) - { - std::cerr << "(EE) deserialisaiton error in " << __PRETTY_FUNCTION__ << std::endl; - ok = false; - } - - if(!ok) - std::cerr << "(WW) something wrong in ID_CLASS.deserialise in " << __PRETTY_FUNCTION__ << std::endl; - - return ok; - } - virtual std::ostream &print(std::ostream &out, uint16_t /* indent */) const - { - for(typename std::set::const_iterator it(ids.begin());it!=ids.end();++it) - out << (*it).toStdString() << ", " ; - - return out ; - } - virtual std::ostream &printHex(std::ostream &out, uint16_t /* indent */) const /* SPECIAL One */ - { - for(typename std::set::const_iterator it(ids.begin());it!=ids.end();++it) - out << (*it).toStdString() << ", " ; - - return out ; - } - - std::set ids ; -}; - -typedef t_RsTlvIdSet RsTlvPeerIdSet ; -typedef t_RsTlvIdSet RsTlvPgpIdSet ; -typedef t_RsTlvIdSet RsTlvHashSet ; -typedef t_RsTlvIdSet RsTlvGxsIdSet ; -typedef t_RsTlvIdSet RsTlvGxsMsgIdSet ; -typedef t_RsTlvIdSet RsTlvGxsCircleIdSet ; -typedef t_RsTlvIdSet RsTlvNodeGroupIdSet ; - -class RS_DEPRECATED RsTlvServiceIdSet: public RsTlvItem -{ - public: - RsTlvServiceIdSet() { return; } -virtual ~RsTlvServiceIdSet() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - std::list ids; /* Mandatory */ -}; - - diff --git a/libretroshare/src/serialiser/rstlvimage.cc b/libretroshare/src/serialiser/rstlvimage.cc deleted file mode 100644 index ce8ea5d6c..000000000 --- a/libretroshare/src/serialiser/rstlvimage.cc +++ /dev/null @@ -1,198 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvimage.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie,Chris Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "serialiser/rstlvimage.h" - -#if 0 -#include - -#include "serialiser/rstlvbase.h" -#include "serialiser/rsbaseserial.h" -#endif - -/*** - * #define TLV_IMG_DEBUG 1 - **/ - -/************************************* RsTlvImage ************************************/ - -RsTlvImage::RsTlvImage() - :RsTlvItem(), image_type(0), binData(TLV_TYPE_BIN_IMAGE) -{ - return; -} - -void RsTlvImage::TlvClear() -{ - image_type = 0; - binData.TlvClear(); -} - - -uint32_t RsTlvImage::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header */ - - /* collect sizes for both uInts and data length */ - s+= 4; - s+= binData.TlvSize(); - - return s; -} - - -bool RsTlvImage::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ -#ifdef TLV_IMG_DEBUG - std::cerr << "RsTlvImage::SetTlv()" << std::endl; -#endif - - - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - { -#ifdef TLV_IMG_DEBUG - std::cerr << "RsTlvImage::SetTlv() no space" << std::endl; -#endif - return false; /* not enough space */ - } - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_IMAGE , tlvsize); -#ifdef TLV_IMG_DEBUG - if (!ok) - std::cerr << "RsTlvImage::SetTlv() NOK base" << std::endl; -#endif - - /* add mandatory part */ - ok &= setRawUInt32(data, tlvend, offset, image_type); -#ifdef TLV_IMG_DEBUG - if (!ok) - std::cerr << "RsTlvImage::SetTlv() NOK image" << std::endl; -#endif - - ok &= binData.SetTlv(data, size, offset); -#ifdef TLV_IMG_DEBUG - if (!ok) - std::cerr << "RsTlvImage::SetTlv() NOK binData" << std::endl; -#endif - - - return ok; - - -} - -bool RsTlvImage::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ -#ifdef TLV_IMG_DEBUG - std::cerr << "RsTlvImage::GetTlv()" << std::endl; -#endif - if (size < *offset + TLV_HEADER_SIZE) - { - return false; - } - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - { -#ifdef TLV_IMG_DEBUG - std::cerr << "RsTlvImage::GetTlv() FAIL no space" << std::endl; -#endif - return false; /* not enough space */ - } - - if (tlvtype != TLV_TYPE_IMAGE) /* check type */ - { -#ifdef TLV_IMG_DEBUG - std::cerr << "RsTlvImage::GetTlv() FAIL wrong type" << std::endl; -#endif - return false; - } - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - /* add mandatory parts first */ - ok &= getRawUInt32(data, tlvend, offset, &(image_type)); - ok &= binData.GetTlv(data, size, offset); - -#ifdef TLV_IMG_DEBUG - if (!ok) - std::cerr << "RsTlvImage::GetTlv() NOK" << std::endl; -#endif - - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvImage::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; - -} - -/* print it out */ -std::ostream &RsTlvImage::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvImage", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - out << "Image_Type: " << image_type; - out << std::endl; - - binData.print(out, int_Indent); - - printEnd(out, "RsTlvImage", indent); - return out; - -} - -RsTlvImage::RsTlvImage(const RsTlvImage& rightOp) -:RsTlvItem(), image_type(0), binData(TLV_TYPE_BIN_IMAGE) -{ - this->image_type = rightOp.image_type; - this->binData.setBinData(rightOp.binData.bin_data, rightOp.binData.bin_len); -} diff --git a/libretroshare/src/serialiser/rstlvimage.h b/libretroshare/src/serialiser/rstlvimage.h deleted file mode 100644 index 562c29090..000000000 --- a/libretroshare/src/serialiser/rstlvimage.h +++ /dev/null @@ -1,52 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvimage.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie,Chris Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -/******************************************************************* - * These are the Compound TLV structures that must be (un)packed. - * - ******************************************************************/ - -#include "serialiser/rstlvitem.h" -#include "serialiser/rstlvbinary.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rsbaseserial.h" - -class RsTlvImage: public RsTlvItem -{ -public: - RsTlvImage(); - RsTlvImage(const RsTlvImage& ); - virtual ~RsTlvImage() { return; } - virtual uint32_t TlvSize() const; - virtual void TlvClear(); - virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; - virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); - - bool empty() const { return binData.bin_len == 0 ; } - virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - uint32_t image_type; // Mandatory: - RsTlvBinaryData binData; // Mandatory: serialised file info -}; - - diff --git a/libretroshare/src/serialiser/rstlvitem.cc b/libretroshare/src/serialiser/rstlvitem.cc deleted file mode 100644 index 62b40e761..000000000 --- a/libretroshare/src/serialiser/rstlvitem.cc +++ /dev/null @@ -1,192 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvitem.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie,Chris Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "rstlvitem.h" -#include "rstlvbase.h" -#include - -#if 0 -#include "rsbaseserial.h" -#include "util/rsprint.h" -#include -#include -#include -#endif - -// #define TLV_DEBUG 1 - -void RsTlvItem::TlvShallowClear() -{ - TlvClear(); /* unless overloaded! */ -} - -std::ostream &RsTlvItem::printBase(std::ostream &out, std::string clsName, uint16_t indent) const -{ - printIndent(out, indent); - out << "RsTlvItem: " << clsName << " Size: " << TlvSize() << " ***********************"; - out << std::endl; - return out; -} - -std::ostream &RsTlvItem::printEnd(std::ostream &out, std::string clsName, uint16_t indent) const -{ - printIndent(out, indent); - out << "********************** " << clsName << " *********************"; - out << std::endl; - return out; -} - -std::ostream &printIndent(std::ostream &out, uint16_t indent) -{ - for(int i = 0; i < indent; i++) - { - out << " "; - } - return out; -} - - - -RsTlvUnit::RsTlvUnit(const uint16_t tlv_type) - :RsTlvItem(), mTlvType(tlv_type) -{ - return; -} - -uint32_t RsTlvUnit::TlvSize() const -{ - return TLV_HEADER_SIZE + TlvSizeUnit(); -} - -/* serialise */ -bool RsTlvUnit::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ -#ifdef TLV_DEBUG - std::cerr << "RsTlvUnit::SetTlv()" << std::endl; -#endif - - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvImage::SetTlv() ERROR not enough space" << std::endl; -#endif - return false; /* not enough space */ - } - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_IMAGE , tlvsize); - - if (!ok) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvUnit::SetTlv() ERROR Setting base" << std::endl; -#endif - return false; - } - - ok &= SetTlvUnit(data, tlvend, offset); - -#ifdef TLV_DEBUG - if (!ok) - std::cerr << "RsTlvUnit::SetTlv() ERROR in SetTlvUnit" << std::endl; -#endif - return ok; -} - -/* deserialise */ -bool RsTlvUnit::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvUnit::GetTlv() ERROR not enough size for header"; - std::cerr << std::endl; -#endif - return false; - } - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - { -#ifdef TLV_IMG_DEBUG - std::cerr << "RsTlvImage::GetTlv() ERROR no space"; - std::cerr << std::endl; -#endif - return false; /* not enough space */ - } - - if (tlvtype != mTlvType) /* check type */ - { -#ifdef TLV_IMG_DEBUG - std::cerr << "RsTlvImage::GetTlv() ERROR wrong type"; - std::cerr << std::endl; -#endif - return false; - } - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - /* extract components */ - ok &= GetTlvUnit(data, tlvend, offset); - -#ifdef TLV_IMG_DEBUG - if (!ok) - { - std::cerr << "RsTlvUnit::GetTlv() ERROR GetTlvUnit() NOK"; - std::cerr << std::endl; - } -#endif - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvUnit::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; - -} - - diff --git a/libretroshare/src/serialiser/rstlvitem.h b/libretroshare/src/serialiser/rstlvitem.h deleted file mode 100644 index 4d45cd120..000000000 --- a/libretroshare/src/serialiser/rstlvitem.h +++ /dev/null @@ -1,81 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvitem.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie,Chris Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -/******************************************************************* - * These are the Compound TLV structures that must be (un)packed. - * - ******************************************************************/ - -#include "util/rsdeprecate.h" - -#include -#include -#include - -/*! A base class for all tlv items - * This class is provided to allow the serialisation and deserialization of - * compund tlv items - * @deprecated TLV serialization system is deprecated! - */ -class RS_DEPRECATED_FOR(RsSerializable) RsTlvItem -{ - public: - RsTlvItem() { return; } -virtual ~RsTlvItem() { return; } -virtual uint32_t TlvSize() const = 0; -virtual void TlvClear() = 0; -virtual void TlvShallowClear(); /*! Don't delete allocated data */ -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const = 0; /* serialise */ -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset) = 0; /* deserialise */ -virtual std::ostream &print(std::ostream &out, uint16_t indent) const = 0; -std::ostream &printBase(std::ostream &out, std::string clsName, uint16_t indent) const; -std::ostream &printEnd(std::ostream &out, std::string clsName, uint16_t indent) const; -}; - -std::ostream &printIndent(std::ostream &out, uint16_t indent); - -class RS_DEPRECATED_FOR(RsSerializable) RsTlvUnit: public RsTlvItem -{ - public: - RsTlvUnit(uint16_t tlv_type); -virtual ~RsTlvUnit() { return; } -virtual uint32_t TlvSize() const; -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); - -virtual uint16_t TlvType() const { return mTlvType; } - -// These Functions need to be implemented. -//virtual void TlvClear() = 0; -//virtual std::ostream &print(std::ostream &out, uint16_t indent) = 0 const; - -virtual uint32_t TlvSizeUnit() const = 0; -virtual bool SetTlvUnit(void *data, uint32_t size, uint32_t *offset) const = 0; -virtual bool GetTlvUnit(void *data, uint32_t size, uint32_t *offset) = 0; - - - private: - uint16_t mTlvType; -}; - - diff --git a/libretroshare/src/serialiser/rstlvkeys.cc b/libretroshare/src/serialiser/rstlvkeys.cc deleted file mode 100644 index e2be0b666..000000000 --- a/libretroshare/src/serialiser/rstlvkeys.cc +++ /dev/null @@ -1,830 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvkeys.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "rstlvkeys.h" -#include "rstlvbase.h" -#include "rsbaseserial.h" -#include "util/stacktrace.h" -#include "gxs/gxssecurity.h" - -#include - -// #define TLV_DEBUG 1 - -// This should be removed eventually, but will break backward compatibility -#define KEEP_OLD_SIGNATURE_SERIALISE_FORMAT - -/************************************* RsTlvSecurityKey ************************************/ - -RsTlvRSAKey::RsTlvRSAKey() - :RsTlvItem(), keyFlags(0), startTS(0), endTS(0), keyData(TLV_TYPE_KEY_EVP_PKEY) -{ - return; -} - -void RsTlvRSAKey::TlvClear() -{ - keyId.clear(); - keyFlags = 0; - startTS = 0; - endTS = 0; - keyData.TlvClear(); -} - -/* clears keyData - but doesn't delete */ -void RsTlvRSAKey::ShallowClear() -{ - keyId.clear(); - keyFlags = 0; - startTS = 0; - endTS = 0; - keyData.bin_data = 0; - keyData.bin_len = 0; -} - -uint32_t RsTlvRSAKey::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header + 4 for size */ - - /* now add comment and title length of this tlv object */ - -#ifdef KEEP_OLD_SIGNATURE_SERIALISE_FORMAT - s += GetTlvStringSize(keyId.toStdString()) ; -#else - s += keyId.serial_size(); -#endif - s += 4; - s += 4; - s += 4; - s += keyData.TlvSize(); - - return s; -} - -bool RsTlvRSAKey::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - { - std::cerr << "RsTlvSecurityKey::SetTlv() Failed not enough space"; - std::cerr << std::endl; - return false; /* not enough space */ - } - - bool ok = checkKey(); // check before serialise, just in case - - /* start at data[offset] */ - /* add mandatory parts first */ - - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_SECURITY_KEY, tlvsize); -#ifdef KEEP_OLD_SIGNATURE_SERIALISE_FORMAT - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEYID, keyId.toStdString()); -#else - ok &= keyId.serialise(data, tlvend, *offset) ; -#endif - ok &= setRawUInt32(data, tlvend, offset, keyFlags); - ok &= setRawUInt32(data, tlvend, offset, startTS); - ok &= setRawUInt32(data, tlvend, offset, endTS); - ok &= keyData.SetTlv(data, tlvend, offset); - - return ok; - -} - -bool RsTlvRSAKey::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvSecurityKey::GetTlv() Fail, not enough space"; - std::cerr << std::endl; -#endif - return false; /* not enough space */ - } - - if (tlvtype != TLV_TYPE_SECURITY_KEY) /* check type */ - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvSecurityKey::GetTlv() Fail, wrong type"; - std::cerr << std::endl; -#endif - return false; - } - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; -#ifdef KEEP_OLD_SIGNATURE_SERIALISE_FORMAT - std::string s ; - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEYID, s); - keyId = RsGxsId(s) ; -#else - ok &= keyId.deserialise(data, tlvend, *offset) ; -#endif - ok &= getRawUInt32(data, tlvend, offset, &(keyFlags)); - ok &= getRawUInt32(data, tlvend, offset, &(startTS)); - ok &= getRawUInt32(data, tlvend, offset, &(endTS)); - ok &= keyData.GetTlv(data, tlvend, offset); - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvSecurityKey::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - if (!ok) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvSecurityKey::GetTlv() Failed somewhere ok == false"; - std::cerr << std::endl; -#endif - } - return ok && checkKey() ; -} - -/** - * @brief RsTlvRSAKey::getKeyTypeTlv: Deserialize data in temp value to get type of key. - * @param data: Serialized data - * @param size: Size of the data - * @param constoffset: Offset where find first data. Not updated by this function. - * @return The keyFlag filtered by RSTLV_KEY_TYPE_MASK. 0 if failed - */ -uint32_t RsTlvRSAKey::getKeyTypeTlv(void *data, uint32_t size, uint32_t *constoffset) const -{ - //Temporay Value. The same name than class to get same code than RsTlvRSAKey::GetTlv - uint32_t offValue = *constoffset; - uint32_t *offset = &offValue; - RsGxsId keyId; // Mandatory : - uint32_t keyFlags; // Mandatory ; - //The Code below have to be same as RsTlvRSAKey::GetTlv excepted last lines until flag is desserialized. - //Just comment TlvClear(); and unused values - - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvSecurityKey::GetTlv() Fail, not enough space"; - std::cerr << std::endl; -#endif - return false; /* not enough space */ - } - - if (tlvtype != TLV_TYPE_SECURITY_KEY) /* check type */ - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvSecurityKey::GetTlv() Fail, wrong type"; - std::cerr << std::endl; -#endif - return false; - } - - bool ok = true; - - /* ready to load */ - //TlvClear();//RsTlvRSAKey::getKeyTypeTlv - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; -#ifdef KEEP_OLD_SIGNATURE_SERIALISE_FORMAT - std::string s ; - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEYID, s); - keyId = RsGxsId(s) ; -#else - ok &= keyId.deserialise(data, tlvend, *offset) ; -#endif - ok &= getRawUInt32(data, tlvend, offset, &(keyFlags)); - //Stop here no need more data - //RsTlvRSAKey::getKeyTypeTlv specific lines - uint32_t ret = keyFlags & RSTLV_KEY_TYPE_MASK; - if (!ok) - { - ret = 0; -#ifdef TLV_DEBUG - std::cerr << "RsTlvRSAKey::getKeyTypeTlv() Failed somewhere ok == false" << std::endl; -#endif - } - return ret ; -} - -std::ostream& RsTlvRSAKey::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvSecurityKey", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - out << "KeyId:" << keyId; - out << std::endl; - - printIndent(out, int_Indent); - out << "KeyFlags:" << keyFlags; - out << std::endl; - - printIndent(out, int_Indent); - out << "StartTS:" << startTS; - out << std::endl; - - printIndent(out, int_Indent); - out << "EndTS:" << endTS; - out << std::endl; - - keyData.print(out, int_Indent); - - out << std::endl; - - printEnd(out, "RsTlvSecurityKey", indent); - return out; -} - - -bool RsTlvPrivateRSAKey::checkKey() const -{ - bool keyFlags_TYPE_FULL = (keyFlags & RSTLV_KEY_TYPE_FULL); - if (!keyFlags_TYPE_FULL) {std::cout << "RsTlvPrivateRSAKey::checkKey() keyFlags not Type Full " << std::hex << keyFlags << " & " << RSTLV_KEY_TYPE_FULL << std::dec << std::endl;} - bool keyFlags_not_PUBLIC_ONLY = !(keyFlags & RSTLV_KEY_TYPE_PUBLIC_ONLY); - if (!keyFlags_not_PUBLIC_ONLY) {std::cout << "RsTlvPrivateRSAKey::checkKey() keyFlags is Public Only " << std::hex << keyFlags << " & " << RSTLV_KEY_TYPE_PUBLIC_ONLY << std::dec << std::endl;} - bool security_OK = false; - if (keyFlags_TYPE_FULL && keyFlags_not_PUBLIC_ONLY) - { - //Don't trigg error if flags already wrong - security_OK = GxsSecurity::checkPrivateKey(*this); - if (!security_OK) {std::cout << "RsTlvPublicRSAKey::checkKey() key is not secure."<< std::endl;} - } - - return keyFlags_TYPE_FULL && keyFlags_not_PUBLIC_ONLY && security_OK ; -} - -bool RsTlvPublicRSAKey::checkKey() const -{ - bool keyFlags_PUBLIC_ONLY = (keyFlags & RSTLV_KEY_TYPE_PUBLIC_ONLY); - if (!keyFlags_PUBLIC_ONLY) {std::cout << "RsTlvPublicRSAKey::checkKey() keyFlags not Public Only " << std::hex << keyFlags << " & " << RSTLV_KEY_TYPE_PUBLIC_ONLY << std::dec << std::endl;} - bool keyFlags_not_TYPE_FULL = !(keyFlags & RSTLV_KEY_TYPE_FULL); - if (!keyFlags_not_TYPE_FULL) {std::cout << "RsTlvPublicRSAKey::checkKey() keyFlags is Type Full " << std::hex << keyFlags << " & " << RSTLV_KEY_TYPE_FULL << std::dec << std::endl;} - bool security_OK = false; - if (keyFlags_PUBLIC_ONLY && keyFlags_not_TYPE_FULL) - { - //Don't trigg error if flags already wrong - security_OK = GxsSecurity::checkPublicKey(*this); - if (!security_OK) {std::cout << "RsTlvPublicRSAKey::checkKey() key is not secure."<< std::endl;} - } - - return keyFlags_PUBLIC_ONLY && keyFlags_not_TYPE_FULL && security_OK ; -} - -/************************************* RsTlvSecurityKeySet ************************************/ - -void RsTlvSecurityKeySet::TlvClear() -{ - groupId.clear(); -#ifdef TODO - public_keys.clear(); //empty list - private_keys.clear(); //empty list -#endif -} - -uint32_t RsTlvSecurityKeySet::TlvSize() const -{ - - uint32_t s = TLV_HEADER_SIZE; /* header */ - - s += GetTlvStringSize(groupId); - - for(std::map::const_iterator it = public_keys.begin(); it != public_keys.end() ; ++it) - s += (it->second).TlvSize(); - - for(std::map::const_iterator it = private_keys.begin(); it != private_keys.end() ; ++it) - s += (it->second).TlvSize(); - - return s; -} - -bool RsTlvSecurityKeySet::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvSecurityKeySet::SetTlv() Failed not enough space"; - std::cerr << std::endl; -#endif - return false; /* not enough space */ - } - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_SECURITYKEYSET , tlvsize); - - /* groupId */ - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_GROUPID, groupId); - - for(std::map::const_iterator it = public_keys.begin(); it != public_keys.end() ; ++it) - ok &= (it->second).SetTlv(data, size, offset); - - for(std::map::const_iterator it = private_keys.begin(); it != private_keys.end() ; ++it) - ok &= (it->second).SetTlv(data, size, offset); - - return ok; -} - - -bool RsTlvSecurityKeySet::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_SECURITYKEYSET) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - /* groupId */ - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_GROUPID, groupId); - - /* while there is TLV */ - while((*offset) + 2 < tlvend) - { - /* get the next type */ - uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - - // Security key set can be composed of public or private keys. We first ask type to desserialize in good one to not trigg errors. - switch(tlvsubtype) - { - case TLV_TYPE_SECURITY_KEY: - { - RsTlvPublicRSAKey gen_key; - uint32_t keyType = gen_key.getKeyTypeTlv(data, tlvend, offset); - if(keyType == RSTLV_KEY_TYPE_PUBLIC_ONLY) - { - - RsTlvPublicRSAKey public_key; - - if(public_key.GetTlv(data, tlvend, offset)) - public_keys[public_key.keyId] = public_key; - } - else if(keyType == RSTLV_KEY_TYPE_FULL) - { - - RsTlvPrivateRSAKey private_key; - - if(private_key.GetTlv(data, tlvend, offset)) - private_keys[private_key.keyId] = private_key; - } - } - break ; - - default: - ok &= SkipUnknownTlv(data, tlvend, offset); - break; - - } - - if (!ok) - break; - } - - - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvSecurityKeySet::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; -} - - -// prints out contents of RsTlvSecurityKeySet -std::ostream &RsTlvSecurityKeySet::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvSecurityKeySet", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - out << "GroupId: " << groupId; - out << std::endl; - - for( std::map::const_iterator it = public_keys.begin(); it != public_keys.end() ; ++it) - (it->second).print(out, int_Indent); - for( std::map::const_iterator it = private_keys.begin(); it != private_keys.end() ; ++it) - (it->second).print(out, int_Indent); - - printEnd(out, "RsTlvSecurityKeySet", indent); - return out; -} - - -/************************************* RsTlvSecurityKey ************************************/ - -RsTlvKeySignature::RsTlvKeySignature() - :RsTlvItem(), signData(TLV_TYPE_SIGN_RSA_SHA1) -{ - ShallowClear() ; // avoids uninitialized memory if the fields are not initialized. -} - -void RsTlvKeySignature::TlvClear() -{ - keyId.clear(); - signData.TlvClear(); -} - -/* clears signData - but doesn't delete */ -void RsTlvKeySignature::ShallowClear() -{ - keyId.clear(); - signData.bin_data = 0; - signData.bin_len = 0; -} - -uint32_t RsTlvKeySignature::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header + 4 for size */ - -#ifdef KEEP_OLD_SIGNATURE_SERIALISE_FORMAT - s += GetTlvStringSize(keyId.toStdString()) ; -#else - s += keyId.serial_size() ; -#endif - s += signData.TlvSize(); - return s; - -} - -bool RsTlvKeySignature::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvKeySignature::SetTlv() Fail, not enough space"; - std::cerr << std::endl; -#endif - return false; /* not enough space */ - } - - bool ok = true; - - /* start at data[offset] */ - /* add mandatory parts first */ - - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_KEYSIGNATURE, tlvsize); - -#ifdef KEEP_OLD_SIGNATURE_SERIALISE_FORMAT - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEYID, keyId.toStdString()); -#else - ok &= keyId.serialise(data, tlvend, *offset) ; -#endif - ok &= signData.SetTlv(data, tlvend, offset); - - if (!ok) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvKeySignature::SetTlv() Failed somewhere"; - std::cerr << std::endl; -#endif - } - - return ok; - -} - - -bool RsTlvKeySignature::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvKeySignature::GetTlv() Not Enough Space"; - std::cerr << std::endl; -#endif - return false; /* not enough space */ - } - - if (tlvtype != TLV_TYPE_KEYSIGNATURE) /* check type */ - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvKeySignature::GetTlv() Type Fail"; - std::cerr << std::endl; -#endif - return false; - } - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - -#ifdef KEEP_OLD_SIGNATURE_SERIALISE_FORMAT - std::string s ; - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEYID, s); - keyId = RsGxsId(s) ; -#else - ok &= keyId.deserialise(data, tlvend, *offset) ; -#endif - ok &= signData.GetTlv(data, tlvend, offset); - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvKeySignature::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; - -} - - -std::ostream &RsTlvKeySignature::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvKeySignature", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - out << "KeyId:" << keyId; - out << std::endl; - - signData.print(out, int_Indent); - - out << std::endl; - - printEnd(out, "RsTlvKeySignature", indent); - return out; -} - - -/************************************* RsTlvKeySignatureSet ************************************/ - -RsTlvKeySignatureSet::RsTlvKeySignatureSet() -{ - -} - -std::ostream &RsTlvKeySignatureSet::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvKeySignatureSet", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - - std::map::const_iterator mit = keySignSet.begin(); - - for(; mit != keySignSet.end(); ++mit) - { - out << "SignType: " << mit->first << std::endl; - const RsTlvKeySignature& sign = mit->second; - sign.print(out, indent); - } - - out << std::endl; - - printEnd(out, "RsTlvKeySignatureSet", indent); - return out; -} - -void RsTlvKeySignatureSet::TlvClear() -{ - keySignSet.clear(); -} - -bool RsTlvKeySignatureSet::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvKeySignatureSet::SetTlv() Failed not enough space"; - std::cerr << std::endl; -#endif - return false; /* not enough space */ - } - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_KEYSIGNATURESET , tlvsize); - - - if(!keySignSet.empty()) - { - std::map::const_iterator it; - - for(it = keySignSet.begin(); it != keySignSet.end() ; ++it) - { - ok &= SetTlvUInt32(data, size, offset, TLV_TYPE_KEYSIGNATURETYPE, it->first); - ok &= (it->second).SetTlv(data, size, offset); - } - } - - -return ok; -} - -bool RsTlvKeySignatureSet::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_KEYSIGNATURESET) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - SignType sign_type = 0; - - /* while there is TLV */ - while((*offset) + 2 < tlvend) - { - - /* get the next type */ - uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - - switch(tlvsubtype) - { - case TLV_TYPE_KEYSIGNATURE: - { - RsTlvKeySignature sign; - ok &= sign.GetTlv(data, size, offset); - if (ok) - { - keySignSet[sign_type] = sign; - } - } - break; - case TLV_TYPE_KEYSIGNATURETYPE: - { - ok = GetTlvUInt32(data, size, offset, TLV_TYPE_KEYSIGNATURETYPE, &sign_type); - } - break; - default: - ok &= SkipUnknownTlv(data, tlvend, offset); - break; - } - - if (!ok) - break; - } - - - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvKeySignatureSet::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; -} - -uint32_t RsTlvKeySignatureSet::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; // header size - std::map::const_iterator it; - - for(it = keySignSet.begin(); it != keySignSet.end() ; ++it) - { - s += GetTlvUInt32Size(); // sign type - s += it->second.TlvSize(); // signature - } - - return s; -} - - - - - - - - - - - - - - - - - - - - diff --git a/libretroshare/src/serialiser/rstlvkeys.h b/libretroshare/src/serialiser/rstlvkeys.h deleted file mode 100644 index 5f82e51f0..000000000 --- a/libretroshare/src/serialiser/rstlvkeys.h +++ /dev/null @@ -1,146 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvkeys.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -/******************************************************************* - * These are the Compound TLV structures that must be (un)packed. - ******************************************************************/ - -#include "serialiser/rstlvitem.h" -#include "serialiser/rstlvbinary.h" -#include "serialiser/rstlvbase.h" -#include "retroshare/rsgxsifacetypes.h" - -#include - -const uint32_t RSTLV_KEY_TYPE_MASK = 0x000f; -const uint32_t RSTLV_KEY_TYPE_PUBLIC_ONLY = 0x0001; -const uint32_t RSTLV_KEY_TYPE_FULL = 0x0002; - -const uint32_t RSTLV_KEY_DISTRIB_PUBLIC_deprecated = 0x0010;// was used as PUBLISH flag. Probably a typo. - -const uint32_t RSTLV_KEY_DISTRIB_PUBLISH = 0x0020; -const uint32_t RSTLV_KEY_DISTRIB_ADMIN = 0x0040; -const uint32_t RSTLV_KEY_DISTRIB_IDENTITY = 0x0080; -const uint32_t RSTLV_KEY_DISTRIB_MASK = 0x00f0; - -// Old class for RsTlvSecurityKey. Is kept for backward compatibility, but should not be serialised anymore - -class RsTlvRSAKey: public RsTlvItem -{ -public: - RsTlvRSAKey(); - virtual bool checkKey() const = 0 ; // this pure virtual forces people to explicitly declare if they use a public or a private key. - - virtual uint32_t TlvSize() const; - virtual void TlvClear(); - virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; - virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); - virtual std::ostream& print(std::ostream &out, uint16_t indent) const; - - /* clears KeyData - but doesn't delete - to transfer ownership */ - void ShallowClear(); - - uint32_t getKeyTypeTlv(void *data, uint32_t size, uint32_t *offset) const; - - RsGxsId keyId; // Mandatory : - uint32_t keyFlags; // Mandatory ; - uint32_t startTS; // Mandatory : - uint32_t endTS; // Mandatory : - RsTlvBinaryData keyData; // Mandatory : -}; - -// The two classes below are by design incompatible, making it impossible to pass a private key as a public key - -class RsTlvPrivateRSAKey: public RsTlvRSAKey -{ -public: - RsTlvPrivateRSAKey():RsTlvRSAKey() {} - virtual ~RsTlvPrivateRSAKey() {} - - virtual bool checkKey() const ; -}; -class RsTlvPublicRSAKey: public RsTlvRSAKey -{ -public: - RsTlvPublicRSAKey():RsTlvRSAKey() {} - virtual ~RsTlvPublicRSAKey() {} - - virtual bool checkKey() const ; -}; - -class RsTlvSecurityKeySet: public RsTlvItem -{ -public: - RsTlvSecurityKeySet() { return; } - virtual ~RsTlvSecurityKeySet() { return; } - - // creates the public keys that are possible missing although the private keys are present. - - void createPublicFromPrivateKeys(); - - virtual uint32_t TlvSize() const; - virtual void TlvClear(); - virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; - virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); - virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - std::string groupId; // Mandatory : - std::map public_keys; // Mandatory : - std::map private_keys; // Mandatory : -}; - - -class RsTlvKeySignature: public RsTlvItem -{ - public: - RsTlvKeySignature(); - virtual ~RsTlvKeySignature() { return; } - virtual uint32_t TlvSize() const; - virtual void TlvClear(); - virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; - virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); - virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - void ShallowClear(); /* clears signData - but doesn't delete */ - - RsGxsId keyId; // Mandatory : - RsTlvBinaryData signData; // Mandatory : -}; - -typedef uint32_t SignType; - -class RsTlvKeySignatureSet : public RsTlvItem -{ -public: - RsTlvKeySignatureSet(); - virtual ~RsTlvKeySignatureSet() { return; } - virtual uint32_t TlvSize() const; - virtual void TlvClear(); - virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; - virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); - virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - std::map keySignSet; // mandatory -}; - - diff --git a/libretroshare/src/serialiser/rstlvkeyvalue.cc b/libretroshare/src/serialiser/rstlvkeyvalue.cc deleted file mode 100644 index c666307ef..000000000 --- a/libretroshare/src/serialiser/rstlvkeyvalue.cc +++ /dev/null @@ -1,295 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvkeyvalue.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie,Chris Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "rstlvkeyvalue.h" -#include "rstlvbase.h" - -// #define TLV_DEBUG 1 - -void RsTlvKeyValue::TlvClear() -{ - key = ""; - value = ""; -} - -uint32_t RsTlvKeyValue::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header */ - - /* now add comment and title length of this tlv object */ - - if (key.length() > 0) - s += GetTlvStringSize(key); - if (value.length() > 0) - s += GetTlvStringSize(value); - - return s; - -} - -bool RsTlvKeyValue::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_KEYVALUE, tlvsize); - - - - /* now optional ones */ - if (key.length() > 0) - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEY, key); // no base tlv type for title? - if (value.length() > 0) - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_VALUE, value); // no base tlv type for comment? - -return ok; - -} - -bool RsTlvKeyValue::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_KEYVALUE) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - /* while there is TLV */ - while((*offset) + 2 < tlvend) - { - /* get the next type */ - uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - - switch(tlvsubtype) - { - case TLV_TYPE_STR_KEY: - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEY, key); - break; - case TLV_TYPE_STR_VALUE: - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_VALUE, value); - break; - default: - ok &= SkipUnknownTlv(data, tlvend, offset); - break; - - } - - if (!ok) - { - break; - } - } - - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvKeyValue::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; - -} - -std::ostream &RsTlvKeyValue::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvKeyValue", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - out << "Key:" << key; - printIndent(out, int_Indent); - out << "Value:" << value; - out << std::endl; - - - printEnd(out, "RsTlvKeyValue", indent); - return out; -} - -/************************************* RsTlvKeyValueSet ************************************/ - -void RsTlvKeyValueSet::TlvClear() -{ - pairs.clear(); //empty list -} - -uint32_t RsTlvKeyValueSet::TlvSize() const -{ - - uint32_t s = TLV_HEADER_SIZE; /* header */ - - std::list::const_iterator it; - - if(!pairs.empty()) - { - - for(it = pairs.begin(); it != pairs.end() ; ++it) - s += it->TlvSize(); - - } - - return s; -} - -bool RsTlvKeyValueSet::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_KEYVALUESET , tlvsize); - - - if(!pairs.empty()) - { - std::list::const_iterator it; - - for(it = pairs.begin(); it != pairs.end() ; ++it) - ok &= it->SetTlv(data, size, offset); - } - - -return ok; - -} - - -bool RsTlvKeyValueSet::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_KEYVALUESET) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - /* while there is TLV */ - while((*offset) + 2 < tlvend) - { - /* get the next type */ - uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - - switch(tlvsubtype) - { - case TLV_TYPE_KEYVALUE: - { - RsTlvKeyValue kv; - ok &= kv.GetTlv(data, size, offset); - if (ok) - { - pairs.push_back(kv); - } - } - break; - default: - ok &= SkipUnknownTlv(data, tlvend, offset); - break; - - } - - if (!ok) - break; - } - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvKeyValueSet::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; -} - -/// prints out contents of RsTlvKeyValueSet -std::ostream &RsTlvKeyValueSet::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvKeyValue", indent); - - std::list::const_iterator it; - - for(it = pairs.begin(); it != pairs.end() ; ++it) - it->print(out, indent); - - printEnd(out, "RsTlvKeyValue", indent); - return out; -} - diff --git a/libretroshare/src/serialiser/rstlvkeyvalue.h b/libretroshare/src/serialiser/rstlvkeyvalue.h deleted file mode 100644 index 63cf3091f..000000000 --- a/libretroshare/src/serialiser/rstlvkeyvalue.h +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvkeyvalue.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie,Chris Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -/******************************************************************* - * These are the Compound TLV structures that must be (un)packed. - * - ******************************************************************/ - -#include "serialiser/rstlvitem.h" -#include - -class RsTlvKeyValue: public RsTlvItem -{ - public: - RsTlvKeyValue() { return; } - RsTlvKeyValue(const std::string& k,const std::string& v): key(k),value(v) {} -virtual ~RsTlvKeyValue() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - std::string key; /// Mandatory : For use in hash tables - std::string value; /// Mandatory : For use in hash tables -}; - -class RsTlvKeyValueSet: public RsTlvItem -{ - public: - RsTlvKeyValueSet() { return; } -virtual ~RsTlvKeyValueSet() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - std::list pairs; /// For use in hash tables -}; - - diff --git a/libretroshare/src/serialiser/rstlvlist.h b/libretroshare/src/serialiser/rstlvlist.h deleted file mode 100644 index 90c430ede..000000000 --- a/libretroshare/src/serialiser/rstlvlist.h +++ /dev/null @@ -1,138 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvlist.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvitem.h" - -#include - -// #define TLV_DEBUG_LIST 1 - -template class t_RsTlvList: public RsTlvItem -{ - public: - t_RsTlvList() {} - virtual ~t_RsTlvList() {} - - virtual uint32_t TlvSize() const - { - uint32_t size = TLV_HEADER_SIZE; - typename std::list::const_iterator it; - for(it = mList.begin();it != mList.end(); ++it) - { - size += it->TlvSize(); - } - return size; - } - virtual void TlvClear(){ mList.clear(); } - virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const - { - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - /* must check sizes */ - - if (size < tlvend) - { -#ifdef TLV_DEBUG_LIST - std::cerr << "RsTlvList::SetTlv() Not enough size"; - std::cerr << std::endl; -#endif - return false; /* not enough space */ - } - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE, tlvsize); - - typename std::list::const_iterator it; - for(it = mList.begin();it != mList.end(); ++it) - { - ok &= it->SetTlv(data,tlvend,offset) ; - } - return ok ; - } - virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset) - { - if (size < *offset + TLV_HEADER_SIZE) - { -#ifdef TLV_DEBUG_LIST - std::cerr << "RsTlvList::GetTlv() Not enough size"; - std::cerr << std::endl; -#endif - return false; - } - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - /* while there is TLV : 2 (type) + 4 (len) */ - while(ok && ((*offset) + 6 < tlvend)) - { - TLV_CLASS item; - ok &= item.GetTlv(data,tlvend,offset); - if (ok) - { - mList.push_back(item); - } - } - - if(*offset != tlvend) - { - std::cerr << "(EE) deserialisation error in " << __PRETTY_FUNCTION__ << std::endl; - } - return *offset == tlvend ; - } - - virtual std::ostream &print(std::ostream &out, uint16_t indent) const - { - printBase(out, "Template TlvList", indent); - typename std::list::const_iterator it; - for(it = mList.begin();it != mList.end(); ++it) - { - it->print(out, indent + 2) ; - } - printEnd(out, "Template TlvList", indent); - return out ; - } - - std::list mList; -}; - - - diff --git a/libretroshare/src/serialiser/rstlvmaps.h b/libretroshare/src/serialiser/rstlvmaps.h deleted file mode 100644 index 49b05e382..000000000 --- a/libretroshare/src/serialiser/rstlvmaps.h +++ /dev/null @@ -1,34 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvmaps.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_TLV_MAPS_H -#define RS_TLV_MAPS_H - -class RsTlvOpinionMapRef: public RsTlvGenericMapRef -{ -public: - RsTlvOpinionMapRef(std::map &refmap) - :RsTlvGenericMapRef(OPINION, STRING_INT_PAIR, refmap) { return; } -}; - - -#endif - diff --git a/libretroshare/src/serialiser/rstlvstring.cc b/libretroshare/src/serialiser/rstlvstring.cc deleted file mode 100644 index d1e636d52..000000000 --- a/libretroshare/src/serialiser/rstlvstring.cc +++ /dev/null @@ -1,371 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvstring.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie,Chris Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "serialiser/rstlvstring.h" - -#include "serialiser/rstlvbase.h" -#include "util/rsprint.h" -#include - -// #define TLV_DEBUG 1 - -/************************************* Peer Id Set ************************************/ - - -RsTlvStringSet::RsTlvStringSet(uint16_t type) :mType(type) -{ -} - - -bool RsTlvStringSet::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, mType , tlvsize); - - /* determine the total size of ids strings in list */ - - std::list::const_iterator it; - - for(it = ids.begin(); it != ids.end() ; ++it) - { - if (it->length() > 0) - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_GENID, *it); - } - - return ok; - -} - - -void RsTlvStringSet::TlvClear() -{ - ids.clear(); - -} - -uint32_t RsTlvStringSet::TlvSize() const -{ - - uint32_t s = TLV_HEADER_SIZE; /* header */ - - /* determine the total size of ids strings in list */ - - std::list::const_iterator it; - - for(it = ids.begin(); it != ids.end() ; ++it) - { - if (it->length() > 0) - s += GetTlvStringSize(*it); - } - - return s; -} - - -bool RsTlvStringSet::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != mType) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - - -/* while there is TLV */ - while((*offset) + 2 < tlvend) - { - /* get the next type */ - uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - - if (tlvsubtype == TLV_TYPE_STR_GENID) - { - std::string newIds; - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_GENID, newIds); - if(ok) - { - ids.push_back(newIds); - - } - } - else - { - /* Step past unknown TLV TYPE */ - ok &= SkipUnknownTlv(data, tlvend, offset); - } - - if (!ok) - { - break; - } - } - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvPeerIdSet::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; -} - -/// print to screen RsTlvStringSet contents -std::ostream &RsTlvStringSet::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvStringSet", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - out << "type:" << mType; - out << std::endl; - - std::list::const_iterator it; - for(it = ids.begin(); it != ids.end() ; ++it) - { - printIndent(out, int_Indent); - out << "id:" << *it; - out << std::endl; - } - - printEnd(out, "RsTlvStringSet", indent); - return out; - -} - -/// print to screen RsTlvStringSet contents -std::ostream &RsTlvStringSet::printHex(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvStringSet", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - out << "type:" << mType; - out << std::endl; - - std::list::const_iterator it; - for(it = ids.begin(); it != ids.end() ; ++it) - { - printIndent(out, int_Indent); - out << "id: 0x" << RsUtil::BinToHex(*it); - out << std::endl; - } - - printEnd(out, "RsTlvStringSet", indent); - return out; - -} - - -/************************************* String Set Ref ************************************/ -/* This is exactly the same as StringSet, but it uses an alternative list. - */ -RsTlvStringSetRef::RsTlvStringSetRef(uint16_t type, std::list &refids) - :mType(type), ids(refids) -{ -} - -void RsTlvStringSetRef::TlvClear() -{ - ids.clear(); - -} - -uint32_t RsTlvStringSetRef::TlvSize() const -{ - - uint32_t s = TLV_HEADER_SIZE; /* header */ - - /* determine the total size of ids strings in list */ - - std::list::const_iterator it; - - for(it = ids.begin(); it != ids.end() ; ++it) - { - if (it->length() > 0) - s += GetTlvStringSize(*it); - } - - return s; -} - - -bool RsTlvStringSetRef::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, mType , tlvsize); - - /* determine the total size of ids strings in list */ - - std::list::const_iterator it; - - for(it = ids.begin(); it != ids.end() ; ++it) - { - if (it->length() > 0) - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_GENID, *it); - } - - return ok; - -} - - -bool RsTlvStringSetRef::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != mType) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - - -/* while there is TLV */ - while((*offset) + 2 < tlvend) - { - /* get the next type */ - uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - - if (tlvsubtype == TLV_TYPE_STR_GENID) - { - std::string newIds; - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_GENID, newIds); - if(ok) - { - ids.push_back(newIds); - - } - } - else - { - /* Step past unknown TLV TYPE */ - ok &= SkipUnknownTlv(data, tlvend, offset); - } - - if (!ok) - { - break; - } - } - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvPeerIdSetRef::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; -} - -/// print to screen RsTlvStringSet contents -std::ostream &RsTlvStringSetRef::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvStringSetRef", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - out << "type:" << mType; - out << std::endl; - - std::list::const_iterator it; - for(it = ids.begin(); it != ids.end() ; ++it) - { - printIndent(out, int_Indent); - out << "id:" << *it; - out << std::endl; - } - - printEnd(out, "RsTlvStringSetRef", indent); - return out; - -} - diff --git a/libretroshare/src/serialiser/rstlvstring.h b/libretroshare/src/serialiser/rstlvstring.h deleted file mode 100644 index 5e0c2f276..000000000 --- a/libretroshare/src/serialiser/rstlvstring.h +++ /dev/null @@ -1,64 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstlvstring.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Robert Fernie,Chris Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -/******************************************************************* - * These are the Compound TLV structures that must be (un)packed. - * - ******************************************************************/ - -#include "serialiser/rstlvitem.h" - -#include - -class RsTlvStringSet: public RsTlvItem -{ - public: -explicit RsTlvStringSet(uint16_t type); -virtual ~RsTlvStringSet() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; -virtual std::ostream &printHex(std::ostream &out, uint16_t indent) const; - - uint16_t mType; - std::list ids; /* Mandatory */ -}; - -class RsTlvStringSetRef: public RsTlvItem -{ - public: - RsTlvStringSetRef(uint16_t type, std::list &refids); -virtual ~RsTlvStringSetRef() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - uint16_t mType; - std::list &ids; /* Mandatory */ -}; - - diff --git a/libretroshare/src/serialiser/rstypeserializer.cc b/libretroshare/src/serialiser/rstypeserializer.cc deleted file mode 100644 index 0c7bfc435..000000000 --- a/libretroshare/src/serialiser/rstypeserializer.cc +++ /dev/null @@ -1,712 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstypeserializer.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2017 Cyril Soler * - * Copyright (C) 2018-2020 Gioacchino Mazzurco * - * Copyright (C) 2020 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "serialiser/rsserializer.h" -#include "serialiser/rstypeserializer.h" -#include "serialiser/rsbaseserial.h" -#include "serialiser/rstlvkeys.h" -#include "serialiser/rsserializable.h" -#include "util/rsbase64.h" -#include "util/rsprint.h" -#include "util/rstime.h" - -#include -#include -#include // for typeid -#include - -#ifdef RSSERIAL_DEBUG -# define SAFE_GET_JSON_V() \ - const char* mName = memberName.c_str(); \ - bool ret = jDoc.HasMember(mName); \ - if(!ret) \ - { \ - std::cerr << __PRETTY_FUNCTION__ << " \"" << memberName \ - << "\" not found in JSON:" << std::endl \ - << jDoc << std::endl << std::endl; \ - return false; \ - } \ - rapidjson::Value& v = jDoc[mName] -#else // ifdef RSSERIAL_DEBUG -# define SAFE_GET_JSON_V() \ - const char* mName = memberName.c_str(); \ - bool ret = jDoc.HasMember(mName); \ - if(!ret) return false; \ - rapidjson::Value& v = jDoc[mName] -#endif // ifdef RSSERIAL_DEBUG - -//============================================================================// -// std::string // -//============================================================================// - -template<> /*static*/ -bool RsTypeSerializer::to_JSON( const std::string& membername, - const std::string& member, RsJson& jDoc ) -{ - rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); - - rapidjson::Value key; - key.SetString( membername.c_str(), - static_cast(membername.length()), - allocator ); - - rapidjson::Value value; - value.SetString( member.c_str(), - static_cast(member.length()), - allocator ); - - jDoc.AddMember(key, value, allocator); - - return true; -} -template<> /*static*/ -bool RsTypeSerializer::from_JSON( const std::string& memberName, - std::string& member, RsJson& jDoc ) -{ - SAFE_GET_JSON_V(); - ret = ret && v.IsString(); - if(ret) member = v.GetString(); - return ret; -} - - -//============================================================================// -// Integral types // -//============================================================================// - -#define SIMPLE_TO_JSON_DEF(T) \ -template<> bool RsTypeSerializer::to_JSON( const std::string& memberName, \ - const T& member, RsJson& jDoc ) \ -{ \ - rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); \ - \ - rapidjson::Value key; \ - key.SetString( memberName.c_str(), \ - static_cast(memberName.length()), \ - allocator ); \ - \ - rapidjson::Value value(member); \ - \ - jDoc.AddMember(key, value, allocator); \ - \ - return true; \ -} - -SIMPLE_TO_JSON_DEF(bool) -SIMPLE_TO_JSON_DEF(int32_t) - -SIMPLE_TO_JSON_DEF(uint8_t) -SIMPLE_TO_JSON_DEF(uint16_t) -SIMPLE_TO_JSON_DEF(uint32_t) - -/** Be very careful in changing this constant as it would break 64 bit integers - * members JSON string representation retrocompatibility */ -static constexpr char strReprKey[] = "xstr64"; - -/** Be very careful in changing this constant as it would break 64 bit integers - * members JSON string representation retrocompatibility */ -static constexpr char intReprKey[] = "xint64"; - -/** While JSON doesn't have problems representing 64 bits integers JavaScript, - * Dart and other languages represents numbers in a double-like format thus they - * are not capable to handle safely integers outside the range - * [-(2^53 - 1), 2^53 - 1]. - * To overcome this limitation we represent 64 bit integers as an object with - * two keys, one as integer and one as string representation. - * In our case we need to wrap those into an object instead of just adding a key - * with a suffix so support well also containers like std::map or std::vector. - * More discussion on the topic at @see https://stackoverflow.com/a/34989371 - */ -#define SIXTYFOUR_INTEGERS_TO_JSON_DEF(T) \ -template<> bool RsTypeSerializer::to_JSON( const std::string& memberName, \ - const T& member, RsJson& jDoc ) \ -{ \ - using namespace rapidjson; \ - Document::AllocatorType& allocator = jDoc.GetAllocator(); \ - \ - Document wrapper(rapidjson::kObjectType, &allocator); \ - \ - Value intKey; \ - intKey.SetString(intReprKey, allocator ); \ - Value intValue(member); \ - wrapper.AddMember(intKey, intValue, allocator); \ - \ - bool ok = to_JSON(strReprKey, std::to_string(member), wrapper); \ - \ - Value key; \ - key.SetString( memberName.c_str(), \ - static_cast(memberName.length()), \ - allocator ); \ - jDoc.AddMember(key, wrapper, allocator); \ - \ - return ok; \ -} - -SIXTYFOUR_INTEGERS_TO_JSON_DEF(int64_t); -SIXTYFOUR_INTEGERS_TO_JSON_DEF(uint64_t); - -template<> /*static*/ -bool RsTypeSerializer::from_JSON( const std::string& memberName, bool& member, - RsJson& jDoc ) -{ - SAFE_GET_JSON_V(); - ret = ret && v.IsBool(); - if(ret) member = v.GetBool(); - return ret; -} - -template<> /*static*/ -bool RsTypeSerializer::from_JSON( const std::string& memberName, - int32_t& member, RsJson& jDoc ) -{ - SAFE_GET_JSON_V(); - ret = ret && v.IsInt(); - if(ret) member = v.GetInt(); - return ret; -} - -template<> /*static*/ -bool RsTypeSerializer::from_JSON( const std::string& memberName, - uint8_t& member, RsJson& jDoc ) -{ - SAFE_GET_JSON_V(); - ret = ret && v.IsUint(); - if(ret) member = static_cast(v.GetUint()); - return ret; -} - -template<> /*static*/ -bool RsTypeSerializer::from_JSON( const std::string& memberName, - uint16_t& member, RsJson& jDoc ) -{ - SAFE_GET_JSON_V(); - ret = ret && v.IsUint(); - if(ret) member = static_cast(v.GetUint()); - return ret; -} - -template<> /*static*/ -bool RsTypeSerializer::from_JSON( const std::string& memberName, - uint32_t& member, RsJson& jDoc ) -{ - SAFE_GET_JSON_V(); - ret = ret && v.IsUint(); - if(ret) member = v.GetUint(); - return ret; -} - -/** inverse of @see SIXTYFOUR_INTEGERS_TO_JSON_DEF */ -#define SIXTYFOUR_INTEGERS_FROM_JSON_DEF(T, PRED, GET, CONV) \ -template<> bool RsTypeSerializer::from_JSON( \ - const std::string& memberName, T& member, RsJson& jDoc ) \ -{ \ - using namespace rapidjson; \ - \ - SAFE_GET_JSON_V(); \ - \ - /* For retro-compatibility take it directly if it is passed as integer */ \ - if(v.PRED()) \ - { \ - member = v.GET(); \ - return true; \ - } \ - \ - ret = ret && v.IsObject(); \ - \ - if(!ret) \ - { \ - RS_DBG3(memberName, " not found"); \ - return false; \ - } \ - \ - if(v.HasMember(intReprKey)) \ - { \ - Value& iVal = v[intReprKey]; \ - if(iVal.PRED()) \ - { \ - member = iVal.GET(); \ - return true; \ - } \ - } \ - \ - Dbg4() << __PRETTY_FUNCTION__ << " integer representation of " << memberName \ - << " not found in JSON then attempt to look for string representation" \ - << std::endl; \ - \ - \ - if(v.HasMember(strReprKey)) \ - { \ - Value& sVal = v[strReprKey]; \ - if(sVal.IsString()) \ - { \ - try { member = CONV(sVal.GetString()); } \ - catch (...) \ - { \ - RsErr() << __PRETTY_FUNCTION__ << " cannot convert " \ - << sVal.GetString() << " to integral type" << std::endl; \ - return false; \ - } \ - \ - return true; \ - } \ - } \ - \ - Dbg3() << __PRETTY_FUNCTION__ << " neither integral representation nor " \ - << "string representation found for: " << memberName << std::endl; \ - \ - return false; \ -} - -SIXTYFOUR_INTEGERS_FROM_JSON_DEF(uint64_t, IsUint64, GetUint64, std::stoull) -SIXTYFOUR_INTEGERS_FROM_JSON_DEF( int64_t, IsInt64, GetInt64, std::stoll) - -//============================================================================// -// Floats // -//============================================================================// - -template<> uint32_t RsTypeSerializer::serial_size(const float&){ return 4; } - -template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t& offset, const float& f) -{ - return setRawUFloat32(data,size,&offset,f) ; -} -template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size, uint32_t &offset, float& f) -{ - return getRawUFloat32(data,size,&offset,f) ; -} -template<> void RsTypeSerializer::print_data(const std::string& n, const float& V) -{ - std::cerr << " [float ] " << n << ": " << V << std::endl; -} - -SIMPLE_TO_JSON_DEF(float) - -template<> /*static*/ -bool RsTypeSerializer::from_JSON( const std::string& memberName, - float& member, RsJson& jDoc ) -{ - SAFE_GET_JSON_V(); - ret = ret && v.IsFloat(); - if(ret) member = v.GetFloat(); - return ret; -} - -template<> /*static*/ -uint32_t RsTypeSerializer::serial_size(const double&) -{ - std::cerr << "Binary [de]serialization not implemented yet for double" - << std::endl; - print_stacktrace(); - return 0; -} - -template<> /*static*/ -bool RsTypeSerializer::serialize(uint8_t[], uint32_t, uint32_t&, const double&) -{ - std::cerr << "Binary [de]serialization not implemented yet for double" - << std::endl; - print_stacktrace(); - return false; -} - -template<> /*static*/ -bool RsTypeSerializer::deserialize(const uint8_t[], uint32_t, uint32_t&, double&) -{ - std::cerr << "Binary [de]serialization not implemented yet for double" - << std::endl; - print_stacktrace(); - return false; -} - -template<> /*static*/ -void RsTypeSerializer::print_data(const std::string& n, const double& V) -{ std::cerr << " [double ] " << n << ": " << V << std::endl; } - -SIMPLE_TO_JSON_DEF(double) - -template<> /*static*/ -bool RsTypeSerializer::from_JSON( const std::string& memberName, - double& member, RsJson& jDoc ) -{ - SAFE_GET_JSON_V(); - ret = ret && v.IsDouble(); - if(ret) member = v.GetDouble(); - return ret; -} - - -//============================================================================// -// TlvString with subtype // -//============================================================================// - -template<> uint32_t RsTypeSerializer::serial_size(uint16_t /* type_subtype */,const std::string& s) -{ - return GetTlvStringSize(s) ; -} - -template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, uint32_t &offset,uint16_t type_substring,const std::string& s) -{ - return SetTlvString(data,size,&offset,type_substring,s) ; -} - -template<> bool RsTypeSerializer::deserialize(const uint8_t data[], uint32_t size,uint32_t& offset,uint16_t type_substring,std::string& s) -{ - return GetTlvString((void*)data,size,&offset,type_substring,s) ; -} - -template<> void RsTypeSerializer::print_data(const std::string& n, uint16_t type_substring,const std::string& V) -{ - std::cerr << " [TlvString ] " << n << ": type=" << std::hex < /*static*/ -bool RsTypeSerializer::to_JSON( const std::string& memberName, - uint16_t /*sub_type*/, - const std::string& member, RsJson& jDoc ) -{ - return to_JSON(memberName, member, jDoc); -} - -template<> /*static*/ -bool RsTypeSerializer::from_JSON( const std::string& memberName, - uint16_t /*sub_type*/, - std::string& member, RsJson& jDoc ) -{ - return from_JSON(memberName, member, jDoc); -} - -//============================================================================// -// TlvInt with subtype // -//============================================================================// - -template<> uint32_t RsTypeSerializer::serial_size( uint16_t /* type_subtype */, - const uint32_t& /*s*/ ) -{ - return GetTlvUInt32Size(); -} - -template<> bool RsTypeSerializer::serialize( uint8_t data[], uint32_t size, - uint32_t &offset,uint16_t sub_type, - const uint32_t& s) -{ - return SetTlvUInt32(data,size,&offset,sub_type,s); -} - -template<> bool RsTypeSerializer::deserialize( const uint8_t data[], - uint32_t size, uint32_t& offset, - uint16_t sub_type, uint32_t& s) -{ - return GetTlvUInt32((void*)data, size, &offset, sub_type, &s); -} - -template<> void RsTypeSerializer::print_data(const std::string& n, uint16_t sub_type,const uint32_t& V) -{ - std::cerr << " [TlvUInt32 ] " << n << ": type=" << std::hex - << std::setw(4) << std::setfill('0') << sub_type << std::dec - << " s=\"" << V << "\"" << std::endl; -} - -template<> /*static*/ -bool RsTypeSerializer::to_JSON( const std::string& memberName, - uint16_t /*sub_type*/, - const uint32_t& member, RsJson& jDoc ) -{ - return to_JSON(memberName, member, jDoc); -} - -template<> /*static*/ -bool RsTypeSerializer::from_JSON( const std::string& memberName, - uint16_t /*sub_type*/, - uint32_t& member, RsJson& jDoc ) -{ - return from_JSON(memberName, member, jDoc); -} - - -//============================================================================// -// TlvItems // -//============================================================================// - -template<> uint32_t RsTypeSerializer::serial_size(const RsTlvItem& s) -{ - return s.TlvSize(); -} - -template<> bool RsTypeSerializer::serialize(uint8_t data[], uint32_t size, - uint32_t &offset,const RsTlvItem& s) -{ - return s.SetTlv(data,size,&offset); -} - -template<> bool RsTypeSerializer::deserialize(const uint8_t data[], - uint32_t size,uint32_t& offset, - RsTlvItem& s) -{ - return s.GetTlv((void*)data,size,&offset) ; -} - -template<> void RsTypeSerializer::print_data( const std::string& n, - const RsTlvItem& s ) -{ - std::cerr << " [" << typeid(s).name() << "] " << n << std::endl; -} - -template<> /*static*/ -bool RsTypeSerializer::to_JSON( const std::string& memberName, - const RsTlvItem& member, RsJson& jDoc ) -{ - rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); - - rapidjson::Value key; - key.SetString(memberName.c_str(), memberName.length(), allocator); - - rapidjson::Value value; - const char* tName = typeid(member).name(); - value.SetString(tName, allocator); - - jDoc.AddMember(key, value, allocator); - - return true; -} - -template<> /*static*/ -bool RsTypeSerializer::from_JSON( const std::string& /*memberName*/, - RsTlvItem& member, RsJson& /*jDoc*/) -{ - member.TlvClear(); - return true; -} - - -//============================================================================// -// Binary blocks // -//============================================================================// - -#if __cplusplus < 201703L -/* Solve weird undefined reference error with C++ < 17 see: - * https://stackoverflow.com/questions/8016780/undefined-reference-to-static-constexpr-char - */ -/*static*/ decltype(RsTypeSerializer::RawMemoryWrapper::base64_key) constexpr -RsTypeSerializer::RawMemoryWrapper::base64_key; - -/*static*/ /* without this Android compilation breaks */ -constexpr uint32_t RsTypeSerializer::RawMemoryWrapper::MAX_SERIALIZED_CHUNK_SIZE; -#endif - -/*static*/ -void RsTypeSerializer::RawMemoryWrapper::serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: - RS_SERIAL_PROCESS(second); - ctx.mOffset += second; - break; - case RsGenericSerializer::SERIALIZE: - if(!ctx.mOk) break; - if(second > MAX_SERIALIZED_CHUNK_SIZE) - { - RsErr() << __PRETTY_FUNCTION__ - << std::errc::message_size << " " - << second << " > " << MAX_SERIALIZED_CHUNK_SIZE - << std::endl; - print_stacktrace(); - break; - } - RS_SERIAL_PROCESS(second); - if(!ctx.mOk) break; - ctx.mOk = ctx.mSize >= ctx.mOffset + second; - if(!ctx.mOk) - { - RsErr() << __PRETTY_FUNCTION__ << std::errc::no_buffer_space - << std::endl; - print_stacktrace(); - break; - } - memcpy(ctx.mData + ctx.mOffset, first, second); - ctx.mOffset += second; - break; - case RsGenericSerializer::DESERIALIZE: - freshMemCheck(); - - RS_SERIAL_PROCESS(second); - if(!ctx.mOk) break; - ctx.mOk = (second <= MAX_SERIALIZED_CHUNK_SIZE); - if(!ctx.mOk) - { - RsErr() << __PRETTY_FUNCTION__ - << std::errc::message_size << " " - << second << " > " << MAX_SERIALIZED_CHUNK_SIZE - << std::endl; - clear(); - break; - } - - if(!second) - { - Dbg3() << __PRETTY_FUNCTION__ << " Deserialized empty memory chunk" - << std::endl; - clear(); - break; - } - - ctx.mOk = ctx.mSize >= ctx.mOffset + second; - if(!ctx.mOk) - { - RsErr() << __PRETTY_FUNCTION__ << std::errc::no_buffer_space - << std::endl; - print_stacktrace(); - - clear(); - break; - } - - first = reinterpret_cast(malloc(second)); - memcpy(first, ctx.mData + ctx.mOffset, second); - ctx.mOffset += second; - break; - case RsGenericSerializer::PRINT: break; - case RsGenericSerializer::TO_JSON: - { - if(!ctx.mOk) break; - std::string encodedValue; - RsBase64::encode(first, second, encodedValue, true, false); - ctx.mOk = ctx.mOk && - RsTypeSerializer::to_JSON(base64_key, encodedValue, ctx.mJson); - break; - } - case RsGenericSerializer::FROM_JSON: - { - freshMemCheck(); - - const auto failure = [&]() -> void { ctx.mOk = false; clear(); }; - const bool yielding = !!( - RsSerializationFlags::YIELDING & ctx.mFlags ); - if(!(ctx.mOk || yielding)) return failure(); - - std::string encodedValue; - if(!RsTypeSerializer::from_JSON( - base64_key, encodedValue, ctx.mJson )) return failure(); - - if( encodedValue.length() > - RsBase64::encodedSize(MAX_SERIALIZED_CHUNK_SIZE, true) ) - { - RsErr() << __PRETTY_FUNCTION__ << " " - << std::errc::message_size << std::endl; - print_stacktrace(); - - return failure(); - } - - std::vector decoded; - auto ec = RsBase64::decode(encodedValue, decoded); - if(ec) - { - RsErr() << __PRETTY_FUNCTION__ << " " << ec << std::endl; - print_stacktrace(); - - return failure(); - } - - const auto decodedSize = decoded.size(); - - if(!decodedSize) - { - clear(); - break; - } - - first = reinterpret_cast(malloc(decodedSize)); - second = static_cast(decodedSize); - - memcpy(first, decoded.data(), second); - break; - } - default: RsTypeSerializer::fatalUnknownSerialJob(j); - } -} - -void RsTypeSerializer::RawMemoryWrapper::clear() -{ - free(first); - first = nullptr; - second = 0; -} - -bool RsTypeSerializer::RawMemoryWrapper::freshMemCheck() -{ - if(first || second) - { - /* Items are created anew before deserialization so buffer pointer - * must be null and size 0 at this point */ - - RsWarn() << __PRETTY_FUNCTION__ << " got uninitialized " - << " or pre-allocated buffer! Buffer pointer: " << first - << " must be null and size: " << second << " must be 0 at " - << "this point. Does your item costructor initialize them " - << "properly?" << std::endl; - print_stacktrace(); - return false; - } - return true; -} - -//============================================================================// -// std::error_condition // -//============================================================================// - -void RsTypeSerializer::ErrConditionWrapper::serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: // fallthrough - case RsGenericSerializer::DESERIALIZE: // fallthrough - case RsGenericSerializer::SERIALIZE: // fallthrough - case RsGenericSerializer::FROM_JSON: // [[fallthrough]] - case RsGenericSerializer::PRINT: - RsFatal() << __PRETTY_FUNCTION__ << " SerializeJob: " << j - << "is not supported on std::error_condition " << std::endl; - print_stacktrace(); - exit(-2); - case RsGenericSerializer::TO_JSON: - { - constexpr RsGenericSerializer::SerializeJob rj = - RsGenericSerializer::TO_JSON; - - int32_t tNum = mec.value(); - RsTypeSerializer::serial_process(rj, ctx, tNum, "errorNumber"); - - std::string tStr = mec.category().name(); - RsTypeSerializer::serial_process(rj, ctx, tStr, "errorCategory"); - - tStr = mec.message(); - RsTypeSerializer::serial_process(rj, ctx, tStr, "errorMessage"); - break; - } - default: RsTypeSerializer::fatalUnknownSerialJob(j); - } -} diff --git a/libretroshare/src/serialiser/rstypeserializer.h b/libretroshare/src/serialiser/rstypeserializer.h deleted file mode 100644 index 6474f6971..000000000 --- a/libretroshare/src/serialiser/rstypeserializer.h +++ /dev/null @@ -1,1369 +0,0 @@ -/******************************************************************************* - * libretroshare/src/serialiser: rstypeserializer.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2017 Cyril Soler * - * Copyright (C) 2018-2020 Gioacchino Mazzurco * - * Copyright (C) 2020 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include // for typeid -#include -#include -#include -#include -#include - -#include "serialiser/rsserial.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvlist.h" -#include "retroshare/rsflags.h" -#include "retroshare/rsids.h" -#include "util/rsendian.h" -#include "serialiser/rsserializer.h" -#include "serialiser/rsserializable.h" -#include "util/rsjson.h" -#include "util/rsdebuglevel1.h" -#include "util/cxx14retrocompat.h" - - -struct RsTypeSerializer -{ - /** Use this wrapper to serialize raw memory chunks - * RsTypeSerializer::RawMemoryWrapper chunkWrapper(chunk_data, chunk_size); - * RsTypeSerializer::serial_process(j, ctx, chunkWrapper, "chunk_data"); - **/ - struct RawMemoryWrapper: std::pair, RsSerializable - { - RawMemoryWrapper(uint8_t*& p,uint32_t& s) : - std::pair(p,s) {} - RawMemoryWrapper(void*& p, uint32_t& s) : - std::pair(*(uint8_t**)(&p),s) {} - - /// Maximum supported size 10MB - static constexpr uint32_t MAX_SERIALIZED_CHUNK_SIZE = 10*1024*1024; - - /** Key used for JSON serialization. - * @note Changing this value breaks JSON API retro-compatibility */ - static constexpr char base64_key[] = "base64"; - - /// @see RsSerializable - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override; - private: - void clear(); - bool freshMemCheck(); - }; - - /// Most types are not valid sequence containers - template - struct is_sequence_container : std::false_type {}; - - /// Trait to match supported strings types - template - struct is_string : std::is_same, std::string> {}; - - /// Integral types - template - typename std::enable_if::value>::type - static /*void*/ serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx, - INTT& member, const std::string& member_name ) - { - const bool VLQ_ENCODING = !!( - RsSerializationFlags::INTEGER_VLQ & ctx.mFlags ); - - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: - if(VLQ_ENCODING) ctx.mOffset += VLQ_size(member); - else ctx.mOffset += sizeof(INTT); - break; - case RsGenericSerializer::SERIALIZE: - { - if(!ctx.mOk) break; - if(VLQ_ENCODING) - ctx.mOk = VLQ_serialize( - ctx.mData, ctx.mSize, ctx.mOffset, member ); - else - { - ctx.mOk = ctx.mSize >= ctx.mOffset + sizeof(INTT); - if(!ctx.mOk) - { - RsErr() << __PRETTY_FUNCTION__ << " Cannot serialise " - << typeid(INTT).name() << " " - << " ctx.mSize: " << ctx.mSize - << " ctx.mOffset: " << ctx.mOffset - << " sizeof(INTT): " << sizeof(INTT) - << std::error_condition(std::errc::no_buffer_space) - << std::endl; - print_stacktrace(); - break; - } - INTT netorder_num = rs_endian_fix(member); - memcpy(ctx.mData + ctx.mOffset, &netorder_num, sizeof(INTT)); - ctx.mOffset += sizeof(INTT); - } - break; - } - case RsGenericSerializer::DESERIALIZE: - if(!ctx.mOk) break; - if(VLQ_ENCODING) ctx.mOk = VLQ_deserialize( - ctx.mData, ctx.mSize, ctx.mOffset, member ); - else - { - ctx.mOk = ctx.mSize >= ctx.mOffset + sizeof(INTT); - if(!ctx.mOk) - { - RsErr() << __PRETTY_FUNCTION__ << " Cannot deserialise " - << typeid(INTT).name() << " " - << " ctx.mSize: " << ctx.mSize - << " ctx.mOffset: " << ctx.mOffset - << " sizeof(INTT): " << sizeof(INTT) - << std::error_condition(std::errc::no_buffer_space) - << std::endl; - print_stacktrace(); - exit(-1); - break; - } - memcpy(&member, ctx.mData + ctx.mOffset, sizeof(INTT)); - member = rs_endian_fix(member); - ctx.mOffset += sizeof(INTT); - } - break; - case RsGenericSerializer::PRINT: break; - case RsGenericSerializer::TO_JSON: - ctx.mOk = ctx.mOk && to_JSON(member_name, member, ctx.mJson); - break; - case RsGenericSerializer::FROM_JSON: - ctx.mOk &= ( ctx.mOk || - !!(RsSerializationFlags::YIELDING & ctx.mFlags) ) - && from_JSON(member_name, member, ctx.mJson); - break; - default: fatalUnknownSerialJob(j); - } - } - -//============================================================================// -// Generic types // -//============================================================================// - - template - typename - std::enable_if< std::is_same::value || !( - std::is_integral::value || - std::is_base_of::value || - std::is_enum::value || - std::is_base_of::value || - std::is_same::value || - is_sequence_container::value || is_string::value ) >::type - static /*void*/ serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx, - T& memberC, const std::string& member_name ) - { - // Avoid problems with const sneaking into template paramether - using m_t = std::remove_const_t; - m_t& member = const_cast(memberC); - - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: - ctx.mOffset += serial_size(member); - break; - case RsGenericSerializer::DESERIALIZE: - ctx.mOk = ctx.mOk && - deserialize(ctx.mData,ctx.mSize,ctx.mOffset,member); - break; - case RsGenericSerializer::SERIALIZE: - ctx.mOk = ctx.mOk && - serialize(ctx.mData,ctx.mSize,ctx.mOffset,member); - break; - case RsGenericSerializer::PRINT: - print_data(member_name,member); - break; - case RsGenericSerializer::TO_JSON: - ctx.mOk = ctx.mOk && to_JSON(member_name, member, ctx.mJson); - break; - case RsGenericSerializer::FROM_JSON: - ctx.mOk &= ( ctx.mOk || - !!(ctx.mFlags & RsSerializationFlags::YIELDING) ) - && from_JSON(member_name, member, ctx.mJson); - break; - default: fatalUnknownSerialJob(j); - } - } - -//============================================================================// -// Generic types + type_id // -//============================================================================// - - /// Generic types + type_id - template RS_DEPRECATED - static void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx, - uint16_t type_id, T& member, const std::string& member_name ) - { - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: - ctx.mOffset += serial_size(type_id,member); - break; - case RsGenericSerializer::DESERIALIZE: - ctx.mOk = ctx.mOk && - deserialize(ctx.mData,ctx.mSize,ctx.mOffset,type_id,member); - break; - case RsGenericSerializer::SERIALIZE: - ctx.mOk = ctx.mOk && - serialize(ctx.mData,ctx.mSize,ctx.mOffset,type_id,member); - break; - case RsGenericSerializer::PRINT: break; - case RsGenericSerializer::TO_JSON: - ctx.mOk = ctx.mOk && - to_JSON(member_name, type_id, member, ctx.mJson); - break; - case RsGenericSerializer::FROM_JSON: - ctx.mOk &= - (ctx.mOk || !!(ctx.mFlags & RsSerializationFlags::YIELDING)) - && from_JSON(member_name, type_id, member, ctx.mJson); - break; - default: fatalUnknownSerialJob(j); - } - } - -//============================================================================// -// std::map // -//============================================================================// - - /// std::map - template - static void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx, - std::map& member, - const std::string& memberName ) - { - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: // [[falltrough]] - case RsGenericSerializer::SERIALIZE: - { - uint32_t mapSize = member.size(); - RS_SERIAL_PROCESS(mapSize); - - for( auto it = member.begin(); - ctx.mOk && it != member.end(); ++it ) - { - RS_SERIAL_PROCESS(const_cast(it->first)); - RS_SERIAL_PROCESS(const_cast(it->second)); - } - break; - } - case RsGenericSerializer::DESERIALIZE: - { - uint32_t mapSize = 0; - RS_SERIAL_PROCESS(mapSize); - - for(uint32_t i=0; ctx.mOk && i(memberName.length()), allocator ); - Value arr(kArrayType); - - for (auto& kv : member) - { - // Use same allocator to avoid deep copy - RsGenericSerializer::SerializeContext kCtx( - nullptr, 0, ctx.mFlags, &allocator ); - serial_process(j, kCtx, const_cast(kv.first), "key"); - - RsGenericSerializer::SerializeContext vCtx( - nullptr, 0, ctx.mFlags, &allocator ); - serial_process(j, vCtx, const_cast(kv.second), "value"); - - if(kCtx.mOk && vCtx.mOk) - { - Value el(kObjectType); - el.AddMember("key", kCtx.mJson["key"], allocator); - el.AddMember("value", vCtx.mJson["value"], allocator); - - arr.PushBack(el, allocator); - } - } - - ctx.mJson.AddMember(arrKey, arr, allocator); - - break; - } - case RsGenericSerializer::FROM_JSON: - { - using namespace rapidjson; - - bool ok = ctx.mOk || !!(ctx.mFlags & RsSerializationFlags::YIELDING); - Document& jDoc(ctx.mJson); - Document::AllocatorType& allocator = jDoc.GetAllocator(); - - Value arrKey; - arrKey.SetString( memberName.c_str(), - static_cast(memberName.length()) ); - - ok = ok && jDoc.IsObject(); - ok = ok && jDoc.HasMember(arrKey); - - if(ok && jDoc[arrKey].IsArray()) - { - for (auto&& kvEl : jDoc[arrKey].GetArray()) - { - ok = ok && kvEl.IsObject(); - ok = ok && kvEl.HasMember("key"); - ok = ok && kvEl.HasMember("value"); - if (!ok) break; - - RsGenericSerializer::SerializeContext kCtx( - nullptr, 0, ctx.mFlags, &allocator ); - if(ok) - kCtx.mJson.AddMember("key", kvEl["key"], allocator); - - T key; - ok = ok && (serial_process(j, kCtx, key, "key"), kCtx.mOk); - - RsGenericSerializer::SerializeContext vCtx( - nullptr, 0, ctx.mFlags, &allocator ); - if(ok) - vCtx.mJson.AddMember("value", kvEl["value"], allocator); - - U value; - ok = ok && ( serial_process(j, vCtx, value, "value"), - vCtx.mOk ); - - ctx.mOk &= ok; - if(ok) member.insert(std::pair(key,value)); - else break; - } - } - else ctx.mOk = false; - break; - } - default: fatalUnknownSerialJob(j); - } - } - - -//============================================================================// -// std::pair // -//============================================================================// - - /// std::pair - template - static void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx, - std::pair& member, const std::string& memberName ) - { - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: // [[fallthrough]] - case RsGenericSerializer::DESERIALIZE: // [[fallthrough]] - case RsGenericSerializer::SERIALIZE: // [[fallthrough]] - case RsGenericSerializer::PRINT: - RS_SERIAL_PROCESS(member.first); - RS_SERIAL_PROCESS(member.second); - break; - case RsGenericSerializer::TO_JSON: - { - RsJson& jDoc(ctx.mJson); - RsJson::AllocatorType& allocator = jDoc.GetAllocator(); - - // Reuse allocator to avoid deep copy later - RsGenericSerializer::SerializeContext lCtx( - nullptr, 0, ctx.mFlags, &allocator ); - - serial_process(j, lCtx, member.first, "first"); - serial_process(j, lCtx, member.second, "second"); - - rapidjson::Value key; - key.SetString( memberName.c_str(), - static_cast(memberName.length()), - allocator); - - /* Because the passed allocator is reused it doesn't go out of scope - * and there is no need of deep copy and we can take advantage of - * the much faster rapidjson move semantic */ - jDoc.AddMember(key, lCtx.mJson, allocator); - - ctx.mOk = ctx.mOk && lCtx.mOk; - break; - } - case RsGenericSerializer::FROM_JSON: - { - RsJson& jDoc(ctx.mJson); - const char* mName = memberName.c_str(); - bool hasMember = jDoc.HasMember(mName); - bool yielding = !!(ctx.mFlags & RsSerializationFlags::YIELDING); - - if(!hasMember) - { - if(!yielding) - { - RsErr() << __PRETTY_FUNCTION__ << " \"" << memberName - << "\" not found in JSON" << std::endl; - print_stacktrace(); - } - ctx.mOk = false; - break; - } - - rapidjson::Value& v = jDoc[mName]; - - RsGenericSerializer::SerializeContext lCtx(nullptr, 0, ctx.mFlags); - lCtx.mJson.SetObject() = v; // Beware of move semantic!! - - serial_process(j, lCtx, member.first, "first"); - serial_process(j, lCtx, member.second, "second"); - ctx.mOk &= lCtx.mOk; - - break; - } - default: fatalUnknownSerialJob(j); - } - } - -//============================================================================// -// Sequence containers // -//============================================================================// - - /** std::list is supported */ template - struct is_sequence_container>: std::true_type {}; - - /** std::set is supported */ template - struct is_sequence_container>: std::true_type {}; - - /** std::vector is supported */ template - struct is_sequence_container>: std::true_type {}; - - - /// STL compatible sequence containers std::list, std::set, std::vector... - template - typename std::enable_if::value>::type - static serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx, - T& member, const std::string& memberName ) - { - using el_t = typename T::value_type; - - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: // [[falltrough]]; - case RsGenericSerializer::SERIALIZE: - { - uint32_t aSize = member.size(); - RS_SERIAL_PROCESS(aSize); - for(auto it = member.begin(); it != member.end(); ++it) - { - if(!ctx.mOk) break; - RS_SERIAL_PROCESS(*it); - } - break; - } - case RsGenericSerializer::DESERIALIZE: - { - uint32_t elCount = 0; - RS_SERIAL_PROCESS(elCount); - if(!ctx.mOk) break; - - /* This check is not perfect but will catch most pathological cases. - * Avoid multiplying by sizeof(el_t) as it is not a good estimation - * of the actual serialized size, depending on the elements - * structure and on the so it would raises many false positives. - * Arithmetic operations on elCount are also at risk of overflow */ - if(elCount > RsSerialiser::MAX_SERIAL_SIZE) - { - ctx.mOk = false; - RsErr() << __PRETTY_FUNCTION__ << " attempt to deserialize a " - << "sequence with apparently malformed elements count." - << " elCount: " << elCount - << " ctx.mSize: " << ctx.mSize - << " ctx.mOffset: " << ctx.mOffset << " " - << std::errc::argument_out_of_domain - << std::endl; - print_stacktrace(); - break; - } - - for(uint32_t i=0; ctx.mOk && i < elCount; ++i ) - { - el_t elem; - RS_SERIAL_PROCESS(elem); - member.insert(member.end(), elem); - } - break; - } - case RsGenericSerializer::PRINT: break; - case RsGenericSerializer::TO_JSON: - { - using namespace rapidjson; - - Document::AllocatorType& allocator = ctx.mJson.GetAllocator(); - - Value arrKey; arrKey.SetString(memberName.c_str(), allocator); - Value arr(kArrayType); - - for(auto& const_el : member) - { - auto el = const_cast(const_el); - - /* Use same allocator to avoid deep copy */ - RsGenericSerializer::SerializeContext elCtx( - nullptr, 0, ctx.mFlags, &allocator ); - serial_process(j, elCtx, el, memberName); - - elCtx.mOk = elCtx.mOk && elCtx.mJson.HasMember(arrKey); - if(elCtx.mOk) arr.PushBack(elCtx.mJson[arrKey], allocator); - else - { - ctx.mOk = false; - break; - } - } - - ctx.mJson.AddMember(arrKey, arr, allocator); - break; - } - case RsGenericSerializer::FROM_JSON: - { - using namespace rapidjson; - - bool ok = ctx.mOk || !!(ctx.mFlags & RsSerializationFlags::YIELDING); - Document& jDoc(ctx.mJson); - Document::AllocatorType& allocator = jDoc.GetAllocator(); - - Value arrKey; - arrKey.SetString( memberName.c_str(), - static_cast(memberName.length()) ); - - ok = ok && jDoc.IsObject() && jDoc.HasMember(arrKey) - && jDoc[arrKey].IsArray(); - if(!ok) { ctx.mOk = false; break; } - - for (auto&& arrEl : jDoc[arrKey].GetArray()) - { - Value arrKeyT; - arrKeyT.SetString( - memberName.c_str(), - static_cast(memberName.length()) ); - - RsGenericSerializer::SerializeContext elCtx( - nullptr, 0, ctx.mFlags, &allocator ); - elCtx.mJson.AddMember(arrKeyT, arrEl, allocator); - - el_t el; - serial_process(j, elCtx, el, memberName); - ok = ok && elCtx.mOk; - ctx.mOk &= ok; - if(ok) member.insert(member.end(), el); - else break; - } - - break; - } - default: fatalUnknownSerialJob(j); - } - } - -//============================================================================// -// Strings // -//============================================================================// - - /// Strings - template - typename std::enable_if::value>::type - static serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx, - T& memberC, - const std::string& memberName ) - { - // Avoid problems with const sneaking into template paramether - using m_t = std::remove_const_t; - m_t& member = const_cast(memberC); - - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: - { - uint32_t aSize = static_cast(member.size()); - RS_SERIAL_PROCESS(aSize); - ctx.mOffset += aSize; - break; - } - case RsGenericSerializer::SERIALIZE: - { - uint32_t len = static_cast(member.length()); - RS_SERIAL_PROCESS(len); - if(len + ctx.mOffset > ctx.mSize) - { - RsErr() << __PRETTY_FUNCTION__ << std::errc::no_buffer_space - << std::endl; - ctx.mOk = false; - } - memcpy(ctx.mData + ctx.mOffset, member.c_str(), len); - ctx.mOffset += len; - break; - } - case RsGenericSerializer::DESERIALIZE: - { - uint32_t len; - RS_SERIAL_PROCESS(len); - if(!ctx.mOk) break; - - if(len > RsSerialiser::MAX_SERIAL_SIZE) - { - ctx.mOk = false; - RsErr() << __PRETTY_FUNCTION__ << " attempt to deserialize a " - << "string with apparently malformed length." - << " len: " << len - << " ctx.mSize: " << ctx.mSize - << " ctx.mOffset: " << ctx.mOffset << " " - << std::errc::argument_out_of_domain << std::endl; - print_stacktrace(); - break; - } - - if(len + ctx.mOffset > ctx.mSize) - { - ctx.mOk = false; - RsErr() << __PRETTY_FUNCTION__ << " attempt to deserialize a " - << "string with a length bigger available data." - << " len: " << len - << " ctx.mSize: " << ctx.mSize - << " ctx.mOffset: " << ctx.mOffset << " " - << std::errc::no_buffer_space << std::endl; - print_stacktrace(); - break; - } - - member.resize(len); - memcpy(&member[0], ctx.mData + ctx.mOffset, len); - ctx.mOffset += len; - break; - } - case RsGenericSerializer::PRINT: break; - case RsGenericSerializer::TO_JSON: - ctx.mOk = ctx.mOk && to_JSON(memberName, member, ctx.mJson); - break; - case RsGenericSerializer::FROM_JSON: - { - bool ok = ctx.mOk || !!( - ctx.mFlags & RsSerializationFlags::YIELDING ); - ctx.mOk = ok && from_JSON(memberName, member, ctx.mJson) && ctx.mOk; - break; - } - default: fatalUnknownSerialJob(j); - } - } - - /// t_RsFlags32<> types - template - static void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx, - t_RsFlags32& v, - const std::string& memberName ) - { serial_process(j, ctx, v._bits, memberName); } - - /** - * @brief serial process enum types - * On declaration of your member of enum type you must specify the - * underlying type otherwise the serialization format may differ in an - * uncompatible way depending on the compiler/platform. - */ - template - typename std::enable_if::value>::type - static /*void*/ serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx, - E& member, - const std::string& memberName ) - { - RS_DBG4( "processing enum: ", typeid(E).name(), " as ", - typeid(typename std::underlying_type::type).name() ); - - serial_process( - j, ctx, - reinterpret_cast::type&>(member), - memberName ); - } - - /// RsSerializable and derivatives - template - typename std::enable_if::value>::type - static serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx, - T& memberC, const std::string& memberName ) - { - using m_t = std::remove_const_t; - m_t& member = const_cast(memberC); - - switch(j) - { - case RsGenericSerializer::SIZE_ESTIMATE: // fallthrough - case RsGenericSerializer::DESERIALIZE: // fallthrough - case RsGenericSerializer::SERIALIZE: // fallthrough - case RsGenericSerializer::PRINT: - member.serial_process(j, ctx); - break; - case RsGenericSerializer::TO_JSON: - { - rapidjson::Document& jDoc(ctx.mJson); - rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); - - // Reuse allocator to avoid deep copy later - RsGenericSerializer::SerializeContext lCtx( - nullptr, 0, ctx.mFlags, &allocator ); - - member.serial_process(j, lCtx); - - rapidjson::Value key; - key.SetString( - memberName.c_str(), - static_cast(memberName.length()), - allocator ); - - /* Because the passed allocator is reused it doesn't go out of scope - * and there is no need of deep copy and we can take advantage of - * the much faster rapidjson move semantic */ - jDoc.AddMember(key, lCtx.mJson, allocator); - - ctx.mOk = ctx.mOk && lCtx.mOk; - break; - } - case RsGenericSerializer::FROM_JSON: - { - RsJson& jDoc(ctx.mJson); - const char* mName = memberName.c_str(); - bool hasMember = jDoc.HasMember(mName); - bool yielding = !!(ctx.mFlags & RsSerializationFlags::YIELDING); - - if(!hasMember) - { - if(!yielding) - { - RsErr() << __PRETTY_FUNCTION__ << " \"" << memberName - << "\" not found in JSON:" << std::endl - << jDoc << std::endl << std::endl; - print_stacktrace(); - } - ctx.mOk = false; - break; - } - - rapidjson::Value& v = jDoc[mName]; - - if(!v.IsObject()) - { - RsErr() << __PRETTY_FUNCTION__ << " \"" << memberName - << "\" has wrong type in JSON, object expected, got:" - << std::endl << jDoc << std::endl << std::endl; - print_stacktrace(); - ctx.mOk = false; - break; - } - - RsGenericSerializer::SerializeContext lCtx(nullptr, 0, ctx.mFlags); - lCtx.mJson.SetObject() = v; // Beware of move semantic!! - - member.serial_process(j, lCtx); - ctx.mOk &= lCtx.mOk; - - break; - } - default: fatalUnknownSerialJob(j); - } - } - - /// RsTlvItem derivatives only - template - typename std::enable_if< - std::is_base_of::value && - !std::is_same::value >::type - static serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx, - T& member, const std::string& memberName ) - { serial_process(j, ctx, static_cast(member), memberName); } - - /** std::error_condition - * supports only TO_JSON ErrConditionWrapper::serial_process will explode - * at runtime if a different SerializeJob is passed down */ - template - typename std::enable_if< std::is_base_of::value >::type - static /*void*/ serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx, - T& cond, const std::string& member_name ) - { - ErrConditionWrapper ew(cond); - serial_process(j, ctx, ew, member_name); - } - - RS_DEPRECATED_FOR(RawMemoryWrapper) - typedef RawMemoryWrapper TlvMemBlock_proxy; - -protected: - -//============================================================================// -// Generic types declarations // -//============================================================================// - - template static bool serialize( - uint8_t data[], uint32_t size, uint32_t &offset, const T& member ); - - template static bool deserialize( - const uint8_t data[], uint32_t size, uint32_t &offset, T& member); - - template static uint32_t serial_size(const T& member); - - template static void print_data( - const std::string& name, const T& member); - - template static bool to_JSON( const std::string& membername, - const T& member, RsJson& jDoc ); - - template static bool from_JSON( const std::string& memberName, - T& member, RsJson& jDoc ); - -//============================================================================// -// Generic types + type_id declarations // -//============================================================================// - - template RS_DEPRECATED - static bool serialize( - uint8_t data[], uint32_t size, uint32_t &offset, uint16_t type_id, - const T& member ); - - template RS_DEPRECATED - static bool deserialize( - const uint8_t data[], uint32_t size, uint32_t &offset, - uint16_t type_id, T& member ); - - template RS_DEPRECATED - static uint32_t serial_size(uint16_t type_id,const T& member); - - template RS_DEPRECATED - static void print_data( - const std::string& n, uint16_t type_id,const T& member ); - - template RS_DEPRECATED - static bool to_JSON( - const std::string& membername, uint16_t type_id, - const T& member, RsJson& jVal ); - - template RS_DEPRECATED - static bool from_JSON( - const std::string& memberName, uint16_t type_id, - T& member, RsJson& jDoc ); - -//============================================================================// -// t_RsGenericId<...> declarations // -//============================================================================// - - template - static bool serialize( - uint8_t data[], uint32_t size, uint32_t &offset, - const t_RsGenericIdType& member ); - - template - static bool deserialize( - const uint8_t data[], uint32_t size, uint32_t &offset, - t_RsGenericIdType& member ); - - template - static uint32_t serial_size( - const t_RsGenericIdType< - ID_SIZE_IN_BYTES, UPPER_CASE, UNIQUE_IDENTIFIER>& member ); - - template - static void print_data( - const std::string& name, - const t_RsGenericIdType& member ); - - template - static bool to_JSON( - const std::string& membername, - const t_RsGenericIdType& member, - RsJson& jVal ); - - template - static bool from_JSON( - const std::string& memberName, - t_RsGenericIdType& member, - RsJson& jDoc ); - -//============================================================================// -// t_RsTlvList<...> declarations // -//============================================================================// - - template - static bool serialize( - uint8_t data[], uint32_t size, uint32_t &offset, - const t_RsTlvList& member ); - - template - static bool deserialize( - const uint8_t data[], uint32_t size, uint32_t &offset, - t_RsTlvList& member ); - - template - static uint32_t serial_size(const t_RsTlvList& member); - - template - static void print_data( - const std::string& name, - const t_RsTlvList& member); - - template - static bool to_JSON( const std::string& membername, - const t_RsTlvList& member, - RsJson& jVal ); - - template - static bool from_JSON( const std::string& memberName, - t_RsTlvList& member, - RsJson& jDoc ); - -//============================================================================// -// Integral types VLQ // -//============================================================================// - - /** - * Size calculation of unsigned integers as Variable Lenght Quantity - * @see RsSerializationFlags::INTEGER_VLQ - * @see https://en.wikipedia.org/wiki/Variable-length_quantity - * @see https://golb.hplar.ch/2019/06/variable-length-int-java.html - * @see https://techoverflow.net/2013/01/25/efficiently-encoding-variable-length-integers-in-cc/ - */ - template static - std::enable_if_t>::value, uint32_t> - VLQ_size(T member) - { - std::decay_t memberBackup = member; - uint32_t ret = 1; -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wbool-compare" - while(member > 127) { ++ret; member >>= 7; } -#pragma GCC diagnostic pop - Dbg2() << __PRETTY_FUNCTION__ << " memberBackup: " << memberBackup - << " return: " << ret << std::endl; - return ret; - } - - /** - * Serialization of unsigned integers as Variable Lenght Quantity - * @see RsSerializationFlags::INTEGER_VLQ - * @see https://en.wikipedia.org/wiki/Variable-length_quantity - * @see https://golb.hplar.ch/2019/06/variable-length-int-java.html - * @see https://techoverflow.net/2013/01/25/efficiently-encoding-variable-length-integers-in-cc/ - */ - template static - std::enable_if_t>::value, bool> - VLQ_serialize( - uint8_t data[], uint32_t size, uint32_t &offset, T member ) - { - std::decay_t backupMember = member; -#if RS_DEBUG_LEVEL >= 3 - uint32_t offsetBackup = offset; -#endif - - bool ok = true; -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wbool-compare" - /* Check with < and not with <= here as we write last byte after - * the loop. Order of && operands very important here! */ - while(member > 127 && (ok = (offset < size))) - { - // | 128: Set the next byte flag - data[offset++] = (static_cast(member & 127)) | 128; - // Remove the seven bits we just wrote - member >>= 7; - } -#pragma GCC diagnostic pop - - if(!(ok = ok && offset <= size)) - { - RsErr() << __PRETTY_FUNCTION__ << " Cannot serialise " - << typeid(T).name() - << " member " << member - << " size: " << size - << " offset: " << offset - << " backupMember: " << backupMember - << std::error_condition(std::errc::no_buffer_space) - << std::endl; - print_stacktrace(); - return false; - } - - data[offset++] = static_cast(member & 127); - -#if RS_DEBUG_LEVEL >= 3 - RsDbg tdbg( __PRETTY_FUNCTION__, " backupMember: ", backupMember, - " offsetBackup: ", offsetBackup, " offeset: ", offset, - " serialized as: " ); - for(; offsetBackup < offset; ++offsetBackup) - tdbg << " " << std::bitset<8>(data[offsetBackup]); -#endif - return ok; - } - - /** - * Deserialization for unsigned integers as Variable Lenght Quantity - * @see RsSerializationFlags::INTEGER_VLQ - * @see https://en.wikipedia.org/wiki/Variable-length_quantity - * @see https://golb.hplar.ch/2019/06/variable-length-int-java.html - * @see https://techoverflow.net/2013/01/25/efficiently-encoding-variable-length-integers-in-cc/ - */ - template static - std::enable_if_t>::value, bool> - VLQ_deserialize( - const uint8_t data[], uint32_t size, uint32_t& offset, T& member ) - { - member = 0; - uint32_t offsetBackup = offset; - - /* In a reasonable VLQ coding representing an integer - * could take at maximum sizeof(integer) + 1 space, if it is - * not the case something fishy is happening. */ - for (size_t i = 0; offset < size && i <= sizeof(T); ++i) - { - member |= (data[offset] & 127) << (7 * i); - // If the next-byte flag is not set. ++ is after on purpose - if(!(data[offset++] & 128)) - { - Dbg2() << __PRETTY_FUNCTION__ - << " size: " << size - << " backupOffset " << offsetBackup - << " offset: " << offset - << " member " << member << std::endl; - return true; - } - } - - /* If return is not triggered inside the for loop, either the buffer - * ended before we encountered the end of the number, or the number - * is VLQ encoded improperly */ - RsErr rserr; - rserr << __PRETTY_FUNCTION__ << std::errc::illegal_byte_sequence - << " size: " << size - << " offsetBackup: " << offsetBackup - << " offset: " << offset << " bytes: "; - for(; offsetBackup < offset; ++offsetBackup) - rserr << " " << std::bitset<8>(data[offsetBackup]); - print_stacktrace(); - - return false; - } - - /** - * Size calculation of signed integers as Variable Lenght Quantity - * @see RsSerializationFlags::INTEGER_VLQ - * @see https://en.wikipedia.org/wiki/Variable-length_quantity#Zigzag_encoding - * @see https://golb.hplar.ch/2019/06/variable-length-int-java.html - */ - template static - std::enable_if_t>::value, uint32_t> - VLQ_size(T member) - { - member = (member << 1) ^ (member >> (sizeof(T)-1)); // ZigZag encoding - return VLQ_size( - static_cast::type>(member)); - } - - /** - * Serialization of signed integers as Variable Lenght Quantity - * @see RsSerializationFlags::INTEGER_VLQ - * @see https://en.wikipedia.org/wiki/Variable-length_quantity#Zigzag_encoding - * @see https://golb.hplar.ch/2019/06/variable-length-int-java.html - */ - template static - std::enable_if_t>::value, bool> - VLQ_serialize( - uint8_t data[], uint32_t size, uint32_t &offset, T member ) - { - member = (member << 1) ^ (member >> (sizeof(T)-1)); // ZigZag encoding - return VLQ_serialize( - data, size, offset, - static_cast::type>(member)); - } - - /** - * Deserialization for signed integers as Variable Lenght Quantity - * @see RsSerializationFlags::INTEGER_VLQ - * @see https://en.wikipedia.org/wiki/Variable-length_quantity#Zigzag_encoding - * @see https://golb.hplar.ch/2019/06/variable-length-int-java.html - */ - template static - std::enable_if_t>::value, bool> - VLQ_deserialize( - const uint8_t data[], uint32_t size, uint32_t& offset, T& member ) - { - using DT = std::decay_t; - typename std::make_unsigned
::type temp = 0; - bool ok = VLQ_deserialize(data, size, offset, temp); - // ZizZag decoding - member = (static_cast
(temp) >> 1) ^ -(static_cast
(temp) & 1); - return ok; - } - -//============================================================================// -// Error Condition Wrapper // -//============================================================================// - - struct ErrConditionWrapper : RsSerializable - { - explicit ErrConditionWrapper(const std::error_condition& ec): mec(ec) {} - - /** supports only TO_JSON if a different SerializeJob is passed it will - * explode at runtime */ - void serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override; - - private: - const std::error_condition& mec; - }; - -//============================================================================// -// Miscellanea // -//============================================================================// - - [[noreturn]] static void fatalUnknownSerialJob(int j) - { - RsFatal() << " Unknown serial job: " << j << std::endl; - print_stacktrace(); - exit(EINVAL); - } - - RS_SET_CONTEXT_DEBUG_LEVEL(1) -}; - - -//============================================================================// -// t_RsGenericId<...> // -//============================================================================// - -template -bool RsTypeSerializer::serialize ( - uint8_t data[], uint32_t size, uint32_t &offset, - const t_RsGenericIdType< - ID_SIZE_IN_BYTES, UPPER_CASE, UNIQUE_IDENTIFIER>& member ) -{ - return (*const_cast *>(&member) - ).serialise(data, size, offset); -} - -template -bool RsTypeSerializer::deserialize( - const uint8_t data[], uint32_t size, uint32_t &offset, - t_RsGenericIdType& member ) -{ return member.deserialise(data, size, offset); } - -template -uint32_t RsTypeSerializer::serial_size( - const t_RsGenericIdType& member ) -{ return member.serial_size(); } - -template -void RsTypeSerializer::print_data( - const std::string& /*name*/, - const t_RsGenericIdType& member ) -{ - std::cerr << " [RsGenericId<" << std::hex - << static_cast(UNIQUE_IDENTIFIER) << ">] : " - << member << std::endl; -} - -template -bool RsTypeSerializer::to_JSON( - const std::string& memberName, - const t_RsGenericIdType& member, - RsJson& jDoc ) -{ - rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); - - rapidjson::Value key; - key.SetString(memberName.c_str(), memberName.length(), allocator); - - const std::string vStr = member.toStdString(); - rapidjson::Value value; - value.SetString(vStr.c_str(), vStr.length(), allocator); - - jDoc.AddMember(key, value, allocator); - - return true; -} - -template -bool RsTypeSerializer::from_JSON( - const std::string& membername, - t_RsGenericIdType& member, - RsJson& jVal ) -{ - const char* mName = membername.c_str(); - bool ret = jVal.HasMember(mName); - if(ret) - { - rapidjson::Value& v = jVal[mName]; - ret = ret && v.IsString(); - if(ret) member = - t_RsGenericIdType( - std::string(v.GetString()) ); - } - return ret; -} - -//============================================================================// -// t_RsTlvList<...> // -//============================================================================// - -template -bool RsTypeSerializer::serialize( - uint8_t data[], uint32_t size, uint32_t &offset, - const t_RsTlvList& member ) -{ - return (*const_cast *>(&member)).SetTlv(data,size,&offset); -} - -template -bool RsTypeSerializer::deserialize( - const uint8_t data[], uint32_t size, uint32_t &offset, - t_RsTlvList& member ) -{ - return member.GetTlv(const_cast(data),size,&offset); -} - -template -uint32_t RsTypeSerializer::serial_size( - const t_RsTlvList& member) -{ return member.TlvSize(); } - -template -void RsTypeSerializer::print_data( - const std::string& /*name*/, - const t_RsTlvList& member) -{ - std::cerr << " [t_RsTlvString<" << std::hex << TLV_TYPE << ">] : size=" - << member.mList.size() << std::endl; -} - -template /* static */ -bool RsTypeSerializer::to_JSON( const std::string& memberName, - const t_RsTlvList& member, - RsJson& jDoc ) -{ - rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); - - rapidjson::Value key; - key.SetString(memberName.c_str(), memberName.length(), allocator); - - rapidjson::Value value; - const char* tName = typeid(member).name(); - value.SetString(tName, allocator); - - jDoc.AddMember(key, value, allocator); - - std::cerr << __PRETTY_FUNCTION__ << " JSON serialization for type " - << typeid(member).name() << " " << memberName - << " not available." << std::endl; - print_stacktrace(); - return true; -} - -template -bool RsTypeSerializer::from_JSON( const std::string& memberName, - t_RsTlvList& member, - RsJson& /*jVal*/ ) -{ - std::cerr << __PRETTY_FUNCTION__ << " JSON deserialization for type " - << typeid(member).name() << " " << memberName - << " not available." << std::endl; - print_stacktrace(); - return true; -} - -//============================================================================// -// Not implemented types macros // -//============================================================================// - -/** - * @def RS_TYPE_SERIALIZER_TO_JSON_NOT_IMPLEMENTED_DEF(T) - * @def RS_TYPE_SERIALIZER_FROM_JSON_NOT_IMPLEMENTED_DEF(T) - * Helper macros for types that has not yet implemented to/from JSON - * should be deleted from the code as soon as they are not needed anymore - */ -#define RS_TYPE_SERIALIZER_TO_JSON_NOT_IMPLEMENTED_DEF(T) \ -template<> /*static*/ \ -bool RsTypeSerializer::to_JSON(const std::string& memberName, T const& member, \ - RsJson& jDoc ) \ -{ \ - rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); \ - \ - rapidjson::Value key; \ - key.SetString(memberName.c_str(), memberName.length(), allocator); \ - \ - rapidjson::Value value; \ - const char* tName = typeid(member).name(); \ - value.SetString(tName, allocator); \ - \ - jDoc.AddMember(key, value, allocator); \ - \ - std::cerr << __FILE__ << __LINE__ << __PRETTY_FUNCTION__ \ - << " JSON serialization for type " \ - << typeid(member).name() << " " << memberName \ - << " not available." << std::endl; \ - print_stacktrace(); \ - return true; \ -} - -#define RS_TYPE_SERIALIZER_FROM_JSON_NOT_IMPLEMENTED_DEF(T) \ -template<> /*static*/ \ -bool RsTypeSerializer::from_JSON( const std::string& memberName, \ - T& member, RsJson& /*jDoc*/ ) \ -{ \ - std::cerr << __FILE__ << __LINE__ << __PRETTY_FUNCTION__ \ - << " JSON deserialization for type " \ - << typeid(member).name() << " " << memberName \ - << " not available." << std::endl; \ - print_stacktrace(); \ - return true; \ -} diff --git a/libretroshare/src/services/autoproxy/p3i2psam3.cpp b/libretroshare/src/services/autoproxy/p3i2psam3.cpp deleted file mode 100644 index c9e77273e..000000000 --- a/libretroshare/src/services/autoproxy/p3i2psam3.cpp +++ /dev/null @@ -1,798 +0,0 @@ -#include "p3i2psam3.h" - -#include - -#include "pqi/p3peermgr.h" -#include "rsitems/rsconfigitems.h" - - -static const std::string kConfigKeySAM3Enable = "SAM3_ENABLE"; - -static const std::string kConfigKeyDestPriv = "DEST_PRIV"; - -static const std::string kConfigKeyInLength = "IN_LENGTH"; -static const std::string kConfigKeyInQuantity = "IN_QUANTITY"; -static const std::string kConfigKeyInVariance = "IN_VARIANCE"; -static const std::string kConfigKeyInBackupQuantity = "IN_BACKUPQUANTITY"; - -static const std::string kConfigKeyOutLength = "OUT_LENGTH"; -static const std::string kConfigKeyOutQuantity = "OUT_QUANTITY"; -static const std::string kConfigKeyOutVariance = "OUT_VARIANCE"; -static const std::string kConfigKeyOutBackupQuantity = "OUT_BACKUPQUANTITY"; - -#ifdef RS_I2P_SAM3_BOB_COMPAT -// used for migration from BOB to SAM -static const std::string kConfigKeyBOBEnable = "BOB_ENABLE"; -static const std::string kConfigKeyBOBKey = "BOB_KEY"; -static const std::string kConfigKeyBOBAddr = "BOB_ADDR"; -#endif - -static constexpr bool kDefaultSAM3Enable = false; - -RS_SET_CONTEXT_DEBUG_LEVEL(2) - -static void inline doSleep(std::chrono::duration> timeToSleepMS) { - std::this_thread::sleep_for(timeToSleepMS); -} - -p3I2pSam3::p3I2pSam3(p3PeerMgr *peerMgr) : - mConfigLoaded(false), mPeerMgr(peerMgr), mPending(), mLock("p3i2p-sam3") -#ifdef RS_USE_I2P_SAM3_LIBSAM3 - , mLockSam3Access("p3i2p-sam3-access") -#endif -{ - RS_DBG4(); - - // set defaults - mSetting.initDefault(); - mSetting.enable = kDefaultSAM3Enable; - mSetting.session = nullptr; - - libsam3_debug = 0; -} - -bool p3I2pSam3::isEnabled() -{ - RS_STACK_MUTEX(mLock); - return mSetting.enable; -} - -bool p3I2pSam3::initialSetup(std::string &addr, uint16_t &/*port*/) -{ - RS_DBG4(); - - RS_STACK_MUTEX(mLock); - - if (!mSetting.address.publicKey.empty() || !mSetting.address.privateKey.empty()) - RS_WARN("overwriting keys!"); - - bool success = generateKey(mSetting.address.publicKey, mSetting.address.privateKey); - - if (!success) { - RS_WARN("failed to retrieve keys"); - return false; - } else { - std::string s, c; - i2p::getKeyTypes(mSetting.address.publicKey, s, c); - RS_INFO("received key ", s, " ", c); - RS_INFO("public key: ", mSetting.address.publicKey); - RS_INFO("private key: ", mSetting.address.privateKey); - RS_INFO("address: ", i2p::keyToBase32Addr(mSetting.address.publicKey)); - - // sanity check - auto pub = i2p::publicKeyFromPrivate(mSetting.address.privateKey); - RS_INFO("pub key derived: ", pub); - RS_INFO("address: ", i2p::keyToBase32Addr(pub)); - if (pub != mSetting.address.publicKey) { - RS_WARN("public key does not match private key! fixing ..."); - mSetting.address.publicKey = pub; - } - - mSetting.address.base32 = i2p::keyToBase32Addr(mSetting.address.publicKey); - - IndicateConfigChanged(); - } - - addr = mSetting.address.base32; - return true; -} - -void p3I2pSam3::processTaskAsync(taskTicket *ticket) -{ - RS_DBG4(); - - switch (ticket->task) { - case autoProxyTask::stop: [[fallthrough]]; - case autoProxyTask::start: [[fallthrough]]; - case autoProxyTask::receiveKey: [[fallthrough]]; - case autoProxyTask::lookupKey: [[fallthrough]]; - case autoProxyTask::proxyStatusCheck: [[fallthrough]]; - case autoProxyTask::establishConnection: [[fallthrough]]; - case autoProxyTask::closeConnection: - { - RS_STACK_MUTEX(mLock); - mPending.push(ticket); - } - break; - case autoProxyTask::status: [[fallthrough]]; - case autoProxyTask::getSettings: [[fallthrough]]; - case autoProxyTask::setSettings: [[fallthrough]]; - case autoProxyTask::getErrorInfo: [[fallthrough]]; - case autoProxyTask::reloadConfig: - // These are supposed to be sync! - RS_DBG("unknown task or sync one!"); - rsAutoProxyMonitor::taskError(ticket); - break; - } -} - -void p3I2pSam3::processTaskSync(taskTicket *ticket) -{ -// RS_DBG4(); - - const bool data = !!ticket->data; - - switch (ticket->task) { - case autoProxyTask::status: - { - samStatus *ss = static_cast(ticket->data); - RS_STACK_MUTEX(mLock); - ss->state = mState; - if (mSetting.session) - ss->sessionName = mSetting.session->channel; - else - ss->sessionName = "none"; - } - rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok); - - break; - case autoProxyTask::getSettings: - // check if everything needed is set - if (!data) { - RS_DBG("autoProxyTask::getSettings data is missing"); - rsAutoProxyMonitor::taskError(ticket); - break; - } - - // get settings - { - RS_STACK_MUTEX(mLock); - *static_cast(ticket->data) = mSetting; - } - - // finish task - rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok); - break; - case autoProxyTask::setSettings: - // check if everything needed is set - if (!data) { - RS_DBG("autoProxyTask::setSettings data is missing"); - rsAutoProxyMonitor::taskError(ticket); - break; - } - - // set settings - { - RS_STACK_MUTEX(mLock); - mSetting = *static_cast(ticket->data); - updateSettings_locked(); - } - - // finish task - rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok); - break; - case autoProxyTask::getErrorInfo: - *static_cast(ticket->data) = mSetting.session->error; - rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok); - break; - case autoProxyTask::reloadConfig: - { - RS_STACK_MUTEX(mLock); - updateSettings_locked(); - } - rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok); - break; - case autoProxyTask::stop: -#if 0 // doesn't seem to work, socket stays "CLOSE_WAIT" - // there can be a case where libsam3 will block forever because for some reason it does not detect that the socket it has is dead - // as a workaroung kill it from here - if (mState == samStatus::samState::connectSession || mState == samStatus::samState::connectForward) { - // lock should be held by the main thread - if (!mTmpSession) { - // now it's getting weird - RS_WARN("session is nullptr but mState says it is connecting."); - // no break! just ignore for now ... - } else { - // just close it from here, libsam3 is not thread safe. - // a bit of a hack but should do the trick -// sam3CloseSession(mSetting.session); - sam3tcpDisconnect(mTmpSession->fd); - // no break! continue as usual to keep everything in line - } - } -#endif - [[fallthrough]]; - case autoProxyTask::start: [[fallthrough]]; - case autoProxyTask::receiveKey: [[fallthrough]]; - case autoProxyTask::lookupKey: [[fallthrough]]; - case autoProxyTask::proxyStatusCheck: [[fallthrough]]; - case autoProxyTask::establishConnection: [[fallthrough]]; - case autoProxyTask::closeConnection: - // These are supposed to be async! - RS_WARN("unknown task or async one!"); - rsAutoProxyMonitor::taskError(ticket); - break; - } -} - -void p3I2pSam3::threadTick() -{ -// { -// RS_STACK_MUTEX(mLock); -// Dbg4() << __PRETTY_FUNCTION__ << " mPending: " << mPending.size() << std::endl; -// } - - if(mPending.empty()) { - // sleep outisde of lock! - doSleep(std::chrono::milliseconds(250)); - return; - } - - // get task - taskTicket *tt = nullptr; - { - RS_STACK_MUTEX(mLock); - tt = mPending.front(); - mPending.pop(); - } - - switch (tt->task) { - case autoProxyTask::stop: - mState = samStatus::samState::offline; - stopForwarding(); - stopSession(); - rsAutoProxyMonitor::taskDone(tt, autoProxyStatus::offline); - break; - - case autoProxyTask::start: - { - if (!mSetting.enable) { - rsAutoProxyMonitor::taskDone(tt, autoProxyStatus::disabled); - break; - } - - // create main session - mState = samStatus::samState::connectSession; - bool ret = startSession(); - if (!ret) { - mState = samStatus::samState::offline; - - rsAutoProxyMonitor::taskError(tt); - break; - } - - // start forwarding - mState = samStatus::samState::connectForward; - ret = startForwarding(); - - // finish ticket - if (ret) { - mState = samStatus::samState::online; - rsAutoProxyMonitor::taskDone(tt, autoProxyStatus::online); - } else { - mState = samStatus::samState::offline; - rsAutoProxyMonitor::taskError(tt); - } - } - break; - - case autoProxyTask::receiveKey: - { - i2p::address *addr = static_cast(tt->data); - if (generateKey(addr->publicKey, addr->privateKey)) { - addr->base32 = i2p::keyToBase32Addr(addr->publicKey); - rsAutoProxyMonitor::taskDone(tt, autoProxyStatus::ok); - } else { - rsAutoProxyMonitor::taskError(tt); - } - } - break; - - case autoProxyTask::lookupKey: - lookupKey(tt); - break; - - case autoProxyTask::proxyStatusCheck: - { - // TODO better detection of status - bool ok; - ok = !!mSetting.session->fd; - ok &= !!mSetting.session->fwd_fd; - *static_cast(tt->data) = ok; - rsAutoProxyMonitor::taskDone(tt, ok ? autoProxyStatus::ok : autoProxyStatus::error); - } - break; - - case autoProxyTask::establishConnection: - establishConnection(tt); - break; - case autoProxyTask::closeConnection: - closeConnection(tt); - break; - case autoProxyTask::status: [[fallthrough]]; - case autoProxyTask::getSettings: [[fallthrough]]; - case autoProxyTask::setSettings: [[fallthrough]]; - case autoProxyTask::getErrorInfo: [[fallthrough]]; - case autoProxyTask::reloadConfig: - RS_ERR("unable to handle! This is a bug! task:", tt->task); - rsAutoProxyMonitor::taskError(tt); - break; - } - tt = nullptr; - - // give i2p backend some time - doSleep(std::chrono::milliseconds(100)); -} - -RsSerialiser *p3I2pSam3::setupSerialiser() -{ - RsSerialiser* rsSerialiser = new RsSerialiser(); - rsSerialiser->addSerialType(new RsGeneralConfigSerialiser()); - - return rsSerialiser; -} - -#define addKVS(_key, _value) \ - kv.key = _key;\ - kv.value = _value;\ - vitem->tlvkvs.pairs.push_back(kv); - -#define addKVSInt(_key, _value) \ - kv.key = _key;\ - rs_sprintf(kv.value, "%d", _value);\ - vitem->tlvkvs.pairs.push_back(kv); - -bool p3I2pSam3::saveList(bool &cleanup, std::list &lst) -{ - RS_DBG4(); - - cleanup = true; - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet; - RsTlvKeyValue kv; - - RS_STACK_MUTEX(mLock); - addKVS(kConfigKeySAM3Enable, mSetting.enable ? "TRUE" : "FALSE") - addKVS(kConfigKeyDestPriv, mSetting.address.privateKey); - - addKVSInt(kConfigKeyInLength, mSetting.inLength) - addKVSInt(kConfigKeyInQuantity, mSetting.inQuantity) - addKVSInt(kConfigKeyInVariance, mSetting.inVariance) - addKVSInt(kConfigKeyInBackupQuantity, mSetting.inBackupQuantity) - - addKVSInt(kConfigKeyOutLength, mSetting.outLength) - addKVSInt(kConfigKeyOutQuantity, mSetting.outQuantity) - addKVSInt(kConfigKeyOutVariance, mSetting.outVariance) - addKVSInt(kConfigKeyOutBackupQuantity, mSetting.outBackupQuantity) - -#ifdef RS_I2P_SAM3_BOB_COMPAT - // these allow SAMv3 users to switch back to BOB - // remove after some time - addKVS(kConfigKeyBOBEnable, mSetting.enable ? "TRUE" : "FALSE") - addKVS(kConfigKeyBOBKey, mSetting.address.privateKey) - addKVS(kConfigKeyBOBAddr, mSetting.address.base32) -#endif - lst.push_back(vitem); - return true; -} - -#undef addKVS -#undef addKVSUInt - -#define getKVSUInt(_kit, _key, _value) \ - else if (_kit->key == _key) {\ - std::istringstream is(_kit->value);\ - int tmp;\ - is >> tmp;\ - _value = (int8_t)tmp;\ - } - -bool p3I2pSam3::loadList(std::list &load) -{ - RS_DBG4(); - - std::string priv; - priv.clear(); - - for(std::list::const_iterator it = load.begin(); it!=load.end(); ++it) { - RsConfigKeyValueSet *vitem = dynamic_cast(*it); - if(vitem != NULL) { - RS_STACK_MUTEX(mLock); - for(std::list::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) { - if (kit->key == kConfigKeySAM3Enable) - mSetting.enable = kit->value == "TRUE"; - else if (kit->key == kConfigKeyDestPriv) - priv = kit->value; - getKVSUInt(kit, kConfigKeyInLength, mSetting.inLength) - getKVSUInt(kit, kConfigKeyInQuantity, mSetting.inQuantity) - getKVSUInt(kit, kConfigKeyInVariance, mSetting.inVariance) - getKVSUInt(kit, kConfigKeyInBackupQuantity, mSetting.inBackupQuantity) - - getKVSUInt(kit, kConfigKeyOutLength, mSetting.outLength) - getKVSUInt(kit, kConfigKeyOutQuantity, mSetting.outQuantity) - getKVSUInt(kit, kConfigKeyOutVariance, mSetting.outVariance) - getKVSUInt(kit, kConfigKeyOutBackupQuantity, mSetting.outBackupQuantity) - -#ifdef RS_I2P_SAM3_BOB_COMPAT - // import BOB settings - else if (kit->key == kConfigKeyBOBEnable) - mSetting.enable = kit->value == "TRUE"; - else if (kit->key == kConfigKeyBOBKey) { - // don't overwirte, just import when not set already! - if (priv.empty()) - priv = kit->value; - } -#endif - else - RS_INFO("unknown key:", kit->key); - } - } - delete vitem; - } - - // get the pub key - std::string pub = i2p::publicKeyFromPrivate(priv); - if (pub.empty() || priv.empty()) - RS_DBG("no destination to load"); - else { - RS_STACK_MUTEX(mLock); - - mSetting.address.publicKey = pub; - mSetting.address.privateKey = priv; - mSetting.address.base32 = i2p::keyToBase32Addr(pub); - } - - RS_STACK_MUTEX(mLock); - mConfigLoaded = true; - - return true; -} - -#undef getKVSUInt - -bool p3I2pSam3::startSession() -{ - RS_DBG4(); - - constexpr size_t len = 8; - const std::string location = RsRandom::alphaNumeric(len); - const std::string nick = "RetroShare-" + location; - - std::vector params; - { - RS_STACK_MUTEX(mLock); - - // length - params.push_back(i2p::makeOption("inbound.length", mSetting.inLength)); - params.push_back(i2p::makeOption("outbound.length", mSetting.outLength)); - // variance - params.push_back(i2p::makeOption("inbound.lengthVariance", + mSetting.inVariance)); - params.push_back(i2p::makeOption("outbound.lengthVariance", + mSetting.outVariance)); - // quantity - params.push_back(i2p::makeOption("inbound.quantity", + mSetting.inQuantity)); - params.push_back(i2p::makeOption("outbound.quantity", + mSetting.outQuantity)); - // backup quantity - params.push_back(i2p::makeOption("inbound.backupQuantity", + mSetting.inBackupQuantity)); - params.push_back(i2p::makeOption("outbound.backupQuantity", + mSetting.outBackupQuantity)); - } - - std::string paramsStr; - for (auto &&p : params) - paramsStr.append(p + " "); - // keep trailing space for easier extending when necessary - - int ret; - - if (mSetting.session) { - stopSession(); - } - - auto session = (Sam3Session*)rs_malloc(sizeof (Sam3Session)); - - // add nick - paramsStr.append("inbound.nickname=" + nick); // leading space is already there - - { - RS_STACK_MUTEX(mLockSam3Access); - - if(!mSetting.address.privateKey.empty()) { - RS_DBG3("with destination"); - ret = sam3CreateSession(session, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT, mSetting.address.privateKey.c_str(), Sam3SessionType::SAM3_SESSION_STREAM, Sam3SigType::EdDSA_SHA512_Ed25519, paramsStr.c_str()); - } else { - RS_DBG("without destination"); - ret = sam3CreateSession(session, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT, SAM3_DESTINATION_TRANSIENT, Sam3SessionType::SAM3_SESSION_STREAM, Sam3SigType::EdDSA_SHA512_Ed25519, paramsStr.c_str()); - } - } - - if (ret != 0) { - delete session; - session = nullptr; - return false; - } - -#if 0 // this check is useless. For non i2p hidden locations the public key is temporal anyway and for i2p hidden ones, it is part of the (fixed) private key. - if (!mSetting.address.publicKey.empty() && mSetting.address.publicKey != session->pubkey) - // This should be ok for non hidden locations. This should be a problem for hidden i2p locations... - RS_DBG("public key changed! Yet unsure if this is ok or a problem. Should be fine for non i2p hidden locations or clear net."); -#endif - /* - * Note: sam3CreateSession will issue a name looup of "ME" to receive its public key, thus it is always correct. - * No need to use i2p::publicKeyFromPrivate() - */ - RS_STACK_MUTEX(mLock); - mSetting.session = session; - mSetting.address.publicKey = session->pubkey; - mSetting.address.base32 = i2p::keyToBase32Addr(session->pubkey); - // do not overwrite the private key, if any!! - - RS_DBG1("nick: ", nick, " address: ", mSetting.address.base32); - RS_DBG2(" myDestination.pub ", mSetting.address.publicKey); - RS_DBG2(" myDestination.priv ", mSetting.address.privateKey); - return true; -} - -bool p3I2pSam3::startForwarding() -{ - RS_DBG4(); - - if(mSetting.address.privateKey.empty()) { - RS_DBG3("no private key set"); - // IMPORANT: return true here! - // since there is no forward session for non hidden nodes, this funtion is successfull by doing nothing - return true; - } - - if (!mSetting.session) { - RS_WARN("no session found!"); - return false; - } - - peerState ps; - mPeerMgr->getOwnNetStatus(ps); - - RS_STACK_MUTEX(mLockSam3Access); - - mSetting.session->silent = true; - int ret = sam3StreamForward(mSetting.session, sockaddr_storage_iptostring(ps.localaddr).c_str(), sockaddr_storage_port(ps.localaddr)); - if (ret < 0) { - RS_DBG("forward failed, due to", mSetting.session->error); - return false; - } - - return true; -} - -void p3I2pSam3::stopSession() -{ - RS_DBG4(); - - { - RS_STACK_MUTEX(mLock); - if (!mSetting.session) - return; - - // swap connections - mInvalidConnections = mValidConnections; - mValidConnections.clear(); - - RS_STACK_MUTEX(mLockSam3Access); - sam3CloseSession(mSetting.session); - free(mSetting.session); - - mSetting.session = nullptr; - mState = samStatus::samState::offline; - } - - // At least i2pd doesn't like to instantaniously stop and (re)start a session, wait here just a little bit. - // Not ideal but does the trick. - // (This happens when using the "restart" button in the settings.) - doSleep(std::chrono::seconds(10)); -} - -void p3I2pSam3::stopForwarding() -{ - // nothing to do here, forwarding is stop when closing the seassion -} - -bool p3I2pSam3::generateKey(std::string &pub, std::string &priv) -{ - RS_DBG4(); - - pub.clear(); - priv.clear(); - - // The session is only usef for transporting the data - Sam3Session ss; - - if (0 > sam3GenerateKeys(&ss, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT, Sam3SigType::EdDSA_SHA512_Ed25519)) { - RS_DBG("got error: ", ss.error); - return false; - } - - pub = std::string(ss.pubkey); - priv = std::string(ss.privkey); - - // sanity check - auto p = i2p::publicKeyFromPrivate(priv); - if (p != pub) { - RS_WARN("public key does not match private key! fixing ..."); - pub = p; - } - - RS_DBG2("publuc key / address ", pub); - RS_DBG2("private key ", priv); - - return true; -} - -void p3I2pSam3::lookupKey(taskTicket *ticket) -{ - // this can be called independend of the main SAM session! - - auto addr = static_cast(ticket->data); - if (addr->base32.empty()) { - RS_ERR("lookupKey: called with empty address"); - rsAutoProxyMonitor::taskError(ticket); - return; - } - - RsThread::async([ticket]() - { - auto addr = static_cast(ticket->data); - - // The session is only usef for transporting the data - Sam3Session ss; - int ret = sam3NameLookup(&ss, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT, addr->base32.c_str()); - if (ret < 0) { - // get error - RS_DBG("key: ", addr->base32); - RS_DBG("got error: ", ss.error); - rsAutoProxyMonitor::taskError(ticket); - } else { - addr->publicKey = ss.destkey; - rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok); - RS_DBG1("success"); - } - }); -} - -void p3I2pSam3::establishConnection(taskTicket *ticket) -{ - if (mState != samStatus::samState::online || !mSetting.session) { - RS_WARN("no session found!"); - rsAutoProxyMonitor::taskError(ticket); - return; - } - - samEstablishConnectionWrapper *wrapper = static_cast(ticket->data); - if (wrapper->address.publicKey.empty()) { - RS_ERR("no public key given"); - rsAutoProxyMonitor::taskError(ticket); - return; - } - - RsThread::async([ticket, this]() { - auto wrapper = static_cast(ticket->data); - - struct Sam3Connection *connection; - { - auto l = this->mLockSam3Access; - RS_STACK_MUTEX(l); - mSetting.session->silent = false; - connection = sam3StreamConnect(this->mSetting.session, wrapper->address.publicKey.c_str()); - } - - if (!connection) { - // get error - RS_DBG("got error:", this->mSetting.session->error); - rsAutoProxyMonitor::taskError(ticket); - } else { - wrapper->connection = connection; - { - auto l = this->mLockSam3Access; - RS_STACK_MUTEX(l); - this->mValidConnections.push_back(connection); - } - RS_DBG1("success"); - rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok); - } - }); -} - -void p3I2pSam3::closeConnection(taskTicket *ticket) -{ - Sam3Connection *conn = static_cast(ticket->data); - - if (mState == samStatus::samState::offline || !mSetting.session) { - // no session found, sam was likely stopped - RS_DBG2("no session found"); - - auto it = std::find(mInvalidConnections.begin(), mInvalidConnections.end(), conn); - if (it != mInvalidConnections.end()) { - // this is the expected case - mInvalidConnections.erase(it); - } else { - // this is unexpected but not a big deal, just warn - RS_WARN("cannot find connection in mInvalidConnections"); - - it = std::find(mValidConnections.begin(), mValidConnections.end(), conn); - if (it != mValidConnections.end()) { - mValidConnections.erase(it); - - // now it is getting even weirder, still not a big deal, just warn - RS_WARN("found connection in mValidConnections"); - } - } - - // when libsam3 has already handled closing of the connection - which should be the case here - the memory has been freed already (-> pointer is invalid) - conn = nullptr; - } else { - RS_STACK_MUTEX(mLock); - - bool callClose = true; - // search in current connections - auto it = std::find(mValidConnections.begin(), mValidConnections.end(), conn); - if (it != mValidConnections.end()) { - RS_DBG2("found valid connection"); - mValidConnections.erase(it); - } else { - // search in old connections - it = std::find(mInvalidConnections.begin(), mInvalidConnections.end(), conn); - if (it != mInvalidConnections.end()) { - // old connection, just ignore. *should* be freed already - mInvalidConnections.erase(it); - - RS_DBG2("found old (invalid) connection"); - - callClose = false; - conn = nullptr; - } else { - // weird - RS_WARN("could'n find connection!"); - - // best thing we can do here - callClose = false; - conn = nullptr; - } - } - - if (callClose) { - RS_DBG2("closing connection"); - - RS_STACK_MUTEX(mLockSam3Access); - sam3CloseConnection(conn); - conn = nullptr; // freed by above call - } - } - - if (conn) { - free(conn); - conn = nullptr; - } - - ticket->data = nullptr; - rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok); - return; -} - -void p3I2pSam3::updateSettings_locked() -{ - RS_DBG4(); - IndicateConfigChanged(); - -#if 0 // TODO recreat session when active, can we just recreat it? - if (mSs) { - stopSession(); - startSession(); - } -#endif -} diff --git a/libretroshare/src/services/autoproxy/p3i2psam3.h b/libretroshare/src/services/autoproxy/p3i2psam3.h deleted file mode 100644 index c6b57615e..000000000 --- a/libretroshare/src/services/autoproxy/p3i2psam3.h +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef P3I2PSAM3_H -#define P3I2PSAM3_H - -#include -#include - -#include "services/autoproxy/rsautoproxymonitor.h" -#include "pqi/p3cfgmgr.h" -#include "util/i2pcommon.h" -#include "util/rsthreads.h" - -/* - * This class implements I2P SAMv3 (Simple Anonymous Messaging) to allow RS - * to automatically setup tunnel to and from I2P. - * SAMv3 is a simple text-based interface: https://geti2p.net/de/docs/api/samv3 - * - * For the actual SAM commands / low level stuff libsam3 (https://github.com/i2p/libsam3) - * is used with some minor adjustments, for exmaple, the FORWARD session is always silent. - * - * SAM in a nutshell works like this: - * 1) setup main/control session which configures everything (destination ID, tunnel number, hops number, and so on) - * 2) setup a forward session, so that I2P will establish a connection to RS for each incoming connection to our i2p destination - * 3a) query/lookup the destination (public key) for a given i2p address - * 3b) connect to the given destination - * - * An established connection (both incoming or outgoing) are then handed over to RS. - * The lifetime of a session (and its subordinates connections) is bound to their tcp socket. When the socket closes, the session is closed, too. - * - */ - -class p3PeerMgr; - -class Sam3Session; -class Sam3Connection; - -typedef Sam3Session samSession; - -struct samSettings : i2p::settings { - samSession *session; -}; - -struct samEstablishConnectionWrapper { - i2p::address address; - Sam3Connection *connection; -}; - -struct samStatus { - std::string sessionName; - enum samState { - offline, - connectSession, - connectForward, - online - } state; // the name is kinda redundant ... -}; - -class p3I2pSam3 : public RsTickingThread, public p3Config, public autoProxyService -{ -public: - p3I2pSam3(p3PeerMgr *peerMgr); - - // autoProxyService interface -public: - bool isEnabled(); - bool initialSetup(std::string &addr, uint16_t &port); - void processTaskAsync(taskTicket *ticket); - void processTaskSync(taskTicket *ticket); - - // RsTickingThread interface -public: - void threadTick(); /// @see RsTickingThread - - // p3Config interface -protected: - RsSerialiser *setupSerialiser(); - bool saveList(bool &cleanup, std::list &); - bool loadList(std::list &load); - -private: - bool startSession(); - bool startForwarding(); - void stopSession(); - void stopForwarding(); - - bool generateKey(std::string &pub, std::string &priv); - void lookupKey(taskTicket *ticket); - void establishConnection(taskTicket *ticket); - void closeConnection(taskTicket *ticket); - void updateSettings_locked(); - - bool mConfigLoaded; - - samSettings mSetting; - p3PeerMgr *mPeerMgr; - std::queue mPending; - - // Used to report the state to the gui - // (Since the create session call/will can block and there is no easy way from outside the main thread to see - // what is going on, it is easier to store the current state in an extra variable independen from the main thread) - samStatus::samState mState; - - // used to keep track of connections, libsam3 does it internally but it can be unreliable since pointers are shared - std::list mValidConnections, mInvalidConnections; - - // mutex - RsMutex mLock; - RsMutex mLockSam3Access; // libsam3 is not thread safe! (except for key lookup) -}; - -#endif // P3I2PSAM3_H diff --git a/libretroshare/src/services/autoproxy/rsautoproxymonitor.cc b/libretroshare/src/services/autoproxy/rsautoproxymonitor.cc deleted file mode 100644 index b2d71571e..000000000 --- a/libretroshare/src/services/autoproxy/rsautoproxymonitor.cc +++ /dev/null @@ -1,350 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services/autoproxy: rsautoproximonitor.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2016 by Sehraf * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "rsautoproxymonitor.h" - -#include /* for usleep() */ -#include "util/rsdebug.h" -#include "util/rstime.h" - -rsAutoProxyMonitor *rsAutoProxyMonitor::mInstance = NULL; - -rsAutoProxyMonitor::rsAutoProxyMonitor() - : mRSShutDown(false), mLock("rs auto proxy monitor") -{ - mProxies.clear(); -} - -rsAutoProxyMonitor *rsAutoProxyMonitor::instance() -{ - if (mInstance == NULL) - mInstance = new rsAutoProxyMonitor(); - return mInstance; -} - -void rsAutoProxyMonitor::addProxy(autoProxyType::autoProxyType_enum type, autoProxyService *service) -{ - RS_STACK_MUTEX(mLock); - if (mProxies.find(type) != mProxies.end()) { - RS_ERR("type ", type, " already added - OVERWRITING"); - print_stacktrace(); - } - - mProxies[type] = service; -} - -void rsAutoProxyMonitor::startAll() -{ - // create ticket - taskTicket *tt = getTicket(); - tt->cb = this; - tt->task = autoProxyTask::start; - - { - std::map::const_iterator it; - - // fill types - RS_STACK_MUTEX(mLock); - for (it = mProxies.begin(); it != mProxies.end(); ++it) - if (it->second->isEnabled()) - tt->types.push_back(it->first); - } - - task(tt); -} - -void rsAutoProxyMonitor::stopAll() -{ - // create ticket - taskTicket *tt = getTicket(); - tt->cb = this; - tt->task = autoProxyTask::stop; - - { - std::map::const_iterator it; - - // fill types - RS_STACK_MUTEX(mLock); - for (it = mProxies.begin(); it != mProxies.end(); ++it) - if (it->second->isEnabled()) - tt->types.push_back(it->first); - } - - task(tt); -} - -void rsAutoProxyMonitor::stopAllRSShutdown() -{ - { - RS_STACK_MUTEX(mLock); - mRSShutDown = true; - - // remove disabled services - std::vector toRemove; - std::map::const_iterator it; - for (it = mProxies.begin(); it != mProxies.end(); ++it) { - if (!it->second->isEnabled()) { - toRemove.push_back(it->first); - } - } - - std::vector::const_iterator it2; - for (it2 = toRemove.begin(); it2 != toRemove.end(); ++it2) { - mProxies.erase(*it2); - } - } - - // stop all remaining - stopAll(); - - // wait for shutdown of all services - uint32_t t = 0, timeout = 15; - do { - rstime::rs_usleep(1000 * 1000); - RS_STACK_MUTEX(mLock); - RS_DBG("waiting for auto proxy service(s) to shut down ", t, "/", timeout, " (remaining: ", mProxies.size(), ")"); - if (mProxies.empty()) - break; - t++; - } while (t < timeout ); -} - -bool rsAutoProxyMonitor::isEnabled(autoProxyType::autoProxyType_enum t) -{ - autoProxyService *s = lookUpService(t); - if (s == NULL) - return false; - - return s->isEnabled(); -} - -bool rsAutoProxyMonitor::initialSetup(autoProxyType::autoProxyType_enum t, std::string &addr, uint16_t &port) -{ - autoProxyService *s = lookUpService(t); - if (s == NULL) - return false; - - return s->initialSetup(addr, port); -} - -void rsAutoProxyMonitor::task(taskTicket *ticket) -{ - // sanity checks - if (!ticket->async && ticket->types.size() > 1) { - RS_ERR("synchronous call to multiple services. This can cause problems!"); - print_stacktrace(); - } - if (ticket->async && !ticket->cb && ticket->data) { - RS_ERR("asynchronous call with data but no callback. This will likely causes memory leak!"); - print_stacktrace(); - } - if (ticket->types.size() > 1 && ticket->data) { - RS_ERR("call with data to multiple services. This will likely causes memory leak!"); - print_stacktrace(); - } - - std::vector::const_iterator it; - - for (it = ticket->types.begin(); it != ticket->types.end(); ++it) { - autoProxyService* s = lookUpService(*it); - if (s == NULL) - continue; - - if (ticket->async) { - // copy ticket - taskTicket *tt = new taskTicket(); - *tt = *ticket; - tt->types.clear(); - tt->types.push_back(*it); - - // it's async! - RsThread::async([s, tt] { - s->processTaskAsync(tt); - }); - } else { - s->processTaskSync(ticket); - } - } -} - -void rsAutoProxyMonitor::taskAsync(autoProxyType::autoProxyType_enum type, autoProxyTask::autoProxyTask_enum task, autoProxyCallback *cb, void *data) -{ - std::vector types; - types.push_back(type); - taskAsync(types, task, cb, data); -} - -void rsAutoProxyMonitor::taskAsync(std::vector types, autoProxyTask::autoProxyTask_enum task, autoProxyCallback *cb, void *data) -{ - if (!isAsyncTask(task)) { - // Usually the services will reject this ticket. - // Just print a warning - maybe there is some special case where this is a good idea. - RS_ERR("called with a synchronous task!"); - print_stacktrace(); - } - - taskTicket *tt = getTicket(); - tt->task = task; - tt->types = types; - if (cb) - tt->cb = cb; - if (data) - tt->data = data; - - instance()->task(tt); - // tickets were copied, clean up - delete tt; -} - -void rsAutoProxyMonitor::taskSync(autoProxyType::autoProxyType_enum type, autoProxyTask::autoProxyTask_enum task, void *data) -{ - std::vector types; - types.push_back(type); - taskSync(types, task, data); -} - -void rsAutoProxyMonitor::taskSync(std::vector types, autoProxyTask::autoProxyTask_enum task, void *data) -{ - if (isAsyncTask(task)) { - // Usually the services will reject this ticket. - // Just print a warning - maybe there is some special case where this is a good idea. - RS_ERR("called with an asynchronous task!"); - print_stacktrace(); - } - - taskTicket *tt = getTicket(); - tt->async = false; - tt->task = task; - tt->types = types; - if (data) - tt->data = data; - - instance()->task(tt); - // call done, clean up - delete tt; -} - -void rsAutoProxyMonitor::taskError(taskTicket *t) -{ - taskDone(t, autoProxyStatus::error); -} - -void rsAutoProxyMonitor::taskDone(taskTicket *t, autoProxyStatus::autoProxyStatus_enum status) -{ - bool cleanUp = false; - - t->result = status; - if (t->cb) { - t->cb->taskFinished(t); - if (t != NULL) { - // callack did not clean up properly - RS_ERR("callback did not clean up!"); - print_stacktrace(); - cleanUp = true; - } - } else if (t->async){ - // async and no callback - // we must take care of deleting - cleanUp = true; - if(t->data) - RS_ERR("async call with data attached but no callback set!"); - } - - if (cleanUp) { - if (t->data) { - RS_ERR("will try to delete void pointer!"); - print_stacktrace(); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdelete-incomplete" - delete t->data; -#pragma GCC diagnostic pop - t->data = NULL; - } - delete t; - t = NULL; - } -} - -taskTicket *rsAutoProxyMonitor::getTicket() -{ - taskTicket *tt = new taskTicket(); - tt->cb = NULL; - tt->data = NULL; - tt->async = true; - tt->result = autoProxyStatus::undefined; - return tt; -} - -void rsAutoProxyMonitor::taskFinished(taskTicket *&ticket) -{ - { - RS_STACK_MUTEX(mLock); - if (mRSShutDown && ticket->task == autoProxyTask::stop) { - mProxies.erase(ticket->types.front()); - } - } - - // clean up - if (ticket->data) { - RS_ERR(" data set. Will try to delete void pointer"); - print_stacktrace(); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdelete-incomplete" - delete ticket->data; -#pragma GCC diagnostic pop - ticket->data = NULL; - } - delete ticket; - ticket = NULL; -} - -autoProxyService *rsAutoProxyMonitor::lookUpService(autoProxyType::autoProxyType_enum t) -{ - RS_STACK_MUTEX(mLock); - std::map::const_iterator itService; - if ((itService = mProxies.find(t)) != mProxies.end()) { - return itService->second; - } - RS_DBG("no service for type ", t, " found!"); - return NULL; -} - -bool rsAutoProxyMonitor::isAsyncTask(autoProxyTask::autoProxyTask_enum t) -{ - // Explicit list all values, so that missing ones will be detected by the compiler. - switch (t) { - case autoProxyTask::start: [[fallthrough]]; - case autoProxyTask::stop: [[fallthrough]]; - case autoProxyTask::receiveKey: [[fallthrough]]; - case autoProxyTask::lookupKey: [[fallthrough]]; - case autoProxyTask::establishConnection: [[fallthrough]]; - case autoProxyTask::closeConnection: - return true; - case autoProxyTask::status: [[fallthrough]]; - case autoProxyTask::getSettings: [[fallthrough]]; - case autoProxyTask::setSettings: [[fallthrough]]; - case autoProxyTask::getErrorInfo: [[fallthrough]]; - case autoProxyTask::reloadConfig: [[fallthrough]]; - case autoProxyTask::proxyStatusCheck: - return false; - } - return false; -} diff --git a/libretroshare/src/services/autoproxy/rsautoproxymonitor.h b/libretroshare/src/services/autoproxy/rsautoproxymonitor.h deleted file mode 100644 index e08692947..000000000 --- a/libretroshare/src/services/autoproxy/rsautoproxymonitor.h +++ /dev/null @@ -1,241 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services/autoproxy: rsautoproximonitor.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2016 by Sehraf * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RSAUTOPROXYMONITOR_H -#define RSAUTOPROXYMONITOR_H - -#include -#include - -#include - -class autoProxyCallback; - -namespace autoProxyType { - enum autoProxyType_enum { -// I2PBOB, - I2PSAM3 - }; -} - -namespace autoProxyTask { - enum autoProxyTask_enum { - /* async tasks */ - start, ///< start up proxy - stop, ///< shut down proxy - receiveKey, ///< renew proxy key (if any) - lookupKey, ///< look up a base32 addr - proxyStatusCheck, ///< use to check if the proxy is still running - establishConnection, ///< create a connection to a given public key or base32 address - closeConnection, ///< closes a connection - /* sync tasks */ - status, ///< get status from auto proxy - getSettings, ///< get setting from auto proxy - setSettings, ///< set setting of auto proxy - reloadConfig, ///< signal config reload/rebuild - getErrorInfo ///< get error information from auto proxy - }; -} - -namespace autoProxyStatus { - enum autoProxyStatus_enum { - undefined, ///< undefined - usually not yet set - disabled, ///< used when a task cannot be done (e.g. a disabled service cannot be startet or stopped) - offline, ///< proxy is not set up - online, ///< proxy is set up - ok, ///< generic ok - error ///< generic error - }; -} - -struct taskTicket { - /// - /// \brief types auto proxy service types that should get the ticket - /// - std::vector types; - - /// - /// \brief task the task to satisfy - /// - autoProxyTask::autoProxyTask_enum task; - - /// - /// \brief cb (optional) callback that gets called once the task is done - /// - autoProxyCallback *cb; - - /// - /// \brief result (optional) result - /// - autoProxyStatus::autoProxyStatus_enum result; - - /// - /// \brief data (optional) service dependent data - /// - /// Needs to be allocated and freed by caller! - /// - void *data; - - /// - /// \brief async is the call Asynchronous - /// - /// Will create a copy of the ticket for each - /// service and delete the original ticket. - /// - bool async; -}; - -class autoProxyCallback { -public: - /// - /// \brief taskFinished called when a task is finished - /// \param ticket - /// - /// Remove everything: ticket and attached data if any! - /// - virtual void taskFinished(taskTicket *&ticket) = 0; -}; - -class autoProxyService { -public: - /// - /// \brief isEnabled must be provided to directly get a result without going through the ticket system - /// \return whether the auto proxy service is enabled or not - /// - virtual bool isEnabled() = 0; - - /// - /// \brief initialSetup used when creating a node - /// \param addr new address for the hidden service - /// \param port new port for the hidden service - /// \return true on success - /// - /// This function is used to do an initial setup when creating a new hidden node. - /// Nothing has been set up at this point to the auto proxy service must take care - /// of everything (e.g. starting (and stoping) of needed threads) - /// - virtual bool initialSetup(std::string &addr, uint16_t &port) = 0; - - /// - /// \brief processTaskAsync adds a ticket to the auto proxies task list - /// \param ticket - /// - /// Don't call the callback in this function as this can cause dead locks! - /// - virtual void processTaskAsync(taskTicket *ticket) = 0; - - /// - /// \brief processTaskSync taskTicket must be satisfied immediately - /// \param ticket - /// - virtual void processTaskSync(taskTicket *ticket) = 0; -}; - -class rsAutoProxyMonitor : autoProxyCallback -{ -public: - static rsAutoProxyMonitor *instance(); - - /// - /// \brief addProxy adds a new auto proxy service to the monitor - /// \param type type of the new auto proxy service - /// \param service pointer to the service - /// - void addProxy(autoProxyType::autoProxyType_enum type, autoProxyService *service); - - // global functions - void startAll(); - void stopAll(); - void stopAllRSShutdown(); - bool isEnabled(autoProxyType::autoProxyType_enum t); - // use this when creating a new node - bool initialSetup(autoProxyType::autoProxyType_enum t, std::string &addr, uint16_t &port); - - /// - /// \brief task Sends a task to all requested services - /// \param ticket Ticket containing required information - /// - /// There are two kind of tasks: asyn and sync. - /// All tasks that involve communication with the target program (e.g. I2P or Tor) are asynchronous. - /// All other task are synchronous (e.g. getting settings) - /// - /// - /// Synchronous: - /// When you want to get the settings from a service you can call task() with a ticket only listing - /// one service and data pointing to the service's settings class/struct. Set async to false so - /// that the service gets your original ticket. Ther service will process the request (get settings) - /// immediately and when the call to task() is done you can access the settings from your ticket. - /// - /// When additionally a call back is set the service will also call it. This can cause deadlocks! - /// - /// - /// Asynchronous: - /// When you want to start up all services or request new keys for all services you can call task() with a list - /// of services and set async to true. When each service has fullfilled the resquest he will - /// use the callback. The original caller ticket will be copied and each call to the callback - /// will use its copy of the original ticket. The attached data is not copied so each service gets - /// the same pointer! - /// - /// - /// Note: - /// Services should not delet or allocate anything unless no call back is provided and it is an - /// async call. In that case the service should delete the ticket and the attacked data. - /// Otherwise the caller must take care of cleaning up. - /// This class provides two wrappers to take care of this that should be used: taskError and taskDone - /// - /// Note2: - /// This function is private so that each user must use the wrappers taskAsync and taskSync that include - /// more sanity checks - /// -private: - void task(taskTicket *ticket); - -public: - static void taskAsync(autoProxyType::autoProxyType_enum type, autoProxyTask::autoProxyTask_enum task, autoProxyCallback *cb = NULL, void *data = NULL); - static void taskAsync(std::vector types, autoProxyTask::autoProxyTask_enum task, autoProxyCallback *cb = NULL, void *data = NULL); - static void taskSync (autoProxyType::autoProxyType_enum type, autoProxyTask::autoProxyTask_enum task, void *data = NULL); - static void taskSync (std::vector types, autoProxyTask::autoProxyTask_enum task, void *data = NULL); - - // usefull helpers - static void taskError(taskTicket *t); - static void taskDone(taskTicket *t, autoProxyStatus::autoProxyStatus_enum status); - static taskTicket *getTicket(); - - // autoProxyCallback interface -public: - void taskFinished(taskTicket *&ticket); - -private: - rsAutoProxyMonitor(); - - autoProxyService *lookUpService(autoProxyType::autoProxyType_enum t); - static bool isAsyncTask(autoProxyTask::autoProxyTask_enum t); - - std::map mProxies; - bool mRSShutDown; - RsMutex mLock; - - static rsAutoProxyMonitor *mInstance; -}; - - - -#endif // RSAUTOPROXYMONITOR_H diff --git a/libretroshare/src/services/broadcastdiscoveryservice.cc b/libretroshare/src/services/broadcastdiscoveryservice.cc deleted file mode 100644 index 380cf8e5d..000000000 --- a/libretroshare/src/services/broadcastdiscoveryservice.cc +++ /dev/null @@ -1,365 +0,0 @@ -/******************************************************************************* - * RetroShare Broadcast Domain Discovery * - * * - * Copyright (C) 2019-2021 Gioacchino Mazzurco * - * Copyright (C) 2019-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include "services/broadcastdiscoveryservice.h" -#include "retroshare/rspeers.h" -#include "serialiser/rsserializable.h" -#include "serialiser/rsserializer.h" -#include "retroshare/rsevents.h" - -#ifdef __ANDROID__ -# include "rs_android/retroshareserviceandroid.hpp" -#endif // def __ANDROID__ - - -/*extern*/ RsBroadcastDiscovery* rsBroadcastDiscovery = nullptr; - -struct BroadcastDiscoveryPack : RsSerializable -{ - BroadcastDiscoveryPack() : mLocalPort(0) {} - - RsPgpFingerprint mPgpFingerprint; - RsPeerId mSslId; - uint16_t mLocalPort; - std::string mProfileName; - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) override - { - RS_SERIAL_PROCESS(mPgpFingerprint); - RS_SERIAL_PROCESS(mSslId); - RS_SERIAL_PROCESS(mLocalPort); - RS_SERIAL_PROCESS(mProfileName); - } - - static BroadcastDiscoveryPack fromPeerDetails(const RsPeerDetails& pd) - { - BroadcastDiscoveryPack bdp; - bdp.mPgpFingerprint = pd.fpr; - bdp.mSslId = pd.id; - bdp.mLocalPort = pd.localPort; - bdp.mProfileName = pd.name; - return bdp; - } - - static BroadcastDiscoveryPack fromSerializedString(const std::string& st) - { - RsGenericSerializer::SerializeContext ctx( - reinterpret_cast(const_cast(st.data())), - static_cast(st.size()) ); - BroadcastDiscoveryPack bdp; - bdp.serial_process(RsGenericSerializer::DESERIALIZE, ctx); - return bdp; - } - - std::string serializeToString() - { - /* After some experiments it seems very unlikely that UDP broadcast - * packets bigger then this could get trought a network */ - std::vector buffer(512, 0); - RsGenericSerializer::SerializeContext ctx( - buffer.data(), static_cast(buffer.size()) ); - serial_process(RsGenericSerializer::SERIALIZE, ctx); - return std::string(reinterpret_cast(buffer.data()), ctx.mOffset); - } - - BroadcastDiscoveryPack(const BroadcastDiscoveryPack&) = default; - ~BroadcastDiscoveryPack() override; -}; - - -BroadcastDiscoveryService::BroadcastDiscoveryService( - RsPeers& pRsPeers ) : - mDiscoveredDataMutex("BroadcastDiscoveryService discovered data mutex"), - mRsPeers(pRsPeers) -{ - if(mRsPeers.isHiddenNode(mRsPeers.getOwnId())) return; - -#ifdef __ANDROID__ - createAndroidMulticastLock(); -#endif // def __ANDROID__ - - enableMulticastListening(); - - mUdcParameters.set_can_discover(true); - mUdcParameters.set_can_be_discovered(true); - mUdcParameters.set_port(port); - mUdcParameters.set_application_id(appId); - - mUdcPeer.Start(mUdcParameters, ""); - updatePublishedData(); -} - -BroadcastDiscoveryService::~BroadcastDiscoveryService() -{ - mUdcPeer.Stop(true); - disableMulticastListening(); -} - -std::vector -BroadcastDiscoveryService::getDiscoveredPeers() -{ - std::vector ret; - - RS_STACK_MUTEX(mDiscoveredDataMutex); - for(auto&& pp: mDiscoveredData) - ret.push_back(createResult(pp.first, pp.second)); - - return ret; -} - -void BroadcastDiscoveryService::updatePublishedData() -{ - RsPeerDetails od; - mRsPeers.getPeerDetails(mRsPeers.getOwnId(), od); - mUdcPeer.SetUserData( - BroadcastDiscoveryPack::fromPeerDetails(od).serializeToString()); -} - -void BroadcastDiscoveryService::threadTick() -{ - if( mUdcParameters.can_discover() && - !mRsPeers.isHiddenNode(mRsPeers.getOwnId()) ) - { - auto currentEndpoints = mUdcPeer.ListDiscovered(); - std::map currentMap; - std::map updateMap; - - mDiscoveredDataMutex.lock(); - for(auto&& dEndpoint: currentEndpoints) - { - currentMap[dEndpoint.ip_port()] = dEndpoint.user_data(); - - auto findIt = mDiscoveredData.find(dEndpoint.ip_port()); - if( !dEndpoint.user_data().empty() && ( - findIt == mDiscoveredData.end() || - findIt->second != dEndpoint.user_data() ) ) - updateMap[dEndpoint.ip_port()] = dEndpoint.user_data(); - } - mDiscoveredData = currentMap; - mDiscoveredDataMutex.unlock(); - - if(!updateMap.empty()) - { - for (auto&& pp : updateMap) - { - RsBroadcastDiscoveryResult rbdr = - createResult(pp.first, pp.second); - - const bool isFriend = mRsPeers.isFriend(rbdr.mSslId); - if( isFriend && rbdr.mLocator.hasPort() && - !mRsPeers.isOnline(rbdr.mSslId) ) - { - mRsPeers.setLocalAddress( - rbdr.mSslId, rbdr.mLocator.host(), - rbdr.mLocator.port() ); - mRsPeers.connectAttempt(rbdr.mSslId); - } - else if(!isFriend) - { - if(rsEvents) - { - auto ev = std::make_shared(); - - ev->mDiscoveryEventType = RsBroadcastDiscoveryEventType::PEER_FOUND; - ev->mData = rbdr; - - rsEvents->postEvent(ev); - } - } - } - } - } - - /* Probably this would be better if done only on actual change */ - if( mUdcParameters.can_be_discovered() && - !mRsPeers.isHiddenNode(mRsPeers.getOwnId()) ) updatePublishedData(); - - // This avoids waiting 5 secs when the thread should actually terminate (when RS closes). - for(uint32_t i=0;i<10;++i) - { - if(shouldStop()) - return; - rstime::rs_usleep(500*1000); // sleep for 0.5 sec. - } -} - -RsBroadcastDiscoveryResult BroadcastDiscoveryService::createResult( - const udpdiscovery::IpPort& ipp, const std::string& uData ) -{ - BroadcastDiscoveryPack bdp = - BroadcastDiscoveryPack::fromSerializedString(uData); - - RsBroadcastDiscoveryResult rbdr; - rbdr.mPgpFingerprint = bdp.mPgpFingerprint; - rbdr.mSslId = bdp.mSslId; - rbdr.mProfileName = bdp.mProfileName; - rbdr.mLocator. - setScheme("ipv4"). - setHost(UDC::IpToString(ipp.ip())). - setPort(bdp.mLocalPort); - - return rbdr; -} - -bool BroadcastDiscoveryService::isMulticastListeningEnabled() -{ -#ifdef __ANDROID__ - if(!mAndroidWifiMulticastLock) - { - RS_ERR("Android multicast lock not initialized!"); - return false; - } - - auto uenv = jni::GetAttachedEnv(RsJni::getVM()); - JNIEnv& env = *uenv; - auto& multicastLockClass = jni::Class::Singleton(env); - - auto isHeld = - multicastLockClass.GetMethod( - env, "isHeld" ); - - return mAndroidWifiMulticastLock.Call(env, isHeld); -#else // def __ANDROID__ - return true; -#endif // def __ANDROID__ -} - -bool BroadcastDiscoveryService::enableMulticastListening() -{ -#ifdef __ANDROID__ - if(!mAndroidWifiMulticastLock) - { - RS_ERR("Android multicast lock not initialized!"); - return false; - } - - if(!isMulticastListeningEnabled()) - { - auto uenv = jni::GetAttachedEnv(RsJni::getVM()); - JNIEnv& env = *uenv; - auto& multicastLockClass = jni::Class::Singleton(env); - - auto acquire = - multicastLockClass.GetMethod( - env, "acquire" ); - - mAndroidWifiMulticastLock.Call(env, acquire); - - return true; - } -#endif // def __ANDROID__ - - return false; -} - -bool BroadcastDiscoveryService::disableMulticastListening() -{ -#ifdef __ANDROID__ - if(!mAndroidWifiMulticastLock) - { - RS_ERR("Android multicast lock not initialized!"); - return false; - } - - if(isMulticastListeningEnabled()) - { - auto uenv = jni::GetAttachedEnv(RsJni::getVM()); - JNIEnv& env = *uenv; - auto& multicastLockClass = jni::Class::Singleton(env); - - auto release = - multicastLockClass.GetMethod( - env, "release" ); - - mAndroidWifiMulticastLock.Call(env, release); - - return true; - } -#endif // def __ANDROID__ - - return false; -} - -#ifdef __ANDROID__ - -bool BroadcastDiscoveryService::createAndroidMulticastLock() -{ - if(mAndroidWifiMulticastLock) - { - RS_ERR("Android multicast lock is already initialized"); - print_stacktrace(); - return false; - } - - auto uenv = jni::GetAttachedEnv(RsJni::getVM()); - JNIEnv& env = *uenv; - - using AContextTag = RetroShareServiceAndroid::Context; - using AContext = jni::Class; - static auto& contextClass = AContext::Singleton(env); - - auto wifiServiceField = jni::StaticField( - env, contextClass, "WIFI_SERVICE"); - - jni::Local WIFI_SERVICE = contextClass.Get( - env, wifiServiceField ); - - auto androidContext = RetroShareServiceAndroid::getAndroidContext(env); - - auto getSystemService = - contextClass.GetMethod (jni::String)>( - env, "getSystemService" ); - - struct WifiManager - { static constexpr auto Name() { return "android/net/wifi/WifiManager"; } }; - - auto& wifiManagerClass = jni::Class::Singleton(env); - - auto wifiManager = jni::Cast( - env, wifiManagerClass, - androidContext.Call(env, getSystemService, WIFI_SERVICE) ); - - auto createMulticastLock = - wifiManagerClass.GetMethod(jni::String)>( - env, "createMulticastLock" ); - - mAndroidWifiMulticastLock = jni::NewGlobal( - env, wifiManager.Call( - env, createMulticastLock, - jni::Make( - env, "RetroShare BroadcastDiscoveryService" ) ) ); - - return true; -} - -#endif // def __ANDROID__ - -RsBroadcastDiscovery::~RsBroadcastDiscovery() = default; -RsBroadcastDiscoveryResult::~RsBroadcastDiscoveryResult() = default; -BroadcastDiscoveryPack::~BroadcastDiscoveryPack() = default; diff --git a/libretroshare/src/services/broadcastdiscoveryservice.h b/libretroshare/src/services/broadcastdiscoveryservice.h deleted file mode 100644 index f4204c324..000000000 --- a/libretroshare/src/services/broadcastdiscoveryservice.h +++ /dev/null @@ -1,100 +0,0 @@ -/******************************************************************************* - * RetroShare Broadcast Domain Discovery * - * * - * Copyright (C) 2019-2021 Gioacchino Mazzurco * - * Copyright (C) 2019-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include -#include - -#include - -#include "retroshare/rsbroadcastdiscovery.h" -#include "util/rsthreads.h" -#include "util/rsdebug.h" - -#ifdef __ANDROID__ -# include -# include "rs_android/rsjni.hpp" -#endif // def __ANDROID__ - - -namespace UDC = udpdiscovery; -class RsPeers; - -class BroadcastDiscoveryService : - public RsBroadcastDiscovery, public RsTickingThread -{ -public: - explicit BroadcastDiscoveryService(RsPeers& pRsPeers); - ~BroadcastDiscoveryService() override; - - /// @see RsBroadcastDiscovery - std::vector getDiscoveredPeers() override; - - /// @see RsBroadcastDiscovery - bool isMulticastListeningEnabled() override; - - /// @see RsBroadcastDiscovery - bool enableMulticastListening() override; - - /// @see RsBroadcastDiscovery - bool disableMulticastListening() override; - - void threadTick() override; /// @see RsTickingThread - -protected: - constexpr static uint16_t port = 36405; - constexpr static uint32_t appId = 904571; - - void updatePublishedData(); - - UDC::PeerParameters mUdcParameters; - UDC::Peer mUdcPeer; - - std::map mDiscoveredData; - RsMutex mDiscoveredDataMutex; - - RsPeers& mRsPeers; - - RsBroadcastDiscoveryResult createResult( - const UDC::IpPort& ipp, const std::string& uData ); - -#ifdef __ANDROID__ - struct AndroidMulticastLock - { - static constexpr auto Name() - { return "android/net/wifi/WifiManager$MulticastLock"; } - }; - - jni::Global> mAndroidWifiMulticastLock; - - /** Initialize the wifi multicast lock without acquiring it - * Needed to enable multicast listening in Android, for RetroShare broadcast - * discovery inspired by: - * https://github.com/flutter/flutter/issues/16335#issuecomment-420547860 - */ - bool createAndroidMulticastLock(); -#endif - - RS_SET_CONTEXT_DEBUG_LEVEL(3) -}; diff --git a/libretroshare/src/services/p3banlist.cc b/libretroshare/src/services/p3banlist.cc deleted file mode 100644 index a257d2772..000000000 --- a/libretroshare/src/services/p3banlist.cc +++ /dev/null @@ -1,1303 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3banlist.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "pqi/p3servicecontrol.h" -#include "pqi/p3netmgr.h" -#include "pqi/p3cfgmgr.h" - -#include "util/rsnet.h" - -#include "services/p3banlist.h" -#include "retroshare/rsdht.h" -#include "retroshare/rsbanlist.h" - -#include "rsitems/rsbanlistitems.h" -#include "rsitems/rsconfigitems.h" - -#include -#include - -/**** - * #define DEBUG_BANLIST 1 - ****/ -// #define DEBUG_BANLIST 1 -//#define DEBUG_BANLIST_CONDENSE 1 - - -/* DEFINE INTERFACE POINTER! */ -//RsBanList *rsBanList = NULL; - -#define RSBANLIST_ENTRY_MAX_AGE (60 * 60 * 24) // 24 HOURS -#define RSBANLIST_SEND_PERIOD 600 // 10 Minutes. - -#define RSBANLIST_DELAY_BETWEEN_TALK_TO_DHT 240 // every 4 mins. - -/************ IMPLEMENTATION NOTES ********************************* - * - * Get Bad Peers passed to us (from DHT mainly). - * we distribute and track the network list of bad peers. - * - */ -RsBanList *rsBanList = NULL ; - -p3BanList::p3BanList(p3ServiceControl *sc, p3NetMgr */*nm*/) - : p3Service(), mBanMtx("p3BanList"), mServiceCtrl(sc) - , mSentListTime(0), mLastDhtInfoRequest(0) - // default number of IPs in same range to trigger a complete IP /24 filter. - , mAutoRangeLimit(2), mAutoRangeIps(true) - , mIPFilteringEnabled(true) - , mIPFriendGatheringEnabled(false) - , mIPDHTGatheringEnabled(false) -{ addSerialType(new RsBanListSerialiser()); } - -const std::string BANLIST_APP_NAME = "banlist"; -const uint16_t BANLIST_APP_MAJOR_VERSION = 1; -const uint16_t BANLIST_APP_MINOR_VERSION = 0; -const uint16_t BANLIST_MIN_MAJOR_VERSION = 1; -const uint16_t BANLIST_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3BanList::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_BANLIST, - BANLIST_APP_NAME, - BANLIST_APP_MAJOR_VERSION, - BANLIST_APP_MINOR_VERSION, - BANLIST_MIN_MAJOR_VERSION, - BANLIST_MIN_MINOR_VERSION); -} - -bool p3BanList::ipFilteringEnabled() { return mIPFilteringEnabled ; } -void p3BanList::enableIPFiltering(bool b) { mIPFilteringEnabled = b ; } -void p3BanList::enableIPsFromFriends(bool b) { mIPFriendGatheringEnabled = b; mLastDhtInfoRequest=0;} -void p3BanList::enableIPsFromDHT(bool b) -{ - mIPDHTGatheringEnabled = b; - mLastDhtInfoRequest=0; - - IndicateConfigChanged(); -} -void p3BanList::enableAutoRange(bool b) -{ - mAutoRangeIps = b; - autoFigureOutBanRanges() ; - - IndicateConfigChanged(); -} -void p3BanList::setAutoRangeLimit(int n) -{ - mAutoRangeLimit = n; - autoFigureOutBanRanges(); - - IndicateConfigChanged(); -} - -namespace services { - -class ZeroedInt -{ - public: - ZeroedInt() { n = 0 ; } - uint32_t n ; -}; - -} - -BanListPeer::BanListPeer() -{ - memset(&addr, 0, sizeof(addr)); - masked_bytes=0; - reason=RSBANLIST_REASON_UNKNOWN ; - level=RSBANLIST_ORIGIN_UNKNOWN ; - state = true ; - connect_attempts=0; - mTs=0; -} - -void BanListPeer::toRsTlvBanListEntry(RsTlvBanListEntry &e) const -{ - e.addr.addr = addr; - e.masked_bytes = masked_bytes; - e.reason = reason; - e.level = level; - e.comment = comment; - e.age = time(NULL) - mTs; -} - -void BanListPeer::fromRsTlvBanListEntry(const RsTlvBanListEntry &e) -{ - addr = e.addr.addr; - masked_bytes = e.masked_bytes; // 0 = []/32. 1=[]/24, 2=[]/16 - reason = e.reason; // User, DHT - level = e.level; // LOCAL, FRIEND, FoF. - state = true; // true=>active, false=>just stored but inactive - connect_attempts = 0; // recorded by the BanList service - comment = e.comment; // recorded by the BanList service - mTs = time(NULL) - e.age; -} - -static uint32_t getBitRange(const sockaddr_storage& addr) -{ - sockaddr_storage s ; - sockaddr_storage_clear(s) ; - sockaddr_storage_copyip(s,addr) ; - - sockaddr_in *ad = (sockaddr_in*)(&s) ; - - if( (ad->sin_addr.s_addr & 0xff000000) != 0xff000000) - return 0 ; - - if( (ad->sin_addr.s_addr & 0x00ff0000) != 0x00ff0000) - return 1 ; - - if( (ad->sin_addr.s_addr & 0x0000ff00) != 0x0000ff00) - return 2 ; - - if( (ad->sin_addr.s_addr & 0x000000ff) != 0x000000ff) - return 3 ; - - return 4 ; -} -static sockaddr_storage makeBitsRange(const sockaddr_storage& addr,int masked_bytes) -{ - sockaddr_storage s ; - sockaddr_storage_clear(s) ; - sockaddr_storage_copyip(s,addr) ; - - sockaddr_in *ad = (sockaddr_in*)(&s) ; - - if(masked_bytes == 1) - ad->sin_addr.s_addr |= 0xff000000 ; - else if(masked_bytes == 2) - ad->sin_addr.s_addr |= 0xffff0000 ; - else if(masked_bytes != 0) - std::cerr << "Warning: unhandled mask size for IP range: " << masked_bytes << std::endl; - - return s ; -} - -void p3BanList::autoFigureOutBanRanges() -{ - RS_STACK_MUTEX(mBanMtx) ; - - // clear automatic ban ranges - - for(std::map::iterator it(mBanRanges.begin()); - it!=mBanRanges.end(); ) - { - if(it->second.reason == RSBANLIST_REASON_AUTO_RANGE) - { - std::map::iterator it2=it ; - ++it2 ; - mBanRanges.erase(it) ; - it=it2 ; - } - else ++it; - } - - IndicateConfigChanged(); - - if(!mAutoRangeIps) return; - -#ifdef DEBUG_BANLIST - std::cerr << "Automatically figuring out IP ranges from banned IPs." << std::endl; -#endif - - std::map range_map ; - - for(std::map::iterator it(mBanSet.begin());it!=mBanSet.end();++it) - ++range_map[makeBitsRange(it->first,1)].n ; - - rstime_t now = time(NULL) ; - - for(std::map::const_iterator it=range_map.begin();it!=range_map.end();++it) - { -#ifdef DEBUG_BANLIST - std::cerr << "Ban range: " << sockaddr_storage_iptostring(it->first) << " : " << it->second.n << std::endl; -#endif - - if(it->second.n >= mAutoRangeLimit) - { -#ifdef DEBUG_BANLIST - std::cerr << " --> creating new ban range." << std::endl; -#endif - BanListPeer& peer(mBanRanges[it->first]) ; - - if (peer.reason == RSBANLIST_REASON_USER) - continue; - - peer.addr = it->first ; - peer.masked_bytes = 1 ; - peer.reason = RSBANLIST_REASON_AUTO_RANGE ; - peer.level = RSBANLIST_ORIGIN_SELF ; - peer.state = true ; - peer.mTs = now ; - peer.connect_attempts = 0 ; - peer.connect_attempts = it->second.n; - } - } - - condenseBanSources_locked() ; -} - -bool p3BanList::acceptedBanSet_locked(const BanListPeer& blp) -{ - // REASON_USER REASON_DHT REASON_AUTO - // --------------------------------------------------------- - // banDHT Y/Y/N Y/Y/Y - // --------------------------------------------------------- - // banFriends - // --------------------------------------------------------- - // banAutoRanges - // - - if(blp.level > 1 && mIPFriendGatheringEnabled) - return true ; - - switch(blp.reason) - { - case RSBANLIST_REASON_USER: return true ; - - case RSBANLIST_REASON_DHT: return mIPDHTGatheringEnabled && blp.level==1; - - default: - case RSBANLIST_REASON_AUTO_RANGE: std::cerr << "(EE) Shouldn't find an AUTO RANGE in BanSet. Wrong call?" << std::endl; - return false ; - } - return false ; -} -bool p3BanList::acceptedBanRanges_locked(const BanListPeer& blp) -{ - // REASON_USER REASON_DHT REASON_AUTO - // --------------------------------------------------------- - // banDHT Y/Y/N Y/Y/Y - // --------------------------------------------------------- - // banFriends - // --------------------------------------------------------- - // banAutoRanges - // - - switch(blp.reason) - { - case RSBANLIST_REASON_USER: return true ; - - default: - case RSBANLIST_REASON_DHT: std::cerr << "(EE) Shouldn't find a DHT ip in BanRange. Wrong call?" << std::endl; - return false ; - - case RSBANLIST_REASON_AUTO_RANGE: return mAutoRangeIps ; - } - return false ; -} - -bool p3BanList::isAddressAccepted( - const sockaddr_storage& dAddr, uint32_t checking_flags, - uint32_t& check_result ) -{ - check_result = RSBANLIST_CHECK_RESULT_NOCHECK; - - sockaddr_storage addr; sockaddr_storage_copy(dAddr, addr); - - if(!sockaddr_storage_ipv6_to_ipv4(addr)) return true; - if(sockaddr_storage_isLoopbackNet(addr)) return true; - - - RS_STACK_MUTEX(mBanMtx); - - if(!mIPFilteringEnabled) return true; - -#ifdef DEBUG_BANLIST - std::cerr << "isAddressAccepted(): tested addr=" << sockaddr_storage_iptostring(addr) << ", checking flags=" << checking_flags ; -#endif - - // we should normally work this including entire ranges of IPs. For now, just check the exact IPs. - - sockaddr_storage addr_32 = makeBitsRange(addr,0) ; // this is necessay because it cleans the address - sockaddr_storage addr_24 = makeBitsRange(addr,1) ; - sockaddr_storage addr_16 = makeBitsRange(addr,2) ; - - bool white_list_found = false ; - - white_list_found = white_list_found || (mWhiteListedRanges.find(addr_16) != mWhiteListedRanges.end()) ; - white_list_found = white_list_found || (mWhiteListedRanges.find(addr_24) != mWhiteListedRanges.end()) ; - white_list_found = white_list_found || (mWhiteListedRanges.find(addr_32) != mWhiteListedRanges.end()) ; - - if(white_list_found) - { - check_result = RSBANLIST_CHECK_RESULT_ACCEPTED; -#ifdef DEBUG_BANLIST - std::cerr << ". Address is in whitelist. Accepting" << std::endl; -#endif - return true ; - } - - if(checking_flags & RSBANLIST_CHECKING_FLAGS_WHITELIST) - { - check_result = RSBANLIST_CHECK_RESULT_NOT_WHITELISTED; -#ifdef DEBUG_BANLIST - std::cerr << ". Address is not whitelist, and whitelist is required. Rejecting" << std::endl; -#endif - return false ; - } - - if(!(checking_flags & RSBANLIST_CHECKING_FLAGS_BLACKLIST)) - { -#ifdef DEBUG_BANLIST - std::cerr << ". No blacklisting required. Accepting." << std::endl; -#endif - check_result = RSBANLIST_CHECK_RESULT_ACCEPTED; - return true; - } - - std::map::iterator it ; - - if(((it=mBanRanges.find(addr_16)) != mBanRanges.end()) && acceptedBanRanges_locked(it->second)) - { - ++it->second.connect_attempts; -#ifdef DEBUG_BANLIST - std::cerr << " found in blacklisted range " << sockaddr_storage_iptostring(it->first) << "/16. returning false. attempts=" << it->second.connect_attempts << std::endl; -#endif - check_result = RSBANLIST_CHECK_RESULT_BLACKLISTED; - return false ; - } - - if(((it=mBanRanges.find(addr_24)) != mBanRanges.end()) && acceptedBanRanges_locked(it->second)) - { - ++it->second.connect_attempts; -#ifdef DEBUG_BANLIST - std::cerr << " found in blacklisted range " << sockaddr_storage_iptostring(it->first) << "/24. returning false. attempts=" << it->second.connect_attempts << std::endl; -#endif - check_result = RSBANLIST_CHECK_RESULT_BLACKLISTED; - return false ; - } - - if(((it=mBanRanges.find(addr_32)) != mBanRanges.end()) && acceptedBanRanges_locked(it->second)) - { - ++it->second.connect_attempts; -#ifdef DEBUG_BANLIST - std::cerr << " found in blacklisted range " << sockaddr_storage_iptostring(it->first) << "/32. returning false. attempts=" << it->second.connect_attempts << std::endl; -#endif - check_result = RSBANLIST_CHECK_RESULT_BLACKLISTED; - return false ; - } - - if((it=mBanSet.find(addr_32)) != mBanSet.end() && acceptedBanSet_locked(it->second)) - { - ++it->second.connect_attempts; -#ifdef DEBUG_BANLIST - std::cerr << "found as blacklisted address " << sockaddr_storage_iptostring(it->first) << ". returning false. attempts=" << it->second.connect_attempts << std::endl; -#endif - check_result = RSBANLIST_CHECK_RESULT_BLACKLISTED; - return false ; - } - -#ifdef DEBUG_BANLIST - std::cerr << " not blacklisted. Accepting." << std::endl; -#endif - check_result = RSBANLIST_CHECK_RESULT_ACCEPTED; - return true ; -} - -void p3BanList::getWhiteListedIps(std::list &lst) -{ - RS_STACK_MUTEX(mBanMtx) ; - - lst.clear() ; - for(std::map::const_iterator it(mWhiteListedRanges.begin());it!=mWhiteListedRanges.end();++it) - lst.push_back(it->second) ; -} -void p3BanList::getBannedIps(std::list &lst) -{ - RS_STACK_MUTEX(mBanMtx) ; - - - lst.clear() ; - for(std::map::const_iterator it(mBanSet.begin());it!=mBanSet.end();++it) - { - if(!acceptedBanSet_locked(it->second)) - continue ; - - std::map::const_iterator found1 = mBanRanges.find(makeBitsRange(it->first,1)) ; - - if(found1!=mBanRanges.end() && acceptedBanRanges_locked(found1->second)) - continue ; - - std::map::const_iterator found2 = mBanRanges.find(makeBitsRange(it->first,2)) ; - - if(found2!=mBanRanges.end() && acceptedBanRanges_locked(found2->second)) - continue ; - - lst.push_back(it->second) ; - } - - for(std::map::const_iterator it(mBanRanges.begin());it!=mBanRanges.end();++it) - if(acceptedBanRanges_locked(it->second)) - lst.push_back(it->second) ; -} - -bool p3BanList::removeIpRange( const struct sockaddr_storage& dAddr, - int masked_bytes, uint32_t list_type ) -{ - sockaddr_storage addr; sockaddr_storage_copy(dAddr, addr); - if(!sockaddr_storage_ipv6_to_ipv4(addr)) - { - std::cerr << __PRETTY_FUNCTION__ << " Cannot handle " - << sockaddr_storage_tostring(dAddr) - << " IPv6 not implemented yet!" - << std::endl; - return false; - } - - RS_STACK_MUTEX(mBanMtx); - - bool changed = false; - std::map::iterator it ; - - if(list_type == RSBANLIST_TYPE_BLACKLIST) - { - if( mBanRanges.end() != (it = mBanRanges.find(makeBitsRange(addr,masked_bytes)))) - { - mBanRanges.erase(it) ; - IndicateConfigChanged(); - changed = true; - } - } - else if(list_type == RSBANLIST_TYPE_WHITELIST) - { - if( mWhiteListedRanges.end() != (it = mWhiteListedRanges.find(makeBitsRange(addr,masked_bytes)))) - { - mWhiteListedRanges.erase(it) ; - IndicateConfigChanged(); - changed = true; - } - } - else - std::cerr << "(EE) Only whitelist or blacklist ranges can be removed." << std::endl; - - condenseBanSources_locked() ; - return changed; -} - -bool p3BanList::addIpRange( const sockaddr_storage &dAddr, int masked_bytes, - uint32_t list_type, const std::string& comment ) -{ - sockaddr_storage addr; sockaddr_storage_copy(dAddr, addr); - if(!sockaddr_storage_ipv6_to_ipv4(addr)) - { - std::cerr << __PRETTY_FUNCTION__ << " Cannot handle " - << sockaddr_storage_tostring(dAddr) - << " IPv6 not implemented yet!" - << std::endl; - return false; - } - - RS_STACK_MUTEX(mBanMtx); - - if(getBitRange(addr) > uint32_t(masked_bytes)) - { - std::cerr << "(EE) Input to p3BanList::addIpRange is inconsistent: ip=" << sockaddr_storage_iptostring(addr) << "/" << 32-8*masked_bytes << std::endl; - return false ; - } - - BanListPeer blp ; - blp.level = RSBANLIST_ORIGIN_SELF ; - blp.connect_attempts = 0 ; - blp.addr = addr ; - blp.masked_bytes = masked_bytes ; - blp.mTs = time(NULL) ; - blp.reason = RSBANLIST_REASON_USER; - blp.comment = comment ; - - if(masked_bytes != 0 && masked_bytes != 1 && masked_bytes != 2) - { - std::cerr << "Unhandled masked byte size " << masked_bytes << ". Should be 0,1 or 2" << std::endl; - return false; - } - if(list_type != RSBANLIST_TYPE_BLACKLIST && list_type != RSBANLIST_TYPE_WHITELIST) - { - std::cerr << "(EE) Cannot add IP range. Bad list_type. Should be eiter RSBANLIST_TYPE_BLACKLIST or RSBANLIST_TYPE_WHITELIST" << std::endl; - return false ; - } - - // Remove all existing ranges that are included into current range. - - std::map& banlist( (list_type == RSBANLIST_TYPE_BLACKLIST)?mBanRanges:mWhiteListedRanges) ; - - for(int i=0;i::iterator it = banlist.find(makeBitsRange(addr,i)) ; - - if(it != banlist.end()) - banlist.erase(it) ; - } - // Add range to list. - - banlist[makeBitsRange(addr,masked_bytes)] = blp ; - - IndicateConfigChanged() ; - condenseBanSources_locked() ; - - return true; -} - -int p3BanList::tick() -{ - processIncoming(); - sendPackets(); - - rstime_t now = time(NULL) ; - - if(mLastDhtInfoRequest + RSBANLIST_DELAY_BETWEEN_TALK_TO_DHT < now) - { - getDhtInfo() ; // This is always done, since these IPs are also sent to friends. - - mLastDhtInfoRequest = now; - - if(mAutoRangeIps) - autoFigureOutBanRanges() ; - } - -#ifdef DEBUG_BANLIST - static rstime_t last_print = 0 ; - - if(now > 10+last_print) - { - RsStackMutex stack(mBanMtx); /****** LOCKED MUTEX *******/ - printBanSet_locked(std::cerr); - last_print = now ; - } -#endif - - return 0; -} - -void p3BanList::getDhtInfo() -{ - // Get the list of masquerading peers from the DHT. Add them as potential IPs to be banned. - // Don't make them active. Just insert them in the list. - - std::list filtered_peers ; - - rsDht->getListOfBannedIps(filtered_peers) ; - -#ifdef DEBUG_BANLIST - std::cerr << "p3BanList::getDhtInfo() Got list of banned IPs." << std::endl; -#endif - RsPeerId ownId = mServiceCtrl->getOwnId(); - - for(std::list::const_iterator it(filtered_peers.begin());it!=filtered_peers.end();++it) - { -#ifdef DEBUG_BANLIST - std::cerr << " filtered peer: " << rs_inet_ntoa((*it).mAddr.sin_addr) << std::endl; -#endif - - int int_reason = RSBANLIST_REASON_DHT ; - int time_stamp = (*it).mLastSeen ; - - sockaddr_storage ad ; - sockaddr_storage_setipv4(ad,&(*it).mAddr) ; - - addBanEntry(ownId, ad, RSBANLIST_ORIGIN_SELF, int_reason, time_stamp); - } - - RsStackMutex stack(mBanMtx); /****** LOCKED MUTEX *******/ - condenseBanSources_locked() ; -} - -/***** Implementation ******/ - -bool p3BanList::processIncoming() -{ - /* for each packet - pass to specific handler */ - RsItem *item = NULL; - bool updated = false; - while(NULL != (item = recvItem())) - { -#ifdef DEBUG_BANLIST - std::cerr << "p3BanList::processingIncoming() Received Item:"; - std::cerr << std::endl; - item->print(std::cerr); - std::cerr << std::endl; -#endif - switch(item->PacketSubType()) - { - default: - break; - case RS_PKT_SUBTYPE_BANLIST_ITEM: - { - // Order is important!. - updated = (recvBanItem((RsBanListItem *) item) || updated); - } - break; - } - - /* clean up */ - delete item; - } - - if (updated) - { - { - RsStackMutex stack(mBanMtx); /****** LOCKED MUTEX *******/ - - condenseBanSources_locked(); - } - - /* pass list to NetAssist */ - - } - - return true ; -} - - -bool p3BanList::recvBanItem(RsBanListItem *item) -{ - bool updated = false; - - rstime_t now = time(NULL) ; - std::list::const_iterator it; - - for(it = item->peerList.mList.begin(); it != item->peerList.mList.end(); ++it) - { - // Order is important!. - updated = (addBanEntry(item->PeerId(), it->addr.addr, it->level, it->reason, now - it->age) || updated); - } - return updated; -} - -/* overloaded from pqiNetAssistSharePeer */ -void p3BanList::updatePeer( const RsPeerId& /*id*/, - const sockaddr_storage &dAddr, - int /*type*/, int /*reason*/, int time_stamp ) -{ - sockaddr_storage addr; sockaddr_storage_copy(dAddr, addr); - if(!sockaddr_storage_ipv6_to_ipv4(addr)) - { - std::cerr << __PRETTY_FUNCTION__ << " Cannot handle " - << sockaddr_storage_tostring(dAddr) - << " IPv6 not implemented yet!" - << std::endl; - return; - } - - RsPeerId ownId = mServiceCtrl->getOwnId(); - - int int_reason = RSBANLIST_REASON_DHT; - - addBanEntry(ownId, addr, RSBANLIST_ORIGIN_SELF, int_reason, time_stamp); - - /* process */ - { - RS_STACK_MUTEX(mBanMtx); - condenseBanSources_locked(); - } -} - -RsSerialiser *p3BanList::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser ; - - rss->addSerialType(new RsBanListSerialiser()) ; - rss->addSerialType(new RsGeneralConfigSerialiser()); - - return rss ; -} - -bool p3BanList::saveList(bool &cleanup, std::list& itemlist) -{ - RsStackMutex stack(mBanMtx); /****** LOCKED MUTEX *******/ - - cleanup = true ; - - for(std::map::const_iterator it(mBanSources.begin());it!=mBanSources.end();++it) - { - RsBanListConfigItem *item = new RsBanListConfigItem ; - - item->banListType = RSBANLIST_TYPE_PEERLIST ; - item->banListPeerId = it->second.mPeerId ; - item->update_time = it->second.mLastUpdate ; - item->banned_peers.TlvClear() ; - - for(std::map::const_iterator it2 = it->second.mBanPeers.begin();it2!=it->second.mBanPeers.end();++it2) - { - RsTlvBanListEntry e ; - it2->second.toRsTlvBanListEntry(e) ; - - item->banned_peers.mList.push_back(e) ; - } - - itemlist.push_back(item) ; - } - - // Add whitelist - RsBanListConfigItem *item = new RsBanListConfigItem ; - - item->banListType = RSBANLIST_TYPE_WHITELIST ; - item->banListPeerId.clear() ; - item->update_time = 0 ; - item->banned_peers.TlvClear() ; - - for(std::map::const_iterator it2 = mWhiteListedRanges.begin();it2!=mWhiteListedRanges.end();++it2) - { - RsTlvBanListEntry e ; - it2->second.toRsTlvBanListEntry(e) ; - - item->banned_peers.mList.push_back(e) ; - } - - itemlist.push_back(item) ; - - // addblacklist - - item = new RsBanListConfigItem ; - - item->banListType = RSBANLIST_TYPE_BLACKLIST ; - item->banListPeerId.clear(); - item->update_time = 0 ; - item->banned_peers.TlvClear() ; - - for(std::map::const_iterator it2 = mBanRanges.begin();it2!=mBanRanges.end();++it2) - { - RsTlvBanListEntry e ; - it2->second.toRsTlvBanListEntry(e) ; - - item->banned_peers.mList.push_back(e) ; - } - - itemlist.push_back(item) ; - - // Other variables - - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; - - RsTlvKeyValue kv; - - kv.key = "IP_FILTERING_ENABLED"; - kv.value = mIPFilteringEnabled?"TRUE":"FALSE" ; - vitem->tlvkvs.pairs.push_back(kv) ; - - kv.key = "IP_FILTERING_AUTORANGE_IPS"; - kv.value = mAutoRangeIps?"TRUE":"FALSE" ; - vitem->tlvkvs.pairs.push_back(kv) ; - - kv.key = "IP_FILTERING_FRIEND_GATHERING_ENABLED"; - kv.value = mIPFriendGatheringEnabled?"TRUE":"FALSE" ; - vitem->tlvkvs.pairs.push_back(kv) ; - - kv.key = "IP_FILTERING_DHT_GATHERING_ENABLED"; - kv.value = mIPDHTGatheringEnabled?"TRUE":"FALSE" ; - vitem->tlvkvs.pairs.push_back(kv) ; - - kv.key = "IP_FILTERING_AUTORANGE_IPS_LIMIT" ; - std::ostringstream os ; - os << mAutoRangeLimit ; - os.flush() ; - kv.value = os.str() ; - vitem->tlvkvs.pairs.push_back(kv) ; - - itemlist.push_back(vitem) ; - - return true ; -} - -bool p3BanList::loadList(std::list& load) -{ - RsStackMutex stack(mBanMtx); /****** LOCKED MUTEX *******/ - - for(std::list::const_iterator it(load.begin());it!=load.end();++it) - { - RsConfigKeyValueSet *vitem = dynamic_cast( *it ) ; - - if(vitem != NULL) - for(std::list::const_iterator it2(vitem->tlvkvs.pairs.begin());it2!=vitem->tlvkvs.pairs.end();++it2) - { - if(it2->key == "IP_FILTERING_ENABLED") mIPFilteringEnabled = (it2->value=="TRUE") ; - if(it2->key == "IP_FILTERING_AUTORANGE_IPS") mAutoRangeIps = (it2->value=="TRUE") ; - if(it2->key == "IP_FILTERING_FRIEND_GATHERING_ENABLED") mIPFriendGatheringEnabled = (it2->value=="TRUE") ; - if(it2->key == "IP_FILTERING_DHT_GATHERING_ENABLED") mIPDHTGatheringEnabled = (it2->value=="TRUE") ; - - if(it2->key == "IP_FILTERING_AUTORANGE_IPS_LIMIT") - { - int val ; - if(sscanf(it2->value.c_str(),"%d",&val) == 1) - mAutoRangeLimit = val ; - } - } - - RsBanListConfigItem *citem = dynamic_cast( *it ) ; - - if(citem != NULL) - { - if(citem->banListType == RSBANLIST_TYPE_PEERLIST) - { - BanList& bl(mBanSources[citem->banListPeerId]) ; - - bl.mPeerId = citem->banListPeerId ; - bl.mLastUpdate = citem->update_time ; - - bl.mBanPeers.clear() ; - - for(std::list::const_iterator it2(citem->banned_peers.mList.begin());it2!=citem->banned_peers.mList.end();++it2) - { - BanListPeer blp ; - blp.fromRsTlvBanListEntry(*it2) ; - - if(sockaddr_storage_isValidNet(blp.addr)) - bl.mBanPeers[blp.addr] = blp ; - else - std::cerr << "(WW) removed wrong address " << sockaddr_storage_iptostring(blp.addr) << std::endl; - } - } - else if(citem->banListType == RSBANLIST_TYPE_BLACKLIST) - { - mBanRanges.clear() ; - - for(std::list::const_iterator it2(citem->banned_peers.mList.begin());it2!=citem->banned_peers.mList.end();++it2) - { - BanListPeer blp ; - blp.fromRsTlvBanListEntry(*it2) ; - - if(sockaddr_storage_isValidNet(blp.addr)) - mBanRanges[makeBitsRange(blp.addr,blp.masked_bytes)] = blp ; - else - std::cerr << "(WW) removed wrong address " << sockaddr_storage_iptostring(blp.addr) << std::endl; - } - } - else if(citem->banListType == RSBANLIST_TYPE_WHITELIST) - { - mWhiteListedRanges.clear() ; - - for(std::list::const_iterator it2(citem->banned_peers.mList.begin());it2!=citem->banned_peers.mList.end();++it2) - { - BanListPeer blp ; - blp.fromRsTlvBanListEntry(*it2) ; - - if(sockaddr_storage_isValidNet(blp.addr)) - mWhiteListedRanges[makeBitsRange(blp.addr,blp.masked_bytes)] = blp ; - else - std::cerr << "(WW) removed wrong address " << sockaddr_storage_iptostring(blp.addr) << std::endl; - - std::cerr << "Read whitelisted range " << sockaddr_storage_iptostring(blp.addr) << "/" << 32 - 8*(blp.masked_bytes) << std::endl; - } - } - else - std::cerr << "(EE) BanList item unknown type " << citem->banListType << ". This is a bug." << std::endl; - } - - delete *it ; - } - - load.clear() ; - return true ; -} - -bool p3BanList::addBanEntry( const RsPeerId &peerId, - const sockaddr_storage &dAddr, - int level, uint32_t reason, rstime_t time_stamp ) -{ - sockaddr_storage addr; sockaddr_storage_copy(dAddr, addr); - if(!sockaddr_storage_ipv6_to_ipv4(addr)) - { - std::cerr << __PRETTY_FUNCTION__ << " Cannot handle " - << sockaddr_storage_tostring(dAddr) - << " IPv6 not implemented yet!" - << std::endl; - return false; - } - - RS_STACK_MUTEX(mBanMtx); - - rstime_t now = time(NULL); - bool updated = false; - -#ifdef DEBUG_BANLIST - std::cerr << "p3BanList::addBanEntry() Addr: " << sockaddr_storage_iptostring(addr) << " Origin: " << level; - std::cerr << " Reason: " << reason << " Age: " << now - time_stamp; - std::cerr << std::endl; -#endif - - /* Only Accept it - if external address */ - if (!sockaddr_storage_isExternalNet(addr)) - { -#ifdef DEBUG_BANLIST - std::cerr << "p3BanList::addBanEntry() Ignoring Non External Addr: " << sockaddr_storage_iptostring(addr); - std::cerr << std::endl; -#endif - return false; - } - - - std::map::iterator it; - it = mBanSources.find(peerId); - if (it == mBanSources.end()) - { - BanList bl; - bl.mPeerId = peerId; - bl.mLastUpdate = now; - mBanSources[peerId] = bl; - - it = mBanSources.find(peerId); - updated = true; - } - - // index is FAMILY + IP - the rest should be Zeros.. - struct sockaddr_storage bannedaddr; - sockaddr_storage_clear(bannedaddr); - bannedaddr.ss_family = AF_INET ; - sockaddr_storage_copyip(bannedaddr, addr); - sockaddr_storage_setport(bannedaddr, 0); - - std::map::iterator mit; - mit = it->second.mBanPeers.find(bannedaddr); - if (mit == it->second.mBanPeers.end()) - { - /* add in */ - BanListPeer blp; - blp.addr = addr; - blp.reason = reason; - blp.level = level; - blp.mTs = time_stamp ; - blp.masked_bytes = 0 ; - - it->second.mBanPeers[bannedaddr] = blp; - it->second.mLastUpdate = now; - updated = true; - } - else - { - /* see if it needs an update */ - if ((mit->second.reason != reason) || - (mit->second.level != uint32_t(level)) || - (mit->second.mTs < time_stamp)) - { - /* update */ - mit->second.addr = addr; - mit->second.reason = reason; - mit->second.level = level; - mit->second.mTs = time_stamp; - mit->second.masked_bytes = 0 ; - - it->second.mLastUpdate = now; - updated = true; - } - } - - if (updated) - IndicateConfigChanged() ; - - return updated; -} - -bool p3BanList::isWhiteListed_locked(const sockaddr_storage& addr) -{ - if(mWhiteListedRanges.find(makeBitsRange(addr,0)) != mWhiteListedRanges.end()) - return true ; - - if(mWhiteListedRanges.find(makeBitsRange(addr,1)) != mWhiteListedRanges.end()) - return true ; - - if(mWhiteListedRanges.find(makeBitsRange(addr,2)) != mWhiteListedRanges.end()) - return true ; - - return false ; - -} - -/*** - * EXTRA DEBUGGING. - * #define DEBUG_BANLIST_CONDENSE 1 - ***/ - -int p3BanList::condenseBanSources_locked() -{ - mBanSet.clear(); - - rstime_t now = time(NULL); - RsPeerId ownId = mServiceCtrl->getOwnId(); - -#ifdef DEBUG_BANLIST - std::cerr << "p3BanList::condenseBanSources_locked()"; - std::cerr << std::endl; -#endif - - std::map::const_iterator it; - for(it = mBanSources.begin(); it != mBanSources.end(); ++it) - { - if (now - it->second.mLastUpdate > RSBANLIST_ENTRY_MAX_AGE) - { -#ifdef DEBUG_BANLIST_CONDENSE - std::cerr << std::dec ; - std::cerr << "p3BanList::condenseBanSources_locked()"; - std::cerr << " Ignoring Out-Of-Date peer: " << it->first; - std::cerr << std::endl; -#endif - continue; - } - -#ifdef DEBUG_BANLIST_CONDENSE - std::cerr << std::dec ; - std::cerr << "p3BanList::condenseBanSources_locked()"; - std::cerr << " Condensing Info from peer: " << it->first; - std::cerr << std::endl; -#endif - - std::map::const_iterator lit; - for(lit = it->second.mBanPeers.begin(); lit != it->second.mBanPeers.end(); ++lit) - { - /* check timestamp */ - if (now > RSBANLIST_ENTRY_MAX_AGE + lit->second.mTs) - { -#ifdef DEBUG_BANLIST_CONDENSE - std::cerr << std::dec ; - std::cerr << "p3BanList::condenseBanSources_locked()"; - std::cerr << " Ignoring Out-Of-Date Entry for: "; - std::cerr << sockaddr_storage_iptostring(lit->second.addr); - std::cerr << " time stamp= " << lit->second.mTs << ", age=" << now - lit->second.mTs; - std::cerr << std::endl; -#endif - continue; - } - - uint32_t lvl = lit->second.level; - if (it->first != ownId) - { - /* as from someone else, increment level */ - lvl++; - } - - struct sockaddr_storage bannedaddr; - sockaddr_storage_clear(bannedaddr); - bannedaddr.ss_family = AF_INET; - sockaddr_storage_copyip(bannedaddr, lit->second.addr); - sockaddr_storage_setport(bannedaddr, 0); - - if (isWhiteListed_locked(bannedaddr)) - continue; - - /* check if it exists in the Set already */ - std::map::iterator sit; - sit = mBanSet.find(bannedaddr); - - if ((sit == mBanSet.end()) || (lvl < sit->second.level)) - { - BanListPeer bp = lit->second; - bp.level = lvl; - bp.masked_bytes = 0 ; - sockaddr_storage_setport(bp.addr, 0); - mBanSet[bannedaddr] = bp; -#ifdef DEBUG_BANLIST_CONDENSE - std::cerr << "p3BanList::condenseBanSources_locked()"; - std::cerr << " Added New Entry for: "; - std::cerr << sockaddr_storage_iptostring(bannedaddr); - std::cerr << std::endl; -#endif - } - else - { -#ifdef DEBUG_BANLIST_CONDENSE - std::cerr << "p3BanList::condenseBanSources_locked()"; - std::cerr << " Merging Info for: "; - std::cerr << sockaddr_storage_iptostring(bannedaddr); - std::cerr << std::endl; -#endif - /* update if necessary */ - if (lvl == sit->second.level) - { - sit->second.reason |= lit->second.reason; - if (sit->second.mTs < lit->second.mTs) - { - sit->second.mTs = lit->second.mTs; - } - } - } - } - } - - -#ifdef DEBUG_BANLIST - std::cerr << "p3BanList::condenseBanSources_locked() Printing New Set:"; - std::cerr << std::endl; - - printBanSet_locked(std::cerr); -#endif - - return true ; -} - - - -int p3BanList::sendPackets() -{ - rstime_t now = time(NULL); - rstime_t pt; - { - RsStackMutex stack(mBanMtx); /****** LOCKED MUTEX *******/ - pt = mSentListTime; - } - - if (now - pt > RSBANLIST_SEND_PERIOD) - { - sendBanLists(); - - RsStackMutex stack(mBanMtx); /****** LOCKED MUTEX *******/ - -#ifdef DEBUG_BANLIST - std::cerr << "p3BanList::sendPackets() Regular Broadcast"; - std::cerr << std::endl; - - printBanSources_locked(std::cerr); - printBanSet_locked(std::cerr); -#endif - - mSentListTime = now; - } - return true ; -} - -void p3BanList::sendBanLists() -{ - - /* we ping our peers */ - /* who is online? */ - std::set idList; - - mServiceCtrl->getPeersConnected(getServiceInfo().mServiceType, idList); - -#ifdef DEBUG_BANLIST - std::cerr << "p3BanList::sendBanList()"; - std::cerr << std::endl; -#endif - - /* prepare packets */ - std::set::iterator it; - for(it = idList.begin(); it != idList.end(); ++it) - { -#ifdef DEBUG_BANLIST - std::cerr << "p3BanList::sendBanList() To: " << *it; - std::cerr << std::endl; -#endif - sendBanSet(*it); - } -} - -// Send all manually banned ranges to friends - -int p3BanList::sendBanSet(const RsPeerId& peerid) -{ - /* */ - RsBanListItem *item = new RsBanListItem(); - item->PeerId(peerid); - - //rstime_t now = time(NULL); - - { - RsStackMutex stack(mBanMtx); /****** LOCKED MUTEX *******/ - std::map::iterator it; - for(it = mBanSet.begin(); it != mBanSet.end(); ++it) - { - if (it->second.level >= RSBANLIST_ORIGIN_FRIEND) - continue; // only share OWN for the moment. - - RsTlvBanListEntry bi; - it->second.toRsTlvBanListEntry(bi) ; - - bi.masked_bytes = 0 ; - bi.comment.clear() ; // don't send comments. - item->peerList.mList.push_back(bi); - } - } - - sendItem(item); - return 1; -} - - -int p3BanList::printBanSet_locked(std::ostream &out) -{ - rstime_t now = time(NULL); - - out << "p3BanList::printBanSet_locked()"; - out << " Only printing active filters (due to user options)."; - out << std::endl; - - std::map::iterator it; - for(it = mBanSet.begin(); it != mBanSet.end(); ++it) - if(acceptedBanSet_locked(it->second)) - { - out << "Ban: " << sockaddr_storage_iptostring(it->second.addr); - out << " Reason: " << it->second.reason; - out << " Level: " << it->second.level; - if (it->second.level > RSBANLIST_ORIGIN_FRIEND) - { - out << " (unused)"; - } - - out << " Age: " << now - it->second.mTs; - out << std::endl; - } - - std::cerr << "Current IP black list (only showing manual ranges, not automatically banned IPs): " << std::dec << std::endl; - - for(std::map::const_iterator it(mBanRanges.begin());it!=mBanRanges.end();++it) - if(acceptedBanRanges_locked(it->second)) - std::cerr << " " << sockaddr_storage_iptostring(it->first) << ". masked_bytes=" << (int)it->second.masked_bytes - << ", IP=" << sockaddr_storage_iptostring(it->second.addr) << "/" << ((int)32 - 8*(int)(it->second.masked_bytes)) << std::endl; - - std::cerr << "Current IP white list: " << std::endl; - - for(std::map::const_iterator it(mWhiteListedRanges.begin());it!=mWhiteListedRanges.end();++it) - if(acceptedBanRanges_locked(it->second)) - std::cerr << " " << sockaddr_storage_iptostring(it->first) << ". masked_bytes=" << (int)it->second.masked_bytes - << ", IP=" << sockaddr_storage_iptostring(it->second.addr) << "/" << ((int)32 - 8*(int)(it->second.masked_bytes)) << std::endl; - - return true ; -} - - - -int p3BanList::printBanSources_locked(std::ostream &out) -{ - rstime_t now = time(NULL); - - std::map::const_iterator it; - for(it = mBanSources.begin(); it != mBanSources.end(); ++it) - { - out << "BanList from: " << it->first; - out << " LastUpdate: " << now - it->second.mLastUpdate; - out << std::endl; - - std::map::const_iterator lit; - for(lit = it->second.mBanPeers.begin(); - lit != it->second.mBanPeers.end(); ++lit) - { - out << "\t"; - out << "Ban: " << sockaddr_storage_iptostring(lit->second.addr); - out << " Reason: " << lit->second.reason; - out << " Level: " << lit->second.level; - out << " Age: " << now - lit->second.mTs; - out << std::endl; - } - } - - return true ; -} - -RsBanList::~RsBanList() = default; diff --git a/libretroshare/src/services/p3banlist.h b/libretroshare/src/services/p3banlist.h deleted file mode 100644 index b61b7cb71..000000000 --- a/libretroshare/src/services/p3banlist.h +++ /dev/null @@ -1,166 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3banlist.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef SERVICE_RSBANLIST_HEADER -#define SERVICE_RSBANLIST_HEADER - -#include -#include -#include - -#include "rsitems/rsbanlistitems.h" -#include "services/p3service.h" -#include "retroshare/rsbanlist.h" - -class p3ServiceControl; -class p3NetMgr; - -class BanList -{ - public: - - RsPeerId mPeerId; /* from */ - rstime_t mLastUpdate; - std::map mBanPeers; -}; - -/** - * The RS BanList service. - * Exchange list of Banned IPv4 addresses with peers. - * - * @warning IPv4 only, IPv6 not supported yet! - */ -class p3BanList: public RsBanList, public p3Service, public pqiNetAssistPeerShare, public p3Config /*, public pqiMonitor */ -{ -public: - p3BanList(p3ServiceControl *sc, p3NetMgr *nm); - virtual RsServiceInfo getServiceInfo(); - - /***** overloaded from RsBanList *****/ - - /// @see RsBanList - virtual bool isAddressAccepted( - const sockaddr_storage& addr, uint32_t checking_flags, - uint32_t& check_result = RS_DEFAULT_STORAGE_PARAM(uint32_t) - ) override; - - virtual void getBannedIps(std::list& list) ; - virtual void getWhiteListedIps(std::list& list) ; - - virtual bool addIpRange( const sockaddr_storage& addr, int masked_bytes, - uint32_t list_type, const std::string& comment ); - virtual bool removeIpRange( const sockaddr_storage &addr, int masked_bytes, - uint32_t list_type ); - - virtual void enableIPFiltering(bool b) ; - virtual bool ipFilteringEnabled() ; - - virtual bool autoRangeEnabled() { return mAutoRangeIps ; } - virtual void enableAutoRange(bool b) ; - - virtual int autoRangeLimit() { return mAutoRangeLimit ; } - virtual void setAutoRangeLimit(int b) ; - - virtual void enableIPsFromFriends(bool b) ; - virtual bool IPsFromFriendsEnabled() { return mIPFriendGatheringEnabled ;} - - virtual void enableIPsFromDHT(bool b) ; - virtual bool iPsFromDHTEnabled() { return mIPDHTGatheringEnabled ;} - - /***** overloaded from pqiNetAssistPeerShare *****/ - - virtual void updatePeer( const RsPeerId& id, const sockaddr_storage &addr, - int type, int reason, int time_stamp ); - - /*********************** p3config ******************************/ - virtual RsSerialiser *setupSerialiser(); - virtual bool saveList(bool &cleanup, std::list& itemlist); - virtual bool loadList(std::list& load); - - /***** overloaded from p3Service *****/ - /*! - * This retrieves all chat msg items and also (important!) - * processes chat-status items that are in service item queue. chat msg item requests are also processed and not returned - * (important! also) notifications sent to notify base on receipt avatar, immediate status and custom status - * : notifyCustomState, notifyChatStatus, notifyPeerHasNewAvatar - * @see NotifyBase - - */ - virtual int tick(); - - int sendPackets(); - bool processIncoming(); - - bool recvBanItem(RsBanListItem *item); - bool addBanEntry( const RsPeerId &peerId, - const sockaddr_storage &addr, int level, uint32_t reason, - rstime_t time_stamp ); - void sendBanLists(); - int sendBanSet(const RsPeerId& peerid); - - - /*! - * Interface stuff. - */ - - /*************** pqiMonitor callback ***********************/ - //virtual void statusChange(const std::list &plist); - - - /************* from p3Config *******************/ - //virtual RsSerialiser *setupSerialiser() ; - //virtual bool saveList(bool& cleanup, std::list&) ; - //virtual void saveDone(); - //virtual bool loadList(std::list& load) ; - -private: - void getDhtInfo() ; - - RsMutex mBanMtx; - - bool acceptedBanSet_locked(const BanListPeer &blp); - bool acceptedBanRanges_locked(const BanListPeer &blp); - void autoFigureOutBanRanges(); - int condenseBanSources_locked(); - int printBanSources_locked(std::ostream &out); - int printBanSet_locked(std::ostream &out); - bool isWhiteListed_locked(const sockaddr_storage &addr); - - p3ServiceControl *mServiceCtrl; - //p3NetMgr *mNetMgr; - rstime_t mSentListTime; - std::map mBanSources; - std::map mBanSet; - std::map mBanRanges; - std::map mWhiteListedRanges; - - rstime_t mLastDhtInfoRequest ; - - uint32_t mAutoRangeLimit ; - bool mAutoRangeIps ; - - bool mIPFilteringEnabled ; - bool mIPFriendGatheringEnabled ; - bool mIPDHTGatheringEnabled ; -}; - -#endif // SERVICE_RSBANLIST_HEADER - diff --git a/libretroshare/src/services/p3bwctrl.cc b/libretroshare/src/services/p3bwctrl.cc deleted file mode 100644 index 65add3935..000000000 --- a/libretroshare/src/services/p3bwctrl.cc +++ /dev/null @@ -1,349 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3bwctrl.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "pqi/p3linkmgr.h" -#include "pqi/p3netmgr.h" -#include "pqi/pqipersongrp.h" - -#include "util/rsnet.h" - -#include "services/p3bwctrl.h" -#include "rsitems/rsbwctrlitems.h" - -#include - -/**** - * #define DEBUG_BWCTRL 1 - ****/ - - -/************ IMPLEMENTATION NOTES ********************************* - * - */ - -p3BandwidthControl *rsBandwidthControl; - - -p3BandwidthControl::p3BandwidthControl(pqipersongrp *pg) - :p3Service(), mPg(pg), mBwMtx("p3BwCtrl") -{ - addSerialType(new RsBwCtrlSerialiser()); - - mLastCheck = 0; -} - - -const std::string BANDWIDTH_CTRL_APP_NAME = "bandwidth_ctrl"; -const uint16_t BANDWIDTH_CTRL_APP_MAJOR_VERSION = 1; -const uint16_t BANDWIDTH_CTRL_APP_MINOR_VERSION = 0; -const uint16_t BANDWIDTH_CTRL_MIN_MAJOR_VERSION = 1; -const uint16_t BANDWIDTH_CTRL_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3BandwidthControl::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_BWCTRL, - BANDWIDTH_CTRL_APP_NAME, - BANDWIDTH_CTRL_APP_MAJOR_VERSION, - BANDWIDTH_CTRL_APP_MINOR_VERSION, - BANDWIDTH_CTRL_MIN_MAJOR_VERSION, - BANDWIDTH_CTRL_MIN_MINOR_VERSION); -} - - - -int p3BandwidthControl::tick() -{ - processIncoming(); - - bool doCheck = false; - { - RsStackMutex stack(mBwMtx); /****** LOCKED MUTEX *******/ - -#define CHECK_PERIOD 5 - - rstime_t now = time(NULL); - if (now - mLastCheck > CHECK_PERIOD) - { - doCheck = true; - mLastCheck = now; - } - } - - if (doCheck) - { - checkAvailableBandwidth(); - } - - return 0; -} - -int p3BandwidthControl::status() -{ - return 1; -} - - -/***** Implementation ******/ - - -bool p3BandwidthControl::checkAvailableBandwidth() -{ - /* check each connection status */ - std::map rateMap; - RsBwRates total; - - mPg->ExtractRates(rateMap, total); - std::map::iterator it; - std::map::iterator bit; - - /* have to merge with existing list, - * erasing as we go ... then any left have to deal with - */ - RsStackMutex stack(mBwMtx); /****** LOCKED MUTEX *******/ - - mTotalRates = total; - - rstime_t now = time(NULL); - std::list oldIds; // unused for now! - - for(bit = mBwMap.begin(); bit != mBwMap.end(); ++bit) - { - /* check alloc rate */ - //rstime_t age = now - bit->second.mLastSend; - - /* find a matching entry */ - it = rateMap.find(bit->first); - if (it == rateMap.end()) - { - oldIds.push_back(bit->first); - continue; - } - - //float delta = bit->second.mAllocated - it->second.mMaxRateIn; - /* if delta < 0 ... then need update (or else we get a queue) */ - /* if delta > 0 ... then need update (to allow more data) */ - - /* for the moment - always send an update */ - bool updatePeer = true; - -#if 0 - /* if changed significantly */ - if (sig) - { - updatePeer = true; - } - - /* if changed small but old */ - if ((any change) && (timeperiod)) - { - updatePeer = true; - } -#endif - - /* update rates info */ - bit->second.mRates = it->second; - bit->second.mRateUpdateTs = now; - - if (updatePeer) - { -#define ALLOC_FACTOR (1.0) - // save value sent, - bit->second.mAllocated = ALLOC_FACTOR * 1000.0 * it->second.mMaxRateIn; - bit->second.mLastSend = now; - - RsBwCtrlAllowedItem *item = new RsBwCtrlAllowedItem(); - item->PeerId(bit->first); - item->allowedBw = bit->second.mAllocated; - - sendItem(item); - } - - /* now cleanup */ - rateMap.erase(it); - } - - //printRateInfo_locked(std::cerr); - - /* any left over rateMaps ... are bad! (or not active - more likely) */ - return true; -} - - - -bool p3BandwidthControl::processIncoming() -{ - RsItem *item = NULL; - rstime_t now = time(NULL); - - while(NULL != (item = recvItem())) - { - RsBwCtrlAllowedItem *bci = dynamic_cast(item); - if (!bci) - { - delete item; - continue; - } - - /* For each packet */ - RsStackMutex stack(mBwMtx); /****** LOCKED MUTEX *******/ - std::map::iterator bit; - - bit = mBwMap.find(bci->PeerId()); - if (bit == mBwMap.end()) - { - // ERROR. - delete item; - continue; - } - - /* update allowed bandwidth */ - bit->second.mAllowedOut = bci->allowedBw; - bit->second.mLastRecvd = now; - delete item; - - /* store info in data */ - //mPg->setAllowedRate(bit->first, bit->second.mAllowedOut / 1000.0); - } - return true; -} - -int p3BandwidthControl::getTotalBandwidthRates(RsConfigDataRates &rates) -{ - RsStackMutex stack(mBwMtx); /****** LOCKED MUTEX *******/ - - rates.mRateIn = mTotalRates.mRateIn; - rates.mRateMaxIn = mTotalRates.mMaxRateIn; - rates.mRateOut = mTotalRates.mRateOut; - rates.mRateMaxOut = mTotalRates.mMaxRateOut; - - rates.mAllocIn = 0; - rates.mAllocTs = 0; - - rates.mAllowedOut = 0; - rates.mAllowedTs = 0; - - rates.mQueueIn = mTotalRates.mQueueIn; - rates.mQueueOut = mTotalRates.mQueueOut; - - return 1; -} - -int p3BandwidthControl::getAllBandwidthRates(std::map &ratemap) -{ - RsStackMutex stack(mBwMtx); /****** LOCKED MUTEX *******/ - - std::map::iterator bit; - for(bit = mBwMap.begin(); bit != mBwMap.end(); ++bit) - { - RsConfigDataRates rates; - - rates.mRateIn = bit->second.mRates.mRateIn; - rates.mRateMaxIn = bit->second.mRates.mMaxRateIn; - rates.mRateOut = bit->second.mRates.mRateOut; - rates.mRateMaxOut = bit->second.mRates.mMaxRateOut; - - rates.mAllocIn = bit->second.mAllocated / 1000.0; - rates.mAllocTs = bit->second.mLastSend; - - rates.mAllowedOut = bit->second.mAllowedOut / 1000.0; - rates.mAllowedTs = bit->second.mLastRecvd; - - rates.mQueueIn = bit->second.mRates.mQueueIn; - rates.mQueueOut = bit->second.mRates.mQueueOut; - - ratemap[bit->first] = rates; - } - return true ; - - -} - -int p3BandwidthControl::ExtractTrafficInfo(std::list& out_stats, std::list& in_stats) -{ - return mPg->ExtractTrafficInfo(out_stats,in_stats) ; -} - - - - - - -int p3BandwidthControl::printRateInfo_locked(std::ostream &out) -{ - out << "p3BandwidthControl::printRateInfo_locked()"; - out << std::endl; - - //rstime_t now = time(NULL); - out << "Totals: "; - out << " In: " << mTotalRates.mRateIn; - out << " MaxIn: " << mTotalRates.mMaxRateIn; - out << " Out: " << mTotalRates.mRateOut; - out << " MaxOut: " << mTotalRates.mMaxRateOut; - out << std::endl; - - std::map::iterator bit; - for(bit = mBwMap.begin(); bit != mBwMap.end(); ++bit) - { - out << "\t" << bit->first; - out << " In: " << bit->second.mRates.mRateIn; - out << " MaxIn: " << bit->second.mRates.mMaxRateIn; - out << " Out: " << bit->second.mRates.mRateOut; - out << " MaxOut: " << bit->second.mRates.mMaxRateOut; - out << std::endl; - } - return true ; -} - - /*************** pqiMonitor callback ***********************/ -void p3BandwidthControl::statusChange(const std::list &plist) -{ - std::list::const_iterator it; - for (it = plist.begin(); it != plist.end(); ++it) - { - RsStackMutex stack(mBwMtx); /****** LOCKED MUTEX *******/ - - if (it->actions & RS_SERVICE_PEER_DISCONNECTED) - { - /* remove from map */ - std::map::iterator bit; - bit = mBwMap.find(it->id); - if (bit == mBwMap.end()) - { - std::cerr << "p3BandwidthControl::statusChange() ERROR"; - std::cerr << " Entry not in map"; - std::cerr << std::endl; - } - else - { - mBwMap.erase(bit); - } - } - else if (it->actions & RS_SERVICE_PEER_CONNECTED) - { - /* stuff */ - BwCtrlData data; - mBwMap[it->id] = data; - } - } - return; -} - - diff --git a/libretroshare/src/services/p3bwctrl.h b/libretroshare/src/services/p3bwctrl.h deleted file mode 100644 index bd6276d5f..000000000 --- a/libretroshare/src/services/p3bwctrl.h +++ /dev/null @@ -1,126 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3bwctrl.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef SERVICE_RSBANDWIDTH_CONTROL_HEADER -#define SERVICE_RSBANDWIDTH_CONTROL_HEADER - -#include -#include -#include - -#include "rsitems/rsbwctrlitems.h" -#include "services/p3service.h" -#include "pqi/pqiservicemonitor.h" -#include "retroshare/rsconfig.h" // for datatypes. - -class pqipersongrp; - -// Extern is defined here - as this is bundled with rsconfig.h -class p3BandwidthControl; -extern p3BandwidthControl *rsBandwidthControl; - - -class BwCtrlData -{ - public: - BwCtrlData() - :mRateUpdateTs(0), mAllocated(0), mLastSend(0), mAllowedOut(0), mLastRecvd(0) - { return; } - - /* Rates are floats in KB/s */ - RsBwRates mRates; - rstime_t mRateUpdateTs; - - /* these are integers (B/s) */ - uint32_t mAllocated; - rstime_t mLastSend; - - uint32_t mAllowedOut; - rstime_t mLastRecvd; -}; - - -//!The RS bandwidth Control Service. - /** - * - * Exchange packets to regulate p2p bandwidth. - * - * Sadly this has to be strongly integrated into pqi, with ref to pqipersongrp. - */ - -class p3BandwidthControl: public p3Service, public pqiServiceMonitor -{ - public: - explicit p3BandwidthControl(pqipersongrp *pg); - virtual RsServiceInfo getServiceInfo(); - - /***** overloaded from RsBanList *****/ - - - /***** overloaded from p3Service *****/ - /*! - * This retrieves all BwCtrl items - */ - virtual int tick(); - virtual int status(); - - - /***** for RsConfig (not directly overloaded) ****/ - - virtual int getTotalBandwidthRates(RsConfigDataRates &rates); - virtual int getAllBandwidthRates(std::map &ratemap); - - - virtual int ExtractTrafficInfo(std::list &out_stats, std::list &in_stats); - - /*! - * Interface stuff. - */ - - /*************** pqiMonitor callback ***********************/ - virtual void statusChange(const std::list &plist); - - - /************* from p3Config *******************/ - //virtual RsSerialiser *setupSerialiser() ; - //virtual bool saveList(bool& cleanup, std::list&) ; - //virtual void saveDone(); - //virtual bool loadList(std::list& load) ; - -private: - - bool checkAvailableBandwidth(); - bool processIncoming(); - - pqipersongrp *mPg; - - RsMutex mBwMtx; - - int printRateInfo_locked(std::ostream &out); - - rstime_t mLastCheck; - - RsBwRates mTotalRates; - std::map mBwMap; - -}; - -#endif // SERVICE_RSBANDWIDTH_CONTROL_HEADER diff --git a/libretroshare/src/services/p3gxschannels.cc b/libretroshare/src/services/p3gxschannels.cc deleted file mode 100644 index 1ee9f6d75..000000000 --- a/libretroshare/src/services/p3gxschannels.cc +++ /dev/null @@ -1,2738 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3gxschannels.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Robert Fernie * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "services/p3gxschannels.h" -#include "rsitems/rsgxschannelitems.h" -#include "util/radix64.h" -#include "util/rsmemory.h" - -#include -#include - - -#include "retroshare/rsgxsflags.h" -#include "retroshare/rsfiles.h" -#include "retroshare/rspeers.h" - -#include "rsserver/p3face.h" -#include "retroshare/rsnotify.h" - -#include -#include -#include - -// For Dummy Msgs. -#include "util/rsrandom.h" -#include "util/rsstring.h" - -#ifdef RS_DEEP_CHANNEL_INDEX -# include "deep_search/channelsindex.hpp" -#endif // RS_DEEP_CHANNEL_INDEX - - -/**** - * #define GXSCHANNEL_DEBUG 1 - ****/ - -/*extern*/ RsGxsChannels* rsGxsChannels = nullptr; - - -#define GXSCHANNEL_STOREPERIOD (3600 * 24 * 30) - -#define GXSCHANNELS_SUBSCRIBED_META 1 -#define GXSCHANNELS_UNPROCESSED_SPECIFIC 2 -#define GXSCHANNELS_UNPROCESSED_GENERIC 3 - -#define CHANNEL_PROCESS 0x0001 -#define CHANNEL_TESTEVENT_DUMMYDATA 0x0002 -#define DUMMYDATA_PERIOD 60 // Long enough for some RsIdentities to be generated. - -#define CHANNEL_DOWNLOAD_PERIOD (3600 * 24 * 7) -#define CHANNEL_MAX_AUTO_DL (8 * 1024 * 1024 * 1024ull) // 8 GB. Just a security ;-) -#define CHANNEL_UNUSED_BY_FRIENDS_DELAY (3600*24*60) // Two months. Will be used to delete a channel if too old -#define CHANNEL_DELAY_FOR_CHECKING_AND_DELETING_OLD_GROUPS 300 // check for old channels every 30 mins. Far too often than above delay by RS needs to run it at least once per session - -/********************************************************************************/ -/******************* Startup / Tick ******************************************/ -/********************************************************************************/ - -p3GxsChannels::p3GxsChannels( - RsGeneralDataService *gds, RsNetworkExchangeService *nes, - RsGixs* gixs ) : - RsGenExchange( gds, nes, new RsGxsChannelSerialiser(), - RS_SERVICE_GXS_TYPE_CHANNELS, gixs, channelsAuthenPolicy() ), - RsGxsChannels(static_cast(*this)), GxsTokenQueue(this), - mSubscribedGroupsMutex("GXS channels subscribed groups cache"), - mKnownChannelsMutex("GXS channels known channels timestamp cache") -#ifdef TO_REMOVE - mSearchCallbacksMapMutex("GXS channels search callbacks map"), - mDistantChannelsCallbacksMapMutex("GXS channels distant channels callbacks map") -#endif -{ - // For Dummy Msgs. - mGenActive = false; - mLastDistantSearchNotificationTS = 0; - mCommentService = new p3GxsCommentService(this, RS_SERVICE_GXS_TYPE_CHANNELS); - - // This is not needed since it just loads all channel data ever 5 mins which takes a lot - // of useless CPU/memory. - // - RsTickEvent::schedule_in(CHANNEL_PROCESS, 0); - // - // Test Data disabled in repo. - // - // RsTickEvent::schedule_in(CHANNEL_TESTEVENT_DUMMYDATA, DUMMYDATA_PERIOD); - - mGenToken = 0; - mGenCount = 0; -} - - -const std::string GXS_CHANNELS_APP_NAME = "gxschannels"; -const uint16_t GXS_CHANNELS_APP_MAJOR_VERSION = 1; -const uint16_t GXS_CHANNELS_APP_MINOR_VERSION = 0; -const uint16_t GXS_CHANNELS_MIN_MAJOR_VERSION = 1; -const uint16_t GXS_CHANNELS_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3GxsChannels::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_GXS_TYPE_CHANNELS, - GXS_CHANNELS_APP_NAME, - GXS_CHANNELS_APP_MAJOR_VERSION, - GXS_CHANNELS_APP_MINOR_VERSION, - GXS_CHANNELS_MIN_MAJOR_VERSION, - GXS_CHANNELS_MIN_MINOR_VERSION); -} - - -uint32_t p3GxsChannels::channelsAuthenPolicy() -{ - uint32_t policy = 0; - uint32_t flag = 0; - - flag = GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS); - - flag |= GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS); - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS); - - flag = 0; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::GRP_OPTION_BITS); - - return policy; -} - -static const uint32_t GXS_CHANNELS_CONFIG_MAX_TIME_NOTIFY_STORAGE = 86400*30*2 ; // ignore notifications for 2 months -static const uint8_t GXS_CHANNELS_CONFIG_SUBTYPE_NOTIFY_RECORD = 0x01 ; - -struct RsGxsChannelNotifyRecordsItem: public RsItem -{ - - RsGxsChannelNotifyRecordsItem() - : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_GXS_TYPE_CHANNELS_CONFIG,GXS_CHANNELS_CONFIG_SUBTYPE_NOTIFY_RECORD) - {} - - virtual ~RsGxsChannelNotifyRecordsItem() {} - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { RS_SERIAL_PROCESS(records); } - - void clear() {} - - std::map records; -}; - -class GxsChannelsConfigSerializer : public RsServiceSerializer -{ -public: - GxsChannelsConfigSerializer() : RsServiceSerializer(RS_SERVICE_GXS_TYPE_CHANNELS_CONFIG) {} - virtual ~GxsChannelsConfigSerializer() {} - - RsItem* create_item(uint16_t service_id, uint8_t item_sub_id) const - { - if(service_id != RS_SERVICE_GXS_TYPE_CHANNELS_CONFIG) - return NULL; - - switch(item_sub_id) - { - case GXS_CHANNELS_CONFIG_SUBTYPE_NOTIFY_RECORD: return new RsGxsChannelNotifyRecordsItem(); - default: - return NULL; - } - } -}; - -bool p3GxsChannels::saveList(bool &cleanup, std::list&saveList) -{ - cleanup = true ; - - RsGxsChannelNotifyRecordsItem *item = new RsGxsChannelNotifyRecordsItem ; - - { - RS_STACK_MUTEX(mKnownChannelsMutex); - item->records = mKnownChannels; - } - - saveList.push_back(item) ; - return true; -} - -bool p3GxsChannels::loadList(std::list& loadList) -{ - while(!loadList.empty()) - { - RsItem *item = loadList.front(); - loadList.pop_front(); - - rstime_t now = time(NULL); - - RsGxsChannelNotifyRecordsItem *fnr = dynamic_cast(item) ; - - if(fnr) - { - RS_STACK_MUTEX(mKnownChannelsMutex); - mKnownChannels.clear(); - - for(auto it(fnr->records.begin());it!=fnr->records.end();++it) - if(now < it->second + GXS_CHANNELS_CONFIG_MAX_TIME_NOTIFY_STORAGE) - mKnownChannels.insert(*it) ; - } - - delete item ; - } - return true; -} - -RsSerialiser* p3GxsChannels::setupSerialiser() -{ - RsSerialiser* rss = new RsSerialiser; - rss->addSerialType(new GxsChannelsConfigSerializer()); - - return rss; -} - - - /** Overloaded to cache new groups **/ -RsGenExchange::ServiceCreate_Return p3GxsChannels::service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& /* keySet */) -{ - updateSubscribedGroup(grpItem->meta); - return SERVICE_CREATE_SUCCESS; -} - - -void p3GxsChannels::notifyChanges(std::vector &changes) -{ -#ifdef GXSCHANNEL_DEBUG - RsDbg() << " Processing " << changes.size() << " channel changes..." << std::endl; -#endif - /* iterate through and grab any new messages */ - std::set unprocessedGroups; - - std::vector::iterator it; - for(it = changes.begin(); it != changes.end(); ++it) - { - RsGxsMsgChange *msgChange = dynamic_cast(*it); - - if (msgChange) - { - if (msgChange->getType() == RsGxsNotify::TYPE_RECEIVED_NEW|| msgChange->getType() == RsGxsNotify::TYPE_PUBLISHED) - { - /* message received */ - if (rsEvents) - { - auto ev = std::make_shared(); - - ev->mChannelMsgId = msgChange->mMsgId; - ev->mChannelGroupId = msgChange->mGroupId; - - if(nullptr != dynamic_cast(msgChange->mNewMsgItem)) - ev->mChannelEventCode = RsChannelEventCode::NEW_COMMENT; - else - if(nullptr != dynamic_cast(msgChange->mNewMsgItem)) - ev->mChannelEventCode = RsChannelEventCode::NEW_VOTE; - else - ev->mChannelEventCode = RsChannelEventCode::NEW_MESSAGE; - - rsEvents->postEvent(ev); - } - } - - if (!msgChange->metaChange()) - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::notifyChanges() Found Message Change Notification"; - std::cerr << std::endl; -#endif - -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::notifyChanges() Msgs for Group: " << mit->first; - std::cerr << std::endl; -#endif - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::notifyChanges() AutoDownload for Group: " << mit->first; - std::cerr << std::endl; -#endif - - /* problem is most of these will be comments and votes, should make it occasional - every 5mins / 10minutes TODO */ - // We do not call if(autoDownLoadEnabled()) here, because it would be too costly when - // many msgs are received from the same group. We back the groupIds and then request one by one. - - unprocessedGroups.insert(msgChange->mGroupId); - } - } - } - - RsGxsGroupChange *grpChange = dynamic_cast(*it); - - if (grpChange && rsEvents) - { -#ifdef GXSCHANNEL_DEBUG - RsDbg() << " Grp Change Event or type " << grpChange->getType() << ":" << std::endl; -#endif - - switch (grpChange->getType()) - { - case RsGxsNotify::TYPE_PROCESSED: // happens when the group is subscribed - { - auto ev = std::make_shared(); - ev->mChannelGroupId = grpChange->mGroupId; - ev->mChannelEventCode = RsChannelEventCode::SUBSCRIBE_STATUS_CHANGED; - rsEvents->postEvent(ev); - - unprocessedGroups.insert(grpChange->mGroupId); - } - break; - - case RsGxsNotify::TYPE_GROUP_SYNC_PARAMETERS_UPDATED: - { - auto ev = std::make_shared(); - ev->mChannelGroupId = grpChange->mGroupId; - ev->mChannelEventCode = RsChannelEventCode::SYNC_PARAMETERS_UPDATED; - rsEvents->postEvent(ev); - - unprocessedGroups.insert(grpChange->mGroupId); - } - break; - - case RsGxsNotify::TYPE_STATISTICS_CHANGED: - { - auto ev = std::make_shared(); - ev->mChannelGroupId = grpChange->mGroupId; - ev->mChannelEventCode = RsChannelEventCode::STATISTICS_CHANGED; - rsEvents->postEvent(ev); - - // also update channel usage. Statistics are updated when a friend sends some sync packets - RS_STACK_MUTEX(mKnownChannelsMutex); - mKnownChannels[grpChange->mGroupId] = time(NULL); - IndicateConfigChanged(); - } - break; - - case RsGxsNotify::TYPE_UPDATED: - { - auto ev = std::make_shared(); - ev->mChannelGroupId = grpChange->mGroupId; - ev->mChannelEventCode = RsChannelEventCode::UPDATED_CHANNEL; - rsEvents->postEvent(ev); - - unprocessedGroups.insert(grpChange->mGroupId); - } - break; - - case RsGxsNotify::TYPE_PUBLISHED: - case RsGxsNotify::TYPE_RECEIVED_NEW: - { - /* group received or updated */ - - bool unknown ; - { - RS_STACK_MUTEX(mKnownChannelsMutex); - - unknown = (mKnownChannels.find(grpChange->mGroupId) == mKnownChannels.end()); - mKnownChannels[grpChange->mGroupId] = time(NULL); - IndicateConfigChanged(); - } - -#ifdef GXSCHANNEL_DEBUG - RsDbg() << " Type = Published/New " << std::endl; -#endif - if(unknown) - { -#ifdef GXSCHANNEL_DEBUG - RsDbg() << " Status: unknown. Sending notification event." << std::endl; -#endif - auto ev = std::make_shared(); - ev->mChannelGroupId = grpChange->mGroupId; - ev->mChannelEventCode = RsChannelEventCode::NEW_CHANNEL; - rsEvents->postEvent(ev); - } -#ifdef GXSCHANNEL_DEBUG - else - RsDbg() << " Not notifying already known channel " << grpChange->mGroupId << std::endl; -#endif - - unprocessedGroups.insert(grpChange->mGroupId); - } - break; - - case RsGxsNotify::TYPE_GROUP_DELETED: - { - auto ev = std::make_shared(); - ev->mChannelGroupId = grpChange->mGroupId; - ev->mChannelEventCode = RsChannelEventCode::DELETED_CHANNEL; - rsEvents->postEvent(ev); - - unprocessedGroups.insert(grpChange->mGroupId); - } - break; - - case RsGxsNotify::TYPE_RECEIVED_PUBLISHKEY: - { - /* group received */ - auto ev = std::make_shared(); - ev->mChannelGroupId = grpChange->mGroupId; - ev->mChannelEventCode = RsChannelEventCode::RECEIVED_PUBLISH_KEY; - - rsEvents->postEvent(ev); - - unprocessedGroups.insert(grpChange->mGroupId); - } - break; - - default: - RsErr() << " Got a GXS event of type " << grpChange->getType() << " Currently not handled." << std::endl; - break; - } - } - - /* shouldn't need to worry about groups - as they need to be subscribed to */ - delete *it; - } - - std::list grps; - for(auto& grp_id:unprocessedGroups) - grps.push_back(grp_id); - - if(!grps.empty()) - request_SpecificSubscribedGroups(grps); -} - -void p3GxsChannels::service_tick() -{ - static rstime_t last_dummy_tick = 0; - rstime_t now = time(NULL); - - if (time(NULL) > last_dummy_tick + 5) - { - dummy_tick(); - last_dummy_tick = now; - } - - RsTickEvent::tick_events(); - GxsTokenQueue::checkRequests(); - - mCommentService->comment_tick(); - - // Notify distant search results, not more than once per sec. Normally we should - // rather send one item for all, but that needs another class type - - if(now > mLastDistantSearchNotificationTS+2 && !mSearchResultsToNotify.empty()) - { - auto ev = std::make_shared(); - ev->mSearchResultsMap = mSearchResultsToNotify; - - mLastDistantSearchNotificationTS = now; - mSearchResultsToNotify.clear(); - - rsEvents->postEvent(ev); - } -} - -bool p3GxsChannels::service_checkIfGroupIsStillUsed(const RsGxsGrpMetaData& meta) -{ -#ifdef GXSFORUMS_CHANNELS - std::cerr << "p3gxsChannels: Checking unused channel: called by GxsCleaning." << std::endl; -#endif - - // request all group infos at once - - rstime_t now = time(nullptr); - - RS_STACK_MUTEX(mKnownChannelsMutex); - - auto it = mKnownChannels.find(meta.mGroupId); - bool unknown_channel = it == mKnownChannels.end(); - -#ifdef GXSFORUMS_CHANNELS - std::cerr << " Channel " << meta.mGroupId ; -#endif - - if(unknown_channel) - { - // This case should normally not happen. It does because this channel was never registered since it may - // arrived before this code was here - -#ifdef GXSFORUMS_CHANNELS - std::cerr << ". Not known yet. Adding current time as new TS." << std::endl; -#endif - mKnownChannels[meta.mGroupId] = now; - IndicateConfigChanged(); - - return true; - } - else - { - bool used_by_friends = (now < it->second + CHANNEL_UNUSED_BY_FRIENDS_DELAY); - bool subscribed = static_cast(meta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED); - -#ifdef GXSFORUMS_CHANNELS - std::cerr << ". subscribed: " << subscribed << ", used_by_friends: " << used_by_friends << " last TS: " << now - it->second << " secs ago (" << (now-it->second)/86400 << " days)"; -#endif - - if(!subscribed && !used_by_friends) - { -#ifdef GXSFORUMS_CHANNELS - std::cerr << ". Scheduling for deletion" << std::endl; -#endif - return false; - } - else - { -#ifdef GXSFORUMS_CHANNELS - std::cerr << ". Keeping!" << std::endl; -#endif - return true; - } - } -} - -bool p3GxsChannels::getGroupData(const uint32_t &token, std::vector &groups) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::getGroupData()"; - std::cerr << std::endl; -#endif - - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); ++vit) - { - RsGxsChannelGroupItem* item = dynamic_cast(*vit); - if (item) - { - RsGxsChannelGroup grp; - item->toChannelGroup(grp, true); - delete item; - groups.push_back(grp); - } - else - { - std::cerr << "p3GxsChannels::getGroupData() ERROR in decode"; - std::cerr << std::endl; - delete(*vit); - } - } - } - else - { - std::cerr << "p3GxsChannels::getGroupData() ERROR in request"; - std::cerr << std::endl; - } - - return ok; -} - -bool p3GxsChannels::groupShareKeys( - const RsGxsGroupId &groupId, const std::set& peers ) -{ - RsGenExchange::shareGroupPublishKey(groupId,peers); - return true; -} - - -/* Okay - chris is not going to be happy with this... - * but I can't be bothered with crazy data structures - * at the moment - fix it up later - */ - -bool p3GxsChannels::getPostData( const uint32_t& token, std::vector& msgs, - std::vector& cmts, - std::vector& vots) -{ -#ifdef GXSCHANNELS_DEBUG - RsDbg() << __PRETTY_FUNCTION__ << std::endl; -#endif - - GxsMsgDataMap msgData; - if(!RsGenExchange::getMsgData(token, msgData)) - { - RsErr() << __PRETTY_FUNCTION__ << " ERROR in request" << std::endl; - return false; - } - - GxsMsgDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsChannelPostItem* postItem = - dynamic_cast(*vit); - - if(postItem) - { - RsGxsChannelPost msg; - postItem->toChannelPost(msg, true); - msgs.push_back(msg); - delete postItem; - } - else - { - RsGxsCommentItem* cmtItem = - dynamic_cast(*vit); - if(cmtItem) - { - RsGxsComment cmt; - RsGxsMsgItem *mi = (*vit); - cmt = cmtItem->mMsg; - cmt.mMeta = mi->meta; -#ifdef GXSCOMMENT_DEBUG - RsDbg() << __PRETTY_FUNCTION__ << " Found Comment:" << std::endl; - cmt.print(std::cerr," ", "cmt"); -#endif - cmts.push_back(cmt); - delete cmtItem; - } - else - { - RsGxsVoteItem* votItem = - dynamic_cast(*vit); - if(votItem) - { - RsGxsVote vot; - RsGxsMsgItem *mi = (*vit); - vot = votItem->mMsg; - vot.mMeta = mi->meta; - vots.push_back(vot); - delete votItem; - } - else - { - RsGxsMsgItem* msg = (*vit); - //const uint16_t RS_SERVICE_GXS_TYPE_CHANNELS = 0x0217; - //const uint8_t RS_PKT_SUBTYPE_GXSCHANNEL_POST_ITEM = 0x03; - //const uint8_t RS_PKT_SUBTYPE_GXSCOMMENT_COMMENT_ITEM = 0xf1; - //const uint8_t RS_PKT_SUBTYPE_GXSCOMMENT_VOTE_ITEM = 0xf2; - RsErr() << __PRETTY_FUNCTION__ - << " Not a GxsChannelPostItem neither a " - << "RsGxsCommentItem neither a RsGxsVoteItem" - << " PacketService=" << std::hex << (int)msg->PacketService() << std::dec - << " PacketSubType=" << std::hex << (int)msg->PacketSubType() << std::dec - << " type name =" << typeid(*msg).name() - << " , deleting!" << std::endl; - delete *vit; - } - } - } - } - } - - return true; -} - -bool p3GxsChannels::getPostData( - const uint32_t& token, std::vector& posts, std::vector& cmts ) -{ - std::vector vots; - return getPostData(token, posts, cmts, vots); -} - -bool p3GxsChannels::getPostData( - const uint32_t& token, std::vector& posts ) -{ - std::vector cmts; - std::vector vots; - return getPostData(token, posts, cmts, vots); -} - -//Not currently used -/*bool p3GxsChannels::getRelatedPosts(const uint32_t &token, std::vector &msgs) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::getRelatedPosts()"; - std::cerr << std::endl; -#endif - - GxsMsgRelatedDataMap msgData; - bool ok = RsGenExchange::getMsgRelatedData(token, msgData); - - if(ok) - { - GxsMsgRelatedDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsChannelPostItem* item = dynamic_cast(*vit); - - if(item) - { - RsGxsChannelPost msg; - item->toChannelPost(msg, true); - msgs.push_back(msg); - delete item; - } - else - { - RsGxsCommentItem* cmt = dynamic_cast(*vit); - if(!cmt) - { - RsGxsMsgItem* msg = (*vit); - //const uint16_t RS_SERVICE_GXS_TYPE_CHANNELS = 0x0217; - //const uint8_t RS_PKT_SUBTYPE_GXSCHANNEL_POST_ITEM = 0x03; - //const uint8_t RS_PKT_SUBTYPE_GXSCOMMENT_COMMENT_ITEM = 0xf1; - std::cerr << "Not a GxsChannelPostItem neither a RsGxsCommentItem" - << " PacketService=" << std::hex << (int)msg->PacketService() << std::dec - << " PacketSubType=" << std::hex << (int)msg->PacketSubType() << std::dec - << " , deleting!" << std::endl; - } - delete *vit; - } - } - } - } - else - { - std::cerr << "p3GxsChannels::getRelatedPosts() ERROR in request"; - std::cerr << std::endl; - } - - return ok; -}*/ - - -/********************************************************************************************/ -/********************************************************************************************/ - -bool p3GxsChannels::setChannelAutoDownload(const RsGxsGroupId &groupId, bool enabled) -{ - return setAutoDownload(groupId, enabled); -} - - -bool p3GxsChannels::getChannelAutoDownload(const RsGxsGroupId &groupId, bool& enabled) -{ - return autoDownloadEnabled(groupId,enabled); -} - -bool p3GxsChannels::setChannelDownloadDirectory( - const RsGxsGroupId &groupId, const std::string& directory ) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " id: " << groupId << " to: " - << directory << std::endl; -#endif - - RS_STACK_MUTEX(mSubscribedGroupsMutex); - - std::map::iterator it; - it = mSubscribedGroups.find(groupId); - if (it == mSubscribedGroups.end()) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Unknown groupId: " - << groupId.toStdString() << std::endl; - return false; - } - - /* extract from ServiceString */ - GxsChannelGroupInfo ss; - ss.load(it->second.mServiceString); - - if (directory == ss.mDownloadDirectory) - { - std::cerr << __PRETTY_FUNCTION__ << " Warning! groupId: " << groupId - << " Was already configured to download into: " << directory - << std::endl; - return false; - } - - ss.mDownloadDirectory = directory; - std::string serviceString = ss.save(); - uint32_t token; - - it->second.mServiceString = serviceString; // update Local Cache. - RsGenExchange::setGroupServiceString(token, groupId, serviceString); // update dbase. - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Feiled setting group " - << " service string" << std::endl; - return false; - } - - /* now reload it */ - std::list groups; - groups.push_back(groupId); - - request_SpecificSubscribedGroups(groups); - - return true; -} - -bool p3GxsChannels::getChannelDownloadDirectory(const RsGxsGroupId & groupId,std::string& directory) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::getChannelDownloadDirectory(" << id << ")" << std::endl; -#endif - - RS_STACK_MUTEX(mSubscribedGroupsMutex); - - std::map::iterator it; - - it = mSubscribedGroups.find(groupId); - if (it == mSubscribedGroups.end()) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Unknown groupId: " - << groupId.toStdString() << std::endl; - return false; - } - - /* extract from ServiceString */ - GxsChannelGroupInfo ss; - ss.load(it->second.mServiceString); - directory = ss.mDownloadDirectory; - - return true; -} - -void p3GxsChannels::request_AllSubscribedGroups() -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::request_SubscribedGroups()"; - std::cerr << std::endl; -#endif // GXSCHANNELS_DEBUG - - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; - - uint32_t token = 0; - - RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); - GxsTokenQueue::queueRequest(token, GXSCHANNELS_SUBSCRIBED_META); - -//#define PERIODIC_ALL_PROCESS 300 // This -// RsTickEvent::schedule_in(CHANNEL_PROCESS, PERIODIC_ALL_PROCESS); -} - - -void p3GxsChannels::request_SpecificSubscribedGroups( const std::list &groups ) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::request_SpecificSubscribedGroups()"; - std::cerr << std::endl; -#endif // GXSCHANNELS_DEBUG - - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; - - uint32_t token = 0; - - if(!RsGenExchange::getTokenService()-> requestGroupInfo(token, ansType, opts, groups)) - { - std::cerr << __PRETTY_FUNCTION__ << " Failed requesting groups info!" - << std::endl; - return; - } - - if(!GxsTokenQueue::queueRequest(token, GXSCHANNELS_SUBSCRIBED_META)) - { - std::cerr << __PRETTY_FUNCTION__ << " Failed queuing request!" - << std::endl; - } -} - - -void p3GxsChannels::load_SubscribedGroups(const uint32_t &token) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::load_SubscribedGroups()"; - std::cerr << std::endl; -#endif // GXSCHANNELS_DEBUG - - std::list groups; - std::list groupList; - - getGroupMeta(token, groups); - - std::list::iterator it; - for(it = groups.begin(); it != groups.end(); ++it) - { - if (it->mSubscribeFlags & - (GXS_SERV::GROUP_SUBSCRIBE_ADMIN | - GXS_SERV::GROUP_SUBSCRIBE_PUBLISH | - GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED )) - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::load_SubscribedGroups() updating Subscribed Group: " << it->mGroupId; - std::cerr << std::endl; -#endif - - updateSubscribedGroup(*it); - bool enabled = false ; - - if (autoDownloadEnabled(it->mGroupId,enabled) && enabled) - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::load_SubscribedGroups() remembering AutoDownload Group: " << it->mGroupId; - std::cerr << std::endl; -#endif - groupList.push_back(it->mGroupId); - } - } - else - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::load_SubscribedGroups() clearing unsubscribed Group: " << it->mGroupId; - std::cerr << std::endl; -#endif - clearUnsubscribedGroup(it->mGroupId); - } - } - - /* Query for UNPROCESSED POSTS from checkGroupList */ - request_GroupUnprocessedPosts(groupList); -} - - - -void p3GxsChannels::updateSubscribedGroup(const RsGroupMetaData &group) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::updateSubscribedGroup() id: " << group.mGroupId; - std::cerr << std::endl; -#endif - - RS_STACK_MUTEX(mSubscribedGroupsMutex); - mSubscribedGroups[group.mGroupId] = group; -} - - -void p3GxsChannels::clearUnsubscribedGroup(const RsGxsGroupId &id) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::clearUnsubscribedGroup() id: " << id; - std::cerr << std::endl; -#endif - - RS_STACK_MUTEX(mSubscribedGroupsMutex); - std::map::iterator it; - it = mSubscribedGroups.find(id); - if (it != mSubscribedGroups.end()) - { - mSubscribedGroups.erase(it); - } -} - - -bool p3GxsChannels::subscribeToGroup(uint32_t &token, const RsGxsGroupId &groupId, bool subscribe) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::subscribedToGroup() id: " << groupId << " subscribe: " << subscribe; - std::cerr << std::endl; -#endif - - std::list groups; - groups.push_back(groupId); - - // Call down to do the real work. - bool response = RsGenExchange::subscribeToGroup(token, groupId, subscribe); - - // reload Group afterwards. - request_SpecificSubscribedGroups(groups); - - return response; -} - - -void p3GxsChannels::request_SpecificUnprocessedPosts(std::list > &ids) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::request_SpecificUnprocessedPosts()"; - std::cerr << std::endl; -#endif // GXSCHANNELS_DEBUG - - uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - - // Only Fetch UNPROCESSED messages. - opts.mStatusFilter = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - opts.mStatusMask = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - - uint32_t token = 0; - - /* organise Ids how they want them */ - GxsMsgReq msgIds; - std::list >::iterator it; - for(it = ids.begin(); it != ids.end(); ++it) - msgIds[it->first].insert(it->second); - - RsGenExchange::getTokenService()->requestMsgInfo(token, ansType, opts, msgIds); - GxsTokenQueue::queueRequest(token, GXSCHANNELS_UNPROCESSED_SPECIFIC); -} - - -void p3GxsChannels::request_GroupUnprocessedPosts(const std::list &grouplist) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::request_GroupUnprocessedPosts()"; - std::cerr << std::endl; -#endif // GXSCHANNELS_DEBUG - - uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - - // Only Fetch UNPROCESSED messages. - opts.mStatusFilter = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - opts.mStatusMask = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - - uint32_t token = 0; - - RsGenExchange::getTokenService()->requestMsgInfo(token, ansType, opts, grouplist); - GxsTokenQueue::queueRequest(token, GXSCHANNELS_UNPROCESSED_GENERIC); -} - - -void p3GxsChannels::load_unprocessedPosts(uint32_t token) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::load_SpecificUnprocessedPosts" << std::endl; -#endif - - std::vector posts; - if (!getPostData(token, posts)) - { - std::cerr << __PRETTY_FUNCTION__ << " ERROR getting post data!" - << std::endl; - return; - } - - std::vector::iterator it; - for(it = posts.begin(); it != posts.end(); ++it) - { - /* autodownload the files */ - handleUnprocessedPost(*it); - } -} - -void p3GxsChannels::handleUnprocessedPost(const RsGxsChannelPost &msg) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " GroupId: " << msg.mMeta.mGroupId - << " MsgId: " << msg.mMeta.mMsgId << std::endl; -#endif - - if (!IS_MSG_UNPROCESSED(msg.mMeta.mMsgStatus)) - { - std::cerr << __PRETTY_FUNCTION__ << " ERROR Msg already Processed! " - << "mMsgId: " << msg.mMeta.mMsgId << std::endl; - return; - } - - /* check that autodownload is set */ - bool enabled = false; - if (autoDownloadEnabled(msg.mMeta.mGroupId, enabled) && enabled) - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " AutoDownload Enabled... handling" - << std::endl; -#endif - - /* check the date is not too old */ - rstime_t age = time(NULL) - msg.mMeta.mPublishTs; - - if (age < (rstime_t) CHANNEL_DOWNLOAD_PERIOD ) - { - /* start download */ - // NOTE WE DON'T HANDLE PRIVATE CHANNELS HERE. - // MORE THOUGHT HAS TO GO INTO THAT STUFF. - -#ifdef GXSCHANNELS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " START DOWNLOAD" << std::endl; -#endif - - std::list::const_iterator fit; - for(fit = msg.mFiles.begin(); fit != msg.mFiles.end(); ++fit) - { - std::string fname = fit->mName; - Sha1CheckSum hash = Sha1CheckSum(fit->mHash); - uint64_t size = fit->mSize; - - std::list srcIds; - std::string localpath = ""; - TransferRequestFlags flags = RS_FILE_REQ_BACKGROUND | RS_FILE_REQ_ANONYMOUS_ROUTING; - - if (size < CHANNEL_MAX_AUTO_DL) - { - std::string directory ; - if(getChannelDownloadDirectory(msg.mMeta.mGroupId,directory)) - localpath = directory ; - - rsFiles->FileRequest(fname, hash, size, localpath, flags, srcIds); - } - else - std::cerr << __PRETTY_FUNCTION__ << "Channel file is not auto-" - << "downloaded because its size exceeds the threshold" - << " of " << CHANNEL_MAX_AUTO_DL << " bytes." - << std::endl; - } - } - - /* mark as processed */ - uint32_t token; - RsGxsGrpMsgIdPair msgId(msg.mMeta.mGroupId, msg.mMeta.mMsgId); - setMessageProcessedStatus(token, msgId, true); - } -#ifdef GXSCHANNELS_DEBUG - else - { - std::cerr << "p3GxsChannels::handleUnprocessedPost() AutoDownload Disabled ... skipping"; - std::cerr << std::endl; - } -#endif -} - - - // Overloaded from GxsTokenQueue for Request callbacks. -void p3GxsChannels::handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::handleResponse(" << token << "," << req_type << "," << status << ")" << std::endl; -#endif // GXSCHANNELS_DEBUG - if (status != RsTokenService::COMPLETE) - return; //For now, only manage Complete request - - // stuff. - switch(req_type) - { - case GXSCHANNELS_SUBSCRIBED_META: - load_SubscribedGroups(token); - break; - - case GXSCHANNELS_UNPROCESSED_SPECIFIC: - load_unprocessedPosts(token); - break; - - case GXSCHANNELS_UNPROCESSED_GENERIC: - load_unprocessedPosts(token); - break; - - default: - std::cerr << __PRETTY_FUNCTION__ << "ERROR Unknown Request Type: " - << req_type << std::endl; - break; - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// Blocking API implementation begin -//////////////////////////////////////////////////////////////////////////////// - -bool p3GxsChannels::getChannelsSummaries( - std::list& channels ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; - if( !requestGroupInfo(token, opts) - || waitToken(token) != RsTokenService::COMPLETE ) return false; - return getGroupSummary(token, channels); -} - -bool p3GxsChannels::getChannelsInfo( const std::list& chanIds, std::vector& channelsInfo ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - - if(chanIds.empty()) - { - if( !requestGroupInfo(token, opts) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - } - else - { - if( !requestGroupInfo(token, opts, chanIds) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - } - - return getGroupData(token, channelsInfo) && !channelsInfo.empty(); -} - -bool p3GxsChannels::getChannelStatistics(const RsGxsGroupId& channelId,GxsGroupStatistic& stat) -{ - uint32_t token; - if(!RsGxsIfaceHelper::requestGroupStatistic(token, channelId) || waitToken(token) != RsTokenService::COMPLETE) - return false; - - return RsGenExchange::getGroupStatistic(token,stat); -} - -bool p3GxsChannels::getChannelServiceStatistics(GxsServiceStatistic& stat) -{ - uint32_t token; - if(!RsGxsIfaceHelper::requestServiceStatistic(token) || waitToken(token) != RsTokenService::COMPLETE) - return false; - - return RsGenExchange::getServiceStatistic(token,stat); -} - -bool p3GxsChannels::getContentSummaries( - const RsGxsGroupId& channelId, std::vector& summaries ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_META; - - std::list channelIds; - channelIds.push_back(channelId); - - if( !requestMsgInfo(token, opts, channelIds) || - waitToken(token, std::chrono::seconds(5)) != RsTokenService::COMPLETE ) - return false; - - GxsMsgMetaMap metaMap; - bool res = RsGenExchange::getMsgMeta(token, metaMap); - summaries = metaMap[channelId]; - - return res; -} - -bool p3GxsChannels::getChannelAllContent( const RsGxsGroupId& channelId, - std::vector& posts, - std::vector& comments, - std::vector& votes ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - - if( !requestMsgInfo(token, opts,std::list({channelId})) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - - return getPostData(token, posts, comments,votes); -} - -bool p3GxsChannels::getChannelContent( const RsGxsGroupId& channelId, - const std::set& contentIds, - std::vector& posts, - std::vector& comments, - std::vector& votes ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - - GxsMsgReq msgIds; - msgIds[channelId] = contentIds; - - if( !requestMsgInfo(token, opts, msgIds) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - - return getPostData(token, posts, comments, votes); -} - -bool p3GxsChannels::getChannelComments(const RsGxsGroupId &channelId, - const std::set &contentIds, - std::vector &comments) -{ - std::vector msgIds; - for (auto& msg:contentIds) - msgIds.push_back(RsGxsGrpMsgIdPair(channelId,msg)); - - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA; - opts.mOptions = RS_TOKREQOPT_MSG_THREAD | RS_TOKREQOPT_MSG_LATEST; - - uint32_t token; - if( !requestMsgRelatedInfo(token, opts, msgIds) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - - return getRelatedComments(token,comments); -} - -bool p3GxsChannels::createChannelV2( - const std::string& name, const std::string& description, - const RsGxsImage& thumbnail, const RsGxsId& authorId, - RsGxsCircleType circleType, const RsGxsCircleId& circleId, - RsGxsGroupId& channelId, std::string& errorMessage ) -{ - const auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - errorMessage = err; - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(!authorId.isNull() && !rsIdentity->isOwnId(authorId)) - return failure("authorId must be either null, or of an owned identity"); - - if( circleType != RsGxsCircleType::PUBLIC - && circleType != RsGxsCircleType::EXTERNAL - && circleType != RsGxsCircleType::NODES_GROUP - && circleType != RsGxsCircleType::LOCAL - && circleType != RsGxsCircleType::YOUR_EYES_ONLY) - return failure("circleType has invalid value"); - - switch(circleType) - { - case RsGxsCircleType::EXTERNAL: - if(circleId.isNull()) - return failure("circleType is EXTERNAL but circleId is null"); - break; - case RsGxsCircleType::NODES_GROUP: - { - RsGroupInfo ginfo; - - if(!rsPeers->getGroupInfo(RsNodeGroupId(circleId), ginfo)) - return failure( "circleType is NODES_GROUP but circleId does not " - "correspond to an actual group of friends" ); - break; - } - default: - if(!circleId.isNull()) - return failure( "circleType requires a null circleId, but a non " - "null circleId (" + circleId.toStdString() + - ") was supplied" ); - break; - } - - // Create a consistent channel group meta from the information supplied - RsGxsChannelGroup channel; - - channel.mMeta.mGroupName = name; - channel.mMeta.mAuthorId = authorId; - channel.mMeta.mCircleType = static_cast(circleType); - - channel.mMeta.mSignFlags = GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_NONEREQ - | GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_REQUIRED; - - channel.mMeta.mGroupFlags = GXS_SERV::FLAG_PRIVACY_PUBLIC; - - channel.mMeta.mCircleId.clear(); - channel.mMeta.mInternalCircle.clear(); - - switch(circleType) - { - case RsGxsCircleType::NODES_GROUP: - channel.mMeta.mInternalCircle = circleId; break; - case RsGxsCircleType::EXTERNAL: - channel.mMeta.mCircleId = circleId; break; - default: break; - } - - // Create the channel - channel.mDescription = description; - channel.mImage = thumbnail; - - uint32_t token; - if(!createGroup(token, channel)) - return failure("Failure creating GXS group"); - - // wait for the group creation to complete. - RsTokenService::GxsRequestStatus wSt = - waitToken( token, std::chrono::seconds(5), - std::chrono::milliseconds(50) ); - if(wSt != RsTokenService::COMPLETE) - return failure( "GXS operation waitToken failed with: " + - std::to_string(wSt) ); - - if(!RsGenExchange::getPublishedGroupMeta(token, channel.mMeta)) - return failure("Failure getting updated group data."); - - channelId = channel.mMeta.mGroupId; - -#ifdef RS_DEEP_CHANNEL_INDEX - DeepChannelsIndex::indexChannelGroup(channel); -#endif // RS_DEEP_CHANNEL_INDEX - - return true; -} - -bool p3GxsChannels::createChannel(RsGxsChannelGroup& channel) -{ - uint32_t token; - if(!createGroup(token, channel)) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Failed creating group." - << std::endl; - return false; - } - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! GXS operation failed." - << std::endl; - return false; - } - - if(!RsGenExchange::getPublishedGroupMeta(token, channel.mMeta)) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Failure getting updated " - << " group data." << std::endl; - return false; - } - -#ifdef RS_DEEP_CHANNEL_INDEX - DeepChannelsIndex::indexChannelGroup(channel); -#endif // RS_DEEP_CHANNEL_INDEX - - return true; -} - -bool p3GxsChannels::createVoteV2( - const RsGxsGroupId& channelId, const RsGxsMessageId& postId, - const RsGxsMessageId& commentId, const RsGxsId& authorId, - RsGxsVoteType tVote, RsGxsMessageId& voteId, std::string& errorMessage ) -{ - std::vector channelsInfo; - if(!getChannelsInfo(std::list({channelId}),channelsInfo)) - { - errorMessage = "Channel with Id " + channelId.toStdString() - + " does not exist."; - return false; - } - - if(commentId.isNull()) - { - errorMessage = "You cannot vote on null comment " - + commentId.toStdString(); - return false; - } - - std::set s({commentId}); - std::vector posts; - std::vector comments; - std::vector votes; - - if(!getChannelContent(channelId, s, posts, comments, votes)) - { - errorMessage = "You cannot vote on comment " - + commentId.toStdString() + " of channel with Id " - + channelId.toStdString() - + ": this comment does not exists locally!"; - return false; - } - - // is the ID a comment ID or a post ID? - // It should be comment => should have a parent ID - if(posts.front().mMeta.mParentId.isNull()) - { - errorMessage = "You cannot vote on channel message " - + commentId.toStdString() + " of channel with Id " - + channelId.toStdString() - + ": given id refers to a post, not a comment!"; - return false; - } - - if( tVote != RsGxsVoteType::NONE - && tVote != RsGxsVoteType::UP - && tVote != RsGxsVoteType::DOWN ) - { - errorMessage = "Your vote to channel with Id " - + channelId.toStdString() + " has wrong vote type. " - + " Only RsGxsVoteType::NONE, RsGxsVoteType::UP, " - + "RsGxsVoteType::DOWN are accepted."; - return false; - } - - if(!rsIdentity->isOwnId(authorId)) - { - errorMessage = "You cannot vote to channel with Id " - + channelId.toStdString() + " with identity " - + authorId.toStdString() + " because it is not yours."; - return false; - } - - // Create the vote - RsGxsVote vote; - vote.mMeta.mGroupId = channelId; - vote.mMeta.mThreadId = postId; - vote.mMeta.mParentId = commentId; - vote.mMeta.mAuthorId = authorId; - vote.mVoteType = static_cast(tVote); - - uint32_t token; - if(!createNewVote(token, vote)) - { - errorMessage = "Error! Failed creating vote."; - return false; - } - - if(waitToken(token) != RsTokenService::COMPLETE) - { - errorMessage = "GXS operation failed."; - return false; - } - - if(!RsGenExchange::getPublishedMsgMeta(token, vote.mMeta)) - { - errorMessage = "Failure getting generated vote data."; - return false; - } - - voteId = vote.mMeta.mMsgId; - return true; -} - -/// @deprecated use createVoteV2 instead -bool p3GxsChannels::createVote(RsGxsVote& vote) -{ - uint32_t token; - if(!createNewVote(token, vote)) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Failed creating vote." - << std::endl; - return false; - } - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! GXS operation failed." - << std::endl; - return false; - } - - if(!RsGenExchange::getPublishedMsgMeta(token, vote.mMeta)) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Failure getting generated " - << " vote data." << std::endl; - return false; - } - - return true; -} - -bool p3GxsChannels::editChannel(RsGxsChannelGroup& channel) -{ - uint32_t token; - if(!updateGroup(token, channel)) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Failed updating group." - << std::endl; - return false; - } - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! GXS operation failed." - << std::endl; - return false; - } - - if(!RsGenExchange::getPublishedGroupMeta(token, channel.mMeta)) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Failure getting updated " - << " group data." << std::endl; - return false; - } - -#ifdef RS_DEEP_CHANNEL_INDEX - DeepChannelsIndex::indexChannelGroup(channel); -#endif // RS_DEEP_CHANNEL_INDEX - - return true; -} - -bool p3GxsChannels::createPostV2( - const RsGxsGroupId& channelId, const std::string& title, - const std::string& body, const std::list& files, - const RsGxsImage& thumbnail, const RsGxsMessageId& origPostId, - RsGxsMessageId& postId, std::string& errorMessage ) -{ - // Do some checks - - std::vector channelsInfo; - - if(!getChannelsInfo(std::list({channelId}),channelsInfo)) - { - errorMessage = "Channel with Id " + channelId.toStdString() + - " does not exist."; - return false; - } - - const RsGxsChannelGroup& cg(*channelsInfo.begin()); - - if(!(cg.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_PUBLISH)) - { - errorMessage = "You cannot post to channel with Id " + - channelId.toStdString() + ": missing publish rights!"; - return false; - } - - if(!origPostId.isNull()) - { - std::set s({origPostId}); - std::vector posts; - std::vector comments; - std::vector votes; - - if(!getChannelContent(channelId,s,posts,comments,votes)) - { - errorMessage = "You cannot edit post " + origPostId.toStdString() - + " of channel with Id " + channelId.toStdString() - + ": this post does not exist locally!"; - return false; - } - } - - // Create the post - RsGxsChannelPost post; - - post.mMeta.mGroupId = channelId; - post.mMeta.mOrigMsgId = origPostId; - post.mMeta.mMsgName = title; - - post.mMsg = body; - post.mFiles = files; - post.mThumbnail = thumbnail; - - uint32_t token; - if(!createPost(token, post) || waitToken(token) != RsTokenService::COMPLETE) - { - errorMessage = "GXS operation failed"; - return false; - } - - if(RsGenExchange::getPublishedMsgMeta(token,post.mMeta)) - { -#ifdef RS_DEEP_CHANNEL_INDEX - DeepChannelsIndex::indexChannelPost(post); -#endif // RS_DEEP_CHANNEL_INDEX - - postId = post.mMeta.mMsgId; - return true; - } - - errorMessage = "Failed to retrive created post metadata"; - return false; -} - -bool p3GxsChannels::createCommentV2( - const RsGxsGroupId& channelId, - const RsGxsMessageId& threadId, - const std::string& comment, - const RsGxsId& authorId, - const RsGxsMessageId& parentId, - const RsGxsMessageId& origCommentId, - RsGxsMessageId& commentMessageId, - std::string& errorMessage ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - errorMessage = err; - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(channelId.isNull()) return failure("channelId cannot be null"); - if(threadId.isNull()) return failure("threadId cannot be null"); - if(parentId.isNull()) return failure("parentId cannot be null"); - - std::vector channelsInfo; - if(!getChannelsInfo(std::list({channelId}),channelsInfo)) - return failure( "Channel with Id " + channelId.toStdString() - + " does not exist." ); - - std::vector posts; - std::vector comments; - std::vector votes; - - if(!getChannelContent( // does the post thread exist? - channelId, std::set({threadId}), - posts, comments, votes) ) - return failure( "You cannot comment post " + threadId.toStdString() + - " of channel with Id " + channelId.toStdString() + - ": this post does not exists locally!" ); - - // check that the post thread Id is actually that of a post thread - if(posts.size() != 1 || !posts[0].mMeta.mParentId.isNull()) - return failure( "You cannot comment post " + threadId.toStdString() + - " of channel with Id " + channelId.toStdString() + - ": supplied threadId is not a thread, or parentMsgId is" - " not a comment!"); - - if(!getChannelContent( // does the post parent exist? - channelId, std::set({parentId}), - posts, comments, votes) ) - return failure( "You cannot comment post " + parentId.toStdString() + - ": supplied parent doesn't exists locally!" ); - - if(!origCommentId.isNull()) - { - std::set s({origCommentId}); - std::vector cmts; - - if( !getChannelContent(channelId, s, posts, cmts, votes) || - comments.size() != 1 ) - return failure( "You cannot edit comment " + - origCommentId.toStdString() + - " of channel with Id " + channelId.toStdString() + - ": this comment does not exist locally!"); - - const RsGxsId& commentAuthor = comments[0].mMeta.mAuthorId; - if(commentAuthor != authorId) - return failure( "Editor identity and creator doesn't match " - + authorId.toStdString() + " != " - + commentAuthor.toStdString() ); - } - - if(!rsIdentity->isOwnId(authorId)) // is the author ID actually ours? - return failure( "You cannot comment to channel with Id " + - channelId.toStdString() + " with identity " + - authorId.toStdString() + " because it is not yours." ); - - // Now create the comment - RsGxsComment cmt; - cmt.mMeta.mGroupId = channelId; - cmt.mMeta.mThreadId = threadId; - cmt.mMeta.mParentId = parentId; - cmt.mMeta.mAuthorId = authorId; - cmt.mMeta.mOrigMsgId = origCommentId; - cmt.mComment = comment; - - uint32_t token; - if(!createNewComment(token, cmt)) - return failure("createNewComment failed"); - - RsTokenService::GxsRequestStatus wSt = waitToken(token); - if(wSt != RsTokenService::COMPLETE) - return failure( "GXS operation waitToken failed with: " + - std::to_string(wSt) ); - - if(!RsGenExchange::getPublishedMsgMeta(token, cmt.mMeta)) - return failure("Failure getting created comment data."); - - commentMessageId = cmt.mMeta.mMsgId; - return true; -} - -bool p3GxsChannels::createComment(RsGxsComment& comment) // deprecated -{ - uint32_t token; - if(!createNewComment(token, comment)) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Failed creating comment." - << std::endl; - return false; - } - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! GXS operation failed." - << std::endl; - return false; - } - - if(!RsGenExchange::getPublishedMsgMeta(token, comment.mMeta)) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Failure getting generated " - << " comment data." << std::endl; - return false; - } - - return true; -} - -bool p3GxsChannels::subscribeToChannel( const RsGxsGroupId& groupId, bool subscribe ) -{ - uint32_t token; - if( !subscribeToGroup(token, groupId, subscribe) || waitToken(token) != RsTokenService::COMPLETE ) return false; - - RsGxsGroupId grpId; - acknowledgeGrp(token,grpId); - return true; -} - -bool p3GxsChannels::markRead(const RsGxsGrpMsgIdPair& msgId, bool read) -{ - uint32_t token; - setMessageReadStatus(token, msgId, read); - if(waitToken(token) != RsTokenService::COMPLETE ) return false; - - RsGxsGrpMsgIdPair p; - acknowledgeMsg(token,p); - - return true; -} - -bool p3GxsChannels::shareChannelKeys( - const RsGxsGroupId& channelId, const std::set& peers) -{ - return groupShareKeys(channelId, peers); -} - - -//////////////////////////////////////////////////////////////////////////////// -/// Blocking API implementation end -//////////////////////////////////////////////////////////////////////////////// - - -/********************************************************************************************/ -/********************************************************************************************/ - - -bool p3GxsChannels::autoDownloadEnabled(const RsGxsGroupId &groupId,bool& enabled) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::autoDownloadEnabled(" << groupId << ")"; - std::cerr << std::endl; -#endif - - RS_STACK_MUTEX(mSubscribedGroupsMutex); - std::map::iterator it; - it = mSubscribedGroups.find(groupId); - if (it == mSubscribedGroups.end()) - { - std::cerr << __PRETTY_FUNCTION__ << " WARNING requested channel: " - << groupId << " is not subscribed" << std::endl; - return false; - } - - /* extract from ServiceString */ - GxsChannelGroupInfo ss; - ss.load(it->second.mServiceString); - enabled = ss.mAutoDownload; - - return true; -} - -bool GxsChannelGroupInfo::load(const std::string &input) -{ - if(input.empty()) - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "SSGxsChannelGroup::load() asked to load a null string." << std::endl; -#endif - return true ; - } - int download_val; - mAutoDownload = false; - mDownloadDirectory.clear(); - - - RsTemporaryMemory tmpmem(input.length()); - - if (1 == sscanf(input.c_str(), "D:%d", &download_val)) - { - if (download_val == 1) - mAutoDownload = true; - } - else if( 2 == sscanf(input.c_str(),"v2 {D:%d} {P:%[^}]}",&download_val,(unsigned char*)tmpmem)) - { - if (download_val == 1) - mAutoDownload = true; - - std::vector vals = Radix64::decode(std::string((char*)(unsigned char *)tmpmem)) ; - mDownloadDirectory = std::string((char*)vals.data(),vals.size()); - } - else if( 1 == sscanf(input.c_str(),"v2 {D:%d}",&download_val)) - { - if (download_val == 1) - mAutoDownload = true; - } - else - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "SSGxsChannelGroup::load(): could not parse string \"" << input << "\"" << std::endl; -#endif - return false ; - } - -#ifdef GXSCHANNELS_DEBUG - std::cerr << "DECODED STRING: autoDL=" << mAutoDownload << ", directory=\"" << mDownloadDirectory << "\"" << std::endl; -#endif - - return true; -} - -std::string GxsChannelGroupInfo::save() const -{ - std::string output = "v2 "; - - if (mAutoDownload) - output += "{D:1}"; - else - output += "{D:0}"; - - if(!mDownloadDirectory.empty()) - { - std::string encoded_str ; - Radix64::encode((unsigned char*)mDownloadDirectory.c_str(),mDownloadDirectory.length(),encoded_str); - - output += " {P:" + encoded_str + "}"; - } - -#ifdef GXSCHANNELS_DEBUG - std::cerr << "ENCODED STRING: " << output << std::endl; -#endif - - return output; -} - -bool p3GxsChannels::setAutoDownload(const RsGxsGroupId& groupId, bool enabled) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " id: " << groupId - << " enabled: " << enabled << std::endl; -#endif - - RS_STACK_MUTEX(mSubscribedGroupsMutex); - std::map::iterator it; - it = mSubscribedGroups.find(groupId); - if (it == mSubscribedGroups.end()) - { - std::cerr << __PRETTY_FUNCTION__ << " ERROR requested channel: " - << groupId.toStdString() << " is not subscribed!" << std::endl; - return false; - } - - /* extract from ServiceString */ - GxsChannelGroupInfo ss; - ss.load(it->second.mServiceString); - if (enabled == ss.mAutoDownload) - { - std::cerr << __PRETTY_FUNCTION__ << " WARNING mAutoDownload was already" - << " properly set to: " << enabled << " for channel:" - << groupId.toStdString() << std::endl; - return false; - } - - ss.mAutoDownload = enabled; - std::string serviceString = ss.save(); - - uint32_t token; - RsGenExchange::setGroupServiceString(token, groupId, serviceString); - - if(waitToken(token) != RsTokenService::COMPLETE) return false; - - it->second.mServiceString = serviceString; // update Local Cache. - - return true; -} - -/********************************************************************************************/ -/********************************************************************************************/ - -void p3GxsChannels::setMessageProcessedStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool processed) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::setMessageProcessedStatus()"; - std::cerr << std::endl; -#endif - - uint32_t mask = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - uint32_t status = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - if (processed) - { - status = 0; - } - setMsgStatusFlags(token, msgId, status, mask); -} - -void p3GxsChannels::setMessageReadStatus( uint32_t& token, - const RsGxsGrpMsgIdPair& msgId, - bool read ) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::setMessageReadStatus()"; - std::cerr << std::endl; -#endif - - /* Always remove status unprocessed */ - uint32_t mask = GXS_SERV::GXS_MSG_STATUS_GUI_NEW | GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; - uint32_t status = GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; - if (read) status = 0; - - setMsgStatusFlags(token, msgId, status, mask); - - if (rsEvents) - { - auto ev = std::make_shared(); - - ev->mChannelMsgId = msgId.second; - ev->mChannelGroupId = msgId.first; - ev->mChannelEventCode = RsChannelEventCode::READ_STATUS_CHANGED; - rsEvents->postEvent(ev); - } -} - -/********************************************************************************************/ -/********************************************************************************************/ - -bool p3GxsChannels::createGroup(uint32_t &token, RsGxsChannelGroup &group) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::createGroup()" << std::endl; -#endif - - RsGxsChannelGroupItem* grpItem = new RsGxsChannelGroupItem(); - grpItem->fromChannelGroup(group, true); - - RsGenExchange::publishGroup(token, grpItem); - return true; -} - - -bool p3GxsChannels::updateGroup(uint32_t &token, RsGxsChannelGroup &group) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::updateGroup()" << std::endl; -#endif - - RsGxsChannelGroupItem* grpItem = new RsGxsChannelGroupItem(); - grpItem->fromChannelGroup(group, true); - - RsGenExchange::updateGroup(token, grpItem); - return true; -} - -/// @deprecated use createPostV2 instead -bool p3GxsChannels::createPost(RsGxsChannelPost& post) -{ - uint32_t token; - if( !createPost(token, post) - || waitToken(token) != RsTokenService::COMPLETE ) return false; - - if(RsGenExchange::getPublishedMsgMeta(token,post.mMeta)) - { -#ifdef RS_DEEP_CHANNEL_INDEX - DeepChannelsIndex::indexChannelPost(post); -#endif // RS_DEEP_CHANNEL_INDEX - - return true; - } - - return false; -} - - -bool p3GxsChannels::createPost(uint32_t &token, RsGxsChannelPost &msg) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " GroupId: " << msg.mMeta.mGroupId - << std::endl; -#endif - - RsGxsChannelPostItem* msgItem = new RsGxsChannelPostItem(); - msgItem->fromChannelPost(msg, true); - - RsGenExchange::publishMsg(token, msgItem); - return true; -} - -/********************************************************************************************/ -/********************************************************************************************/ - -bool p3GxsChannels::ExtraFileHash(const std::string& path) -{ - TransferRequestFlags flags = RS_FILE_REQ_ANONYMOUS_ROUTING; - return rsFiles->ExtraFileHash(path, GXSCHANNEL_STOREPERIOD, flags); -} - - -bool p3GxsChannels::ExtraFileRemove(const RsFileHash& hash) -{ return rsFiles->ExtraFileRemove(hash); } - - -/********************************************************************************************/ -/********************************************************************************************/ - -/* so we need the same tick idea as wiki for generating dummy channels - */ - -#define MAX_GEN_GROUPS 20 -#define MAX_GEN_POSTS 500 -#define MAX_GEN_COMMENTS 600 -#define MAX_GEN_VOTES 700 - -std::string p3GxsChannels::genRandomId() -{ - std::string randomId; - for(int i = 0; i < 20; i++) - { - randomId += (char) ('a' + (RSRandom::random_u32() % 26)); - } - - return randomId; -} - -bool p3GxsChannels::generateDummyData() -{ - mGenCount = 0; - mGenRefs.resize(MAX_GEN_VOTES); - - std::string groupName; - rs_sprintf(groupName, "TestChannel_%d", mGenCount); - -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::generateDummyData() Starting off with Group: " << groupName; - std::cerr << std::endl; -#endif - - /* create a new group */ - generateGroup(mGenToken, groupName); - - mGenActive = true; - - return true; -} - - -void p3GxsChannels::dummy_tick() -{ - /* check for a new callback */ - - if (mGenActive) - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::dummyTick() Gen Active"; - std::cerr << std::endl; -#endif - - uint32_t status = RsGenExchange::getTokenService()->requestStatus(mGenToken); - if (status != RsTokenService::COMPLETE) - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::dummy_tick() Status: " << status; - std::cerr << std::endl; -#endif - - if (status == RsTokenService::FAILED) - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::dummy_tick() generateDummyMsgs() FAILED"; - std::cerr << std::endl; -#endif - mGenActive = false; - } - return; - } - - if (mGenCount < MAX_GEN_GROUPS) - { - /* get the group Id */ - RsGxsGroupId groupId; - RsGxsMessageId emptyId; - if (!acknowledgeTokenGrp(mGenToken, groupId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mGenActive = false; - return; - } - -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::dummy_tick() Acknowledged GroupId: " << groupId; - std::cerr << std::endl; -#endif - - ChannelDummyRef ref(groupId, emptyId, emptyId); - mGenRefs[mGenCount] = ref; - } - else if (mGenCount < MAX_GEN_POSTS) - { - /* get the msg Id, and generate next snapshot */ - RsGxsGrpMsgIdPair msgId; - if (!acknowledgeTokenMsg(mGenToken, msgId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mGenActive = false; - return; - } - -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::dummy_tick() Acknowledged Post "; - std::cerr << std::endl; -#endif - - /* store results for later selection */ - - ChannelDummyRef ref(msgId.first, mGenThreadId, msgId.second); - mGenRefs[mGenCount] = ref; - } - else if (mGenCount < MAX_GEN_COMMENTS) - { - /* get the msg Id, and generate next snapshot */ - RsGxsGrpMsgIdPair msgId; - if (!acknowledgeTokenMsg(mGenToken, msgId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mGenActive = false; - return; - } - -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::dummy_tick() Acknowledged Comment "; - std::cerr << std::endl; -#endif - - /* store results for later selection */ - - ChannelDummyRef ref(msgId.first, mGenThreadId, msgId.second); - mGenRefs[mGenCount] = ref; - } - else if (mGenCount < MAX_GEN_VOTES) - { - /* get the msg Id, and generate next snapshot */ - RsGxsGrpMsgIdPair msgId; - if (!acknowledgeVote(mGenToken, msgId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mGenActive = false; - return; - } - -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::dummy_tick() Acknowledged Vote "; - std::cerr << std::endl; -#endif - - /* store results for later selection */ - - ChannelDummyRef ref(msgId.first, mGenThreadId, msgId.second); - mGenRefs[mGenCount] = ref; - } - else - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::dummy_tick() Finished"; - std::cerr << std::endl; -#endif - - /* done */ - mGenActive = false; - return; - } - - mGenCount++; - - if (mGenCount < MAX_GEN_GROUPS) - { - std::string groupName; - rs_sprintf(groupName, "TestChannel_%d", mGenCount); - -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::dummy_tick() Generating Group: " << groupName; - std::cerr << std::endl; -#endif - - /* create a new group */ - generateGroup(mGenToken, groupName); - } - else if (mGenCount < MAX_GEN_POSTS) - { - /* create a new post */ - uint32_t idx = (uint32_t) (MAX_GEN_GROUPS * RSRandom::random_f32()); - ChannelDummyRef &ref = mGenRefs[idx]; - - RsGxsGroupId grpId = ref.mGroupId; - RsGxsMessageId parentId = ref.mMsgId; - mGenThreadId = ref.mThreadId; - if (mGenThreadId.isNull()) - { - mGenThreadId = parentId; - } - -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::dummy_tick() Generating Post ... "; - std::cerr << " GroupId: " << grpId; - std::cerr << " ThreadId: " << mGenThreadId; - std::cerr << " ParentId: " << parentId; - std::cerr << std::endl; -#endif - - generatePost(mGenToken, grpId); - } - else if (mGenCount < MAX_GEN_COMMENTS) - { - /* create a new post */ - uint32_t idx = (uint32_t) ((mGenCount - MAX_GEN_GROUPS) * RSRandom::random_f32()); - ChannelDummyRef &ref = mGenRefs[idx + MAX_GEN_GROUPS]; - - RsGxsGroupId grpId = ref.mGroupId; - RsGxsMessageId parentId = ref.mMsgId; - mGenThreadId = ref.mThreadId; - if (mGenThreadId.isNull()) - { - mGenThreadId = parentId; - } - -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::dummy_tick() Generating Comment ... "; - std::cerr << " GroupId: " << grpId; - std::cerr << " ThreadId: " << mGenThreadId; - std::cerr << " ParentId: " << parentId; - std::cerr << std::endl; -#endif - - generateComment(mGenToken, grpId, parentId, mGenThreadId); - } - else - { - /* create a new post */ - uint32_t idx = (uint32_t) ((MAX_GEN_COMMENTS - MAX_GEN_POSTS) * RSRandom::random_f32()); - ChannelDummyRef &ref = mGenRefs[idx + MAX_GEN_POSTS]; - - RsGxsGroupId grpId = ref.mGroupId; - RsGxsMessageId parentId = ref.mMsgId; - mGenThreadId = ref.mThreadId; - if (mGenThreadId.isNull()) - { - mGenThreadId = parentId; - } - -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::dummy_tick() Generating Vote ... "; - std::cerr << " GroupId: " << grpId; - std::cerr << " ThreadId: " << mGenThreadId; - std::cerr << " ParentId: " << parentId; - std::cerr << std::endl; -#endif - - generateVote(mGenToken, grpId, parentId, mGenThreadId); - } - - } - -#ifdef TO_REMOVE - cleanTimedOutCallbacks(); -#endif -} - - -bool p3GxsChannels::generatePost(uint32_t &token, const RsGxsGroupId &grpId) -{ - RsGxsChannelPost msg; - - std::string rndId = genRandomId(); - - rs_sprintf(msg.mMsg, "Channel Msg: GroupId: %s, some randomness: %s", - grpId.toStdString().c_str(), rndId.c_str()); - - msg.mMeta.mMsgName = msg.mMsg; - - msg.mMeta.mGroupId = grpId; - msg.mMeta.mThreadId.clear() ; - msg.mMeta.mParentId.clear() ; - - msg.mMeta.mMsgStatus = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - - createPost(token, msg); - - return true; -} - - -bool p3GxsChannels::generateComment(uint32_t &token, const RsGxsGroupId &grpId, const RsGxsMessageId &parentId, const RsGxsMessageId &threadId) -{ - RsGxsComment msg; - - std::string rndId = genRandomId(); - - rs_sprintf(msg.mComment, "Channel Comment: GroupId: %s, ThreadId: %s, ParentId: %s + some randomness: %s", - grpId.toStdString().c_str(), threadId.toStdString().c_str(), parentId.toStdString().c_str(), rndId.c_str()); - - msg.mMeta.mMsgName = msg.mComment; - - msg.mMeta.mGroupId = grpId; - msg.mMeta.mThreadId = threadId; - msg.mMeta.mParentId = parentId; - - msg.mMeta.mMsgStatus = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - - /* chose a random Id to sign with */ - std::list ownIds; - std::list::iterator it; - - rsIdentity->getOwnIds(ownIds); - - uint32_t idx = (uint32_t) (ownIds.size() * RSRandom::random_f32()); - uint32_t i = 0; - for(it = ownIds.begin(); (it != ownIds.end()) && (i < idx); ++it, ++i); - - if (it != ownIds.end()) - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::generateComment() Author: " << *it; - std::cerr << std::endl; -#endif - msg.mMeta.mAuthorId = *it; - } -#ifdef GXSCHANNELS_DEBUG - else - { - std::cerr << "p3GxsChannels::generateComment() No Author!"; - std::cerr << std::endl; - } -#endif - - createNewComment(token, msg); - - return true; -} - - -bool p3GxsChannels::generateVote(uint32_t &token, const RsGxsGroupId &grpId, const RsGxsMessageId &parentId, const RsGxsMessageId &threadId) -{ - RsGxsVote vote; - - vote.mMeta.mGroupId = grpId; - vote.mMeta.mThreadId = threadId; - vote.mMeta.mParentId = parentId; - vote.mMeta.mMsgStatus = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - - /* chose a random Id to sign with */ - std::list ownIds; - std::list::iterator it; - - rsIdentity->getOwnIds(ownIds); - - uint32_t idx = (uint32_t) (ownIds.size() * RSRandom::random_f32()); - uint32_t i = 0; - for(it = ownIds.begin(); (it != ownIds.end()) && (i < idx); ++it, ++i) ; - - if (it != ownIds.end()) - { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::generateVote() Author: " << *it; - std::cerr << std::endl; -#endif - vote.mMeta.mAuthorId = *it; - } -#ifdef GXSCHANNELS_DEBUG - else - { - std::cerr << "p3GxsChannels::generateVote() No Author!"; - std::cerr << std::endl; - } -#endif - - if (0.7 > RSRandom::random_f32()) - { - // 70 % postive votes - vote.mVoteType = GXS_VOTE_UP; - } - else - { - vote.mVoteType = GXS_VOTE_DOWN; - } - - createNewVote(token, vote); - - return true; -} - - -bool p3GxsChannels::generateGroup(uint32_t &token, std::string groupName) -{ - /* generate a new channel */ - RsGxsChannelGroup channel; - channel.mMeta.mGroupName = groupName; - - createGroup(token, channel); - - return true; -} - - - // Overloaded from RsTickEvent for Event callbacks. -void p3GxsChannels::handle_event(uint32_t event_type, const std::string &elabel) -{ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::handle_event(" << event_type << ")"; - std::cerr << std::endl; -#endif - - // stuff. - switch(event_type) - { - case CHANNEL_TESTEVENT_DUMMYDATA: - generateDummyData(); - break; - - case CHANNEL_PROCESS: - request_AllSubscribedGroups(); - break; - - default: - /* error */ - std::cerr << "p3GxsChannels::handle_event() Unknown Event Type: " << event_type << " elabel:" << elabel; - std::cerr << std::endl; - break; - } -} - -TurtleRequestId p3GxsChannels::turtleGroupRequest(const RsGxsGroupId& group_id) -{ - return netService()->turtleGroupRequest(group_id) ; -} -TurtleRequestId p3GxsChannels::turtleSearchRequest(const std::string& match_string) -{ - return netService()->turtleSearchRequest(match_string); -} - -bool p3GxsChannels::clearDistantSearchResults(TurtleRequestId req) -{ - return netService()->clearDistantSearchResults(req); -} -bool p3GxsChannels::retrieveDistantSearchResults(TurtleRequestId req,std::map& results) -{ - return netService()->retrieveDistantSearchResults(req,results); -} - -DistantSearchGroupStatus p3GxsChannels::getDistantSearchStatus(const RsGxsGroupId& group_id) -{ - return netService()->getDistantSearchStatus(group_id); -} -bool p3GxsChannels::getDistantSearchResultGroupData(const RsGxsGroupId& group_id,RsGxsChannelGroup& distant_group) -{ - RsGxsGroupSearchResults gs; - - if(netService()->retrieveDistantGroupSummary(group_id,gs)) - { - // This is a placeholder information by the time we receive the full group meta data and check the signature. - distant_group.mMeta.mGroupId = gs.mGroupId ; - distant_group.mMeta.mGroupName = gs.mGroupName; - distant_group.mMeta.mGroupFlags = GXS_SERV::FLAG_PRIVACY_PUBLIC ; - distant_group.mMeta.mSignFlags = gs.mSignFlags; - - distant_group.mMeta.mPublishTs = gs.mPublishTs; - distant_group.mMeta.mAuthorId = gs.mAuthorId; - - distant_group.mMeta.mCircleType = GXS_CIRCLE_TYPE_PUBLIC ;// guessed, otherwise the group would not be search-able. - - // other stuff. - distant_group.mMeta.mAuthenFlags = 0; // wild guess... - - distant_group.mMeta.mSubscribeFlags = GXS_SERV::GROUP_SUBSCRIBE_NOT_SUBSCRIBED ; - - distant_group.mMeta.mPop = gs.mPopularity; // Popularity = number of friend subscribers - distant_group.mMeta.mVisibleMsgCount = gs.mNumberOfMessages; // Max messages reported by friends - distant_group.mMeta.mLastPost = gs.mLastMessageTs; // Timestamp for last message. Not used yet. - - return true ; - } - else - return false ; -} - -#ifdef TO_REMOVE -bool p3GxsChannels::turtleSearchRequest( - const std::string& matchString, - const std::function& multiCallback, - rstime_t maxWait ) -{ - if(matchString.empty()) - { - std::cerr << __PRETTY_FUNCTION__ << " match string can't be empty!" - << std::endl; - return false; - } - - TurtleRequestId sId = turtleSearchRequest(matchString); - - { - RS_STACK_MUTEX(mSearchCallbacksMapMutex); - mSearchCallbacksMap.emplace( - sId, - std::make_pair( - multiCallback, - std::chrono::system_clock::now() + - std::chrono::seconds(maxWait) ) ); - } - - return true; -} - -/// @see RsGxsChannels::turtleChannelRequest -bool p3GxsChannels::turtleChannelRequest( - const RsGxsGroupId& channelId, - const std::function& multiCallback, - rstime_t maxWait) -{ - if(channelId.isNull()) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! channelId can't be null!" - << std::endl; - return false; - } - - TurtleRequestId sId = turtleGroupRequest(channelId); - - { - RS_STACK_MUTEX(mDistantChannelsCallbacksMapMutex); - mDistantChannelsCallbacksMap.emplace( - sId, - std::make_pair( - multiCallback, - std::chrono::system_clock::now() + - std::chrono::seconds(maxWait) ) ); - } - - return true; -} - -/// @see RsGxsChannels::localSearchRequest -bool p3GxsChannels::localSearchRequest( - const std::string& matchString, - const std::function& multiCallback, - rstime_t maxWait ) -{ - if(matchString.empty()) - { - std::cerr << __PRETTY_FUNCTION__ << " match string can't be empty!" - << std::endl; - return false; - } - - auto timeout = std::chrono::steady_clock::now() + std::chrono::seconds(maxWait); - RsThread::async([=]() - { - std::list results; - RsGenExchange::localSearch(matchString, results); - if(std::chrono::steady_clock::now() < timeout) - for(const RsGxsGroupSummary& result : results) multiCallback(result); - }); - - return true; -} -#endif - -void p3GxsChannels::receiveDistantSearchResults( TurtleRequestId id, const RsGxsGroupId& grpId ) -{ - if(!rsEvents) - return; - - // We temporise here, in order to avoid notifying clients with many events - // So we put some data in there and will send an event with all of them at once every 1 sec at most. - - mSearchResultsToNotify[id].insert(grpId); -} - -bool p3GxsChannels::exportChannelLink( std::string& link, const RsGxsGroupId& chanId, bool includeGxsData, const std::string& baseUrl, std::string& errMsg ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - errMsg = err; - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(chanId.isNull()) return failure("chanId cannot be null"); - - const bool outputRadix = baseUrl.empty(); - if(outputRadix && !includeGxsData) return - failure("includeGxsData must be true if format requested is base64"); - - if( includeGxsData && - !RsGenExchange::exportGroupBase64(link, chanId, errMsg) ) - return failure(errMsg); - - if(outputRadix) return true; - - std::vector chansInfo; - if( !getChannelsInfo(std::list({chanId}), chansInfo) - || chansInfo.empty() ) - return failure("failure retrieving channel information"); - - RsUrl inviteUrl(baseUrl); - inviteUrl.setQueryKV(CHANNEL_URL_ID_FIELD, chanId.toStdString()); - inviteUrl.setQueryKV(CHANNEL_URL_NAME_FIELD, chansInfo[0].mMeta.mGroupName); - if(includeGxsData) inviteUrl.setQueryKV(CHANNEL_URL_DATA_FIELD, link); - - link = inviteUrl.toString(); - return true; -} - -bool p3GxsChannels::importChannelLink( const std::string& link, RsGxsGroupId& chanId, std::string& errMsg ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - errMsg = err; - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(link.empty()) return failure("link is empty"); - - const std::string* radixPtr(&link); - - RsUrl url(link); - const auto& query = url.query(); - const auto qIt = query.find(CHANNEL_URL_DATA_FIELD); - if(qIt != query.end()) radixPtr = &qIt->second; - - if(radixPtr->empty()) return failure(CHANNEL_URL_DATA_FIELD + " is empty"); - - if(!RsGenExchange::importGroupBase64(*radixPtr, chanId, errMsg)) - return failure(errMsg); - - return true; -} - -/*static*/ const std::string RsGxsChannels::DEFAULT_CHANNEL_BASE_URL = "retroshare:///channels"; -/*static*/ const std::string RsGxsChannels::CHANNEL_URL_NAME_FIELD = "chanName"; -/*static*/ const std::string RsGxsChannels::CHANNEL_URL_ID_FIELD = "chanId"; -/*static*/ const std::string RsGxsChannels::CHANNEL_URL_DATA_FIELD = "chanData"; -/*static*/ const std::string RsGxsChannels::CHANNEL_URL_MSG_TITLE_FIELD = "chanMsgTitle"; -/*static*/ const std::string RsGxsChannels::CHANNEL_URL_MSG_ID_FIELD = "chanMsgId"; - -RsGxsChannelGroup::~RsGxsChannelGroup() = default; -RsGxsChannelPost::~RsGxsChannelPost() = default; -RsGxsChannels::~RsGxsChannels() = default; diff --git a/libretroshare/src/services/p3gxschannels.h b/libretroshare/src/services/p3gxschannels.h deleted file mode 100644 index b5fe1426f..000000000 --- a/libretroshare/src/services/p3gxschannels.h +++ /dev/null @@ -1,415 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3gxschannels.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Robert Fernie * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - - -#include "retroshare/rsgxschannels.h" -#include "services/p3gxscommon.h" -#include "gxs/rsgenexchange.h" -#include "gxs/gxstokenqueue.h" -#include "util/rsmemory.h" -#include "util/rsdebug.h" -#include "util/rstickevent.h" - -#include -#include - - -// This class is only a helper to parse the channel group service string. - -class GxsChannelGroupInfo -{ - public: - GxsChannelGroupInfo(): mAutoDownload(false), mDownloadDirectory("") {} - bool load(const std::string &input); - std::string save() const; - - bool mAutoDownload; - std::string mDownloadDirectory; -}; - - -class p3GxsChannels: public RsGenExchange, public RsGxsChannels, - public GxsTokenQueue, public p3Config, - public RsTickEvent /* only needed for testing - remove after */ -{ -public: - p3GxsChannels( RsGeneralDataService* gds, RsNetworkExchangeService* nes, - RsGixs* gixs ); - virtual RsServiceInfo getServiceInfo() override; - - virtual void service_tick() override; - -protected: - - virtual bool service_checkIfGroupIsStillUsed(const RsGxsGrpMetaData& meta) override; // see RsGenExchange - - virtual RsSerialiser* setupSerialiser() override; // @see p3Config::setupSerialiser() - virtual bool saveList(bool &cleanup, std::list&saveList) override; // @see p3Config::saveList(bool &cleanup, std::list&) - virtual bool loadList(std::list& loadList) override; // @see p3Config::loadList(std::list&) - - virtual TurtleRequestId turtleGroupRequest(const RsGxsGroupId& group_id) override; - virtual TurtleRequestId turtleSearchRequest(const std::string& match_string) override; - virtual bool retrieveDistantSearchResults(TurtleRequestId req, std::map &results) override; - virtual bool clearDistantSearchResults(TurtleRequestId req) override; - virtual bool getDistantSearchResultGroupData(const RsGxsGroupId& group_id,RsGxsChannelGroup& distant_group) override; - virtual DistantSearchGroupStatus getDistantSearchStatus(const RsGxsGroupId& group_id) override; - - // Overloaded to cache new groups. -virtual RsGenExchange::ServiceCreate_Return service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet) override; - -virtual void notifyChanges(std::vector& changes) override; - - // Overloaded from RsTickEvent. -virtual void handle_event(uint32_t event_type, const std::string &elabel) override; - -public: - -virtual bool getGroupData(const uint32_t &token, std::vector &groups ) override; -virtual bool getPostData(const uint32_t &token, std::vector &posts, std::vector &cmts, std::vector &vots) override; -virtual bool getPostData(const uint32_t &token, std::vector &posts, std::vector &cmts) override; -virtual bool getPostData(const uint32_t &token, std::vector &posts) override; -//Not currently used -//virtual bool getRelatedPosts(const uint32_t &token, std::vector &posts); - - ////////////////////////////////////////////////////////////////////////////// - -//virtual bool setMessageStatus(const std::string &msgId, const uint32_t status, const uint32_t statusMask); -//virtual bool setGroupSubscribeFlags(const std::string &groupId, uint32_t subscribeFlags, uint32_t subscribeMask); - -//virtual bool groupRestoreKeys(const std::string &groupId); - virtual bool groupShareKeys( - const RsGxsGroupId &groupId, const std::set& peers) override; - -virtual bool createGroup(uint32_t &token, RsGxsChannelGroup &group) override; -virtual bool createPost(uint32_t &token, RsGxsChannelPost &post) override; - -virtual bool updateGroup(uint32_t &token, RsGxsChannelGroup &group) override; - -// no tokens... should be cached. -virtual bool setChannelAutoDownload(const RsGxsGroupId &groupId, bool enabled) override; -virtual bool getChannelAutoDownload(const RsGxsGroupId &groupid, bool& enabled) override; -virtual bool setChannelDownloadDirectory(const RsGxsGroupId &groupId, const std::string& directory) override; -virtual bool getChannelDownloadDirectory(const RsGxsGroupId &groupId, std::string& directory) override; - -#ifdef TO_REMOVE - /// @see RsGxsChannels::turtleSearchRequest - virtual bool turtleSearchRequest(const std::string& matchString, - const std::function& multiCallback, - rstime_t maxWait = 300 ) override; - - /// @see RsGxsChannels::turtleChannelRequest - virtual bool turtleChannelRequest( - const RsGxsGroupId& channelId, - const std::function& multiCallback, - rstime_t maxWait = 300 ) override; - - /// @see RsGxsChannels::localSearchRequest - virtual bool localSearchRequest(const std::string& matchString, - const std::function& multiCallback, - rstime_t maxWait = 30 ) override; -#endif - - /** - * Receive results from turtle search @see RsGenExchange @see RsNxsObserver - * @see RsGxsNetService::receiveTurtleSearchResults - * @see p3turtle::handleSearchResult - */ - void receiveDistantSearchResults( TurtleRequestId id, - const RsGxsGroupId& grpId ) override; - - /* Comment service - Provide RsGxsCommentService - redirect to p3GxsCommentService */ - virtual bool getCommentData(uint32_t token, std::vector &msgs) override - { return mCommentService->getGxsCommentData(token, msgs); } - - virtual bool getRelatedComments( uint32_t token, - std::vector &msgs ) override - { return mCommentService->getGxsRelatedComments(token, msgs); } - - virtual bool createNewComment(uint32_t &token, const RsGxsComment &msg) override - { - return mCommentService->createGxsComment(token, msg); - } - - virtual bool setCommentAsRead(uint32_t& token,const RsGxsGroupId& gid,const RsGxsMessageId& comment_msg_id) override - { - setMessageReadStatus(token,RsGxsGrpMsgIdPair(gid,comment_msg_id),true); - return true; - } - - virtual bool createNewVote(uint32_t &token, RsGxsVote &msg) override - { - return mCommentService->createGxsVote(token, msg); - } - - virtual bool acknowledgeComment(uint32_t token, std::pair& msgId) override - { - return acknowledgeMsg(token, msgId); - } - - virtual bool acknowledgeVote(uint32_t token, std::pair& msgId) override - { - if (mCommentService->acknowledgeVote(token, msgId)) - { - return true; - } - return acknowledgeMsg(token, msgId); - } - - - // Overloaded from RsGxsIface. -virtual bool subscribeToGroup(uint32_t &token, const RsGxsGroupId &groupId, bool subscribe) override; - - // Set Statuses. -virtual void setMessageProcessedStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool processed); -virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) override; - - // File Interface - virtual bool ExtraFileHash(const std::string& path) override; -virtual bool ExtraFileRemove(const RsFileHash &hash) override; - - - /// Implementation of @see RsGxsChannels::getChannelsSummaries - bool getChannelsSummaries(std::list& channels) override; - - /// Implementation of @see RsGxsChannels::getChannelsInfo - bool getChannelsInfo( - const std::list& chanIds, - std::vector& channelsInfo ) override; - - /// Implementation of @see RsGxsChannels::getChannelAllMessages - bool getChannelAllContent(const RsGxsGroupId& channelId, - std::vector& posts, - std::vector& comments, - std::vector& votes ) override; - - /// Implementation of @see RsGxsChannels::getChannelMessages - bool getChannelContent(const RsGxsGroupId& channelId, - const std::set& contentIds, - std::vector& posts, - std::vector& comments, - std::vector& votes ) override; - - /// Implementation of @see RsGxsChannels::getChannelComments - virtual bool getChannelComments(const RsGxsGroupId &channelId, - const std::set &contentIds, - std::vector &comments) override; - - /// Implementation of @see RsGxsChannels::getContentSummaries - bool getContentSummaries( - const RsGxsGroupId& channelId, - std::vector& summaries ) override; - - /// Implementation of @see RsGxsChannels::getChannelStatistics - bool getChannelStatistics(const RsGxsGroupId& channelId,GxsGroupStatistic& stat) override; - - /// Iplementation of @see RsGxsChannels::getChannelServiceStatistics - bool getChannelServiceStatistics(GxsServiceStatistic& stat) override; - - /// Implementation of @see RsGxsChannels::createChannelV2 - bool createChannelV2( - const std::string& name, const std::string& description, - const RsGxsImage& thumbnail = RsGxsImage(), - const RsGxsId& authorId = RsGxsId(), - RsGxsCircleType circleType = RsGxsCircleType::PUBLIC, - const RsGxsCircleId& circleId = RsGxsCircleId(), - RsGxsGroupId& channelId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId), - std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - /// Implementation of @see RsGxsChannels::createComment - bool createCommentV2( - const RsGxsGroupId& channelId, - const RsGxsMessageId& threadId, - const std::string& comment, - const RsGxsId& authorId, - const RsGxsMessageId& parentId = RsGxsMessageId(), - const RsGxsMessageId& origCommentId = RsGxsMessageId(), - RsGxsMessageId& commentMessageId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId), - std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - /// Implementation of @see RsGxsChannels::editChannel - bool editChannel(RsGxsChannelGroup& channel) override; - - /// Implementation of @see RsGxsChannels::createPostV2 - bool createPostV2( - const RsGxsGroupId& channelId, const std::string& title, - const std::string& body, - const std::list& files = std::list(), - const RsGxsImage& thumbnail = RsGxsImage(), - const RsGxsMessageId& origPostId = RsGxsMessageId(), - RsGxsMessageId& postId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId), - std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - /// Implementation of @see RsGxsChannels::createVoteV2 - bool createVoteV2( - const RsGxsGroupId& channelId, const RsGxsMessageId& postId, - const RsGxsMessageId& commentId, const RsGxsId& authorId, - RsGxsVoteType vote, - RsGxsMessageId& voteId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId), - std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - /// Implementation of @see RsGxsChannels::subscribeToChannel - bool subscribeToChannel( const RsGxsGroupId &groupId, - bool subscribe ) override; - - /// @see RsGxsChannels - virtual bool markRead(const RsGxsGrpMsgIdPair& msgId, bool read) override; - - /// @see RsGxsChannels - bool exportChannelLink( - std::string& link, const RsGxsGroupId& chanId, - bool includeGxsData = true, - const std::string& baseUrl = DEFAULT_CHANNEL_BASE_URL, - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - /// @see RsGxsChannels - bool importChannelLink( - const std::string& link, - RsGxsGroupId& chanId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId), - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - virtual bool shareChannelKeys( - const RsGxsGroupId& channelId, const std::set& peers ) override; - - /// Implementation of @see RsGxsChannels::createChannel - RS_DEPRECATED_FOR(createChannelV2) - bool createChannel(RsGxsChannelGroup& channel) override; - - /// @deprecated Implementation of @see RsGxsChannels::createPost - RS_DEPRECATED_FOR(createPostV2) - bool createPost(RsGxsChannelPost& post) override; - - /// @deprecated Implementation of @see RsGxsChannels::createComment - RS_DEPRECATED_FOR(createCommentV2) - bool createComment(RsGxsComment &comment) override; - - /// @deprecated Implementation of @see RsGxsChannels::createVote - RS_DEPRECATED_FOR(createVoteV2) - bool createVote(RsGxsVote& vote) override; - - -protected: - // Overloaded from GxsTokenQueue for Request callbacks. - virtual void handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) override; - - -private: - -static uint32_t channelsAuthenPolicy(); - - // Handle Processing. - void request_AllSubscribedGroups(); - void request_SpecificSubscribedGroups(const std::list &groups); - void load_SubscribedGroups(const uint32_t &token); - - void request_SpecificUnprocessedPosts(std::list > &ids); - void request_GroupUnprocessedPosts(const std::list &grouplist); - void load_unprocessedPosts(uint32_t token); - - void handleUnprocessedPost(const RsGxsChannelPost &msg); - - // Local Cache of Subscribed Groups. and AutoDownload Flag. - void updateSubscribedGroup(const RsGroupMetaData &group); - void clearUnsubscribedGroup(const RsGxsGroupId &id); - bool setAutoDownload(const RsGxsGroupId &groupId, bool enabled); - bool autoDownloadEnabled(const RsGxsGroupId &groupId, bool &enabled); - bool checkForOldAndUnusedChannels(); - -// DUMMY DATA, -virtual bool generateDummyData(); - -std::string genRandomId(); - -void dummy_tick(); - -bool generatePost(uint32_t &token, const RsGxsGroupId &grpId); -bool generateComment(uint32_t &token, const RsGxsGroupId &grpId, - const RsGxsMessageId &parentId, const RsGxsMessageId &threadId); -bool generateVote(uint32_t &token, const RsGxsGroupId &grpId, - const RsGxsMessageId &parentId, const RsGxsMessageId &threadId); - -bool generateGroup(uint32_t &token, std::string groupName); - - class ChannelDummyRef - { - public: - ChannelDummyRef() {} - ChannelDummyRef( - const RsGxsGroupId &grpId, const RsGxsMessageId &threadId, - const RsGxsMessageId &msgId ) : - mGroupId(grpId), mThreadId(threadId), mMsgId(msgId) {} - - RsGxsGroupId mGroupId; - RsGxsMessageId mThreadId; - RsGxsMessageId mMsgId; - }; - - std::map mSubscribedGroups; - RsMutex mSubscribedGroupsMutex; - - /** G10h4ck: Is this stuff really used? And for what? BEGIN */ - uint32_t mGenToken; - bool mGenActive; - int mGenCount; - std::vector mGenRefs; - RsGxsMessageId mGenThreadId; - /** G10h4ck: Is this stuff really used? And for what? END */ - - p3GxsCommentService* mCommentService; - - std::map mKnownChannels; - RsMutex mKnownChannelsMutex; - - rstime_t mLastDistantSearchNotificationTS; - - std::map > mSearchResultsToNotify; -#ifdef TO_REMOVE - /** Store search callbacks with timeout*/ - std::map< - TurtleRequestId, - std::pair< - std::function, - std::chrono::system_clock::time_point > - > mSearchCallbacksMap; - RsMutex mSearchCallbacksMapMutex; - - /** Store distant channels requests callbacks with timeout*/ - std::map< - TurtleRequestId, - std::pair< - std::function, - std::chrono::system_clock::time_point > - > mDistantChannelsCallbacksMap; - RsMutex mDistantChannelsCallbacksMapMutex; - - /// Cleanup mSearchCallbacksMap and mDistantChannelsCallbacksMap - void cleanTimedOutCallbacks(); -#endif -}; diff --git a/libretroshare/src/services/p3gxscircles.cc b/libretroshare/src/services/p3gxscircles.cc deleted file mode 100644 index 2fc99759f..000000000 --- a/libretroshare/src/services/p3gxscircles.cc +++ /dev/null @@ -1,2822 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3gxscircles.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012-2014 Robert Fernie * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "rsitems/rsgxscircleitems.h" - -#include "services/p3gxscircles.h" -#include "retroshare/rsgxsflags.h" -#include "util/rsrandom.h" -#include "util/rsdir.h" -#include "util/radix64.h" -#include "util/rsstring.h" -#include "util/rsdebug.h" -#include "pgp/pgpauxutils.h" -#include "retroshare/rsgxscircles.h" -#include "retroshare/rspeers.h" -#include "rsserver/p3face.h" - -#include -#include - -/**** - * #define DEBUG_CIRCLES 1 - ****/ - -/*extern*/ RsGxsCircles* rsGxsCircles = nullptr; - -/*static*/ const std::string RsGxsCircles::DEFAULT_CIRCLE_BASE_URL = - "retroshare:///circles"; -/*static*/ const std::string RsGxsCircles::CIRCLE_URL_NAME_FIELD = "circleName"; -/*static*/ const std::string RsGxsCircles::CIRCLE_URL_ID_FIELD = "circleId"; -/*static*/ const std::string RsGxsCircles::CIRCLE_URL_DATA_FIELD = "circleData"; - -static const uint32_t CIRCLES_UNUSED_BY_FRIENDS_DELAY = 60*86400 ; // 60 days ...O... - -RsGxsCircles::~RsGxsCircles() = default; -RsGxsCircleMsg::~RsGxsCircleMsg() = default; -RsGxsCircleDetails::~RsGxsCircleDetails() = default; -RsGxsCircleGroup::~RsGxsCircleGroup() = default; -RsGxsCircleEvent::~RsGxsCircleEvent() = default; - -/****** - * - * GxsCircles are used to limit the spread of Gxs Groups and Messages. - * - * This is done via GxsCircle parameters in GroupMetaData: - * mCircleType (ALL, External, Internal). - * mCircleId. - * - * The Circle Group contains the definition of who is allowed access to the Group. - * and GXS asks this service before forwarding any data. - * - * The CircleGroup contains: - * list of invited GxsId's - * list of GxsCircleId's (subcircles also allowed). - * - * This service runs a background task to transform the CircleGroups - * into a list of friends/peers who are allowed access. - * These results are cached to provide GXS with quick access to the information. - * This involves: - * - fetching the GroupData via GXS. - * - querying the list of GxsId to see if they are known (NB: this will cause caching of GxsId in p3IdService. - * - recursively loading subcircles to complete Circle definition. - * - saving the result into Cache. - * - * For Phase 1, we will only use the list of GxsIds. No subcircles will be allowed. - * Recursively determining membership via sub-circles is complex and needs more thought. - * The data-types for the full system, however, will be in-place. - * - * Circle Membership - * - Actual members of the circle are computed by intersecting the set of invited IDs with the set of IDs actually requesting membership. - * - To be a member, one therefore has to publish a membership message. To leave the circle, a new message is published accordingly. - * - * Circle Subscription system - * - Circles are subscribed only when we need to dispatch information about our own membership, or when we are admin of the circle. - * - Circle (group) membership is decided automatically. Not to be mixed up with whether or not to be a member of the circle, which is GUI based. - * - * Handling of old/dead circles - * - auto-subscription based on own membership requests should limit the spread of unwanted circles (such as when one adds all visible IDs into - * the invited list of a new circle. Such a circle would not be visible beyond friend nodes of the node creating that circle. - * - * - since this feature is new (in 0.6.6), there is already a bunch of unwanted circles. How we can get rid of them is not entirely clear. - * Indeed, once a node requests membership (and even later on denies it), it will have to remain subscribed to the circle group in order - * to ensure that this unsubscribe request keeps spreading from its actual source. A some point however, the circle msgs disappear, and - * therefore the circle will switch to unsubscribe automatically. - */ - -#define CIRCLEREQ_CACHELOAD 0x0001 -#define CIRCLEREQ_CIRCLE_LIST 0x0002 -#define CIRCLEREQ_MESSAGE_DATA 0x0003 - -//#define CIRCLEREQ_PGPHASH 0x0010 -//#define CIRCLEREQ_REPUTATION 0x0020 - -//#define CIRCLEREQ_CACHETEST 0x1000 - -// Events. -#define CIRCLE_EVENT_LOADIDS 0x0001 -#define CIRCLE_EVENT_CACHELOAD 0x0002 -#define CIRCLE_EVENT_RELOADIDS 0x0003 -#define CIRCLE_EVENT_DUMMYSTART 0x0004 -#define CIRCLE_EVENT_DUMMYLOAD 0x0005 -#define CIRCLE_EVENT_DUMMYGEN 0x0006 - -#define CIRCLE_DUMMY_STARTPERIOD 300 // MUST BE LONG ENOUGH FOR IDS TO HAVE BEEN MADE. -#define CIRCLE_DUMMY_GENPERIOD 10 - -//#define CIRCLE_EVENT_CACHETEST 0x1000 -//#define CACHETEST_PERIOD 60 -//#define OWNID_RELOAD_DELAY 10 - -#define GXSID_LOAD_CYCLE 10 // GXSID completes a load in this period. - -#define MIN_CIRCLE_LOAD_GAP 5 -#define GXS_CIRCLE_DELAY_TO_FORCE_MEMBERSHIP_UPDATE 60 // re-check every 1 mins. Normally this shouldn't be necessary since notifications inform abotu new messages. -#define GXS_CIRCLE_DELAY_TO_CHECK_MEMBERSHIP_UPDATE 60 // re-check every 1 mins. Normally this shouldn't be necessary since notifications inform abotu new messages. -#define GXS_CIRCLE_DELAY_TO_SEND_CACHE_UPDATED_EVENT 2 // do not send cache update events more often than every 2 secs. - -//====================================================================================// -// Startup // -//====================================================================================// - -p3GxsCircles::p3GxsCircles( RsGeneralDataService *gds, RsNetworkExchangeService *nes, p3IdService *identities, PgpAuxUtils *pgpUtils) - : RsGxsCircleExchange( gds, nes, new RsGxsCircleSerialiser(), RS_SERVICE_GXS_TYPE_GXSCIRCLE, identities, circleAuthenPolicy() ), - RsGxsCircles(static_cast(*this)), GxsTokenQueue(this), - RsTickEvent(), mIdentities(identities), mPgpUtils(pgpUtils), - mCircleMtx("p3GxsCircles"), - mKnownCirclesMtx("p3GxsCircles"), -// mCircleCache(DEFAULT_MEM_CACHE_SIZE, "GxsCircleCache" ), - mShouldSendCacheUpdateNotification(false) -{ - // Kick off Cache Testing, + Others. - //RsTickEvent::schedule_in(CIRCLE_EVENT_CACHETEST, CACHETEST_PERIOD); - mLastCacheMembershipUpdateTS = 0 ; - mLastCacheUpdateEvent = 0; - mLastDebugPrintTS = 0; - - RsTickEvent::schedule_now(CIRCLE_EVENT_CACHELOAD); - - mDummyIdToken = 0; -} - -static bool allowedGxsIdFlagTest(uint32_t subscription_flags,bool group_is_self_restricted) -{ - if(group_is_self_restricted) - return (subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST) && (subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_KEY_AVAILABLE); - else - return (subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST) && (subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED) && (subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_KEY_AVAILABLE); -} - -const std::string GXS_CIRCLES_APP_NAME = "gxscircle"; -const uint16_t GXS_CIRCLES_APP_MAJOR_VERSION = 1; -const uint16_t GXS_CIRCLES_APP_MINOR_VERSION = 0; -const uint16_t GXS_CIRCLES_MIN_MAJOR_VERSION = 1; -const uint16_t GXS_CIRCLES_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3GxsCircles::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_GXS_TYPE_GXSCIRCLE, - GXS_CIRCLES_APP_NAME, - GXS_CIRCLES_APP_MAJOR_VERSION, - GXS_CIRCLES_APP_MINOR_VERSION, - GXS_CIRCLES_MIN_MAJOR_VERSION, - GXS_CIRCLES_MIN_MINOR_VERSION); -} - -//====================================================================================// -// Synchroneous API from rsGxsCircles // -//====================================================================================// - -bool p3GxsCircles::createCircle( - const std::string& circleName, RsGxsCircleType circleType, - RsGxsCircleId& circleId, const RsGxsCircleId& restrictedId, - const RsGxsId& authorId, const std::set& gxsIdMembers, - const std::set& localMembers ) -{ - // 1 - Check consistency of the request data - - if(!checkCircleParamConsistency(circleName,circleType,restrictedId,authorId,gxsIdMembers,localMembers)) - { - RsErr() << __PRETTY_FUNCTION__ << " Circle parameters are inconsistent" << std::endl; - return false; - } - - // 2 - Create the actual request - - RsGxsCircleGroup cData; - cData.mMeta.mGroupName = circleName; - cData.mMeta.mAuthorId = authorId; - cData.mMeta.mCircleType = static_cast(circleType); - cData.mMeta.mGroupFlags = GXS_SERV::FLAG_PRIVACY_PUBLIC; - cData.mMeta.mCircleId = restrictedId; - cData.mMeta.mSignFlags = GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_NONEREQ | GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_REQUIRED; - cData.mLocalFriends = localMembers; - cData.mInvitedMembers = gxsIdMembers; - - - // 3 - Send it and wait, for a sync response. - - uint32_t token; - createGroup(token, cData); - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed." << std::endl; - return false; - } - - if(!RsGenExchange::getPublishedGroupMeta(token, cData.mMeta)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting created" << " group data." << std::endl; - return false; - } - - circleId = static_cast(cData.mMeta.mGroupId); - return true; -}; - -bool p3GxsCircles::checkCircleParamConsistency( const std::string& circleName, RsGxsCircleType circleType, - const RsGxsCircleId& restrictedId, - const RsGxsId& /*authorId*/, const std::set& gxsIdMembers, - const std::set& localMembers ) const -{ - if(circleName.empty()) - { - RsErr() << __PRETTY_FUNCTION__ << " Circle name is empty" << std::endl; - return false; - } - - switch(circleType) - { - case RsGxsCircleType::PUBLIC: - if(!restrictedId.isNull()) - { - RsErr() << __PRETTY_FUNCTION__ << " restrictedId: " << restrictedId - << " must be null with RsGxsCircleType::PUBLIC" - << std::endl; - return false; - } - break; - case RsGxsCircleType::EXTERNAL: - if(restrictedId.isNull()) - { - RsErr() << __PRETTY_FUNCTION__ << " restrictedId can't be null " - << "with RsGxsCircleType::EXTERNAL" << std::endl; - return false; - } - break; - case RsGxsCircleType::NODES_GROUP: - if(localMembers.empty()) - { - RsErr() << __PRETTY_FUNCTION__ << " localMembers can't be empty " - << "with RsGxsCircleType::NODES_GROUP" << std::endl; - return false; - } - break; - case RsGxsCircleType::LOCAL: - break; - case RsGxsCircleType::EXT_SELF: - if(!restrictedId.isNull()) - { - RsErr() << __PRETTY_FUNCTION__ << " restrictedId: " << restrictedId - << " must be null with RsGxsCircleType::EXT_SELF" - << std::endl; - return false; - } - if(gxsIdMembers.empty()) - { - RsErr() << __PRETTY_FUNCTION__ << " gxsIdMembers can't be empty " - << "with RsGxsCircleType::EXT_SELF" << std::endl; - return false; - } - break; - case RsGxsCircleType::YOUR_EYES_ONLY: - break; - default: - RsErr() << __PRETTY_FUNCTION__ << " Invalid circle type: " - << static_cast(circleType) << std::endl; - return false; - } - return true; -} - -bool p3GxsCircles::editCircle(RsGxsCircleGroup& cData) -{ - uint32_t token; - updateGroup(token, cData); - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed." - << std::endl; - return false; - } - - if(!RsGenExchange::getPublishedGroupMeta(token, cData.mMeta)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting updated" - << " group data." << std::endl; - return false; - } - - return true; -} - -bool p3GxsCircles::editCircle(const RsGxsCircleId &circleId, const std::string& circleName, RsGxsCircleType circleType, const RsGxsCircleId& restrictedId, - const RsGxsId& authorId, const std::set& gxsIdMembers, - const std::set& localMembers ) -{ - // 1 - Check consistency of the request data - - if(!checkCircleParamConsistency(circleName,circleType,restrictedId,authorId,gxsIdMembers,localMembers)) - { - RsErr() << __PRETTY_FUNCTION__ << " Circle data is not consistent." << std::endl; - return false; - } - - // 2 - Create the actual request - - RsGxsCircleGroup cData; - cData.mMeta.mGroupId = RsGxsGroupId(circleId); - cData.mMeta.mGroupName = circleName; - cData.mMeta.mAuthorId = authorId; - cData.mMeta.mCircleType = static_cast(circleType); - cData.mMeta.mGroupFlags = GXS_SERV::FLAG_PRIVACY_PUBLIC; - cData.mMeta.mCircleId = restrictedId; - cData.mLocalFriends = localMembers; - cData.mInvitedMembers = gxsIdMembers; - - // 3 - Send it and wait, for a sync response. - - uint32_t token; - updateGroup(token, cData); - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed." - << std::endl; - return false; - } - - if(!RsGenExchange::getPublishedGroupMeta(token, cData.mMeta)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting updated" - << " group data." << std::endl; - return false; - } - - return true; -}; - -bool p3GxsCircles::getCirclesSummaries(std::list& circles) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; - if( !requestGroupInfo(token, opts) || waitToken(token) != RsTokenService::COMPLETE ) - { - std::cerr << "Cannot get circles summary. Token queue is overloaded?" << std::endl; - return false; - } - else - return getGroupSummary(token, circles); -} - -bool p3GxsCircles::getCirclesInfo( const std::list& circlesIds, - std::vector& circlesInfo ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - if( !requestGroupInfo(token, opts, circlesIds) || waitToken(token) != RsTokenService::COMPLETE ) - { - std::cerr << "Cannot get circle info. Token queue is overloaded?" << std::endl; - return false; - } - else - return getGroupData(token, circlesInfo); -} - -bool p3GxsCircles::getCircleRequests( const RsGxsGroupId& circleId, - std::vector& requests ) -{ - uint32_t token; - std::list grpIds { circleId }; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - - if( !requestMsgInfo(token, opts, grpIds) || - waitToken(token) != RsTokenService::COMPLETE ) return false; - - return getMsgData(token, requests); -} - -bool p3GxsCircles::getCircleRequest(const RsGxsGroupId& circleId,const RsGxsMessageId& msgId,RsGxsCircleMsg& msg) -{ - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - - std::set contentsIds; - contentsIds.insert(msgId); - - GxsMsgReq msgIds; - msgIds[circleId] = contentsIds; - - uint32_t token; - if( !requestMsgInfo(token, opts, msgIds) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - - std::vector msgs; - - if(getMsgData(token, msgs) && msgs.size() == 1) - { - msg = msgs.front(); - return true; - } - else - return false; -} - -bool p3GxsCircles::inviteIdsToCircle( const std::set& identities, - const RsGxsCircleId& circleId ) -{ - const std::list circlesIds{ RsGxsGroupId(circleId) }; - std::vector circlesInfo; - - if(!getCirclesInfo(circlesIds, circlesInfo)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting group data." - << std::endl; - return false; - } - - if(circlesInfo.empty()) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Circle: " - << circleId.toStdString() << " not found!" << std::endl; - return false; - } - - RsGxsCircleGroup& circleGrp = circlesInfo[0]; - - if(!(circleGrp.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Attempt to edit non-own " - << "circle: " << circleId.toStdString() << std::endl; - return false; - } - - circleGrp.mInvitedMembers.insert(identities.begin(), identities.end()); - - return editCircle(circleGrp); -} - -bool p3GxsCircles::revokeIdsFromCircle( const std::set& identities, const RsGxsCircleId& circleId ) -{ - const std::list circlesIds{ RsGxsGroupId(circleId) }; - std::vector circlesInfo; - - if(!getCirclesInfo(circlesIds, circlesInfo)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting group data." << std::endl; - return false; - } - - if(circlesInfo.empty()) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Circle: " << circleId.toStdString() << " not found!" << std::endl; - return false; - } - - RsGxsCircleGroup& circleGrp = circlesInfo[0]; - - if(!(circleGrp.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Attempt to edit non-own " << "circle: " << circleId.toStdString() << std::endl; - return false; - } - - // /!\ AVOID calling circleGrp.mInvitedMembers.erase(identities.begin(),identities.end()), because it is not the same set. Consequently - // STL code would corrupt the structure of mInvitedMembers. - - std::set new_invited_members; - for(auto& gxs_id: circleGrp.mInvitedMembers) - if(identities.find(gxs_id) == identities.end()) - new_invited_members.insert(gxs_id); - - circleGrp.mInvitedMembers = new_invited_members; - - return editCircle(circleGrp); -} - -bool p3GxsCircles::exportCircleLink( - std::string& link, const RsGxsCircleId& circleId, - bool includeGxsData, const std::string& baseUrl, std::string& errMsg ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - errMsg = err; - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(circleId.isNull()) return failure("circleId cannot be null"); - - const bool outputRadix = baseUrl.empty(); - if(outputRadix && !includeGxsData) return - failure("includeGxsData must be true if format requested is base64"); - - RsGxsGroupId&& groupId = static_cast(circleId); - if( includeGxsData && - !RsGenExchange::exportGroupBase64(link, groupId, errMsg) ) - return failure(errMsg); - - if(outputRadix) return true; - - std::vector circlesInfo; - if( !getCirclesInfo( - std::list({groupId}), circlesInfo ) - || circlesInfo.empty() ) - return failure("failure retrieving circle information"); - - RsUrl inviteUrl(baseUrl); - inviteUrl.setQueryKV(CIRCLE_URL_ID_FIELD, circleId.toStdString()); - inviteUrl.setQueryKV(CIRCLE_URL_NAME_FIELD, circlesInfo[0].mMeta.mGroupName); - if(includeGxsData) inviteUrl.setQueryKV(CIRCLE_URL_DATA_FIELD, link); - - link = inviteUrl.toString(); - return true; -} - -bool p3GxsCircles::importCircleLink( - const std::string& link, RsGxsCircleId& circleId, - std::string& errMsg ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - errMsg = err; - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(link.empty()) return failure("link is empty"); - - const std::string* radixPtr(&link); - - RsUrl url(link); - const auto& query = url.query(); - const auto qIt = query.find(CIRCLE_URL_DATA_FIELD); - if(qIt != query.end()) radixPtr = &qIt->second; - - if(radixPtr->empty()) return failure(CIRCLE_URL_DATA_FIELD + " is empty"); - - if(!RsGenExchange::importGroupBase64( - *radixPtr, reinterpret_cast(circleId), errMsg) ) - return failure(errMsg); - - return true; -} - -uint32_t p3GxsCircles::circleAuthenPolicy() -{ - uint32_t policy = 0; - uint8_t flag = 0; - - flag = GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS); - - flag |= GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS); - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS); - - flag = 0; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::GRP_OPTION_BITS); - - return policy; -} - -//====================================================================================// -// Tick // -//====================================================================================// - -void p3GxsCircles::service_tick() -{ - RsTickEvent::tick_events(); - GxsTokenQueue::checkRequests(); // GxsTokenQueue handles all requests. - - rstime_t now = time(NULL); - - if(mShouldSendCacheUpdateNotification && now > mLastCacheUpdateEvent + GXS_CIRCLE_DELAY_TO_SEND_CACHE_UPDATED_EVENT) - { - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mCircleEventType = RsGxsCircleEventCode::CACHE_DATA_UPDATED; - rsEvents->postEvent(ev); - } - - mLastCacheUpdateEvent = now; - mShouldSendCacheUpdateNotification = false; - } - - if(now > mLastCacheMembershipUpdateTS + GXS_CIRCLE_DELAY_TO_CHECK_MEMBERSHIP_UPDATE) - { - checkCircleCache(); - mLastCacheMembershipUpdateTS = now ; - } - -#ifdef DEBUG_CIRCLES - if(now > mLastDebugPrintTS) - { - mLastDebugPrintTS = now; - debug_dumpCache(); - } -#endif -} - -//====================================================================================// -// Handling of GXS changes // -//====================================================================================// - -void p3GxsCircles::notifyChanges(std::vector &changes) -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::notifyChanges()"; - std::cerr << std::endl; -#endif - - //p3Notify *notify = RsServer::notify(); - std::set circles_to_reload; - - for(auto it = changes.begin(); it != changes.end(); ++it) - { - RsGxsNotify *c = *it; - RsGxsMsgChange *msgChange = dynamic_cast(c); - - if (msgChange) - { -#ifdef DEBUG_CIRCLES - std::cerr << " Found circle Message Change Notification for group " << msgChange->mGroupId << ", msg ID " << msgChange->mMsgId << std::endl; - std::cerr << " Msgs for Group: " << msgChange->mGroupId << std::endl; -#endif - RsGxsCircleId circle_id(msgChange->mGroupId); - - if(rsEvents && ((c->getType() == RsGxsNotify::TYPE_RECEIVED_NEW) || (c->getType() == RsGxsNotify::TYPE_PUBLISHED))) - { - const RsGxsCircleSubscriptionRequestItem *item = dynamic_cast(msgChange->mNewMsgItem); - - if(item) - { - auto ev = std::make_shared(); - ev->mCircleId = circle_id; - ev->mGxsId = msgChange->mNewMsgItem->meta.mAuthorId; - - if (item->subscription_type == RsGxsCircleSubscriptionType::UNSUBSCRIBE) - { - ev->mCircleEventType = RsGxsCircleEventCode::CIRCLE_MEMBERSHIP_LEAVE; - rsEvents->postEvent(ev); - } - else if(item->subscription_type == RsGxsCircleSubscriptionType::SUBSCRIBE) - { - ev->mCircleEventType = RsGxsCircleEventCode::CIRCLE_MEMBERSHIP_REQUEST; - rsEvents->postEvent(ev); - } - else - RsErr() << __PRETTY_FUNCTION__ << " Unknown subscription request type " << static_cast(item->subscription_type) << " in msg item" << std::endl; - } - else - RsErr() << __PRETTY_FUNCTION__ << ": missing SubscriptionRequestItem in msg notification for msg " << msgChange->mMsgId << std::endl; - } - - circles_to_reload.insert(circle_id); - } - - RsGxsGroupChange *groupChange = dynamic_cast(c); - - /* add groups to ExternalIdList (Might get Personal Circles here until NetChecks in place) */ - if (groupChange) - { - const RsGxsGroupId *git(&groupChange->mGroupId); - -#ifdef DEBUG_CIRCLES - std::cerr << " Found Group Change Notification of type " << c->getType() << std::endl; -#endif - switch(c->getType()) - { - case RsGxsNotify::TYPE_RECEIVED_NEW: - case RsGxsNotify::TYPE_UPDATED: - case RsGxsNotify::TYPE_PUBLISHED: - { -#ifdef DEBUG_CIRCLES - std::cerr << " Incoming/created/updated Group: " << *git << ". Forcing cache load." << std::endl; -#endif - - // for new circles we need to add them to the list. - // we don't know the type of this circle here - // original behavior was to add all ids to the external ids list - circles_to_reload.insert(RsGxsCircleId(*git)); - - } // fallthrough - case RsGxsNotify::TYPE_STATISTICS_CHANGED: - { - RS_STACK_MUTEX(mKnownCirclesMtx); - mKnownCircles[*git] = time(nullptr); - IndicateConfigChanged(); - } - break; - default: -#ifdef DEBUG_CIRCLES - std::cerr << " Type: " << c->getType() << " is ignored" << std::endl; -#endif - break; - } - - // Now compute which events should be sent. - - if(rsEvents) - { - if(c->getType() == RsGxsNotify::TYPE_RECEIVED_NEW|| c->getType() == RsGxsNotify::TYPE_PUBLISHED) - { - auto ev = std::make_shared(); - ev->mCircleId = RsGxsCircleId(*git); - ev->mCircleEventType = RsGxsCircleEventCode::NEW_CIRCLE; - - rsEvents->postEvent(ev); - - // we also need to look into invitee list here! - - RsGxsCircleGroupItem *new_circle_grp_item = dynamic_cast(groupChange->mNewGroupItem); - - if(new_circle_grp_item) // groups published by us do not come in the mNewGroupItem field. It's possible to add them, in rsgenexchange.cc:2806 - for(auto& gxs_id: new_circle_grp_item->gxsIdSet.ids) - { - auto ev = std::make_shared(); - - ev->mCircleEventType = RsGxsCircleEventCode::CIRCLE_MEMBERSHIP_ID_ADDED_TO_INVITEE_LIST; - ev->mCircleId = RsGxsCircleId(*git); - ev->mGxsId = gxs_id; - - rsEvents->postEvent(ev); - } - } - else if(c->getType()==RsGxsNotify::TYPE_UPDATED) - { - // Happens when the group data has changed. In this case we need to analyse the old and new group in order to detect possible notifications for clients - - RsGxsCircleGroupItem *old_circle_grp_item = dynamic_cast(groupChange->mOldGroupItem); - RsGxsCircleGroupItem *new_circle_grp_item = dynamic_cast(groupChange->mNewGroupItem); - - if(old_circle_grp_item == nullptr || new_circle_grp_item == nullptr) - { - RsErr() << __PRETTY_FUNCTION__ << " received GxsGroupUpdate item with mOldGroup and mNewGroup not of type RsGxsCircleGroupItem. This is inconsistent!" << std::endl; - delete groupChange; - continue; - } - - const RsGxsCircleId circle_id ( old_circle_grp_item->meta.mGroupId ); - - // First of all, we check if there is a difference between the old and new list of invited members - - for(auto& gxs_id: new_circle_grp_item->gxsIdSet.ids) - if(old_circle_grp_item->gxsIdSet.ids.find(gxs_id) == old_circle_grp_item->gxsIdSet.ids.end()) - { - auto ev = std::make_shared(); - - ev->mCircleEventType = RsGxsCircleEventCode::CIRCLE_MEMBERSHIP_ID_ADDED_TO_INVITEE_LIST; - ev->mCircleId = circle_id; - ev->mGxsId = gxs_id; - - rsEvents->postEvent(ev); - } - - for(auto& gxs_id: old_circle_grp_item->gxsIdSet.ids) - if(new_circle_grp_item->gxsIdSet.ids.find(gxs_id) == old_circle_grp_item->gxsIdSet.ids.end()) - { - auto ev = std::make_shared(); - - ev->mCircleEventType = RsGxsCircleEventCode::CIRCLE_MEMBERSHIP_ID_REMOVED_FROM_INVITEE_LIST; - ev->mCircleId = circle_id; - ev->mGxsId = gxs_id; - - rsEvents->postEvent(ev); - } - - if( old_circle_grp_item->meta.mGroupName != new_circle_grp_item->meta.mGroupName - || old_circle_grp_item->meta.mGroupFlags != new_circle_grp_item->meta.mGroupFlags - || old_circle_grp_item->meta.mAuthorId != new_circle_grp_item->meta.mAuthorId - || old_circle_grp_item->meta.mCircleId != new_circle_grp_item->meta.mCircleId - ) - { - auto ev = std::make_shared(); - ev->mCircleId = RsGxsCircleId(new_circle_grp_item->meta.mGroupId); - ev->mCircleEventType = RsGxsCircleEventCode::CIRCLE_UPDATED; - rsEvents->postEvent(ev); - } - } - else if(c->getType()==RsGxsNotify::TYPE_GROUP_DELETED) - { - auto ev = std::make_shared(); - - ev->mCircleEventType = RsGxsCircleEventCode::CIRCLE_DELETED; - ev->mCircleId = RsGxsCircleId(groupChange->mGroupId); - - rsEvents->postEvent(ev); - } - } - } - - delete c; - } - - for(auto& circle_id:circles_to_reload) - force_cache_reload(circle_id); -} - -//====================================================================================// -// Synchroneous API using cache storage // -//====================================================================================// - -bool p3GxsCircles::getCircleDetails(const RsGxsCircleId& id, RsGxsCircleDetails& details) -{ - -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::getCircleDetails(" << id << ")"; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - - { - bool should_reload = false; - - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - RsGxsCircleCache& data(mCircleCache[id]); - - if(data.mStatus < CircleEntryCacheStatus::LOADING) - should_reload = true; - - if(data.mStatus == CircleEntryCacheStatus::LOADING) - return false; - - // should also have meta data.... - - if(!should_reload) - { - details.mCircleId = id; - details.mCircleName = data.mCircleName; - - details.mCircleType = data.mCircleType; - details.mRestrictedCircleId = data.mRestrictedCircleId; - - details.mAllowedNodes = data.mAllowedNodes; - details.mSubscriptionFlags.clear(); - details.mAllowedGxsIds.clear(); - details.mAmIAllowed = false ; - details.mAmIAdmin = bool(data.mGroupSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN); - - for(std::map::const_iterator it(data.mMembershipStatus.begin());it!=data.mMembershipStatus.end();++it) - { - details.mSubscriptionFlags[it->first] = it->second.subscription_flags ; - - if(it->second.subscription_flags == GXS_EXTERNAL_CIRCLE_FLAGS_ALLOWED) - { - details.mAllowedGxsIds.insert(it->first) ; - - if(rsIdentity->isOwnId(it->first)) - details.mAmIAllowed = true ; - } - } - - return true; - } - } - - cache_request_load(id); - return false; -} - -bool p3GxsCircles::getCircleExternalIdList(std::set &circleIds) -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::getCircleIdList()"; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - - for(auto& cache: mCircleCache) - if(cache.second.mIsExternal) - circleIds.insert(cache.first); - - return true; -} - -bool p3GxsCircles::isLoaded(const RsGxsCircleId &circleId) -{ - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - - return mCircleCache.is_cached(circleId) && (mCircleCache[circleId].mStatus >= CircleEntryCacheStatus::UPDATING); -} - -bool p3GxsCircles::loadCircle(const RsGxsCircleId &circleId) -{ - return cache_request_load(circleId); -} - -int p3GxsCircles::canSend(const RsGxsCircleId &circleId, const RsPgpId &id, bool& should_encrypt) -{ - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - if (mCircleCache.is_cached(circleId)) - { - RsGxsCircleCache& data = mCircleCache.ref(circleId); - - if(data.mStatus < CircleEntryCacheStatus::UPDATING) - return 0; - - should_encrypt = (data.mCircleType == RsGxsCircleType::EXTERNAL); - - if (data.isAllowedPeer(id)) - return 1; - - return 0; - } - return -1; -} - -int p3GxsCircles::canReceive(const RsGxsCircleId &circleId, const RsPgpId &id) -{ - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - if (mCircleCache.is_cached(circleId)) - { - RsGxsCircleCache &data = mCircleCache.ref(circleId); - - if(data.mStatus < CircleEntryCacheStatus::UPDATING) - return 0; - - if (data.isAllowedPeer(id)) - { - return 1; - } - return 0; - } - return -1; -} - -bool p3GxsCircles::recipients(const RsGxsCircleId &circleId, std::list& friendlist) -{ - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - if (mCircleCache.is_cached(circleId)) - { - RsGxsCircleCache &data = mCircleCache.ref(circleId); - - if(data.mStatus < CircleEntryCacheStatus::UPDATING) - return 0; - - data.getAllowedPeersList(friendlist); - return true; - } - return false; -} - -bool p3GxsCircles::isRecipient(const RsGxsCircleId &circleId, const RsGxsGroupId& destination_group, const RsGxsId& id) -{ - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - if (mCircleCache.is_cached(circleId)) - { - const RsGxsCircleCache &data = mCircleCache.ref(circleId); - - if(data.mStatus < CircleEntryCacheStatus::UPDATING) - return 0; - - return data.isAllowedPeer(id,destination_group); - } - return false; -} - -// This function uses the destination group for the transaction in order to decide which list of -// keys to ecnrypt to. When sending to a self-restricted group, the list of recipients is extended to -// the admin list rather than just the members list. - -bool p3GxsCircles::recipients(const RsGxsCircleId& circleId, const RsGxsGroupId& dest_group, std::list& gxs_ids) -{ - gxs_ids.clear() ; - - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - if (!mCircleCache.is_cached(circleId)) - return false ; - - const RsGxsCircleCache& cache = mCircleCache.ref(circleId); - - if(cache.mStatus < CircleEntryCacheStatus::UPDATING) - return 0; - - for(std::map::const_iterator it(cache.mMembershipStatus.begin());it!=cache.mMembershipStatus.end();++it) - if(allowedGxsIdFlagTest(it->second.subscription_flags, RsGxsCircleId(dest_group) == circleId)) - gxs_ids.push_back(it->first) ; - - return true; -} - -//====================================================================================// -// Asynchroneous API using token system // -//====================================================================================// - - -bool p3GxsCircles::getGroupData(const uint32_t &token, std::vector &groups) -{ - - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); ++vit) - { - RsGxsCircleGroupItem* item = dynamic_cast(*vit); - if (item) - { - RsGxsCircleGroup group; - item->convertTo(group); - - // If its cached - add that info (TODO). - groups.push_back(group); - delete(item); - } - else - { - std::cerr << "p3GxsCircles::getGroupData()"; - std::cerr << " Not a RsGxsCircleGroupItem, deleting!"; - std::cerr << std::endl; - delete *vit; - } - } - } - - return ok; -} - -bool p3GxsCircles::getMsgData(const uint32_t &token, std::vector &msgs) -{ - GxsMsgDataMap msgData; - bool ok = RsGenExchange::getMsgData(token, msgData); - - if(ok) - { - GxsMsgDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsCircleSubscriptionRequestItem* rsItem = dynamic_cast(*vit); - - if (rsItem) - { - RsGxsCircleMsg msg ;//= rsItem->mMsg; - msg.mMeta = rsItem->meta; - msg.mSubscriptionType = rsItem->subscription_type; - - msgs.push_back(msg); - delete rsItem; - } - else - { - std::cerr << "Not a GxsCircleMsgItem, deleting!" << std::endl; - delete *vit; - } - } - } - } - - return ok; -} - -void p3GxsCircles::createGroup(uint32_t& token, RsGxsCircleGroup &group) -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::createGroup()"; - std::cerr << " CircleType: " << (uint32_t) group.mMeta.mCircleType; - std::cerr << " CircleId: " << group.mMeta.mCircleId.toStdString(); - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - - RsGxsCircleGroupItem* item = new RsGxsCircleGroupItem(); - item->convertFrom(group); - - RsGenExchange::publishGroup(token, item); -} - -void p3GxsCircles::updateGroup(uint32_t &token, RsGxsCircleGroup &group) -{ - // note: refresh of circle cache gets triggered in the RsGenExchange::notifyChanges() callback - RsGxsCircleGroupItem* item = new RsGxsCircleGroupItem(); - item->convertFrom(group); - - RsGenExchange::updateGroup(token, item); -} - -RsGenExchange::ServiceCreate_Return p3GxsCircles::service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& /*keySet*/) -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::service_CreateGroup()"; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - - RsGxsCircleGroupItem *item = dynamic_cast(grpItem); - if (!item) - { - std::cerr << "p3GxsCircles::service_CreateGroup() ERROR invalid cast"; - std::cerr << std::endl; - return SERVICE_CREATE_FAIL; - } - - // Now copy the GroupId into the mCircleId, and set the mode. - if (item->meta.mCircleType == GXS_CIRCLE_TYPE_EXT_SELF) - { - item->meta.mCircleType = GXS_CIRCLE_TYPE_EXTERNAL; - item->meta.mCircleId = RsGxsCircleId(item->meta.mGroupId); - } - - return SERVICE_CREATE_SUCCESS; -} - -//====================================================================================// -// Cache system management // -//====================================================================================// - -RsGxsCircleCache::RsGxsCircleCache() -{ - mCircleType = RsGxsCircleType::EXTERNAL; - mIsExternal = true; - mLastUpdateTime = 0; - mGroupStatus = 0; - mGroupSubscribeFlags = 0; - mLastUpdatedMembershipTS = 0 ; - mStatus = CircleEntryCacheStatus::NO_DATA_YET; - mAllIdsHere = false; - mDoIAuthorAMembershipMsg = false; - - return; -} - -bool RsGxsCircleCache::loadBaseCircle(const RsGxsCircleGroup& circle) -{ -#ifdef DEBUG_CIRCLES - std::cerr << "RsGxsCircleCache::loadBaseCircle(" << mCircleId << "):" << std::endl; -#endif // DEBUG_CIRCLES - - mCircleId = RsGxsCircleId(circle.mMeta.mGroupId); - mCircleName = circle.mMeta.mGroupName; - // mProcessedCircles.insert(mCircleId); - - mCircleType = static_cast(circle.mMeta.mCircleType); - mIsExternal = (mCircleType != RsGxsCircleType::LOCAL); - mGroupStatus = circle.mMeta.mGroupStatus; - mGroupSubscribeFlags = circle.mMeta.mSubscribeFlags; - mOriginator = circle.mMeta.mOriginator ; - - mAllowedNodes = circle.mLocalFriends ; - mRestrictedCircleId = circle.mMeta.mCircleId ; - - // We do not clear mMembershipStatus because this might be an update and if we do, it will clear membership requests - // that are not in the invited list! - - for(std::set::const_iterator it(circle.mInvitedMembers.begin());it!=circle.mInvitedMembers.end();++it) - { - RsGxsCircleMembershipStatus& s(mMembershipStatus[*it]) ; - s.subscription_flags |= GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST ; - - // This one can be cleared because it will anyway be updated to the latest when loading subscription request messages and it wil only - // be used there as well. - - s.last_subscription_TS = 0 ; - -#ifdef DEBUG_CIRCLES - std::cerr << " Invited member " << *it << " Initializing/updating membership status to " << std::hex << s.subscription_flags << std::dec << std::endl; -#endif // DEBUG_CIRCLES - } - - // also sweep through the list of subscribed members and remove the membership to those who are not in the invitee list anymore - - for(auto& m:mMembershipStatus) - if(circle.mInvitedMembers.find(m.first) == circle.mInvitedMembers.end()) - { - m.second.subscription_flags &= ~GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST; -#ifdef DEBUG_CIRCLES - std::cerr << " member " << m.first << " is not in invitee list. Updating flags to " << std::hex << m.second.subscription_flags << std::dec << std::endl; -#endif // DEBUG_CIRCLES - } - - return true; -} - -bool RsGxsCircleCache::loadSubCircle(const RsGxsCircleCache &subcircle) -{ - /* copy across all the lists */ - - /* should not be any unprocessed circles or peers */ -#ifdef DEBUG_CIRCLES -#endif // DEBUG_CIRCLES - - std::cerr << "RsGxsCircleCache::loadSubCircle(" << subcircle.mCircleId << ") TODO"; - std::cerr << std::endl; - - return true; -} - -bool RsGxsCircleCache::getAllowedPeersList(std::list& friendlist) const -{ - friendlist.clear() ; - - for(auto it = mAllowedNodes.begin(); it != mAllowedNodes.end(); ++it) - friendlist.push_back(*it) ; - - return true; -} - -bool RsGxsCircleCache::isAllowedPeer(const RsGxsId& id,const RsGxsGroupId& destination_group) const -{ - auto it = mMembershipStatus.find(id) ; - - if(it == mMembershipStatus.end()) - return false ; - - return allowedGxsIdFlagTest(it->second.subscription_flags, RsGxsGroupId(mCircleId) == destination_group) ; -} - -bool RsGxsCircleCache::isAllowedPeer(const RsPgpId &id) const -{ - return mAllowedNodes.find(id) != mAllowedNodes.end() ; -} - -bool RsGxsCircleCache::addLocalFriend(const RsPgpId &pgpId) -{ - /* empty list as no GxsID associated */ - mAllowedNodes.insert(pgpId) ; - return true; -} - -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ -// Complicated deal of loading Circles. - -bool p3GxsCircles::force_cache_reload(const RsGxsCircleId& id) -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::force_cache_reload(): Forcing cache reload of Circle ID " << id << std::endl; -#endif - - cache_request_load(id) ; - return true ; -} - -bool p3GxsCircles::cache_request_load(const RsGxsCircleId &id) -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::cache_request_load(" << id << ")"; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - - { - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - - /* check it is not already being loaded */ - - RsGxsCircleCache& cache(mCircleCache[id]); - - if(cache.mStatus < CircleEntryCacheStatus::LOADING) - cache.mCircleId = id; - - if(cache.mStatus == CircleEntryCacheStatus::LOADING || cache.mStatus == CircleEntryCacheStatus::UPDATING) - return false; - - // Put it into the Loading Cache - so we will detect it later. - - if(cache.mLastUpdateTime > 0) - cache.mStatus = CircleEntryCacheStatus::UPDATING; - else - cache.mStatus = CircleEntryCacheStatus::LOADING; - - mCirclesToLoad.insert(id); - } - - if (RsTickEvent::event_count(CIRCLE_EVENT_CACHELOAD) > 0) /* its already scheduled */ - return true; - - int32_t age = 0; - if (RsTickEvent::prev_event_ago(CIRCLE_EVENT_CACHELOAD, age) && age groupIds; - { - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - - /* now we process the modGroupList -> a map so we can use it easily later, and create id list too */ - - for(auto& circle_id:mCirclesToLoad) - { -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::cache_start_load() GroupId: " << circle_id << std::endl; -#endif // DEBUG_CIRCLES - - groupIds.push_back(RsGxsGroupId(circle_id.toStdString())); // might need conversion? - } - - mCirclesToLoad.clear(); - } - - if (groupIds.size() > 0) - { -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::cache_start_load() #Groups: " << groupIds.size(); - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - - uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - uint32_t token = 0; - - RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts, groupIds); - GxsTokenQueue::queueRequest(token, CIRCLEREQ_CACHELOAD); - } - return true; -} - - -bool p3GxsCircles::cache_load_for_token(uint32_t token) -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::cache_load_for_token() : " << token << std::endl; -#endif // DEBUG_CIRCLES - - std::vector grpData; - - if(!RsGenExchange::getGroupData(token, grpData)) - { - std::cerr << "p3GxsCircles::cache_load_for_token() ERROR no data"; - std::cerr << std::endl; - - return false; - } - - for(auto vit = grpData.begin(); vit != grpData.end(); ++vit) - { - RsGxsCircleGroupItem *item = dynamic_cast(*vit); - - if (!item) - { - std::cerr << " Not a RsGxsCircleGroupItem Item, deleting!" << std::endl; - delete(*vit); - continue; - } - RsGxsCircleGroup group; - item->convertTo(group); - -#ifdef DEBUG_CIRCLES - std::cerr << " Loaded Id with Meta: " << item->meta << std::endl; -#endif // DEBUG_CIRCLES - - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - - /* should already have a LoadingCache entry */ - RsGxsCircleId id = RsGxsCircleId(item->meta.mGroupId) ; - RsGxsCircleCache& cache(mCircleCache[id]); - - cache.loadBaseCircle(group); - delete item; - - if(locked_processLoadingCacheEntry(cache)) - { -#ifdef DEBUG_CIRCLES - std::cerr << " All peers available. Moving to cache..." << std::endl; -#endif - cache.mAllIdsHere = true; - - // We can check for self inclusion in the circle right away, since own ids are always loaded. - // that allows to subscribe/unsubscribe uncomplete circles - - cache.mStatus = CircleEntryCacheStatus::CHECKING_MEMBERSHIP; - cache.mLastUpdatedMembershipTS = 0; // force processing of membership request - locked_checkCircleCacheForMembershipUpdate(cache); - } - else - { -#ifdef DEBUG_CIRCLES - std::cerr << " Unprocessed peers. Requesting reload..." << std::endl; -#endif - cache.mAllIdsHere = false; - cache.mStatus = CircleEntryCacheStatus::UPDATING; - - /* schedule event to try reload gxsIds */ - RsTickEvent::schedule_in(CIRCLE_EVENT_RELOADIDS, GXSID_LOAD_CYCLE, id.toStdString()); - } - mShouldSendCacheUpdateNotification = true; - } - - return true; -} - -// This method parses the cache entry and makes sure that all ids are known. If not, requests the missing ids -// when done, the entry is removed from mLoadingCache - -bool p3GxsCircles::locked_processLoadingCacheEntry(RsGxsCircleCache& cache) -{ - //bool isUnprocessedPeers = false; - - if (!cache.mIsExternal) - return true; - -#ifdef DEBUG_CIRCLES - std::cerr << "Processing External Circle " << cache.mCircleId << std::endl; -#endif - bool all_ids_here = true; - - // Do we actually need to retrieve the missing keys for all members of a circle??? - // These keys are needed for subscribtion request signature checking. But this is only - // when a subscription msg is posted, which would trigger retrieval of the key anyway - // Maybe this can be made an option of p3GxsCircles, or of rsIdentity. - - // need to trigger the searches. - for(std::map::iterator pit = cache.mMembershipStatus.begin(); pit != cache.mMembershipStatus.end(); ++pit) - { -#ifdef DEBUG_CIRCLES - std::cerr << " Member status: " << pit->first << " : " << pit->second.subscription_flags; -#endif - - /* check cache */ - if(!(pit->second.subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_KEY_AVAILABLE)) - { - if(mIdentities->haveKey(pit->first)) - { - pit->second.subscription_flags |= GXS_EXTERNAL_CIRCLE_FLAGS_KEY_AVAILABLE; - -#ifdef DEBUG_CIRCLES - std::cerr << " Key is now available!"<< std::endl; -#endif - } - else - { - std::list peers; - - if(!cache.mOriginator.isNull()) - { - peers.push_back(cache.mOriginator) ; -#ifdef DEBUG_CIRCLES - std::cerr << " Requesting unknown/unloaded identity: " << pit->first << " to originator " << cache.mOriginator << std::endl; -#endif - } - else - { -#ifdef DEBUG_CIRCLES - std::cerr << " (WW) cache entry for circle " << cache.mCircleId << " has empty originator. Asking info for GXS id " << pit->first << " to all connected friends." << std::endl; -#endif - - rsPeers->getOnlineList(peers) ; - } - - mIdentities->requestKey(pit->first, peers,RsIdentityUsage(RsServiceType::GXSCIRCLE,RsIdentityUsage::CIRCLE_MEMBERSHIP_CHECK,RsGxsGroupId(cache.mCircleId))); - - all_ids_here = false; - } - } -#ifdef DEBUG_CIRCLES - else - std::cerr << " Key is available. Nothing to process." << std::endl; -#endif - } - - return all_ids_here; -} - -bool p3GxsCircles::cache_reloadids(const RsGxsCircleId &circleId) -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::cache_reloadids()"; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - - RsGxsCircleCache& cache(mCircleCache[circleId]); - - /* fetch from loadMap */ - - if(locked_processLoadingCacheEntry(cache)) - { - cache.mAllIdsHere = true; - - // We can check for self inclusion in the circle right away, since own ids are always loaded. - // that allows to subscribe/unsubscribe uncomplete circles - - cache.mStatus = CircleEntryCacheStatus::CHECKING_MEMBERSHIP; - locked_checkCircleCacheForMembershipUpdate(cache); - - std::cerr << " Loading complete." << std::endl; - - return true ; - } - - else - { - cache.mAllIdsHere = false; - -#ifdef DEBUG_CIRCLES - std::cerr << " Unprocessed peers. Requesting reload for circle " << circleId << std::endl; -#endif - - /* schedule event to try reload gxsIds */ - RsTickEvent::schedule_in(CIRCLE_EVENT_RELOADIDS, GXSID_LOAD_CYCLE, circleId.toStdString()); - } - - return true; -} - -bool p3GxsCircles::checkCircleCache() -{ -#ifdef DEBUG_CIRCLES - std::cerr << "checkCircleCache(): calling auto-subscribe check and membership update check." << std::endl; -#endif - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - - mCircleCache.applyToAllCachedEntries(*this,&p3GxsCircles::locked_checkCircleCacheForMembershipUpdate) ; - - return true ; -} - -bool p3GxsCircles::locked_setGroupUnprocessedStatus(RsGxsCircleCache& cache,bool unprocessed) -{ - uint32_t token2; - - if(unprocessed) - cache.mGroupStatus |= GXS_SERV::GXS_GRP_STATUS_UNPROCESSED; - else - cache.mGroupStatus &= ~GXS_SERV::GXS_GRP_STATUS_UNPROCESSED; - - RsGenExchange::setGroupStatusFlags(token2, RsGxsGroupId(cache.mCircleId), unprocessed, GXS_SERV::GXS_GRP_STATUS_UNPROCESSED); - - // Now we need to async acknowledge the token when the job is finished. We cannot do this sync because it's the - // current thread that takes care of calling the handling of group processing. - - RsThread::async([token2,this]() - { - std::chrono::milliseconds maxWait = std::chrono::milliseconds(10000); - std::chrono::milliseconds checkEvery = std::chrono::milliseconds(100); - - auto timeout = std::chrono::steady_clock::now() + maxWait; // wait for 10 secs at most - auto st = requestStatus(token2); - - while( !(st == RsTokenService::FAILED || st >= RsTokenService::COMPLETE) && std::chrono::steady_clock::now() < timeout ) - { - std::this_thread::sleep_for(checkEvery); - st = requestStatus(token2); - } - - RsGxsGroupId grpId; - acknowledgeGrp(token2,grpId); - }); - return true; -} - -bool p3GxsCircles::locked_subscribeToCircle(const RsGxsCircleId &grpId, bool subscribe) -{ - uint32_t token; - if(!RsGenExchange::subscribeToGroup(token, RsGxsGroupId(grpId), subscribe)) - return false; - - // Now we need to async acknowledge the token when the job is finished. We cannot do this sync because it's the - // current thread that takes care of calling the handling of group processing. - - RsThread::async([token,this]() - { - std::chrono::milliseconds maxWait = std::chrono::milliseconds(10000); - std::chrono::milliseconds checkEvery = std::chrono::milliseconds(100); - - auto timeout = std::chrono::steady_clock::now() + maxWait; // wait for 10 secs at most - auto st = requestStatus(token); - - while( !(st == RsTokenService::FAILED || st >= RsTokenService::COMPLETE) && std::chrono::steady_clock::now() < timeout ) - { - std::this_thread::sleep_for(checkEvery); - st = requestStatus(token); - } - - RsGxsGroupId grpId; - acknowledgeGrp(token,grpId); - }); - - return true; -} - -bool p3GxsCircles::locked_checkCircleCacheForMembershipUpdate(RsGxsCircleCache& cache) -{ - rstime_t now = time(NULL) ; - - if(cache.mStatus < CircleEntryCacheStatus::UPDATING) - return false; - - if(cache.mLastUpdatedMembershipTS + GXS_CIRCLE_DELAY_TO_FORCE_MEMBERSHIP_UPDATE < now) - { -#ifdef DEBUG_CIRCLES - std::cerr << "Cache entry for circle " << cache.mCircleId << " needs a swab over membership requests. Re-scheduling it." << std::endl; -#endif - locked_setGroupUnprocessedStatus(cache,true); // forces the re-check of the group - - // this should be called regularly - - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - std::list grpIds ; - uint32_t token2; - - grpIds.push_back(RsGxsGroupId(cache.mCircleId)) ; - - RsGenExchange::getTokenService()->requestMsgInfo(token2, RS_TOKREQ_ANSTYPE_SUMMARY, opts, grpIds); - GxsTokenQueue::queueRequest(token2, CIRCLEREQ_MESSAGE_DATA); - } - return true ; -} - -/* We need to AutoSubscribe if the Circle is relevent to us */ - -bool p3GxsCircles::locked_checkCircleCacheForAutoSubscribe(RsGxsCircleCache& cache) -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::locked_checkCircleCacheForAutoSubscribe() : "<< cache.mCircleId << std::endl; -#endif - - /* if processed already - ignore */ - if (!(cache.mGroupStatus & GXS_SERV::GXS_GRP_STATUS_UNPROCESSED)) - { -#ifdef DEBUG_CIRCLES - std::cerr << " Already Processed" << std::endl; -#endif - - return false; - } - - /* if personal - we created ... is subscribed already */ - if (!cache.mIsExternal) - { -#ifdef DEBUG_CIRCLES - std::cerr << " Personal Circle. Nothing to do." << std::endl; -#endif - - return false; - } - - if(cache.mStatus < CircleEntryCacheStatus::UPDATING) - return false; - - /* if we appear in the group - then autosubscribe, and mark as processed. This also applies if we're the group admin */ - - std::list myOwnIds; - - if(!rsIdentity->getOwnIds(myOwnIds)) - { - std::cerr << " own ids not loaded yet." << std::endl; - - /* schedule event to try reload gxsIds */ - RsTickEvent::schedule_in(CIRCLE_EVENT_RELOADIDS, GXSID_LOAD_CYCLE, cache.mCircleId.toStdString()); - return false ; - } - - bool am_I_invited = false ; - - for(std::list::const_iterator it(myOwnIds.begin());it!=myOwnIds.end() && (!am_I_invited);++it) - { - std::map::const_iterator it2 = cache.mMembershipStatus.find(*it) ; - - if(it2 != cache.mMembershipStatus.end()) - am_I_invited = am_I_invited || bool(it2->second.subscription_flags & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST) ; - } - - bool am_I_admin( cache.mGroupSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) ; - bool do_I_have_a_msg( cache.mDoIAuthorAMembershipMsg ); - -#ifdef DEBUG_CIRCLES - std::cerr << " own ID invited in circle: " << am_I_invited << ", membership msg author: " << do_I_have_a_msg << ", admin: " << am_I_admin << std::endl; -#endif - if(do_I_have_a_msg || am_I_admin) - { - if(! (cache.mGroupSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED)) - { -#ifdef DEBUG_CIRCLES - /* we are part of this group - subscribe, clear unprocessed flag */ - std::cerr << " either admin or have posted a subscribe/unsubscribe message => AutoSubscribing!" << std::endl; -#endif - locked_subscribeToCircle(cache.mCircleId,true); - mShouldSendCacheUpdateNotification = true; - } -#ifdef DEBUG_CIRCLES - else - std::cerr << " either admin or have posted a subscribe/unsubscribe message, already subscribed." << std::endl; -#endif - - cache.mGroupStatus &= ~GXS_SERV::GXS_GRP_STATUS_UNPROCESSED; - - return true; - } - else - { - /* we know all the peers - we are not part - we can flag as PROCESSED. */ - if(cache.mGroupSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) - { - locked_subscribeToCircle(cache.mCircleId,false); - mShouldSendCacheUpdateNotification = true; -#ifdef DEBUG_CIRCLES - std::cerr << " Neither admin nor subscription msg author! Let's unsubscribe this circle of unfriendly Napoleons!" << std::endl; -#endif - } -#ifdef DEBUG_CIRCLES - else - std::cerr << " Neither admin nor subscription msg author! Not subscribed either." << std::endl; -#endif - return true ; - } - -#ifdef DEBUG_CIRCLES - std::cerr << " Marking the cache entry as processed." << std::endl; -#endif - locked_setGroupUnprocessedStatus(cache,false); - - return true; -} - -rstime_t p3GxsCircles::service_getLastGroupSeenTs(const RsGxsGroupId& gid) -{ - rstime_t now = time(nullptr); - - RS_STACK_MUTEX(mKnownCirclesMtx); - - auto it = mKnownCircles.find(gid); - bool unknown_posted = (it == mKnownCircles.end()); - - if(unknown_posted) - { - mKnownCircles[gid] = now; - IndicateConfigChanged(); - return now; - } - else - return it->second; -} -bool p3GxsCircles::service_checkIfGroupIsStillUsed(const RsGxsGrpMetaData& meta) -{ -#ifdef GXSFORUMS_CIRCLES - std::cerr << "p3gxsChannels: Checking unused circles: called by GxsCleaning." << std::endl; -#endif - - // request all group infos at once - - rstime_t now = time(nullptr); - - RS_STACK_MUTEX(mKnownCirclesMtx); - - auto it = mKnownCircles.find(meta.mGroupId); - bool unknown_posted = (it == mKnownCircles.end()); - -#ifdef GXSFORUMS_CIRCLES - std::cerr << " Circle " << meta.mGroupId ; -#endif - - if(unknown_posted) - { - // This case should normally not happen. It does because this board was never registered since it may - // arrived before this code was here - -#ifdef GXSFORUMS_CIRCLES - std::cerr << ". Not known yet. Adding current time as new TS." << std::endl; -#endif - mKnownCircles[meta.mGroupId] = now; - IndicateConfigChanged(); - - return true; - } - else - { - bool used_by_friends = (now < it->second + CIRCLES_UNUSED_BY_FRIENDS_DELAY); - bool subscribed = static_cast(meta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED); - -#ifdef GXSFORUMS_CIRCLES - std::cerr << ". subscribed: " << subscribed << ", used_by_friends: " << used_by_friends << " last TS: " << now - it->second << " secs ago (" << (now-it->second)/86400 << " days)"; -#endif - - if(!subscribed && !used_by_friends) - { -#ifdef GXSFORUMS_CIRCLES - std::cerr << ". Scheduling for deletion" << std::endl; -#endif - return false; - } - else - { -#ifdef GXSFORUMS_CIRCLES - std::cerr << ". Keeping!" << std::endl; -#endif - return true; - } - } -} - -//====================================================================================// -// Event handling // -//====================================================================================// - - // Overloaded from GxsTokenQueue for Request callbacks. -void p3GxsCircles::handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::handleResponse(" << token << "," << req_type << "," << status << ")" << std::endl; -#endif // DEBUG_CIRCLES - if (status != RsTokenService::COMPLETE) - return; //For now, only manage Complete request - - - // stuff. - switch(req_type) - { - case CIRCLEREQ_MESSAGE_DATA: - processMembershipRequests(token); - break; - - case CIRCLEREQ_CACHELOAD: - cache_load_for_token(token); - break; - default: - RsErr() << __PRETTY_FUNCTION__ << " Unknown Request Type: " - << req_type << std::endl; - break; - } -} - - // Overloaded from RsTickEvent for Event callbacks. -void p3GxsCircles::handle_event(uint32_t event_type, const std::string &elabel) -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::handle_event(" << event_type << ")"; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - - // stuff. - switch(event_type) - { - case CIRCLE_EVENT_CACHELOAD: - cache_start_load(); - break; - - case CIRCLE_EVENT_RELOADIDS: - cache_reloadids(RsGxsCircleId(elabel)); - break; - - case CIRCLE_EVENT_DUMMYSTART: - generateDummyData(); - break; - - case CIRCLE_EVENT_DUMMYLOAD: - checkDummyIdData(); - break; - - case CIRCLE_EVENT_DUMMYGEN: - generateDummyCircle(); - break; - - default: - RsErr() << __PRETTY_FUNCTION__ << " Unknown Event Type: " << event_type - << std::endl; - break; - } -} - -//====================================================================================// -// Membership request handling // -//====================================================================================// - -// Circle membership is requested/denied by posting a message into the cicle group, according to the following rules: -// -// - a subscription request is a RsItem (which serialises into a radix64 message, that is further signed by the group message publishing system) -// The item contains: -// * subscribe order (yes/no), boolean -// * circle ID (this is important, otherwise people can copy subscribe messages from one circle to another) -// * subscribe date -// * subscribe timeout (how long is the message kept. When timed out, the message is removed and subscription cancelled) -// -// - subscribe messages follow the following rules, which are enforced by a timer-based method: -// * subscription requests from a given user are always replaced by the last subscription request -// * a complete list of who's subscribed to a given group is kept, saved, and regularly updated when new subscribe messages are received, or when admin list is changed. -// * getGroupDetails reads this list in order to respond who's subscribed to a group. The list of -// -// - compatibility with self-restricted circles: -// * subscription should be based on admin list, so that non subscribed peers still receive the invitation -// -// - two possible subscription models for circle member list (Restricted forums only propagate to members): -// 1 - list of admin who have not opposed subscription -// - solves propagation issue. Only admin see data. They can however unsubscribe using a negative req. Admin needs to remove them. -// - bad for security. Admin can refuse to remove them => back to square one -// 2 - list of admin who have also requested membership -// - propagation is ok. On restricted circle, the circle msgs/group should be sent to admin list, instead of member list. -// - solves membership issue since people need to actively be in the group. -// => choose 2 -// - forum group : encrypted for Member list -// - circle group : clear / encrypted for admin list (for self-restricted) -// We decide between the two by comparing the group we're sending and the circle id it is restricted to. -// -// - Use cases -// * user sees group (not self restricted) and requests to subscribe => RS subscribes the group and the user can propagate the response -// * user is invited to self-restricted circle. He will see it and can subscribe, so he will be in admin list and receive e.g. forum posts. -// * -// -// - Threat model -// * a malicious user forges a new subscription request: NP-hard as it needs to break the RSA key of the GXS id. -// * a malicious corrupts a subscription request: NP-hard. Messages are signed. -// * a malicious user copies an old subscription of someone else and inserts it in the system. -// => not possible. Either this existing old susbscription already exists, or it has been replaced by a more recent one, which -// will always replace the old one because of the date. -// * a malicious user removes someone's subscription messages. This is possible, but the mesh nature of the network will allow the message to propagate anyway. -// * a malicious user creates a circle with an incriminating name/content and adds everyone in it -// => people can oppose their membership in the circle using a msg -// -// -// - the table below summarizes the various choices: forum and circle propagation when restricted to a circle, and group subscribe to the circle -// -// +------------------------------+-----------------------------+ -// | User in admin list | User not in admin list | -// +-------------+------------------------------+-----------------------------+ -// | User request| Forum Grp/Msg: YES | Forum Grp/Msg: NO | -// | Subscription| Circle Grp/Msg: YES/YES | Circle Grp/Msg: YES/NO | -// | | Grp Subscribed: YES | Grp Subscribed: YES | -// +-------------+------------------------------+-----------------------------+ -// | No request | Forum Grp/Msg: NO | Forum Grp/Msg: NO | -// | Subscription| Circle Grp/Msg: YES/YES | Circle Grp/Msg: YES/NO | -// | | Grp Subscribed: NO | Grp Subscribed: NO | -// +-------------+------------------------------+-----------------------------+ - -bool p3GxsCircles::pushCircleMembershipRequest( const RsGxsId& own_gxsid, const RsGxsCircleId& circle_id, RsGxsCircleSubscriptionType request_type ) -{ - Dbg3() << __PRETTY_FUNCTION__ << "own_gxsid = " << own_gxsid - << ", circle=" << circle_id << ", req type=" << request_type - << std::endl; - - if( request_type != RsGxsCircleSubscriptionType::SUBSCRIBE && request_type != RsGxsCircleSubscriptionType::UNSUBSCRIBE ) - { - RsErr() << __PRETTY_FUNCTION__ << " Unknown request type: " << static_cast(request_type) << std::endl; - return false; - } - - if(!rsIdentity->isOwnId(own_gxsid)) - { - RsErr() << __PRETTY_FUNCTION__ << " Cannot generate membership request " - << "from not-own id: " << own_gxsid << std::endl; - return false; - } - - if(!getCirclesInfo( std::list{static_cast(circle_id)}, RS_DEFAULT_STORAGE_PARAM(std::vector) )) - { - RsErr() << __PRETTY_FUNCTION__ << " Cannot generate membership request from unknown circle: " << circle_id << std::endl; - return false; - } - // If the circle is not subscribed, then subscribe, whatever the subscription type. Indeed, if we publish a msg, even a msg for - // unsubscribing, we need to have a subscribed group first. - - if(!locked_subscribeToCircle(circle_id,true)) - { - std::cerr << __PRETTY_FUNCTION__ << " Could not subscribe to Circle group." << std::endl; - return false; - } - - // Create a subscribe item - - RsGxsCircleSubscriptionRequestItem *s = new RsGxsCircleSubscriptionRequestItem ; - - s->time_stamp = time(NULL) ; - s->time_out = 0 ; // means never - s->subscription_type = request_type ; - - RsTemporaryMemory tmpmem(circle_id.serial_size() + own_gxsid.serial_size()) ; - - uint32_t off = 0 ; - circle_id.serialise(tmpmem,tmpmem.size(),off) ; - own_gxsid.serialise(tmpmem,tmpmem.size(),off) ; - - s->meta.mGroupId = RsGxsGroupId(circle_id) ; - s->meta.mMsgId.clear(); - s->meta.mThreadId = RsGxsMessageId(RsDirUtil::sha1sum(tmpmem,tmpmem.size())); // make the ID from the hash of the cirle ID and the author ID - s->meta.mAuthorId = own_gxsid; - - // msgItem->meta.mParentId = ; // leave these blank - // msgItem->meta.mOrigMsgId= ; - -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::publishSubscribeRequest()" << std::endl; - std::cerr << " GroupId : " << circle_id << std::endl; - std::cerr << " AuthorId : " << s->meta.mAuthorId << std::endl; - std::cerr << " ThreadId : " << s->meta.mThreadId << std::endl; -#endif - - uint32_t token; - RsGenExchange::publishMsg(token, s); - - // This is manual handling of token. We need to clear it up from the notification when done, and that needs - // to be async-ed, since the processing of message publication is done in the same thread. - - RsThread::async( [this,token]() - { - std::chrono::milliseconds maxWait = std::chrono::milliseconds(10000); - std::chrono::milliseconds checkEvery = std::chrono::milliseconds(100); - - auto timeout = std::chrono::steady_clock::now() + maxWait; // wait for 10 secs at most - auto st = requestStatus(token); - - while( !(st == RsTokenService::FAILED || st >= RsTokenService::COMPLETE) && std::chrono::steady_clock::now() < timeout ) - { - std::this_thread::sleep_for(checkEvery); - st = requestStatus(token); - } - - std::pair grpmsgId; - acknowledgeMsg(token,grpmsgId); - }); - - // update the cache. - force_cache_reload(circle_id); - - return true; -} - -bool p3GxsCircles::requestCircleMembership(const RsGxsId& own_gxsid,const RsGxsCircleId& circle_id) -{ - return pushCircleMembershipRequest(own_gxsid,circle_id,RsGxsCircleSubscriptionType::SUBSCRIBE) ; -} -bool p3GxsCircles::cancelCircleMembership(const RsGxsId& own_gxsid,const RsGxsCircleId& circle_id) -{ - return pushCircleMembershipRequest(own_gxsid,circle_id,RsGxsCircleSubscriptionType::UNSUBSCRIBE) ; -} - -bool p3GxsCircles::locked_processMembershipMessages(RsGxsCircleCache& cache, const std::vector& items, GxsMsgReq& messages_to_delete, const std::set &own_ids) -{ -#ifdef DEBUG_CIRCLES - std::cerr << " Circle found in cache!" << std::endl; - std::cerr << " Retrieving messages..." << std::endl; -#endif - cache.mDoIAuthorAMembershipMsg = false; // default - - for(uint32_t i=0;imeta.mGroupId << ", Message ID: " << items[i]->meta.mMsgId << ", thread ID: " << items[i]->meta.mThreadId << ", author: " << items[i]->meta.mAuthorId << ": " ; -#endif - RsGxsCircleSubscriptionRequestItem *item = dynamic_cast(items[i]) ; - - if(item == NULL) - { - std::cerr << " (EE) item is not a RsGxsCircleSubscriptionRequestItem. Weird. Scheduling for deletion." << std::endl; - - messages_to_delete[RsGxsGroupId(cache.mCircleId)].insert(item->meta.mMsgId); - continue ; - } - - RsGxsCircleMembershipStatus& info(cache.mMembershipStatus[item->meta.mAuthorId]) ; - -#ifdef DEBUG_CIRCLES - std::cerr << " " << time(NULL) - item->time_stamp << " seconds ago, " ; -#endif - - if(info.last_subscription_TS <= item->time_stamp) // the <= here allows to make sure we update the flags is something happenned - { - info.last_subscription_TS = item->time_stamp ; - - if(item->subscription_type == RsGxsCircleSubscriptionType::SUBSCRIBE) - info.subscription_flags |= GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED; - else if(item->subscription_type == RsGxsCircleSubscriptionType::UNSUBSCRIBE) - info.subscription_flags &= ~GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED; - else - std::cerr << " (EE) unknown subscription order type: " << static_cast(item->subscription_type) ; - - mShouldSendCacheUpdateNotification = true; -#ifdef DEBUG_CIRCLES - std::cerr << " UPDATING status to " << std::hex << info.subscription_flags << std::dec << std::endl; -#endif - - if(own_ids.end() != own_ids.find(item->meta.mAuthorId)) // we have at least one subscribe/unsubscribe message. So we update the flag accordingly. - cache.mDoIAuthorAMembershipMsg = true; - } - else if(info.last_subscription_TS > item->time_stamp) - std::cerr << " Too old: item->TS=" << item->time_stamp << ", last_subscription_TS=" << info.last_subscription_TS << ". IGNORING." << std::endl; - } - - // now do another sweep and remove all msgs that are older than the latest - -#ifdef DEBUG_CIRCLES - std::cerr << " Cleaning older messages..." << std::endl; -#endif - - for(uint32_t i=0;imeta.mAuthorId]) ; - RsGxsCircleSubscriptionRequestItem *item = dynamic_cast(items[i]) ; - - if(item && info.last_subscription_TS > item->time_stamp) - { -#ifdef DEBUG_CIRCLES - std::cerr << " " << item->meta.mMsgId << ": Older than last known (" << (long int)info.last_subscription_TS - (long int)item->time_stamp << " seconds before): deleting." << std::endl; -#endif - messages_to_delete[RsGxsGroupId(cache.mCircleId)].insert(item->meta.mMsgId) ; - } - } - -#ifdef DEBUG_CIRCLES - std::cerr << " Cleaning older messages..." << std::endl; -#endif - - cache.mLastUpdatedMembershipTS = time(NULL) ; - cache.mStatus = CircleEntryCacheStatus::UP_TO_DATE; - cache.mLastUpdateTime = time(NULL); - mShouldSendCacheUpdateNotification = true; - - return true; -} - -bool p3GxsCircles::processMembershipRequests(uint32_t token) -{ - // Go through membership request messages and process them according to the following rule: - // * for each ID only keep the latest membership request. Delete the older ones. - // * for each circle, keep a list of IDs sorted into membership categories (e.g. keep updated flags for each IDs) - // Because msg loading is async-ed, the job in split in two methods: one calls the loading, the other one handles the loaded data. - -#ifdef DEBUG_CIRCLES - std::cerr << "Processing circle membership requests." << std::endl; -#endif - t_RsGxsGenericDataTemporaryMapVector msgItems; - - if(!RsGenExchange::getMsgData(token, msgItems)) - { - std::cerr << "(EE) Cannot get msg data for circle. Something's weird." << std::endl; - return false; - } - - std::list own_ids ; - rsIdentity->getOwnIds(own_ids); - std::set own_ids_set; - for(auto& id:own_ids) - own_ids_set.insert(id); - - GxsMsgReq messages_to_delete ; - - for(GxsMsgDataMap::const_iterator it(msgItems.begin());it!=msgItems.end();++it) - { - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ -#ifdef DEBUG_CIRCLES - std::cerr << " Circle ID: " << it->first << std::endl; -#endif - // Find the circle ID in cache and process the list of messages to keep the latest order in time. - - RsGxsCircleId circle_id(it->first); - RsGxsCircleCache& cache( mCircleCache[circle_id] ); - - // First process membership messages -#ifdef DEBUG_CIRCLES - std::cerr << " Processing membership messages..." << std::endl; -#endif - locked_processMembershipMessages(cache,it->second,messages_to_delete,own_ids_set); -#ifdef DEBUG_CIRCLES - std::cerr << " Now checking for auto-subscribe..." << std::endl; -#endif - locked_checkCircleCacheForAutoSubscribe(cache); - } - - if(!messages_to_delete.empty()) - { - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - uint32_t token2; - RsGenExchange::deleteMsgs(token2,messages_to_delete); - } - return true ; -} - -//====================================================================================// -// p3Config methods // -//====================================================================================// - -static const uint32_t GXS_FORUMS_CONFIG_MAX_TIME_NOTIFY_STORAGE = 86400*30*2 ; // ignore notifications for 2 months -static const uint8_t GXS_CIRCLES_CONFIG_SUBTYPE_NOTIFY_RECORD = 0x01 ; - -struct RsGxsCirclesNotifyRecordsItem: public RsItem -{ - - RsGxsCirclesNotifyRecordsItem() - : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_GXS_TYPE_CIRCLES_CONFIG,GXS_CIRCLES_CONFIG_SUBTYPE_NOTIFY_RECORD) - {} - - virtual ~RsGxsCirclesNotifyRecordsItem() {} - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { RS_SERIAL_PROCESS(records); } - - void clear() {} - - std::map records; -}; - -class GxsCirclesConfigSerializer : public RsServiceSerializer -{ -public: - GxsCirclesConfigSerializer() : RsServiceSerializer(RS_SERVICE_GXS_TYPE_CIRCLES_CONFIG) {} - virtual ~GxsCirclesConfigSerializer() {} - - RsItem* create_item(uint16_t service_id, uint8_t item_sub_id) const - { - if(service_id != RS_SERVICE_GXS_TYPE_CIRCLES_CONFIG) - return NULL; - - switch(item_sub_id) - { - case GXS_CIRCLES_CONFIG_SUBTYPE_NOTIFY_RECORD: return new RsGxsCirclesNotifyRecordsItem(); - default: - return NULL; - } - } -}; - -bool p3GxsCircles::saveList(bool& cleanup, std::list&saveList) -{ - cleanup = true ; - - RsGxsCirclesNotifyRecordsItem *item = new RsGxsCirclesNotifyRecordsItem ; - - { - RS_STACK_MUTEX(mKnownCirclesMtx); - item->records = mKnownCircles ; - } - - saveList.push_back(item) ; - return true; -} - -bool p3GxsCircles::loadList(std::list& loadList) -{ - while(!loadList.empty()) - { - RsItem *item = loadList.front(); - loadList.pop_front(); - - rstime_t now = time(NULL); - - RsGxsCirclesNotifyRecordsItem *fnr = dynamic_cast(item) ; - - if(fnr != NULL) - { - RS_STACK_MUTEX(mKnownCirclesMtx); - - mKnownCircles.clear(); - - for(auto it(fnr->records.begin());it!=fnr->records.end();++it) - if( now < it->second + GXS_FORUMS_CONFIG_MAX_TIME_NOTIFY_STORAGE) - mKnownCircles.insert(*it) ; - } - - delete item ; - } - return true; -} - -RsSerialiser* p3GxsCircles::setupSerialiser() -{ - RsSerialiser* rss = new RsSerialiser; - rss->addSerialType(new GxsCirclesConfigSerializer()); - - return rss; -} - -//====================================================================================// -// DEBUG STUFF // -//====================================================================================// - -bool p3GxsCircles::debug_dumpCacheEntry(RsGxsCircleCache& cache) -{ - std::cerr << " Circle: " << cache.mCircleId - << " status: " << static_cast(cache.mStatus) - << " MembershipTS: " << cache.mLastUpdatedMembershipTS - << " UpdateTS: " << cache.mLastUpdateTime - << " All Ids here: " << cache.mAllIdsHere - << " Has own msg: " << cache.mDoIAuthorAMembershipMsg << std::endl; - - return true; -} - -void p3GxsCircles::debug_dumpCache() -{ - std::cerr << "Debug dump of CircleCache:" << std::endl; - - mCircleCache.printStats(); - mCircleCache.applyToAllCachedEntries(*this,&p3GxsCircles::debug_dumpCacheEntry); -} - -std::string p3GxsCircles::genRandomId() -{ - std::string randomId; - for(int i = 0; i < 20; i++) - { - randomId += (char) ('a' + (RSRandom::random_u32() % 26)); - } - - return randomId; -} - -void p3GxsCircles::generateDummyData() -{ - // request Id Data... -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::generateDummyData() getting Id List"; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - - uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - - uint32_t token; - rsIdentity->getTokenService()->requestGroupInfo(token, ansType, opts); - - { - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - mDummyIdToken = token; - } - - RsTickEvent::schedule_in(CIRCLE_EVENT_DUMMYLOAD, CIRCLE_DUMMY_GENPERIOD); -} - - -void p3GxsCircles::checkDummyIdData() -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::checkDummyIdData()"; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - - // check the token. - uint32_t status = rsIdentity->getTokenService()->requestStatus(mDummyIdToken); - if ( (RsTokenService::FAILED == status) || - (RsTokenService::COMPLETE == status) ) - { - std::vector ids; - if (!rsIdentity->getGroupData(mDummyIdToken, ids)) - { - std::cerr << "p3GxsCircles::checkDummyIdData() ERROR getting data"; - std::cerr << std::endl; - /* error */ - return; - } - - std::vector::iterator it; - for(it = ids.begin(); it != ids.end(); ++it) - { - if (it->mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility) - { -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::checkDummyIdData() PgpLinkedId: " << it->mMeta.mGroupId; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - mDummyPgpLinkedIds.push_back(RsGxsId(it->mMeta.mGroupId.toStdString())); - - if (it->mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) - { -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::checkDummyIdData() OwnId: " << it->mMeta.mGroupId; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - mDummyOwnIds.push_back(RsGxsId(it->mMeta.mGroupId.toStdString())); - } - } - else - { -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::checkDummyIdData() Other Id: " << it->mMeta.mGroupId; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - } - } - - /* schedule the generate events */ -#define MAX_CIRCLES 10 - for(int i = 0; i < MAX_CIRCLES; i++) - { - RsTickEvent::schedule_in(CIRCLE_EVENT_DUMMYGEN, i * CIRCLE_DUMMY_GENPERIOD); - } - return; - } - - // Otherwise - reschedule to come back here. - RsTickEvent::schedule_in(CIRCLE_EVENT_DUMMYLOAD, CIRCLE_DUMMY_GENPERIOD); - return; -} - - -void p3GxsCircles::generateDummyCircle() -{ -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::generateDummyCircle()"; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - - int npgps = mDummyPgpLinkedIds.size(); - - if(npgps == 0) - return ; - - RsGxsCircleGroup group; - - std::set idset; - // select a random number of them. -#define MAX_PEERS_PER_CIRCLE_GROUP 20 - int nIds = 1 + (RSRandom::random_u32() % MAX_PEERS_PER_CIRCLE_GROUP); - for(int i = 0; i < nIds; i++) - { - - int selection = (RSRandom::random_u32() % npgps); - std::list::iterator it = mDummyPgpLinkedIds.begin(); - for(int j = 0; (it != mDummyPgpLinkedIds.end()) && (j < selection); j++, ++it) ; - if (it != mDummyPgpLinkedIds.end()) - { - idset.insert(*it); - } - } - - /* be sure to add one of our IDs too (otherwise we wouldn't get the group) - */ - { - - int selection = (RSRandom::random_u32() % mDummyOwnIds.size()); - std::list::iterator it = mDummyOwnIds.begin(); - mDummyOwnIds.push_back(*it); - for(int j = 0; (it != mDummyOwnIds.end()) && (j < selection); j++, ++it) ; - if (it != mDummyOwnIds.end()) - { - idset.insert(*it); - } - } - - group.mMeta.mGroupName = genRandomId(); -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::generateDummyCircle() Name: " << group.mMeta.mGroupName; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - - std::set::iterator it; - for(it = idset.begin(); it != idset.end(); ++it) - { - group.mInvitedMembers.insert(*it); -#ifdef DEBUG_CIRCLES - std::cerr << "p3GxsCircles::generateDummyCircle() Adding: " << *it; - std::cerr << std::endl; -#endif // DEBUG_CIRCLES - } - - uint32_t dummyToken; - createGroup(dummyToken, group); -} - - -/****************************************************************************/ -// ID STUFF. \/ \/ \/ \/ \/ \/ \/ :) -/****************************************************************************/ -#if 0 - -/************************************************************************************/ -/************************************************************************************/ - -bool p3GxsCircles::cachetest_getlist() -{ - std::cerr << "p3GxsCircles::cachetest_getlist() making request"; - std::cerr << std::endl; - - uint32_t ansType = RS_TOKREQ_ANSTYPE_LIST; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_IDS; - uint32_t token = 0; - - RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); - GxsTokenQueue::queueRequest(token, CIRCLEREQ_CACHETEST); - - // Schedule Next Event. - RsTickEvent::schedule_in(CIRCLE_EVENT_CACHETEST, CACHETEST_PERIOD); - return true; -} - -bool p3GxsCircles::cachetest_handlerequest(uint32_t token) -{ - std::cerr << "p3GxsCircles::cachetest_handlerequest() token: " << token; - std::cerr << std::endl; - - std::list grpIds; - bool ok = RsGenExchange::getGroupList(token, grpIds); - - if(ok) - { - std::list::iterator vit = grpIds.begin(); - for(; vit != grpIds.end(); ++vit) - { - /* 5% chance of checking it! */ - if (RSRandom::random_f32() < 0.25) - { - std::cerr << "p3GxsCircles::cachetest_request() Testing Id: " << *vit; - std::cerr << std::endl; - - /* try the cache! */ - if (!haveKey(*vit)) - { - std::list nullpeers; - requestKey(*vit, nullpeers); - - std::cerr << "p3GxsCircles::cachetest_request() Requested Key Id: " << *vit; - std::cerr << std::endl; - } - else - { - RsTlvSecurityKey seckey; - if (getKey(*vit, seckey)) - { - std::cerr << "p3GxsCircles::cachetest_request() Got Key OK Id: " << *vit; - std::cerr << std::endl; - - // success! - seckey.print(std::cerr, 10); - std::cerr << std::endl; - - - } - else - { - std::cerr << "p3GxsCircles::cachetest_request() ERROR no Key for Id: " << *vit; - std::cerr << std::endl; - } - } - - /* try private key too! */ - if (!havePrivateKey(*vit)) - { - requestPrivateKey(*vit); - std::cerr << "p3GxsCircles::cachetest_request() Requested PrivateKey Id: " << *vit; - std::cerr << std::endl; - } - else - { - RsTlvSecurityKey seckey; - if (getPrivateKey(*vit, seckey)) - { - // success! - std::cerr << "p3GxsCircles::cachetest_request() Got PrivateKey OK Id: " << *vit; - std::cerr << std::endl; - } - else - { - std::cerr << "p3GxsCircles::cachetest_request() ERROR no PrivateKey for Id: " << *vit; - std::cerr << std::endl; - } - } - } - } - } - else - { - std::cerr << "p3GxsCircles::cache_load_for_token() ERROR no data"; - std::cerr << std::endl; - - return false; - } - return true; -} - -/****************************************************************************/ -// ID STUFF. /\ /\ /\ /\ /\ /\ /\ /\ :) -/****************************************************************************/ -#endif - -#ifdef HANDLE_SUBCIRCLES -#if 0 -/**** TODO BELOW ****/ - -bool p3GxsCircles::cache_load_subcircles(uint32_t token) -{ - std::cerr << "p3GxsCircles::cache_load_subcircles() : " << token; - std::cerr << std::endl; - - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); ++vit) - { - RsGxsIdGroupItem* item = dynamic_cast(*vit); - - RsGxsCircleId id = item->meta.mGroupId; - RsGxsCircleGroup group = item->group; - group.mMeta = item->meta; - delete item; - - std::cerr << "p3GxsCircles::cache_load_subcircles() Loaded Id with Meta: "; - std::cerr << item->meta; - std::cerr << std::endl; - - - RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/ - - /* stage 2 of loading, load subcircles */ - std::map >::iterator sit; - sit = mCacheLoad_SubCircle.find(id) - if (sit == mCacheLoad_SubCircle.end()) - { - /* ERROR */ - continue; - } - - std::list updateCaches = sit->second; - // cleanup while we're here. - mCacheLoad_SubCircle.erase(sit); - - /* Now iterate through peers / subcircles, and apply - * - similarly to base load function - */ - - - RsGxsCircleCache &cache = it->second; - cache.loadBaseCircle(group); - - bool isComplete = true; - - std::list &peers = group.peers; - std::list::const_iterator pit; - - // need to trigger the searches. - for(pit = peers.begin(); pit != peers.end(); ++pit) - { - /* check cache */ - if (mIdentities->is_cached(*pit)) - { - /* we can process now! */ - RsIdentityDetails details; - if (mIdentities->getDetails(*pit, details)) - { - if (details.isPgpKnown) - { - // Problem - could have multiple GxsIds here! - // TODO. - //cache.mAllowedPeers[details.mPgpId] = *pit; - - for(uit = updateCaches.begin(); uit != updateCaches.end(); ++uit) - { - /* fetch the cache - and update */ - mLoadingCache[id] = RsGxsCircleCache(); - std::map::iterator it; - it = mLoadingCache.find(id); - } - - } - else - { - //cache.mUnknownPeers.push_back(*pit); - } - } - else - { - // ERROR. - } - } - else - { - /* store in to_process queue. */ - cache.mUnprocessedPeers.push_back(*pit); - - if (isComplete) - { - /* store reference to update */ - isComplete = false; - mCacheLoad_KeyWait.push_back(id); - } - } - } - - std::list &circles = group.circles; - std::list::const_iterator cit; - for(cit = circles.begin(); cit != circles.end(); ++cit) - { - /* if its cached already -> then its complete. */ - if (mCircleCache.is_loaded(*cit)) - { - RsGxsCircleCache cachedCircle; - if (mCircleCache.fetch(&cit, cachedCircle)) - { - /* copy cached circle into circle */ - cache.loadSubCircle(cachedCircle); - } - else - { - /* error */ - continue; - } - } - else - { - /* push into secondary processing queues */ - std::list &proc_circles = mCacheLoad_SubCircle[id]; - proc_circles.push_back(id); - - subCirclesToLoad.push_back(id); - - isComplete = false; - } - } - - if (isComplete) - { - /* move straight into the cache */ - mCircleCache.store(id, cache); - - /* remove from loading queue */ - mLoadingCache.erase(it); - } - } - } - else - { - std::cerr << "p3GxsCircles::cache_load_for_token() ERROR no data"; - std::cerr << std::endl; - - return false; - } - - if (!keysToLoad.empty()) - { - /* schedule event to try reload gxsIds */ - - } - - if (!subCirclesToLoad.empty()) - { - /* request load of subcircles */ - - - } - return true; -} - -#endif -#endif - -#ifdef HANDLE_SUBCIRCLES -#if 0 - std::list &circles = group.mSubCircles; - std::list::const_iterator cit; - for(cit = circles.begin(); cit != circles.end(); ++cit) - { - /* if its cached already -> then its complete. */ - if (mCircleCache.is_loaded(*cit)) - { - RsGxsCircleCache cachedCircle; - if (mCircleCache.fetch(&cit, cachedCircle)) - { - /* copy cached circle into circle */ - cache.loadSubCircle(cachedCircle); - } - else - { - /* error */ - continue; - } - } - else - { - /* push into secondary processing queues */ - std::list &proc_circles = mCacheLoad_SubCircle[*cit]; - proc_circles.push_back(id); - - subCirclesToLoad.push_back(*cit); - - isComplete = false; - isUnprocessedCircles = true; - } - } -#endif -#endif diff --git a/libretroshare/src/services/p3gxscircles.h b/libretroshare/src/services/p3gxscircles.h deleted file mode 100644 index e71e26ed0..000000000 --- a/libretroshare/src/services/p3gxscircles.h +++ /dev/null @@ -1,400 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3gxscircles.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012-2014 Robert Fernie * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - - -#include "retroshare/rsgxscircles.h" // External Interfaces. -#include "gxs/rsgenexchange.h" // GXS service. -#include "gxs/rsgixs.h" // Internal Interfaces. -#include "services/p3idservice.h" // For constructing Caches -#include "gxs/gxstokenqueue.h" -#include "util/rstickevent.h" -#include "util/rsmemcache.h" -#include "util/rsdebug.h" - -#include -#include - -// TODO: -// can now edit circles. this leads to the following situation: -// if someone gets removed from a self.retricted circle, he won't notice -// because he can't receive the updated circle group if he is not part of the group anymore -// -// idea 1: refresh circle groups for example every week -// if a circle was not refreshed since two weeks we can assume we where deleted -// pro: does not leak info, simple to implement, does work even if the network topology changed (unfriending) -// con: delay until we know about the deletion -// -// idea 2: add a field with deleted members to the circle group -// then circle members can tell deleted circle members that they where deleted -// pro: faster notification about deletion -// con: more complicated, leaks info because the deleted member learns who is still a member -// question: how to authenticate the deletion message? -// -// idea 3: make a two phase deletion process -// first add members to a to-delete list -// then wait a week to let the changes propagate -// then remove from allowed peers list -// pro: easy to implement -// con: deletion process is slow -// improvement idea: let only circle groups sync when the member is on he to-delete list -// but don't allow sync of data from other services -// this requires that the netservice knows that he is dealing with a circle group -// -// fact: have to use a timeout mechanism. -// a timeout is the only thing which works even with a two months old backup - -/* - * Circles Identity Service - * - * A collection of notes: - * - * We want to be able to express the following types of Circles. - * - * - Public - * - Groups & Messages can be passed onto anyone. ( No Restrictions. ) - * - GXS Notes: - * - This is what we have currently. - * - * - External Circle - * - List of Identities that can receive the Group / Messages. - * - This list will be defined via a set of RsIdentities - which have PGPHashes set. - * - We need the PGPHashes to be able to identify which peers can receive msgs. - * - Messages are passed to the Intersection of (Identified PGPHashes & Friends) - * - Distribution of Circle Definitions can be also be restricted via circles. - * - You can have Public External Groups, or Groups that only the Members know about. - * - Control of these External Groups is determined by Admin / Publish Keys. - * - The Danger with External Groups, is your ID wll be associated with other people... - * - Leaking information!!! - * - GXS Notes: - * - p3Circles will provide a distrib list for a given Circle Group. - * - * - Personal Circle or "Your Eyes Only". - * - Same as an Internal Circle Definition. (What will be used for File Sharing initially) - * - Each peer will have a bunch of these, Friends, Family, etc. - * - * - The list is not publically shared, only the originator of the message will distribute. - * - You can communicate back to the originator, who will share with the other members. - * but you mustn't discuss / share content with anyone else. - * - This is quite a Weak / Fragile Group, as there is only one distributor. - * - GXS NOTES: - * - TO make this work, we need GXS or RsCircles to maintain extra info: - * - GXS stores the original source, so communications can go back there. - * - If Originator, GXS store a REFERENCE, Circles turn this into a distrib list of peers. - * - * - * - * Like RsIdentities are used to validation messages, - * RsCircles will be used to determine if a peer can receive a group / messages. - * - * bool RsCircles::canSend(RsGxsCircleId, RsPeerId) - * bool RsCircles::canSend(RsCircleInternalId, RsPeerId) - * - * or maybe just: - * - * bool RsCircles::recipients(GxsPermission &perms, std::list friendlist); - * - */ - -/* Permissions is part of GroupMetaData - */ - -class RsGxsCircleMembershipStatus -{ -public: - RsGxsCircleMembershipStatus() : last_subscription_TS(0), subscription_flags(0) {} - - rstime_t last_subscription_TS ; - uint32_t subscription_flags ; // combination of GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST and GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED -}; - -enum class CircleEntryCacheStatus: uint8_t { - UNKNOWN = 0x00, // Used to detect uninitialized memory - NO_DATA_YET = 0x01, // Used in the constuctor - LOADING = 0x02, // When the token request to load cache has been sent and no data is present - UPDATING = 0x03, // Starting from this level the cache entry can be used - CHECKING_MEMBERSHIP = 0x04, // Means we're actually looking into msgs to update membership status - UP_TO_DATE = 0x05 // Everything should be loaded here. -}; - -class RsGxsCircleCache -{ -public: - RsGxsCircleCache(); - - bool loadBaseCircle(const RsGxsCircleGroup &circle); - bool loadSubCircle(const RsGxsCircleCache &subcircle); - - bool getAllowedPeersList(std::list &friendlist) const; - bool isAllowedPeer(const RsPgpId &id) const; - bool isAllowedPeer(const RsGxsId &id, const RsGxsGroupId &destination_group) const; - bool addAllowedPeer(const RsPgpId &pgpid); - bool addLocalFriend(const RsPgpId &pgpid); - - // Cache related data - - rstime_t mLastUpdatedMembershipTS ; // Last time the subscribe messages have been requested. Should be reset when new messages arrive. - rstime_t mLastUpdateTime; // Last time the cache entry was loaded - CircleEntryCacheStatus mStatus; // Overall state of the cache entry - bool mAllIdsHere ; // True when all ids are knwon and available. - - // GxsCircle related data - - RsGxsCircleId mCircleId; - std::string mCircleName; - - RsGxsCircleType mCircleType; - bool mIsExternal; - RsGxsCircleId mRestrictedCircleId ; // circle ID that circle is restricted to. - - bool mDoIAuthorAMembershipMsg; // Do I have a subscribe/unsubscribe message in the circle group? Will be used to determine if we subscribe to the group or not - uint32_t mGroupStatus; // Copy of the group status from the GXS group. - uint32_t mGroupSubscribeFlags; // Subscribe flags of the group. - -#ifdef SUBSCIRCLES - std::set mUnprocessedCircles; - std::set mProcessedCircles; -#endif - std::map mMembershipStatus; // Membership status of each ID cited in the group (including the ones posting a message) - - std::set mAllowedGxsIds; // IDs that are allowed in the circle and have requested membership. This is the official members list. - std::set mAllowedNodes; // List of friend nodes allowed in the circle (local circles only) - - RsPeerId mOriginator ; // peer who sent the data, in case we need to ask for ids -}; - - -class PgpAuxUtils; - -class RsCirclesMemCache : public std::map -{ -public: - RsCirclesMemCache() : std::map(){} - - bool is_cached(const RsGxsCircleId& id) { return end() != find(id) ; } - RsGxsCircleCache& ref(const RsGxsCircleId& id) { return operator[](id) ; } - - void printStats() { std::cerr << "CircleMemCache: " << size() << " elements." << std::endl; } - - template void applyToAllCachedEntries(ClientClass& c,bool (ClientClass::*method)(RsGxsCircleCache&)) - { - for(auto& it:*this) - (c.*method)(it.second); - } - template void applyToAllCachedEntries(ClientClass& c,bool (ClientClass::*method)(const RsGxsCircleCache&)) - { - for(const auto& it:*this) - (c.*method)(it.second); - } -}; - -class p3GxsCircles: public RsGxsCircleExchange, public RsGxsCircles, public GxsTokenQueue, public RsTickEvent, public p3Config -{ -public: - p3GxsCircles( - RsGeneralDataService* gds, RsNetworkExchangeService* nes, - p3IdService* identities, PgpAuxUtils* pgpUtils ); - - RsServiceInfo getServiceInfo() override; - - /// @see RsGxsCircles - bool createCircle( - const std::string& circleName, RsGxsCircleType circleType, - RsGxsCircleId& circleId = RS_DEFAULT_STORAGE_PARAM(RsGxsCircleId), - const RsGxsCircleId& restrictedId = RsGxsCircleId(), - const RsGxsId& authorId = RsGxsId(), - const std::set& gxsIdMembers = std::set(), - const std::set& localMembers = std::set() - ) override; - - bool editCircle( const RsGxsCircleId& circleId,const std::string& circleName, RsGxsCircleType circleType, - const RsGxsCircleId& restrictedId, - const RsGxsId& authorId, const std::set& gxsIdMembers, - const std::set& localMembers ) ; - - /// @see RsGxsCircles - bool editCircle(RsGxsCircleGroup& cData) override; - - /// @see RsGxsCircles - bool getCirclesSummaries(std::list& circles) override; - - /// @see RsGxsCircles - bool getCirclesInfo( - const std::list& circlesIds, - std::vector& circlesInfo ) override; - - /// @see RsGxsCircles - bool getCircleRequests( const RsGxsGroupId& circleId, - std::vector& requests ) override; - - /// @see RsGxsCircles - bool inviteIdsToCircle( const std::set& identities, - const RsGxsCircleId& circleId ) override; - - /// @see RsGxsCircles - bool revokeIdsFromCircle( const std::set& identities, - const RsGxsCircleId& circleId ) override; - - /// @see RsGxsCircles - bool getCircleRequest(const RsGxsGroupId& circleId, - const RsGxsMessageId& msgId, - RsGxsCircleMsg& msg) override; - - /// @see RsGxsCircles - bool exportCircleLink( - std::string& link, const RsGxsCircleId& circleId, - bool includeGxsData = true, - const std::string& baseUrl = DEFAULT_CIRCLE_BASE_URL, - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - /// @see RsGxsCircles - bool importCircleLink( - const std::string& link, - RsGxsCircleId& circleId = RS_DEFAULT_STORAGE_PARAM(RsGxsCircleId), - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - virtual bool getCircleDetails(const RsGxsCircleId &id, RsGxsCircleDetails &details) override; - virtual bool getCircleExternalIdList(std::set &circleIds) override; - - virtual bool isLoaded(const RsGxsCircleId &circleId) override; - virtual bool loadCircle(const RsGxsCircleId &circleId) override; - - virtual int canSend(const RsGxsCircleId &circleId, const RsPgpId &id, bool &should_encrypt) override; - virtual int canReceive(const RsGxsCircleId &circleId, const RsPgpId &id) override; - - virtual bool recipients(const RsGxsCircleId &circleId, std::list &friendlist) override; - virtual bool recipients(const RsGxsCircleId &circleId, const RsGxsGroupId& dest_group, std::list &gxs_ids) override; - virtual bool isRecipient(const RsGxsCircleId &circleId, const RsGxsGroupId& destination_group, const RsGxsId& id) override; - - - virtual bool getGroupData(const uint32_t &token, std::vector &groups) override; - virtual bool getMsgData(const uint32_t &token, std::vector &msgs) override; - virtual void createGroup(uint32_t& token, RsGxsCircleGroup &group) override; - virtual void updateGroup(uint32_t &token, RsGxsCircleGroup &group) override; - - virtual bool service_checkIfGroupIsStillUsed(const RsGxsGrpMetaData& meta) override; - virtual rstime_t service_getLastGroupSeenTs(const RsGxsGroupId&) override; - - /* membership management for external circles */ - - virtual bool requestCircleMembership(const RsGxsId &own_gxsid, const RsGxsCircleId& circle_id) override; - virtual bool cancelCircleMembership(const RsGxsId &own_gxsid, const RsGxsCircleId& circle_id) override; - - /**********************************************/ - - // needed for background processing. - virtual void service_tick() override; - -protected: - bool checkCircleParamConsistency( const std::string& circleName, RsGxsCircleType circleType, - const RsGxsCircleId& restrictedId, - const RsGxsId& authorId, const std::set& gxsIdMembers, - const std::set& localMembers ) const ; - - // overloads p3Config - virtual bool saveList(bool &cleanup, std::list&saveList) override; - virtual bool loadList(std::list& loadList) override; - virtual RsSerialiser *setupSerialiser() override; - - bool pushCircleMembershipRequest(const RsGxsId& own_gxsid, const RsGxsCircleId& circle_id, RsGxsCircleSubscriptionType request_type) ; - static uint32_t circleAuthenPolicy(); - - /** Notifications **/ - virtual void notifyChanges(std::vector& changes) override; - - /** Overloaded to add PgpIdHash to Group Definition **/ - virtual ServiceCreate_Return service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet) override; - - // Overloaded from GxsTokenQueue for Request callbacks. - virtual void handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) override; - - // Overloaded from RsTickEvent. - virtual void handle_event(uint32_t event_type, const std::string &elabel) override; - - private: - - // Load data. - bool processMembershipRequests(uint32_t token); - - // Need some crazy arsed cache to store the circle info. - // so we don't have to keep loading groups. - - int cache_tick(); - - bool cache_request_load(const RsGxsCircleId &id); - bool cache_start_load(); - bool force_cache_reload(const RsGxsCircleId& id); - bool cache_load_for_token(uint32_t token); - bool cache_reloadids(const RsGxsCircleId &circleId); - - bool checkCircleCache(); - - bool locked_checkCircleCacheForAutoSubscribe(RsGxsCircleCache &cache); - bool locked_processMembershipMessages(RsGxsCircleCache& cache,const std::vector& items, GxsMsgReq& messages_to_delete,const std::set& own_ids); - bool locked_processLoadingCacheEntry(RsGxsCircleCache &cache); - bool locked_checkCircleCacheForMembershipUpdate(RsGxsCircleCache &cache); - bool locked_setGroupUnprocessedStatus(RsGxsCircleCache& cache,bool unprocessed); - bool locked_subscribeToCircle(const RsGxsCircleId &grpId, bool subscribe); - - p3IdService *mIdentities; // Needed for constructing Circle Info, - PgpAuxUtils *mPgpUtils; - - RsMutex mCircleMtx; /* Locked Below Here */ - RsMutex mKnownCirclesMtx; /* Locked Below Here */ - - std::map mKnownCircles; - - /***** Caching Circle Info, *****/ - - // waiting for subcircle to load. (first is part of each of the second list) - // TODO. - //std::map > mCacheLoad_SubCircle; - - std::set mCirclesToLoad; // list of circles to update/load, so that we can treat them by groups. - RsCirclesMemCache mCircleCache; - //RsMemCache mCircleCache; // actual cache data - - void debug_dumpCache(); // debug method to overview what's going on - bool debug_dumpCacheEntry(RsGxsCircleCache &cache); -private: - - std::string genRandomId(); - - void generateDummyData(); - void checkDummyIdData(); - void generateDummyCircle(); - - rstime_t mLastCacheMembershipUpdateTS ; - - uint32_t mDummyIdToken; - std::list mDummyPgpLinkedIds; - std::list mDummyOwnIds; - bool mShouldSendCacheUpdateNotification ; - rstime_t mLastCacheUpdateEvent; - rstime_t mLastDebugPrintTS; - - RS_SET_CONTEXT_DEBUG_LEVEL(2) -}; diff --git a/libretroshare/src/services/p3gxscommon.cc b/libretroshare/src/services/p3gxscommon.cc deleted file mode 100644 index 7c37bd6aa..000000000 --- a/libretroshare/src/services/p3gxscommon.cc +++ /dev/null @@ -1,772 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3gxscommon.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2013 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "retroshare/rsgxscommon.h" -#include "services/p3gxscommon.h" -#include "rsitems/rsgxscommentitems.h" -#include "util/rsstring.h" - -#include -#include -#include - -//#define DEBUG_GXSCOMMON - -RsGxsComment::RsGxsComment() -{ - mUpVotes = 0; - mDownVotes = 0; - mScore = 0; - mOwnVote = 0; -} - -/********************************************************************************/ - -RsGxsImage::RsGxsImage() -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "RsGxsImage(" << this << ")"; - std::cerr << std::endl; -#endif - mData = NULL; - mSize = 0; -} - -RsGxsImage::RsGxsImage(const RsGxsImage& a) -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "RsGxsImage(" << this << ") = RsGxsImage(" << (void *) &a << ")"; - std::cerr << std::endl; -#endif - mData = NULL; - mSize = 0; - copy(a.mData, a.mSize); -} - - -RsGxsImage::~RsGxsImage() -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "~RsGxsImage(" << this << ")"; - std::cerr << std::endl; -#endif - clear(); -} - - -RsGxsImage &RsGxsImage::operator=(const RsGxsImage &a) -{ - copy(a.mData, a.mSize); - return *this; -} - - -bool RsGxsImage::empty() const -{ - return ((mData == NULL) || (mSize == 0)); -} - -void RsGxsImage::take(uint8_t *data, uint32_t size) -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "RsGxsImage(" << this << ")::take(" << (void *) data << "," << size << ")"; - std::cerr << std::endl; -#endif - // Copies Pointer. - clear(); - mData = data; - mSize = size; -} - -// NB Must make sure that we always use malloc/free for this data. -uint8_t *RsGxsImage::allocate(uint32_t size) -{ - uint8_t *val = (uint8_t *) rs_malloc(size); - -#ifdef DEBUG_GXSCOMMON - std::cerr << "RsGxsImage()::allocate(" << (void *) val << ")"; - std::cerr << std::endl; -#endif - return val; -} - -void RsGxsImage::release(void *data) -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "RsGxsImage()::release(" << (void *) data << ")"; - std::cerr << std::endl; -#endif - free(data); -} - -void RsGxsImage::copy(uint8_t *data, uint32_t size) -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "RsGxsImage(" << this << ")::copy(" << (void *) data << "," << size << ")"; - std::cerr << std::endl; -#endif - // Allocates and Copies. - clear(); - if (data && size) - { - mData = allocate(size); - memcpy(mData, data, size); - mSize = size; - } -} - -void RsGxsImage::clear() -{ - // Frees. - if (mData) - { - release(mData); - } - mData = NULL; - mSize = 0; -} - -void RsGxsImage::shallowClear() -{ - // Clears Pointer. - mData = NULL; - mSize = 0; -} - -/********************************************************************************/ - - -RsGxsFile::RsGxsFile() -{ - mSize = 0; -} - -RsGxsVote::RsGxsVote() -{ - mVoteType = 0; -} - -/********************************************************************************/ -/******************* Startup / Tick ******************************************/ -/********************************************************************************/ - -#define GXSCOMMENTS_VOTE_CHECK 0x0002 -#define GXSCOMMENTS_VOTE_DONE 0x0003 - -p3GxsCommentService::p3GxsCommentService(RsGenExchange *exchange, uint16_t service_type) - : GxsTokenQueue(exchange), mExchange(exchange), mServiceType(service_type) -{ - return; -} - -void p3GxsCommentService::comment_tick() -{ - GxsTokenQueue::checkRequests(); -} - -bool p3GxsCommentService::getGxsCommentData(const uint32_t &token, std::vector &comments) -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::getGxsCommentData()"; - std::cerr << std::endl; -#endif - - GxsMsgDataMap msgData; - bool ok = mExchange->getMsgData(token, msgData); - - if(ok) - { - GxsMsgDataMap::iterator mit = msgData.begin(); - std::multimap voteMap; - - for(; mit != msgData.end(); ++mit) - { - //RsGxsGroupId grpId = mit->first; - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - /* now split into Comments and Votes */ - - for(; vit != msgItems.end(); ++vit) - { - RsGxsCommentItem* item = dynamic_cast(*vit); - - if(item) - { - RsGxsComment comment = item->mMsg; - comment.mMeta = item->meta; - comments.push_back(comment); - delete item; - } - else - { - RsGxsVoteItem* vote = dynamic_cast(*vit); - if (vote) - { - voteMap.insert(std::make_pair(vote->meta.mParentId, vote)); - } - else - { - std::cerr << "Not a Comment or Vote, deleting!" << std::endl; - delete *vit; - } - } - } - } - - /* now iterate through comments - and set the vote counts */ - std::vector::iterator cit; - std::multimap::iterator it; - for(cit = comments.begin(); cit != comments.end(); ++cit) - { - for (it = voteMap.lower_bound(cit->mMeta.mMsgId); it != voteMap.upper_bound(cit->mMeta.mMsgId); ++it) - { - if (it->second->mMsg.mVoteType == GXS_VOTE_UP) - { - cit->mUpVotes++; - } - else - { - cit->mDownVotes++; - } - } - cit->mScore = calculateBestScore(cit->mUpVotes, cit->mDownVotes); - - /* convert Status -> mHaveVoted */ - if (cit->mMeta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_VOTE_MASK) - { - if (cit->mMeta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_VOTE_UP) - { - cit->mOwnVote = GXS_VOTE_UP; - } - else - { - cit->mOwnVote = GXS_VOTE_DOWN; - } - } - else - { - cit->mOwnVote = GXS_VOTE_NONE; - } - } - -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::getGxsCommentData() Found " << comments.size() << " Comments"; - std::cerr << std::endl; - std::cerr << "p3GxsCommentService::getGxsCommentData() Found " << voteMap.size() << " Votes"; - std::cerr << std::endl; -#endif - - /* delete the votes */ - for (it = voteMap.begin(); it != voteMap.end(); ++it) - { - delete it->second; - } - - - - } - - return ok; -} - - - - -bool p3GxsCommentService::getGxsRelatedComments(const uint32_t &token, std::vector &comments) -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::getGxsRelatedComments()"; - std::cerr << std::endl; -#endif - - GxsMsgRelatedDataMap msgData; - bool ok = mExchange->getMsgRelatedData(token, msgData); - - if(ok) - { - GxsMsgRelatedDataMap::iterator mit = msgData.begin(); - std::multimap voteMap; - - for(; mit != msgData.end(); ++mit) - { - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsCommentItem* item = dynamic_cast(*vit); - - if(item) - { - RsGxsComment comment = item->mMsg; - comment.mMeta = item->meta; - comments.push_back(comment); - delete item; - } - else - { - RsGxsVoteItem* vote = dynamic_cast(*vit); - if (vote) - { - voteMap.insert(std::make_pair(vote->meta.mParentId, vote)); - } - else - { - std::cerr << "Not a Comment or Vote, deleting!" << std::endl; - delete *vit; - } - } - } - } - - /* now iterate through comments - and set the vote counts */ - std::vector::iterator cit; - std::multimap::iterator it; - for(cit = comments.begin(); cit != comments.end(); ++cit) - { - for (it = voteMap.lower_bound(cit->mMeta.mMsgId); it != voteMap.upper_bound(cit->mMeta.mMsgId); ++it) - { - if (it->second->mMsg.mVoteType == GXS_VOTE_UP) - { - cit->mUpVotes++; - } - else - { - cit->mDownVotes++; - } - } - cit->mScore = calculateBestScore(cit->mUpVotes, cit->mDownVotes); - - /* convert Status -> mHaveVoted */ - if (cit->mMeta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_VOTE_MASK) - { - if (cit->mMeta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_VOTE_UP) - { - cit->mOwnVote = GXS_VOTE_UP; - } - else - { - cit->mOwnVote = GXS_VOTE_DOWN; - } - } - else - { - cit->mOwnVote = GXS_VOTE_NONE; - } - } - -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::getGxsRelatedComments() Found " << comments.size() << " Comments"; - std::cerr << std::endl; - std::cerr << "p3GxsCommentService::getGxsRelatedComments() Found " << voteMap.size() << " Votes"; - std::cerr << std::endl; -#endif - - /* delete the votes */ - for (it = voteMap.begin(); it != voteMap.end(); ++it) - { - delete it->second; - } - } - - return ok; -} - - - -double p3GxsCommentService::calculateBestScore(int upVotes, int downVotes) -{ - - float score; - int n = upVotes + downVotes; - - if(n==0) - score = 0.0; - else - { - // See https://github.com/reddit/reddit/blob/master/r2/r2/lib/db/_sorts.pyx#L45 for the source of this nice formula. - // http://www.evanmiller.org/how-not-to-sort-by-average-rating.html for the mathematical explanation. - - float p = upVotes/n; - float z = 1.281551565545 ; - - float left = p + 1/(2*n)*z*z ; - float right = z*sqrt(p*(1-p)/n + z*z/(4*n*n)) ; - float under = 1+1/n*z*z ; - - score = (left - right)/under ; - - //static float z = 1.0; - //score = sqrt(phat+z*z/(2*n)-z*((phat*(1-phat)+z*z/(4*n))/n))/(1+z*z/n); - } - return score; -} - - - -/********************************************************************************************/ - -bool p3GxsCommentService::createGxsComment(uint32_t &token, const RsGxsComment &msg) -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::createGxsComment() GroupId: " << msg.mMeta.mGroupId; - std::cerr << std::endl; -#endif - - RsGxsCommentItem* msgItem = new RsGxsCommentItem(mServiceType); - msgItem->mMsg = msg; - msgItem->meta = msg.mMeta; - - mExchange->publishMsg(token, msgItem); - return true; -} - - - -bool p3GxsCommentService::createGxsVote(uint32_t &token, RsGxsVote &vote) -{ - // NOTE Because we cannot do this operation immediately, we create a token, - // and monitor acknowledgeTokenMsg ... to return correct answer. - -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::createGxsVote() GroupId: " << vote.mMeta.mGroupId; - std::cerr << std::endl; -#endif - - /* vote must be associated with another item */ - if (vote.mMeta.mThreadId.isNull()) - { - std::cerr << "p3GxsCommentService::createGxsVote() ERROR Missing Required ThreadId"; - std::cerr << std::endl; - return false; - } - - if (vote.mMeta.mParentId.isNull()) - { - std::cerr << "p3GxsCommentService::createGxsVote() ERROR Missing Required ParentId"; - std::cerr << std::endl; - return false; - } - - if (vote.mMeta.mGroupId.isNull()) - { - std::cerr << "p3GxsCommentService::createGxsVote() ERROR Missing Required GroupId"; - std::cerr << std::endl; - return false; - } - - if (vote.mMeta.mAuthorId.isNull()) - { - std::cerr << "p3GxsCommentService::createGxsVote() ERROR Missing Required AuthorId"; - std::cerr << std::endl; - return false; - } - - - /* now queue */ - - RsGxsGrpMsgIdPair parentId(vote.mMeta.mGroupId, vote.mMeta.mParentId); - - std::map::iterator it; - it = mPendingVotes.find(parentId); - if (it != mPendingVotes.end()) - { - std::cerr << "p3GxsCommentService::createGxsVote() ERROR Already a pending vote!"; - std::cerr << std::endl; - return false; - } - - token = mExchange->generatePublicToken(); - mPendingVotes[parentId] = VoteHolder(vote, token); - - // request parent, and queue for response. - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_META; - - GxsMsgReq msgIds; - std::set &vect_msgIds = msgIds[parentId.first]; - vect_msgIds.insert(parentId.second); - - uint32_t int_token; - mExchange->getTokenService()->requestMsgInfo(int_token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, msgIds); - GxsTokenQueue::queueRequest(int_token, GXSCOMMENTS_VOTE_CHECK); - - return true; -} - - - - - - - -void p3GxsCommentService::load_PendingVoteParent(const uint32_t &token) -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::load_PendingVoteParent()"; - std::cerr << std::endl; -#endif - GxsMsgMetaMap msginfo; - if (!mExchange->getMsgMeta(token, msginfo)) - { - std::cerr << "p3GxsCommentService::load_PendingVoteParent() ERROR Fetching Data"; - std::cerr << std::endl; - std::cerr << "p3GxsCommentService::load_PendingVoteParent() Warning - this means LOST QUEUE ENTRY"; - std::cerr << std::endl; - std::cerr << "p3GxsCommentService::load_PendingVoteParent() Need to track tokens - if this happens"; - std::cerr << std::endl; - return; - } - - GxsMsgMetaMap::iterator it; - for(it = msginfo.begin(); it != msginfo.end(); ++it) - { - std::vector::iterator mit; - for(mit = it->second.begin(); mit != it->second.end(); ++mit) - { - /* find the matching Pending Vote */ - RsMsgMetaData &meta = *mit; - -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::load_PendingVoteParent() recv (groupId: " << meta.mGroupId; - std::cerr << ", msgId: " << meta.mMsgId << ")"; - std::cerr << std::endl; -#endif - - RsGxsGrpMsgIdPair parentId(meta.mGroupId, meta.mMsgId); - std::map::iterator pit; - pit = mPendingVotes.find(parentId); - if (pit == mPendingVotes.end()) - { - std::cerr << __PRETTY_FUNCTION__ - << " ERROR Finding Pending Vote" << std::endl; - continue; - } - - RsGxsVote vote = pit->second.mVote; - if (meta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_VOTE_MASK) - { - std::cerr << __PRETTY_FUNCTION__ << " ERROR Already Voted" - << std::endl - << "mGroupId: " << meta.mGroupId << std::endl - << "mMsgId: " << meta.mMsgId << std::endl; - - pit->second.mStatus = VoteHolder::VOTE_ERROR; - mExchange->updatePublicRequestStatus( - pit->second.mReqToken, RsTokenService::FAILED ); - continue; - } - -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::load_PendingVoteParent() submitting Vote"; - std::cerr << std::endl; -#endif - - uint32_t status_token; - if (vote.mVoteType == GXS_VOTE_UP) - { - mExchange->setMsgStatusFlags(status_token, parentId, - GXS_SERV::GXS_MSG_STATUS_VOTE_UP, GXS_SERV::GXS_MSG_STATUS_VOTE_MASK); - } - else - { - mExchange->setMsgStatusFlags(status_token, parentId, - GXS_SERV::GXS_MSG_STATUS_VOTE_DOWN, GXS_SERV::GXS_MSG_STATUS_VOTE_MASK); - } - - uint32_t vote_token; - castVote(vote_token, vote); - GxsTokenQueue::queueRequest(vote_token, GXSCOMMENTS_VOTE_DONE); - - pit->second.mVoteToken = vote_token; - pit->second.mStatus = VoteHolder::VOTE_SUBMITTED; - } - } -} - - - -void p3GxsCommentService::completeInternalVote(uint32_t &token) -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::completeInternalVote() token: " << token; - std::cerr << std::endl; -#endif - std::map::iterator it; - for (it = mPendingVotes.begin(); it != mPendingVotes.end(); ++it) - { - if (it->second.mVoteToken == token) - { - RsTokenService::GxsRequestStatus status = - mExchange->getTokenService()->requestStatus(token); - mExchange->updatePublicRequestStatus(it->second.mReqToken, status); - -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::completeInternalVote() Matched to PendingVote. status: " << status; - std::cerr << std::endl; -#endif - - it->second.mStatus = VoteHolder::VOTE_READY; - return; - } - } - - std::cerr << "p3GxsCommentService::completeInternalVote() ERROR Failed to match PendingVote"; - std::cerr << std::endl; - - return; -} - - -bool p3GxsCommentService::acknowledgeVote(const uint32_t& token, RsGxsGrpMsgIdPair& msgId) -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::acknowledgeVote() token: " << token; - std::cerr << std::endl; -#endif - - std::map::iterator it; - for (it = mPendingVotes.begin(); it != mPendingVotes.end(); ++it) - { - if (it->second.mReqToken == token) - { -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::acknowledgeVote() Matched to PendingVote"; - std::cerr << std::endl; -#endif - - bool ans = false; - if (it->second.mStatus == VoteHolder::VOTE_READY) - { -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::acknowledgeVote() PendingVote = READY"; - std::cerr << std::endl; -#endif - - // Finally finish this Vote off. - ans = mExchange->acknowledgeTokenMsg(it->second.mVoteToken, msgId); - } - else if (it->second.mStatus == VoteHolder::VOTE_ERROR) - { - std::cerr << "p3GxsCommentService::acknowledgeVote() PendingVote = ERROR ???"; - std::cerr << std::endl; - } -#ifdef DEBUG_GXSCOMMON - else - { - std::cerr << "p3GxsCommentService::acknowledgeVote() PendingVote = OTHER STATUS"; - std::cerr << std::endl; - } - - std::cerr << "p3GxsCommentService::acknowledgeVote() cleanup token & PendingVote"; - std::cerr << std::endl; -#endif - mExchange->disposeOfPublicToken(it->second.mReqToken); - mPendingVotes.erase(it); - - return ans; - } - } - -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::acknowledgeVote() Failed to match PendingVote"; - std::cerr << std::endl; -#endif - - return false; -} - - - // Overloaded from GxsTokenQueue for Request callbacks. -void p3GxsCommentService::handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::handleResponse(" << token << "," << req_type << "," << status << ")" << std::endl; -#endif - if (status != RsTokenService::COMPLETE) - return; //For now, only manage Complete request - - - // stuff. - switch(req_type) - { - case GXSCOMMENTS_VOTE_CHECK: - load_PendingVoteParent(token); - break; - - case GXSCOMMENTS_VOTE_DONE: - completeInternalVote(token); - break; - - default: - /* error */ - std::cerr << "p3GxsCommentService::handleResponse() Unknown Request Type: " << req_type; - std::cerr << std::endl; - break; - } -} - - - - - -bool p3GxsCommentService::castVote(uint32_t &token, RsGxsVote &msg) -{ -#ifdef DEBUG_GXSCOMMON - std::cerr << "p3GxsCommentService::castVote() GroupId: " << msg.mMeta.mGroupId; - std::cerr << std::endl; -#endif - - RsGxsVoteItem* msgItem = new RsGxsVoteItem(mServiceType); - msgItem->mMsg = msg; - msgItem->meta = msg.mMeta; - - mExchange->publishMsg(token, msgItem); - return true; -} - - - - - - - -/********************************************************************************************/ -/********************************************************************************************/ - -#if 0 -void p3GxsCommentService::setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) -{ - uint32_t mask = GXS_SERV::GXS_MSG_STATUS_UNREAD | GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - uint32_t status = GXS_SERV::GXS_MSG_STATUS_UNREAD; - if (read) - { - status = 0; - } - - setMsgStatusFlags(token, msgId, status, mask); - -} - -#endif - diff --git a/libretroshare/src/services/p3gxscommon.h b/libretroshare/src/services/p3gxscommon.h deleted file mode 100644 index fb51a0d30..000000000 --- a/libretroshare/src/services/p3gxscommon.h +++ /dev/null @@ -1,106 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3gxscommon.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2013 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef P3_GXSCOMMON_SERVICE_HEADER -#define P3_GXSCOMMON_SERVICE_HEADER - -#include "retroshare/rsgxscommon.h" -#include "gxs/rsgenexchange.h" -#include "gxs/gxstokenqueue.h" -#include - - -/**** - * This mirrors rsGxsCommentService, with slightly different names, - * provides the implementation for any services requiring Comments. - */ - -# -class VoteHolder -{ - public: - - static const uint32_t VOTE_ERROR = 0; - static const uint32_t VOTE_QUEUED = 1; - static const uint32_t VOTE_SUBMITTED = 2; - static const uint32_t VOTE_READY = 3; - - VoteHolder() :mVoteToken(0), mReqToken(0), mStatus(VOTE_ERROR) { return; } - - VoteHolder(const RsGxsVote &vote, uint32_t reqToken) - :mVote(vote), mVoteToken(0), mReqToken(reqToken), mStatus(VOTE_QUEUED) { return; } - - RsGxsVote mVote; - uint32_t mVoteToken; - uint32_t mReqToken; - uint32_t mStatus; -}; - - -class p3GxsCommentService: public GxsTokenQueue -{ - public: - - p3GxsCommentService(RsGenExchange *exchange, uint16_t service_type); - - void comment_tick(); - - bool getGxsCommentData(const uint32_t &token, std::vector &msgs); - bool getGxsRelatedComments(const uint32_t &token, std::vector &msgs); - - bool createGxsComment(uint32_t &token, const RsGxsComment &msg); - bool createGxsVote(uint32_t &token, RsGxsVote &msg); - - // Special Acknowledge. - bool acknowledgeVote(const uint32_t& token, RsGxsGrpMsgIdPair& msgId); - -static double calculateBestScore(int upVotes, int downVotes); - - -#if 0 - void setGxsMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read); -#endif - - protected: - - // Overloaded from GxsTokenQueue for Request callbacks. - virtual void handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) override; - - private: - - void load_PendingVoteParent(const uint32_t &token); - void completeInternalVote(uint32_t &token); - - bool castVote(uint32_t &token, RsGxsVote &msg); - - RsGenExchange *mExchange; - uint16_t mServiceType; - - /* pending queue of Votes */ - std::map mPendingVotes; - - -}; - - -#endif - diff --git a/libretroshare/src/services/p3gxsforums.cc b/libretroshare/src/services/p3gxsforums.cc deleted file mode 100644 index 97d880880..000000000 --- a/libretroshare/src/services/p3gxsforums.cc +++ /dev/null @@ -1,1691 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3gxsforums.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012-2014 Robert Fernie * - * Copyright (C) 2018-2021 Gioacchino Mazzurco * - * Copyright (C) 2019-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include -#include - -#include "services/p3gxsforums.h" -#include "rsitems/rsgxsforumitems.h" -#include "retroshare/rspeers.h" -#include "retroshare/rsidentity.h" -#include "util/rsdebug.h" -#include "rsserver/p3face.h" -#include "retroshare/rsnotify.h" -#include "util/rsdebuglevel2.h" -#include "retroshare/rsgxsflags.h" - - -// For Dummy Msgs. -#include "util/rsrandom.h" -#include "util/rsstring.h" - -/**** - * #define GXSFORUM_DEBUG 1 - ****/ - -RsGxsForums *rsGxsForums = NULL; - -#define FORUM_TESTEVENT_DUMMYDATA 0x0001 -#define DUMMYDATA_PERIOD 60 // long enough for some RsIdentities to be generated. -#define FORUM_UNUSED_BY_FRIENDS_DELAY (2*30*86400) // unused forums are deleted after 2 months - -/********************************************************************************/ -/******************* Startup / Tick ******************************************/ -/********************************************************************************/ - -p3GxsForums::p3GxsForums( RsGeneralDataService *gds, - RsNetworkExchangeService *nes, RsGixs* gixs ) : - RsGenExchange( gds, nes, new RsGxsForumSerialiser(), - RS_SERVICE_GXS_TYPE_FORUMS, gixs, forumsAuthenPolicy()), - RsGxsForums(static_cast(*this)), mGenToken(0), - mGenActive(false), mGenCount(0), - mKnownForumsMutex("GXS forums known forums timestamp cache") -#ifdef RS_DEEP_FORUMS_INDEX - , mDeepIndex(DeepForumsIndex::dbDefaultPath()) -#endif -{ - // Test Data disabled in Repo. - //RsTickEvent::schedule_in(FORUM_TESTEVENT_DUMMYDATA, DUMMYDATA_PERIOD); -} - - -const std::string GXS_FORUMS_APP_NAME = "gxsforums"; -const uint16_t GXS_FORUMS_APP_MAJOR_VERSION = 1; -const uint16_t GXS_FORUMS_APP_MINOR_VERSION = 0; -const uint16_t GXS_FORUMS_MIN_MAJOR_VERSION = 1; -const uint16_t GXS_FORUMS_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3GxsForums::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_GXS_TYPE_FORUMS, - GXS_FORUMS_APP_NAME, - GXS_FORUMS_APP_MAJOR_VERSION, - GXS_FORUMS_APP_MINOR_VERSION, - GXS_FORUMS_MIN_MAJOR_VERSION, - GXS_FORUMS_MIN_MINOR_VERSION); -} - - -uint32_t p3GxsForums::forumsAuthenPolicy() -{ - uint32_t policy = 0; - uint32_t flag = GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS); - - flag |= GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS); - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS); - - flag = 0; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::GRP_OPTION_BITS); - - return policy; -} - -static const uint32_t GXS_FORUMS_CONFIG_MAX_TIME_NOTIFY_STORAGE = 86400*30*2 ; // ignore notifications for 2 months -static const uint8_t GXS_FORUMS_CONFIG_SUBTYPE_NOTIFY_RECORD = 0x01 ; - -struct RsGxsForumNotifyRecordsItem: public RsItem -{ - - RsGxsForumNotifyRecordsItem() - : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_GXS_TYPE_FORUMS_CONFIG,GXS_FORUMS_CONFIG_SUBTYPE_NOTIFY_RECORD) - {} - - virtual ~RsGxsForumNotifyRecordsItem() {} - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { RS_SERIAL_PROCESS(records); } - - void clear() {} - - std::map records; -}; - -class GxsForumsConfigSerializer : public RsServiceSerializer -{ -public: - GxsForumsConfigSerializer() : RsServiceSerializer(RS_SERVICE_GXS_TYPE_FORUMS_CONFIG) {} - virtual ~GxsForumsConfigSerializer() {} - - RsItem* create_item(uint16_t service_id, uint8_t item_sub_id) const - { - if(service_id != RS_SERVICE_GXS_TYPE_FORUMS_CONFIG) - return NULL; - - switch(item_sub_id) - { - case GXS_FORUMS_CONFIG_SUBTYPE_NOTIFY_RECORD: return new RsGxsForumNotifyRecordsItem(); - default: - return NULL; - } - } -}; - -bool p3GxsForums::saveList(bool &cleanup, std::list&saveList) -{ - cleanup = true ; - - RsGxsForumNotifyRecordsItem *item = new RsGxsForumNotifyRecordsItem ; - - { - RS_STACK_MUTEX(mKnownForumsMutex); - item->records = mKnownForums ; - } - - saveList.push_back(item) ; - return true; -} - -bool p3GxsForums::loadList(std::list& loadList) -{ - while(!loadList.empty()) - { - RsItem *item = loadList.front(); - loadList.pop_front(); - - rstime_t now = time(NULL); - - RsGxsForumNotifyRecordsItem *fnr = dynamic_cast(item) ; - - if(fnr != NULL) - { - RS_STACK_MUTEX(mKnownForumsMutex); - - mKnownForums.clear(); - - for(auto it(fnr->records.begin());it!=fnr->records.end();++it) - if( now < it->second + GXS_FORUMS_CONFIG_MAX_TIME_NOTIFY_STORAGE) - mKnownForums.insert(*it) ; - } - - delete item ; - } - return true; -} - -RsSerialiser* p3GxsForums::setupSerialiser() -{ - RsSerialiser* rss = new RsSerialiser; - rss->addSerialType(new GxsForumsConfigSerializer()); - - return rss; -} - -void p3GxsForums::notifyChanges(std::vector& changes) -{ - RS_DBG2(changes.size(), " changes to notify"); - - for(RsGxsNotify* gxsChange: changes) - { - // Let the compiler delete the change for us - std::unique_ptr gxsChangeDeleter(gxsChange); - - switch(gxsChange->getType()) - { - case RsGxsNotify::TYPE_RECEIVED_NEW: // [[fallthrough]] - case RsGxsNotify::TYPE_PUBLISHED: - { - auto msgChange = dynamic_cast(gxsChange); - - if(msgChange) /* Message received */ - { - uint8_t msgSubtype = msgChange->mNewMsgItem->PacketSubType(); - switch(static_cast(msgSubtype)) - { - case RsGxsForumsItems::MESSAGE_ITEM: - { - auto newForumMessageItem = - dynamic_cast( - msgChange->mNewMsgItem ); - - if(!newForumMessageItem) - { - RS_ERR("Received message change with mNewMsgItem type " - "mismatching or null"); - print_stacktrace(); - return; - } - -#ifdef RS_DEEP_FORUMS_INDEX - RsGxsForumMsg tmpPost = newForumMessageItem->mMsg; - tmpPost.mMeta = newForumMessageItem->meta; - mDeepIndex.indexForumPost(tmpPost); -#endif - auto ev = std::make_shared(); - ev->mForumMsgId = msgChange->mMsgId; - ev->mForumGroupId = msgChange->mGroupId; - ev->mForumEventCode = RsForumEventCode::NEW_MESSAGE; - rsEvents->postEvent(ev); - break; - } - default: - RS_WARN("Got unknown gxs message subtype: ", msgSubtype); - break; - } - } - - auto groupChange = dynamic_cast(gxsChange); - if(groupChange) /* Group received */ - { - bool unknown; - { - RS_STACK_MUTEX(mKnownForumsMutex); - unknown = ( mKnownForums.find(gxsChange->mGroupId) - == mKnownForums.end() ); - mKnownForums[gxsChange->mGroupId] = time(nullptr); - IndicateConfigChanged(); - } - - if(unknown) - { - auto ev = std::make_shared(); - ev->mForumGroupId = gxsChange->mGroupId; - ev->mForumEventCode = RsForumEventCode::NEW_FORUM; - rsEvents->postEvent(ev); - } - -#ifdef RS_DEEP_FORUMS_INDEX - uint8_t itemType = groupChange->mNewGroupItem->PacketSubType(); - switch(static_cast(itemType)) - { - case RsGxsForumsItems::GROUP_ITEM: - { - auto newForumGroupItem = - static_cast( - groupChange->mNewGroupItem ); - mDeepIndex.indexForumGroup(newForumGroupItem->mGroup); - break; - } - default: - RS_WARN("Got unknown gxs group subtype: ", itemType); - break; - } -#endif // def RS_DEEP_FORUMS_INDEX - - } - break; - } - case RsGxsNotify::TYPE_PROCESSED: // happens when the group is subscribed - { - auto ev = std::make_shared(); - ev->mForumGroupId = gxsChange->mGroupId; - ev->mForumEventCode = RsForumEventCode::SUBSCRIBE_STATUS_CHANGED; - rsEvents->postEvent(ev); - break; - } - case RsGxsNotify::TYPE_GROUP_SYNC_PARAMETERS_UPDATED: - { - auto ev = std::make_shared(); - ev->mForumGroupId = gxsChange->mGroupId; - ev->mForumEventCode = RsForumEventCode::SYNC_PARAMETERS_UPDATED; - rsEvents->postEvent(ev); - break; - } - case RsGxsNotify::TYPE_MESSAGE_DELETED: - { - auto delChange = dynamic_cast(gxsChange); - if(!delChange) - { - RS_ERR( "Got mismatching notification type: ", - gxsChange->getType() ); - print_stacktrace(); - break; - } - -#ifdef RS_DEEP_FORUMS_INDEX - mDeepIndex.removeForumPostFromIndex( - delChange->mGroupId, delChange->messageId); -#endif - - auto ev = std::make_shared(); - ev->mForumEventCode = RsForumEventCode::DELETED_POST; - ev->mForumGroupId = delChange->mGroupId; - ev->mForumMsgId = delChange->messageId; - break; - } - case RsGxsNotify::TYPE_GROUP_DELETED: - { -#ifdef RS_DEEP_FORUMS_INDEX - mDeepIndex.removeForumFromIndex(gxsChange->mGroupId); -#endif - auto ev = std::make_shared(); - ev->mForumGroupId = gxsChange->mGroupId; - ev->mForumEventCode = RsForumEventCode::DELETED_FORUM; - rsEvents->postEvent(ev); - break; - } - case RsGxsNotify::TYPE_STATISTICS_CHANGED: - { - auto ev = std::make_shared(); - ev->mForumGroupId = gxsChange->mGroupId; - ev->mForumEventCode = RsForumEventCode::STATISTICS_CHANGED; - rsEvents->postEvent(ev); - - RS_STACK_MUTEX(mKnownForumsMutex); - mKnownForums[gxsChange->mGroupId] = time(nullptr); - IndicateConfigChanged(); - break; - } - case RsGxsNotify::TYPE_UPDATED: - { - /* Happens when the group data has changed. In this case we need to - * analyse the old and new group in order to detect possible - * notifications for clients */ - - auto grpChange = dynamic_cast(gxsChange); - - RsGxsForumGroupItem* old_forum_grp_item = - dynamic_cast(grpChange->mOldGroupItem); - RsGxsForumGroupItem* new_forum_grp_item = - dynamic_cast(grpChange->mNewGroupItem); - - if( old_forum_grp_item == nullptr || new_forum_grp_item == nullptr) - { - RS_ERR( "received GxsGroupUpdate item with mOldGroup and " - "mNewGroup not of type RsGxsForumGroupItem or NULL. " - "This is inconsistent!"); - print_stacktrace(); - break; - } - -#ifdef RS_DEEP_FORUMS_INDEX - mDeepIndex.indexForumGroup(new_forum_grp_item->mGroup); -#endif - - /* First of all, we check if there is a difference between the old - * and new list of moderators */ - - std::list added_mods, removed_mods; - for(auto& gxs_id: new_forum_grp_item->mGroup.mAdminList.ids) - if( old_forum_grp_item->mGroup.mAdminList.ids.find(gxs_id) - == old_forum_grp_item->mGroup.mAdminList.ids.end() ) - added_mods.push_back(gxs_id); - - for(auto& gxs_id: old_forum_grp_item->mGroup.mAdminList.ids) - if( new_forum_grp_item->mGroup.mAdminList.ids.find(gxs_id) - == new_forum_grp_item->mGroup.mAdminList.ids.end() ) - removed_mods.push_back(gxs_id); - - if(!added_mods.empty() || !removed_mods.empty()) - { - auto ev = std::make_shared(); - - ev->mForumGroupId = new_forum_grp_item->meta.mGroupId; - ev->mModeratorsAdded = added_mods; - ev->mModeratorsRemoved = removed_mods; - ev->mForumEventCode = RsForumEventCode::MODERATOR_LIST_CHANGED; - - rsEvents->postEvent(ev); - } - - // check the list of pinned posts - std::list added_pins, removed_pins; - - for(auto& msg_id: new_forum_grp_item->mGroup.mPinnedPosts.ids) - if( old_forum_grp_item->mGroup.mPinnedPosts.ids.find(msg_id) - == old_forum_grp_item->mGroup.mPinnedPosts.ids.end() ) - added_pins.push_back(msg_id); - - for(auto& msg_id: old_forum_grp_item->mGroup.mPinnedPosts.ids) - if( new_forum_grp_item->mGroup.mPinnedPosts.ids.find(msg_id) - == new_forum_grp_item->mGroup.mPinnedPosts.ids.end() ) - removed_pins.push_back(msg_id); - - if(!added_pins.empty() || !removed_pins.empty()) - { - auto ev = std::make_shared(); - ev->mForumGroupId = new_forum_grp_item->meta.mGroupId; - ev->mForumEventCode = RsForumEventCode::PINNED_POSTS_CHANGED; - rsEvents->postEvent(ev); - } - - if( old_forum_grp_item->mGroup.mDescription != new_forum_grp_item->mGroup.mDescription - || old_forum_grp_item->meta.mGroupName != new_forum_grp_item->meta.mGroupName - || old_forum_grp_item->meta.mGroupFlags != new_forum_grp_item->meta.mGroupFlags - || old_forum_grp_item->meta.mAuthorId != new_forum_grp_item->meta.mAuthorId - || old_forum_grp_item->meta.mCircleId != new_forum_grp_item->meta.mCircleId ) - { - auto ev = std::make_shared(); - ev->mForumGroupId = new_forum_grp_item->meta.mGroupId; - ev->mForumEventCode = RsForumEventCode::UPDATED_FORUM; - rsEvents->postEvent(ev); - } - - break; - } - - default: - RS_ERR( "Got a GXS event of type ", gxsChange->getType(), - " Currently not handled." ); - break; - } - } -} - -void p3GxsForums::service_tick() -{ - dummy_tick(); - RsTickEvent::tick_events(); - return; -} - -rstime_t p3GxsForums::service_getLastGroupSeenTs(const RsGxsGroupId& gid) -{ - rstime_t now = time(nullptr); - - RS_STACK_MUTEX(mKnownForumsMutex); - - auto it = mKnownForums.find(gid); - bool unknown_forum = it == mKnownForums.end(); - - if(unknown_forum) - { - mKnownForums[gid] = now; - IndicateConfigChanged(); - return now; - } - else - return it->second; -} -bool p3GxsForums::service_checkIfGroupIsStillUsed(const RsGxsGrpMetaData& meta) -{ -#ifdef GXSFORUMS_DEBUG - std::cerr << "p3gxsForums: Checking unused forums: called by GxsCleaning." << std::endl; -#endif - - // request all group infos at once - - rstime_t now = time(nullptr); - - RS_STACK_MUTEX(mKnownForumsMutex); - - auto it = mKnownForums.find(meta.mGroupId); - bool unknown_forum = it == mKnownForums.end(); - -#ifdef GXSFORUMS_DEBUG - std::cerr << " Forum " << meta.mGroupId ; -#endif - - if(unknown_forum) - { - // This case should normally not happen. It does because this forum was never registered since it may - // arrived before this code was here - -#ifdef GXSFORUMS_DEBUG - std::cerr << ". Not known yet. Adding current time as new TS." << std::endl; -#endif - mKnownForums[meta.mGroupId] = now; - IndicateConfigChanged(); - - return true; - } - else - { - bool used_by_friends = (now < it->second + FORUM_UNUSED_BY_FRIENDS_DELAY); - bool subscribed = static_cast(meta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED); - -#ifdef GXSFORUMS_DEBUG - std::cerr << ". subscribed: " << subscribed << ", used_by_friends: " << used_by_friends << " last TS: " << now - it->second << " secs ago (" << (now-it->second)/86400 << " days)"; -#endif - - if(!subscribed && !used_by_friends) - { -#ifdef GXSFORUMS_DEBUG - std::cerr << ". Scheduling for deletion" << std::endl; -#endif - return false; - } - else - { -#ifdef GXSFORUMS_DEBUG - std::cerr << ". Keeping!" << std::endl; -#endif - return true; - } - } -} -bool p3GxsForums::getGroupData(const uint32_t &token, std::vector &groups) -{ - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); ++vit) - { - RsGxsForumGroupItem* item = dynamic_cast(*vit); - if (item) - { - RsGxsForumGroup grp = item->mGroup; - grp.mMeta = item->meta; - delete item; - groups.push_back(grp); - } - else - { - std::cerr << "Not a GxsForumGrpItem, deleting!" << std::endl; - delete *vit; - } - } - } - return ok; -} - -bool p3GxsForums::getMsgMetaData(const uint32_t &token, GxsMsgMetaMap& msg_metas) -{ - return RsGenExchange::getMsgMeta(token, msg_metas); -} - -/* Okay - chris is not going to be happy with this... - * but I can't be bothered with crazy data structures - * at the moment - fix it up later - */ - -bool p3GxsForums::getMsgData(const uint32_t &token, std::vector &msgs) -{ - GxsMsgDataMap msgData; - bool ok = RsGenExchange::getMsgData(token, msgData); - - if(ok) - { - GxsMsgDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsForumMsgItem* item = dynamic_cast(*vit); - - if(item) - { - RsGxsForumMsg msg = item->mMsg; - msg.mMeta = item->meta; - msgs.push_back(msg); - delete item; - } - else - { - std::cerr << "Not a GxsForumMsgItem, deleting!" << std::endl; - delete *vit; - } - } - } - } - - return ok; -} - -bool p3GxsForums::createForumV2( - const std::string& name, const std::string& description, - const RsGxsId& authorId, const std::set& moderatorsIds, - RsGxsCircleType circleType, const RsGxsCircleId& circleId, - RsGxsGroupId& forumId, std::string& errorMessage ) -{ - auto createFail = [&](std::string mErr) - { - errorMessage = mErr; - RsErr() << __PRETTY_FUNCTION__ << " " << errorMessage << std::endl; - return false; - }; - - if(name.empty()) return createFail("Forum name is required"); - - if(!authorId.isNull() && !rsIdentity->isOwnId(authorId)) - return createFail("Author must be iether null or and identity owned by " - "this node"); - - switch(circleType) - { - case RsGxsCircleType::PUBLIC: // fallthrough - case RsGxsCircleType::LOCAL: // fallthrough - case RsGxsCircleType::YOUR_EYES_ONLY: - break; - case RsGxsCircleType::EXTERNAL: - if(circleId.isNull()) - return createFail("circleType is EXTERNAL but circleId is null"); - break; - case RsGxsCircleType::NODES_GROUP: - { - RsGroupInfo ginfo; - if(!rsPeers->getGroupInfo(RsNodeGroupId(circleId), ginfo)) - return createFail("circleType is NODES_GROUP but circleId does not " - "correspond to an actual group of friends"); - break; - } - default: return createFail("circleType has invalid value"); - } - - // Create a consistent channel group meta from the information supplied - RsGxsForumGroup forum; - - forum.mMeta.mGroupName = name; - forum.mMeta.mAuthorId = authorId; - forum.mMeta.mCircleType = static_cast(circleType); - - forum.mMeta.mSignFlags = GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_NONEREQ - | GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_REQUIRED; - - /* This flag have always this value even for circle restricted forums due to - * how GXS distribute/verify groups */ - forum.mMeta.mGroupFlags = GXS_SERV::FLAG_PRIVACY_PUBLIC; - - forum.mMeta.mCircleId.clear(); - forum.mMeta.mInternalCircle.clear(); - - switch(circleType) - { - case RsGxsCircleType::NODES_GROUP: - forum.mMeta.mInternalCircle = circleId; break; - case RsGxsCircleType::EXTERNAL: - forum.mMeta.mCircleId = circleId; break; - default: break; - } - - forum.mDescription = description; - forum.mAdminList.ids = moderatorsIds; - - uint32_t token; - if(!createGroup(token, forum)) - return createFail("Failed creating GXS group."); - - // wait for the group creation to complete. - RsTokenService::GxsRequestStatus wSt = - waitToken( token, std::chrono::milliseconds(5000), - std::chrono::milliseconds(20) ); - if(wSt != RsTokenService::COMPLETE) - return createFail( "GXS operation waitToken failed with: " - + std::to_string(wSt) ); - - if(!RsGenExchange::getPublishedGroupMeta(token, forum.mMeta)) - return createFail("Failure getting updated group data."); - - forumId = forum.mMeta.mGroupId; - - return true; -} - -bool p3GxsForums::createPost( - const RsGxsGroupId& forumId, const std::string& title, - const std::string& mBody, - const RsGxsId& authorId, const RsGxsMessageId& parentId, - const RsGxsMessageId& origPostId, RsGxsMessageId& postMsgId, - std::string& errorMessage ) -{ - RsGxsForumMsg post; - - auto failure = [&](std::string errMsg) - { - errorMessage = errMsg; - RsErr() << __PRETTY_FUNCTION__ << " " << errorMessage << std::endl; - return false; - }; - - if(title.empty()) return failure("Title is required"); - - if(authorId.isNull()) return failure("Author id is needed"); - - if(!rsIdentity->isOwnId(authorId)) - return failure( "Author id: " + authorId.toStdString() + " is not of" - "own identity" ); - - if(!parentId.isNull()) - { - std::vector msgs; - if( getForumContent(forumId, std::set({parentId}), msgs) - && msgs.size() == 1 ) - { - post.mMeta.mParentId = parentId; - post.mMeta.mThreadId = msgs[0].mMeta.mThreadId; - } - else return failure("Parent post " + parentId.toStdString() - + " doesn't exists locally"); - } - - std::vector forumInfo; - if(!getForumsInfo(std::list({forumId}), forumInfo)) - return failure( "Forum with Id " + forumId.toStdString() - + " does not exist locally." ); - - if(!origPostId.isNull()) - { - std::vector msgs; - if( getForumContent( forumId, - std::set({origPostId}), msgs) - && msgs.size() == 1 ) - post.mMeta.mOrigMsgId = origPostId; - else return failure("Original post " + origPostId.toStdString() - + " doesn't exists locally"); - } - - post.mMeta.mGroupId = forumId; - post.mMeta.mMsgName = title; - post.mMeta.mAuthorId = authorId; - post.mMsg = mBody; - - uint32_t token; - if( !createMsg(token, post) - || waitToken( - token, - std::chrono::milliseconds(5000) ) != RsTokenService::COMPLETE ) - return failure("Failure creating GXS message"); - - if(!RsGenExchange::getPublishedMsgMeta(token, post.mMeta)) - return failure("Failure getting created GXS message metadata"); - - postMsgId = post.mMeta.mMsgId; - return true; -} - -bool p3GxsForums::createForum(RsGxsForumGroup& forum) -{ - uint32_t token; - if(!createGroup(token, forum)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failed creating group." - << std::endl; - return false; - } - - if(waitToken(token,std::chrono::milliseconds(5000)) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed." - << std::endl; - return false; - } - - if(!RsGenExchange::getPublishedGroupMeta(token, forum.mMeta)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting updated " - << " group data." << std::endl; - return false; - } - - return true; -} - -bool p3GxsForums::editForum(RsGxsForumGroup& forum) -{ - uint32_t token; - if(!updateGroup(token, forum)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failed updating group." - << std::endl; - return false; - } - - if(waitToken(token,std::chrono::milliseconds(5000)) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed." - << std::endl; - return false; - } - - if(!RsGenExchange::getPublishedGroupMeta(token, forum.mMeta)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting updated " - << " group data." << std::endl; - return false; - } - - return true; -} - -bool p3GxsForums::getForumsSummaries( std::list& forums ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; - if( !requestGroupInfo(token, opts) - || waitToken(token,std::chrono::milliseconds(5000)) != RsTokenService::COMPLETE ) return false; - return getGroupSummary(token, forums); -} - -bool p3GxsForums::getForumsInfo( const std::list& forumIds, std::vector& forumsInfo ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - - if(forumIds.empty()) - { - if( !requestGroupInfo(token, opts) || waitToken(token,std::chrono::milliseconds(5000)) != RsTokenService::COMPLETE ) - return false; - } - else - { - if( !requestGroupInfo(token, opts, forumIds, forumIds.size()==1) || waitToken(token,std::chrono::milliseconds(5000)) != RsTokenService::COMPLETE ) - return false; - } - return getGroupData(token, forumsInfo); -} - -bool p3GxsForums::getForumContent( - const RsGxsGroupId& forumId, - const std::set& msgs_to_request, - std::vector& msgs ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - - GxsMsgReq msgIds; - msgIds[forumId] = msgs_to_request; - - if( !requestMsgInfo(token, opts, msgIds) || waitToken(token,std::chrono::seconds(5)) != RsTokenService::COMPLETE ) - return false; - - return getMsgData(token, msgs); -} - - -bool p3GxsForums::getForumMsgMetaData(const RsGxsGroupId& forumId, std::vector& msg_metas) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_META; - - GxsMsgMetaMap meta_map; - std::list forumIds; - forumIds.push_back(forumId); - - if( !requestMsgInfo(token, opts, forumIds) || waitToken(token,std::chrono::milliseconds(5000)) != RsTokenService::COMPLETE ) return false; - - bool res = getMsgMetaData(token, meta_map); - - msg_metas = meta_map[forumId]; - - return res; -} - -bool p3GxsForums::markRead(const RsGxsGrpMsgIdPair& msgId, bool read) -{ - uint32_t token; - setMessageReadStatus(token, msgId, read); - if(waitToken(token,std::chrono::milliseconds(5000)) != RsTokenService::COMPLETE ) return false; - - RsGxsGrpMsgIdPair p; - acknowledgeMsg(token,p); - - return true; -} - -bool p3GxsForums::subscribeToForum(const RsGxsGroupId& groupId, bool subscribe ) -{ - uint32_t token; - if( !RsGenExchange::subscribeToGroup(token, groupId, subscribe) || - waitToken(token) != RsTokenService::COMPLETE ) return false; - - RsGxsGroupId grp; - acknowledgeGrp(token, grp); - - /* Since subscribe has been requested, the caller is most probably - * interested in getting the group messages ASAP so check updates from peers - * without waiting GXS sync timer. - * Do it here as this is meaningful or not depending on the service. - * Do it only after the token has been completed otherwise the pull have no - * effect. */ - if(subscribe) RsGenExchange::netService()->checkUpdatesFromPeers(); - - return true; -} - -bool p3GxsForums::exportForumLink( - std::string& link, const RsGxsGroupId& forumId, bool includeGxsData, - const std::string& baseUrl, std::string& errMsg ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - errMsg = err; - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(forumId.isNull()) return failure("forumId cannot be null"); - - const bool outputRadix = baseUrl.empty(); - if(outputRadix && !includeGxsData) return - failure("includeGxsData must be true if format requested is base64"); - - if( includeGxsData && - !RsGenExchange::exportGroupBase64(link, forumId, errMsg) ) - return failure(errMsg); - - if(outputRadix) return true; - - std::vector forumsInfo; - if( !getForumsInfo(std::list({forumId}), forumsInfo) - || forumsInfo.empty() ) - return failure("failure retrieving forum information"); - - RsUrl inviteUrl(baseUrl); - inviteUrl.setQueryKV(FORUM_URL_ID_FIELD, forumId.toStdString()); - inviteUrl.setQueryKV(FORUM_URL_NAME_FIELD, forumsInfo[0].mMeta.mGroupName); - if(includeGxsData) inviteUrl.setQueryKV(FORUM_URL_DATA_FIELD, link); - - link = inviteUrl.toString(); - return true; -} - -bool p3GxsForums::importForumLink( - const std::string& link, RsGxsGroupId& forumId, std::string& errMsg ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - errMsg = err; - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(link.empty()) return failure("link is empty"); - - const std::string* radixPtr(&link); - - RsUrl url(link); - const auto& query = url.query(); - const auto qIt = query.find(FORUM_URL_DATA_FIELD); - if(qIt != query.end()) radixPtr = &qIt->second; - - if(radixPtr->empty()) return failure(FORUM_URL_DATA_FIELD + " is empty"); - - if(!RsGenExchange::importGroupBase64(*radixPtr, forumId, errMsg)) - return failure(errMsg); - - return true; -} - -std::error_condition p3GxsForums::getChildPosts( - const RsGxsGroupId& forumId, const RsGxsMessageId& parentId, - std::vector& childPosts ) -{ - RS_DBG3("forumId: ", forumId, " parentId: ", parentId); - - if(forumId.isNull() || parentId.isNull()) - return std::errc::invalid_argument; - - std::vector msgIds; - msgIds.push_back(RsGxsGrpMsgIdPair(forumId, parentId)); - - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA; - opts.mOptions = RS_TOKREQOPT_MSG_PARENT | RS_TOKREQOPT_MSG_LATEST; - - uint32_t token; - if( !requestMsgRelatedInfo(token, opts, msgIds) || - waitToken(token) != RsTokenService::COMPLETE ) - return std::errc::timed_out; - - GxsMsgRelatedDataMap msgData; - if(!getMsgRelatedData(token, msgData)) - return std::errc::no_message_available; - - for(auto& mit: msgData) - { - for(auto& vit: mit.second) - { - auto msgItem = dynamic_cast(vit); - if(msgItem) - { - RsGxsForumMsg post = msgItem->mMsg; - post.mMeta = msgItem->meta; - childPosts.push_back(post); - } - else RS_WARN("Got item of unexpected type: ", vit); - - delete vit; - } - } - - return std::error_condition(); -} - -bool p3GxsForums::createGroup(uint32_t &token, RsGxsForumGroup &group) -{ - std::cerr << "p3GxsForums::createGroup()" << std::endl; - - RsGxsForumGroupItem* grpItem = new RsGxsForumGroupItem(); - grpItem->mGroup = group; - grpItem->meta = group.mMeta; - - RsGenExchange::publishGroup(token, grpItem); - return true; -} - -bool p3GxsForums::getForumServiceStatistics(GxsServiceStatistic& stat) -{ - uint32_t token; - if(!RsGxsIfaceHelper::requestServiceStatistic(token) || waitToken(token) != RsTokenService::COMPLETE) - return false; - - return RsGenExchange::getServiceStatistic(token,stat); -} - -bool p3GxsForums::getForumStatistics(const RsGxsGroupId& ForumId,GxsGroupStatistic& stat) -{ - uint32_t token; - if(!RsGxsIfaceHelper::requestGroupStatistic(token, ForumId) || waitToken(token) != RsTokenService::COMPLETE) - return false; - - return RsGenExchange::getGroupStatistic(token,stat); -} - -bool p3GxsForums::updateGroup(uint32_t &token, const RsGxsForumGroup &group) -{ - std::cerr << "p3GxsForums::updateGroup()" << std::endl; - - - if(group.mMeta.mGroupId.isNull()) - return false; - - RsGxsForumGroupItem* grpItem = new RsGxsForumGroupItem(); - grpItem->mGroup = group; - grpItem->meta = group.mMeta; - - RsGenExchange::updateGroup(token, grpItem); - return true; -} - -bool p3GxsForums::createMessage(RsGxsForumMsg& message) -{ - uint32_t token; - if( !createMsg(token, message) - || waitToken(token,std::chrono::milliseconds(5000)) != RsTokenService::COMPLETE ) return false; - - if(RsGenExchange::getPublishedMsgMeta(token, message.mMeta)) return true; - - return false; -} - -bool p3GxsForums::createMsg(uint32_t &token, RsGxsForumMsg &msg) -{ - std::cerr << "p3GxsForums::createForumMsg() GroupId: " << msg.mMeta.mGroupId; - std::cerr << std::endl; - - RsGxsForumMsgItem* msgItem = new RsGxsForumMsgItem(); - msgItem->mMsg = msg; - msgItem->meta = msg.mMeta; - - RsGenExchange::publishMsg(token, msgItem); - return true; -} - - -/********************************************************************************************/ -/********************************************************************************************/ - -void p3GxsForums::setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) -{ - uint32_t mask = GXS_SERV::GXS_MSG_STATUS_GUI_NEW | GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; - uint32_t status = GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; - if (read) - status = 0; - - setMsgStatusFlags(token, msgId, status, mask); - - /* WARNING: The event may be received before the operation is completed! - * TODO: move notification to blocking method markRead(...) which wait the - * operation to complete */ - if (rsEvents) - { - auto ev = std::make_shared(); - - ev->mForumMsgId = msgId.second; - ev->mForumGroupId = msgId.first; - ev->mForumEventCode = RsForumEventCode::READ_STATUS_CHANGED; - rsEvents->postEvent(ev); - } -} - -/********************************************************************************************/ -/********************************************************************************************/ - -std::error_condition p3GxsForums::setPostKeepForever( - const RsGxsGroupId& forumId, const RsGxsMessageId& postId, - bool keepForever ) -{ - if(forumId.isNull() || postId.isNull()) return std::errc::invalid_argument; - - uint32_t mask = GXS_SERV::GXS_MSG_STATUS_KEEP_FOREVER; - uint32_t status = keepForever ? GXS_SERV::GXS_MSG_STATUS_KEEP_FOREVER : 0; - - uint32_t token; - setMsgStatusFlags(token, RsGxsGrpMsgIdPair(forumId, postId), status, mask); - - switch(waitToken(token)) - { - case RsTokenService::PENDING: // [[fallthrough]]; - case RsTokenService::PARTIAL: return std::errc::timed_out; - case RsTokenService::COMPLETE: // [[fallthrough]]; - case RsTokenService::DONE: - { - auto ev = std::make_shared(); - ev->mForumGroupId = forumId; - ev->mForumMsgId = postId; - ev->mForumEventCode = RsForumEventCode::UPDATED_MESSAGE; - rsEvents->postEvent(ev); - return std::error_condition(); - } - case RsTokenService::CANCELLED: return std::errc::operation_canceled; - default: return std::errc::bad_message; - } -} - -std::error_condition p3GxsForums::requestSynchronization() -{ - auto errc = RsGenExchange::netService()->checkUpdatesFromPeers(); - if(errc) return errc; - return RsGenExchange::netService()->requestPull(); -} - -/* so we need the same tick idea as wiki for generating dummy forums - */ - -#define MAX_GEN_GROUPS 5 -#define MAX_GEN_MESSAGES 100 - -std::string p3GxsForums::genRandomId() -{ - std::string randomId; - for(int i = 0; i < 20; i++) - { - randomId += (char) ('a' + (RSRandom::random_u32() % 26)); - } - - return randomId; -} - -bool p3GxsForums::generateDummyData() -{ - mGenCount = 0; - mGenRefs.resize(MAX_GEN_MESSAGES); - - std::string groupName; - rs_sprintf(groupName, "TestForum_%d", mGenCount); - - std::cerr << "p3GxsForums::generateDummyData() Starting off with Group: " << groupName; - std::cerr << std::endl; - - /* create a new group */ - generateGroup(mGenToken, groupName); - - mGenActive = true; - - return true; -} - - -void p3GxsForums::dummy_tick() -{ - /* check for a new callback */ - - if (mGenActive) - { - std::cerr << "p3GxsForums::dummyTick() AboutActive"; - std::cerr << std::endl; - - uint32_t status = RsGenExchange::getTokenService()->requestStatus(mGenToken); - if (status != RsTokenService::COMPLETE) - { - std::cerr << "p3GxsForums::dummy_tick() Status: " << status; - std::cerr << std::endl; - - if (status == RsTokenService::FAILED) - { - std::cerr << "p3GxsForums::dummy_tick() generateDummyMsgs() FAILED"; - std::cerr << std::endl; - mGenActive = false; - } - return; - } - - if (mGenCount < MAX_GEN_GROUPS) - { - /* get the group Id */ - RsGxsGroupId groupId; - RsGxsMessageId emptyId; - if (!acknowledgeTokenGrp(mGenToken, groupId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mGenActive = false; - return; - } - - std::cerr << "p3GxsForums::dummy_tick() Acknowledged GroupId: " << groupId; - std::cerr << std::endl; - - ForumDummyRef ref(groupId, emptyId, emptyId); - mGenRefs[mGenCount] = ref; - } - else if (mGenCount < MAX_GEN_MESSAGES) - { - /* get the msg Id, and generate next snapshot */ - RsGxsGrpMsgIdPair msgId; - if (!acknowledgeTokenMsg(mGenToken, msgId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mGenActive = false; - return; - } - - std::cerr << "p3GxsForums::dummy_tick() Acknowledged "; - std::cerr << std::endl; - - /* store results for later selection */ - - ForumDummyRef ref(msgId.first, mGenThreadId, msgId.second); - mGenRefs[mGenCount] = ref; - } - else - { - std::cerr << "p3GxsForums::dummy_tick() Finished"; - std::cerr << std::endl; - - /* done */ - mGenActive = false; - return; - } - - mGenCount++; - - if (mGenCount < MAX_GEN_GROUPS) - { - std::string groupName; - rs_sprintf(groupName, "TestForum_%d", mGenCount); - - std::cerr << "p3GxsForums::dummy_tick() Generating Group: " << groupName; - std::cerr << std::endl; - - /* create a new group */ - generateGroup(mGenToken, groupName); - } - else - { - /* create a new message */ - uint32_t idx = (uint32_t) (mGenCount * RSRandom::random_f32()); - ForumDummyRef &ref = mGenRefs[idx]; - - RsGxsGroupId grpId = ref.mGroupId; - RsGxsMessageId parentId = ref.mMsgId; - mGenThreadId = ref.mThreadId; - if (mGenThreadId.isNull()) - { - mGenThreadId = parentId; - } - - std::cerr << "p3GxsForums::dummy_tick() Generating Msg ... "; - std::cerr << " GroupId: " << grpId; - std::cerr << " ThreadId: " << mGenThreadId; - std::cerr << " ParentId: " << parentId; - std::cerr << std::endl; - - generateMessage(mGenToken, grpId, parentId, mGenThreadId); - } - } -} - - -bool p3GxsForums::generateMessage(uint32_t &token, const RsGxsGroupId &grpId, const RsGxsMessageId &parentId, const RsGxsMessageId &threadId) -{ - RsGxsForumMsg msg; - - std::string rndId = genRandomId(); - - rs_sprintf(msg.mMsg, "Forum Msg: GroupId: %s, ThreadId: %s, ParentId: %s + some randomness: %s", - grpId.toStdString().c_str(), threadId.toStdString().c_str(), parentId.toStdString().c_str(), rndId.c_str()); - - msg.mMeta.mMsgName = msg.mMsg; - - msg.mMeta.mGroupId = grpId; - msg.mMeta.mThreadId = threadId; - msg.mMeta.mParentId = parentId; - - msg.mMeta.mMsgStatus = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - - /* chose a random Id to sign with */ - std::list ownIds; - std::list::iterator it; - - rsIdentity->getOwnIds(ownIds); - - uint32_t idx = (uint32_t) (ownIds.size() * RSRandom::random_f32()); - uint32_t i = 0; - for(it = ownIds.begin(); (it != ownIds.end()) && (i < idx); ++it, i++) ; - - if (it != ownIds.end()) - { - std::cerr << "p3GxsForums::generateMessage() Author: " << *it; - std::cerr << std::endl; - msg.mMeta.mAuthorId = *it; - } - else - { - std::cerr << "p3GxsForums::generateMessage() No Author!"; - std::cerr << std::endl; - } - - createMsg(token, msg); - - return true; -} - - -bool p3GxsForums::generateGroup(uint32_t &token, std::string groupName) -{ - /* generate a new forum */ - RsGxsForumGroup forum; - forum.mMeta.mGroupName = groupName; - - createGroup(token, forum); - - return true; -} - - - // Overloaded from RsTickEvent for Event callbacks. -void p3GxsForums::handle_event(uint32_t event_type, const std::string &/*elabel*/) -{ - std::cerr << "p3GxsForums::handle_event(" << event_type << ")"; - std::cerr << std::endl; - - // stuff. - switch(event_type) - { - case FORUM_TESTEVENT_DUMMYDATA: - generateDummyData(); - break; - - default: - /* error */ - std::cerr << "p3GxsForums::handle_event() Unknown Event Type: " << event_type; - std::cerr << std::endl; - break; - } -} - -void RsGxsForumGroup::serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - RS_SERIAL_PROCESS(mMeta); - RS_SERIAL_PROCESS(mDescription); - - /* Work around to have usable JSON API, without breaking binary - * serialization retrocompatibility */ - switch (j) - { - case RsGenericSerializer::TO_JSON: // fallthrough - case RsGenericSerializer::FROM_JSON: - RsTypeSerializer::serial_process( j, ctx, - mAdminList.ids, "mAdminList" ); - RsTypeSerializer::serial_process( j, ctx, - mPinnedPosts.ids, "mPinnedPosts" ); - break; - default: - RS_SERIAL_PROCESS(mAdminList); - RS_SERIAL_PROCESS(mPinnedPosts); - } -} - -bool RsGxsForumGroup::canEditPosts(const RsGxsId& id) const -{ - return mAdminList.ids.find(id) != mAdminList.ids.end() || - id == mMeta.mAuthorId; -} - -std::error_condition p3GxsForums::getContentSummaries( - const RsGxsGroupId& forumId, - const std::set& contentIds, - std::vector& summaries ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_META; - - GxsMsgReq msgReq; - msgReq[forumId] = contentIds; - - - if(!requestMsgInfo(token, opts, msgReq)) - { - RS_ERR("requestMsgInfo failed"); - return std::errc::invalid_argument; - } - - switch(waitToken(token, std::chrono::seconds(5))) - { - case RsTokenService::COMPLETE: - { - GxsMsgMetaMap metaMap; - if(!RsGenExchange::getMsgMeta(token, metaMap)) - return std::errc::result_out_of_range; - summaries = metaMap[forumId]; - return std::error_condition(); - } - case RsTokenService::PARTIAL: // [[fallthrough]]; - case RsTokenService::PENDING: - return std::errc::timed_out; - default: - return std::errc::not_supported; - } -} - -#ifdef RS_DEEP_FORUMS_INDEX -std::error_condition p3GxsForums::handleDistantSearchRequest( - rs_view_ptr requestData, uint32_t requestSize, - rs_owner_ptr& resultData, uint32_t& resultSize ) -{ - RS_DBG1(""); - - RsGxsForumsSearchRequest request; - { - RsGenericSerializer::SerializeContext ctx(requestData, requestSize); - RsGenericSerializer::SerializeJob j = - RsGenericSerializer::SerializeJob::DESERIALIZE; - RS_SERIAL_PROCESS(request); - } - - if(request.mType != RsGxsForumsItems::SEARCH_REQUEST) - { - // If more types are implemented we would put a switch on mType instead - RS_WARN( "Got search request with unkown type: ", - static_cast(request.mType) ); - return std::errc::bad_message; - } - - RsGxsForumsSearchReply reply; - auto mErr = prepareSearchResults(request.mQuery, true, reply.mResults); - if(mErr || reply.mResults.empty()) return mErr; - - { - RsGenericSerializer::SerializeContext ctx; - RsGenericSerializer::SerializeJob j = - RsGenericSerializer::SerializeJob::SIZE_ESTIMATE; - RS_SERIAL_PROCESS(reply); - resultSize = ctx.mOffset; - } - - resultData = rs_malloc(resultSize); - RsGenericSerializer::SerializeContext ctx(resultData, resultSize); - RsGenericSerializer::SerializeJob j = - RsGenericSerializer::SerializeJob::SERIALIZE; - RS_SERIAL_PROCESS(reply); - - return std::error_condition(); -} - -std::error_condition p3GxsForums::distantSearchRequest( - const std::string& matchString, TurtleRequestId& searchId ) -{ - RsGxsForumsSearchRequest request; - request.mQuery = matchString; - - uint32_t requestSize; - { - RsGenericSerializer::SerializeContext ctx; - RsGenericSerializer::SerializeJob j = - RsGenericSerializer::SerializeJob::SIZE_ESTIMATE; - RS_SERIAL_PROCESS(request); - requestSize = ctx.mOffset; - } - - std::error_condition ec; - auto requestData = rs_malloc(requestSize, &ec); - if(!requestData) return ec; - { - RsGenericSerializer::SerializeContext ctx(requestData, requestSize); - RsGenericSerializer::SerializeJob j = - RsGenericSerializer::SerializeJob::SERIALIZE; - RS_SERIAL_PROCESS(request); - } - - return netService()->distantSearchRequest( - requestData, requestSize, - static_cast(serviceType()), searchId ); -} - -std::error_condition p3GxsForums::localSearch( - const std::string& matchString, - std::vector& searchResults ) -{ return prepareSearchResults(matchString, false, searchResults); } - -std::error_condition p3GxsForums::prepareSearchResults( - const std::string& matchString, bool publicOnly, - std::vector& searchResults ) -{ - std::vector results; - auto mErr = mDeepIndex.search(matchString, results); - if(mErr) return mErr; - - searchResults.clear(); - for(auto uRes: results) - { - RsUrl resUrl(uRes.mUrl); - const auto forumIdStr = resUrl.getQueryV(RsGxsForums::FORUM_URL_ID_FIELD); - if(!forumIdStr) - { - RS_ERR( "Forum URL retrieved from deep index miss ID. ", - "Should never happen! ", uRes.mUrl ); - print_stacktrace(); - return std::errc::address_not_available; - } - - std::vector forumsInfo; - RsGxsGroupId forumId(*forumIdStr); - if(forumId.isNull()) - { - RS_ERR( "Forum ID retrieved from deep index is invalid. ", - "Should never happen! ", uRes.mUrl ); - print_stacktrace(); - return std::errc::bad_address; - } - - if( !getForumsInfo(std::list{forumId}, forumsInfo) || - forumsInfo.empty() ) - { - RS_ERR( "Forum just parsed from deep index link not found. " - "Should never happen! ", forumId, " ", uRes.mUrl ); - print_stacktrace(); - return std::errc::identifier_removed; - } - - RsGroupMetaData& fMeta(forumsInfo[0].mMeta); - - // Avoid leaking sensitive information to unkown peers - if( publicOnly && - ( static_cast(fMeta.mCircleType) != - RsGxsCircleType::PUBLIC ) ) continue; - - RsGxsSearchResult res; - res.mGroupId = forumId; - res.mGroupName = fMeta.mGroupName; - res.mAuthorId = fMeta.mAuthorId; - res.mPublishTs = fMeta.mPublishTs; - res.mSearchContext = uRes.mSnippet; - - auto postIdStr = - resUrl.getQueryV(RsGxsForums::FORUM_URL_MSG_ID_FIELD); - if(postIdStr) - { - RsGxsMessageId msgId(*postIdStr); - if(msgId.isNull()) - { - RS_ERR( "Post just parsed from deep index link is invalid. " - "Should never happen! ", postIdStr, " ", uRes.mUrl ); - print_stacktrace(); - return std::errc::bad_address; - } - - std::vector msgSummaries; - auto errc = getContentSummaries( - forumId, std::set{msgId}, msgSummaries); - if(errc) return errc; - - if(msgSummaries.size() != 1) - { - RS_ERR( "getContentSummaries returned: ", msgSummaries.size(), - "should never happen!" ); - return std::errc::result_out_of_range; - } - - RsMsgMetaData& msgMeta(msgSummaries[0]); - res.mMsgId = msgMeta.mMsgId; - res.mMsgName = msgMeta.mMsgName; - res.mAuthorId = msgMeta.mAuthorId; - } - - RS_DBG4(res); - searchResults.push_back(res); - } - - return std::error_condition(); -} - -std::error_condition p3GxsForums::receiveDistantSearchResult( - const TurtleRequestId requestId, - rs_owner_ptr& resultData, uint32_t& resultSize ) -{ - RsGxsForumsSearchReply reply; - { - RsGenericSerializer::SerializeContext ctx(resultData, resultSize); - RsGenericSerializer::SerializeJob j = - RsGenericSerializer::SerializeJob::DESERIALIZE; - RS_SERIAL_PROCESS(reply); - } - free(resultData); - - if(reply.mType != RsGxsForumsItems::SEARCH_REPLY) - { - // If more types are implemented we would put a switch on mType instead - RS_WARN( "Got search request with unkown type: ", - static_cast(reply.mType) ); - return std::errc::bad_message; - } - - auto event = std::make_shared(); - event->mSearchId = requestId; - event->mSearchResults = reply.mResults; - rsEvents->postEvent(event); - return std::error_condition(); -} - -#else // def RS_DEEP_FORUMS_INDEX - -std::error_condition p3GxsForums::distantSearchRequest( - const std::string&, TurtleRequestId& ) -{ return std::errc::function_not_supported; } - -std::error_condition p3GxsForums::localSearch( - const std::string&, - std::vector& ) -{ return std::errc::function_not_supported; } - -#endif // def RS_DEEP_FORUMS_INDEX - -/*static*/ const std::string RsGxsForums::DEFAULT_FORUM_BASE_URL = - "retroshare:///forums"; -/*static*/ const std::string RsGxsForums::FORUM_URL_NAME_FIELD = - "forumName"; -/*static*/ const std::string RsGxsForums::FORUM_URL_ID_FIELD = - "forumId"; -/*static*/ const std::string RsGxsForums::FORUM_URL_DATA_FIELD = - "forumData"; -/*static*/ const std::string RsGxsForums::FORUM_URL_MSG_TITLE_FIELD = - "forumMsgTitle"; -/*static*/ const std::string RsGxsForums::FORUM_URL_MSG_ID_FIELD = - "forumMsgId"; - -RsGxsForumGroup::~RsGxsForumGroup() = default; -RsGxsForumMsg::~RsGxsForumMsg() = default; -RsGxsForums::~RsGxsForums() = default; -RsGxsForumEvent::~RsGxsForumEvent() = default; diff --git a/libretroshare/src/services/p3gxsforums.h b/libretroshare/src/services/p3gxsforums.h deleted file mode 100644 index 9400de652..000000000 --- a/libretroshare/src/services/p3gxsforums.h +++ /dev/null @@ -1,240 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3gxsforums.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012-2014 Robert Fernie * - * Copyright (C) 2018-2021 Gioacchino Mazzurco * - * Copyright (C) 2019-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include - -#include "retroshare/rsgxsforums.h" -#include "gxs/rsgenexchange.h" -#include "retroshare/rsgxscircles.h" -#include "util/rstickevent.h" -#include "util/rsdebug.h" - -#ifdef RS_DEEP_FORUMS_INDEX -#include "deep_search/forumsindex.hpp" -#endif - - -class p3GxsForums: public RsGenExchange, public RsGxsForums, public p3Config, - public RsTickEvent /* only needed for testing - remove after */ -{ -public: - p3GxsForums( - RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs* gixs); - - virtual RsServiceInfo getServiceInfo() override; - virtual void service_tick() override; - -protected: - virtual void notifyChanges(std::vector& changes) override; - /// Overloaded from RsTickEvent. - virtual void handle_event(uint32_t event_type, const std::string &elabel) override; - - virtual RsSerialiser* setupSerialiser() override; // @see p3Config::setupSerialiser() - virtual bool saveList(bool &cleanup, std::list&saveList) override; // @see p3Config::saveList(bool &cleanup, std::list&) - virtual bool loadList(std::list& loadList) override; // @see p3Config::loadList(std::list&) - - virtual bool service_checkIfGroupIsStillUsed(const RsGxsGrpMetaData& meta) override; - virtual rstime_t service_getLastGroupSeenTs(const RsGxsGroupId&) override; -public: - /// @see RsGxsForums::createForumV2 - bool createForumV2( - const std::string& name, const std::string& description, - const RsGxsId& authorId = RsGxsId(), - const std::set& moderatorsIds = std::set(), - RsGxsCircleType circleType = RsGxsCircleType::PUBLIC, - const RsGxsCircleId& circleId = RsGxsCircleId(), - RsGxsGroupId& forumId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId), - std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - /// @see RsGxsForums::createPost - bool createPost( - const RsGxsGroupId& forumId, - const std::string& title, - const std::string& mBody, - const RsGxsId& authorId, - const RsGxsMessageId& parentId = RsGxsMessageId(), - const RsGxsMessageId& origPostId = RsGxsMessageId(), - RsGxsMessageId& postMsgId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId), - std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - /// @see RsGxsForums::createForum @deprecated - RS_DEPRECATED_FOR(createForumV2) - virtual bool createForum(RsGxsForumGroup& forum) override; - - /// @see RsGxsForums::createMessage @deprecated - RS_DEPRECATED_FOR(createPost) - virtual bool createMessage(RsGxsForumMsg& message) override; - - /// @see RsGxsForums::editForum - virtual bool editForum(RsGxsForumGroup& forum) override; - - /// @see RsGxsForums::getForumsSummaries - virtual bool getForumsSummaries(std::list& forums) override; - - /// @see RsGxsForums::getForumsInfo - virtual bool getForumsInfo( - const std::list& forumIds, - std::vector& forumsInfo ) override; - - /// Implementation of @see RsGxsForums::getForumStatistics - bool getForumStatistics(const RsGxsGroupId& ForumId,GxsGroupStatistic& stat) override; - - /// Implementation of @see RsGxsForums::getForumServiceStatistics - bool getForumServiceStatistics(GxsServiceStatistic& stat) override; - - /// @see RsGxsForums::getForumMsgMetaData - virtual bool getForumMsgMetaData(const RsGxsGroupId& forumId, std::vector& msg_metas) override; - - /// @see RsGxsForums::getForumContent - virtual bool getForumContent( - const RsGxsGroupId& forumId, - const std::set& msgs_to_request, - std::vector& msgs ) override; - - /// @see RsGxsForums::markRead - virtual bool markRead(const RsGxsGrpMsgIdPair& messageId, bool read) override; - - /// @see RsGxsForums::subscribeToForum - virtual bool subscribeToForum( const RsGxsGroupId& forumId, - bool subscribe ) override; - - /// @see RsGxsForums - bool exportForumLink( - std::string& link, const RsGxsGroupId& forumId, - bool includeGxsData = true, - const std::string& baseUrl = DEFAULT_FORUM_BASE_URL, - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - /// @see RsGxsForums - bool importForumLink( - const std::string& link, - RsGxsGroupId& forumId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId), - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - /// @see RsGxsForums - std::error_condition getChildPosts( - const RsGxsGroupId& forumId, const RsGxsMessageId& parentId, - std::vector& childPosts ) override; - - /// @see RsGxsForums - std::error_condition setPostKeepForever( - const RsGxsGroupId& forumId, const RsGxsMessageId& postId, - bool keepForever ) override; - - /// @see RsGxsForums - std::error_condition getContentSummaries( - const RsGxsGroupId& forumId, - const std::set& contentIds, - std::vector& summaries ) override; - - /// @see RsGxsForums - std::error_condition distantSearchRequest( - const std::string& matchString, TurtleRequestId& searchId ) override; - - /// @see RsGxsForums - std::error_condition localSearch( - const std::string& matchString, - std::vector& searchResults ) override; - -#ifdef RS_DEEP_FORUMS_INDEX - /// @see RsNxsObserver - std::error_condition handleDistantSearchRequest( - rs_view_ptr requestData, uint32_t requestSize, - rs_owner_ptr& resultData, uint32_t& resultSize ) override; - - /// @see RsNxsObserver - std::error_condition receiveDistantSearchResult( - const TurtleRequestId requestId, - rs_owner_ptr& resultData, uint32_t& resultSize ) override; -#endif - - std::error_condition requestSynchronization() override; - - /// implementation of rsGxsGorums - /// - bool getGroupData(const uint32_t &token, std::vector &groups) override; - bool getMsgData(const uint32_t &token, std::vector &msgs) override; - void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) override; - bool createGroup(uint32_t &token, RsGxsForumGroup &group) override; - bool createMsg(uint32_t &token, RsGxsForumMsg &msg) override; - bool updateGroup(uint32_t &token, const RsGxsForumGroup &group) override; - - bool getMsgMetaData(const uint32_t &token, GxsMsgMetaMap& msg_metas) ; - -protected: -#ifdef RS_DEEP_FORUMS_INDEX - /** Internal usage - * @param[in] publicOnly if true is passed only results pertaining to - * publicly shared forums are returned - */ - std::error_condition prepareSearchResults( - const std::string& matchString, bool publicOnly, - std::vector& searchResults ); -#endif //def RS_DEEP_FORUMS_INDEX - -private: - -static uint32_t forumsAuthenPolicy(); - -virtual bool generateDummyData(); - -std::string genRandomId(); - -void dummy_tick(); - -bool generateMessage(uint32_t &token, const RsGxsGroupId &grpId, - const RsGxsMessageId &parentId, const RsGxsMessageId &threadId); -bool generateGroup(uint32_t &token, std::string groupName); - - class ForumDummyRef - { - public: - ForumDummyRef() { return; } - ForumDummyRef(const RsGxsGroupId &grpId, const RsGxsMessageId &threadId, const RsGxsMessageId &msgId) - :mGroupId(grpId), mThreadId(threadId), mMsgId(msgId) { return; } - - RsGxsGroupId mGroupId; - RsGxsMessageId mThreadId; - RsGxsMessageId mMsgId; - }; - - uint32_t mGenToken; - bool mGenActive; - int mGenCount; - std::vector mGenRefs; - RsGxsMessageId mGenThreadId; - std::map mKnownForums ; - - RsMutex mKnownForumsMutex; - -#ifdef RS_DEEP_FORUMS_INDEX - DeepForumsIndex mDeepIndex; -#endif -}; diff --git a/libretroshare/src/services/p3gxsreputation.cc b/libretroshare/src/services/p3gxsreputation.cc deleted file mode 100644 index 4b7383a93..000000000 --- a/libretroshare/src/services/p3gxsreputation.cc +++ /dev/null @@ -1,1635 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3gxsreputation.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014-2014 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include -#include "pqi/p3linkmgr.h" - -#include "retroshare/rspeers.h" - -#include "services/p3gxsreputation.h" - -#include "rsitems/rsgxsreputationitems.h" -#include "rsitems/rsconfigitems.h" - -#include - -#include - -/**** - * #define DEBUG_REPUTATION 1 - ****/ - -/************ IMPLEMENTATION NOTES ********************************* - * - * p3GxsReputation shares opinions / reputations with peers. - * This is closely linked to p3IdService, receiving info, updating - * reputations as needed. - * - * It is designed as separate service as the exchange of peer opinions - * is not well suited to Gxs Groups / Messages... - * - * Instead we can broadcast opinions to all peers. - * - * To avoid too much traffic, changes are transmitted rather than whole lists. - * Peer A Peer B - * last update -----------> - * <----------- modified opinions. - * - * If not clever enough, this service will have to store a huge amount of data. - * To make things tractable we do this: - * - do not store reputations when no data is present, or when all friends are neutral - * - only send a neutral opinion when they are a true change over someone's opinion - * - only send a neutral opinion when it is a true change over someone's opinion - * - auto-clean reputations for default values - * - * std::map mReputations. - * std::multimap mUpdated. - * - * std::map mConfig; - * - * Updates from p3GxsReputation -> p3IdService. - * Updates from p3IdService -> p3GxsReputation. - * - * Each peer locally stores reputations for all GXS ids. If not stored, a default value - * is used, corresponding to a neutral opinion. Peers also share their reputation level - * with their neighbor nodes. - * - * The calculation method is the following: - * - * Local values: - * Good: 2 - * Neutral: 1 - * Bad: 0 - * - * Overall reputation score: - * - * if(own_opinion == 0) // means we dont' care - * r = average_of_friends_opinions - * else - * r = own_opinion - * - * Decisions based on reputation score: - * - * 0 x1 1 x2 2 - * | <-----------------------------------------------------------------------> | - * ---------+ - * Lobbies | Msgs dropped - * Forums | Msgs dropped - * Messages | Msgs dropped - * ---------+---------------------------------------------------------------------------- - * - * We select x1=0.5 - * - * => to kill an identity, either you, or at least 50% of your friends need to flag it - * as bad. - * Rules: - * * a single peer cannot drastically change the behavior of a given GXS id - * * it should be easy for many peers to globally kill a GXS id - * - * Typical examples: - * - * Friends | Friend average | Own | alpha | Score - * -----------+---------------------+----------+------------+-------------- - * 10 | 0.5 | 1 | 0.25 | 0.375 - * 10 | 1.0 | 1 | 0.25 | 1.0 - * 10 | 1.0 | 0 | 0.25 | 1.0 - * - * To check: - * [X] Opinions are saved/loaded accross restart - * [X] Opinions are transmitted to friends - * [X] Opinions are transmitted to friends when updated - * - * To do: - * [X] Add debug info - * [X] Test the whole thing - * [X] Implement a system to allow not storing info when we don't have it - */ - -//static const uint32_t LOWER_LIMIT = 0; // used to filter valid Opinion values from serialized data -static const uint32_t UPPER_LIMIT = 2; // used to filter valid Opinion values from serialized data -//static const int kMaximumPeerAge = 180; // half a year. -static const int kMaximumSetSize = 100; // max set of updates to send at once. -static const int CLEANUP_PERIOD = 600 ; // 10 minutes -//static const int ACTIVE_FRIENDS_ONLINE_DELAY = 86400*7 ; // 1 week. -static const int kReputationRequestPeriod = 600; // 10 mins -static const int kReputationStoreWait = 180; // 3 minutes. -//static const float REPUTATION_ASSESSMENT_THRESHOLD_X1 = 0.5f ; // reputation under which the peer gets killed. Warning there's a 1 shift with what's shown in GUI. Be careful. -//static const uint32_t PGP_AUTO_BAN_THRESHOLD_DEFAULT = 2 ; // above this, auto ban any GXS id signed by this node -static const uint32_t IDENTITY_FLAGS_UPDATE_DELAY = 100 ; // -static const uint32_t BANNED_NODES_UPDATE_DELAY = 313 ; // update approx every 5 mins. Chosen to not be a multiple of IDENTITY_FLAGS_UPDATE_DELAY -static const uint32_t REPUTATION_INFO_KEEP_DELAY_DEFAULT = 86400*35; // remove old reputation info 5 days after last usage limit, in case the ID would come back.. -static const uint32_t BANNED_NODES_INACTIVITY_KEEP_DEFAULT = 86400*60; // remove all info about banned nodes after 2 months of inactivity - -static const uint32_t REPUTATION_DEFAULT_MIN_VOTES_FOR_REMOTELY_POSITIVE = 1; // min difference in votes that makes friends opinion globally positive -static const uint32_t REPUTATION_DEFAULT_MIN_VOTES_FOR_REMOTELY_NEGATIVE = 1; // min difference in votes that makes friends opinion globally negative -static const uint32_t MIN_DELAY_BETWEEN_REPUTATION_CONFIG_SAVE = 61 ; // never save more often than once a minute. - -p3GxsReputation::p3GxsReputation(p3LinkMgr *lm) - :p3Service(), p3Config(), - mReputationMtx("p3GxsReputation"), mLinkMgr(lm) -{ - addSerialType(new RsGxsReputationSerialiser()); - - //mPgpAutoBanThreshold = PGP_AUTO_BAN_THRESHOLD_DEFAULT ; - mRequestTime = 0; - mStoreTime = 0; - mReputationsUpdated = false; - mLastIdentityFlagsUpdate = time(NULL) - 3; - mLastBannedNodesUpdate = 0 ; - mBannedNodesProxyNeedsUpdate = false; - - mAutoSetPositiveOptionToContacts = true; // default - mMinVotesForRemotelyPositive = REPUTATION_DEFAULT_MIN_VOTES_FOR_REMOTELY_POSITIVE; - mMinVotesForRemotelyNegative = REPUTATION_DEFAULT_MIN_VOTES_FOR_REMOTELY_NEGATIVE; - - mLastReputationConfigSaved = 0; - mChanged = false ; - mMaxPreventReloadBannedIds = 0 ; // default is "never" - mLastCleanUp = time(NULL) ; -} - -const std::string GXS_REPUTATION_APP_NAME = "gxsreputation"; -const uint16_t GXS_REPUTATION_APP_MAJOR_VERSION = 1; -const uint16_t GXS_REPUTATION_APP_MINOR_VERSION = 0; -const uint16_t GXS_REPUTATION_MIN_MAJOR_VERSION = 1; -const uint16_t GXS_REPUTATION_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3GxsReputation::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_GXS_TYPE_REPUTATION, - GXS_REPUTATION_APP_NAME, - GXS_REPUTATION_APP_MAJOR_VERSION, - GXS_REPUTATION_APP_MINOR_VERSION, - GXS_REPUTATION_MIN_MAJOR_VERSION, - GXS_REPUTATION_MIN_MINOR_VERSION); -} - -int p3GxsReputation::tick() -{ - processIncoming(); - sendPackets(); - - rstime_t now = time(NULL); - - if(mLastCleanUp + CLEANUP_PERIOD < now) - { - cleanup() ; - - mLastCleanUp = now ; - } - - // no more than once per 5 second chunk. - - if(now > IDENTITY_FLAGS_UPDATE_DELAY+mLastIdentityFlagsUpdate) - { - updateStaticIdentityFlags() ; - mLastIdentityFlagsUpdate = now ; - } - if(now > BANNED_NODES_UPDATE_DELAY+mLastBannedNodesUpdate) // 613 is not a multiple of 100, to avoid piling up work - { - updateStaticIdentityFlags() ; // needed before updateBannedNodesList! - updateBannedNodesProxy(); - mLastBannedNodesUpdate = now ; - } - - if(mBannedNodesProxyNeedsUpdate) - { - updateBannedNodesProxy(); - mBannedNodesProxyNeedsUpdate = false ; - } - -#ifdef DEBUG_REPUTATION - static rstime_t last_debug_print = time(NULL) ; - - if(now > 10+last_debug_print) - { - last_debug_print = now ; - debug_print() ; - } -#endif - - if(mChanged && now > mLastReputationConfigSaved + MIN_DELAY_BETWEEN_REPUTATION_CONFIG_SAVE) - { - IndicateConfigChanged() ; - mLastReputationConfigSaved = now ; - mChanged = false ; - } - - return 0; -} - -void p3GxsReputation::setAutoPositiveOpinionForContacts(bool b) -{ - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - if(b != mAutoSetPositiveOptionToContacts) - { - mLastIdentityFlagsUpdate = 0 ; - mLastCleanUp = 0 ; - mAutoSetPositiveOptionToContacts = b ; - - IndicateConfigChanged() ; - } -} -bool p3GxsReputation::autoPositiveOpinionForContacts() -{ - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - return mAutoSetPositiveOptionToContacts ; -} - -void p3GxsReputation::setRememberBannedIdThreshold(uint32_t days) -{ - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - if(mMaxPreventReloadBannedIds != days*86400) - { - mMaxPreventReloadBannedIds = days*86400 ; - IndicateConfigChanged(); - } -} -uint32_t p3GxsReputation::rememberBannedIdThreshold() -{ - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - return mMaxPreventReloadBannedIds/86400; -} - -int p3GxsReputation::status() -{ - return 1; -} -class ZeroInitCnt -{ - public: - ZeroInitCnt(): cnt(0) {} - uint32_t cnt ; - - operator uint32_t& () { return cnt ; } - operator uint32_t() const { return cnt ; } -}; - -void p3GxsReputation::updateBannedNodesProxy() -{ - // This function keeps the Banned GXS id proxy up to date. - // - - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - mPerNodeBannedIdsProxy.clear(); - - for( std::map::iterator rit = mBannedPgpIds.begin();rit!=mBannedPgpIds.end();++rit) - for(std::set::const_iterator it(rit->second.known_identities.begin());it!=rit->second.known_identities.end();++it) - mPerNodeBannedIdsProxy.insert(*it) ; -} - -void p3GxsReputation::updateStaticIdentityFlags() -{ - // This function is the *only* place where rsIdentity is called. Normally the cross calls between p3IdService and p3GxsReputations should only - // happen one way: from rsIdentity to rsReputations. Still, reputations need to keep track of some identity flags. It's very important to make sure that - // rsIdentity is not called inside a mutex-protected zone, because normally calls happen in the other way. - - std::list to_update ; - - // we need to gather the list to be used in a non locked frame - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - -#ifdef DEBUG_REPUTATION - std::cerr << "Updating reputation identity flags" << std::endl; -#endif - - for( std::map::iterator rit = mReputations.begin();rit!=mReputations.end();++rit) - { - if( (!(rit->second.mIdentityFlags & REPUTATION_IDENTITY_FLAG_UP_TO_DATE)) && (mPerNodeBannedIdsProxy.find(rit->first) == mPerNodeBannedIdsProxy.end())) - to_update.push_back(rit->first) ; - } - } - - for(std::list::const_iterator rit(to_update.begin());rit!=to_update.end();++rit) - { - RsIdentityDetails details; - - if(!rsIdentity->getIdDetails(*rit,details)) - { -#ifdef DEBUG_REPUTATION - std::cerr << " cannot obtain info for " << *rit << ". Will do it later." << std::endl; -#endif - continue ; - } - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - std::map::iterator it = mReputations.find(*rit) ; - - if(it == mReputations.end()) - { - std::cerr << " Weird situation: item " << *rit << " has been deleted from the list??" << std::endl; - continue ; - } - it->second.mIdentityFlags = REPUTATION_IDENTITY_FLAG_UP_TO_DATE ; // resets the NEEDS_UPDATE flag. All other flags set later on. - - if(details.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED) - { - it->second.mIdentityFlags |= REPUTATION_IDENTITY_FLAG_PGP_LINKED ; - it->second.mOwnerNode = details.mPgpId ; - } - if(details.mFlags & RS_IDENTITY_FLAGS_PGP_KNOWN ) it->second.mIdentityFlags |= REPUTATION_IDENTITY_FLAG_PGP_KNOWN ; - -#ifdef DEBUG_REPUTATION - std::cerr << " updated flags for " << *rit << " to " << std::hex << it->second.mIdentityFlags << std::dec << std::endl; -#endif - - it->second.updateReputation() ; - mChanged = true ; - } - } -} - -void p3GxsReputation::cleanup() -{ - // remove opinions from friends that havn't been seen online for more than the specified delay - -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::cleanup() " << std::endl; -#endif - rstime_t now = time(NULL) ; - - // We should keep opinions about identities that do not exist anymore, but only rely on the usage TS. That will in particular avoid asking p3idservice about deleted - // identities, which would cause an excess of hits to the database. We do it in two steps to avoid a deadlock when calling rsIdentity from here. - // Also, neutral opinions for banned PGP linked nodes are kept, so as to be able to not request them again. - - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - for(std::map::iterator it(mReputations.begin());it!=mReputations.end();) - { - bool should_delete = false ; - - if( it->second.mOwnOpinion == - static_cast(RsOpinion::NEGATIVE) && - mMaxPreventReloadBannedIds != 0 && - it->second.mOwnOpinionTs + mMaxPreventReloadBannedIds < now ) - { -#ifdef DEBUG_REPUTATION - std::cerr << " ID " << it->first << ": own is negative for more than " << mMaxPreventReloadBannedIds/86400 << " days. Reseting it!" << std::endl; -#endif - should_delete = true; - } - - // Delete slots with basically no information - - if( it->second.mOpinions.empty() && - it->second.mOwnOpinion == - static_cast(RsOpinion::NEUTRAL) && - it->second.mOwnerNode.isNull() ) - { -#ifdef DEBUG_REPUTATION - std::cerr << " ID " << it->first << ": own is neutral and no opinions from friends => remove entry" << std::endl; -#endif - should_delete = true ; - } - - // Delete slots that havn't been used for a while. The else below is here for debug display purposes, and not harmful since both conditions lead the same effect. - - else if(it->second.mLastUsedTS + REPUTATION_INFO_KEEP_DELAY_DEFAULT < now) - { -#ifdef DEBUG_REPUTATION - std::cerr << " ID " << it->first << ": no request for reputation for more than " << REPUTATION_INFO_KEEP_DELAY_DEFAULT/86400 << " days => deleting." << std::endl; -#endif - should_delete = true ; - } -#ifdef DEBUG_REPUTATION - else - std::cerr << " ID " << it->first << ": flags=" << std::hex << it->second.mIdentityFlags << std::dec << ". Last used: " << (now - it->second.mLastUsedTS)/86400 << " days ago: kept." << std::endl; -#endif - - if(should_delete) - { - std::map::iterator tmp(it) ; - ++tmp ; - mReputations.erase(it) ; - it = tmp ; - mChanged = true ; - } - else - ++it; - } - } - - // Clean up of the banned PGP ids. - - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - for(std::map::iterator it(mBannedPgpIds.begin());it!=mBannedPgpIds.end();) - if(it->second.last_activity_TS + BANNED_NODES_INACTIVITY_KEEP_DEFAULT < now) - { -#ifdef DEBUG_REPUTATION - std::cerr << " Removing all info about banned node " << it->first << " by lack of activity." << std::endl; -#endif - std::map::iterator tmp(it ) ; - ++tmp ; - mBannedPgpIds.erase(it) ; - it = tmp ; - - mChanged = true ; - } - else - ++it ; - } - - // Update opinions based on flags and contact information. - // Note: the call to rsIdentity->isARegularContact() is done off-mutex, in order to avoid a cross-deadlock, as - // normally, p3GxsReputation gets called by p3dentity and not te reverse. That explains the weird implementation - // of these two loops. - { - std::list should_set_to_positive_candidates ; - - if(mAutoSetPositiveOptionToContacts) - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - for(std::map::iterator it(mReputations.begin());it!=mReputations.end();++it) - if( it->second.mOwnOpinion == - static_cast(RsOpinion::NEUTRAL) ) - should_set_to_positive_candidates.push_back(it->first) ; - } - - for(std::list::const_iterator it(should_set_to_positive_candidates.begin());it!=should_set_to_positive_candidates.end();++it) - if(rsIdentity->isARegularContact(*it)) - setOwnOpinion(*it, RsOpinion::POSITIVE); - } -} - -static RsOpinion safe_convert_uint32t_to_opinion(uint32_t op) -{ - return RsOpinion(std::min( static_cast(op), UPPER_LIMIT )); -} -/***** Implementation ******/ - -bool p3GxsReputation::processIncoming() -{ - /* for each packet - pass to specific handler */ - RsItem *item = NULL; - while(NULL != (item = recvItem())) - { -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::processingIncoming() Received Item:"; - std::cerr << std::endl; - item->print(std::cerr); - std::cerr << std::endl; -#endif - bool itemOk = true; - switch(item->PacketSubType()) - { - default: - case RS_PKT_SUBTYPE_GXS_REPUTATION_CONFIG_ITEM: - case RS_PKT_SUBTYPE_GXS_REPUTATION_SET_ITEM: - std::cerr << "p3GxsReputation::processingIncoming() Unknown Item"; - std::cerr << std::endl; - itemOk = false; - break; - - case RS_PKT_SUBTYPE_GXS_REPUTATION_REQUEST_ITEM: - { - RsGxsReputationRequestItem *requestItem = dynamic_cast(item); - if (requestItem) - SendReputations(requestItem); - else - itemOk = false; - } - break; - - case RS_PKT_SUBTYPE_GXS_REPUTATION_UPDATE_ITEM: - { - RsGxsReputationUpdateItem *updateItem = dynamic_cast(item); - - if (updateItem) - RecvReputations(updateItem); - else - itemOk = false; - } - break; - } - - if (!itemOk) - { - std::cerr << "p3GxsReputation::processingIncoming() Error with Item"; - std::cerr << std::endl; - } - - /* clean up */ - delete item; - } - return true ; -} - - -bool p3GxsReputation::SendReputations(RsGxsReputationRequestItem *request) -{ -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::SendReputations()" << std::endl; -#endif - - RsPeerId peerId = request->PeerId(); - rstime_t last_update = request->mLastUpdate; - rstime_t now = time(NULL); - - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - std::multimap::iterator tit; - tit = mUpdated.upper_bound(last_update); // could skip some - (fixed below). - - int count = 0; - int totalcount = 0; - RsGxsReputationUpdateItem *pkt = new RsGxsReputationUpdateItem(); - - pkt->PeerId(peerId); - for(;tit != mUpdated.end(); ++tit) - { - /* find */ - std::map::iterator rit = mReputations.find(tit->second); - - if (rit == mReputations.end()) - { - std::cerr << "p3GxsReputation::SendReputations() ERROR Missing Reputation"; - std::cerr << std::endl; - // error. - continue; - } - - if (rit->second.mOwnOpinionTs == 0) - { - std::cerr << "p3GxsReputation::SendReputations() ERROR OwnOpinionTS = 0"; - std::cerr << std::endl; - // error. - continue; - } - - RsGxsId gxsId = rit->first; - pkt->mOpinions[gxsId] = rit->second.mOwnOpinion; - pkt->mLatestUpdate = rit->second.mOwnOpinionTs; - - if (pkt->mLatestUpdate == (uint32_t) now) - { - // if we could possibly get another Update at this point (same second). - // then set Update back one second to ensure there are none missed. - pkt->mLatestUpdate--; - } - - count++; - totalcount++; - - if (count > kMaximumSetSize) - { -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::SendReputations() Sending Full Packet"; - std::cerr << std::endl; -#endif - - sendItem(pkt); - - pkt = new RsGxsReputationUpdateItem(); - pkt->PeerId(peerId); - count = 0; - } - } - - if (!pkt->mOpinions.empty()) - { -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::SendReputations() Sending Final Packet"; - std::cerr << std::endl; -#endif - - sendItem(pkt); - } - else - { - delete pkt; - } - -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::SendReputations() Total Count: " << totalcount; - std::cerr << std::endl; -#endif - - return true; -} - -void p3GxsReputation::locked_updateOpinion( - const RsPeerId& from, const RsGxsId& about, RsOpinion op ) -{ - /* find matching Reputation */ - std::map::iterator rit = mReputations.find(about); - - RsOpinion new_opinion = op; - RsOpinion old_opinion = RsOpinion::NEUTRAL ; // default if not set - - bool updated = false ; - -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::update opinion of " << about << " from " << from << " to " << op << std::endl; -#endif - // now 4 cases; - // Opinion already stored - // New opinion is same: nothing to do - // New opinion is different: if neutral, remove entry - // Nothing stored - // New opinion is neutral: nothing to do - // New opinion is != 1: create entry and store - - if (rit == mReputations.end()) - { -#ifdef DEBUG_REPUTATION - std::cerr << " no preview record"<< std::endl; -#endif - - if(new_opinion != RsOpinion::NEUTRAL) - { - mReputations[about] = Reputation(); - rit = mReputations.find(about); - } - else - { -#ifdef DEBUG_REPUTATION - std::cerr << " no changes!"<< std::endl; -#endif - return ; // nothing to do - } - } - - Reputation& reputation = rit->second; - - std::map::iterator it2 = reputation.mOpinions.find(from) ; - - if(it2 == reputation.mOpinions.end()) - { - if(new_opinion != RsOpinion::NEUTRAL) - { - reputation.mOpinions[from] = new_opinion; // filters potentially tweaked reputation score sent by friend - updated = true ; - } - } - else - { - old_opinion = it2->second ; - - if(new_opinion == RsOpinion::NEUTRAL) - { - reputation.mOpinions.erase(it2) ; // don't store when the opinion is neutral - updated = true ; - } - else if(new_opinion != old_opinion) - { - it2->second = new_opinion ; - updated = true ; - } - } - - if( reputation.mOpinions.empty() && - reputation.mOwnOpinion == static_cast(RsOpinion::NEUTRAL) ) - { - mReputations.erase(rit) ; -#ifdef DEBUG_REPUTATION - std::cerr << " own is neutral and no opinions from friends => remove entry" << std::endl; -#endif - updated = true ; - } - else if(updated) - { -#ifdef DEBUG_REPUTATION - std::cerr << " reputation changed. re-calculating." << std::endl; -#endif - reputation.updateReputation() ; - } - - if(updated) - IndicateConfigChanged() ; -} - -bool p3GxsReputation::RecvReputations(RsGxsReputationUpdateItem *item) -{ -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::RecvReputations() from " << item->PeerId() << std::endl; -#endif - - RsPeerId peerid = item->PeerId(); - - for( std::map::iterator it = item->mOpinions.begin(); it != item->mOpinions.end(); ++it) - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - locked_updateOpinion(peerid,it->first,safe_convert_uint32t_to_opinion(it->second)); - } - - updateLatestUpdate(peerid,item->mLatestUpdate); - - return true; -} - - -bool p3GxsReputation::updateLatestUpdate(RsPeerId peerid,rstime_t latest_update) -{ - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - std::map::iterator it = mConfig.find(peerid); - - if (it == mConfig.end()) - { - mConfig[peerid] = ReputationConfig(peerid); - it = mConfig.find(peerid) ; - } - it->second.mLatestUpdate = latest_update ; - - mReputationsUpdated = true; - // Switched to periodic save due to scale of data. - - IndicateConfigChanged(); - - return true; -} - -/******************************************************************** - * Opinion - ****/ - -RsReputationLevel p3GxsReputation::overallReputationLevel( - const RsGxsId& id, uint32_t* identity_flags ) -{ - RsReputationInfo info ; - getReputationInfo(id,RsPgpId(),info) ; - - RsPgpId owner_id ; - - if(identity_flags) - getIdentityFlagsAndOwnerId(id,*identity_flags,owner_id); - - return info.mOverallReputationLevel ; -} - -bool p3GxsReputation::getIdentityFlagsAndOwnerId(const RsGxsId& gxsid, uint32_t& identity_flags,RsPgpId& owner_id) -{ - if(gxsid.isNull()) - return false ; - - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - std::map::iterator it = mReputations.find(gxsid) ; - - if(it == mReputations.end()) - return false ; - - if(!(it->second.mIdentityFlags & REPUTATION_IDENTITY_FLAG_UP_TO_DATE)) - return false ; - - if(it->second.mIdentityFlags & REPUTATION_IDENTITY_FLAG_PGP_LINKED) - identity_flags |= RS_IDENTITY_FLAGS_PGP_LINKED ; - - if(it->second.mIdentityFlags & REPUTATION_IDENTITY_FLAG_PGP_KNOWN) - identity_flags |= RS_IDENTITY_FLAGS_PGP_KNOWN ; - - owner_id = it->second.mOwnerNode ; - - return true ; -} - -bool p3GxsReputation::getReputationInfo( - const RsGxsId& gxsid, const RsPgpId& ownerNode, RsReputationInfo& info, - bool stamp ) -{ - if(gxsid.isNull()) - return false ; - - rstime_t now = time(nullptr); - - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - -#ifdef DEBUG_REPUTATION2 - std::cerr << "getReputationInfo() for " << gxsid << ", stamp = " << stamp << std::endl; -#endif - std::map::iterator it = mReputations.find(gxsid) ; - RsPgpId owner_id ; - - if(it == mReputations.end()) - { - info.mOwnOpinion = RsOpinion::NEUTRAL ; - info.mFriendAverageScore = RS_REPUTATION_THRESHOLD_DEFAULT ; - info.mFriendsNegativeVotes = 0 ; - info.mFriendsPositiveVotes = 0 ; - - owner_id = ownerNode ; - } - else - { - Reputation& rep(it->second) ; - - info.mOwnOpinion = - safe_convert_uint32t_to_opinion( - static_cast(rep.mOwnOpinion) ); - info.mFriendAverageScore = rep.mFriendAverage ; - info.mFriendsNegativeVotes = rep.mFriendsNegative ; - info.mFriendsPositiveVotes = rep.mFriendsPositive ; - - if(rep.mOwnerNode.isNull() && !ownerNode.isNull()) - rep.mOwnerNode = ownerNode ; - - owner_id = rep.mOwnerNode ; - - if(stamp) - rep.mLastUsedTS = now ; - - mChanged = true ; - } - - // now compute overall score and reputation - - // 0 - check for own opinion. If positive or negative, it decides on the result - - if(info.mOwnOpinion == RsOpinion::NEGATIVE) - { - // own opinion is always read in priority - - info.mOverallReputationLevel = RsReputationLevel::LOCALLY_NEGATIVE; - return true ; - } - if(info.mOwnOpinion == RsOpinion::POSITIVE) - { - // own opinion is always read in priority - - info.mOverallReputationLevel = RsReputationLevel::LOCALLY_POSITIVE; - return true ; - } - - // 1 - check for banned PGP ids. - - std::map::iterator it2 ; - - if(!owner_id.isNull() && (it2 = mBannedPgpIds.find(owner_id))!=mBannedPgpIds.end()) - { - // Check if current identity is present in the list of known identities for this banned node. - - if(it2->second.known_identities.find(gxsid) == it2->second.known_identities.end()) - { - it2->second.known_identities.insert(gxsid) ; - it2->second.last_activity_TS = now ; - - // if so, update - - mBannedNodesProxyNeedsUpdate = true ; - } - -#ifdef DEBUG_REPUTATION2 - std::cerr << "p3GxsReputations: identity " << gxsid << " is banned because owner node ID " << owner_id << " is banned (found in banned nodes list)." << std::endl; -#endif - info.mOverallReputationLevel = RsReputationLevel::LOCALLY_NEGATIVE; - return true ; - } - // also check the proxy - - if(mPerNodeBannedIdsProxy.find(gxsid) != mPerNodeBannedIdsProxy.end()) - { -#ifdef DEBUG_REPUTATION2 - std::cerr << "p3GxsReputations: identity " << gxsid << " is banned because owner node ID " << owner_id << " is banned (found in proxy)." << std::endl; -#endif - info.mOverallReputationLevel = RsReputationLevel::LOCALLY_NEGATIVE; - return true; - } - // 2 - now, our own opinion is neutral, which means we rely on what our friends tell - - if(info.mFriendsPositiveVotes >= info.mFriendsNegativeVotes + mMinVotesForRemotelyPositive) - info.mOverallReputationLevel = RsReputationLevel::REMOTELY_POSITIVE; - else if(info.mFriendsPositiveVotes + mMinVotesForRemotelyNegative <= info.mFriendsNegativeVotes) - info.mOverallReputationLevel = RsReputationLevel::REMOTELY_NEGATIVE; - else - info.mOverallReputationLevel = RsReputationLevel::NEUTRAL; - -#ifdef DEBUG_REPUTATION2 - std::cerr << " information present. OwnOp = " << info.mOwnOpinion << ", owner node=" << owner_id << ", overall score=" << info.mAssessment << std::endl; -#endif - - return true ; -} - -uint32_t p3GxsReputation::thresholdForRemotelyNegativeReputation() -{ - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - return mMinVotesForRemotelyNegative ; -} -uint32_t p3GxsReputation::thresholdForRemotelyPositiveReputation() -{ - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - return mMinVotesForRemotelyPositive ; -} -void p3GxsReputation::setThresholdForRemotelyPositiveReputation(uint32_t thresh) -{ - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - if(mMinVotesForRemotelyPositive == thresh || thresh==0) - return ; - - mMinVotesForRemotelyPositive = thresh ; - IndicateConfigChanged(); -} - -void p3GxsReputation::setThresholdForRemotelyNegativeReputation(uint32_t thresh) -{ - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - if(mMinVotesForRemotelyNegative == thresh || thresh==0) - return ; - - mMinVotesForRemotelyNegative = thresh ; - IndicateConfigChanged(); -} - -void p3GxsReputation::banNode(const RsPgpId& id,bool b) -{ - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - if(b) - { - if(mBannedPgpIds.find(id) == mBannedPgpIds.end()) - { - mBannedPgpIds[id] = BannedNodeInfo() ; - IndicateConfigChanged(); - } - } - else - { - if(mBannedPgpIds.find(id) != mBannedPgpIds.end()) - { - mBannedPgpIds.erase(id) ; - IndicateConfigChanged(); - } - } -} - -RsReputationLevel p3GxsReputation::overallReputationLevel(const RsGxsId& id) -{ return overallReputationLevel(id, nullptr); } - -bool p3GxsReputation::isNodeBanned(const RsPgpId& id) -{ - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - return mBannedPgpIds.find(id) != mBannedPgpIds.end(); -} - -bool p3GxsReputation::isIdentityBanned(const RsGxsId &id) -{ - RsReputationInfo info; - - if(!getReputationInfo(id,RsPgpId(),info)) - return false ; - -#ifdef DEBUG_REPUTATION - std::cerr << "isIdentityBanned(): returning " << (info.mOverallReputationLevel == RsReputations::REPUTATION_LOCALLY_NEGATIVE) << " for GXS id " << id << std::endl; -#endif - return info.mOverallReputationLevel == RsReputationLevel::LOCALLY_NEGATIVE; -} - -bool p3GxsReputation::getOwnOpinion( - const RsGxsId& gxsid, RsOpinion& opinion ) -{ -#ifdef DEBUG_REPUTATION - std::cerr << "setOwnOpinion(): for GXS id " << gxsid << " to " << opinion << std::endl; -#endif - if(gxsid.isNull()) - { - std::cerr << " ID " << gxsid << " is rejected. Look for a bug in calling method." << std::endl; - return false ; - } - - RS_STACK_MUTEX(mReputationMtx); - - std::map::iterator rit = mReputations.find(gxsid); - - if(rit != mReputations.end()) - opinion = safe_convert_uint32t_to_opinion( - static_cast(rit->second.mOwnOpinion) ); - else - opinion = RsOpinion::NEUTRAL; - - return true; -} - -bool p3GxsReputation::setOwnOpinion( - const RsGxsId& gxsid, RsOpinion opinion ) -{ -#ifdef DEBUG_REPUTATION - std::cerr << "setOwnOpinion(): for GXS id " << gxsid << " to " << opinion << std::endl; -#endif - if(gxsid.isNull()) - { - std::cerr << " ID " << gxsid << " is rejected. Look for a bug in calling method." << std::endl; - return false ; - } - - RS_STACK_MUTEX(mReputationMtx); - - std::map::iterator rit; - - /* find matching Reputation */ - rit = mReputations.find(gxsid); - - if (rit == mReputations.end()) - { -#warning csoler 2017-01-05: We should set the owner node id here. - mReputations[gxsid] = Reputation(); - rit = mReputations.find(gxsid); - } - - // we should remove previous entries from Updates... - Reputation &reputation = rit->second; - if (reputation.mOwnOpinionTs != 0) - { - if (reputation.mOwnOpinion == static_cast(opinion)) - { - // if opinion is accurate, don't update. - return false; - } - - std::multimap::iterator uit, euit; - uit = mUpdated.lower_bound(reputation.mOwnOpinionTs); - euit = mUpdated.upper_bound(reputation.mOwnOpinionTs); - for(; uit != euit; ++uit) - { - if (uit->second == gxsid) - { - mUpdated.erase(uit); - break; - } - } - } - - rstime_t now = time(nullptr); - reputation.mOwnOpinion = static_cast(opinion); - reputation.mOwnOpinionTs = now; - reputation.updateReputation(); - - mUpdated.insert(std::make_pair(now, gxsid)); - mReputationsUpdated = true; - mLastBannedNodesUpdate = 0 ; // for update of banned nodes - - // Switched to periodic save due to scale of data. - IndicateConfigChanged(); - - return true; -} - - -/******************************************************************** - * Configuration. - ****/ - -RsSerialiser *p3GxsReputation::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser ; - rss->addSerialType(new RsGxsReputationSerialiser()); - rss->addSerialType(new RsGeneralConfigSerialiser()); - return rss ; -} - -bool p3GxsReputation::saveList(bool& cleanup, std::list &savelist) -{ - cleanup = true; - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::saveList()" << std::endl; -#endif - - /* save */ - std::map::iterator it; - for(it = mConfig.begin(); it != mConfig.end(); ++it) - { - if (!rsPeers->isFriend(it->first)) - { - // discard info from non-friends. - continue; - } - - RsGxsReputationConfigItem *item = new RsGxsReputationConfigItem(); - item->mPeerId = it->first; - item->mLatestUpdate = it->second.mLatestUpdate; - item->mLastQuery = it->second.mLastQuery; - savelist.push_back(item); - } - - int count = 0; - std::map::iterator rit; - for(rit = mReputations.begin(); rit != mReputations.end(); ++rit, count++) - { - RsGxsReputationSetItem *item = new RsGxsReputationSetItem(); - item->mGxsId = rit->first; - item->mOwnOpinion = rit->second.mOwnOpinion; - item->mOwnOpinionTS = rit->second.mOwnOpinionTs; - item->mIdentityFlags = rit->second.mIdentityFlags; - item->mOwnerNodeId = rit->second.mOwnerNode; - item->mLastUsedTS = rit->second.mLastUsedTS; - - std::map::iterator oit; - for(oit = rit->second.mOpinions.begin(); oit != rit->second.mOpinions.end(); ++oit) - { - // should be already limited. - item->mOpinions[oit->first] = (uint32_t)oit->second; - } - - savelist.push_back(item); - count++; - } - - for(std::map::const_iterator it(mBannedPgpIds.begin());it!=mBannedPgpIds.end();++it) - { - RsGxsReputationBannedNodeSetItem *item = new RsGxsReputationBannedNodeSetItem(); - - item->mPgpId = it->first ; - item->mLastActivityTS = it->second.last_activity_TS; - item->mKnownIdentities.ids = it->second.known_identities; - - savelist.push_back(item) ; - } - - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; - RsTlvKeyValue kv; - - kv.key = "AUTO_REMOTELY_POSITIVE_THRESHOLD" ; - rs_sprintf(kv.value, "%d", mMinVotesForRemotelyPositive); - vitem->tlvkvs.pairs.push_back(kv) ; - - kv.key = "AUTO_REMOTELY_NEGATIVE_THRESHOLD" ; - rs_sprintf(kv.value, "%d", mMinVotesForRemotelyNegative); - vitem->tlvkvs.pairs.push_back(kv) ; - - kv.key = "AUTO_POSITIVE_CONTACTS" ; - kv.value = mAutoSetPositiveOptionToContacts?"YES":"NO"; - vitem->tlvkvs.pairs.push_back(kv) ; - - kv.key = "MAX_PREVENT_RELOAD_BANNED_IDS" ; - rs_sprintf(kv.value, "%d", mMaxPreventReloadBannedIds) ; - vitem->tlvkvs.pairs.push_back(kv) ; - - savelist.push_back(vitem) ; - - return true; -} - -void p3GxsReputation::saveDone() -{ - return; -} - -bool p3GxsReputation::loadList(std::list& loadList) -{ -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::loadList()" << std::endl; -#endif - std::list::iterator it; - std::set peerSet; - - for(it = loadList.begin(); it != loadList.end(); ++it) - { - RsGxsReputationConfigItem *item = dynamic_cast(*it); - - // Configurations are loaded first. (to establish peerSet). - if (item) - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - RsPeerId peerId(item->mPeerId); - ReputationConfig &config = mConfig[peerId]; - config.mPeerId = peerId; - config.mLatestUpdate = item->mLatestUpdate; - config.mLastQuery = 0; - - peerSet.insert(peerId); - } - - RsGxsReputationSetItem *set = dynamic_cast(*it); - - if (set) - loadReputationSet(set, peerSet); - -#ifdef TO_REMOVE - RsGxsReputationSetItem_deprecated3 *set2 = dynamic_cast(*it); - - if(set2) - { - std::cerr << "(II) reading and converting old format ReputationSetItem." << std::endl; - loadReputationSet_deprecated3(set2, peerSet); - } -#endif - - RsGxsReputationBannedNodeSetItem *itm2 = dynamic_cast(*it) ; - - if(itm2 != NULL) - { - BannedNodeInfo& info(mBannedPgpIds[itm2->mPgpId]) ; - info.last_activity_TS = itm2->mLastActivityTS ; - info.known_identities = itm2->mKnownIdentities.ids ; - } - - RsConfigKeyValueSet *vitem = dynamic_cast(*it); - - if(vitem) - for(std::list::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) - { - if(kit->key == "AUTO_REMOTELY_POSITIVE_THRESHOLD") - { - int val ; - if (sscanf(kit->value.c_str(), "%d", &val) == 1) - { - mMinVotesForRemotelyPositive = val ; - std::cerr << "Setting mMinVotesForRemotelyPositive threshold to " << val << std::endl ; - } - }; - if(kit->key == "AUTO_REMOTELY_NEGATIVE_THRESHOLD") - { - int val ; - if (sscanf(kit->value.c_str(), "%d", &val) == 1) - { - mMinVotesForRemotelyNegative = val ; - std::cerr << "Setting mMinVotesForRemotelyNegative threshold to " << val << std::endl ; - } - }; - if(kit->key == "AUTO_POSITIVE_CONTACTS") - { - mAutoSetPositiveOptionToContacts = (kit->value == "YES"); - std::cerr << "Setting AutoPositiveContacts to " << kit->value << std::endl ; - mLastBannedNodesUpdate = 0 ; // force update - } - if(kit->key == "MAX_PREVENT_RELOAD_BANNED_IDS" ) - { - int val ; - if (sscanf(kit->value.c_str(), "%d", &val) == 1) - { - mMaxPreventReloadBannedIds = val ; - std::cerr << "Setting mMaxPreventReloadBannedIds threshold to " << val << std::endl ; - } - } - } - - delete (*it); - } - - updateBannedNodesProxy(); - loadList.clear() ; - return true; -} -#ifdef TO_REMOVE -bool p3GxsReputation::loadReputationSet_deprecated3(RsGxsReputationSetItem_deprecated3 *item, const std::set &peerSet) -{ - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - std::map::iterator rit; - - if(item->mGxsId.isNull()) // just a protection against potential errors having put 00000 into ids. - return false ; - - /* find matching Reputation */ - RsGxsId gxsId(item->mGxsId); - rit = mReputations.find(gxsId); - if (rit != mReputations.end()) - { - std::cerr << "ERROR"; - std::cerr << std::endl; - } - - Reputation &reputation = mReputations[gxsId]; - - // install opinions. - std::map::const_iterator oit; - for(oit = item->mOpinions.begin(); oit != item->mOpinions.end(); ++oit) - { - // expensive ... but necessary. - RsPeerId peerId(oit->first); - if (peerSet.end() != peerSet.find(peerId)) - reputation.mOpinions[peerId] = safe_convert_uint32t_to_opinion(oit->second); - } - - reputation.mOwnOpinion = item->mOwnOpinion; - reputation.mOwnOpinionTs = item->mOwnOpinionTS; - reputation.mOwnerNode = item->mOwnerNodeId; - reputation.mIdentityFlags = item->mIdentityFlags & (~REPUTATION_IDENTITY_FLAG_UP_TO_DATE); - reputation.mLastUsedTS = time(NULL); - - // if dropping entries has changed the score -> must update. - - reputation.updateReputation() ; - - mUpdated.insert(std::make_pair(reputation.mOwnOpinionTs, gxsId)); - } -#ifdef DEBUG_REPUTATION - RsReputations::ReputationInfo info ; - getReputationInfo(item->mGxsId,item->mOwnerNodeId,info) ; - std::cerr << item->mGxsId << " : own: " << info.mOwnOpinion << ", owner node: " << item->mOwnerNodeId << ", overall level: " << info.mOverallReputationLevel << std::endl; -#endif - return true; -} -#endif - -bool p3GxsReputation::loadReputationSet(RsGxsReputationSetItem *item, const std::set &peerSet) -{ - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - std::map::iterator rit; - - if(item->mGxsId.isNull()) // just a protection against potential errors having put 00000 into ids. - return false ; - - /* find matching Reputation */ - RsGxsId gxsId(item->mGxsId); - rit = mReputations.find(gxsId); - if (rit != mReputations.end()) - { - std::cerr << "ERROR"; - std::cerr << std::endl; - } - - Reputation &reputation = mReputations[gxsId]; - - // install opinions. - std::map::const_iterator oit; - for(oit = item->mOpinions.begin(); oit != item->mOpinions.end(); ++oit) - { - // expensive ... but necessary. - RsPeerId peerId(oit->first); - if (peerSet.end() != peerSet.find(peerId)) - reputation.mOpinions[peerId] = safe_convert_uint32t_to_opinion(oit->second); - } - - reputation.mOwnOpinion = item->mOwnOpinion; - reputation.mOwnOpinionTs = item->mOwnOpinionTS; - reputation.mOwnerNode = item->mOwnerNodeId; - reputation.mIdentityFlags = item->mIdentityFlags; - reputation.mLastUsedTS = item->mLastUsedTS; - - // if dropping entries has changed the score -> must update. - - reputation.updateReputation() ; - - mUpdated.insert(std::make_pair(reputation.mOwnOpinionTs, gxsId)); - } -#ifdef DEBUG_REPUTATION - RsReputations::ReputationInfo info ; - getReputationInfo(item->mGxsId,item->mOwnerNodeId,info,false) ; - std::cerr << item->mGxsId << " : own: " << info.mOwnOpinion << ", owner node: " << item->mOwnerNodeId << ", level: " << info.mOverallReputationLevel << std::endl; -#endif - return true; -} - - -/******************************************************************** - * Send Requests. - ****/ - -int p3GxsReputation::sendPackets() -{ - rstime_t now = time(NULL); - rstime_t requestTime, storeTime; - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - requestTime = mRequestTime; - storeTime = mStoreTime; - } - - if (now > requestTime + kReputationRequestPeriod) - { - sendReputationRequests(); - - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::sendPackets() Regular Broadcast"; - std::cerr << std::endl; -#endif - mRequestTime = now; - mStoreTime = now + kReputationStoreWait; - } - - if (now > storeTime) - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - -#ifdef DEBUG_REPUTATION - std::cerr << "p3GxsReputation::sendPackets() Regular Broadcast"; - std::cerr << std::endl; -#endif - // push it into the future. - // store time will be reset when requests are send. - mStoreTime = now + kReputationRequestPeriod; - - if (mReputationsUpdated) - { - IndicateConfigChanged(); - mReputationsUpdated = false; - } - } - - return true ; -} - -void p3GxsReputation::sendReputationRequests() -{ - /* we ping our peers */ - /* who is online? */ - std::list idList; - - mLinkMgr->getOnlineList(idList); - - /* prepare packets */ - std::list::iterator it; - for(it = idList.begin(); it != idList.end(); ++it) - sendReputationRequest(*it); -} - -int p3GxsReputation::sendReputationRequest(RsPeerId peerid) -{ -#ifdef DEBUG_REPUTATION - rstime_t now = time(NULL) ; - std::cerr << " p3GxsReputation::sendReputationRequest(" << peerid << ") " ; -#endif - - /* */ - RsGxsReputationRequestItem *requestItem = new RsGxsReputationRequestItem(); - requestItem->PeerId(peerid); - - { - RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/ - - /* find the last timestamp we have */ - std::map::iterator it = mConfig.find(peerid); - - if (it != mConfig.end()) - { -#ifdef DEBUG_REPUTATION - std::cerr << " lastUpdate = " << now - it->second.mLatestUpdate << " secs ago. Requesting only more recent." << std::endl; -#endif - requestItem->mLastUpdate = it->second.mLatestUpdate; - } - else - { -#ifdef DEBUG_REPUTATION - std::cerr << " lastUpdate = never. Requesting all!" << std::endl; -#endif - // get whole list. - requestItem->mLastUpdate = 0; - } - } - - sendItem(requestItem); - return 1; -} - -void Reputation::updateReputation() -{ - // the calculation of reputation makes the whole thing - - int friend_total = 0; - - mFriendsNegative = 0 ; - mFriendsPositive = 0 ; - - // accounts for all friends. Neutral opinions count for 1-1=0 - // because the average is performed over only accessible peers (not the total number) we need to shift to 1 - - for( std::map::const_iterator it(mOpinions.begin()); - it != mOpinions.end(); ++it ) - { - if( it->second == RsOpinion::NEGATIVE) - ++mFriendsNegative ; - - if( it->second == RsOpinion::POSITIVE) - ++mFriendsPositive ; - - friend_total += static_cast(it->second) - 1; - } - - if(mOpinions.empty()) // includes the case of no friends! - mFriendAverage = 1.0f ; - else - { - static const float REPUTATION_FRIEND_FACTOR_ANON = 2.0f ; - static const float REPUTATION_FRIEND_FACTOR_PGP_LINKED = 5.0f ; - static const float REPUTATION_FRIEND_FACTOR_PGP_KNOWN = 10.0f ; - - // For positive votes, start from 1 and slowly tend to 2 - // for negative votes, start from 1 and slowly tend to 0 - // depending on signature state, the ID is harder (signed ids) or easier (anon ids) to ban or to promote. - // - // when REPUTATION_FRIEND_VARIANCE = 3, that gives the following values: - // - // total votes | mFriendAverage anon | mFriendAverage PgpLinked | mFriendAverage PgpKnown | - // | F=2.0 | F=5.0 | F=10.0 | - // -------------+----------------------+---------------------------+--------------------------+ - // -10 | 0.00 Banned | 0.13 Banned | 0.36 Banned | - // -5 | 0.08 Banned | 0.36 Banned | 0.60 | - // -4 | 0.13 Banned | 0.44 Banned | 0.67 | - // -3 | 0.22 Banned | 0.54 | 0.74 | - // -2 | 0.36 Banned | 0.67 | 0.81 | - // -1 | 0.60 | 0.81 | 0.90 | - // 0 | 1.0 | 1.0 | 1.00 | - // 1 | 1.39 | 1.18 | 1.09 | - // 2 | 1.63 | 1.32 | 1.18 | - // 3 | 1.77 | 1.45 | 1.25 | - // 4 | 1.86 | 1.55 | 1.32 | - // 5 | 1.91 | 1.63 | 1.39 | - // - // Banning info is provided by the reputation system, and does not depend on PGP-sign state. - // - // However, each service might have its own rules for the different cases. For instance - // PGP-favoring forums might want a score > 1.4 for anon ids, and >= 1.0 for PGP-signed. - - float reputation_bias ; - - if(mIdentityFlags & REPUTATION_IDENTITY_FLAG_PGP_KNOWN) - reputation_bias = REPUTATION_FRIEND_FACTOR_PGP_KNOWN ; - else if(mIdentityFlags & REPUTATION_IDENTITY_FLAG_PGP_LINKED) - reputation_bias = REPUTATION_FRIEND_FACTOR_PGP_LINKED ; - else - reputation_bias = REPUTATION_FRIEND_FACTOR_ANON ; - - if(friend_total > 0) - mFriendAverage = 2.0f-exp(-friend_total / reputation_bias) ; - else - mFriendAverage = exp( friend_total / reputation_bias) ; - } - - // now compute a bias for PGP-signed ids. - - if(mOwnOpinion == static_cast(RsOpinion::NEUTRAL)) - mReputationScore = mFriendAverage; - else mReputationScore = static_cast(mOwnOpinion); -} - -void p3GxsReputation::debug_print() -{ - std::cerr << "Reputations database: " << std::endl; - std::cerr << " GXS ID data: " << std::endl; - std::cerr << std::dec ; - - std::map rep_copy; - - { - RS_STACK_MUTEX(mReputationMtx); - rep_copy = mReputations; - } - - rstime_t now = time(nullptr); - - - for( std::map::const_iterator it(rep_copy.begin()); - it != rep_copy.end(); ++it ) - { - RsReputationInfo info; - getReputationInfo(it->first, RsPgpId(), info, false); - uint32_t lev = static_cast(info.mOverallReputationLevel); - - std::cerr << " " << it->first << ": own: " << it->second.mOwnOpinion - << ", PGP id=" << it->second.mOwnerNode - << ", flags=" << std::setfill('0') << std::setw(4) << std::hex << it->second.mIdentityFlags << std::dec - << ", Friend pos/neg: " << it->second.mFriendsPositive << "/" << it->second.mFriendsNegative - << ", reputation lev: [" << lev - << "], last own update: " << std::setfill(' ') << std::setw(10) << now - it->second.mOwnOpinionTs << " secs ago" - << ", last needed: " << std::setfill(' ') << std::setw(10) << now - it->second.mLastUsedTS << " secs ago, " - << std::endl; - -#ifdef DEBUG_REPUTATION2 - for(std::map::const_iterator it2(it->second.mOpinions.begin());it2!=it->second.mOpinions.end();++it2) - std::cerr << " " << it2->first << ": " << it2->second << std::endl; -#endif - } - - RS_STACK_MUTEX(mReputationMtx); - std::cerr << " Banned RS nodes by ID: " << std::endl; - - for(std::map::const_iterator it(mBannedPgpIds.begin());it!=mBannedPgpIds.end();++it) - { - std::cerr << " Node " << it->first << ", last activity: " << now - it->second.last_activity_TS << " secs ago." << std::endl; - - for(std::set::const_iterator it2(it->second.known_identities.begin());it2!=it->second.known_identities.end();++it2) - std::cerr << " " << *it2 << std::endl; - } - - std::cerr << " Per node Banned GXSIds proxy: " << std::endl; - - for(std::set::const_iterator it(mPerNodeBannedIdsProxy.begin());it!=mPerNodeBannedIdsProxy.end();++it) - std::cerr << " " << *it << std::endl; -} - diff --git a/libretroshare/src/services/p3gxsreputation.h b/libretroshare/src/services/p3gxsreputation.h deleted file mode 100644 index 2045e6f05..000000000 --- a/libretroshare/src/services/p3gxsreputation.h +++ /dev/null @@ -1,204 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3gxsreputation.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014-2014 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef SERVICE_RSGXSREPUTATION_HEADER -#define SERVICE_RSGXSREPUTATION_HEADER - -#include -#include -#include -#include - -static const uint32_t REPUTATION_IDENTITY_FLAG_UP_TO_DATE = 0x0100; // This flag means that the static info has been initialised from p3IdService. Normally such a call should happen once. -static const uint32_t REPUTATION_IDENTITY_FLAG_PGP_LINKED = 0x0001; -static const uint32_t REPUTATION_IDENTITY_FLAG_PGP_KNOWN = 0x0002; - -#include "rsitems/rsgxsreputationitems.h" - -#include "retroshare/rsidentity.h" -#include "retroshare/rsreputations.h" -#include "gxs/rsgixs.h" -#include "services/p3service.h" - - -class p3LinkMgr; - -class ReputationConfig -{ -public: - ReputationConfig() - :mPeerId(), mLatestUpdate(0), mLastQuery(0) { return; } - - ReputationConfig(const RsPeerId& peerId) - :mPeerId(peerId), mLatestUpdate(0), mLastQuery(0) { return; } - - RsPeerId mPeerId; - rstime_t mLatestUpdate; - rstime_t mLastQuery; -}; - -struct BannedNodeInfo -{ - rstime_t last_activity_TS ; // updated everytime a node or one of its former identities is required - std::set known_identities ; // list of known identities from this node. This is kept for a while, and useful in order to avoid re-asking these keys. -}; - -class Reputation -{ -public: - Reputation() : - mOwnOpinion(static_cast(RsOpinion::NEUTRAL)), - mOwnOpinionTs(0), - mFriendAverage(1.0f), - mFriendsPositive(0), - mFriendsNegative(0), - mReputationScore(1.0f), - mIdentityFlags(0), - mLastUsedTS(0) {} - - void updateReputation(); - - std::map mOpinions; - int32_t mOwnOpinion; - rstime_t mOwnOpinionTs; - - float mFriendAverage ; - uint32_t mFriendsPositive ; // number of positive vites from friends - uint32_t mFriendsNegative ; // number of negative vites from friends - - float mReputationScore; - - RsPgpId mOwnerNode; - - uint32_t mIdentityFlags; - - rstime_t mLastUsedTS ; // last time the reputation was asked. Used to keep track of activity and clean up some reputation data. -}; - - -//!The p3GxsReputation service. -class p3GxsReputation: public p3Service, public p3Config, public RsGixsReputation, public RsReputations /* , public pqiMonitor */ -{ -public: - p3GxsReputation(p3LinkMgr *lm); - virtual RsServiceInfo getServiceInfo(); - - /***** Interface for RsReputations *****/ - virtual bool setOwnOpinion(const RsGxsId& key_id, RsOpinion op); - virtual bool getOwnOpinion(const RsGxsId& key_id, RsOpinion& op) ; - virtual bool getReputationInfo( - const RsGxsId& id, const RsPgpId& ownerNode, RsReputationInfo& info, - bool stamp = true ); - virtual bool isIdentityBanned(const RsGxsId& id) ; - - virtual bool isNodeBanned(const RsPgpId& id); - virtual void banNode(const RsPgpId& id,bool b) ; - - RsReputationLevel overallReputationLevel(const RsGxsId& id) override; - - virtual RsReputationLevel overallReputationLevel( - const RsGxsId& id, uint32_t* identity_flags ); - - virtual void setAutoPositiveOpinionForContacts(bool b) ; - virtual bool autoPositiveOpinionForContacts() ; - - virtual void setRememberBannedIdThreshold(uint32_t days) ; - virtual uint32_t rememberBannedIdThreshold() ; - - uint32_t thresholdForRemotelyNegativeReputation(); - uint32_t thresholdForRemotelyPositiveReputation(); - void setThresholdForRemotelyNegativeReputation(uint32_t thresh); - void setThresholdForRemotelyPositiveReputation(uint32_t thresh); - - /***** overloaded from p3Service *****/ - virtual int tick(); - virtual int status(); - - /*! - * Interface stuff. - */ - - /************* from p3Config *******************/ - virtual RsSerialiser *setupSerialiser() ; - virtual bool saveList(bool& cleanup, std::list&) ; - virtual void saveDone(); - virtual bool loadList(std::list& load) ; - -private: - bool getIdentityFlagsAndOwnerId(const RsGxsId& gxsid, uint32_t& identity_flags, RsPgpId &owner_id); - - bool processIncoming(); - - bool SendReputations(RsGxsReputationRequestItem *request); - bool RecvReputations(RsGxsReputationUpdateItem *item); - bool updateLatestUpdate(RsPeerId peerid, rstime_t latest_update); - - void updateBannedNodesProxy(); - - // internal update of data. Takes care of cleaning empty boxes. - void locked_updateOpinion( - const RsPeerId& from, const RsGxsId& about, RsOpinion op); - bool loadReputationSet(RsGxsReputationSetItem *item, const std::set &peerSet); -#ifdef TO_REMOVE - bool loadReputationSet_deprecated3(RsGxsReputationSetItem_deprecated3 *item, const std::set &peerSet); -#endif - int sendPackets(); - void cleanup(); - void sendReputationRequests(); - int sendReputationRequest(RsPeerId peerid); - void debug_print() ; - void updateStaticIdentityFlags(); - -private: - RsMutex mReputationMtx; - - rstime_t mLastCleanUp; - rstime_t mRequestTime; - rstime_t mStoreTime; - rstime_t mLastBannedNodesUpdate ; - rstime_t mLastIdentityFlagsUpdate ; - bool mReputationsUpdated; - - //float mAutoBanIdentitiesLimit ; - bool mAutoSetPositiveOptionToContacts; - - p3LinkMgr *mLinkMgr; - - // Data for Reputation. - std::map mConfig; - std::map mReputations; - std::multimap mUpdated; - - // PGP Ids auto-banned. This is updated regularly. - std::map mBannedPgpIds ; - std::set mPerNodeBannedIdsProxy ; - bool mBannedNodesProxyNeedsUpdate ; - - uint32_t mMinVotesForRemotelyPositive ; - uint32_t mMinVotesForRemotelyNegative ; - uint32_t mMaxPreventReloadBannedIds ; - - bool mChanged ; // slow version of IndicateConfigChanged(); - rstime_t mLastReputationConfigSaved ; -}; - -#endif //SERVICE_RSGXSREPUTATION_HEADER - diff --git a/libretroshare/src/services/p3heartbeat.cc b/libretroshare/src/services/p3heartbeat.cc deleted file mode 100644 index 38426a454..000000000 --- a/libretroshare/src/services/p3heartbeat.cc +++ /dev/null @@ -1,143 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3heartbeat.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2013 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "util/rstime.h" - -#include "services/p3heartbeat.h" -#include "rsitems/rsheartbeatitems.h" - -#include "pqi/p3servicecontrol.h" -#include "pqi/pqipersongrp.h" - -//#define HEART_DEBUG 1 - - -p3heartbeat::p3heartbeat(p3ServiceControl *sc, pqipersongrp *pqipg) -:p3Service(), mServiceCtrl(sc), mPqiPersonGrp(pqipg), - mHeartMtx("p3heartbeat") -{ - RsStackMutex stack(mHeartMtx); /********** STACK LOCKED MTX ******/ - - addSerialType(new RsHeartbeatSerialiser()); - -#ifdef HEART_DEBUG - std::cerr << "p3heartbeat::p3heartbeat()"; - std::cerr << std::endl; -#endif - - mLastHeartbeat = 0; - - return; -} - -p3heartbeat::~p3heartbeat() -{ - return; - -} - - -const std::string HEARTBEAT_APP_NAME = "heartbeat"; -const uint16_t HEARTBEAT_APP_MAJOR_VERSION = 1; -const uint16_t HEARTBEAT_APP_MINOR_VERSION = 0; -const uint16_t HEARTBEAT_MIN_MAJOR_VERSION = 1; -const uint16_t HEARTBEAT_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3heartbeat::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_HEARTBEAT, - HEARTBEAT_APP_NAME, - HEARTBEAT_APP_MAJOR_VERSION, - HEARTBEAT_APP_MINOR_VERSION, - HEARTBEAT_MIN_MAJOR_VERSION, - HEARTBEAT_MIN_MINOR_VERSION); -} - - -int p3heartbeat::tick() -{ - //send a heartbeat to all connected peers - RsStackMutex stack(mHeartMtx); /********** STACK LOCKED MTX ******/ - - if (time(NULL) - mLastHeartbeat > HEARTBEAT_REPEAT_TIME) - { - mLastHeartbeat = time(NULL); - - std::set peers; - std::set::const_iterator pit; - - mServiceCtrl->getPeersConnected(getServiceInfo().mServiceType, peers); - for (pit = peers.begin(); pit != peers.end(); ++pit) - { - sendHeartbeat(*pit); - } - } - - int nhandled = 0; - RsItem *item = NULL; - - // While messages read - while(NULL != (item = recvItem())) - { - RsHeartbeatItem *beat = NULL; - nhandled++; - - // if discovery reply then respond if haven't already. - if (NULL != (beat = dynamic_cast (item))) - { - recvHeartbeat(beat->PeerId()); - } - else - { - // unknown. - } - - delete item; - } - - return nhandled ; -} - -void p3heartbeat::sendHeartbeat(const RsPeerId &toId) -{ - -#ifdef HEART_DEBUG - std::cerr << "p3heartbeat::sendHeartbeat() to " << toId; - std::cerr << std::endl; -#endif - RsHeartbeatItem *item = new RsHeartbeatItem(); - item->PeerId(toId); - sendItem(item); -} - - -void p3heartbeat::recvHeartbeat(const RsPeerId &fromId) -{ - -#ifdef HEART_DEBUG - std::cerr << "p3heartbeat::recvHeartbeat() from " << fromId; - std::cerr << std::endl; -#endif - - mPqiPersonGrp->tagHeartbeatRecvd(fromId); -} - - diff --git a/libretroshare/src/services/p3heartbeat.h b/libretroshare/src/services/p3heartbeat.h deleted file mode 100644 index 6dd9f6e5b..000000000 --- a/libretroshare/src/services/p3heartbeat.h +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3heartbeat.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2013 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef MRK_SERVICES_HEARTBEAT_H -#define MRK_SERVICES_HEARTBEAT_H - -// Moved Heartbeat to a seperate service. - -#include "services/p3service.h" - -class p3ServiceControl; -class pqipersongrp; - -class p3heartbeat: public p3Service -{ - public: - - p3heartbeat(p3ServiceControl *sc, pqipersongrp *pqipg); -virtual ~p3heartbeat(); - -virtual RsServiceInfo getServiceInfo(); - - int tick(); - - private: - - void sendHeartbeat(const RsPeerId &toId); - void recvHeartbeat(const RsPeerId &fromId); - - private: - - p3ServiceControl *mServiceCtrl; - pqipersongrp *mPqiPersonGrp; - - /* data */ - RsMutex mHeartMtx; - - rstime_t mLastHeartbeat; -}; - -#endif // MRK_SERVICES_HEARTBEAT_H diff --git a/libretroshare/src/services/p3idservice.cc b/libretroshare/src/services/p3idservice.cc deleted file mode 100644 index bf034bcb2..000000000 --- a/libretroshare/src/services/p3idservice.cc +++ /dev/null @@ -1,5017 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3idservice.cc * - * * - * Copyright (C) 2012-2014 Robert Fernie * - * Copyright (C) 2017-2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -/// RetroShare GXS identities service - - -#include -#include -#include -#include - -#include "services/p3idservice.h" -#include "pgp/pgpauxutils.h" -#include "rsitems/rsgxsiditems.h" -#include "rsitems/rsconfigitems.h" -#include "retroshare/rsgxsflags.h" -#include "util/rsrandom.h" -#include "util/rsstring.h" -#include "util/radix64.h" -#include "util/rsdir.h" -#include "util/rstime.h" -#include "crypto/hashstream.h" -#include "gxs/gxssecurity.h" -#include "retroshare/rspeers.h" -#include "retroshare/rsnotify.h" - - -/**** - * #define DEBUG_IDS 1 - * #define DEBUG_RECOGN 1 - * #define DEBUG_OPINION 1 - * #define DEBUG_SERVICE_STRING 1 - * #define GXSID_GEN_DUMMY_DATA 1 - ****/ - -#define ID_REQUEST_LIST 0x0001 -#define ID_REQUEST_IDENTITY 0x0002 -#define ID_REQUEST_REPUTATION 0x0003 -#define ID_REQUEST_OPINION 0x0004 - -#define GXSID_MAX_CACHE_SIZE 15000 - -// unused keys are deleted according to some heuristic that should favor known keys, signed keys etc. - -static const rstime_t MAX_KEEP_KEYS_BANNED_DEFAULT = 2 * 86400 ; // get rid of banned ids after 1 days. That gives a chance to un-ban someone before he gets definitely kicked out - -static const rstime_t MAX_KEEP_KEYS_DEFAULT = 5 * 86400 ; // default for unsigned identities: 5 days -static const rstime_t MAX_KEEP_KEYS_SIGNED = 8 * 86400 ; // signed identities by unknown key -static const rstime_t MAX_KEEP_KEYS_SIGNED_KNOWN = 30 * 86400 ; // signed identities by known node keys - -static const uint32_t MAX_DELAY_BEFORE_CLEANING= 1800 ; // clean old keys every 30 mins - -static const uint32_t MAX_SERIALISED_IDENTITY_AGE = 600 ; // after 10 mins, a serialised identity record must be renewed. - -RsIdentity* rsIdentity = nullptr; - -/****** - * Some notes: - * Identity tasks: - * - Provide keys for signing / validating author signatures. - * - Reputations - * - Identify Known Friend's IDs. - * - Provide details to other services (nicknames, reputations, gpg ids, etc) - * - * Background services: - * - Lookup and cache keys / details of identities. - * - Check GPGHashes. - * - Calculate Reputations. - * - * We have a lot of information to store in Service Strings. - * - GPGId or last check ts. - * - Reputation stuff. - */ - -#define RSGXSID_MAX_SERVICE_STRING 1024 - -#define BG_PGPHASH 1 -#define BG_RECOGN 2 -#define BG_REPUTATION 3 - - -#define GXSIDREQ_CACHELOAD 0x0001 -#define GXSIDREQ_CACHEOWNIDS 0x0002 -#define GXSIDREQ_PGPHASH 0x0010 -#define GXSIDREQ_RECOGN 0x0020 -#define GXSIDREQ_OPINION 0x0030 -#define GXSIDREQ_SERIALIZE_TO_MEMORY 0x0040 -#define GXSIDREQ_LOAD_PGPIDDATA 0x0080 - -#define GXSIDREQ_CACHETEST 0x1000 - -// Events. -#define GXSID_EVENT_CACHEOWNIDS 0x0001 -#define GXSID_EVENT_CACHELOAD 0x0002 - -#define GXSID_EVENT_PGPHASH 0x0010 -#define GXSID_EVENT_PGPHASH_PROC 0x0011 - -#define GXSID_EVENT_RECOGN 0x0020 -#define GXSID_EVENT_RECOGN_PROC 0x0021 - -#define GXSID_EVENT_REPUTATION 0x0030 - -#define GXSID_EVENT_CACHETEST 0x1000 - -#define GXSID_EVENT_DUMMYDATA 0x2000 -#define GXSID_EVENT_DUMMY_OWNIDS 0x2001 -#define GXSID_EVENT_DUMMY_PGPID 0x2002 -#define GXSID_EVENT_DUMMY_UNKNOWN_PGPID 0x2003 -#define GXSID_EVENT_DUMMY_PSEUDOID 0x2004 -#define GXSID_EVENT_REQUEST_IDS 0x2005 - - -/* delays */ - -#define CACHETEST_PERIOD 60 -#define DELAY_BETWEEN_CONFIG_UPDATES 300 -#define GXS_MAX_KEY_TS_USAGE_MAP_SIZE 5 - -#define OWNID_RELOAD_DELAY 10 - -#define PGPHASH_PERIOD 60 -#define PGPHASH_RETRY_PERIOD 11 -#define PGPHASH_PROC_PERIOD 1 - -#define RECOGN_PERIOD 90 -#define RECOGN_RETRY_PERIOD 17 -#define RECOGN_PROC_PERIOD 1 - -#define REPUTATION_PERIOD 60 -#define REPUTATION_RETRY_PERIOD 13 -#define REPUTATION_PROC_PERIOD 1 - -/********************************************************************************/ -/******************* Startup / Tick ******************************************/ -/********************************************************************************/ - -p3IdService::p3IdService( RsGeneralDataService *gds - , RsNetworkExchangeService *nes - , PgpAuxUtils *pgpUtils ) - : RsGxsIdExchange( gds, nes, new RsGxsIdSerialiser(), - RS_SERVICE_GXS_TYPE_GXSID, idAuthenPolicy() ) - , RsIdentity(static_cast(*this)) - , GxsTokenQueue(this), RsTickEvent(), p3Config() - , mKeyCache(GXSID_MAX_CACHE_SIZE, "GxsIdKeyCache") - , mBgSchedule_Active(false), mBgSchedule_Mode(0) - , mIdMtx("p3IdService"), mNes(nes), mPgpUtils(pgpUtils) - , mLastConfigUpdate(0), mOwnIdsLoaded(false) - , mAutoAddFriendsIdentitiesAsContacts(true) /*default*/ - , mMaxKeepKeysBanned(MAX_KEEP_KEYS_BANNED_DEFAULT) -{ - mLastKeyCleaningTime = time(NULL) - int(MAX_DELAY_BEFORE_CLEANING * 0.9) ; - mLastPGPHashProcessTime = 0; - - // Kick off Cache Testing, + Others. - RsTickEvent::schedule_now(GXSID_EVENT_CACHEOWNIDS);//First Thing to do - RsTickEvent::schedule_in(GXSID_EVENT_PGPHASH, PGPHASH_PERIOD); - RsTickEvent::schedule_in(GXSID_EVENT_REPUTATION, REPUTATION_PERIOD); - - //RsTickEvent::schedule_in(GXSID_EVENT_CACHETEST, CACHETEST_PERIOD); - -#ifdef GXSID_GEN_DUMMY_DATA - //RsTickEvent::schedule_now(GXSID_EVENT_DUMMYDATA); -#endif - - loadRecognKeys(); -} - -const std::string GXSID_APP_NAME = "gxsid"; -const uint16_t GXSID_APP_MAJOR_VERSION = 1; -const uint16_t GXSID_APP_MINOR_VERSION = 0; -const uint16_t GXSID_MIN_MAJOR_VERSION = 1; -const uint16_t GXSID_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3IdService::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_GXS_TYPE_GXSID, - GXSID_APP_NAME, - GXSID_APP_MAJOR_VERSION, - GXSID_APP_MINOR_VERSION, - GXSID_MIN_MAJOR_VERSION, - GXSID_MIN_MINOR_VERSION); -} - - - -void p3IdService::setNes(RsNetworkExchangeService *nes) -{ - RsStackMutex stack(mIdMtx); - mNes = nes; -} - -bool p3IdService::getIdentitiesInfo( - const std::set& ids, std::vector& idsInfo ) -{ - uint32_t token; - - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - - std::list idsList; - for (auto&& id : ids) idsList.push_back(RsGxsGroupId(id)); - - if( !requestGroupInfo(token, opts, idsList) - || waitToken(token) != RsTokenService::COMPLETE ) return false; - return getGroupData(token, idsInfo); -} - -bool p3IdService::getIdentitiesSummaries(std::list& ids) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; - if( !requestGroupInfo(token, opts) - || waitToken(token) != RsTokenService::COMPLETE ) return false; - return getGroupSummary(token, ids); -} - -uint32_t p3IdService::idAuthenPolicy() -{ - uint32_t policy = 0; - uint8_t flag = 0; - - // Messages are send reputations. normally not by ID holder - so need signatures. - flag = GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS); - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS); - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS); - - // No ID required. - flag = 0; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::GRP_OPTION_BITS); - - return policy; -} - -uint32_t p3IdService::nbRegularContacts() -{ - RsStackMutex stack(mIdMtx); - return mContacts.size(); -} - -bool p3IdService::isARegularContact(const RsGxsId& id) -{ - RsStackMutex stack(mIdMtx); - return mContacts.find(id) != mContacts.end() ; -} - -bool p3IdService::receiveNewIdentity(RsNxsGrp *identity_grp) -{ - receiveNewGroups(std::vector{ identity_grp }); - return true; -} - -bool p3IdService::retrieveNxsIdentity(const RsGxsId& group_id,RsNxsGrp *& identity_grp) -{ - return RsGenExchange::retrieveNxsIdentity(RsGxsGroupId(group_id),identity_grp); -} - -bool p3IdService::setAsRegularContact(const RsGxsId& id,bool b) -{ - RsStackMutex stack(mIdMtx); - std::set::iterator it = mContacts.find(id) ; - - if(b && (it == mContacts.end())) - { - mContacts.insert(id) ; - slowIndicateConfigChanged() ; - } - - if( (!b) &&(it != mContacts.end())) - { - mContacts.erase(it) ; - slowIndicateConfigChanged() ; - } - - return true ; -} - -void p3IdService::slowIndicateConfigChanged() -{ - rstime_t now = time(NULL) ; - - if(mLastConfigUpdate + DELAY_BETWEEN_CONFIG_UPDATES < now) - { - IndicateConfigChanged() ; - mLastConfigUpdate = now ; - } -} -rstime_t p3IdService::locked_getLastUsageTS(const RsGxsId& gxs_id) -{ - std::map::const_iterator it = mKeysTS.find(gxs_id) ; - - if(it == mKeysTS.end()) - return 0 ; - else - return it->second.TS ; -} -void p3IdService::timeStampKey(const RsGxsId& gxs_id, const RsIdentityUsage& reason) -{ - if(rsReputations->isIdentityBanned(gxs_id) ) - { - std::cerr << "(II) p3IdService:timeStampKey(): refusing to time stamp key " << gxs_id << " because it is banned." << std::endl; - return ; - } -#ifdef DEBUG_IDS - std::cerr << "(II) time stamping key " << gxs_id << " for the following reason: " << reason.mUsageCode << std::endl; -#endif - - RS_STACK_MUTEX(mIdMtx) ; - - rstime_t now = time(NULL) ; - - keyTSInfo& info(mKeysTS[gxs_id]) ; - - info.TS = now ; - info.usage_map[reason] = now; - - while(info.usage_map.size() > GXS_MAX_KEY_TS_USAGE_MAP_SIZE) - { - // This is very costly, but normally the outerloop should never be rolled more than once. - - std::map::iterator best_it ; - rstime_t best_time = now+1; - - for(std::map::iterator it(info.usage_map.begin());it!=info.usage_map.end();++it) - if(it->second < best_time) - { - best_time = it->second ; - best_it = it; - } - - info.usage_map.erase(best_it) ; - } - - slowIndicateConfigChanged() ; -} - -bool p3IdService::loadList(std::list& items) -{ - RS_STACK_MUTEX(mIdMtx) ; - RsGxsIdLocalInfoItem *lii; - - for(std::list::const_iterator it = items.begin();it!=items.end();++it) - { - if( (lii = dynamic_cast(*it)) != NULL) - { - for(std::map::const_iterator it2 = lii->mTimeStamps.begin();it2!=lii->mTimeStamps.end();++it2) - mKeysTS[it2->first].TS = it2->second; - - mContacts = lii->mContacts ; - } - - RsConfigKeyValueSet *vitem = dynamic_cast(*it); - - if(vitem) - for(std::list::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) - { - if(kit->key == "REMOVE_BANNED_IDENTITIES_DELAY") - { - int val ; - if (sscanf(kit->value.c_str(), "%d", &val) == 1) - { - mMaxKeepKeysBanned = val ; - std::cerr << "Setting mMaxKeepKeysBanned threshold to " << val << std::endl ; - } - }; - if(kit->key == "AUTO_SET_FRIEND_IDENTITIES_AS_CONTACT") - mAutoAddFriendsIdentitiesAsContacts = (kit->value == "YES") ; - } - - delete *it ; - } - - items.clear() ; - return true ; -} - -void p3IdService::setDeleteBannedNodesThreshold(uint32_t days) -{ - RsStackMutex stack(mIdMtx); /****** LOCKED MUTEX *******/ - if(mMaxKeepKeysBanned != days*86400) - { - mMaxKeepKeysBanned = days*86400 ; - IndicateConfigChanged(); - } -} -uint32_t p3IdService::deleteBannedNodesThreshold() -{ - RsStackMutex stack(mIdMtx); /****** LOCKED MUTEX *******/ - - return mMaxKeepKeysBanned/86400; -} - -void p3IdService::setAutoAddFriendIdsAsContact(bool b) -{ - RS_STACK_MUTEX(mIdMtx) ; - if(b != mAutoAddFriendsIdentitiesAsContacts) - { - IndicateConfigChanged(); - mAutoAddFriendsIdentitiesAsContacts=b; - } -} -bool p3IdService::autoAddFriendIdsAsContact() -{ - RS_STACK_MUTEX(mIdMtx) ; - return mAutoAddFriendsIdentitiesAsContacts; -} - -bool p3IdService::saveList(bool& cleanup,std::list& items) -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::saveList()" << std::endl; -#endif - - RS_STACK_MUTEX(mIdMtx) ; - cleanup = true ; - RsGxsIdLocalInfoItem *item = new RsGxsIdLocalInfoItem ; - - for(std::map::const_iterator it(mKeysTS.begin());it!=mKeysTS.end();++it) - item->mTimeStamps[it->first] = it->second.TS; - - item->mContacts = mContacts ; - - items.push_back(item) ; - - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; - RsTlvKeyValue kv; - - kv.key = "REMOVE_BANNED_IDENTITIES_DELAY" ; - rs_sprintf(kv.value, "%d", mMaxKeepKeysBanned); - vitem->tlvkvs.pairs.push_back(kv) ; - - kv.key = "AUTO_SET_FRIEND_IDENTITIES_AS_CONTACT" ; - kv.value = mAutoAddFriendsIdentitiesAsContacts?"YES":"NO"; - vitem->tlvkvs.pairs.push_back(kv) ; - - items.push_back(vitem) ; - - return true ; -} - -class IdCacheEntryCleaner -{ -public: - IdCacheEntryCleaner(const std::map& last_usage_TSs,uint32_t m) : mLastUsageTS(last_usage_TSs),mMaxKeepKeysBanned(m) {} - - bool processEntry(RsGxsIdCache& entry) - { - rstime_t now = time(NULL); - const RsGxsId& gxs_id = entry.details.mId ; - - bool is_id_banned = rsReputations->isIdentityBanned(gxs_id) ; - bool is_own_id = (bool)(entry.details.mFlags & RS_IDENTITY_FLAGS_IS_OWN_ID) ; - bool is_known_id = (bool)(entry.details.mFlags & RS_IDENTITY_FLAGS_PGP_KNOWN) ; - bool is_signed_id = (bool)(entry.details.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED) ; - bool is_a_contact = (bool)(entry.details.mFlags & RS_IDENTITY_FLAGS_IS_A_CONTACT) ; - -#ifdef DEBUG_IDS - std::cerr << "Identity: " << gxs_id << ": banned: " << is_id_banned << ", own: " << is_own_id << ", contact: " << is_a_contact << ", signed: " << is_signed_id << ", known: " << is_known_id; -#endif - - if(is_own_id || is_a_contact) - { -#ifdef DEBUG_IDS - std::cerr << " => kept" << std::endl; -#endif - return true ; - } - - std::map::const_iterator it = mLastUsageTS.find(gxs_id) ; - - bool no_ts = (it == mLastUsageTS.end()) ; - - rstime_t last_usage_ts = no_ts?0:(it->second.TS); - rstime_t max_keep_time = 0; - bool should_check = true ; - - if(no_ts) - max_keep_time = 0 ; - else if(is_id_banned) - { - if(mMaxKeepKeysBanned == 0) - should_check = false ; - else - max_keep_time = mMaxKeepKeysBanned ; - } - else if(is_known_id) - max_keep_time = MAX_KEEP_KEYS_SIGNED_KNOWN ; - else if(is_signed_id) - max_keep_time = MAX_KEEP_KEYS_SIGNED ; - else - max_keep_time = MAX_KEEP_KEYS_DEFAULT ; - -#ifdef DEBUG_IDS - std::cerr << ". Max keep = " << max_keep_time/86400 << " days. Unused for " << (now - last_usage_ts + 86399)/86400 << " days " ; -#endif - - if(should_check && now > last_usage_ts + max_keep_time) - { -#ifdef DEBUG_IDS - std::cerr << " => delete " << std::endl; -#endif - ids_to_delete.push_back(gxs_id) ; - } -#ifdef DEBUG_IDS - else - std::cerr << " => keep " << std::endl; -#endif - - return true; - } - - std::list ids_to_delete ; - const std::map& mLastUsageTS; - uint32_t mMaxKeepKeysBanned ; -}; - -void p3IdService::cleanUnusedKeys() -{ - std::list ids_to_delete ; - - std::cerr << "Cleaning unused keys:" << std::endl; - - // we need to stash all ids to delete into an off-mutex structure since deleteIdentity() will trigger the lock - { - RS_STACK_MUTEX(mIdMtx) ; - - if(!mOwnIdsLoaded) - { - std::cerr << "(EE) Own ids not loaded. Cannot clean unused keys." << std::endl; - return ; - } - - // grab at most 10 identities to delete. No need to send too many requests to the token queue at once. - IdCacheEntryCleaner idcec(mKeysTS,mMaxKeepKeysBanned) ; - - mKeyCache.applyToAllCachedEntries(idcec,&IdCacheEntryCleaner::processEntry); - - ids_to_delete = idcec.ids_to_delete ; - } - std::cerr << "Collected " << ids_to_delete.size() << " keys to delete among " << mKeyCache.size() << std::endl; - - for(std::list::const_iterator it(ids_to_delete.begin());it!=ids_to_delete.end();++it) - { -#ifdef DEBUG_IDS - std::cerr << "Deleting identity " << *it << " which is too old." << std::endl; -#endif - uint32_t token ; - RsGxsIdGroup group; - group.mMeta.mGroupId=RsGxsGroupId(*it); - rsIdentity->deleteIdentity(token, group); - - { - RS_STACK_MUTEX(mIdMtx) ; - mKeysTS.erase(*it) ; - - // mPublicKeyCache.erase(*it) ; no need to do it now. It's done in p3IdService::deleteGroup() - } - } -} - -void p3IdService::service_tick() -{ - RsTickEvent::tick_events(); - GxsTokenQueue::checkRequests(); // GxsTokenQueue handles all requests. - - rstime_t now = time(NULL) ; - - if(mLastKeyCleaningTime + MAX_DELAY_BEFORE_CLEANING < now) - { - cleanUnusedKeys() ; - mLastKeyCleaningTime = now ; - } - - if(mLastPGPHashProcessTime + PGPHASH_PROC_PERIOD < now && !mGroupsToProcess.empty()) - { - pgphash_process(); - mLastPGPHashProcessTime=now; - } - - return; -} - -bool p3IdService::acceptNewGroup(const RsGxsGrpMetaData *grpMeta) -{ - bool res = !rsReputations->isIdentityBanned(RsGxsId(grpMeta->mGroupId)) ; - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::acceptNewGroup: ID=" << grpMeta->mGroupId << ": " << (res?"ACCEPTED":"DENIED") << std::endl; -#endif - - return res ; -} - -void p3IdService::notifyChanges(std::vector &changes) -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::notifyChanges()"; - std::cerr << std::endl; -#endif - - /* iterate through and grab any new messages */ - std::list unprocessedGroups; - - for(uint32_t i = 0;i(changes[i]); - - if (msgChange && !msgChange->metaChange()) - RsWarn() << __PRETTY_FUNCTION__ << " Found a Msg data change in p3IdService. This is quite unexpected." << std::endl; - - RsGxsGroupChange *groupChange = dynamic_cast(changes[i]); - - if (groupChange) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::notifyChanges() Found Group Change Notification"; - std::cerr << std::endl; -#endif - const RsGxsGroupId& gid(groupChange->mGroupId); -#ifdef DEBUG_IDS - std::cerr << "p3IdService::notifyChanges() Auto Subscribe to Incoming Groups: " << gid; - std::cerr << std::endl; -#endif - - if(!rsReputations->isIdentityBanned(RsGxsId(gid))) - { - // notify that a new identity is received, if needed - - bool should_subscribe = false; - - switch(groupChange->getType()) - { - case RsGxsNotify::TYPE_PROCESSED: break ; // Happens when the group is subscribed. This is triggered by RsGenExchange::subscribeToGroup, so better not - // call it again from here!! - - case RsGxsNotify::TYPE_UPDATED: - case RsGxsNotify::TYPE_PUBLISHED: - { - auto ev = std::make_shared(); - ev->mIdentityId = gid; - ev->mIdentityEventCode = RsGxsIdentityEventCode::UPDATED_IDENTITY; - rsEvents->postEvent(ev); - - // also time_stamp the key that this group represents - timeStampKey(RsGxsId(gid),RsIdentityUsage(RsServiceType(serviceType()),RsIdentityUsage::IDENTITY_NEW_FROM_GXS_SYNC)) ; - should_subscribe = true; - } - break; - - case RsGxsNotify::TYPE_RECEIVED_NEW: - { - auto ev = std::make_shared(); - ev->mIdentityId = gid; - ev->mIdentityEventCode = RsGxsIdentityEventCode::NEW_IDENTITY; - rsEvents->postEvent(ev); - - // also time_stamp the key that this group represents - timeStampKey(RsGxsId(gid),RsIdentityUsage(RsServiceType(serviceType()),RsIdentityUsage::IDENTITY_NEW_FROM_GXS_SYNC)) ; - should_subscribe = true; - - std::cerr << "Received new identity " << gid << " and subscribing to it" << std::endl; - } - break; - - default: - break; - } - - if(should_subscribe) - { - uint32_t token; - RsGenExchange::subscribeToGroup(token, gid, true); - - // we need to acknowledge the token in a async process - - RsThread::async( [this,token]() - { - std::chrono::milliseconds maxWait = std::chrono::milliseconds(10000); - std::chrono::milliseconds checkEvery = std::chrono::milliseconds(100); - - auto timeout = std::chrono::steady_clock::now() + maxWait; // wait for 10 secs at most - auto st = requestStatus(token); - - while( !(st == RsTokenService::FAILED || st >= RsTokenService::COMPLETE) && std::chrono::steady_clock::now() < timeout ) - { - std::this_thread::sleep_for(checkEvery); - st = requestStatus(token); - } - - RsGxsGroupId grpId; - acknowledgeGrp(token,grpId); - }); - } - - } - } - - delete changes[i]; - } -} - -/********************************************************************************/ -/******************* RsIdentity Interface ***************************************/ -/********************************************************************************/ - -#if 0 -bool p3IdService:: getNickname(const RsGxsId &id, std::string &nickname) -{ - return false; -} -#endif - -rstime_t p3IdService::getLastUsageTS(const RsGxsId &id) -{ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - return locked_getLastUsageTS(id) ; -} - -bool p3IdService::getIdDetails(const RsGxsId &id, RsIdentityDetails &details) -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::getIdDetails(" << id << ")"; - std::cerr << std::endl; -#endif - - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - RsGxsIdCache data; - - if (mKeyCache.fetch(id, data)) - { - bool is_a_contact = (mContacts.find(id) != mContacts.end()); - - details = data.details; - - if(mAutoAddFriendsIdentitiesAsContacts && (!is_a_contact) && (details.mFlags & RS_IDENTITY_FLAGS_PGP_KNOWN) && rsPeers->isPgpFriend(details.mPgpId)) - { - mContacts.insert(id) ; - slowIndicateConfigChanged() ; - - is_a_contact = true; - } - - // This step is needed, because p3GxsReputation does not know all identities, and might not have any data for - // the ones in the contact list. So we change them on demand. - - if(is_a_contact && rsReputations->autoPositiveOpinionForContacts()) - { - RsOpinion op; - if( rsReputations->getOwnOpinion(id,op) && - op == RsOpinion::NEUTRAL ) - rsReputations->setOwnOpinion(id, RsOpinion::POSITIVE); - } - - std::map::const_iterator it = mKeysTS.find(id) ; - - if(it == mKeysTS.end()) - details.mLastUsageTS = 0 ; - else - { - details.mLastUsageTS = it->second.TS ; - details.mUseCases = it->second.usage_map ; - } - details.mPublishTS = data.mPublishTs; - - // one utf8 symbol can be at most 4 bytes long - would be better to measure real unicode length !!! - if(details.mNickname.length() > RSID_MAXIMUM_NICKNAME_SIZE*4) - details.mNickname = "[too long a name]" ; - - rsReputations->getReputationInfo(id,details.mPgpId,details.mReputation) ; - - return true; - } - } - - /* it isn't there - add to public requests */ - cache_request_load(id); - - return false; -} - -bool p3IdService::isOwnId(const RsGxsId& id) -{ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - return std::find(mOwnIds.begin(),mOwnIds.end(),id) != mOwnIds.end() ; -} - - -bool p3IdService::getOwnSignedIds(std::vector& ids) -{ - ids.clear(); - - std::chrono::seconds maxWait(5); - auto timeout = std::chrono::steady_clock::now() + maxWait; - while( !ownIdsAreLoaded() && std::chrono::steady_clock::now() < timeout ) - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - - if(ownIdsAreLoaded()) - { - RS_STACK_MUTEX(mIdMtx); - ids.resize(mOwnSignedIds.size()); - std::copy(mOwnSignedIds.begin(), mOwnSignedIds.end(), ids.begin()); - return true; - } - - return false; -} - -bool p3IdService::getOwnPseudonimousIds(std::vector& ids) -{ - ids.clear(); - std::vector signedV; - - // this implicitely ensure ids are already loaded ;) - if(!getOwnSignedIds(signedV)) return false; - - std::set signedS(signedV.begin(), signedV.end()); - - { - RS_STACK_MUTEX(mIdMtx); - ids.resize(mOwnIds.size() - signedV.size()); - std::copy_if( mOwnIds.begin(), mOwnIds.end(), ids.begin(), - [&](const RsGxsId& id) {return !signedS.count(id);} ); - } - - return true; -} - -bool p3IdService::getOwnIds(std::list &ownIds,bool signed_only) -{ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - if(!mOwnIdsLoaded) - { - std::cerr << "p3IdService::getOwnIds(): own identities are not loaded yet." << std::endl; - return false ; - } - - ownIds = signed_only ? mOwnSignedIds : mOwnIds; - - return true ; -} - -bool p3IdService::isKnownId(const RsGxsId& id) -{ - RS_STACK_MUTEX(mIdMtx); - return mKeyCache.is_cached(id) || - std::find(mOwnIds.begin(), mOwnIds.end(),id) != mOwnIds.end(); -} - -bool p3IdService::serialiseIdentityToMemory( const RsGxsId& id, - std::string& radix_string ) -{ - RS_STACK_MUTEX(mIdMtx); - - // look into cache. If available, return the data. If not, request it. - - std::map::const_iterator it = mSerialisedIdentities.find(id); - - if(it != mSerialisedIdentities.end()) - { - Radix64::encode(it->second.mMem,it->second.mSize,radix_string) ; - - if(it->second.mLastUsageTS + MAX_SERIALISED_IDENTITY_AGE > time(NULL)) - return true ; - - std::cerr << "Identity " << id << " will be re-serialised, because the last record is too old." << std::endl; - } - - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - uint32_t token = 0; - std::list groupIds; - - groupIds.push_back(RsGxsGroupId(id)) ; - - RsGenExchange::getTokenService()->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds); - GxsTokenQueue::queueRequest(token, GXSIDREQ_SERIALIZE_TO_MEMORY); - - return false; -} - -void p3IdService::handle_get_serialized_grp(uint32_t token) -{ - // store the serialized data in cache. - - unsigned char *mem = NULL; - uint32_t size; - RsGxsGroupId id ; - - if(!RsGenExchange::getSerializedGroupData(token,id, mem,size)) - { - std::cerr << "(EE) call to RsGenExchage::getSerializedGroupData() failed." << std::endl; - return ; - } - - std::cerr << "Received serialised group from RsGenExchange." << std::endl; - - std::map::const_iterator it = mSerialisedIdentities.find(RsGxsId(id)); - - if(it != mSerialisedIdentities.end()) - free(it->second.mMem) ; - - SerialisedIdentityStruct s ; - s.mMem = mem ; - s.mSize = size ; - s.mLastUsageTS = time(NULL) ; - - mSerialisedIdentities[RsGxsId(id)] = s ; -} - -bool p3IdService::deserialiseIdentityFromMemory(const std::string& radix_string, - RsGxsId* id /* = nullptr */) -{ - std::vector mem = Radix64::decode(radix_string); - - if(mem.empty()) - { - std::cerr << __PRETTY_FUNCTION__ << "Cannot decode radix string \"" - << radix_string << "\"" << std::endl; - return false; - } - - if( !RsGenExchange::deserializeGroupData( - mem.data(), mem.size(), reinterpret_cast(id)) ) - { - std::cerr << __PRETTY_FUNCTION__ << "Cannot load identity from radix " - << "string \"" << radix_string << "\"" << std::endl; - return false; - } - - return true; -} - -bool p3IdService::createIdentity( RsGxsId& id, const std::string& name, const RsGxsImage& avatar, bool pseudonimous, const std::string& pgpPassword) -{ - bool ret = true; - RsIdentityParameters params; - uint32_t token = 0; - RsGroupMetaData meta; - RsTokenService::GxsRequestStatus wtStatus = RsTokenService::CANCELLED; - - if(!pseudonimous && !pgpPassword.empty()) - { - if(!rsNotify->cachePgpPassphrase(pgpPassword)) - { - RsErr() << __PRETTY_FUNCTION__ << " Failure caching password" << std::endl; - ret = false; - goto LabelCreateIdentityCleanup; - } - - if(!rsNotify->setDisableAskPassword(true)) - { - RsErr() << __PRETTY_FUNCTION__ << " Failure disabling password user request" << std::endl; - ret = false; - goto LabelCreateIdentityCleanup; - } - } - - params.isPgpLinked = !pseudonimous; - params.nickname = name; - params.mImage = avatar; - - if(!createIdentity(token, params)) - { - RsErr() << __PRETTY_FUNCTION__ << " Failed creating GXS group." << std::endl; - ret = false; - goto LabelCreateIdentityCleanup; - } - - /* Use custom timeout for waitToken because creating identities involves - * creating multiple signatures, which can take a lot of time expecially on - * slow hardware like phones or embedded devices */ - if( (wtStatus = waitToken( - token, std::chrono::seconds(10), std::chrono::milliseconds(20) )) - != RsTokenService::COMPLETE ) - { - RsErr() << __PRETTY_FUNCTION__ << " waitToken("<< token << ") failed with: " << wtStatus << std::endl; - ret = false; - goto LabelCreateIdentityCleanup; - } - - if(!RsGenExchange::getPublishedGroupMeta(token, meta)) - { - RsErr() << __PRETTY_FUNCTION__ << " Failure getting updated group data." << std::endl; - ret = false; - goto LabelCreateIdentityCleanup; - } - - id = RsGxsId(meta.mGroupId); - - { - RS_STACK_MUTEX(mIdMtx); - mOwnIds.push_back(id); - if(!pseudonimous) mOwnSignedIds.push_back(id); - } - -LabelCreateIdentityCleanup: - if(!pseudonimous && !pgpPassword.empty()) - { - rsNotify->setDisableAskPassword(false); - rsNotify->clearPgpPassphrase(); - } - - return ret; -} - -bool p3IdService::createIdentity(uint32_t& token, RsIdentityParameters ¶ms) -{ - - RsGxsIdGroup id; - - id.mMeta.mGroupName = params.nickname; - id.mMeta.mCircleType = GXS_CIRCLE_TYPE_PUBLIC ; - id.mImage = params.mImage; - - if (params.isPgpLinked) - { -#warning csoler 2017-02-07: Backward compatibility issue to fix here in v0.7.0 - - // This is a hack, because a bad decision led to having RSGXSID_GROUPFLAG_REALID be equal to GXS_SERV::FLAG_PRIVACY_PRIVATE. - // In order to keep backward compatibility, we'll also add the new value - // When the ID is not PGP linked, the group flag cannot be let empty, so we use PUBLIC. - // - // The correct combination of flags should be: - // PGP-linked: GXS_SERV::FLAGS_PRIVACY_PUBLIC | RSGXSID_GROUPFLAG_REALID - // Anonymous : GXS_SERV::FLAGS_PRIVACY_PUBLIC - - id.mMeta.mGroupFlags |= GXS_SERV::FLAG_PRIVACY_PRIVATE; // this is also equal to RSGXSID_GROUPFLAG_REALID_deprecated - id.mMeta.mGroupFlags |= RSGXSID_GROUPFLAG_REALID; - - // The current version should be able to produce new identities that old peers will accept as well. - // In the future, we need to: - // - set the current group flags here (see above) - // - replace all occurences of RSGXSID_GROUPFLAG_REALID_deprecated by RSGXSID_GROUPFLAG_REALID in the code. - } - else - id.mMeta.mGroupFlags |= GXS_SERV::FLAG_PRIVACY_PUBLIC; - - // Anticipate signature validation, since we're creating the signature ourselves. - - SSGxsIdGroup ssdata; - ssdata.pgp.validatedSignature = params.isPgpLinked; - - if(params.isPgpLinked) - { - ssdata.pgp.pgpId = AuthPGP::getPgpOwnId(); - ssdata.pgp.lastCheckTs = time(nullptr); - } - - /* save string */ - id.mMeta.mServiceString = ssdata.save(); - - createGroup(token, id); - - return true; -} - -bool p3IdService::updateIdentity( const RsGxsId& id, const std::string& name, const RsGxsImage& avatar, bool pseudonimous, const std::string& pgpPassword) -{ - // 1 - get back the identity group - - std::vector idsInfo; - - if(!getIdentitiesInfo(std::set{ id }, idsInfo)) - return false; - - RsGxsIdGroup& group(idsInfo[0]); - - // 2 - update it with the new information - - group.mMeta.mGroupName = name; - group.mMeta.mCircleType = GXS_CIRCLE_TYPE_PUBLIC ; - group.mImage = avatar; - - if(!pseudonimous) - { -#warning csoler 2020-01-21: Backward compatibility issue to fix here in v0.7.0 - - // This is a hack, because a bad decision led to having RSGXSID_GROUPFLAG_REALID be equal to GXS_SERV::FLAG_PRIVACY_PRIVATE. - // In order to keep backward compatibility, we'll also add the new value - // When the ID is not PGP linked, the group flag cannot be let empty, so we use PUBLIC. - // - // The correct combination of flags should be: - // PGP-linked: GXS_SERV::FLAGS_PRIVACY_PUBLIC | RSGXSID_GROUPFLAG_REALID - // Anonymous : GXS_SERV::FLAGS_PRIVACY_PUBLIC - - group.mMeta.mGroupFlags |= GXS_SERV::FLAG_PRIVACY_PRIVATE; // this is also equal to RSGXSID_GROUPFLAG_REALID_deprecated - group.mMeta.mGroupFlags |= RSGXSID_GROUPFLAG_REALID; - - // The current version should be able to produce new identities that old peers will accept as well. - // In the future, we need to: - // - set the current group flags here (see above) - // - replace all occurences of RSGXSID_GROUPFLAG_REALID_deprecated by RSGXSID_GROUPFLAG_REALID in the code. - } - else - group.mMeta.mGroupFlags |= GXS_SERV::FLAG_PRIVACY_PUBLIC; - - uint32_t token; - bool ret = true; - - // Cache pgp passphrase to allow a proper re-signing of the group data - - if(!pseudonimous && !pgpPassword.empty()) - { - if(!rsNotify->cachePgpPassphrase(pgpPassword)) - { - RsErr() << __PRETTY_FUNCTION__ << " Failure caching password" << std::endl; - ret = false; - goto LabelUpdateIdentityCleanup; - } - - if(!rsNotify->setDisableAskPassword(true)) - { - RsErr() << __PRETTY_FUNCTION__ << " Failure disabling password user request" << std::endl; - ret = false; - goto LabelUpdateIdentityCleanup; - } - } - mKeyCache.erase(id); - - if(!updateGroup(token, group)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failed updating group." << std::endl; - ret = false; - goto LabelUpdateIdentityCleanup; - } - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed." << std::endl; - ret = false; - goto LabelUpdateIdentityCleanup; - } - - // clean the Identity cache as well - cache_request_load(id); - -LabelUpdateIdentityCleanup: - if(!pseudonimous && !pgpPassword.empty()) - rsNotify->clearPgpPassphrase(); - - return ret; -} - -bool p3IdService::deleteIdentity(RsGxsId& id) -{ - uint32_t token; - RsGxsGroupId grouId = RsGxsGroupId(id); - if(!deleteGroup(token, grouId)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failed deleting group." - << std::endl; - return false; - } - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed." - << std::endl; - return false; - } - - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mIdentityId = grouId; - ev->mIdentityEventCode = RsGxsIdentityEventCode::DELETED_IDENTITY; - rsEvents->postEvent(ev); - } - - return true; -} - -bool p3IdService::deleteIdentity(uint32_t& token, RsGxsIdGroup &group) -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::deleteIdentity()"; - std::cerr << std::endl; -#endif - - deleteGroup(token, group.mMeta.mGroupId); - - return false; -} - - -bool p3IdService::parseRecognTag(const RsGxsId &id, const std::string &nickname, - const std::string &tag, RsRecognTagDetails &details) -{ -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::parseRecognTag()"; - std::cerr << std::endl; -#endif - - RsGxsRecognTagItem *tagitem = RsRecogn::extractTag(tag); - if (!tagitem) - { - return false; - } - - bool isPending = false; - bool isValid = recogn_checktag(id, nickname, tagitem, true, isPending); - - details.valid_from = tagitem->valid_from; - details.valid_to = tagitem->valid_to; - details.tag_class = tagitem->tag_class; - details.tag_type = tagitem->tag_type; - details.signer = tagitem->sign.keyId.toStdString(); - - details.is_valid = isValid; - details.is_pending = isPending; - - delete tagitem; - - return true; -} - -bool p3IdService::getRecognTagRequest(const RsGxsId &id, const std::string &comment, uint16_t tag_class, uint16_t tag_type, std::string &tag) -{ -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::getRecognTagRequest()"; - std::cerr << std::endl; -#endif - if(!isOwnId(id)) - { - std::cerr << "(EE) cannot retrieve own key to create tag request. KeyId=" << id << std::endl; - return false ; - } - - RsTlvPrivateRSAKey key; - std::string nickname; - RsGxsIdCache data ; - - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - if(!mKeyCache.fetch(id, data)) - return false ; - - nickname = data.details.mNickname ; - key = data.priv_key ; - } - - return RsRecogn::createTagRequest(key, id, nickname, tag_class, tag_type, comment, tag); -} - - - -/********************************************************************************/ -/******************* RsGixs Interface ***************************************/ -/********************************************************************************/ - -bool p3IdService::haveKey(const RsGxsId &id) -{ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - return mKeyCache.is_cached(id); -} - -bool p3IdService::havePrivateKey(const RsGxsId &id) -{ - if(! isOwnId(id)) - return false ; - - RS_STACK_MUTEX(mIdMtx); - return mKeyCache.is_cached(id); -} - -static void mergeIds(std::map >& idmap,const RsGxsId& id,const std::list& peers) -{ - /* merge the two lists, use std::set to avoid duplicates efficiently */ - - std::set new_peers(std::begin(peers), std::end(peers)); - - std::list& stored_peers(idmap[id]); - std::copy( std::begin(stored_peers), std::end(stored_peers), - std::inserter(new_peers, std::begin(new_peers)) ); - stored_peers.clear(); - std::copy( std::begin(new_peers), std::end(new_peers), - std::inserter(stored_peers, std::begin(stored_peers)) ); -} - -bool p3IdService::requestIdentity( - const RsGxsId& id, const std::vector& peers ) -{ - std::list askPeersList(peers.begin(), peers.end()); - - // Empty list passed? Ask to all online peers. - if(askPeersList.empty()) rsPeers->getOnlineList(askPeersList); - - if(askPeersList.empty()) // Still empty? Fail! - { - RsErr() << __PRETTY_FUNCTION__ << " failure retrieving peers list" - << std::endl; - return false; - } - - RsIdentityUsage usageInfo( RsServiceType::GXSID, RsIdentityUsage::IDENTITY_NEW_FROM_EXPLICIT_REQUEST ); - - return requestKey(id, askPeersList, usageInfo); -} - -bool p3IdService::requestKey(const RsGxsId &id, const std::list& peers,const RsIdentityUsage& use_info) -{ - Dbg3() << __PRETTY_FUNCTION__ << " id: " << id << std::endl; - - if(id.isNull()) - { - RsErr() << __PRETTY_FUNCTION__ << " cannot request null id" - << std::endl; - return false; - } - - if(peers.empty()) - { - RsErr() << __PRETTY_FUNCTION__ << " cannot request id: " << id - << " to empty lists of peers" << std::endl; - return false; - } - - if(isKnownId(id)) return true; - - /* Normally we should call getIdDetails(), but since the key is not known, - * we need to dig a possibly old information from the reputation system, - * which keeps its own list of banned keys. - * Of course, the owner ID is not known at this point.c*/ - - RsReputationInfo info; - rsReputations->getReputationInfo(id, RsPgpId(), info); - - if( info.mOverallReputationLevel == RsReputationLevel::LOCALLY_NEGATIVE ) - { -#ifdef DEBUG_IDS - RsInfo() << __PRETTY_FUNCTION__ << " not requesting Key " << id << " because it has been banned." << std::endl; -#endif - - RS_STACK_MUTEX(mIdMtx); - mIdsNotPresent.erase(id); - - return false; - } - - { - RS_STACK_MUTEX(mIdMtx); - mergeIds(mIdsNotPresent, id, peers); - mKeysTS[id].usage_map[use_info] = time(nullptr); - } - - return cache_request_load(id, peers); -} - -bool p3IdService::isPendingNetworkRequest(const RsGxsId& gxsId) -{ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - // if ids has beens confirmed as not physically present return - // immediately, id will be removed from list if found by auto nxs net search - if(mIdsNotPresent.find(gxsId) != mIdsNotPresent.end()) - return true; - - return false; -} - -bool p3IdService::getKey(const RsGxsId &id, RsTlvPublicRSAKey &key) -{ - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - RsGxsIdCache data; - - if (mKeyCache.fetch(id, data)) - { - key = data.pub_key; - return true; - } - } - - cache_request_load(id); - - key.keyId.clear() ; - return false; -} - -bool p3IdService::requestPrivateKey(const RsGxsId &id) -{ - if (havePrivateKey(id)) - return true; - - return cache_request_load(id); -} - -bool p3IdService::getPrivateKey(const RsGxsId &id, RsTlvPrivateRSAKey &key) -{ - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - RsGxsIdCache data; - - if (mKeyCache.fetch(id, data)) - { - key = data.priv_key; - return true; - } - } - - key.keyId.clear() ; - cache_request_load(id); - - return false ; -} - - -bool p3IdService::signData(const uint8_t *data,uint32_t data_size,const RsGxsId& own_gxs_id,RsTlvKeySignature& signature,uint32_t& error_status) -{ - RsTlvPrivateRSAKey signature_key ; - - int i ; - for(i=0;i<6;++i) - if(!getPrivateKey(own_gxs_id,signature_key) || signature_key.keyData.bin_data == NULL) - { -#ifdef DEBUG_IDS - std::cerr << " Cannot get key. Waiting for caching. try " << i << "/6" << std::endl; -#endif - rstime::rs_usleep(500 * 1000) ; // sleep for 500 msec. - } - else - break ; - - if(i == 6) - { - std::cerr << " (EE) Could not retrieve own private key for ID = " << own_gxs_id << ". Giging up sending DH session params. This should not happen." << std::endl; - error_status = RS_GIXS_ERROR_KEY_NOT_AVAILABLE ; - return false ; - } - -#ifdef DEBUG_IDS - std::cerr << " Signing..." << std::endl; -#endif - - if(!GxsSecurity::getSignature((char *)data,data_size,signature_key,signature)) - { - std::cerr << " (EE) Cannot sign for id " << own_gxs_id << ". Signature call failed." << std::endl; - error_status = RS_GIXS_ERROR_UNKNOWN ; - return false ; - } - error_status = RS_GIXS_ERROR_NO_ERROR ; - timeStampKey(own_gxs_id,RsIdentityUsage(RsServiceType(serviceType()),RsIdentityUsage::IDENTITY_GENERIC_SIGNATURE_CREATION)) ; - - return true ; -} -bool p3IdService::validateData(const uint8_t *data,uint32_t data_size,const RsTlvKeySignature& signature,bool force_load,const RsIdentityUsage& info,uint32_t& signing_error) -{ - // RsIdentityDetails details ; - // getIdDetails(signature.keyId,details); - RsTlvPublicRSAKey signature_key ; - - for(int i=0;i< (force_load?6:1);++i) - if(!getKey(signature.keyId,signature_key) || signature_key.keyData.bin_data == NULL) - { -#ifdef DEBUG_IDS - std::cerr << " Cannot get key. Waiting for caching. try " << i << "/6" << std::endl; -#endif - if(force_load) rstime::rs_usleep(500 * 1000) ; // sleep for 500 msec. - } - else - break ; - - if(signature_key.keyData.bin_data == NULL) - { -#ifdef DEBUG_IDS - std::cerr << "(EE) Cannot validate signature for unknown key " << signature.keyId << std::endl; -#endif - signing_error = RS_GIXS_ERROR_KEY_NOT_AVAILABLE ; - return false; - } - - if(!GxsSecurity::validateSignature((char*)data,data_size,signature_key,signature)) - { - std::cerr << "(SS) Signature was verified and it doesn't check! This is a security issue!" << std::endl; - signing_error = RS_GIXS_ERROR_SIGNATURE_MISMATCH ; - return false; - } - signing_error = RS_GIXS_ERROR_NO_ERROR ; - - timeStampKey(signature.keyId,info); - return true ; -} - -bool p3IdService::encryptData( const uint8_t *decrypted_data, - uint32_t decrypted_data_size, - uint8_t *& encrypted_data, - uint32_t& encrypted_data_size, - const RsGxsId& encryption_key_id, - uint32_t& error_status, - bool force_load ) -{ - RsTlvPublicRSAKey encryption_key ; - - // get the key, and let the cache find it. - for(int i=0; i<(force_load?6:1);++i) - if(getKey(encryption_key_id,encryption_key)) - break ; - else - rstime::rs_usleep(500*1000) ; // sleep half a sec. - - if(encryption_key.keyId.isNull()) - { - std::cerr << " (EE) Cannot get encryption key for id " << encryption_key_id << std::endl; - error_status = RS_GIXS_ERROR_KEY_NOT_AVAILABLE ; - return false ; - } - - if(!GxsSecurity::encrypt(encrypted_data,encrypted_data_size,decrypted_data,decrypted_data_size,encryption_key)) - { - std::cerr << " (EE) Encryption failed." << std::endl; - error_status = RS_GIXS_ERROR_UNKNOWN ; - return false ; - } - error_status = RS_GIXS_ERROR_NO_ERROR ; - timeStampKey(encryption_key_id,RsIdentityUsage(RsServiceType::GXSID,RsIdentityUsage::IDENTITY_GENERIC_ENCRYPTION)) ; - - return true ; -} - -bool p3IdService::encryptData( const uint8_t* decrypted_data, - uint32_t decrypted_data_size, - uint8_t*& encrypted_data, - uint32_t& encrypted_data_size, - const std::set& encrypt_ids, - uint32_t& error_status, bool force_load ) -{ - std::set keyNotYetFoundIds; - - for( std::set::const_iterator it = encrypt_ids.begin(); - it != encrypt_ids.end(); ++it ) - { - const RsGxsId& gId(*it); - if(gId.isNull()) - { - std::cerr << "p3IdService::encryptData(...) (EE) got null GXS id" - << std::endl; - return false; - } - else keyNotYetFoundIds.insert(&gId); - } - - if(keyNotYetFoundIds.empty()) - { - std::cerr << "p3IdService::encryptData(...) (EE) got empty GXS ids set" - << std::endl; - print_stacktrace(); - return false; - } - - std::vector encryption_keys; - int maxRounds = force_load ? 6 : 1; - for( int i=0; i < maxRounds; ++i ) - { - for( std::set::iterator it = keyNotYetFoundIds.begin(); - it !=keyNotYetFoundIds.end(); ) - { - RsTlvPublicRSAKey encryption_key; - if(getKey(**it, encryption_key) && !encryption_key.keyId.isNull()) - { - encryption_keys.push_back(encryption_key); - it = keyNotYetFoundIds.erase(it); - } - else - { - ++it; - } - } - - if(keyNotYetFoundIds.empty()) break; - else rstime::rs_usleep(500*1000); - } - - if(!keyNotYetFoundIds.empty()) - { - std::cerr << "p3IdService::encryptData(...) (EE) Cannot get " - << "encryption key for: "; - for( std::set::iterator it = keyNotYetFoundIds.begin(); - it !=keyNotYetFoundIds.end(); ++it ) - std::cerr << **it << " "; - std::cerr << std::endl; - print_stacktrace(); - - error_status = RS_GIXS_ERROR_KEY_NOT_AVAILABLE; - return false; - } - - if(!GxsSecurity::encrypt( encrypted_data, encrypted_data_size, - decrypted_data, decrypted_data_size, - encryption_keys )) - { - std::cerr << "p3IdService::encryptData(...) (EE) Encryption failed." - << std::endl; - print_stacktrace(); - - error_status = RS_GIXS_ERROR_UNKNOWN; - return false ; - } - - for( std::set::const_iterator it = encrypt_ids.begin(); - it != encrypt_ids.end(); ++it ) - { - timeStampKey( *it, - RsIdentityUsage( - RsServiceType::GXSID, - RsIdentityUsage::IDENTITY_GENERIC_ENCRYPTION ) ); - } - - error_status = RS_GIXS_ERROR_NO_ERROR; - return true; -} - -bool p3IdService::decryptData( const uint8_t *encrypted_data, - uint32_t encrypted_data_size, - uint8_t *& decrypted_data, - uint32_t& decrypted_size, - const RsGxsId& key_id, uint32_t& error_status, - bool force_load ) -{ - RsTlvPrivateRSAKey encryption_key ; - - // Get the key, and let the cache find it. It's our own key, so we should be able to find it, even if it takes - // some seconds. - - int maxRounds = force_load ? 6 : 1; - for(int i=0; i& decrypt_ids, - uint32_t& error_status, - bool force_load ) -{ - std::set keyNotYetFoundIds; - - for( std::set::const_iterator it = decrypt_ids.begin(); - it != decrypt_ids.end(); ++it ) - { - const RsGxsId& gId(*it); - if(gId.isNull()) - { - std::cerr << "p3IdService::decryptData(...) (EE) got null GXS id" - << std::endl; - print_stacktrace(); - return false; - } - else keyNotYetFoundIds.insert(&gId); - } - - if(keyNotYetFoundIds.empty()) - { - std::cerr << "p3IdService::decryptData(...) (EE) got empty GXS ids set" - << std::endl; - print_stacktrace(); - return false; - } - - std::vector decryption_keys; - int maxRounds = force_load ? 6 : 1; - for( int i=0; i < maxRounds; ++i ) - { - for( std::set::iterator it = keyNotYetFoundIds.begin(); - it !=keyNotYetFoundIds.end(); ) - { - RsTlvPrivateRSAKey decryption_key; - if( getPrivateKey(**it, decryption_key) - && !decryption_key.keyId.isNull() ) - { - decryption_keys.push_back(decryption_key); - it = keyNotYetFoundIds.erase(it); - } - else - { - ++it; - } - } - - if(keyNotYetFoundIds.empty()) break; - else rstime::rs_usleep(500*1000); - } - - if(!keyNotYetFoundIds.empty()) - { - std::cerr << "p3IdService::decryptData(...) (EE) Cannot get private key" - << " for: "; - for( std::set::iterator it = keyNotYetFoundIds.begin(); - it !=keyNotYetFoundIds.end(); ++it ) - std::cerr << **it << " "; - std::cerr << std::endl; - print_stacktrace(); - - error_status = RS_GIXS_ERROR_KEY_NOT_AVAILABLE; - return false; - } - - if(!GxsSecurity::decrypt( decrypted_data, decrypted_data_size, - encrypted_data, encrypted_data_size, - decryption_keys )) - { - std::cerr << "p3IdService::decryptData(...) (EE) Decryption failed." - << std::endl; - print_stacktrace(); - - error_status = RS_GIXS_ERROR_UNKNOWN; - return false ; - } - - for( std::set::const_iterator it = decrypt_ids.begin(); - it != decrypt_ids.end(); ++it ) - { - timeStampKey( *it, - RsIdentityUsage( - RsServiceType::GXSID, - RsIdentityUsage::IDENTITY_GENERIC_DECRYPTION ) ); - } - - error_status = RS_GIXS_ERROR_NO_ERROR; - return true; -} - -#ifdef TO_BE_REMOVED -/********************************************************************************/ -/******************* RsGixsReputation ***************************************/ -/********************************************************************************/ - -bool p3IdService::haveReputation(const RsGxsId &id) -{ - return haveKey(id); -} - -bool p3IdService::loadReputation(const RsGxsId &id, const std::list& peers) -{ - if (haveKey(id)) - return true; - else - { - if(isPendingNetworkRequest(id)) - return true; - } - - - return cache_request_load(id, peers); -} - -bool p3IdService::getReputation(const RsGxsId &id, GixsReputation &rep) -{ - /* this is the key part for accepting messages */ - - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - RsGxsIdCache data; - - if (mKeyCache.fetch(id, data)) - { - rep.id = id; - rep.score = 0;//data.details.mReputation.mOverallScore; -#ifdef DEBUG_IDS - std::cerr << "p3IdService::getReputation() id: "; - std::cerr << id.toStdString() << " score: " << - rep.score; - std::cerr << std::endl; -#endif - - return true; - } - else - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::getReputation() id: "; - std::cerr << id.toStdString() << " not cached"; - std::cerr << std::endl; -#endif - } - return false; -} -#endif - -#if 0 -class RegistrationRequest -{ -public: - RegistrationRequest(uint32_t token, RsGxsId &id, int score) - :m_extToken(token), m_id(id), m_score(score) { return; } - - uint32_t m_intToken; - uint32_t m_extToken; - RsGxsId m_id; - int m_score; -}; -#endif - - -bool p3IdService::submitOpinion(uint32_t& token, const RsGxsId &id, bool absOpinion, int score) -{ -#ifdef DEBUG_OPINION - std::cerr << "p3IdService::submitOpinion()"; - std::cerr << std::endl; -#endif - - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; - - token = RsGenExchange::generatePublicToken(); - - uint32_t intToken; - std::list groups; - groups.push_back(RsGxsGroupId(id)); - - RsGenExchange::getTokenService()->requestGroupInfo(intToken, ansType, opts, groups); - GxsTokenQueue::queueRequest(intToken, GXSIDREQ_OPINION); - - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - mPendingOpinion[intToken] = OpinionRequest(token, id, absOpinion, score); - return true; -} - - - -bool p3IdService::opinion_handlerequest(uint32_t token) -{ -#ifdef DEBUG_OPINION - std::cerr << "p3IdService::opinion_handlerequest()"; - std::cerr << std::endl; -#endif - - OpinionRequest req; - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - /* find in pendingReputation */ - std::map::iterator it; - it = mPendingOpinion.find(token); - if (it == mPendingOpinion.end()) - { - std::cerr << "p3IdService::opinion_handlerequest() ERROR finding PendingOpinion"; - std::cerr << std::endl; - - return false; - } - req = it->second; - mPendingOpinion.erase(it); - } - -#ifdef DEBUG_OPINION - std::cerr << "p3IdService::opinion_handlerequest() Id: " << req.mId << " score: " << req.mScore; - std::cerr << std::endl; -#endif - - std::list groups; - std::list groupList; - - if (!getGroupMeta(token, groups)) - { - std::cerr << "p3IdService::opinion_handlerequest() ERROR getGroupMeta()"; - std::cerr << std::endl; - - updatePublicRequestStatus(req.mToken, RsTokenService::FAILED); - return false; - } - - if (groups.size() != 1) - { - std::cerr << "p3IdService::opinion_handlerequest() ERROR group.size() != 1"; - std::cerr << std::endl; - - // error. - updatePublicRequestStatus(req.mToken, RsTokenService::FAILED); - return false; - } - RsGroupMetaData &meta = *(groups.begin()); - - if (meta.mGroupId != RsGxsGroupId(req.mId)) - { - std::cerr << "p3IdService::opinion_handlerequest() ERROR Id mismatch"; - std::cerr << std::endl; - - // error. - updatePublicRequestStatus(req.mToken, RsTokenService::FAILED); - return false; - } - - /* get the string */ - SSGxsIdGroup ssdata; - ssdata.load(meta.mServiceString); // attempt load - okay if fails. - - /* modify score */ - if (req.mAbsOpinion) - { - ssdata.score.rep.mOwnOpinion = req.mScore; - } - else - { - ssdata.score.rep.mOwnOpinion += req.mScore; - } - - // update IdScore too. - bool pgpId = (meta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility); - ssdata.score.rep.updateIdScore(pgpId, ssdata.pgp.validatedSignature); - ssdata.score.rep.update(); - - /* save string */ - std::string serviceString = ssdata.save(); -#ifdef DEBUG_OPINION - std::cerr << "p3IdService::opinion_handlerequest() new service_string: " << serviceString; - std::cerr << std::endl; -#endif - - /* set new Group ServiceString */ - uint32_t dummyToken = 0; - setGroupServiceString(dummyToken, meta.mGroupId, serviceString); - cache_update_if_cached(RsGxsId(meta.mGroupId), serviceString); - - updatePublicRequestStatus(req.mToken, RsTokenService::COMPLETE); - return true; -} - - -/********************************************************************************/ -/******************* Get/Set Data ******************************************/ -/********************************************************************************/ - -RsSerialiser *p3IdService::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser ; - - rss->addSerialType(new RsGxsIdSerialiser()) ; - rss->addSerialType(new RsGeneralConfigSerialiser()); - - return rss ; -} - -bool p3IdService::getGroupData(const uint32_t &token, std::vector &groups) -{ - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); ++vit) - { - RsGxsIdGroupItem* item = dynamic_cast(*vit); - if (item) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::getGroupData() Item is:"; - std::cerr << std::endl; - item->print(std::cerr); - std::cerr << std::endl; -#endif // DEBUG_IDS - RsGxsIdGroup group ; - item->toGxsIdGroup(group,false) ; - - { - RS_STACK_MUTEX(mIdMtx) ; - group.mLastUsageTS = locked_getLastUsageTS(RsGxsId(group.mMeta.mGroupId)) ; - } - - // Decode information from serviceString. - SSGxsIdGroup ssdata; - if (ssdata.load(group.mMeta.mServiceString)) - { - group.mPgpKnown = ssdata.pgp.validatedSignature; - group.mPgpId = ssdata.pgp.pgpId; - group.mReputation = ssdata.score.rep; -#ifdef DEBUG_IDS - std::cerr << "p3IdService::getGroupData() Success decoding ServiceString"; - std::cerr << std::endl; - std::cerr << "\t mGpgKnown: " << group.mPgpKnown; - std::cerr << std::endl; - std::cerr << "\t mGpgId: " << group.mPgpId; - std::cerr << std::endl; -#endif // DEBUG_IDS - } - else - { - group.mPgpKnown = false; - group.mPgpId.clear(); - - if(!group.mMeta.mServiceString.empty()) - std::cerr << "p3IdService::getGroupData() " << group.mMeta.mGroupId << " (" << group.mMeta.mGroupName << ") : Failed to decode, or no ServiceString \"" << group.mMeta.mServiceString << "\"" << std::endl; - } - - group.mIsAContact = (mContacts.find(RsGxsId(group.mMeta.mGroupId)) != mContacts.end()); - group.mPgpLinked = (!!(group.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility)) || !!(group.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID); - - groups.push_back(group); - delete(item); - } - else - { - std::cerr << "Not a Id Item, deleting!" << std::endl; - delete(*vit); - } - } - } - - return ok; -} - -bool p3IdService::getGroupSerializedData(const uint32_t &token, std::map& serialized_groups) -{ - unsigned char *mem = NULL; - uint32_t size; - RsGxsGroupId id ; - - serialized_groups.clear() ; - - if(!RsGenExchange::getSerializedGroupData(token,id, mem,size)) - { - std::cerr << "(EE) call to RsGenExchage::getSerializedGroupData() failed." << std::endl; - return false; - } - - std::string radix ; - - Radix64::encode(mem,size,radix) ; - - serialized_groups[RsGxsId(id)] = radix ; - - return true; -} - -/********************************************************************************/ -/********************************************************************************/ -/********************************************************************************/ - -bool p3IdService::createGroup(uint32_t& token, RsGxsIdGroup &group) -{ - RsGxsIdGroupItem* item = new RsGxsIdGroupItem(); - - item->meta = group.mMeta; - item->mImage.binData.setBinData(group.mImage.mData, group.mImage.mSize); - - RsGenExchange::publishGroup(token, item); - return true; -} - -bool p3IdService::updateGroup(uint32_t& token, RsGxsIdGroup &group) -{ - RsGxsId id(group.mMeta.mGroupId); - RsGxsIdGroupItem* item = new RsGxsIdGroupItem(); - - item->fromGxsIdGroup(group,false) ; - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::updateGroup() Updating RsGxsId: " << id; - std::cerr << std::endl; -#endif - - RsGenExchange::updateGroup(token, item); - - // if its in the cache - clear it. - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - if (mKeyCache.erase(id)) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::updateGroup() Removed from PublicKeyCache"; - std::cerr << std::endl; -#endif - } - else - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::updateGroup() Not in PublicKeyCache"; - std::cerr << std::endl; -#endif - } - } - - return true; -} - -bool p3IdService::deleteGroup(uint32_t& token, RsGxsGroupId& groupId) -{ - RsGxsId id(groupId); - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::deleteGroup() Deleting RsGxsId: " << id; - std::cerr << std::endl; -#endif - - RsGenExchange::deleteGroup(token, groupId); - - // if its in the cache - clear it. - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - if (mKeyCache.erase(id)) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::deleteGroup() Removed from PublicKeyCache"; - std::cerr << std::endl; -#endif - } - else - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::deleteGroup() Not in PublicKeyCache"; - std::cerr << std::endl; -#endif - } - - std::list::iterator lit = std::find( mOwnIds.begin(), mOwnIds.end(), id); - if (lit != mOwnIds.end()) - { - mOwnIds.remove((RsGxsId)*lit); -#ifdef DEBUG_IDS - std::cerr << "p3IdService::deleteGroup() Removed from OwnIds"; - std::cerr << std::endl; -#endif - } - else - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::deleteGroup() Not in OwnIds"; - std::cerr << std::endl; -#endif - } - } - - return true; -} - -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ - -/* Encoding / Decoding Group Service String stuff - * - * Pgp stuff. - * - * If flagged as pgp id.... - * then we need to know if its been matched, or when we last tried to match. - * - */ - -bool SSGxsIdPgp::load(const std::string &input) -{ - char pgpline[RSGXSID_MAX_SERVICE_STRING]; - int timestamp = 0; - uint32_t attempts = 0; - if (1 == sscanf(input.c_str(), "K:1 I:%[^)]", pgpline)) - { - validatedSignature = true; - std::string str_line = pgpline; - pgpId = RsPgpId(str_line); - return true; - } - else if (3 == sscanf(input.c_str(), "K:0 T:%d C:%d I:%[^)]", ×tamp, &attempts,pgpline)) - { - lastCheckTs = timestamp; - checkAttempts = attempts; - validatedSignature = false; - std::string str_line = pgpline; - pgpId = RsPgpId(str_line); - return true; - } - else if (2 == sscanf(input.c_str(), "K:0 T:%d C:%d", ×tamp, &attempts)) - { - lastCheckTs = timestamp; - checkAttempts = attempts; - validatedSignature = false; - return true; - } - else if (1 == sscanf(input.c_str(), "K:0 T:%d", ×tamp)) - { - lastCheckTs = timestamp; - checkAttempts = 0; - validatedSignature = false; - return true; - } - else - { - lastCheckTs = 0; - checkAttempts = 0; - validatedSignature = false; - return false; - } -} - -std::string SSGxsIdPgp::save() const -{ - std::string output; - if (validatedSignature) - { - output += "K:1 I:"; - output += pgpId.toStdString(); - } - else - { - rs_sprintf(output, "K:0 T:%d C:%d", lastCheckTs, checkAttempts); - - if(!pgpId.isNull()) - output += " I:"+pgpId.toStdString(); - } - return output; -} - - -/* Encoding / Decoding Group Service String stuff - * - * RecognTags. - */ - -bool SSGxsIdRecognTags::load(const std::string &input) -{ - //char pgpline[RSGXSID_MAX_SERVICE_STRING]; - int pubTs = 0; - int lastTs = 0; - uint32_t flags = 0; - - if (3 == sscanf(input.c_str(), "F:%u P:%d T:%d", &flags, &pubTs, &lastTs)) - { - publishTs = pubTs; - lastCheckTs = lastTs; - tagFlags = flags; - } - else - { - return false; - } - return true; -} - -std::string SSGxsIdRecognTags::save() const -{ - std::string output; - rs_sprintf(output, "F:%u P:%d T:%d", tagFlags, publishTs, lastCheckTs); - return output; -} - -bool SSGxsIdRecognTags::tagsProcessed() const -{ - return (tagFlags & 0x1000); -} - -bool SSGxsIdRecognTags::tagsPending() const -{ - return (tagFlags & 0x2000); -} - -bool SSGxsIdRecognTags::tagValid(int i) const -{ - uint32_t idx = 0x01 << i; - -#ifdef DEBUG_RECOGN - std::cerr << "SSGxsIdRecognTags::tagValid(" << i << ") idx: " << idx; - std::cerr << " result: " << (tagFlags & idx); - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - return (tagFlags & idx); -} - -void SSGxsIdRecognTags::setTags(bool processed, bool pending, uint32_t flags) -{ - flags &= 0x00ff; // clear top bits; - if (processed) - { - flags |= 0x1000; - } - if (pending) - { - flags |= 0x2000; - } - -#ifdef DEBUG_RECOGN - std::cerr << "SSGxsIdRecognTags::setTags(" << processed << "," << pending << "," << flags << ")"; - std::cerr << " tagFlags: " << tagFlags; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - tagFlags = flags; -} - - -GxsReputation::GxsReputation() - :mOverallScore(0), mIdScore(0), mOwnOpinion(0), mPeerOpinion(0) -{ - updateIdScore(false, false); - update(); -} - -static const int kIdReputationPgpKnownScore = 50; -static const int kIdReputationPgpUnknownScore = 20; -static const int kIdReputationAnonScore = 5; - -bool GxsReputation::updateIdScore(bool pgpLinked, bool pgpKnown) -{ - if (pgpLinked) - { - if (pgpKnown) - { - mIdScore = kIdReputationPgpKnownScore; - } - else - { - mIdScore = kIdReputationPgpUnknownScore; - } - } - else - { - mIdScore = kIdReputationAnonScore; - } - return true; -} - -bool GxsReputation::update() -{ - mOverallScore = mIdScore + mOwnOpinion + mPeerOpinion; - return true; -} - - -bool SSGxsIdReputation::load(const std::string &input) -{ - return (4 == sscanf(input.c_str(), "%d %d %d %d", - &(rep.mOverallScore), &(rep.mIdScore), &(rep.mOwnOpinion), &(rep.mPeerOpinion))); -} - -std::string SSGxsIdReputation::save() const -{ - std::string output; - rs_sprintf(output, "%d %d %d %d", rep.mOverallScore, rep.mIdScore, rep.mOwnOpinion, rep.mPeerOpinion); - return output; -} - - -bool SSGxsIdCumulator::load(const std::string &input) -{ - return (4 == sscanf(input.c_str(), "%d %d %lf %lf", &count, &nullcount, &sum, &sumsq)); -} - -std::string SSGxsIdCumulator::save() const -{ - std::string output; - rs_sprintf(output, "%d %d %lf %lf", count, nullcount, sum, sumsq); - return output; -} - -bool SSGxsIdGroup::load(const std::string &input) -{ - char pgpstr[RSGXSID_MAX_SERVICE_STRING]; - char recognstr[RSGXSID_MAX_SERVICE_STRING]; - char scorestr[RSGXSID_MAX_SERVICE_STRING]; - - // split into parts. - if (3 != sscanf(input.c_str(), "v2 {P:%[^}]}{T:%[^}]}{R:%[^}]}", pgpstr, recognstr, scorestr)) - { -#ifdef DEBUG_SERVICE_STRING - std::cerr << "SSGxsIdGroup::load() Failed to extract 4 Parts"; - std::cerr << std::endl; -#endif // DEBUG_IDS - return false; - } - - bool ok = true; - if (pgp.load(pgpstr)) - { -#ifdef DEBUG_SERVICE_STRING - std::cerr << "SSGxsIdGroup::load() pgpstr: " << pgpstr; - std::cerr << std::endl; -#endif // DEBUG_IDS - } - else - { -#ifdef DEBUG_SERVICE_STRING - std::cerr << "SSGxsIdGroup::load() Invalid pgpstr: " << pgpstr; - std::cerr << std::endl; -#endif // DEBUG_IDS - ok = false; - } - - if (recogntags.load(recognstr)) - { -#ifdef DEBUG_RECOGN - std::cerr << "SSGxsIdGroup::load() recognstr: " << recognstr; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - } - else - { -#ifdef DEBUG_RECOGN - std::cerr << "SSGxsIdGroup::load() Invalid recognstr: " << recognstr; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - ok = false; - } - - if (score.load(scorestr)) - { -#ifdef DEBUG_SERVICE_STRING - std::cerr << "SSGxsIdGroup::load() scorestr: " << scorestr; - std::cerr << std::endl; -#endif // DEBUG_IDS - } - else - { -#ifdef DEBUG_SERVICE_STRING - std::cerr << "SSGxsIdGroup::load() Invalid scorestr: " << scorestr; - std::cerr << std::endl; -#endif // DEBUG_IDS - ok = false; - } - -#if 0 - if (opinion.load(opinionstr)) - { -#ifdef DEBUG_IDS - std::cerr << "SSGxsIdGroup::load() opinionstr: " << opinionstr; - std::cerr << std::endl; -#endif // DEBUG_IDS - } - else - { -#ifdef DEBUG_IDS - std::cerr << "SSGxsIdGroup::load() Invalid opinionstr: " << opinionstr; - std::cerr << std::endl; -#endif // DEBUG_IDS - ok = false; - } - - if (reputation.load(repstr)) - { -#ifdef DEBUG_IDS - std::cerr << "SSGxsIdGroup::load() repstr: " << repstr; - std::cerr << std::endl; -#endif // DEBUG_IDS - } - else - { -#ifdef DEBUG_IDS - std::cerr << "SSGxsIdGroup::load() Invalid repstr: " << repstr; - std::cerr << std::endl; -#endif // DEBUG_IDS - ok = false; - } -#endif - -#ifdef DEBUG_IDS - std::cerr << "SSGxsIdGroup::load() regurgitated: " << save(); - std::cerr << std::endl; - - std::cerr << "SSGxsIdGroup::load() isOkay?: " << ok; - std::cerr << std::endl; -#endif // DEBUG_IDS - return ok; -} - -std::string SSGxsIdGroup::save() const -{ - std::string output = "v2 "; - - output += "{P:"; - output += pgp.save(); - output += "}"; - - output += "{T:"; - output += recogntags.save(); - output += "}"; - - output += "{R:"; - output += score.save(); - output += "}"; - - //std::cerr << "SSGxsIdGroup::save() output: " << output; - //std::cerr << std::endl; - - return output; -} - -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ - -/* Cache of recently used keys - * - * It is expensive to fetch the keys, so we want to keep them around if possible. - * It only stores the immutable stuff. - * - * This is probably crude and crap to start with. - * Want Least Recently Used (LRU) discard policy, without having to search whole cache. - * Use two maps: - * - CacheMap[key] => data. - * - LRUMultiMap[AccessTS] => key - * - * NOTE: This could be moved to a seperate class and templated to make generic - * as it might be generally useful. - * - */ - -RsGxsIdCache::RsGxsIdCache() {} - -RsGxsIdCache::RsGxsIdCache(const RsGxsIdGroupItem *item, const RsTlvPublicRSAKey& in_pkey, const std::list &tagList) -{ - init(item,in_pkey,RsTlvPrivateRSAKey(),tagList) ; -} - -RsGxsIdCache::RsGxsIdCache(const RsGxsIdGroupItem *item, const RsTlvPublicRSAKey& in_pkey, const RsTlvPrivateRSAKey& privkey, const std::list &tagList) -{ - init(item,in_pkey,privkey,tagList) ; -} - -void RsGxsIdCache::init(const RsGxsIdGroupItem *item, const RsTlvPublicRSAKey& in_pub_key, const RsTlvPrivateRSAKey& in_priv_key,const std::list &tagList) -{ - // Save Keys. - pub_key = in_pub_key; - priv_key = in_priv_key; - - // Save Time for ServiceString comparisions. - mPublishTs = item->meta.mPublishTs; - - // Save RecognTags. - mRecognTags = tagList; - - details.mAvatar.copy((uint8_t *) item->mImage.binData.bin_data, item->mImage.binData.bin_len); - - // Fill in Details. - details.mNickname = item->meta.mGroupName; - details.mId = RsGxsId(item->meta.mGroupId); - -#ifdef DEBUG_IDS - std::cerr << "RsGxsIdCache::RsGxsIdCache() for: " << details.mId; - std::cerr << std::endl; -#endif // DEBUG_IDS - - details.mFlags = 0 ; - - if(item->meta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) details.mFlags |= RS_IDENTITY_FLAGS_IS_OWN_ID; - if(item->meta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility) details.mFlags |= RS_IDENTITY_FLAGS_PGP_LINKED; - - // do some tests - if(details.mFlags & RS_IDENTITY_FLAGS_IS_OWN_ID) - { - if(!priv_key.checkKey()) - std::cerr << "(EE) Private key missing for own identity " << pub_key.keyId << std::endl; - - } - if(!pub_key.checkKey()) - std::cerr << "(EE) Public key missing for identity " << pub_key.keyId << std::endl; - - if(!GxsSecurity::checkFingerprint(pub_key)) - details.mFlags |= RS_IDENTITY_FLAGS_IS_DEPRECATED; - - /* rest must be retrived from ServiceString */ - updateServiceString(item->meta.mServiceString); -} - -void RsGxsIdCache::updateServiceString(std::string serviceString) -{ - details.mRecognTags.clear(); - - SSGxsIdGroup ssdata; - if (ssdata.load(serviceString)) - { - if (details.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED) - { - if(ssdata.pgp.validatedSignature) details.mFlags |= RS_IDENTITY_FLAGS_PGP_KNOWN ; - - if (details.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED) - details.mPgpId = ssdata.pgp.pgpId; - else - details.mPgpId.clear(); - } - - - // process RecognTags. - if (ssdata.recogntags.tagsProcessed()) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsGxsIdCache::updateServiceString() updating recogntags"; - std::cerr << std::endl; -#endif - if (ssdata.recogntags.publishTs == mPublishTs) - { - std::list::iterator it; - int i = 0; - for(it = mRecognTags.begin(); it != mRecognTags.end(); ++it, i++) - { - if (ssdata.recogntags.tagValid(i) && it->valid) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsGxsIdCache::updateServiceString() Valid Tag: " << it->tag_class << ":" << it->tag_type; - std::cerr << std::endl; -#endif - details.mRecognTags.push_back(*it); - } - else - { -#ifdef DEBUG_RECOGN - std::cerr << "RsGxsIdCache::updateServiceString() Invalid Tag: " << it->tag_class << ":" << it->tag_type; - std::cerr << std::endl; -#endif - } - } - } - else - { -#ifdef DEBUG_RECOGN - std::cerr << "RsGxsIdCache::updateServiceString() recogntags old publishTs"; - std::cerr << std::endl; -#endif - } - - } - else - { -#ifdef DEBUG_RECOGN - std::cerr << "RsGxsIdCache::updateServiceString() recogntags unprocessed"; - std::cerr << std::endl; -#endif - } - - // copy over Reputation scores. - //details.mReputation = ssdata.score.rep; - } - else - { - details.mFlags &= ~RS_IDENTITY_FLAGS_PGP_KNOWN ; - details.mPgpId.clear(); - //details.mReputation.updateIdScore(false, false); - //details.mReputation.update(); - } -} - - -bool p3IdService::recogn_extract_taginfo(const RsGxsIdGroupItem *item, std::list &tagItems) -{ -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_extract_taginfo()"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - /* process Recogn Tags */ - - std::list::const_iterator rit; - int count = 0; - for(rit = item->mRecognTags.begin(); rit != item->mRecognTags.end(); ++rit) - { - if (++count > RSRECOGN_MAX_TAGINFO) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_extract_taginfo() Too many tags."; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - return true; - } - - RsGxsRecognTagItem *tagitem = RsRecogn::extractTag(*rit); - - if (!tagitem) - { - continue; - } - -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_extract_taginfo() Got TagItem: "; - std::cerr << std::endl; - tagitem->print(std::cerr); -#endif // DEBUG_RECOGN - - tagItems.push_back(tagitem); - } - return true; -} - - -bool p3IdService::cache_process_recogntaginfo(const RsGxsIdGroupItem *item, std::list &tagList) -{ - /* ServiceString decode */ - SSGxsIdGroup ssdata; - bool recognProcess = false; - if (ssdata.load(item->meta.mServiceString)) - { - if (!ssdata.recogntags.tagsProcessed()) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::cache_process_recogntaginfo() tags not processed"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - /* we need to reprocess it */ - recognProcess = true; - } - else - { - if (item->meta.mPublishTs != ssdata.recogntags.publishTs) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::cache_process_recogntaginfo() publishTs old"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - recognProcess = true; - } - else if (ssdata.recogntags.tagsPending()) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::cache_process_recogntaginfo() tagsPending"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - /* reprocess once a day */ - recognProcess = true; - } - } - } - else - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::cache_process_recogntaginfo() ServiceString invalid"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - recognProcess = true; - } - - std::list tagItems; - std::list::iterator it; - - recogn_extract_taginfo(item, tagItems); - - //rstime_t now = time(NULL); - for(it = tagItems.begin(); it != tagItems.end(); ++it) - { - RsRecognTag info((*it)->tag_class, (*it)->tag_type, false); - bool isPending = false; - if (recogn_checktag(RsGxsId(item->meta.mGroupId.toStdString()), item->meta.mGroupName, *it, false, isPending)) - { - info.valid = true; - } -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::cache_process_recogntaginfo() Adding Tag: "; - std::cerr << info.tag_class << ":"; - std::cerr << info.tag_type << ":"; - std::cerr << info.valid; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - tagList.push_back(info); - delete *it; - } - - - if (recognProcess) - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - mRecognGroupIds.push_back(item->meta.mGroupId); - -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::cache_process_recogntaginfo() Reprocessing groupId: "; - std::cerr << item->meta.mGroupId; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - recogn_schedule(); - } - - return true; -} - -// Loads in the cache the group data from the given group item, retrieved from sqlite storage. - -bool p3IdService::cache_store(const RsGxsIdGroupItem *item) -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cache_store() Item: " << item->meta.mGroupId; - std::cerr << std::endl; -#endif // DEBUG_IDS - //item->print(std::cerr, 0); NEEDS CONST!!!! TODO - //std::cerr << std::endl; - - /* extract key from keys */ - RsTlvSecurityKeySet keySet; - - RsTlvPublicRSAKey pubkey; - RsTlvPrivateRSAKey fullkey; - - bool pub_key_ok = false; - bool full_key_ok = false; - - RsGxsId id (item->meta.mGroupId.toStdString()); - - if (!getGroupKeys(RsGxsGroupId(id.toStdString()), keySet)) - { - std::cerr << "p3IdService::cache_store() ERROR getting GroupKeys for: "<< item->meta.mGroupId << std::endl; - return false; - } - - for (std::map::iterator kit = keySet.private_keys.begin(); kit != keySet.private_keys.end(); ++kit) - if (kit->second.keyFlags & RSTLV_KEY_DISTRIB_ADMIN) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cache_store() Found Admin Key" << std::endl; -#endif - fullkey = kit->second; - full_key_ok = true; - } - for (std::map::iterator kit = keySet.public_keys.begin(); kit != keySet.public_keys.end(); ++kit) - if (kit->second.keyFlags & RSTLV_KEY_DISTRIB_ADMIN) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cache_store() Found Admin public Key" << std::endl; -#endif - pubkey = kit->second; - pub_key_ok = true ; - } - - assert(!( pubkey.keyFlags & RSTLV_KEY_TYPE_FULL)) ; - assert(!full_key_ok || (fullkey.keyFlags & RSTLV_KEY_TYPE_FULL)) ; - - if (!pub_key_ok) - { - std::cerr << "p3IdService::cache_store() ERROR No Public Key Found"; - std::cerr << std::endl; - return false; - } - - // extract tags. - std::list tagList; - cache_process_recogntaginfo(item, tagList); - - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - // Create Cache Data. - RsGxsIdCache keycache(item, pubkey, fullkey,tagList); - - if(mContacts.find(id) != mContacts.end()) - keycache.details.mFlags |= RS_IDENTITY_FLAGS_IS_A_CONTACT; - - mKeyCache.store(id, keycache); - mKeyCache.resize(); - - return true; -} - - - -/***** BELOW LOADS THE CACHE FROM GXS DATASTORE *****/ - -#define MIN_CYCLE_GAP 2 - -bool p3IdService::cache_request_load(const RsGxsId &id, const std::list &peers) -{ - Dbg4() << __PRETTY_FUNCTION__ << " id: " << id << std::endl; - - { - RS_STACK_MUTEX(mIdMtx); - // merge, even if peers is empty - mergeIds(mCacheLoad_ToCache, id, peers); - } - - if(RsTickEvent::event_count(GXSID_EVENT_CACHELOAD) > 0) - { - Dbg3() << __PRETTY_FUNCTION__ << " cache reload already scheduled " - << "skipping" << std::endl; - return true; - } - - int32_t age = 0; - if( RsTickEvent::prev_event_ago(GXSID_EVENT_CACHELOAD, age) && age < MIN_CYCLE_GAP ) - { - RsTickEvent::schedule_in(GXSID_EVENT_CACHELOAD, MIN_CYCLE_GAP - age); - return true; - } - - RsTickEvent::schedule_now(GXSID_EVENT_CACHELOAD); - return true; -} - - -bool p3IdService::cache_start_load() -{ - /* trigger request to load missing ids into cache */ - std::list groupIds; - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - /* now we process the modGroupList -> a map so we can use it easily later, and create id list too */ - std::map >::iterator it; - for(it = mCacheLoad_ToCache.begin(); it != mCacheLoad_ToCache.end(); ++it) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cache_start_load() GroupId: " << it->first; - std::cerr << std::endl; -#endif // DEBUG_IDS - groupIds.push_back(RsGxsGroupId(it->first)); // might need conversion? - } - - for(std::map >::const_iterator it(mCacheLoad_ToCache.begin());it!=mCacheLoad_ToCache.end();++it) - mergeIds(mPendingCache,it->first,it->second) ; - - mCacheLoad_ToCache.clear(); - } - - if (groupIds.size() > 0) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cache_start_load() #Groups: " << groupIds.size(); - std::cerr << std::endl; -#endif // DEBUG_IDS - - uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - uint32_t token = 0; - - RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts, groupIds); - GxsTokenQueue::queueRequest(token, GXSIDREQ_CACHELOAD); - } - return 1; -} - - -bool p3IdService::cache_load_for_token(uint32_t token) -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cache_load_for_token() : " << token; - std::cerr << std::endl; -#endif // DEBUG_IDS - - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); ++vit) - { - RsGxsIdGroupItem* item = dynamic_cast(*vit); - if (!item) - { - std::cerr << "Not a RsGxsIdGroupItem Item, deleting!" << std::endl; - delete(*vit); - continue; - } - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cache_load_for_token() Loaded Id with Meta: "; - std::cerr << item->meta; - std::cerr << std::endl; -#endif // DEBUG_IDS - - - { - // remove identities that are present - RsStackMutex stack(mIdMtx); - mPendingCache.erase(RsGxsId(item->meta.mGroupId.toStdString())); - } - - /* cache the data */ - cache_store(item); - delete item; - } - - { - // now store identities that aren't present - - RsStackMutex stack(mIdMtx); - - // No need to merge empty peers since the request would fail. - - for(std::map >::const_iterator itt(mPendingCache.begin());itt!=mPendingCache.end();++itt) - if(!itt->second.empty()) - mergeIds(mIdsNotPresent,itt->first,itt->second) ; -#ifdef DEBUG_IDS - else - std::cerr << "(WW) empty list of peers to request ID " << itt->first << ": cannot request" << std::endl; -#endif - - - mPendingCache.clear(); - - if(!mIdsNotPresent.empty()) - schedule_now(GXSID_EVENT_REQUEST_IDS); - } - - } - else - { - std::cerr << "p3IdService::cache_load_for_token() ERROR no data"; - std::cerr << std::endl; - - return false; - } - return true; -} - -void p3IdService::requestIdsFromNet() -{ - RS_STACK_MUTEX(mIdMtx); - - if(!mNes) - { - RsErr() << __PRETTY_FUNCTION__ << " Cannot request missing GXS IDs " - << "because network service is not present." << std::endl; - return; - } - - std::map >::iterator cit; - std::map > requests; - - /* Transform to appropriate structure ( > map) - * to make request to nes per peer ID - * Only delete entries in mIdsNotPresent that can actually be performed, or - * that have empty peer list */ - - for(cit = mIdsNotPresent.begin(); cit != mIdsNotPresent.end();) - { -#ifdef DEBUG_IDS - Dbg2() << __PRETTY_FUNCTION__ << " Processing missing key RsGxsId: " << cit->first << std::endl; -#endif - RsGxsIdCache data; - - if(mKeyCache.fetch(cit->first,data)) - { -#ifdef DEBUG_IDS - std::cerr << __PRETTY_FUNCTION__ << ". Dropping request for ID " << cit->first << " at last minute, because it was found in cache"<< std::endl; -#endif - auto tmp(cit); - ++tmp; - mIdsNotPresent.erase(cit); - cit = tmp; - continue; - } - - const RsGxsId& gxsId = cit->first; - const std::list& peers = cit->second; - std::list::const_iterator cit2; - - bool request_can_proceed = false ; - - for(cit2 = peers.begin(); cit2 != peers.end(); ++cit2) - { - const RsPeerId& peer = *cit2; - - if(rsPeers->isOnline(peer) || mNes->isDistantPeer(peer)) - { - /* make sure that the peer in online, so that we know that the - * request has some chance to succeed.*/ - requests[peer].push_back(cit->first); - request_can_proceed = true ; - -#ifdef DEBUG_IDS - Dbg2() << __PRETTY_FUNCTION__ << " Moving missing key RsGxsId:" - << gxsId << " to peer: " << peer << " requests queue" - << std::endl; -#endif - } - } - - const bool noPeersFound = peers.empty(); - if(noPeersFound) - RsWarn() << __PRETTY_FUNCTION__ << " No peers supplied to request " - << "RsGxsId: " << gxsId << " dropping." << std::endl; - - if(request_can_proceed || noPeersFound) - { - std::map >::iterator tmp(cit); - ++tmp; - mIdsNotPresent.erase(cit); - cit = tmp; - } - else - { -#ifdef DEBUG_IDS - RsInfo() << __PRETTY_FUNCTION__ << " no online peers among supplied" - << " list in request for RsGxsId: " << gxsId - << ". Keeping it until peers show up."<< std::endl; -#endif - ++cit; - } - } - - for( std::map >::const_iterator cit2( - requests.begin() ); cit2 != requests.end(); ++cit2 ) - { - const RsPeerId& peer = cit2->first; - std::list grpIds; - for( std::list::const_iterator gxs_id_it = cit2->second.begin(); gxs_id_it != cit2->second.end(); ++gxs_id_it ) - { -#ifdef DEBUG_IDS - Dbg2() << __PRETTY_FUNCTION__ << " passing RsGxsId: " << *gxs_id_it - << " request for peer: " << peer - << " to RsNetworkExchangeService " << std::endl; -#endif - grpIds.push_back(RsGxsGroupId(*gxs_id_it)); - } - - mNes->requestGrp(grpIds, peer); - } -} - -bool p3IdService::cache_update_if_cached(const RsGxsId &id, std::string serviceString) -{ - /* if these entries are cached - update with new info */ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cache_update_if_cached(" << id << ")"; - std::cerr << std::endl; -#endif // DEBUG_IDS - - /* retrieve - update, save */ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - RsGxsIdCache updated_data; - - if(mKeyCache.fetch(id, updated_data)) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cache_update_if_cached() Updating Public Cache"; - std::cerr << std::endl; -#endif // DEBUG_IDS - - updated_data.updateServiceString(serviceString); - - mKeyCache.store(id, updated_data); - } - - return true; -} - -/************************************************************************************/ -/************************************************************************************/ - -bool p3IdService::cache_request_ownids() -{ - /* trigger request to load missing ids into cache */ - std::list groupIds; -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cache_request_ownids()"; - std::cerr << std::endl; -#endif // DEBUG_IDS - - uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - //opts.mSubscribeFlags = GXS_SERV::GROUP_SUBSCRIBE_ADMIN; - - uint32_t token = 0; - - RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); - GxsTokenQueue::queueRequest(token, GXSIDREQ_CACHEOWNIDS); - return true; -} - - -bool p3IdService::cache_load_ownids(uint32_t token) -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cache_load_ownids() : " << token; - std::cerr << std::endl; -#endif // DEBUG_IDS - - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - // Save List - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - mOwnIds.clear(); - for(vit = grpData.begin(); vit != grpData.end(); ++vit) - { - RsGxsIdGroupItem* item = dynamic_cast(*vit); - if (!item) - { - std::cerr << "Not a IdOpinion Item, deleting!" << std::endl; - delete(*vit); - continue; - } - - if (item->meta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) - { - mOwnIds.push_back(RsGxsId(item->meta.mGroupId)); - - SSGxsIdGroup ssdata; - - std::cerr << "Adding own ID " << item->meta.mGroupId << " mGroupFlags=" << std::hex << item->meta.mGroupFlags << std::dec; - - if (ssdata.load(item->meta.mServiceString) && ssdata.pgp.validatedSignature) // (cyril) note: we cannot use if(item->meta.mGroupFlags & RSGXSID_GROUPFLAG_REALID) - { // or we need to cmbine it with the deprecated value that overlaps with GXS_SERV::FLAG_PRIVACY_PRIVATE - std::cerr << " signed = YES" << std::endl; // see comments line 799 in ::createIdentity(); - mOwnSignedIds.push_back(RsGxsId(item->meta.mGroupId)); - } - else - std::cerr << " signed = NO" << std::endl; - - // This prevents automatic deletion to get rid of them. - // In other words, own ids are always used. - - mKeysTS[RsGxsId(item->meta.mGroupId)].TS = time(NULL) ; - } - delete item ; - } - mOwnIdsLoaded = true ; - - std::cerr << mOwnIds.size() << " own Ids loaded, " << mOwnSignedIds.size() << " of which are signed" << std::endl; - } - - // No need to cache these items... - // as it just causes the cache to be flushed. -#if 0 - // Cache Items too. - for(vit = grpData.begin(); vit != grpData.end(); ++vit) - { - RsGxsIdGroupItem* item = dynamic_cast(*vit); - if (item->meta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) - { - - std::cerr << "p3IdService::cache_load_ownids() Loaded Id with Meta: "; - std::cerr << item->meta; - std::cerr << std::endl; - - /* cache the data */ - cache_store(item); - } - delete item; - } -#endif - - } - else - { - std::cerr << "p3IdService::cache_load_ownids() ERROR no data"; - std::cerr << std::endl; - - return false; - } - return true; -} - -/************************************************************************************/ -/************************************************************************************/ - -bool p3IdService::cachetest_getlist() -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cachetest_getlist() making request"; - std::cerr << std::endl; -#endif // DEBUG_IDS - - uint32_t ansType = RS_TOKREQ_ANSTYPE_LIST; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_IDS; - uint32_t token = 0; - - RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); - GxsTokenQueue::queueRequest(token, GXSIDREQ_CACHETEST); - - // Schedule Next Event. - RsTickEvent::schedule_in(GXSID_EVENT_CACHETEST, CACHETEST_PERIOD); - return true; -} - -bool p3IdService::cachetest_handlerequest(uint32_t token) -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cachetest_handlerequest() token: " << token; - std::cerr << std::endl; -#endif // DEBUG_IDS - - std::list grpIds; - std::list grpIdsC; - bool ok = RsGenExchange::getGroupList(token, grpIdsC); - - std::list::const_iterator cit = grpIdsC.begin(); - for(; cit != grpIdsC.end(); ++cit) - grpIds.push_back(RsGxsId(cit->toStdString())); - - if(ok) - { - std::list::iterator vit = grpIds.begin(); - for(; vit != grpIds.end(); ++vit) - { - /* 5% chance of checking it! */ - if (RSRandom::random_f32() < 0.25) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cachetest_request() Testing Id: " << *vit; - std::cerr << std::endl; -#endif // DEBUG_IDS - - /* try the cache! */ - if (!haveKey(*vit)) - { - std::list nullpeers; - requestKey(*vit, nullpeers,RsIdentityUsage(RsServiceType::GXSID,RsIdentityUsage::UNKNOWN_USAGE)); - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cachetest_request() Requested Key Id: " << *vit; - std::cerr << std::endl; -#endif // DEBUG_IDS - } - else - { - RsTlvPublicRSAKey seckey; - if (getKey(*vit, seckey)) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cachetest_request() Got Key OK Id: " << *vit; - std::cerr << std::endl; -#endif // DEBUG_IDS - - // success! - seckey.print(std::cerr, 10); - std::cerr << std::endl; - - - } - else - { - std::cerr << "p3IdService::cachetest_request() ERROR no Key for Id: " << *vit; - std::cerr << std::endl; - } - } - - /* try private key too! */ - if (!havePrivateKey(*vit)) - { - requestPrivateKey(*vit); -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cachetest_request() Requested PrivateKey Id: " << *vit; - std::cerr << std::endl; -#endif // DEBUG_IDS - } - else - { - RsTlvPrivateRSAKey seckey; - if (getPrivateKey(*vit, seckey)) - { - // success! -#ifdef DEBUG_IDS - std::cerr << "p3IdService::cachetest_request() Got PrivateKey OK Id: " << *vit; - std::cerr << std::endl; -#endif // DEBUG_IDS - } - else - { - std::cerr << "p3IdService::cachetest_request() ERROR no PrivateKey for Id: " << *vit; - std::cerr << std::endl; - } - } - } - } - } - else - { - std::cerr << "p3IdService::cache_load_for_token() ERROR no data"; - std::cerr << std::endl; - - return false; - } - return true; -} - -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ - -/* - * We have three background tasks that use the ServiceString: PGPHash & Reputation & Recogn - * - * Only one task can be run at a time - otherwise potential overwrite issues. - * So this part coordinates that part of the code. - * - * We are going to have a "fetcher task", which gets all the UNPROCESSED / UPDATED GROUPS. - * and sets the CHECK_PGP, CHECK_RECOGN, etc... this will reduce the "Get All" calls. - * - */ - - -bool p3IdService::CacheArbitration(uint32_t mode) -{ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - if (!mBgSchedule_Active) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::CacheArbitration() Okay: mode " << mode; - std::cerr << std::endl; -#endif // DEBUG_IDS - - mBgSchedule_Active = true; - mBgSchedule_Mode = mode; - return true; - } - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::CacheArbitration() Is busy in mode: " << mBgSchedule_Mode; - std::cerr << std::endl; -#endif // DEBUG_IDS - - return false; -} - -void p3IdService::CacheArbitrationDone(uint32_t mode) -{ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - if (mBgSchedule_Mode != mode) - { - /* issues */ - std::cerr << "p3IdService::CacheArbitrationDone() ERROR Wrong Current Mode"; - std::cerr << std::endl; - return; - } - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::CacheArbitrationDone()"; - std::cerr << std::endl; -#endif // DEBUG_IDS - - mBgSchedule_Active = false; -} - -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ - -/* Task to determine PGPHash matches - * - * Info to be stored in GroupServiceString + Cache. - * - * Actually - it must be a Signature here - otherwise, you could - * put in a hash from someone else! - * - * Don't think that we need to match very often - maybe once a day? - * Actually - we should scale the matching based on number of keys we have. - * - * imagine - 10^6 rsa keys + 10^3 gpg keys => 10^9 combinations. - * -- far too many to check all quickly. - * - * Need to grab and cache data we need... then check over slowly. - * - * maybe grab a list of all gpgids - that we know of: store id list. - * then big GroupRequest, and iterate through these. - **/ - -//const int SHA_DIGEST_LENGTH = 20; - -static void calcPGPHash(const RsGxsId &id, const PGPFingerprintType &pgp, Sha1CheckSum &hash); - - -// Must Use meta. -RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup( - RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet ) -{ - Dbg2() << __PRETTY_FUNCTION__ << std::endl; - - RsGxsIdGroupItem *item = dynamic_cast(grpItem); - if (!item) - { - std::cerr << "p3IdService::service_CreateGroup() ERROR invalid cast"; - std::cerr << std::endl; - return SERVICE_CREATE_FAIL; - } - - item->meta.mGroupId.clear(); - - /********************* TEMP HACK UNTIL GXS FILLS IN GROUP_ID *****************/ - // find private admin key - for( std::map::iterator mit = - keySet.private_keys.begin(); mit != keySet.private_keys.end(); ++mit ) - if(mit->second.keyFlags == (RSTLV_KEY_DISTRIB_ADMIN | RSTLV_KEY_TYPE_FULL)) - { - item->meta.mGroupId = RsGxsGroupId(mit->second.keyId); - break; - } - - if(item->meta.mGroupId.isNull()) - { - RsErr() << __PRETTY_FUNCTION__ << " missing admin key!" << std::endl; - return SERVICE_CREATE_FAIL; - } - mKeysTS[RsGxsId(item->meta.mGroupId)].TS = time(NULL) ; - - /********************* TEMP HACK UNTIL GXS FILLS IN GROUP_ID *****************/ - - // SANITY CHECK. - // if (item->mMeta.mAuthorId != item->meta.mAuthorId) - // { - // std::cerr << "p3IdService::service_CreateGroup() AuthorId mismatch("; - // std::cerr << item->mMeta.mAuthorId; - // std::cerr << " vs "; - // std::cerr << item->meta.mAuthorId; - // std::cerr << std::endl; - // } - // - // if (item->group.mMeta.mGroupId != item->meta.mGroupId) - // { - // std::cerr << "p3IdService::service_CreateGroup() GroupId mismatch("; - // std::cerr << item->mMeta.mGroupId; - // std::cerr << " vs "; - // std::cerr << item->meta.mGroupId; - // std::cerr << std::endl; - // } - // - // - // if (item->group.mMeta.mGroupFlags != item->meta.mGroupFlags) - // { - // std::cerr << "p3IdService::service_CreateGroup() GroupFlags mismatch("; - // std::cerr << item->mMeta.mGroupFlags; - // std::cerr << " vs "; - // std::cerr << item->meta.mGroupFlags; - // std::cerr << std::endl; - // } - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::service_CreateGroup() for : " << item->meta.mGroupId; - std::cerr << std::endl; - std::cerr << "p3IdService::service_CreateGroup() Alt GroupId : " << item->meta.mGroupId; - std::cerr << std::endl; -#endif // DEBUG_IDS - - ServiceCreate_Return createStatus; - - if (item->meta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility) - { - /* create the hash */ - Sha1CheckSum hash; - - RsPgpFingerprint ownFinger; - RsPgpId ownId(mPgpUtils->getPGPOwnId()); - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::service_CreateGroup() OwnPgpID: " << ownId.toStdString(); - std::cerr << std::endl; -#endif - -#ifdef GXSID_GEN_DUMMY_DATA - // if (item->group.mMeta.mAuthorId != "") - // { - // ownId = RsPgpId(item->group.mMeta.mAuthorId); - // } -#endif - - if(!mPgpUtils->getKeyFingerprint(ownId,ownFinger)) - { - RsErr() << __PRETTY_FUNCTION__ - << " failure retriving own PGP fingerprint" << std::endl; - return SERVICE_CREATE_FAIL; // abandon attempt! - } - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::service_CreateGroup() OwnFingerprint: " << ownFinger.toStdString(); - std::cerr << std::endl; -#endif - - RsGxsId gxsId(item->meta.mGroupId.toStdString()); - calcPGPHash(gxsId, ownFinger, hash); - item->mPgpIdHash = hash; - -#ifdef DEBUG_IDS - - std::cerr << "p3IdService::service_CreateGroup() Calculated PgpIdHash : " << item->mPgpIdHash; - std::cerr << std::endl; -#endif // DEBUG_IDS - - /* do signature */ - - -#define MAX_SIGN_SIZE 2048 - uint8_t signarray[MAX_SIGN_SIZE]; - unsigned int sign_size = MAX_SIGN_SIZE; - memset(signarray,0,MAX_SIGN_SIZE) ; // just in case. - - int result = AuthPGP::SignDataBin( - static_cast(hash.toByteArray()), - hash.SIZE_IN_BYTES, signarray, &sign_size, - __PRETTY_FUNCTION__ ) - ? - SELF_SIGNATURE_RESULT_SUCCESS : - SELF_SIGNATURE_RESULT_FAILED; - - switch(result) - { - case SELF_SIGNATURE_RESULT_PENDING: - createStatus = SERVICE_CREATE_FAIL_TRY_LATER; - Dbg1() << __PRETTY_FUNCTION__ << " signature still pending" - << std::endl; - break; - case SELF_SIGNATURE_RESULT_SUCCESS: - { - // Additional consistency checks. - if(sign_size == MAX_SIGN_SIZE) - { - RsErr() << __PRETTY_FUNCTION__ << "Inconsistent result. " - << "Signature uses full buffer. This is probably an " - << "error." << std::endl; - return SERVICE_CREATE_FAIL; - } - - /* push binary into string -> really bad! */ - item->mPgpIdSign = ""; - for(unsigned int i = 0; i < sign_size; i++) - item->mPgpIdSign += static_cast(signarray[i]); - - createStatus = SERVICE_CREATE_SUCCESS; - break; - } - case SELF_SIGNATURE_RESULT_FAILED: /* fall-through */ - default: - RsErr() << __PRETTY_FUNCTION__ << " signature failed with: " - << result << std::endl; - return SERVICE_CREATE_FAIL; - } - } - else createStatus = SERVICE_CREATE_SUCCESS; - - // Enforce no AuthorId. - item->meta.mAuthorId.clear() ; - //item->mMeta.mAuthorId.clear() ; - // copy meta data to be sure its all the same. - //item->group.mMeta = item->meta; - - // do it like p3gxscircles: save the new grp id - // this allows the user interface - // to see the grp id on the list of ownIds immediately after the group was created - { - RS_STACK_MUTEX(mIdMtx); - RsGxsId gxsId(item->meta.mGroupId); - if (std::find(mOwnIds.begin(), mOwnIds.end(), gxsId) == mOwnIds.end()) - { - mOwnIds.push_back(gxsId); - mKeysTS[gxsId].TS = time(nullptr); - } - } - -#ifdef DEBUG_IDS - Dbg2() << __PRETTY_FUNCTION__ << " returns: " << createStatus << std::endl; -#endif - return createStatus; -} - - -#define HASHPGP_PERIOD 180 - - -bool p3IdService::pgphash_start() -{ - if (!CacheArbitration(BG_PGPHASH)) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::pgphash_start() Other Events running... Rescheduling"; - std::cerr << std::endl; -#endif // DEBUG_IDS - - /* reschedule in a bit */ - RsTickEvent::schedule_in(GXSID_EVENT_PGPHASH, PGPHASH_RETRY_PERIOD); - return false; - } - - // SCHEDULE NEXT ONE. - RsTickEvent::schedule_in(GXSID_EVENT_PGPHASH, PGPHASH_PERIOD); - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::pgphash_start() making request"; - std::cerr << std::endl; -#endif // DEBUG_IDS - - // ACTUALLY only need summary - but have written code for data. - // Also need to use opts.groupFlags to filter stuff properly to REALID's only. - // TODO - - uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; - - uint32_t token = 0; - - RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); - GxsTokenQueue::queueRequest(token, GXSIDREQ_PGPHASH); - - return true; -} - - -bool p3IdService::pgphash_handlerequest(uint32_t token) -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::pgphash_handlerequest(" << token << ")"; - std::cerr << std::endl; -#endif // DEBUG_IDS - - // We need full data - for access to Hash & Signature. - // Perhaps we will change this to an initial pass through Meta, - // and use this to discard lots of things. - - // Even better - we can set flags in the Meta Data, (IdType), - // And use GXS to filter out all the AnonIds, and only have to process - // Proper Ids. - - // We Will do this later! - - std::list group_metas; - std::list groups_to_process; - bool ok = getGroupMeta(token, group_metas); - - if(ok) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::pgphash_request() Have " << group_metas.size() << " Groups" << std::endl; -#endif // DEBUG_IDS - - for(auto vit = group_metas.begin(); vit != group_metas.end(); ++vit) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::pgphash_request() Group Id: " << vit->mGroupId << " "; -#endif // DEBUG_IDS - - /* Filter based on IdType */ - - if (!(vit->mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility)) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::pgphash_request() discarding AnonID" << std::endl; -#endif // DEBUG_IDS - continue; - } - - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - if(mGroupsToProcess.find(vit->mGroupId) != mGroupsToProcess.end()) - { -#ifdef DEBUG_IDS - std::cerr << " => already in checking list!" << std::endl; -#endif - continue; - } - } - - /* now we need to decode the Service String - see what is saved there */ - SSGxsIdGroup ssdata; - - if (ssdata.load(vit->mServiceString)) - { - if (ssdata.pgp.validatedSignature) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::pgphash_request() discarding Already Known" << std::endl; -#endif // DEBUG_IDS - continue; - } - - /* Have a linear attempt policy - - * if zero checks - try now. - * if 1 check, at least a day. - * if 2 checks: 2days, etc. - */ - -#define SECS_PER_DAY (3600 * 24) - rstime_t age = time(NULL) - ssdata.pgp.lastCheckTs; - rstime_t wait_period = ssdata.pgp.checkAttempts * SECS_PER_DAY; - - if (wait_period > 30 * SECS_PER_DAY) - wait_period = 30 * SECS_PER_DAY; - -#ifdef DEBUG_IDS - std::cerr << "p3IdService: group " << *vit << " age=" << age << ", attempts=" << ssdata.pgp.checkAttempts << ", wait period = " << wait_period ; -#endif - - if (age < wait_period) - { -#ifdef DEBUG_IDS - std::cerr << " => discard." << std::endl; -#endif // DEBUG_IDS - continue; - } - - -#ifdef DEBUG_IDS - std::cerr << " => recheck!" << std::endl; -#endif - } - - /* if we get here -> then its to be processed */ - - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - groups_to_process.push_back(vit->mGroupId); - } - } - else - { - std::cerr << "p3IdService::pgphash_request() getGroupData ERROR"; - std::cerr << std::endl; - } - - // If they are groups to process, load the data for these groups - - if(!groups_to_process.empty()) - { - uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - uint32_t token = 0; - - RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts,groups_to_process); - GxsTokenQueue::queueRequest(token, GXSIDREQ_LOAD_PGPIDDATA); - } - - return true; -} - -bool p3IdService::pgphash_load_group_data(uint32_t token) -{ - // Update PgpIdList -> if there are groups to process. - - getPgpIdList(); - std::vector groups; - - // Add the loaded groups into the list of groups to process - - getGroupData(token, groups); - - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - for(auto grp:groups) - { - mGroupsToProcess[grp.mMeta.mGroupId] = grp; -#ifdef DEBUG_IDS - std::cerr << "pgphash_load_group_data(): loaded group data for group " << grp.mMeta.mGroupId << ". mGroupsToProcess contains " << mGroupsToProcess.size() << " elements." << std::endl; -#endif - } - - return true; -} - -bool p3IdService::pgphash_process() -{ - /* each time this is called - process one Id from mGroupsToProcess */ - RsGxsIdGroup pg; - bool isDone = false; - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - if (!mGroupsToProcess.empty()) - { - pg = mGroupsToProcess.begin()->second; - mGroupsToProcess.erase(mGroupsToProcess.begin()); - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::pgphash_process() Popped Group: " << pg.mMeta.mGroupId; - std::cerr << std::endl; -#endif // DEBUG_IDS - } - else - isDone = true; - } - - if (isDone) - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::pgphash_process() List Empty... Done"; - std::cerr << std::endl; -#endif // DEBUG_IDS - // FINISHED. - CacheArbitrationDone(BG_PGPHASH); - return true; - } - - - SSGxsIdGroup ssdata; - ssdata.load(pg.mMeta.mServiceString); // attempt load - okay if fails. - - RsPgpId pgpId; - bool error = false ; - - if (checkId(pg, pgpId,error)) - { - /* found a match - update everything */ - /* Consistency issues here - what if Reputation was recently updated? */ - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::pgphash_process() CheckId Success for Group: " << pg.mMeta.mGroupId; - std::cerr << " PgpId: " << pgpId; - std::cerr << std::endl; -#endif // DEBUG_IDS - - /* update */ - ssdata.pgp.validatedSignature = true; - ssdata.pgp.pgpId = pgpId; - - } - else if(error) - { - std::cerr << "Identity has an invalid signature. It will be deleted." << std::endl; - - uint32_t token ; - deleteIdentity(token,pg) ; - } - else - { -#ifdef DEBUG_IDS - std::cerr << "p3IdService::pgphash_process() No Match for Group: " << pg.mMeta.mGroupId; - std::cerr << std::endl; -#endif // DEBUG_IDS - - ssdata.pgp.lastCheckTs = time(NULL); - ssdata.pgp.checkAttempts++; - ssdata.pgp.pgpId = pgpId; // read from the signature, but not verified - } - - if(!error) - { - // update IdScore too. - ssdata.score.rep.updateIdScore(true, ssdata.pgp.validatedSignature); - ssdata.score.rep.update(); - - /* set new Group ServiceString */ - uint32_t dummyToken = 0; - std::string serviceString = ssdata.save(); - setGroupServiceString(dummyToken, pg.mMeta.mGroupId, serviceString); - - cache_update_if_cached(RsGxsId(pg.mMeta.mGroupId), serviceString); - } - return true; -} - -// This method allows to have a null issuer ID in the signature, in which case the signature is anonymous. -// The correct PGP key to check is looked for by bruteforcing -// -// grp.mPgpIdHash == SHA1( GroupId | PgpFingerPrint ) -// -// For now, this is probably never used because signed IDs use a clear signature. The advntage of hiding the -// ID has not been clearly demonstrated anyway, which allows to directly look for the ID in the list of -// known keys instead of computing tons of hashes. - -bool p3IdService::checkId(const RsGxsIdGroup &grp, RsPgpId &pgpId,bool& error) -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::checkId() Starting Match Check for RsGxsId: "; - std::cerr << grp.mMeta.mGroupId; - std::cerr << std::endl; -#endif // DEBUG_IDS - - error = false ; - - /* some sanity checking... make sure hash is the right size */ - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::checkId() PgpIdHash is: " << grp.mPgpIdHash; - std::cerr << std::endl; -#endif // DEBUG_IDS - - /* iterate through and check hash */ - Sha1CheckSum hash; - -#ifdef DEBUG_IDS - std::string esign ; - Radix64::encode((unsigned char *) grp.mPgpIdSign.c_str(), grp.mPgpIdSign.length(),esign) ; - std::cerr << "Checking group signature " << esign << std::endl; -#endif - RsPgpId issuer_id ; - RsPgpFingerprint pgp_fingerprint; - pgpId.clear() ; - - if(mPgpUtils->parseSignature((unsigned char *) grp.mPgpIdSign.c_str(), grp.mPgpIdSign.length(),issuer_id) && !issuer_id.isNull()) - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - pgpId = issuer_id ; - - auto mit = mPgpFingerprintMap.find(issuer_id); - - if(mit == mPgpFingerprintMap.end()) - { -#ifdef DEBUG_IDS - std::cerr << "Issuer Id: " << issuer_id << " is not known. Key will be marked as non verified." << std::endl; -#endif - error = false; - return false; - } - calcPGPHash(RsGxsId(grp.mMeta.mGroupId), mit->second, hash); -#ifdef DEBUG_IDS - std::cerr << "Issuer from PGP signature: " << issuer_id << " is known. Computed corresponding hash: " << hash << std::endl; -#endif - if(grp.mPgpIdHash != hash) - { - std::cerr << "(EE) Unexpected situation: GxsId signature hash (" << hash << ") doesn't correspond to what's listed in the mPgpIdHash field (" << grp.mPgpIdHash << ")." << std::endl; - error = true; - return false; - } - pgp_fingerprint = mit->second; - } - else - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - -#ifdef DEBUG_IDS - std::cerr << "Bruteforcing PGP hash from GxsId mPgpHash: " << grp.mPgpIdHash << std::endl; -#endif - for(auto mit = mPgpFingerprintMap.begin(); mit != mPgpFingerprintMap.end(); ++mit) - { - calcPGPHash(RsGxsId(grp.mMeta.mGroupId), mit->second, hash); - - std::cerr << " profile key " << mit->first << " (" << mit->second << ") : "; - - if (grp.mPgpIdHash == hash) - { -#ifdef DEBUG_IDS - std::cerr << "MATCH!" << std::endl; -#endif - pgpId = mit->first; - pgp_fingerprint = mit->second; - break; - } -#ifdef DEBUG_IDS - else - std::cerr << "fails" << std::endl; -#endif - } - } - - // Look for the PGP id given by the signature - -#ifdef DEBUG_IDS - std::cerr << "Now checking the signature: "; -#endif - - if (mPgpUtils->VerifySignBin((void *) hash.toByteArray(), hash.SIZE_IN_BYTES, (unsigned char *) grp.mPgpIdSign.c_str(), grp.mPgpIdSign.length(), pgp_fingerprint)) - { -#ifdef DEBUG_IDS - std::cerr << " Signature validates!" << std::endl; -#endif - error = false; - return true; - } - else - { -#ifdef DEBUG_IDS - std::cerr << " Signature fails!" << std::endl; -#endif - error = true; - return false; - } -} - -/* worker functions */ -void p3IdService::getPgpIdList() -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::getPgpIdList() Starting...."; - std::cerr << std::endl; -#endif // DEBUG_IDS - - std::list list; - mPgpUtils->getPgpAllList(list); - - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - mPgpFingerprintMap.clear(); - - std::list::iterator it; - for(it = list.begin(); it != list.end(); ++it) - { - RsPgpId pgpId(*it); - PGPFingerprintType fp; - mPgpUtils->getKeyFingerprint(pgpId, fp); - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::getPgpIdList() Id: " << pgpId.toStdString() << " => " << fp.toStdString(); - std::cerr << std::endl; -#endif // DEBUG_IDS - - mPgpFingerprintMap[pgpId] = fp; - } - -#ifdef DEBUG_IDS - std::cerr << "p3IdService::getPgpIdList() Items: " << mPgpFingerprintMap.size(); - std::cerr << std::endl; -#endif // DEBUG_IDS -} - - -void calcPGPHash(const RsGxsId &id, const PGPFingerprintType &pgp, Sha1CheckSum &hash) -{ - unsigned char signature[SHA_DIGEST_LENGTH]; - /* hash id + pubkey => pgphash */ - SHA_CTX *sha_ctx = new SHA_CTX; - SHA1_Init(sha_ctx); - - SHA1_Update(sha_ctx, id.toStdString().c_str(), id.toStdString().length()); // TO FIX ONE DAY. - SHA1_Update(sha_ctx, pgp.toByteArray(), pgp.SIZE_IN_BYTES); - SHA1_Final(signature, sha_ctx); - hash = Sha1CheckSum(signature); - -#ifdef DEBUG_IDS - std::cerr << "calcPGPHash():"; - std::cerr << std::endl; - std::cerr << "\tRsGxsId: " << id; - std::cerr << std::endl; - std::cerr << "\tFingerprint: " << pgp.toStdString(); - std::cerr << std::endl; - std::cerr << "\tFinal Hash: " << hash.toStdString(); - std::cerr << std::endl; -#endif // DEBUG_IDS - - delete sha_ctx; -} - -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ - -/* Task to validate Recogn Tags. - * - * Info to be stored in GroupServiceString + Cache. - **/ - -bool p3IdService::recogn_schedule() -{ -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_schedule()"; - std::cerr << std::endl; -#endif - - int32_t age = 0; - int32_t next_event = 0; - - if (RsTickEvent::event_count(GXSID_EVENT_RECOGN) > 0) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_schedule() Skipping GXSIS_EVENT_RECOGN already scheduled"; - std::cerr << std::endl; -#endif - return false; - } - - if (RsTickEvent::prev_event_ago(GXSID_EVENT_RECOGN, age)) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_schedule() previous event " << age << " secs ago"; - std::cerr << std::endl; -#endif - - next_event = RECOGN_PERIOD - age; - if (next_event < 0) - { - next_event = 0; - } - } - - RsTickEvent::schedule_in(GXSID_EVENT_RECOGN, next_event); - return true; -} - - -bool p3IdService::recogn_start() -{ - if (!CacheArbitration(BG_RECOGN)) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_start() Other Events running... Rescheduling"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - /* reschedule in a bit */ - RsTickEvent::schedule_in(GXSID_EVENT_RECOGN, RECOGN_RETRY_PERIOD); - return false; - } - - // NEXT EVENT is scheduled via recogn_schedule. - -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_start() making request"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - std::list recognList; - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - recognList = mRecognGroupIds; - mRecognGroupIds.clear(); - } - - if (recognList.empty()) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_start() List is Empty, cancelling"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - // FINISHED. - CacheArbitrationDone(BG_RECOGN); - return false; - } - - uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - uint32_t token = 0; - - RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts, recognList); - GxsTokenQueue::queueRequest(token, GXSIDREQ_RECOGN); - return true; - -} - - -bool p3IdService::recogn_handlerequest(uint32_t token) -{ -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_handlerequest(" << token << ")"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_request() Have " << grpData.size() << " Groups"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); ++vit) - { - RsGxsIdGroupItem* item = dynamic_cast(*vit); - if (item) - { - -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_request() Group Id: " << item->meta.mGroupId; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - mRecognGroupsToProcess.push_back(item); - } - else - { - delete (*vit); - } - } - } - else - { - std::cerr << "p3IdService::recogn_request() getGroupData ERROR"; - std::cerr << std::endl; - } - - // Schedule Processing. - RsTickEvent::schedule_in(GXSID_EVENT_RECOGN_PROC, RECOGN_PROC_PERIOD); - return true; -} - - -bool p3IdService::recogn_process() -{ - /* each time this is called - process one Id from mGroupsToProcess */ - RsGxsIdGroupItem *item; - bool isDone = false; - { - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - if (!mRecognGroupsToProcess.empty()) - { - item = mRecognGroupsToProcess.front(); - mRecognGroupsToProcess.pop_front(); - -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_process() Popped Group: " << item->meta.mGroupId; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - } - else - { - isDone = true; - } - } - - if (isDone) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_process() List Empty... Done"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - // FINISHED. - CacheArbitrationDone(BG_RECOGN); - return true; - } - - - - std::list tagItems; - std::list::iterator it; - - recogn_extract_taginfo(item, tagItems); - - bool isPending = false; - int i = 1; - uint32_t tagValidFlags = 0; - for(it = tagItems.begin(); it != tagItems.end(); ++it) - { - bool isTagPending = false; - bool isTagOk = recogn_checktag(RsGxsId(item->meta.mGroupId.toStdString()), item->meta.mGroupName, *it, true, isPending); - if (isTagOk) - { - tagValidFlags |= i; - } - else - { - isPending |= isTagPending; - } - - delete *it; - i *= 2; - } - -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_process() Tags Checked, saving"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - SSGxsIdGroup ssdata; - ssdata.load(item->meta.mServiceString); // attempt load - okay if fails. - - ssdata.recogntags.setTags(true, isPending, tagValidFlags); - ssdata.recogntags.lastCheckTs = time(NULL); - ssdata.recogntags.publishTs = item->meta.mPublishTs; - - // update IdScore too. - bool pgpId = (item->meta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility); - ssdata.score.rep.updateIdScore(pgpId, ssdata.pgp.validatedSignature); - ssdata.score.rep.update(); - - /* set new Group ServiceString */ - uint32_t dummyToken = 0; - std::string serviceString = ssdata.save(); - setGroupServiceString(dummyToken, item->meta.mGroupId, serviceString); - - cache_update_if_cached(RsGxsId(item->meta.mGroupId.toStdString()), serviceString); - - delete item; - - // Schedule Next Processing. - RsTickEvent::schedule_in(GXSID_EVENT_RECOGN_PROC, RECOGN_PROC_PERIOD); - return false; // as there are more items on the queue to process. -} - - -bool p3IdService::recogn_checktag(const RsGxsId &id, const std::string &nickname, RsGxsRecognTagItem *item, bool doSignCheck, bool &isPending) -{ - -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_checktag() groupId: " << id; - std::cerr << std::endl; - std::cerr << "p3IdService::recogn_checktag() nickname: " << nickname; - std::cerr << std::endl; - std::cerr << "p3IdService::recogn_checktag() item: "; - std::cerr << std::endl; - ((RsGxsRecognTagItem *) item)->print(std::cerr); -#endif // DEBUG_RECOGN - - // To check: - // ------------------- - // date range. - // id matches. - // nickname matches. - // signer is valid. - // ------ - // signature is valid. (only if doSignCheck == true) - - rstime_t now = time(NULL); - isPending = false; - - // check date range. - if ((item->valid_from > now) || (item->valid_to < now)) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_checktag() failed timestamp"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - return false; - } - - // id match. - if (id != item->identity) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_checktag() failed identity"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - return false; - } - - // nickname match. - if (nickname != item->nickname) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_checktag() failed nickname"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - return false; - } - - - - { - /* check they validity of the Tag */ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - - std::map::iterator it; - it = mRecognSignKeys.find(item->sign.keyId); - if (it == mRecognSignKeys.end()) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_checktag() failed to find signkey"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - - // If OldKey, then we don't want to reprocess. - if (mRecognOldSignKeys.end() != - mRecognOldSignKeys.find(item->sign.keyId)) - { - isPending = true; // need to reprocess later with new key - } - return false; - } - - // Check tag_class is okay for signer. - if (it->second->signing_classes.ids.end() == - std::find(it->second->signing_classes.ids.begin(), it->second->signing_classes.ids.end(), item->tag_class)) - { -#ifdef DEBUG_RECOGN - std::cerr << "p3IdService::recogn_checktag() failed signing_class check"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - return false; - } - - // ALL Okay, just signature to check. - if (!doSignCheck) - { - return true; - } - - return RsRecogn::validateTagSignature(it->second, item); - } -} - - -void p3IdService::loadRecognKeys() -{ - RsStackMutex stack(mIdMtx); /**** LOCKED MUTEX ****/ - - RsRecogn::loadSigningKeys(mRecognSignKeys); -} - - - -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ - -#define MAX_KNOWN_PGPIDS 20 -#define MAX_UNKNOWN_PGPIDS 20 -#define MAX_PSEUDOIDS 20 - -#define DUMMY_GXSID_DELAY 5 - -void p3IdService::generateDummyData() -{ - - generateDummy_OwnIds(); - - rstime_t age = 0; - for(int i = 0; i < MAX_KNOWN_PGPIDS; i++) - { - age += DUMMY_GXSID_DELAY; - RsTickEvent::schedule_in(GXSID_EVENT_DUMMY_PGPID, age); - } - - for(int i = 0; i < MAX_PSEUDOIDS; i++) - { - age += DUMMY_GXSID_DELAY; - RsTickEvent::schedule_in(GXSID_EVENT_DUMMY_PSEUDOID, age); - } - - for(int i = 0; i < MAX_UNKNOWN_PGPIDS; i++) - { - age += DUMMY_GXSID_DELAY; - RsTickEvent::schedule_in(GXSID_EVENT_DUMMY_UNKNOWN_PGPID, age); - } -} - - - - - -void p3IdService::generateDummy_OwnIds() -{ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - /* grab all the gpg ids... and make some ids */ - - /*RsPgpId ownId = */mPgpUtils->getPGPOwnId(); - -#if 0 - // generate some ownIds. - //int genCount = 0; - int i; - - int nIds = 2 + (RSRandom::random_u32() % 2); - for(i = 0; i < nIds; i++) - { - RsGxsIdGroup id; - RsPeerDetails details; - - id.mMeta.mGroupFlags = RSGXSID_GROUPFLAG_REALID; - -// // HACK FOR DUMMY GENERATION. -// id.mMeta.mAuthorId = ownId.toStdString(); -// if (rsPeers->getPeerDetails(ownId, details)) -// { -// std::ostringstream out; -// out << details.name << "_" << i + 1; -// -// id.mMeta.mGroupName = out.str(); -// } - - uint32_t dummyToken = 0; - createGroup(dummyToken, id); - } -#endif -} - - -void p3IdService::generateDummy_FriendPGP() -{ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - // Now Generate for friends. - std::list gpgids; - std::list::const_iterator it; - mPgpUtils->getPgpAllList(gpgids); - - RsGxsIdGroup id; - - id.mMeta.mGroupFlags = RSGXSID_GROUPFLAG_REALID_kept_for_compatibility; - - int idx = RSRandom::random_f32() * (gpgids.size() - 1); - it = gpgids.begin(); - for(int j = 0; j < idx; j++, ++it) ; - -#if 0 - // HACK FOR DUMMY GENERATION. - id.mMeta.mAuthorId = RsGxsId::random() ; - - RsPeerDetails details; - if (/*rsPeers->getPeerDetails(*it, details)*/false) - { - std::ostringstream out; - out << details.name << "_" << RSRandom::random_u32() % 1000; - id.mMeta.mGroupName = out.str(); - } - else - { - std::cerr << "p3IdService::generateDummy_FriendPGP() missing" << std::endl; - std::cerr << std::endl; - id.mMeta.mGroupName = RSRandom::random_alphaNumericString(10) ; - } - - uint32_t dummyToken = 0; - createGroup(dummyToken, id); -#endif -} - - -void p3IdService::generateDummy_UnknownPGP() -{ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - RsGxsIdGroup id; - - // FAKE DATA. - id.mMeta.mGroupFlags = RSGXSID_GROUPFLAG_REALID_kept_for_compatibility; - id.mPgpIdHash = Sha1CheckSum::random() ; - id.mPgpIdSign = RSRandom::random_alphaNumericString(20) ; - id.mMeta.mGroupName = RSRandom::random_alphaNumericString(10) ; - - uint32_t dummyToken = 0; - createGroup(dummyToken, id); -} - - -void p3IdService::generateDummy_UnknownPseudo() -{ - RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ - - RsGxsIdGroup id; - - // FAKE DATA. - id.mMeta.mGroupFlags = 0; - id.mMeta.mGroupName = RSRandom::random_alphaNumericString(10) ; - - uint32_t dummyToken = 0; - createGroup(dummyToken, id); -} - - -std::string rsIdTypeToString(uint32_t idtype) -{ - std::string str; - if (idtype & RSID_TYPE_REALID) - { - str += "GPGID "; - } - if (idtype & RSID_TYPE_PSEUDONYM) - { - str += "PSEUDO "; - } - if (idtype & RSID_RELATION_YOURSELF) - { - str += "YOURSELF "; - } - if (idtype & RSID_RELATION_FRIEND) - { - str += "FRIEND "; - } - if (idtype & RSID_RELATION_FOF) - { - str += "FOF "; - } - if (idtype & RSID_RELATION_OTHER) - { - str += "OTHER "; - } - if (idtype & RSID_RELATION_UNKNOWN) - { - str += "UNKNOWN "; - } - return str; -} - - - - - - - - -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ - - -/* here we are running a background process that calculates the reputation scores - * for each of the IDs.... - * - * As this class will be extensively used by many other threads... it is best - * that we don't block at all. This should be in a background thread. - * Perhaps a generic method to handle this will be advisable.... but we do that later. - * - * - * So Reputation.... - * 4 components: - * 1) Your Opinion: Should override everything else. - * 2) Implicit Factors: Know the associated GPG Key. - * 3) Your Friends Opinions: - * 4) Your Friends Calculated Reputation Scores. - * - * Must make sure that there is no Feedback loop in the Reputation calculation. - * - * So: Our Score + Friends Scores => Local Reputation. - * Local Reputation + Friends Reputations => Final Reputation? - * - * Do we need to 'ignore' Non-scores? - * ---> This becomes like the "Best Comment" algorithm from Reddit... - * Use a statistical mechanism to work out a lower bound on Reputation. - * - * But what if your opinion is wrong?.... well likely your friends will - * get their messages and reply... you'll see the missing message - request it - check reputation etc. - * - * So we are going to have three different scores (Own, Peers, (the neighbour) Hood)... - * - * So next question, when do we need to incrementally calculate the score? - * .... how often do we need to recalculate everything -> this could lead to a flux of messages. - * - * - * - * MORE NOTES: - * - * The Opinion Messages will have to be signed by PGP or SSL Keys, to guarantee that we don't - * multiple votes per person... As the message system doesn't handle uniqueness in this respect, - * we might have to do FULL_CALC for everything - This bit TODO. - * - * This will make IdService quite different to the other GXS services. - */ - -/************************************************************************************/ -/* - * Processing Algorithm: - * - Grab all Groups which have received messages. - * (opt 1)-> grab latest msgs for each of these and process => score. - * (opt 2)-> try incremental system (people probably won't change opinions often -> just set them once) - * --> if not possible, fallback to full calculation. - * - * - */ - -void p3IdService::checkPeerForIdentities() -{ - RsStackMutex stack(mIdMtx); - - // crud, i needed peers instead! - mGroupNotPresent.clear(); -} - - -// Overloaded from GxsTokenQueue for Request callbacks. -void p3IdService::handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::handleResponse(" << token << "," << req_type << "," << status << ")" << std::endl; -#endif // DEBUG_IDS - - // stuff. - switch(req_type) - { - case GXSIDREQ_CACHEOWNIDS: - if (status == RsTokenService::COMPLETE) cache_load_ownids(token); - if (status == RsTokenService::CANCELLED) RsTickEvent::schedule_now(GXSID_EVENT_CACHEOWNIDS);//Cancelled by time-out so ask a new time - break; - case GXSIDREQ_CACHELOAD: - if (status == RsTokenService::COMPLETE) cache_load_for_token(token); - break; - case GXSIDREQ_PGPHASH: - if (status == RsTokenService::COMPLETE) pgphash_handlerequest(token); - break; - case GXSIDREQ_RECOGN: - if (status == RsTokenService::COMPLETE) recogn_handlerequest(token); - break; - case GXSIDREQ_CACHETEST: - if (status == RsTokenService::COMPLETE) cachetest_handlerequest(token); - break; - case GXSIDREQ_OPINION: - if (status == RsTokenService::COMPLETE) opinion_handlerequest(token); - break; - case GXSIDREQ_LOAD_PGPIDDATA: - if (status == RsTokenService::COMPLETE) pgphash_load_group_data(token); - break; - case GXSIDREQ_SERIALIZE_TO_MEMORY: - if (status == RsTokenService::COMPLETE) handle_get_serialized_grp(token); - break; - default: - std::cerr << "p3IdService::handleResponse() Unknown Request Type: " - << req_type << std::endl; - break; - } -} - - - // Overloaded from RsTickEvent for Event callbacks. -void p3IdService::handle_event(uint32_t event_type, const std::string &/*elabel*/) -{ -#ifdef DEBUG_IDS - std::cerr << "p3IdService::handle_event(" << event_type << ")"; - std::cerr << std::endl; -#endif // DEBUG_IDS - - // stuff. - switch(event_type) - { - case GXSID_EVENT_CACHEOWNIDS: - cache_request_ownids(); - break; - - case GXSID_EVENT_CACHELOAD: - cache_start_load(); - break; - - case GXSID_EVENT_CACHETEST: - cachetest_getlist(); - break; - - case GXSID_EVENT_PGPHASH: - pgphash_start(); - break; - - case GXSID_EVENT_RECOGN: - recogn_start(); - break; - - case GXSID_EVENT_RECOGN_PROC: - recogn_process(); - break; - - case GXSID_EVENT_DUMMYDATA: - generateDummyData(); - break; - - case GXSID_EVENT_DUMMY_OWNIDS: - generateDummy_OwnIds(); - break; - - case GXSID_EVENT_DUMMY_PGPID: - generateDummy_FriendPGP(); - break; - - case GXSID_EVENT_DUMMY_UNKNOWN_PGPID: - generateDummy_UnknownPGP(); - break; - - case GXSID_EVENT_DUMMY_PSEUDOID: - generateDummy_UnknownPseudo(); - break; - case GXSID_EVENT_REQUEST_IDS: - requestIdsFromNet(); - break; - case GXSID_EVENT_REPUTATION: - break; - default: - RsErr() << __PRETTY_FUNCTION__ << " Unknown Event Type: " - << event_type << std::endl; - print_stacktrace(); - break; - } -} - -/*static*/ const std::string RsIdentity::DEFAULT_IDENTITY_BASE_URL = - "retroshare:///identities"; -/*static*/ const std::string RsIdentity::IDENTITY_URL_NAME_FIELD = "identityName"; -/*static*/ const std::string RsIdentity::IDENTITY_URL_ID_FIELD = "identityId"; -/*static*/ const std::string RsIdentity::IDENTITY_URL_DATA_FIELD = "identityData"; - -bool p3IdService::exportIdentityLink( - std::string& link, const RsGxsId& id, bool includeGxsData, - const std::string& baseUrl, std::string& errMsg ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - errMsg = err; - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(id.isNull()) return failure("id cannot be null"); - - const bool outputRadix = baseUrl.empty(); - if(outputRadix && !includeGxsData) return - failure("includeGxsData must be true if format requested is base64"); - - if( includeGxsData && - !RsGenExchange::exportGroupBase64( - link, reinterpret_cast(id), errMsg ) ) - return failure(errMsg); - - if(outputRadix) return true; - - std::vector idsInfo; - if( !getIdentitiesInfo(std::set({id}), idsInfo ) - || idsInfo.empty() ) - return failure("failure retrieving identity information"); - - RsUrl inviteUrl(baseUrl); - inviteUrl.setQueryKV(IDENTITY_URL_ID_FIELD, id.toStdString()); - inviteUrl.setQueryKV(IDENTITY_URL_NAME_FIELD, idsInfo[0].mMeta.mGroupName); - if(includeGxsData) inviteUrl.setQueryKV(IDENTITY_URL_DATA_FIELD, link); - - link = inviteUrl.toString(); - return true; -} - -bool p3IdService::importIdentityLink( - const std::string& link, RsGxsId& id, std::string& errMsg ) -{ - constexpr auto fname = __PRETTY_FUNCTION__; - const auto failure = [&](const std::string& err) - { - errMsg = err; - RsErr() << fname << " " << err << std::endl; - return false; - }; - - if(link.empty()) return failure("link is empty"); - - const std::string* radixPtr(&link); - - RsUrl url(link); - const auto& query = url.query(); - const auto qIt = query.find(IDENTITY_URL_DATA_FIELD); - if(qIt != query.end()) radixPtr = &qIt->second; - - if(radixPtr->empty()) return failure(IDENTITY_URL_DATA_FIELD + " is empty"); - - if(!RsGenExchange::importGroupBase64( - *radixPtr, reinterpret_cast(id), errMsg )) - return failure(errMsg); - - return true; -} - - -void RsGxsIdGroup::serial_process( - RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - RS_SERIAL_PROCESS(mMeta); - RS_SERIAL_PROCESS(mPgpIdHash); - switch(j) - { - /* mPgpIdSign is declared as std::string but it is a disguised raw memory - * chunk, serializing it as plain string breaks JSON and eventually - * teminals if it get printed, it should have been declared as a raw memory - * chunk in the first place, but as of today just ignoring it in *JSON and - * PRINT operations seems a reasonable workaround */ - case RsGenericSerializer::SerializeJob::PRINT: // [[fallthrough]] - case RsGenericSerializer::SerializeJob::TO_JSON: // [[fallthrough]] - case RsGenericSerializer::SerializeJob::FROM_JSON: - break; - default: - RS_SERIAL_PROCESS(mPgpIdSign); - break; - } - RS_SERIAL_PROCESS(mImage); - RS_SERIAL_PROCESS(mLastUsageTS); - RS_SERIAL_PROCESS(mPgpKnown); - RS_SERIAL_PROCESS(mIsAContact); - RS_SERIAL_PROCESS(mPgpId); - RS_SERIAL_PROCESS(mReputation); -} - -RsIdentityUsage::RsIdentityUsage(RsServiceType service, RsIdentityUsage::UsageCode code, - const RsGxsGroupId& gid, const RsGxsMessageId& mid, const RsGxsMessageId &pid, const RsGxsMessageId &tid, - uint64_t additional_id, const std::string& comment ) : - mServiceId(service), mUsageCode(code), mGrpId(gid), mMsgId(mid),mParentId(pid),mThreadId(tid), - mAdditionalId(additional_id), mComment(comment) -{ - /* This is a hack, since it will hash also mHash, but because it is - * initialized to 0, and only computed in the constructor here, it should - * be ok. */ - librs::crypto::HashStream hs(librs::crypto::HashStream::SHA1); - - hs << static_cast(service); // G10h4ck: Why uint32 if it's 16 bits? - hs << static_cast(code); - hs << gid; - hs << mid; - hs << static_cast(additional_id); - hs << comment; - - mHash = hs.hash(); -} - -RsIdentityUsage::RsIdentityUsage() : - mServiceId(RsServiceType::NONE), mUsageCode(UNKNOWN_USAGE), mAdditionalId(0) -{} - -RsIdentity::~RsIdentity() = default; -RsReputationInfo::~RsReputationInfo() = default; -RsGixs::~RsGixs() = default; -RsIdentityDetails::~RsIdentityDetails() = default; -GxsReputation::~GxsReputation() = default; -RsGxsIdGroup::~RsGxsIdGroup() = default; diff --git a/libretroshare/src/services/p3idservice.h b/libretroshare/src/services/p3idservice.h deleted file mode 100644 index 370c7a35a..000000000 --- a/libretroshare/src/services/p3idservice.h +++ /dev/null @@ -1,640 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3idservice.h * - * * - * Copyright (C) 2012-2014 Robert Fernie * - * Copyright (C) 2017-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -/// RetroShare GXS identities service - - -#include -#include - -#include "retroshare/rsidentity.h" // External Interfaces. -#include "gxs/rsgenexchange.h" // GXS service. -#include "gxs/rsgixs.h" // Internal Interfaces. -#include "util/rsdebug.h" -#include "gxs/gxstokenqueue.h" -#include "rsitems/rsgxsiditems.h" -#include "util/rsmemcache.h" -#include "util/rstickevent.h" -#include "util/rsrecogn.h" -#include "pqi/authgpg.h" -#include "rsitems/rsgxsrecognitems.h" - -class PgpAuxUtils; - -class OpinionRequest -{ - public: - OpinionRequest(uint32_t token, RsGxsId id, bool absOpinion, int32_t score) - :mToken(token), mId(id), mAbsOpinion(absOpinion), mScore(score) - { return; } - OpinionRequest() - :mToken(0), mId(), mAbsOpinion(false), mScore(0) - { return; } - - uint32_t mToken; - RsGxsId mId; - bool mAbsOpinion; - int32_t mScore; -}; - - -// INTERNAL DATA TYPES. -// Describes data stored in GroupServiceString. - -class SSBit -{ - public: -virtual bool load(const std::string &input) = 0; -virtual std::string save() const = 0; -}; - - - -class SSGxsIdPgp: public SSBit -{ - public: - SSGxsIdPgp() - :validatedSignature(false), lastCheckTs(0), checkAttempts(0) { return; } - -virtual bool load(const std::string &input); -virtual std::string save() const; - - bool validatedSignature; - rstime_t lastCheckTs; - uint32_t checkAttempts; - RsPgpId pgpId; -}; - -class SSGxsIdRecognTags: public SSBit -{ - public: - SSGxsIdRecognTags() - :tagFlags(0), publishTs(0), lastCheckTs(0) { return; } - -virtual bool load(const std::string &input); -virtual std::string save() const; - - void setTags(bool processed, bool pending, uint32_t flags); - - bool tagsProcessed() const; // have we processed? - bool tagsPending() const; // should we reprocess? - bool tagValid(int i) const; - - uint32_t tagFlags; - rstime_t publishTs; - rstime_t lastCheckTs; -}; - - -class SSGxsIdReputation: public SSBit -{ - public: - SSGxsIdReputation() - :rep() { return; } - -virtual bool load(const std::string &input); -virtual std::string save() const; - - GxsReputation rep; -}; - -class SSGxsIdCumulator: public SSBit -{ -public: - SSGxsIdCumulator() - :count(0), nullcount(0), sum(0), sumsq(0) { return; } - -virtual bool load(const std::string &input); -virtual std::string save() const; - - uint32_t count; - uint32_t nullcount; - double sum; - double sumsq; - - // derived parameters: -}; - -class SSGxsIdGroup: public SSBit -{ -public: - SSGxsIdGroup() { return; } - -virtual bool load(const std::string &input); -virtual std::string save() const; - - // pgphash status - SSGxsIdPgp pgp; - - // recogTags. - SSGxsIdRecognTags recogntags; - - // reputation score. - SSGxsIdReputation score; - - // These are depreciated (will load, but not save) - SSGxsIdCumulator opinion; - SSGxsIdCumulator reputation; - -}; - -#define ID_LOCAL_STATUS_FULL_CALC_FLAG 0x00010000 -#define ID_LOCAL_STATUS_INC_CALC_FLAG 0x00020000 - -class RsGxsIdGroupItem; - -class RsGxsIdCache -{ -public: - RsGxsIdCache(); - - RsGxsIdCache(const RsGxsIdGroupItem *item, const RsTlvPublicRSAKey& in_pkey, const RsTlvPrivateRSAKey& privkey, const std::list &tagList); - RsGxsIdCache(const RsGxsIdGroupItem *item, const RsTlvPublicRSAKey& in_pkey, const std::list &tagList); - - void updateServiceString(std::string serviceString); - - rstime_t mPublishTs; - std::list mRecognTags; // Only partially validated. - - RsIdentityDetails details; - - RsTlvPublicRSAKey pub_key; - RsTlvPrivateRSAKey priv_key; - -private: - void init(const RsGxsIdGroupItem *item, const RsTlvPublicRSAKey& in_pub_key, const RsTlvPrivateRSAKey& in_priv_key,const std::list &tagList); -}; - -struct SerialisedIdentityStruct -{ - unsigned char *mMem ; - uint32_t mSize ; - rstime_t mLastUsageTS; -}; - -// We cache all identities, and provide alternative (instantaneous) -// functions to extract info, rather than the horrible Token system. -class p3IdService: public RsGxsIdExchange, public RsIdentity, public GxsTokenQueue, public RsTickEvent, public p3Config -{ -public: - p3IdService(RsGeneralDataService* gds, RsNetworkExchangeService* nes, PgpAuxUtils *pgpUtils); - - virtual RsServiceInfo getServiceInfo()override; - static uint32_t idAuthenPolicy(); - - virtual void service_tick()override; // needed for background processing. - - - /*! - * Design hack, id service must be constructed first as it - * is need for construction of subsequent net services - */ - void setNes(RsNetworkExchangeService* nes); - - /* General Interface is provided by RsIdentity / RsGxsIfaceImpl. */ - - /* Data Specific Interface */ - - /// @see RsIdentity - bool getIdentitiesInfo(const std::set& ids, - std::vector& idsInfo ) override; - - /// @see RsIdentity - bool getIdentitiesSummaries(std::list& ids) override; - - // These are exposed via RsIdentity. - virtual bool getGroupData(const uint32_t &token, std::vector &groups) override; - virtual bool getGroupSerializedData(const uint32_t &token, std::map& serialized_groups) override; - - //virtual bool getMsgData(const uint32_t &token, std::vector &opinions); - - // These are local - and not exposed via RsIdentity. - virtual bool createGroup(uint32_t& token, RsGxsIdGroup &group); - virtual bool updateGroup(uint32_t& token, RsGxsIdGroup &group); - virtual bool deleteGroup(uint32_t& token, RsGxsGroupId& group); - //virtual bool createMsg(uint32_t& token, RsGxsIdOpinion &opinion); - - virtual bool receiveNewIdentity(RsNxsGrp *identity_grp) override; - virtual bool retrieveNxsIdentity(const RsGxsId& group_id,RsNxsGrp *& identity_grp)override; - - /**************** RsIdentity External Interface. - * Notes: - * - * All the data is cached together for the moment - We should probably - * seperate and sort this out. - * - * Also need to handle Cache updates / invalidation from internal changes. - * - */ - //virtual bool getNickname(const RsGxsId &id, std::string &nickname); - virtual bool getIdDetails(const RsGxsId &id, RsIdentityDetails &details) override; - - RS_DEPRECATED_FOR(RsReputations) - virtual bool submitOpinion(uint32_t& token, const RsGxsId &id, - bool absOpinion, int score) override; - - /// @see RsIdentity - virtual bool createIdentity( - RsGxsId& id, - const std::string& name, const RsGxsImage& avatar = RsGxsImage(), - bool pseudonimous = true, const std::string& pgpPassword = "" ) override; - - virtual bool createIdentity(uint32_t& token, RsIdentityParameters ¶ms) override; - - /// @see RsIdentity - bool updateIdentity( const RsGxsId& id, const std::string& name, const RsGxsImage& avatar, bool pseudonimous, const std::string& pgpPassword) override; - - /// @see RsIdentity - bool deleteIdentity(RsGxsId& id) override; - - RS_DEPRECATED - virtual bool deleteIdentity(uint32_t& token, RsGxsIdGroup &group) override; - - virtual void setDeleteBannedNodesThreshold(uint32_t days) override; - virtual uint32_t deleteBannedNodesThreshold() override; - - virtual bool parseRecognTag(const RsGxsId &id, const std::string &nickname, - const std::string &tag, RsRecognTagDetails &details) override; - virtual bool getRecognTagRequest(const RsGxsId &id, const std::string &comment, - uint16_t tag_class, uint16_t tag_type, std::string &tag) override; - - virtual bool setAsRegularContact(const RsGxsId& id,bool is_a_contact) override; - virtual bool isARegularContact(const RsGxsId& id) override; - virtual void setAutoAddFriendIdsAsContact(bool b) override; - virtual bool autoAddFriendIdsAsContact() override; - - virtual uint32_t nbRegularContacts() override; - virtual rstime_t getLastUsageTS(const RsGxsId &id) override ; - - /**************** RsGixs Implementation ***************/ - - /// @see RsIdentity - bool getOwnSignedIds(std::vector& ids) override; - - /// @see RsIdentity - bool getOwnPseudonimousIds(std::vector& ids) override; - - /// @see RsIdentity - bool getOwnIds( - std::list &ownIds, bool signed_only = false ) override; - - /// @see RsIdentity - bool isKnownId(const RsGxsId& id) override; - - /// @see RsIdentity - bool isOwnId(const RsGxsId& key_id) override; - - /// @see RsIdentity - bool exportIdentityLink( - std::string& link, const RsGxsId& id, - bool includeGxsData = true, - const std::string& baseUrl = DEFAULT_IDENTITY_BASE_URL, - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - /// @see RsIdentity - bool importIdentityLink( - const std::string& link, - RsGxsId& id = RS_DEFAULT_STORAGE_PARAM(RsGxsId), - std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) - ) override; - - - virtual bool signData( const uint8_t* data, - uint32_t data_size, - const RsGxsId& signer_id, - RsTlvKeySignature& signature, - uint32_t& signing_error)override; - - virtual bool validateData( const uint8_t *data, uint32_t data_size, - const RsTlvKeySignature& signature, - bool force_load, const RsIdentityUsage &info, - uint32_t& signing_error )override; - - virtual bool encryptData( const uint8_t* decrypted_data, - uint32_t decrypted_data_size, - uint8_t*& encrypted_data, - uint32_t& encrypted_data_size, - const RsGxsId& encryption_key_id, - uint32_t& error_status, - bool force_load = true )override; - - bool encryptData( const uint8_t* decrypted_data, - uint32_t decrypted_data_size, - uint8_t*& encrypted_data, - uint32_t& encrypted_data_size, - const std::set& encrypt_ids, - uint32_t& error_status, bool force_loa = true ); - - virtual bool decryptData( const uint8_t* encrypted_data, - uint32_t encrypted_data_size, - uint8_t*& decrypted_data, - uint32_t& decrypted_data_size, - const RsGxsId& decryption_key_id, - uint32_t& error_status, - bool force_load = true )override; - - virtual bool decryptData(const uint8_t* encrypted_data, - uint32_t encrypted_data_size, - uint8_t*& decrypted_data, - uint32_t& decrypted_data_size, - const std::set& decrypt_ids, - uint32_t& error_status, - bool force_load = true ); - - - virtual bool haveKey(const RsGxsId &id)override; - virtual bool havePrivateKey(const RsGxsId &id)override; - - virtual bool getKey(const RsGxsId &id, RsTlvPublicRSAKey &key)override; - virtual bool getPrivateKey(const RsGxsId &id, RsTlvPrivateRSAKey &key)override; - - virtual bool requestKey( const RsGxsId &id, - const std::list &peers, - const RsIdentityUsage &use_info )override; - virtual bool requestPrivateKey(const RsGxsId &id)override; - - RS_DEPRECATED_FOR(exportIdentityLink) - virtual bool serialiseIdentityToMemory(const RsGxsId& id, std::string& radix_string) override; - RS_DEPRECATED_FOR(importIdentityLink) - virtual bool deserialiseIdentityFromMemory(const std::string& radix_string, RsGxsId* id = nullptr) override; - - /// @see RsIdentity - bool requestIdentity( - const RsGxsId& id, - const std::vector& peers = std::vector() - ) override; - - /**************** RsGixsReputation Implementation ****************/ - - // get Reputation. -#ifdef TO_BE_REMOVED - virtual bool haveReputation(const RsGxsId &id); - virtual bool loadReputation(const RsGxsId &id, const std::list& peers); - virtual bool getReputation(const RsGxsId &id, GixsReputation &rep); -#endif - - -protected: - /** Notifications **/ - virtual void notifyChanges(std::vector& changes) override; - - /** Overloaded to add PgpIdHash to Group Definition **/ - virtual ServiceCreate_Return service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet) override; - - // Overloads RsGxsGenExchange - virtual bool acceptNewGroup(const RsGxsGrpMetaData *grpMeta) override ; - - // Overloaded from GxsTokenQueue for Request callbacks. - virtual void handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) override; - - // Overloaded from RsTickEvent. - virtual void handle_event(uint32_t event_type, const std::string &elabel) override; - - //===================================================// - // p3Config methods // - //===================================================// - - // Load/save the routing info, the pending items in transit, and the config variables. - // - virtual bool loadList(std::list& items) override ; - virtual bool saveList(bool& cleanup,std::list& items) override ; - - virtual RsSerialiser *setupSerialiser() override ; - - -private: - - /************************************************************************ - * This is the Cache for minimising calls to the DataStore. - * - */ - int cache_tick(); - - bool cache_request_load(const RsGxsId &id, const std::list& peers = std::list()); - bool cache_start_load(); - bool cache_load_for_token(uint32_t token); - - bool cache_store(const RsGxsIdGroupItem *item); - bool cache_update_if_cached(const RsGxsId &id, std::string serviceString); - - bool isPendingNetworkRequest(const RsGxsId& gxsId); - void requestIdsFromNet(); - - // Mutex protected. - - //std::list mCacheLoad_ToCache; - std::map > mCacheLoad_ToCache, mPendingCache; - - // Switching to RsMemCache for Key Caching. - RsMemCache mKeyCache; - - /************************************************************************ - * Refreshing own Ids. - * - */ - bool cache_request_ownids(); - bool cache_load_ownids(uint32_t token); - - std::list mOwnIds; - std::list mOwnSignedIds; - - /************************************************************************ - * Test fns for Caching. - * - */ - bool cachetest_tick(); - bool cachetest_getlist(); - bool cachetest_handlerequest(uint32_t token); - - /************************************************************************ - * for processing background tasks that use the serviceString. - * - must be mutually exclusive to avoid clashes. - */ - bool CacheArbitration(uint32_t mode); - void CacheArbitrationDone(uint32_t mode); - - bool mBgSchedule_Active; - uint32_t mBgSchedule_Mode; - - /***********************************8 - * Fonction to receive and handle group serialisation to memory - */ - - virtual void handle_get_serialized_grp(uint32_t token); - - /************************************************************************ - * pgphash processing. - * - */ - bool pgphash_start(); - bool pgphash_load_group_data(uint32_t token); - bool pgphash_handlerequest(uint32_t token); - bool pgphash_process(); - - bool checkId(const RsGxsIdGroup &grp, RsPgpId &pgp_id, bool &error); - void getPgpIdList(); - - /* MUTEX PROTECTED DATA (mIdMtx - maybe should use a 2nd?) */ - - std::map mPgpFingerprintMap; - std::map mGroupsToProcess; - - /************************************************************************ - * recogn processing. - * - */ - bool recogn_schedule(); - bool recogn_start(); - bool recogn_handlerequest(uint32_t token); - bool recogn_process(); - - // helper functions. - bool recogn_extract_taginfo(const RsGxsIdGroupItem *item, std::list &tagItems); - bool cache_process_recogntaginfo(const RsGxsIdGroupItem *item, std::list &tagList); - - bool recogn_checktag(const RsGxsId &id, const std::string &nickname, RsGxsRecognTagItem *item, bool doSignCheck, bool &isPending); - - void loadRecognKeys(); - - - /************************************************************************ - * opinion processing. - * - */ - - bool opinion_handlerequest(uint32_t token); - - /* MUTEX PROTECTED DATA */ - std::map mPendingOpinion; - - - /************************************************************************ - * for getting identities that are not present - * - */ - void checkPeerForIdentities(); - - - /* MUTEX PROTECTED DATA (mIdMtx - maybe should use a 2nd?) */ - - bool checkRecognSignature_locked(std::string encoded, RSA &key, std::string signature); - bool getRecognKey_locked(std::string signer, RSA &key); - - std::list mRecognGroupIds; - std::list mRecognGroupsToProcess; - std::map mRecognSignKeys; - std::map mRecognOldSignKeys; - - /************************************************************************ - * Below is the background task for processing opinions => reputations - * - */ - - virtual void generateDummyData(); - void generateDummy_OwnIds(); - void generateDummy_FriendPGP(); - void generateDummy_UnknownPGP(); - void generateDummy_UnknownPseudo(); - - void cleanUnusedKeys() ; - void slowIndicateConfigChanged() ; - - virtual void timeStampKey(const RsGxsId& id, const RsIdentityUsage& reason) override; - rstime_t locked_getLastUsageTS(const RsGxsId& gxs_id); - - std::string genRandomId(int len = 20); - -#if 0 - bool reputation_start(); - bool reputation_continue(); - - int background_tick(); - bool background_checkTokenRequest(); - bool background_requestGroups(); - bool background_requestNewMessages(); - bool background_processNewMessages(); - bool background_FullCalcRequest(); - bool background_processFullCalc(); - - bool background_cleanup(); -#endif - - RsMutex mIdMtx; - -#if 0 - /***** below here is locked *****/ - bool mLastBgCheck; - bool mBgProcessing; - - uint32_t mBgToken; - uint32_t mBgPhase; - - std::map mBgGroupMap; - std::list mBgFullCalcGroups; -#endif - - /************************************************************************ - * Other Data that is protected by the Mutex. - */ - -private: - - struct keyTSInfo - { - keyTSInfo() : TS(0) {} - - rstime_t TS ; - std::map usage_map ; - }; - friend class IdCacheEntryCleaner; - - std::map > mIdsPendingCache; - std::map > mGroupNotPresent; - std::map > mIdsNotPresent; - std::map mKeysTS ; - - std::map mSerialisedIdentities ; - - // keep a list of regular contacts. This is useful to sort IDs, and allow some services to priviledged ids only. - std::set mContacts; - RsNetworkExchangeService* mNes; - - /************************** - * AuxUtils provides interface to Security Function (e.g. GPGAuth(), notify etc.) - * without depending directly on all these classes. - */ - - PgpAuxUtils *mPgpUtils; - rstime_t mLastPGPHashProcessTime ; - rstime_t mLastKeyCleaningTime ; - rstime_t mLastConfigUpdate ; - - bool mOwnIdsLoaded; - bool ownIdsAreLoaded() { RS_STACK_MUTEX(mIdMtx); return mOwnIdsLoaded; } - - bool mAutoAddFriendsIdentitiesAsContacts; - uint32_t mMaxKeepKeysBanned; - - RS_SET_CONTEXT_DEBUG_LEVEL(2) -}; diff --git a/libretroshare/src/services/p3msgservice.cc b/libretroshare/src/services/p3msgservice.cc deleted file mode 100644 index 44ad7e024..000000000 --- a/libretroshare/src/services/p3msgservice.cc +++ /dev/null @@ -1,2464 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3msgservice.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2008 Robert Fernie * - * Copyright (C) 2016-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "retroshare/rsiface.h" -#include "retroshare/rspeers.h" -#include "retroshare/rsidentity.h" - -#include "pqi/pqibin.h" -#include "pqi/p3linkmgr.h" -#include "pqi/authgpg.h" -#include "pqi/p3cfgmgr.h" - -#include "gxs/gxssecurity.h" - -#include "services/p3idservice.h" -#include "services/p3msgservice.h" - -#include "pgp/pgpkeyutil.h" -#include "rsserver/p3face.h" - -#include "rsitems/rsconfigitems.h" - -#include "grouter/p3grouter.h" -#include "grouter/groutertypes.h" - -#include "util/rsdebug.h" -#include "util/rsdir.h" -#include "util/rsstring.h" -#include "util/radix64.h" -#include "util/rsrandom.h" -#include "util/rsmemory.h" -#include "util/rsprint.h" -#include "util/rsthreads.h" - -#include -#include -#include -#include - -using namespace Rs::Msgs; - -/// keep msg hashes for 2 months to avoid re-sent msgs -static constexpr uint32_t RS_MSG_DISTANT_MESSAGE_HASH_KEEP_TIME = 2*30*86400; - -/* Another little hack ..... unique message Ids - * will be handled in this class..... - * These are unique within this run of the server, - * and are not stored long term.... - * - * Only 3 entry points: - * (1) from network.... - * (2) from local send - * (3) from storage... - */ - -p3MsgService::p3MsgService( p3ServiceControl *sc, p3IdService *id_serv, - p3GxsTrans& gxsMS ) - : p3Service(), p3Config(), - gxsOngoingMutex("p3MsgService Gxs Outgoing Mutex"), mIdService(id_serv), - mServiceCtrl(sc), mMsgMtx("p3MsgService"), mMsgUniqueId(0), - recentlyReceivedMutex("p3MsgService recently received hash mutex"), - mGxsTransServ(gxsMS) -{ - /* this serialiser is used for services. It's not the same than the one - * returned by setupSerialiser(). We need both!! */ - _serialiser = new RsMsgSerialiser(); - addSerialType(_serialiser); - - /* MsgIds are not transmitted, but only used locally as a storage index. - * As such, thay do not need to be different at friends nodes. */ - mMsgUniqueId = 1; - - mShouldEnableDistantMessaging = true; - mDistantMessagingEnabled = false; - mDistantMessagePermissions = RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NONE; - - if(sc) initStandardTagTypes(); // Initialize standard tag types - - mGxsTransServ.registerGxsTransClient( GxsTransSubServices::P3_MSG_SERVICE, - this ); -} - -const std::string MSG_APP_NAME = "msg"; -const uint16_t MSG_APP_MAJOR_VERSION = 1; -const uint16_t MSG_APP_MINOR_VERSION = 0; -const uint16_t MSG_MIN_MAJOR_VERSION = 1; -const uint16_t MSG_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3MsgService::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_MSG, - MSG_APP_NAME, - MSG_APP_MAJOR_VERSION, - MSG_APP_MINOR_VERSION, - MSG_MIN_MAJOR_VERSION, - MSG_MIN_MINOR_VERSION); -} - -p3MsgService::~p3MsgService() -{ - RS_STACK_MUTEX(mMsgMtx); /********** STACK LOCKED MTX ******/ - - for(auto tag:mTags) delete tag.second; - for(auto tag:mMsgTags) delete tag.second; - for(auto msgid:mSrcIds) delete msgid.second; - for(auto parentid:mParentId) delete parentid.second; - for(auto img:imsg) delete img.second; - for(auto mout:msgOutgoing) delete mout.second; - - for(auto mpend:_pendingPartialMessages) delete mpend.second; -} - -uint32_t p3MsgService::getNewUniqueMsgId() -{ - RS_STACK_MUTEX(mMsgMtx); /********** STACK LOCKED MTX ******/ - return mMsgUniqueId++; -} - -int p3MsgService::tick() -{ - /* don't worry about increasing tick rate! - * (handled by p3service) - */ - - incomingMsgs(); - - static rstime_t last_management_time = 0 ; - rstime_t now = time(NULL) ; - - if(now > last_management_time + 5) - { - manageDistantPeers(); - checkOutgoingMessages(); - cleanListOfReceivedMessageHashes(); - - last_management_time = now; - } - - return 0; -} - -void p3MsgService::cleanListOfReceivedMessageHashes() -{ - RS_STACK_MUTEX(recentlyReceivedMutex); - - rstime_t now = time(nullptr); - - for( auto it = mRecentlyReceivedMessageHashes.begin(); - it != mRecentlyReceivedMessageHashes.end(); ) - if( now > RS_MSG_DISTANT_MESSAGE_HASH_KEEP_TIME + it->second ) - { - std::cerr << "p3MsgService(): cleanListOfReceivedMessageHashes(). " - << "Removing old hash " << it->first << ", aged " - << now - it->second << " secs ago" << std::endl; - - it = mRecentlyReceivedMessageHashes.erase(it); - } - else ++it; -} - -void p3MsgService::processIncomingMsg(RsMsgItem *mi) -{ - mi -> recvTime = static_cast(time(nullptr)); - mi -> msgId = getNewUniqueMsgId(); - - { - RS_STACK_MUTEX(mMsgMtx); - - /* from a peer */ - - mi->msgFlags &= (RS_MSG_FLAGS_DISTANT | RS_MSG_FLAGS_SYSTEM); // remove flags except those - mi->msgFlags |= RS_MSG_FLAGS_NEW; - - if (rsEvents) - { - auto ev = std::make_shared(); - ev->mMailStatusEventCode = RsMailStatusEventCode::NEW_MESSAGE; - ev->mChangedMsgIds.insert(std::to_string(mi->msgId)); - rsEvents->postEvent(ev); - } - - imsg[mi->msgId] = mi; - RsMsgSrcId* msi = new RsMsgSrcId(); - msi->msgId = mi->msgId; - msi->srcId = mi->PeerId(); - mSrcIds.insert(std::pair(msi->msgId, msi)); - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - /**** STACK UNLOCKED ***/ - } - - // If the peer is allowed to push files, then auto-download the recommended files. - - RsIdentityDetails id_details; - if(rsIdentity->getIdDetails(RsGxsId(mi->PeerId()),id_details) && !id_details.mPgpId.isNull() && (rsPeers->servicePermissionFlags(id_details.mPgpId) & RS_NODE_PERM_ALLOW_PUSH)) - { - std::list srcIds; - srcIds.push_back(mi->PeerId()); - - for(std::list::const_iterator it(mi->attachment.items.begin());it!=mi->attachment.items.end();++it) - rsFiles->FileRequest((*it).name,(*it).hash,(*it).filesize,std::string(),RS_FILE_REQ_ANONYMOUS_ROUTING,srcIds) ; - } -} - -bool p3MsgService::checkAndRebuildPartialMessage(RsMsgItem *ci) -{ - // Check is the item is ending an incomplete item. - // - std::map::iterator it = _pendingPartialMessages.find(ci->PeerId()) ; - - bool ci_is_partial = ci->msgFlags & RS_MSG_FLAGS_PARTIAL ; - - if(it != _pendingPartialMessages.end()) - { -#ifdef MSG_DEBUG - std::cerr << "Pending message found. Appending it." << std::endl; -#endif - // Yes, there is. Append the item to ci. - - ci->message = it->second->message + ci->message ; - ci->msgFlags |= it->second->msgFlags ; - - delete it->second ; - - if(!ci_is_partial) - _pendingPartialMessages.erase(it) ; - } - - if(ci_is_partial) - { -#ifdef MSG_DEBUG - std::cerr << "Message is partial, storing for later." << std::endl; -#endif - // The item is a partial message. Push it, and wait for the rest. - // - _pendingPartialMessages[ci->PeerId()] = ci ; - return false ; - } - else - { -#ifdef MSG_DEBUG - std::cerr << "Message is complete, using it now." << std::endl; -#endif - return true ; - } -} - -int p3MsgService::incomingMsgs() -{ - RsMsgItem *mi; - int i = 0; - - while((mi = (RsMsgItem *) recvItem()) != NULL) - { - handleIncomingItem(mi) ; - ++i ; - } - - return i; -} - -void p3MsgService::handleIncomingItem(RsMsgItem *mi) -{ - // only returns true when a msg is complete. - if(checkAndRebuildPartialMessage(mi)) - { - processIncomingMsg(mi); - } -} - -void p3MsgService::statusChange(const std::list &plist) -{ - /* should do it properly! */ - /* only do this when a new peer is connected */ - bool newPeers = false; - std::list::const_iterator it; - for(it = plist.begin(); it != plist.end(); ++it) - { - if (it->actions & RS_SERVICE_PEER_CONNECTED) - { - newPeers = true; - } - } - - if (newPeers) - { - checkOutgoingMessages(); - } -} - -void p3MsgService::checkSizeAndSendMessage(RsMsgItem *msg) -{ - // We check the message item, and possibly split it into multiple messages, if the message is too big. - - static const uint32_t MAX_STRING_SIZE = 15000 ; - - std::cerr << "Msg is size " << msg->message.size() << std::endl; - - while(msg->message.size() > MAX_STRING_SIZE) - { - // chop off the first 15000 wchars - - RsMsgItem *item = new RsMsgItem(*msg) ; - - item->message = item->message.substr(0,MAX_STRING_SIZE) ; - msg->message = msg->message.substr(MAX_STRING_SIZE,msg->message.size()-MAX_STRING_SIZE) ; - -#ifdef DEBUG_DISTANT_MSG - std::cerr << " Chopped off msg of size " << item->message.size() << std::endl; -#endif - - // Indicate that the message is to be continued. - // - item->msgFlags |= RS_MSG_FLAGS_PARTIAL ; - sendItem(item) ; - } -#ifdef DEBUG_DISTANT_MSG - std::cerr << " Chopped off msg of size " << msg->message.size() << std::endl; -#endif - - sendItem(msg) ; -} - -int p3MsgService::checkOutgoingMessages() -{ - std::list output_queue; - - auto pEvent = std::make_shared(); - pEvent->mMailStatusEventCode = RsMailStatusEventCode::MESSAGE_SENT; - - { - RS_STACK_MUTEX(mMsgMtx); /********** STACK LOCKED MTX ******/ - - const RsPeerId& ownId = mServiceCtrl->getOwnId(); - - std::list::iterator it; - std::list toErase; - - std::map::iterator mit; - for( mit = msgOutgoing.begin(); mit != msgOutgoing.end(); ++mit ) - { - if (mit->second->msgFlags & RS_MSG_FLAGS_TRASH) continue; - - /* find the certificate */ - RsPeerId pid = mit->second->PeerId(); - bool should_send = false; - - if( pid == ownId) should_send = true; - - // FEEDBACK Msg to Ourselves - if( mServiceCtrl->isPeerConnected(getServiceInfo().mServiceType, - pid) ) - should_send = true; - - if( (mit->second->msgFlags & RS_MSG_FLAGS_DISTANT) && - !(mit->second->msgFlags & RS_MSG_FLAGS_ROUTED)) - should_send = true; - - if(should_send) - { - Dbg3() << __PRETTY_FUNCTION__ << " Sending out message" - << std::endl; - /* remove the pending flag */ - - output_queue.push_back(mit->second); - pEvent->mChangedMsgIds.insert(std::to_string(mit->first)); - - /* When the message is a distant msg, dont remove it yet from - * the list. Only mark it as being sent, so that we don't send - * it again. */ - if(!(mit->second->msgFlags & RS_MSG_FLAGS_DISTANT)) - { - (mit->second)->msgFlags &= ~RS_MSG_FLAGS_PENDING; - toErase.push_back(mit->first); - } - else - { -#ifdef DEBUG_DISTANT_MSG - std::cerr << "Message id " << mit->first << " is distant: " - << "kept in outgoing, and marked as ROUTED" - << std::endl; -#endif - mit->second->msgFlags |= RS_MSG_FLAGS_ROUTED; - } - } -#ifdef DEBUG_DISTANT_MSG - else - Dbg3() << __PRETTY_FUNCTION__ << " Delaying until available..." << std::endl; -#endif - } - - /* clean up */ - for(it = toErase.begin(); it != toErase.end(); ++it) - { - mit = msgOutgoing.find(*it); - if ( mit != msgOutgoing.end() ) msgOutgoing.erase(mit); - - std::map::iterator srcIt = mSrcIds.find(*it); - if (srcIt != mSrcIds.end()) - { - delete (srcIt->second); - mSrcIds.erase(srcIt); - } - } - - if (toErase.size() > 0) IndicateConfigChanged(); - } - - for( std::list::const_iterator it(output_queue.begin()); - it != output_queue.end(); ++it ) - if( (*it)->msgFlags & RS_MSG_FLAGS_DISTANT ) // don't split distant messages. The global router takes care of it. - sendDistantMsgItem(*it); - else - checkSizeAndSendMessage(*it); - - if(rsEvents && !pEvent->mChangedMsgIds.empty()) - rsEvents->postEvent(pEvent); - - return 0; -} - -bool p3MsgService::saveList(bool& cleanup, std::list& itemList) -{ - RsMsgGRouterMap* gxsmailmap = new RsMsgGRouterMap; - { - RS_STACK_MUTEX(gxsOngoingMutex); - gxsmailmap->ongoing_msgs = gxsOngoingMessages; - } - itemList.push_front(gxsmailmap); - - std::map::iterator mit; - std::map::iterator mit2; - std::map::iterator mit3; - std::map::iterator lit; - std::map::iterator mit4; - - cleanup = true; - - mMsgMtx.lock(); - - for(mit = imsg.begin(); mit != imsg.end(); ++mit) - itemList.push_back(new RsMsgItem(*mit->second)); - - for(lit = mSrcIds.begin(); lit != mSrcIds.end(); ++lit) - itemList.push_back(new RsMsgSrcId(*lit->second)); - - - for(mit = msgOutgoing.begin(); mit != msgOutgoing.end(); ++mit) - itemList.push_back(new RsMsgItem(*mit->second)) ; - - for(mit2 = mTags.begin(); mit2 != mTags.end(); ++mit2) - itemList.push_back(new RsMsgTagType(*mit2->second)); - - for(mit3 = mMsgTags.begin(); mit3 != mMsgTags.end(); ++mit3) - itemList.push_back(new RsMsgTags(*mit3->second)); - - for(mit4 = mParentId.begin(); mit4 != mParentId.end(); ++mit4) - itemList.push_back(new RsMsgParentId(*mit4->second)); - - RsMsgGRouterMap *grmap = new RsMsgGRouterMap ; - grmap->ongoing_msgs = _ongoing_messages ; - - itemList.push_back(grmap) ; - - RsMsgDistantMessagesHashMap *ghm = new RsMsgDistantMessagesHashMap; - { - RS_STACK_MUTEX(recentlyReceivedMutex); - ghm->hash_map = mRecentlyReceivedMessageHashes; - } - itemList.push_back(ghm); - - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; - RsTlvKeyValue kv; - kv.key = "DISTANT_MESSAGES_ENABLED" ; - kv.value = mShouldEnableDistantMessaging?"YES":"NO" ; - vitem->tlvkvs.pairs.push_back(kv) ; - - kv.key = "DISTANT_MESSAGE_PERMISSION_FLAGS" ; - kv.value = RsUtil::NumberToString(mDistantMessagePermissions) ; - vitem->tlvkvs.pairs.push_back(kv) ; - - itemList.push_back(vitem); - - return true; -} - -void p3MsgService::saveDone() -{ - // unlocks mutex which has been locked by savelist - mMsgMtx.unlock(); -} - -RsSerialiser* p3MsgService::setupSerialiser() // this serialiser is used for config. So it adds somemore info in the serialised items -{ - RsSerialiser *rss = new RsSerialiser ; - - rss->addSerialType(new RsMsgSerialiser(RsSerializationFlags::CONFIG)); - rss->addSerialType(new RsGeneralConfigSerialiser()); - - return rss; -} - -// build list of standard tag types -static void getStandardTagTypes(MsgTagType &tags) -{ - /* create standard tag types, the text must be translated in the GUI */ - tags.types [RS_MSGTAGTYPE_IMPORTANT] = std::pair ("Important", 0xFF0000); - tags.types [RS_MSGTAGTYPE_WORK] = std::pair ("Work", 0xFF9900); - tags.types [RS_MSGTAGTYPE_PERSONAL] = std::pair ("Personal", 0x009900); - tags.types [RS_MSGTAGTYPE_TODO] = std::pair ("Todo", 0x3333FF); - tags.types [RS_MSGTAGTYPE_LATER] = std::pair ("Later", 0x993399); -} - -// Initialize the standard tag types after load -void p3MsgService::initStandardTagTypes() -{ - bool bChanged = false; - const RsPeerId& ownId = mServiceCtrl->getOwnId(); - - MsgTagType tags; - getStandardTagTypes(tags); - - std::map >::iterator tit; - for (tit = tags.types.begin(); tit != tags.types.end(); ++tit) { - std::map::iterator mit = mTags.find(tit->first); - if (mit == mTags.end()) { - RsMsgTagType* tagType = new RsMsgTagType(); - tagType->PeerId (ownId); - tagType->tagId = tit->first; - tagType->text = tit->second.first; - tagType->rgb_color = tit->second.second; - - mTags.insert(std::pair(tit->first, tagType)); - - bChanged = true; - } - } - - if (bChanged) { - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - } -} - -bool p3MsgService::loadList(std::list& load) -{ - auto gxsmIt = load.begin(); - RsMsgGRouterMap* gxsmailmap = dynamic_cast(*gxsmIt); - if(gxsmailmap) - { - { - RS_STACK_MUTEX(gxsOngoingMutex); - gxsOngoingMessages = gxsmailmap->ongoing_msgs; - } - delete *gxsmIt; load.erase(gxsmIt); - } - - RsMsgItem *mitem; - RsMsgTagType* mtt; - RsMsgTags* mti; - RsMsgSrcId* msi; - RsMsgParentId* msp; - RsMsgGRouterMap* grm; - RsMsgDistantMessagesHashMap *ghm; - - std::list items; - std::list::iterator it; - std::map::iterator tagIt; - std::map srcIdMsgMap; - std::map::iterator srcIt; - - uint32_t max_msg_id = 0 ; - - // load items and calculate next unique msgId - for(it = load.begin(); it != load.end(); ++it) - { - if (NULL != (mitem = dynamic_cast(*it))) - { - /* STORE MsgID */ - if (mitem->msgId > max_msg_id) - max_msg_id = mitem->msgId ; - - items.push_back(mitem); - } - else if (NULL != (grm = dynamic_cast(*it))) - { - typedef std::map tT; - for( tT::const_iterator bit = grm->ongoing_msgs.begin(); - bit != grm->ongoing_msgs.end(); ++bit ) - _ongoing_messages.insert(*bit); - delete *it; - continue; - } - else if(NULL != (ghm = dynamic_cast(*it))) - { - { - RS_STACK_MUTEX(recentlyReceivedMutex); - mRecentlyReceivedMessageHashes = ghm->hash_map; - } -#ifdef DEBUG_DISTANT_MSG - std::cerr << " loaded recently received message map: " << std::endl; - - for(std::map::const_iterator it(mRecentlyReceivedDistantMessageHashes.begin());it!=mRecentlyReceivedDistantMessageHashes.end();++it) - std::cerr << " " << it->first << " received " << time(NULL)-it->second << " secs ago." << std::endl; -#endif - delete *it ; - continue ; - } - else if(NULL != (mtt = dynamic_cast(*it))) - { - // delete standard tags as they are now save in config - if(mTags.end() == (tagIt = mTags.find(mtt->tagId))) - { - mTags.insert(std::pair(mtt->tagId, mtt)); - } - else - { - delete mTags[mtt->tagId]; - mTags.erase(tagIt); - mTags.insert(std::pair(mtt->tagId, mtt)); - } - - } - else if(NULL != (mti = dynamic_cast(*it))) - { - mMsgTags.insert(std::pair(mti->msgId, mti)); - } - else if(NULL != (msi = dynamic_cast(*it))) - { - srcIdMsgMap.insert(std::pair(msi->msgId, msi->srcId)); - mSrcIds.insert(std::pair(msi->msgId, msi)); // does not need to be kept - } - else if(NULL != (msp = dynamic_cast(*it))) - { - mParentId.insert(std::pair(msp->msgId, msp)); - } - - RsConfigKeyValueSet *vitem = NULL ; - - if(NULL != (vitem = dynamic_cast(*it))) - { - for(std::list::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) - { - if(kit->key == "DISTANT_MESSAGES_ENABLED") - { -#ifdef MSG_DEBUG - std::cerr << "Loaded config default nick name for distant chat: " << kit->value << std::endl ; -#endif - mShouldEnableDistantMessaging = (kit->value == "YES") ; - } - if(kit->key == "DISTANT_MESSAGE_PERMISSION_FLAGS") - { -#ifdef MSG_DEBUG - std::cerr << "Loaded distant message permission flags: " << kit->value << std::endl ; -#endif - if (!kit->value.empty()) - { - std::istringstream is(kit->value) ; - - uint32_t tmp ; - is >> tmp ; - - if(tmp < 3) - mDistantMessagePermissions = tmp ; - else - std::cerr << "(EE) Invalid value read for DistantMessagePermission flags in config: " << tmp << std::endl; - } - } - } - - delete *it ; - continue ; - } - } - mMsgUniqueId = max_msg_id + 1; // make it unique with respect to what was loaded. Not totally safe, but works 99.9999% of the cases. - load.clear() ; - - // sort items into lists - std::list::iterator msgIt; - for (msgIt = items.begin(); msgIt != items.end(); ++msgIt) - { - mitem = *msgIt; - - /* STORE MsgID */ - if (mitem->msgId == 0) { - mitem->msgId = getNewUniqueMsgId(); - } - - RS_STACK_MUTEX(mMsgMtx); - - srcIt = srcIdMsgMap.find(mitem->msgId); - if(srcIt != srcIdMsgMap.end()) { - mitem->PeerId(srcIt->second); - srcIdMsgMap.erase(srcIt); - } - - /* switch depending on the PENDING - * flags - */ - if (mitem -> msgFlags & RS_MSG_FLAGS_PENDING) - { - - //std::cerr << "MSG_PENDING"; - //std::cerr << std::endl; - //mitem->print(std::cerr); - - msgOutgoing[mitem->msgId] = mitem; - } - else - { - imsg[mitem->msgId] = mitem; - } - } - - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - /* remove missing msgId in mSrcIds */ - for (srcIt = srcIdMsgMap.begin(); srcIt != srcIdMsgMap.end(); ++srcIt) { - std::map::iterator it = mSrcIds.find(srcIt->first); - if (it != mSrcIds.end()) { - delete(it->second); - mSrcIds.erase(it); - } - } - - /* remove missing msgId in mParentId */ - std::map::iterator mit = mParentId.begin(); - while (mit != mParentId.end()) { - if (imsg.find(mit->first) == imsg.end()) { - if (msgOutgoing.find(mit->first) == msgOutgoing.end()) { - /* not found */ - mParentId.erase(mit++); - continue; - } - } - - ++mit; - } - - return true; -} - -void p3MsgService::loadWelcomeMsg() -{ - /* Load Welcome Message */ - RsMsgItem *msg = new RsMsgItem(); - - //msg -> PeerId(mServiceCtrl->getOwnId()); - - msg -> sendTime = time(NULL); - msg -> recvTime = time(NULL); - msg -> msgFlags = RS_MSG_FLAGS_NEW; - - msg -> subject = "Welcome to Retroshare"; - - msg -> message = "Send and receive messages with your friends...\n"; - msg -> message += "These can hold recommendations from your local shared files.\n\n"; - msg -> message += "Add recommendations through the Local Files Dialog.\n\n"; - msg -> message += "Enjoy."; - - msg -> msgId = getNewUniqueMsgId(); - - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - imsg[msg->msgId] = msg; - - IndicateConfigChanged(); -} - - -/***********************************************************************/ -/***********************************************************************/ -/***********************************************************************/ -/***********************************************************************/ - - -/****************************************/ -/****************************************/ - -bool p3MsgService::getMessageSummaries(std::list &msgList) -{ - /* do stuff */ - msgList.clear(); - - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator mit; - for(mit = imsg.begin(); mit != imsg.end(); ++mit) - { - MsgInfoSummary mis; - initRsMIS(mit->second, mis); - msgList.push_back(mis); - } - - for(mit = msgOutgoing.begin(); mit != msgOutgoing.end(); ++mit) - { - MsgInfoSummary mis; - initRsMIS(mit->second, mis); - msgList.push_back(mis); - } - return true; -} - -bool p3MsgService::getMessage(const std::string &mId, MessageInfo &msg) -{ - std::map::iterator mit; - uint32_t msgId = atoi(mId.c_str()); - - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - mit = imsg.find(msgId); - if (mit == imsg.end()) - { - mit = msgOutgoing.find(msgId); - if (mit == msgOutgoing.end()) - { - return false; - } - } - - /* mit valid */ - initRsMI(mit->second, msg); - - std::map::const_iterator it = mSrcIds.find(msgId) ; - if(it != mSrcIds.end()) - msg.rsgxsid_srcId = RsGxsId(it->second->srcId) ; // (cyril) this is a hack. Not good. I'm not removing it because it may have consequences, but I dont like this. - - return true; -} - -void p3MsgService::getMessageCount(uint32_t &nInbox, uint32_t &nInboxNew, uint32_t &nOutbox, uint32_t &nDraftbox, uint32_t &nSentbox, uint32_t &nTrashbox) -{ - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - nInbox = 0; - nInboxNew = 0; - nOutbox = 0; - nDraftbox = 0; - nSentbox = 0; - nTrashbox = 0; - - std::map::iterator mit; - std::map *apMsg [2] = { &imsg, &msgOutgoing }; - - for (int i = 0; i < 2; i++) { - for (mit = apMsg [i]->begin(); mit != apMsg [i]->end(); ++mit) { - MsgInfoSummary mis; - initRsMIS(mit->second, mis); - - if (mis.msgflags & RS_MSG_TRASH) { - ++nTrashbox; - continue; - } - switch (mis.msgflags & RS_MSG_BOXMASK) { - case RS_MSG_INBOX: - ++nInbox; - if ((mis.msgflags & RS_MSG_NEW) == RS_MSG_NEW) - ++nInboxNew; - break; - case RS_MSG_OUTBOX: - ++nOutbox; - break; - case RS_MSG_DRAFTBOX: - ++nDraftbox; - break; - case RS_MSG_SENTBOX: - ++nSentbox; - break; - } - } - } -} - -/* remove based on the unique mid (stored in sid) */ -bool p3MsgService::removeMsgId(const std::string &mid) -{ - std::map::iterator mit; - uint32_t msgId = atoi(mid.c_str()); - if (msgId == 0) { - std::cerr << "p3MsgService::removeMsgId: Unknown msgId " << msgId << std::endl; - return false; - } - - bool changed = false; - - auto pEvent = std::make_shared(); - pEvent->mMailStatusEventCode = RsMailStatusEventCode::MESSAGE_REMOVED; - - { - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - mit = imsg.find(msgId); - if (mit != imsg.end()) - { - changed = true; - RsMsgItem *mi = mit->second; - imsg.erase(mit); - delete mi; - pEvent->mChangedMsgIds.insert(mid); - } - - mit = msgOutgoing.find(msgId); - if (mit != msgOutgoing.end()) - { - changed = true ; - RsMsgItem *mi = mit->second; - msgOutgoing.erase(mit); - delete mi; - pEvent->mChangedMsgIds.insert(mid); - } - - std::map::iterator srcIt = mSrcIds.find(msgId); - if (srcIt != mSrcIds.end()) { - changed = true; - delete (srcIt->second); - mSrcIds.erase(srcIt); - pEvent->mChangedMsgIds.insert(mid); - } - } - - if(changed) { - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - setMessageTag(mid, 0, false); - setMsgParentId(msgId, 0); - } - - if(rsEvents && !pEvent->mChangedMsgIds.empty()) - rsEvents->postEvent(pEvent); - - return changed; -} - -bool p3MsgService::markMsgIdRead(const std::string &mid, bool unreadByUser) -{ - std::map::iterator mit; - uint32_t msgId = atoi(mid.c_str()); - - { - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - mit = imsg.find(msgId); - if (mit != imsg.end()) - { - RsMsgItem *mi = mit->second; - - uint32_t msgFlags = mi->msgFlags; - - /* remove new state */ - mi->msgFlags &= ~(RS_MSG_FLAGS_NEW); - - /* set state from user */ - if (unreadByUser) { - mi->msgFlags |= RS_MSG_FLAGS_UNREAD_BY_USER; - } else { - mi->msgFlags &= ~RS_MSG_FLAGS_UNREAD_BY_USER; - } - - if (mi->msgFlags != msgFlags) - { - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - auto pEvent = std::make_shared(); - pEvent->mMailStatusEventCode = RsMailStatusEventCode::MESSAGE_CHANGED; - pEvent->mChangedMsgIds.insert(mid); - rsEvents->postEvent(pEvent); - } - } else { - return false; - } - } /* UNLOCKED */ - - return true; -} - -bool p3MsgService::setMsgFlag(const std::string &mid, uint32_t flag, uint32_t mask) -{ - std::map::iterator mit; - uint32_t msgId = atoi(mid.c_str()); - - { - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - mit = imsg.find(msgId); - if (mit == imsg.end()) - { - mit = msgOutgoing.find(msgId); - if (mit == msgOutgoing.end()) - { - return false; - } - } - - uint32_t oldFlag = mit->second->msgFlags; - - mit->second->msgFlags &= ~mask; - mit->second->msgFlags |= flag; - - if (mit->second->msgFlags != oldFlag) { - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - auto pEvent = std::make_shared(); - pEvent->mMailStatusEventCode = RsMailStatusEventCode::MESSAGE_CHANGED; - pEvent->mChangedMsgIds.insert(mid); - rsEvents->postEvent(pEvent); - } - } /* UNLOCKED */ - - return true; -} - -bool p3MsgService::getMsgParentId(const std::string &msgId, std::string &msgParentId) -{ - msgParentId.clear(); - - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator mit = mParentId.find(atoi(msgId.c_str())); - if (mit == mParentId.end()) { - return false; - } - - rs_sprintf(msgParentId, "%lu", mit->second->msgParentId); - - return true; -} - -bool p3MsgService::setMsgParentId(uint32_t msgId, uint32_t msgParentId) -{ - std::map::iterator mit; - - bool changed = false; - - { - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - mit = mParentId.find(msgId); - if (mit == mParentId.end()) - { - if (msgParentId) { - RsMsgParentId* msp = new RsMsgParentId(); - msp->PeerId (mServiceCtrl->getOwnId()); - msp->msgId = msgId; - msp->msgParentId = msgParentId; - mParentId.insert(std::pair(msgId, msp)); - - changed = true; - } - } else { - if (msgParentId) { - if (mit->second->msgParentId != msgParentId) { - mit->second->msgParentId = msgParentId; - changed = true; - } - } else { - delete mit->second; - mParentId.erase(mit); - changed = true; - } - } - } /* UNLOCKED */ - - if (changed) { - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - } - - return true; -} - -/****************************************/ -/****************************************/ - /* Message Items */ -// no from field because it's implicitly our own PeerId -uint32_t p3MsgService::sendMessage(RsMsgItem* item) -{ - if(!item) - { - RsErr() << __PRETTY_FUNCTION__ << " item can't be null" << std::endl; - return 0; - } - - item->msgId = getNewUniqueMsgId(); /* grabs Mtx as well */ - item->msgFlags |= (RS_MSG_FLAGS_OUTGOING | RS_MSG_FLAGS_PENDING); /* add pending flag */ - - { - RS_STACK_MUTEX(mMsgMtx) ; - - /* STORE MsgID */ - msgOutgoing[item->msgId] = item; - - if (item->PeerId() != mServiceCtrl->getOwnId()) - { - /* not to the loopback device */ - - RsMsgSrcId* msi = new RsMsgSrcId(); - msi->msgId = item->msgId; - msi->srcId = mServiceCtrl->getOwnId(); - mSrcIds.insert(std::pair(msi->msgId, msi)); - } - } - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - auto pEvent = std::make_shared(); - pEvent->mMailStatusEventCode = RsMailStatusEventCode::MESSAGE_SENT; - pEvent->mChangedMsgIds.insert(std::to_string(item->msgId)); - rsEvents->postEvent(pEvent); - - return item->msgId; -} - -uint32_t p3MsgService::sendDistantMessage(RsMsgItem *item, const RsGxsId& from) -{ - if(!item) - { - RsErr() << __PRETTY_FUNCTION__ << " item can't be null" << std::endl; - print_stacktrace(); - return 0; - } - - item->msgId = getNewUniqueMsgId(); /* grabs Mtx as well */ - item->msgFlags |= ( RS_MSG_FLAGS_DISTANT | RS_MSG_FLAGS_OUTGOING | - RS_MSG_FLAGS_PENDING ); /* add pending flag */ - - { - RS_STACK_MUTEX(mMsgMtx); - - /* STORE MsgID */ - msgOutgoing[item->msgId] = item; - mDistantOutgoingMsgSigners[item->msgId] = from ; - - if (item->PeerId() != mServiceCtrl->getOwnId()) - { - /* not to the loopback device */ - - RsMsgSrcId* msi = new RsMsgSrcId(); - msi->msgId = item->msgId; - msi->srcId = RsPeerId(from); - mSrcIds.insert(std::pair(msi->msgId, msi)); - } - } - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - auto pEvent = std::make_shared(); - pEvent->mMailStatusEventCode = RsMailStatusEventCode::MESSAGE_SENT; - pEvent->mChangedMsgIds.insert(std::to_string(item->msgId)); - rsEvents->postEvent(pEvent); - - return item->msgId; -} - -bool p3MsgService::MessageSend(MessageInfo &info) -{ - for(std::set::const_iterator pit = info.rspeerid_msgto.begin(); pit != info.rspeerid_msgto.end(); ++pit) sendMessage(initMIRsMsg(info, *pit)); - for(std::set::const_iterator pit = info.rspeerid_msgcc.begin(); pit != info.rspeerid_msgcc.end(); ++pit) sendMessage(initMIRsMsg(info, *pit)); - for(std::set::const_iterator pit = info.rspeerid_msgbcc.begin(); pit != info.rspeerid_msgbcc.end(); ++pit) sendMessage(initMIRsMsg(info, *pit)); - - for(std::set::const_iterator pit = info.rsgxsid_msgto.begin(); pit != info.rsgxsid_msgto.end(); ++pit) sendDistantMessage(initMIRsMsg(info, *pit),info.rsgxsid_srcId); - for(std::set::const_iterator pit = info.rsgxsid_msgcc.begin(); pit != info.rsgxsid_msgcc.end(); ++pit) sendDistantMessage(initMIRsMsg(info, *pit),info.rsgxsid_srcId); - for(std::set::const_iterator pit = info.rsgxsid_msgbcc.begin(); pit != info.rsgxsid_msgbcc.end(); ++pit) sendDistantMessage(initMIRsMsg(info, *pit),info.rsgxsid_srcId); - - // store message in outgoing list. In order to appear as sent the message needs to have the OUTGOING flg, but no pending flag on. - - RsMsgItem *msg = initMIRsMsg(info, mServiceCtrl->getOwnId()); - - if (msg) - { - if (msg->msgFlags & RS_MSG_FLAGS_SIGNED) - msg->msgFlags |= RS_MSG_FLAGS_SIGNATURE_CHECKS; // this is always true, since we are sending the message - - /* use processMsg to get the new msgId */ - msg->recvTime = time(NULL); - msg->msgId = getNewUniqueMsgId(); - - msg->msgFlags |= RS_MSG_OUTGOING; - - imsg[msg->msgId] = msg; - - // Update info for caller - info.msgId = std::to_string(msg->msgId); - info .msgflags = msg->msgFlags; - } - - auto pEvent = std::make_shared(); - pEvent->mMailStatusEventCode = RsMailStatusEventCode::MESSAGE_SENT; - pEvent->mChangedMsgIds.insert(std::to_string(msg->msgId)); - rsEvents->postEvent(pEvent); - - return true; -} - -uint32_t p3MsgService::sendMail( - const RsGxsId from, - const std::string& subject, - const std::string& body, - const std::set& to, - const std::set& cc, - const std::set& bcc, - const std::vector& attachments, - std::set& trackingIds, - std::string& errorMsg ) -{ - errorMsg.clear(); - const std::string fname = __PRETTY_FUNCTION__; - auto pCheck = [&](bool test, const std::string& errMsg) - { - if(!test) - { - errorMsg = errMsg; - RsErr() << fname << " " << errMsg << std::endl; - } - return test; - }; - - if(!pCheck(!from.isNull(), "from can't be null")) return false; - if(!pCheck( rsIdentity->isOwnId(from), - "from must be own identity") ) return false; - if(!pCheck(!(to.empty() && cc.empty() && bcc.empty()), - "You must specify at least one recipient" )) return false; - - auto dstCheck = - [&](const std::set& dstSet, const std::string& setName) - { - for(const RsGxsId& dst: dstSet) - { - if(dst.isNull()) - { - errorMsg = setName + " contains a null recipient"; - RsErr() << fname << " " << errorMsg << std::endl; - return false; - } - - if(!rsIdentity->isKnownId(dst)) - { - rsIdentity->requestIdentity(dst); - errorMsg = setName + " contains an unknown recipient: " + - dst.toStdString(); - RsErr() << fname << " " << errorMsg << std::endl; - return false; - } - } - return true; - }; - - if(!dstCheck(to, "to")) return false; - if(!dstCheck(cc, "cc")) return false; - if(!dstCheck(bcc, "bcc")) return false; - - MessageInfo msgInfo; - - msgInfo.rsgxsid_srcId = from; - msgInfo.title = subject; - msgInfo.msg = body; - msgInfo.rsgxsid_msgto = to; - msgInfo.rsgxsid_msgcc = cc; - msgInfo.rsgxsid_msgbcc = bcc; - std::copy( attachments.begin(), attachments.end(), - std::back_inserter(msgInfo.files) ); - - uint32_t ret = 0; - - auto pEvent = std::make_shared(); - pEvent->mMailStatusEventCode = RsMailStatusEventCode::MESSAGE_SENT; - - auto pSend = [&](const std::set& sDest) - { - for(const RsGxsId& dst : sDest) - { - RsMsgItem* msgItem = initMIRsMsg(msgInfo, dst); - if(!msgItem) - { - errorMsg += " initMIRsMsg from: " + from.toStdString() - + " dst: " + dst.toStdString() + " subject: " + subject - + " returned nullptr!\n"; - RsErr() << fname << errorMsg; - continue; - } - - uint32_t msgId = sendDistantMessage(msgItem, from); - // ensure we don't use that ptr again without noticing - msgItem = nullptr; - - if(!msgId) - { - errorMsg += " sendDistantMessage from: " + from.toStdString() - + " dst: " + dst.toStdString() + " subject: " + subject - + " returned 0!\n"; - RsErr() << fname << errorMsg; - continue; - } - - const RsMailMessageId mailId = std::to_string(msgId); - pEvent->mChangedMsgIds.insert(mailId); - trackingIds.insert(RsMailIdRecipientIdPair(mailId, dst)); - ++ret; - } - }; - - pSend(to); - pSend(cc); - pSend(bcc); - - if(rsEvents) rsEvents->postEvent(pEvent); - return ret; -} - -bool p3MsgService::SystemMessage(const std::string &title, const std::string &message, uint32_t systemFlag) -{ - if ((systemFlag & RS_MSG_SYSTEM) == 0) { - /* no flag specified */ - return false; - } - - - RsMsgItem *msg = new RsMsgItem(); - - msg->PeerId();// Notification == null - - msg->msgFlags = 0; - - if (systemFlag & RS_MSG_USER_REQUEST) { - msg->msgFlags |= RS_MSG_FLAGS_USER_REQUEST; - } - if (systemFlag & RS_MSG_FRIEND_RECOMMENDATION) { - msg->msgFlags |= RS_MSG_FLAGS_FRIEND_RECOMMENDATION; - } - if (systemFlag & RS_MSG_PUBLISH_KEY) { - msg->msgFlags |= RS_MSG_FLAGS_PUBLISH_KEY; - } - - msg->msgId = 0; - msg->sendTime = time(NULL); - msg->recvTime = 0; - - msg->subject = title; - msg->message = message; - - msg->rspeerid_msgto.ids.insert(mServiceCtrl->getOwnId()); - - processIncomingMsg(msg); - - return true; -} - -bool p3MsgService::MessageToDraft(MessageInfo &info, const std::string &msgParentId) -{ - RsMsgItem *msg = initMIRsMsg(info, mServiceCtrl->getOwnId()); - if (msg) - { - uint32_t msgId = 0; - if (info.msgId.empty() == false) { - msgId = atoi(info.msgId.c_str()); - } - - if (msgId) { - msg->msgId = msgId; - } else { - msg->msgId = getNewUniqueMsgId(); /* grabs Mtx as well */ - } - - { - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - /* add pending flag */ - msg->msgFlags |= (RS_MSG_OUTGOING | RS_MSG_FLAGS_DRAFT); - - if (msgId) { - // remove existing message - std::map::iterator mit; - mit = imsg.find(msgId); - if (mit != imsg.end()) { - RsMsgItem *mi = mit->second; - imsg.erase(mit); - delete mi; - } - } - /* STORE MsgID */ - imsg[msg->msgId] = msg; - - // return new message id - rs_sprintf(info.msgId, "%lu", msg->msgId); - } - - setMsgParentId(msg->msgId, atoi(msgParentId.c_str())); - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - auto pEvent = std::make_shared(); - pEvent->mMailStatusEventCode = RsMailStatusEventCode::MESSAGE_SENT; - pEvent->mChangedMsgIds.insert(std::to_string(msg->msgId)); - rsEvents->postEvent(pEvent); - - return true; - } - - return false; -} - -bool p3MsgService::getMessageTag(const std::string &msgId, Rs::Msgs::MsgTagInfo& info) -{ - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - return locked_getMessageTag(msgId,info); -} - -bool p3MsgService::getMessageTagTypes(MsgTagType& tags) -{ - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator mit; - - for(mit = mTags.begin(); mit != mTags.end(); ++mit) { - std::pair p(mit->second->text, mit->second->rgb_color); - tags.types.insert(std::pair >(mit->first, p)); - } - - return true; -} - -bool p3MsgService::setMessageTagType(uint32_t tagId, std::string& text, uint32_t rgb_color) -{ - auto ev = std::make_shared(); - - { - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator mit; - mit = mTags.find(tagId); - - if (mit == mTags.end()) { - if (tagId < RS_MSGTAGTYPE_USER) { - std::cerr << "p3MsgService::MessageSetTagType: Standard tag type " << tagId << " cannot be inserted" << std::endl; - return false; - } - - /* new tag */ - RsMsgTagType* tagType = new RsMsgTagType(); - tagType->PeerId (mServiceCtrl->getOwnId()); - tagType->rgb_color = rgb_color; - tagType->tagId = tagId; - tagType->text = text; - - mTags.insert(std::pair(tagId, tagType)); - - ev->mMailTagEventCode = RsMailTagEventCode::TAG_ADDED; - ev->mChangedMsgTagIds.insert(std::to_string(tagId)); - } else { - if (mit->second->text != text || mit->second->rgb_color != rgb_color) { - /* modify existing tag */ - if (tagId >= RS_MSGTAGTYPE_USER) { - mit->second->text = text; - } else { - /* don't change text for standard tag types */ - if (mit->second->text != text) { - std::cerr << "p3MsgService::MessageSetTagType: Text " << text << " for standard tag type " << tagId << " cannot be changed" << std::endl; - } - } - mit->second->rgb_color = rgb_color; - - ev->mMailTagEventCode = RsMailTagEventCode::TAG_CHANGED; - ev->mChangedMsgTagIds.insert(std::to_string(tagId)); - } - } - - } /* UNLOCKED */ - - if (!ev->mChangedMsgTagIds.empty()) { - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - rsEvents->postEvent(ev); - - return true; - } - - return false; -} - -bool p3MsgService::removeMessageTagType(uint32_t tagId) -{ - if (tagId < RS_MSGTAGTYPE_USER) { - std::cerr << "p3MsgService::MessageRemoveTagType: Can't delete standard tag type " << tagId << std::endl; - return false; - } - - auto msgEvent = std::make_shared(); - msgEvent->mMailStatusEventCode = RsMailStatusEventCode::TAG_CHANGED; - - { - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator mit; - mit = mTags.find(tagId); - - if (mit == mTags.end()) { - /* tag id not found */ - std::cerr << "p3MsgService::MessageRemoveTagType: Tag Id not found " << tagId << std::endl; - return false; - } - - /* search for messages with this tag type */ - std::map::iterator mit1; - for (mit1 = mMsgTags.begin(); mit1 != mMsgTags.end(); ) { - RsMsgTags* tag = mit1->second; - - std::list::iterator lit; - lit = std::find(tag->tagIds.begin(), tag->tagIds.end(), tagId); - if (lit != tag->tagIds.end()) { - tag->tagIds.erase(lit); - - if (tag->tagIds.empty()) { - /* remove empty tag */ - delete(tag); - - mMsgTags.erase(mit1++); - } - - if (msgEvent->mChangedMsgIds.find(std::to_string(mit1->first)) == msgEvent->mChangedMsgIds.end()) { - msgEvent->mChangedMsgIds.insert(std::to_string(mit1->first)); - } - } - ++mit1; - } - - /* remove tag type */ - delete(mit->second); - mTags.erase(mit); - - } /* UNLOCKED */ - - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - auto ev = std::make_shared(); - ev->mMailTagEventCode = RsMailTagEventCode::TAG_REMOVED; - ev->mChangedMsgTagIds.insert(std::to_string(tagId)); - rsEvents->postEvent(ev); - - if (!msgEvent->mChangedMsgIds.empty()) { - rsEvents->postEvent(msgEvent); - } - - return true; -} - -bool p3MsgService::locked_getMessageTag(const std::string &msgId, MsgTagInfo& info) -{ - uint32_t mid = atoi(msgId.c_str()); - if (mid == 0) { - std::cerr << "p3MsgService::MessageGetMsgTag: Unknown msgId " << msgId << std::endl; - return false; - } - - std::map::iterator mit; - - if(mMsgTags.end() != (mit = mMsgTags.find(mid))) { - rs_sprintf(info.msgId, "%lu", mit->second->msgId); - info.tagIds = mit->second->tagIds; - - return true; - } - - return false; -} - -/* set == false && tagId == 0 --> remove all */ -bool p3MsgService::setMessageTag(const std::string &msgId, uint32_t tagId, bool set) -{ - uint32_t mid = atoi(msgId.c_str()); - if (mid == 0) { - std::cerr << "p3MsgService::MessageSetMsgTag: Unknown msgId " << msgId << std::endl; - return false; - } - - if (tagId == 0) { - if (set == true) { - std::cerr << "p3MsgService::MessageSetMsgTag: No valid tagId given " << tagId << std::endl; - return false; - } - } - - auto ev = std::make_shared(); - ev->mMailStatusEventCode = RsMailStatusEventCode::TAG_CHANGED; - - { - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator mit; - mit = mMsgTags.find(mid); - - if (mit == mMsgTags.end()) { - if (set) { - /* new msg */ - RsMsgTags* tag = new RsMsgTags(); - tag->PeerId (mServiceCtrl->getOwnId()); - - tag->msgId = mid; - tag->tagIds.push_back(tagId); - - mMsgTags.insert(std::pair(tag->msgId, tag)); - - ev->mChangedMsgIds.insert(msgId); - } - } else { - RsMsgTags* tag = mit->second; - - /* search existing tagId */ - std::list::iterator lit; - if (tagId) { - lit = std::find(tag->tagIds.begin(), tag->tagIds.end(), tagId); - } else { - lit = tag->tagIds.end(); - } - - if (set) { - if (lit == tag->tagIds.end()) { - tag->tagIds.push_back(tagId); - /* keep the list sorted */ - tag->tagIds.sort(); - ev->mChangedMsgIds.insert(msgId); - } - } else { - if (tagId == 0) { - /* remove all */ - delete(tag); - mMsgTags.erase(mit); - ev->mChangedMsgIds.insert(msgId); - } else { - if (lit != tag->tagIds.end()) { - tag->tagIds.erase(lit); - ev->mChangedMsgIds.insert(msgId); - - if (tag->tagIds.empty()) { - /* remove empty tag */ - delete(tag); - mMsgTags.erase(mit); - } - } - } - } - } - - } /* UNLOCKED */ - - if (!ev->mChangedMsgIds.empty()) { - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - rsEvents->postEvent(ev); - - return true; - } - - return false; -} - -bool p3MsgService::resetMessageStandardTagTypes(MsgTagType& tags) -{ - MsgTagType standardTags; - getStandardTagTypes(standardTags); - - std::map >::iterator mit; - for (mit = standardTags.types.begin(); mit != standardTags.types.end(); ++mit) { - tags.types[mit->first] = mit->second; - } - - return true; -} - -/* move message to trash based on the unique mid */ -bool p3MsgService::MessageToTrash(const std::string &mid, bool bTrash) -{ - std::map::iterator mit; - uint32_t msgId = atoi(mid.c_str()); - - bool bFound = false; - auto pEvent = std::make_shared(); - pEvent->mMailStatusEventCode = RsMailStatusEventCode::MESSAGE_CHANGED; - - { - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - RsMsgItem *mi = NULL; - - mit = imsg.find(msgId); - if (mit != imsg.end()) { - mi = mit->second; - } else { - mit = msgOutgoing.find(msgId); - if (mit != msgOutgoing.end()) { - mi = mit->second; - } - } - - if (mi) { - bFound = true; - - if (bTrash) { - if ((mi->msgFlags & RS_MSG_FLAGS_TRASH) == 0) { - mi->msgFlags |= RS_MSG_FLAGS_TRASH; - pEvent->mChangedMsgIds.insert(std::to_string(mi->msgId)); - } - } else { - if (mi->msgFlags & RS_MSG_FLAGS_TRASH) { - mi->msgFlags &= ~RS_MSG_FLAGS_TRASH; - pEvent->mChangedMsgIds.insert(std::to_string(mi->msgId)); - } - } - } - } - - if (!pEvent->mChangedMsgIds.empty()) { - IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ - - checkOutgoingMessages(); - - if(rsEvents) { - rsEvents->postEvent(pEvent); - } - } - - return bFound; -} - -/****************************************/ -/****************************************/ - - -/****************************************/ - -/**** HELPER FNS For Chat/Msg/Channel Lists ************ - * These aren't required to be locked, unless - * the data used is from internal stores -> then they should be. - */ - -void p3MsgService::initRsMI(RsMsgItem *msg, MessageInfo &mi) -{ - - mi.msgflags = 0; - - /* translate flags, if we sent it... outgoing */ - - if (msg->msgFlags & RS_MSG_FLAGS_OUTGOING) mi.msgflags |= RS_MSG_OUTGOING; - if (msg->msgFlags & RS_MSG_FLAGS_PENDING) mi.msgflags |= RS_MSG_PENDING; /* if it has a pending flag, then its in the outbox */ - if (msg->msgFlags & RS_MSG_FLAGS_DRAFT) mi.msgflags |= RS_MSG_DRAFT; - if (msg->msgFlags & RS_MSG_FLAGS_NEW) mi.msgflags |= RS_MSG_NEW; - - if (msg->msgFlags & RS_MSG_FLAGS_SIGNED) mi.msgflags |= RS_MSG_SIGNED ; - if (msg->msgFlags & RS_MSG_FLAGS_SIGNATURE_CHECKS) mi.msgflags |= RS_MSG_SIGNATURE_CHECKS ; - if (msg->msgFlags & RS_MSG_FLAGS_DISTANT) mi.msgflags |= RS_MSG_DISTANT ; - if (msg->msgFlags & RS_MSG_FLAGS_TRASH) mi.msgflags |= RS_MSG_TRASH; - if (msg->msgFlags & RS_MSG_FLAGS_UNREAD_BY_USER) mi.msgflags |= RS_MSG_UNREAD_BY_USER; - if (msg->msgFlags & RS_MSG_FLAGS_REPLIED) mi.msgflags |= RS_MSG_REPLIED; - if (msg->msgFlags & RS_MSG_FLAGS_FORWARDED) mi.msgflags |= RS_MSG_FORWARDED; - if (msg->msgFlags & RS_MSG_FLAGS_STAR) mi.msgflags |= RS_MSG_STAR; - if (msg->msgFlags & RS_MSG_FLAGS_SPAM) mi.msgflags |= RS_MSG_SPAM; - if (msg->msgFlags & RS_MSG_FLAGS_USER_REQUEST) mi.msgflags |= RS_MSG_USER_REQUEST; - if (msg->msgFlags & RS_MSG_FLAGS_FRIEND_RECOMMENDATION) mi.msgflags |= RS_MSG_FRIEND_RECOMMENDATION; - if (msg->msgFlags & RS_MSG_FLAGS_PUBLISH_KEY) mi.msgflags |= RS_MSG_PUBLISH_KEY; - if (msg->msgFlags & RS_MSG_FLAGS_LOAD_EMBEDDED_IMAGES) mi.msgflags |= RS_MSG_LOAD_EMBEDDED_IMAGES; - - mi.ts = msg->sendTime; - mi.rspeerid_srcId = msg->PeerId(); - - mi.rspeerid_msgto = msg->rspeerid_msgto.ids ; - mi.rspeerid_msgcc = msg->rspeerid_msgcc.ids ; - mi.rspeerid_msgbcc = msg->rspeerid_msgbcc.ids ; - - mi.rsgxsid_msgto = msg->rsgxsid_msgto.ids ; - mi.rsgxsid_msgcc = msg->rsgxsid_msgcc.ids ; - mi.rsgxsid_msgbcc = msg->rsgxsid_msgbcc.ids ; - - mi.title = msg->subject; - mi.msg = msg->message; - { - //msg->msgId; - rs_sprintf(mi.msgId, "%lu", msg->msgId); - } - - mi.attach_title = msg->attachment.title; - mi.attach_comment = msg->attachment.comment; - - mi.count = 0; - mi.size = 0; - - for(std::list::iterator it = msg->attachment.items.begin(); it != msg->attachment.items.end(); ++it) - { - FileInfo fi; - fi.fname = RsDirUtil::getTopDir(it->name); - fi.size = it->filesize; - fi.hash = it->hash; - fi.path = it->path; - mi.files.push_back(fi); - mi.count++; - mi.size += fi.size; - } -} - -void p3MsgService::initRsMIS(RsMsgItem *msg, MsgInfoSummary &mis) -{ - mis.msgflags = 0; - - if(msg->msgFlags & RS_MSG_FLAGS_DISTANT) - mis.msgflags |= RS_MSG_DISTANT ; - - if (msg->msgFlags & RS_MSG_FLAGS_SIGNED) - mis.msgflags |= RS_MSG_SIGNED ; - - if (msg->msgFlags & RS_MSG_FLAGS_SIGNATURE_CHECKS) - mis.msgflags |= RS_MSG_SIGNATURE_CHECKS ; - - /* translate flags, if we sent it... outgoing */ - if ((msg->msgFlags & RS_MSG_FLAGS_OUTGOING) - /*|| (msg->PeerId() == mServiceCtrl->getOwnId())*/) - { - mis.msgflags |= RS_MSG_OUTGOING; - } - /* if it has a pending flag, then its in the outbox */ - if (msg->msgFlags & RS_MSG_FLAGS_PENDING) - { - mis.msgflags |= RS_MSG_PENDING; - } - if (msg->msgFlags & RS_MSG_FLAGS_DRAFT) - { - mis.msgflags |= RS_MSG_DRAFT; - } - if (msg->msgFlags & RS_MSG_FLAGS_NEW) - { - mis.msgflags |= RS_MSG_NEW; - } - if (msg->msgFlags & RS_MSG_FLAGS_TRASH) - { - mis.msgflags |= RS_MSG_TRASH; - } - if (msg->msgFlags & RS_MSG_FLAGS_UNREAD_BY_USER) - { - mis.msgflags |= RS_MSG_UNREAD_BY_USER; - } - if (msg->msgFlags & RS_MSG_FLAGS_REPLIED) - { - mis.msgflags |= RS_MSG_REPLIED; - } - if (msg->msgFlags & RS_MSG_FLAGS_FORWARDED) - { - mis.msgflags |= RS_MSG_FORWARDED; - } - if (msg->msgFlags & RS_MSG_FLAGS_STAR) - { - mis.msgflags |= RS_MSG_STAR; - } - if (msg->msgFlags & RS_MSG_FLAGS_SPAM) - { - mis.msgflags |= RS_MSG_SPAM; - } - if (msg->msgFlags & RS_MSG_FLAGS_USER_REQUEST) - { - mis.msgflags |= RS_MSG_USER_REQUEST; - } - if (msg->msgFlags & RS_MSG_FLAGS_FRIEND_RECOMMENDATION) - { - mis.msgflags |= RS_MSG_FRIEND_RECOMMENDATION; - } - if (msg->msgFlags & RS_MSG_FLAGS_PUBLISH_KEY) - { - mis.msgflags |= RS_MSG_PUBLISH_KEY; - } - if (msg->msgFlags & RS_MSG_FLAGS_LOAD_EMBEDDED_IMAGES) - { - mis.msgflags |= RS_MSG_LOAD_EMBEDDED_IMAGES; - } - - mis.srcId = msg->PeerId(); - { - //msg->msgId; - rs_sprintf(mis.msgId, "%lu", msg->msgId); - } - - mis.title = msg->subject; - mis.count = msg->attachment.items.size(); - mis.ts = msg->sendTime; - - MsgTagInfo taginfo; - locked_getMessageTag(mis.msgId,taginfo); - mis.msgtags = taginfo.tagIds ; -} - -void p3MsgService::initMIRsMsg(RsMsgItem *msg,const MessageInfo& info) -{ - msg -> msgFlags = 0; - msg -> msgId = 0; - msg -> sendTime = time(NULL); - msg -> recvTime = 0; - msg -> subject = info.title; - msg -> message = info.msg; - - msg->rspeerid_msgto.ids = info.rspeerid_msgto ; - msg->rspeerid_msgcc.ids = info.rspeerid_msgcc ; - - msg->rsgxsid_msgto.ids = info.rsgxsid_msgto ; - msg->rsgxsid_msgcc.ids = info.rsgxsid_msgcc ; - - /* We don't fill in bcc (unless to ourselves) */ - - if (msg->PeerId() == mServiceCtrl->getOwnId()) - { - msg->rsgxsid_msgbcc.ids = info.rsgxsid_msgbcc ; - msg->rspeerid_msgbcc.ids = info.rspeerid_msgbcc ; - } - - msg -> attachment.title = info.attach_title; - msg -> attachment.comment = info.attach_comment; - - for(std::list::const_iterator it = info.files.begin(); it != info.files.end(); ++it) - { - RsTlvFileItem mfi; - mfi.hash = it -> hash; - mfi.name = it -> fname; - mfi.filesize = it -> size; - msg -> attachment.items.push_back(mfi); - } - /* translate flags from outside */ - if (info.msgflags & RS_MSG_USER_REQUEST) - msg->msgFlags |= RS_MSG_FLAGS_USER_REQUEST; - - if (info.msgflags & RS_MSG_FRIEND_RECOMMENDATION) - msg->msgFlags |= RS_MSG_FLAGS_FRIEND_RECOMMENDATION; -} -RsMsgItem *p3MsgService::initMIRsMsg(const MessageInfo& info, const RsGxsId& to) -{ - RsMsgItem *msg = new RsMsgItem(); - - initMIRsMsg(msg,info) ; - - msg->PeerId(RsPeerId(to)); - msg->msgFlags |= RS_MSG_FLAGS_DISTANT; - - if (info.msgflags & RS_MSG_SIGNED) - msg->msgFlags |= RS_MSG_FLAGS_SIGNED; - -// // We replace the msg text by the whole message serialized possibly signed, -// // and binary encrypted, so as to obfuscate all its content. -// // -// if(!createDistantMessage(to,info.rsgxsid_srcId,msg)) -// { -// std::cerr << "Cannot encrypt distant message. Something went wrong." << std::endl; -// delete msg ; -// return NULL ; -// } - - return msg ; -} - -RsMsgItem *p3MsgService::initMIRsMsg(const MessageInfo &info, const RsPeerId& to) -{ - RsMsgItem *msg = new RsMsgItem(); - - initMIRsMsg(msg,info) ; - - msg->PeerId(to) ; - - /* load embedded images from own messages */ - msg->msgFlags |= RS_MSG_FLAGS_LOAD_EMBEDDED_IMAGES; - - return msg; -} - -void p3MsgService::connectToGlobalRouter(p3GRouter *gr) -{ - mGRouter = gr ; - gr->registerClientService(GROUTER_CLIENT_ID_MESSAGES,this) ; -} - -void p3MsgService::enableDistantMessaging(bool b) -{ - // We use a temporary variable because the call to OwnIds() might fail. - - mShouldEnableDistantMessaging = b ; - IndicateConfigChanged() ; -} - -bool p3MsgService::distantMessagingEnabled() -{ - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - return mShouldEnableDistantMessaging ; -} - -void p3MsgService::manageDistantPeers() -{ - // now possibly flush pending messages - - if(mShouldEnableDistantMessaging == mDistantMessagingEnabled) - return ; - -#ifdef DEBUG_DISTANT_MSG - std::cerr << "p3MsgService::manageDistantPeers()" << std::endl; -#endif - std::list own_id_list ; - - if(mIdService->getOwnIds(own_id_list)) - { -#ifdef DEBUG_DISTANT_MSG - for(std::list::const_iterator it(own_id_list.begin());it!=own_id_list.end();++it) - std::cerr << (mShouldEnableDistantMessaging?"Enabling":"Disabling") << " distant messaging, with peer id = " << *it << std::endl; -#endif - - for(std::list::const_iterator it(own_id_list.begin());it!=own_id_list.end();++it) - { - if(mShouldEnableDistantMessaging) - mGRouter->registerKey(*it,GROUTER_CLIENT_ID_MESSAGES,"Messaging contact") ; - else - mGRouter->unregisterKey(*it,GROUTER_CLIENT_ID_MESSAGES) ; - } - - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - mDistantMessagingEnabled = mShouldEnableDistantMessaging ; - } -} - -void p3MsgService::notifyDataStatus( const GRouterMsgPropagationId& id, - const RsGxsId &signer_id, - uint32_t data_status ) -{ - if(data_status == GROUTER_CLIENT_SERVICE_DATA_STATUS_FAILED) - { - RS_STACK_MUTEX(mMsgMtx); - - auto it = _ongoing_messages.find(id); - if(it == _ongoing_messages.end()) - { - RsErr() << __PRETTY_FUNCTION__ - << " cannot find pending message to acknowledge. " - << "Weird. grouter id: " << id << std::endl; - return; - } - - uint32_t msg_id = it->second; - - RsWarn() << __PRETTY_FUNCTION__ << " Global router tells " - << "us that item ID " << id - << " could not be delivered on time. Message id: " - << msg_id << std::endl; - - /* this is needed because it's not saved in config, but we should - * probably include it in _ongoing_messages */ - mDistantOutgoingMsgSigners[msg_id] = signer_id; - - std::map::iterator mit = msgOutgoing.find(msg_id); - if(mit == msgOutgoing.end()) - { - RsInfo() << __PRETTY_FUNCTION__ - << " message has been notified as not delivered, " - << "but it's not in outgoing list. Probably it has been " - << "delivered successfully by other means." << std::endl; - } - else - { - std::cerr << " reseting the ROUTED flag so that the message is " - << "requested again" << std::endl; - - // clear the routed flag so that the message is requested again - mit->second->msgFlags &= ~RS_MSG_FLAGS_ROUTED; - } - - return; - } - - if(data_status == GROUTER_CLIENT_SERVICE_DATA_STATUS_RECEIVED) - { - RS_STACK_MUTEX(mMsgMtx); -#ifdef DEBUG_DISTANT_MSG - std::cerr << "p3MsgService::acknowledgeDataReceived(): acknowledging data received for msg propagation id " << id << std::endl; -#endif - auto it = _ongoing_messages.find(id); - if(it == _ongoing_messages.end()) - { - std::cerr << " (EE) cannot find pending message to acknowledge. " - << "Weird. grouter id = " << id << std::endl; - return; - } - - uint32_t msg_id = it->second; - - // we should now remove the item from the msgOutgoing list. - std::map::iterator it2 = msgOutgoing.find(msg_id); - if(it2 == msgOutgoing.end()) - { - std::cerr << "(II) message has been notified as delivered, but it's" - << " not in outgoing list. Probably it has been delivered" - << " successfully by other means." << std::endl; - return; - } - -#if 0 - delete it2->second; - msgOutgoing.erase(it2); -#else - // Do not delete it move to sent folder instead! - it2->second->msgFlags &= ~RS_MSG_FLAGS_PENDING; - imsg[msg_id] = it2->second; - msgOutgoing.erase(it2); -#endif - - IndicateConfigChanged(); - - if(rsEvents) - { - auto pEvent = std::make_shared(); - pEvent->mMailStatusEventCode = RsMailStatusEventCode::MESSAGE_CHANGED; - pEvent->mChangedMsgIds.insert(std::to_string(msg_id)); - rsEvents->postEvent(pEvent); - } - - return; - } - - RsErr() << __PRETTY_FUNCTION__ - << " unhandled data status info from global router" - << " for msg ID " << id << ": this is a bug." << std::endl; -} - -bool p3MsgService::acceptDataFromPeer(const RsGxsId& to_gxs_id) -{ - if(mDistantMessagePermissions & RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_NON_CONTACTS) - return (rsIdentity!=NULL) && rsIdentity->isARegularContact(to_gxs_id) ; - - if(mDistantMessagePermissions & RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_FILTER_EVERYBODY) - return false ; - - return true ; -} - -void p3MsgService::setDistantMessagingPermissionFlags(uint32_t flags) -{ - if(flags != mDistantMessagePermissions) - { - mDistantMessagePermissions = flags ; - - IndicateConfigChanged() ; - } -} - -uint32_t p3MsgService::getDistantMessagingPermissionFlags() -{ - return mDistantMessagePermissions ; -} - -bool p3MsgService::receiveGxsTransMail( const RsGxsId& authorId, - const RsGxsId& recipientId, - const uint8_t* data, uint32_t dataSize ) -{ - Dbg2() << __PRETTY_FUNCTION__ << " " << authorId << ", " << recipientId - << ",, " << dataSize << std::endl; - - Sha1CheckSum hash = RsDirUtil::sha1sum(data, dataSize); - - { - RS_STACK_MUTEX(recentlyReceivedMutex); - if( mRecentlyReceivedMessageHashes.find(hash) != mRecentlyReceivedMessageHashes.end() ) - { - RsInfo() << __PRETTY_FUNCTION__ << " (II) receiving " - << "message of hash " << hash << " more than once. " - << "Probably it has arrived before by other means." - << std::endl; - return true; - } - mRecentlyReceivedMessageHashes[hash] = static_cast(time(nullptr)); - } - - IndicateConfigChanged(); - - RsItem *item = _serialiser->deserialise( const_cast(data), &dataSize ); - RsMsgItem *msg_item = dynamic_cast(item); - - if(msg_item) - { - Dbg3() << __PRETTY_FUNCTION__ << " Encrypted item correctly " - << "deserialised. Passing on to incoming list." - << std::endl; - - msg_item->msgFlags |= RS_MSG_FLAGS_DISTANT; - /* we expect complete msgs - remove partial flag just in case - * someone has funny ideas */ - msg_item->msgFlags &= ~RS_MSG_FLAGS_PARTIAL; - - // hack to pass on GXS id. - msg_item->PeerId(RsPeerId(authorId)); - handleIncomingItem(msg_item); - } - else - { - RsWarn() << __PRETTY_FUNCTION__ << " Item could not be " - << "deserialised. Format error?" << std::endl; - return false; - } - - return true; -} - -bool p3MsgService::notifyGxsTransSendStatus( RsGxsTransId mailId, - GxsTransSendStatus status ) -{ - Dbg2() << __PRETTY_FUNCTION__ << " " << mailId << ", " - << static_cast(status) << std::endl; - - auto pEvent = std::make_shared(); - - if( status == GxsTransSendStatus::RECEIPT_RECEIVED ) - { - pEvent->mMailStatusEventCode = RsMailStatusEventCode::MESSAGE_RECEIVED_ACK; - uint32_t msg_id; - - { - RS_STACK_MUTEX(gxsOngoingMutex); - - auto it = gxsOngoingMessages.find(mailId); - if(it == gxsOngoingMessages.end()) - { - RsErr() << __PRETTY_FUNCTION__<< " " << mailId << ", " - << static_cast(status) - << " cannot find pending message to acknowledge!" - << std::endl; - return false; - } - - msg_id = it->second; - } - - // we should now remove the item from the msgOutgoing list. - - { - RS_STACK_MUTEX(mMsgMtx); - - auto it2 = msgOutgoing.find(msg_id); - if(it2 == msgOutgoing.end()) - { - RsInfo() << __PRETTY_FUNCTION__ << " " << mailId - << ", " << static_cast(status) - << " received receipt for message that is not in " - << "outgoing list, probably it has been acknoweldged " - << "before by other means." << std::endl; - } - else - { -#if 0 - delete it2->second; - msgOutgoing.erase(it2); -#else - // Do not delete it move to sent folder instead! - it2->second->msgFlags &= ~RS_MSG_FLAGS_PENDING; - imsg[msg_id] = it2->second; - msgOutgoing.erase(it2); -#endif - pEvent->mChangedMsgIds.insert(std::to_string(msg_id)); - } - } - - IndicateConfigChanged(); - } - else if( status >= GxsTransSendStatus::FAILED_RECEIPT_SIGNATURE ) - { - uint32_t msg_id; - pEvent->mMailStatusEventCode = RsMailStatusEventCode::SIGNATURE_FAILED; - - { - RS_STACK_MUTEX(gxsOngoingMutex); - RsErr() << __PRETTY_FUNCTION__ << " mail delivery " - << "mailId: " << mailId - << " failed with " << static_cast(status); - - auto it = gxsOngoingMessages.find(mailId); - if(it == gxsOngoingMessages.end()) - { - RsErr() << __PRETTY_FUNCTION__ - << " cannot find pending message to notify" - << std::endl; - return false; - } - - msg_id = it->second; - } - - std::cerr << " message id = " << msg_id << std::endl; - - { - RS_STACK_MUTEX(mMsgMtx); - auto mit = msgOutgoing.find(msg_id); - if( mit == msgOutgoing.end() ) - { - std::cerr << " message has been notified as not delivered, " - << "but it not on outgoing list." - << std::endl; - } - else - { - std::cerr << " reseting the ROUTED flag so that the message is " - << "requested again" << std::endl; - // clear the routed flag so that the message is requested again - mit->second->msgFlags &= ~RS_MSG_FLAGS_ROUTED; - - pEvent->mChangedMsgIds.insert(std::to_string(msg_id)); - } - } - } - - if(rsEvents && !pEvent->mChangedMsgIds.empty()) - rsEvents->postEvent(pEvent); - - return true; -} - -void p3MsgService::receiveGRouterData( const RsGxsId &destination_key, - const RsGxsId &signing_key, - GRouterServiceId &/*client_id*/, - uint8_t *data, uint32_t data_size ) -{ - std::cerr << "p3MsgService::receiveGRouterData(): received message item of" - << " size " << data_size << ", for key " << destination_key - << std::endl; - - /* first make sure that we havn't already received the data. Since we allow - * to re-send messages, it's necessary to check. */ - - Sha1CheckSum hash = RsDirUtil::sha1sum(data, data_size); - - { - RS_STACK_MUTEX(recentlyReceivedMutex); - if( mRecentlyReceivedMessageHashes.find(hash) != - mRecentlyReceivedMessageHashes.end() ) - { - std::cerr << "p3MsgService::receiveGRouterData(...) (II) receiving" - << "distant message of hash " << hash << " more than once" - << ". Probably it has arrived before by other means." - << std::endl; - free(data); - return; - } - mRecentlyReceivedMessageHashes[hash] = time(NULL); - } - - IndicateConfigChanged() ; - - RsItem *item = _serialiser->deserialise(data,&data_size) ; - free(data) ; - - RsMsgItem *msg_item = dynamic_cast(item) ; - - if(msg_item != NULL) - { - std::cerr << " Encrypted item correctly deserialised. Passing on to incoming list." << std::endl; - - msg_item->msgFlags |= RS_MSG_FLAGS_DISTANT ; - /* we expect complete msgs - remove partial flag just in case someone has funny ideas */ - msg_item->msgFlags &= ~RS_MSG_FLAGS_PARTIAL; - - msg_item->PeerId(RsPeerId(signing_key)) ; // hack to pass on GXS id. - handleIncomingItem(msg_item) ; - } - else - std::cerr << " Item could not be deserialised. Format error??" << std::endl; -} - -void p3MsgService::sendDistantMsgItem(RsMsgItem *msgitem) -{ - RsGxsId destination_key_id(msgitem->PeerId()); - RsGxsId signing_key_id; - - /* just in case, but normally we should always have this flag set, when - * ending up here. */ - msgitem->msgFlags |= RS_MSG_FLAGS_DISTANT; - - { - RS_STACK_MUTEX(mMsgMtx); - - std::map::const_iterator it = - mDistantOutgoingMsgSigners.find(msgitem->msgId); - - if(it == mDistantOutgoingMsgSigners.end()) - { - std::cerr << "(EE) no signer registered for distant message " - << msgitem->msgId << ". Cannot send!" << std::endl; - return; - } - - signing_key_id = it->second; - - if(signing_key_id.isNull()) - { - std::cerr << "ERROR: cannot find signing key id for msg id " - << msgitem->msgId << " available keys are:" << std::endl; - typedef std::map::const_iterator itT; - for( itT it = mDistantOutgoingMsgSigners.begin(); - it != mDistantOutgoingMsgSigners.end(); ++it ) - std::cerr << "\t" << it->first << " " << it->second - << std::endl; - return; - } - } -#ifdef DEBUG_DISTANT_MSG - std::cerr << "p3MsgService::sendDistanteMsgItem(): sending distant msg item" - << " msg ID: " << msgitem->msgId << " to peer:" - << destination_key_id << " signing: " << signing_key_id - << std::endl; -#endif - - /* The item is serialized and turned into a generic turtle item. Use use the - * explicit serialiser to make sure that the msgId is not included */ - - uint32_t msg_serialized_rssize = RsMsgSerialiser().size(msgitem); - RsTemporaryMemory msg_serialized_data(msg_serialized_rssize) ; - - if( !RsMsgSerialiser(). - serialise(msgitem,msg_serialized_data,&msg_serialized_rssize) ) - { - std::cerr << "(EE) p3MsgService::sendTurtleData(): Serialization error." << std::endl; - return ; - } -#ifdef DEBUG_DISTANT_MSG - std::cerr << " serialised size : " << msg_serialized_rssize << std::endl; -#endif - - GRouterMsgPropagationId grouter_message_id; - mGRouter->sendData( destination_key_id, GROUTER_CLIENT_ID_MESSAGES, - msg_serialized_data, msg_serialized_rssize, - signing_key_id, grouter_message_id ); - RsGxsTransId gxsMailId; - mGxsTransServ.sendData( gxsMailId, GxsTransSubServices::P3_MSG_SERVICE, - signing_key_id, destination_key_id, - msg_serialized_data, msg_serialized_rssize ); - - /* now store the grouter id along with the message id, so that we can keep - * track of received messages */ - - { - RS_STACK_MUTEX(mMsgMtx); - _ongoing_messages[grouter_message_id] = msgitem->msgId; - } - - { - RS_STACK_MUTEX(gxsOngoingMutex); - gxsOngoingMessages[gxsMailId] = msgitem->msgId; - } - - IndicateConfigChanged(); // save _ongoing_messages -} - - - - diff --git a/libretroshare/src/services/p3msgservice.h b/libretroshare/src/services/p3msgservice.h deleted file mode 100644 index 30ad1e135..000000000 --- a/libretroshare/src/services/p3msgservice.h +++ /dev/null @@ -1,248 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3msgservice.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef MESSAGE_SERVICE_HEADER -#define MESSAGE_SERVICE_HEADER - -#include -#include -#include - -#include "retroshare/rsmsgs.h" - -#include "pqi/pqi.h" -#include "pqi/pqiindic.h" - -#include "pqi/pqiservicemonitor.h" -#include "pqi/p3cfgmgr.h" - -#include "services/p3service.h" -#include "rsitems/rsmsgitems.h" -#include "util/rsthreads.h" -#include "util/rsdebug.h" -#include "retroshare/rsgxsifacetypes.h" - -#include "grouter/p3grouter.h" -#include "grouter/grouterclientservice.h" -#include "turtle/p3turtle.h" -#include "turtle/turtleclientservice.h" -#include "gxstrans/p3gxstrans.h" - -class p3LinkMgr; -class p3IdService; - -// Temp tweak to test grouter -class p3MsgService : - public p3Service, public p3Config, public pqiServiceMonitor, GRouterClientService, - GxsTransClient -{ -public: - p3MsgService(p3ServiceControl *sc, p3IdService *id_service, p3GxsTrans& gxsMS); - virtual ~p3MsgService(); - - virtual RsServiceInfo getServiceInfo(); - - /// @see RsMsgs::sendMail - uint32_t sendMail(const RsGxsId from, - const std::string& subject, - const std::string& body, - const std::set& to = std::set(), - const std::set& cc = std::set(), - const std::set& bcc = std::set(), - const std::vector& attachments = std::vector(), - std::set& trackingIds = - RS_DEFAULT_STORAGE_PARAM(std::set), - std::string& errorMsg = - RS_DEFAULT_STORAGE_PARAM(std::string) ); - - /* External Interface */ - bool getMessageSummaries(std::list &msgList); - bool getMessage(const std::string &mid, Rs::Msgs::MessageInfo &msg); - void getMessageCount(uint32_t &nInbox, uint32_t &nInboxNew, uint32_t &nOutbox, uint32_t &nDraftbox, uint32_t &nSentbox, uint32_t &nTrashbox); - - bool decryptMessage(const std::string& mid) ; - bool removeMsgId(const std::string &mid); - bool markMsgIdRead(const std::string &mid, bool bUnreadByUser); - bool setMsgFlag(const std::string &mid, uint32_t flag, uint32_t mask); - bool getMsgParentId(const std::string &msgId, std::string &msgParentId); - // msgParentId == 0 --> remove - bool setMsgParentId(uint32_t msgId, uint32_t msgParentId); - - RS_DEPRECATED_FOR(sendMail) - bool MessageSend(Rs::Msgs::MessageInfo &info); - bool SystemMessage(const std::string &title, const std::string &message, uint32_t systemFlag); - bool MessageToDraft(Rs::Msgs::MessageInfo &info, const std::string &msgParentId); - bool MessageToTrash(const std::string &mid, bool bTrash); - - bool getMessageTag(const std::string &msgId, Rs::Msgs::MsgTagInfo& info); - bool getMessageTagTypes(Rs::Msgs::MsgTagType& tags); - bool setMessageTagType(uint32_t tagId, std::string& text, uint32_t rgb_color); - bool removeMessageTagType(uint32_t tagId); - - /* set == false && tagId == 0 --> remove all */ - bool setMessageTag(const std::string &msgId, uint32_t tagId, bool set); - - bool resetMessageStandardTagTypes(Rs::Msgs::MsgTagType& tags); - - void loadWelcomeMsg(); /* startup message */ - - - //std::list &getMsgList(); - //std::list &getMsgOutList(); - - int tick(); - - /*** Overloaded from p3Config ****/ - virtual RsSerialiser *setupSerialiser(); - virtual bool saveList(bool& cleanup, std::list&); - virtual bool loadList(std::list& load); - virtual void saveDone(); - /*** Overloaded from p3Config ****/ - - /*** Overloaded from pqiMonitor ***/ - virtual void statusChange(const std::list &plist); - - /// iterate through the outgoing queue if online, send - int checkOutgoingMessages(); - /*** Overloaded from pqiMonitor ***/ - - /*** overloaded from p3turtle ***/ - - virtual void connectToGlobalRouter(p3GRouter *) ; - - struct DistantMessengingInvite - { - rstime_t time_of_validity ; - }; - struct DistantMessengingContact - { - rstime_t last_hit_time ; - RsPeerId virtual_peer_id ; - uint32_t status ; - bool pending_messages ; - }; - void enableDistantMessaging(bool b) ; - bool distantMessagingEnabled() ; - - void setDistantMessagingPermissionFlags(uint32_t flags) ; - uint32_t getDistantMessagingPermissionFlags() ; - - /// @see GxsTransClient::receiveGxsTransMail(...) - virtual bool receiveGxsTransMail( const RsGxsId& authorId, - const RsGxsId& recipientId, - const uint8_t* data, uint32_t dataSize ); - - /// @see GxsTransClient::notifyGxsTransSendStatus(...) - virtual bool notifyGxsTransSendStatus( RsGxsTransId mailId, - GxsTransSendStatus status ); - -private: - void sendDistantMsgItem(RsMsgItem *msgitem); - bool locked_getMessageTag(const std::string &msgId, Rs::Msgs::MsgTagInfo& info); - - /** This contains the ongoing tunnel handling contacts. - * The map is indexed by the hash */ - std::map _ongoing_messages; - - /// Contains ongoing messages handed to gxs mail - std::map gxsOngoingMessages; - RsMutex gxsOngoingMutex; - - // Overloaded from GRouterClientService - virtual bool acceptDataFromPeer(const RsGxsId& gxs_id) ; - virtual void receiveGRouterData(const RsGxsId& destination_key,const RsGxsId& signing_key, GRouterServiceId &client_id, uint8_t *data, uint32_t data_size) ; - virtual void notifyDataStatus(const GRouterMsgPropagationId& msg_id,const RsGxsId& signer_id,uint32_t data_status) ; - - // Utility functions - - bool createDistantMessage(const RsGxsId& destination_gxs_id,const RsGxsId& source_gxs_id,RsMsgItem *msg) ; - bool locked_findHashForVirtualPeerId(const RsPeerId& pid,Sha1CheckSum& hash) ; - void sendGRouterData(const RsGxsId &key_id,RsMsgItem *) ; - - void manageDistantPeers() ; - - void handleIncomingItem(RsMsgItem *) ; - - uint32_t getNewUniqueMsgId(); - uint32_t sendMessage(RsMsgItem *item); - uint32_t sendDistantMessage(RsMsgItem *item,const RsGxsId& signing_gxs_id); - void checkSizeAndSendMessage(RsMsgItem *msg); - void cleanListOfReceivedMessageHashes(); - - int incomingMsgs(); - void processIncomingMsg(RsMsgItem *mi) ; - bool checkAndRebuildPartialMessage(RsMsgItem*) ; - - void initRsMI(RsMsgItem *msg, Rs::Msgs::MessageInfo &mi); - void initRsMIS(RsMsgItem *msg, Rs::Msgs::MsgInfoSummary &mis); - - RsMsgItem *initMIRsMsg(const Rs::Msgs::MessageInfo &info, const RsPeerId& to); - RsMsgItem *initMIRsMsg(const Rs::Msgs::MessageInfo &info, const RsGxsId& to); - void initMIRsMsg(RsMsgItem *item,const Rs::Msgs::MessageInfo &info) ; - - void initStandardTagTypes(); - - p3IdService *mIdService ; - p3ServiceControl *mServiceCtrl; - p3GRouter *mGRouter ; - - /* Mutex Required for stuff below */ - - RsMutex mMsgMtx; - RsMsgSerialiser *_serialiser ; - - /* stored list of messages */ - std::map imsg; - /* ones that haven't made it out yet! */ - std::map msgOutgoing; - - std::map _pendingPartialMessages ; - - /* maps for tags types and msg tags */ - - std::map mTags; - std::map mMsgTags; - - uint32_t mMsgUniqueId; - std::map mRecentlyReceivedMessageHashes; - RsMutex recentlyReceivedMutex; - - // used delete msgSrcIds after config save - std::map mSrcIds; - - // temporary storage. Will not be needed when messages have a proper "from" field. Not saved! - std::map mDistantOutgoingMsgSigners; - - // save the parent of the messages in draft for replied and forwarded - std::map mParentId; - - std::string config_dir; - - bool mDistantMessagingEnabled ; - uint32_t mDistantMessagePermissions ; - bool mShouldEnableDistantMessaging ; - - p3GxsTrans& mGxsTransServ; - - RS_SET_CONTEXT_DEBUG_LEVEL(3) -}; - -#endif // MESSAGE_SERVICE_HEADER diff --git a/libretroshare/src/services/p3photoservice.cc b/libretroshare/src/services/p3photoservice.cc deleted file mode 100644 index 24e9d90b6..000000000 --- a/libretroshare/src/services/p3photoservice.cc +++ /dev/null @@ -1,351 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3photoservice.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008-2012 Robert Fernie,Chris Evi-Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "p3photoservice.h" -#include "rsitems/rsphotoitems.h" -#include "retroshare/rsgxsflags.h" - -RsPhoto *rsPhoto = NULL; - -RsPhotoPhoto::RsPhotoPhoto() - :mOrder(0) -{ - return; -} - -RsPhotoAlbum::RsPhotoAlbum() - :mShareMode(RSPHOTO_SHAREMODE_LOWRESONLY), mAutoDownload(false) -{ - return; -} - -std::ostream &operator<<(std::ostream &out, const RsPhotoPhoto &photo) -{ - out << "RsPhotoPhoto [ "; - out << "Title: " << photo.mMeta.mMsgName; - out << "]"; - return out; -} - -std::ostream &operator<<(std::ostream &out, const RsPhotoAlbum &album) -{ - out << "RsPhotoAlbum [ "; - out << "Title: " << album.mMeta.mGroupName; - out << "]"; - return out; -} - -p3PhotoService::p3PhotoService(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs* gixs) - : RsGenExchange(gds, nes, new RsGxsPhotoSerialiser(), RS_SERVICE_GXS_TYPE_PHOTO, gixs, photoAuthenPolicy()), - RsPhoto(static_cast(*this)), - mPhotoMutex(std::string("Photo Mutex")) -{ - mCommentService = new p3GxsCommentService(this, RS_SERVICE_GXS_TYPE_PHOTO); -} - -const std::string GXS_PHOTO_APP_NAME = "gxsphoto"; -const uint16_t GXS_PHOTO_APP_MAJOR_VERSION = 1; -const uint16_t GXS_PHOTO_APP_MINOR_VERSION = 0; -const uint16_t GXS_PHOTO_MIN_MAJOR_VERSION = 1; -const uint16_t GXS_PHOTO_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3PhotoService::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_GXS_TYPE_PHOTO, - GXS_PHOTO_APP_NAME, - GXS_PHOTO_APP_MAJOR_VERSION, - GXS_PHOTO_APP_MINOR_VERSION, - GXS_PHOTO_MIN_MAJOR_VERSION, - GXS_PHOTO_MIN_MINOR_VERSION); -} - -uint32_t p3PhotoService::photoAuthenPolicy() -{ - uint32_t policy = 0; - uint8_t flag = 0; - - flag = GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS); - - flag |= GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS); - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS); - - flag = GXS_SERV::GRP_OPTION_AUTHEN_AUTHOR_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::GRP_OPTION_BITS); - - return policy; -} - -bool p3PhotoService::updated() -{ - RsStackMutex stack(mPhotoMutex); - - bool changed = (!mGroupChange.empty() || !mMsgChange.empty()); - - return changed; -} - -void p3PhotoService::service_tick() -{ - mCommentService->comment_tick(); -} - - -void p3PhotoService::groupsChanged(std::list& grpIds) -{ - RsStackMutex stack(mPhotoMutex); - - while(!mGroupChange.empty()) - { - RsGxsGroupChange* gc = mGroupChange.back(); - grpIds.push_back(gc->mGroupId); - - mGroupChange.pop_back(); - delete gc; - } -} - - -void p3PhotoService::msgsChanged(GxsMsgIdResult& msgs) -{ - RsStackMutex stack(mPhotoMutex); - - while(!mMsgChange.empty()) - { - RsGxsMsgChange* mc = mMsgChange.back(); - - msgs[mc->mGroupId].insert(mc->mMsgId); - mMsgChange.pop_back(); - delete mc; - } -} - - -RsTokenService* p3PhotoService::getTokenService() { - - return RsGenExchange::getTokenService(); -} - - -bool p3PhotoService::getGroupList(const uint32_t& token, - std::list& groupIds) -{ - bool okay = RsGenExchange::getGroupList(token, groupIds); - return okay; -} - - -bool p3PhotoService::getMsgList(const uint32_t& token, - GxsMsgIdResult& msgIds) -{ - - return RsGenExchange::getMsgList(token, msgIds); -} - - -bool p3PhotoService::getGroupSummary(const uint32_t& token, - std::list& groupInfo) -{ - bool okay = RsGenExchange::getGroupMeta(token, groupInfo); - return okay; -} - - -bool p3PhotoService::getMsgSummary(const uint32_t& token, - MsgMetaResult& msgInfo) -{ - return RsGenExchange::getMsgMeta(token, msgInfo); -} - - -bool p3PhotoService::getAlbum(const uint32_t& token, std::vector& albums) -{ - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); ++vit) - { - RsGxsPhotoAlbumItem* item = dynamic_cast(*vit); - if (item) - { - RsPhotoAlbum album = item->album; - item->album.mMeta = item->meta; - album.mMeta = item->album.mMeta; - delete item; - albums.push_back(album); - } - else - { - std::cerr << "Not a RsGxsPhotoAlbumItem, deleting!" << std::endl; - delete *vit; - } - } - } - - return ok; -} - -bool p3PhotoService::getPhoto(const uint32_t& token, PhotoResult& photos) -{ - GxsMsgDataMap msgData; - bool ok = RsGenExchange::getMsgData(token, msgData); - - if(ok) - { - GxsMsgDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - RsGxsGroupId grpId = mit->first; - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsPhotoPhotoItem* item = dynamic_cast(*vit); - - if(item) - { - RsPhotoPhoto photo = item->photo; - photo.mMeta = item->meta; - photos[grpId].push_back(photo); - delete item; - }else - { - std::cerr << "Not a photo Item, deleting!" << std::endl; - delete *vit; - } - } - } - } - - return ok; -} - -bool p3PhotoService::submitAlbumDetails(uint32_t& token, RsPhotoAlbum& album) -{ - RsGxsPhotoAlbumItem* albumItem = new RsGxsPhotoAlbumItem(); - albumItem->album = album; - albumItem->meta = album.mMeta; - RsGenExchange::publishGroup(token, albumItem); - return true; -} - -void p3PhotoService::notifyChanges(std::vector& changes) -{ - - RsStackMutex stack(mPhotoMutex); - - std::vector::iterator vit = changes.begin(); - - for(; vit != changes.end(); ++vit) - { - RsGxsNotify* n = *vit; - RsGxsGroupChange* gc; - RsGxsMsgChange* mc; - if((mc = dynamic_cast(n)) != NULL) - { - mMsgChange.push_back(mc); - } - else if((gc = dynamic_cast(n)) != NULL) - { - mGroupChange.push_back(gc); - } - else - { - delete n; - } - } -} - -bool p3PhotoService::submitPhoto(uint32_t& token, RsPhotoPhoto& photo) -{ - RsGxsPhotoPhotoItem* photoItem = new RsGxsPhotoPhotoItem(); - photoItem->photo = photo; - photoItem->meta = photo.mMeta; - - RsGenExchange::publishMsg(token, photoItem); - return true; -} - -bool p3PhotoService::acknowledgeMsg(const uint32_t& token, - std::pair& msgId) -{ - return RsGenExchange::acknowledgeTokenMsg(token, msgId); -} - - -bool p3PhotoService::acknowledgeGrp(const uint32_t& token, - RsGxsGroupId& grpId) -{ - return RsGenExchange::acknowledgeTokenGrp(token, grpId); -} - -bool p3PhotoService::subscribeToAlbum(uint32_t &token, const RsGxsGroupId &grpId, bool subscribe) -{ - if(subscribe) - RsGenExchange::setGroupSubscribeFlags(token, grpId, GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED, GXS_SERV::GROUP_SUBSCRIBE_MASK); - else - RsGenExchange::setGroupSubscribeFlags(token, grpId, 0, GXS_SERV::GROUP_SUBSCRIBE_MASK); - - return true; -} - -// Blocking versions ============================================================= - -bool p3PhotoService::createAlbum(RsPhotoAlbum &album) -{ - uint32_t token; - return submitAlbumDetails(token, album) && waitToken(token) == RsTokenService::COMPLETE; -} - -bool p3PhotoService::updateAlbum(const RsPhotoAlbum &/*album*/) -{ - // TODO - return false; -} - -bool p3PhotoService::getAlbums(const std::list &groupIds, - std::vector &albums) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - - if (groupIds.empty()) - { - if (!requestGroupInfo(token, opts) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - } - else - { - if (!requestGroupInfo(token, opts, groupIds) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - } - - return getAlbum(token, albums) && !albums.empty(); -} - diff --git a/libretroshare/src/services/p3photoservice.h b/libretroshare/src/services/p3photoservice.h deleted file mode 100644 index f540d4f66..000000000 --- a/libretroshare/src/services/p3photoservice.h +++ /dev/null @@ -1,214 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3photoservice.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008-2012 Robert Fernie,Chris Evi-Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef P3PHOTOSERVICEV2_H -#define P3PHOTOSERVICEV2_H - -#include "gxs/rsgenexchange.h" -#include "retroshare/rsphoto.h" -#include "services/p3gxscommon.h" - -class p3PhotoService : public RsGenExchange, public RsPhoto -{ -public: - - p3PhotoService(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs* gixs); - virtual RsServiceInfo getServiceInfo() override; - - static uint32_t photoAuthenPolicy(); - -public: - - /*! - * @return true if a change has occured - */ - bool updated() override; - - /*! - * - */ - void service_tick() override; - -protected: - - void notifyChanges(std::vector& changes) override; -public: - - /** Requests **/ - - void groupsChanged(std::list& grpIds) override; - - - void msgsChanged(GxsMsgIdResult& msgs) override; - - RsTokenService* getTokenService() override; - - bool getGroupList(const uint32_t &token, std::list &groupIds) override; - bool getMsgList(const uint32_t &token, GxsMsgIdResult& msgIds) override; - - /* Generic Summary */ - bool getGroupSummary(const uint32_t &token, std::list &groupInfo) override; - - bool getMsgSummary(const uint32_t &token, MsgMetaResult &msgInfo) override; - - /* Specific Service Data */ - bool getAlbum(const uint32_t &token, std::vector &albums) override; - bool getPhoto(const uint32_t &token, PhotoResult &photos) override; - -public: - /* Comment service - Provide RsGxsCommentService - redirect to p3GxsCommentService */ - virtual bool getCommentData(uint32_t token, std::vector &msgs) override - { - return mCommentService->getGxsCommentData(token, msgs); - } - - virtual bool getRelatedComments( uint32_t token, std::vector &msgs ) override - { - return mCommentService->getGxsRelatedComments(token, msgs); - } - - virtual bool createNewComment(uint32_t &token, const RsGxsComment &msg) override - { - return mCommentService->createGxsComment(token, msg); - } - - virtual bool createNewVote(uint32_t &token, RsGxsVote &msg) override - { - return mCommentService->createGxsVote(token, msg); - } - - virtual bool acknowledgeComment(uint32_t token, std::pair& msgId) override - { - return acknowledgeMsg(token, msgId); - } - - virtual bool acknowledgeVote(uint32_t token, std::pair& msgId) override - { - if (mCommentService->acknowledgeVote(token, msgId)) - { - return true; - } - return acknowledgeMsg(token, msgId); - } - - //Not currently used - virtual bool setCommentAsRead(uint32_t& /*token*/,const RsGxsGroupId& /*gid*/,const RsGxsMessageId& /*comment_msg_id*/) override - { - return true; - } - - - // Blocking versions. - virtual bool createComment(RsGxsComment &msg) override - { - uint32_t token; - return mCommentService->createGxsComment(token, msg) && waitToken(token) == RsTokenService::COMPLETE; - } - -public: - - /** Modifications **/ - - /*! - * submits album, which returns a token that needs - * to be acknowledge to get album grp id - * @param token token to redeem for acknowledgement - * @param album album to be submitted - */ - bool submitAlbumDetails(uint32_t& token, RsPhotoAlbum &album) override; - - /*! - * submits photo, which returns a token that needs - * to be acknowledge to get photo msg-grp id pair - * @param token token to redeem for acknowledgement - * @param photo photo to be submitted - */ - bool submitPhoto(uint32_t& token, RsPhotoPhoto &photo) override; - - /*! - * submits photo comment, which returns a token that needs - * to be acknowledged to get photo msg-grp id pair - * The mParentId needs to be set to an existing msg for which - * commenting is enabled - * @param token token to redeem for acknowledgement - * @param comment comment to be submitted - */ - // bool submitComment(uint32_t& token, RsPhotoComment &photo); - - /*! - * subscribes to group, and returns token which can be used - * to be acknowledged to get group Id - * @param token token to redeem for acknowledgement - * @param grpId the id of the group to subscribe to - */ - bool subscribeToAlbum(uint32_t& token, const RsGxsGroupId& grpId, bool subscribe) override; - - /*! - * This allows the client service to acknowledge that their msgs has - * been created/modified and retrieve the create/modified msg ids - * @param token the token related to modification/create request - * @param msgIds map of grpid->msgIds of message created/modified - * @return true if token exists false otherwise - */ - bool acknowledgeMsg(const uint32_t& token, std::pair& msgId) override; - - /*! - * This allows the client service to acknowledge that their grps has - * been created/modified and retrieve the create/modified grp ids - * @param token the token related to modification/create request - * @param msgIds vector of ids of groups created/modified - * @return true if token exists false otherwise - */ - bool acknowledgeGrp(const uint32_t& token, RsGxsGroupId& grpId) override; - - // Blocking versions. - /*! - * request to create a new album. Blocks until process completes. - * @param album album to be submitted - * @return true if created false otherwise - */ - virtual bool createAlbum(RsPhotoAlbum &album) override; - - /*! - * request to update an existing album. Blocks until process completes. - * @param album album to be submitted - * @return true if created false otherwise - */ - virtual bool updateAlbum(const RsPhotoAlbum &album) override; - - /*! - * retrieve albums based in groupIds. - * @param groupIds the ids to fetch. - * @param albums vector to be filled by request. - * @return true is successful, false otherwise. - */ - virtual bool getAlbums(const std::list &groupIds, - std::vector &albums) override; -private: - p3GxsCommentService* mCommentService; - - std::vector mGroupChange; - std::vector mMsgChange; - - RsMutex mPhotoMutex; -}; - -#endif // P3PHOTOSERVICEV2_H diff --git a/libretroshare/src/services/p3postbase.cc b/libretroshare/src/services/p3postbase.cc deleted file mode 100644 index 6792255a4..000000000 --- a/libretroshare/src/services/p3postbase.cc +++ /dev/null @@ -1,1028 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3postbase.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008-2012 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include - -#include "retroshare/rsgxsflags.h" -#include -#include - -#include "services/p3postbase.h" -#include "rsitems/rsgxscommentitems.h" - -#include "rsserver/p3face.h" -#include "retroshare/rsposted.h" - -// For Dummy Msgs. -#include "util/rsrandom.h" -#include "util/rsstring.h" - -/**** - * #define POSTBASE_DEBUG 1 - ****/ - -#define POSTBASE_BACKGROUND_PROCESSING 0x0002 -#define PROCESSING_START_PERIOD 30 -#define PROCESSING_INC_PERIOD 15 - -#define POSTBASE_ALL_GROUPS 0x0011 -#define POSTBASE_UNPROCESSED_MSGS 0x0012 -#define POSTBASE_ALL_MSGS 0x0013 -#define POSTBASE_BG_POST_META 0x0014 - -#define POSTED_UNUSED_BY_FRIENDS_DELAY (2*30*86400) // delete unused posted groups after 2 months - -/********************************************************************************/ -/******************* Startup / Tick ******************************************/ -/********************************************************************************/ - -p3PostBase::p3PostBase(RsGeneralDataService *gds, RsNetworkExchangeService *nes, RsGixs* gixs, - RsSerialType* serviceSerialiser, uint16_t serviceType) - : RsGenExchange(gds, nes, serviceSerialiser, serviceType, gixs, postBaseAuthenPolicy()), GxsTokenQueue(this), RsTickEvent(), - mPostBaseMtx("PostBaseMutex"), - mKnownPostedMutex("PostBaseKnownPostedMutex") -{ - mBgProcessing = false; - - mCommentService = new p3GxsCommentService(this, serviceType); - RsTickEvent::schedule_in(POSTBASE_BACKGROUND_PROCESSING, PROCESSING_START_PERIOD); -} - - -uint32_t p3PostBase::postBaseAuthenPolicy() -{ - uint32_t policy = 0; - uint32_t flag = 0; - - flag = GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS); - - flag |= GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS); - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS); - - flag = 0; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::GRP_OPTION_BITS); - - return policy; -} - -void p3PostBase::notifyChanges(std::vector &changes) -{ -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::notifyChanges()"; - std::cerr << std::endl; -#endif - - for(auto it = changes.begin(); it != changes.end(); ++it) - { - RsGxsMsgChange *msgChange = dynamic_cast(*it); - - if(msgChange) - { - // To start with we are just going to trigger updates on these groups. - // FUTURE OPTIMISATION. - // It could be taken a step further and directly request these msgs for an update. - addGroupForProcessing(msgChange->mGroupId); - - if (rsEvents) - { - switch(msgChange->getType()) - { - case RsGxsNotify::TYPE_RECEIVED_NEW: - case RsGxsNotify::TYPE_PUBLISHED: - { - auto ev = std::make_shared(); - ev->mPostedMsgId = msgChange->mMsgId; - ev->mPostedThreadId = msgChange->mNewMsgItem->meta.mThreadId; - ev->mPostedGroupId = msgChange->mGroupId; - - if(nullptr != dynamic_cast(msgChange->mNewMsgItem)) - ev->mPostedEventCode = RsPostedEventCode::NEW_COMMENT; - else - if(nullptr != dynamic_cast(msgChange->mNewMsgItem)) - ev->mPostedEventCode = RsPostedEventCode::NEW_VOTE; - else - ev->mPostedEventCode = RsPostedEventCode::NEW_MESSAGE; - - rsEvents->postEvent(ev); -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::notifyChanges() Found Message Change Notification: NEW/PUBLISHED ID=" << msgChange->mMsgId << " in group " << msgChange->mGroupId << ", thread ID = " << msgChange->mNewMsgItem->meta.mThreadId << std::endl; -#endif - - } - break; - - - case RsGxsNotify::TYPE_PROCESSED: - { - auto ev = std::make_shared(); - ev->mPostedMsgId = msgChange->mMsgId; - ev->mPostedGroupId = msgChange->mGroupId; - ev->mPostedEventCode = RsPostedEventCode::MESSAGE_VOTES_UPDATED; - rsEvents->postEvent(ev); -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::notifyChanges() Found Message Change Notification: PROCESSED ID=" << msgChange->mMsgId << " in group " << msgChange->mGroupId << std::endl; -#endif - } - break; - default: -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::notifyChanges() Found Message Change Notification: type " << msgChange->getType() << " (ignored) " << msgChange->mMsgId << std::endl; -#endif - break; - } - } - } - - RsGxsGroupChange *grpChange = dynamic_cast(*it); - - /* pass on Group Changes to GUI */ - if (grpChange && rsEvents) - { -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::notifyChanges() Found Group Change Notification"; - std::cerr << std::endl; -#endif - const RsGxsGroupId& group_id(grpChange->mGroupId); - - switch(grpChange->getType()) - { - case RsGxsNotify::TYPE_PROCESSED: // happens when the group is subscribed - { - auto ev = std::make_shared(); - ev->mPostedGroupId = group_id; - ev->mPostedEventCode = RsPostedEventCode::SUBSCRIBE_STATUS_CHANGED; - rsEvents->postEvent(ev); - } - break; - - case RsGxsNotify::TYPE_GROUP_SYNC_PARAMETERS_UPDATED: - { - auto ev = std::make_shared(); - ev->mPostedGroupId = group_id; - ev->mPostedEventCode = RsPostedEventCode::SYNC_PARAMETERS_UPDATED; - rsEvents->postEvent(ev); - } - break; - - case RsGxsNotify::TYPE_GROUP_DELETED: - { - auto ev = std::make_shared(); - ev->mPostedGroupId = group_id; - ev->mPostedEventCode = RsPostedEventCode::BOARD_DELETED; - - rsEvents->postEvent(ev); - } - break; - - case RsGxsNotify::TYPE_STATISTICS_CHANGED: - { - auto ev = std::make_shared(); - ev->mPostedGroupId = group_id; - ev->mPostedEventCode = RsPostedEventCode::STATISTICS_CHANGED; - rsEvents->postEvent(ev); - - RS_STACK_MUTEX(mKnownPostedMutex); - mKnownPosted[group_id] = time(nullptr); - IndicateConfigChanged(); - } - break; - - case RsGxsNotify::TYPE_UPDATED: - { - // Happens when the group data has changed. In this case we need to analyse the old and new group in order to detect possible notifications for clients - - auto ev = std::make_shared(); - ev->mPostedGroupId = grpChange->mGroupId; - ev->mPostedEventCode = RsPostedEventCode::UPDATED_POSTED_GROUP; - rsEvents->postEvent(ev); - } - break; - - - case RsGxsNotify::TYPE_PUBLISHED: - case RsGxsNotify::TYPE_RECEIVED_NEW: - { - /* group received */ - - bool unknown; - { - RS_STACK_MUTEX(mKnownPostedMutex); - - unknown = (mKnownPosted.find(grpChange->mGroupId) == mKnownPosted.end()); - mKnownPosted[group_id] = time(nullptr); - IndicateConfigChanged(); - } - if(unknown) - { - auto ev = std::make_shared(); - ev->mPostedGroupId = group_id; - ev->mPostedEventCode = RsPostedEventCode::NEW_POSTED_GROUP; - rsEvents->postEvent(ev); - -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::notifyChanges() Incoming Group: " << group_id; - std::cerr << std::endl; -#endif - } - else - RsInfo() << __PRETTY_FUNCTION__ - << " Not notifying already known forum " - << group_id << std::endl; - } - break; - - default: - RsErr() << " Got a GXS event of type " << grpChange->getType() << " Currently not handled." << std::endl; - break; - } - } - - delete *it; - } -} - -void p3PostBase::service_tick() -{ - RsTickEvent::tick_events(); - GxsTokenQueue::checkRequests(); - - mCommentService->comment_tick(); - - return; -} - -/********************************************************************************************/ -/********************************************************************************************/ - -void p3PostBase::setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) -{ - uint32_t mask = GXS_SERV::GXS_MSG_STATUS_GUI_NEW | GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; - uint32_t status = GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; - if (read) - { - status = 0; - } - - setMsgStatusFlags(token, msgId, status, mask); - - if (rsEvents) - { - auto ev = std::make_shared(); - - ev->mPostedMsgId = msgId.second; - ev->mPostedGroupId = msgId.first; - ev->mPostedEventCode = RsPostedEventCode::READ_STATUS_CHANGED; - rsEvents->postEvent(ev); - } -} - - - // Overloaded from RsTickEvent for Event callbacks. -void p3PostBase::handle_event(uint32_t event_type, const std::string & /* elabel */) -{ -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::handle_event(" << event_type << ")"; - std::cerr << std::endl; -#endif - - // stuff. - switch(event_type) - { - case POSTBASE_BACKGROUND_PROCESSING: - background_tick(); - break; - - default: - /* error */ -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::handle_event() Unknown Event Type: " << event_type; - std::cerr << std::endl; -#endif - break; - } -} - - -/********************************************************************************* - * Background Calculations. - * - * Get list of change groups from Notify.... - * this doesn't imclude your own submissions (at this point). - * So they will not be processed until someone else changes something. - * TODO FIX: Must push for that change. - * - * Eventually, we should just be able to get the new messages from Notify, - * and only process them! - */ - -void p3PostBase::background_tick() -{ - -#if 0 - { - RsStackMutex stack(mPostBaseMtx); /********** STACK LOCKED MTX ******/ - if (mBgGroupList.empty()) - { - background_requestAllGroups(); - } - } -#endif - - background_requestUnprocessedGroup(); - - RsTickEvent::schedule_in(POSTBASE_BACKGROUND_PROCESSING, PROCESSING_INC_PERIOD); - -} - -bool p3PostBase::background_requestAllGroups() -{ -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_requestAllGroups()"; - std::cerr << std::endl; -#endif - - uint32_t ansType = RS_TOKREQ_ANSTYPE_LIST; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_IDS; - - uint32_t token = 0; - RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); - GxsTokenQueue::queueRequest(token, POSTBASE_ALL_GROUPS); - - return true; -} - - -void p3PostBase::background_loadGroups(const uint32_t &token) -{ - /* get messages */ -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_loadGroups()"; - std::cerr << std::endl; -#endif - - std::list groupList; - bool ok = RsGenExchange::getGroupList(token, groupList); - - if (!ok) - { - return; - } - - std::list::iterator it; - for(it = groupList.begin(); it != groupList.end(); ++it) - { - addGroupForProcessing(*it); - } -} - - -void p3PostBase::addGroupForProcessing(RsGxsGroupId grpId) -{ -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::addGroupForProcessing(" << grpId << ")"; - std::cerr << std::endl; -#endif // POSTBASE_DEBUG - - { - RsStackMutex stack(mPostBaseMtx); /********** STACK LOCKED MTX ******/ - // no point having multiple lookups queued. - mBgGroupList.insert(grpId); - } -} - - -void p3PostBase::background_requestUnprocessedGroup() -{ -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_requestUnprocessedGroup()"; - std::cerr << std::endl; -#endif // POSTBASE_DEBUG - - - RsGxsGroupId grpId; - { - RsStackMutex stack(mPostBaseMtx); /********** STACK LOCKED MTX ******/ - if (mBgProcessing) - { -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_requestUnprocessedGroup() Already Active"; - std::cerr << std::endl; -#endif - return; - } - if (mBgGroupList.empty()) - { -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_requestUnprocessedGroup() No Groups to Process"; - std::cerr << std::endl; -#endif - return; - } - - grpId = *mBgGroupList.begin(); - mBgGroupList.erase(grpId); - mBgProcessing = true; - } - - background_requestGroupMsgs(grpId, true); -} - - - - - -void p3PostBase::background_requestGroupMsgs(const RsGxsGroupId &grpId, bool unprocessedOnly) -{ -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_requestGroupMsgs() id: " << grpId; - std::cerr << std::endl; -#endif - - uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - - if (unprocessedOnly) - { - opts.mStatusFilter = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - opts.mStatusMask = GXS_SERV::GXS_MSG_STATUS_UNPROCESSED; - } - - std::list grouplist; - grouplist.push_back(grpId); - - uint32_t token = 0; - - RsGenExchange::getTokenService()->requestMsgInfo(token, ansType, opts, grouplist); - - if (unprocessedOnly) - { - GxsTokenQueue::queueRequest(token, POSTBASE_UNPROCESSED_MSGS); - } - else - { - GxsTokenQueue::queueRequest(token, POSTBASE_ALL_MSGS); - } -} - - - - -void p3PostBase::background_loadUnprocessedMsgs(const uint32_t &token) -{ - background_loadMsgs(token, true); -} - - -void p3PostBase::background_loadAllMsgs(const uint32_t &token) -{ - background_loadMsgs(token, false); -} - - -/* This function is generalised to support any collection of messages, across multiple groups */ - -void p3PostBase::background_loadMsgs(const uint32_t &token, bool unprocessed) -{ - /* get messages */ -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_loadMsgs()"; - std::cerr << std::endl; -#endif - - std::map > msgData; - bool ok = RsGenExchange::getMsgData(token, msgData); - - if (!ok) - { - std::cerr << "p3PostBase::background_loadMsgs() Failed to getMsgData()"; - std::cerr << std::endl; - - /* cleanup */ - background_cleanup(); - return; - - } - - { - RsStackMutex stack(mPostBaseMtx); /********** STACK LOCKED MTX ******/ - mBgStatsMap.clear(); - mBgIncremental = unprocessed; - } - - std::map > postMap; - - // generate vector of changes to push to the GUI. - std::vector changes; - - RsGxsGroupId groupId; - std::map >::iterator mit; - std::vector::iterator vit; - for (mit = msgData.begin(); mit != msgData.end(); ++mit) - { - groupId = mit->first; - for (vit = mit->second.begin(); vit != mit->second.end(); ++vit) - { - RsGxsMessageId parentId = (*vit)->meta.mParentId; - RsGxsMessageId threadId = (*vit)->meta.mThreadId; - - - bool inc_counters = false; - uint32_t vote_up_inc = 0; - uint32_t vote_down_inc = 0; - uint32_t comment_inc = 0; - - bool add_voter = false; - RsGxsId voterId; - RsGxsCommentItem *commentItem; - RsGxsVoteItem *voteItem; - - /* THIS Should be handled by UNPROCESSED Filter - but isn't */ - if (!IS_MSG_UNPROCESSED((*vit)->meta.mMsgStatus)) - { - RsStackMutex stack(mPostBaseMtx); /********** STACK LOCKED MTX ******/ - if (mBgIncremental) - { -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_loadMsgs() Msg already Processed - Skipping"; - std::cerr << std::endl; - std::cerr << "p3PostBase::background_loadMsgs() ERROR This should not happen"; - std::cerr << std::endl; -#endif - delete(*vit); - continue; - } - } - - /* 3 types expected: PostedPost, Comment and Vote */ - if (parentId.isNull()) - { -#ifdef POSTBASE_DEBUG - /* we don't care about top-level (Posts) */ - std::cerr << "\tIgnoring TopLevel Item"; - std::cerr << std::endl; -#endif - - /* but we need to notify GUI about them */ - changes.push_back(new RsGxsMsgChange(RsGxsNotify::TYPE_PROCESSED, mit->first,(*vit)->meta.mMsgId, false)); - } - else if (NULL != (commentItem = dynamic_cast(*vit))) - { -#ifdef POSTBASE_DEBUG - /* comment - want all */ - /* Comments are counted by Thread Id */ - std::cerr << "\tProcessing Comment: " << commentItem; - std::cerr << std::endl; -#endif - - inc_counters = true; - comment_inc = 1; - } - else if (NULL != (voteItem = dynamic_cast(*vit))) - { - /* vote - only care about direct children */ - if (parentId == threadId) - { - /* Votes are organised by Parent Id, - * ie. you can vote for both Posts and Comments - */ -#ifdef POSTBASE_DEBUG - std::cerr << "\tProcessing Vote: " << voteItem; - std::cerr << std::endl; -#endif - - inc_counters = true; - add_voter = true; - voterId = voteItem->meta.mAuthorId; - - if (voteItem->mMsg.mVoteType == GXS_VOTE_UP) - { - vote_up_inc = 1; - } - else - { - vote_down_inc = 1; - } - } - } - else - { - /* unknown! */ - std::cerr << "p3PostBase::background_processNewMessages() ERROR Strange NEW Message:" << std::endl; - std::cerr << "\t" << (*vit)->meta; - std::cerr << std::endl; - - } - - if (inc_counters) - { - RsStackMutex stack(mPostBaseMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator sit = mBgStatsMap.find(threadId); - if (sit == mBgStatsMap.end()) - { - // add to map of ones to update. - postMap[groupId].insert(threadId); - - mBgStatsMap[threadId] = PostStats(0,0,0); - sit = mBgStatsMap.find(threadId); - } - - sit->second.comments += comment_inc; - sit->second.up_votes += vote_up_inc; - sit->second.down_votes += vote_down_inc; - - - if (add_voter) - { - sit->second.voters.push_back(voterId); - } - -#ifdef POSTBASE_DEBUG - std::cerr << "\tThreadId: " << threadId; - std::cerr << " Comment Total: " << sit->second.comments; - std::cerr << " UpVote Total: " << sit->second.up_votes; - std::cerr << " DownVote Total: " << sit->second.down_votes; - std::cerr << std::endl; -#endif - } - - /* flag all messages as processed and new for the gui */ - if ((*vit)->meta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_UNPROCESSED) - { - uint32_t token_a; - RsGxsGrpMsgIdPair msgId = std::make_pair(groupId, (*vit)->meta.mMsgId); - RsGenExchange::setMsgStatusFlags(token_a, msgId, GXS_SERV::GXS_MSG_STATUS_GUI_NEW | GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD, GXS_SERV::GXS_MSG_STATUS_UNPROCESSED | GXS_SERV::GXS_MSG_STATUS_GUI_NEW | GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD); - } - delete(*vit); - } - } - - /* push updates of new Posts */ - notifyChanges(changes); - - /* request the summary info from the parents */ - uint32_t token_b; - uint32_t anstype = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_META; - RsGenExchange::getTokenService()->requestMsgInfo(token_b, anstype, opts, postMap); - - GxsTokenQueue::queueRequest(token_b, POSTBASE_BG_POST_META); - return; -} - - -#define RSGXS_MAX_SERVICE_STRING 1024 -bool encodePostCache(std::string &str, const PostStats &s) -{ - char line[RSGXS_MAX_SERVICE_STRING]; - - snprintf(line, RSGXS_MAX_SERVICE_STRING, "%d %d %d", s.comments, s.up_votes, s.down_votes); - - str = line; - return true; -} - -bool extractPostCache(const std::string &str, PostStats &s) -{ - - uint32_t iupvotes, idownvotes, icomments; - if (3 == sscanf(str.c_str(), "%u %u %u", &icomments, &iupvotes, &idownvotes)) - { - s.comments = icomments; - s.up_votes = iupvotes; - s.down_votes = idownvotes; - return true; - } - return false; -} - - -void p3PostBase::background_updateVoteCounts(const uint32_t &token) -{ -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_updateVoteCounts()"; - std::cerr << std::endl; -#endif - - GxsMsgMetaMap parentMsgList; - GxsMsgMetaMap::iterator mit; - std::vector::iterator vit; - - bool ok = RsGenExchange::getMsgMeta(token, parentMsgList); - - if (!ok) - { -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_updateVoteCounts() ERROR"; - std::cerr << std::endl; -#endif - background_cleanup(); - return; - } - - // generate vector of changes to push to the GUI. - std::vector changes; - - for(mit = parentMsgList.begin(); mit != parentMsgList.end(); ++mit) - { - for(vit = mit->second.begin(); vit != mit->second.end(); ++vit) - { -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_updateVoteCounts() Processing Msg(" << mit->first; - std::cerr << ", " << vit->mMsgId << ")"; - std::cerr << std::endl; -#endif - - RsStackMutex stack(mPostBaseMtx); /********** STACK LOCKED MTX ******/ - - /* extract current vote count */ - PostStats stats; - if (mBgIncremental) - { - if (!extractPostCache(vit->mServiceString, stats)) - { - if (!(vit->mServiceString.empty())) - { - std::cerr << "p3PostBase::background_updateVoteCounts() Failed to extract Votes"; - std::cerr << std::endl; - std::cerr << "\tFrom String: " << vit->mServiceString; - std::cerr << std::endl; - } - } - } - - /* get increment */ - std::map::iterator it; - it = mBgStatsMap.find(vit->mMsgId); - - if (it != mBgStatsMap.end()) - { -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_updateVoteCounts() Adding to msgChangeMap: "; - std::cerr << mit->first << " MsgId: " << vit->mMsgId; - std::cerr << std::endl; -#endif - - stats.increment(it->second); - - changes.push_back(new RsGxsMsgChange(RsGxsNotify::TYPE_PROCESSED,mit->first,vit->mMsgId, false)); - } - else - { -#ifdef POSTBASE_DEBUG - // warning. - std::cerr << "p3PostBase::background_updateVoteCounts() Warning No New Votes found."; - std::cerr << " For MsgId: " << vit->mMsgId; - std::cerr << std::endl; -#endif - } - - std::string str; - if (!encodePostCache(str, stats)) - { - std::cerr << "p3PostBase::background_updateVoteCounts() Failed to encode Votes"; - std::cerr << std::endl; - } - else - { -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_updateVoteCounts() Encoded String: " << str; - std::cerr << std::endl; -#endif - /* store new result */ - uint32_t token_c; - RsGxsGrpMsgIdPair msgId = std::make_pair(vit->mGroupId, vit->mMsgId); - RsGenExchange::setMsgServiceString(token_c, msgId, str); - } - } - } - - notifyChanges(changes); - - // DONE!. - background_cleanup(); - return; - -} - - -bool p3PostBase::background_cleanup() -{ -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::background_cleanup()"; - std::cerr << std::endl; -#endif - - RsStackMutex stack(mPostBaseMtx); /********** STACK LOCKED MTX ******/ - - // Cleanup. - mBgStatsMap.clear(); - mBgProcessing = false; - - return true; -} - - - // Overloaded from GxsTokenQueue for Request callbacks. -void p3PostBase::handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) -{ -#ifdef POSTBASE_DEBUG - std::cerr << "p3PostBase::handleResponse(" << token << "," << req_type << "," << status << ")" << std::endl; -#endif - if (status != RsTokenService::COMPLETE) - return; //For now, only manage Complete request - - // stuff. - switch(req_type) - { - case POSTBASE_ALL_GROUPS: - background_loadGroups(token); - break; - case POSTBASE_UNPROCESSED_MSGS: - background_loadUnprocessedMsgs(token); - break; - case POSTBASE_ALL_MSGS: - background_loadAllMsgs(token); - break; - case POSTBASE_BG_POST_META: - background_updateVoteCounts(token); - break; - default: - /* error */ - std::cerr << "p3PostBase::handleResponse() Unknown Request Type: " << req_type; - std::cerr << std::endl; - break; - } -} - -static const uint32_t GXS_POSTED_CONFIG_MAX_TIME_NOTIFY_STORAGE = 86400*30*2 ; // ignore notifications for 2 months -static const uint8_t GXS_POSTED_CONFIG_SUBTYPE_NOTIFY_RECORD = 0x01 ; - -struct RsGxsPostedNotifyRecordsItem: public RsItem -{ - - RsGxsPostedNotifyRecordsItem() - : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_GXS_TYPE_POSTED_CONFIG,GXS_POSTED_CONFIG_SUBTYPE_NOTIFY_RECORD) - {} - - virtual ~RsGxsPostedNotifyRecordsItem() {} - - void serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) - { RS_SERIAL_PROCESS(records); } - - void clear() {} - - std::map records; -}; - -class GxsPostedConfigSerializer : public RsServiceSerializer -{ -public: - GxsPostedConfigSerializer() : RsServiceSerializer(RS_SERVICE_GXS_TYPE_POSTED_CONFIG) {} - virtual ~GxsPostedConfigSerializer() {} - - RsItem* create_item(uint16_t service_id, uint8_t item_sub_id) const - { - if(service_id != RS_SERVICE_GXS_TYPE_POSTED_CONFIG) - return NULL; - - switch(item_sub_id) - { - case GXS_POSTED_CONFIG_SUBTYPE_NOTIFY_RECORD: return new RsGxsPostedNotifyRecordsItem(); - default: - return NULL; - } - } -}; - -bool p3PostBase::service_checkIfGroupIsStillUsed(const RsGxsGrpMetaData& meta) -{ -#ifdef GXSFORUMS_CHANNELS - std::cerr << "p3gxsChannels: Checking unused board: called by GxsCleaning." << std::endl; -#endif - - // request all group infos at once - - rstime_t now = time(nullptr); - - RS_STACK_MUTEX(mKnownPostedMutex); - - auto it = mKnownPosted.find(meta.mGroupId); - bool unknown_posted = (it == mKnownPosted.end()); - -#ifdef GXSFORUMS_CHANNELS - std::cerr << " Board " << meta.mGroupId ; -#endif - - if(unknown_posted) - { - // This case should normally not happen. It does because this board was never registered since it may - // arrived before this code was here - -#ifdef GXSFORUMS_CHANNELS - std::cerr << ". Not known yet. Adding current time as new TS." << std::endl; -#endif - mKnownPosted[meta.mGroupId] = now; - IndicateConfigChanged(); - - return true; - } - else - { - bool used_by_friends = (now < it->second + POSTED_UNUSED_BY_FRIENDS_DELAY); - bool subscribed = static_cast(meta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED); - - std::cerr << ". subscribed: " << subscribed << ", used_by_friends: " << used_by_friends << " last TS: " << now - it->second << " secs ago (" << (now-it->second)/86400 << " days)"; - - if(!subscribed && !used_by_friends) - { -#ifdef GXSFORUMS_CHANNELS - std::cerr << ". Scheduling for deletion" << std::endl; -#endif - return false; - } - else - { -#ifdef GXSFORUMS_CHANNELS - std::cerr << ". Keeping!" << std::endl; -#endif - return true; - } - } -} - -bool p3PostBase::saveList(bool& cleanup, std::list&saveList) -{ - cleanup = true ; - - RsGxsPostedNotifyRecordsItem *item = new RsGxsPostedNotifyRecordsItem ; - - { - RS_STACK_MUTEX(mKnownPostedMutex); - item->records = mKnownPosted ; - } - - saveList.push_back(item) ; - return true; -} - -bool p3PostBase::loadList(std::list& loadList) -{ - while(!loadList.empty()) - { - RsItem *item = loadList.front(); - loadList.pop_front(); - - rstime_t now = time(NULL); - - RsGxsPostedNotifyRecordsItem *fnr = dynamic_cast(item) ; - - if(fnr != NULL) - { - RS_STACK_MUTEX(mKnownPostedMutex); - - mKnownPosted.clear(); - - for(auto it(fnr->records.begin());it!=fnr->records.end();++it) - if( now < it->second + GXS_POSTED_CONFIG_MAX_TIME_NOTIFY_STORAGE) - mKnownPosted.insert(*it) ; - } - - delete item ; - } - return true; -} - -RsSerialiser* p3PostBase::setupSerialiser() -{ - RsSerialiser* rss = new RsSerialiser; - rss->addSerialType(new GxsPostedConfigSerializer()); - - return rss; -} - diff --git a/libretroshare/src/services/p3postbase.h b/libretroshare/src/services/p3postbase.h deleted file mode 100644 index 3c2f5f67f..000000000 --- a/libretroshare/src/services/p3postbase.h +++ /dev/null @@ -1,137 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3postbase.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008-2012 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef P3_POSTBASE_SERVICE_HEADER -#define P3_POSTBASE_SERVICE_HEADER - - -#include "services/p3gxscommon.h" -#include "gxs/rsgenexchange.h" - -#include "util/rstickevent.h" - -#include - -#include -#include -#include - -/* - * - */ - - -class PostStats -{ - public: - PostStats() :up_votes(0), down_votes(0), comments(0) { return; } - PostStats(int up, int down, int c) :up_votes(up), down_votes(down), comments(c) { return; } - - void increment(const PostStats &s) - { - up_votes += s.up_votes; - down_votes += s.down_votes; - comments += s.comments; - return; - } - - int up_votes; - int down_votes; - int comments; - std::list voters; -}; - -bool encodePostCache(std::string &str, const PostStats &s); -bool extractPostCache(const std::string &str, PostStats &s); - - -class p3PostBase: public RsGenExchange, public GxsTokenQueue, public RsTickEvent, public p3Config -{ -public: - - p3PostBase(RsGeneralDataService *gds, RsNetworkExchangeService *nes, RsGixs* gixs, - RsSerialType* serviceSerialiser, uint16_t serviceType); - - virtual void service_tick() override; - -protected: - - virtual void notifyChanges(std::vector& changes) override; - - // Overloaded from GxsTokenQueue for Request callbacks. - virtual void handleResponse(uint32_t token, uint32_t req_type - , RsTokenService::GxsRequestStatus status) override; - - // Overloaded from RsTickEvent. - virtual void handle_event(uint32_t event_type, const std::string &elabel) override; - - // overloads p3Config - virtual RsSerialiser* setupSerialiser() override; // @see p3Config::setupSerialiser() - virtual bool saveList(bool &cleanup, std::list&saveList) override; // @see p3Config::saveList(bool &cleanup, std::list&) - virtual bool loadList(std::list& loadList) override; // @see p3Config::loadList(std::list&) - - virtual bool service_checkIfGroupIsStillUsed(const RsGxsGrpMetaData& meta) override; -public: - - ////////////////////////////////////////////////////////////////////////////// - - virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read); - - -protected: - - p3GxsCommentService *mCommentService; - -private: - - static uint32_t postBaseAuthenPolicy(); - - // Background processing. - void background_tick(); - - bool background_requestAllGroups(); - void background_loadGroups(const uint32_t &token); - - void addGroupForProcessing(RsGxsGroupId grpId); - void background_requestUnprocessedGroup(); - - void background_requestGroupMsgs(const RsGxsGroupId &grpId, bool unprocessedOnly); - void background_loadUnprocessedMsgs(const uint32_t &token); - void background_loadAllMsgs(const uint32_t &token); - void background_loadMsgs(const uint32_t &token, bool unprocessed); - - - void background_updateVoteCounts(const uint32_t &token); - bool background_cleanup(); - - - RsMutex mPostBaseMtx; - RsMutex mKnownPostedMutex; - - bool mBgProcessing; - bool mBgIncremental; - std::set mBgGroupList; - std::map mBgStatsMap; - - std::map mKnownPosted; -}; - -#endif diff --git a/libretroshare/src/services/p3posted.cc b/libretroshare/src/services/p3posted.cc deleted file mode 100644 index 20c3f2151..000000000 --- a/libretroshare/src/services/p3posted.cc +++ /dev/null @@ -1,526 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3posted.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2013 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "services/p3posted.h" -#include "rsitems/rsposteditems.h" - -#include -#include - - -/**** - * #define POSTED_DEBUG 1 - ****/ - -/*extern*/ RsPosted* rsPosted = nullptr; - -/********************************************************************************/ -/******************* Startup / Tick ******************************************/ -/********************************************************************************/ - -p3Posted::p3Posted( - RsGeneralDataService *gds, RsNetworkExchangeService *nes, - RsGixs* gixs ) : - p3PostBase( gds, nes, gixs, new RsGxsPostedSerialiser(), - RS_SERVICE_GXS_TYPE_POSTED ), - RsPosted(static_cast(*this)) {} - -const std::string GXS_POSTED_APP_NAME = "gxsposted"; -const uint16_t GXS_POSTED_APP_MAJOR_VERSION = 1; -const uint16_t GXS_POSTED_APP_MINOR_VERSION = 0; -const uint16_t GXS_POSTED_MIN_MAJOR_VERSION = 1; -const uint16_t GXS_POSTED_MIN_MINOR_VERSION = 0; - -static const uint32_t GXS_POSTED_CONFIG_MAX_TIME_NOTIFY_STORAGE = 86400*30*2 ; // ignore notifications for 2 months -static const uint8_t GXS_POSTED_CONFIG_SUBTYPE_NOTIFY_RECORD = 0x01 ; - -RsServiceInfo p3Posted::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_GXS_TYPE_POSTED, - GXS_POSTED_APP_NAME, - GXS_POSTED_APP_MAJOR_VERSION, - GXS_POSTED_APP_MINOR_VERSION, - GXS_POSTED_MIN_MAJOR_VERSION, - GXS_POSTED_MIN_MINOR_VERSION); -} - -bool p3Posted::groupShareKeys(const RsGxsGroupId& groupId,const std::set& peers) -{ - RsGenExchange::shareGroupPublishKey(groupId,peers) ; - return true ; -} - -bool p3Posted::getGroupData(const uint32_t &token, std::vector &groups) -{ - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); ++vit) - { - RsGxsPostedGroupItem* item = dynamic_cast(*vit); - if (item) - { - RsPostedGroup grp; - item->toPostedGroup(grp, true); - delete item; - groups.push_back(grp); - } - else - { - std::cerr << "Not a RsGxsPostedGroupItem, deleting!" << std::endl; - delete *vit; - } - } - } - return ok; -} - -bool p3Posted::getPostData( - const uint32_t &token, std::vector &msgs, - std::vector &cmts, - std::vector &vots) -{ -#ifdef POSTED_DEBUG - RsDbg() << __PRETTY_FUNCTION__ << std::endl; -#endif - - GxsMsgDataMap msgData; - rstime_t now = time(NULL); - if(!RsGenExchange::getMsgData(token, msgData)) - { - RsErr() << __PRETTY_FUNCTION__ << " ERROR in request" << std::endl; - return false; - } - - GxsMsgDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsPostedPostItem* postItem = - dynamic_cast(*vit); - - if(postItem) - { - // TODO Really needed all of these lines? - RsPostedPost msg = postItem->mPost; - msg.mMeta = postItem->meta; - postItem->toPostedPost(msg, true); - msg.calculateScores(now); - - msgs.push_back(msg); - delete postItem; - } - else - { - RsGxsCommentItem* cmtItem = - dynamic_cast(*vit); - if(cmtItem) - { - RsGxsComment cmt; - RsGxsMsgItem *mi = (*vit); - cmt = cmtItem->mMsg; - cmt.mMeta = mi->meta; -#ifdef GXSCOMMENT_DEBUG - RsDbg() << __PRETTY_FUNCTION__ << " Found Comment:" << std::endl; - cmt.print(std::cerr," ", "cmt"); -#endif - cmts.push_back(cmt); - delete cmtItem; - } - else - { - RsGxsVoteItem* votItem = - dynamic_cast(*vit); - if(votItem) - { - RsGxsVote vot; - RsGxsMsgItem *mi = (*vit); - vot = votItem->mMsg; - vot.mMeta = mi->meta; - vots.push_back(vot); - delete votItem; - } - else - { - RsGxsMsgItem* msg = (*vit); - //const uint16_t RS_SERVICE_GXS_TYPE_CHANNELS = 0x0217; - //const uint8_t RS_PKT_SUBTYPE_GXSCHANNEL_POST_ITEM = 0x03; - //const uint8_t RS_PKT_SUBTYPE_GXSCOMMENT_COMMENT_ITEM = 0xf1; - //const uint8_t RS_PKT_SUBTYPE_GXSCOMMENT_VOTE_ITEM = 0xf2; - RsErr() << __PRETTY_FUNCTION__ - << "Not a PostedPostItem neither a " - << "RsGxsCommentItem neither a RsGxsVoteItem" - << " PacketService=" << std::hex << (int)msg->PacketService() << std::dec - << " PacketSubType=" << std::hex << (int)msg->PacketSubType() << std::dec - << " type name =" << typeid(*msg).name() - << " , deleting!" << std::endl; - delete *vit; - } - } - } - } - } - - return true; -} - -bool p3Posted::getPostData( - const uint32_t &token, std::vector &posts, std::vector &cmts) -{ - std::vector vots; - return getPostData( token, posts, cmts, vots); -} - -bool p3Posted::getPostData( - const uint32_t &token, std::vector &posts) -{ - std::vector cmts; - std::vector vots; - return getPostData( token, posts, cmts, vots); -} - -//Not currently used -/*bool p3Posted::getRelatedPosts(const uint32_t &token, std::vector &msgs) -{ - GxsMsgRelatedDataMap msgData; - bool ok = RsGenExchange::getMsgRelatedData(token, msgData); - rstime_t now = time(NULL); - - if(ok) - { - GxsMsgRelatedDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsPostedPostItem* item = dynamic_cast(*vit); - - if(item) - { - RsPostedPost msg = item->mPost; - msg.mMeta = item->meta; - msg.calculateScores(now); - - msgs.push_back(msg); - delete item; - } - else - { - std::cerr << "Not a PostedPostItem, deleting!" << std::endl; - delete *vit; - } - } - } - } - - return ok; -}*/ - - -/********************************************************************************************/ -/********************************************************************************************/ -/********************************************************************************************/ - -/* Switched from having explicit Ranking calculations to calculating the set of scores - * on each RsPostedPost item. - * - * TODO: move this function to be part of RsPostedPost - then the GUI - * can reuse is as necessary. - * - */ - -bool RsPostedPost::calculateScores(rstime_t ref_time) -{ - /* so we want to calculate all the scores for this Post. */ - - PostStats stats; - extractPostCache(mMeta.mServiceString, stats); - - mUpVotes = stats.up_votes; - mDownVotes = stats.down_votes; - mComments = stats.comments; - mHaveVoted = (mMeta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_VOTE_MASK); - - rstime_t age_secs = ref_time - mMeta.mPublishTs; -#define POSTED_AGESHIFT (2.0) -#define POSTED_AGEFACTOR (3600.0) - - mTopScore = ((int) mUpVotes - (int) mDownVotes); - if (mTopScore > 0) - { - // score drops with time. - mHotScore = mTopScore / pow(POSTED_AGESHIFT + age_secs / POSTED_AGEFACTOR, 1.5); - } - else - { - // gets more negative with time. - mHotScore = mTopScore * pow(POSTED_AGESHIFT + age_secs / POSTED_AGEFACTOR, 1.5); - } - mNewScore = -age_secs; - - return true; -} - -/********************************************************************************************/ -/********************************************************************************************/ - -bool p3Posted::createGroup(uint32_t &token, RsPostedGroup &group) -{ - std::cerr << "p3Posted::createGroup()" << std::endl; - - RsGxsPostedGroupItem* grpItem = new RsGxsPostedGroupItem(); - grpItem->fromPostedGroup(group, true); - - - RsGenExchange::publishGroup(token, grpItem); - return true; -} - - -bool p3Posted::updateGroup(uint32_t &token, RsPostedGroup &group) -{ - std::cerr << "p3Posted::updateGroup()" << std::endl; - - RsGxsPostedGroupItem* grpItem = new RsGxsPostedGroupItem(); - grpItem->fromPostedGroup(group, true); - - - RsGenExchange::updateGroup(token, grpItem); - return true; -} - - -bool p3Posted::createPost(uint32_t &token, RsPostedPost &msg) -{ - std::cerr << "p3Posted::createPost() GroupId: " << msg.mMeta.mGroupId; - std::cerr << std::endl; - - RsGxsPostedPostItem* msgItem = new RsGxsPostedPostItem(); - //msgItem->mPost = msg; - //msgItem->meta = msg.mMeta; - msgItem->fromPostedPost(msg, true); - - - RsGenExchange::publishMsg(token, msgItem); - return true; -} - -bool p3Posted::getBoardsInfo( - const std::list& boardsIds, - std::vector& groupsInfo ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - - if(boardsIds.empty()) - { - if( !requestGroupInfo(token, opts) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - } - else - { - if( !requestGroupInfo(token, opts, boardsIds) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - } - - return getGroupData(token, groupsInfo) && !groupsInfo.empty(); -} - -bool p3Posted::getBoardAllContent( const RsGxsGroupId& groupId, - std::vector& posts, - std::vector& comments, - std::vector& votes ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - - if( !requestMsgInfo(token, opts, std::list({groupId})) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - - return getPostData(token, posts, comments, votes); -} - -bool p3Posted::getBoardContent( const RsGxsGroupId& groupId, - const std::set& contentsIds, - std::vector& posts, - std::vector& comments, - std::vector& votes ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - - GxsMsgReq msgIds; - msgIds[groupId] = contentsIds; - - if( !requestMsgInfo(token, opts, msgIds) || - waitToken(token) != RsTokenService::COMPLETE ) return false; - - return getPostData(token, posts, comments, votes); -} - -bool p3Posted::getBoardsSummaries(std::list& boards ) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; - if( !requestGroupInfo(token, opts) || waitToken(token) != RsTokenService::COMPLETE ) return false; - - return getGroupSummary(token, boards); -} - -bool p3Posted::getBoardsServiceStatistics(GxsServiceStatistic& stat) -{ - uint32_t token; - if(!RsGxsIfaceHelper::requestServiceStatistic(token) || waitToken(token) != RsTokenService::COMPLETE) - return false; - - return RsGenExchange::getServiceStatistic(token,stat); -} - - -bool p3Posted::getBoardStatistics(const RsGxsGroupId& boardId,GxsGroupStatistic& stat) -{ - uint32_t token; - if(!RsGxsIfaceHelper::requestGroupStatistic(token, boardId) || waitToken(token) != RsTokenService::COMPLETE) - return false; - - return RsGenExchange::getGroupStatistic(token,stat); -} - -bool p3Posted::createBoard(RsPostedGroup& board) -{ - uint32_t token; - if(!createGroup(token, board)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failed creating group." << std::endl; - return false; - } - - if(waitToken(token,std::chrono::milliseconds(5000)) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed." << std::endl; - return false; - } - - if(!RsGenExchange::getPublishedGroupMeta(token, board.mMeta)) - { - std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting updated " << " group data." << std::endl; - return false; - } - - return true; -} - -bool p3Posted::voteForPost(bool up,const RsGxsGroupId& postGrpId,const RsGxsMessageId& postMsgId,const RsGxsId& authorId) -{ - // Do some basic tests - - if(!rsIdentity->isOwnId(authorId)) // This is ruled out before waitToken complains. Not sure it's needed. - { - std::cerr << __PRETTY_FUNCTION__ << ": vote submitted with an ID that is not yours! This cannot work." << std::endl; - return false; - } - - RsGxsVote vote; - - vote.mMeta.mGroupId = postGrpId; - vote.mMeta.mThreadId = postMsgId; - vote.mMeta.mParentId = postMsgId; - vote.mMeta.mAuthorId = authorId; - - if (up) - vote.mVoteType = GXS_VOTE_UP; - else - vote.mVoteType = GXS_VOTE_DOWN; - - uint32_t token; - - if(!createNewVote(token, vote)) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Failed submitting vote to (group,msg) " << postGrpId << "," << postMsgId << " from author " << authorId << std::endl; - return false; - } - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! GXS operation failed." << std::endl; - return false; - } - return true; -} - -bool p3Posted::setPostReadStatus(const RsGxsGrpMsgIdPair& msgId, bool read) -{ - uint32_t token; - - setMessageReadStatus(token,msgId,read); - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! GXS operation failed." << std::endl; - return false; - } - RsGxsGrpMsgIdPair p; - acknowledgeMsg(token,p); - return true; -} -bool p3Posted::editBoard(RsPostedGroup& board) -{ - uint32_t token; - if(!updateGroup(token, board)) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Failed updating group." << std::endl; - return false; - } - - if(waitToken(token) != RsTokenService::COMPLETE) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! GXS operation failed." << std::endl; - return false; - } - - if(!RsGenExchange::getPublishedGroupMeta(token, board.mMeta)) - { - std::cerr << __PRETTY_FUNCTION__ << " Error! Failure getting updated " << " group data." << std::endl; - return false; - } - - return true; -} - -RsPosted::~RsPosted() = default; -RsGxsPostedEvent::~RsGxsPostedEvent() = default; diff --git a/libretroshare/src/services/p3posted.h b/libretroshare/src/services/p3posted.h deleted file mode 100644 index 0965ec1d1..000000000 --- a/libretroshare/src/services/p3posted.h +++ /dev/null @@ -1,158 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3posted.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2013 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef P3_POSTED_SERVICE_HEADER -#define P3_POSTED_SERVICE_HEADER - - -#include "retroshare/rsposted.h" -#include "services/p3postbase.h" - -#include - -#include -#include -#include - -/* - * - */ - -class p3Posted: public p3PostBase, public RsPosted -{ -public: - - p3Posted(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs* gixs); - virtual RsServiceInfo getServiceInfo(); - -protected: - -virtual void notifyChanges(std::vector& changes) -{ - return p3PostBase::notifyChanges(changes); -} - - public: - -#ifdef TO_REMOVE -virtual void receiveHelperChanges(std::vector& changes) -{ - return RsGxsIfaceHelper::receiveChanges(changes); -} -#endif - - bool getBoardsInfo(const std::list& boardsIds, - std::vector& groupsInfo ) override; - - bool getBoardAllContent(const RsGxsGroupId& groupId, - std::vector& posts, - std::vector& comments, - std::vector& votes ) override; - - bool getBoardContent(const RsGxsGroupId& groupId, - const std::set& contentsIds, - std::vector& posts, - std::vector& comments, - std::vector& votes ) override; - - bool getBoardsSummaries(std::list& groupInfo) override; - - bool getBoardStatistics(const RsGxsGroupId& boardId,GxsGroupStatistic& stat) override; - - bool getBoardsServiceStatistics(GxsServiceStatistic& stat) override; - - bool editBoard(RsPostedGroup& board) override; - - bool createBoard(RsPostedGroup& board) override; - - bool voteForPost(bool up,const RsGxsGroupId& postGrpId,const RsGxsMessageId& postMsgId,const RsGxsId& voterId) override; - - bool setPostReadStatus(const RsGxsGrpMsgIdPair& msgId, bool read) override; - - virtual bool getGroupData(const uint32_t &token, std::vector &groups) override; - virtual bool getPostData(const uint32_t &token, std::vector &posts, std::vector &cmts, std::vector &vots) override; - virtual bool getPostData(const uint32_t &token, std::vector &posts, std::vector &cmts) override; - virtual bool getPostData(const uint32_t &token, std::vector &posts) override; - -//Not currently used -//virtual bool getRelatedPosts(const uint32_t &token, std::vector &posts); - -virtual bool createGroup(uint32_t &token, RsPostedGroup &group) override; -virtual bool createPost(uint32_t &token, RsPostedPost &post) override; - -virtual bool updateGroup(uint32_t &token, RsPostedGroup &group) override; -virtual bool groupShareKeys(const RsGxsGroupId &group, const std::set& peers) override; - - ////////////////////////////////////////////////////////////////////////////// - // WRAPPERS due to the separate Interface. - -virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) override - { - return p3PostBase::setMessageReadStatus(token, msgId, read); - } - - virtual bool setCommentAsRead(uint32_t& token,const RsGxsGroupId& gid,const RsGxsMessageId& comment_msg_id) override - { - p3PostBase::setMessageReadStatus(token,RsGxsGrpMsgIdPair(gid,comment_msg_id),true); - return true; - } - - - - /** Comment service - Provide RsGxsCommentService - - * redirect to p3GxsCommentService */ - virtual bool getCommentData(uint32_t token, std::vector &msgs) override - { return mCommentService->getGxsCommentData(token, msgs); } - - virtual bool getRelatedComments( uint32_t token, - std::vector &msgs ) override - { return mCommentService->getGxsRelatedComments(token, msgs); } - - virtual bool createNewComment(uint32_t &token, const RsGxsComment &msg) override - { - return mCommentService->createGxsComment(token, msg); - } - virtual bool createComment(RsGxsComment& msg) override - { - uint32_t token; - - return mCommentService->createGxsComment(token, msg) && waitToken(token) == RsTokenService::COMPLETE ; - } - - virtual bool createNewVote(uint32_t &token, RsGxsVote &msg) override - { - return mCommentService->createGxsVote(token, msg); - } - - virtual bool acknowledgeComment( - uint32_t token, std::pair& msgId ) override - { return acknowledgeMsg(token, msgId); } - - virtual bool acknowledgeVote( - uint32_t token, std::pair& msgId ) override - { - if (mCommentService->acknowledgeVote(token, msgId)) return true; - return acknowledgeMsg(token, msgId); - } -}; - -#endif diff --git a/libretroshare/src/services/p3rtt.cc b/libretroshare/src/services/p3rtt.cc deleted file mode 100644 index 0dc2f41e2..000000000 --- a/libretroshare/src/services/p3rtt.cc +++ /dev/null @@ -1,461 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3rtt.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2013 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include -#include -#include - -#include "util/rsdir.h" -#include "retroshare/rsiface.h" -#include "retroshare/rspeers.h" -#include "pqi/pqibin.h" -#include "pqi/pqistore.h" -#include "pqi/p3linkmgr.h" -#include "rsserver/p3face.h" -#include "util/cxx17retrocompat.h" -#include "services/p3rtt.h" -#include "rsitems/rsrttitems.h" - - -/**** - * #define DEBUG_RTT 1 - ****/ - -/* DEFINE INTERFACE POINTER! */ -RsRtt *rsRtt = NULL; - - -#define MAX_PONG_RESULTS 150 -#define RTT_PING_PERIOD 10 - -/************ IMPLEMENTATION NOTES ********************************* - * - * Voice over Retroshare ;) - * - * This will be a simple test VoIP system aimed at testing out the possibilities. - * - * Important things to test: - * 1) lag, and variability in data rate - * - To do this we time tag every packet..., the destination can use this info to calculate the results. - * - Like imixitup. Dt = clock_diff + lag. - * we expect clock_diff to be relatively constant, but lag to vary. - * lag cannot be negative, so minimal Dt is ~clock_diff, and delays on this are considered +lag. - * - * 2) we could directly measure lag. ping back and forth with Timestamps. - * - * 3) we also want to measure bandwidth... - * - not sure the best method? - * one way: send a ping, then a large amount of data (5 seconds worth), then another ping. - * the delta in timestamps should be a decent indication of bandwidth. - * say we have a 100kb/s connection... need 500kb. - * actually the amount of data should be based on a reasonable maximum that we require. - * what does decent video require? - * Audio we can test for 64kb/s - which seems like a decent rate: e.g. mono, 16bit 22k = 1 x 2 x 22k = 44 kilobytes/sec - * best to do this without a VoIP call going on ;) - * - * - */ - - -#ifdef WINDOWS_SYS -#include "util/rstime.h" -#include -#endif - -static double getCurrentTS() -{ - -#ifndef WINDOWS_SYS - struct timeval cts_tmp; - gettimeofday(&cts_tmp, NULL); - double cts = (cts_tmp.tv_sec) + ((double) cts_tmp.tv_usec) / 1000000.0; -#else - struct _timeb timebuf; - _ftime( &timebuf); - double cts = (timebuf.time) + ((double) timebuf.millitm) / 1000.0; -#endif - return cts; -} - -static uint64_t convertTsTo64bits(double ts) -{ - uint32_t secs = (uint32_t) ts; - uint32_t usecs = (uint32_t) ((ts - (double) secs) * 1000000); - uint64_t bits = (((uint64_t) secs) << 32) + usecs; - return bits; -} - - -static double convert64bitsToTs(uint64_t bits) -{ - uint32_t usecs = (uint32_t) (bits & 0xffffffff); - uint32_t secs = (uint32_t) ((bits >> 32) & 0xffffffff); - double ts = (secs) + ((double) usecs) / 1000000.0; - - return ts; -} - - - - -p3rtt::p3rtt(p3ServiceControl *sc) - :p3FastService(), mRttMtx("p3rtt"), mServiceCtrl(sc) -{ - addSerialType(new RsRttSerialiser()); - - mSentPingTime = 0; - mCounter = 0; - -} - - -const std::string RTT_APP_NAME = "rtt"; -const uint16_t RTT_APP_MAJOR_VERSION = 1; -const uint16_t RTT_APP_MINOR_VERSION = 0; -const uint16_t RTT_MIN_MAJOR_VERSION = 1; -const uint16_t RTT_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3rtt::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_RTT, - RTT_APP_NAME, - RTT_APP_MAJOR_VERSION, - RTT_APP_MINOR_VERSION, - RTT_MIN_MAJOR_VERSION, - RTT_MIN_MINOR_VERSION); -} - - - -int p3rtt::tick() -{ - sendPackets(); - - return 0; -} - -int p3rtt::status() -{ - return 1; -} - - - -int p3rtt::sendPackets() -{ - rstime_t now = time(NULL); - rstime_t pt; - { - RsStackMutex stack(mRttMtx); /****** LOCKED MUTEX *******/ - pt = mSentPingTime; - } - - if (now >= pt+RTT_PING_PERIOD) - { - sendPingMeasurements(); - - RsStackMutex stack(mRttMtx); /****** LOCKED MUTEX *******/ - mSentPingTime = now; - } - return true ; -} - - - -void p3rtt::sendPingMeasurements() -{ - - - /* we ping our peers */ - /* who is online? */ - std::set idList; - - mServiceCtrl->getPeersConnected(getServiceInfo().mServiceType, idList); - - /* prepare packets */ - std::set::iterator it; - for(it = idList.begin(); it != idList.end(); ++it) - { - double ts = getCurrentTS(); - - /* create the packet */ - RsRttPingItem *pingPkt = new RsRttPingItem(); - pingPkt->PeerId(*it); - pingPkt->mSeqNo = mCounter; - pingPkt->mPingTS = convertTsTo64bits(ts); - - storePingAttempt(*it, ts, mCounter); - -#ifdef DEBUG_RTT - std::cerr << "p3rtt::sendPingMeasurements() Pinging: " << *it << " [" << pingPkt->mSeqNo << "," << std::hex << pingPkt->mPingTS << std::dec << "]" << std::endl;; -#endif - sendItem(pingPkt); - } - - RsStackMutex stack(mRttMtx); /****** LOCKED MUTEX *******/ - mCounter++; -} - - -bool p3rtt::recvItem(RsItem *item) -{ - switch(item->PacketSubType()) - { - default: - break; - case RS_PKT_SUBTYPE_RTT_PING: - { - handlePing(item); - } - break; - case RS_PKT_SUBTYPE_RTT_PONG: - { - handlePong(item); - } - break; - } - - /* clean up */ - delete item; - return true ; -} - - -int p3rtt::handlePing(RsItem *item) -{ - /* cast to right type */ - RsRttPingItem *ping = (RsRttPingItem *) item; - - double ts = getCurrentTS(); -#ifdef DEBUG_RTT - std::cerr << "p3rtt::handlePing() from: " << ping->PeerId() << " - [" << ping->mSeqNo << "," << std::hex << ping->mPingTS << std::dec << "] " << std::endl; - std::cerr << "incoming ping travel time: " << ts - convert64bitsToTs(ping->mPingTS) << std::endl; -#endif - - /* with a ping, we just respond as quickly as possible - they do all the analysis */ - RsRttPongItem *pong = new RsRttPongItem(); - - pong->PeerId(ping->PeerId()); - pong->mPingTS = ping->mPingTS; - pong->mSeqNo = ping->mSeqNo; - - // add our timestamp. - pong->mPongTS = convertTsTo64bits(ts); - -#ifdef DEBUG_RTT - static double mLastResponseToPong = 0.0 ;// bad stuff - std::cerr << "Delay since last response to PONG: " << ts - mLastResponseToPong << std::endl; - mLastResponseToPong = ts ; -#endif - - sendItem(pong); - return true ; -} - - -int p3rtt::handlePong(RsItem *item) -{ - /* cast to right type */ - RsRttPongItem *pong = (RsRttPongItem *) item; - -#ifdef DEBUG_RTT - std::cerr << "p3rtt::handlePong() from: " << pong->PeerId() << " - [" << pong->mSeqNo << "," << std::hex << pong->mPingTS << " -> " << pong->mPongTS << std::dec << "] "<< std::endl; -#endif - - /* with a pong, we do the maths! */ - double recvTS = getCurrentTS(); - double pingTS = convert64bitsToTs(pong->mPingTS); - double pongTS = convert64bitsToTs(pong->mPongTS); - - double rtt = recvTS - pingTS; - double offset = pongTS - (recvTS - rtt / 2.0); // so to get to their time, we go ourTS + offset. - -#ifdef DEBUG_RTT - std::cerr << "incoming pong travel time: " << recvTS - convert64bitsToTs(pong->mPongTS) << std::endl; - std::cerr << " RTT analysis: pingTS: " << std::setprecision(16) << pingTS << ", pongTS: " << pongTS - << ", recvTS: " << std::setprecision(16) << recvTS << " ==> rtt: " << rtt << ", offset: " << offset << std::endl; -#endif - - storePongResult(pong->PeerId(), pong->mSeqNo, recvTS, rtt, offset); - return true ; -} - - - - -int p3rtt::storePingAttempt(const RsPeerId& id, double ts, uint32_t seqno) -{ - RsStackMutex stack(mRttMtx); /****** LOCKED MUTEX *******/ - - /* find corresponding local data */ - RttPeerInfo *peerInfo = locked_GetPeerInfo(id); - -#ifdef DEBUG_RTT - std::cerr << "Delay since previous ping attempt: " << ts - peerInfo->mCurrentPingTS << std::endl; -#endif - peerInfo->mCurrentPingTS = ts; - peerInfo->mCurrentPingCounter = seqno; - - peerInfo->mSentPings++; - if (!peerInfo->mCurrentPongRecvd) - { - peerInfo->mLostPongs++; - } - - peerInfo->mCurrentPongRecvd = true; - - return 1; -} - - - -int p3rtt::storePongResult(const RsPeerId& id, uint32_t counter, double recv_ts, double rtt, double offset) -{ - RsStackMutex stack(mRttMtx); /****** LOCKED MUTEX *******/ - - /* find corresponding local data */ - RttPeerInfo *peerInfo = locked_GetPeerInfo(id); - - if (peerInfo->mCurrentPingCounter != counter) - { -#ifdef DEBUG_RTT - std::cerr << "p3rtt::storePongResult() ERROR Severly Delayed Measurements!" << std::endl; -#endif - } - else - { - peerInfo->mCurrentPongRecvd = true; - } -#ifdef DEBUG_RTT - if(!peerInfo->mPongResults.empty()) - std::cerr << "Delay since last pong: " << recv_ts - peerInfo->mPongResults.back().mTS << std::endl; -#endif - - peerInfo->mPongResults.push_back(RsRttPongResult(recv_ts, rtt, offset)); - - - while(peerInfo->mPongResults.size() > MAX_PONG_RESULTS) - peerInfo->mPongResults.pop_front(); - - //Wait at least 20 pongs before compute mean time offset - if(peerInfo->mPongResults.size() > 20) - { - double mean = 0; - for(auto prIt : std::as_const(peerInfo->mPongResults)) - mean += prIt.mOffset; - peerInfo->mCurrentMeanOffset = mean / peerInfo->mPongResults.size(); - - if(fabs(peerInfo->mCurrentMeanOffset) > 120) - { - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mSslId = peerInfo->mId; - ev->mTimeShift = static_cast(peerInfo->mCurrentMeanOffset); - ev->mConnectionInfoCode = RsConnectionEventCode::PEER_TIME_SHIFT; - rsEvents->postEvent(ev); - } - RsWarn() << __PRETTY_FUNCTION__ << " Peer: " << peerInfo->mId - << " have a time offset of more than two minutes with you" - << std::endl; - } - } - return 1; -} - - -uint32_t p3rtt::getPongResults(const RsPeerId& id, int n, std::list &results) -{ - RsStackMutex stack(mRttMtx); /****** LOCKED MUTEX *******/ - - RttPeerInfo *peer = locked_GetPeerInfo(id); - - std::list::reverse_iterator it; - int i = 0; - for(it = peer->mPongResults.rbegin(); (it != peer->mPongResults.rend()) && (i < n); ++it, i++) - { - /* reversing order - so its easy to trim later */ - results.push_back(*it); - } - return i ; -} - -double p3rtt::getMeanOffset(const RsPeerId &id) -{ - RsStackMutex stack(mRttMtx); /****** LOCKED MUTEX *******/ - - RttPeerInfo *peer = locked_GetPeerInfo(id); - if(peer) - return peer->mCurrentMeanOffset; - else - return 0; -} - -RttPeerInfo *p3rtt::locked_GetPeerInfo(const RsPeerId& id) -{ - std::map::iterator it; - it = mPeerInfo.find(id); - if (it == mPeerInfo.end()) - { - /* add it in */ - RttPeerInfo pinfo; - - /* initialise entry */ - pinfo.initialisePeerInfo(id); - - mPeerInfo[id] = pinfo; - - it = mPeerInfo.find(id); - - } - - return &(it->second); -} - - - -bool RttPeerInfo::initialisePeerInfo(const RsPeerId& id) -{ - mId = id; - - /* reset variables */ - mCurrentPingTS = 0; - mCurrentPingCounter = 0; - mCurrentPongRecvd = true; - mCurrentMeanOffset = 0; - - mSentPings = 0; - mLostPongs = 0; - - mPongResults.clear(); - - return true; -} - - - - - - - - - - diff --git a/libretroshare/src/services/p3rtt.h b/libretroshare/src/services/p3rtt.h deleted file mode 100644 index c8df64034..000000000 --- a/libretroshare/src/services/p3rtt.h +++ /dev/null @@ -1,118 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3rtt.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011-2013 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef SERVICE_RSRTT_HEADER -#define SERVICE_RSRTT_HEADER - -#include -#include - -#include "rsitems/rsrttitems.h" -#include "services/p3service.h" -#include "retroshare/rsrtt.h" - -class p3ServiceControl; - -class RttPeerInfo -{ - public: - RttPeerInfo() - : mCurrentPingTS(0.0),mCurrentPingCounter(0.0),mCurrentPongRecvd(false),mCurrentMeanOffset(0.0),mLostPongs(0),mSentPings(0){} - - bool initialisePeerInfo(const RsPeerId& id); - - RsPeerId mId; - double mCurrentPingTS; - double mCurrentPingCounter; - bool mCurrentPongRecvd; - double mCurrentMeanOffset; - - uint32_t mLostPongs; - uint32_t mSentPings; - - std::list mPongResults; -}; - - -//!The RS Rtt Test service. - /** - * - * Used to test Latency. - */ - -class p3rtt: public RsRtt, public p3FastService -{ - public: - p3rtt(p3ServiceControl *sc); -virtual RsServiceInfo getServiceInfo(); - - /***** overloaded from rsRtt *****/ - -virtual uint32_t getPongResults(const RsPeerId& id, int n, std::list &results); -virtual double getMeanOffset(const RsPeerId &id); - - /***** overloaded from p3Service *****/ - - virtual int tick(); - virtual int status(); - - int sendPackets(); - void sendPingMeasurements(); - -virtual bool recvItem(RsItem *item); // Overloaded from p3FastService. - - int handlePing(RsItem *item); - int handlePong(RsItem *item); - - int storePingAttempt(const RsPeerId& id, double ts, uint32_t mCounter); - int storePongResult(const RsPeerId& id, uint32_t counter, double recv_ts, double rtt, double offset); - - - /*! - * This retrieves all public chat msg items - */ - //bool getPublicChatQueue(std::list &chats); - - /*************** pqiMonitor callback ***********************/ - //virtual void statusChange(const std::list &plist); - - - /************* from p3Config *******************/ - //virtual RsSerialiser *setupSerialiser() ; - //virtual bool saveList(bool& cleanup, std::list&) ; - //virtual void saveDone(); - //virtual bool loadList(std::list& load) ; - - private: - RsMutex mRttMtx; - - RttPeerInfo *locked_GetPeerInfo(const RsPeerId& id); - - std::map mPeerInfo; - rstime_t mSentPingTime; - uint32_t mCounter; - - p3ServiceControl *mServiceCtrl; - -}; - -#endif // SERVICE_RSRTT_HEADER - diff --git a/libretroshare/src/services/p3service.cc b/libretroshare/src/services/p3service.cc deleted file mode 100644 index 54ba176ef..000000000 --- a/libretroshare/src/services/p3service.cc +++ /dev/null @@ -1,223 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3service.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2013 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "rsitems/itempriorities.h" - -#include "pqi/pqi.h" -#include "util/rsstring.h" -#include "services/p3service.h" -#include - -#ifdef WINDOWS_SYS -#include "util/rstime.h" -#endif - -/***** - * #define SERV_DEBUG 1 - ****/ - - - -RsItem *p3Service::recvItem() -{ - RsStackMutex stack(srvMtx); /***** LOCK MUTEX *****/ - - if (recv_queue.empty()) - { - return NULL; /* nothing there! */ - } - - /* get something off front */ - RsItem *item = recv_queue.front(); - recv_queue.pop_front(); - - return item; -} - - -bool p3Service::receivedItems() -{ - RsStackMutex stack(srvMtx); /***** LOCK MUTEX *****/ - - return (!recv_queue.empty()); -} - - -bool p3Service::recvItem(RsItem *item) -{ - if (item) - { - RsStackMutex stack(srvMtx); /***** LOCK MUTEX *****/ - - recv_queue.push_back(item); - } - return true; -} - - - - - -void p3FastService::addSerialType(RsSerialType *st) -{ - rsSerialiser->addSerialType(st); -} - - - // overloaded pqiService interface. -bool p3FastService::recv(RsRawItem *raw) -{ - RsItem *item = NULL; - { - RsStackMutex stack(srvMtx); /***** LOCK MUTEX *****/ - - #ifdef SERV_DEBUG - std::cerr << "p3Service::recv()"; - std::cerr << std::endl; - #endif - - /* convert to RsServiceItem */ - uint32_t size = raw->getRawLength(); - item = rsSerialiser->deserialise(raw->getRawData(), &size); - if ((!item) || (size != raw->getRawLength())) - { - /* error in conversion */ - #ifdef SERV_DEBUG - std::cerr << "p3Service::recv() Error" << std::endl; - std::cerr << "p3Service::recv() Size: " << size << std::endl; - std::cerr << "p3Service::recv() RawLength: " << raw->getRawLength() << std::endl; - #endif - - if (item) - { - #ifdef SERV_DEBUG - std::cerr << "p3Service::recv() Bad Item:"; - std::cerr << std::endl; - item->print(std::cerr, 0); - std::cerr << std::endl; - #endif - delete item; - item=NULL ; - } - } - } - - /* if we have something - pass it on */ - if (item) - { -#ifdef SERV_DEBUG - std::cerr << "p3Service::recv() item:"; - std::cerr << std::endl; - item->print(std::cerr, 0); - std::cerr << std::endl; -#endif - - /* ensure PeerId is transferred */ - item->PeerId(raw->PeerId()); - recvItem(item); - } - - /* cleanup input */ - delete raw; - return (item != NULL); -} - - - -int p3FastService::sendItem(RsItem *si) -{ - RsStackMutex stack(srvMtx); /***** LOCK MUTEX *****/ - -#ifdef SERV_DEBUG - std::cerr << "p3Service::sendItem() Sending item:"; - std::cerr << std::endl; - si->print(std::cerr, 0); - std::cerr << std::endl; -#endif - - /* try to convert */ - uint32_t size = rsSerialiser->size(si); - if (!size) - { - std::cerr << "p3Service::send() ERROR size == 0"; - std::cerr << std::endl; - - /* can't convert! */ - delete si; - return 0; - } - - RsRawItem *raw = new RsRawItem(si->PacketId(), size); - if (!rsSerialiser->serialise(si, raw->getRawData(), &size)) - { - std::cerr << "p3Service::send() ERROR serialise failed"; - std::cerr << std::endl; - - delete raw; - raw = NULL; - } - - if ((raw) && (size != raw->getRawLength())) - { - std::cerr << "p3Service::send() ERROR serialise size mismatch"; - std::cerr << std::endl; - - delete raw; - raw = NULL; - } - - /* ensure PeerId is transferred */ - if (raw) - { - raw->PeerId(si->PeerId()); - - if(si->priority_level() == QOS_PRIORITY_UNKNOWN) - { - std::cerr << "************************************************************" << std::endl; - std::cerr << "********** Warning: p3Service::send() ********" << std::endl; - std::cerr << "********** Warning: caught a RsItem with undefined ********" << std::endl; - std::cerr << "********** priority level. That should not ********" << std::endl; - std::cerr << "********** happen. Please fix your items! ********" << std::endl; - std::cerr << "************************************************************" << std::endl; - } - raw->setPriorityLevel(si->priority_level()) ; - -#ifdef SERV_DEBUG - std::cerr << "p3Service::send() returning RawItem."; - std::cerr << std::endl; -#endif - delete si; - - return pqiService::send(raw); - } - else - { - std::cerr << "p3service: item could not be properly serialised. Will be wasted. Item is: "<< std::endl; - si->print(std::cerr,0) ; - - /* cleanup */ - delete si; - - return 0 ; - } -} - - diff --git a/libretroshare/src/services/p3service.h b/libretroshare/src/services/p3service.h deleted file mode 100644 index a394b1094..000000000 --- a/libretroshare/src/services/p3service.h +++ /dev/null @@ -1,173 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3service.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2008 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef P3_GENERIC_SERVICE_HEADER -#define P3_GENERIC_SERVICE_HEADER - -#include "pqi/pqi.h" -#include "pqi/pqiservice.h" -#include "util/rsthreads.h" - -/* This provides easy to use extensions to the pqiservice class provided in src/pqi. - * - * We will have a number of different strains. - * - * (1) p3Service -> pqiService - * - * Basic service with serialisation handled by a RsSerialiser. - * - * (2) p3ThreadedService -> p3service. - * - * Independent thread with mutex locks for i/o Queues. - * ideal for games etc. - * - * (3) p3CacheService -> p3service + CacheSource + CacheStore. - * - * For both Cached and Messages. - */ - -std::string generateRandomServiceId(); - -//TODO : encryption and upload / download rate implementation - - -// p3FastService(uint16_t type) -// :pqiService((RsServiceInfo::RsServiceInfoUIn16ToFullServiceId(type)), - - -class p3FastService: public pqiService -{ - protected: - - p3FastService() - :pqiService(), - srvMtx("p3FastService"), rsSerialiser(NULL) - { - rsSerialiser = new RsSerialiser(); - return; - } - - public: - -virtual ~p3FastService() { delete rsSerialiser; return; } - -/*************** INTERFACE ******************************/ -int sendItem(RsItem *); -virtual int tick() { return 0; } -/*************** INTERFACE ******************************/ - - public: - // overloaded pqiService interface. -virtual bool recv(RsRawItem *); - - // called by recv(). -virtual bool recvItem(RsItem *item) = 0; - - - protected: -void addSerialType(RsSerialType *); - - RsMutex srvMtx; /* below locked by Mutex */ - - RsSerialiser *rsSerialiser; -}; - - -class p3Service: public p3FastService -{ - protected: - - p3Service() - :p3FastService() - { - return; - } - - public: - -/*************** INTERFACE ******************************/ - /* called from Thread/tick/GUI */ -//int sendItem(RsItem *); -RsItem * recvItem(); -bool receivedItems(); - -//virtual int tick() { return 0; } -/*************** INTERFACE ******************************/ - - public: - // overloaded p3FastService interface. -virtual bool recvItem(RsItem *item); - - private: - - /* below locked by srvMtx Mutex */ - std::list recv_queue; -}; - - -class nullService: public pqiService -{ - protected: - - nullService() - :pqiService() - { - return; - } - -//virtual int tick() - - public: - // overloaded NULL pqiService interface. -virtual bool recv(RsRawItem *item) - { - /* drop any items */ - delete item; - return true; - } - -virtual bool send(RsRawItem *item) - { - delete item; - return true; - } - -}; - - -class p3ThreadedService: public p3Service, public RsTickingThread -{ - protected: - - p3ThreadedService() - :p3Service() { return; } - - public: - -virtual ~p3ThreadedService() { return; } - - private: - -}; - - -#endif // P3_GENERIC_SERVICE_HEADER - diff --git a/libretroshare/src/services/p3serviceinfo.cc b/libretroshare/src/services/p3serviceinfo.cc deleted file mode 100644 index f05604021..000000000 --- a/libretroshare/src/services/p3serviceinfo.cc +++ /dev/null @@ -1,260 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3serviceinfo.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "pqi/p3linkmgr.h" -#include "pqi/p3netmgr.h" - -#include "util/rsnet.h" - -#include "services/p3serviceinfo.h" -#include "rsitems/rsbanlistitems.h" - -#include - -/**** - * #define DEBUG_INFO 1 - ****/ - -/************ IMPLEMENTATION NOTES ********************************* - * - * Send Info to peers about services we are providing. - */ - -p3ServiceInfo::p3ServiceInfo(p3ServiceControl *serviceControl) - :p3Service(), mInfoMtx("p3ServiceInfo"), - mServiceControl(serviceControl) -{ - addSerialType(new RsServiceInfoSerialiser()); -} - -const std::string SERVICE_INFO_APP_NAME = "serviceinfo"; -const uint16_t SERVICE_INFO_APP_MAJOR_VERSION = 1; -const uint16_t SERVICE_INFO_APP_MINOR_VERSION = 0; -const uint16_t SERVICE_INFO_MIN_MAJOR_VERSION = 1; -const uint16_t SERVICE_INFO_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3ServiceInfo::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_SERVICEINFO, - SERVICE_INFO_APP_NAME, - SERVICE_INFO_APP_MAJOR_VERSION, - SERVICE_INFO_APP_MINOR_VERSION, - SERVICE_INFO_MIN_MAJOR_VERSION, - SERVICE_INFO_MIN_MINOR_VERSION); -} - - - -int p3ServiceInfo::tick() -{ - processIncoming(); - sendPackets(); - return 0; -} - -int p3ServiceInfo::status() -{ - return 1; -} - - -/***** Implementation ******/ - -bool p3ServiceInfo::processIncoming() -{ - /* for each packet - pass to specific handler */ - RsItem *item = NULL; - while(NULL != (item = recvItem())) - { -#ifdef DEBUG_INFO - std::cerr << "p3ServiceInfo::processingIncoming() Received Item:"; - std::cerr << std::endl; - item->print(std::cerr); - std::cerr << std::endl; -#endif - switch(item->PacketSubType()) - { - default: - break; - case RS_PKT_SUBTYPE_SERVICELIST_ITEM: - { - // Order is important!. - RsServiceInfoListItem *listItem = dynamic_cast(item); - if (listItem) - { - recvServiceInfoList(listItem); - } - else - { - // error. - std::cerr << "p3ServiceInfo::processingIncoming() Error with Received Item:"; - std::cerr << std::endl; - item->print(std::cerr); - std::cerr << std::endl; - } - } - break; - } - - /* clean up */ - delete item; - } - return true ; -} - - -bool convertServiceInfoToItem( - const RsPeerServiceInfo &info, - RsServiceInfoListItem *item) -{ - item->mServiceInfo = info.mServiceList; - item->PeerId(info.mPeerId); - return true; -} - -bool convertServiceItemToInfo( - const RsServiceInfoListItem *item, - RsPeerServiceInfo &info) -{ - info.mServiceList = item->mServiceInfo; - info.mPeerId = item->PeerId(); - return true; -} - - -bool p3ServiceInfo::recvServiceInfoList(RsServiceInfoListItem *item) -{ - RsPeerId peerId = item->PeerId(); - -#ifdef DEBUG_INFO - std::cerr << "p3ServiceInfo::recvServiceInfoList() from: " << peerId.toStdString(); - std::cerr << std::endl; -#endif - - RsPeerServiceInfo info; - if (convertServiceItemToInfo(item, info)) - { - -#ifdef DEBUG_INFO - std::cerr << "p3ServiceInfo::recvServiceInfoList() Info: "; - std::cerr << std::endl; - std::cerr << info; - std::cerr << std::endl; -#endif - - /* update service control */ - mServiceControl->updateServicesProvided(peerId, info); - return true; - } - return false; -} - - -bool p3ServiceInfo::sendPackets() -{ - std::set updateSet; - - { - RsStackMutex stack(mInfoMtx); /****** LOCKED MUTEX *******/ - updateSet = mPeersToUpdate; - mPeersToUpdate.clear(); - } - - mServiceControl->getServiceChanges(updateSet); - - RsStackMutex stack(mInfoMtx); /****** LOCKED MUTEX *******/ - std::set::iterator it; - for(it = updateSet.begin(); it != updateSet.end(); ++it) - { - sendServiceInfoList(*it); - } - - return (!updateSet.empty()); -} - - -int p3ServiceInfo::sendServiceInfoList(const RsPeerId &peerId) -{ -#ifdef DEBUG_INFO - std::cerr << "p3ServiceInfo::sendServiceInfoList() to " << peerId.toStdString(); - std::cerr << std::endl; -#endif - - RsServiceInfoListItem *item = new RsServiceInfoListItem(); - - RsPeerServiceInfo info; - bool sent = false; - if (mServiceControl->getServicesAllowed(peerId, info)) - { -#ifdef DEBUG_INFO - std::cerr << "p3ServiceInfo::sendServiceInfoList() Info: "; - std::cerr << std::endl; - std::cerr << info; - std::cerr << std::endl; -#endif - - if (convertServiceInfoToItem(info, item)) - { - item->PeerId(peerId); - - sent = true; - sendItem(item); - } - } - - if (!sent) - { - delete item; - } - - return sent; -} - -void p3ServiceInfo::statusChange(const std::list &plist) -{ -#ifdef DEBUG_INFO - std::cerr << "p3ServiceInfo::statusChange()"; - std::cerr << std::endl; -#endif - - std::list::const_iterator it; - for (it = plist.begin(); it != plist.end(); ++it) - { - if (it->state & RS_PEER_S_FRIEND) - { - if (it->actions & RS_PEER_CONNECTED) - { -#ifdef DEBUG_INFO - std::cerr << "p3ServiceInfo::statusChange()"; - std::cerr << "Peer: " << it->id; - std::cerr << " Connected"; - std::cerr << std::endl; -#endif - - RsStackMutex stack(mInfoMtx); /****** LOCKED MUTEX *******/ - mPeersToUpdate.insert(it->id); - } - } - } -} - - - diff --git a/libretroshare/src/services/p3serviceinfo.h b/libretroshare/src/services/p3serviceinfo.h deleted file mode 100644 index 2d8f8a8af..000000000 --- a/libretroshare/src/services/p3serviceinfo.h +++ /dev/null @@ -1,70 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3serviceinfo.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2014 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef SERVICE_RSSERVICEINFO_HEADER -#define SERVICE_RSSERVICEINFO_HEADER - -#include -#include -#include - -#include "pqi/p3servicecontrol.h" -#include "pqi/pqimonitor.h" - -#include "services/p3service.h" - -#include "rsitems/rsserviceinfoitems.h" - -//!The ServiceInfo service. - /** - * - * Exchange list of Available Services with peers. - */ - -class p3ServiceInfo: public p3Service, public pqiMonitor -{ - public: - p3ServiceInfo(p3ServiceControl *serviceControl); - virtual RsServiceInfo getServiceInfo(); - - virtual int tick(); - virtual int status(); - - /*************** pqiMonitor callback ***********************/ - virtual void statusChange(const std::list &plist); - - private: - - bool sendPackets(); - bool processIncoming(); - - bool recvServiceInfoList(RsServiceInfoListItem *item); - int sendServiceInfoList(const RsPeerId &peerid); - - private: - RsMutex mInfoMtx; - - std::set mPeersToUpdate; - p3ServiceControl *mServiceControl; -}; - -#endif // SERVICE_RSSERVICEINFO_HEADER - diff --git a/libretroshare/src/services/p3statusservice.cc b/libretroshare/src/services/p3statusservice.cc deleted file mode 100644 index f3f44cf9b..000000000 --- a/libretroshare/src/services/p3statusservice.cc +++ /dev/null @@ -1,416 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3statusservice.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Vinny Do, Chris Evi-Parker. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "services/p3statusservice.h" -#include "rsitems/rsstatusitems.h" -#include "rsserver/p3face.h" -#include "retroshare/rsiface.h" - -#include -#include -#include -#include -#include "util/rstime.h" - -#include "pqi/p3linkmgr.h" - -std::ostream& operator<<(std::ostream& out, const StatusInfo& si) -{ - out << "StatusInfo: " << std::endl; - out << "id: " << si.id << std::endl; - out << "status: " << si.status << std::endl; - out << "time_stamp: " << si.time_stamp << std::endl; - return out; -} - -RsStatus *rsStatus = NULL; - -p3StatusService::p3StatusService(p3ServiceControl *sc) - :p3Service(), p3Config(), mServiceCtrl(sc), mStatusMtx("p3StatusService") -{ - addSerialType(new RsStatusSerialiser()); - -} - -p3StatusService::~p3StatusService() -{ -} - - -const std::string STATUS_APP_NAME = "status"; -const uint16_t STATUS_APP_MAJOR_VERSION = 1; -const uint16_t STATUS_APP_MINOR_VERSION = 0; -const uint16_t STATUS_MIN_MAJOR_VERSION = 1; -const uint16_t STATUS_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3StatusService::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_STATUS, - STATUS_APP_NAME, - STATUS_APP_MAJOR_VERSION, - STATUS_APP_MINOR_VERSION, - STATUS_MIN_MAJOR_VERSION, - STATUS_MIN_MINOR_VERSION); -} - - -bool p3StatusService::getOwnStatus(StatusInfo& statusInfo) -{ -#ifdef STATUS_DEBUG - std::cerr << "p3StatusService::getOwnStatus() " << std::endl; -#endif - - std::map::iterator it; - const RsPeerId& ownId = mServiceCtrl->getOwnId(); - - RsStackMutex stack(mStatusMtx); - it = mStatusInfoMap.find(ownId); - - if (it == mStatusInfoMap.end()){ - std::cerr << "p3StatusService::saveList() :" << "Did not find your status" << ownId << std::endl; - - // own status not set, set it to online - statusInfo.id = ownId; - statusInfo.status = RS_STATUS_ONLINE; - - std::pair pr(ownId, statusInfo); - mStatusInfoMap.insert(pr); - IndicateConfigChanged(); - - return true; - } - - statusInfo = it->second; - - return true; -} - -bool p3StatusService::getStatusList(std::list& statusInfo) -{ -#ifdef STATUS_DEBUG - std::cerr << "p3StatusService::getStatusList() " << std::endl; -#endif - - statusInfo.clear(); - - RsStackMutex stack(mStatusMtx); - - // fill up statusInfo list with this information - std::map::iterator mit; - for(mit = mStatusInfoMap.begin(); mit != mStatusInfoMap.end(); ++mit){ - statusInfo.push_back(mit->second); - } - - return true; -} - -bool p3StatusService::getStatus(const RsPeerId &id, StatusInfo &statusInfo) -{ -#ifdef STATUS_DEBUG - std::cerr << "p3StatusService::getStatus() " << std::endl; -#endif - - RsStackMutex stack(mStatusMtx); - - std::map::iterator mit = mStatusInfoMap.find(id); - - if (mit == mStatusInfoMap.end()) { - /* return fake status info as offline */ - statusInfo = StatusInfo(); - - statusInfo.id = id; - statusInfo.status = RS_STATUS_OFFLINE; - return false; - } - - statusInfo = mit->second; - - return true; -} - -/* id = "", status is sent to all online peers */ -bool p3StatusService::sendStatus(const RsPeerId &id, uint32_t status) -{ - StatusInfo statusInfo; - std::set onlineList; - - { - RsStackMutex stack(mStatusMtx); - - statusInfo.id = mServiceCtrl->getOwnId(); - statusInfo.status = status; - - // don't save inactive status - if(statusInfo.status != RS_STATUS_INACTIVE){ - - // If your id is not set, set it - if(mStatusInfoMap.find(statusInfo.id) == mStatusInfoMap.end()){ - - std::pair pr(statusInfo.id, statusInfo); - mStatusInfoMap.insert(pr); - IndicateConfigChanged(); - } else if(mStatusInfoMap[statusInfo.id].status != statusInfo.status){ - - IndicateConfigChanged(); - mStatusInfoMap[statusInfo.id] = statusInfo; - } - } - - if (id.isNull()) { - mServiceCtrl->getPeersConnected(getServiceInfo().mServiceType, onlineList); - } else { - onlineList.insert(id); - } - } - - std::set::iterator it; - -#ifdef STATUS_DEBUG - std::cerr << "p3StatusService::sendStatus() " << std::endl; - std::cerr << statusInfo; -#endif - - // send to all peers online - for(it = onlineList.begin(); it != onlineList.end(); ++it){ - RsStatusItem* statusItem = new RsStatusItem(); - statusItem->sendTime = time(NULL); - statusItem->status = statusInfo.status; - statusItem->PeerId(*it); - sendItem(statusItem); - } - - /* send notify of own status change */ - RsServer::notify()->notifyPeerStatusChanged(statusInfo.id.toStdString(), statusInfo.status); - - return true; -} - -/******************************/ - -void p3StatusService::receiveStatusQueue() -{ - std::map changed; - - { - RsStackMutex stack(mStatusMtx); - - RsItem* item; - - while(NULL != (item = recvItem())){ - - RsStatusItem* status_item = dynamic_cast(item); - - if(status_item == NULL) { - std::cerr << "p3Status::getStatusQueue() " << "Failed to cast Item \n" << std::endl; - delete (item); - continue; - } - -#ifdef STATUS_DEBUG - std::cerr << "p3StatusService::getStatusQueue()" << std::endl; - std::cerr << "PeerId : " << status_item->PeerId() << std::endl; - std::cerr << "Status: " << status_item->status << std::endl; - std::cerr << "Got status Item" << std::endl; -#endif - - std::map::iterator mit = mStatusInfoMap.find(status_item->PeerId()); - - if(mit != mStatusInfoMap.end()){ - mit->second.id = status_item->PeerId(); - - if (mit->second.status != status_item->status) { - changed [mit->second.id] = status_item->status; - } - - mit->second.status = status_item->status; - mit->second.time_stamp = status_item->sendTime; -#ifdef STATUS_DEBUG - } else { - std::cerr << "getStatus() " << "Could not find Peer" << status_item->PeerId(); - std::cerr << std::endl; -#endif - } - - delete (status_item); - } - - } /* UNLOCKED */ - - if (changed.size()) { - std::map::iterator it; - for (it = changed.begin(); it != changed.end(); ++it) { - RsServer::notify()->notifyPeerStatusChanged(it->first.toStdString(), it->second); - } - RsServer::notify()->notifyPeerStatusChangedSummary(); - } -} - -/* p3Config */ - -RsSerialiser* p3StatusService::setupSerialiser(){ - - RsSerialiser *rss = new RsSerialiser; - rss->addSerialType(new RsStatusSerialiser); - - return rss; -} - -bool p3StatusService::saveList(bool& cleanup, std::list& ilist){ - - // save your status before quiting - cleanup = true; - RsStatusItem* own_status = new RsStatusItem; - StatusInfo own_info; - - std::map::iterator it; - - { - RsStackMutex stack(mStatusMtx); - it = mStatusInfoMap.find(mServiceCtrl->getOwnId()); - - if(it == mStatusInfoMap.end()){ - std::cerr << "p3StatusService::saveList() :" << "Did not find your status" - << mServiceCtrl->getOwnId() << std::endl; - delete own_status; - return false; - } - - own_info = it->second; - } - - own_status->PeerId(own_info.id); - own_status->sendTime = own_info.time_stamp; - own_status->status = own_info.status; - - ilist.push_back(own_status); - - return true; -} - -bool p3StatusService::loadList(std::list& load) -{ - // load your status from last rs session - StatusInfo own_info; - - - for(std::list::const_iterator it = load.begin() ; it != load.end(); ++it) - { - RsStatusItem* own_status = dynamic_cast(*it); - - if(own_status != NULL) - { - own_info.id = mServiceCtrl->getOwnId(); - own_info.status = own_status->status; - own_info.time_stamp = own_status->sendTime; - - { - RsStackMutex stack(mStatusMtx); - std::pair pr(mServiceCtrl->getOwnId(), own_info); - mStatusInfoMap.insert(pr); - } - - } - - delete *it ; - } - load.clear() ; - return false; -} - - -int p3StatusService::tick() -{ - if (receivedItems()) { - receiveStatusQueue(); - } - - return 0; -} - -int p3StatusService::status(){ - return 1; -} - -/*************** pqiMonitor callback ***********************/ - -void p3StatusService::statusChange(const std::list &plist) -{ - bool changedState = false; - - StatusInfo statusInfo; - std::list::const_iterator it; - for (it = plist.begin(); it != plist.end(); ++it) - { - if (it->actions & RS_SERVICE_PEER_DISCONNECTED) - { - { - RsStackMutex stack(mStatusMtx); - /* remove peer from status map */ - mStatusInfoMap.erase(it->id); - } /* UNLOCKED */ - - changedState = true; - RsServer::notify()->notifyPeerStatusChanged(it->id.toStdString(), RS_STATUS_OFFLINE); - } - - if (it->actions & RS_SERVICE_PEER_CONNECTED) - { - /* send current status, only call getOwnStatus once in the loop */ - if (statusInfo.id.isNull() == false || getOwnStatus(statusInfo)) - { - sendStatus(it->id, statusInfo.status); - } - - { - RsStackMutex stack(mStatusMtx); - - /* We assume that the peer is online. If not, he send us a new status */ - StatusInfo info; - info.id = it->id; - info.status = RS_STATUS_ONLINE; - info.time_stamp = time(NULL); - - mStatusInfoMap[it->id] = info; - } /* UNLOCKED */ - - changedState = true; - RsServer::notify()->notifyPeerStatusChanged(it->id.toStdString(), RS_STATUS_ONLINE); - } - - if (it->actions & RS_SERVICE_PEER_REMOVED) - { - /* now handle remove */ - { - RsStackMutex stack(mStatusMtx); - /* remove peer from status map */ - mStatusInfoMap.erase(it->id); - } /* UNLOCKED */ - - changedState = true; - RsServer::notify()->notifyPeerStatusChanged(it->id.toStdString(), RS_STATUS_OFFLINE); - } - } - - if (changedState) - { - RsServer::notify()->notifyPeerStatusChangedSummary(); - } -} diff --git a/libretroshare/src/services/p3statusservice.h b/libretroshare/src/services/p3statusservice.h deleted file mode 100644 index ac0b70653..000000000 --- a/libretroshare/src/services/p3statusservice.h +++ /dev/null @@ -1,102 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3statusservice.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008 by Vinny Do, Chris Evi-Parker. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_P3_STATUS_INTERFACE_H -#define RS_P3_STATUS_INTERFACE_H - -#include -#include - -#include "rsitems/rsstatusitems.h" -#include "retroshare/rsstatus.h" -#include "services/p3service.h" -#include "pqi/p3cfgmgr.h" -#include "pqi/pqiservicemonitor.h" - -class p3ServiceControl; - -//! handles standard status messages (busy, away, online, offline) set by user -/*! - * The is a retroshare service which allows peers - * to inform each other about their status in a standard way, as opposed to - * custom string. - * @see rsiface/rsstatus.h for status constants - */ -class p3StatusService: public p3Service, public p3Config, public pqiServiceMonitor -{ - public: - - p3StatusService(p3ServiceControl *sc); -virtual ~p3StatusService(); - -virtual RsServiceInfo getServiceInfo(); - -/***** overloaded from p3Service *****/ -virtual int tick(); -virtual int status(); - -/*************** pqiMonitor callback ***********************/ -virtual void statusChange(const std::list &plist); - -/********* RsStatus ***********/ - -/** - * Status is set to offline as default if no info received from relevant peer - */ -virtual bool getOwnStatus(StatusInfo& statusInfo); -virtual bool getStatusList(std::list& statusInfo); -virtual bool getStatus(const RsPeerId &id, StatusInfo &statusInfo); -/* id = "", status is sent to all online peers */ -virtual bool sendStatus(const RsPeerId &id, uint32_t status); - -/******************************/ - - -/** implemented from p3Config **/ - -/*! - * @return The serialiser the enables storage of save info - */ -virtual RsSerialiser *setupSerialiser(); - -/*! - * This stores information on what your status was before you exited rs - */ -virtual bool saveList(bool& cleanup, std::list&); - -/*! - * @param load Should contain a single item which is clients status from last rs session - */ -virtual bool loadList(std::list& load); - - private: - -virtual void receiveStatusQueue(); - -p3ServiceControl *mServiceCtrl; - -std::map mStatusInfoMap; - -RsMutex mStatusMtx; - -}; - -#endif diff --git a/libretroshare/src/services/p3wiki.cc b/libretroshare/src/services/p3wiki.cc deleted file mode 100644 index c1b8f86e1..000000000 --- a/libretroshare/src/services/p3wiki.cc +++ /dev/null @@ -1,798 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3wiki.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "services/p3wiki.h" -#include "retroshare/rsgxsflags.h" -#include "rsitems/rswikiitems.h" - -#include "util/rsrandom.h" - -/**** - * #define WIKI_DEBUG 1 - ****/ - -RsWiki *rsWiki = NULL; - - -#define WIKI_EVENT_DUMMYTICK 0x0001 -#define WIKI_EVENT_DUMMYSTART 0x0002 - -#define DUMMYSTART_PERIOD 60 // some time for dummyIds to be generated. -#define DUMMYTICK_PERIOD 3 - -p3Wiki::p3Wiki(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs *gixs) - :RsGenExchange(gds, nes, new RsGxsWikiSerialiser(), RS_SERVICE_GXS_TYPE_WIKI, gixs, wikiAuthenPolicy()), - RsWiki(static_cast(*this)) -{ - // Setup of dummy Pages. - mAboutActive = false; - mImprovActive = false; - mMarkdownActive = false; - - // TestData disabled in Repo. - //RsTickEvent::schedule_in(WIKI_EVENT_DUMMYSTART, DUMMYSTART_PERIOD); - -} - - -const std::string GXS_WIKI_APP_NAME = "gxswiki"; -const uint16_t GXS_WIKI_APP_MAJOR_VERSION = 1; -const uint16_t GXS_WIKI_APP_MINOR_VERSION = 0; -const uint16_t GXS_WIKI_MIN_MAJOR_VERSION = 1; -const uint16_t GXS_WIKI_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3Wiki::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_GXS_TYPE_WIKI, - GXS_WIKI_APP_NAME, - GXS_WIKI_APP_MAJOR_VERSION, - GXS_WIKI_APP_MINOR_VERSION, - GXS_WIKI_MIN_MAJOR_VERSION, - GXS_WIKI_MIN_MINOR_VERSION); -} - - -uint32_t p3Wiki::wikiAuthenPolicy() -{ - uint32_t policy = 0; - uint8_t flag = 0; - - // Edits generally need an authors signature. - - flag = GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS); - - flag |= GXS_SERV::MSG_AUTHEN_CHILD_PUBLISH_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS); - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS); - - flag = 0; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::GRP_OPTION_BITS); - - return policy; -} - - -void p3Wiki::service_tick() -{ - RsTickEvent::tick_events(); - return; -} - - -void p3Wiki::notifyChanges(std::vector& changes) -{ - std::cerr << "p3Wiki::notifyChanges() New stuff"; - std::cerr << std::endl; -} - - /* Specific Service Data */ -bool p3Wiki::getCollections(const uint32_t &token, std::vector &collections) -{ - std::cerr << "p3Wiki::getCollections()"; - std::cerr << std::endl; - - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); ++vit) - { - RsGxsWikiCollectionItem* item = dynamic_cast(*vit); - - if (item) - { - RsWikiCollection collection = item->collection; - collection.mMeta = item->meta; - delete item; - collections.push_back(collection); - - std::cerr << "p3Wiki::getCollections() Adding Collection to Vector: "; - std::cerr << std::endl; - std::cerr << collection; - std::cerr << std::endl; - } - else - { - std::cerr << "Not a WikiCollectionItem, deleting!" << std::endl; - delete *vit; - } - - } - } - return ok; -} - - -bool p3Wiki::getSnapshots(const uint32_t &token, std::vector &snapshots) -{ - GxsMsgDataMap msgData; - bool ok = RsGenExchange::getMsgData(token, msgData); - - if(ok) - { - GxsMsgDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - RsGxsGroupId grpId = mit->first; - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsWikiSnapshotItem* item = dynamic_cast(*vit); - - if(item) - { - RsWikiSnapshot snapshot = item->snapshot; - snapshot.mMeta = item->meta; - snapshots.push_back(snapshot); - delete item; - } - else - { - std::cerr << "Not a WikiSnapshot Item, deleting!" << std::endl; - delete *vit; - } - } - } - } - - return ok; -} - - -bool p3Wiki::getRelatedSnapshots(const uint32_t &token, std::vector &snapshots) -{ - GxsMsgRelatedDataMap msgData; - bool ok = RsGenExchange::getMsgRelatedData(token, msgData); - - if(ok) - { - GxsMsgRelatedDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsWikiSnapshotItem* item = dynamic_cast(*vit); - - if(item) - { - RsWikiSnapshot snapshot = item->snapshot; - snapshot.mMeta = item->meta; - snapshots.push_back(snapshot); - delete item; - } - else - { - std::cerr << "Not a WikiSnapshot Item, deleting!" << std::endl; - delete *vit; - } - } - } - } - - return ok; -} - - -bool p3Wiki::getComments(const uint32_t &token, std::vector &comments) -{ - GxsMsgDataMap msgData; - bool ok = RsGenExchange::getMsgData(token, msgData); - - if(ok) - { - GxsMsgDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - RsGxsGroupId grpId = mit->first; - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); vit++) - { - RsGxsWikiCommentItem* item = dynamic_cast(*vit); - - if(item) - { - RsWikiComment comment = item->comment; - comment.mMeta = item->meta; - comments.push_back(comment); - delete item; - } - else - { - std::cerr << "Not a WikiComment Item, deleting!" << std::endl; - delete *vit; - } - } - } - } - - return ok; - return false; -} - - - -bool p3Wiki::submitCollection(uint32_t &token, RsWikiCollection &collection) -{ - RsGxsWikiCollectionItem* collectionItem = new RsGxsWikiCollectionItem(); - collectionItem->collection = collection; - collectionItem->meta = collection.mMeta; - - std::cerr << "p3Wiki::submitCollection(): "; - std::cerr << std::endl; - std::cerr << collection; - std::cerr << std::endl; - - std::cerr << "p3Wiki::submitCollection() pushing to RsGenExchange"; - std::cerr << std::endl; - - RsGenExchange::publishGroup(token, collectionItem); - return true; -} - - -bool p3Wiki::submitSnapshot(uint32_t &token, RsWikiSnapshot &snapshot) -{ - std::cerr << "p3Wiki::submitSnapshot(): " << snapshot; - std::cerr << std::endl; - - RsGxsWikiSnapshotItem* snapshotItem = new RsGxsWikiSnapshotItem(); - snapshotItem->snapshot = snapshot; - snapshotItem->meta = snapshot.mMeta; - snapshotItem->meta.mMsgFlags = FLAG_MSG_TYPE_WIKI_SNAPSHOT; - - RsGenExchange::publishMsg(token, snapshotItem); - return true; -} - - -bool p3Wiki::submitComment(uint32_t &token, RsWikiComment &comment) -{ - std::cerr << "p3Wiki::submitComment(): " << comment; - std::cerr << std::endl; - - RsGxsWikiCommentItem* commentItem = new RsGxsWikiCommentItem(); - commentItem->comment = comment; - commentItem->meta = comment.mMeta; - commentItem->meta.mMsgFlags = FLAG_MSG_TYPE_WIKI_COMMENT; - - RsGenExchange::publishMsg(token, commentItem); - return true; -} - -bool p3Wiki::updateCollection(uint32_t &token, RsWikiCollection &group) -{ - std::cerr << "p3Wiki::updateCollection()" << std::endl; - - RsGxsWikiCollectionItem* grpItem = new RsGxsWikiCollectionItem(); - grpItem->collection = group; - grpItem->meta = group.mMeta; - - RsGenExchange::updateGroup(token, grpItem); - return true; -} - -// Blocking Interfaces. -bool p3Wiki::createCollection(RsWikiCollection &group) -{ - uint32_t token; - return submitCollection(token, group) && waitToken(token) == RsTokenService::COMPLETE; -} - -bool p3Wiki::updateCollection(const RsWikiCollection &group) -{ - uint32_t token; - RsWikiCollection update(group); - return updateCollection(token, update) && waitToken(token) == RsTokenService::COMPLETE; -} - -bool p3Wiki::getCollections(const std::list groupIds, std::vector &groups) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - - if (groupIds.empty()) - { - if (!requestGroupInfo(token, opts) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - } - else - { - if (!requestGroupInfo(token, opts, groupIds) || waitToken(token) != RsTokenService::COMPLETE ) - return false; - } - return getCollections(token, groups) && !groups.empty(); -} - -std::ostream &operator<<(std::ostream &out, const RsWikiCollection &group) -{ - out << "RsWikiCollection [ "; - out << " Name: " << group.mMeta.mGroupName; - out << " Desc: " << group.mDescription; - out << " Category: " << group.mCategory; - out << " ]"; - return out; -} - -std::ostream &operator<<(std::ostream &out, const RsWikiSnapshot &shot) -{ - out << "RsWikiSnapshot [ "; - out << "Title: " << shot.mMeta.mMsgName; - out << "]"; - return out; -} - -std::ostream &operator<<(std::ostream &out, const RsWikiComment &comment) -{ - out << "RsWikiComment [ "; - out << "Title: " << comment.mMeta.mMsgName; - out << "]"; - return out; -} - - -/***** FOR TESTING *****/ - -const int about_len = 10; -const std::string about_txt[] = - { "Welcome to RsWiki, a fully distributed Wiki system that anyone can edit.", - "Please read through these dummy Wiki pages to learn how it should work\n", - "Basic Functionality:", - " - New Group: creates a collection of Wiki Pages, the creator of group", - " and anyone they share the publish keys with) is the moderator\n", - " - New Page: Create a new Wiki Page, only Group Moderators can do this\n", - " - Edit: Anyone Can Edit the Wiki Page, and the changes form a tree under the original\n", - " - RePublish: This is used by the Moderators to accept and reject Edits.", - " the republished page becomes a new version of the Root Page, allowing more edits to be done\n", - "Please read the improvements section to see how we envision the wiki's working", - }; - - -const int improvements_len = 14; -const std::string improvements_txt[] = - { "As you can see, the current Wiki is a basic framework waiting to be expanded.", - "There are lots of potential improvements... some of my ideas are listed below\n", - "Ideas:", - " - Formatting: No HTML, lets use Markdown or something similar.\n", - " - Diffs, lots of edits will lead to complex merges - a robust merge tool is essential\n", - " - Read Mode... hide all the Edits, and only show the most recently published versions\n", - " - Easy Duplication - to take over an Abandoned or badly moderated Wiki. Copies All base versions to a new group\n", - " - WikiLinks. A generic Wiki Cross Linking system. This should be combined with Easy Duplication option,", - " to allow easy replacement of groups if necessary... A good design here is critical to a successful Wiki ecosystem\n", - " - work out how to include media (photos, audio, video, etc) without embedding in pages", - " this would leverage the turtle transfer system somehow - maybe like channels.\n", - " - Comments, reviews etc can be incorporated - ideas here are welcome.\n", - " - Any other suggestion???", - " - Come on more ideas!" - }; - - -const int markdown_len = 34; -const std::string markdown_txt[] = { - "# An Example of Markdown Editing.", - "", - "Markdown is quite simple to use, and allows simple HTML.", - "", - "## Some Blocks below an H2 heading.", - "", - " * Firstly, we can put a link [in here][]", - " * Secondly, as you can see we're in a list.", - " * Thirdly, I don't know.", - "", - "### A Sub (H3) heading.", - "", - "#### If we want to get into the very small details. (H6).", - "", - " A bit of code.", - " This is a lit", - " foreach(in loop)", - " a++", - " Double quoted stuff.", - "", - "Or it can be indented like this:", - "", - "> A block of indented stuff looks like this", - "> > With double indenting and ", - "> > > triple indenting possible too", - "", - "Images can be embedded, but thats somethinng to work on in the future.", - "", - "Sadly it doesn't support tables or div's or anything that complex.", - "", - "Keep it simple and help write good wiki pages, thx.", - "", - "[in here]: http://example.com/ \"Optional Title Here\"", - "" - }; - - -void p3Wiki::generateDummyData() -{ - std::cerr << "p3Wiki::generateDummyData()"; - std::cerr << std::endl; - -#define GEN_COLLECTIONS 0 - - int i; - for(i = 0; i < GEN_COLLECTIONS; i++) - { - RsWikiCollection wiki; - wiki.mMeta.mGroupId = RsGxsGroupId::random(); - wiki.mMeta.mGroupFlags = 0; - wiki.mMeta.mGroupName = RsGxsGroupId::random().toStdString(); - - uint32_t dummyToken = 0; - submitCollection(dummyToken, wiki); - } - - - RsWikiCollection wiki; - wiki.mMeta.mGroupFlags = 0; - wiki.mMeta.mGroupName = "About RsWiki"; - - submitCollection(mAboutToken, wiki); - - wiki.mMeta.mGroupFlags = 0; - wiki.mMeta.mGroupName = "RsWiki Improvements"; - - submitCollection(mImprovToken, wiki); - - wiki.mMeta.mGroupFlags = 0; - wiki.mMeta.mGroupName = "RsWiki Markdown"; - - submitCollection(mMarkdownToken, wiki); - - mAboutLines = 0; - mImprovLines = 0; - mMarkdownLines = 0; - - mAboutActive = true; - mImprovActive = true; - mMarkdownActive = true; - - RsTickEvent::schedule_in(WIKI_EVENT_DUMMYTICK, DUMMYTICK_PERIOD); -} - - -bool generateNextDummyPage(const RsGxsMessageId &threadId, const int lines, const RsGxsGrpMsgIdPair &parentId, - const std::string *page_lines, const int num_pagelines, RsWikiSnapshot &snapshot) -{ - snapshot.mMeta.mGroupId = parentId.first; - - // Create an About Page. -#define NUM_SUB_PAGES 3 - - if ((lines % NUM_SUB_PAGES == 0) || (lines == num_pagelines)) - { - /* do a new baseline */ - snapshot.mMeta.mOrigMsgId = threadId; - } - else - { - snapshot.mMeta.mParentId = parentId.second; - snapshot.mMeta.mThreadId = threadId; - } - - std::string page; - for(int i = 0; (i < lines) && (i < num_pagelines); i++) - { - snapshot.mPage += page_lines[i]; - snapshot.mPage += '\n'; - } - - return (lines <= num_pagelines); -} - - -#include - -RsGxsId chooseRandomAuthorId() -{ - /* chose a random Id to sign with */ - std::list ownIds; - std::list::iterator it; - - rsIdentity->getOwnIds(ownIds); - - uint32_t idx = (uint32_t) (RSRandom::random_u32() % (int)ownIds.size()) ; - int i = 0; - for(it = ownIds.begin(); (it != ownIds.end()) && (i < idx); ++it, i++) ; - - return *it ; -} - - - -void p3Wiki::dummyTick() -{ - if (mAboutActive) - { - std::cerr << "p3Wiki::dummyTick() AboutActive"; - std::cerr << std::endl; - - uint32_t status = RsGenExchange::getTokenService()->requestStatus(mAboutToken); - - if (status == RsTokenService::COMPLETE) - { - std::cerr << "p3Wiki::dummyTick() AboutActive, Lines: " << mAboutLines; - std::cerr << std::endl; - - if (mAboutLines == 0) - { - /* get the group Id */ - RsGxsGroupId groupId; - if (!acknowledgeTokenGrp(mAboutToken, groupId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mAboutActive = false; - } - - /* create baseline snapshot */ - RsWikiSnapshot page; - page.mMeta.mGroupId = groupId; - page.mPage = "Baseline page... a placeholder for About Wiki"; - page.mMeta.mMsgName = "About RsWiki"; - page.mMeta.mAuthorId = chooseRandomAuthorId(); - - submitSnapshot(mAboutToken, page); - mAboutLines++; - } - else - { - /* get the msg Id, and generate next snapshot */ - RsGxsGrpMsgIdPair msgId; - if (!acknowledgeTokenMsg(mAboutToken, msgId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mAboutActive = false; - } - - if (mAboutLines == 1) - { - mAboutThreadId = msgId.second; - } - - RsWikiSnapshot page; - page.mMeta.mMsgName = "About RsWiki"; - page.mMeta.mAuthorId = chooseRandomAuthorId(); - if (!generateNextDummyPage(mAboutThreadId, mAboutLines, msgId, about_txt, about_len, page)) - { - std::cerr << "About Pages Done"; - std::cerr << std::endl; - mAboutActive = false; - } - else - { - mAboutLines++; - submitSnapshot(mAboutToken, page); - } - } - } - } - - if (mImprovActive) - { - std::cerr << "p3Wiki::dummyTick() ImprovActive"; - std::cerr << std::endl; - - uint32_t status = RsGenExchange::getTokenService()->requestStatus(mImprovToken); - - if (status == RsTokenService::COMPLETE) - { - std::cerr << "p3Wiki::dummyTick() ImprovActive, Lines: " << mImprovLines; - std::cerr << std::endl; - - if (mImprovLines == 0) - { - /* get the group Id */ - RsGxsGroupId groupId; - if (!acknowledgeTokenGrp(mImprovToken, groupId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mImprovActive = false; - } - - /* create baseline snapshot */ - RsWikiSnapshot page; - page.mMeta.mGroupId = groupId; - page.mPage = "Baseline page... a placeholder for Improv Wiki"; - page.mMeta.mMsgName = "Improv RsWiki"; - page.mMeta.mAuthorId = chooseRandomAuthorId(); - - submitSnapshot(mImprovToken, page); - mImprovLines++; - } - else - { - /* get the msg Id, and generate next snapshot */ - RsGxsGrpMsgIdPair msgId; - if (!acknowledgeTokenMsg(mImprovToken, msgId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mImprovActive = false; - } - - if (mImprovLines == 1) - { - mImprovThreadId = msgId.second; - } - - RsWikiSnapshot page; - page.mMeta.mMsgName = "Improv RsWiki"; - page.mMeta.mAuthorId = chooseRandomAuthorId(); - if (!generateNextDummyPage(mImprovThreadId, mImprovLines, msgId, improvements_txt, improvements_len, page)) - { - std::cerr << "Improv Pages Done"; - std::cerr << std::endl; - mImprovActive = false; - } - else - { - mImprovLines++; - submitSnapshot(mImprovToken, page); - } - } - } - } - - - if (mMarkdownActive) - { - std::cerr << "p3Wiki::dummyTick() MarkdownActive"; - std::cerr << std::endl; - - uint32_t status = RsGenExchange::getTokenService()->requestStatus(mMarkdownToken); - - if (status == RsTokenService::COMPLETE) - { - std::cerr << "p3Wiki::dummyTick() MarkdownActive, Lines: " << mMarkdownLines; - std::cerr << std::endl; - - if (mMarkdownLines == 0) - { - /* get the group Id */ - RsGxsGroupId groupId; - if (!acknowledgeTokenGrp(mMarkdownToken, groupId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mMarkdownActive = false; - } - - /* create baseline snapshot */ - RsWikiSnapshot page; - page.mMeta.mGroupId = groupId; - page.mPage = "Baseline page... a placeholder for Markdown Wiki"; - page.mMeta.mMsgName = "Markdown RsWiki"; - page.mMeta.mAuthorId = chooseRandomAuthorId(); - - submitSnapshot(mMarkdownToken, page); - mMarkdownLines++; - } - else - { - /* get the msg Id, and generate next snapshot */ - RsGxsGrpMsgIdPair msgId; - if (!acknowledgeTokenMsg(mMarkdownToken, msgId)) - { - std::cerr << " ERROR "; - std::cerr << std::endl; - mMarkdownActive = false; - } - - if (mMarkdownLines == 1) - { - mMarkdownThreadId = msgId.second; - } - - RsWikiSnapshot page; - page.mMeta.mMsgName = "Markdown RsWiki"; - page.mMeta.mAuthorId = chooseRandomAuthorId(); - if (!generateNextDummyPage(mMarkdownThreadId, mMarkdownLines, msgId, markdown_txt, markdown_len, page)) - { - std::cerr << "Markdown Pages Done"; - std::cerr << std::endl; - mMarkdownActive = false; - } - else - { - mMarkdownLines++; - submitSnapshot(mMarkdownToken, page); - } - } - } - } - - if ((mAboutActive) || (mImprovActive) || (mMarkdownActive)) - { - /* reschedule next one */ - RsTickEvent::schedule_in(WIKI_EVENT_DUMMYTICK, DUMMYTICK_PERIOD); - } -} - - - - - - // Overloaded from RsTickEvent for Event callbacks. -void p3Wiki::handle_event(uint32_t event_type, const std::string &elabel) -{ - std::cerr << "p3Wiki::handle_event(" << event_type << ")"; - std::cerr << std::endl; - - // stuff. - switch(event_type) - { - case WIKI_EVENT_DUMMYSTART: - generateDummyData(); - break; - - case WIKI_EVENT_DUMMYTICK: - dummyTick(); - break; - - default: - /* error */ - std::cerr << "p3Wiki::handle_event() Unknown Event Type: " << event_type; - std::cerr << std::endl; - break; - } -} - - diff --git a/libretroshare/src/services/p3wiki.h b/libretroshare/src/services/p3wiki.h deleted file mode 100644 index a92aec795..000000000 --- a/libretroshare/src/services/p3wiki.h +++ /dev/null @@ -1,103 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3wiki.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef P3_WIKI_SERVICE_HEADER -#define P3_WIKI_SERVICE_HEADER - -#include "retroshare/rswiki.h" -#include "gxs/rsgenexchange.h" - -#include "util/rstickevent.h" - -#include -#include - -/* - * Wiki Service - * - * - */ - -class p3Wiki: public RsGenExchange, public RsWiki, - public RsTickEvent -{ -public: - p3Wiki(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs *gixs); -virtual RsServiceInfo getServiceInfo(); -static uint32_t wikiAuthenPolicy(); - -protected: - -virtual void notifyChanges(std::vector& changes) ; - - // Overloaded from RsTickEvent. -virtual void handle_event(uint32_t event_type, const std::string &elabel); - -public: - -virtual void service_tick(); - - /* Specific Service Data */ -virtual bool getCollections(const uint32_t &token, std::vector &collections) override; -virtual bool getSnapshots(const uint32_t &token, std::vector &snapshots) override; -virtual bool getComments(const uint32_t &token, std::vector &comments) override; - -virtual bool getRelatedSnapshots(const uint32_t &token, std::vector &snapshots) override; - -virtual bool submitCollection(uint32_t &token, RsWikiCollection &collection) override; -virtual bool submitSnapshot(uint32_t &token, RsWikiSnapshot &snapshot) override; -virtual bool submitComment(uint32_t &token, RsWikiComment &comment) override; - -virtual bool updateCollection(uint32_t &token, RsWikiCollection &collection) override; - -// Blocking Interfaces. -virtual bool createCollection(RsWikiCollection &collection) override; -virtual bool updateCollection(const RsWikiCollection &collection) override; -virtual bool getCollections(const std::list groupIds, std::vector &groups) override; - - private: - -std::string genRandomId(); -// RsMutex mWikiMtx; - - -virtual void generateDummyData(); - - // Dummy Stuff. - void dummyTick(); - - bool mAboutActive; - uint32_t mAboutToken; - int mAboutLines; - RsGxsMessageId mAboutThreadId; - - bool mImprovActive; - uint32_t mImprovToken; - int mImprovLines; - RsGxsMessageId mImprovThreadId; - - bool mMarkdownActive; - uint32_t mMarkdownToken; - int mMarkdownLines; - RsGxsMessageId mMarkdownThreadId; -}; - -#endif diff --git a/libretroshare/src/services/p3wire.cc b/libretroshare/src/services/p3wire.cc deleted file mode 100644 index 283e9a804..000000000 --- a/libretroshare/src/services/p3wire.cc +++ /dev/null @@ -1,1351 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3wire.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2020 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "services/p3wire.h" -#include "rsitems/rswireitems.h" - -#include "util/rsrandom.h" - -/**** - * #define WIRE_DEBUG 1 - ****/ - -RsWire *rsWire = NULL; - -RsWireGroup::RsWireGroup() - :mGroupPulses(0),mGroupRepublishes(0),mGroupLikes(0),mGroupReplies(0) - ,mRefMentions(0),mRefRepublishes(0),mRefLikes(0),mRefReplies(0) -{ - return; -} - -uint32_t RsWirePulse::ImageCount() -{ - uint32_t images = 0; - if (!mImage1.empty()) { - images++; - } - if (!mImage2.empty()) { - images++; - } - if (!mImage3.empty()) { - images++; - } - if (!mImage4.empty()) { - images++; - } - return images; -} - -p3Wire::p3Wire(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs *gixs) - :RsGenExchange(gds, nes, new RsGxsWireSerialiser(), RS_SERVICE_GXS_TYPE_WIRE, gixs, wireAuthenPolicy()), - RsWire(static_cast(*this)), mWireMtx("WireMtx") -{ - -} - - -const std::string WIRE_APP_NAME = "gxswire"; -const uint16_t WIRE_APP_MAJOR_VERSION = 1; -const uint16_t WIRE_APP_MINOR_VERSION = 0; -const uint16_t WIRE_MIN_MAJOR_VERSION = 1; -const uint16_t WIRE_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3Wire::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_GXS_TYPE_WIRE, - WIRE_APP_NAME, - WIRE_APP_MAJOR_VERSION, - WIRE_APP_MINOR_VERSION, - WIRE_MIN_MAJOR_VERSION, - WIRE_MIN_MINOR_VERSION); -} - - - -uint32_t p3Wire::wireAuthenPolicy() -{ - uint32_t policy = 0; - uint8_t flag = 0; - - // Edits generally need an authors signature. - - // Wire requires all TopLevel (Orig/Reply) msgs to be signed with both PUBLISH & AUTHOR. - // Reply References need to be signed by Author. - flag = GXS_SERV::MSG_AUTHEN_ROOT_PUBLISH_SIGN | GXS_SERV::MSG_AUTHEN_CHILD_AUTHOR_SIGN; - flag |= GXS_SERV::MSG_AUTHEN_ROOT_AUTHOR_SIGN; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PUBLIC_GRP_BITS); - - // expect the requirements to be the same for RESTRICTED / PRIVATE groups too. - // This needs to be worked through / fully evaluated. - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::RESTRICTED_GRP_BITS); - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::PRIVATE_GRP_BITS); - - flag = 0; - RsGenExchange::setAuthenPolicyFlag(flag, policy, RsGenExchange::GRP_OPTION_BITS); - - return policy; -} - -void p3Wire::service_tick() -{ - return; -} - -RsTokenService* p3Wire::getTokenService() { - - return RsGenExchange::getTokenService(); -} - -void p3Wire::notifyChanges(std::vector& /*changes*/) -{ - std::cerr << "p3Wire::notifyChanges() New stuff"; - std::cerr << std::endl; -} - - /* Specific Service Data */ -bool p3Wire::getGroupData(const uint32_t &token, std::vector &groups) -{ - std::cerr << "p3Wire::getGroupData()"; - std::cerr << std::endl; - - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); ++vit) - { - RsGxsWireGroupItem* item = dynamic_cast(*vit); - - if (item) - { - RsWireGroup group = item->group; - group.mMeta = item->meta; - delete item; - groups.push_back(group); - - std::cerr << "p3Wire::getGroupData() Adding WireGroup to Vector: "; - std::cerr << std::endl; - std::cerr << group; - std::cerr << std::endl; - } - else - { - std::cerr << "Not a WireGroupItem, deleting!" << std::endl; - delete *vit; - } - - } - } - return ok; -} - -bool p3Wire::getGroupPtrData(const uint32_t &token, std::map &groups) -{ - std::cerr << "p3Wire::getGroupPtrData()"; - std::cerr << std::endl; - - std::vector grpData; - bool ok = RsGenExchange::getGroupData(token, grpData); - - if(ok) - { - std::vector::iterator vit = grpData.begin(); - - for(; vit != grpData.end(); ++vit) - { - RsGxsWireGroupItem* item = dynamic_cast(*vit); - - if (item) - { - RsWireGroupSPtr pGroup = std::make_shared(item->group); - pGroup->mMeta = item->meta; - delete item; - - groups[pGroup->mMeta.mGroupId] = pGroup; - - std::cerr << "p3Wire::getGroupPtrData() Adding WireGroup to Vector: "; - std::cerr << pGroup->mMeta.mGroupId.toStdString(); - std::cerr << std::endl; - } - else - { - std::cerr << "Not a WireGroupItem, deleting!" << std::endl; - delete *vit; - } - - } - } - return ok; -} - - -bool p3Wire::getPulseData(const uint32_t &token, std::vector &pulses) -{ - GxsMsgDataMap msgData; - bool ok = RsGenExchange::getMsgData(token, msgData); - - if(ok) - { - GxsMsgDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsWirePulseItem* item = dynamic_cast(*vit); - - if(item) - { - RsWirePulse pulse = item->pulse; - pulse.mMeta = item->meta; - pulses.push_back(pulse); - delete item; - } - else - { - std::cerr << "Not a WirePulse Item, deleting!" << std::endl; - delete *vit; - } - } - } - } - return ok; -} - -bool p3Wire::getPulsePtrData(const uint32_t &token, std::list &pulses) -{ - GxsMsgDataMap msgData; - bool ok = RsGenExchange::getMsgData(token, msgData); - - if(ok) - { - GxsMsgDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsWirePulseItem* item = dynamic_cast(*vit); - - if(item) - { - RsWirePulseSPtr pPulse = std::make_shared(item->pulse); - pPulse->mMeta = item->meta; - pulses.push_back(pPulse); - delete item; - } - else - { - std::cerr << "Not a WirePulse Item, deleting!" << std::endl; - delete *vit; - } - } - } - } - return ok; -} - -bool p3Wire::getRelatedPulseData(const uint32_t &token, std::vector &pulses) -{ - GxsMsgRelatedDataMap msgData; - std::cerr << "p3Wire::getRelatedPulseData()"; - std::cerr << std::endl; - bool ok = RsGenExchange::getMsgRelatedData(token, msgData); - - if (ok) - { - std::cerr << "p3Wire::getRelatedPulseData() is OK"; - std::cerr << std::endl; - GxsMsgRelatedDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) - { - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); - - for(; vit != msgItems.end(); ++vit) - { - RsGxsWirePulseItem* item = dynamic_cast(*vit); - - if(item) - { - RsWirePulse pulse = item->pulse; - pulse.mMeta = item->meta; - pulses.push_back(pulse); - delete item; - } - else - { - std::cerr << "Not a WirePulse Item, deleting!" << std::endl; - delete *vit; - } - } - } - } - else - { - std::cerr << "p3Wire::getRelatedPulseData() is NOT OK"; - std::cerr << std::endl; - } - - return ok; -} - - -bool p3Wire::createGroup(uint32_t &token, RsWireGroup &group) -{ - RsGxsWireGroupItem* groupItem = new RsGxsWireGroupItem(); - groupItem->group = group; - groupItem->meta = group.mMeta; - - std::cerr << "p3Wire::createGroup(): "; - std::cerr << std::endl; - std::cerr << group; - std::cerr << std::endl; - - std::cerr << "p3Wire::createGroup() pushing to RsGenExchange"; - std::cerr << std::endl; - - RsGenExchange::publishGroup(token, groupItem); - return true; -} - - -bool p3Wire::createPulse(uint32_t &token, RsWirePulse &pulse) -{ - std::cerr << "p3Wire::createPulse(): " << pulse; - std::cerr << std::endl; - - RsGxsWirePulseItem* pulseItem = new RsGxsWirePulseItem(); - pulseItem->pulse = pulse; - pulseItem->meta = pulse.mMeta; - - RsGenExchange::publishMsg(token, pulseItem); - return true; -} - -// Blocking Interfaces. -bool p3Wire::createGroup(RsWireGroup &group) -{ - uint32_t token; - return createGroup(token, group) && waitToken(token) == RsTokenService::COMPLETE; -} - -bool p3Wire::updateGroup(const RsWireGroup & /*group*/) -{ - // TODO - return false; -} - -bool p3Wire::getGroups(const std::list groupIds, std::vector &groups) -{ - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - - if (groupIds.empty()) - { - if (!requestGroupInfo(token, opts) || waitToken(token) != RsTokenService::COMPLETE ) - { - return false; - } - } - else - { - if (!requestGroupInfo(token, opts, groupIds) || waitToken(token) != RsTokenService::COMPLETE ) - { - return false; - } - } - return getGroupData(token, groups) && !groups.empty(); -} - - -std::ostream &operator<<(std::ostream &out, const RsWireGroup &group) -{ - out << "RsWireGroup [ "; - out << " Name: " << group.mMeta.mGroupName; - out << " Tagline: " << group.mTagline; - out << " Location: " << group.mLocation; - out << " ]"; - return out; -} - -std::ostream &operator<<(std::ostream &out, const RsWirePulse &pulse) -{ - out << "RsWirePulse [ "; - out << "Title: " << pulse.mMeta.mMsgName; - out << "PulseText: " << pulse.mPulseText; - out << "]"; - return out; -} - -/***** FOR TESTING *****/ - -std::string p3Wire::genRandomId() -{ - std::string randomId; - for(int i = 0; i < 20; i++) - { - randomId += (char) ('a' + (RSRandom::random_u32() % 26)); - } - - return randomId; -} - -void p3Wire::generateDummyData() -{ - -} - - -// New Interfaces. -bool p3Wire::fetchPulse(RsGxsGroupId grpId, RsGxsMessageId msgId, RsWirePulseSPtr &pPulse) -{ - std::cerr << "p3Wire::fetchPulse(" << grpId << ", " << msgId << ") waiting for token"; - std::cerr << std::endl; - - uint32_t token; - { - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - opts.mOptions = RS_TOKREQOPT_MSG_LATEST; - - GxsMsgReq ids; - std::set &set_msgIds = ids[grpId]; - set_msgIds.insert(msgId); - - getTokenService()->requestMsgInfo( - token, RS_TOKREQ_ANSTYPE_DATA, opts, ids); - } - - // wait for pulse request to completed. - std::cerr << "p3Wire::fetchPulse() waiting for token"; - std::cerr << std::endl; - - int result = waitToken(token); - if (result != RsTokenService::COMPLETE) - { - std::cerr << "p3Wire::fetchPulse() token FAILED, result: " << result; - std::cerr << std::endl; - return false; - } - - // retrieve Pulse. - std::cerr << "p3Wire::fetchPulse() retrieving token"; - std::cerr << std::endl; - { - bool okay = true; - std::vector pulses; - if (getPulseData(token, pulses)) { - if (pulses.size() == 1) { - // save to output pulse. - pPulse = std::make_shared(pulses[0]); - std::cerr << "p3Wire::fetchPulse() retrieved token: " << *pPulse; - std::cerr << std::endl; - std::cerr << "p3Wire::fetchPulse() ANS GrpId: " << pPulse->mMeta.mGroupId; - std::cerr << " MsgId: " << pPulse->mMeta.mMsgId; - std::cerr << " OrigMsgId: " << pPulse->mMeta.mOrigMsgId; - std::cerr << std::endl; - } else { - std::cerr << "p3Wire::fetchPulse() ERROR multiple pulses"; - std::cerr << std::endl; - okay = false; - } - } else { - std::cerr << "p3Wire::fetchPulse() ERROR failed to retrieve token"; - std::cerr << std::endl; - okay = false; - } - - if (!okay) { - std::cerr << "p3Wire::fetchPulse() tokenPulse ERROR"; - std::cerr << std::endl; - // TODO cancel other request. - return false; - } - } - return true; -} - -// New Interfaces. -bool p3Wire::createOriginalPulse(const RsGxsGroupId &grpId, RsWirePulseSPtr pPulse) -{ - // request Group. - std::list groupIds = { grpId }; - std::vector groups; - bool groupOkay = getGroups(groupIds, groups); - if (!groupOkay) { - std::cerr << "p3Wire::createOriginalPulse() getGroups failed"; - std::cerr << std::endl; - return false; - } - - if (groups.size() != 1) { - std::cerr << "p3Wire::createOriginalPulse() getGroups invalid size"; - std::cerr << std::endl; - return false; - } - - // ensure Group is suitable. - RsWireGroup group = groups[0]; - if ((group.mMeta.mGroupId != grpId) || - (!(group.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_PUBLISH))) - { - std::cerr << "p3Wire::createOriginalPulse() Group unsuitable"; - std::cerr << std::endl; - return false; - } - - // Create Msg. - // Start fresh, just to be sure nothing dodgy happens in UX world. - RsWirePulse pulse; - - pulse.mMeta.mGroupId = group.mMeta.mGroupId; - pulse.mMeta.mAuthorId = group.mMeta.mAuthorId; - pulse.mMeta.mThreadId.clear(); - pulse.mMeta.mParentId.clear(); - pulse.mMeta.mOrigMsgId.clear(); - - // copy info over - pulse.mPulseType = WIRE_PULSE_TYPE_ORIGINAL; - pulse.mSentiment = pPulse->mSentiment; - pulse.mPulseText = pPulse->mPulseText; - pulse.mImage1 = pPulse->mImage1; - pulse.mImage2 = pPulse->mImage2; - pulse.mImage3 = pPulse->mImage3; - pulse.mImage4 = pPulse->mImage4; - - // all mRefs should empty. - - uint32_t token; - createPulse(token, pulse); - - int result = waitToken(token); - if (result != RsTokenService::COMPLETE) - { - std::cerr << "p3Wire::createOriginalPulse() Failed to create Pulse"; - std::cerr << std::endl; - return false; - } - - return true; -} - -bool p3Wire::createReplyPulse(RsGxsGroupId grpId, RsGxsMessageId msgId, RsGxsGroupId replyWith, uint32_t reply_type, RsWirePulseSPtr pPulse) -{ - // check reply_type. can only be ONE. - if (!((reply_type == WIRE_PULSE_TYPE_REPLY) || - (reply_type == WIRE_PULSE_TYPE_REPUBLISH) || - (reply_type == WIRE_PULSE_TYPE_LIKE))) - { - std::cerr << "p3Wire::createReplyPulse() reply_type is invalid"; - std::cerr << std::endl; - return false; - } - - // request both groups. - std::list groupIds = { grpId, replyWith }; - std::vector groups; - bool groupOkay = getGroups(groupIds, groups); - if (!groupOkay) { - std::cerr << "p3Wire::createReplyPulse() getGroups failed"; - std::cerr << std::endl; - return false; - } - - // extract group info. - RsWireGroup replyToGroup; - RsWireGroup replyWithGroup; - - if (grpId == replyWith) - { - if (groups.size() != 1) { - std::cerr << "p3Wire::createReplyPulse() getGroups != 1"; - std::cerr << std::endl; - return false; - } - - replyToGroup = groups[0]; - replyWithGroup = groups[0]; - } - else - { - if (groups.size() != 2) { - std::cerr << "p3Wire::createReplyPulse() getGroups != 2"; - std::cerr << std::endl; - return false; - } - - if (groups[0].mMeta.mGroupId == grpId) { - replyToGroup = groups[0]; - replyWithGroup = groups[1]; - } else { - replyToGroup = groups[1]; - replyWithGroup = groups[0]; - } - } - - // check groupIds match - if ((replyToGroup.mMeta.mGroupId != grpId) || - (replyWithGroup.mMeta.mGroupId != replyWith)) - { - std::cerr << "p3Wire::createReplyPulse() groupid mismatch"; - std::cerr << std::endl; - return false; - } - - // ensure Group is suitable. - if ((!(replyToGroup.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED)) || - (!(replyWithGroup.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_PUBLISH))) - { - std::cerr << "p3Wire::createReplyPulse() Group unsuitable"; - std::cerr << std::endl; - return false; - } - - // ********************************************************** - RsWirePulseSPtr replyToPulse; - if (!fetchPulse(grpId, msgId, replyToPulse)) - { - std::cerr << "p3Wire::createReplyPulse() fetchPulse FAILED"; - std::cerr << std::endl; - return false; - } - - // create Reply Msg. - RsWirePulse responsePulse; - - responsePulse.mMeta.mGroupId = replyWithGroup.mMeta.mGroupId; - responsePulse.mMeta.mAuthorId = replyWithGroup.mMeta.mAuthorId; - responsePulse.mMeta.mThreadId.clear(); - responsePulse.mMeta.mParentId.clear(); - responsePulse.mMeta.mOrigMsgId.clear(); - - responsePulse.mPulseType = WIRE_PULSE_TYPE_RESPONSE | reply_type; - responsePulse.mSentiment = pPulse->mSentiment; - responsePulse.mPulseText = pPulse->mPulseText; - responsePulse.mImage1 = pPulse->mImage1; - responsePulse.mImage2 = pPulse->mImage2; - responsePulse.mImage3 = pPulse->mImage3; - responsePulse.mImage4 = pPulse->mImage4; - - // mRefs refer to parent post. - responsePulse.mRefGroupId = replyToPulse->mMeta.mGroupId; - responsePulse.mRefGroupName = replyToGroup.mMeta.mGroupName; - responsePulse.mRefOrigMsgId = replyToPulse->mMeta.mOrigMsgId; - responsePulse.mRefAuthorId = replyToPulse->mMeta.mAuthorId; - responsePulse.mRefPublishTs = replyToPulse->mMeta.mPublishTs; - responsePulse.mRefPulseText = replyToPulse->mPulseText; - responsePulse.mRefImageCount = replyToPulse->ImageCount(); - - std::cerr << "p3Wire::createReplyPulse() create Response Pulse"; - std::cerr << std::endl; - - uint32_t token; - if (!createPulse(token, responsePulse)) - { - std::cerr << "p3Wire::createReplyPulse() FAILED to create Response Pulse"; - std::cerr << std::endl; - return false; - } - - int result = waitToken(token); - if (result != RsTokenService::COMPLETE) - { - std::cerr << "p3Wire::createReplyPulse() FAILED(2) to create Response Pulse"; - std::cerr << std::endl; - return false; - } - - // get MsgId. - std::pair responsePair; - if (!acknowledgeMsg(token, responsePair)) - { - std::cerr << "p3Wire::createReplyPulse() FAILED acknowledgeMsg for Response Pulse"; - std::cerr << std::endl; - return false; - } - - std::cerr << "p3Wire::createReplyPulse() Response Pulse ID: ("; - std::cerr << responsePair.first.toStdString() << ", "; - std::cerr << responsePair.second.toStdString() << ")"; - std::cerr << std::endl; - - // retrieve newly generated message. - // ********************************************************** - RsWirePulseSPtr createdResponsePulse; - if (!fetchPulse(responsePair.first, responsePair.second, createdResponsePulse)) - { - std::cerr << "p3Wire::createReplyPulse() fetch createdReponsePulse FAILED"; - std::cerr << std::endl; - return false; - } - - /* Check that pulses is created properly */ - if ((createdResponsePulse->mMeta.mGroupId != responsePulse.mMeta.mGroupId) || - (createdResponsePulse->mPulseText != responsePulse.mPulseText) || - (createdResponsePulse->mRefGroupId != responsePulse.mRefGroupId) || - (createdResponsePulse->mRefOrigMsgId != responsePulse.mRefOrigMsgId)) - { - std::cerr << "p3Wire::createReplyPulse() fetch createdReponsePulse FAILED"; - std::cerr << std::endl; - return false; - } - - // create ReplyTo Ref Msg. - std::cerr << "PulseAddDialog::postRefPulse() create Reference!"; - std::cerr << std::endl; - - // Reference Pulse. posted on Parent's Group. - RsWirePulse refPulse; - - refPulse.mMeta.mGroupId = replyToPulse->mMeta.mGroupId; - refPulse.mMeta.mAuthorId = replyWithGroup.mMeta.mAuthorId; // own author Id. - refPulse.mMeta.mThreadId = replyToPulse->mMeta.mOrigMsgId; - refPulse.mMeta.mParentId = replyToPulse->mMeta.mOrigMsgId; - refPulse.mMeta.mOrigMsgId.clear(); - - refPulse.mPulseType = WIRE_PULSE_TYPE_REFERENCE | reply_type; - refPulse.mSentiment = 0; // should this be =? createdResponsePulse->mSentiment; - - // Dont put parent PulseText into refPulse - it is available on Thread Msg. - // otherwise gives impression it is correctly setup Parent / Reply... - // when in fact the parent PublishTS, and AuthorId are wrong. - refPulse.mPulseText = ""; - - // refs refer back to own Post. - refPulse.mRefGroupId = replyWithGroup.mMeta.mGroupId; - refPulse.mRefGroupName = replyWithGroup.mMeta.mGroupName; - refPulse.mRefOrigMsgId = createdResponsePulse->mMeta.mOrigMsgId; - refPulse.mRefAuthorId = replyWithGroup.mMeta.mAuthorId; - refPulse.mRefPublishTs = createdResponsePulse->mMeta.mPublishTs; - refPulse.mRefPulseText = createdResponsePulse->mPulseText; - refPulse.mRefImageCount = createdResponsePulse->ImageCount(); - - // publish Ref Msg. - if (!createPulse(token, refPulse)) - { - std::cerr << "p3Wire::createReplyPulse() FAILED to create Ref Pulse"; - std::cerr << std::endl; - return false; - } - - result = waitToken(token); - if (result != RsTokenService::COMPLETE) - { - std::cerr << "p3Wire::createReplyPulse() FAILED(2) to create Ref Pulse"; - std::cerr << std::endl; - return false; - } - - // get MsgId. - std::pair refPair; - if (!acknowledgeMsg(token, refPair)) - { - std::cerr << "p3Wire::createReplyPulse() FAILED acknowledgeMsg for Ref Pulse"; - std::cerr << std::endl; - return false; - } - - std::cerr << "p3Wire::createReplyPulse() Success: Ref Pulse ID: ("; - std::cerr << refPair.first.toStdString() << ", "; - std::cerr << refPair.second.toStdString() << ")"; - std::cerr << std::endl; - - return true; -} - - - // Blocking, request structures for display. -#if 0 -bool p3Wire::createReplyPulse(uint32_t &token, RsWirePulse &pulse) -{ - - return true; -} - -bool p3Wire::createRepublishPulse(uint32_t &token, RsWirePulse &pulse) -{ - - return true; -} - -bool p3Wire::createLikePulse(uint32_t &token, RsWirePulse &pulse) -{ - - return true; -} -#endif - - // WireGroup Details. -bool p3Wire::getWireGroup(const RsGxsGroupId &groupId, RsWireGroupSPtr &grp) -{ - std::list groupIds = { groupId }; - std::map groups; - if (!fetchGroupPtrs(groupIds, groups)) - { - std::cerr << "p3Wire::getWireGroup() failed to fetchGroupPtrs"; - std::cerr << std::endl; - return false; - } - - if (groups.size() != 1) - { - std::cerr << "p3Wire::getWireGroup() invalid group size"; - std::cerr << std::endl; - return false; - } - - grp = groups.begin()->second; - - // TODO Should fill in Counters of pulses/likes/republishes/replies - return true; -} - -// TODO Remove duplicate ... -bool p3Wire::getWirePulse(const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, RsWirePulseSPtr &pPulse) -{ - return fetchPulse(groupId, msgId, pPulse); -} - - - - -bool compare_time(const RsWirePulseSPtr& first, const RsWirePulseSPtr &second) -{ - return first->mMeta.mPublishTs > second->mMeta.mPublishTs; -} - - // should this filter them in some way? - // date, or count would be more likely. -bool p3Wire::getPulsesForGroups(const std::list &groupIds, std::list &pulsePtrs) -{ - // request all the pulses (Top-Level Thread Msgs). - std::cerr << "p3Wire::getPulsesForGroups()"; - std::cerr << std::endl; - - uint32_t token; - { - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - opts.mOptions = RS_TOKREQOPT_MSG_LATEST | RS_TOKREQOPT_MSG_THREAD; - - getTokenService()->requestMsgInfo( - token, RS_TOKREQ_ANSTYPE_DATA, opts, groupIds); - } - - // wait for pulse request to completed. - std::cerr << "p3Wire::getPulsesForGroups() waiting for token"; - std::cerr << std::endl; - - int result = waitToken(token); - if (result != RsTokenService::COMPLETE) - { - std::cerr << "p3Wire::getPulsesForGroups() token FAILED, result: " << result; - std::cerr << std::endl; - return false; - } - - // retrieve Pulses. - std::cerr << "p3Wire::getPulsesForGroups() retrieving token"; - std::cerr << std::endl; - if (!getPulsePtrData(token, pulsePtrs)) - { - std::cerr << "p3Wire::getPulsesForGroups() tokenPulse ERROR"; - std::cerr << std::endl; - return false; - } - - std::cerr << "p3Wire::getPulsesForGroups() size = " << pulsePtrs.size(); - std::cerr << std::endl; - { - std::list::iterator it; - for (it = pulsePtrs.begin(); it != pulsePtrs.end(); it++) - { - std::cerr << "p3Wire::getPulsesForGroups() Flags: "; - std::cerr << (*it)->mPulseType << " Msg: " << (*it)->mPulseText; - std::cerr << std::endl; - } - } - - std::cerr << "p3Wire::getPulsesForGroups() size = " << pulsePtrs.size(); - std::cerr << " sorting and trimming"; - std::cerr << std::endl; - - // sort and filter list. - pulsePtrs.sort(compare_time); - - // trim to N max. - uint32_t N = 10; - if (pulsePtrs.size() > N) { - pulsePtrs.resize(N); - } - - // for each fill in details. - std::list::iterator it; - for (it = pulsePtrs.begin(); it != pulsePtrs.end(); it++) - { - if (!updatePulse(*it, 1)) - { - std::cerr << "p3Wire::getPulsesForGroups() Failed to updatePulse"; - std::cerr << std::endl; - return false; - } - } - - // update GroupPtrs for all pulsePtrs. - if (!updateGroups(pulsePtrs)) - { - std::cerr << "p3Wire::getPulsesForGroups() failed to updateGroups"; - std::cerr << std::endl; - return false; - } - - return true; -} - - -bool p3Wire::getPulseFocus(const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, int /* type */, RsWirePulseSPtr &pPulse) -{ - std::cerr << "p3Wire::getPulseFocus("; - std::cerr << "grpId: " << groupId << " msgId: " << msgId; - std::cerr << " )"; - std::cerr << std::endl; - - if (!fetchPulse(groupId, msgId, pPulse)) - { - std::cerr << "p3Wire::getPulseFocus() failed to fetch Pulse"; - std::cerr << std::endl; - return false; - } - - if (!updatePulse(pPulse, 3)) - { - std::cerr << "p3Wire::getPulseFocus() failed to update Pulse"; - std::cerr << std::endl; - return false; - } - - /* Fill in GroupPtrs */ - std::list pulsePtrs; - pulsePtrs.push_back(pPulse); - - if (!updateGroups(pulsePtrs)) - { - std::cerr << "p3Wire::getPulseFocus() failed to updateGroups"; - std::cerr << std::endl; - return false; - } - - return true; -} - - -// function to update a pulse with the (Ref) child with actual data. -bool p3Wire::updatePulse(RsWirePulseSPtr pPulse, int levels) -{ - bool okay = true; - - // setup logging label. - std::ostringstream out; - out << "pulse[" << (void *) pPulse.get() << "], " << levels; - std::string label = out.str(); - - std::cerr << "p3Wire::updatePulse(" << label << ") starting"; - std::cerr << std::endl; - - // is pPulse is a REF, then request the original. - // if no original available the done. - if (pPulse->mPulseType & WIRE_PULSE_TYPE_REFERENCE) - { - RsWirePulseSPtr fullPulse; - std::cerr << "p3Wire::updatePulse(" << label << ") fetching REF ("; - std::cerr << "grpId: " << pPulse->mRefGroupId << " msgId: " << pPulse->mRefOrigMsgId; - std::cerr << " )"; - std::cerr << std::endl; - if (!fetchPulse(pPulse->mRefGroupId, pPulse->mRefOrigMsgId, fullPulse)) - { - std::cerr << "p3Wire::updatePulse(" << label << ") failed to fetch REF"; - std::cerr << std::endl; - return false; - } - std::cerr << "p3Wire::updatePulse(" << label << ") replacing REF"; - std::cerr << std::endl; - - *pPulse = *fullPulse; - } - - // Request children: (Likes / Retweets / Replies) - std::cerr << "p3Wire::updatePulse(" << label << ") requesting children"; - std::cerr << std::endl; - - uint32_t token; - { - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_RELATED_DATA; - // OR opts.mOptions = RS_TOKREQOPT_MSG_LATEST | RS_TOKREQOPT_MSG_PARENT; - opts.mOptions = RS_TOKREQOPT_MSG_LATEST | RS_TOKREQOPT_MSG_THREAD; - - std::vector msgIds = { - std::make_pair(pPulse->mMeta.mGroupId, pPulse->mMeta.mOrigMsgId) - }; - - getTokenService()->requestMsgRelatedInfo( - token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds); - } - - // wait for request to complete - std::cerr << "p3Wire::updatePulse(" << label << ") waiting for token"; - std::cerr << std::endl; - - int result = waitToken(token); - if (result != RsTokenService::COMPLETE) - { - std::cerr << "p3Wire::updatePulse(" << label << ") token FAILED, result: " << result; - std::cerr << std::endl; - return false; - } - - /* load children */ - okay = updatePulseChildren(pPulse, token); - if (!okay) - { - std::cerr << "p3Wire::updatePulse(" << label << ") FAILED to update Children"; - std::cerr << std::endl; - return false; - } - - /* if down to last level, no need to updateChildren */ - if (levels <= 1) - { - std::cerr << "p3Wire::updatePulse(" << label << ") Level <= 1 finished"; - std::cerr << std::endl; - return okay; - } - - /* recursively update children */ - std::cerr << "p3Wire::updatePulse(" << label << ") updating children recursively"; - std::cerr << std::endl; - std::list::iterator it; - for (it = pPulse->mReplies.begin(); it != pPulse->mReplies.end(); it++) - { - bool childOkay = updatePulse(*it, levels - 1); - if (!childOkay) { - std::cerr << "p3Wire::updatePulse(" << label << ") update children (reply) failed"; - std::cerr << std::endl; - } - } - - for (it = pPulse->mRepublishes.begin(); it != pPulse->mRepublishes.end(); it++) - { - bool childOkay = updatePulse(*it, levels - 1); - if (!childOkay) { - std::cerr << "p3Wire::updatePulse(" << label << ") update children (repub) failed"; - std::cerr << std::endl; - } - } - - return okay; -} - - -// function to update the (Ref) child with actual data. -bool p3Wire::updatePulseChildren(RsWirePulseSPtr pParent, uint32_t token) -{ - { - bool okay = true; - std::vector pulses; - if (getRelatedPulseData(token, pulses)) { - std::vector::iterator it; - for (it = pulses.begin(); it != pulses.end(); it++) - { - std::cerr << "p3Wire::updatePulseChildren() retrieved child: " << *it; - std::cerr << std::endl; - - RsWirePulseSPtr pPulse = std::make_shared(*it); - // switch on type. - if (it->mPulseType & WIRE_PULSE_TYPE_LIKE) { - pParent->mLikes.push_back(pPulse); - std::cerr << "p3Wire::updatePulseChildren() adding Like"; - std::cerr << std::endl; - } - else if (it->mPulseType & WIRE_PULSE_TYPE_REPUBLISH) { - pParent->mRepublishes.push_back(pPulse); - std::cerr << "p3Wire::updatePulseChildren() adding Republish"; - std::cerr << std::endl; - } - else if (it->mPulseType & WIRE_PULSE_TYPE_REPLY) { - pParent->mReplies.push_back(pPulse); - std::cerr << "p3Wire::updatePulseChildren() adding Reply"; - std::cerr << std::endl; - } - else { - std::cerr << "p3Wire::updatePulseChildren() unknown child type: " << it->mPulseType; - std::cerr << std::endl; - } - } - } else { - std::cerr << "p3Wire::updatePulseChildren() ERROR failed to retrieve token"; - std::cerr << std::endl; - okay = false; - } - - if (!okay) { - std::cerr << "p3Wire::updatePulseChildren() token ERROR"; - std::cerr << std::endl; - } - return okay; - } -} - -/* High-level utility function to update mGroupPtr / mRefGroupPtr links. - * fetches associated groups and reference them from pulses - * - * extractGroupIds (owner + refs). - * fetch all available GroupIDs. (just IDs - so light). - * do intersection of IDs. - * apply IDs. - */ - -bool p3Wire::updateGroups(std::list &pulsePtrs) -{ - std::set pulseGroupIds; - - std::list::iterator it; - for (it = pulsePtrs.begin(); it != pulsePtrs.end(); it++) - { - if (!extractGroupIds(*it, pulseGroupIds)) - { - std::cerr << "p3Wire::updateGroups() failed to extractGroupIds"; - std::cerr << std::endl; - return false; - } - } - - std::list availGroupIds; - if (!trimToAvailGroupIds(pulseGroupIds, availGroupIds)) - { - std::cerr << "p3Wire::updateGroups() failed to trimToAvailGroupIds"; - std::cerr << std::endl; - return false; - } - - std::map groups; - if (!fetchGroupPtrs(availGroupIds, groups)) - { - std::cerr << "p3Wire::updateGroups() failed to fetchGroupPtrs"; - std::cerr << std::endl; - return false; - } - - for (it = pulsePtrs.begin(); it != pulsePtrs.end(); it++) - { - if (!updateGroupPtrs(*it, groups)) - { - std::cerr << "p3Wire::updateGroups() failed to updateGroupPtrs"; - std::cerr << std::endl; - return false; - } - } - return true; -} - - -// this function doesn't depend on p3Wire, could make static. -bool p3Wire::extractGroupIds(RsWirePulseConstSPtr pPulse, std::set &groupIds) -{ - std::cerr << "p3Wire::extractGroupIds()"; - std::cerr << std::endl; - - if (!pPulse) { - std::cerr << "p3Wire::extractGroupIds() INVALID pPulse"; - std::cerr << std::endl; - return false; - } - - // install own groupId. - groupIds.insert(pPulse->mMeta.mGroupId); - - /* do this recursively */ - if (pPulse->mPulseType & WIRE_PULSE_TYPE_REFERENCE) { - // REPLY: mRefGroupId, PARENT was in mMeta.mGroupId. - groupIds.insert(pPulse->mRefGroupId); - /* skipping */ - return true; - } - - - if (pPulse->mPulseType & WIRE_PULSE_TYPE_RESPONSE) { - // REPLY: meta.mGroupId, PARENT: mRefGroupId - groupIds.insert(pPulse->mRefGroupId); - } - - /* iterate through children, recursively */ - std::list::const_iterator it; - for (it = pPulse->mReplies.begin(); it != pPulse->mReplies.end(); it++) - { - bool childOkay = extractGroupIds(*it, groupIds); - if (!childOkay) { - std::cerr << "p3Wire::extractGroupIds() update children (reply) failed"; - std::cerr << std::endl; - return false; - } - } - - for (it = pPulse->mRepublishes.begin(); it != pPulse->mRepublishes.end(); it++) - { - bool childOkay = extractGroupIds(*it, groupIds); - if (!childOkay) { - std::cerr << "p3Wire::extractGroupIds() update children (repub) failed"; - std::cerr << std::endl; - return false; - } - } - - // not bothering with LIKEs at the moment. TODO. - return true; -} - -bool p3Wire::updateGroupPtrs(RsWirePulseSPtr pPulse, const std::map &groups) -{ - std::map::const_iterator git; - git = groups.find(pPulse->mMeta.mGroupId); - if (git == groups.end()) { - // error - return false; - } - - pPulse->mGroupPtr = git->second; - - // if REF, fill in mRefGroupPtr based on mRefGroupId. - if (pPulse->mPulseType & WIRE_PULSE_TYPE_REFERENCE) { - // if RefGroupId is in list, fill in. No error if its not there. - std::map::const_iterator rgit; - rgit = groups.find(pPulse->mRefGroupId); - if (rgit != groups.end()) { - pPulse->mRefGroupPtr = rgit->second; - } - - // no children for REF pulse, so can return now. - return true; - } - - // if Response, fill in mRefGroupPtr based on mRefGroupId. - if (pPulse->mPulseType & WIRE_PULSE_TYPE_RESPONSE) { - // if RefGroupId is in list, fill in. No error if its not there. - std::map::const_iterator rgit; - rgit = groups.find(pPulse->mRefGroupId); - if (rgit != groups.end()) { - pPulse->mRefGroupPtr = rgit->second; - } - // do children as well. - } - - /* recursively apply to children */ - std::list::iterator it; - for (it = pPulse->mReplies.begin(); it != pPulse->mReplies.end(); it++) - { - bool childOkay = updateGroupPtrs(*it, groups); - if (!childOkay) { - std::cerr << "p3Wire::updateGroupPtrs() update children (reply) failed"; - std::cerr << std::endl; - return false; - } - } - - for (it = pPulse->mRepublishes.begin(); it != pPulse->mRepublishes.end(); it++) - { - bool childOkay = updateGroupPtrs(*it, groups); - if (!childOkay) { - std::cerr << "p3Wire::updateGroupPtrs() update children (repub) failed"; - std::cerr << std::endl; - return false; - } - } - - // not bothering with LIKEs at the moment. TODO. - return true; -} - -bool p3Wire::trimToAvailGroupIds(const std::set &pulseGroupIds, - std::list &availGroupIds) -{ - /* request all groupIds */ - std::cerr << "p3Wire::trimToAvailGroupIds()"; - std::cerr << std::endl; - - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_IDS; - - if (!requestGroupInfo(token, opts) || waitToken(token) != RsTokenService::COMPLETE ) - { - std::cerr << "p3Wire::trimToAvailGroupIds() failed to fetch groups"; - std::cerr << std::endl; - return false; - } - - std::list localGroupIds; - if (!RsGenExchange::getGroupList(token, localGroupIds)) - { - std::cerr << "p3Wire::trimToAvailGroupIds() failed to get GroupIds"; - std::cerr << std::endl; - return false; - } - - /* do intersection between result ^ pulseGroups -> availGroupIds */ - std::set_intersection(localGroupIds.begin(), localGroupIds.end(), - pulseGroupIds.begin(), pulseGroupIds.end(), - std::back_inserter(availGroupIds)); - - return true; -} - -bool p3Wire::fetchGroupPtrs(const std::list &groupIds, - std::map &groups) -{ - std::cerr << "p3Wire::fetchGroupPtrs()"; - std::cerr << std::endl; - - uint32_t token; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - - if (!requestGroupInfo(token, opts, groupIds) || waitToken(token) != RsTokenService::COMPLETE ) - { - std::cerr << "p3Wire::fetchGroupPtrs() failed to fetch groups"; - std::cerr << std::endl; - return false; - } - return getGroupPtrData(token, groups); -} - diff --git a/libretroshare/src/services/p3wire.h b/libretroshare/src/services/p3wire.h deleted file mode 100644 index 2e7375578..000000000 --- a/libretroshare/src/services/p3wire.h +++ /dev/null @@ -1,119 +0,0 @@ -/******************************************************************************* - * libretroshare/src/services: p3wire.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2020 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef P3_WIRE_SERVICE_HEADER -#define P3_WIRE_SERVICE_HEADER - -#include "retroshare/rswire.h" -#include "gxs/rsgenexchange.h" - -#include -#include - -/* - * Wire Service - * - * - */ - -class p3Wire: public RsGenExchange, public RsWire -{ -public: - p3Wire(RsGeneralDataService* gds, RsNetworkExchangeService* nes, RsGixs *gixs); - virtual RsServiceInfo getServiceInfo(); - static uint32_t wireAuthenPolicy(); - -protected: - virtual void notifyChanges(std::vector& changes) ; - -public: - virtual void service_tick(); - - virtual RsTokenService* getTokenService(); - - /* Specific Service Data */ - virtual bool getGroupData(const uint32_t &token, std::vector &groups) override; - virtual bool getPulseData(const uint32_t &token, std::vector &pulses) override; - - virtual bool createGroup(uint32_t &token, RsWireGroup &group) override; - virtual bool createPulse(uint32_t &token, RsWirePulse &pulse) override; - - // Blocking Interfaces. - virtual bool createGroup(RsWireGroup &group) override; - virtual bool updateGroup(const RsWireGroup &group) override; - virtual bool getGroups(const std::list grpIds, std::vector &groups) override; - - // New Interfaces. - // Blocking, request structures for display. - virtual bool createOriginalPulse(const RsGxsGroupId &grpId, RsWirePulseSPtr pPulse) override; - virtual bool createReplyPulse(RsGxsGroupId grpId, RsGxsMessageId msgId, - RsGxsGroupId replyWith, uint32_t reply_type, - RsWirePulseSPtr pPulse) override; - -#if 0 - virtual bool createReplyPulse(uint32_t &token, RsWirePulse &pulse) override; - virtual bool createRepublishPulse(uint32_t &token, RsWirePulse &pulse) override; - virtual bool createLikePulse(uint32_t &token, RsWirePulse &pulse) override; -#endif - - virtual bool getWireGroup(const RsGxsGroupId &groupId, RsWireGroupSPtr &grp) override; - virtual bool getWirePulse(const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, RsWirePulseSPtr &pPulse) override; - - virtual bool getPulsesForGroups(const std::list &groupIds, std::list &pulsePtrs) override; - - virtual bool getPulseFocus(const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, int type, RsWirePulseSPtr &pPulse) override; - -private: - // Internal Service Data. - // They should eventually all be here. - bool getRelatedPulseData(const uint32_t &token, std::vector &pulses); - bool getGroupPtrData(const uint32_t &token, - std::map &groups); - bool getPulsePtrData(const uint32_t &token, std::list &pulses); - - // util functions fetching data. - bool fetchPulse(RsGxsGroupId grpId, RsGxsMessageId msgId, RsWirePulseSPtr &pPulse); - bool updatePulse(RsWirePulseSPtr pPulse, int levels); - bool updatePulseChildren(RsWirePulseSPtr pParent, uint32_t token); - - // update GroupPtrs - bool updateGroups(std::list &pulsePtrs); - - // sub utility functions used by updateGroups. - bool extractGroupIds(RsWirePulseConstSPtr pPulse, std::set &groupIds); - - bool updateGroupPtrs(RsWirePulseSPtr pPulse, - const std::map &groups); - - bool trimToAvailGroupIds(const std::set &pulseGroupIds, - std::list &availGroupIds); - - bool fetchGroupPtrs(const std::list &groupIds, - std::map &groups); - - - virtual void generateDummyData(); - std::string genRandomId(); - - RsMutex mWireMtx; -}; - -#endif diff --git a/libretroshare/src/services/rseventsservice.cc b/libretroshare/src/services/rseventsservice.cc deleted file mode 100644 index 3bbb852be..000000000 --- a/libretroshare/src/services/rseventsservice.cc +++ /dev/null @@ -1,197 +0,0 @@ -/******************************************************************************* - * Retroshare events service * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2019-2020 Gioacchino Mazzurco * - * Copyright (C) 2019-2020 Retroshare Team * - * Copyright (C) 2020 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include -#include - -#include "services/rseventsservice.h" - - -/*extern*/ RsEvents* rsEvents = nullptr; - -RsEvent::~RsEvent() = default; -RsEvents::~RsEvents() = default; - -/*static*/ const RsEventsErrorCategory RsEventsErrorCategory::instance; - -std::error_condition RsEventsErrorCategory::default_error_condition(int ev) -const noexcept -{ - switch(static_cast(ev)) - { - case RsEventsErrorNum::INVALID_HANDLER_ID: // [[fallthrough]]; - case RsEventsErrorNum::NULL_EVENT_POINTER: // [[fallthrough]]; - case RsEventsErrorNum::EVENT_TYPE_UNDEFINED: // [[fallthrough]]; - case RsEventsErrorNum::EVENT_TYPE_OUT_OF_RANGE: - return std::errc::invalid_argument; - default: - return std::error_condition(ev, *this); - } -} - -std::error_condition RsEventsService::isEventTypeInvalid(RsEventType eventType) -{ - if(eventType == RsEventType::__NONE) - return RsEventsErrorNum::EVENT_TYPE_UNDEFINED; - - if( eventType < RsEventType::__NONE || - eventType >= static_cast(mHandlerMaps.size()) ) - return RsEventsErrorNum::EVENT_TYPE_OUT_OF_RANGE; - - return std::error_condition(); -} - -std::error_condition RsEventsService::isEventInvalid( - std::shared_ptr event) -{ - if(!event) return RsEventsErrorNum::NULL_EVENT_POINTER; - return isEventTypeInvalid(event->mType); -} - -std::error_condition RsEventsService::postEvent( - std::shared_ptr event ) -{ - if(std::error_condition ec = isEventInvalid(event)) return ec; - - RS_STACK_MUTEX(mEventQueueMtx); - mEventQueue.push_back(event); - return std::error_condition(); -} - -std::error_condition RsEventsService::sendEvent( - std::shared_ptr event ) -{ - if(std::error_condition ec = isEventInvalid(event)) return ec; - handleEvent(event); - return std::error_condition(); -} - -RsEventsHandlerId_t RsEventsService::generateUniqueHandlerId() -{ - RS_STACK_MUTEX(mHandlerMapMtx); - return generateUniqueHandlerId_unlocked(); -} - -RsEventsHandlerId_t RsEventsService::generateUniqueHandlerId_unlocked() -{ - if(++mLastHandlerId) return mLastHandlerId; // Avoid 0 after overflow - return 1; -} - -std::error_condition RsEventsService::registerEventsHandler( - std::function)> multiCallback, - RsEventsHandlerId_t& hId, RsEventType eventType ) -{ - RS_STACK_MUTEX(mHandlerMapMtx); - - if(eventType != RsEventType::__NONE) - if(std::error_condition ec = isEventTypeInvalid(eventType)) - return ec; - - if(!hId) hId = generateUniqueHandlerId_unlocked(); - else if (hId > mLastHandlerId) - { - print_stacktrace(); - return RsEventsErrorNum::INVALID_HANDLER_ID; - } - - mHandlerMaps[static_cast(eventType)][hId] = multiCallback; - return std::error_condition(); -} - -std::error_condition RsEventsService::unregisterEventsHandler( - RsEventsHandlerId_t hId ) -{ - RS_STACK_MUTEX(mHandlerMapMtx); - - for(uint32_t i=0; i eventPtr(nullptr); - size_t futureEventsCounter = 0; - -dispatchEventFromQueueLock: - mEventQueueMtx.lock(); - if(mEventQueue.size() > futureEventsCounter) - { - eventPtr = mEventQueue.front(); - mEventQueue.pop_front(); - - if(eventPtr->mTimePoint >= nextRunAt) - { - mEventQueue.push_back(eventPtr); - ++futureEventsCounter; - } - } - mEventQueueMtx.unlock(); - - if(eventPtr) - { - /* It is relevant that this stays out of mEventQueueMtx */ - handleEvent(eventPtr); - eventPtr = nullptr; // ensure refcounter is decremented before sleep - goto dispatchEventFromQueueLock; - } - - std::this_thread::sleep_until(nextRunAt); -} - -void RsEventsService::handleEvent(std::shared_ptr event) -{ - if(std::error_condition ec = isEventInvalid(event)) - { - RsErr() << __PRETTY_FUNCTION__ << " " << ec << std::endl; - print_stacktrace(); - return; - } - - RS_STACK_MUTEX(mHandlerMapMtx); - /* It is important to also call the callback under mutex protection to - * ensure they are not unregistered in the meanwhile. - * If a callback try to fiddle with registering/unregistering it will - * deadlock */ - - // Call all clients that registered a callback for this event type - for(auto cbit: mHandlerMaps[static_cast(event->mType)]) - cbit.second(event); - - /* Also call all clients that registered with NONE, meaning that they - * expect all events */ - for(auto cbit: mHandlerMaps[static_cast(RsEventType::__NONE)]) - cbit.second(event); -} diff --git a/libretroshare/src/services/rseventsservice.h b/libretroshare/src/services/rseventsservice.h deleted file mode 100644 index 4f6ce98eb..000000000 --- a/libretroshare/src/services/rseventsservice.h +++ /dev/null @@ -1,88 +0,0 @@ -/******************************************************************************* - * Retroshare events service * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2019-2020 Gioacchino Mazzurco * - * Copyright (C) 2020 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -#include "retroshare/rsevents.h" -#include "util/rsthreads.h" -#include "util/rsdebug.h" - -class RsEventsService : - public RsEvents, public RsTickingThread -{ -public: - RsEventsService(): - mHandlerMapMtx("RsEventsService::mHandlerMapMtx"), mLastHandlerId(1), - mEventQueueMtx("RsEventsService::mEventQueueMtx") {} - - /// @see RsEvents - std::error_condition postEvent( - std::shared_ptr event ) override; - - /// @see RsEvents - std::error_condition sendEvent( - std::shared_ptr event ) override; - - /// @see RsEvents - RsEventsHandlerId_t generateUniqueHandlerId() override; - - /// @see RsEvents - std::error_condition registerEventsHandler( - std::function)> multiCallback, - RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0), - RsEventType eventType = RsEventType::__NONE ) override; - - /// @see RsEvents - std::error_condition unregisterEventsHandler( - RsEventsHandlerId_t hId ) override; - -protected: - std::error_condition isEventTypeInvalid(RsEventType eventType); - std::error_condition isEventInvalid(std::shared_ptr event); - - RsMutex mHandlerMapMtx; - RsEventsHandlerId_t mLastHandlerId; - - /** Storage for event handlers, keep 10 extra types for plugins that might - * be released indipendently */ - std::array< - std::map< - RsEventsHandlerId_t, - std::function)> >, - static_cast(RsEventType::__MAX) + 10 - > mHandlerMaps; - - RsMutex mEventQueueMtx; - std::deque< std::shared_ptr > mEventQueue; - - void threadTick() override; /// @see RsTickingThread - - void handleEvent(std::shared_ptr event); - RsEventsHandlerId_t generateUniqueHandlerId_unlocked(); - - RS_SET_CONTEXT_DEBUG_LEVEL(3) -}; diff --git a/libretroshare/src/tcponudp/bio_tou.h b/libretroshare/src/tcponudp/bio_tou.h deleted file mode 100644 index a82444ccc..000000000 --- a/libretroshare/src/tcponudp/bio_tou.h +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: bio_tou.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef BIO_TCPONUDP_H -#define BIO_TCPONUDP_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -int BIO_tou_socket_should_retry(int s, int e); -int BIO_tou_socket_non_fatal_error(int error); - -#define BIO_TYPE_TOU_SOCKET (30|0x0400|0x0100) /* NEW rmfern type */ - -BIO_METHOD *BIO_s_tou_socket(void); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/libretroshare/src/tcponudp/bss_tou.cc b/libretroshare/src/tcponudp/bss_tou.cc deleted file mode 100644 index 286201f53..000000000 --- a/libretroshare/src/tcponudp/bss_tou.cc +++ /dev/null @@ -1,355 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: bss_tou.c * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 1995-1998 Eric Young * - * Copyright (C) 2004-2006 Robert Fernie * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef OPENSSL_NO_SOCK - -#include "bio_tou.h" - -#include -#include -#include /* for strlen() */ - -#define USE_SOCKETS -#include - -#include "tou.h" -#include "util/rsdebug.h" - -RS_SET_CONTEXT_DEBUG_LEVEL(0); - -static int tou_socket_write(BIO *h, const char *buf, int num); -static int tou_socket_read(BIO *h, char *buf, int size); -static int tou_socket_puts(BIO *h, const char *str); -static long tou_socket_ctrl(BIO *h, int cmd, long arg1, void *arg2); -static int tou_socket_new(BIO *h); -static int tou_socket_free(BIO *data); -static int get_last_tou_socket_error(int s); -static int clear_tou_socket_error(int s); - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - -static int BIO_get_init(BIO *a) { return a->init; } - -#if (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000) \ - || (!defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L) - -static int BIO_get_shutdown(BIO *a) { return a->shutdown; } -static void BIO_set_init(BIO *a,int i) { a->init=i; } -static void BIO_set_data(BIO *a,void *p) { a->ptr = p; } -long (*BIO_meth_get_ctrl(const BIO_METHOD* biom)) (BIO*, int, long, void*) -{ return biom->ctrl; } - -#endif /* (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000) \ -|| (!defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L) */ - -static BIO_METHOD methods_tou_sockp = -{ - BIO_TYPE_TOU_SOCKET, - "tou_socket", - tou_socket_write, - tou_socket_read, - tou_socket_puts, - nullptr, // bgets - tou_socket_ctrl, - tou_socket_new, - tou_socket_free, - nullptr, // callback_ctrl -}; - -BIO_METHOD* BIO_s_tou_socket(void) -{ - Dbg2() << __PRETTY_FUNCTION__ << std::endl; - return(&methods_tou_sockp); -} - -#else // OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - -BIO_METHOD* BIO_s_tou_socket(void) -{ - static BIO_METHOD* methods_tou_sockp_ptr = NULL; - if(!methods_tou_sockp_ptr) - { - methods_tou_sockp_ptr = BIO_meth_new(BIO_TYPE_TOU_SOCKET, "tou_socket"); - - BIO_meth_set_write( methods_tou_sockp_ptr, tou_socket_write ); - BIO_meth_set_read( methods_tou_sockp_ptr, tou_socket_read ); - BIO_meth_set_puts( methods_tou_sockp_ptr, tou_socket_puts ); - BIO_meth_set_ctrl( methods_tou_sockp_ptr, tou_socket_ctrl ); - BIO_meth_set_create( methods_tou_sockp_ptr, tou_socket_new ); - BIO_meth_set_destroy( methods_tou_sockp_ptr, tou_socket_free ); - } - - return methods_tou_sockp_ptr; -} - -#endif // OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - -static int tou_socket_new(BIO *bi) -{ - Dbg2() << __PRETTY_FUNCTION__ << std::endl; - - BIO_set_init(bi,0) ; - BIO_set_data(bi, nullptr); // sets bi->ptr - BIO_set_flags(bi,0) ; - BIO_set_fd(bi,0,0) ; - return(1); -} - -static int tou_socket_free(BIO *a) -{ - Dbg2() << __PRETTY_FUNCTION__ << std::endl; - - if (!a) return(0); - - if(BIO_get_shutdown(a)) - { - if(BIO_get_init(a)) tou_close(static_cast(BIO_get_fd(a, nullptr))); - BIO_set_init(a,0) ; - BIO_set_flags(a,0) ; - } - return(1); - } - -static int tou_socket_read(BIO *b, char *out, int outl) -{ - Dbg2() << __PRETTY_FUNCTION__ << std::endl; - - int ret=0; - - if (out) - { - clear_tou_socket_error(BIO_get_fd(b,NULL)); - /* call tou library */ - ret=tou_read(BIO_get_fd(b,NULL),out,outl); - BIO_clear_retry_flags(b); - if (ret <= 0) - { - if (BIO_tou_socket_should_retry(BIO_get_fd(b,NULL), ret)) - BIO_set_retry_read(b); - } - } -#ifdef DEBUG_TOU_BIO - fprintf(stderr, "tou_socket_read() = %d\n", ret); -#endif - return(ret); - } - -static int tou_socket_write(BIO *b, const char *in, int inl) - { - int ret; -#ifdef DEBUG_TOU_BIO - fprintf(stderr, "tou_socket_write(%p,%p,%d)\n",b,in,inl); -#endif - - clear_tou_socket_error(BIO_get_fd(b,NULL)); - /* call tou library */ - ret=tou_write(BIO_get_fd(b,NULL),in,inl); - BIO_clear_retry_flags(b); - if (ret <= 0) - { - if (BIO_tou_socket_should_retry(BIO_get_fd(b,NULL),ret)) - { - BIO_set_retry_write(b); -#ifdef DEBUG_TOU_BIO - fprintf(stderr, "tou_socket_write() setting retry flag\n"); -#endif - } - } -#ifdef DEBUG_TOU_BIO - fprintf(stderr, "tou_socket_write() = %d\n", ret); -#endif - return(ret); - } - -static long tou_socket_ctrl(BIO *b, int cmd, long num, void *ptr) - { - long ret=1; -#ifdef DEBUG_TOU_BIO - fprintf(stderr, "tou_socket_ctrl(%p,%d,%ld)\n", b, cmd, num); -#endif - - // We are not allowed to call BIO_set_fd here, because it will trigger a callback, which re-ends here - - switch (cmd) - { - case BIO_CTRL_RESET: - num=0; - /* fallthrough */ - case BIO_C_FILE_SEEK: - ret=0; - break; - case BIO_C_FILE_TELL: - case BIO_CTRL_INFO: - ret=0; - break; - case BIO_C_SET_FD: - tou_socket_free(b); - ret = BIO_meth_get_ctrl((BIO_METHOD*)BIO_s_fd())(b,cmd,num,ptr); - break; - case BIO_C_GET_FD: - ret = BIO_meth_get_ctrl((BIO_METHOD*)BIO_s_fd())(b,cmd,num,ptr); - break; - case BIO_CTRL_GET_CLOSE: - ret = BIO_meth_get_ctrl((BIO_METHOD*)BIO_s_fd())(b,cmd,num,ptr); - break; - case BIO_CTRL_SET_CLOSE: - ret = BIO_meth_get_ctrl((BIO_METHOD*)BIO_s_fd())(b,cmd,num,ptr); - break; - case BIO_CTRL_PENDING: - ret = tou_maxread(BIO_get_fd(b,NULL)); -#ifdef DEBUG_TOU_BIO - fprintf(stderr, "tou_pending = %ld\n", ret); -#endif - break; - case BIO_CTRL_WPENDING: - ret = tou_maxwrite(BIO_get_fd(b,NULL)); -#ifdef DEBUG_TOU_BIO - fprintf(stderr, "tou_wpending = %ld\n", ret); -#endif - break; - case BIO_CTRL_DUP: - case BIO_CTRL_FLUSH: - ret=1; - break; - default: - ret=0; - break; - } - return(ret); - } - -static int tou_socket_puts(BIO *bp, const char *str) - { - int n,ret; - -#ifdef DEBUG_TOU_BIO - fprintf(stderr, "tou_socket_puts()\n"); -#endif - - n=strlen(str); - ret=tou_socket_write(bp,str,n); - return(ret); - } - -static int clear_tou_socket_error(int fd) -{ -#ifdef DEBUG_TOU_BIO - fprintf(stderr, "clear_tou_socket_error()\n"); -#endif - return tou_clear_error(fd); -} - -static int get_last_tou_socket_error(int s) -{ -#ifdef DEBUG_TOU_BIO - fprintf(stderr, "get_last_tou_socket_error()\n"); -#endif - return tou_errno(s); -} - -int BIO_tou_socket_should_retry(int s, int i) - { - int err; -#ifdef DEBUG_TOU_BIO - fprintf(stderr, "BIO_tou_socket_should_retry()\n"); -#endif - - if ((i == 0) || (i == -1)) - { - err=get_last_tou_socket_error(s); - -#if defined(OPENSSL_SYS_WINDOWS) && 0 /* more microsoft stupidity? perhaps not? Ben 4/1/99 */ - if ((i == -1) && (err == 0)) - return(1); -#endif - - return(BIO_tou_socket_non_fatal_error(err)); - } - return(0); - } - -int BIO_tou_socket_non_fatal_error(int err) -{ - constexpr int fatalError = 0; - constexpr int nonFatalError = 1; - - switch (err) - { -#if defined(OPENSSL_SYS_WINDOWS) -# if defined(WSAEWOULDBLOCK) - case WSAEWOULDBLOCK: -# endif // defined(WSAEWOULDBLOCK) -#endif // defined(OPENSSL_SYS_WINDOWS) - -#ifdef EWOULDBLOCK -# ifdef WSAEWOULDBLOCK -# if WSAEWOULDBLOCK != EWOULDBLOCK - case EWOULDBLOCK: -# endif // WSAEWOULDBLOCK != EWOULDBLOCK -# else // def WSAEWOULDBLOCK - case EWOULDBLOCK: -# endif // def WSAEWOULDBLOCK -#endif - -#if defined(ENOTCONN) - case ENOTCONN: -#endif // defined(ENOTCONN) - -#ifdef EINTR - case EINTR: -#endif // def EINTR - -#ifdef EAGAIN -# if EWOULDBLOCK != EAGAIN - case EAGAIN: -# endif // EWOULDBLOCK != EAGAIN -#endif // def EAGAIN - -#ifdef EPROTO - case EPROTO: -#endif // def EPROTO - -#ifdef EINPROGRESS - case EINPROGRESS: -#endif // def EINPROGRESS - -#ifdef EALREADY - case EALREADY: -#endif // def EALREADY - - Dbg2() << __PRETTY_FUNCTION__ << " err: " << err - << " return nonFatalError " << nonFatalError << std::endl; - return nonFatalError; - - default: - break; - } - - Dbg2() << __PRETTY_FUNCTION__ << " err: " << err << " return fatalError " - << fatalError << std::endl; - - return fatalError; -} - -#endif // ndef OPENSSL_NO_SOCK diff --git a/libretroshare/src/tcponudp/rsudpstack.h b/libretroshare/src/tcponudp/rsudpstack.h deleted file mode 100644 index 77c25692c..000000000 --- a/libretroshare/src/tcponudp/rsudpstack.h +++ /dev/null @@ -1,107 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: rsudpstack.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef RS_UDP_STACK_RECEIVER_H -#define RS_UDP_STACK_RECEIVER_H - -#ifdef RS_USE_BITDHT - -#include "udp/udpstack.h" - - -#else - -class UdpStack -{ - public: - UdpStack(int testmode, struct sockaddr_in &local) { return; } - UdpStack(struct sockaddr_in &local) { return; } - - /* from pqiNetListener */ -virtual bool resetAddress(struct sockaddr_in &local) { return false; } - -}; - -#endif -/*******************************************************/ - -#include "pqi/pqimonitor.h" -#include "util/rsnet.h" -#include "util/stacktrace.h" - -#include - -class rsUdpStack: public UdpStack, public pqiNetListener -{ -public: - rsUdpStack(struct sockaddr_in &local) : UdpStack(local) {} - - rsUdpStack(int testmode, struct sockaddr_in &local) : - UdpStack(testmode, local) {} - - /// @see pqiNetListener - virtual bool resetListener(const sockaddr_storage& local) - { - sockaddr_storage temp; - sockaddr_storage_copy(local, temp); - - if (!sockaddr_storage_ipv6_to_ipv4(temp)) - { - std::cerr << __PRETTY_FUNCTION__ << " Got non IPv4 address ERROR" - << std::endl; - sockaddr_storage_dump(local); - print_stacktrace(); - return -EINVAL; - } - - sockaddr_in *addr = reinterpret_cast(&temp); - return resetAddress(*addr); - } -}; - -class rsFixedUdpStack: public UdpStack, public pqiNetListener -{ - public: - rsFixedUdpStack(struct sockaddr_in &local) - :UdpStack(local) { return; } - - rsFixedUdpStack(int testmode, struct sockaddr_in &local) - :UdpStack(testmode, local) { return; } - - /* from pqiNetListener */ -virtual bool resetListener(const struct sockaddr_storage & /* local */) - { - struct sockaddr_in addr; - getLocalAddress(addr); - - // The const_cast below is not so nice but without it, the compiler can't - // find the correct operator<<(). No idea why! - //std::cerr << "rsFixedUdpStack::resetListener(" << sockaddr_storage_tostring(local) << ")"; - //std::cerr << " Resetting with original addr: " << const_cast(addr); - //std::cerr << std::endl; - - return resetAddress(addr); - } - -}; - -#endif diff --git a/libretroshare/src/tcponudp/tcppacket.cc b/libretroshare/src/tcponudp/tcppacket.cc deleted file mode 100644 index 2da199288..000000000 --- a/libretroshare/src/tcponudp/tcppacket.cc +++ /dev/null @@ -1,262 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: tcppacket.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "tcppacket.h" - -/* - * #include - */ - -#include "util/rsnet.h" /* for winsock.h -> htons etc */ - -#include -#include -#include - -#include - -/* NOTE That these BIT #defines will only - * work on little endian machines.... - * due to the ntohs ... - */ - -/* flags 16bit is: - * - * || 0 1 2 3 | 4 5 6 7 || 8 9 | 10 11 12 13 14 15 || - * <- HLen -> <--- unused ---> <---- flags -------> - * URG PSH SYN - * ACK RST FIN - * - * - * So in little endian world. - * 0 & 1 -> unused... - * URG -> bit 2 => 0x0004 - * ACK -> bit 3 => 0x0008 - * PSH -> bit 4 => 0x0010 - * RST -> bit 5 => 0x0020 - * SYN -> bit 6 => 0x0040 - * FIN -> bit 7 => 0x0080 - * - * and second byte 0-3 -> hlen, 4-7 unused. - */ - -#define TCP_URG_BIT 0x0004 -#define TCP_ACK_BIT 0x0008 -#define TCP_PSH_BIT 0x0010 -#define TCP_RST_BIT 0x0020 -#define TCP_SYN_BIT 0x0040 -#define TCP_FIN_BIT 0x0080 - - -TcpPacket::TcpPacket(uint8 *ptr, int size) - :data(0), datasize(0), seqno(0), ackno(0), hlen_flags(0), - winsize(0), ts(0), retrans(0) - { - if (size > 0) - { - datasize = size; - data = (uint8 *) rs_malloc(datasize); - - if(data != NULL) - memcpy(data, (void *) ptr, size); - } - return; - } - -TcpPacket::TcpPacket() /* likely control packet */ - :data(0), datasize(0), seqno(0), ackno(0), hlen_flags(0), - winsize(0), ts(0), retrans(0) - { - return; - } - - -TcpPacket::~TcpPacket() - { - if (data) - free(data); - } - - -int TcpPacket::writePacket(void *buf, int &size) -{ - if (size < TCP_PSEUDO_HDR_SIZE + datasize) - { - size = 0; - return -1; - } - - /* byte: 0 => uint16 srcport = 0 */ - *((uint16 *) &(((uint8 *) buf)[0])) = htons(0); - - /* byte: 2 => uint16 destport = 0 */ - *((uint16 *) &(((uint8 *) buf)[2])) = htons(0); - - /* byte: 4 => uint32 seqno */ - *((uint32 *) &(((uint8 *) buf)[4])) = htonl(seqno); - - /* byte: 8 => uint32 ackno */ - *((uint32 *) &(((uint8 *) buf)[8])) = htonl(ackno); - - /* byte: 12 => uint16 len + flags */ - *((uint16 *) &(((uint8 *) buf)[12])) = htons(hlen_flags); - - /* byte: 14 => uint16 winsize */ - *((uint16 *) &(((uint8 *) buf)[14])) = htons(winsize); - - /* byte: 16 => uint16 chksum */ - *((uint16 *) &(((uint8 *) buf)[16])) = htons(0); - - /* byte: 18 => uint16 urgptr */ - *((uint16 *) &(((uint8 *) buf)[18])) = htons(0); - - /* total 20 bytes */ - - /* now the data */ - memcpy((void *) &(((uint8 *) buf)[20]), data, datasize); - - return size = TCP_PSEUDO_HDR_SIZE + datasize; -} - - -int TcpPacket::readPacket(void *buf, int size) -{ - if (size < TCP_PSEUDO_HDR_SIZE) - { - std::cerr << "TcpPacket::readPacket() Failed Too Small!"; - std::cerr << std::endl; - return -1; - } - - /* byte: 0 => uint16 srcport = 0 ******************* - *((uint16 *) &(((uint8 *) buf)[0])) = htons(0); - ***********/ - - /* byte: 2 => uint16 destport = 0 ****************** - *((uint16 *) &(((uint8 *) buf)[2])) = htons(0); - ***********/ - - /* byte: 4 => uint32 seqno */ - seqno = ntohl( *((uint32 *) &(((uint8 *) buf)[4])) ); - - /* byte: 8 => uint32 ackno */ - ackno = ntohl( *((uint32 *) &(((uint8 *) buf)[8])) ); - - /* byte: 12 => uint16 len + flags */ - hlen_flags = ntohs( *((uint16 *) &(((uint8 *) buf)[12])) ); - - /* byte: 14 => uint16 winsize */ - winsize = ntohs( *((uint16 *) &(((uint8 *) buf)[14])) ); - - /* byte: 16 => uint16 chksum ************************* - *((uint16 *) &(((uint8 *) buf)[16])) = htons(0); - ***********/ - - /* byte: 18 => uint16 urgptr ************************* - *((uint16 *) &(((uint8 *) buf)[18])) = htons(0); - ***********/ - - /* total 20 bytes */ - - if (data) - { - free(data); - data = NULL ; - } - datasize = size - TCP_PSEUDO_HDR_SIZE; - - // this happens for control packets (e.g. syn/ack/fin) - if(datasize == 0) - { - // data is already NULL - // just return packet size - return size; - } - - data = (uint8 *) rs_malloc(datasize); - - if(data == NULL) - { - // malloc failed! - // return 0 to drop packet (will be retransmitted eventually) - return 0 ; - } - - /* now the data */ - memcpy(data, (void *) &(((uint8 *) buf)[20]), datasize); - - return size; -} - - /* flags */ -bool TcpPacket::hasSyn() -{ - return (hlen_flags & TCP_SYN_BIT); -} - -bool TcpPacket::hasFin() -{ - return (hlen_flags & TCP_FIN_BIT); -} - -bool TcpPacket::hasAck() -{ - return (hlen_flags & TCP_ACK_BIT); -} - -bool TcpPacket::hasRst() -{ - return (hlen_flags & TCP_RST_BIT); -} - - -void TcpPacket::setSyn() -{ - hlen_flags |= TCP_SYN_BIT; -} - -void TcpPacket::setFin() -{ - hlen_flags |= TCP_FIN_BIT; -} - -void TcpPacket::setRst() -{ - hlen_flags |= TCP_RST_BIT; -} - -void TcpPacket::setAckFlag() -{ - hlen_flags |= TCP_ACK_BIT; -} - -void TcpPacket::setAck(uint32 val) -{ - setAckFlag(); - ackno = val; -} - -uint32 TcpPacket::getAck() -{ - return ackno; -} - - diff --git a/libretroshare/src/tcponudp/tcppacket.h b/libretroshare/src/tcponudp/tcppacket.h deleted file mode 100644 index e87c3e394..000000000 --- a/libretroshare/src/tcponudp/tcppacket.h +++ /dev/null @@ -1,91 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: tcppacket.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef TOU_TCP_PACKET_H -#define TOU_TCP_PACKET_H - -#include - - -typedef unsigned int uint32; -typedef unsigned short uint16; -typedef unsigned char uint8; - -#define TCP_PSEUDO_HDR_SIZE 20 - -class TcpPacket -{ - public: - - uint8 *data; - int datasize; - - - /* ports aren't needed -> in udp - * uint16 srcport, destport - **************************/ - uint32 seqno, ackno; - uint16 hlen_flags; - uint16 winsize; - /* don't need these -> in udp + not supported - uint16 chksum, urgptr; - **************************/ - /* no options. - **************************/ - - - /* other variables */ - double ts; /* transmit time */ - uint16 retrans; /* retransmit counter */ - - TcpPacket(uint8 *ptr, int size); - TcpPacket(); /* likely control packet */ - ~TcpPacket(); - -int writePacket(void *buf, int &size); -int readPacket(void *buf, int size); - -void *getData(); -void *releaseData(); - -void *setData(void *data, int size); -int getDataSize(); - - /* flags */ -bool hasSyn(); -bool hasFin(); -bool hasAck(); -bool hasRst(); - -void setSyn(); -void setFin(); -void setRst(); -void setAckFlag(); - -void setAck(uint32 val); -uint32 getAck(); - - -}; - - -#endif - diff --git a/libretroshare/src/tcponudp/tcpstream.cc b/libretroshare/src/tcponudp/tcpstream.cc deleted file mode 100644 index 439f98854..000000000 --- a/libretroshare/src/tcponudp/tcpstream.cc +++ /dev/null @@ -1,2792 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: tcpstream.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include -#include - -#include "tcpstream.h" -#include -#include -#include -#include -#include -#include - -#include -#include "util/rstime.h" - -/* Debugging for STATE change, and Startup SYNs */ -#include "util/rsdebug.h" -#include "util/rsstring.h" -#include "util/rsrandom.h" - -static struct RsLog::logInfo rstcpstreamzoneInfo = {RsLog::Default, "rstcpstream"}; -#define rstcpstreamzone &rstcpstreamzoneInfo - -/* - * #define DEBUG_TCP_STREAM 1 - * #define DEBUG_TCP_STREAM_RETRANS 1 - * #define DEBUG_TCP_STREAM_CLOSE 1 - */ - -//#define DEBUG_TCP_STREAM_RETRANS 1 -//#define DEBUG_TCP_STREAM_CLOSE 1 - -/* - *#define DEBUG_TCP_STREAM_EXTRA 1 - */ - -/* - * #define TCP_NO_PARTIAL_READ 1 - */ - -#ifdef DEBUG_TCP_STREAM -int checkData(uint8 *data, int size, int idx); -int setupBinaryCheck(std::string fname); -#endif - -static const uint32 kMaxQueueSize = 300; // Was 100, which means max packet size of 100k (smaller than max packet size). -static const uint32 kMaxPktRetransmit = 10; -static const uint32 kMaxSynPktRetransmit = 100; // 100 => 200secs = over 3 minutes startup -static const int TCP_STD_TTL = 64; -static const int TCP_DEFAULT_FIREWALL_TTL = 4; - -static const double RTT_ALPHA = 0.875; - -int dumpPacket(std::ostream &out, unsigned char *pkt, uint32_t size); - -// platform independent fractional timestamp. -static double getCurrentTS(); - -TcpStream::TcpStream(UdpSubReceiver *lyr) - : tcpMtx("TcpStream"), inSize(0), outSizeRead(0), outSizeNet(0), - state(TCP_CLOSED), - inStreamActive(false), - outStreamActive(false), - outSeqno(0), outAcked(0), outWinSize(0), - inAckno(0), inWinSize(0), - maxWinSize(TCP_MAX_WIN), - keepAliveTimeout(TCP_ALIVE_TIMEOUT), - retransTimerOn(false), - retransTimeout(TCP_RETRANS_TIMEOUT), - retransTimerTs(0), - keepAliveTimer(0), - lastIncomingPkt(0), - lastSentAck(0), - lastSentWinSize(0), - initOurSeqno(0), - initPeerSeqno(0), - lastWriteTF(0),lastReadTF(0), - wcount(0), rcount(0), - errorState(0), - /* retranmission variables - init to large */ - rtt_est(TCP_RETRANS_TIMEOUT), - rtt_dev(0), - congestThreshold(TCP_MAX_WIN), - congestWinSize(MAX_SEG), - congestUpdate(0), - ttl(0), - mTTL_period(0), - mTTL_start(0), - mTTL_end(0), - peerKnown(false), - udp(lyr) -{ - sockaddr_clear(&peeraddr); - - return; -} - -/* Stream Control! */ -int TcpStream::connect(const struct sockaddr_in &raddr, uint32_t conn_period) -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - setRemoteAddress(raddr); - - /* check state */ - if (state != TCP_CLOSED) - { - if (state == TCP_ESTABLISHED) - { - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return 0; - } - else if (state < TCP_ESTABLISHED) - { - errorState = EAGAIN; - } - else - { - // major issues! - errorState = EFAULT; - } - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return -1; - } - - /* setup Seqnos */ - outSeqno = genSequenceNo(); - initOurSeqno = outSeqno; - - outAcked = outSeqno; /* min - 1 expected */ - inWinSize = maxWinSize; - - congestThreshold = TCP_MAX_WIN; - congestWinSize = MAX_SEG; - congestUpdate = outAcked + congestWinSize; - - /* Init Connection */ - /* send syn packet */ - TcpPacket *pkt = new TcpPacket(); - pkt -> setSyn(); - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::connect() Send Init Pkt" << std::endl; -#endif - - - /* ********* SLOW START ************* - * As this is the only place where a syn - * is sent ..... we switch the ttl to 0, - * and increment it as we retransmit the packet.... - * This should help the firewalls along. - */ - - setTTL(1); - - mTTL_start = getCurrentTS(); - mTTL_period = conn_period; - mTTL_end = mTTL_start + mTTL_period; - - toSend(pkt); - /* change state */ - state = TCP_SYN_SENT; - errorState = EAGAIN; - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream STATE -> TCP_SYN_SENT" << std::endl; -#endif - { - rslog(RSL_WARNING,rstcpstreamzone,"TcpStream::state => TCP_SYN_SENT (Connect)"); - } - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - - return -1; -} - - -int TcpStream::listenfor(const struct sockaddr_in &raddr) -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - setRemoteAddress(raddr); - - /* check state */ - if (state != TCP_CLOSED) - { - if (state == TCP_ESTABLISHED) - { - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return 0; - } - else if (state < TCP_ESTABLISHED) - { - errorState = EAGAIN; - } - else - { - // major issues! - errorState = EFAULT; - } - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return -1; - } - - errorState = EAGAIN; - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return -1; -} - - -/* Stream Control! */ -int TcpStream::close() -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - cleanup(); - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return 0; -} - -int TcpStream::closeWrite() -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - /* check state */ - /* will always close socket.... */ - /* if in TCP_ESTABLISHED.... - * -> to state: TCP_FIN_WAIT_1 - * and shutdown outward stream. - */ - - /* if in CLOSE_WAIT.... - * -> to state: TCP_LAST_ACK - * and shutdown outward stream. - * do this one first!. - */ - - outStreamActive = false; - - if (state == TCP_CLOSE_WAIT) - { - /* don't think we need to be - * graceful at this point... - * connection already closed by other end. - * XXX might fix later with scheme - * - * flag stream closed, and when outqueue - * emptied then fin will be sent. - */ - - /* do nothing */ - } - - if (state == TCP_ESTABLISHED) - { - /* fire off the damned thing. */ - /* by changing state */ - - /* again this is handled by internals - * the flag however indicates that - * no more data can be send, - * and once the queue empties - * the FIN will be sent. - */ - - } - if (state == TCP_CLOSED) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::close() Flag Set" << std::endl; -#endif - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return 0; - } - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::close() pending" << std::endl; -#endif - errorState = EAGAIN; - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return -1; -} - -bool TcpStream::isConnected() -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - bool isConn = (state == TCP_ESTABLISHED); - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - - return isConn; -} - -int TcpStream::status(std::ostream &out) -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - int s = status_locked(out); - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - - return s; -} - - -int TcpStream::status_locked(std::ostream &out) -{ - - int tmpstate = state; - - // can leave the timestamp here as time()... rough but okay. - out << "TcpStream::status @ (" << time(NULL) << ")" << std::endl; - out << "TcpStream::state = " << (int) state << std::endl; - out << std::endl; - out << "writeBuffer: " << inSize << " + MAX_SEG * " << inQueue.size(); - out << " bytes Queued for transmission" << std::endl; - out << "readBuffer: " << outSizeRead << " + MAX_SEG * "; - out << outQueue.size() << " + " << outSizeNet; - out << " incoming bytes waiting" << std::endl; - out << std::endl; - out << "inPkts: " << inPkt.size() << " packets waiting for processing"; - out << std::endl; - out << "outPkts: " << outPkt.size() << " packets waiting for acks"; - out << std::endl; - out << "us -> peer: nextSeqno: " << outSeqno << " lastAcked: " << outAcked; - out << " winsize: " << outWinSize; - out << std::endl; - out << "peer -> us: Expected SeqNo: " << inAckno; - out << " winsize: " << inWinSize; - out << std::endl; - out << std::endl; - - return tmpstate; -} - -int TcpStream::write_allowed() -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - int ret = 1; - if (state == TCP_CLOSED) - { - errorState = EBADF; - ret = -1; - } - else if (state < TCP_ESTABLISHED) - { - errorState = EAGAIN; - ret = -1; - } - else if (!outStreamActive) - { - errorState = EBADF; - ret = -1; - } - - if (ret < 1) - { - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return ret; - } - - int maxwrite = (kMaxQueueSize - inQueue.size()) * MAX_SEG; - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return maxwrite; -} - -int TcpStream::read_pending() -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - /* error should be detected next time */ - int maxread = int_read_pending(); - if (state == TCP_CLOSED) - { - errorState = EBADF; - maxread = -1; - } - else if (state < TCP_ESTABLISHED) - { - errorState = EAGAIN; - maxread = -1; - } - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - - return maxread; -} - -/* INTERNAL */ -int TcpStream::int_read_pending() -{ - return outSizeRead + outQueue.size() * MAX_SEG + outSizeNet; -} - - - /* stream Interface */ -int TcpStream::write(char *dta, int size) /* write -> pkt -> net */ -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - int ret = 1; /* initial error checking */ - -#ifdef DEBUG_TCP_STREAM_EXTRA -static uint32 TMPtotalwrite = 0; -#endif - - if (state == TCP_CLOSED) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::write() Error TCP_CLOSED" << std::endl; -#endif - errorState = EBADF; - ret = -1; - } - else if (state < TCP_ESTABLISHED) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::write() Error TCP Not Established" << std::endl; -#endif - errorState = EAGAIN; - ret = -1; - } - else if (inQueue.size() > kMaxQueueSize) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::write() Error EAGAIN" << std::endl; -#endif - errorState = EAGAIN; - ret = -1; - } - else if (!outStreamActive) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::write() Error TCP_CLOSED" << std::endl; -#endif - errorState = EBADF; - ret = -1; - } - - if (ret < 1) /* check for initial error */ - { - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return ret; - } - - -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::write() = Will Succeed " << size << std::endl; - std::cerr << "TcpStream::write() Write Start: " << TMPtotalwrite << std::endl; - std::cerr << printPktOffset(TMPtotalwrite, dta, size) << std::endl; - TMPtotalwrite += size; -#endif - - - if (size + inSize < MAX_SEG) - { -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::write() Add Itty Bit" << std::endl; - std::cerr << "TcpStream::write() inData: " << (void *) inData; - std::cerr << " inSize: " << inSize << " dta: " << (void *) dta; - std::cerr << " size: " << size << " dest: " << (void *) &(inData[inSize]); - std::cerr << std::endl; -#endif -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::write() = " << size << std::endl; -#endif - memcpy((void *) &(inData[inSize]), dta, size); - inSize += size; - //std::cerr << "Small Packet - write to net:" << std::endl; - //std::cerr << printPkt(dta, size) << std::endl; - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return size; - } - - /* otherwise must construct a dataBuffer. - */ - -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::write() filling 1 dataBuffer" << std::endl; - std::cerr << "TcpStream::write() from inData(" << inSize << ")" << std::endl; - std::cerr << "TcpStream::write() + dta(" << MAX_SEG - inSize; - std::cerr << "/" << size << ")" << std::endl; -#endif - - /* first create 1. */ - dataBuffer *db = new dataBuffer; - memcpy((void *) db->data, (void *) inData, inSize); - - - int remSize = size; - memcpy((void *) &(db->data[inSize]), dta, MAX_SEG - inSize); - - inQueue.push_back(db); - remSize -= (MAX_SEG - inSize); - -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::write() remaining " << remSize << " bytes to load" << std::endl; -#endif - - while(remSize >= MAX_SEG) - { -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::write() filling whole dataBuffer" << std::endl; - std::cerr << "TcpStream::write() from dta[" << size-remSize << "]" << std::endl; -#endif - db = new dataBuffer; - memcpy((void *) db->data, (void *) &(dta[size-remSize]), MAX_SEG); - - inQueue.push_back(db); - remSize -= MAX_SEG; - } - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::write() = " << size << std::endl; -#endif - - if (remSize > 0) - { - -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::write() putting last bit in inData" << std::endl; - std::cerr << "TcpStream::write() from dta[" << size-remSize << "] size: "; - std::cerr << remSize << std::endl; -#endif - memcpy((void *) inData, (void *) &(dta[size-remSize]), remSize); - inSize = remSize; - } - else - { - -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::write() Data fitted exactly in dataBuffer!" << std::endl; -#endif - inSize = 0; - } - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return size; -} - -int TcpStream::read(char *dta, int size) /* net -> pkt -> read */ -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - -#ifdef DEBUG_TCP_STREAM_EXTRA -static uint32 TMPtotalread = 0; -#endif - /* max available data is - * outDataRead + outQueue + outDataNet - */ - - int maxread = outSizeRead + outQueue.size() * MAX_SEG + outSizeNet; - int ret = 1; /* used only for initial errors */ - - if (state == TCP_CLOSED) - { - errorState = EBADF; - ret = -1; - } - else if (state < TCP_ESTABLISHED) - { - errorState = EAGAIN; - ret = -1; - } - else if ((!inStreamActive) && (maxread == 0)) - { - // finished stream. - ret = 0; - } - else if (maxread == 0) - { - /* must wait for more data */ - errorState = EAGAIN; - ret = -1; - } - - if (ret < 1) /* if ret has been changed */ - { - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return ret; - } - - if (maxread < size) - { -#ifdef TCP_NO_PARTIAL_READ - if (inStreamActive) - { - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::read() No Partial Read! "; - std::cerr << "Can only supply " << maxread << " of "; - std::cerr << size; - std::cerr << std::endl; -#endif - errorState = EAGAIN; - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return -1; - } -#endif /* TCP_NO_PARTIAL_READ */ - size = maxread; - } - - /* if less than outDataRead size */ - if (((unsigned) (size) < outSizeRead) && (outSizeRead)) - { -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::read() Add Itty Bit" << std::endl; - std::cerr << "TcpStream::read() outSizeRead: " << outSizeRead; - std::cerr << " size: " << size << " remaining: " << outSizeRead - size; - std::cerr << std::endl; -#endif - memcpy(dta,(void *) outDataRead, size); - memmove((void *) outDataRead, - (void *) &(outDataRead[size]), outSizeRead - (size)); - outSizeRead -= size; - - -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::read() = Succeeded " << size << std::endl; - std::cerr << "TcpStream::read() Read Start: " << TMPtotalread << std::endl; - std::cerr << printPktOffset(TMPtotalread, dta, size) << std::endl; -#endif - -#ifdef DEBUG_TCP_STREAM_EXTRA - checkData((uint8 *) dta, size, TMPtotalread); - TMPtotalread += size; -#endif - - /* can allow more in! - update inWinSize */ - UpdateInWinSize(); - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return size; - } - - /* move the whole of outDataRead. */ - if (outSizeRead) - { -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::read() Move All outSizeRead" << std::endl; - std::cerr << "TcpStream::read() outSizeRead: " << outSizeRead; - std::cerr << " size: " << size; - std::cerr << std::endl; -#endif - memcpy(dta,(void *) outDataRead, outSizeRead); - - } - - int remSize = size - outSizeRead; - outSizeRead = 0; - -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::read() remaining size: " << remSize << std::endl; -#endif - - while((outQueue.size() > 0) && (remSize > 0)) - { - dataBuffer *db = outQueue.front(); - outQueue.pop_front(); /* remove */ - -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::read() Taking Data from outQueue" << std::endl; -#endif - - /* load into outDataRead */ - if (remSize < MAX_SEG) - { -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::read() Partially using Segment" << std::endl; - std::cerr << "TcpStream::read() moving: " << remSize << " to dta @: " << size-remSize; - std::cerr << std::endl; - std::cerr << "TcpStream::read() rest to outDataRead: " << MAX_SEG - remSize; - std::cerr << std::endl; -#endif - memcpy((void *) &(dta[(size)-remSize]), (void *) db->data, remSize); - memcpy((void *) outDataRead, (void *) &(db->data[remSize]), MAX_SEG - remSize); - outSizeRead = MAX_SEG - remSize; - - delete db; - - -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::read() = Succeeded " << size << std::endl; - std::cerr << "TcpStream::read() Read Start: " << TMPtotalread << std::endl; - std::cerr << printPktOffset(TMPtotalread, dta, size) << std::endl; -#endif - -#ifdef DEBUG_TCP_STREAM_EXTRA - checkData((uint8 *) dta, size, TMPtotalread); - TMPtotalread += size; -#endif - - /* can allow more in! - update inWinSize */ - UpdateInWinSize(); - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return size; - } -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::read() Move Whole Segment to dta @ " << size-remSize << std::endl; -#endif - - /* else copy whole segment */ - memcpy((void *) &(dta[(size)-remSize]), (void *) db->data, MAX_SEG); - remSize -= MAX_SEG; - delete db; - } - - /* assumes that outSizeNet >= remSize due to initial - * constraint - */ - if ((remSize > 0)) - { -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::read() Using up : " << remSize; - std::cerr << " last Bytes, leaving: " << outSizeNet - remSize << std::endl; -#endif - - - memcpy((void *) &(dta[(size)-remSize]),(void *) outDataNet, remSize); - outSizeNet -= remSize; - if (outSizeNet > 0) - { - /* move to the outDataRead */ - memcpy((void *) outDataRead,(void *) &(outDataNet[remSize]), outSizeNet); - outSizeRead = outSizeNet; - outSizeNet = 0; -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::read() moving last of outSizeNet to outSizeRead: " << outSizeRead; - std::cerr << std::endl; -#endif - - } - - -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::read() = Succeeded " << size << std::endl; - std::cerr << "TcpStream::read() Read Start: " << TMPtotalread << std::endl; - std::cerr << printPktOffset(TMPtotalread, dta, size) << std::endl; -#endif - -#ifdef DEBUG_TCP_STREAM_EXTRA - checkData((uint8 *) dta, size, TMPtotalread); - TMPtotalread += size; -#endif - - /* can allow more in! - update inWinSize */ - UpdateInWinSize(); - - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return size; - } - -#ifdef DEBUG_TCP_STREAM_EXTRA - std::cerr << "TcpStream::read() = Succeeded " << size << std::endl; - std::cerr << "TcpStream::read() Read Start: " << TMPtotalread << std::endl; - std::cerr << printPktOffset(TMPtotalread, dta, size) << std::endl; -#endif - -#ifdef DEBUG_TCP_STREAM_EXTRA - checkData((uint8 *) dta, size, TMPtotalread); - TMPtotalread += size; -#endif - - /* can allow more in! - update inWinSize */ - UpdateInWinSize(); - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return size; -} - - - /* Callback from lower Layers */ -void TcpStream::recvPkt(void *data, int size) -{ -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::recvPkt()"; - std::cerr << std::endl; -#endif - - tcpMtx.lock(); /********** LOCK MUTEX *********/ - uint8 *input = (uint8 *) data; - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::recvPkt() Past Lock!"; - std::cerr << std::endl; -#endif - -#ifdef DEBUG_TCP_STREAM - if (state > TCP_SYN_RCVD) - { - int availRead = outSizeRead + outQueue.size() * MAX_SEG + outSizeNet; - std::cerr << "TcpStream::recvPkt() CC: "; - std::cerr << " iWS: " << inWinSize; - std::cerr << " aRead: " << availRead; - std::cerr << " iAck: " << inAckno; - std::cerr << std::endl; - } - else - { - std::cerr << "TcpStream::recv() Not Connected"; - std::cerr << std::endl; - } -#endif - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::recv() ReadPkt(" << size << ")" << std::endl; - //std::cerr << printPkt(input, size); - //std::cerr << std::endl; -#endif - TcpPacket *pkt = new TcpPacket(); - if (0 < pkt -> readPacket(input, size)) - { - lastIncomingPkt = getCurrentTS(); - handleIncoming(pkt); - } - else - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::recv() Bad Packet Deleting!"; - std::cerr << std::endl; -#endif - delete pkt; - } - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return; -} - - -int TcpStream::tick() -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - //std::cerr << "TcpStream::tick()" << std::endl; - recv_check(); /* recv is async */ - send(); - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - - return 1; -} - -bool TcpStream::getRemoteAddress(struct sockaddr_in &raddr) -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - if (peerKnown) - { - raddr = peeraddr; - } - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - - return peerKnown; -} - -uint8 TcpStream::TcpState() -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - uint8 err = state; - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - - return err; -} - -int TcpStream::TcpErrorState() -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - int err = errorState; - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - - return err; -} - - - -/********************* SOME EXPOSED DEBUGGING FNS ******************/ - -static int ilevel = 100; - -bool TcpStream::widle() -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - /* init */ - if (!lastWriteTF) - { - lastWriteTF = int_wbytes(); - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return false; - } - - if ((lastWriteTF == int_wbytes()) && (inSize == 0) && inQueue.empty()) - { - wcount++; - if (wcount > ilevel) - { - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return true; - } - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return false; - } - wcount = 0; - lastWriteTF = int_wbytes(); - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return false; -} - - -bool TcpStream::ridle() -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - /* init */ - if (!lastReadTF) - { - lastReadTF = int_rbytes(); - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return false; - } - - if ((lastReadTF == int_rbytes()) && (outSizeRead + outQueue.size() + outSizeNet== 0)) - { - rcount++; - if (rcount > ilevel) - { - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return true; - } - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return false; - } - rcount = 0; - lastReadTF = int_rbytes(); - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return false; -} - -uint32 TcpStream::wbytes() -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - uint32 wb = int_wbytes(); - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return wb; -} - -uint32 TcpStream::rbytes() -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - uint32 rb = int_rbytes(); - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - return rb; -} - -/********************* ALL BELOW HERE IS INTERNAL ****************** - ******************* AND ALWAYS PROTECTED BY A MUTEX ***************/ - -int TcpStream::recv_check() -{ - double cts = getCurrentTS(); // fractional seconds. - -#ifdef DEBUG_TCP_STREAM - if (state > TCP_SYN_RCVD) - { - int availRead = outSizeRead + outQueue.size() * MAX_SEG + outSizeNet; - std::cerr << "TcpStream::recv_check() CC: "; - std::cerr << " iWS: " << inWinSize; - std::cerr << " aRead: " << availRead; - std::cerr << " iAck: " << inAckno; - std::cerr << std::endl; - } - else - { - std::cerr << "TcpStream::recv_check() Not Connected"; - std::cerr << std::endl; - } -#endif - - // make sure we've rcvd something! - if ((state > TCP_SYN_RCVD) && - (cts - lastIncomingPkt > kNoPktTimeout)) - { - /* shut it all down */ - /* this period should be equivalent - * to the firewall timeouts ??? - * - * for max efficiency - */ - -#ifdef DEBUG_TCP_STREAM_CLOSE - std::cerr << "TcpStream::recv_check() state = CLOSED (NoPktTimeout)"; - std::cerr << std::endl; - dumpstate_locked(std::cerr); -#endif - - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_CLOSED (kNoPktTimeout)"); - - outStreamActive = false; - inStreamActive = false; - state = TCP_CLOSED; - cleanup(); - } - return 1; -} - -int TcpStream::cleanup() -{ - // This shuts it all down! no matter what. - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::cleanup() state = TCP_CLOSED"); - - outStreamActive = false; - inStreamActive = false; - state = TCP_CLOSED; - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream STATE -> TCP_CLOSED" << std::endl; -#endif - - //peerKnown = false; //??? NOT SURE -> for a rapid reconnetion this might be key?? - - /* reset TTL */ - setTTL(TCP_STD_TTL); - - // clear arrays. - inSize = 0; - while(inQueue.size() > 0) - { - dataBuffer *db = inQueue.front(); - inQueue.pop_front(); - delete db; - } - - while(outPkt.size() > 0) - { - TcpPacket *pkt = outPkt.front(); - outPkt.pop_front(); - delete pkt; - } - - - // clear arrays. - outSizeRead = 0; - outSizeNet = 0; - while(outQueue.size() > 0) - { - dataBuffer *db = outQueue.front(); - outQueue.pop_front(); - delete db; - } - - while(inPkt.size() > 0) - { - TcpPacket *pkt = inPkt.front(); - inPkt.pop_front(); - delete pkt; - } - return 1; -} - -int TcpStream::handleIncoming(TcpPacket *pkt) -{ -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::handleIncoming()" << std::endl; -#endif - switch(state) - { - case TCP_CLOSED: - case TCP_LISTEN: - /* if receive SYN - * -> respond SYN/ACK - * To State: SYN_RCVD - * - * else Discard. - */ - return incoming_Closed(pkt); - break; - case TCP_SYN_SENT: - /* if receive SYN - * -> respond SYN/ACK - * To State: SYN_RCVD - * - * if receive SYN+ACK - * -> respond ACK - * To State: TCP_ESTABLISHED - * - * else Discard. - */ - return incoming_SynSent(pkt); - break; - case TCP_SYN_RCVD: - /* if receive ACK - * To State: TCP_ESTABLISHED - */ - return incoming_SynRcvd(pkt); - break; - case TCP_ESTABLISHED: - /* if receive FIN - * -> respond ACK - * To State: TCP_CLOSE_WAIT - * else Discard. - */ - return incoming_Established(pkt); - break; - case TCP_FIN_WAIT_1: - /* state entered by close() call. - * if receive FIN - * -> respond ACK - * To State: TCP_CLOSING - * - * if receive ACK - * -> no response - * To State: TCP_FIN_WAIT_2 - * - * if receive FIN+ACK - * -> respond ACK - * To State: TCP_TIMED_WAIT - * - */ - return incoming_Established(pkt); - //return incoming_FinWait1(pkt); - break; - case TCP_FIN_WAIT_2: - /* if receive FIN - * -> respond ACK - * To State: TCP_TIMED_WAIT - */ - return incoming_Established(pkt); - //return incoming_FinWait2(pkt); - break; - case TCP_CLOSING: - /* if receive ACK - * To State: TCP_TIMED_WAIT - */ - /* all handled in Established */ - return incoming_Established(pkt); - //return incoming_Closing(pkt); - break; - case TCP_CLOSE_WAIT: - /* - * wait for our close to be called. - */ - /* all handled in Established */ - return incoming_Established(pkt); - //return incoming_CloseWait(pkt); - break; - case TCP_LAST_ACK: - /* entered by the local close() after sending FIN. - * if receive ACK - * To State: TCP_CLOSED - */ - /* all handled in Established */ - return incoming_Established(pkt); - /* - return incoming_LastAck(pkt); - */ - - break; - /* this is actually the only - * final state where packets not expected! - */ - case TCP_TIMED_WAIT: - /* State: TCP_TIMED_WAIT - * - * discard all -> both connections FINed - * timeout of this state. - * - */ - -#ifdef DEBUG_TCP_STREAM_CLOSE - std::cerr << "TcpStream::handleIncoming() state = CLOSED (TimedWait)"; - std::cerr << std::endl; - dumpstate_locked(std::cerr); -#endif - - state = TCP_CLOSED; - // return incoming_TimedWait(pkt); - { - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_CLOSED (recvd TCP_TIMED_WAIT?)"); - } - break; - } - delete pkt; - return 1; -} - - -int TcpStream::incoming_Closed(TcpPacket *pkt) -{ - /* if receive SYN - * -> respond SYN/ACK - * To State: SYN_RCVD - * - * else Discard. - */ - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::incoming_Closed()" << std::endl; -#endif - if ((pkt -> hasSyn()) && (!pkt -> hasAck())) - { - /* Init Connection */ - - /* save seqno */ - initPeerSeqno = pkt -> seqno; - inAckno = initPeerSeqno + 1; - outWinSize = pkt -> winsize; - - - inWinSize = maxWinSize; - - /* we can get from SynSent as well, - * but only send one SYN packet - */ - - /* start packet */ - TcpPacket *rsp = new TcpPacket(); - - if (state == TCP_CLOSED) - { - outSeqno = genSequenceNo(); - initOurSeqno = outSeqno; - outAcked = outSeqno; /* min - 1 expected */ - - /* setup Congestion Charging */ - congestThreshold = TCP_MAX_WIN; - congestWinSize = MAX_SEG; - congestUpdate = outAcked + congestWinSize; - - rsp -> setSyn(); - } - - rsp -> setAck(inAckno); - /* seq + winsize set in toSend() */ - - /* as we have received something ... we can up the TTL */ - setTTL(TCP_STD_TTL); - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::incoming_Closed() Sending reply" << std::endl; - std::cerr << "SeqNo: " << rsp->seqno << " Ack: " << rsp->ackno; - std::cerr << std::endl; -#endif - - toSend(rsp); - /* change state */ - state = TCP_SYN_RCVD; - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream STATE -> TCP_SYN_RCVD" << std::endl; -#endif - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_SYN_RECVD (recvd SYN & !ACK)"); - } - - delete pkt; - return 1; -} - - -int TcpStream::incoming_SynSent(TcpPacket *pkt) -{ - /* if receive SYN - * -> respond SYN/ACK - * To State: SYN_RCVD - * - * if receive SYN+ACK - * -> respond ACK - * To State: TCP_ESTABLISHED - * - * else Discard. - */ - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::incoming_SynSent()" << std::endl; -#endif - - if ((pkt -> hasSyn()) && (pkt -> hasAck())) - { - /* check stuff */ - if (pkt -> getAck() != outSeqno) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::incoming_SynSent() Bad Ack - Deleting " << std::endl; -#endif - /* bad ignore */ - delete pkt; - return -1; - } - - /* Complete Connection */ - - /* save seqno */ - initPeerSeqno = pkt -> seqno; - inAckno = initPeerSeqno + 1; - - outWinSize = pkt -> winsize; - - outAcked = pkt -> getAck(); - - /* before ACK, reset the TTL - * As they have sent something, and we have received - * through the firewall, set to STD. - */ - setTTL(TCP_STD_TTL); - - /* ack the Syn Packet */ - sendAck(); - - /* change state */ - state = TCP_ESTABLISHED; - outStreamActive = true; - inStreamActive = true; - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream STATE -> TCP_ESTABLISHED" << std::endl; -#endif - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_ESTABLISHED (recvd SUN & ACK)"); - - delete pkt; - } - else /* same as if closed! (simultaneous open) */ - { - return incoming_Closed(pkt); - } - return 1; -} - - -int TcpStream::incoming_SynRcvd(TcpPacket *pkt) -{ - /* if receive ACK - * To State: TCP_ESTABLISHED - */ - if (pkt -> hasRst()) - { - /* trouble */ - state = TCP_CLOSED; -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream STATE -> TCP_CLOSED" << std::endl; -#endif - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_CLOSED (recvd RST)"); - - delete pkt; - return 1; - } - - bool ackWithData = false; - - if (pkt -> hasAck()) - { - if (pkt -> hasSyn()) - { - /* has resent syn -> check it matches */ -#ifdef DEBUG_TCP_STREAM - std::cerr << "incoming_SynRcvd -> Pkt with ACK + SYN" << std::endl; -#endif - } - - /* check stuff */ - if (pkt -> getAck() != outSeqno) - { - /* bad ignore */ -#ifdef DEBUG_TCP_STREAM - std::cerr << "incoming_SynRcvd -> Ignoring Pkt with bad ACK" << std::endl; -#endif - delete pkt; - return -1; - } - - /* Complete Connection */ - - /* save seqno */ - if (pkt -> datasize > 0) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::incoming_SynRcvd() ACK with Data!" << std::endl; - std::cerr << "TcpStream::incoming_SynRcvd() Shoudn't recv ... unless initACK lost!" << std::endl; -#endif - // managed to trigger this under windows... - // perhaps the initial Ack was lost, - // believe we should just pass this packet - // directly to the incoming_Established... once - // the following has been done. - // and it should all work! - //exit(1); - ackWithData = true; - } - - inAckno = pkt -> seqno; /* + pkt -> datasize; */ - outWinSize = pkt -> winsize; - - outAcked = pkt -> getAck(); - - - /* As they have sent something, and we have received - * through the firewall, set to STD. - */ - setTTL(TCP_STD_TTL); - - /* change state */ - state = TCP_ESTABLISHED; - outStreamActive = true; - inStreamActive = true; -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream STATE -> TCP_ESTABLISHED" << std::endl; -#endif - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_ESTABLISHED (have SYN, recvd ACK)"); - } - - if (ackWithData) - { - /* connection Established -> handle normally */ -#ifdef DEBUG_TCP_STREAM - std::cerr << "incoming_SynRcvd -> Handling Data with Ack Pkt!"; - std::cerr << std::endl; -#endif - incoming_Established(pkt); - } - else - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "incoming_SynRcvd -> Ignoring Pkt!" << std::endl; -#endif - /* else nothing */ - delete pkt; - } - return 1; -} - -int TcpStream::incoming_Established(TcpPacket *pkt) -{ - /* first handle the Ack ... - * this must be done before the queue, - * to keep the values as up-to-date as possible. - * - * must sanity check ..... - * make sure that the sequence number is within the correct range. - */ - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::incoming_Established() "; - std::cerr << " Pkt->seqno: " << std::hex << pkt->seqno; - std::cerr << " Pkt->datasize: " << std::hex << pkt->datasize; - std::cerr << std::dec << std::endl; -#endif - - if ((!isOldSequence(pkt->seqno, inAckno)) && // seq >= inAckno - isOldSequence(pkt->seqno, inAckno + maxWinSize)) // seq < inAckno + maxWinSize. - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::incoming_Established() valid Packet Seqno."; - std::cerr << std::endl; -#endif - if (pkt->hasAck()) - { -#ifdef DEBUG_TCP_STREAM - if (outAcked != pkt->ackno) - { - std::cerr << "TcpStream::incoming_Established() valid Packet Seqno & new Ackno."; - std::cerr << std::endl; - std::cerr << "\tUpdating OutAcked to: " << outAcked; - std::cerr << std::endl; - } -#endif - outAcked = pkt->ackno; - } - - outWinSize = pkt->winsize; - -#ifdef DEBUG_TCP_STREAM - std::cerr << "\tUpdating OutWinSize to: " << outWinSize; - std::cerr << std::endl; -#endif - } - else - { - /* what we do! (This is actually okay - and happens occasionally) */ -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::incoming_Established() ERROR out-of-range Packet Seqno."; - std::cerr << std::endl; - std::cerr << "\t Pkt->SeqNo: " << std::hex << pkt->seqno; - std::cerr << std::endl; - std::cerr << "\t inAckno: " << std::hex << inAckno; - std::cerr << std::endl; - std::cerr << "\t inAckno + maxWinSize: " << std::hex << inAckno + maxWinSize; - std::cerr << std::endl; - std::cerr << "\t outAcked: " << std::hex << outAcked; - std::cerr << std::endl; - std::cerr << "\t Pkt->SeqNo: " << std::hex << pkt->seqno; - std::cerr << std::dec << std::endl; - std::cerr << "\t !isOldSequence(pkt->seqno, inAckno): " << (!isOldSequence(pkt->seqno, inAckno)); - std::cerr << std::endl; - std::cerr << "\t isOldSequence(pkt->seqno, inAckno + maxWinSize): " << isOldSequence(pkt->seqno, inAckno + maxWinSize); - std::cerr << std::endl; - std::cerr << std::endl; - - std::cerr << "TcpStream::incoming_Established() Sending Ack to update Peer"; - std::cerr << std::endl; -#endif - - sendAck(); - } - - - /* add to queue */ - inPkt.push_back(pkt); - - if (inPkt.size() > kMaxQueueSize) - { - TcpPacket *pkt = inPkt.front(); - inPkt.pop_front(); - delete pkt; - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::incoming_Established() inPkt reached max size...Discarding Oldest Pkt"; - std::cerr << std::endl; -#endif - - } - - /* use as many packets as possible */ - return check_InPkts(); -} - -int TcpStream::check_InPkts() -{ - bool found = true; - TcpPacket *pkt; - std::list::iterator it; - while(found) - { - found = false; - for(it = inPkt.begin(); (!found) && (it != inPkt.end());) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "Checking expInAck: " << std::hex << inAckno; - std::cerr << " vs: " << std::hex << (*it)->seqno << std::dec << std::endl; -#endif - - pkt = *it; - if ((*it)->seqno == inAckno) - { - //std::cerr << "\tFOUND MATCH!"; - //std::cerr << std::endl; - - found = true; - it = inPkt.erase(it); - - } - - /* see if we can discard it */ - /* if smaller seqno, and not wrapping around */ - else if (isOldSequence((*it)->seqno, inAckno)) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "Discarding Old Packet expAck: " << std::hex << inAckno; - std::cerr << " seqno: " << std::hex << (*it)->seqno; - std::cerr << " pkt->size: " << std::hex << (*it)->datasize; - std::cerr << " pkt->seqno+size: " << std::hex << (*it)->seqno + (*it)->datasize; - std::cerr << std::dec << std::endl; -#endif - - /* discard */ - it = inPkt.erase(it); - delete pkt; - - } - else - { - ++it; - } - } - if (found) - { - -#ifdef DEBUG_TCP_STREAM_EXTRA - if (pkt->datasize) - { - checkData(pkt->data, pkt->datasize, pkt->seqno-initPeerSeqno-1); - } -#endif - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::check_inPkts() Updating inAckno from: " << std::hex << inAckno; -#endif - - /* update ack number - let it rollover */ - inAckno = pkt->seqno + pkt->datasize; - -#ifdef DEBUG_TCP_STREAM - std::cerr << " to: " << std::hex << inAckno; - std::cerr << std::dec << std::endl; -#endif - - /* XXX This shouldn't be here, as it prevents - * the Ack being used until the packet is. - * This means that a dropped packet will stop traffic in both - * directions.... - * - * Moved it to incoming_Established .... but extra - * check here to be sure! - */ - - if (pkt->hasAck()) - { - if (isOldSequence(outAcked, pkt->ackno)) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::check_inPkts() ERROR Ack Not Already Used!"; - std::cerr << std::endl; - std::cerr << "\t Pkt->ackno: " << std::hex << pkt->ackno; - std::cerr << std::endl; - std::cerr << "\t outAcked: " << std::hex << outAcked; - std::cerr << std::endl; - std::cerr << "\t Pkt->winsize: " << std::hex << pkt->winsize; - std::cerr << std::endl; - std::cerr << "\t outWinSize: " << std::hex << outWinSize; - std::cerr << std::endl; - std::cerr << "\t isOldSequence(outAcked, pkt->ackno): " << isOldSequence(outAcked, pkt->ackno); - std::cerr << std::endl; - std::cerr << std::endl; -#endif - - outAcked = pkt->ackno; - outWinSize = pkt->winsize; - -#ifdef DEBUG_TCP_STREAM - std::cerr << "\tUpdating OutAcked to: " << outAcked; - std::cerr << std::endl; - std::cerr << "\tUpdating OutWinSize to: " << outWinSize; - std::cerr << std::endl; -#endif - - } - else - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::check_inPkts() GOOD Ack Already Used!"; - std::cerr << std::endl; -#endif - } - } - - /* push onto queue */ - - if (outSizeNet + pkt->datasize < MAX_SEG) - { - /* move onto outSizeNet */ - if (pkt->datasize) - { - memcpy((void *) &(outDataNet[outSizeNet]), pkt->data, pkt->datasize); - outSizeNet += pkt->datasize; - } - } - else - { - /* if it'll overflow the buffer. */ - dataBuffer *db = new dataBuffer(); - - /* move outDatNet -> buffer */ - memcpy((void *) db->data, (void *) outDataNet, outSizeNet); - - /* fill rest of space */ - int remSpace = MAX_SEG - outSizeNet; - memcpy((void *) &(db->data[outSizeNet]), (void *) pkt->data, remSpace); - - /* push packet onto queue */ - outQueue.push_back(db); - - /* any big chunks that will take up a full dataBuffer */ - int remData = pkt->datasize - remSpace; - while(remData >= MAX_SEG) - { - db = new dataBuffer(); - memcpy((void *) db->data, (void *) &(pkt->data[remSpace]), MAX_SEG); - - remData -= MAX_SEG; - outQueue.push_back(db); - } - - /* remove any remaining to outDataNet */ - outSizeNet = remData; - if (outSizeNet > 0) - { - memcpy((void *) outDataNet, (void *) &(pkt->data[pkt->datasize - remData]), outSizeNet); - } - } - - /* can allow more in! - update inWinSize */ - UpdateInWinSize(); - - /* if pkt is FIN */ - /* these must be here -> at the end of the reliable stream */ - /* if the fin is set, ack it specially close stream */ - if (pkt->hasFin()) - { - /* send final ack */ - sendAck(); - - /* closedown stream */ - inStreamActive = false; - - if (state == TCP_ESTABLISHED) - { - state = TCP_CLOSE_WAIT; -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::state = TCP_CLOSE_WAIT"; - std::cerr << std::endl; -#endif - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_CLOSE_WAIT (recvd FIN)"); - } - else if (state == TCP_FIN_WAIT_1) - { - state = TCP_CLOSING; -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::state = TCP_CLOSING"; - std::cerr << std::endl; -#endif - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_CLOSING (FIN_WAIT_1, recvd FIN)"); - } - else if (state == TCP_FIN_WAIT_2) - { - state = TCP_TIMED_WAIT; -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::state = TCP_TIMED_WAIT"; - std::cerr << std::endl; -#endif - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_TIMED_WAIT (FIN_WAIT_2, recvd FIN)"); - - cleanup(); - } - } - - /* if ack for our FIN */ - if ((pkt->hasAck()) && (!outStreamActive) - && (pkt->ackno == outSeqno)) - { - if (state == TCP_FIN_WAIT_1) - { - state = TCP_FIN_WAIT_2; -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::state = TCP_FIN_WAIT_2"; - std::cerr << std::endl; -#endif - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_FIN_WAIT_2 (FIN_WAIT_1, recvd ACK)"); - } - else if (state == TCP_LAST_ACK) - { -#ifdef DEBUG_TCP_STREAM_CLOSE - std::cerr << "TcpStream::state = TCP_CLOSED (LastAck)"; - std::cerr << std::endl; - dumpstate_locked(std::cerr); -#endif - - state = TCP_CLOSED; - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_CLOSED (LAST_ACK, recvd ACK)"); - - cleanup(); - } - else if (state == TCP_CLOSING) - { - state = TCP_TIMED_WAIT; -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::state = TCP_TIMED_WAIT"; - std::cerr << std::endl; -#endif - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_TIMED_WAIT (TCP_CLOSING, recvd ACK)"); - - cleanup(); - } - } - - delete pkt; - - } /* end of found */ - } /* while(found) */ - return 1; -} - -/* This Fn should be called after each read, or recvd data (thats added to the buffer) - */ -int TcpStream::UpdateInWinSize() -{ - /* InWinSize = maxWinSze - QueuedData, - * actually we can allow a lot more to queue up... - * inWinSize = 65536, unless QueuedData > 65536. - * inWinSize = 2 * maxWinSize - QueuedData; - * - */ - - uint32 queuedData = int_read_pending(); - if (queuedData < maxWinSize) - { - inWinSize = maxWinSize; - } - else if (queuedData < 2 * maxWinSize) - { - inWinSize = 2 * maxWinSize - queuedData; - } - else - { - inWinSize = 0; - } - return inWinSize; -} - -int TcpStream::sendAck() -{ - /* simple -> toSend fills in ack/winsize - * and the rest is history - */ -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::sendAck()"; - std::cerr << std::endl; -#endif - - return toSend(new TcpPacket(), false); -} - -void TcpStream::setRemoteAddress(const struct sockaddr_in &raddr) -{ - peeraddr = raddr; - peerKnown = true; -} - - -int TcpStream::toSend(TcpPacket *pkt, bool retrans) -{ - int outPktSize = MAX_SEG + TCP_PSEUDO_HDR_SIZE; - char tmpOutPkt[outPktSize]; - - if (!peerKnown) - { - /* Major Error! */ -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::toSend() peerUnknown ERROR!!!"; - std::cerr << std::endl; -#endif - delete pkt; - return 0; - } - - /* get accurate timestamp */ - double cts = getCurrentTS(); - - pkt -> winsize = inWinSize; - pkt -> seqno = outSeqno; - - /* increment seq no */ - if (pkt->datasize) - { -#ifdef DEBUG_TCP_STREAM_EXTRA - checkData(pkt->data, pkt->datasize, outSeqno-initOurSeqno-1); -#endif - outSeqno += pkt->datasize; - } - - if (pkt->hasSyn()) - { - /* should not have data! */ - if (pkt->datasize) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "SYN Packet shouldn't contain data!" << std::endl; -#endif - } - outSeqno++; - } - else - { - /* cannot auto Ack SynPackets */ - pkt -> setAck(inAckno); - } - - pkt -> winsize = inWinSize; - - /* store old info */ - lastSentAck = pkt -> ackno; - lastSentWinSize = pkt -> winsize; - keepAliveTimer = cts; - - pkt -> writePacket(tmpOutPkt, outPktSize); - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::toSend() Seqno: "; - std::cerr << pkt->seqno << " size: " << pkt->datasize; - std::cerr << " Ackno: "; - std::cerr << pkt->ackno << " winsize: " << pkt->winsize; - std::cerr << std::endl; - //std::cerr << printPkt(tmpOutPkt, outPktSize) << std::endl; -#endif - - udp -> sendPkt(tmpOutPkt, outPktSize, peeraddr, ttl); - - if (retrans) - { - /* restart timers */ - pkt -> ts = cts; - pkt -> retrans = 0; - - startRetransmitTimer(); - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::toSend() Adding to outPkt --> Seqno: "; - std::cerr << pkt->seqno << " size: " << pkt->datasize; - std::cerr << std::endl; -#endif - - outPkt.push_back(pkt); - } - else - { - delete pkt; - } - return 1; -} - - -/* single retransmit timer. - * - */ -void TcpStream::startRetransmitTimer() -{ - if (retransTimerOn) - { - return; - } - - retransTimerTs = getCurrentTS(); - retransTimerOn = true; - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::startRetransmitTimer() peer: " << peeraddr; - std::cerr << " retransTimeout: " << retransTimeout; - std::cerr << " retransTimerTs: " << std::setprecision(12) < TCP_RETRANS_MAX_TIMEOUT) - { - retransTimeout = TCP_RETRANS_MAX_TIMEOUT; - } - -#ifdef DEBUG_TCP_STREAM_RETRANS - std::cerr << "TcpStream::incRetransmitTimer() peer: " << peeraddr; - std::cerr << " retransTimeout: " << std::setprecision(12) << retransTimeout; - std::cerr << std::endl; -#endif - -} - - - - - -int TcpStream::retrans() -{ - int outPktSize = MAX_SEG + TCP_PSEUDO_HDR_SIZE; - char tmpOutPkt[outPktSize]; - - if (!peerKnown) - { - /* Major Error! */ -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::retrans() peerUnknown ERROR!!!"; - std::cerr << std::endl; -#endif - return 0; - } - - if (!retransTimerOn) - { - return 0; - } - - double cts = getCurrentTS(); - if (cts - retransTimerTs < retransTimeout) - { - return 0; - } - - if (outPkt.begin() == outPkt.end()) - { - resetRetransmitTimer(); - return 0; - } - - TcpPacket *pkt = outPkt.front(); - - if (!pkt) - { - /* error */ - return 0; - } - - /* retransmission -> adjust the congestWinSize and congestThreshold - */ - - congestThreshold = congestWinSize / 2; - congestWinSize = MAX_SEG; - congestUpdate = outAcked + congestWinSize; // point when we can up the winSize. - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::retrans() Adjusting Congestion Parameters: "; - std::cerr << std::endl; - std::cerr << "\tcongestWinSize: " << congestWinSize; - std::cerr << " congestThreshold: " << congestThreshold; - std::cerr << " congestUpdate: " << congestUpdate; - std::cerr << std::endl; -#endif - - /* update ackno and winsize */ - if (!(pkt->hasSyn())) - { - pkt->setAck(inAckno); - lastSentAck = pkt -> ackno; - } - - pkt->winsize = inWinSize; - lastSentWinSize = pkt -> winsize; - - keepAliveTimer = cts; - - pkt->writePacket(tmpOutPkt, outPktSize); - -#ifdef DEBUG_TCP_STREAM_RETRANS - std::cerr << "TcpStream::retrans()"; - std::cerr << " peer: " << peeraddr; - std::cerr << " hasSyn: " << pkt->hasSyn(); - std::cerr << " Seqno: "; - std::cerr << pkt->seqno << " size: " << pkt->datasize; - std::cerr << " Ackno: "; - std::cerr << pkt->ackno << " winsize: " << pkt->winsize; - std::cerr << " retrans: " << (int) pkt->retrans; - std::cerr << " timeout: " << std::setprecision(12) << retransTimeout; - std::cerr << std::endl; - - //std::cerr << printPkt(tmpOutPkt, outPktSize) << std::endl; -#endif - - /* if its a syn packet ** thats been - * transmitting for a while, maybe - * we should increase the ttl. - */ - - if ((pkt->hasSyn()) && (getTTL() < TCP_STD_TTL)) - { - /* calculate a new TTL */ - if (mTTL_end > cts) - { - setTTL(TCP_DEFAULT_FIREWALL_TTL); - } - else - { - setTTL(getTTL() + 1); - } - - std::string out; - rs_sprintf(out, "TcpStream::retrans() Startup SYNs retrans count: %u New TTL: %d", pkt->retrans, getTTL()); - - rslog(RSL_WARNING, rstcpstreamzone, out); - -#ifdef DEBUG_TCP_STREAM - std::cerr << out.str() << std::endl; -#endif - } - - /* catch excessive retransmits - * - Allow Syn case more.... - * - if not SYN or TTL has reached STD then timeout quickly. - - * OLD 2nd Logic (below) has been replaced with lower logic. - * (((!pkt->hasSyn()) || (TCP_STD_TTL == getTTL())) - * && (pkt->retrans > kMaxPktRetransmit))) - * Problem was that the retransmit of Syn packet had STD_TTL, and was triggering Close (and SeqNo change). - * It seemed to work anyway.... But might cause coonnection failures. Will reduce the MaxSyn Retransmit - * so something more reasonable as well. - * ((!pkt->hasSyn()) && (pkt->retrans > kMaxPktRetransmit))) - */ - - if ((pkt->hasSyn() && (pkt->retrans > kMaxSynPktRetransmit)) || - ((!pkt->hasSyn()) && (pkt->retrans > kMaxPktRetransmit))) - - { - - /* too many attempts close stream */ -#ifdef DEBUG_TCP_STREAM_CLOSE - std::cerr << "TcpStream::retrans() Too many Retransmission Attempts ("; - std::cerr << (int) pkt->retrans << ") for Peer: " << peeraddr << std::endl; - std::cerr << "TcpStream::retrans() Closing Socket Connection"; - std::cerr << std::endl; - - //dumpPacket(std::cerr, (unsigned char *) tmpOutPkt, outPktSize); - dumpstate_locked(std::cerr); -#endif - - rslog(RSL_WARNING,rstcpstreamzone,"TcpStream::state => TCP_CLOSED (Too Many Retransmits)"); - - outStreamActive = false; - inStreamActive = false; - state = TCP_CLOSED; - cleanup(); - return 0; - } - - - udp -> sendPkt(tmpOutPkt, outPktSize, peeraddr, ttl); - - /* restart timers */ - pkt->ts = cts; - pkt->retrans++; - - /* - * finally - double the retransTimeout ... (Karn's Algorithm) - * except if we are starting a connection... i.e. hasSyn() - */ - - if (!pkt->hasSyn()) - { - incRetransmitTimeout(); - restartRetransmitTimer(); - } - else - { - resetRetransmitTimer(); - startRetransmitTimer(); - } - - return 1; -} - - -void TcpStream::acknowledge() -{ - /* cleans up acknowledge packets */ - /* packets are pushed back in order */ - std::list::iterator it; - double cts = getCurrentTS(); - bool updateRTT = true; - bool clearedPkts = false; - - for(it = outPkt.begin(); (it != outPkt.end()) && - (isOldSequence((*it)->seqno, outAcked)); - it = outPkt.erase(it)) - { - TcpPacket *pkt = (*it); - clearedPkts = true; - - /* adjust the congestWinSize and congestThreshold - * congestUpdate <= outAcked - * - ***/ - - if (!isOldSequence(outAcked, congestUpdate)) - { - if (congestWinSize < congestThreshold) - { - /* double it baby! */ - congestWinSize *= 2; - } - else - { - /* linear increase */ - congestWinSize += MAX_SEG; - } - - if (congestWinSize > maxWinSize) - { - congestWinSize = maxWinSize; - } - - congestUpdate = outAcked + congestWinSize; // point when we can up the winSize. - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::acknowledge() Adjusting Congestion Parameters: "; - std::cerr << std::endl; - std::cerr << "\tcongestWinSize: " << congestWinSize; - std::cerr << " congestThreshold: " << congestThreshold; - std::cerr << " congestUpdate: " << congestUpdate; - std::cerr << std::endl; -#endif - } - - - /* update the RoundTripTime, - * using Jacobson's values. - * RTT = a RTT + (1-a) M - * where - * RTT is RoundTripTime estimate. - * a = 7/8, - * M = time for ack. - * - * D = a D + (1 - a) | RTT - M | - * where - * D is approx Deviation. - * a,RTT & M are the same as above. - * - * Timeout = RTT + 4 * D. - * - * And Karn's Algorithm... - * which says - * (1) do not update RTT or D for retransmitted packets. - * + the ones that follow .... (the ones whos ack was - * delayed by the retranmission) - * (2) double timeout, when packets fail. (done in retrans). - */ - - if (pkt->retrans) - { - updateRTT = false; - } - - if (updateRTT) /* can use for RTT calc */ - { - double ack_time = cts - pkt->ts; - rtt_est = RTT_ALPHA * rtt_est + (1.0 - RTT_ALPHA) * ack_time; - rtt_dev = RTT_ALPHA * rtt_dev + (1.0 - RTT_ALPHA) * fabs(rtt_est - ack_time); - retransTimeout = rtt_est + 4.0 * rtt_dev; -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::acknowledge() Updating RTT: "; - std::cerr << std::endl; - std::cerr << "\tAckTime: " << ack_time; - std::cerr << std::endl; - std::cerr << "\tRRT_est: " << rtt_est; - std::cerr << std::endl; - std::cerr << "\tRTT_dev: " << rtt_dev; - std::cerr << std::endl; - std::cerr << "\tTimeout: " << retransTimeout; - std::cerr << std::endl; -#endif - } - -#ifdef DEBUG_TCP_STREAM - else - { - std::cerr << "TcpStream::acknowledge() Not Updating RTT for retransmitted Pkt Sequence"; - std::cerr << std::endl; - } -#endif - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::acknowledge() Removing Seqno: "; - std::cerr << pkt->seqno << " size: " << pkt->datasize; - std::cerr << std::endl; -#endif - delete pkt; - } - - /* This is triggered if we have recieved acks for retransmitted packets.... - * In this case we want to reset the timeout, and remove the doubling. - * - * If we don't do this, and there have been more dropped packets, - * the the timeout gets continually doubled. which will virtually stop - * all communication. - * - * This will effectively trigger the retransmission of the next dropped packet. - */ - - /* - * if have acked all data - resetRetransTimer() - */ - - if (it == outPkt.end()) - { - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::acknowledge() peer: " << peeraddr; - std::cerr << " Backlog cleared, resetRetransmitTimer"; - std::cerr << std::endl; -#endif - resetRetransmitTimer(); - } - else if (clearedPkts) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::acknowledge() peer: " << peeraddr; - std::cerr << " Cleared some packets -> resetRetransmitTimer + start"; - std::cerr << std::endl; -#endif - resetRetransmitTimer(); - startRetransmitTimer(); - } - return; -} - - -int TcpStream::send() -{ - /* handle network interface always */ - /* clean up as much as possible */ - acknowledge(); - /* send any old packets */ - retrans(); - - - if (state < TCP_ESTABLISHED) - { - return -1; - } - - /* get the inQueue, can send */ - - - /* determine exactly how much we can send */ - uint32 maxsend = congestWinSize; - uint32 inTransit; - - if (outWinSize < congestWinSize) - { - maxsend = outWinSize; - } - - if (outSeqno < outAcked) - { - inTransit = (TCP_MAX_SEQ - outAcked) + outSeqno; - } - else - { - inTransit = outSeqno - outAcked; - } - - if (maxsend > inTransit) - { - maxsend -= inTransit; - } - else - { - maxsend = 0; - } - -#ifdef DEBUG_TCP_STREAM - int availSend = inQueue.size() * MAX_SEG + inSize; - std::cerr << "TcpStream::send() CC: "; - std::cerr << "oWS: " << outWinSize; - std::cerr << " cWS: " << congestWinSize; - std::cerr << " | inT: " << inTransit; - std::cerr << " mSnd: " << maxsend; - std::cerr << " aSnd: " << availSend; - std::cerr << " | oSeq: " << outSeqno; - std::cerr << " oAck: " << outAcked; - std::cerr << " cUpd: " << congestUpdate; - std::cerr << std::endl; -#endif - - int sent = 0; - while((inQueue.size() > 0) && (maxsend >= MAX_SEG)) - { - dataBuffer *db = inQueue.front(); - inQueue.pop_front(); - - TcpPacket *pkt = new TcpPacket(db->data, MAX_SEG); -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::send() Segment ===> Seqno: "; - std::cerr << pkt->seqno << " size: " << pkt->datasize; - std::cerr << std::endl; -#endif - sent++; - maxsend -= MAX_SEG; - toSend(pkt); - delete db; - } - - /* if inqueue empty, and enough window space, send partial stuff */ - if ((!sent) && (inQueue.empty()) && (maxsend >= inSize) && (inSize)) - { - TcpPacket *pkt = new TcpPacket(inData, inSize); -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::send() Remaining ===>"; - std::cerr << std::endl; -#endif - inSize = 0; - sent++; - maxsend -= inSize; - toSend(pkt); - } - - /* if send nothing */ - bool needsAck = false; - - if (!sent) - { - double cts = getCurrentTS(); - /* if needs ack */ - if (isOldSequence(lastSentAck,inAckno)) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::send() Ack Triggered (Ackno)"; - std::cerr << std::endl; -#endif - needsAck = true; - } - - /* if needs window - * if added enough space for packet, or - * (this case is equivalent to persistence timer) - * haven't sent anything for a while, and the - * window size has drastically increased. - * */ - if (((lastSentWinSize < MAX_SEG) && (inWinSize > MAX_SEG)) || - ((cts - keepAliveTimer > retransTimeout * 4) && - (inWinSize > lastSentWinSize + 4 * MAX_SEG))) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::send() Ack Triggered (Window)"; - std::cerr << std::endl; -#endif - needsAck = true; - } - - /* if needs keepalive */ - if (cts - keepAliveTimer > keepAliveTimeout) - { -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::send() Ack Triggered (KAlive)"; - std::cerr << std::endl; -#endif - needsAck = true; - } - - - /* if end of stream -> switch mode -> send fin (with ack) */ - if ((!outStreamActive) && (inQueue.size() + inSize == 0) && - ((state == TCP_ESTABLISHED) || (state == TCP_CLOSE_WAIT))) - { - /* finish the stream */ - TcpPacket *pkt = new TcpPacket(); - pkt -> setFin(); - - needsAck = false; - toSend(pkt, false); - -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::send() Fin Triggered"; - std::cerr << std::endl; -#endif - - if (state == TCP_ESTABLISHED) - { - state = TCP_FIN_WAIT_1; -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::state = TCP_FIN_WAIT_1"; - std::cerr << std::endl; -#endif - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_FIN_WAIT_1 (End of Stream)"); - } - else if (state == TCP_CLOSE_WAIT) - { - state = TCP_LAST_ACK; -#ifdef DEBUG_TCP_STREAM - std::cerr << "TcpStream::state = TCP_LAST_ACK"; - std::cerr << std::endl; -#endif - - rslog(RSL_WARNING, rstcpstreamzone, "TcpStream::state => TCP_LAST_ACK (CLOSE_WAIT, End of Stream)"); - } - - } - - if (needsAck) - { - sendAck(); - } -#ifdef DEBUG_TCP_STREAM_EXTRA - else - { - std::cerr << "TcpStream::send() No Ack"; - std::cerr << std::endl; - } -#endif - } -#ifdef DEBUG_TCP_STREAM_EXTRA - else - { - std::cerr << "TcpStream::send() Stuff Sent"; - std::cerr << std::endl; - } -#endif - return 1; -} - - -uint32 TcpStream::genSequenceNo() -{ - return RSRandom::random_u32(); - //return 1000; // TCP_MAX_SEQ - 1000; //1000; //(rand() - 100000) + time(NULL) % 100000; - //return (rand() - 100000) + time(NULL) % 100000; - -} - - -bool TcpStream::isOldSequence(uint32 tst, uint32 curr) -{ - return ((int)((tst)-(curr)) < 0); - - std::cerr << "TcpStream::isOldSequence(): Case "; - /* if tst < curr */ - if ((int)((tst)-(curr)) < 0) - { - if (curr - tst < TCP_MAX_SEQ/2) /* diff less than half span -> old */ - { - std::cerr << "1T" << std::endl; - return true; - } - std::cerr << "2F" << std::endl; - return false; - } - else if ((tst - curr) > TCP_MAX_SEQ/2) - { - std::cerr << "3T: tst-curr:" << (tst-curr) << std::endl; - return true; - } - std::cerr << "4F: tst-curr:" << (tst-curr) << std::endl; - return false; -} - -#ifdef WINDOWS_SYS -#include "util/rstime.h" -#include -#endif - -// Little fn to get current timestamp in an independent manner. -static double getCurrentTS() -{ - -#ifndef WINDOWS_SYS - struct timeval cts_tmp; - gettimeofday(&cts_tmp, NULL); - double cts = (cts_tmp.tv_sec) + ((double) cts_tmp.tv_usec) / 1000000.0; -#else - struct _timeb timebuf; - _ftime( &timebuf); - double cts = (timebuf.time) + ((double) timebuf.millitm) / 1000.0; -#endif - return cts; -} - - - -uint32 TcpStream::int_wbytes() -{ - return outSeqno - initOurSeqno - 1; -} - -uint32 TcpStream::int_rbytes() -{ - return inAckno - initPeerSeqno - 1; -} - - - - -/********* Special debugging stuff *****/ - -#ifdef DEBUG_TCP_STREAM_EXTRA - -#include - -static FILE *bc_fd = 0; -int setupBinaryCheck(std::string fname) -{ - bc_fd = RsDirUtil::rs_fopen(fname.c_str(), "r"); - return 1; -} - -/* uses seq number to track position -> ensure no rollover */ -int checkData(uint8 *data, int size, int idx) -{ - if (bc_fd <= 0) - { - return -1; - } - std::cerr << "checkData(" << idx << "+" << size << ")"; - - int tmpsize = size; - uint8 tmpdata[tmpsize]; - if (-1 == fseek(bc_fd, idx, SEEK_SET)) - { - std::cerr << "Fseek Issues!" << std::endl; - exit(1); - return -1; - } - - if (1 != fread(tmpdata, tmpsize, 1, bc_fd)) - { - std::cerr << "Length Difference!" << std::endl; - exit(1); - return -1; - } - - for(int i = 0; i < size; i++) - { - if (data[i] != tmpdata[i]) - { - std::cerr << "Byte Difference!" << std::endl; - exit(1); - return -1; - } - } - std::cerr << "OK" << std::endl; - return 1; -} - -#endif - - -/***** Dump state of TCP Stream - to workout why it was closed ****/ -int TcpStream::dumpstate_locked(std::ostream &out) -{ - out << "TcpStream::dumpstate()"; - out << "======================================================="; - - out << std::endl; - out << "state: " << (int) state; - out << " errorState: " << (int) errorState; - out << std::endl; - - out << "(Streams) inStreamActive: " << inStreamActive; - out << " outStreamActive: " << outStreamActive; - out << std::endl; - - out << "(Timeouts) maxWinSize: " << maxWinSize; - out << " keepAliveTimeout: " << keepAliveTimeout; - out << " retransTimeout: " << retransTimeout; - out << std::endl; - - out << "(Timers) keepAliveTimer: " << std::setprecision(12) << keepAliveTimer; - out << " lastIncomingPkt: " << std::setprecision(12) << lastIncomingPkt; - out << std::endl; - - out << "(Tracking) lastSendAck: " << lastSentAck; - out << " lastSendWinSize: " << lastSentWinSize; - out << std::endl; - - out << "(Init) initOutSeqno: " << initOurSeqno; - out << " initPeerSeqno: " << initPeerSeqno; - out << std::endl; - - out << "(r/w) lastWriteTF: " << lastWriteTF; - out << " lastReadTF: " << lastReadTF; - out << " wcount: " << wcount; - out << " rcount: " << rcount; - out << std::endl; - - out << "(rtt) rtt_est: " << rtt_est; - out << " rtt_dev: " << rtt_dev; - out << std::endl; - - out << "(congestion) congestThreshold: " << congestThreshold; - out << " congestWinSize: " << congestWinSize; - out << " congestUpdate: " << congestUpdate; - out << std::endl; - - out << "(TTL) mTTL_period: " << mTTL_period; - out << " mTTL_start: " << std::setprecision(12) << mTTL_start; - out << " mTTL_end: " << std::setprecision(12) << mTTL_end; - out << std::endl; - - out << "(Peer) peerKnown: " << peerKnown; - out << " peerAddr: " << peeraddr; - out << std::endl; - - out << "-------------------------------------------------------"; - out << std::endl; - status_locked(out); - out << "======================================================="; - out << std::endl; - - return 1; -} - - -int TcpStream::dumpstate(std::ostream &out) -{ - tcpMtx.lock(); /********** LOCK MUTEX *********/ - - dumpstate_locked(out); - - tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ - - return 1; -} - - -int dumpPacket(std::ostream &out, unsigned char *pkt, uint32_t size) -{ - uint32_t i; - - out << "dumpPacket() Size: " << size; - out << std::endl; - out << "------------------------------------------------------"; - for(i = 0; i < size; i++) - { - if (i % 16 == 0) - { - out << std::endl; - } - out << std::hex << std::setfill('0') << std::setw(2) << (int) pkt[i] << ":"; - } - if ((i - 1) % 16 != 0) - { - out << std::endl; - } - out << "------------------------------------------------------"; - out << std::dec << std::endl; - - return 1; -} - - diff --git a/libretroshare/src/tcponudp/tcpstream.h b/libretroshare/src/tcponudp/tcpstream.h deleted file mode 100644 index 87ed693d0..000000000 --- a/libretroshare/src/tcponudp/tcpstream.h +++ /dev/null @@ -1,266 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: tcpstream.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef TOU_TCP_PROTO_H -#define TOU_TCP_PROTO_H - - -/* so the packet will contain - * a tcp header + data. - * - * This is done simplistically for speed. - */ - -#include "tcppacket.h" -#include "udppeer.h" - -// WINDOWS doesn't like UDP packets bigger than 1492 (truncates them). -// We have up to 64 bytes of headers: 28(udp) + 16(relay) + 20(tou) = 64 bytes. -// 64 bytes + 1400 = 1464, leaves a small margin, but close to maximum throughput. -//#define MAX_SEG 1400 -// We are going to start at 1000 (to avoid any fragmentation, and work up). -#define MAX_SEG 1000 - -#define TCP_MAX_SEQ UINT_MAX -#define TCP_MAX_WIN 65500 -#define TCP_ALIVE_TIMEOUT 15 /* 15 sec ... < 20 sec UDP state limit on some firewalls */ -#define TCP_RETRANS_TIMEOUT 1 /* 1 sec (Initial value) */ -#define TCP_RETRANS_MAX_TIMEOUT 15 /* 15 secs */ -#define kNoPktTimeout 60 /* 1 min */ - - -#define TCP_CLOSED 0 -#define TCP_LISTEN 1 -#define TCP_SYN_SENT 2 -#define TCP_SYN_RCVD 3 -#define TCP_ESTABLISHED 4 -#define TCP_FIN_WAIT_1 5 -#define TCP_FIN_WAIT_2 6 -#define TCP_TIMED_WAIT 7 -#define TCP_CLOSING 8 -#define TCP_CLOSE_WAIT 9 -#define TCP_LAST_ACK 10 - -class dataBuffer -{ - public: - uint8 data[MAX_SEG]; -}; - -#include -#include - - -class TcpStream: public UdpPeer -{ - public: - /* Top-Level exposed */ - - TcpStream(UdpSubReceiver *udp); -virtual ~TcpStream() { return; } - - /* user interface */ -int status(std::ostream &out); -int connect(const struct sockaddr_in &raddr, uint32_t conn_period); -int listenfor(const struct sockaddr_in &raddr); -bool isConnected(); - - /* get tcp information */ -bool getRemoteAddress(struct sockaddr_in &raddr); -uint8 TcpState(); -int TcpErrorState(); - - /* stream Interface */ -int write(char *dta, int size); /* write -> pkt -> net */ -int read(char *dta, int size); /* net -> pkt -> read */ - - /* check ahead for allowed bytes */ -int write_allowed(); -int read_pending(); - -int closeWrite(); /* non-standard, but for clean exit */ -int close(); /* standard unix behaviour */ - -int tick(); /* check iface etc */ - - /* Callback Funcion from UDP Layers */ -virtual void recvPkt(void *data, int size); /* overloaded */ - - - - /* Exposed Data Counting */ -bool widle(); /* write idle */ -bool ridle(); /* read idle */ -uint32 wbytes(); -uint32 rbytes(); - - /* Exposed for debugging */ -int dumpstate(std::ostream &out); - - private: - - /* Internal Functions - use the Mutex (not reentrant) */ - /* Internal Functions - that don't need mutex protection */ - -uint32 genSequenceNo(); -bool isOldSequence(uint32 tst, uint32 curr); - - RsMutex tcpMtx; - - /* Internal Functions - only called inside mutex protection */ - -int dumpstate_locked(std::ostream &out); -int status_locked(std::ostream &out); - -int cleanup(); - -/* incoming data */ -int recv_check(); -int handleIncoming(TcpPacket *pkt); -int incoming_Closed(TcpPacket *pkt); -int incoming_SynSent(TcpPacket *pkt); -int incoming_SynRcvd(TcpPacket *pkt); -int incoming_Established(TcpPacket *pkt); -int incoming_FinWait1(TcpPacket *pkt); -int incoming_FinWait2(TcpPacket *pkt); -int incoming_TimedWait(TcpPacket *pkt); -int incoming_Closing(TcpPacket *pkt); -int incoming_CloseWait(TcpPacket *pkt); -int incoming_LastAck(TcpPacket *pkt); -int check_InPkts(); -int UpdateInWinSize(); -int int_read_pending(); - -/* outgoing data */ -int send(); -int toSend(TcpPacket *pkt, bool retrans = true); -void acknowledge(); -int retrans(); -int sendAck(); -void setRemoteAddress(const struct sockaddr_in &raddr); - -int getTTL() { return ttl; } -void setTTL(int t) { ttl = t; } - -/* retransmission */ -void startRetransmitTimer(); -void restartRetransmitTimer(); -void stopRetransmitTimer(); -void resetRetransmitTimer(); -void incRetransmitTimeout(); - - -/* data counting */ -uint32 int_wbytes(); -uint32 int_rbytes(); - - /* Internal Data - must have mutex to access! */ - - /* data (in -> pkts) && (pkts -> out) */ - - /* for small amounts of data */ - uint8 inData[MAX_SEG]; - uint32 inSize; - - - /* two variable sized buffers required here */ - uint8 outDataRead[MAX_SEG]; - uint32 outSizeRead; - uint8 outDataNet[MAX_SEG]; - uint32 outSizeNet; - - /* get packed into here as size increases */ - std::deque inQueue, outQueue; - - /* packets waiting for acks */ - std::list inPkt, outPkt; - - - uint8 state; /* stream state */ - bool inStreamActive; - bool outStreamActive; - - uint32 outSeqno; /* next out */ - uint32 outAcked; /* other size has received */ - uint32 outWinSize; /* we allowed to send */ - - uint32 inAckno; /* next expected */ - uint32 inWinSize; /* allowing other to send */ - - /* some (initially) consts */ - uint32 maxWinSize; - uint32 keepAliveTimeout; - - /* retransmit */ - bool retransTimerOn; - double retransTimeout; - double retransTimerTs; - - /* some timers */ - double keepAliveTimer; - double lastIncomingPkt; - - /* tracking */ - uint32 lastSentAck; - uint32 lastSentWinSize; - uint32 initOurSeqno; - uint32 initPeerSeqno; - - uint32 lastWriteTF,lastReadTF; - uint16 wcount, rcount; - - int errorState; - - /* RoundTripTime estimations */ - double rtt_est; - double rtt_dev; - - /* congestion limits */ - uint32 congestThreshold; - uint32 congestWinSize; - uint32 congestUpdate; - - /* existing TTL for this stream (tweaked at startup) */ - int ttl; - - double mTTL_period; - double mTTL_start; - double mTTL_end; - - struct sockaddr_in peeraddr; - bool peerKnown; - - /* UdpSubReceiver (has own Mutex!) */ - UdpSubReceiver *udp; - -}; - - -/* for debugging */ - -#ifdef TCP_DEBUG_STREAM_EXTRA /* for extra checking! */ -int setupBinaryCheck(std::string fname); -#endif - - - -#endif - diff --git a/libretroshare/src/tcponudp/tou.cc b/libretroshare/src/tcponudp/tou.cc deleted file mode 100644 index 96c8797d9..000000000 --- a/libretroshare/src/tcponudp/tou.cc +++ /dev/null @@ -1,663 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: tou.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "tou.h" - -static const int kInitStreamTable = 5; - -#include -#include -#include -#include -#include - -#include "util/rstime.h" -#include "udp/udpstack.h" -#include "pqi/pqinetwork.h" -#include "tcpstream.h" -#include "util/stacktrace.h" - -#define DEBUG_TOU_INTERFACE 1 -#define EUSERS 87 - -struct TcpOnUdp_t -{ - int tou_fd; - int lasterrno; - TcpStream *tcp; - UdpSubReceiver *udpsr; - int udptype; - bool idle; -}; - -typedef struct TcpOnUdp_t TcpOnUdp; - -static RsMutex touMutex("touMutex"); -// Mutex is used to control addition / removals from tou_streams. -// Lookup should be okay - as long as you stick to your allocated ID! - -static std::vector tou_streams; - -static int tou_inited = 0; - - -#include "tcponudp/udppeer.h" -#include "tcponudp/udprelay.h" - -static UdpSubReceiver *udpSR[MAX_TOU_RECEIVERS] = {NULL}; -static uint32_t udpType[MAX_TOU_RECEIVERS] = { 0 }; -static uint32_t noUdpSR = 0; - -/* tou_init - * - * Modified to accept a number of UdpSubRecievers! - * these can be linked to arbitary UdpStacks. - * (removed all UdpStack references here!) - * - * Unfortunately, the UdpSubReceivers have different initialisation for starting a connection. - * So the TOU interface has to accomodate this. - * - */ -/* tou_init - opens the udp port (universal bind) */ -int tou_init(void **in_udpsubrecvs, int *type, int number) -{ - RsStackMutex stack(touMutex); /***** LOCKED ******/ - - UdpSubReceiver **usrArray = (UdpSubReceiver **) in_udpsubrecvs; - if (number > MAX_TOU_RECEIVERS) - { - std::cerr << "tou_init() Invalid number of receivers"; - std::cerr << std::endl; - return 0; - } - - if (tou_inited) - { - return 1; - } - - noUdpSR = number; - uint32_t i; - for(i = 0; i < noUdpSR; i++) - { - udpSR[i] = usrArray[i]; - udpType[i] = type[i]; - } - - tou_streams.resize(kInitStreamTable); - - tou_inited = 1; - return 1; -} - - -/* open - allocates a sockfd, and checks that the type is okay */ -int tou_socket(uint32_t recvIdx, uint32_t type, int /*protocol*/) -{ - RsStackMutex stack(touMutex); /***** LOCKED ******/ - - if (!tou_inited) - { - return -1; - } - - if (recvIdx >= noUdpSR) - { - std::cerr << "tou_socket() ERROR recvIdx greater than #receivers"; - std::cerr << std::endl; - return -1; - } - - /* check that the index matches the type */ - UdpSubReceiver *recver = udpSR[recvIdx]; - uint32_t recverType = udpType[recvIdx]; - - if (recverType != type) - { - std::cerr << "tou_socket() ERROR type doesn't match expected type"; - std::cerr << std::endl; - return -1; - } - - for(unsigned int i = 1; i < tou_streams.size(); i++) - { - if (tou_streams[i] == NULL) - { - tou_streams[i] = new TcpOnUdp(); - tou_streams[i] -> tou_fd = i; - tou_streams[i] -> tcp = NULL; - tou_streams[i] -> udpsr = recver; - tou_streams[i] -> udptype = recverType; - return i; - } - } - - TcpOnUdp *tou = new TcpOnUdp(); - - tou_streams.push_back(tou); - - if (tou == tou_streams[tou_streams.size() -1]) - { - tou -> tou_fd = tou_streams.size() -1; - tou -> tcp = NULL; - tou -> udpsr = recver; - tou -> udptype = recverType; - return tou->tou_fd; - } - - tou -> lasterrno = EUSERS; - - return -1; -} - - -bool tou_stream_check(int sockfd) -{ - if(sockfd < 0) - { - std::cerr << __PRETTY_FUNCTION__ << " ERROR sockfd: " << sockfd - << " < 0" << std::endl; - print_stacktrace(); - return false; - } - - if(sockfd >= tou_streams.size()) - { - std::cerr << __PRETTY_FUNCTION__ << " ERROR sockfd: " << sockfd - << " out of bound!" << std::endl; - print_stacktrace(); - return false; - } - - if(!tou_streams[sockfd]) - { - std::cerr << __PRETTY_FUNCTION__ << " ERROR tou_streams[sockfd] == NULL" - << std::endl; - print_stacktrace(); - return false; - } - - return true; -} - -/* bind - opens the udp port */ -int tou_bind(int sockfd, const struct sockaddr * /* my_addr */, socklen_t /* addrlen */ ) -{ - if (!tou_stream_check(sockfd)) - { - return -1; - } - TcpOnUdp *tous = tou_streams[sockfd]; - - /* this now always returns an error! */ - tous -> lasterrno = EADDRINUSE; - return -1; -} - -/* records peers address, and sends syn pkt - * the timeout is very slow initially - to give - * the peer a chance to startup - * - * - like a tcp/ip connection, the connect - * will return -1 EAGAIN, until connection complete. - * - always non blocking. - */ -int tou_connect(int sockfd, const struct sockaddr *serv_addr, - socklen_t addrlen, uint32_t conn_period) -{ - if (!tou_stream_check(sockfd)) - { - return -1; - } - TcpOnUdp *tous = tou_streams[sockfd]; - - - if (addrlen < sizeof(struct sockaddr_in)) - { - std::cerr << "tou_connect() ERROR invalid size of sockaddr"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - return -1; - } - - // only IPv4 for the moment. - const struct sockaddr_storage *ss_addr = (struct sockaddr_storage *) serv_addr; - if (ss_addr->ss_family != AF_INET) - { - std::cerr << "tou_connect() ERROR not ipv4"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - return -1; - } - - /* enforce that the udptype is correct */ - if (tous -> udptype != TOU_RECEIVER_TYPE_UDPPEER) - { - std::cerr << "tou_connect() ERROR connect method invalid for udptype"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - return -1; - } - - -#ifdef TOU_DYNAMIC_CAST_CHECK - /* extra checking -> for testing purposes (dynamic cast) */ - UdpPeerReceiver *upr = dynamic_cast(tous->udpsr); - if (!upr) - { - std::cerr << "tou_connect() ERROR cannot convert type to UdpPeerReceiver"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - return -1; - } -#else - UdpPeerReceiver *upr = (UdpPeerReceiver *) (tous->udpsr); -#endif - - /* create a TCP stream to connect with. */ - if (!tous->tcp) - { - tous->tcp = new TcpStream(tous->udpsr); - upr->addUdpPeer(tous->tcp, - *((const struct sockaddr_in *) serv_addr)); - } - - tous->tcp->connect(*(const struct sockaddr_in *) serv_addr, conn_period); - tous->tcp->tick(); - if (tous->tcp->isConnected()) - { - return 0; - } - - tous -> lasterrno = EINPROGRESS; - return -1; -} - -/* is this ever used? should it be depreciated? */ -int tou_listenfor(int sockfd, const struct sockaddr *serv_addr, - socklen_t addrlen) -{ - if (!tou_stream_check(sockfd)) - { - return -1; - } - TcpOnUdp *tous = tou_streams[sockfd]; - - if (addrlen < sizeof(struct sockaddr_in)) - { - std::cerr << "tou_listenfor() ERROR invalid size of sockaddr"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - return -1; - } - - // only IPv4 for the moment. - const struct sockaddr_storage *ss_addr = (struct sockaddr_storage *) serv_addr; - if (ss_addr->ss_family != AF_INET) - { - std::cerr << "tou_listenfor() ERROR not ipv4"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - return -1; - } - - - /* enforce that the udptype is correct */ - if (tous -> udptype != TOU_RECEIVER_TYPE_UDPPEER) - { - std::cerr << "tou_connect() ERROR connect method invalid for udptype"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - return -1; - } - -#ifdef TOU_DYNAMIC_CAST_CHECK - /* extra checking -> for testing purposes (dynamic cast) */ - UdpPeerReceiver *upr = dynamic_cast(tous->udpsr); - if (!upr) - { - std::cerr << "tou_connect() ERROR cannot convert type to UdpPeerReceiver"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - return -1; - } -#else - UdpPeerReceiver *upr = (UdpPeerReceiver *) (tous->udpsr); -#endif - - /* create a TCP stream to connect with. */ - if (!tous->tcp) - { - tous->tcp = new TcpStream(tous->udpsr); - upr->addUdpPeer(tous->tcp, - *((const struct sockaddr_in *) serv_addr)); - } - - tous->tcp->listenfor(*((struct sockaddr_in *) serv_addr)); - tous->tcp->tick(); - - return 0; -} - -int tou_listen(int /* sockfd */ , int /* backlog */ ) -{ - return 1; -} - -/* - * This is the alternative RELAY connection. - * - * User needs to provide 3 ip addresses. - * These addresses should have been provided by the RELAY negogiation - * a) own ip:port - * b) proxy ip:port - * c) dest ip:port - * - * The reset of the startup is similar to other TOU connections. - * As this is likely to be run over an established UDP connection, - * there is little need for a big connection period. - * - * - like a tcp/ip connection, the connect - * will return -1 EAGAIN, until connection complete. - * - always non blocking. - */ -#define DEFAULT_RELAY_CONN_PERIOD 1 - -int tou_connect_via_relay( int sockfd, const sockaddr_in& own_addr, - const sockaddr_in& proxy_addr, - const sockaddr_in& dest_addr ) - -{ - std::cerr << __PRETTY_FUNCTION__ << std::endl; - - if (!tou_stream_check(sockfd)) return -EINVAL; - - TcpOnUdp& tous = *tou_streams[sockfd]; - - /* enforce that the udptype is correct */ - if (tous.udptype != TOU_RECEIVER_TYPE_UDPRELAY) - { - std::cerr << __PRETTY_FUNCTION__ << " ERROR connect method invalid for " - << "udptype" << std::endl; - tous.lasterrno = EINVAL; - return -EINVAL; - } - - UdpRelayReceiver* urr_ptr = dynamic_cast(tous.udpsr); - if(!urr_ptr) - { - std::cerr << __PRETTY_FUNCTION__ << " ERROR cannot convert to " - << "UdpRelayReceiver" << std::endl; - tous.lasterrno = EINVAL; - return -EINVAL; - } - - UdpRelayReceiver& urr = *urr_ptr; urr_ptr = nullptr; - - /* create a TCP stream to connect with. */ - if (!tous.tcp) - { - tous.tcp = new TcpStream(tous.udpsr); - - UdpRelayAddrSet addrSet(&own_addr, &dest_addr); - urr.addUdpPeer(tous.tcp, &addrSet, &proxy_addr); - } - - /* We Point it at the Destination Address. - * The UdpRelayReceiver wraps and re-directs the packets to the proxy - */ - tous.tcp->connect(dest_addr, DEFAULT_RELAY_CONN_PERIOD); - tous.tcp->tick(); - if (tous.tcp->isConnected()) return 0; - - tous.lasterrno = EINPROGRESS; - return -EINPROGRESS; -} - - - /* slightly different - returns sockfd on connection */ -int tou_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) -{ - if (!tou_stream_check(sockfd)) - { - return -1; - } - TcpOnUdp *tous = tou_streams[sockfd]; - - if (*addrlen < sizeof(struct sockaddr_in)) - { - std::cerr << "tou_accept() ERROR invalid size of sockaddr"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - return -1; - } - - // only IPv4 for the moment. - const struct sockaddr_storage *ss_addr = (struct sockaddr_storage *) addr; - if (ss_addr->ss_family != AF_INET) - { - std::cerr << "tou_accept() ERROR not ipv4"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - return -1; - } - - //tous->tcp->connect(); - tous->tcp->tick(); - if (tous->tcp->isConnected()) - { - // should get remote address - tous->tcp->getRemoteAddress(*((struct sockaddr_in *) addr)); - return sockfd; - } - - tous -> lasterrno = EAGAIN; - return -1; -} - - -int tou_connected(int sockfd) -{ - if (!tou_stream_check(sockfd)) - { - return -1; - } - TcpOnUdp *tous = tou_streams[sockfd]; - - tous->tcp->tick(); - - return (tous->tcp->TcpState() == 4); -} - - -/* standard stream read/write non-blocking of course - */ - -ssize_t tou_read(int sockfd, void *buf, size_t count) -{ - if (!tou_stream_check(sockfd)) - { - return -1; - } - TcpOnUdp *tous = tou_streams[sockfd]; - - tous->tcp->tick(); - - int err = tous->tcp->read((char *) buf, count); - if (err < 0) - { - tous->lasterrno = tous->tcp->TcpErrorState(); - return -1; - } - return err; -} - -ssize_t tou_write(int sockfd, const void *buf, size_t count) -{ - if (!tou_stream_check(sockfd)) - { - return -1; - } - TcpOnUdp *tous = tou_streams[sockfd]; - - - int err = tous->tcp->write((char *) buf, count); - if (err < 0) - { - tous->lasterrno = tous->tcp->TcpErrorState(); - tous->tcp->tick(); - return -1; - } - tous->tcp->tick(); - return err; -} - - /* check stream */ -int tou_maxread(int sockfd) -{ - if (!tou_stream_check(sockfd)) - { - return -1; - } - TcpOnUdp *tous = tou_streams[sockfd]; - tous->tcp->tick(); - - int ret = tous->tcp->read_pending(); - if (ret < 0) - { - tous->lasterrno = tous->tcp->TcpErrorState(); - return 0; // error detected next time. - } - return ret; -} - -int tou_maxwrite(int sockfd) -{ - if (!tou_stream_check(sockfd)) - { - return -1; - } - TcpOnUdp *tous = tou_streams[sockfd]; - tous->tcp->tick(); - - int ret = tous->tcp->write_allowed(); - if (ret < 0) - { - tous->lasterrno = tous->tcp->TcpErrorState(); - return 0; // error detected next time? - } - return ret; -} - - -/* close down the tcp over udp connection */ -int tou_close(int sockfd) -{ - TcpOnUdp *tous = NULL; - { - RsStackMutex stack(touMutex); /***** LOCKED ******/ - if (!tou_stream_check(sockfd)) - { - return -1; - } - tous = tou_streams[sockfd]; - tou_streams[sockfd] = NULL; - } - - if (tous->tcp) - { - tous->tcp->tick(); - - /* shut it down */ - tous->tcp->close(); - - /* now we need to work out which type of receiver we have */ -#ifdef TOU_DYNAMIC_CAST_CHECK - /* extra checking -> for testing purposes (dynamic cast) */ - UdpRelayReceiver *urr = dynamic_cast(tous->udpsr); - UdpPeerReceiver *upr = dynamic_cast(tous->udpsr); - if (urr) - { - urr->removeUdpPeer(tous->tcp); - } - else if (upr) - { - upr->removeUdpPeer(tous->tcp); - } - else - { - /* error */ - std::cerr << "tou_close() ERROR unknown udptype"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - } -#else - if (tous -> udptype == TOU_RECEIVER_TYPE_UDPRELAY) - { - UdpRelayReceiver *urr = (UdpRelayReceiver *) (tous->udpsr); - urr->removeUdpPeer(tous->tcp); - } - else if (tous -> udptype == TOU_RECEIVER_TYPE_UDPPEER) - { - UdpPeerReceiver *upr = (UdpPeerReceiver *) (tous->udpsr); - upr->removeUdpPeer(tous->tcp); - } - else - { - /* error */ - std::cerr << "tou_close() ERROR unknown udptype"; - std::cerr << std::endl; - tous -> lasterrno = EINVAL; - } - -#endif - - delete tous->tcp; - tous->tcp = NULL ; // prevents calling - - } - - delete tous; - return 1; -} - -/* get an error number */ -int tou_errno(int sockfd) -{ - if (!tou_stream_check(sockfd)) - { - return ENOTSOCK; - } - TcpOnUdp *tous = tou_streams[sockfd]; - return tous->lasterrno; -} - -int tou_clear_error(int sockfd) -{ - if (!tou_stream_check(sockfd)) - { - return -1; - } - TcpOnUdp *tous = tou_streams[sockfd]; - tous->lasterrno = 0; - return 0; -} - diff --git a/libretroshare/src/tcponudp/tou.h b/libretroshare/src/tcponudp/tou.h deleted file mode 100644 index 5635c50c5..000000000 --- a/libretroshare/src/tcponudp/tou.h +++ /dev/null @@ -1,138 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: tou.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef TOU_C_HEADER_H -#define TOU_C_HEADER_H - - -/* get OS-specific definitions for: - * struct sockaddr, socklen_t, ssize_t - */ - -#ifndef WINDOWS_SYS - - #include - #include - #include - -#else - #include - #include - #include -// #include - typedef int socklen_t; -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -/* standard C interface (as Unix-like as possible) - * for the tou (Tcp On Udp) library - */ - /* - * Init: - * The TOU library no longer references any UdpStack items. - * instead, two arrays should be passed to the init function. - * int tou_init( (void **) UdpSubReceiver **udpRecvers, int *udpType, int nUdps); - * - * The UdpSubReceivers should be derived classes, with corresponding types: - * UdpPeerReceiver TOU_RECEIVER_TYPE_UDPPEER - * UdpRelayReceiver TOU_RECEIVER_TYPE_UDPRELAY - * - */ - -#define MAX_TOU_RECEIVERS 16 - -#define TOU_RECEIVER_TYPE_NONE 0x0000 -#define TOU_RECEIVER_TYPE_UDPPEER 0x0001 -#define TOU_RECEIVER_TYPE_UDPRELAY 0x0002 - -// hack to avoid classes in C code. (MacOSX complaining) -int tou_init(void **udpSubRecvs, int *udpTypes, int nUdps); - - /* Connections are as similar to UNIX as possible - * (1) create a socket: tou_socket() this reserves a socket id. - * (2) connect: active: tou_connect() or passive: tou_listenfor(). - * (3) use as a normal socket. - * - * connect() now has a conn_period parameter - this is the - * estimate (in seconds) of how slowly the connection should proceed. - * - * tou_bind() is not valid. tou_init performs this role. - * tou_listen() is not valid. (must listen for a specific address) use tou_listenfor() instead. - * tou_accept() can still be used. - * - ****** THE ABOVE IS BECOMING LESS TRUE ******** - * - * I have now added Multiple type of TOU Connections (Proxy, Relay), - * and multiple UDP Receivers (meaning you can use different ports too). - * - * The UDP receivers must be specified at startup (new tou_init()) - * and the Receiver, and Type of connection must be specified when you - * open the socket. - * - * The parameters to tou_socket, therefore mean something! - * some extra checking has been put in to try and catch bad usage. - */ - - /* creation/connections */ -int tou_socket(uint32_t domain, uint32_t type, int protocol); -int tou_bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen); /* null op now */ -int tou_listen(int sockfd, int backlog); /* null op now */ -int tou_connect(int sockfd, const struct sockaddr *serv_addr, - socklen_t addrlen, uint32_t conn_period); -int tou_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); - -/* non-standard bonuses */ -int tou_connected(int sockfd); -int tou_listenfor(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen); - - - - /* UNIX interface: minimum for the SSL BIO interface */ -ssize_t tou_read(int sockfd, void *buf, size_t count); -ssize_t tou_write(int sockfd, const void *buf, size_t count); -int tou_close(int sockfd); - - /* non-standard */ -int tou_errno(int sockfd); -int tou_clear_error(int sockfd); - - /* check stream */ -int tou_maxread(int sockfd); -int tou_maxwrite(int sockfd); - - -#ifdef __cplusplus -} - -typedef struct sockaddr_in sockaddr_in; - -/// for relay connections -int tou_connect_via_relay( int sockfd, const sockaddr_in& own_addr, - const sockaddr_in& proxy_addr, - const sockaddr_in& dest_addr ); - -#endif -#endif - diff --git a/libretroshare/src/tcponudp/udppeer.cc b/libretroshare/src/tcponudp/udppeer.cc deleted file mode 100644 index b3cf10913..000000000 --- a/libretroshare/src/tcponudp/udppeer.cc +++ /dev/null @@ -1,140 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: udppeer.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010-2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "udppeer.h" -#include - -/* - * #define DEBUG_UDP_PEER 1 - */ - - -UdpPeerReceiver::UdpPeerReceiver(UdpPublisher *pub) - :UdpSubReceiver(pub), peerMtx("UdpSubReceiver") -{ - return; -} - -/* higher level interface */ -int UdpPeerReceiver::recvPkt(void *data, int size, struct sockaddr_in &from) -{ - /* print packet information */ -#ifdef DEBUG_UDP_PEER - std::cerr << "UdpPeerReceiver::recvPkt(" << size << ") from: " << from; - std::cerr << std::endl; -#endif - - RsStackMutex stack(peerMtx); /********** LOCK MUTEX *********/ - - /* look for a peer */ - std::map::iterator it; - it = streams.find(from); - - if (it == streams.end()) - { - /* peer unknown */ -#ifdef DEBUG_UDP_PEER - std::cerr << "UdpPeerReceiver::recvPkt() Peer Unknown!"; - std::cerr << std::endl; -#endif - return 0; - } - else - { - /* forward to them */ -#ifdef DEBUG_UDP_PEER - std::cerr << "UdpPeerReceiver::recvPkt() Sending to UdpPeer: "; - std::cerr << it->first; - std::cerr << std::endl; -#endif - (it->second)->recvPkt(data, size); - return 1; - } - /* done */ -} - - -int UdpPeerReceiver::status(std::ostream &out) -{ - RsStackMutex stack(peerMtx); /********** LOCK MUTEX *********/ - - out << "UdpPeerReceiver::status()" << std::endl; - out << "UdpPeerReceiver::peers:" << std::endl; - std::map::iterator it; - for(it = streams.begin(); it != streams.end(); ++it) - { - out << "\t" << it->first << std::endl; - } - out << std::endl; - - return 1; -} - - /* add a TCPonUDP stream */ -int UdpPeerReceiver::addUdpPeer(UdpPeer *peer, const struct sockaddr_in &raddr) -{ - RsStackMutex stack(peerMtx); /********** LOCK MUTEX *********/ - - - /* check for duplicate */ - std::map::iterator it; - it = streams.find(raddr); - bool ok = (it == streams.end()); - if (!ok) - { -#ifdef DEBUG_UDP_PEER - std::cerr << "UdpPeerReceiver::addUdpPeer() Peer already exists!" << std::endl; - std::cerr << "UdpPeerReceiver::addUdpPeer() ERROR" << std::endl; -#endif - } - else - { - streams[raddr] = peer; - } - - return ok; -} - -int UdpPeerReceiver::removeUdpPeer(UdpPeer *peer) -{ - RsStackMutex stack(peerMtx); /********** LOCK MUTEX *********/ - - /* check for duplicate */ - std::map::iterator it; - for(it = streams.begin(); it != streams.end(); ++it) - { - if (it->second == peer) - { -#ifdef DEBUG_UDP_PEER - std::cerr << "UdpPeerReceiver::removeUdpPeer() SUCCESS" << std::endl; -#endif - streams.erase(it); - return 1; - } - } - -#ifdef DEBUG_UDP_PEER - std::cerr << "UdpPeerReceiver::removeUdpPeer() ERROR" << std::endl; -#endif - return 0; -} - - diff --git a/libretroshare/src/tcponudp/udppeer.h b/libretroshare/src/tcponudp/udppeer.h deleted file mode 100644 index 9ecf23419..000000000 --- a/libretroshare/src/tcponudp/udppeer.h +++ /dev/null @@ -1,70 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: udppeer.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010-2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_UDP_PEER_RECV_H -#define RS_UDP_PEER_RECV_H - -#ifndef WINDOWS_SYS -#include -#endif - -#include "util/rsthreads.h" - -#include -#include -#include - -#include "tcponudp/rsudpstack.h" - -class UdpPeer -{ - public: -virtual ~UdpPeer() { return; } -virtual void recvPkt(void *data, int size) = 0; -}; - - -class UdpPeerReceiver: public UdpSubReceiver -{ - public: - - UdpPeerReceiver(UdpPublisher *pub); -virtual ~UdpPeerReceiver() { return; } - - /* add a TCPonUDP stream */ -int addUdpPeer(UdpPeer *peer, const struct sockaddr_in &raddr); -int removeUdpPeer(UdpPeer *peer); - - /* callback for recved data (overloaded from UdpReceiver) */ -virtual int recvPkt(void *data, int size, struct sockaddr_in &from); - -int status(std::ostream &out); - - private: - - RsMutex peerMtx; /* for all class data (below) */ - - std::map streams; - -}; - - -#endif diff --git a/libretroshare/src/tcponudp/udprelay.cc b/libretroshare/src/tcponudp/udprelay.cc deleted file mode 100644 index 68062b860..000000000 --- a/libretroshare/src/tcponudp/udprelay.cc +++ /dev/null @@ -1,1117 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: udprelay.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010-2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "udprelay.h" -#include -#include "util/rstime.h" -#include - -/* - * #define DEBUG_UDP_RELAY 1 - * #define DEBUG_UDP_RELAY_PKTS 1 - * #define DEBUG_UDP_RELAY_ERRORS 1 - */ - -#define DEBUG_UDP_RELAY_ERRORS 1 - -#ifdef DEBUG_UDP_RELAY -// DEBUG FUNCTION -#include "util/rsstring.h" -#include -int displayUdpRelayPacketHeader(const void *data, const int size); -#endif - -/****************** UDP RELAY STUFF **********/ - -// This packet size must be able to handle TcpStream Packets. -// At the moment, they can be 1000 + 20 for TcpOnUdp ... + 16 => 1036 minimal size. -// See Notes in tcpstream.h for more info -#define MAX_RELAY_UDP_PACKET_SIZE (1400 + 20 + 16) - - -UdpRelayReceiver::UdpRelayReceiver(UdpPublisher *pub) - :UdpSubReceiver(pub), udppeerMtx("UdpSubReceiver"), relayMtx("UdpSubReceiver") -{ - mClassLimit.resize(UDP_RELAY_NUM_CLASS); - mClassCount.resize(UDP_RELAY_NUM_CLASS); - mClassBandwidth.resize(UDP_RELAY_NUM_CLASS); - - - for(int i = 0; i < UDP_RELAY_NUM_CLASS; i++) - { - mClassCount[i] = 0; - mClassBandwidth[i] = 0; - } - - setRelayTotal(UDP_RELAY_DEFAULT_COUNT_ALL); - setRelayClassMax(UDP_RELAY_CLASS_FRIENDS, UDP_RELAY_DEFAULT_FRIEND, UDP_RELAY_DEFAULT_BANDWIDTH); - setRelayClassMax(UDP_RELAY_CLASS_FOF, UDP_RELAY_DEFAULT_FOF, UDP_RELAY_DEFAULT_BANDWIDTH); - setRelayClassMax(UDP_RELAY_CLASS_GENERAL, UDP_RELAY_DEFAULT_GENERAL, UDP_RELAY_DEFAULT_BANDWIDTH); - - /* only allocate this space once */ - mTmpSendPkt = rs_malloc(MAX_RELAY_UDP_PACKET_SIZE); - mTmpSendSize = MAX_RELAY_UDP_PACKET_SIZE; - - clearDataTransferred(); - - return; -} - -UdpRelayReceiver::~UdpRelayReceiver() -{ - free(mTmpSendPkt); -} - - -int UdpRelayReceiver::addUdpPeer(UdpPeer *peer, UdpRelayAddrSet *endPoints, const struct sockaddr_in *proxyaddr) -{ - struct sockaddr_in realPeerAddr = endPoints->mDestAddr; - { - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - /* check for duplicate */ - std::map::iterator it; - it = mStreams.find(realPeerAddr); - bool ok = (it == mStreams.end()); - if (!ok) - { -#ifdef DEBUG_UDP_RELAY_ERRORS - std::cerr << "UdpRelayReceiver::addUdpPeer() ERROR Peer already exists!" << std::endl; -#endif - return 0; - } - - /* setup a peer */ - UdpRelayEnd ure(endPoints, proxyaddr); - -#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::addUdpPeer() Installing UdpRelayEnd: " << ure << std::endl; -#endif - - mStreams[realPeerAddr] = ure; - } - - { - RsStackMutex stack(udppeerMtx); /********** LOCK MUTEX *********/ - - -#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::addUdpPeer() Installing UdpPeer" << std::endl; -#endif - - /* just overwrite */ - mPeers[realPeerAddr] = peer; - - } - - return 1; -} - - -int UdpRelayReceiver::removeUdpPeer(UdpPeer *peer) -{ - bool found = false; - struct sockaddr_in realPeerAddr; - - /* cleanup UdpPeer, and get reference for data */ - { - RsStackMutex stack(udppeerMtx); /********** LOCK MUTEX *********/ - - std::map::iterator it; - for(it = mPeers.begin(); it != mPeers.end(); ++it) - { - if (it->second == peer) - { - realPeerAddr = it->first; - mPeers.erase(it); - found = true; - -#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::removeUdpPeer() removing UdpPeer" << std::endl; -#endif - break; - } - } - } - - if (!found) - { -#ifdef DEBUG_UDP_RELAY_ERRORS - std::cerr << "UdpRelayReceiver::removeUdpPeer() Warning: Failed to find UdpPeer" << std::endl; -#endif - return 0; - } - - /* now we cleanup the associated data */ - { - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - std::map::iterator it; - it = mStreams.find(realPeerAddr); - if (it != mStreams.end()) - { - mStreams.erase(it); - } - else - { - /* ERROR */ -#ifdef DEBUG_UDP_RELAY_ERRORS - std::cerr << "UdpRelayReceiver::removeUdpPeer() ERROR failed to find Mapping" << std::endl; -#endif - } - } - return 1; -} - -int UdpRelayReceiver::getRelayEnds(std::list &relayEnds) -{ - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - std::map::iterator rit; - - for(rit = mStreams.begin(); rit != mStreams.end(); ++rit) - { - relayEnds.push_back(rit->second); - } - return 1; - - -} - -int UdpRelayReceiver::getRelayProxies(std::list &relayProxies) -{ - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - std::map::iterator rit; - - for(rit = mRelays.begin(); rit != mRelays.end(); ++rit) - { - relayProxies.push_back(rit->second); - } - return 1; -} - -#define RELAY_MAX_BANDWIDTH 1000 -#define RELAY_TIMEOUT 30 - - -int UdpRelayReceiver::checkRelays() -{ - -#ifdef DEBUG_UDP_RELAY - // As this locks - must be out of the Mutex. - status(std::cerr); -#endif - - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - /* iterate through the Relays */ - -#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::checkRelays()"; - std::cerr << std::endl; -#endif - - std::list eraseList; - std::map::iterator rit; - rstime_t now = time(NULL); - -#define BANDWIDTH_FILTER_K (0.8) - - for(rit = mRelays.begin(); rit != mRelays.end(); ++rit) - { - /* calc bandwidth */ - //rit->second.mBandwidth = rit->second.mDataSize / (float) (now - rit->second.mLastBandwidthTS); - // Switch to a Low-Pass Filter to average it out. - float instantBandwidth = rit->second.mDataSize / (float) (now - rit->second.mLastBandwidthTS); - - rit->second.mBandwidth *= (BANDWIDTH_FILTER_K); - rit->second.mBandwidth += (1.0 - BANDWIDTH_FILTER_K) * instantBandwidth; - - rit->second.mDataSize = 0; - rit->second.mLastBandwidthTS = now; - -#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::checkRelays()"; - std::cerr << "Relay: " << rit->first; - std::cerr << " using bandwidth: " << rit->second.mBandwidth; - std::cerr << std::endl; -#endif - - // ONLY A WARNING. -#ifdef DEBUG_UDP_RELAY - if (instantBandwidth > rit->second.mBandwidthLimit) - { - std::cerr << "UdpRelayReceiver::checkRelays() "; - std::cerr << "Warning instantBandwidth: " << instantBandwidth; - std::cerr << " Exceeding Limit: " << rit->second.mBandwidthLimit; - std::cerr << " for Relay: " << rit->first; - std::cerr << std::endl; - } -#endif - - if (rit->second.mBandwidth > rit->second.mBandwidthLimit) - { -#ifdef DEBUG_UDP_RELAY_ERRORS - std::cerr << "UdpRelayReceiver::checkRelays() "; - std::cerr << "Dropping Relay due to excessive Bandwidth: " << rit->second.mBandwidth; - std::cerr << " Exceeding Limit: " << rit->second.mBandwidthLimit; - std::cerr << " Relay: " << rit->first; - std::cerr << std::endl; -#endif - - /* if exceeding bandwidth -> drop */ - eraseList.push_back(rit->first); - } - else if (now - rit->second.mLastTS > RELAY_TIMEOUT) - { -#ifdef DEBUG_UDP_RELAY_ERRORS - /* if haven't transmitted for ages -> drop */ - std::cerr << "UdpRelayReceiver::checkRelays() "; - std::cerr << "Dropping Relay due to Timeout: " << rit->first; - std::cerr << std::endl; -#endif - eraseList.push_back(rit->first); - } - else - { - /* check the length of the relay - we will drop them after a certain amount of time */ - int lifetime = 0; - switch(rit->second.mRelayClass) - { - default: - case UDP_RELAY_CLASS_GENERAL: - lifetime = UDP_RELAY_LIFETIME_GENERAL; - break; - case UDP_RELAY_CLASS_FOF: - lifetime = UDP_RELAY_LIFETIME_FOF; - break; - case UDP_RELAY_CLASS_FRIENDS: - lifetime = UDP_RELAY_LIFETIME_FRIENDS; - break; - } - if (now - rit->second.mStartTS > lifetime) - { -#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::checkRelays() "; - std::cerr << "Dropping Relay due to Passing Lifetime Limit: " << lifetime; - std::cerr << " for class: " << rit->second.mRelayClass; - std::cerr << " Relay: " << rit->first; - std::cerr << std::endl; -#endif - - eraseList.push_back(rit->first); - } - } - } - - std::list::iterator it; - for(it = eraseList.begin(); it != eraseList.end(); ++it) - { - removeUdpRelay_relayLocked(&(*it)); - } - - return 1; -} - - -int UdpRelayReceiver::removeUdpRelay(UdpRelayAddrSet *addrSet) -{ - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - -#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::removeUdpRelay() :" << *addrSet << std::endl; -#endif - - return removeUdpRelay_relayLocked(addrSet); -} - - -int UdpRelayReceiver::addUdpRelay(UdpRelayAddrSet *addrSet, int &relayClass, uint32_t &bandwidth) -{ - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - /* check for duplicate */ - std::map::iterator rit = mRelays.find(*addrSet); - int ok = (rit == mRelays.end()); - if (!ok) - { -#ifdef DEBUG_UDP_RELAY_ERRORS - std::cerr << "UdpRelayReceiver::addUdpRelay() ERROR Peer already exists!" << std::endl; -#endif - return 0; - } - - /* will install if there is space! */ - if (installRelayClass_relayLocked(relayClass, bandwidth)) - { -#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::addUdpRelay() adding Relay" << std::endl; -#endif - /* create UdpRelay */ - UdpRelayProxy udpRelay(addrSet, relayClass, bandwidth); - UdpRelayAddrSet alt = addrSet->flippedSet(); - UdpRelayProxy altUdpRelay(&alt, relayClass, bandwidth); - - /* must install two (A, B) & (B, A) */ - mRelays[*addrSet] = udpRelay; - mRelays[alt] = altUdpRelay; - - /* grab bandwidth from one set */ - bandwidth = altUdpRelay.mBandwidthLimit; - - return 1; - } - -#ifdef DEBUG_UDP_RELAY_ERRORS - std::cerr << "UdpRelayReceiver::addUdpRelay() WARNING Too many Relays!" << std::endl; -#endif - return 0; -} - - - -int UdpRelayReceiver::removeUdpRelay_relayLocked(UdpRelayAddrSet *addrSet) -{ -#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::removeUdpRelay_relayLocked() :" << *addrSet << std::endl; -#endif - - /* find in Relay list */ - std::map::iterator rit = mRelays.find(*addrSet); - if (rit == mRelays.end()) - { - /* ERROR */ - std::cerr << "UdpRelayReceiver::removeUdpRelay()"; - std::cerr << "ERROR Finding Relay: " << *addrSet; - std::cerr << std::endl; - } - else - { - /* lets drop the count here too */ - removeRelayClass_relayLocked(rit->second.mRelayClass); - mRelays.erase(rit); - } - - /* rotate around and delete matching set */ - UdpRelayAddrSet alt = addrSet->flippedSet(); - - rit = mRelays.find(alt); - if (rit == mRelays.end()) - { - std::cerr << "UdpRelayReceiver::removeUdpRelay()"; - std::cerr << "ERROR Finding Alt Relay: " << alt; - std::cerr << std::endl; - /* ERROR */ - } - else - { - mRelays.erase(rit); - } - return 1; -} - - /* Need some stats, to work out how many relays we are supporting - * modified the code to allow degrading of class .... - * so if you have too many friends, they will fill a FOF spot - */ -int UdpRelayReceiver::installRelayClass_relayLocked(int &classIdx, uint32_t &bandwidth) -{ - /* check for total number of Relays */ - if (mClassCount[UDP_RELAY_CLASS_ALL] >= mClassLimit[UDP_RELAY_CLASS_ALL]) - { - std::cerr << "UdpRelayReceiver::installRelayClass() WARNING Too many Relays already"; - std::cerr << std::endl; - return 0; - } - - /* check the idx too */ - if ((classIdx < 0) || (classIdx >= UDP_RELAY_NUM_CLASS)) - { - std::cerr << "UdpRelayReceiver::installRelayClass() ERROR class Idx invalid"; - std::cerr << std::endl; - return 0; - } - - /* now check the specifics of the class */ - while(mClassCount[classIdx] >= mClassLimit[classIdx]) - { - std::cerr << "UdpRelayReceiver::installRelayClass() WARNING Relay Class Limit Exceeded"; - std::cerr << std::endl; - std::cerr << "UdpRelayReceiver::installRelayClass() ClassIdx: " << classIdx; - std::cerr << std::endl; - std::cerr << "UdpRelayReceiver::installRelayClass() ClassLimit: " << mClassLimit[classIdx]; - std::cerr << std::endl; - std::cerr << "UdpRelayReceiver::installRelayClass() Degrading Class =>: " << classIdx; - std::cerr << std::endl; - - classIdx--; - if (classIdx == 0) - { - std::cerr << "UdpRelayReceiver::installRelayClass() No Spaces Left"; - std::cerr << std::endl; - - return 0; - } - } - - std::cerr << "UdpRelayReceiver::installRelayClass() Relay Class Ok, Count incremented"; - std::cerr << std::endl; - - /* if we get here we can add one */ - ++mClassCount[UDP_RELAY_CLASS_ALL]; - ++mClassCount[classIdx]; - bandwidth = mClassBandwidth[classIdx]; - - return 1; -} - -int UdpRelayReceiver::removeRelayClass_relayLocked(int classIdx) -{ - /* check for total number of Relays */ - if (mClassCount[UDP_RELAY_CLASS_ALL] < 1) - { - std::cerr << "UdpRelayReceiver::removeRelayClass() ERROR no relays installed"; - std::cerr << std::endl; - return 0; - } - - /* check the idx too */ - if ((classIdx < 0) || (classIdx >= UDP_RELAY_NUM_CLASS)) - { - std::cerr << "UdpRelayReceiver::removeRelayClass() ERROR class Idx invalid"; - std::cerr << std::endl; - return 0; - } - - /* now check the specifics of the class */ - if (mClassCount[classIdx] < 1) - { - std::cerr << "UdpRelayReceiver::removeRelayClass() ERROR no relay of class installed"; - std::cerr << std::endl; - - return 0; - } - - std::cerr << "UdpRelayReceiver::removeRelayClass() Ok, Count decremented"; - std::cerr << std::endl; - - /* if we get here we can add one */ - mClassCount[UDP_RELAY_CLASS_ALL]--; - mClassCount[classIdx]--; - - return 1; -} - - -int UdpRelayReceiver::setRelayTotal(int count) -{ - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - mClassLimit[UDP_RELAY_CLASS_ALL] = count; - mClassLimit[UDP_RELAY_CLASS_GENERAL] = (int) (UDP_RELAY_FRAC_GENERAL * count); - mClassLimit[UDP_RELAY_CLASS_FOF] = (int) (UDP_RELAY_FRAC_FOF * count); - mClassLimit[UDP_RELAY_CLASS_FRIENDS] = (int) (UDP_RELAY_FRAC_FRIENDS * count); - - return count; -} - - -int UdpRelayReceiver::setRelayClassMax(int classIdx, int count, int bandwidth) -{ - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - /* check the idx */ - if ((classIdx < 0) || (classIdx >= UDP_RELAY_NUM_CLASS)) - { - std::cerr << "UdpRelayReceiver::setRelayMaximum() ERROR class Idx invalid"; - std::cerr << std::endl; - return 0; - } - - mClassLimit[classIdx] = count; - mClassBandwidth[classIdx] = bandwidth; - return 1; -} - - -int UdpRelayReceiver::getRelayClassMax(int classIdx) -{ - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - /* check the idx */ - if ((classIdx < 0) || (classIdx >= UDP_RELAY_NUM_CLASS)) - { - std::cerr << "UdpRelayReceiver::getRelayMaximum() ERROR class Idx invalid"; - std::cerr << std::endl; - return 0; - } - - return mClassLimit[classIdx]; -} - -int UdpRelayReceiver::getRelayClassBandwidth(int classIdx) -{ - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - /* check the idx */ - if ((classIdx < 0) || (classIdx >= UDP_RELAY_NUM_CLASS)) - { - std::cerr << "UdpRelayReceiver::getRelayMaximum() ERROR class Idx invalid"; - std::cerr << std::endl; - return 0; - } - - return mClassBandwidth[classIdx]; -} - -int UdpRelayReceiver::getRelayCount(int classIdx) -{ - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - /* check the idx */ - if ((classIdx < 0) || (classIdx >= UDP_RELAY_NUM_CLASS)) - { - std::cerr << "UdpRelayReceiver::getRelayCount() ERROR class Idx invalid"; - std::cerr << std::endl; - return 0; - } - - return mClassCount[classIdx]; -} - - -int UdpRelayReceiver::RelayStatus(std::ostream &out) -{ - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - /* iterate through the Relays */ - out << "UdpRelayReceiver::RelayStatus()"; - out << std::endl; - - std::map::iterator rit; - for(rit = mRelays.begin(); rit != mRelays.end(); ++rit) - { - out << "Relay for: " << rit->first; - out << std::endl; - - out << "\tClass: " << rit->second.mRelayClass; - out << "\tBandwidth: " << rit->second.mBandwidth; - out << "\tDataSize: " << rit->second.mDataSize; - out << "\tLastBandwidthTS: " << rit->second.mLastBandwidthTS; - out << std::endl; - } - - out << "ClassLimits:" << std::endl; - for(int i = 0; i < UDP_RELAY_NUM_CLASS; i++) - { - out << "Limit[" << i << "] = " << mClassLimit[i]; - out << " Count: " << mClassCount[i]; - out << " Bandwidth: " << mClassBandwidth[i]; - out << std::endl; - } - - return 1; -} - -int UdpRelayReceiver::status(std::ostream &out) -{ - - out << "UdpRelayReceiver::status()" << std::endl; - out << "UdpRelayReceiver::Relayed Connections:" << std::endl; - - RelayStatus(out); - - { - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - out << "UdpRelayReceiver::Connections:" << std::endl; - - std::map::iterator pit; - for(pit = mStreams.begin(); pit != mStreams.end(); ++pit) - { - out << "\t" << pit->first << " : " << pit->second; - out << std::endl; - } - } - - UdpPeersStatus(out); - - return 1; -} - -int UdpRelayReceiver::UdpPeersStatus(std::ostream &out) -{ - RsStackMutex stack(udppeerMtx); /********** LOCK MUTEX *********/ - - /* iterate through the Relays */ - out << "UdpRelayReceiver::UdpPeersStatus()"; - out << std::endl; - - std::map::iterator pit; - for(pit = mPeers.begin(); pit != mPeers.end(); ++pit) - { - out << "UdpPeer for: " << pit->first; - out << " is: " << pit->second; - out << std::endl; - } - return 1; -} - - -void UdpRelayReceiver::clearDataTransferred() -{ - { - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - mWriteBytes = 0; - mRelayBytes = 0; - } - - { - RsStackMutex stack(udppeerMtx); /********** LOCK MUTEX *********/ - - mReadBytes = 0; - } -} - - -void UdpRelayReceiver::getDataTransferred(uint32_t &read, uint32_t &write, uint32_t &relay) -{ - { - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - write = mWriteBytes; - relay = mRelayBytes; - } - - { - RsStackMutex stack(udppeerMtx); /********** LOCK MUTEX *********/ - - read = mReadBytes; - } - clearDataTransferred(); -} - - - -#define UDP_RELAY_HEADER_SIZE 16 - -/* higher level interface */ -int UdpRelayReceiver::recvPkt(void *data, int size, struct sockaddr_in &from) -{ - /* remove unused parameter warnings */ - (void) from; - - /* print packet information */ -#ifdef DEBUG_UDP_RELAY_PKTS - std::cerr << "UdpRelayReceiver::recvPkt(" << size << ") from: " << from; - std::cerr << std::endl; - displayUdpRelayPacketHeader(data, size); - -#endif - - if (!isUdpRelayPacket(data, size)) - { -#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::recvPkt() ERROR: is Not RELAY Pkt"; - std::cerr << std::endl; -#endif - return 0; - } - - /* decide if we are the relay, or the endpoint */ - UdpRelayAddrSet addrSet; - if (!extractUdpRelayAddrSet(data, size, addrSet)) - { -#ifdef DEBUG_UDP_RELAY_ERRORS - std::cerr << "UdpRelayReceiver::recvPkt() ERROR: cannot extract Addresses"; - std::cerr << std::endl; -#endif - /* fails most basic test, drop */ - return 0; - } - - { - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - /* lookup relay first (double entries) */ - std::map::iterator rit = mRelays.find(addrSet); - if (rit != mRelays.end()) - { - /* we are the relay */ -#ifdef DEBUG_UDP_RELAY_PKTS - std::cerr << "UdpRelayReceiver::recvPkt() We are the Relay. Passing onto: "; - std::cerr << rit->first.mDestAddr; - std::cerr << std::endl; -#endif - /* do accounting */ - rit->second.mLastTS = time(NULL); - rit->second.mDataSize += size; - - mRelayBytes += size; - - mPublisher->sendPkt(data, size, rit->first.mDestAddr, STD_RELAY_TTL); - return 1; - } - } - - /* otherwise we are likely to be the endpoint, - * use the peers Address from the header - */ - - { - RsStackMutex stack(udppeerMtx); /********** LOCK MUTEX *********/ - - std::map::iterator pit = mPeers.find(addrSet.mSrcAddr); - if (pit != mPeers.end()) - { - /* we are the end-point */ -#ifdef DEBUG_UDP_RELAY_PKTS - std::cerr << "UdpRelayReceiver::recvPkt() Sending to UdpPeer: "; - std::cerr << pit->first; - std::cerr << std::endl; -#endif - mReadBytes += size; - - /* remove the header */ - void *pktdata = (void *) (((uint8_t *) data) + UDP_RELAY_HEADER_SIZE); - int pktsize = size - UDP_RELAY_HEADER_SIZE; - if (pktsize > 0) - { - (pit->second)->recvPkt(pktdata, pktsize); - } - else - { - /* packet undersized */ -//#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::recvPkt() ERROR Packet Undersized"; - std::cerr << std::endl; -//#endif - } - return 1; - } - /* done */ - } - - /* unknown */ -//#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::recvPkt() Peer Unknown!"; - std::cerr << std::endl; -//#endif - return 0; -} - - -/* the address here must be the end point!, - * it cannot be proxy, as we could be using the same proxy for multiple connections. - */ -int UdpRelayReceiver::sendPkt(const void *data, int size, const struct sockaddr_in &to, int /*ttl*/) -{ - RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ - - /* work out who the proxy is */ - std::map::iterator it; - it = mStreams.find(to); - if (it == mStreams.end()) - { -//#ifdef DEBUG_UDP_RELAY - std::cerr << "UdpRelayReceiver::sendPkt() Peer Unknown!"; - std::cerr << std::endl; -//#endif - return 0; - } - -#ifdef DEBUG_UDP_RELAY_PKTS - std::cerr << "UdpRelayReceiver::sendPkt() to Relay: " << it->second; - std::cerr << std::endl; -#endif - - mWriteBytes += size; - - /* add a header to packet */ - int finalPktSize = createRelayUdpPacket(data, size, mTmpSendPkt, MAX_RELAY_UDP_PACKET_SIZE, &(it->second)); - - /* send the packet on */ - return mPublisher->sendPkt(mTmpSendPkt, finalPktSize, it->second.mProxyAddr, STD_RELAY_TTL); -} - -/***** RELAY PACKET FORMAT **************************** - * - * - * [ 0 | 1 | 2 | 3 ] - * - * [ 'R' 'L' 'Y' Version ] - * [ IP Address 1 ] - * [ Port 1 ][ IP Address 2 .... - * ... IP Address 2][ Port 2 ] - * [.... TUNNELLED DATA .... - * - * - * ... ] - * - * 16 Bytes: 4 ID, 6 IP:Port 1, 6 IP:Port 2 - */ - -#define UDP_IDENTITY_STRING_V1 "RLY1" -#define UDP_IDENTITY_SIZE_V1 4 - -int isUdpRelayPacket(const void *data, const int size) -{ - if (size < UDP_RELAY_HEADER_SIZE) - return 0; - - return (0 == strncmp((char *) data, UDP_IDENTITY_STRING_V1, UDP_IDENTITY_SIZE_V1)); -} - -#ifdef DEBUG_UDP_RELAY - -int displayUdpRelayPacketHeader(const void *data, const int size) -{ - int dsize = UDP_RELAY_HEADER_SIZE + 16; - if (size < dsize) - { - dsize = size; - } - - std::string out; - for(int i = 0; i < dsize; i++) - { - if ((i > 0) && (i % 16 == 0)) - { - out += "\n"; - } - - rs_sprintf_append(out, "%02x", (uint32_t) ((uint8_t*) data)[i]); - } - - std::cerr << "displayUdpRelayPacketHeader()" << std::endl; - std::cerr << out; - std::cerr << std::endl; - - return 1; -} -#endif - - -int extractUdpRelayAddrSet(const void *data, const int size, UdpRelayAddrSet &addrSet) -{ - if (size < UDP_RELAY_HEADER_SIZE) - { - std::cerr << "createRelayUdpPacket() ERROR invalid size"; - std::cerr << std::endl; - return 0; - } - - uint8_t *header = (uint8_t *) data; - - sockaddr_clear(&(addrSet.mSrcAddr)); - sockaddr_clear(&(addrSet.mDestAddr)); - - /* as IP:Port are already in network byte order, we can just write them to the dataspace */ - uint32_t ipaddr; - uint16_t port; - - memcpy(&ipaddr, &(header[4]), 4); - memcpy(&port, &(header[8]), 2); - - addrSet.mSrcAddr.sin_addr.s_addr = ipaddr; - addrSet.mSrcAddr.sin_port = port; - - memcpy(&ipaddr, &(header[10]), 4); - memcpy(&port, &(header[14]), 2); - - addrSet.mDestAddr.sin_addr.s_addr = ipaddr; - addrSet.mDestAddr.sin_port = port; - - return 1; -} - - -int createRelayUdpPacket(const void *data, const int size, void *newpkt, int newsize, UdpRelayEnd *ure) -{ - int pktsize = size + UDP_RELAY_HEADER_SIZE; - if (newsize < pktsize) - { - std::cerr << "createRelayUdpPacket() ERROR invalid size"; - std::cerr << std::endl; - std::cerr << "Incoming DataSize: " << size << " + Header: " << UDP_RELAY_HEADER_SIZE; - std::cerr << " > " << newsize; - std::cerr << std::endl; - return 0; - } - uint8_t *header = (uint8_t *) newpkt; - memcpy(header, UDP_IDENTITY_STRING_V1, UDP_IDENTITY_SIZE_V1); - - /* as IP:Port are already in network byte order, we can just write them to the dataspace */ - uint32_t ipaddr = ure->mLocalAddr.sin_addr.s_addr; - uint16_t port = ure->mLocalAddr.sin_port; - - memcpy(&(header[4]), &ipaddr, 4); - memcpy(&(header[8]), &port, 2); - - ipaddr = ure->mRemoteAddr.sin_addr.s_addr; - port = ure->mRemoteAddr.sin_port; - - memcpy(&(header[10]), &ipaddr, 4); - memcpy(&(header[14]), &port, 2); - - memcpy(&(header[16]), data, size); - - return pktsize; -} - - - -/******* Small Container Class Helper Functions ****/ - -UdpRelayAddrSet::UdpRelayAddrSet() -{ - sockaddr_clear(&mSrcAddr); - sockaddr_clear(&mDestAddr); -} - -UdpRelayAddrSet::UdpRelayAddrSet(const sockaddr_in *ownAddr, const sockaddr_in *destAddr) -{ - mSrcAddr = *ownAddr; - mDestAddr = *destAddr; -} - -UdpRelayAddrSet UdpRelayAddrSet::flippedSet() -{ - UdpRelayAddrSet flipped(&mDestAddr, &mSrcAddr); - return flipped; -} - - -int operator<(const UdpRelayAddrSet &a, const UdpRelayAddrSet &b) -{ - if (a.mSrcAddr < b.mSrcAddr) - { - return 1; - } - - if (a.mSrcAddr == b.mSrcAddr) - { - if (a.mDestAddr < b.mDestAddr) - { - return 1; - } - } - return 0; -} - - -UdpRelayProxy::UdpRelayProxy() -{ - mBandwidth = 0; - mDataSize = 0; - mLastBandwidthTS = 0; - mLastTS = time(NULL); // Must be set here, otherwise Proxy Timesout before anything can happen! - mRelayClass = 0; - - mStartTS = time(NULL); - mBandwidthLimit = 0; -} - -UdpRelayProxy::UdpRelayProxy(UdpRelayAddrSet *addrSet, int relayClass, uint32_t bandwidth) - : mAddrs(*addrSet), - mBandwidth(0), - mDataSize(0), - mLastBandwidthTS(0), - mLastTS(time(NULL)), - mStartTS(time(NULL)), - mBandwidthLimit(bandwidth), - mRelayClass(relayClass) -{ - /* bandwidth fallback */ - if (bandwidth == 0) - { - switch(relayClass) - { - default: - case UDP_RELAY_CLASS_GENERAL: - mBandwidthLimit = RELAY_MAX_BANDWIDTH; - break; - case UDP_RELAY_CLASS_FOF: - mBandwidthLimit = RELAY_MAX_BANDWIDTH; - break; - case UDP_RELAY_CLASS_FRIENDS: - mBandwidthLimit = RELAY_MAX_BANDWIDTH; - break; - } - } -} - -UdpRelayEnd::UdpRelayEnd() -{ - sockaddr_clear(&mLocalAddr); - sockaddr_clear(&mProxyAddr); - sockaddr_clear(&mRemoteAddr); - -} - -UdpRelayEnd::UdpRelayEnd(UdpRelayAddrSet *endPoints, const struct sockaddr_in *proxyaddr) -{ - mLocalAddr = endPoints->mSrcAddr; - mRemoteAddr = endPoints->mDestAddr; - mProxyAddr = *proxyaddr; -} - - - - - -std::ostream &operator<<(std::ostream &out, const UdpRelayAddrSet &uras) -{ - out << "<" << uras.mSrcAddr << "," << uras.mDestAddr << ">"; - return out; -} - -std::ostream &operator<<(std::ostream &out, const UdpRelayProxy &urp) -{ - rstime_t now = time(NULL); - out << "UdpRelayProxy for " << urp.mAddrs; - out << std::endl; - out << "\tRelayClass: " << urp.mRelayClass; - out << std::endl; - out << "\tBandwidth: " << urp.mBandwidth; - out << std::endl; - out << "\tDataSize: " << urp.mDataSize; - out << std::endl; - out << "\tLastBandwidthTS: " << now - urp.mLastBandwidthTS << " secs ago"; - out << std::endl; - out << "\tLastTS: " << now - urp.mLastTS << " secs ago"; - out << std::endl; - - return out; -} - -std::ostream &operator<<(std::ostream &out, const UdpRelayEnd &ure) -{ - out << "UdpRelayEnd: <" << ure.mLocalAddr << " => " << ure.mProxyAddr << " <= "; - out << ure.mRemoteAddr << ">"; - return out; -} - - - - diff --git a/libretroshare/src/tcponudp/udprelay.h b/libretroshare/src/tcponudp/udprelay.h deleted file mode 100644 index ba412ac5a..000000000 --- a/libretroshare/src/tcponudp/udprelay.h +++ /dev/null @@ -1,215 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: udprelay.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010-2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_UDP_RELAY_H -#define RS_UDP_RELAY_H - -#include "tcponudp/udppeer.h" -#include -#include - -class UdpRelayAddrSet; - -class UdpRelayAddrSet -{ - public: - UdpRelayAddrSet(); - UdpRelayAddrSet(const sockaddr_in *ownAddr, const sockaddr_in *destAddr); - - UdpRelayAddrSet flippedSet(); - - struct sockaddr_in mSrcAddr; /* msg source */ - struct sockaddr_in mDestAddr; /* final destination */ -}; - -int operator<(const UdpRelayAddrSet &a, const UdpRelayAddrSet &b); - -class UdpRelayProxy -{ - public: - UdpRelayProxy(); - UdpRelayProxy(UdpRelayAddrSet *addrSet, int relayClass, uint32_t bandwidth); - - UdpRelayAddrSet mAddrs; - double mBandwidth; - uint32_t mDataSize; - rstime_t mLastBandwidthTS; - rstime_t mLastTS; - - rstime_t mStartTS; - double mBandwidthLimit; - - int mRelayClass; -}; - - -class UdpRelayEnd -{ - public: - - UdpRelayEnd(); - UdpRelayEnd(UdpRelayAddrSet *endPoints, const struct sockaddr_in *proxyaddr); - - struct sockaddr_in mLocalAddr; - struct sockaddr_in mProxyAddr; - struct sockaddr_in mRemoteAddr; -}; - -std::ostream &operator<<(std::ostream &out, const UdpRelayAddrSet &uras); -std::ostream &operator<<(std::ostream &out, const UdpRelayProxy &urp); -std::ostream &operator<<(std::ostream &out, const UdpRelayEnd &ure); - -/* we define a couple of classes (determining which class is done elsewhere) - * There will be various maximums for each type. - * Ideally you want to allow your friends to use your proxy in preference - * to randoms. - * - * At N x 2 x maxBandwidth. - * - * 10 x 2 x 1Kb/s => 20Kb/s In and Out. (quite a bit!) - * 20 x 2 x 1Kb/s => 40Kb/s Huge. - */ - -#define UDP_RELAY_DEFAULT_COUNT_ALL 2 -#define UDP_RELAY_DEFAULT_FRIEND 0 -#define UDP_RELAY_DEFAULT_FOF 1 -#define UDP_RELAY_DEFAULT_GENERAL 1 -#define UDP_RELAY_DEFAULT_BANDWIDTH 1024 - -#define UDP_RELAY_FRAC_GENERAL (0.5) -#define UDP_RELAY_FRAC_FOF (0.5) -#define UDP_RELAY_FRAC_FRIENDS (0.0) - - - -/**** DEFINED IN EXTERNAL HEADER FILE ***/ -// sehraf: this is a bit ugly but since the int is used as an integer i'lll stick to this hack for now -/// TODO fix me! -#define UDP_RELAY_NUM_CLASS static_cast::type>(RsDhtRelayClass::NUM_CLASS) - -#define UDP_RELAY_CLASS_ALL static_cast::type>(RsDhtRelayClass::ALL) -#define UDP_RELAY_CLASS_GENERAL static_cast::type>(RsDhtRelayClass::GENERAL) -#define UDP_RELAY_CLASS_FOF static_cast::type>(RsDhtRelayClass::FOF) -#define UDP_RELAY_CLASS_FRIENDS static_cast::type>(RsDhtRelayClass::FRIENDS) - -// Just for some testing fun! -//#define UDP_RELAY_LIFETIME_GENERAL 180 // 3 minutes -//#define UDP_RELAY_LIFETIME_FOF 360 // 6 minutes. -//#define UDP_RELAY_LIFETIME_FRIENDS 720 // 12 minutes. - -#define UDP_RELAY_LIFETIME_GENERAL 3600 // 1 hour (chosen so we at least transfer 1 or 2 meg at lowest speed) -#define UDP_RELAY_LIFETIME_FOF 7200 // 2 Hours. -#define UDP_RELAY_LIFETIME_FRIENDS 14400 // 4 Hours. - -#define STD_RELAY_TTL 64 - -class UdpRelayReceiver: public UdpSubReceiver -{ - public: - - UdpRelayReceiver(UdpPublisher *pub); -virtual ~UdpRelayReceiver(); - - /* add a TCPonUDP stream (ENDs) */ -int addUdpPeer(UdpPeer *peer, UdpRelayAddrSet *endPoints, const struct sockaddr_in *proxyaddr); -int removeUdpPeer(UdpPeer *peer); - - /* add a Relay Point (for the Relay). - * These don't have to be explicitly removed. - * They will be timed out when - * the end-points drop the connections - */ - - int addUdpRelay(UdpRelayAddrSet *addrSet, int &relayClass, uint32_t &bandwidth); - int removeUdpRelay(UdpRelayAddrSet *addrs); - - /* Need some stats, to work out how many relays we are supporting */ - int checkRelays(); - - int setRelayTotal(int count); /* sets all the Relay Counts (frac based on total) */ - int setRelayClassMax(int classIdx, int count, int bandwidth); /* set a specific class maximum */ - int getRelayClassMax(int classIdx); - int getRelayClassBandwidth(int classIdx); - int getRelayCount(int classIdx); /* how many relays (of this type) do we have */ - int RelayStatus(std::ostream &out); - - /* Extract Relay Data */ - int getRelayEnds(std::list &relayEnds); - int getRelayProxies(std::list &relayProxies); - - /* callback for recved data (overloaded from UdpReceiver) */ -virtual int recvPkt(void *data, int size, struct sockaddr_in &from); - - /* wrapper function for relay (overloaded from UdpSubReceiver) */ -virtual int sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl); - -int status(std::ostream &out); -int UdpPeersStatus(std::ostream &out); - -void getDataTransferred(uint32_t &read, uint32_t &write, uint32_t &relay); - - private: - - void clearDataTransferred(); - - int removeUdpRelay_relayLocked(UdpRelayAddrSet *addrs); - int installRelayClass_relayLocked(int &classIdx, uint32_t &bandwidth); - int removeRelayClass_relayLocked(int classIdx); - - /* Unfortunately, Due the reentrant nature of this classes activities... - * the SendPkt() must be callable from inside RecvPkt(). - * This means we need two seperate mutexes. - * - one for UdpPeer's, and one for Relay Data. - * - * care must be taken to lock these mutex's in a consistent manner to avoid deadlock. - * - You are not allowed to hold both at the same time! - */ - - RsMutex udppeerMtx; /* for all class data (below) */ - - std::map mPeers; /* indexed by */ - uint32_t mReadBytes; - - RsMutex relayMtx; /* for all class data (below) */ - - std::vector mClassLimit, mClassCount, mClassBandwidth; - std::map mStreams; /* indexed by */ - std::map mRelays; /* indexed by */ - - void *mTmpSendPkt; - uint32_t mTmpSendSize; - - uint32_t mWriteBytes; - uint32_t mRelayBytes; - -}; - -/* utility functions for creating / extracting UdpRelayPackets */ -int isUdpRelayPacket(const void *data, const int size); -int getPacketFromUdpRelayPacket(const void *data, const int size, void **realdata, int *realsize); - -int createRelayUdpPacket(const void *data, const int size, void *newpkt, int newsize, UdpRelayEnd *ure); -int extractUdpRelayAddrSet(const void *data, const int size, UdpRelayAddrSet &addrSet); - - - - -#endif diff --git a/libretroshare/src/tcponudp/udpstunner.cc b/libretroshare/src/tcponudp/udpstunner.cc deleted file mode 100644 index 4409f256f..000000000 --- a/libretroshare/src/tcponudp/udpstunner.cc +++ /dev/null @@ -1,1194 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: udpstunner.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010-2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "tcponudp/udpstunner.h" -#include -#include "util/rstime.h" - -#include "util/rsrandom.h" -#include "util/rsprint.h" -#include "util/rsmemory.h" -#include "util/rsstring.h" - -static const int STUN_TTL = 64; - -#define TOU_STUN_MIN_PEERS 20 - -/* - * #define DEBUG_UDP_STUNNER 1 - * #define DEBUG_UDP_STUNNER_FILTER 1 - */ - -//#define DEBUG_UDP_STUNNER 1 - -const uint32_t TOU_STUN_MAX_FAIL_COUNT = 3; /* 3 tries (could be higher?) */ -const int32_t TOU_STUN_MAX_SEND_RATE = 5; /* every 5 seconds */ -const uint32_t TOU_STUN_MAX_RECV_RATE = 25; /* every 25 seconds */ -// TIMEOUT is now tied to STUN RATE ... const int32_t TOU_STUN_ADDR_MAX_AGE = 120; /* 2 minutes */ - -const int32_t TOU_STUN_DEFAULT_TARGET_RATE = 15; /* 20 secs is minimum to keep a NAT UDP port open */ -const double TOU_SUCCESS_LPF_FACTOR = 0.90; - -#define EXCLUSIVE_MODE_TIMEOUT 300 - -UdpStunner::UdpStunner(UdpPublisher *pub) - :UdpSubReceiver(pub), stunMtx("UdpSubReceiver"), eaddrKnown(false), eaddrStable(false), - mStunLastRecvResp(0), mStunLastRecvAny(0), - mStunLastSendStun(0), mStunLastSendAny(0) -{ -#ifdef UDPSTUN_ALLOW_LOCALNET - mAcceptLocalNet = false; - mSimExclusiveNat = false; - mSimSymmetricNat = false; - mSimUnstableExt = false; -#endif - - - - /* these parameters determine the rate we attempt stuns */ - mPassiveStunMode = false; - mSuccessRate = 0.0; - mTargetStunPeriod = TOU_STUN_DEFAULT_TARGET_RATE; - - mExclusiveMode = false; - mExclusiveModeTS = 0; - mForceRestun = false; - - return; -} - -#ifdef UDPSTUN_ALLOW_LOCALNET - - // For Local Testing Only (Releases should have the #define disabled) -void UdpStunner::SetAcceptLocalNet() -{ - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - mAcceptLocalNet = true; -} - - // For Local Testing Only (Releases should have the #define disabled) -void UdpStunner::SimExclusiveNat() -{ - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - mSimExclusiveNat = true; - mSimUnstableExt = true; -} - -void UdpStunner::SimSymmetricNat() -{ - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - mSimSymmetricNat = true; - mSimUnstableExt = true; -} - - - -#endif - - - -int UdpStunner::grabExclusiveMode(std::string holder) /* returns seconds since last send/recv */ -{ - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - rstime_t now = time(NULL); - - -#ifdef DEBUG_UDP_STUNNER_FILTER - std::cerr << "UdpStunner::grabExclusiveMode()"; - std::cerr << std::endl; -#endif - - if (mExclusiveMode) - { -#ifdef DEBUG_UDP_STUNNER_FILTER - std::cerr << "UdpStunner::grabExclusiveMode() FAILED"; - std::cerr << std::endl; -#endif - - std::cerr << "UdpStunner::grabExclusiveMode() FAILED, already held by: " << mExclusiveHolder; - std::cerr << std::endl; - std::cerr << "UdpStunner::grabExclusiveMode() Was Grabbed: " << now - mExclusiveModeTS; - std::cerr << " secs ago"; - std::cerr << std::endl; - - /* This can happen if AUTH, but START never received! (occasionally). - */ - if (now - mExclusiveModeTS > EXCLUSIVE_MODE_TIMEOUT) - { - mExclusiveMode = false; - mForceRestun = true; - - std::cerr << "UdpStunner::grabExclusiveMode() Held for too Long... TIMEOUT & Stun Forced"; - std::cerr << std::endl; - } - - return 0; - } - - mExclusiveMode = true; - mExclusiveModeTS = now; - mExclusiveHolder = holder; - - int lastcomms = mStunLastRecvAny; - if (mStunLastSendAny > lastcomms) - { - lastcomms = mStunLastSendAny; - } - - int commsage = now - lastcomms; - - /* cannot return 0, as this indicates error */ - if (commsage == 0) - { - commsage = 1; - } -#ifdef DEBUG_UDP_STUNNER_FILTER - std::cerr << "UdpStunner::grabExclusiveMode() SUCCESS. last comms: " << commsage; - std::cerr << " ago"; - std::cerr << std::endl; - std::cerr << "UdpStunner::grabExclusiveMode() Exclusive held by: " << mExclusiveHolder; - std::cerr << std::endl; -#endif - - return commsage; -} - -int UdpStunner::releaseExclusiveMode(std::string holder, bool forceStun) -{ - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - if (!mExclusiveMode) - { -#ifdef DEBUG_UDP_STUNNER_FILTER - std::cerr << "UdpStunner::cancelExclusiveMode() ERROR, not in exclusive Mode"; - std::cerr << std::endl; -#endif - return 0; - } - - mExclusiveMode = false; - if (forceStun) - { - mForceRestun = true; - } - -#ifdef UDPSTUN_ALLOW_LOCALNET - /* if we are simulating an exclusive NAT, then immediately after we release - it'll become unstable. - * In reality, it will only become unstable if we have tried a UDP connection. - * so we use the forceStun parameter (which is true when a UDP connection has been tried). - */ - - if ((mSimExclusiveNat) && (forceStun)) - { - mSimUnstableExt = true; - } -#endif - - if (mExclusiveHolder != holder) - { - std::cerr << "UdpStunner::cancelExclusiveMode() ERROR release MisMatch: "; - std::cerr << " Original Grabber: "; - std::cerr << mExclusiveHolder; - std::cerr << " Releaser: "; - std::cerr << holder; - std::cerr << std::endl; - } - -#ifdef DEBUG_UDP_STUNNER_FILTER - rstime_t now = time(nullptr); - std::cerr << "UdpStunner::cancelExclusiveMode() Canceled. Was in ExclusiveMode for: " << now - mExclusiveModeTS; - std::cerr << " secs"; - std::cerr << std::endl; -#endif - - return 1; -} - - -void UdpStunner::setTargetStunPeriod(int32_t sec_per_stun) -{ - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - if (sec_per_stun < 0) - { - mPassiveStunMode = false; - mTargetStunPeriod = TOU_STUN_DEFAULT_TARGET_RATE; - } - else - { - if (sec_per_stun == 0) - { - mPassiveStunMode = true; - } - else - { - mPassiveStunMode = false; - } - mTargetStunPeriod = sec_per_stun; - } - -} - -/* higher level interface */ -int UdpStunner::recvPkt(void *data, int size, struct sockaddr_in &from) -{ - /* print packet information */ -#ifdef DEBUG_UDP_STUNNER_FILTER - std::cerr << "UdpStunner::recvPkt(" << size << ") from: " << from; - std::cerr << std::endl; -#endif - - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - /* check for STUN packet */ - if (UdpStun_isStunPacket(data, size)) - { - mStunLastRecvAny = time(NULL); -#ifdef DEBUG_UDP_STUNNER_FILTER - std::cerr << "UdpStunner::recvPkt() is Stun Packet"; - std::cerr << std::endl; -#endif - - /* respond */ - locked_handleStunPkt(data, size, from); - - return 1; - } - return 0; -} - - -int UdpStunner::status(std::ostream &out) -{ - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - out << "UdpStunner::status() TargetStunPeriod: " << mTargetStunPeriod; - out << " SuccessRate: " << mSuccessRate; - out << std::endl; - - out << "UdpStunner::status()" << std::endl; - - locked_printStunList(); - - return 1; -} - -int UdpStunner::tick() -{ - -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::tick()" << std::endl; -#endif - - if (checkStunDesired()) - { - attemptStun(); -#ifdef DEBUG_UDP_STUNNER - status(std::cerr); -#endif - } - - return 1; -} - -/******************************* STUN Handling ********************************/ - - /* respond */ -bool UdpStunner::locked_handleStunPkt(void *data, int size, struct sockaddr_in &from) -{ - if (size == 20) /* request */ - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::handleStunPkt() got Request from: "; - std::cerr << inet_ntoa(from.sin_addr) << ":" << ntohs(from.sin_port); - std::cerr << std::endl; -#endif - /* generate a response */ - int len; - void *pkt = UdpStun_generate_stun_reply(&from, &len, data); - if (!pkt) - return false; - - rstime_t now = time(NULL); - mStunLastSendAny = now; - int sentlen = sendPkt(pkt, len, from, STUN_TTL); - free(pkt); - -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::handleStunPkt() sent Response size:" << sentlen; - std::cerr << std::endl; -#endif - - return (len == sentlen); - } - else if (size == 28) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::handleStunPkt() got Response"; - std::cerr << std::endl; -#endif - /* got response */ - struct sockaddr_in eAddr; - bool good = UdpStun_response(data, size, eAddr); - if (good) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::handleStunPkt() got Ext Addr: "; - std::cerr << inet_ntoa(eAddr.sin_addr) << ":" << ntohs(eAddr.sin_port); - std::cerr << " from: " << from; - std::cerr << std::endl; -#endif - locked_recvdStun(from, eAddr); - - return true; - } - } - -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::handleStunPkt() Bad Packet"; - std::cerr << std::endl; -#endif - return false; -} - - -bool UdpStunner::externalAddr(struct sockaddr_in &external, uint8_t &stable) -{ - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - if (eaddrKnown) - { - /* address timeout - * no timeout if in exclusive mode - */ - if ((time(NULL) - eaddrTime > (long) (mTargetStunPeriod * 2)) && (!mExclusiveMode)) - { - std::cerr << "UdpStunner::externalAddr() eaddr expired"; - std::cerr << std::endl; - - eaddrKnown = false; - return false; - } - - /* Force Restun is triggered after an Exclusive Mode... as Ext Address is likely to have changed - * Until the Restun has got an address - we act as if we don't have an external address - */ - if (mForceRestun) - { - return false; - } - - external = eaddr; - - if (eaddrStable) - stable = 1; - else - stable = 0; - -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::externalAddr() eaddr:" << inet_ntoa(external.sin_addr); - std::cerr << ":" << ntohs(external.sin_port) << " stable: " << (int) stable; - std::cerr << std::endl; -#endif - - - return true; - } -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::externalAddr() eaddr unknown"; - std::cerr << std::endl; -#endif - - return false; -} - - -int UdpStunner::doStun(struct sockaddr_in stun_addr) -{ -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::doStun()"; - std::cerr << std::endl; -#endif - - /* send out a stun packet -> save in the local variable */ - -#define MAX_STUN_SIZE 64 - char stundata[MAX_STUN_SIZE]; - int tmplen = MAX_STUN_SIZE; - bool done = UdpStun_generate_stun_pkt(stundata, &tmplen); - if (!done) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::doStun() Failed"; - std::cerr << std::endl; -#endif - //pqioutput(PQL_ALERT, pqistunzone, "pqistunner::stun() Failed!"); - return 0; - } - - /* send it off */ -#ifdef DEBUG_UDP_STUNNER - int sentlen = -#endif - sendPkt(stundata, tmplen, stun_addr, STUN_TTL); - - { - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - rstime_t now = time(NULL); - mStunLastSendStun = now; - mStunLastSendAny = now; - } - -#ifdef DEBUG_UDP_STUNNER - std::string out; - rs_sprintf(out, "UdpStunner::doStun() Sent Stun Packet(%d) to:%s:%u", sentlen, rs_inet_ntoa(stun_addr.sin_addr).c_str(), ntohs(stun_addr.sin_port)); - - std::cerr << out << std::endl; - - //pqioutput(PQL_ALERT, pqistunzone, out); -#endif - - return 1; -} - -/******************************* STUN Handling ********************************/ -/***** These next functions are generic and not dependent on class variables **/ -/******************************* STUN Handling ********************************/ - -bool UdpStun_response(void *stun_pkt, int size, struct sockaddr_in &addr) -{ - /* check what type it is */ - if (size < 28) - { - return false; - } - - if (htons(((uint16_t *) stun_pkt)[0]) != UdpStunner::STUN_BINDING_RESPONSE) - { - /* not a response */ - return false; - } - - /* iterate through the packet */ - /* for now assume the address follows the header directly */ - /* all stay in netbyteorder! */ - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = ((uint32_t *) stun_pkt)[6]; - addr.sin_port = ((uint16_t *) stun_pkt)[11]; - - -#ifdef DEBUG_UDP_STUNNER_FILTER - std::string out; - rs_sprintf(out, "UdpStunner::response() Recvd a Stun Response, ext_addr: %s:%u", rs_inet_ntoa(addr.sin_addr).c_str(), ntohs(addr.sin_port)); - std::cerr << out << std::endl; -#endif - - return true; - -} - -bool UdpStun_generate_stun_pkt(void *stun_pkt, int *len) -{ - if (*len < 20) - { - return false; - } - - /* just the header */ - ((uint16_t *) stun_pkt)[0] = (uint16_t) htons(UdpStunner::STUN_BINDING_REQUEST); - ((uint16_t *) stun_pkt)[1] = (uint16_t) htons(20); /* only header */ - /* RFC 3489 - * The transaction ID is used to correlate requests and responses. - * - * RFC 5389 introduces a mmgic cokie at the location where preciously the transaction ID was located: - * In RFC 3489, this field was part of - * the transaction ID; placing the magic cookie in this location allows - * a server to detect if the client will understand certain attributes - * that were added in this revised specification. - */ - RsRandom::random_bytes(&((uint8_t *) stun_pkt)[4], 4 * sizeof (uint32_t)); - *len = 20; - return true; -} - - -void *UdpStun_generate_stun_reply(struct sockaddr_in *stun_addr, int *len, const void *transId) -{ - /* just the header */ - void *stun_pkt = rs_malloc(28); - - if(!stun_pkt) - return nullptr ; - - ((uint16_t *) stun_pkt)[0] = (uint16_t) htons(UdpStunner::STUN_BINDING_RESPONSE); - ((uint16_t *) stun_pkt)[1] = (uint16_t) htons(28); /* only header + 8 byte addr */ - /* RFC 3489 - * The Binding Response MUST contain the same transaction ID contained in the Binding Request. - */ - memcpy(&((uint32_t *) stun_pkt)[1], &((uint32_t *) transId)[1], 4 * sizeof (uint32_t)); - - /* now add address - * 0 1 2 3 - * - * - */ - - /* THESE SHOULD BE NET ORDER ALREADY */ - ((uint16_t *) stun_pkt)[10] = AF_INET; - ((uint16_t *) stun_pkt)[11] = stun_addr->sin_port; - ((uint32_t *) stun_pkt)[6] = stun_addr->sin_addr.s_addr; - - *len = 28; - return stun_pkt; -} - -bool UdpStun_isStunPacket(void *data, int size) -{ -#ifdef DEBUG_UDP_STUNNER_FILTER - std::cerr << "UdpStunner::isStunPacket() ?"; - std::cerr << std::endl; -#endif - - if (size < 20) - { -#ifdef DEBUG_UDP_STUNNER_FILTER - std::cerr << "UdpStunner::isStunPacket() (size < 20) -> false"; - std::cerr << std::endl; -#endif - return false; - } - - /* match size field */ - uint16_t pktsize = ntohs(((uint16_t *) data)[1]); - if (size != pktsize) - { -#ifdef DEBUG_UDP_STUNNER_FILTER - std::cerr << "UdpStunner::isStunPacket() (size != pktsize) -> false"; - std::cerr << std::endl; -#endif - return false; - } - - if ((size == 20) && (UdpStunner::STUN_BINDING_REQUEST == ntohs(((uint16_t *) data)[0]))) - { -#ifdef DEBUG_UDP_STUNNER_FILTER - std::cerr << "UdpStunner::isStunPacket() (size=20 & data[0]=STUN_BINDING_REQUEST) -> true"; - std::cerr << std::endl; -#endif - /* request */ - return true; - } - - if ((size == 28) && (UdpStunner::STUN_BINDING_RESPONSE == ntohs(((uint16_t *) data)[0]))) - { -#ifdef DEBUG_UDP_STUNNER_FILTER - std::cerr << "UdpStunner::isStunPacket() (size=28 & data[0]=STUN_BINDING_RESPONSE) -> true"; - std::cerr << std::endl; -#endif - /* response */ - return true; - } - return false; -} - - -/******************************* STUN Handling ******************************** - * KeepAlive has been replaced by a targetStunRate. Set this to zero to disable. - */ - -/******************************* STUN Handling ********************************/ - - -bool UdpStunner::addStunPeer(const struct sockaddr_in &remote, const char *peerid) -{ - /* add to the list */ -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::addStunPeer()"; - std::cerr << std::endl; -#endif - - bool toStore = true; - { - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - /* only store if we're active */ - toStore = !mPassiveStunMode; - } - - if (toStore) - { - storeStunPeer(remote, peerid, 0); - } - return true; -} - -bool UdpStunner::storeStunPeer(const struct sockaddr_in &remote, const char *peerid, bool sent) -{ - -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::storeStunPeer()"; - std::cerr << std::endl; -#endif - - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - std::list::iterator it; - for(it = mStunList.begin(); it != mStunList.end(); ++it) - { - if ((remote.sin_addr.s_addr == it->remote.sin_addr.s_addr) && - (remote.sin_port == it->remote.sin_port)) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::storeStunPeer() Peer Already There!"; - std::cerr << std::endl; -#endif - /* already there */ - if (sent) - { - it->failCount += 1; - it->lastsend = time(NULL); - } - return false; - } - } - - std::string peerstring; - if (peerid) - { - peerstring = std::string(peerid); - } - - TouStunPeer peer(peerstring, remote); - if (sent) - { - peer.failCount += 1; - peer.lastsend = time(NULL); - } - - mStunList.push_back(peer); - -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::storeStunPeer() Added Peer"; - std::cerr << std::endl; -#endif - - return true; -} - - -bool UdpStunner::dropStunPeer(const struct sockaddr_in &remote) -{ - -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::dropStunPeer() : "; - std::cerr << std::endl; -#endif - - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - std::list::iterator it; - int count = 0; - for(it = mStunList.begin(); it != mStunList.end();) - { - if ((remote.sin_addr.s_addr == it->remote.sin_addr.s_addr) && - (remote.sin_port == it->remote.sin_port)) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::dropStunPeer() Found Entry"; - std::cerr << std::endl; -#endif - - it = mStunList.erase(it); - count++; - } - else - { - ++it; - } - } - - if (count) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::dropStunPeer() Dropped " << count << " Instances"; - std::cerr << std::endl; -#endif - return true; - } - -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::dropStunPeer() Peer Not Here"; - std::cerr << std::endl; -#endif - - return false; -} - - -bool UdpStunner::checkStunDesired() -{ - -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::checkStunDesired()"; - std::cerr << std::endl; -#endif - - rstime_t now; - { - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - if (mPassiveStunMode) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::checkStunDesired() In Passive Mode"; - std::cerr << std::endl; -#endif - return false; /* all good */ - } - - if (mExclusiveMode) - { - return false; /* no pings in exclusive mode */ - } - - if (mForceRestun) - { - return true; - } - - - if (!eaddrKnown) - { - /* check properly! (this will limit it to two successful stuns) */ - if (!locked_checkExternalAddress()) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::checkStunDesired() YES, we don't have extAddr Yet"; - std::cerr << std::endl; -#endif - return true; /* want our external address */ - } - } - - /* check if we need to send one now */ - now = time(NULL); - - /* based on SuccessRate & TargetStunRate, we work out if we should send one - * - * if we have 100% success rate, then we can delay until exactly TARGET RATE. - * if we have 0% success rate, then try at double TARGET RATE. - * - * generalised to a rate_scale parameter below... - */ - -#define RATE_SCALE (3.0) - double stunPeriod = (mTargetStunPeriod / (RATE_SCALE)) * (1.0 + mSuccessRate * (RATE_SCALE - 1.0)); - rstime_t nextStun = mStunLastRecvResp + (int) stunPeriod; - -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::checkStunDesired() TargetStunPeriod: " << mTargetStunPeriod; - std::cerr << " SuccessRate: " << mSuccessRate; - std::cerr << " DesiredStunPeriod: " << stunPeriod; - std::cerr << " NextStun: " << nextStun - now << " secs"; - std::cerr << std::endl; -#endif - - if (now >= nextStun) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::checkStunDesired() Stun is Desired"; - std::cerr << std::endl; -#endif - return true; - } - else - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::checkStunDesired() Stun is Not Needed"; - std::cerr << std::endl; -#endif - return false; - } - } -} - - -bool UdpStunner::attemptStun() -{ - bool found = false; - TouStunPeer peer; - rstime_t now = time(NULL); - -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::attemptStun()"; - std::cerr << std::endl; -#endif - - { - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - size_t i; - for(i = 0; ((i < mStunList.size()) && (mStunList.size() > 0) && (!found)); i++) - { - /* extract entry */ - peer = mStunList.front(); - mStunList.pop_front(); - - /* check if expired */ - if (peer.failCount > TOU_STUN_MAX_FAIL_COUNT) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::attemptStun() Peer has expired, dropping"; - std::cerr << std::endl; -#endif - } - else - { - // Peer Okay, check last send time. - if (now - peer.lastsend < TOU_STUN_MAX_SEND_RATE) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::attemptStun() Peer was sent to Too Recently, pushing back"; - std::cerr << std::endl; -#endif - mStunList.push_back(peer); - } - else - { - /* we have found a peer! */ -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::attemptStun() Found Peer to Stun."; - std::cerr << std::endl; -#endif - peer.failCount++; - peer.lastsend = now; - mStunList.push_back(peer); - mSuccessRate *= TOU_SUCCESS_LPF_FACTOR; - - found = true; - } - } - } // END OF WHILE LOOP. - - if (mStunList.size() < 1) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::attemptStun() No Peers in List. FAILED"; - std::cerr << std::endl; -#endif - return false; - } - -#ifdef DEBUG_UDP_STUNNER - locked_printStunList(); -#endif - - } // END OF MUTEX LOCKING. - - if (found) - { - doStun(peer.remote); - return true; - } - return false; -} - - -bool UdpStunner::locked_recvdStun(const struct sockaddr_in &remote, const struct sockaddr_in &extaddr) -{ -#ifdef DEBUG_UDP_STUNNER - std::string out; - rs_sprintf(out, "UdpStunner::locked_recvdStun() from:%s:%u", rs_inet_ntoa(remote.sin_addr).c_str(), ntohs(remote.sin_port)); - rs_sprintf_append(out, " claiming ExtAddr is:%s:%u", rs_inet_ntoa(extaddr.sin_addr).c_str(), ntohs(extaddr.sin_port)); - - std::cerr << out << std::endl; -#endif - -#ifdef UDPSTUN_ALLOW_LOCALNET - struct sockaddr_in fakeExtaddr = extaddr; - if (mSimUnstableExt) - { - std::cerr << "UdpStunner::locked_recvdStun() TEST SIM UNSTABLE EXT: Forcing Port to be wrong to sim an ExclusiveNat"; - std::cerr << std::endl; - -#define UNSTABLE_PORT_RANGE 100 - - fakeExtaddr.sin_port = htons(ntohs(fakeExtaddr.sin_port) - (UNSTABLE_PORT_RANGE / 2) + RSRandom::random_u32() % UNSTABLE_PORT_RANGE); - if (!mSimSymmetricNat) - { - mSimUnstableExt = false; - } - } -#endif - - /* sanoty checks on the address - * have nasty peer that is returning its own address.... - */ - -#ifndef UDPSTUN_ALLOW_LOCALNET // CANNOT HAVE THIS CHECK IN TESTING MODE! - - if (remote.sin_addr.s_addr == extaddr.sin_addr.s_addr) - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::locked_recvdStun() WARNING, BAD PEER: "; - std::cerr << "Stun Peer Returned its own address: " << rs_inet_ntoa(remote.sin_addr); - std::cerr << std::endl; -#endif - return false; - } -#endif - - bool found = false; - std::list::iterator it; - for(it = mStunList.begin(); it != mStunList.end(); ++it) - { - if ((remote.sin_addr.s_addr == it->remote.sin_addr.s_addr) && - (remote.sin_port == it->remote.sin_port)) - { - it->failCount = 0; -#ifdef UDPSTUN_ALLOW_LOCALNET - it->eaddr = fakeExtaddr; -#else - it->eaddr = extaddr; -#endif - it->response = true; - - found = true; - break; - } - } - - /* We've received a Stun, so the ForceStun can be cancelled */ - if (found) - { - mForceRestun = false; - } - - /* if not found.. should we add it back in? */ - - /* How do we calculate the success rate? - * Don't want to count all the stuns? - * Low Pass filter won't work either... - * at send... - * mSuccessRate = 0.95 * mSuccessRate. - * at recv... - * mSuccessRate = 0.95 * mSuccessRate + 0.05; - * - * But if we split into a two stage eqn. it'll work! - * a - * mSuccessRate = 0.95 * mSuccessRate. - * at recv... - * mSuccessRate += 0.05; - */ - - mSuccessRate += (1.0-TOU_SUCCESS_LPF_FACTOR); - - rstime_t now = time(NULL); - mStunLastRecvResp = now; - mStunLastRecvAny = now; - -#ifdef DEBUG_UDP_STUNNER - locked_printStunList(); -#endif - - if (!mExclusiveMode) - { - locked_checkExternalAddress(); - } - - return found; -} - -bool UdpStunner::locked_checkExternalAddress() -{ -#ifdef DEBUG_UDP_STUNNER - std::string out = "UdpStunner::locked_checkExternalAddress()"; - std::cerr << out << std::endl; -#endif - - bool found1 = false; - bool found2 = false; - rstime_t now = time(NULL); - /* iterator backwards - as these are the most recent */ - - /******** - * DUE TO PEERS SENDING BACK FAKE STUN PACKETS... we are increasing. - * requirements to three peers...they all need matching IP addresses to have a known ExtAddr - * - * Wanted to compare 3 peer addresses... but this will mean that the UDP connections - * will take much longer... have to think of a better solution. - * - */ - std::list::reverse_iterator it; - std::list::reverse_iterator p1; - std::list::reverse_iterator p2; - for(it = mStunList.rbegin(); it != mStunList.rend(); ++it) - { - /* check: - 1) have response. - 2) have eaddr. - 3) no fails. - 4) recent age. - */ - - rstime_t age = (now - it->lastsend); - if (it->response && -#ifdef UDPSTUN_ALLOW_LOCALNET - ( mAcceptLocalNet || isExternalNet(&(it->eaddr.sin_addr))) && -#else - (isExternalNet(&(it->eaddr.sin_addr))) && -#endif - (it->failCount == 0) && (age < (long) (mTargetStunPeriod * 2))) - { - if (!found1) - { - p1 = it; - found1 = true; - } - else - { - p2 = it; - found2 = true; - break; - } - } - } - - if (found1 && found2) - { - /* If any of the addresses are different - two possibilities... - * 1) We have changed IP address. - * 2) Someone has sent us a fake STUN Packet. (Wrong Address). - * - */ - if (p1->eaddr.sin_addr.s_addr == p2->eaddr.sin_addr.s_addr) - { - eaddrKnown = true; - } - else - { -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::locked_checkExternalAddress() Found Address mismatch:"; - std::cerr << std::endl; - std::cerr << " " << inet_ntoa(p1->eaddr.sin_addr); - std::cerr << " " << inet_ntoa(p2->eaddr.sin_addr); - std::cerr << std::endl; - std::cerr << "UdpStunner::locked_checkExternalAddress() Flagging Ext Addr as Unknown"; - std::cerr << std::endl; -#endif - eaddrKnown = false; - } - - if ((eaddrKnown) && - (p1->eaddr.sin_port == p2->eaddr.sin_port)) - { - eaddrStable = true; - } - else - { - eaddrStable = false; - } - - eaddr = p1->eaddr; - eaddrTime = now; - -#ifdef DEBUG_UDP_STUNNER - std::cerr << "UdpStunner::locked_checkExternalAddress() Found State:"; - if (eaddrStable) - std::cerr << " Stable NAT translation (GOOD!) "; - else - std::cerr << " unStable (symmetric NAT translation (BAD!) or Address Unknown"; - - std::cerr << std::endl; -#endif - - return true; - } - - return false; -} - - - -bool UdpStunner::locked_printStunList() -{ -#ifdef DEBUG_UDP_STUNNER - std::string out = "locked_printStunList()\n"; - - rstime_t now = time(NULL); - rs_sprintf_append(out, "\tLastSendStun: %ld\n", now - mStunLastSendStun); - rs_sprintf_append(out, "\tLastSendAny: %ld\n", now - mStunLastSendAny); - rs_sprintf_append(out, "\tLastRecvResp: %ld\n", now - mStunLastRecvResp); - rs_sprintf_append(out, "\tLastRecvAny: %ld\n", now - mStunLastRecvAny); - - std::list::iterator it; - for(it = mStunList.begin(); it != mStunList.end(); ++it) - { - out += "id:" + RsUtil::BinToHex(it->id); - rs_sprintf_append(out, " addr: %s:%u", rs_inet_ntoa(it->remote.sin_addr).c_str(), htons(it->remote.sin_port)); - rs_sprintf_append(out, " eaddr: %s:%u", rs_inet_ntoa(it->eaddr.sin_addr).c_str(), htons(it->eaddr.sin_port)); - rs_sprintf_append(out, " failCount: %lu", it->failCount); - rs_sprintf_append(out, " lastSend: %ld\n", now - it->lastsend); - } - - std::cerr << out; -#endif - - return true; -} - - -bool UdpStunner::getStunPeer(int idx, std::string &id, - struct sockaddr_in &remote, struct sockaddr_in &eaddr, - uint32_t &failCount, rstime_t &lastSend) -{ - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - std::list::iterator it; - int i; - for(i=0, it=mStunList.begin(); (iid); - remote = it->remote; - eaddr = it->eaddr; - failCount = it->failCount; - lastSend = it->lastsend; - return true; - } - - return false; -} - - -bool UdpStunner::needStunPeers() -{ - RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ - - return (mStunList.size() < TOU_STUN_MIN_PEERS); -} - - diff --git a/libretroshare/src/tcponudp/udpstunner.h b/libretroshare/src/tcponudp/udpstunner.h deleted file mode 100644 index 00accaa45..000000000 --- a/libretroshare/src/tcponudp/udpstunner.h +++ /dev/null @@ -1,197 +0,0 @@ -/******************************************************************************* - * libretroshare/src/tcponudp: udpstunner.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010-2010 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_UDP_STUN_H -#define RS_UDP_STUN_H - -#ifndef WINDOWS_SYS -#include -#endif - -#include "tcponudp/rsudpstack.h" -#include "util/rsthreads.h" -#include - -/** - * @brief The TouStunPeer class - * Stuns peers to determine external addresses. - */ -class TouStunPeer -{ - public: - TouStunPeer() - :response(false), lastsend(0), failCount(0) - { - eaddr.sin_addr.s_addr = 0; - eaddr.sin_port = 0; - return; - } - - TouStunPeer(std::string id_in, const struct sockaddr_in &addr) - :id(id_in), remote(addr), response(false), lastsend(0), failCount(0) - { - eaddr.sin_addr.s_addr = 0; - eaddr.sin_port = 0; - return; - } - - /// id for identification - std::string id; - /// Remote address of the peer. - struct sockaddr_in remote; - /// Our external IP address as reported by the peer. - struct sockaddr_in eaddr; - /// true when a response was received in the past - bool response; - /// used to rate limit STUN requests - rstime_t lastsend; - /// fail counter for dead/bad peer detection (0 = good) - uint32_t failCount; -}; - -/* - * FOR TESTING ONLY. - * #define UDPSTUN_ALLOW_LOCALNET 1 - */ - -/** - * @brief The UdpStunner class - * The UDP stunner implements the STUN protocol to determin the NAT type (behind that RS is usually running). - * It maintains a list of DHT peers that are regulary contacted. - * - * The actual NAT type determination logic is located in void pqiNetStateBox::determineNetworkState() - */ -class UdpStunner: public UdpSubReceiver -{ - public: - - UdpStunner(UdpPublisher *pub); -virtual ~UdpStunner() { return; } - -#ifdef UDPSTUN_ALLOW_LOCALNET - // For Local Testing Mode. - void SetAcceptLocalNet(); - void SimExclusiveNat(); - void SimSymmetricNat(); -#endif - -int grabExclusiveMode(std::string holder); /* returns seconds since last send/recv */ -int releaseExclusiveMode(std::string holder, bool forceStun); - - -void setTargetStunPeriod(int32_t sec_per_stun); -bool addStunPeer(const struct sockaddr_in &remote, const char *peerid); -bool dropStunPeer(const struct sockaddr_in &remote); - -bool getStunPeer(int idx, std::string &id, - struct sockaddr_in &remote, struct sockaddr_in &eaddr, - uint32_t &failCount, rstime_t &lastSend); - -bool needStunPeers(); - -bool externalAddr(struct sockaddr_in &remote, uint8_t &stable); - - /* Packet IO */ -virtual int recvPkt(void *data, int size, struct sockaddr_in &from); -virtual int status(std::ostream &out); - - /* monitoring / updates */ - int tick(); - - /* - * based on RFC 3489 - */ - static constexpr uint16_t STUN_BINDING_REQUEST = 0x0001; - static constexpr uint16_t STUN_BINDING_RESPONSE = 0x0101; - - private: - -bool checkStunDesired(); -bool attemptStun(); - -int doStun(struct sockaddr_in stun_addr); -bool storeStunPeer(const struct sockaddr_in &remote, const char *peerid, bool sent); - - - /* STUN handling */ -bool locked_handleStunPkt(void *data, int size, struct sockaddr_in &from); - -bool locked_printStunList(); -bool locked_recvdStun(const struct sockaddr_in &remote, const struct sockaddr_in &extaddr); -bool locked_checkExternalAddress(); - - - RsMutex stunMtx; /* for all class data (below) */ - - struct sockaddr_in eaddr; /* external addr */ - - bool eaddrKnown; - bool eaddrStable; /* if true then usable. if false -> Symmettric NAT */ - rstime_t eaddrTime; - - rstime_t mStunLastRecvResp; - rstime_t mStunLastRecvAny; - rstime_t mStunLastSendStun; - rstime_t mStunLastSendAny; - - std::list mStunList; /* potentials */ - -#ifdef UDPSTUN_ALLOW_LOCALNET - // For Local Testing Mode. - bool mAcceptLocalNet; - bool mSimUnstableExt; - bool mSimExclusiveNat; - bool mSimSymmetricNat; - -#endif - - /// The UDP stunner will only (actively) contact it's peers when mPassiveStunMode is false. (has priority over mForceRestun - bool mPassiveStunMode; - /// Time between STUNs - uint32_t mTargetStunPeriod; - /// Rate that determines how often STUN attempts are successfull - double mSuccessRate; - - /// Some variables used for tracking who and when exclusive mode is enabled - bool mExclusiveMode; /* when this is switched on, the stunner stays silent (and extAddr is maintained) */ - rstime_t mExclusiveModeTS; - std::string mExclusiveHolder; - - /// force a STUN immediately - bool mForceRestun; - -}; - - /* generic stun functions */ - -bool UdpStun_isStunPacket(void *data, int size); -bool UdpStun_response(void *stun_pkt, int size, struct sockaddr_in &addr); -/** - * @brief UdpStun_generate_stun_reply Generates a STUN reply package. - * @param stun_addr The address to set in the response field. - * @param len Lenght of the generated package (always 28). - * @param transId The transaction ID of the request package. - * @return Pointer to the generated reply package. - */ -void *UdpStun_generate_stun_reply(struct sockaddr_in *stun_addr, int *len, const void* transId); -bool UdpStun_generate_stun_pkt(void *stun_pkt, int *len); - -#endif diff --git a/libretroshare/src/tests/TestNotes.txt b/libretroshare/src/tests/TestNotes.txt deleted file mode 100644 index 5d993d8d1..000000000 --- a/libretroshare/src/tests/TestNotes.txt +++ /dev/null @@ -1,39 +0,0 @@ - -This file documents the high-level status of the regression cases. ------------+----------------------+------------------------------------------------- -DIRECTORY | STATUS | TODO ------------+----------------------+------------------------------------------------- -services | NO TESTS | write test framework for services. -turtle | NO TESTS | write tests -rsserver | NO TESTS | write tests -upnp | automatic tests | [--S] -pgp | automatic tests | [---] -util | automatic tests | [---] -dbase | automatic tests | [--S] -pqi | automatic tests | [C--] -ft | automatic tests | [-FS] (ftcontrollertest, ftserver2test, fttransfermoduletest) -tcponudp | automatic tests | [-F-] Takes 15 mins. test_tou,bidir_tou,stacks_tou fail -dht | NO TESTS | write tests -serialiser | automatic tests | [-F-] (tlvrandom_test) ------------+----------------------+------------------------------------------------- - -Legend: - [---] : nothing to do. All work perfectly. - [ S] : needs scripts - [ F ] : some tests fail - [C ] : some tests don't compile - [E ] : some test execution fail - -Commands: - - to launch tests in a directory: - > \rm *.tstout - > make regress - - - to use parameters: - * create a script [testname].sh where [testname] is the name of the - executable test. It will be used automatically by the above command. - * in the script, use a single command, or if necessary put all commands - on one line using &&. - - - diff --git a/libretroshare/src/tests/common/testutils.h b/libretroshare/src/tests/common/testutils.h deleted file mode 100644 index f5323139c..000000000 --- a/libretroshare/src/tests/common/testutils.h +++ /dev/null @@ -1,100 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -class TestUtils -{ - public: - // Creates a random file of the given size at the given place. Useful for file transfer tests. - // - static bool createRandomFile(const std::string& filename,const uint64_t size) - { - FILE *f = fopen(filename.c_str(),"wb") ; - - if(f == NULL) - return 0 ; - - uint32_t S = 5000 ; - uint32_t *data = new uint32_t[S] ; - - for(uint64_t i=0;i::random().toStdString(false); - } - static std::string createRandomSSLId() - { - return t_RsGenericIdType<16>::random().toStdString(false); - } - static std::string createRandomPGPId() - { - return t_RsGenericIdType<8>::random().toStdString(true); - } - - class DummyAuthGPG: public AuthGPG - { - public: - DummyAuthGPG(const std::string& ownId) - :AuthGPG("pgp_pubring.pgp","pgp_secring.pgp","pgp_trustdb.pgp","lock"), mOwnId(ownId) - { - } - - virtual std::string getGPGOwnId() - { - return mOwnId ; - } - - virtual bool isGPGAccepted(const std::string& pgp_id) { return true ; } - - private: - std::string mOwnId ; - }; - - class DummyAuthSSL: public AuthSSLimpl - { - public: - DummyAuthSSL(const std::string& ownId) - : mOwnId(ownId) - { - } - - virtual std::string OwnId() - { - return mOwnId ; - } - - private: - std::string mOwnId ; - }; - - class DummyRsPeers: public p3Peers - { - public: - DummyRsPeers(p3LinkMgr *lm, p3PeerMgr *pm, p3NetMgr *nm) : p3Peers(lm,pm,nm) {} - - //virtual bool getFriendList(std::list& fl) { ; return true ;} - - private: - std::list mFriends ; - }; -}; diff --git a/libretroshare/src/tests/dbase/ficachetest.cc b/libretroshare/src/tests/dbase/ficachetest.cc deleted file mode 100644 index 3d2c62074..000000000 --- a/libretroshare/src/tests/dbase/ficachetest.cc +++ /dev/null @@ -1,208 +0,0 @@ -/* - * RetroShare FileCache Module: ficachetest.cc - * - * Copyright 2004-2007 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "dbase/cachestrapper.h" -#include "dbase/cachetest.h" -#include "pqi/p3connmgr.h" - -#include -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS -#else - #include -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - -void handleQuery(CacheStrapper *csp, RsPeerId pid, - std::map &strappers); - -/* A simple test of the CacheStrapper Code. - * - * create 3 different CacheStrappers, each with a Source/Store Pair and Transfer Class. - * pass queries and responses between the CacheStrappers, - * and ensure that the hashes in the Caches are updated. - * - */ - -int main(int argc, char **argv) -{ - - rstime_t period = 11; - RsPeerId pid1("0x0101"); - RsPeerId pid2("0x0102"); - RsPeerId pid3("0x0103"); - - p3ConnectMgr *connMgr1 = new p3ConnectMgr(); - p3ConnectMgr *connMgr2 = connMgr1; - p3ConnectMgr *connMgr3 = connMgr1; - - CacheStrapper sc1(connMgr1); - CacheStrapper sc2(connMgr2); - CacheStrapper sc3(connMgr3); - CacheTransfer ctt1(&sc1); - CacheTransfer ctt2(&sc2); - CacheTransfer ctt3(&sc3); - - std::map strappers; - strappers[pid1] = &sc1; - strappers[pid2] = &sc2; - strappers[pid3] = &sc3; - - - std::string nulldir = ""; - - CacheSource *csrc1 = new CacheTestSource(&sc1, nulldir); - CacheStore *cstore1 = new CacheTestStore(&ctt1, &sc1, nulldir); - CacheId cid1(TESTID, 0); - - CacheSource *csrc2 = new CacheTestSource(&sc2, nulldir); - CacheStore *cstore2 = new CacheTestStore(&ctt2, &sc2, nulldir); - CacheId cid2(TESTID, 0); - - CacheSource *csrc3 = new CacheTestSource(&sc3, nulldir); - CacheStore *cstore3 = new CacheTestStore(&ctt3, &sc3, nulldir); - CacheId cid3(TESTID, 0); - - CachePair cp1(csrc1, cstore1, cid1); - CachePair cp2(csrc2, cstore2, cid2); - CachePair cp3(csrc3, cstore3, cid3); - - sc1.addCachePair(cp1); - sc2.addCachePair(cp2); - sc3.addCachePair(cp3); - - /* add in a cache to sc2 */ - RsCacheData cdata; - - cdata.pid = pid1; - cdata.cid = cid1; - cdata.name = "Perm Cache"; - cdata.path = "./"; - cdata.hash = "GHJKI"; - - csrc1->refreshCache(cdata); - - cdata.pid = pid2; - cdata.cid = cid2; - cdata.name = "Funny Cache"; - cdata.path = "./"; - cdata.hash = "ABCDEF"; - - csrc2->refreshCache(cdata); - - /* now exercise it */ - - for(int i = 0; 1 ; i++) - { - RsPeerId src(""); - CacheStrapper *csp = NULL; - - if (i % 5 == 1) - { - src = pid1; - csp = &sc1; - } - else if (i % 5 == 2) - { - src = pid2; - csp = &sc2; - } - else if (i % 5 == 3) - { - src = pid3; - csp = &sc3; - } - std::cerr << std::endl; - std::cerr << "Cache Iteraton: " << time(NULL) << std::endl; - std::cerr << std::endl; - - if (src != "") - { - handleQuery(csp, src, strappers); - } - - - if (i % 21 == 0) - { - /* print out the resources */ - sc1.listCaches(std::cerr); - sc2.listCaches(std::cerr); - sc3.listCaches(std::cerr); - } - - /* every once in a while change the cache on 2 */ - if (i % 31 == 25) - { - cdata.hash += "X"; - csrc2->refreshCache(cdata); - } - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - sleep(1); -#else - Sleep(1000); -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - /* tick the systems */ - - } - - /* Cleanup - TODO */ - - return 1; -} - -void handleQuery(CacheStrapper *csp, RsPeerId pid, - std::map &strappers) -{ - /* query */ - std::list ids; - std::list::iterator pit; - - std::cerr << "Cache Query from: " << pid << std::endl; - - //csp -> sendCacheQuery(ids, time(NULL)); - for(pit = ids.begin(); pit != ids.end(); pit++) - { - std::cerr << "Cache Query for: " << (*pit) << std::endl; - std::map::iterator sit; - if (strappers.end() != (sit = strappers.find(*pit))) - { - std::map hashs; - std::map::iterator hit; - (sit -> second) -> handleCacheQuery(pid, hashs); - for(hit = hashs.begin(); hit != hashs.end(); hit++) - { - csp -> recvCacheResponse(hit->second, time(NULL)); - } - } - else - { - std::cerr << "Unknown Query Destination!" << std::endl; - } - } -} - diff --git a/libretroshare/src/tests/dbase/fimontest.cc b/libretroshare/src/tests/dbase/fimontest.cc deleted file mode 100644 index ec9e9989b..000000000 --- a/libretroshare/src/tests/dbase/fimontest.cc +++ /dev/null @@ -1,99 +0,0 @@ -/* - * RetroShare FileCache Module: fimontest.cc - * - * Copyright 2004-2007 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -//#include "pqi/p3connmgr.h" -#include "retroshare/rsiface.h" -#include "dbase/cachestrapper.h" -#include "dbase/findex.h" -#include "dbase/fimonitor.h" - -#include - -void usage(char *name) -{ - std::cerr << "Usage: " << name << " [-p ] shareDir1 [shareDir2 [shareDir3 [...]]]"; - std::cerr << std::endl; - exit(1); -} - - -/*! - * What is tested: - * 1. - * 2. - * 3. - */ -int main(int argc, char **argv) -{ - /* handle commandline arguments */ - int c; - int period = 60; /* recheck period in seconds */ - - while((c = getopt(argc, argv,"p:")) != -1) - { - switch(c) - { - case 'p': - period = atoi(optarg); - break; - default: - std::cerr << "Bad Option."; - std::cerr << std::endl; - usage(argv[0]); - break; - } - } - - std::list rootdirs; - - /* add all the rest of the commandline arguments to rootdirs list */ - for(; optind < argc; optind++) - { - SharedDirInfo dir; - dir.filename = argv[optind]; - dir.shareflags = DIR_FLAGS_PERMISSIONS_MASK ; - rootdirs.push_back(dir); - std::cerr << "Adding shared directory: " << argv[optind] << std::endl; - } - - if (rootdirs.size() < 1) - { - usage(argv[0]); - } - - //p3ConnectMgr connMgr; - NotifyBase nb; - CacheStrapper* cs = NULL; - - FileIndexMonitor mon(cs, &nb, "", "OWN ID", std::string(".")); - - /* setup monitor */ - mon.setSharedDirectories(rootdirs); - - /* simulate running the thread */ - mon.run(); - - return 1; -} - - diff --git a/libretroshare/src/tests/dbase/fisavetest.cc b/libretroshare/src/tests/dbase/fisavetest.cc deleted file mode 100644 index 94d2905d6..000000000 --- a/libretroshare/src/tests/dbase/fisavetest.cc +++ /dev/null @@ -1,123 +0,0 @@ -/* - * RetroShare FileCache Module: fisavetest.cc - * - * Copyright 2004-2007 by Kefei Zhou. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "dbase/findex.h" -#include - -FileIndex *createBasicFileIndex(rstime_t age); - -int main() -{ - FileIndex *fi1 = createBasicFileIndex(100); - FileIndex *fi2 = new FileIndex("A SILLY ID"); - - std::string out ; - fi1->printFileIndex(out); - std::cout << out < forbiddenroots; - fi1->saveIndex("test.index", fhash, size, forbiddenroots); - - std::cout << " Saved Index: Size: " << size << " Hash: " << fhash << std::endl; - std::cout << " -- new file index -- " << std::endl; - - fi2->loadIndex("test.index", fhash, size); - out.clear() ; - fi2->printFileIndex(out); - std::cout << out << std::endl; - - delete fi1; - delete fi2; - - return 1; -} - - -FileIndex *createBasicFileIndex(rstime_t age) -{ - FileIndex *fi = new FileIndex("A SILLY ID"); - - FileEntry fe; - - std::list rootdirs; - rootdirs.push_back("base1"); - rootdirs.push_back("base2"); - rootdirs.push_back("base3"); - - fi -> setRootDirectories(rootdirs, age); - - /* add some entries */ - fe.name = "dir1"; - fi -> updateDirEntry("base1",fe, age); - fe.name = "dir2"; - fi -> updateDirEntry("base1",fe, age); - - fe.name = "dir01"; - fi -> updateDirEntry("/base1/dir1/",fe, age); - - fe.name = "dir001"; - fi -> updateDirEntry("/base1/dir1/dir01/",fe, age); - - fe.name = "file1"; - fi -> updateFileEntry("/base1/dir1/",fe, age); - fe.name = "file2"; - fi -> updateFileEntry("/base1/dir1/",fe, age); - fe.name = "file3"; - fi -> updateFileEntry("/base1/dir1/",fe, age); - fe.name = "file4"; - fi -> updateFileEntry("/base1/dir1/",fe, age); - - - fe.name = "dir2"; - fi -> updateDirEntry("/base1",fe, age); - fe.name = "file5"; - fi -> updateFileEntry("/base1/dir2/",fe, age); - fe.name = "file6"; - fi -> updateFileEntry("/base1/dir2/",fe, age); - fe.name = "file7"; - fi -> updateFileEntry("/base1/dir2/",fe, age); - fe.name = "file8"; - fi -> updateFileEntry("/base1/",fe, age); - - - fe.name = "dir3"; - fi -> updateDirEntry("/base1/dir2/",fe, age); - fe.name = "file10"; - fi -> updateFileEntry("/base1/dir2/dir3",fe, age); - fe.name = "file11"; - fi -> updateFileEntry("/base1/dir2/dir3",fe, age); - fe.name = "file12"; - fi -> updateFileEntry("/base1/dir2/dir3",fe, age); - - - fe.name = "dir4"; - fi -> updateDirEntry("/base3/",fe, age); - fe.name = "file20"; - fi -> updateFileEntry("/base3/dir4/",fe, age); - fe.name = "file21"; - fi -> updateFileEntry("/base3/dir4",fe, age); - - return fi; -} - diff --git a/libretroshare/src/tests/dbase/fitest2.cc b/libretroshare/src/tests/dbase/fitest2.cc deleted file mode 100644 index b3f74775d..000000000 --- a/libretroshare/src/tests/dbase/fitest2.cc +++ /dev/null @@ -1,226 +0,0 @@ -/* - * RetroShare FileCache Module: fitest2.cc - * - * Copyright 2004-2007 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "dbase/findex.h" - -#include - -FileIndex *createBasicFileIndex(rstime_t age); - -int test1(FileIndex *fi); -int test2(FileIndex *fi); - -int main() -{ - FileIndex *fi = createBasicFileIndex(100); - - test1(fi); - - delete fi; - - return 1; -} - -int test1(FileIndex *fi) -{ - /* in this test we are going to get the old directories - and update them */ - rstime_t stamp = 200; - - DirEntry *olddir = NULL; - FileEntry fe; - while((olddir = fi -> findOldDirectory(stamp))) - { - /* update the directories and files here */ - std::map::iterator dit; - std::map::iterator fit; - - /* update this dir */ - fe.name = olddir->name; - fi -> updateDirEntry(olddir->parent->path, fe, stamp); - - /* update subdirs */ - for(dit = olddir->subdirs.begin(); dit != olddir->subdirs.end(); dit++) - { - fe.name = (dit->second)->name; - /* set the age as out-of-date so that it gets checked */ - fi -> updateDirEntry(olddir->path, fe, 0); - } - - /* update files */ - for(fit = olddir->files.begin(); fit != olddir->files.end(); fit++) - { - fe.name = (fit->second)->name; - fi -> updateFileEntry(olddir->path, fe, stamp); - } - - /* clean up the dir (should have no effect) */ - fi -> removeOldDirectory(olddir->parent->path, olddir->name, stamp); - - std::string out ; - fi -> printFileIndex(out); - std::cout << out << std::endl; - } - - std::string out ; - fi -> printFileIndex(out); - std::cout << out << std::endl; - - return 1; -} - - -int test2(FileIndex *fi) -{ - /* in this test we are going to simulate that 2 directories have disappeared */ - rstime_t stamp = 200; - - DirEntry *olddir = NULL; - FileEntry fe; - bool missingdir = false; - int i = 0; - - while((olddir = fi -> findOldDirectory(stamp))) - { - missingdir = false; - if (i % 2 == 0) - { - std::cerr << " Simulating that dir doesnt exist :" << olddir->path; - std::cerr << std::endl; - missingdir = true; - } - i++; - - if (!missingdir) - { - /* update the directories and files here */ - std::map::iterator dit; - std::map::iterator fit; - - /* update this dir */ - fe.name = olddir->name; - fi -> updateDirEntry(olddir->parent->path, fe, stamp); - - /* update subdirs */ - for(dit = olddir->subdirs.begin(); dit != olddir->subdirs.end(); dit++) - { - fe.name = (dit->second)->name; - /* set the age as out-of-date so that it gets checked */ - fi -> updateDirEntry(olddir->path, fe, 0); - } - - /* update files */ - for(fit = olddir->files.begin(); fit != olddir->files.end(); fit++) - { - fe.name = (fit->second)->name; - fi -> updateFileEntry(olddir->path, fe, stamp); - } - } - /* clean up the dir */ - fi -> removeOldDirectory(olddir->parent->path, olddir->name, stamp); - - std::string out ; - fi -> printFileIndex(out); - std::cout << out << std::endl; - } - - std::string out ; - fi -> printFileIndex(out); - std::cout << out << std::endl; - - return 1; -} - - - - - -FileIndex *createBasicFileIndex(rstime_t age) -{ - FileIndex *fi = new FileIndex("A SILLY ID"); - - FileEntry fe; - - /* print empty FileIndex */ - std::string out ; - fi -> printFileIndex(out); - std::cout << out << std::endl; - - std::list rootdirs; - rootdirs.push_back("base1"); - rootdirs.push_back("base2"); - rootdirs.push_back("base3"); - - fi -> setRootDirectories(rootdirs, age); - - /* add some entries */ - fe.name = "dir1"; - fi -> updateDirEntry("base1",fe, age); - fe.name = "file1"; - fi -> updateFileEntry("/base1/dir1/",fe, age); - fe.name = "file2"; - fi -> updateFileEntry("/base1/dir1/",fe, age); - fe.name = "file3"; - fi -> updateFileEntry("/base1/dir1/",fe, age); - fe.name = "file4"; - fi -> updateFileEntry("/base1/dir1/",fe, age); - - fe.name = "dir2"; - fi -> updateDirEntry("/base1",fe, age); - fe.name = "file5"; - fi -> updateFileEntry("/base1/dir2/",fe, age); - fe.name = "file6"; - fi -> updateFileEntry("/base1/dir2/",fe, age); - fe.name = "file7"; - fi -> updateFileEntry("/base1/dir2/",fe, age); - fe.name = "file8"; - fi -> updateFileEntry("/base1/",fe, age); - - - fe.name = "dir3"; - fi -> updateDirEntry("/base1/dir2/",fe, age); - fe.name = "file10"; - fi -> updateFileEntry("/base1/dir2/dir3",fe, age); - fe.name = "file11"; - fi -> updateFileEntry("/base1/dir2/dir3",fe, age); - fe.name = "file12"; - fi -> updateFileEntry("/base1/dir2/dir3",fe, age); - - - fe.name = "dir4"; - fi -> updateDirEntry("/base3/",fe, age); - fe.name = "file20"; - fi -> updateFileEntry("/base3/dir4/",fe, age); - fe.name = "file21"; - fi -> updateFileEntry("/base3/dir4",fe, age); - - // one that will fail. - fe.name = "file20"; - fi -> updateFileEntry("/base3/",fe, age); - - out.clear() ; - fi -> printFileIndex(out); - std::cout << out << std::endl; - - return fi; -} - diff --git a/libretroshare/src/tests/dbase/searchtest.cc b/libretroshare/src/tests/dbase/searchtest.cc deleted file mode 100644 index d09e1b565..000000000 --- a/libretroshare/src/tests/dbase/searchtest.cc +++ /dev/null @@ -1,78 +0,0 @@ -/* - * RetroShare FileCache Module: searchtest.cc - * - * Copyright 2004-2007 by Kefei Zhou. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "dbase/findex.h" -#include -#include - -int main() -{ - - std::cout << std::string::npos << std::endl; - std::string testfile = "searchtest.index"; - std::string fhash = "6851c28d99a6616a86942c3914476bf11997242a"; - FileIndex *fi = new FileIndex("DUMB ID"); - - // loading fileindex - std::cout << std::endl << "Test load" << std::endl; - fi->loadIndex(testfile, fhash, 1532); - fi->printFileIndex(std::cout); - std::cout << "FileIndex Loaded" << std::endl << std::endl; - - std::list hashresult; - std::list termresult; - - // searchhash - std::string findhash = "82bffa6e1cdf8419397311789391238174817481"; - - - std::cout << "Search hash : " << findhash << std::endl; - fi->searchHash(findhash, hashresult); - - while(!hashresult.empty()) - { - std::string out ; - hashresult.back()->print(out); - std::cout << out << std::endl; - hashresult.pop_back(); - } - - // searchterm - std::list terms; - terms.push_back("paper"); - terms.push_back("doc"); - - std::cout << "Search terms" << std::endl; - fi->searchTerms(terms, termresult); - - while(!termresult.empty()) - { - std::string out ; - termresult.back()->print(out); - std::cout << out << std::endl; - termresult.pop_back(); - } - - delete fi; - return 1; -} diff --git a/libretroshare/src/tests/ft/TestNotes.txt b/libretroshare/src/tests/ft/TestNotes.txt deleted file mode 100644 index 013fe879e..000000000 --- a/libretroshare/src/tests/ft/TestNotes.txt +++ /dev/null @@ -1,54 +0,0 @@ - -Features that need to be tested, and which test checks it. ------------------------------------------------------------ - -(*) Transfer Related - -(*) Search Related - -(*) ExtraList Related - -(*) Cache Related - -(*) Config / Storage. - Change Config Directory works dynamically. (no restart required). - - -(*) Miscelleous - - - ------------------------------------------------------------ ------------------------------------------------------------ -Actual Tests, and what they check. ------------------------------------------------------------ - -ftserver1test.cc -================== - -Used to develop test framework. -Tests. - 1) Test Framework. OK - 2) File Indexing. OK - 3) Cache Packet Exchange. OK - 4) Cache downloads (including loopback). FAILS - 5) FileIndex Store loading. - 6) Basic Search. - -ftserver2test.cc -================== - -Test out the ExtraList functions. -Demonstrates the use of libretroshare/src/util/utest.h - -Tests. - 1) Load ExtraList path OK - 2) Hashing of ExtraList File OK - 3) ExtraHashDone. OK - 4) Local Search for ExtraList Data. OK - 5) Remote Search of ExtraList (should Fail) OK - 6) Transfer of ExtraList File (Local) TODO - 7) Transfer of ExtraList File (Remote) TODO - - - diff --git a/libretroshare/src/tests/ft/ftcontrollertest.cc b/libretroshare/src/tests/ft/ftcontrollertest.cc deleted file mode 100644 index 00fb95fa2..000000000 --- a/libretroshare/src/tests/ft/ftcontrollertest.cc +++ /dev/null @@ -1,451 +0,0 @@ -/* - * libretroshare/src/ft: ftserver1test.cc - * - * File Transfer for RetroShare. - * - * Copyright 2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/* - * ftServer2Test - Demonstrates how to check for test stuff. - */ - -#include "retroshare/rsfiles.h" -#include "retroshare/rspeers.h" -#include "retroshare/rsiface.h" -#include "rsserver/p3peers.h" -#include "ft/ftserver.h" - -#include "ft/ftextralist.h" -#include "ft/ftdatamultiplex.h" -#include "ft/ftfilesearch.h" - -//#include "pqi/p3authmgr.h" -//#include "pqi/p3connmgr.h" -#include "pqi/p3peermgr.h" -#include "pqi/p3linkmgr.h" -#include "pqi/p3netmgr.h" - -#include "pqi/authssl.h" -#include "pqi/authgpg.h" - -#include "common/testutils.h" -#include "util/rsdebug.h" - -#include "pqitestor.h" -#include "util/rsdir.h" -#include "util/utest.h" - - -#include - -class TestData -{ - public: - - ftServer *loadServer; - std::list otherServers; - std::list extraList; -}; - - -extern "C" void *do_server_test_thread(void *p); - - -void usage(char *name) -{ - std::cerr << "Usage: " << name << " [-sa] [-p ] [-d ] [-e ] [ [ ... ]] "; - std::cerr << std::endl; -} - -int main(int argc, char **argv) -{ - int c; - uint32_t debugLevel = 5; - bool loadAll = false; - - std::list fileList; - std::list extraList; - std::list peerIds; - std::map mFtServers; - std::map mLinkMgrs; - - ftServer *mLoadServer = NULL; - std::list mOtherServers; - std::list::iterator eit; - - while(-1 != (c = getopt(argc, argv, "asd:p:e:"))) - { - switch (c) - { - case 'p': - peerIds.push_back(optarg); - break; - case 'd': - debugLevel = atoi(optarg); - break; -// case 's': -// debugStderr = true; -// break; - case 'e': - extraList.push_back(optarg); - break; - case 'a': - loadAll = true; - break; - default: - usage(argv[0]); - break; - } - } - - if(peerIds.empty()) - { - peerIds.push_back(TestUtils::createRandomSSLId()) ; - - // then add some other peer ids. - peerIds.push_back(TestUtils::createRandomSSLId()) ; - peerIds.push_back(TestUtils::createRandomSSLId()) ; - peerIds.push_back(TestUtils::createRandomSSLId()) ; - } - - std::string ssl_own_id = TestUtils::createRandomSSLId() ; - std::string gpg_own_id = TestUtils::createRandomPGPId() ; - - TestUtils::DummyAuthGPG fakeGPG(gpg_own_id) ; - AuthGPG::setAuthGPG_debug(&fakeGPG) ; - - TestUtils::DummyAuthSSL fakeSSL(ssl_own_id) ; - AuthSSL::setAuthSSL_debug(&fakeSSL) ; - - /* do logging */ - setOutputLevel(debugLevel); - - if (optind >= argc) - { - std::cerr << "Missing Shared Directories" << std::endl; - usage(argv[0]); - } - - for(; optind < argc; optind++) - { - std::cerr << "Adding: " << argv[optind] << std::endl; - - SharedDirInfo info ; - info.shareflags = DIR_FLAGS_PERMISSIONS_MASK; - info.filename = std::string(argv[optind]); - info.virtualname = info.filename ; - - fileList.push_back(info) ; - } - - /* We need to setup a series 2 - 4 different ftServers.... - * - * Each one needs: - * - * - * A List of peerIds... - */ - - std::list::const_iterator it, jit; - - std::list baseFriendList, friendList; - std::list::iterator fit; - - P3Hub *testHub = new P3Hub(0,NULL); - testHub->start(); - - /* Setup Base Friend Info */ - for(it = peerIds.begin(); it != peerIds.end(); it++) - { - RsPeerDetails pad; - pad.id = *it; - pad.gpg_id = TestUtils::createRandomPGPId() ; - pad.name = *it; - pad.trustLvl = 5; - pad.ownsign = true; - //pad.trusted = false; - - baseFriendList.push_back(pad); - - std::cerr << "ftserver1test::setup peer: " << *it << std::endl; - } - - std::ostringstream pname; - pname << "/tmp/rstst-" << time(NULL); - - std::string basepath = pname.str(); - RsDirUtil::checkCreateDirectory(basepath); - - - - for(it = peerIds.begin(); it != peerIds.end(); it++) - { - friendList = baseFriendList; - /* remove current one */ - for(fit = friendList.begin(); fit != friendList.end(); fit++) - { - if (fit->id == *it) - { - friendList.erase(fit); - break; - } - } - - //p3AuthMgr *authMgr = new p3DummyAuthMgr(*it, friendList); - p3PeerMgrIMPL *peerMgr = new p3PeerMgrIMPL(ssl_own_id,gpg_own_id,"My GPG name","My SSL location"); - - p3NetMgrIMPL *netMgr = new p3NetMgrIMPL ; - p3LinkMgrIMPL *linkMgr = new p3LinkMgrIMPL(peerMgr,netMgr); - mLinkMgrs[*it] = linkMgr; - - rsPeers = new TestUtils::DummyRsPeers(linkMgr,peerMgr,netMgr) ; - - for(fit = friendList.begin(); fit != friendList.end(); fit++) - { - /* add as peer to authMgr */ - peerMgr->addFriend(fit->id,fit->gpg_id); - } - - P3Pipe *pipe = new P3Pipe(); //(*it); - - /* add server */ - ftServer *server; - server = new ftServer(peerMgr,linkMgr); - mFtServers[*it] = server; - if (!mLoadServer) - { - mLoadServer = server; - } - else - { - mOtherServers.push_back(server); - } - - - server->setP3Interface(pipe); - - std::string configpath = basepath + "/" + *it; - RsDirUtil::checkCreateDirectory(configpath); - - std::string cachepath = configpath + "/cache"; - RsDirUtil::checkCreateDirectory(cachepath); - - std::string localpath = cachepath + "/local"; - RsDirUtil::checkCreateDirectory(localpath); - - std::string remotepath = cachepath + "/remote"; - RsDirUtil::checkCreateDirectory(remotepath); - - server->setConfigDirectory(configpath); - - NotifyBase *base = new NotifyBase; - server->SetupFtServer(base); - - testHub->addP3Pipe(*it, pipe, linkMgr); - server->StartupThreads(); - - /* setup any extra bits */ - if (loadAll) - { - server->setSharedDirectories(fileList); - for(eit = extraList.begin(); eit != extraList.end(); eit++) - { - server->ExtraFileHash(*eit, 3600, TransferRequestFlags(0)); - } - } - - } - - if (mLoadServer) - { - mLoadServer->setSharedDirectories(fileList); - for(eit = extraList.begin(); eit != extraList.end(); eit++) - { - mLoadServer->ExtraFileHash(*eit, 3600, TransferRequestFlags(0)); - } - } - - - /* stick your real test here */ - std::map::iterator sit; - std::map::iterator cit; - - /* Start up test thread */ - pthread_t tid; - TestData *mFt = new TestData; - - /* set data */ - mFt->loadServer = mLoadServer; - mFt->otherServers = mOtherServers; - mFt->extraList = extraList; - - void *data = (void *) mFt; - pthread_create(&tid, 0, &do_server_test_thread, data); - pthread_detach(tid); /* so memory is reclaimed in linux */ - - while(1) - { - std::cerr << "ftserver2test::sleep()"; - std::cerr << std::endl; - sleep(1); - - /* tick the connmgrs */ - for(sit = mFtServers.begin(); sit != mFtServers.end(); sit++) - { - /* update */ - (sit->second)->tick(); - } - - for(cit = mLinkMgrs.begin(); cit != mLinkMgrs.end(); cit++) - { - /* update */ - (cit->second)->tick(); - } - } -} - -/* So our actual test can run here..... - * - */ - -INITTEST(); - -void *do_server_test_thread(void *data) -{ - TestData *mFt = (TestData *) data; - - std::cerr << "do_server_test_thread() running"; - std::cerr << std::endl; - - /************************* TEST 1 ********************** - * Check that the extra List has been processed. - */ - rstime_t start = time(NULL); - - FileInfo info, info2; - rstime_t now = time(NULL); - std::list::iterator eit; - for(eit = mFt->extraList.begin(); eit != mFt->extraList.end(); eit++) - { - std::cerr << "Treating extra file " << *eit << std::endl; - - while(!mFt->loadServer->ExtraFileStatus(*eit, info)) - { - - /* max of 30 seconds */ - now = time(NULL); - if (now - start > 30) - { - /* FAIL */ - REPORT2( false, "Extra File Hashing"); - } - - sleep(1); - } - - /* Got ExtraFileStatus */ - REPORT("Successfully Found ExtraFile"); - - /* now we can try a search (should succeed) */ - FileSearchFlags hintflags = RS_FILE_HINTS_EXTRA; - - if (mFt->loadServer->FileDetails(info.hash, hintflags, info2)) - { - CHECK(info2.hash == info.hash); - CHECK(info2.size == info.size); - CHECK(info2.fname == info.fname); - } - else - { - REPORT2( false, "Search for Extra File (Basic)"); - } - - /* search with flags (should succeed) */ - hintflags = RS_FILE_HINTS_EXTRA; - if (mFt->loadServer->FileDetails(info.hash, hintflags, info2)) - { - CHECK(info2.hash == info.hash); - CHECK(info2.size == info.size); - CHECK(info2.fname == info.fname); - } - else - { - REPORT2( false, "Search for Extra File (Extra Flag)"); - } - - /* search with other flags (should fail) */ - hintflags = RS_FILE_HINTS_REMOTE | RS_FILE_HINTS_SPEC_ONLY; - - if (mFt->loadServer->FileDetails(info.hash, hintflags, info2)) - { - REPORT2( false, "Search for Extra File (Fail Flags)"); - } - else - { - REPORT("Search for Extra File (Fail Flags)"); - } - - /* if we try to download it ... should just find existing one*/ - - REPORT("Testing with Extra File"); - } - - FINALREPORT("ExtraList Hashing, Searching and Downloading"); - - /************************* TEST 2 ********************** - * test ftController and ftTransferModule - */ - ftServer *server=mFt->loadServer; - - std::string fname,filehash,destination; - FileSearchFlags flags; - std::list srcIds; - - /* select a file from otherServers */ - if (mFt->otherServers.empty() ) - { - REPORT2(false,"No otherServers available"); - exit(1); - } - - DirDetails details; - flags = RS_FILE_HINTS_REMOTE; - void *ref = NULL; - - if(!server->RequestDirDetails(ref,details,flags)) - { - REPORT2(false,"fail to call RequestDirDetails"); - } - - if (details.type == DIR_TYPE_FILE) - { - REPORT("RemoteDirModel::downloadSelected() Calling File Request"); - std::list srcIds; - srcIds.push_back(details.id); - server->FileRequest(details.name, details.hash, details.count, "", TransferRequestFlags(0), srcIds); - } - - exit(1); -} - - - - diff --git a/libretroshare/src/tests/ft/ftcontrollertest.sh b/libretroshare/src/tests/ft/ftcontrollertest.sh deleted file mode 100755 index e4a9d2fa5..000000000 --- a/libretroshare/src/tests/ft/ftcontrollertest.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -./ftcontrollertest -p 8cb3a1677872c9e8248fd5ddeac84000 -p 8cb3a1677872c9e8248fd5ddeac84001 -p 8cb3a1677872c9e8248fd5ddeac84002 -e ftcontrollertest . diff --git a/libretroshare/src/tests/ft/ftcrc32test.cc b/libretroshare/src/tests/ft/ftcrc32test.cc deleted file mode 100644 index f20144df9..000000000 --- a/libretroshare/src/tests/ft/ftcrc32test.cc +++ /dev/null @@ -1,127 +0,0 @@ -/* - * libretroshare/src/ft: ftcrc32test.cc - * - * File Transfer for RetroShare. - * - * Copyright 2008 by Cyril Soler - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include -#include -#include "retroshare/rstypes.h" -#include -#include - -#ifdef WIN32 -#include "util/rswin.h" -#endif - -#include "util/rsdir.h" -#include "util/utest.h" -#include -#include - -INITTEST() ; - -int main(int argc, char **argv) -{ - int c; - uint32_t period = 1; - uint32_t dPeriod = 600; /* default 10 minutes */ - - std::string inputfile ; - - argstream as(argc,argv) ; - - as >> parameter('i',"input",inputfile,"Input file to hash. If none, a random file will be created in /tmp",false) - >> help() ; - - as.defaultErrorHandling() ; - - if(inputfile == "") - { - uint64_t S = 3983782 ; - std::cerr << "Creating a dummy input file in /tmp, of size " << S << std::endl; - inputfile = "crc_test_data.bin" ; - - if(!TestUtils::createRandomFile(inputfile,S)) - return 1 ; - } - - std::list hashList ; - hashList.push_back(inputfile) ; - - uint32_t flags = 0; - for(std::list::const_iterator it(hashList.begin()); it != hashList.end(); it++) - { - std::cerr << "Hashing file :" << *it << std::endl ; - - std::string hash ; - uint64_t size ; - std::string name ; - RsDirUtil::hashFile( *it,name,hash,size) ; - - std::cerr << "Hash = " << hash << std::endl; - - FILE *f = fopen( (*it).c_str(),"rb" ) ; - - if(f == NULL) - { - std::cerr << "Could not open this file! Sorry." << std::endl ; - return 1 ; - } - CRC32Map crc_map ; - - if(fseek(f,0,SEEK_END)) - { - std::cerr << "Could not fseek to end of this file! Sorry." << std::endl ; - fclose(f) ; - return 1 ; - } - - size = ftell(f) ; - - if(fseek(f,0,SEEK_SET)) - { - std::cerr << "Could not fseek to beginning of this file! Sorry." << std::endl ; - fclose(f) ; - return 1 ; - } - - std::cerr << "File size:" << size << std::endl ; - - RsDirUtil::crc32File(f,size,ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE,crc_map) ; - fclose(f) ; - - std::cerr << "Got this CRC map: "<< std::endl ; - - for(uint32_t i=0;i -#include "ft/ftfilecreator.h" - -#include "util/utest.h" -#include "util/rsdir.h" -#include "util/rsdiscspace.h" -#include - -#include "util/rswin.h" -#include "ft/ftserver.h" - -INITTEST(); - -static void createTmpFile(const std::string& name,uint64_t size,std::string& hash) ; -static void transfer(ftFileProvider *server, const std::string& server_peer_id,ftFileCreator *client,const std::string& client_peer_id) ; - -static const float TRANSFER_FAIL_PROBABILITY = 0.0f ; - -void validateChunksToCheck(const Sha1Map& chunk_crc_map,ftFileCreator *client,const std::string& client_name) -{ - std::vector chunks ; - client->getChunksToCheck(chunks) ; - - if(chunks.size() > 0) - for(uint32_t i=0;iverifyChunk(chunks[i],chunk_crc_map[chunks[i]]) ; - } -} - -void initChunkCrcMap(const std::string& fname,Sha1Map& map) -{ - FILE *fd = fopen(fname.c_str(),"rb") ; - unsigned char *buf = new unsigned char[ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE] ; - - if(fd == NULL) - { - std::cerr << "Cannot read file " << fname << ". Something's wrong!" << std::endl; - delete[] buf ; - exit(1) ; - } - - for(int i=0;isetChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_RANDOM) ; - client2->setChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE) ; - - // 3 - Exchange chunks, and build two copies of the file. - // - std::string peer_id_1("client peer id 1") ; - std::string peer_id_2("client peer id 2") ; - std::string server_id("server peer id") ; - - // 4 - prepare a chunk crc map to verify chunks. - - Sha1Map chunk_crc_map(size,ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE) ; - - initChunkCrcMap(fname,chunk_crc_map) ; - - std::cerr << "Computed chunk CRC map: " << std::endl; - - for(int i=0;ifinished() && client2->finished())) - { - // 1 - select a random client, get the data from him. - - ftFileProvider *tmpserver ; - ftFileCreator *tmpclient ; - std::string tmpserver_pid ; - std::string tmpclient_pid ; - - // choose client and server, randomly, provided that they are not finished. - // - if((!client1->finished()) && (client2->finished() || (lrand48()&1))) - { - //std::cerr << "###### Client 1 asking to " ; - tmpclient = client1 ; - tmpclient_pid = peer_id_1 ; - - if(lrand48()&1) - { - //std::cerr << "Client 2 " ; - tmpserver = client2 ; - tmpserver_pid = peer_id_2 ; - } - else - { - //std::cerr << "Server "; - tmpserver = server ; - tmpserver_pid = server_id ; - } - } - else // client 2 is necessarily unfinished there. - { - //std::cerr << "###### Client 2 asking to " ; - tmpclient = client2 ; - tmpclient_pid = peer_id_2 ; - - if(lrand48()&1) - { - //std::cerr << "Client 1 " ; - tmpserver = client1 ; - tmpserver_pid = peer_id_1 ; - } - else - { - //std::cerr << "Server " ; - tmpserver = server ; - tmpserver_pid = server_id ; - } - - } - - // 2 - transfer from the server to the client. - - transfer(tmpserver,tmpserver_pid,tmpclient,tmpclient_pid) ; - - printf("Client1: %08lld, Client2: %08lld, transfer from %s to %s\r",client1->getRecvd(),client2->getRecvd(),tmpserver_pid.c_str(),tmpclient_pid.c_str()) ; - fflush(stdout) ; - - // Also get chunk checking list from each server, and validate them. - - validateChunksToCheck(chunk_crc_map,client1,"client 1") ; - validateChunksToCheck(chunk_crc_map,client2,"client 2") ; - } - - // hash the received data - - std::string hash1 ; client1->hashReceivedData(hash1) ; - std::string hash2 ; client2->hashReceivedData(hash2) ; - - std::cout << "Hash = " << hash << std::endl ; - std::cout << "Hash1 = " << hash1 << std::endl ; - std::cout << "Hash2 = " << hash2 << std::endl ; - - if(hash != hash1) FAILED("hashs 0/1 defer after transfer !") ; - if(hash != hash2) FAILED("hashs 0/2 defer after transfer !") ; - if(hash1 != hash2) FAILED("hashs 1/2 defer after transfer !") ; - - FINALREPORT("File transfer test"); - - return TESTRESULT(); -} - -void transfer(ftFileProvider *server, const std::string& server_peer_id,ftFileCreator *client,const std::string& client_peer_id) -{ - uint32_t size_hint = 128 + (lrand48()%1000) ; - uint64_t offset = 0; - uint32_t chunk_size = 0; - bool toOld = false ; - - //std::cerr << " for a pending chunk of size " << size_hint ; - - if(! client->getMissingChunk(server_peer_id, size_hint, offset, chunk_size, toOld)) - { - std::cerr << "###### Server does not have any chunk to offer: server is " << server_peer_id << ", client is " << client_peer_id << std::endl ; - // Normally this can't be true, because the ChunkMap class assumes availability for non turtle - // peers. - if(toOld) - { - std::cerr << "###### Map is too old. Transferring chunk map" << std::endl ; - CompressedChunkMap map ; - server->getAvailabilityMap(map) ; - client->setSourceMap(server_peer_id,map) ; - } - return ; - } - - std::cerr << "###### Got chunk " << offset << ", size=" << chunk_size << std::endl ; - - void *data = malloc(chunk_size) ; - std::cerr << "###### Asking data " << offset << ", size=" << chunk_size << std::endl ; - - if( server->getFileData(client_peer_id,offset,chunk_size,data) ) - { - if(drand48() < TRANSFER_FAIL_PROBABILITY) - { - std::cerr << "simulating faulting data chunk " << offset << " + " << chunk_size << "." << std::endl; - } - else - { - client->addFileData(offset,chunk_size,data) ; - std::cerr << "###### Added data " << offset << ", size=" << chunk_size << std::endl ; - } - } - - std::cerr << ", completion=" << client->getRecvd() << std::endl ; - - - free(data) ; -} - -void createTmpFile(const std::string& name,uint64_t S,std::string& hash) -{ - FILE *tmpf = fopen("source_tmp.bin","w") ; - - // write 1MB chunks - uint64_t C = 1024*1024 ; - uint8_t *data = new uint8_t[C] ; - - for(uint i=0;i<=S/C;++i) - { - int Cp = C ; - if(i==S/C) - { - if(S%C>0) - Cp = S%C ; - else - break ; - } - - for(int k=0;krecvDataRequest(peerId,hash,size,offset,chunksize); -} - - /* Server Send */ -bool ftDataSendPair::sendData(const std::string &peerId, const std::string &hash, - uint64_t size, uint64_t offset, uint32_t chunksize, void *data) -{ - return mDataRecv->recvData(peerId, hash,size,offset,chunksize,data); -} - - /* Send a request for a chunk map */ -bool ftDataSendPair::sendChunkMapRequest(const std::string& peer_id,const std::string& hash,bool is_client) -{ - return mDataRecv->recvChunkMapRequest(peer_id,hash,is_client); -} - - /* Send a chunk map */ -bool ftDataSendPair::sendChunkMap(const std::string& peer_id,const std::string& hash, const CompressedChunkMap& cmap,bool is_client) -{ - return mDataRecv->recvChunkMap(peer_id,hash,cmap, is_client); -} - /* Send a request for a chunk map */ -bool ftDataSendPair::sendCRC32MapRequest(const std::string& peer_id,const std::string& hash) -{ - return mDataRecv->recvCRC32MapRequest(peer_id,hash); -} - - /* Send a chunk map */ -bool ftDataSendPair::sendCRC32Map(const std::string& peer_id,const std::string& hash, const CRC32Map& crcmap) -{ - return mDataRecv->recvCRC32Map(peer_id,hash,crcmap) ; -} - -bool ftDataSendPair::sendSingleChunkCRCRequest(const std::string& peer_id, const std::string& hash, unsigned int c_id) -{ - return mDataRecv->recvSingleChunkCRCRequest(peer_id,hash,c_id) ; -} -bool ftDataSendPair::sendSingleChunkCRC(const std::string& peer_id, const std::string& hash, uint32_t c_id, const Sha1CheckSum& crc) -{ - return mDataRecv->recvSingleChunkCRC(peer_id,hash,c_id,crc) ; -} - /* Client Send */ -bool ftDataSendDummy::sendDataRequest(const std::string &/*peerId*/, const std::string &/*hash*/, - uint64_t /*size*/, uint64_t /*offset*/, uint32_t /*chunksize*/) -{ - return true; -} - - /* Server Send */ -bool ftDataSendDummy::sendData(const std::string &/*peerId*/, const std::string &/*hash*/, - uint64_t /*size*/, uint64_t /*offset*/, uint32_t /*chunksize*/, void */*data*/) -{ - return true; -} - - - /* Send a request for a chunk map */ -bool ftDataSendDummy::sendChunkMapRequest(const std::string& /*peer_id*/,const std::string& /*hash*/,bool /*is_client*/) -{ - return true; -} - - /* Send a chunk map */ -bool ftDataSendDummy::sendChunkMap(const std::string& /*peer_id*/,const std::string& /*hash*/, const CompressedChunkMap& /*cmap*/,bool /*is_client*/) -{ - return true; -} -bool ftDataSendDummy::sendCRC32MapRequest(const std::string& /*peer_id*/,const std::string& /*hash*/) -{ - return true; -} - - /* Send a chunk map */ -bool ftDataSendDummy::sendCRC32Map(const std::string& /*peer_id*/,const std::string& /*hash*/, const CRC32Map& /*cmap*/) -{ - return true; -} - - /* Client Recv */ -bool ftDataRecvDummy::recvData(const std::string &/*peerId*/, const std::string &/*hash*/, - uint64_t /*size*/, uint64_t /*offset*/, uint32_t /*chunksize*/, void */*data*/) -{ - return true; -} - - - /* Server Recv */ -bool ftDataRecvDummy::recvDataRequest(const std::string &/*peerId*/, const std::string &/*hash*/, - uint64_t /*size*/, uint64_t /*offset*/, uint32_t /*chunksize*/) -{ - return true; -} - - /* Send a request for a chunk map */ -bool ftDataRecvDummy::recvChunkMapRequest(const std::string& /*peer_id*/,const std::string& /*hash*/, - bool /*is_client*/) -{ - return true; -} - - /* Send a chunk map */ -bool ftDataRecvDummy::recvChunkMap(const std::string& /*peer_id*/,const std::string& /*hash*/, - const CompressedChunkMap& /*cmap*/,bool /*is_client*/) -{ - return true; -} -bool ftDataRecvDummy::recvSingleChunkCrcRequest(const std::string& peer_id,const std::string& hash,uint32_t chunk_id) -{ - return true ; -} -bool ftDataRecvDummy::recvSingleChunkCrc(const std::string& peer_id,const std::string& hash,uint32_t chunk_id,const Sha1CheckSum& sum) -{ - return true ; -} - -bool ftDataRecvDummy::recvCRC32MapRequest(const std::string& /*peer_id*/,const std::string& /*hash*/) -{ - return true ; -} - - /* Send a chunk map */ -bool ftDataRecvDummy::recvCRC32Map(const std::string& /*peer_id*/,const std::string& /*hash*/, const CompressedChunkMap& /*cmap*/) -{ - return true ; -} - -bool ftDataSendDummy::sendSingleChunkCRCRequest(const std::string&, const std::string&, unsigned int) -{ - return true ; -} -bool ftDataSendDummy::sendSingleChunkCRC(const std::string&, const std::string&, uint32_t, const Sha1CheckSum&) -{ - return true ; -} diff --git a/libretroshare/src/tests/ft/ftdata_dummy.h b/libretroshare/src/tests/ft/ftdata_dummy.h deleted file mode 100644 index 6a30b5606..000000000 --- a/libretroshare/src/tests/ft/ftdata_dummy.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * libretroshare/src/ft: ftdata.h - * - * File Transfer for RetroShare. - * - * Copyright 2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#ifndef FT_DATA_TEST_INTERFACE_HEADER -#define FT_DATA_TEST_INTERFACE_HEADER - -/* - * ftData. - * - * Internal Interfaces for sending and receiving data. - * Most likely to be implemented by ftServer. - * Provided as an independent interface for testing purposes. - * - */ - -#include -#include - -#include -#include - - /*************** SEND INTERFACE *******************/ - -class CompressedChunkMap ; -class Sha1CheckSum ; - - /**************** FOR TESTING ***********************/ - -/******* Pair of Send/Recv (Only need to handle Send side) ******/ -class ftDataSendPair: public ftDataSend -{ - public: - - ftDataSendPair(ftDataRecv *recv); -virtual ~ftDataSendPair() { return; } - - /* Client Send */ -virtual bool sendDataRequest(const std::string &peerId, const std::string &hash, - uint64_t size, uint64_t offset, uint32_t chunksize); - - /* Server Send */ -virtual bool sendData(const std::string &peerId, const std::string &hash, uint64_t size, - uint64_t offset, uint32_t chunksize, void *data); - - /* Send a request for a chunk map */ -virtual bool sendChunkMapRequest(const std::string& peer_id,const std::string& hash,bool is_client); - - /* Send a chunk map */ -virtual bool sendChunkMap(const std::string& peer_id,const std::string& hash, const CompressedChunkMap& cmap,bool is_client); - - /* Send a request for a chunk map */ -virtual bool sendCRC32MapRequest(const std::string& peer_id,const std::string& hash); - - /* Send a chunk map */ -virtual bool sendCRC32Map(const std::string& peer_id,const std::string& hash, const CRC32Map& cmap); - ftDataRecv *mDataRecv; - - virtual bool sendSingleChunkCRCRequest(const std::string&, const std::string&, uint32_t); - virtual bool sendSingleChunkCRC(const std::string&, const std::string&, uint32_t, const Sha1CheckSum&); -}; - - -class ftDataSendDummy: public ftDataSend -{ - public: - virtual ~ftDataSendDummy() { return; } - - /* Client Send */ - virtual bool sendDataRequest(const std::string &peerId, const std::string &hash, - uint64_t size, uint64_t offset, uint32_t chunksize); - - /* Server Send */ - virtual bool sendData(const std::string &peerId, const std::string &hash, uint64_t size, - uint64_t offset, uint32_t chunksize, void *data); - - /* Send a request for a chunk map */ - virtual bool sendChunkMapRequest(const std::string& peer_id,const std::string& hash,bool is_client); - - /* Send a chunk map */ - virtual bool sendChunkMap(const std::string& peer_id,const std::string& hash, const CompressedChunkMap& cmap,bool is_client); - - /* Send a request for a chunk map */ - virtual bool sendCRC32MapRequest(const std::string& peer_id,const std::string& hash); - - /* Send a chunk map */ - virtual bool sendCRC32Map(const std::string& peer_id,const std::string& hash, const CRC32Map& cmap); - - virtual bool sendSingleChunkCRCRequest(const std::string&, const std::string&, uint32_t); - virtual bool sendSingleChunkCRC(const std::string&, const std::string&, uint32_t, const Sha1CheckSum&); - -}; - -class ftDataRecvDummy: public ftDataRecv -{ - public: - -virtual ~ftDataRecvDummy() { return; } - - /* Client Recv */ -virtual bool recvData(const std::string& peerId, const std::string& hash, - uint64_t size, uint64_t offset, uint32_t chunksize, void *data); - - /* Server Recv */ -virtual bool recvDataRequest(const std::string& peerId, const std::string& hash, - uint64_t size, uint64_t offset, uint32_t chunksize); - - /* Send a request for a chunk map */ -virtual bool recvChunkMapRequest(const std::string& peer_id,const std::string& hash, - bool is_client); - - /* Send a chunk map */ -virtual bool recvChunkMap(const std::string& peer_id,const std::string& hash, - const CompressedChunkMap& cmap,bool is_client); - - /* Send a request for a chunk map */ -virtual bool recvCRC32MapRequest(const std::string& peer_id,const std::string& hash); - - /* Send a chunk map */ -virtual bool recvCRC32Map(const std::string& peer_id,const std::string& hash, const CompressedChunkMap& cmap); - -virtual bool recvSingleChunkCrcRequest(const std::string& peer_id,const std::string& hash,uint32_t chunk_id) ; -virtual bool recvSingleChunkCrc(const std::string& peer_id,const std::string& hash,uint32_t chunk_id,const Sha1CheckSum& sum); -}; - -#endif diff --git a/libretroshare/src/tests/ft/ftdataplextest.cc b/libretroshare/src/tests/ft/ftdataplextest.cc deleted file mode 100644 index 7872aa72d..000000000 --- a/libretroshare/src/tests/ft/ftdataplextest.cc +++ /dev/null @@ -1,200 +0,0 @@ -/* - * libretroshare/src/ft: ftextralisttest.cc - * - * File Transfer for RetroShare. - * - * Copyright 2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/* - * Test for Multiplexor..... - * As this is a key middle component, it is hard to test without other bits. - * It relies on ftFileProvider/ftFileCreator/ftTransferModule... - * - * And has dummy ftDataSend and ftSearch. - * - */ - -#ifdef WIN32 -#include "util/rswin.h" -#endif - -#include -#include -#include -#include "ft/ftextralist.h" -#include "ft/ftdatamultiplex.h" -#include "ft/ftfilesearch.h" - -#include "ftdata_dummy.h" -#include "ftsearch_dummy.h" - -void do_random_server_test(ftDataMultiplex *mplex, ftExtraList *eList, std::list &files); - -INITTEST() ; - -void usage(char *name) -{ - std::cerr << "Usage: " << name << " [-p ] [-d ] [ ... ] "; - std::cerr << std::endl; -} - -int main(int argc, char **argv) -{ - int c; - uint32_t period = 1; - uint32_t dPeriod = 600; /* default 10 minutes */ - - std::list fileList; - - while(-1 != (c = getopt(argc, argv, "d:p:"))) - { - switch (c) - { - case 'p': - period = atoi(optarg); - break; - case 'd': - dPeriod = atoi(optarg); - break; - default: - usage(argv[0]); - break; - } - } - - if (optind >= argc) - { - uint32_t N = 4 ; - std::cerr << "Missing Files. Generating " << N << " random files." << std::endl; - - for(uint32_t i=0;istart(); - - ftSearch *ftsd = new ftSearchDummy(); - ftFileSearch *ftfs = new ftFileSearch(); - - ftfs-> addSearchMode(ftsd, RS_FILE_HINTS_LOCAL); - ftfs-> addSearchMode(eList, RS_FILE_HINTS_EXTRA); - - ftDataSend *ftds = new ftDataSendDummy(); - - /* setup Actual Test bit */ - ftDataMultiplex *ftmplex = new ftDataMultiplex("ownId", ftds, ftfs); - ftmplex->start(); - - /* Setup Search with some valid results */ - - - /* Request Data */ - - /* now work the thread */ - std::list::iterator it; - TransferRequestFlags flags(0); - for(it = fileList.begin(); it != fileList.end(); it++) - { - eList->hashExtraFile(*it, dPeriod, flags); - } - - - /* now request files from ftDataMultiplex */ - - /* just request random data packets first */ - do_random_server_test(ftmplex, eList, fileList); - - FINALREPORT("FtDataPlex test") ; - - return TESTRESULT() ; -} - - - -uint32_t do_random_server_iteration(ftDataMultiplex *mplex, ftExtraList *eList, std::list &files) -{ - std::cerr << "do_random_server_iteration()"; - std::cerr << std::endl; - - std::list::iterator it; - uint32_t i = 0; - for(it = files.begin(); it != files.end(); it++) - { - FileInfo info; - if (eList->hashExtraFileDone(*it, info)) - { - std::cerr << "Hash Done for: " << *it; - std::cerr << std::endl; - std::cerr << info << std::endl; - - std::cerr << "Requesting Data Packet"; - std::cerr << std::endl; - - /* Server Recv */ - uint64_t offset = 10000; - uint32_t chunk = 20000; - mplex->recvDataRequest("Peer", info.hash, info.size, offset, chunk); - - i++; - } - else - { - std::cerr << "do_random_server_iteration() Hash Not Done for: " << *it; - std::cerr << std::endl; - } - } - - return i; - -} - - -void do_random_server_test(ftDataMultiplex *mplex, ftExtraList *eList, std::list &files) -{ - std::cerr << "do_random_server_test()"; - std::cerr << std::endl; - - uint32_t size = files.size(); - while(size > do_random_server_iteration(mplex, eList, files)) - { - std::cerr << "do_random_server_test() sleep"; - std::cerr << std::endl; - - sleep(10); - } -} - - diff --git a/libretroshare/src/tests/ft/ftextralisttest.cc b/libretroshare/src/tests/ft/ftextralisttest.cc deleted file mode 100644 index 65f443eb1..000000000 --- a/libretroshare/src/tests/ft/ftextralisttest.cc +++ /dev/null @@ -1,172 +0,0 @@ -/* - * libretroshare/src/ft: ftextralisttest.cc - * - * File Transfer for RetroShare. - * - * Copyright 2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#ifdef WIN32 -#include "util/rswin.h" -#endif - -#include "ft/ftextralist.h" -#include "util/utest.h" - -extern "C" void* runExtraList(void* p) -{ - ftExtraList *eList = (ftExtraList *) p; - if (!eList) - { - pthread_exit(NULL); - } - - while (1) - { - //eList->tick(); - sleep(1); - - } - - delete eList; - - pthread_exit(NULL); - - return NULL; -} - - - -void displayExtraListDetails(ftExtraList *eList, std::list toHash, std::list hashed); - - -void usage(char *name) -{ - std::cerr << "Usage: " << name << " -h -p -d "; - std::cerr << std::endl; -} - -INITTEST() ; - -int main(int argc, char **argv) -{ - int c; - uint32_t period = 1; - uint32_t dPeriod = 600; /* default 10 minutes */ - - std::list hashList; - - while(-1 != (c = getopt(argc, argv, "h:p:d:"))) - { - switch (c) - { - case 'h': - hashList.push_back(std::string(optarg)); - break; - case 'p': - period = atoi(optarg); - break; - case 'd': - dPeriod = atoi(optarg); - break; - default: - usage(argv[0]); - break; - } - } - - ftExtraList *eList = new ftExtraList(); - - /* now startup background thread to keep it reunning */ - eList->start(); - - - - /* now work the thread */ - std::list toHash; - std::list hashed; - std::list::iterator it; - - TransferRequestFlags flags(0); - for(it = hashList.begin(); it != hashList.end(); it++) - { - sleep(period); - - /* load up file */ - //eList->addExtraFile(*it); - eList->hashExtraFile(*it, dPeriod, flags); - - toHash.push_back(*it); - - displayExtraListDetails(eList, toHash, hashed); - } - - for(int i=0;i<20;++i) - { - sleep(period); - - displayExtraListDetails(eList, toHash, hashed); - } - - FINALREPORT("Extra list test.") ; - return 0; -} - -void displayExtraListDetails(ftExtraList *eList, std::list toHash, std::list hashed) -{ - std::cerr << "displayExtraListDetails()"; - std::cerr << std::endl; - - std::list::iterator it; - for(it = toHash.begin(); it != toHash.end(); it++) - { - FileInfo info; - if (eList->hashExtraFileDone(*it, info)) - { - std::cerr << "displayExtraListDetails() Hash Completed for: " << *it; - std::cerr << std::endl; - std::cerr << info << std::endl; - } - else - { - std::cerr << "displayExtraListDetails() Hash Not Done for: " << *it; - std::cerr << std::endl; - } - } - - for(it = hashed.begin(); it != hashed.end(); it++) - { - FileInfo info; - if (eList->search(*it, FileSearchFlags(0), info)) - { - std::cerr << "displayExtraListDetails() Found Hash: " << *it; - std::cerr << std::endl; - std::cerr << info << std::endl; - } - else - { - std::cerr << "displayExtraListDetails() Hash Not Found: " << *it; - std::cerr << std::endl; - } - } -} - - - diff --git a/libretroshare/src/tests/ft/ftfilecreatortest.cc b/libretroshare/src/tests/ft/ftfilecreatortest.cc deleted file mode 100644 index ae03ded20..000000000 --- a/libretroshare/src/tests/ft/ftfilecreatortest.cc +++ /dev/null @@ -1,165 +0,0 @@ -#include "ft/ftfilecreator.h" - -#include "util/utest.h" -#include "common/testutils.h" -#include - -#include "util/rswin.h" -#include "util/rsdir.h" -#include "util/rsdiscspace.h" -#include "pqi/p3cfgmgr.h" -#include "ft/ftserver.h" -#include "turtle/p3turtle.h" - -INITTEST(); - -static int test_timeout(ftFileCreator *creator); -static int test_fill(ftFileCreator *creator); - -int main() -{ - RsDiscSpace::setDownloadPath("/tmp") ; - RsDiscSpace::setPartialsPath("/tmp") ; - - /* use ftcreator to create a file on tmp drive */ - std::string hash = TestUtils::createRandomFileHash() ; - uint64_t size = 12943090 ; - - ftFileCreator fcreator1("/tmp/rs-ftfc-test.dta",size,hash,true); - ftFileCreator fcreator2("/tmp/rs-ftfc-test.dta",size,hash,true); - - test_timeout(&fcreator1); - test_fill(&fcreator2); - - FINALREPORT("RsTlvItem Stack Tests"); - - return TESTRESULT(); -} - - -int test_timeout(ftFileCreator *creator) -{ - uint32_t chunk = 1000; - uint64_t offset = 0; - int max_timeout = 5; - int max_offset = chunk * max_timeout; - int i; - std::cerr << "60 second test of chunk queue."; - std::cerr << std::endl; - - uint32_t size_hint = 1000; - std::string peer_id = "dummyId"; - bool toOld = false; - - for(i = 0; i < max_timeout; i++) - { - creator->getMissingChunk(peer_id, size_hint, offset, chunk, toOld); - std::cerr << "Allocated Offset: " << offset << " chunk: " << chunk << std::endl; - - CHECK(offset <= max_offset); - // sleep(1); - } - - std::cerr << "Expect Repeats now"; - std::cerr << std::endl; - - for(i = 0; i < max_timeout; i++) - { - // sleep(1); - creator->getMissingChunk(peer_id, size_hint, offset, chunk, toOld); - std::cerr << "Allocated Offset: " << offset << " chunk: " << chunk << std::endl; - - CHECK(offset <= max_offset); - } - REPORT("Chunk Queue"); - - return 1; -} - - -int test_fill(ftFileCreator *creator) -{ - uint32_t chunk = 1000; - uint64_t offset = 0; - - uint64_t init_size = creator->getFileSize(); - uint64_t init_trans = creator->getRecvd(); - std::cerr << "Initial FileSize: " << init_size << std::endl; - std::cerr << "Initial Transferred:" << init_trans << std::endl; - - uint32_t size_hint = 1000; - std::string peer_id = TestUtils::createRandomSSLId(); - bool toOld = false; - std::cerr << "Allocating data size in memory for " << creator->fileSize() << " bytes." << std::endl; - unsigned char *total_file_data = new unsigned char[creator->fileSize()] ; - - while(creator->getMissingChunk(peer_id, size_hint, offset, chunk, toOld)) - { - if (chunk == 0) - { - std::cerr << "Missing Data already Alloced... wait"; - std::cerr << std::endl; - sleep(1); - chunk = 1000; - continue; - } - - /* give it to them */ - void *data = malloc(chunk); - /* fill with ascending numbers */ - for(int i = 0; i < chunk; i++) - { - ((uint8_t *) data)[i] = 'a' + i % 27; - if (i % 27 == 26) - { - ((uint8_t *) data)[i] = '\n'; - } - } - memcpy(total_file_data+offset,data,chunk) ; - - //std::cerr << " adding file data at offset " << offset << ", size = " << chunk << std::endl; - - creator->addFileData(offset, chunk, data); - free(data); -//#ifndef WINDOWS_SYS -///********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -// usleep(250000); /* 1/4 of sec */ -//#else -///********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -// Sleep(250); /* 1/4 of sec */ -//#endif -///********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - chunk = 1000; /* reset chunk size */ - - } - // validate all chunks - - std::vector chunks_to_check ; - creator->getChunksToCheck(chunks_to_check) ; - - std::cerr << "Validating " << chunks_to_check.size() << " chunks." << std::endl; - - uint32_t CHUNKMAP_SIZE = 1024*1024 ; - - for(uint32_t i=0;ifileSize() - chunks_to_check[i]*CHUNKMAP_SIZE)) ; - Sha1CheckSum crc = RsDirUtil::sha1sum(total_file_data+chunks_to_check[i]*CHUNKMAP_SIZE,chunk_size) ; - std::cerr << " Checking crc for chunk " << chunks_to_check[i] << " of size " << chunk_size << ". Reference is " << crc.toStdString() << std::endl; - creator->verifyChunk(chunks_to_check[i],crc) ; - } - delete[] total_file_data ; - - uint64_t end_size = creator->getFileSize(); - uint64_t end_trans = creator->getRecvd(); - std::cerr << "End FileSize: " << end_size << std::endl; - std::cerr << "End Transferred:" << end_trans << std::endl; - CHECK(init_size == end_size); - CHECK(end_trans == end_size); - - REPORT("Test Fill"); - - return 1; -} - diff --git a/libretroshare/src/tests/ft/ftfilemappertest.cc b/libretroshare/src/tests/ft/ftfilemappertest.cc deleted file mode 100644 index 69c97a3c4..000000000 --- a/libretroshare/src/tests/ft/ftfilemappertest.cc +++ /dev/null @@ -1,91 +0,0 @@ -#include "ft/ftfilemapper.h" -#include "ft/ftchunkmap.h" -#include "retroshare/rstypes.h" - -#include -#include -#include -#include -#include - -INITTEST(); - -int main() -{ - /* Use ftfilemapper to create a file with chunks downloaded on a random direction. */ - - static const std::string tmpdir = "." ; - static const std::string input_file = tmpdir+"/"+"input.bin" ; - static const std::string output_file = tmpdir+"/"+"output.bin" ; - static const uint64_t size = 1024*1024*12+234;//4357283 ; // some size. Not an integer number of chunks - static const uint32_t chunk_size = 1024*1024 ; // 1MB - - pid_t pid = getpid() ; - srand48(pid) ; - srand(pid) ; - std::cerr << "Inited random number generator with seed " << pid << std::endl; - - // 0 - create a random file in memory, of size SIZE - - void *membuf = malloc(size) ; - CHECK(membuf != NULL) ; - - for(int i=0;i - -#include "util/rswin.h" - -INITTEST() - -int main() -{ - std::string ownId = TestUtils::createRandomSSLId() ; - - RsDiscSpace::setPartialsPath("/tmp") ; - RsDiscSpace::setDownloadPath("/tmp") ; - - /* create a random file */ - uint64_t size = 10000000; - uint32_t max_chunk = 10000; - uint32_t chunk = 1000; - uint64_t offset = 0; - - std::string filename = "/tmp/ft_test.dta"; - std::string filename2 = "/tmp/ft_test.dta.dup"; - - std::string hash = TestUtils::createRandomFileHash() ; - - /* use creator to make it */ - - TestUtils::createRandomFile(filename,size) ; - - std::cerr << "Created file: " << filename << " of size: " << size; - std::cerr << std::endl; - - /* load it with file provider */ - ftFileCreator *creator = new ftFileCreator(filename2, size, hash, true); - ftFileProvider *provider = new ftFileProvider(filename, size, hash); - - /* create duplicate with file creator */ - std::string peer_id = TestUtils::createRandomSSLId() ; - uint32_t size_hint = 10000; - bool toOld = false; - unsigned char *data = new unsigned char[max_chunk]; - - while(creator->getMissingChunk(peer_id, size_hint, offset, chunk, toOld)) - { - if (chunk == 0) - { - std::cerr << "All currently allocated .... waiting"; - std::cerr << std::endl; - sleep(1); - /* reset chunk size */ - chunk = (uint64_t) max_chunk * (rand() / (1.0 + RAND_MAX)); - std::cerr << "ChunkSize = " << chunk << std::endl; - continue; - } - - if (!provider->getFileData(ownId,offset, chunk, data)) - { - FAILED("Read from Test Data File"); - std::cerr << "Failed to get data"; - std::cerr << std::endl; - } - - if (!creator->addFileData(offset, chunk, data)) - { - FAILED("Write to Duplicate"); - std::cerr << "Failed to add data"; - std::cerr << std::endl; - } - - std::cerr << "Transferred: " << chunk << " @ " << offset; - std::cerr << std::endl; - - - /* reset chunk size */ - chunk = (uint64_t) max_chunk * (rand() / (1.0 + RAND_MAX)); - - std::cerr << "ChunkSize = " << chunk << std::endl; - } - std::string path,hash2 ; - - RsDirUtil::hashFile(filename ,path,hash,size) ; - RsDirUtil::hashFile(filename2,path,hash2,size) ; - - std::cerr << "Checking hash1 : " << hash << std::endl; - std::cerr << "Checking hash2 : " << hash2 << std::endl; - - CHECK(hash == hash2) ; - - FINALREPORT("ftfilecreatortest") ; - - return TESTRESULT(); -} - diff --git a/libretroshare/src/tests/ft/ftsearch_dummy.cc b/libretroshare/src/tests/ft/ftsearch_dummy.cc deleted file mode 100644 index 72b59d471..000000000 --- a/libretroshare/src/tests/ft/ftsearch_dummy.cc +++ /dev/null @@ -1,16 +0,0 @@ -#include "ftsearch_dummy.h" - -bool ftSearchDummy::search(const std::string& /*hash*/, FileSearchFlags hintflags, FileInfo &/*info*/) const -{ - /* remove unused parameter warnings */ - (void) hintflags; - -#ifdef DEBUG_SEARCH - std::cerr << "ftSearchDummy::search(" << hash ; - std::cerr << ", " << hintflags << ");"; - std::cerr << std::endl; -#endif - return false; -} - - diff --git a/libretroshare/src/tests/ft/ftsearch_dummy.h b/libretroshare/src/tests/ft/ftsearch_dummy.h deleted file mode 100644 index 9a5ffcdff..000000000 --- a/libretroshare/src/tests/ft/ftsearch_dummy.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * libretroshare/src/ft: ftsearch.h - * - * File Transfer for RetroShare. - * - * Copyright 2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#pragma once - -#include "ft/ftsearch.h" - -class ftSearchDummy: public ftSearch -{ - public: - - ftSearchDummy() { return; } -virtual ~ftSearchDummy() { return; } -virtual bool search(const std::string& hash, FileSearchFlags hintflags, FileInfo &info) const; -}; - diff --git a/libretroshare/src/tests/ft/ftserver1test.cc b/libretroshare/src/tests/ft/ftserver1test.cc deleted file mode 100644 index d8722eb9c..000000000 --- a/libretroshare/src/tests/ft/ftserver1test.cc +++ /dev/null @@ -1,351 +0,0 @@ -/* - * libretroshare/src/ft: ftserver1test.cc - * - * File Transfer for RetroShare. - * - * Copyright 2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/* - * Test for Whole Basic system..... - * - * Put it all together, and make it compile. - */ - -#ifdef WIN32 -#include "util/rswin.h" -#endif - -#include "ft/ftserver.h" - -#include "ft/ftextralist.h" -#include "ft/ftdatamultiplex.h" -#include "ft/ftfilesearch.h" - -#include "pqi/p3linkmgr.h" -#include "pqi/p3peermgr.h" -#include "pqi/p3netmgr.h" - -#include "util/rsdebug.h" -#include "util/utest.h" -#include "common/testutils.h" -#include "retroshare/rsiface.h" - -#include "pqitestor.h" -#include "util/rsdir.h" - -#include - - -INITTEST(); - -void do_random_server_test(ftDataMultiplex *mplex, ftExtraList *eList, std::list &files); - - -void usage(char *name) -{ - std::cerr << "Usage: " << name << " [-p ] [-d ] [ ... ] "; - std::cerr << std::endl; -} - -int main(int argc, char **argv) -{ - int c; - uint32_t period = 1; - uint32_t debugLevel = 5; - bool debugStderr = true; - - std::list fileList; - std::list peerIds; - std::map mFtServers; - std::map mLinkMgrs; - -#ifdef PTW32_STATIC_LIB - pthread_win32_process_attach_np(); -#endif - -#ifdef WIN32 - // Windows Networking Init. - WORD wVerReq = MAKEWORD(2,2); - WSADATA wsaData; - - if (0 != WSAStartup(wVerReq, &wsaData)) - { - std::cerr << "Failed to Startup Windows Networking"; - std::cerr << std::endl; - } - else - { - std::cerr << "Started Windows Networking"; - std::cerr << std::endl; - } - -#endif - - - while(-1 != (c = getopt(argc, argv, "d:p:s"))) - { - switch (c) - { - case 'p': - peerIds.push_back(optarg); - break; - case 'd': - debugLevel = atoi(optarg); - break; - case 's': - debugStderr = true; - break; - default: - usage(argv[0]); - break; - } - } - - /* do logging */ - setOutputLevel(debugLevel); - - if (optind >= argc) - { - std::cerr << "Missing Files" << std::endl; - usage(argv[0]); - } - std::cerr << "Point 1" << std::endl; - - for(; optind < argc; optind++) - { - std::cerr << "Adding: " << argv[optind] << std::endl; - - SharedDirInfo info ; - info.filename = std::string(argv[optind]) ; - info.virtualname = info.filename ; - info.shareflags = DIR_FLAGS_PERMISSIONS_MASK ; - info.parent_groups.clear() ; - - fileList.push_back(info); - } - std::cerr << "Point 2" << std::endl; - - std::string ssl_own_id = TestUtils::createRandomSSLId() ; - std::string gpg_own_id = TestUtils::createRandomPGPId() ; - - TestUtils::DummyAuthGPG fakeGPG(gpg_own_id) ; - AuthGPG::setAuthGPG_debug(&fakeGPG) ; - - TestUtils::DummyAuthSSL fakeSSL(ssl_own_id) ; - AuthSSL::setAuthSSL_debug(&fakeSSL) ; - - /* We need to setup a series 2 - 4 different ftServers.... - * - * Each one needs: - * - * - * A List of peerIds... - */ - - std::list::const_iterator it, jit; - - std::list baseFriendList, friendList; - std::list::iterator fit; - - P3Hub *testHub = new P3Hub(0,NULL); - testHub->start(); - - /* Setup Base Friend Info */ - for(it = peerIds.begin(); it != peerIds.end(); it++) - { - RsPeerDetails pad; - pad.id = *it; - pad.gpg_id = TestUtils::createRandomPGPId() ; - pad.name = *it; - pad.trustLvl = 5; - pad.ownsign = true; - //pad.trusted = false; - - baseFriendList.push_back(pad); - - std::cerr << "ftserver1test::setup peer: " << *it << std::endl; - } - - std::ostringstream pname; - pname << "/tmp/rstst-" << time(NULL); - - std::string basepath = pname.str(); - RsDirUtil::checkCreateDirectory(basepath); - - - - for(it = peerIds.begin(); it != peerIds.end(); it++) - { - friendList = baseFriendList; - /* remove current one */ - for(fit = friendList.begin(); fit != friendList.end(); fit++) - { - if (fit->id == *it) - { - friendList.erase(fit); - break; - } - } - - //p3AuthMgr *authMgr = new p3DummyAuthMgr(*it, friendList); - p3PeerMgrIMPL *peerMgr = new p3PeerMgrIMPL(ssl_own_id,gpg_own_id,"My GPG name","My SSL location"); - - p3NetMgrIMPL *netMgr = new p3NetMgrIMPL ; - p3LinkMgrIMPL *linkMgr = new p3LinkMgrIMPL(peerMgr,netMgr); - mLinkMgrs[*it] = linkMgr; - - rsPeers = new TestUtils::DummyRsPeers(linkMgr,peerMgr,netMgr) ; - - for(fit = friendList.begin(); fit != friendList.end(); fit++) - { - /* add as peer to authMgr */ - peerMgr->addFriend(fit->id,fit->gpg_id); - } - - P3Pipe *pipe = new P3Pipe(); //(*it); - - /* add server */ - ftServer *server; - server = new ftServer(peerMgr,linkMgr); - mFtServers[*it] = server; - - server->setP3Interface(pipe); - - std::string configpath = basepath + "/" + *it; - RsDirUtil::checkCreateDirectory(configpath); - - std::string cachepath = configpath + "/cache"; - RsDirUtil::checkCreateDirectory(cachepath); - - std::string partialspath = configpath + "/partials"; - RsDirUtil::checkCreateDirectory(partialspath); - - std::string downloadpath = configpath + "/downloads"; - RsDirUtil::checkCreateDirectory(downloadpath); - - std::string localpath = cachepath + "/local"; - RsDirUtil::checkCreateDirectory(localpath); - - std::string remotepath = cachepath + "/remote"; - RsDirUtil::checkCreateDirectory(remotepath); - - server->setConfigDirectory(configpath); - - //sleep(60); - - NotifyBase *base = new NotifyBase; - server->SetupFtServer(base); - - testHub->addP3Pipe(*it, pipe, linkMgr); - server->StartupThreads(); - - /* setup any extra bits */ - server->setPartialsDirectory(partialspath); - server->setDownloadDirectory(downloadpath); - server->setSharedDirectories(fileList); - } - - /* stick your real test here */ - std::map::iterator sit; - std::map::iterator cit; - - for(int i=0;i < 20;++i) - { - std::cerr << "ftserver1test::sleep()"; - std::cerr << std::endl; - sleep(1); - - /* tick the connmgrs */ - for(sit = mFtServers.begin(); sit != mFtServers.end(); sit++) - { - /* update */ - (sit->second)->tick(); - } - - for(cit = mLinkMgrs.begin(); cit != mLinkMgrs.end(); cit++) - { - /* update */ - (cit->second)->tick(); - } - } - - FINALREPORT("FtServer running.") ; -} - - -#if 0 - -uint32_t do_random_server_iteration(ftDataMultiplex *mplex, ftExtraList *eList, std::list &files) -{ - std::cerr << "do_random_server_iteration()"; - std::cerr << std::endl; - - std::list::iterator it; - uint32_t i = 0; - for(it = files.begin(); it != files.end(); it++) - { - FileInfo info; - if (eList->hashExtraFileDone(*it, info)) - { - std::cerr << "Hash Done for: " << *it; - std::cerr << std::endl; - std::cerr << info << std::endl; - - std::cerr << "Requesting Data Packet"; - std::cerr << std::endl; - - /* Server Recv */ - uint64_t offset = 10000; - uint32_t chunk = 20000; - mplex->recvDataRequest("Peer", info.hash, info.size, offset, chunk); - - i++; - } - else - { - std::cerr << "do_random_server_iteration() Hash Not Done for: " << *it; - std::cerr << std::endl; - } - } - - return i; - -} - - -void do_random_server_test(ftDataMultiplex *mplex, ftExtraList *eList, std::list &files) -{ - std::cerr << "do_random_server_test()"; - std::cerr << std::endl; - - uint32_t size = files.size(); - while(size > do_random_server_iteration(mplex, eList, files)) - { - std::cerr << "do_random_server_test() sleep"; - std::cerr << std::endl; - - sleep(10); - } -} - - -#endif - diff --git a/libretroshare/src/tests/ft/ftserver1test.sh b/libretroshare/src/tests/ft/ftserver1test.sh deleted file mode 100755 index 379ecc7fa..000000000 --- a/libretroshare/src/tests/ft/ftserver1test.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -./ftserver1test -p 8cb3a1677872c9e8248fd5ddeac84000 -p 8cb3a1677872c9e8248fd5ddeac84001 -p 8cb3a1677872c9e8248fd5ddeac84002 . diff --git a/libretroshare/src/tests/ft/ftserver2test.cc b/libretroshare/src/tests/ft/ftserver2test.cc deleted file mode 100644 index 84f4c9937..000000000 --- a/libretroshare/src/tests/ft/ftserver2test.cc +++ /dev/null @@ -1,444 +0,0 @@ -/* - * libretroshare/src/ft: ftserver1test.cc - * - * File Transfer for RetroShare. - * - * Copyright 2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/* - * Test for Whole Basic system..... - * - * Put it all together, and make it compile. - */ - -#ifdef WIN32 -#include "util/rswin.h" -#endif - -#include "ft/ftserver.h" - -#include "ft/ftextralist.h" -#include "ft/ftdatamultiplex.h" -#include "ft/ftfilesearch.h" - -#include "pqi/p3linkmgr.h" -#include "pqi/p3peermgr.h" -#include "pqi/p3netmgr.h" - -#include "util/rsdebug.h" -#include "util/utest.h" -#include "common/testutils.h" -#include "retroshare/rsiface.h" - -#include "pqitestor.h" -#include "util/rsdir.h" -#include "util/utest.h" - - -#include - - -class TestData -{ - public: - - ftServer *loadServer; - std::list otherServers; - std::list extraList; -}; - - -extern "C" void *do_server_test_thread(void *p); - - -void usage(char *name) -{ - std::cerr << "Usage: " << name << " [-sa] [-p ] [-d ] [-e ] [ [ ... ]] "; - std::cerr << std::endl; -} - -int main(int argc, char **argv) -{ - int c; - uint32_t period = 1; - uint32_t debugLevel = 5; - bool debugStderr = true; - bool loadAll = false; - - std::list fileList; - std::list extraList; - std::list peerIds; - std::map mFtServers; - std::map mLinkMgrs; - - ftServer *mLoadServer = NULL; - std::list mOtherServers; - std::list::iterator eit; - -#ifdef PTW32_STATIC_LIB - pthread_win32_process_attach_np(); -#endif - -#ifdef WIN32 - // Windows Networking Init. - WORD wVerReq = MAKEWORD(2,2); - WSADATA wsaData; - - if (0 != WSAStartup(wVerReq, &wsaData)) - { - std::cerr << "Failed to Startup Windows Networking"; - std::cerr << std::endl; - } - else - { - std::cerr << "Started Windows Networking"; - std::cerr << std::endl; - } - -#endif - - - while(-1 != (c = getopt(argc, argv, "asd:p:e:"))) - { - switch (c) - { - case 'p': - peerIds.push_back(optarg); - break; - case 'd': - debugLevel = atoi(optarg); - break; - case 's': - debugStderr = true; - break; - case 'e': - extraList.push_back(optarg); - break; - case 'a': - loadAll = true; - break; - default: - usage(argv[0]); - break; - } - } - - /* do logging */ - setOutputLevel(debugLevel); - - if (optind >= argc) - { - std::cerr << "Missing Shared Directories" << std::endl; - usage(argv[0]); - } - - for(; optind < argc; optind++) - { - std::cerr << "Adding: " << argv[optind] << std::endl; - SharedDirInfo info ; - info.shareflags = DIR_FLAGS_PERMISSIONS_MASK; - info.filename = std::string(argv[optind]); - info.virtualname = std::string(argv[optind]); - fileList.push_back(info) ; - } - std::cerr << "Point 2" << std::endl; - - std::string ssl_own_id = TestUtils::createRandomSSLId() ; - std::string gpg_own_id = TestUtils::createRandomPGPId() ; - - TestUtils::DummyAuthGPG fakeGPG(gpg_own_id) ; - AuthGPG::setAuthGPG_debug(&fakeGPG) ; - - TestUtils::DummyAuthSSL fakeSSL(ssl_own_id) ; - AuthSSL::setAuthSSL_debug(&fakeSSL) ; - - /* We need to setup a series 2 - 4 different ftServers.... - * - * Each one needs: - * - * - * A List of peerIds... - */ - - std::list::const_iterator it, jit; - - std::list baseFriendList, friendList; - std::list::iterator fit; - - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsFileItemSerialiser()); - rss->addSerialType(new RsCacheItemSerialiser()); - rss->addSerialType(new RsServiceSerialiser()); - - - P3Hub *testHub = new P3Hub(0, rss); - testHub->start(); - - /* Setup Base Friend Info */ - for(it = peerIds.begin(); it != peerIds.end(); it++) - { - RsPeerDetails pad; - pad.id = *it; - pad.gpg_id = TestUtils::createRandomPGPId() ; - pad.name = *it; - pad.trustLvl = 5; - pad.ownsign = true; - //pad.trusted = false; - - baseFriendList.push_back(pad); - - std::cerr << "ftserver1test::setup peer: " << *it << std::endl; - } - - std::ostringstream pname; - pname << "/tmp/rstst-" << time(NULL); - - std::string basepath = pname.str(); - RsDirUtil::checkCreateDirectory(basepath); - - - - for(it = peerIds.begin(); it != peerIds.end(); it++) - { - friendList = baseFriendList; - /* remove current one */ - for(fit = friendList.begin(); fit != friendList.end(); fit++) - { - if (fit->id == *it) - { - friendList.erase(fit); - break; - } - } - - //p3AuthMgr *authMgr = new p3DummyAuthMgr(*it, friendList); - p3PeerMgrIMPL *peerMgr = new p3PeerMgrIMPL(ssl_own_id,gpg_own_id,"My GPG name","My SSL location"); - - p3NetMgrIMPL *netMgr = new p3NetMgrIMPL ; - p3LinkMgrIMPL *linkMgr = new p3LinkMgrIMPL(peerMgr,netMgr); - mLinkMgrs[*it] = linkMgr; - - //rsPeers = new TestUtils::DummyRsPeers(linkMgr,peerMgr,netMgr) ; - for(fit = friendList.begin(); fit != friendList.end(); fit++) - { - /* add as peer to authMgr */ - peerMgr->addFriend(fit->id,fit->gpg_id); - linkMgr->addFriend(fit->id,true); - } - - P3Pipe *pipe = new P3Pipe(); //(*it); - - /* add server */ - ftServer *server; - server = new ftServer(peerMgr,linkMgr); - mFtServers[*it] = server; - if (!mLoadServer) - { - mLoadServer = server; - } - else - { - mOtherServers.push_back(server); - } - - server->setP3Interface(pipe); - - std::string configpath = basepath + "/" + *it; - RsDirUtil::checkCreateDirectory(configpath); - - std::string cachepath = configpath + "/cache"; - RsDirUtil::checkCreateDirectory(cachepath); - - std::string partialspath = configpath + "/partials"; - RsDirUtil::checkCreateDirectory(partialspath); - - std::string downloadpath = configpath + "/downloads"; - RsDirUtil::checkCreateDirectory(downloadpath); - - std::string localpath = cachepath + "/local"; - RsDirUtil::checkCreateDirectory(localpath); - - std::string remotepath = cachepath + "/remote"; - RsDirUtil::checkCreateDirectory(remotepath); - - server->setConfigDirectory(configpath); - - //sleep(60); - - NotifyBase *base = new NotifyBase; - server->SetupFtServer(base); - - testHub->addP3Pipe(*it, pipe, linkMgr); - server->StartupThreads(); - - /* setup any extra bits */ - /* everyone gets download directories */ - server->setPartialsDirectory(partialspath); - server->setDownloadDirectory(downloadpath); - - if (loadAll) - { - server->setSharedDirectories(fileList); - for(eit = extraList.begin(); eit != extraList.end(); eit++) - { - server->ExtraFileHash(*eit, 3600, TransferRequestFlags(0)); - } - } - - } - - if (mLoadServer) - { - mLoadServer->setSharedDirectories(fileList); - for(eit = extraList.begin(); eit != extraList.end(); eit++) - { - mLoadServer->ExtraFileHash(*eit, 3600, TransferRequestFlags(0)); - } - } - - /* stick your real test here */ - std::map::iterator sit; - std::map::iterator cit; - - /* Start up test thread */ - pthread_t tid; - TestData *mFt = new TestData; - - /* set data */ - mFt->loadServer = mLoadServer; - mFt->otherServers = mOtherServers; - mFt->extraList = extraList; - - void *data = (void *) mFt; - pthread_create(&tid, 0, &do_server_test_thread, data); - pthread_detach(tid); /* so memory is reclaimed in linux */ - - while(1) - { - std::cerr << "ftserver2test::sleep()"; - std::cerr << std::endl; - sleep(1); - - /* tick the connmgrs */ - for(sit = mFtServers.begin(); sit != mFtServers.end(); sit++) - { - /* update */ - (sit->second)->tick(); - } - - for(cit = mLinkMgrs.begin(); cit != mLinkMgrs.end(); cit++) - { - /* update */ - (cit->second)->tick(); - } - } -} - -/* So our actual test can run here..... - * - */ - -INITTEST(); - -void *do_server_test_thread(void *data) -{ - TestData *mFt = (TestData *) data; - - std::cerr << "do_server_test_thread() running"; - std::cerr << std::endl; - - /************************* TEST 1 ********************** - * Check that the extra List has been processed. - */ - rstime_t start = time(NULL); - - FileInfo info, info2; - rstime_t now = time(NULL); - std::list::iterator eit; - for(eit = mFt->extraList.begin(); eit != mFt->extraList.end(); eit++) - { - while(!mFt->loadServer->ExtraFileStatus(*eit, info)) - { - - /* max of 30 seconds */ - now = time(NULL); - if (now - start > 30) - { - /* FAIL */ - REPORT2( false, "Extra File Hashing"); - } - - sleep(1); - } - - /* Got ExtraFileStatus */ - REPORT("Successfully Found ExtraFile"); - - /* now we can try a search (should succeed) */ - FileSearchFlags hintflags = RS_FILE_HINTS_EXTRA; - - if (mFt->loadServer->FileDetails(info.hash, hintflags, info2)) - { - CHECK(info2.hash == info.hash); - CHECK(info2.size == info.size); - CHECK(info2.fname == info.fname); - } - else - { - REPORT2( false, "Search for Extra File (Basic)"); - } - - /* search with flags (should succeed) */ - hintflags = RS_FILE_HINTS_EXTRA; - if (mFt->loadServer->FileDetails(info.hash, hintflags, info2)) - { - CHECK(info2.hash == info.hash); - CHECK(info2.size == info.size); - CHECK(info2.fname == info.fname); - } - else - { - REPORT2( false, "Search for Extra File (Extra Flag)"); - } - - /* search with other flags (should fail) */ - hintflags = RS_FILE_HINTS_REMOTE | RS_FILE_HINTS_SPEC_ONLY; - if (mFt->loadServer->FileDetails(info.hash, hintflags, info2)) - { - REPORT2( false, "Search for Extra File (Fail Flags)"); - } - else - { - REPORT("Search for Extra File (Fail Flags)"); - } - - /* if we try to download it ... should just find existing one*/ - - REPORT("Testing with Extra File"); - } - - FINALREPORT("ExtraList Hashing, Searching and Downloading"); - exit(1); -} - - - - diff --git a/libretroshare/src/tests/ft/ftserver2test.sh b/libretroshare/src/tests/ft/ftserver2test.sh deleted file mode 100755 index fce1f4fa6..000000000 --- a/libretroshare/src/tests/ft/ftserver2test.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -./ftserver2test -p 8cb3a1677872c9e8248fd5ddeac84000 -p 8cb3a1677872c9e8248fd5ddeac84001 -p 8cb3a1677872c9e8248fd5ddeac84002 . -e ftserver1test ftcontrollertest diff --git a/libretroshare/src/tests/ft/ftserver3test.cc b/libretroshare/src/tests/ft/ftserver3test.cc deleted file mode 100644 index e887eee6b..000000000 --- a/libretroshare/src/tests/ft/ftserver3test.cc +++ /dev/null @@ -1,491 +0,0 @@ -/* - * libretroshare/src/ft: ftserver3test.cc - * - * File Transfer for RetroShare. - * - * Copyright 2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/* - * ftServer3Test - Test of the file transfer from a server level. - * Steps: - * 1) load shared directories into others, and let them be - transferred between clients. - * 2) search for local item on others. - * 3) request item on load server. - should transfer from all others simultaneously. - */ - -#ifdef WIN32 -#include "util/rswin.h" -#endif - -#include -#include "retroshare/rsexpr.h" -#include "retroshare/rstypes.h" -#include "retroshare/rsfiles.h" - -#include "ft/ftserver.h" - -#include "ft/ftextralist.h" -#include "ft/ftdatamultiplex.h" -#include "ft/ftfilesearch.h" - -#include "pqi/p3linkmgr.h" -#include "pqi/p3peermgr.h" -#include "pqi/p3netmgr.h" - -#include "util/rsdebug.h" -#include "util/utest.h" -#include "common/testutils.h" -#include "retroshare/rsiface.h" - -#include "pqitestor.h" -#include "util/rsdir.h" -#include "util/utest.h" - - -#include - - -class TestData -{ - public: - - ftServer *loadServer; - std::list otherServers; - std::list extraList; -}; - - -extern "C" void *do_server_test_thread(void *p); - - -void usage(char *name) -{ - std::cerr << "Usage: " << name << " [-soa] [-p ] [-d ] [-e ] [ [ ... ]] "; - std::cerr << std::endl; -} - -int main(int argc, char **argv) -{ - int c; - uint32_t period = 1; - uint32_t debugLevel = 5; - bool debugStderr = true; - bool loadAll = false; - bool loadOthers = false; - - std::list fileList; - std::list extraList; - std::list peerIds; - std::map mFtServers; - std::map mLinkMgrs; - - ftServer *mLoadServer = NULL; - std::list mOtherServers; - std::list::iterator eit; - -#ifdef PTW32_STATIC_LIB - pthread_win32_process_attach_np(); -#endif - -#ifdef WIN32 - // Windows Networking Init. - WORD wVerReq = MAKEWORD(2,2); - WSADATA wsaData; - - if (0 != WSAStartup(wVerReq, &wsaData)) - { - std::cerr << "Failed to Startup Windows Networking"; - std::cerr << std::endl; - } - else - { - std::cerr << "Started Windows Networking"; - std::cerr << std::endl; - } - -#endif - - - while(-1 != (c = getopt(argc, argv, "aosd:p:e:"))) - { - switch (c) - { - case 'p': - peerIds.push_back(optarg); - break; - case 'd': - debugLevel = atoi(optarg); - break; - case 's': - debugStderr = true; - break; - case 'e': - extraList.push_back(optarg); - break; - case 'a': - loadAll = true; - break; - case 'o': - loadOthers = true; - break; - default: - usage(argv[0]); - break; - } - } - - /* do logging */ - setOutputLevel(debugLevel); - - if (optind >= argc) - { - std::cerr << "Missing Shared Directories" << std::endl; - usage(argv[0]); - } - - for(; optind < argc; optind++) - { - std::cerr << "Adding: " << argv[optind] << std::endl; - - SharedDirInfo info ; - info.filename = std::string(argv[optind]); - info.virtualname = info.filename ; - info.shareflags = DIR_FLAGS_PERMISSIONS_MASK; - - fileList.push_back(info) ; - } - std::cerr << "Point 2" << std::endl; - - std::string ssl_own_id = TestUtils::createRandomSSLId() ; - std::string gpg_own_id = TestUtils::createRandomPGPId() ; - - TestUtils::DummyAuthGPG fakeGPG(gpg_own_id) ; - AuthGPG::setAuthGPG_debug(&fakeGPG) ; - - TestUtils::DummyAuthSSL fakeSSL(ssl_own_id) ; - AuthSSL::setAuthSSL_debug(&fakeSSL) ; - - /* We need to setup a series 2 - 4 different ftServers.... - * - * Each one needs: - * - * - * A List of peerIds... - */ - - std::list::const_iterator it, jit; - - std::list baseFriendList, friendList; - std::list::iterator fit; - - /* Add in Serialiser Test - */ - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsFileItemSerialiser()); - rss->addSerialType(new RsCacheItemSerialiser()); - rss->addSerialType(new RsServiceSerialiser()); - - P3Hub *testHub = new P3Hub(0, rss); - testHub->start(); - - /* Setup Base Friend Info */ - for(it = peerIds.begin(); it != peerIds.end(); it++) - { - RsPeerDetails pad; - pad.id = *it; - pad.gpg_id = TestUtils::createRandomPGPId() ; - pad.name = *it; - pad.trustLvl = 5; - pad.ownsign = true; - //pad.trusted = false; - - baseFriendList.push_back(pad); - - std::cerr << "ftserver1test::setup peer: " << *it << std::endl; - } - - std::ostringstream pname; - pname << "/tmp/rstst-" << time(NULL); - - std::string basepath = pname.str(); - RsDirUtil::checkCreateDirectory(basepath); - - - - for(it = peerIds.begin(); it != peerIds.end(); it++) - { - friendList = baseFriendList; - /* remove current one */ - for(fit = friendList.begin(); fit != friendList.end(); fit++) - { - if (fit->id == *it) - { - friendList.erase(fit); - break; - } - } - - //p3AuthMgr *authMgr = new p3DummyAuthMgr(*it, friendList); - p3PeerMgrIMPL *peerMgr = new p3PeerMgrIMPL(ssl_own_id,gpg_own_id,"My GPG name","My SSL location"); - - p3NetMgrIMPL *netMgr = new p3NetMgrIMPL ; - p3LinkMgrIMPL *linkMgr = new p3LinkMgrIMPL(peerMgr,netMgr); - mLinkMgrs[*it] = linkMgr; - - rsPeers = new TestUtils::DummyRsPeers(linkMgr,peerMgr,netMgr) ; - - for(fit = friendList.begin(); fit != friendList.end(); fit++) - { - /* add as peer to authMgr */ - peerMgr->addFriend(fit->id,fit->gpg_id); - } - - P3Pipe *pipe = new P3Pipe(); //(*it); - - /* add server */ - ftServer *server; - server = new ftServer(peerMgr,linkMgr); - mFtServers[*it] = server; - bool isOther; - if (!mLoadServer) - { - mLoadServer = server; - isOther = false; - } - else - { - mOtherServers.push_back(server); - isOther = true; - } - - - server->setP3Interface(pipe); - - std::string configpath = basepath + "/" + *it; - RsDirUtil::checkCreateDirectory(configpath); - - std::string cachepath = configpath + "/cache"; - RsDirUtil::checkCreateDirectory(cachepath); - - std::string partialspath = configpath + "/partials"; - RsDirUtil::checkCreateDirectory(partialspath); - - std::string downloadpath = configpath + "/downloads"; - RsDirUtil::checkCreateDirectory(downloadpath); - - std::string localpath = cachepath + "/local"; - RsDirUtil::checkCreateDirectory(localpath); - - std::string remotepath = cachepath + "/remote"; - RsDirUtil::checkCreateDirectory(remotepath); - - server->setConfigDirectory(configpath); - - //sleep(60); - - NotifyBase *base = new NotifyBase; - server->SetupFtServer(base); - - testHub->addP3Pipe(*it, pipe, linkMgr); - server->StartupThreads(); - - /* setup any extra bits */ - server->setPartialsDirectory(partialspath); - server->setDownloadDirectory(downloadpath); - - if ((loadAll) || (isOther && loadOthers)) - { - server->setSharedDirectories(fileList); - for(eit = extraList.begin(); eit != extraList.end(); eit++) - { - server->ExtraFileHash(*eit, 3600, TransferRequestFlags(0)); - } - } - - } - - if ((mLoadServer) && (!loadOthers)) - { - mLoadServer->setSharedDirectories(fileList); - for(eit = extraList.begin(); eit != extraList.end(); eit++) - { - mLoadServer->ExtraFileHash(*eit, 3600, TransferRequestFlags(0)); - } - } - - - /* stick your real test here */ - std::map::iterator sit; - std::map::iterator cit; - - /* Start up test thread */ - pthread_t tid; - TestData *mFt = new TestData; - - /* set data */ - mFt->loadServer = mLoadServer; - mFt->otherServers = mOtherServers; - mFt->extraList = extraList; - - void *data = (void *) mFt; - pthread_create(&tid, 0, &do_server_test_thread, data); - pthread_detach(tid); /* so memory is reclaimed in linux */ - - while(1) - { - //std::cerr << "ftserver3test::sleep()"; - //std::cerr << std::endl; - sleep(1); - - /* tick the connmgrs */ - for(sit = mFtServers.begin(); sit != mFtServers.end(); sit++) - { - /* update */ - (sit->second)->tick(); - } - - for(cit = mLinkMgrs.begin(); cit != mLinkMgrs.end(); cit++) - { - /* update */ - (cit->second)->tick(); - } - } -} - -/* So our actual test can run here..... - * - */ - -INITTEST(); - -void *do_server_test_thread(void *data) -{ - TestData *mFt = (TestData *) data; - rstime_t startTS = time(NULL); - - std::cerr << "do_server_test_thread() running"; - std::cerr << std::endl; - - /* search Others for a suitable file - * (Tests GUI search functionality) - */ - if (mFt->otherServers.size() < 1) - { - std::cerr << "no Other Servers to search on"; - std::cerr << std::endl; - exit(1); - return NULL; - } - - - for(int i = 0; i < 90; i++) - { - int age = time(NULL) - startTS; - std::cerr << "Waited " << age << " seconds to share caches"; - std::cerr << std::endl; - sleep(1); - } - - ftServer *oServer = *(mFt->otherServers.begin()); - std::string oId = oServer->OwnId(); - - /* create Expression */ - uint64_t minFileSize = 1000; - SizeExpression se(Greater, minFileSize); - //SizeExpression se(Smaller, minFileSize); - Expression *expr = &se; - - std::list results; - std::list::iterator it; - - oServer->SearchBoolExp(expr, results, RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_BROWSABLE); - - if (results.size() < 1) - { - std::cerr << "no Shared Files > " << minFileSize; - std::cerr << std::endl; - exit(1); - return NULL; - } - - /* find the first remote entry */ - DirDetails sFile; - bool foundFile = false; - for(it = results.begin(); (it != results.end()); it++) - { - std::cerr << "Shared File: " << it->name; - std::cerr << std::endl; - - if (!foundFile) - { - if (it->id != mFt->loadServer->OwnId()) - { - std::cerr << "Selected: " << it->name; - std::cerr << std::endl; - foundFile = true; - sFile = *it; - } - else - { - std::cerr << "LoadId: "; - std::cerr << mFt->loadServer->OwnId(); - std::cerr << "FileId: "; - std::cerr << it->id; - std::cerr << std::endl; - } - } - } - - if (!foundFile) - { - std::cerr << "Not Found Suitable File"; - std::cerr << std::endl; - } - - - /*** Now Download it! ***/ - std::list srcIds; - //srcIds.push_back(sFile.id); - // Don't add srcId - to test whether the search works - or not - //srcIds.push_back(oId); - if (foundFile) - { - mFt->loadServer->FileRequest(sFile.name, sFile.hash, sFile.count, "", TransferRequestFlags(0), srcIds); - } - - /* Give it a while to transfer */ - for(int i = 0; i < 100; i++) - { - int age = time(NULL) - startTS; - std::cerr << "Waited " << age << " seconds for tranfer"; - std::cerr << std::endl; - sleep(1); - } - - FINALREPORT("Shared Directories, Bool Search, multi-source transfers"); - exit(1); -} - - - - diff --git a/libretroshare/src/tests/ft/ftserver3test.sh b/libretroshare/src/tests/ft/ftserver3test.sh deleted file mode 100644 index 80ffb1166..000000000 --- a/libretroshare/src/tests/ft/ftserver3test.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -./ftserver3test -p 8cb3a1677872c9e8248fd5ddeac84000 -p 8cb3a1677872c9e8248fd5ddeac84001 -p 8cb3a1677872c9e8248fd5ddeac84002 . ftserver3test diff --git a/libretroshare/src/tests/ft/fttransfermoduletest.cc b/libretroshare/src/tests/ft/fttransfermoduletest.cc deleted file mode 100644 index f98d47a93..000000000 --- a/libretroshare/src/tests/ft/fttransfermoduletest.cc +++ /dev/null @@ -1,182 +0,0 @@ -/* - * libretroshare/src/ft: fttransfermoduletest.cc - * - * File Transfer for RetroShare. - * - * Copyright 2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/* - * Test for Multiplexor..... - * As this is a key middle component, it is hard to test without other bits. - * It relies on ftFileProvider/ftFileCreator/ftTransferModule... - * - * And has dummy ftDataSend and ftSearch. - * - */ - -#ifdef WIN32 -#include "util/rswin.h" -#endif - -#include "ft/ftextralist.h" -#include "ft/ftdatamultiplex.h" -#include "ft/ftfilesearch.h" - -#include "ft/ftfileprovider.h" -#include "ft/ftfilecreator.h" -#include "ft/ftcontroller.h" -#include "ft/fttransfermodule.h" - -#include "util/utest.h" -#include "ftdata_dummy.h" -#include "ftsearch_dummy.h" - -INITTEST() - - -void do_random_server_test(ftDataMultiplex *mplex, ftExtraList *eList, std::list &files); - - -void usage(char *name) -{ - std::cerr << "Usage: " << name << " [-p ] [-d ] [ ... ] "; - std::cerr << std::endl; -} - -int main(int argc, char **argv) -{ - int c; - uint32_t period = 1; - uint32_t dPeriod = 600; /* default 10 minutes */ - - std::list fileList; - - while(-1 != (c = getopt(argc, argv, "d:p:"))) - { - switch (c) - { - case 'p': - period = atoi(optarg); - break; - case 'd': - dPeriod = atoi(optarg); - break; - default: - usage(argv[0]); - break; - } - } - - if (optind >= argc) - { - std::cerr << "Missing Files" << std::endl; - usage(argv[0]); - } - - for(; optind < argc; optind++) - { - std::cerr << "Adding: " << argv[optind] << std::endl; - fileList.push_back(std::string(argv[optind])); - } - - ftExtraList *eList = new ftExtraList(); - eList->start(); - - ftSearch *ftsd = new ftSearchDummy(); - ftFileSearch *ftfs = new ftFileSearch(); - - ftfs-> addSearchMode(ftsd, RS_FILE_HINTS_LOCAL); - ftfs-> addSearchMode(eList, RS_FILE_HINTS_EXTRA); - - ftDataSendPair *ftds1 = new ftDataSendPair(NULL); - ftDataSendPair *ftds2 = new ftDataSendPair(NULL); - - /* setup Actual Test bit */ - ftDataMultiplex *ftmplex1 = new ftDataMultiplex("ownId", ftds2, ftfs); - ftDataMultiplex *ftmplex2 = new ftDataMultiplex("ownId", ftds1, ftfs); - - ftds1->mDataRecv = ftmplex1; - ftds2->mDataRecv = ftmplex2; - - ftmplex1->start(); - ftmplex2->start(); - - /* Setup Search with some valid results */ - /* Request Data */ - - /* now work the thread */ - std::list::iterator it; - TransferRequestFlags flags(0); - for(it = fileList.begin(); it != fileList.end(); it++) - { - eList->hashExtraFile(*it, dPeriod, flags); - } - - if (fileList.size() < 1) - { - std::cerr << "come on, give us some files..."; - std::cerr << std::endl; - return 0; - } - - /* now request files from ftDataMultiplex - * by adding in a ftTransferModule! - */ - std::string filename = *(fileList.begin()); - - /* wait for file to hash */ - FileInfo info; - while(!eList->hashExtraFileDone(filename, info)) - { - std::cerr << "Waiting for file to hash"; - std::cerr << std::endl; - sleep(1); - } - - std::string savename = "/tmp/" + info.fname; - ftFileCreator *creator = new ftFileCreator(savename, info.size, info.hash,false); - ftController *controller = NULL; - - ftTransferModule *transfer = new ftTransferModule(creator, ftmplex1, controller); - - ftmplex1->addTransferModule(transfer, creator); - - std::list peerIds; - peerIds.push_back("ownId2"); - - transfer->setFileSources(peerIds); - transfer->setPeerState("ownId2", PQIPEER_IDLE, 1000); - //transfer->resumeTransfer(); - - /* check file progress */ - while(1) - { - std::cerr << "File Transfer Status"; - std::cerr << std::endl; - - std::cerr << "Transfered: " << creator->getRecvd(); - std::cerr << std::endl; - - transfer->tick(); - sleep(1); - } -} - diff --git a/libretroshare/src/tests/ft/pqitestor.cc b/libretroshare/src/tests/ft/pqitestor.cc deleted file mode 100644 index 2e879ff7b..000000000 --- a/libretroshare/src/tests/ft/pqitestor.cc +++ /dev/null @@ -1,333 +0,0 @@ -/* - * libretroshare/src/ft: pqitestor.cc - * - * File Transfer for RetroShare. - * - * Copyright 2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "ft/pqitestor.h" -#include "pqi/p3linkmgr.h" - -/****** - *#define HUB_DEBUG 1 - *****/ - -P3Hub::P3Hub(uint32_t flags, RsSerialiser *rss) - :mSerialiser(rss), mUseSerialiser(false) -{ - if (rss) - { - mUseSerialiser = true; - } - return; -} - -void P3Hub::addP3Pipe(std::string id, P3Pipe *pqi, p3LinkMgr *mgr) -{ - hubItem item(id, pqi, mgr); - - std::map::iterator it; - for(it = mPeers.begin(); it != mPeers.end(); it++) - { - sockaddr_in remote_addr ; - (it->second).mLinkMgr->connectResult(id, true, 0,remote_addr); - mgr->connectResult(it->first, true, 0,remote_addr); - } - - mPeers[id] = item; - - /* tell all the other peers we are connected */ - -#ifdef HUB_DEBUG - std::cerr << "P3Hub::addPQIPipe()"; - std::cerr << std::endl; -#endif - -} - -RsItem *P3Hub::SerialiserPass(RsItem *inItem) -{ - /* pass through serialiser */ - - RsItem *item = NULL; - - uint32_t pktsize = mSerialiser->size(inItem); - void *ptr = malloc(pktsize); - -#ifdef HUB_DEBUG - std::cerr << "P3Hub::SerialiserPass() Expected Size: " << pktsize; - std::cerr << std::endl; -#endif - - if (!mSerialiser->serialise(inItem, ptr, &pktsize)) - { - -#ifdef HUB_DEBUG - std::cerr << "P3Hub::SerialiserPass() serialise Failed"; - std::cerr << std::endl; -#endif - - } - else - { - -#ifdef HUB_DEBUG - std::cerr << "P3Hub::SerialiserPass() serialise success, size: " << pktsize; - std::cerr << std::endl; -#endif - - item = mSerialiser->deserialise(ptr, &pktsize); - item->PeerId(inItem->PeerId()); - - if (!item) - { -#ifdef HUB_DEBUG - std::cerr << "P3Hub::SerialiserPass() deSerialise Failed"; - std::cerr << std::endl; -#endif - } - } - - delete inItem; - free(ptr); - return item; -} - - -void P3Hub::run() -{ -#ifdef HUB_DEBUG - std::cerr << "P3Hub::run()"; - std::cerr << std::endl; -#endif - - RsItem *item; - std::list > recvdQ; - std::list >::iterator lit; - while(1) - { -#ifdef HUB_DEBUG - std::cerr << "P3Hub::run()"; - std::cerr << std::endl; -#endif - - std::map::iterator it; - for(it = mPeers.begin(); it != mPeers.end(); it++) - { - while (NULL != (item = it->second.mPQI->PopSentItem())) - { -#ifdef HUB_DEBUG - std::cerr << "P3Hub::run() recvd msg from: "; - std::cerr << it->first; - std::cerr << " for " << item->PeerId(); - std::cerr << std::endl; - item->print(std::cerr, 10); - std::cerr << std::endl; -#endif - - if (mUseSerialiser) - { - item = SerialiserPass(item); - } - - /* serialiser might hav munched it. */ - if (item) - { - recvdQ.push_back(make_pair(it->first, item)); - } - } - } - - /* now send out */ - for(lit = recvdQ.begin(); lit != recvdQ.end(); lit++) - { - std::string srcId = lit->first; - std::string destId = (lit->second)->PeerId(); - if (mPeers.end() == (it = mPeers.find(destId))) - { -#ifdef HUB_DEBUG - std::cerr << "Failed to Find destination: " << destId; - std::cerr << std::endl; - std::cerr << "Deleting Packet"; - std::cerr << std::endl; -#endif - - delete (lit->second); - - } - else - { - /* now we have dest, set source Id */ - (lit->second)->PeerId(srcId); -#ifdef HUB_DEBUG - std::cerr << "P3Hub::run() sending msg from: "; - std::cerr << srcId << "to: "; - std::cerr << destId; - std::cerr << std::endl; - (lit->second)->print(std::cerr, 10); - std::cerr << std::endl; -#endif - - (it->second).mPQI->PushRecvdItem(lit->second); - } - } - - recvdQ.clear(); - - - - /* Tick the Connection Managers (normally done by rsserver) - */ - - /* sleep a bit */ -#ifdef WIN32 - Sleep(1000); -#else - sleep(1); -#endif - } -} - - - - - - -PQIPipe::PQIPipe(std::string peerId) - :PQInterface(peerId),pipeMtx("Pipe mutex") -{ - return; -} - -int PQIPipe::SendItem(RsItem *item) -{ - RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ - - mSentItems.push_back(item); - - return 1; -} - -RsItem *PQIPipe::PopSentItem() -{ - RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ - - if (mSentItems.size() == 0) - { - return NULL; - } - - RsItem *item = mSentItems.front(); - mSentItems.pop_front(); - - return item; -} - -int PQIPipe::PushRecvdItem(RsItem *item) -{ - RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ - - mRecvdItems.push_back(item); - - return 1; -} - -RsItem *PQIPipe::GetItem() -{ - RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ - - if (mRecvdItems.size() == 0) - { - return NULL; - } - - RsItem *item = mRecvdItems.front(); - mRecvdItems.pop_front(); - - return item; -} - - - - -/***** P3Pipe here *****/ - - - - -int P3Pipe::SendAllItem(RsItem *item) -{ - RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ - - mSentItems.push_back(item); - - return 1; -} - -RsItem *P3Pipe::PopSentItem() -{ - RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ - - if (mSentItems.size() == 0) - { - return NULL; - } - - RsItem *item = mSentItems.front(); - mSentItems.pop_front(); - - return item; -} - -int P3Pipe::PushRecvdItem(RsItem *item) -{ - RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ - - RsCacheRequest *rcr; - RsCacheItem *rci; - RsFileRequest *rfr; - RsFileData *rfd; - RsRawItem *rri; - - if (NULL != (rcr = dynamic_cast(item))) - { - mRecvdRsCacheRequests.push_back(rcr); - } - else if (NULL != (rci = dynamic_cast(item))) - { - mRecvdRsCacheItems.push_back(rci); - } - else if (NULL != (rfr = dynamic_cast(item))) - { - mRecvdRsFileRequests.push_back(rfr); - } - else if (NULL != (rfd = dynamic_cast(item))) - { - mRecvdRsFileDatas.push_back(rfd); - } - else if (NULL != (rri = dynamic_cast(item))) - { - mRecvdRsRawItems.push_back(rri); - } - - return 1; -} - diff --git a/libretroshare/src/tests/ft/pqitestor.h b/libretroshare/src/tests/ft/pqitestor.h deleted file mode 100644 index 744426e0d..000000000 --- a/libretroshare/src/tests/ft/pqitestor.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * libretroshare/src/ft: pqitestor.h - * - * File Transfer for RetroShare. - * - * Copyright 2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#ifndef PQI_HUB_TEST_H -#define PQI_HUB_TEST_H - -/* - * pqi Test Interface. - */ - -/*** - * Structures for ftserver simulations - * - ****/ - -#include "pqi/pqi.h" -#include "util/rsthreads.h" -#include "serialiser/rsbaseitems.h" - -#include - -class hubItem; -class PQIPipe; -class PQIHub; -class P3Pipe; -class P3Hub; -class p3LinkMgr; - -class hubItem -{ - public: - hubItem() - :mPQI(NULL), mLinkMgr(NULL) { return; } - - hubItem(std::string id, P3Pipe *pqi, p3LinkMgr *mgr) - :mPeerId(id), mPQI(pqi), mLinkMgr(mgr) { return; } - - std::string mPeerId; - P3Pipe *mPQI; - p3LinkMgr *mLinkMgr; -}; - - -class P3Hub: public RsThread -{ - public: - - P3Hub(uint32_t flags, RsSerialiser *rss); -void addP3Pipe(std::string id, P3Pipe *, p3LinkMgr *mgr); - -virtual void run(); - - private: - -RsItem* SerialiserPass(RsItem *inItem); - - std::map mPeers; - RsSerialiser *mSerialiser; - bool mUseSerialiser; -}; - - -class PQIPipe: public PQInterface -{ -public: - PQIPipe(std::string peerId); - -virtual int SendItem(RsItem *); -virtual RsItem *GetItem(); - - // PQIHub Interface. -RsItem *PopSentItem(); -int PushRecvdItem(RsItem *); - - /* - */ - -private: - - RsMutex pipeMtx; - - std::list mSentItems; - std::list mRecvdItems; - -}; - -class P3Pipe: public P3Interface -{ - public: - P3Pipe() : pipeMtx(std::string("Pipe mutex")) {return; } - virtual ~P3Pipe() {return; } - - virtual int tick() { return 1; } - virtual int status() { return 1; } - - /* Overloaded from P3Interface */ - - virtual RsCacheRequest *RequestedSearch() { return GetSpecificItem(mRecvdRsCacheRequests) ; } - virtual RsCacheItem *GetSearchResult() { return GetSpecificItem(mRecvdRsCacheItems) ; } - virtual RsFileRequest *GetFileRequest() { return GetSpecificItem(mRecvdRsFileRequests) ; } - virtual RsFileData *GetFileData() { return GetSpecificItem(mRecvdRsFileDatas) ; } - virtual RsRawItem *GetRsRawItem() { return GetSpecificItem(mRecvdRsRawItems) ; } - virtual RsFileChunkMapRequest* GetFileChunkMapRequest() { return GetSpecificItem(mRecvdRsChunkMapRequests) ; } - virtual RsFileChunkMap* GetFileChunkMap() { return GetSpecificItem(mRecvdRsChunkMaps) ; } - virtual RsFileCRC32MapRequest* GetFileCRC32MapRequest() { return GetSpecificItem(mRecvdRsCRC32MapRequests) ; } - virtual RsFileCRC32Map* GetFileCRC32Map() { return GetSpecificItem(mRecvdRsCRC32Maps) ; } - virtual RsFileSingleChunkCrcRequest* GetFileSingleChunkCrcRequest() { return GetSpecificItem(mRecvdRsSingleChunkCRCRequests) ; } - virtual RsFileSingleChunkCrc* GetFileSingleChunkCrc() { return GetSpecificItem(mRecvdRsSingleChunkCRCs) ; } - - virtual int SearchSpecific(RsCacheRequest *item) { SendAllItem(item); return 1 ; } - virtual int SendSearchResult(RsCacheItem *item) { SendAllItem(item); return 1 ; } - virtual int SendFileRequest(RsFileRequest *item) { SendAllItem(item); return 1 ; } - virtual int SendFileData(RsFileData *item) { SendAllItem(item); return 1 ; } - virtual int SendRsRawItem(RsRawItem *item) { SendAllItem(item); return 1 ; } - virtual int SendFileChunkMapRequest(RsFileChunkMapRequest*item) { SendAllItem(item); return 1 ; } - virtual int SendFileChunkMap(RsFileChunkMap*item) { SendAllItem(item); return 1 ; } - virtual int SendFileCRC32MapRequest(RsFileCRC32MapRequest*item) { SendAllItem(item); return 1 ; } - virtual int SendFileCRC32Map(RsFileCRC32Map*item) { SendAllItem(item); return 1 ; } - virtual int SendFileSingleChunkCrcRequest(RsFileSingleChunkCrcRequest*item) { SendAllItem(item); return 1 ; } - virtual int SendFileSingleChunkCrc(RsFileSingleChunkCrc*item) { SendAllItem(item); return 1 ; } - - /* Lower Interface for PQIHub */ - - RsItem *PopSentItem(); - int PushRecvdItem(RsItem *item); - - private: - template T *GetSpecificItem(std::list& item_list) - { - RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ - - if (item_list.size() == 0) - return NULL; - - T *item = item_list.front(); - item_list.pop_front(); - - return item; - } - - int SendAllItem(RsItem *item); - - RsMutex pipeMtx; - - std::list mSentItems; - - std::list mRecvdRsCacheRequests; - std::list mRecvdRsCacheItems; - std::list mRecvdRsFileRequests; - std::list mRecvdRsFileDatas; - std::list mRecvdRsRawItems; - std::list mRecvdRsChunkMapRequests; - std::list mRecvdRsChunkMaps; - std::list mRecvdRsCRC32MapRequests; - std::list mRecvdRsCRC32Maps; - std::list mRecvdRsSingleChunkCRCRequests; - std::list mRecvdRsSingleChunkCRCs; -}; - - -#endif diff --git a/libretroshare/src/tests/general/memory_management_test.cc b/libretroshare/src/tests/general/memory_management_test.cc deleted file mode 100644 index 2b680a293..000000000 --- a/libretroshare/src/tests/general/memory_management_test.cc +++ /dev/null @@ -1,61 +0,0 @@ -#ifdef LINUX -#include -#endif -#include -#include -#include -#include -#include "util/utest.h" -#include "serialiser/rsserial.h" - -INITTEST(); - -// Make a fake class of size n. -// -template class RsTestItem: public RsItem -{ - public: - unsigned char buff[n] ; - - RsTestItem(uint32_t s) : RsItem(s) {} - virtual void clear() {} - virtual std::ostream& print(std::ostream& o, uint16_t) { return o ; } -}; - -int main(int argc, char **argv) -{ -#ifdef LINUX - feenableexcept(FE_INVALID) ; - feenableexcept(FE_DIVBYZERO) ; -#endif - typedef RsTestItem<17> Test17 ; - typedef RsTestItem<31> Test31 ; - - std::vector v; - - for(int i=0;i<300;++i) - v.push_back(new Test17(0)) ; - for(int i=0;i<700;++i) - v.push_back(new Test31(0)) ; - - RsMemoryManagement::printStatistics() ; - - // Now delete objects randomly. - // - for(int i=0;i<1000;++i) - { - int indx = lrand48()%(int)v.size() ; - - delete v[indx] ; - v[indx] = v.back() ; - v.pop_back() ; - } - - std::cerr << "After memory free: " << std::endl; - - RsMemoryManagement::printStatistics() ; - - FINALREPORT("memory_management_test"); - exit(TESTRESULT()); -} - diff --git a/libretroshare/src/tests/general/netsetup_test.cc b/libretroshare/src/tests/general/netsetup_test.cc deleted file mode 100644 index 7fe740dfd..000000000 --- a/libretroshare/src/tests/general/netsetup_test.cc +++ /dev/null @@ -1,281 +0,0 @@ - -//#include "pqi/p3connmgr.h" -//#include "pqi/p3authmgr.h" -#include "util/utest.h" - -#include "upnp/upnphandler_linux.h" -#include "dht/opendhtmgr.h" -#include "tcponudp/tou.h" - - -INITTEST(); - -int end_test() -{ - FINALREPORT("net_test1"); - - exit(TESTRESULT()); -} - - -void printNetworkStatus(p3ConnectMgr *connMgr) -{ - std::cerr << "network status for : " << connMgr->getOwnId() << std::endl; - std::cerr << "Net Ok:" << connMgr->getNetStatusOk() << std::endl; - std::cerr << "Upnp Ok:" << connMgr->getNetStatusUpnpOk() << std::endl; - std::cerr << "DHT Ok:" << connMgr->getNetStatusDhtOk() << std::endl; - std::cerr << "Ext Ok:" << connMgr->getNetStatusExtOk() << std::endl; - std::cerr << "Udp Ok:" << connMgr->getNetStatusUdpOk() << std::endl; - std::cerr << "Tcp Ok:" << connMgr->getNetStatusTcpOk() << std::endl; - std::cerr << "network status for : " << connMgr->getOwnId() << std::endl; - - peerConnectState state; - if (connMgr->getOwnNetStatus(state)) - { - std::string txt = textPeerConnectState(state); - std::cerr << "State: " << txt << std::endl; - } - else - { - std::cerr << "No Net Status" << std::endl; - } -} - - -void setupTest(int i, p3ConnectMgr *cMgr) -{ - switch(i) - { - case 1: - { - /* Test One */ - - } - break; - - case 10: - { - /* Test One */ - - } - break; - - case 15: - { - /* Test One */ - - } - break; - - case 20: - { - /* Test One */ - - } - break; - - case 13: - { - /* Test One */ - - } - break; - - default: - std::cerr << "setupTest(" << i << ") no test here" << std::endl; - } -} - -void checkResults(int i, p3ConnectMgr *cMgr) -{ - switch(i) - { - /* Test One: Setup - without any support */ - case 1: - { - /* Expect UDP ports to be established by now */ - - //CHECK(isExternalNet(&loopback_addr)==false); - } - break; - - case 10: - { - /* Expect Local IP Address to be known */ - - } - break; - - case 15: - { - - REPORT("Basic Networking Setup"); - } - break; - - /* Test Two: DHT Running */ - case 111: - { - /* Expect UDP ports to be established by now */ - - //CHECK(isExternalNet(&loopback_addr)==false); - } - break; - - case 110: - { - /* Expect Local IP Address to be known */ - - } - break; - - /* Test 3: */ - case 145: - { - - } - break; - - case 100: - { - /* Test One */ - - } - break; - - case 5000: - { - /* End of Tests */ - end_test(); - } - break; - - default: - { - std::cerr << "checkResults(" << i << ") no test here" << std::endl; - printNetworkStatus(cMgr); - - } - } -} - -class TestMonitor: public pqiMonitor -{ - public: -virtual void statusChange(const std::list &plist) -{ - std::cerr << "TestMonitor::statusChange()"; - std::cerr << std::endl; - std::list::const_iterator it; - for(it = plist.begin(); it != plist.end(); it++) - { - std::cerr << "Event!"; - std::cerr << std::endl; - } -} - -}; - -int main(int argc, char **argv) -{ - /* options */ - bool enable_upnp = true; - bool enable_dht = true; - bool enable_forward = true; - - /* handle options */ - - int testtype = 1; - switch(testtype) - { - case 1: - /* udp test */ - enable_upnp = false; - enable_forward = false; - enable_dht = true; - break; - - } - - -#ifndef WINDOWS_SYS -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#else - // Windows Networking Init. - WORD wVerReq = MAKEWORD(2,2); - WSADATA wsaData; - - if (0 != WSAStartup(wVerReq, &wsaData)) - { - std::cerr << "Failed to Startup Windows Networking"; - std::cerr << std::endl; - } - else - { - std::cerr << "Started Windows Networking"; - std::cerr << std::endl; - } - -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - - std::string ownId = "OWNID"; - - /* create a dummy auth mgr */ - p3AuthMgr *authMgr = new p3DummyAuthMgr(); - p3ConnectMgr *connMgr = new p3ConnectMgr(authMgr); - - /* Setup Notify Early - So we can use it. */ - //rsNotify = new p3Notify(); - - pqiNetAssistFirewall *upnpMgr = NULL; - p3DhtMgr *dhtMgr = NULL; - - if (enable_upnp) - { - std::cerr << "Switching on UPnP" << std::endl; - upnpMgr = new upnphandler(); - connMgr->addNetAssistFirewall(1, upnpMgr); - } - - if (enable_dht) - { - p3DhtMgr *dhtMgr = new OpenDHTMgr(ownId, connMgr, "./"); - connMgr->addNetAssistConnect(1, dhtMgr); - - dhtMgr->start(); - std::cerr << "Switching on DHT" << std::endl; - dhtMgr->enable(true); - } - - - /**************************************************************************/ - /* need to Monitor too! */ - - TestMonitor *testmonitor = new TestMonitor(); - connMgr->addMonitor(testmonitor); - - connMgr->checkNetAddress(); - int i; - for(i=0; 1; i++) - { - connMgr->tick(); - - setupTest(i, connMgr); -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // ie UNIX - sleep(1); -#else - Sleep(1000); -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - connMgr->tick(); - - checkResults(i, connMgr); - - tou_tick_stunkeepalive(); - } -} - diff --git a/libretroshare/src/tests/general/pgpkey_test.cc b/libretroshare/src/tests/general/pgpkey_test.cc deleted file mode 100644 index a6b49651f..000000000 --- a/libretroshare/src/tests/general/pgpkey_test.cc +++ /dev/null @@ -1,59 +0,0 @@ -#ifdef LINUX -#include -#endif -#include -#include -#include -#include -#include -#include "util/utest.h" -#include "pgp/pgpkeyutil.h" - -INITTEST(); - -int main(int argc, char **argv) -{ -#ifdef LINUX - feenableexcept(FE_INVALID) ; - feenableexcept(FE_DIVBYZERO) ; -#endif - try - { - if(argc < 2) - { - std::cerr << argv[0] << ": test gpg certificate cleaning method. " << std::endl; - std::cerr << " Usage: " << argv[0] << " certificate.asc" << std::endl; - return 0 ; - } - - FILE *f = fopen(argv[1],"r") ; - - if(f == NULL) - throw std::runtime_error(std::string("Could not open file ") + argv[1]) ; - - std::string cert ; - int c ; - - while((c = getc(f) ) != EOF) - cert += (char)c ; - - std::cerr << "got this certificate: " << std::endl; - std::cerr << cert << std::endl; - - std::cerr << "Calling cert simplification code..." << std::endl; - std::string cleaned_key ; - - PGPKeyManagement::createMinimalKey(cert,cleaned_key) ; - - std::cerr << "Minimal key produced: " << std::endl; - std::cerr << cleaned_key << std::endl; - FINALREPORT("pgpkey_test"); - exit(TESTRESULT()); - } - catch(std::exception& e) - { - std::cerr << "Exception never handled: " << e.what() << std::endl ; - return 1 ; - } -} - diff --git a/libretroshare/src/tests/general/random_test.cc b/libretroshare/src/tests/general/random_test.cc deleted file mode 100644 index 8340b1d67..000000000 --- a/libretroshare/src/tests/general/random_test.cc +++ /dev/null @@ -1,168 +0,0 @@ -#ifdef LINUX -#include -#endif -#include -#include -#include -#include -#include -#include "util/utest.h" -#include "util/rsrandom.h" - -INITTEST(); -typedef double (* Ifctn)( double t); -/* Numerical integration method */ -double Simpson3_8( Ifctn f, double a, double b, int N) -{ - int j; - double l1; - double h = (b-a)/N; - double h1 = h/3.0; - double sum = f(a) + f(b); - - for (j=3*N-1; j>0; j--) { - l1 = (j%3)? 3.0 : 2.0; - sum += l1*f(a+h1*j) ; - } - return h*sum/8.0; -} - -#define A 12 -double Gamma_Spouge( double z ) -{ - int k; - static double cspace[A]; - static double *coefs = NULL; - double accum; - double a = A; - - if (!coefs) { - double k1_factrl = 1.0; - coefs = cspace; - coefs[0] = sqrt(2.0*M_PI); - for(k=1; k 2.0e-8) && (y < x)) y += .4; - if (y>x) y=x; - - return 1.0 - Simpson3_8( &f0, 0, y, std::max(5,(int)(y/h)))/Gamma_Spouge(a); -} - -double chi2Probability( int dof, double distance) -{ - return GammaIncomplete_Q( 0.5*dof, 0.5*distance); -} - -class myThread: public RsThread -{ - public: - myThread() - { - _finished = false ; - } - virtual void run() - { - // test that random numbers are regularly disposed - // - int N = 5000 ; - int B = 8 ; - - std::vector buckets(B,0) ; - - for(int i=0;i significance) - std::cerr << ": passed" << std::endl ; - else - std::cerr << ": failed" << std::endl ; - - _finished = true ; - } - - bool finished() const { return _finished ; } - private: - bool _finished ; -}; - - -int main(int argc, char **argv) -{ -#ifdef LINUX - feenableexcept(FE_INVALID) ; - feenableexcept(FE_DIVBYZERO) ; -#endif - std::cerr << "Generating random 64 chars string (run that again to test that it's changing): " << RSRandom::random_alphaNumericString(64) << std::endl; - std::cerr << "Generating 10 random uint64_t:" << std::endl; - - for(int i=0;i<10;++i) - std::cerr << std::hex << RSRandom::random_u64() << std::endl; - - int nt = 10 ; // number of threads. - std::vector threads(nt,(myThread*)NULL) ; - - for(int i=0;istart() ; - } - - while(true) - { - bool finished = true ; - - for(int i=0;ifinished()) - finished = false ; - - if(finished) - break ; - } - for(int i=0;imGroupId); - randString(SHORT_STR, metaGrp->mOrigGrpId); - randString(SHORT_STR, metaGrp->mAuthorId); - randString(SHORT_STR, metaGrp->mGroupName); - - init_item(metaGrp->signSet); - init_item(metaGrp->keys); - - metaGrp->mPublishTs = rand()%3452; - metaGrp->mGroupFlags = rand()%43; - - metaGrp->mGroupStatus = rand()%313; - metaGrp->mSubscribeFlags = rand()%2251; - metaGrp->mMsgCount = rand()%2421; - metaGrp->mLastPost = rand()%2211; - metaGrp->mPop = rand()%5262; -} - -void init_item(RsGxsMsgMetaData* metaMsg) -{ - - randString(SHORT_STR, metaMsg->mGroupId); - randString(SHORT_STR, metaMsg->mMsgId); - randString(SHORT_STR, metaMsg->mThreadId); - randString(SHORT_STR, metaMsg->mParentId); - randString(SHORT_STR, metaMsg->mAuthorId); - randString(SHORT_STR, metaMsg->mOrigMsgId); - randString(SHORT_STR, metaMsg->mMsgName); - - init_item(metaMsg->signSet); - - metaMsg->mPublishTs = rand()%313; - metaMsg->mMsgFlags = rand()%224; - metaMsg->mMsgStatus = rand()%4242; - metaMsg->mChildTs = rand()%221; -} diff --git a/libretroshare/src/tests/gxs/common/data_support.h b/libretroshare/src/tests/gxs/common/data_support.h deleted file mode 100644 index 930cfbdc1..000000000 --- a/libretroshare/src/tests/gxs/common/data_support.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef DATA_SUPPORT_H -#define DATA_SUPPORT_H - -#include "serialiser/rsnxsitems.h" -#include "gxs/rsgxsdata.h" - -bool operator==(const RsNxsGrp&, const RsNxsGrp&); -bool operator==(const RsNxsMsg&, const RsNxsMsg&); - -void init_item(RsNxsGrp& nxg); -void init_item(RsNxsMsg& nxm); -void init_item(RsGxsGrpMetaData* metaGrp); -void init_item(RsGxsMsgMetaData* metaMsg); - -#endif // DATA_SUPPORT_H diff --git a/libretroshare/src/tests/gxs/common/support.cc b/libretroshare/src/tests/gxs/common/support.cc deleted file mode 100644 index 9003b6b60..000000000 --- a/libretroshare/src/tests/gxs/common/support.cc +++ /dev/null @@ -1,340 +0,0 @@ -/* - * libretroshare/src/serialiser: t_support.h.cc - * - * RetroShare Serialiser tests. - * - * Copyright 2007-2008 by Christopher Evi-Parker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include - -#include "support.h" -#include "serialiser/rstlvbase.h" - -void randString(const uint32_t length, std::string& outStr) -{ - char alpha = 'a'; - char* stringData = NULL; - - stringData = new char[length]; - - for(uint32_t i=0; i != length; i++) - stringData[i] = alpha + (rand() % 26); - - outStr.assign(stringData, length); - delete[] stringData; - - return; -} - -void randString(const uint32_t length, std::wstring& outStr) -{ - wchar_t alpha = L'a'; - wchar_t* stringData = NULL; - - stringData = new wchar_t[length]; - - for(uint32_t i=0; i != length; i++) - stringData[i] = (alpha + (rand() % 26)); - - outStr.assign(stringData, length); - delete[] stringData; - - return; -} - -void init_item(RsTlvSecurityKeySet& ks) -{ - int n = rand()%24; - randString(SHORT_STR, ks.groupId); - for(int i=1; i::const_iterator l_cit = l.keys.begin(), - r_cit = r.keys.begin(); - - for(; l_cit != l.keys.end(); l_cit++, r_cit++){ - if(l_cit->first != r_cit->first) return false; - if(!(l_cit->second == r_cit->second)) return false; - } - - return true; -} - -bool operator==(const RsTlvSecurityKey& sk1, const RsTlvSecurityKey& sk2) -{ - - if(sk1.startTS != sk2.startTS) return false; - if(sk1.endTS != sk2.endTS) return false; - if(sk1.keyFlags != sk2.keyFlags) return false; - if(sk1.keyId != sk2.keyId) return false; - if(!(sk1.keyData == sk1.keyData)) return false; - - return true; -} - -bool operator==(const RsTlvKeySignatureSet& kss1, const RsTlvKeySignatureSet& kss2) -{ - const std::map& set1 = kss1.keySignSet, - &set2 = kss2.keySignSet; - - if(set1.size() != set2.size()) return false; - - std::map::const_iterator it1 = set1.begin(), it2; - - for(; it1 != set1.end(); it1++) - { - SignType st1 = it1->first; - - if( (it2 =set2.find(st1)) == set2.end()) - return false; - - if(!(it1->second == it2->second)) - return false; - - } - - return true; -} - -bool operator==(const RsTlvKeySignature& ks1, const RsTlvKeySignature& ks2) -{ - - if(ks1.keyId != ks2.keyId) return false; - if(!(ks1.signData == ks2.signData)) return false; - - return true; -} - -bool operator==(const RsTlvPeerIdSet& pids1, const RsTlvPeerIdSet& pids2) -{ - std::list::const_iterator it1 = pids1.ids.begin(), - it2 = pids2.ids.begin(); - - - for(; ((it1 != pids1.ids.end()) && (it2 != pids2.ids.end())); it1++, it2++) - { - if(*it1 != *it2) return false; - } - - return true; - -} - - -void init_item(RsTlvImage& im) -{ - std::string imageData; - randString(LARGE_STR, imageData); - im.binData.setBinData(imageData.c_str(), imageData.size()); - im.image_type = RSTLV_IMAGE_TYPE_PNG; - - return; -} - -void init_item(RsTlvKeySignatureSet &kss) -{ - int numSign = rand()%21; - - for(int i=0; i < numSign; i++) - { - RsTlvKeySignature sign; - SignType sType = rand()%2452; - init_item(sign); - kss.keySignSet.insert(std::make_pair(sType, sign)); - } -} - -bool operator==(const RsTlvBinaryData& bd1, const RsTlvBinaryData& bd2) -{ - if(bd1.tlvtype != bd2.tlvtype) return false; - if(bd1.bin_len != bd2.bin_len) return false; - - unsigned char *bin1 = (unsigned char*)(bd1.bin_data), - *bin2 = (unsigned char*)(bd2.bin_data); - - for(uint32_t i=0; i < bd1.bin_len; bin1++, bin2++, i++) - { - if(*bin1 != *bin2) - return false; - } - - return true; -} - - -void init_item(RsTlvSecurityKey& sk) -{ - int randnum = rand()%313131; - - sk.endTS = randnum; - sk.keyFlags = randnum; - sk.startTS = randnum; - randString(SHORT_STR, sk.keyId); - - std::string randomStr; - randString(LARGE_STR, randomStr); - - sk.keyData.setBinData(randomStr.c_str(), randomStr.size()); - - return; -} - -void init_item(RsTlvKeySignature& ks) -{ - randString(SHORT_STR, ks.keyId); - - std::string signData; - randString(LARGE_STR, signData); - - ks.signData.setBinData(signData.c_str(), signData.size()); - - return; -} - - -bool operator==(const RsTlvImage& img1, const RsTlvImage& img2) -{ - if(img1.image_type != img2.image_type) return false; - if(!(img1.binData == img2.binData)) return false; - - return true; - -} - -/** channels, forums and blogs **/ - -void init_item(RsTlvHashSet& hs) -{ - std::string hash; - - for(int i=0; i < 10; i++) - { - randString(SHORT_STR, hash); - hs.ids.push_back(hash); - } - - hs.mType = TLV_TYPE_HASHSET; - return; -} - -void init_item(RsTlvPeerIdSet& ps) -{ - std::string peer; - - for(int i=0; i < 10; i++) - { - randString(SHORT_STR, peer); - ps.ids.push_back(peer); - } - - ps.mType = TLV_TYPE_PEERSET; - return; -} - -bool operator==(const RsTlvHashSet& hs1,const RsTlvHashSet& hs2) -{ - if(hs1.mType != hs2.mType) return false; - - std::list::const_iterator it1 = hs1.ids.begin(), - it2 = hs2.ids.begin(); - - for(; ((it1 != hs1.ids.end()) && (it2 != hs2.ids.end())); it1++, it2++) - { - if(*it1 != *it2) return false; - } - - return true; -} - -void init_item(RsTlvFileItem& fi) -{ - fi.age = rand()%200; - fi.filesize = rand()%34030313; - randString(SHORT_STR, fi.hash); - randString(SHORT_STR, fi.name); - randString(SHORT_STR, fi.path); - fi.piecesize = rand()%232; - fi.pop = rand()%2354; - init_item(fi.hashset); - - return; -} - -void init_item(RsTlvBinaryData& bd){ - bd.TlvClear(); - std::string data; - randString(LARGE_STR, data); - bd.setBinData(data.data(), data.length()); -} - -void init_item(RsTlvFileSet& fSet){ - - randString(LARGE_STR, fSet.comment); - randString(SHORT_STR, fSet.title); - RsTlvFileItem fi1, fi2; - init_item(fi1); - init_item(fi2); - fSet.items.push_back(fi1); - fSet.items.push_back(fi2); - - return; -} - -bool operator==(const RsTlvFileSet& fs1,const RsTlvFileSet& fs2) -{ - if(fs1.comment != fs2.comment) return false; - if(fs1.title != fs2.title) return false; - - std::list::const_iterator it1 = fs1.items.begin(), - it2 = fs2.items.begin(); - - for(; ((it1 != fs1.items.end()) && (it2 != fs2.items.end())); it1++, it2++) - if(!(*it1 == *it2)) return false; - - return true; -} - -bool operator==(const RsTlvFileItem& fi1,const RsTlvFileItem& fi2) -{ - if(fi1.age != fi2.age) return false; - if(fi1.filesize != fi2.filesize) return false; - if(fi1.hash != fi2.hash) return false; - if(!(fi1.hashset == fi2.hashset)) return false; - if(fi1.name != fi2.name) return false; - if(fi1.path != fi2.path) return false; - if(fi1.piecesize != fi2.piecesize) return false; - if(fi1.pop != fi2.pop) return false; - - return true; -} diff --git a/libretroshare/src/tests/gxs/common/support.h b/libretroshare/src/tests/gxs/common/support.h deleted file mode 100644 index bf33716af..000000000 --- a/libretroshare/src/tests/gxs/common/support.h +++ /dev/null @@ -1,226 +0,0 @@ -#ifndef SUPPORT_H_ -#define SUPPORT_H_ - -/* - * libretroshare/src/tests/serialiser: - * - * RetroShare Serialiser tests. - * - * Copyright 2007-2008 by Christopher Evi-Parker, Cyril Soler - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include -#include -#include - -#include "util/utest.h" -#include "serialiser/rsserial.h" -#include "serialiser/rstlvutil.h" -#include "serialiser/rstlvkeys.h" -#include "serialiser/rstlvtypes.h" - - - -/** - * This contains functions that may be useful for testing throughout the - * retroshare's serialiser - * package, if you find a function you keep using everywhere, might be a good idea to add it here - */ - - -#define SHORT_STR 100 -#define LARGE_STR 1000 - -void randString(const uint32_t, std::string&); -void randString(const uint32_t, std::wstring&); - - -/* for testing compound tlv items */ - -void init_item(RsTlvSecurityKey&); -void init_item(RsTlvKeySignature&); -void init_item(RsTlvKeySignatureSet&); -void init_item(RsTlvBinaryData&); -void init_item(RsTlvFileItem&); -void init_item(RsTlvFileSet&); -void init_item(RsTlvHashSet&); -void init_item(RsTlvPeerIdSet&); -void init_item(RsTlvImage&); -void init_item(RsTlvPeerIdSet&); -void init_item(RsTlvSecurityKeySet& ); - -bool operator==(const RsTlvSecurityKey&, const RsTlvSecurityKey& ); -bool operator==(const RsTlvKeySignature&, const RsTlvKeySignature& ); -bool operator==(const RsTlvBinaryData&, const RsTlvBinaryData&); -bool operator==(const RsTlvFileItem&, const RsTlvFileItem&); -bool operator==(const RsTlvFileSet&, const RsTlvFileSet& ); -bool operator==(const RsTlvHashSet&, const RsTlvHashSet&); -bool operator==(const RsTlvImage&, const RsTlvImage& ); -bool operator==(const RsTlvPeerIdSet& , const RsTlvPeerIdSet& ); -bool operator==(const RsTlvSecurityKeySet& , const RsTlvSecurityKeySet& ); -bool operator==(const RsTlvKeySignatureSet& , const RsTlvKeySignatureSet& ); - - - -/*! - * This templated test function which allows you to test - * retroshare serialiser items (except compound tlv items) - * you the function must implement a function - * - * 'RsSerialType* init_item(YourRsItem& rs_item)' - * which returns valid serialiser that - * can serialiser rs_item. You also need to implement an operator - * - * Also need to implement a function - * 'bool operator =(YourRsItem& rs_itemL, YourRsItem& rs_temR)' - * which allows this function to test for equality between both parameters. - * rs_temR is the result of deserialising the left operand (1st parameter). - * not YourRsItem in specifier in about functions should be a derived type from RsItem - * - * @param T the item you want to test - */ - -template int test_RsItem() -{ - /* make a serialisable RsTurtleItem */ - - RsSerialiser srl; - - /* initialise */ - T rsfi ; - RsSerialType *rsfis = init_item(rsfi) ; - - /* attempt to serialise it before we add it to the serialiser */ - - CHECK(0 == srl.size(&rsfi)); - - static const uint32_t MAX_BUFSIZE = 22000 ; - - char *buffer = new char[MAX_BUFSIZE]; - uint32_t sersize = MAX_BUFSIZE; - - CHECK(false == srl.serialise(&rsfi, (void *) buffer, &sersize)); - - /* now add to serialiser */ - - srl.addSerialType(rsfis); - - uint32_t size = srl.size(&rsfi); - bool done = srl.serialise(&rsfi, (void *) buffer, &sersize); - - std::cerr << "test_Item() size: " << size << std::endl; - std::cerr << "test_Item() done: " << done << std::endl; - std::cerr << "test_Item() sersize: " << sersize << std::endl; - - std::cerr << "test_Item() serialised:" << std::endl; - //displayRawPacket(std::cerr, (void *) buffer, sersize); - - CHECK(done == true); - - uint32_t sersize2 = sersize; - RsItem *output = srl.deserialise((void *) buffer, &sersize2); - - CHECK(output != NULL); - CHECK(sersize2 == sersize); - - T *outfi = dynamic_cast(output); - - CHECK(outfi != NULL); - - if (outfi) - CHECK(*outfi == rsfi) ; - - sersize2 = MAX_BUFSIZE; - bool done2 = srl.serialise(outfi, (void *) &(buffer[16*8]), &sersize2); - - CHECK(done2) ; - CHECK(sersize2 == sersize); - -// displayRawPacket(std::cerr, (void *) buffer, 16 * 8 + sersize2); - - delete[] buffer ; - //delete rsfis; - - return 1; -} - -template int test_RsItem(uint16_t servtype) -{ - /* make a serialisable RsTurtleItem */ - - RsSerialiser srl; - - /* initialise */ - T rsfi(servtype) ; - RsSerialType *rsfis = init_item(rsfi) ; // deleted on destruction of srl - - /* attempt to serialise it before we add it to the serialiser */ - - CHECK(0 == srl.size(&rsfi)); - - static const uint32_t MAX_BUFSIZE = 22000 ; - - char *buffer = new char[MAX_BUFSIZE]; - uint32_t sersize = MAX_BUFSIZE; - - CHECK(false == srl.serialise(&rsfi, (void *) buffer, &sersize)); - - /* now add to serialiser */ - - srl.addSerialType(rsfis); - - uint32_t size = srl.size(&rsfi); - bool done = srl.serialise(&rsfi, (void *) buffer, &sersize); - - std::cerr << "test_Item() size: " << size << std::endl; - std::cerr << "test_Item() done: " << done << std::endl; - std::cerr << "test_Item() sersize: " << sersize << std::endl; - - std::cerr << "test_Item() serialised:" << std::endl; - //displayRawPacket(std::cerr, (void *) buffer, sersize); - - CHECK(done == true); - - uint32_t sersize2 = sersize; - RsItem *output = srl.deserialise((void *) buffer, &sersize2); - - CHECK(output != NULL); - CHECK(sersize2 == sersize); - - T *outfi = dynamic_cast(output); - - CHECK(outfi != NULL); - - if (outfi) - CHECK(*outfi == rsfi) ; - - sersize2 = MAX_BUFSIZE; - bool done2 = srl.serialise(outfi, (void *) &(buffer[16*8]), &sersize2); - - CHECK(done2) ; - CHECK(sersize2 == sersize); - -// displayRawPacket(std::cerr, (void *) buffer, 16 * 8 + sersize2); - - delete[] buffer ; - - return 1; -} -#endif /* SUPPORT_H_ */ diff --git a/libretroshare/src/tests/gxs/data_service/nxs_tests.pro b/libretroshare/src/tests/gxs/data_service/nxs_tests.pro deleted file mode 100644 index 8fa292c61..000000000 --- a/libretroshare/src/tests/gxs/data_service/nxs_tests.pro +++ /dev/null @@ -1,203 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2012-05-06T09:19:26 -# -#------------------------------------------------- - - -# -QT += core network - -QT -= gui - -#CONFIG += gen_exchange_target -CONFIG += nxs_net_test -#CONFIG += dstore_target -#CONFIG += gxsdata_target - -CONFIG += bitdht - - - -#gen_exchange_target { - -#TARGET = gen_exchange_test - -#} - -#nxs_net_test { - -TARGET = nxs_net_test - -#} - -#gxsdata_target { - -#TARGET = gxsdata_test -#} - -CONFIG += console -CONFIG -= app_bundle - -TEMPLATE = app - -CONFIG += debug - -debug { -# DEFINES *= DEBUG -# DEFINES *= OPENDHT_DEBUG DHT_DEBUG CONN_DEBUG DEBUG_UDP_SORTER P3DISC_DEBUG DEBUG_UDP_LAYER FT_DEBUG EXTADDRSEARCH_DEBUG -# DEFINES *= CONTROL_DEBUG FT_DEBUG DEBUG_FTCHUNK P3TURTLE_DEBUG -# DEFINES *= P3TURTLE_DEBUG -# DEFINES *= NET_DEBUG -# DEFINES *= DISTRIB_DEBUG -# DEFINES *= P3TURTLE_DEBUG FT_DEBUG DEBUG_FTCHUNK MPLEX_DEBUG -# DEFINES *= STATUS_DEBUG SERV_DEBUG RSSERIAL_DEBUG #CONN_DEBUG - - QMAKE_CXXFLAGS -= -O2 -fomit-frame-pointer - QMAKE_CXXFLAGS *= -g -fno-omit-frame-pointer -} -################################# Linux ########################################## -# Put lib dir in QMAKE_LFLAGS so it appears before -L/usr/lib -linux-* { - #CONFIG += version_detail_bash_script - QMAKE_CXXFLAGS *= -D_FILE_OFFSET_BITS=64 - - system(which gpgme-config >/dev/null 2>&1) { - INCLUDEPATH += $$system(gpgme-config --cflags | sed -e "s/-I//g") - } else { - message(Could not find gpgme-config on your system, assuming gpgme.h is in /usr/include) - } - - PRE_TARGETDEPS *= ../../lib/libretroshare.a - - LIBS += ../../lib/libretroshare.a - LIBS += ../../../../libbitdht/src/lib/libbitdht.a - LIBS += ../../../../openpgpsdk/src/lib/libops.a - LIBS += -lssl -lgpgme -lupnp -lixml -lgnome-keyring -lsqlite3 -lbz2 - LIBS *= -rdynamic -frtti - DEFINES *= HAVE_XSS # for idle time, libx screensaver extensions - DEFINES *= HAS_GNOME_KEYRING -} - -linux-g++ { - OBJECTS_DIR = temp/linux-g++/obj -} - -linux-g++-64 { - OBJECTS_DIR = temp/linux-g++-64/obj -} - -#################################### Windows ##################################### - -win32 { - - DEFINES *= WINDOWS_SYS \ - WIN32 \ - STATICLIB \ - MINGW - # Switch on extra warnings - QMAKE_CFLAGS += -Wextra - QMAKE_CXXFLAGS += -Wextra - - # Switch off optimization for release version - QMAKE_CXXFLAGS_RELEASE -= -O2 - QMAKE_CXXFLAGS_RELEASE += -O0 - QMAKE_CFLAGS_RELEASE -= -O2 - QMAKE_CFLAGS_RELEASE += -O0 - - # Switch on optimization for debug version - #QMAKE_CXXFLAGS_DEBUG += -O2 - #QMAKE_CFLAGS_DEBUG += -O2 - -# PRE_TARGETDEPS += ../../libretroshare/src/lib/libretroshare.a - PRE_TARGETDEPS += ../../../../libretroshare/libretroshare-build-desktop/lib/libretroshare.a - - LIBS += ../../../../libretroshare/libretroshare-build-desktop/lib/libretroshare.a - LIBS += C:\Development\Rs\v0.5-gxs-b1\openpgpsdk\openpgpsdk-build-desktop\lib\libops.a - LIBS += C:\Development\Libraries\sqlite\sqlite-autoconf-3070900\lib\libsqlite3.a - LIBS += -L"../../../../../lib" - LIBS += -lssl -lcrypto -lgpgme -lpthreadGC2d -lminiupnpc -lz -lbz2 -# added after bitdht -# LIBS += -lws2_32 - LIBS += -luuid -lole32 -liphlpapi -lcrypt32 -lgdi32 - LIBS += -lole32 -lwinmm - - # export symbols for the plugins - #LIBS += -Wl,--export-all-symbols,--out-implib,lib/libretroshare-gui.a - - GPG_ERROR_DIR = ../../../../libgpg-error-1.7 - GPGME_DIR = ../../../../gpgme-1.1.8 - GPG_ERROR_DIR = ../../../../lib/libgpg-error-1.7 - GPGME_DIR = ../../../../lib/gpgme-1.1.8 - SSL_DIR = ../../../../../OpenSSL - OPENPGPSDK_DIR = ../../../../openpgpsdk/src - INCLUDEPATH += . $${SSL_DIR}/include $${GPGME_DIR}/src $${GPG_ERROR_DIR}/src \ - $${OPENPGPSDK_DIR} - - SQLITE_DIR = ../../../../../../Libraries/sqlite/sqlite-autoconf-3070900 - INCLUDEPATH += . \ - $${SQLITE_DIR} - - - - -} - -bitdht { - - # Chris version. - #LIBS += ../../libbitdht/libbitdht-build-desktop/lib/libbitdht.a - #PRE_TARGETDEPS *= ../../libbitdht/libbitdht-build-desktop/lib/libbitdht.a -} - -win32 { -# must be added after bitdht - LIBS += -lws2_32 -} - -version_detail_bash_script { - DEFINES += ADD_LIBRETROSHARE_VERSION_INFO - QMAKE_EXTRA_TARGETS += write_version_detail - PRE_TARGETDEPS = write_version_detail - write_version_detail.commands = ./version_detail.sh -} - -install_rs { - INSTALLS += binary_rs - binary_rs.path = $$(PREFIX)/usr/bin - binary_rs.files = ./RetroShare -} - - -#gen_exchange_target { - -# SOURCES += \ -# support.cc \ -# genexchangetester.cpp \ -# genexchangetestservice.cpp \ -# rsdummyservices.cc \ -# rsgenexchange_test.cc - -# HEADERS += support.h \ -# rsdataservice_test.h \ -# rsdummyservices.h \ -# data_support.h -#} - -nxs_net_test { - - SOURCES += \ - support.cc \ - data_support.cc \ - nxstesthub.cc \ - nxstestscenario.cc \ - rsgxsnetservice_test.cc - - HEADERS += support.h \ - nxstestscenario.h \ - nxstesthub.h \ - data_support.h - -} - -INCLUDEPATH += ../../ diff --git a/libretroshare/src/tests/gxs/data_service/rsdataservice_test.cc b/libretroshare/src/tests/gxs/data_service/rsdataservice_test.cc deleted file mode 100644 index 4cb126cce..000000000 --- a/libretroshare/src/tests/gxs/data_service/rsdataservice_test.cc +++ /dev/null @@ -1,337 +0,0 @@ - -#include "support.h" -#include "data_support.h" -#include "rsdataservice_test.h" -#include "gxs/rsgds.h" -#include "gxs/rsdataservice.h" - -#define DATA_BASE_NAME "msg_grp_Store" - -INITTEST(); -RsGeneralDataService* dStore = NULL; - -void setUp(); -void tearDown(); - -int main() -{ - - std::cerr << "RsDataService Tests" << std::endl; - - test_groupStoreAndRetrieve(); REPORT("test_groupStoreAndRetrieve"); - test_messageStoresAndRetrieve(); REPORT("test_messageStoresAndRetrieve"); - - FINALREPORT("RsDataService Tests"); - - return TESTRESULT(); - -} - - - -/*! - * All memory is disposed off, good for looking - * for memory leaks - */ -void test_groupStoreAndRetrieve(){ - - setUp(); - - int nGrp = rand()%32; - std::map grps, grps_copy; - RsNxsGrp* grp; - RsGxsGrpMetaData* grpMeta; - for(int i = 0; i < nGrp; i++){ - std::pair p; - grp = new RsNxsGrp(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); - grpMeta = new RsGxsGrpMetaData(); - p.first = grp; - p.second = grpMeta; - init_item(*grp); - init_item(grpMeta); - grpMeta->mGroupId = grp->grpId; - grps.insert(p); - RsNxsGrp* grp_copy = new RsNxsGrp(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); - *grp_copy = *grp; - RsGxsGrpMetaData* grpMeta_copy = new RsGxsGrpMetaData(); - *grpMeta_copy = *grpMeta; - grps_copy.insert(std::make_pair(grp_copy, grpMeta_copy )); - grpMeta = NULL; - grp = NULL; - } - - dStore->storeGroup(grps); - - //use copy, a grps are deleted in store - grps.clear(); - grps = grps_copy; - - std::map gR; - std::map grpMetaR; - dStore->retrieveNxsGrps(gR, false, false); - dStore->retrieveGxsGrpMetaData(grpMetaR); - - std::map::iterator mit = grps.begin(); - - bool grpMatch = true, grpMetaMatch = true; - - for(; mit != grps.end(); mit++) - { - const std::string grpId = mit->first->grpId; - - // check if it exists - if(gR.find(grpId) == gR.end()) { - grpMatch = false; - break; - } - - RsNxsGrp *l = mit->first, - *r = gR[grpId]; - - // assign transaction number - // to right to as tn is not stored - // in db - r->transactionNumber = l->transactionNumber; - - // then do a comparison - if(!( *l == *r)) { - grpMatch = false; - break; - } - - // now do a comparison of grp meta types - - if(grpMetaR.find(grpId) == grpMetaR.end()) - { - grpMetaMatch = false; - break; - } - - RsGxsGrpMetaData *l_Meta = mit->second, - *r_Meta = grpMetaR[grpId]; - - if(!(*l_Meta == *r_Meta)) - { - grpMetaMatch = false; - break; - } - - /* release resources */ - delete l_Meta; - delete r_Meta; - delete l; - delete r; - - remove(grpId.c_str()); - } - - grpMetaR.clear(); - - CHECK(grpMatch); - tearDown(); -} - -/*! - * Test for both selective and - * bulk msg retrieval - */ -void test_messageStoresAndRetrieve() -{ - setUp(); - - // first create a grpId - std::string grpId0, grpId1; - - randString(SHORT_STR, grpId0); - randString(SHORT_STR, grpId1); - std::vector grpV; // stores grpIds of all msgs stored and retrieved - grpV.push_back(grpId0); - grpV.push_back(grpId1); - - std::map msgs; - std::map msgs_copy; - RsNxsMsg* msg = NULL; - RsGxsMsgMetaData* msgMeta = NULL; - int nMsgs = rand()%120; - GxsMsgReq req; - - std::map VergrpId0, VergrpId1; - std::map VerMetagrpId0, VerMetagrpId1; - - for(int i=0; i p(msg, msgMeta); - int chosen = 0; - if(rand()%50 > 24){ - chosen = 1; - - } - - const std::string& grpId = grpV[chosen]; - - if(chosen) - req[grpId].push_back(msg->msgId); - - msgMeta->mMsgId = msg->msgId; - msgMeta->mGroupId = msg->grpId = grpId; - - RsNxsMsg* msg_copy = new RsNxsMsg(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); - RsGxsMsgMetaData* msgMeta_copy = new RsGxsMsgMetaData(); - - *msg_copy = *msg; - *msgMeta_copy = *msgMeta; - - // store msgs in map to use for verification - std::pair vP(msg->msgId, msg_copy); - std::pair vPmeta(msg->msgId, msgMeta_copy); - - if(!chosen) - { - VergrpId0.insert(vP); - VerMetagrpId0.insert(vPmeta); - } - else - { - VergrpId1.insert(vP); - VerMetagrpId0.insert(vPmeta); - } - - - - msg = NULL; - msgMeta = NULL; - - msgs.insert(p); - msgs_copy.insert(std::make_pair(msg_copy, msgMeta_copy)); - } - - req[grpV[0]] = std::vector(); // assign empty list for other - - dStore->storeMessage(msgs); - msgs.clear(); - msgs = msgs_copy; - - // now retrieve msgs for comparison - // first selective retrieval - - GxsMsgResult msgResult; - GxsMsgMetaResult msgMetaResult; - dStore->retrieveNxsMsgs(req, msgResult, false); - - dStore->retrieveGxsMsgMetaData(req, msgMetaResult); - - // now look at result for grpId 1 - std::vector& result0 = msgResult[grpId0]; - std::vector& result1 = msgResult[grpId1]; - std::vector& resultMeta0 = msgMetaResult[grpId0]; - std::vector& resultMeta1 = msgMetaResult[grpId1]; - - - - bool msgGrpId0_Match = true, msgGrpId1_Match = true; - bool msgMetaGrpId0_Match = true, msgMetaGrpId1_Match = true; - - // MSG test, selective retrieval - for(std::vector::size_type i = 0; i < result0.size(); i++) - { - RsNxsMsg* l = result0[i] ; - - if(VergrpId0.find(l->msgId) == VergrpId0.end()) - { - msgGrpId0_Match = false; - break; - } - - RsNxsMsg* r = VergrpId0[l->msgId]; - r->transactionNumber = l->transactionNumber; - - if(!(*l == *r)) - { - msgGrpId0_Match = false; - break; - } - } - - CHECK(msgGrpId0_Match); - - // META test - for(std::vector::size_type i = 0; i < resultMeta0.size(); i++) - { - RsGxsMsgMetaData* l = resultMeta0[i] ; - - if(VerMetagrpId0.find(l->mMsgId) == VerMetagrpId0.end()) - { - msgMetaGrpId0_Match = false; - break; - } - - RsGxsMsgMetaData* r = VerMetagrpId0[l->mMsgId]; - - if(!(*l == *r)) - { - msgMetaGrpId0_Match = false; - break; - } - } - - CHECK(msgMetaGrpId0_Match); - - // MSG test, bulk retrieval - for(std::vector::size_type i = 0; i < result1.size(); i++) - { - RsNxsMsg* l = result1[i] ; - - if(VergrpId1.find(l->msgId) == VergrpId1.end()) - { - msgGrpId1_Match = false; - break; - } - - RsNxsMsg* r = VergrpId1[l->msgId]; - - r->transactionNumber = l->transactionNumber; - - if(!(*l == *r)) - { - msgGrpId1_Match = false; - break; - } - } - - CHECK(msgGrpId1_Match); - - //dStore->retrieveGxsMsgMetaData(); - std::string msgFile = grpId0 + "-msgs"; - remove(msgFile.c_str()); - msgFile = grpId1 + "-msgs"; - remove(msgFile.c_str()); - tearDown(); -} - - - -void setUp(){ - dStore = new RsDataService(".", DATA_BASE_NAME, RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); -} - -void tearDown(){ - - dStore->resetDataStore(); // reset to clean up store files except db - delete dStore; - dStore = NULL; - int rc = remove(DATA_BASE_NAME); - - if(rc == 0){ - std::cerr << "Successful tear down" << std::endl; - } - else{ - std::cerr << "Tear down failed" << std::endl; - perror("Error: "); - } - -} - diff --git a/libretroshare/src/tests/gxs/data_service/rsdataservice_test.h b/libretroshare/src/tests/gxs/data_service/rsdataservice_test.h deleted file mode 100644 index 89d4a4f5c..000000000 --- a/libretroshare/src/tests/gxs/data_service/rsdataservice_test.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef RSDATASERVICE_TEST_H -#define RSDATASERVICE_TEST_H - -#include "util/rsthreads.h" -#include "serialiser/rsnxsitems.h" -#include "gxs/rsgds.h" - -void test_messageStoresAndRetrieve(); - -void test_groupStoreAndRetrieve(); - -void test_storeAndDeleteGroup(); -void test_storeAndDeleteMessage(); - -void test_searchMsg(); -void test_searchGrp(); - -bool operator ==(const RsGxsGrpMetaData& l, const RsGxsGrpMetaData& r); -bool operator ==(const RsGxsMsgMetaData& l, const RsGxsMsgMetaData& r); - -void test_multiThreaded(); - -class DataReadWrite : RsThread -{ - - - -}; - -void test_cacheSize(); - - -#endif // RSDATASERVICE_TEST_H diff --git a/libretroshare/src/tests/gxs/data_service/rsgxsdata_test.cc b/libretroshare/src/tests/gxs/data_service/rsgxsdata_test.cc deleted file mode 100644 index fa5dc3c6b..000000000 --- a/libretroshare/src/tests/gxs/data_service/rsgxsdata_test.cc +++ /dev/null @@ -1,78 +0,0 @@ - -#include "support.h" -#include "data_support.h" -#include "gxs/rsgxsdata.h" -#include "util/utest.h" - -INITTEST(); - -bool operator ==(const RsGxsGrpMetaData& l, const RsGxsGrpMetaData& r); -bool operator ==(const RsGxsMsgMetaData& l, const RsGxsMsgMetaData& r); - -int main() -{ - - RsGxsGrpMetaData grpMeta1, grpMeta2; - RsGxsMsgMetaData msgMeta1, msgMeta2; - - grpMeta1.clear(); - init_item(&grpMeta1); - - msgMeta1.clear(); - init_item(&msgMeta1); - - uint32_t pktsize = grpMeta1.serial_size(); - char grp_data[pktsize]; - - bool ok = true; - - ok &= grpMeta1.serialise(grp_data, pktsize); - grpMeta2.clear(); - ok &= grpMeta2.deserialise(grp_data, pktsize); - - CHECK(grpMeta1 == grpMeta2); - - pktsize = msgMeta1.serial_size(); - char msg_data[pktsize]; - - ok &= msgMeta1.serialise(msg_data, &pktsize); - msgMeta2.clear(); - ok &= msgMeta2.deserialise(msg_data, &pktsize); - - CHECK(msgMeta1 == msgMeta2); - - FINALREPORT("GxsMeta Data Test"); - - return TESTRESULT(); -} - - -bool operator ==(const RsGxsGrpMetaData& l, const RsGxsGrpMetaData& r) -{ - if(!(l.signSet == r.signSet)) return false; - if(!(l.keys == r.keys)) return false; - if(l.mGroupFlags != r.mGroupFlags) return false; - if(l.mPublishTs != r.mPublishTs) return false; - if(l.mAuthorId != r.mAuthorId) return false; - if(l.mGroupName != r.mGroupName) return false; - if(l.mGroupId != r.mGroupId) return false; - - return true; -} - -bool operator ==(const RsGxsMsgMetaData& l, const RsGxsMsgMetaData& r) -{ - - if(!(l.signSet == r.signSet)) return false; - if(l.mGroupId != r.mGroupId) return false; - if(l.mAuthorId != r.mAuthorId) return false; - if(l.mParentId != r.mParentId) return false; - if(l.mOrigMsgId != r.mOrigMsgId) return false; - if(l.mThreadId != r.mThreadId) return false; - if(l.mMsgId != r.mMsgId) return false; - if(l.mMsgName != r.mMsgName) return false; - if(l.mPublishTs != r.mPublishTs) return false; - if(l.mMsgFlags != r.mMsgFlags) return false; - - return true; -} diff --git a/libretroshare/src/tests/gxs/gen_exchange/genexchange_test.pro b/libretroshare/src/tests/gxs/gen_exchange/genexchange_test.pro deleted file mode 100644 index d95c4bcd4..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/genexchange_test.pro +++ /dev/null @@ -1,180 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2012-05-06T09:19:26 -# -#------------------------------------------------- - - -# -QT += core network - -QT -= gui - -CONFIG += gen_exchange_target - - -CONFIG += bitdht - - - -TARGET = gen_exchange_test - -CONFIG += console -CONFIG -= app_bundle - -TEMPLATE = app - -CONFIG += debug - -debug { -# DEFINES *= DEBUG -# DEFINES *= OPENDHT_DEBUG DHT_DEBUG CONN_DEBUG DEBUG_UDP_SORTER P3DISC_DEBUG DEBUG_UDP_LAYER FT_DEBUG EXTADDRSEARCH_DEBUG -# DEFINES *= CONTROL_DEBUG FT_DEBUG DEBUG_FTCHUNK P3TURTLE_DEBUG -# DEFINES *= P3TURTLE_DEBUG -# DEFINES *= NET_DEBUG -# DEFINES *= DISTRIB_DEBUG -# DEFINES *= P3TURTLE_DEBUG FT_DEBUG DEBUG_FTCHUNK MPLEX_DEBUG -# DEFINES *= STATUS_DEBUG SERV_DEBUG RSSERIAL_DEBUG #CONN_DEBUG - - QMAKE_CXXFLAGS -= -O2 -fomit-frame-pointer - QMAKE_CXXFLAGS *= -g -fno-omit-frame-pointer -} -################################# Linux ########################################## -# Put lib dir in QMAKE_LFLAGS so it appears before -L/usr/lib -linux-* { - #CONFIG += version_detail_bash_script - QMAKE_CXXFLAGS *= -D_FILE_OFFSET_BITS=64 - - system(which gpgme-config >/dev/null 2>&1) { - INCLUDEPATH += $$system(gpgme-config --cflags | sed -e "s/-I//g") - } else { - message(Could not find gpgme-config on your system, assuming gpgme.h is in /usr/include) - } - - PRE_TARGETDEPS *= ../../../lib/libretroshare.a - - LIBS += ../../../lib/libretroshare.a - LIBS += ../../../../../libbitdht/src/lib/libbitdht.a - LIBS += ../../../../../openpgpsdk/src/lib/libops.a - LIBS += -lssl -lgpgme -lupnp -lixml -lgnome-keyring -lbz2 - # We need a explicit path here, to force using the home version of sqlite3 that really encrypts the database. - LIBS += /home/crispy/Development/retroshare/sqlcipher/sqlcipher/.libs/libsqlite3.a - LIBS *= -rdynamic -frtti - DEFINES *= HAVE_XSS # for idle time, libx screensaver extensions - DEFINES *= HAS_GNOME_KEYRING -} - -linux-g++ { - OBJECTS_DIR = temp/linux-g++/obj -} - -linux-g++-64 { - OBJECTS_DIR = temp/linux-g++-64/obj -} - -#################################### Windows ##################################### - -win32 { - - DEFINES *= WINDOWS_SYS \ - WIN32 \ - STATICLIB \ - MINGW - # Switch on extra warnings - QMAKE_CFLAGS += -Wextra - QMAKE_CXXFLAGS += -Wextra - - # Switch off optimization for release version - QMAKE_CXXFLAGS_RELEASE -= -O2 - QMAKE_CXXFLAGS_RELEASE += -O0 - QMAKE_CFLAGS_RELEASE -= -O2 - QMAKE_CFLAGS_RELEASE += -O0 - - # Switch on optimization for debug version - #QMAKE_CXXFLAGS_DEBUG += -O2 - #QMAKE_CFLAGS_DEBUG += -O2 - -# PRE_TARGETDEPS += ../../libretroshare/src/lib/libretroshare.a - PRE_TARGETDEPS += ../../../../../libretroshare/libretroshare-build-desktop/lib/libretroshare.a - - LIBS += ../../../../../libretroshare/libretroshare-build-desktop/lib/libretroshare.a - LIBS += C:\Development\Rs\v0.5-gxs-b1\openpgpsdk\openpgpsdk-build-desktop\lib\libops.a - LIBS += C:\Development\Libraries\sqlite\sqlite-autoconf-3070900\lib\libsqlite3.a - LIBS += -L"../../../../../lib" - LIBS += -lssl -lcrypto -lgpgme -lpthreadGC2d -lminiupnpc -lz -lbz2 -# added after bitdht -# LIBS += -lws2_32 - LIBS += -luuid -lole32 -liphlpapi -lcrypt32 -lgdi32 - LIBS += -lole32 -lwinmm - - # export symbols for the plugins - #LIBS += -Wl,--export-all-symbols,--out-implib,lib/libretroshare-gui.a - - GPG_ERROR_DIR = ../../../../libgpg-error-1.7 - GPGME_DIR = ../../../../gpgme-1.1.8 - GPG_ERROR_DIR = ../../../../lib/libgpg-error-1.7 - GPGME_DIR = ../../../../lib/gpgme-1.1.8 - SSL_DIR = ../../../../../OpenSSL - OPENPGPSDK_DIR = ../../../../openpgpsdk/src - INCLUDEPATH += . $${SSL_DIR}/include $${GPGME_DIR}/src $${GPG_ERROR_DIR}/src \ - $${OPENPGPSDK_DIR} - - SQLITE_DIR = ../../../../../../Libraries/sqlite/sqlite-autoconf-3070900 - INCLUDEPATH += . \ - $${SQLITE_DIR} - - - - -} - -bitdht { - - # Chris version. - #LIBS += ../../libbitdht/libbitdht-build-desktop/lib/libbitdht.a - #PRE_TARGETDEPS *= ../../libbitdht/libbitdht-build-desktop/lib/libbitdht.a -} - -win32 { -# must be added after bitdht - LIBS += -lws2_32 -} - -version_detail_bash_script { - DEFINES += ADD_LIBRETROSHARE_VERSION_INFO - QMAKE_EXTRA_TARGETS += write_version_detail - PRE_TARGETDEPS = write_version_detail - write_version_detail.commands = ./version_detail.sh -} - -install_rs { - INSTALLS += binary_rs - binary_rs.path = $$(PREFIX)/usr/bin - binary_rs.files = ./RetroShare -} - - -gen_exchange_target { - - SOURCES += \ - ../common/support.cc \ - genexchangetester.cpp \ - genexchangetestservice.cpp \ - rsdummyservices.cc \ - gxspublishgrouptest.cc \ - gxspublishmsgtest.cc \ - rsgenexchange_test.cc - - HEADERS += ../common/support.h \ - ../data_service/rsdataservice_test.h \ - gxspublishgrouptest.h \ - gxspublishmsgtest.h \ - rsdummyservices.h \ - ../common/data_support.h \ - ../common/support.h - -} - - -INCLUDEPATH += ../../../ -INCLUDEPATH += ../common diff --git a/libretroshare/src/tests/gxs/gen_exchange/genexchangetester.cpp b/libretroshare/src/tests/gxs/gen_exchange/genexchangetester.cpp deleted file mode 100644 index f46594d9a..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/genexchangetester.cpp +++ /dev/null @@ -1,589 +0,0 @@ -#include "genexchangetester.h" -#include "support.h" -#include "gxs/rsdataservice.h" -#include "retroshare/rsgxsflags.h" - - -GenExchangeTest::GenExchangeTest(GenExchangeTestService* const mTestService, RsGeneralDataService* dataService, int pollingTO) - : mDataService(dataService), mTestService(mTestService), mTokenService(mTestService->getTokenService()), - mPollingTO(pollingTO) -{ -} - -GenExchangeTest::~GenExchangeTest() -{ -} - - -void GenExchangeTest::pollForToken(uint32_t token, const RsTokReqOptions &opts, bool fill) -{ - double timeDelta = 0.2; - rstime_t now = time(NULL); - rstime_t stopw = now + mPollingTO; - - while(now < stopw) - { -#ifndef WINDOWS_SYS - usleep((int) (timeDelta * 1000000)); -#else - Sleep((int) (timeDelta * 1000)); -#endif - - if((RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE == mTokenService->requestStatus(token))) - { - switch(opts.mReqType) - { - case GXS_REQUEST_TYPE_GROUP_DATA: - if(fill) - mTestService->getGroupDataTS(token, mGrpDataIn); - break; - case GXS_REQUEST_TYPE_GROUP_META: - if(fill) - mTestService->getGroupMetaTS(token, mGrpMetaDataIn); - break; - case GXS_REQUEST_TYPE_GROUP_IDS: - if(fill) - mTestService->getGroupListTS(token, mGrpIdsIn); - break; - case GXS_REQUEST_TYPE_MSG_DATA: - if(fill) - mTestService->getMsgDataTS(token, mMsgDataIn); - break; - case GXS_REQUEST_TYPE_MSG_META: - if(fill) - mTestService->getMsgMetaTS(token, mMsgMetaDataIn); - break; - case GXS_REQUEST_TYPE_MSG_IDS: - if(fill) - mTestService->getMsgListTS(token, mMsgIdsIn); - break; - case GXS_REQUEST_TYPE_MSG_RELATED_IDS: - if(fill) - mTestService->getMsgRelatedListTS(token, mMsgRelatedIdsIn); - break; - case GXS_REQUEST_TYPE_MSG_RELATED_DATA: - if(fill) - mTestService->getMsgRelatedDataTS(token, mMsgRelatedDataMapIn); - break; - } - break; - } - else if(RsTokenService::GXS_REQUEST_V2_STATUS_FAILED == mTokenService->requestStatus(token)) - { - mTokenService->cancelRequest(token); - break; - } - now = time(NULL); - } -} - - - -bool GenExchangeTest::pollForMsgAcknowledgement(uint32_t token, - RsGxsGrpMsgIdPair& msgId) -{ - double timeDelta = 0.2; - - rstime_t now = time(NULL); - rstime_t stopw = now + mPollingTO; - - while(now < stopw) - { -#ifndef WINDOWS_SYS - usleep((int) (timeDelta * 1000000)); -#else - Sleep((int) (timeDelta * 1000)); -#endif - - if((RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE == mTokenService->requestStatus(token))) - { - mTestService->acknowledgeTokenMsg(token, msgId); - return true; - } - else if(RsTokenService::GXS_REQUEST_V2_STATUS_FAILED == mTokenService->requestStatus(token)) - { - mTokenService->cancelRequest(token); - return false; - } - now = time(NULL); - } - return false; -} - -GenExchangeTestService* GenExchangeTest::getTestService() -{ - return mTestService; -} - -RsTokenService* GenExchangeTest::getTokenService() -{ - return mTokenService; -} -bool GenExchangeTest::pollForGrpAcknowledgement(uint32_t token, - RsGxsGroupId& grpId) -{ - double timeDelta = 0.2; - rstime_t now = time(NULL); - rstime_t stopw = now + mPollingTO; - while(now < stopw) - { -#ifndef WINDOWS_SYS - usleep((int) (timeDelta * 1000000)); -#else - Sleep((int) (timeDelta * 1000)); -#endif - - if((RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE == mTokenService->requestStatus(token))) - { - mTestService->acknowledgeTokenGrp(token, grpId); - return true; - } - else if(RsTokenService::GXS_REQUEST_V2_STATUS_FAILED == mTokenService->requestStatus(token)) - { - mTokenService->cancelRequest(token); - return false; - } - now = time(NULL); - } - return false; -} - -void GenExchangeTest::setUp() -{ - mDataService->resetDataStore(); - - // would be useful for genexchange services - // to have a protected reset button - mTestService->start(); -} - -void GenExchangeTest::breakDown() -{ - mDataService->resetDataStore(); - mTestService->join(); - clearAllData(); -} - -bool msgDataSort(const RsDummyMsg* m1, const RsDummyMsg* m2) -{ - return m1->meta.mMsgId < m2->meta.mMsgId; -} - -bool GenExchangeTest::compareMsgDataMaps() -{ - DummyMsgMap::iterator mit = mMsgDataOut.begin(); - - bool ok = true; - for(; mit != mMsgDataOut.end(); mit++) - { - const RsGxsGroupId& grpId = mit->first; - std::vector& v1 = mit->second, - &v2 = mMsgDataIn[grpId]; - - if(v1.size() != v2.size()) - return false; - - std::sort(v1.begin(), v1.end(), msgDataSort); - std::sort(v2.begin(), v2.end(), msgDataSort); - - ok &= Comparison, RsDummyMsg*>::comparison(v1, v2); - } - - return ok; -} - - -bool GenExchangeTest::compareMsgIdMaps() -{ - GxsMsgIdResult::const_iterator mit = mMsgIdsOut.begin(); - bool ok = true; - for(; mit != mMsgIdsOut.end(); mit++) - { - const RsGxsGroupId& grpId = mit->first; - const std::vector& v1 = mit->second, - &v2 = mMsgIdsIn[grpId]; - - ok &= Comparison, RsGxsMessageId>::comparison(v1, v2); - } - return ok; -} - - -bool GenExchangeTest::compareMsgMetaMaps() -{ - GxsMsgMetaMap::iterator mit = mMsgMetaDataOut.begin(); - bool ok = true; - for(; mit != mMsgMetaDataOut.end(); mit++) - { - const RsGxsGroupId& grpId = mit->first; - const std::vector& v1 = mit->second, - &v2 = mMsgMetaDataOut[grpId]; - ok &= Comparison, RsMsgMetaData>::comparison(v1, v2); - } - return ok; -} - - -bool GenExchangeTest::compareMsgRelateIdsMap() -{ - return false; -} - - -bool GenExchangeTest::compareMsgRelatedDataMap() -{ - return false; -} - -bool grpDataSort(const RsDummyGrp* g1, const RsDummyGrp* g2) -{ - return g1->meta.mGroupId < g2->meta.mGroupId; -} - -bool GenExchangeTest::compareGrpData() -{ - - std::sort(mGrpDataIn.begin(), mGrpDataIn.end(), grpDataSort); - std::sort(mGrpDataOut.begin(), mGrpDataOut.end(), grpDataSort); - bool ok = Comparison, RsDummyGrp*>::comparison - (mGrpDataIn, mGrpDataOut); - return ok; -} - -bool operator<(const RsGroupMetaData& l, const RsGroupMetaData& r) -{ - return l.mGroupId < r.mGroupId; -} - -bool GenExchangeTest::compareGrpMeta() -{ - - mGrpMetaDataIn.sort(); - mGrpMetaDataOut.sort(); - - bool ok = Comparison, RsGroupMetaData>::comparison - (mGrpMetaDataIn, mGrpMetaDataOut); - return ok; -} - - -bool GenExchangeTest::compareGrpIds() -{ - mGrpIdsIn.sort(); - mGrpIdsOut.sort(); - bool ok = Comparison, RsGxsGroupId>::comparison - (mGrpIdsIn, mGrpIdsOut); - return ok; -} - -void GenExchangeTest::createGrps(uint32_t nGrps, - std::list& groupId) -{ - // create n groups and publish all nGrps and collect id information - for(uint32_t i=0; i < nGrps; i++) - { - RsDummyGrp* grp = new RsDummyGrp(); - init(*grp); - uint32_t token; - mTestService->publishDummyGrp(token, grp); - RsGxsGroupId grpId; - pollForGrpAcknowledgement(token, grpId); - groupId.push_back(grpId); - } -} - -void GenExchangeTest::init(RsMsgMetaData& msgMetaData) const -{ - //randString(SHORT_STR, msgMeta.mAuthorId); - randString(SHORT_STR, msgMetaData.mMsgName); - randString(SHORT_STR, msgMetaData.mServiceString); - randString(SHORT_STR, msgMetaData.mOrigMsgId); - randString(SHORT_STR, msgMetaData.mParentId); - randString(SHORT_STR, msgMetaData.mThreadId); - randString(SHORT_STR, msgMetaData.mGroupId); - - msgMetaData.mChildTs = randNum(); - msgMetaData.mMsgStatus = randNum(); - msgMetaData.mMsgFlags = randNum(); - msgMetaData.mPublishTs = randNum(); -} - -uint32_t GenExchangeTest::randNum() const -{ - return rand()%23562424; -} - -void GenExchangeTest::init(RsGroupMetaData& grpMetaData) const -{ - randString(SHORT_STR, grpMetaData.mGroupId); - //randString(SHORT_STR, grpMetaData.mAuthorId); - randString(SHORT_STR, grpMetaData.mGroupName); - randString(SHORT_STR, grpMetaData.mServiceString); - - - grpMetaData.mGroupFlags = randNum(); - grpMetaData.mLastPost = randNum(); - grpMetaData.mGroupStatus = randNum(); - grpMetaData.mMsgCount = randNum(); - grpMetaData.mPop = randNum(); - grpMetaData.mSignFlags = randNum(); - grpMetaData.mPublishTs = randNum(); - grpMetaData.mSubscribeFlags = GXS_SERV::GROUP_SUBSCRIBE_ADMIN; -} - -void GenExchangeTest::init(RsDummyGrp& grpItem) const -{ - randString(SHORT_STR, grpItem.grpData); - init(grpItem.meta); -} - - -void GenExchangeTest::init(RsDummyMsg& msgItem) const -{ - randString(SHORT_STR, msgItem.msgData); - init(msgItem.meta); -} - -void GenExchangeTest::storeToMsgDataOutMaps(const DummyMsgMap& msgDataOut) -{ - mMsgDataOut.insert(msgDataOut.begin(), msgDataOut.end()); -} - - -void GenExchangeTest::storeToMsgIdsOutMaps(const GxsMsgIdResult& msgIdsOut) -{ - mMsgIdsOut.insert(msgIdsOut.begin(), msgIdsOut.end()); -} - - -void GenExchangeTest::storeToMsgMetaOutMaps(const GxsMsgMetaMap& msgMetaOut) -{ - mMsgMetaDataOut.insert(msgMetaOut.begin(), msgMetaOut.end()); -} - - -void GenExchangeTest::storeToMsgDataInMaps(const DummyMsgMap& msgDataIn) -{ - mMsgDataIn.insert(msgDataIn.begin(), msgDataIn.end()); -} - - -void GenExchangeTest::storeToMsgIdsInMaps(const GxsMsgIdResult& msgIdsIn) -{ - mMsgIdsIn.insert(msgIdsIn.begin(), msgIdsIn.end()); -} - - -void GenExchangeTest::storeToMsgMetaInMaps(const GxsMsgMetaMap& msgMetaIn) -{ - mMsgMetaDataIn.insert(msgMetaIn.begin(), msgMetaIn.end()); -} - - -void GenExchangeTest::storeToGrpIdsOutList( - const std::list& grpIdOut) -{ - mGrpIdsOut.insert(mGrpIdsOut.end(), grpIdOut.begin(), grpIdOut.end()); -} - - -void GenExchangeTest::storeToGrpMetaOutList( - const std::list& grpMetaOut) -{ - mGrpMetaDataOut.insert(mGrpMetaDataOut.end(), grpMetaOut.begin(), grpMetaOut.end()); -} - - -void GenExchangeTest::storeToGrpDataOutList( - const std::vector& grpDataOut) -{ - mGrpDataOut.insert(mGrpDataOut.end(), grpDataOut.begin(), grpDataOut.end()); -} - - -void GenExchangeTest::storeToGrpIdsInList( - const std::list& grpIdIn) -{ - mGrpIdsIn.insert(mGrpIdsIn.end(), grpIdIn.begin(), grpIdIn.end()); -} - - -void GenExchangeTest::storeToGrpMetaInList( - const std::list& grpMetaIn) -{ - mGrpMetaDataIn.insert(mGrpMetaDataIn.end(), grpMetaIn.begin(), grpMetaIn.end()); -} - - -void GenExchangeTest::storeToGrpDataInList( - const std::vector& grpDataIn) -{ - mGrpDataIn.insert(mGrpDataIn.begin(), grpDataIn.begin(), grpDataIn.end()); -} -void GenExchangeTest::clearAllData() -{ - clearMsgDataInMap(); - clearMsgDataOutMap(); - clearMsgIdInMap(); - clearMsgIdOutMap(); - clearMsgMetaInMap(); - clearMsgMetaOutMap(); - clearGrpDataInList(); - clearGrpDataOutList(); - clearGrpMetaInList(); - clearGrpMetaOutList(); - clearGrpIdInList(); - clearGrpIdOutList(); -} -void GenExchangeTest::clearMsgDataInMap() -{ - mMsgDataIn.clear(); -} - - -void GenExchangeTest::clearMsgDataOutMap() -{ - - clearMsgDataMap(mMsgDataOut); -} - -void GenExchangeTest::clearMsgDataMap(DummyMsgMap& msgDataMap) const -{ - DummyMsgMap::iterator it = msgDataMap.begin(); - - for(; it != msgDataMap.end(); it++) - { - deleteResVector(it->second); - } -} - -void GenExchangeTest::clearMsgMetaInMap() -{ - mMsgMetaDataIn.clear(); -} - - -void GenExchangeTest::clearMsgMetaOutMap() -{ - mMsgMetaDataOut.clear(); -} - - -void GenExchangeTest::clearMsgIdInMap() -{ - mMsgIdsIn.clear(); -} - - -void GenExchangeTest::clearMsgIdOutMap() -{ - mMsgIdsOut.clear(); -} - - -void GenExchangeTest::clearMsgRelatedIdInMap() -{ - mMsgRelatedIdsIn.clear(); -} - - -void GenExchangeTest::clearGrpDataInList() -{ - clearGrpDataList(mGrpDataIn); -} - -void GenExchangeTest::clearGrpDataList(std::vector& grpData) const -{ - deleteResVector(grpData); -} - - -void GenExchangeTest::clearGrpDataOutList() -{ - clearGrpDataList(mGrpDataOut); -} - - -void GenExchangeTest::clearGrpMetaInList() -{ - mGrpMetaDataIn.clear(); -} - - -void GenExchangeTest::clearGrpMetaOutList() -{ - mGrpMetaDataOut.clear(); -} - - -void GenExchangeTest::clearGrpIdInList() -{ - mGrpIdsIn.clear(); -} - - -void GenExchangeTest::clearGrpIdOutList() -{ - mGrpIdsOut.clear(); -} - - -bool operator ==(const RsMsgMetaData& lMeta, const RsMsgMetaData& rMeta) -{ - - if(lMeta.mAuthorId != rMeta.mAuthorId) return false; - if(lMeta.mChildTs != rMeta.mChildTs) return false; - if(lMeta.mGroupId != rMeta.mGroupId) return false; - if(lMeta.mMsgFlags != rMeta.mMsgFlags) return false; - if(lMeta.mMsgId != rMeta.mMsgId) return false; - if(lMeta.mMsgName != rMeta.mMsgName) return false; - //if(lMeta.mMsgStatus != rMeta.mMsgStatus) return false; - if(lMeta.mOrigMsgId != rMeta.mOrigMsgId) return false; - if(lMeta.mParentId != rMeta.mParentId) return false; - //if(lMeta.mPublishTs != rMeta.mPublishTs) return false; // don't compare this as internally set in gxs - if(lMeta.mThreadId != rMeta.mThreadId) return false; - if(lMeta.mServiceString != rMeta.mServiceString) return false; - - return true; -} - -bool operator ==(const RsGroupMetaData& lMeta, const RsGroupMetaData& rMeta) -{ - if(lMeta.mAuthorId != rMeta.mAuthorId) return false; - if(lMeta.mGroupFlags != rMeta.mGroupFlags) return false; - if(lMeta.mGroupId != rMeta.mGroupId) return false; - if(lMeta.mGroupName != rMeta.mGroupName) return false; - if(lMeta.mGroupStatus != rMeta.mGroupStatus) return false; - if(lMeta.mLastPost != rMeta.mLastPost) return false; - if(lMeta.mMsgCount != rMeta.mMsgCount) return false; - if(lMeta.mPop != rMeta.mPop) return false; - // if(lMeta.mPublishTs != rMeta.mPublishTs) return false; set in gxs - if(lMeta.mServiceString != rMeta.mServiceString) return false; - if(lMeta.mSignFlags != rMeta.mSignFlags) return false; - // if(lMeta.mSubscribeFlags != rMeta.mSubscribeFlags) return false; - - return true; -} - -bool operator ==(const RsDummyGrp& lGrp, const RsDummyGrp& rGrp) -{ - - if(lGrp.grpData != rGrp.grpData) return false; - if(! (lGrp.meta == rGrp.meta)) return false; - - return true; -} - -bool operator ==(const RsDummyMsg& lMsg, const RsDummyMsg& rMsg) -{ - if(lMsg.msgData != rMsg.msgData) return false; - if(!(lMsg.meta == rMsg.meta)) return false; - - return true; -} - -bool operator ==(const RsGxsGrpItem& lGrp, const RsGxsGrpItem& rGrp) -{ - return false; -} - diff --git a/libretroshare/src/tests/gxs/gen_exchange/genexchangetester.h b/libretroshare/src/tests/gxs/gen_exchange/genexchangetester.h deleted file mode 100644 index 13bb1cf6e..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/genexchangetester.h +++ /dev/null @@ -1,278 +0,0 @@ -#ifndef GENEXCHANGETESTER_H -#define GENEXCHANGETESTER_H - -#include "genexchangetestservice.h" -#include "gxs/rsgds.h" -#include "gxs/rsnxs.h" - -bool operator ==(const RsMsgMetaData& lMeta, const RsMsgMetaData& rMeta); -bool operator ==(const RsDummyMsg& lMsg, const RsDummyMsg& rMsg); -bool operator ==(const RsGxsGrpItem& lMsg, const RsGxsGrpItem& rMsg); - -bool operator ==(const RsGroupMetaData& lMeta, const RsGroupMetaData& rMeta); -bool operator ==(const RsDummyGrp& lMsg, const RsDummyGrp& rMsg); -bool operator ==(const RsGxsMsgItem& lMsg, const RsGxsMsgItem& rMsg); - -/*! - * The idea of GenExchangeTest is to simplify test - * of the RsGenExchange via the RsGxsDummyService - * One can test all publish/request/meta-modify - * capabilities of RsGenExchange - * Simplifications comes from: \n - * - * - ability to store in and out data for comparison (in data are - * usually from requests, out data are from publications, - * but generally what you want to compare) \n - * - convenience function to poll tokens \n - * - also allows filling in-data automatically from polls \n - * - convenience interface for running tests - */ -class GenExchangeTest -{ -public: - - /*! - * Constructs the GenExchangeTest with a tokenService - * @param tokenService This is needed. If not an instance of token service, - * behaviour of GenExchangeTest is undefined - */ - GenExchangeTest(GenExchangeTestService* const mTestService, RsGeneralDataService* dataService, int pollingTO = 5 /* 5 secs default */); - - virtual ~GenExchangeTest(); - - /*! - * This should be called in the main - * routines to execute all tests - * When implementing ensure units test header - * is in same file scope as implementation - * (you chould be using the CHECK functions - * to assert tests has passed) - */ - virtual void runTests() = 0; - -protected: - - /*! - * After each request and publish operation this should - * be called to ensure the operation has completed - * Requests will result in in data maps being filled - * @param - * @param opts - * @param fill if set to true, the received that is - * routed to IN data structures - */ - void pollForToken(uint32_t token, const RsTokReqOptions& opts, bool fill = false); - - /*! - * Allows to poll for token, and receive the message id - * as acknowledgement. This function blocks for as long the - * timeout value set on construction of tester - * @param token - * @param msgId - */ - bool pollForMsgAcknowledgement(uint32_t token, RsGxsGrpMsgIdPair& msgId); - - /*! - * Allows to poll for token, and receive the group id - * as acknowledgement. This function blocks for as long the - * timeout value set on construction of tester - * @param token - * @param msgId - */ - bool pollForGrpAcknowledgement(uint32_t token, RsGxsGroupId& msgId); - - GenExchangeTestService* getTestService(); - RsTokenService* getTokenService(); -// bool testGrpMetaModRequest(); -// bool testMsgMetaModRequest(); - - // convenience functions for clearing IN and OUT data structures - void clearMsgDataInMap(); - void clearMsgDataOutMap(); - void clearMsgMetaInMap(); - void clearMsgMetaOutMap(); - void clearMsgIdInMap(); - void clearMsgIdOutMap(); - void clearMsgRelatedIdInMap(); - void clearGrpDataInList(); - void clearGrpDataOutList(); - void clearGrpMetaInList(); - void clearGrpMetaOutList(); - void clearGrpIdInList(); - void clearGrpIdOutList(); - - /*! - * clears up all internal - * IN and OUT data structure for - * both msgs and groups - * frees resources in relation to allocated data - */ - void clearAllData(); - - template - void deleteResVector(std::vector& v) const - { - typename std::vector::iterator vit = v.begin(); - for(; vit != v.end(); vit++) - delete *vit; - v.clear(); - } - - // using class to enable partial - // function specialisation, bit of a hack in a - // way - template - class Comparison - { - public: - - static bool comparison(const Cont& l, const Cont& r) - { - if(l.size() != r.size()) return false; - - typename Cont::const_iterator vit1 = l.begin(), vit2 = r.begin(); - - while(vit1 != l.end()) - { - const Item& item1 = (*vit1); - const Item& item2 = (*vit2); - if(!(item1 == item2)) return false; - - vit1++; - vit2++; - } - return true; - } - }; - - - template - class Comparison - { - public: - - static bool comparison(const Cont& l, const Cont& r) - { - if(l.size() != r.size()) - return false; - - typename Cont::const_iterator vit1 = l.begin(), vit2 = r.begin(); - - while(vit1 != l.end()) - { - const Item* item1 = (*vit1); - const Item* item2 = (*vit2); - if(!(*item1 == *item2)) - return false; - - vit1++; - vit2++; - } - return true; - } - }; - - // convenience function for comparing IN and OUT data structures - bool compareMsgDataMaps() ; - bool compareMsgIdMaps() ; - bool compareMsgMetaMaps() ; - bool compareMsgRelateIdsMap() ; - bool compareMsgRelatedDataMap() ; - bool compareGrpData() ; - bool compareGrpMeta() ; - bool compareGrpIds() ; - - void storeToMsgDataOutMaps(const DummyMsgMap& msgDataOut); - void storeToMsgIdsOutMaps(const GxsMsgIdResult& msgIdsOut); - void storeToMsgMetaOutMaps(const GxsMsgMetaMap& msgMetaOut); - - void storeToMsgDataInMaps(const DummyMsgMap& msgDataOut); - void storeToMsgIdsInMaps(const GxsMsgIdResult& msgIdsOut); - void storeToMsgMetaInMaps(const GxsMsgMetaMap& msgMetaOut); - - void storeToGrpIdsOutList(const std::list& grpIdOut); - void storeToGrpMetaOutList(const std::list& grpMetaOut); - void storeToGrpDataOutList(const std::vector& grpDataOut); - - void storeToGrpIdsInList(const std::list& grpIdIn); - void storeToGrpMetaInList(const std::list& grpMetaOut); - void storeToGrpDataInList(const std::vector& grpDataOut); - - /*! - * This sets up any resources required to operate a test - */ - void setUp(); - - /*! - * Call at end of test to ensure resources - * used in tests are released - * This can invalidate other test runs if not called - */ - void breakDown(); - - /*! - * initialises item to random data - * @param grpItem item to initialise - */ - void init(RsDummyGrp& grpItem) const; - - /*! - * Initialises meta data to random data - * @param grpMetaData - */ - void init(RsGroupMetaData& grpMetaData) const; - - /*! - * Initialises msg item to random data - * @param msgItem - */ - void init(RsDummyMsg& msgItem) const; - - /*! - * Initialises meta data to random data - * @param msgMetaData - */ - void init(RsMsgMetaData& msgMetaData) const; - - - void clearMsgDataMap(DummyMsgMap& msgDataMap) const; - void clearGrpDataList(std::vector& grpData) const; - - /*! - * Helper function which sets up groups - * data in to be used for publication - * group data - * @param nGrps number of groups to publish - * @param groupId the ids for the created groups - */ - void createGrps(uint32_t nGrps, std::list& groupId); - - /*! - * @return random number - */ - uint32_t randNum() const; - -private: - - std::vector mGrpDataOut, mGrpDataIn; - std::list mGrpMetaDataOut, mGrpMetaDataIn; - std::list mGrpIdsOut, mGrpIdsIn; - - std::map > mMsgDataOut, mMsgDataIn; - GxsMsgMetaMap mMsgMetaDataOut, mMsgMetaDataIn; - GxsMsgIdResult mMsgIdsOut, mMsgIdsIn; - - MsgRelatedIdResult mMsgRelatedIdsOut, mMsgRelatedIdsIn; - GxsMsgRelatedDataMap mMsgRelatedDataMapOut, mMsgRelatedDataMapIn; - - std::vector mRandGrpIds; // ids that exist to help group testing - -private: - - RsGeneralDataService* mDataService; - GenExchangeTestService* mTestService; - RsTokenService* mTokenService; - int mPollingTO; -}; - -#endif // GENEXCHANGETESTER_H diff --git a/libretroshare/src/tests/gxs/gen_exchange/genexchangetestservice.cpp b/libretroshare/src/tests/gxs/gen_exchange/genexchangetestservice.cpp deleted file mode 100644 index dd9ba328a..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/genexchangetestservice.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include "genexchangetestservice.h" - -GenExchangeTestService::GenExchangeTestService(RsGeneralDataService *dataServ, RsNetworkExchangeService * netService, - RsGixs* gixs) - : RsGenExchange(dataServ, netService, new RsDummySerialiser(), RS_SERVICE_TYPE_DUMMY, gixs, 0) -{ - -} - -void GenExchangeTestService::notifyChanges(std::vector &changes) -{ - return; -} - -void GenExchangeTestService::publishDummyGrp(uint32_t &token, RsDummyGrp *grp) -{ - publishGroup(token, grp); -} - -void GenExchangeTestService::updateDummyGrp(uint32_t &token, RsGxsGroupUpdateMeta &updateMeta, RsDummyGrp *group) -{ - updateGroup(token, updateMeta, group); -} - -void GenExchangeTestService::publishDummyMsg(uint32_t &token, RsDummyMsg *msg) -{ - publishMsg(token, msg); -} - -bool GenExchangeTestService::getGroupListTS(const uint32_t &token, std::list &groupIds) -{ - return getGroupList(token, groupIds); -} - -bool GenExchangeTestService::getGroupMetaTS(const uint32_t &token, std::list &groupInfo) -{ - return getGroupMeta(token, groupInfo); -} - -bool GenExchangeTestService::getGroupDataTS(const uint32_t &token, std::vector& grpItem) -{ - return getGroupDataT(token, grpItem); -} - -bool GenExchangeTestService::getMsgDataTS(const uint32_t &token, DummyMsgMap &msgItems) -{ - return getMsgDataT(token, msgItems); -} - -bool GenExchangeTestService::getMsgRelatedDataTS(const uint32_t &token, GxsMsgRelatedDataMap &msgItems) -{ - return getMsgRelatedData(token, msgItems); -} - -bool GenExchangeTestService::getMsgMetaTS(const uint32_t &token, GxsMsgMetaMap &msgInfo) -{ - return getMsgMeta(token, msgInfo); -} - -bool GenExchangeTestService::getMsgListTS(const uint32_t &token, GxsMsgIdResult &msgIds) -{ - return getMsgList(token, msgIds); -} - -bool GenExchangeTestService::getMsgRelatedListTS(const uint32_t &token, MsgRelatedIdResult &msgIds) -{ - return getMsgRelatedList(token, msgIds); -} - -void GenExchangeTestService::setGroupServiceStringTS(uint32_t &token, const RsGxsGroupId &grpId, const std::string &servString) -{ - RsGenExchange::setGroupServiceString(token, grpId, servString); -} - -void GenExchangeTestService::setGroupStatusFlagTS(uint32_t &token, const RsGxsGroupId &grpId, const uint32_t &status, const uint32_t& mask) -{ - RsGenExchange::setGroupStatusFlags(token, grpId, status, mask); -} - -void GenExchangeTestService::setGroupSubscribeFlagTS(uint32_t &token, const RsGxsGroupId &grpId, const uint32_t &status, const uint32_t& mask) -{ - RsGenExchange::setGroupSubscribeFlags(token, grpId, status, mask); -} - -void GenExchangeTestService::setMsgServiceStringTS(uint32_t &token, const RsGxsGrpMsgIdPair &msgId, const std::string &servString) -{ - RsGenExchange::setMsgServiceString(token, msgId, servString); -} - -void GenExchangeTestService::setMsgStatusFlagTS(uint32_t &token, const RsGxsGrpMsgIdPair &msgId, const uint32_t &status, const uint32_t& mask) -{ - RsGenExchange::setMsgStatusFlags(token, msgId, status, mask); -} - -void GenExchangeTestService::service_tick() -{ - -} diff --git a/libretroshare/src/tests/gxs/gen_exchange/genexchangetestservice.h b/libretroshare/src/tests/gxs/gen_exchange/genexchangetestservice.h deleted file mode 100644 index 588808eb9..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/genexchangetestservice.h +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef GENEXCHANGETESTSERVICE_H -#define GENEXCHANGETESTSERVICE_H - -#include "gxs/rsgenexchange.h" -#include "retroshare/rsgxsifacehelper.h" -#include "rsdummyservices.h" - -typedef std::map > DummyMsgMap; - -class GenExchangeTestService : public RsGenExchange -{ -public: - GenExchangeTestService(RsGeneralDataService* dataServ, RsNetworkExchangeService* nxs, RsGixs* gixs); - - void notifyChanges(std::vector& changes); - - void publishDummyGrp(uint32_t& token, RsDummyGrp* grp); - void updateDummyGrp(uint32_t &token, RsGxsGroupUpdateMeta& meta, RsDummyGrp *group); - void publishDummyMsg(uint32_t& token, RsDummyMsg* msg); - - /*! - * Retrieve group list for a given token - * @param token - * @param groupIds - * @return false if token cannot be redeemed, if false you may have tried to redeem when not ready - */ - bool getGroupListTS(const uint32_t &token, std::list &groupIds); - - /*! - * Retrieve msg list for a given token sectioned by group Ids - * @param token token to be redeemed - * @param msgIds a map of grpId -> msgList (vector) - */ - bool getMsgListTS(const uint32_t &token, GxsMsgIdResult &msgIds); - - - /*! - * retrieve group meta data associated to a request token - * @param token - * @param groupInfo - */ - bool getGroupMetaTS(const uint32_t &token, std::list &groupInfo); - - /*! - * retrieves message meta data associated to a request token - * @param token token to be redeemed - * @param msgInfo the meta data to be retrieved for token store here - */ - bool getMsgMetaTS(const uint32_t &token, GxsMsgMetaMap &msgInfo); - - /*! - * retrieves group data associated to a request token - * @param token token to be redeemed for grpitem retrieval - * @param grpItem the items to be retrieved for token are stored here - */ - bool getGroupDataTS(const uint32_t &token, std::vector& grpItem); - - - - /*! - * retrieves message data associated to a request token - * @param token token to be redeemed for message item retrieval - * @param msgItems - */ - bool getMsgDataTS(const uint32_t &token, DummyMsgMap& msgItems); - - /*! - * Retrieve msg related list for a given token sectioned by group Ids - * @param token token to be redeemed - * @param msgIds a map of grpMsgIdPair -> msgList (vector) - */ - bool getMsgRelatedListTS(const uint32_t &token, MsgRelatedIdResult &msgIds); - - /*! - * retrieves msg related data msgItems as a map of msg-grpID pair to vector - * of items - * @param token token to be redeemed - * @param msgItems map of msg items - */ - bool getMsgRelatedDataTS(const uint32_t &token, GxsMsgRelatedDataMap& msgItems); - - - void setGroupSubscribeFlagTS(uint32_t& token, const RsGxsGroupId& grpId, const uint32_t& status, const uint32_t& mask); - - void setGroupStatusFlagTS(uint32_t& token, const RsGxsGroupId& grpId, const uint32_t& status, const uint32_t& mask); - - void setGroupServiceStringTS(uint32_t& token, const RsGxsGroupId& grpId, const std::string& servString); - - void setMsgStatusFlagTS(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, const uint32_t& status, const uint32_t& mask); - - void setMsgServiceStringTS(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, const std::string& servString ); - - void service_tick(); - -}; - -#endif // GENEXCHANGETESTSERVICE_H diff --git a/libretroshare/src/tests/gxs/gen_exchange/gxsmsgrelatedtest.cpp b/libretroshare/src/tests/gxs/gen_exchange/gxsmsgrelatedtest.cpp deleted file mode 100644 index 8b2eacd88..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/gxsmsgrelatedtest.cpp +++ /dev/null @@ -1,18 +0,0 @@ -/* - * gxsmsgrelatedtest.cpp - * - * Created on: 27 Apr 2013 - * Author: crispy - */ - -#include "gxsmsgrelatedtest.h" - -GxsMsgRelatedTest::GxsMsgRelatedTest() { - // TODO Auto-generated constructor stub - -} - -GxsMsgRelatedTest::~GxsMsgRelatedTest() { - // TODO Auto-generated destructor stub -} - diff --git a/libretroshare/src/tests/gxs/gen_exchange/gxsmsgrelatedtest.h b/libretroshare/src/tests/gxs/gen_exchange/gxsmsgrelatedtest.h deleted file mode 100644 index 2277142d9..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/gxsmsgrelatedtest.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * gxsmsgrelatedtest.h - * - * Created on: 27 Apr 2013 - * Author: crispy - */ - -#ifndef GXSMSGRELATEDTEST_H_ -#define GXSMSGRELATEDTEST_H_ - -#include "genexchangetester.h" - -class GxsMsgRelatedTest: public GenExchangeTest { -public: - GxsMsgRelatedTest(); - virtual ~GxsMsgRelatedTest(); - - // request msg related tests - bool testMsgRelatedChildIdRetrieval(); - bool testMsgRelatedChildDataRetrieval(); - bool testMsgRelatedChildDataRetrieval_Multi(); - bool testMsgAllVersions(); -}; - -#endif /* GXSMSGRELATEDTEST_H_ */ diff --git a/libretroshare/src/tests/gxs/gen_exchange/gxspublishgrouptest.cc b/libretroshare/src/tests/gxs/gen_exchange/gxspublishgrouptest.cc deleted file mode 100644 index 2fe0d5fac..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/gxspublishgrouptest.cc +++ /dev/null @@ -1,301 +0,0 @@ -/* - * gxspublishgrouptest.cc - * - * Created on: 27 Apr 2013 - * Author: crispy - */ - -#include "gxspublishgrouptest.h" -#include "util/utest.h" -#include "support.h" - -#define POLLING_TIME_OUT 5 - -GxsPublishGroupTest::GxsPublishGroupTest(GenExchangeTestService* const testService, - RsGeneralDataService* dataService) - : GenExchangeTest(testService, dataService, POLLING_TIME_OUT) -{ - -} - -GxsPublishGroupTest::~GxsPublishGroupTest() -{ -} - -bool GxsPublishGroupTest::testGrpSubmissionRetrieval() -{ - - setUp(); - - GenExchangeTestService* testService = getTestService(); - RsTokenService* tokenService = getTokenService(); - - // create some random grps to allow msg testing - - RsDummyGrp* dgrp1 = new RsDummyGrp(); - RsDummyGrp* dgrp2 = new RsDummyGrp(); - RsDummyGrp* dgrp3 = new RsDummyGrp(); - - RsDummyGrp* dgrp1_copy = new RsDummyGrp(); - RsDummyGrp* dgrp2_copy = new RsDummyGrp(); - RsDummyGrp* dgrp3_copy = new RsDummyGrp(); - - init(*dgrp1); - init(*dgrp2); - init(*dgrp3); - - RsTokReqOptions opts; - opts.mReqType = 45000; - uint32_t token; - RsGxsGroupId grpId; - - std::vector groupsPublished; - - *dgrp1_copy = *dgrp1; - testService->publishDummyGrp(token, dgrp1); - pollForGrpAcknowledgement(token, grpId); - dgrp1_copy->meta.mGroupId = grpId; - groupsPublished.push_back(dgrp1_copy); - - *dgrp2_copy = *dgrp2; - testService->publishDummyGrp(token, dgrp2); - pollForGrpAcknowledgement(token, grpId); - dgrp2_copy->meta.mGroupId = grpId; - groupsPublished.push_back(dgrp2_copy); - - *dgrp3_copy = *dgrp3; - testService->publishDummyGrp(token, dgrp3); - pollForGrpAcknowledgement(token, grpId); - dgrp3_copy->meta.mGroupId = grpId; - groupsPublished.push_back(dgrp3_copy); - - - storeToGrpDataOutList(groupsPublished); - - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - std::list grpIds; - tokenService->requestGroupInfo(token, 0, opts); - - pollForToken(token, opts, true); - - - bool ok = compareGrpData(); - - breakDown(); - - return ok; -} - -bool GxsPublishGroupTest::testSpecificGrpRetrieval() -{ - setUp(); - - GenExchangeTestService* testService = getTestService(); - RsTokenService* tokenService = getTokenService(); - - // create some random grps to allow msg testing - - RsDummyGrp* dgrp1 = new RsDummyGrp(); - RsDummyGrp* dgrp2 = new RsDummyGrp(); - RsDummyGrp* dgrp3 = new RsDummyGrp(); - - RsDummyGrp* dgrp1_copy = new RsDummyGrp(); - RsDummyGrp* dgrp2_copy = new RsDummyGrp(); - - init(*dgrp1); - init(*dgrp2); - init(*dgrp3); - - RsTokReqOptions opts; - opts.mReqType = 45000; - uint32_t token; - RsGxsGroupId grpId; - - std::vector groupsPublished; - std::list grpIds; - - *dgrp1_copy = *dgrp1; - testService->publishDummyGrp(token, dgrp1); - pollForGrpAcknowledgement(token, grpId); - dgrp1_copy->meta.mGroupId = grpId; - groupsPublished.push_back(dgrp1_copy); - grpIds.push_back(grpId); - - *dgrp2_copy = *dgrp2; - testService->publishDummyGrp(token, dgrp2); - pollForGrpAcknowledgement(token, grpId); - dgrp2_copy->meta.mGroupId = grpId; - groupsPublished.push_back(dgrp2_copy); - grpIds.push_back(grpId); - - - testService->publishDummyGrp(token, dgrp3); - pollForGrpAcknowledgement(token, grpId); - - - storeToGrpDataOutList(groupsPublished); - - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - - tokenService->requestGroupInfo(token, 0, opts, grpIds); - - pollForToken(token, opts, true); - - - bool ok = compareGrpData(); - - breakDown(); - - return ok; -} - -bool GxsPublishGroupTest::testGrpIdRetrieval() -{ - setUp(); - - std::list grpIds; - createGrps(5, grpIds); - storeToGrpIdsOutList(grpIds); - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_IDS; - uint32_t token; - - getTokenService()->requestGroupInfo(token, 0, opts); - - pollForToken(token, opts, true); - - bool ok = compareGrpIds(); - - breakDown(); - - return ok; -} - -bool GxsPublishGroupTest::testUpdateGroup() -{ - setUp(); - - GenExchangeTestService* testService = getTestService(); - RsTokenService* tokenService = getTokenService(); - -// create some random grps to allow msg testing - - RsDummyGrp* dgrp1 = new RsDummyGrp(); - RsDummyGrp* dgrp2 = new RsDummyGrp(); - - RsDummyGrp* dgrp2_copy = new RsDummyGrp(); - - init(*dgrp1); - init(*dgrp2); - - RsTokReqOptions opts; - opts.mReqType = 45000; - uint32_t token; - RsGxsGroupId grpId; - - std::vector groupsPublished; - std::list grpIds; - - std::string name = dgrp1->meta.mGroupName; - *dgrp2 = *dgrp1; - testService->publishDummyGrp(token, dgrp1); - bool ok = pollForGrpAcknowledgement(token, grpId); - - grpIds.push_back(grpId); - RsGxsGroupUpdateMeta updateMeta(grpId); - - updateMeta.setMetaUpdate(RsGxsGroupUpdateMeta::NAME, name); - randString(SHORT_STR, dgrp2->grpData); - dgrp2->meta.mGroupId = grpId; - *dgrp2_copy = *dgrp2; - dgrp2->grpData ="ojfosfjsofjsof"; - testService->updateDummyGrp(token, updateMeta, dgrp2); - ok &= pollForGrpAcknowledgement(token, grpId); - - groupsPublished.push_back(dgrp2_copy); - - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - - tokenService->requestGroupInfo(token, 0, opts, grpIds); - - pollForToken(token, opts, true); - - - ok &= compareGrpData(); - - breakDown(); - - return ok; - -} - -bool GxsPublishGroupTest::testGrpMetaRetrieval() -{ - - setUp(); - - GenExchangeTestService* testService = getTestService(); - - // create some random grps to allow msg testing - - RsDummyGrp* dgrp1 = new RsDummyGrp(); - RsDummyGrp* dgrp2 = new RsDummyGrp(); - RsDummyGrp* dgrp3 = new RsDummyGrp(); - - init(*dgrp1); - init(*dgrp2); - init(*dgrp3); - - RsTokReqOptions opts; - opts.mReqType = 45000; - uint32_t token; - RsGxsGroupId grpId; - - RsGroupMetaData meta1(dgrp1->meta); - RsGroupMetaData meta2(dgrp2->meta); - RsGroupMetaData meta3(dgrp3->meta); - - std::list groupsMetaPublished; - - testService->publishDummyGrp(token, dgrp1); - pollForGrpAcknowledgement(token, grpId); - meta1.mGroupId = grpId; - groupsMetaPublished.push_back(meta1); - - testService->publishDummyGrp(token, dgrp2); - pollForGrpAcknowledgement(token, grpId); - meta2.mGroupId = grpId; - groupsMetaPublished.push_back(meta2); - - testService->publishDummyGrp(token, dgrp3); - pollForGrpAcknowledgement(token, grpId); - meta3.mGroupId = grpId; - groupsMetaPublished.push_back(meta3); - - storeToGrpMetaOutList(groupsMetaPublished); - - opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; - std::list grpIds; - - getTokenService()->requestGroupInfo(token, 0, opts); - - pollForToken(token, opts, true); - - bool ok = compareGrpMeta(); - - breakDown(); - - return ok; -} -void GxsPublishGroupTest::runTests() -{ -// CHECK(testGrpSubmissionRetrieval()); -// CHECK(testGrpIdRetrieval()); -// CHECK(testGrpMetaRetrieval()); - // CHECK(testSpecificGrpRetrieval()); - CHECK(testUpdateGroup()); -} - - - - diff --git a/libretroshare/src/tests/gxs/gen_exchange/gxspublishgrouptest.h b/libretroshare/src/tests/gxs/gen_exchange/gxspublishgrouptest.h deleted file mode 100644 index a0f642828..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/gxspublishgrouptest.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * gxspublishgrouptest.h - * - * Created on: 27 Apr 2013 - * Author: crispy - */ - -#ifndef GXSPUBLISHGROUPTEST_H_ -#define GXSPUBLISHGROUPTEST_H_ - -#include "genexchangetester.h" - -class GxsPublishGroupTest : public GenExchangeTest { -public: - - GxsPublishGroupTest(GenExchangeTestService* const testService, - RsGeneralDataService* dataService); - virtual ~GxsPublishGroupTest(); - - void runTests(); - -private: - - // group tests - bool testGrpSubmissionRetrieval(); - bool testSpecificGrpRetrieval(); - bool testGrpIdRetrieval(); - bool testGrpMetaRetrieval(); - bool testUpdateGroup(); - - -private: - -}; - -#endif /* GXSPUBLISHGROUPTEST_H_ */ diff --git a/libretroshare/src/tests/gxs/gen_exchange/gxspublishmsgtest.cc b/libretroshare/src/tests/gxs/gen_exchange/gxspublishmsgtest.cc deleted file mode 100644 index adfa2026c..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/gxspublishmsgtest.cc +++ /dev/null @@ -1,75 +0,0 @@ -/* - * gxspublishmsgtest.cpp - * - * Created on: 27 Apr 2013 - * Author: crispy - */ - -#include "gxspublishmsgtest.h" -#include "util/utest.h" - -#define POLLING_TIME_OUT 5 - -GxsPublishMsgTest::GxsPublishMsgTest(GenExchangeTestService* const testService, - RsGeneralDataService* dataService) - : GenExchangeTest(testService, dataService, POLLING_TIME_OUT) -{ -} - -GxsPublishMsgTest::~GxsPublishMsgTest() -{ -} - -void GxsPublishMsgTest::runTests() -{ - CHECK(testMsgSubmissionRetrieval()); -} - -bool GxsPublishMsgTest::testMsgSubmissionRetrieval() -{ - // start up - setUp(); - std::list grpIds; - createGrps(4, grpIds); - - /********************/ - - RsDummyMsg* msg = new RsDummyMsg(); - init(*msg); - - msg->meta.mGroupId = grpIds.front(); - uint32_t token; - RsDummyMsg* msgOut = new RsDummyMsg(); - *msgOut = *msg; - getTestService()->publishDummyMsg(token, msg); - - - RsGxsGrpMsgIdPair msgId; - pollForMsgAcknowledgement(token, msgId); - msgOut->meta.mMsgId = msgId.second; - - DummyMsgMap msgMap; - std::vector msgV; - msgV.push_back(msgOut); - msgMap[msgOut->meta.mGroupId] = msgV; - storeToMsgDataOutMaps(msgMap); - - - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; - - getTokenService()->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, grpIds); - - // poll again - pollForToken(token, opts, true); - - bool ok = compareMsgDataMaps(); - - // complete - breakDown(); - - return ok; -} - - - diff --git a/libretroshare/src/tests/gxs/gen_exchange/gxspublishmsgtest.h b/libretroshare/src/tests/gxs/gen_exchange/gxspublishmsgtest.h deleted file mode 100644 index bcdfa6aeb..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/gxspublishmsgtest.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * gxspublishmsgtest.h - * - * Created on: 27 Apr 2013 - * Author: crispy - */ - -#ifndef GXSPUBLISHMSGTEST_H_ -#define GXSPUBLISHMSGTEST_H_ - -#include "genexchangetester.h" - -class GxsPublishMsgTest: public GenExchangeTest { -public: - GxsPublishMsgTest(GenExchangeTestService* const testService, - RsGeneralDataService* dataService); - virtual ~GxsPublishMsgTest(); - - void runTests(); - - // message tests - bool testMsgSubmissionRetrieval(); -// bool testMsgIdRetrieval(); -// bool testMsgIdRetrieval_OptParents(); -// bool testMsgIdRetrieval_OptOrigMsgId(); -// bool testMsgIdRetrieval_OptLatest(); -// bool testSpecificMsgMetaRetrieval(); - - -}; - -#endif /* GXSPUBLISHMSGTEST_H_ */ diff --git a/libretroshare/src/tests/gxs/gen_exchange/rsdummyservices.cc b/libretroshare/src/tests/gxs/gen_exchange/rsdummyservices.cc deleted file mode 100644 index 4d8dd4984..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/rsdummyservices.cc +++ /dev/null @@ -1,226 +0,0 @@ - - -#include "rsdummyservices.h" - - -uint32_t RsDummySerialiser::size(RsItem *item) -{ - RsDummyMsg* msg; - RsDummyGrp* grp; - - if( (msg = dynamic_cast(item)) != NULL ) - { - return sizeDummyMsgItem(msg); - }else if( (grp = dynamic_cast(item)) != NULL ) - { - return sizeDummyGrpItem(grp); - }else - { - std::cerr << "RsDummySerialiser::size(RsItem *item) Error with dummy cast!\n"; - } - - return 0; -} - - -bool RsDummySerialiser::serialise(RsItem *item, void *data, uint32_t *size) -{ - RsDummyMsg* msg; - RsDummyGrp* grp; - - if( (msg = dynamic_cast(item)) != NULL ) - { - return serialiseDummyMsgItem(msg, data, size); - }else if( (grp = dynamic_cast(item)) != NULL ) - { - return serialiseDummyGrpItem(grp, data, size); - }else - { - std::cerr << "RsDummySerialiser::size(RsItem *item) Error with dummy cast!\n"; - } - - return false; -} - -RsItem* RsDummySerialiser::deserialise(void *data, uint32_t *size) -{ - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (RS_SERVICE_TYPE_DUMMY != getRsItemService(rstype))) - { - return NULL; /* wrong type */ - } - - switch(getRsItemSubType(rstype)) - { - case RS_PKT_SUBTYPE_DUMMY_MSG: - return deserialiseDummyMsgItem(data, size); - case RS_PKT_SUBTYPE_DUMMY_GRP: - return deserialiseDummyGrpItem(data, size); - default: - return NULL; - } - - return NULL; -} - - -uint32_t RsDummySerialiser::sizeDummyMsgItem(RsDummyMsg *item) -{ - uint32_t s = 8; // header - s += GetTlvStringSize(item->msgData); - - return s; -} - -bool RsDummySerialiser::serialiseDummyMsgItem (RsDummyMsg *item, void *data, uint32_t *size) -{ - uint32_t tlvsize = sizeDummyMsgItem(item); - uint32_t offset = 0; - - if (*size < tlvsize) - return false; /* not enough space */ - - *size = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - - /* skip the header */ - offset += 8; - - /* RsDistribMsg first */ - - ok &= SetTlvString(data, *size, &offset, 1, item->msgData); - - if (offset != tlvsize) - { - ok = false; - std::cerr << "RsDummySerialiser::serialiseDummyMsgItem Size Error! " << std::endl; - } - - return ok; -} - -RsDummyMsg * RsDummySerialiser::deserialiseDummyMsgItem(void *data, uint32_t *size) -{ - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t rssize = getRsItemSize(data); - - uint32_t offset = 0; - - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (RS_SERVICE_TYPE_DUMMY != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_DUMMY_MSG != getRsItemSubType(rstype))) - { - return NULL; /* wrong type */ - } - - if (*size < rssize) /* check size */ - return NULL; /* not enough data */ - - /* set the packet length */ - *size = rssize; - - bool ok = true; - - /* ready to load */ - RsDummyMsg *item = new RsDummyMsg(); - - /* skip the header */ - offset += 8; - - ok &= GetTlvString(data, *size, &offset, 1, item->msgData); - - if (!ok) - { - delete item; - return NULL; - } - - return item; -} - -uint32_t RsDummySerialiser::sizeDummyGrpItem(RsDummyGrp *item) -{ - uint32_t s = 8; - s += GetTlvStringSize(item->grpData); - - return s; -} - -bool RsDummySerialiser::serialiseDummyGrpItem (RsDummyGrp *item, void *data, uint32_t *size) -{ - uint32_t tlvsize = sizeDummyGrpItem(item); - uint32_t offset = 0; - - if (*size < tlvsize) - return false; /* not enough space */ - - *size = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - - /* skip the header */ - offset += 8; - - ok &= SetTlvString(data, *size, &offset, 1, item->grpData); - - if (offset != tlvsize) - { - ok = false; - std::cerr << "RsDummySerialiser::serialiseDummyGrpItem Size Error! " << std::endl; - } - - return ok; -} - -RsDummyGrp * RsDummySerialiser::deserialiseDummyGrpItem(void *data, uint32_t *size) -{ - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t rssize = getRsItemSize(data); - - uint32_t offset = 0; - - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (RS_SERVICE_TYPE_DUMMY != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_DUMMY_GRP != getRsItemSubType(rstype))) - { - return NULL; /* wrong type */ - } - - if (*size < rssize) /* check size */ - return NULL; /* not enough data */ - - /* set the packet length */ - *size = rssize; - - bool ok = true; - - /* ready to load */ - RsDummyGrp *item = new RsDummyGrp(); - - /* skip the header */ - offset += 8; - - ok &= GetTlvString(data, *size, &offset, 1, item->grpData); - - if (!ok) - { - delete item; - return NULL; - } - - return item; -} - - diff --git a/libretroshare/src/tests/gxs/gen_exchange/rsdummyservices.h b/libretroshare/src/tests/gxs/gen_exchange/rsdummyservices.h deleted file mode 100644 index 4720f6be7..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/rsdummyservices.h +++ /dev/null @@ -1,167 +0,0 @@ -#ifndef RSDUMMYSERVICES_H -#define RSDUMMYSERVICES_H - - -// dummy services to make - -#include "gxs/rsnxs.h" -#include "gxs/rsgixs.h" -#include "serialiser/rsgxsitems.h" - -class RsDummyNetService: public RsNetworkExchangeService -{ -public: - - RsDummyNetService(){ return;} - virtual ~RsDummyNetService() { } - - void setSyncAge(uint32_t age){} - - void requestGroupsOfPeer(const std::string& peerId){} - - void requestMessagesOfPeer(const std::string& peerId, const std::string& grpId){} - - void pauseSynchronisation(bool enabled) {} - - int requestMsg(const std::string& msgId, uint8_t hops){ return 0;} - - int requestGrp(const std::list& grpId, uint8_t hops) { return 0;} -}; - - - -const uint16_t RS_SERVICE_TYPE_DUMMY = 0x01; -const uint8_t RS_PKT_SUBTYPE_DUMMY_MSG = 0x02; -const uint8_t RS_PKT_SUBTYPE_DUMMY_GRP = 0x03; - - -class RsDummyMsg : public RsGxsMsgItem -{ -public: - RsDummyMsg() : RsGxsMsgItem(RS_SERVICE_TYPE_DUMMY, RS_PKT_SUBTYPE_DUMMY_MSG) { return; } - virtual ~RsDummyMsg() { return; } - - std::string msgData; - - std::ostream &print(std::ostream &out, uint16_t indent = 0){ return out; } - void clear() { msgData.clear(); } - -}; - -class RsDummyGrp : public RsGxsGrpItem -{ -public: - - RsDummyGrp() : RsGxsGrpItem(RS_SERVICE_TYPE_DUMMY, RS_PKT_SUBTYPE_DUMMY_GRP) { return; } - virtual ~RsDummyGrp() { return; } - - - std::string grpData; - void clear() { grpData.clear(); } - std::ostream &print(std::ostream &out, uint16_t indent = 0){ return out; } -}; - - - -class RsDummySerialiser : public RsSerialType -{ - -public: - - - RsDummySerialiser() - : RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_DUMMY) - { return; } - virtual ~RsDummySerialiser() { return; } - - uint32_t size(RsItem *item); - bool serialise (RsItem *item, void *data, uint32_t *size); - RsItem * deserialise(void *data, uint32_t *size); - - private: - - uint32_t sizeDummyMsgItem(RsDummyMsg *item); - bool serialiseDummyMsgItem (RsDummyMsg *item, void *data, uint32_t *size); - RsDummyMsg * deserialiseDummyMsgItem(void *data, uint32_t *size); - - uint32_t sizeDummyGrpItem(RsDummyGrp *item); - bool serialiseDummyGrpItem (RsDummyGrp *item, void *data, uint32_t *size); - RsDummyGrp * deserialiseDummyGrpItem(void *data, uint32_t *size); - - -}; - -/*! - * Dummy implementation of Gixs service for - * testing - * Limited to creating two ids upon construction which can be used - * for signing data - */ -class RsGixsDummy : public RsGixs -{ - -public: - - /*! - * constructs keys for both incoming and outgoing id (no private keys for incoming id) - * @param - * @param dummyId This is is the only id thats exists in this dummy interface - */ - RsGixsDummy(const RsGxsId& incomingId, const RsGxsId& outgoingId){} - - virtual ~RsGixsDummy(){} - - /*! - * - * @return id used for signing incoming data (should have both public and private components) - */ - const RsGxsId& getOutgoing(){ return mOutgoingId; } - - /*! - * - * @return id used for signing outgoing data(only have public parts) - */ - const RsGxsId& getIncoming(){ return mIncomingId; } - - // Key related interface - used for validating msgs and groups. - /*! - * Use to query a whether given key is available by its key reference - * @param keyref the keyref of key that is being checked for - * @return true if available, false otherwise - */ - bool haveKey(const RsGxsId &id){ return false;} - - /*! - * Use to query whether private key member of the given key reference is available - * @param keyref the KeyRef of the key being checked for - * @return true if private key is held here, false otherwise - */ - bool havePrivateKey(const RsGxsId &id){ return false; } - - // The fetchKey has an optional peerList.. this is people that had the msg with the signature. - // These same people should have the identity - so we ask them first. - /*! - * Use to request a given key reference - * @param keyref the KeyRef of the key being requested - * @return will - */ - bool requestKey(const RsGxsId &id, const std::list &peers){ return false ;} - bool requestPrivateKey(const RsGxsId &id){ return false;} - - - /*! - * Retrieves a key identity - * @param keyref - * @return a pointer to a valid profile if successful, otherwise NULL - * - */ - int getKey(const RsGxsId &id, RsTlvSecurityKey &key){ return false; } - int getPrivateKey(const RsGxsId &id, RsTlvSecurityKey &key){ return false; } // For signing outgoing messages. - -private: - - RsGxsId mIncomingId, mOutgoingId; -}; - - -#endif // RSDUMMYSERVICES_H diff --git a/libretroshare/src/tests/gxs/gen_exchange/rsgenexchange_test.cc b/libretroshare/src/tests/gxs/gen_exchange/rsgenexchange_test.cc deleted file mode 100644 index 8b28bad17..000000000 --- a/libretroshare/src/tests/gxs/gen_exchange/rsgenexchange_test.cc +++ /dev/null @@ -1,47 +0,0 @@ - - -#include "genexchangetester.h" -#include "gxspublishgrouptest.h" -#include "gxspublishmsgtest.h" -#include "util/utest.h" -#include "gxs/rsdataservice.h" -#include "rsdummyservices.h" - - -/*! - * It always hard to say exactly what coverage of a test would - * be ahead of time. Partly because its difficult to create the - * actual conditions of a test or the permutations of different request - * options to a module is extremely large (and there are probably ways to deal with this) - * In so far as the genexchange test is concerned we are primarily interested that it - * retrieves and stores data correctly - * The auxillary (and important) requirement is authentication and ensuring the authentication - * rules are respected. This auxillary requirement is of the "hard" situation to create as - * genexchange depends on an external module (rsidentity) for satisfying a significant sum - * of its authentication. This difficulty is solved with a dummy identity service. - * Which passes all authentications (In this respect authentication) is reserved for "online" - * testing and is relatively straight forward. - * - */ - -INITTEST(); - - -int main() -{ - - RsGeneralDataService* dataStore = new RsDataService("./", "testServiceDb", RS_SERVICE_TYPE_DUMMY, NULL, ""); - - // we want to use default authentication which is NO authentication :) - GenExchangeTestService testService(dataStore, NULL, NULL); - - GxsPublishGroupTest testGrpPublishing(&testService, dataStore); - testGrpPublishing.runTests(); - - //GxsPublishMsgTest testMsgPublishing(&testService, dataStore); - //testMsgPublishing.runTests(); - - FINALREPORT("RsGenExchangeTest"); - - return 0; -} diff --git a/libretroshare/src/tests/gxs/nxs_test/nxs_tests.pro b/libretroshare/src/tests/gxs/nxs_test/nxs_tests.pro deleted file mode 100644 index 8fa292c61..000000000 --- a/libretroshare/src/tests/gxs/nxs_test/nxs_tests.pro +++ /dev/null @@ -1,203 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2012-05-06T09:19:26 -# -#------------------------------------------------- - - -# -QT += core network - -QT -= gui - -#CONFIG += gen_exchange_target -CONFIG += nxs_net_test -#CONFIG += dstore_target -#CONFIG += gxsdata_target - -CONFIG += bitdht - - - -#gen_exchange_target { - -#TARGET = gen_exchange_test - -#} - -#nxs_net_test { - -TARGET = nxs_net_test - -#} - -#gxsdata_target { - -#TARGET = gxsdata_test -#} - -CONFIG += console -CONFIG -= app_bundle - -TEMPLATE = app - -CONFIG += debug - -debug { -# DEFINES *= DEBUG -# DEFINES *= OPENDHT_DEBUG DHT_DEBUG CONN_DEBUG DEBUG_UDP_SORTER P3DISC_DEBUG DEBUG_UDP_LAYER FT_DEBUG EXTADDRSEARCH_DEBUG -# DEFINES *= CONTROL_DEBUG FT_DEBUG DEBUG_FTCHUNK P3TURTLE_DEBUG -# DEFINES *= P3TURTLE_DEBUG -# DEFINES *= NET_DEBUG -# DEFINES *= DISTRIB_DEBUG -# DEFINES *= P3TURTLE_DEBUG FT_DEBUG DEBUG_FTCHUNK MPLEX_DEBUG -# DEFINES *= STATUS_DEBUG SERV_DEBUG RSSERIAL_DEBUG #CONN_DEBUG - - QMAKE_CXXFLAGS -= -O2 -fomit-frame-pointer - QMAKE_CXXFLAGS *= -g -fno-omit-frame-pointer -} -################################# Linux ########################################## -# Put lib dir in QMAKE_LFLAGS so it appears before -L/usr/lib -linux-* { - #CONFIG += version_detail_bash_script - QMAKE_CXXFLAGS *= -D_FILE_OFFSET_BITS=64 - - system(which gpgme-config >/dev/null 2>&1) { - INCLUDEPATH += $$system(gpgme-config --cflags | sed -e "s/-I//g") - } else { - message(Could not find gpgme-config on your system, assuming gpgme.h is in /usr/include) - } - - PRE_TARGETDEPS *= ../../lib/libretroshare.a - - LIBS += ../../lib/libretroshare.a - LIBS += ../../../../libbitdht/src/lib/libbitdht.a - LIBS += ../../../../openpgpsdk/src/lib/libops.a - LIBS += -lssl -lgpgme -lupnp -lixml -lgnome-keyring -lsqlite3 -lbz2 - LIBS *= -rdynamic -frtti - DEFINES *= HAVE_XSS # for idle time, libx screensaver extensions - DEFINES *= HAS_GNOME_KEYRING -} - -linux-g++ { - OBJECTS_DIR = temp/linux-g++/obj -} - -linux-g++-64 { - OBJECTS_DIR = temp/linux-g++-64/obj -} - -#################################### Windows ##################################### - -win32 { - - DEFINES *= WINDOWS_SYS \ - WIN32 \ - STATICLIB \ - MINGW - # Switch on extra warnings - QMAKE_CFLAGS += -Wextra - QMAKE_CXXFLAGS += -Wextra - - # Switch off optimization for release version - QMAKE_CXXFLAGS_RELEASE -= -O2 - QMAKE_CXXFLAGS_RELEASE += -O0 - QMAKE_CFLAGS_RELEASE -= -O2 - QMAKE_CFLAGS_RELEASE += -O0 - - # Switch on optimization for debug version - #QMAKE_CXXFLAGS_DEBUG += -O2 - #QMAKE_CFLAGS_DEBUG += -O2 - -# PRE_TARGETDEPS += ../../libretroshare/src/lib/libretroshare.a - PRE_TARGETDEPS += ../../../../libretroshare/libretroshare-build-desktop/lib/libretroshare.a - - LIBS += ../../../../libretroshare/libretroshare-build-desktop/lib/libretroshare.a - LIBS += C:\Development\Rs\v0.5-gxs-b1\openpgpsdk\openpgpsdk-build-desktop\lib\libops.a - LIBS += C:\Development\Libraries\sqlite\sqlite-autoconf-3070900\lib\libsqlite3.a - LIBS += -L"../../../../../lib" - LIBS += -lssl -lcrypto -lgpgme -lpthreadGC2d -lminiupnpc -lz -lbz2 -# added after bitdht -# LIBS += -lws2_32 - LIBS += -luuid -lole32 -liphlpapi -lcrypt32 -lgdi32 - LIBS += -lole32 -lwinmm - - # export symbols for the plugins - #LIBS += -Wl,--export-all-symbols,--out-implib,lib/libretroshare-gui.a - - GPG_ERROR_DIR = ../../../../libgpg-error-1.7 - GPGME_DIR = ../../../../gpgme-1.1.8 - GPG_ERROR_DIR = ../../../../lib/libgpg-error-1.7 - GPGME_DIR = ../../../../lib/gpgme-1.1.8 - SSL_DIR = ../../../../../OpenSSL - OPENPGPSDK_DIR = ../../../../openpgpsdk/src - INCLUDEPATH += . $${SSL_DIR}/include $${GPGME_DIR}/src $${GPG_ERROR_DIR}/src \ - $${OPENPGPSDK_DIR} - - SQLITE_DIR = ../../../../../../Libraries/sqlite/sqlite-autoconf-3070900 - INCLUDEPATH += . \ - $${SQLITE_DIR} - - - - -} - -bitdht { - - # Chris version. - #LIBS += ../../libbitdht/libbitdht-build-desktop/lib/libbitdht.a - #PRE_TARGETDEPS *= ../../libbitdht/libbitdht-build-desktop/lib/libbitdht.a -} - -win32 { -# must be added after bitdht - LIBS += -lws2_32 -} - -version_detail_bash_script { - DEFINES += ADD_LIBRETROSHARE_VERSION_INFO - QMAKE_EXTRA_TARGETS += write_version_detail - PRE_TARGETDEPS = write_version_detail - write_version_detail.commands = ./version_detail.sh -} - -install_rs { - INSTALLS += binary_rs - binary_rs.path = $$(PREFIX)/usr/bin - binary_rs.files = ./RetroShare -} - - -#gen_exchange_target { - -# SOURCES += \ -# support.cc \ -# genexchangetester.cpp \ -# genexchangetestservice.cpp \ -# rsdummyservices.cc \ -# rsgenexchange_test.cc - -# HEADERS += support.h \ -# rsdataservice_test.h \ -# rsdummyservices.h \ -# data_support.h -#} - -nxs_net_test { - - SOURCES += \ - support.cc \ - data_support.cc \ - nxstesthub.cc \ - nxstestscenario.cc \ - rsgxsnetservice_test.cc - - HEADERS += support.h \ - nxstestscenario.h \ - nxstesthub.h \ - data_support.h - -} - -INCLUDEPATH += ../../ diff --git a/libretroshare/src/tests/gxs/nxs_test/nxstesthub.cc b/libretroshare/src/tests/gxs/nxs_test/nxstesthub.cc deleted file mode 100644 index e0c505464..000000000 --- a/libretroshare/src/tests/gxs/nxs_test/nxstesthub.cc +++ /dev/null @@ -1,129 +0,0 @@ -#include "nxstesthub.h" - -NxsTestHub::NxsTestHub(NxsTestScenario * nts, std::set &peers) : mTestScenario(nts) -{ - - std::set::iterator sit = peers.begin(); - - for(; sit != peers.end(); sit++) - { - std::set msgPeers = peers; - - // add peers all peers except one iterator currently points to - msgPeers.erase(*sit); - NxsNetDummyMgr* dummyMgr = new NxsNetDummyMgr(*sit, msgPeers); - RsGeneralDataService* ds = mTestScenario->getDataService(*sit); - NxsMessageTestObserver* obs = new NxsMessageTestObserver(ds); - - RsGxsNetService* netService = - new RsGxsNetService(mTestScenario->getServiceType(), - ds, dummyMgr, obs); - - - mNetServices.insert(std::make_pair(*sit, netService)); - mObservers.insert(std::make_pair(*sit, obs)); - } - - sit = peers.begin(); - - // launch net services - for(; sit != peers.end(); sit++) - { - RsGxsNetService* n = mNetServices[*sit]; - createThread(*n); - mServices.insert(std::make_pair(*sit, n)); - } -} - -NxsTestHub::~NxsTestHub() -{ - std::map::iterator mit = mNetServices.begin(); - - for(; mit != mNetServices.end(); mit++) - delete mit->second; -} - - -void NxsTestHub::run() -{ - double timeDelta = .2; - - while(isRunning()){ - - // make thread sleep for a bit - #ifndef WINDOWS_SYS - usleep((int) (timeDelta * 1000000)); - #else - Sleep((int) (timeDelta * 1000)); - #endif - - - std::map::iterator mit = mServices.begin(); - - for(; mit != mServices.end(); mit++) - { - p3Service* s = mit->second; - s->tick(); - } - - mit = mServices.begin(); - - // collect msgs to send to peers from peers - for(; mit != mServices.end(); mit++) - { - const std::string& peer = mit->first; - p3Service* s = mit->second; - - // first store all the sends from all services - RsItem* item = NULL; - - while((item = s->send()) != NULL){ - - const std::string peerToReceive = item->PeerId(); - - // set the peer this item comes from - item->PeerId(peer); - mPeerQueues[peerToReceive].push_back(item); - } - - - } - - // now route items to peers - std::map >::iterator mit_queue = mPeerQueues.begin(); - - for(; mit_queue != mPeerQueues.end(); mit_queue++) - { - std::vector& queueV = mit_queue->second; - std::vector::iterator vit = queueV.begin(); - const std::string peerToReceive = mit_queue->first; - for(; vit != queueV.end(); vit++) - { - - RsItem* item = *vit; - p3Service* service = mServices[peerToReceive]; - - service->receive(dynamic_cast(item)); - } - queueV.clear(); - } - } -} - -void NxsTestHub::cleanUp() -{ - std::map::iterator mit = mNetServices.begin(); - for(; mit != mNetServices.end(); mit++) - { - RsGxsNetService* n = mit->second; - n->join(); - } - - // also shut down this net service peers if this goes down - mTestScenario->cleanUp(); -} - -bool NxsTestHub::testsPassed() -{ - return false; -} diff --git a/libretroshare/src/tests/gxs/nxs_test/nxstesthub.h b/libretroshare/src/tests/gxs/nxs_test/nxstesthub.h deleted file mode 100644 index 15f10e0b4..000000000 --- a/libretroshare/src/tests/gxs/nxs_test/nxstesthub.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef NXSTESTHUB_H -#define NXSTESTHUB_H - -#include "util/rsthreads.h" -#include "gxs/rsgxsnetservice.h" -#include "nxstestscenario.h" - -// it would probably be useful if the test scenario -// provided the net dummy managers -// hence one could envision synchronising between an arbitrary number -// of peers - - -class NxsNetDummyMgr : public RsNxsNetMgr -{ - -public: - - NxsNetDummyMgr(std::string ownId, std::set peers) : mOwnId(ownId), mPeers(peers) { - - } - - std::string getOwnId() { return mOwnId; } - void getOnlineList(std::set& ssl_peers) { ssl_peers = mPeers; } - -private: - - std::string mOwnId; - std::set mPeers; - -}; - - -/*! - * Testing of nxs services occurs through use of two services - * When a service sends this class can interrogate the send and the receives of - * - * NxsScenario stores the type of synchronisation to be tested - * Operation: - * First NxsTestHub needs to be instantiated with a test scenario - * * The scenario contains two databases to be used on the communicating pair of RsGxsNetService instances (net instances) - * The Test hub has a ticker service for the p3Services which allows the netservices to search what groups and messages they have - * and synchronise according to their subscriptions. The default is to subscribe to all groups held by other peer - * The threads for both net instances are started which begins their processing of transactions - */ -class NxsTestHub : public RsThread -{ -public: - - - /*! - * This construct the test hub - * for a give scenario in mind - */ - NxsTestHub(NxsTestScenario*, std::set& peers); - - - /*! - * - */ - virtual ~NxsTestHub(); - - /*! - * To be called only after this thread has - * been shutdown - */ - bool testsPassed(); - - /*! - * This simulates the p3Service ticker and calls both gxs net services tick methods - * Also enables transport of messages between both services - */ - void run(); - - - void cleanUp(); -private: - - std::map mServices; - std::map mNetServices; - std::map mObservers; - - std::map > mPeerQueues; - - NxsTestScenario *mTestScenario; - -}; - -#endif // NXSTESTHUB_H diff --git a/libretroshare/src/tests/gxs/nxs_test/nxstestscenario.cc b/libretroshare/src/tests/gxs/nxs_test/nxstestscenario.cc deleted file mode 100644 index c4cf5c666..000000000 --- a/libretroshare/src/tests/gxs/nxs_test/nxstestscenario.cc +++ /dev/null @@ -1,177 +0,0 @@ -/* - * nxstestscenario.cc - * - * Created on: 10 Jul 2012 - * Author: crispy - */ - -#include "nxstestscenario.h" -#include "gxs/rsdataservice.h" -#include "retroshare/rsgxsflags.h" -#include "data_support.h" -#include - -NxsMessageTest::NxsMessageTest(uint16_t servtype) -: mServType(servtype), mMsgTestMtx("mMsgTestMtx") -{ - -} - -std::string NxsMessageTest::getTestName() -{ - return std::string("Nxs Message Test!"); -} - -NxsMessageTest::~NxsMessageTest(){ - - std::map::iterator mit = mPeerStoreMap.begin(); - - for(; mit != mPeerStoreMap.end(); mit++) - { - delete mit->second; - } - - std::set::iterator sit = mStoreNames.begin(); - - // remove db file - for(; sit != mStoreNames.end(); sit++) - { - const std::string& name = *sit; - remove(name.c_str()); - } -} -RsGeneralDataService* NxsMessageTest::getDataService(const std::string& peer) -{ - if(mPeerStoreMap.find(peer) != mPeerStoreMap.end()) return NULL; - - RsDataService* dStore = new RsDataService("./", peer, mServType); - mStoreNames.insert(peer); - mPeerStoreMap.insert(std::make_pair(peer, dStore)); - populateStore(dStore); - - return dStore; -} - -uint16_t NxsMessageTest::getServiceType() -{ - return mServType; -} - -void NxsMessageTest::populateStore(RsGeneralDataService* dStore) -{ - - int nGrp = (rand()%2)+1; - std::vector grpIdList; - std::map grps; - RsNxsGrp* grp = NULL; - RsGxsGrpMetaData* grpMeta =NULL; - for(int i = 0; i < nGrp; i++) - { - std::pair p; - grp = new RsNxsGrp(mServType); - grpMeta = new RsGxsGrpMetaData(); - p.first = grp; - p.second = grpMeta; - init_item(*grp); - init_item(grpMeta); - grpMeta->mGroupId = grp->grpId; - grps.insert(p); - grpIdList.push_back(grp->grpId); - grpMeta = NULL; - grp = NULL; - } - - dStore->storeGroup(grps); - - int nMsgs = rand()%23; - std::map msgs; - RsNxsMsg* msg = NULL; - RsGxsMsgMetaData* msgMeta = NULL; - - for(int i=0; i p(msg, msgMeta); - - // pick a grp at random to associate the msg to - const std::string& grpId = grpIdList[rand()%nGrp]; - msgMeta->mMsgId = msg->msgId; - msgMeta->mGroupId = msg->grpId = grpId; - - msg = NULL; - msgMeta = NULL; - - msgs.insert(p); - } - - - dStore->storeMessage(msgs); - - return; -} - -void NxsMessageTest::cleanUp() -{ - - std::map::iterator mit = mPeerStoreMap.begin(); - - for(; mit != mPeerStoreMap.end(); mit++) - { - RsGeneralDataService* d = mit->second; - d->resetDataStore(); - } - - return; -} - -bool NxsMessageTest::testPassed(){ - return false; -} - -/*******************************/ - -NxsMessageTestObserver::NxsMessageTestObserver(RsGeneralDataService *dStore) - :mStore(dStore) -{ - -} - -void NxsMessageTestObserver::notifyNewGroups(std::vector &groups) -{ - std::vector::iterator vit = groups.begin(); - std::map grps; - - for(; vit != groups.end(); vit++) - { - RsNxsGrp* grp = *vit; - RsGxsGrpMetaData* meta = new RsGxsGrpMetaData(); - meta->deserialise(grp->meta.bin_data, grp->meta.bin_len); - meta->mSubscribeFlags |= GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED; - meta->mGroupId = grp->grpId; - grps.insert(std::make_pair(grp, meta)); - } - - mStore->storeGroup(grps); -} - -void NxsMessageTestObserver::notifyNewMessages(std::vector &messages) -{ - - std::vector::iterator vit = messages.begin(); - std::map msgs; - - for(; vit != messages.end(); vit++) - { - RsNxsMsg* msg = *vit; - RsGxsMsgMetaData* meta = new RsGxsMsgMetaData(); - meta->mGroupId = msg->grpId; - meta->mMsgId = msg->msgId; - msgs.insert(std::make_pair(msg, meta)); - } - - mStore->storeMessage(msgs); -} - diff --git a/libretroshare/src/tests/gxs/nxs_test/nxstestscenario.h b/libretroshare/src/tests/gxs/nxs_test/nxstestscenario.h deleted file mode 100644 index 72500e4d3..000000000 --- a/libretroshare/src/tests/gxs/nxs_test/nxstestscenario.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * nxstestscenario.h - * - * Created on: 10 Jul 2012 - * Author: crispy - */ - -#ifndef NXSTESTSCENARIO_H_ -#define NXSTESTSCENARIO_H_ - -#include -#include "gxs/rsdataservice.h" -#include "gxs/rsnxsobserver.h" - -/*! - * This scenario module provides data resources - */ -class NxsTestScenario -{ - -public: - - virtual std::string getTestName() = 0; - - /*! - * @param peer - * @param namePath - * @return data service with populated with random grp/msg data, null if peer or pathname exists - */ - virtual RsGeneralDataService* getDataService(const std::string& peer) = 0; - - - virtual bool testPassed() = 0; - /*! - * Service type for this test - * should correspond to serialiser service type - */ - virtual uint16_t getServiceType() = 0; - - /*! - * Call to remove files created - * in the test directory - */ - virtual void cleanUp() = 0; - - -}; - -class NxsMessageTestObserver : public RsNxsObserver -{ -public: - - NxsMessageTestObserver(RsGeneralDataService* dStore); - - /*! - * @param messages messages are deleted after function returns - */ - void notifyNewMessages(std::vector& messages); - - /*! - * @param messages messages are deleted after function returns - */ - void notifyNewGroups(std::vector& groups); - -private: - - RsGeneralDataService* mStore; - -}; - -class NxsMessageTest : public NxsTestScenario -{ - -public: - - NxsMessageTest(uint16_t servtype); - virtual ~NxsMessageTest(); - std::string getTestName(); - uint16_t getServiceType(); - RsGeneralDataService* getDataService(const std::string& peer); - - /*! - * Call to remove files created - * in the test directory - */ - void cleanUp(); - - bool testPassed(); - -private: - void setUpDataBases(); - void populateStore(RsGeneralDataService* dStore); - -private: - - std::string mTestName; - std::map mPeerStoreMap; - std::set mStoreNames; - uint16_t mServType; - - RsMutex mMsgTestMtx; - -}; - - -#endif /* NXSTESTSCENARIO_H_ */ diff --git a/libretroshare/src/tests/gxs/nxs_test/rsgxsnetservice_test.cc b/libretroshare/src/tests/gxs/nxs_test/rsgxsnetservice_test.cc deleted file mode 100644 index ddcc2f6c0..000000000 --- a/libretroshare/src/tests/gxs/nxs_test/rsgxsnetservice_test.cc +++ /dev/null @@ -1,46 +0,0 @@ -/* - * rsgxsnetservice_test.cc - * - * Created on: 11 Jul 2012 - * Author: crispy - */ - -#include "util/utest.h" -#include "nxstesthub.h" -#include "nxstestscenario.h" - -INITTEST(); - - -int main() -{ - - // first setup - NxsMessageTest msgTest(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); - std::set peers; - peers.insert("PeerA"); - peers.insert("PeerB"); - NxsTestHub hub(&msgTest, peers); - - // now get things started - createThread(hub); - - double timeDelta = 50; - - // put this thread to sleep for 10 secs - // make thread sleep for a bit -#ifndef WINDOWS_SYS - usleep((int) (timeDelta * 1000000)); -#else - Sleep((int) (timeDelta * 1000)); -#endif - - hub.join(); - CHECK(hub.testsPassed()); - - hub.cleanUp(); - - FINALREPORT("RsGxsNetService Tests"); - - return TESTRESULT(); -} diff --git a/libretroshare/src/tests/network_simulator/README.txt b/libretroshare/src/tests/network_simulator/README.txt deleted file mode 100644 index 2a669d3c3..000000000 --- a/libretroshare/src/tests/network_simulator/README.txt +++ /dev/null @@ -1,87 +0,0 @@ -TODO -==== - -Testing the router algorithm with network simulator - * generate a random network - * simulate disconnections (also in GUI) - * send messages from/to random peers and measure: - - how many times a given message is stored - - how much time a given message took to arrive. - -Implement - * clueing of GR from GXS (simulated in network simulator, when initing the network) - -In GLobal Router, by order of priority - * when a ACK is received for a msg that is already ACKed, we should still update the routing matrix and add a clue, but with lower prioity, - so that the matrix gets filled with additional routes. Can be checked in the simulator - - * routing strategy: - - when a route is known and available, always select it, but possibly add another random route, very rarely. - Peer disconnection is likely to cause the discovery of new routes anyway. - - * we should use clues from GXS to improve the routing matrix - - That would avoid lots of spamming. - - allows to init the routing matrices for all keys - - random walk will be a supplemental help, but restricted to small depth if no indication of route is available. - - needs to be implemented in network simulator. When providing a new key, the key should be spread in the network and new clues - should be added to the RGrouter matrix. - - * make sure the depth is accounted better: - - if single route is known => don't limit depth - - if no route is known => strictly limit depth - => add a counter which is increased when no route is available, and *reset* otherwise, so that the max number of bounce - we can do without knowledge of the keys is limited, but the total depth has no limits. - -Unsolved questions: - * handle dead routes correctly. How? - * should we send ACKs everywhere even upward? No, if we severely limit the depth of random walk. - * better distribute routing events, so that the matrix gets filled better? - * find a strategy to avoid storing too many items - * how to handle cases where a ACK cannot be sent back? The previous peer is going to try indefinitly? - => the ACK will be automatically collected by another route! - * how to make sure ACKed messages are not stored any longer than necessary? - * send signed ACKs, so that the receiver cannot be spoofed. - * only ACK when the message was properly received by the client service. No ACK if the client does not register that item? - -================================================================================================================ - - -The purpose of this directory is to write a Network simulator, that can have multiple turtle routers interact -together. The routers will talk to a fake link manager, which reports the peers for each node of a network graph. - -Required components: -=================== - NetworkGraph: a set of friends, with connections. Should be able to be saved to a file for debugging. - - GraphNode: a RS peer, represented by a random SSL id, a link manager, and possibly components such as file transfer, etc. - - Main loop: a loop calling tick() on all turtle routers. - - Functions: - * gather statistics over network load. See if tunnels are ok, improve bandwidth allocation strategy, see request broadcast. - - GUI: - * visualization of the graph. OpenGL + qglviewer window. Show tunnels, data flow as colors, etc. - * give quantitative information under mouse - * the user can trigger behaviors, execute tunnel handling orders, cause file transfer, etc. - - -Implementation constraints -========================== - * sendItem() and recvItems() should come from above. The class p3Service thus needs to be re-implemented to get/send the - data properly. - - => define subclass of p3turtle , where send() and recv() are redefined. - - * LinkMgr: - getOwnId(), getLinkType(), getOnlineList() - - used by turtle - - * turtle needs LinkMgr and ftServer. The ftServer can be contructed from PeerMgr (not called except in ftServer::setupFtServer. not needed here. - -Complilation -============ - * needs the QGLViewer-dev library (standard on ubuntu, package name is libqglviewer-qt4-dev) - * should compile on windows and MacOS as well. Use http://www.libqglviewer.com - diff --git a/libretroshare/src/tests/network_simulator/gui/GlobalRouterStatistics.cpp b/libretroshare/src/tests/network_simulator/gui/GlobalRouterStatistics.cpp deleted file mode 100644 index c1642cbb6..000000000 --- a/libretroshare/src/tests/network_simulator/gui/GlobalRouterStatistics.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/**************************************************************** - * RetroShare is distributed under the following license: - * - * Copyright (C) 20011, RetroShare Team - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - ****************************************************************/ - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include "GlobalRouterStatistics.h" - -static const int MAX_TUNNEL_REQUESTS_DISPLAY = 10 ; - -static QColor colorScale(float f) -{ - if(f == 0) - return QColor::fromHsv(0,0,192) ; - else - return QColor::fromHsv((int)((1.0-f)*280),200,255) ; -} - -GlobalRouterStatistics::GlobalRouterStatistics(QWidget *parent) - : RsAutoUpdatePage(2000,parent) -{ - setupUi(this) ; - - _router_F->setWidget( _tst_CW = new GlobalRouterStatisticsWidget() ) ; - _grouter = NULL ; -} - -GlobalRouterStatistics::~GlobalRouterStatistics() -{ -} - -void GlobalRouterStatistics::setGlobalRouter(const RsGRouter *grouter) -{ - _grouter = const_cast(grouter); - updateDisplay() ; -} -void GlobalRouterStatistics::updateDisplay() -{ - if(_grouter != NULL) - _tst_CW->updateContent(_grouter) ; -} - -QString GlobalRouterStatistics::getPeerName(const RsPeerId &peer_id) -{ - static std::map names ; - - std::map::const_iterator it = names.find(peer_id) ; - - if( it != names.end()) - return it->second ; - else - { - RsPeerDetails detail ; - if(!rsPeers->getPeerDetails(peer_id,detail)) - return tr("Unknown Peer"); - - return (names[peer_id] = QString::fromUtf8(detail.name.c_str())) ; - } -} - -GlobalRouterStatisticsWidget::GlobalRouterStatisticsWidget(QWidget *parent) - : QWidget(parent) -{ - maxWidth = 400 ; - maxHeight = 0 ; -} - -void GlobalRouterStatisticsWidget::updateContent(RsGRouter *grouter) -{ - std::vector cache_infos ; - RsGRouter::GRouterRoutingMatrixInfo matrix_info ; - - grouter->getRoutingCacheInfo(cache_infos) ; - grouter->getRoutingMatrixInfo(matrix_info) ; - - // What do we need to draw? - // - // Routing matrix - // Key [][][][][][][][][][] - // - // -> each [] shows a square (one per friend location) that is the routing probabilities for all connected friends - // computed using the "computeRoutingProbabilitites()" method. - // - // Own key ids - // key service id description - // - // Data items - // Msg id Local origin Destination Time Status - // - static const int cellx = 6 ; - static const int celly = 10+4 ; - - QPixmap tmppixmap(maxWidth, maxHeight); - tmppixmap.fill(this, 0, 0); - setFixedHeight(maxHeight); - - QPainter painter(&tmppixmap); - painter.initFrom(this); - painter.setPen(QColor::fromRgb(0,0,0)) ; - - maxHeight = 500 ; - - // std::cerr << "Drawing into pixmap of size " << maxWidth << "x" << maxHeight << std::endl; - // draw... - int ox=5,oy=5 ; - - painter.drawText(ox,oy+celly,tr("Pending packets")+":" + QString::number(cache_infos.size())) ; oy += celly*2 ; - - for(uint32_t i=0;i::const_iterator it(matrix_info.published_keys.begin());it!=matrix_info.published_keys.end();++it) - { - QString packet_string ; - packet_string += QString::fromStdString(it->first.toStdString()) ; - packet_string += tr(" : Service ID = ")+QString::number(it->second.service_id,16) ; - packet_string += " \""+QString::fromUtf8(it->second.description_string.c_str()) + "\"" ; - - painter.drawText(ox+2*cellx,oy+celly,packet_string ) ; oy += celly ; - } - oy += celly ; - - QString prob_string ; - - painter.drawText(ox+0*cellx,oy+celly,tr("Routing matrix (")) ; - - // draw scale - - for(int i=0;i<100;++i) - { - painter.setPen(colorScale(i/100.0)) ; - painter.drawLine(ox+120+i,oy+celly+2,ox+120+i,oy+2) ; - } - painter.setPen(QColor::fromRgb(0,0,0)) ; - - painter.drawText(ox+230,oy+celly,")") ; - - oy += celly ; - oy += celly ; - - static const int MaxKeySize = 20 ; - - for(std::map >::const_iterator it(matrix_info.per_friend_probabilities.begin());it!=matrix_info.per_friend_probabilities.end();++it) - { - painter.drawText(ox+2*cellx,oy+celly,QString::fromStdString(it->first.toStdString())+" : ") ; - - for(uint32_t i=0;isecond[i])) ; - - oy += celly ; - } - - oy += celly ; - oy += celly ; - - // update the pixmap - // - pixmap = tmppixmap; - maxHeight = oy ; -} - -QString GlobalRouterStatisticsWidget::speedString(float f) -{ - if(f < 1.0f) - return QString("0 B/s") ; - if(f < 1024.0f) - return QString::number((int)f)+" B/s" ; - - return QString::number(f/1024.0,'f',2) + " KB/s"; -} - -void GlobalRouterStatisticsWidget::paintEvent(QPaintEvent */*event*/) -{ - QStylePainter(this).drawPixmap(0, 0, pixmap); -} - -void GlobalRouterStatisticsWidget::resizeEvent(QResizeEvent *event) -{ - QRect TaskGraphRect = geometry(); - maxWidth = TaskGraphRect.width(); - maxHeight = TaskGraphRect.height() ; - - QWidget::resizeEvent(event); -// updateContent(); -} - diff --git a/libretroshare/src/tests/network_simulator/gui/GlobalRouterStatistics.h b/libretroshare/src/tests/network_simulator/gui/GlobalRouterStatistics.h deleted file mode 100644 index b3bc067de..000000000 --- a/libretroshare/src/tests/network_simulator/gui/GlobalRouterStatistics.h +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************** - * RetroShare is distributed under the following license: - * - * Copyright (C) 20011, RetroShare Team - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - ****************************************************************/ - -#pragma once - -#include -#include -#include - -#include "RsAutoUpdatePage.h" -#include "ui_GlobalRouterStatistics.h" - -class GlobalRouterStatisticsWidget ; -class p3GRouter ; - -class GlobalRouterStatistics: public RsAutoUpdatePage, public Ui::GlobalRouterStatistics -{ - Q_OBJECT - - public: - GlobalRouterStatistics(QWidget *parent = NULL) ; - ~GlobalRouterStatistics(); - - // Cache for peer names. - static QString getPeerName(const RsPeerId& peer_id) ; - - void setGlobalRouter(const RsGRouter *grouter) ; - virtual void updateDisplay() ; - - private: - - - GlobalRouterStatisticsWidget *_tst_CW ; - RsGRouter *_grouter ; -} ; - -class GlobalRouterStatisticsWidget: public QWidget -{ - Q_OBJECT - - public: - GlobalRouterStatisticsWidget(QWidget *parent = NULL) ; - - virtual void paintEvent(QPaintEvent *event) ; - virtual void resizeEvent(QResizeEvent *event); - - void updateContent(RsGRouter *grouter) ; - private: - static QString speedString(float f) ; - - QPixmap pixmap ; - int maxWidth,maxHeight ; -}; - diff --git a/libretroshare/src/tests/network_simulator/gui/GlobalRouterStatistics.ui b/libretroshare/src/tests/network_simulator/gui/GlobalRouterStatistics.ui deleted file mode 100644 index 0e6e28f7b..000000000 --- a/libretroshare/src/tests/network_simulator/gui/GlobalRouterStatistics.ui +++ /dev/null @@ -1,55 +0,0 @@ - - - GlobalRouterStatistics - - - - 0 - 0 - 611 - 408 - - - - Router Statistics - - - - :/images/rstray3.png:/images/rstray3.png - - - - - - Qt::Vertical - - - - QFrame::NoFrame - - - Qt::ScrollBarAlwaysOff - - - true - - - - - 0 - 0 - 593 - 390 - - - - - - - - - - - - - diff --git a/libretroshare/src/tests/network_simulator/gui/NetworkSimulatorGUI.cpp b/libretroshare/src/tests/network_simulator/gui/NetworkSimulatorGUI.cpp deleted file mode 100644 index b32e70931..000000000 --- a/libretroshare/src/tests/network_simulator/gui/NetworkSimulatorGUI.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include -#include - -#include "NetworkSimulatorGUI.h" -#include "NetworkViewer.h" -#include "TurtleRouterStatistics.h" -#include "GlobalRouterStatistics.h" - -NetworkSimulatorGUI::NetworkSimulatorGUI(Network& net) -{ - setupUi(this) ; - tickTimerId = 0 ; - - QVBoxLayout *layout = new QVBoxLayout(networkViewFrame) ; - layout->addWidget(_viewer = new NetworkViewer(networkViewFrame,net)) ; - - QObject::connect(_viewer,SIGNAL(nodeSelected(int)),this,SLOT(updateSelectedNode(int))) ; - QObject::connect(flow_CB,SIGNAL(toggled(bool)),this,SLOT(toggleNetworkTraffic(bool))) ; - - QVBoxLayout *layout2 = new QVBoxLayout(inspectorFrame) ; - QTabWidget *tabwidget = new QTabWidget() ; - - layout2->addWidget(tabwidget) ; - - tabwidget->addTab(_turtle_router_statistics = new TurtleRouterStatistics(),"Turtle router" ) ; - tabwidget->addTab(_global_router_statistics = new GlobalRouterStatistics(),"Global router" ) ; -} - -void NetworkSimulatorGUI::updateSelectedNode(int node_id) -{ - const RsTurtle *turtle = _viewer->network().node(node_id).turtle_service() ; - const RsGRouter *grouter = _viewer->network().node(node_id).global_router_service() ; - - _turtle_router_statistics->setTurtleRouter( turtle ) ; - _global_router_statistics->setGlobalRouter( grouter ) ; - - // make only the selected node to display grouter info - - for(uint32_t i=0;i<_viewer->network().n_nodes();++i) - _viewer->network().node(i).global_router_service()->setDebugEnabled(i==node_id) ; - - std::cerr << "Selected objects: turtle=" << std::hex << turtle << ", grouter=" << grouter << std::dec << std::endl; -} - -void NetworkSimulatorGUI::toggleNetworkTraffic(bool b) -{ - if(!b && tickTimerId > 0) - { - killTimer(tickTimerId) ; - tickTimerId = 0 ; - return ; - } - - if(b && tickTimerId == 0) - { - tickTimerId = startTimer(1000) ; - return ; - } - - std::cerr << "ERROR !!" << std::endl; -} - -void NetworkSimulatorGUI::timerEvent(QTimerEvent *event) -{ - Q_UNUSED(event) ; - - //std::cerr << "timer event!" << std::endl; - - _viewer->network().tick() ; - -} - diff --git a/libretroshare/src/tests/network_simulator/gui/NetworkSimulatorGUI.h b/libretroshare/src/tests/network_simulator/gui/NetworkSimulatorGUI.h deleted file mode 100644 index ddd2abef6..000000000 --- a/libretroshare/src/tests/network_simulator/gui/NetworkSimulatorGUI.h +++ /dev/null @@ -1,28 +0,0 @@ -#include "ui_NetworkSimulatorGUI.h" - -class TurtleRouterStatistics ; -class GlobalRouterStatistics ; -class NetworkViewer ; -class Network ; - -class NetworkSimulatorGUI: public QMainWindow, public Ui::NetworkSimulatorGUI -{ - Q_OBJECT - - public: - NetworkSimulatorGUI(Network& net) ; - - public slots: - void updateSelectedNode(int) ; - void toggleNetworkTraffic(bool) ; - - virtual void timerEvent(QTimerEvent *e) ; - - private: - NetworkViewer *_viewer ; - TurtleRouterStatistics *_turtle_router_statistics ; - GlobalRouterStatistics *_global_router_statistics ; - - int tickTimerId ; -}; - diff --git a/libretroshare/src/tests/network_simulator/gui/NetworkSimulatorGUI.ui b/libretroshare/src/tests/network_simulator/gui/NetworkSimulatorGUI.ui deleted file mode 100644 index 6ac45d8bf..000000000 --- a/libretroshare/src/tests/network_simulator/gui/NetworkSimulatorGUI.ui +++ /dev/null @@ -1,106 +0,0 @@ - - - NetworkSimulatorGUI - - - - 0 - 0 - 901 - 600 - - - - MainWindow - - - - - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - - flow - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - - 0 - 0 - 901 - 25 - - - - - File - - - - - - - - - - Load network - - - - - Save network - - - - - - diff --git a/libretroshare/src/tests/network_simulator/gui/NetworkViewer.cpp b/libretroshare/src/tests/network_simulator/gui/NetworkViewer.cpp deleted file mode 100644 index 8f1cf9535..000000000 --- a/libretroshare/src/tests/network_simulator/gui/NetworkViewer.cpp +++ /dev/null @@ -1,681 +0,0 @@ -#include -#include -#include - -#include - -#include "nscore/Network.h" -#include "nscore/MonitoredGRouterClient.h" -#include "NetworkViewer.h" - -NetworkViewer::NetworkViewer(QWidget *parent,Network&net) - : QGLViewer(parent),_network(net) , timerId(0) -{ - _current_selected_node = -1 ; - _current_displayed_node = -1 ; - _current_acted_node = -1 ; - - _dragging = false ; - _nodes_need_recomputing = true ; - - _node_coords.resize(net.n_nodes()) ; - _node_speeds.resize(net.n_nodes()) ; - - for(int i=0;i<_node_coords.size();++i) - { - _node_coords[i].x = drand48()*width()*5; - _node_coords[i].y = drand48()*height()*5 ; - _node_speeds[i].x = 0 ; - _node_speeds[i].y = 0 ; - } - - timerId = startTimer(1000/25) ; - - connect(this,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(contextMenu(QPoint))); - - action_ClientForHash = new QAction(tr("Client for new random hash"),this) ; - QObject::connect(action_ClientForHash,SIGNAL(triggered()),this,SLOT(actionClientForHash())) ; - - action_ProvideGRKey = new QAction(tr("Provide new GRouter key"),this) ; - QObject::connect(action_ProvideGRKey,SIGNAL(triggered()),this,SLOT(actionProvideGRKey())) ; - - setMouseTracking(true) ; -} - -void NetworkViewer::draw() -{ - glDisable(GL_DEPTH_TEST) ; - glClear(GL_COLOR_BUFFER_BIT) ; - - // for now, view is fixed. - - glMatrixMode(GL_MODELVIEW) ; - glPushMatrix() ; - glLoadIdentity() ; - glMatrixMode(GL_PROJECTION) ; - glPushMatrix() ; - glLoadIdentity() ; - glOrtho(0,width(),0,height(),1,-1) ; - - glEnable(GL_BLEND) ; - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA) ; - - // Now, draw all edges - - std::set tunnel_nodes ; - - glEnable(GL_LINE_SMOOTH) ; - glBegin(GL_LINES) ; - - for(uint32_t i=0;i<_network.n_nodes();++i) - { - PeerNode::NodeTrafficInfo traffic_info ; - _network.node(i).getTrafficInfo(traffic_info) ; - - const std::set& neighs( _network.neighbors(i) ) ; - - for(std::set::const_iterator it(neighs.begin());it!=neighs.end();++it) - { - if(traffic_info.local_src.find(_network.node(*it).id().toStdString())!=traffic_info.local_src.end() || traffic_info.local_dst.find(_network.node(*it).id().toStdString())!=traffic_info.local_dst.end()) - { - glColor3f(0.9f,0.4f,0.2f) ; - tunnel_nodes.insert(i) ; - tunnel_nodes.insert(*it) ; - } - else - glColor3f(0.4f,0.4f,0.4f) ; - - if( i < *it ) - { - glVertex2f(_node_coords[ i].x, _node_coords[ i].y) ; - glVertex2f(_node_coords[*it].x, _node_coords[*it].y) ; - } - } - } - - glEnd() ; - - // Draw all nodes. - // - glEnable(GL_POINT_SMOOTH) ; - glPointSize(20.0f) ; - glBegin(GL_POINTS) ; - - if(_current_selected_node > -1) - { - glColor4f(1.0f,0.2f,0.1f,0.7f) ; - glVertex2f(_node_coords[_current_selected_node].x, _node_coords[_current_selected_node].y) ; - } - glEnd() ; - - glPointSize(10.0f) ; - glBegin(GL_POINTS) ; - - for(uint32_t i=0;i<_network.n_nodes();++i) - { - float r = 0.8 ; - float g = 0.8 ; - float b = 0.8 ; - - if(!_network.node(i).providedHashes().empty()) - r *= 2.0, g /= 2.0, b /= 2.0f ; - - if(!_network.node(i).managedHashes().empty()) - g *= 2.0, b /= 2.0, r /= 2.0f ; - - if(tunnel_nodes.find(i) != tunnel_nodes.end() && r==0.8f && g==0.8f && b==0.8f) - r = 0.9f, g=0.4f,b=0.2f ; - - std::vector infos ; - _network.node(i).global_router_service()->getRoutingCacheInfo(infos) ; - - if(infos.size() == 1) - switch(infos[0].status) - { - case 1: r=1 ; g=0.5; b=0.1 ; break ; - case 2: r=0.4; g=0.5; b=0.4 ; break ; - case 3: r=0.2; g=0.2; b=0.7 ; break ; - case 4: r=0.6; g=0.1; b=0.2 ; break ; - default: - r=0.2; g=0.2; b=0.2 ; break ; - } - - glColor3f(r,g,b) ; - - glVertex2f(_node_coords[i].x, _node_coords[i].y) ; - } - - glEnd() ; - - // Draw info about current node under mouse. - // - if(_current_displayed_node > -1) - { - const PeerNode& node(_network.node(_current_displayed_node)) ; - int offset = 0 ; - int text_height = 15 ; - - drawText(10+_node_coords[_current_displayed_node].x,offset + height()-_node_coords[_current_displayed_node].y, "Node id = " + QString::fromStdString(node.id().toStdString())) ; - offset += text_height ; - - for(std::set::const_iterator it(node.providedHashes().begin());it!=node.providedHashes().end();++it) - { - drawText(10+_node_coords[_current_displayed_node].x,offset + height()-_node_coords[_current_displayed_node].y, "Server for hash " + QString::fromStdString((*it).toStdString()) ); - offset += text_height ; - } - - for(std::set::const_iterator it(node.managedHashes().begin());it!=node.managedHashes().end();++it) - { - drawText(10+_node_coords[_current_displayed_node].x,offset + height()-_node_coords[_current_displayed_node].y, "Client for hash " + QString::fromStdString((*it).toStdString()) ) ; - offset += text_height ; - } - } - - glMatrixMode(GL_MODELVIEW) ; - glPopMatrix() ; - glMatrixMode(GL_PROJECTION) ; - glPopMatrix() ; -} - -#define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr - -void fourn(double data[],unsigned long nn[],unsigned long ndim,int isign) -{ - int i1,i2,i3,i2rev,i3rev,ip1,ip2,ip3,ifp1,ifp2; - int ibit,idim,k1,k2,n,nprev,nrem,ntot; - double tempi,tempr; - double theta,wi,wpi,wpr,wr,wtemp; - - ntot=1; - for (idim=1;idim<=(long)ndim;idim++) - ntot *= nn[idim]; - nprev=1; - for (idim=ndim;idim>=1;idim--) { - n=nn[idim]; - nrem=ntot/(n*nprev); - ip1=nprev << 1; - ip2=ip1*n; - ip3=ip2*nrem; - i2rev=1; - for (i2=1;i2<=ip2;i2+=ip1) { - if (i2 < i2rev) { - for (i1=i2;i1<=i2+ip1-2;i1+=2) { - for (i3=i1;i3<=ip3;i3+=ip2) { - i3rev=i2rev+i3-i2; - SWAP(data[i3],data[i3rev]); - SWAP(data[i3+1],data[i3rev+1]); - } - } - } - ibit=ip2 >> 1; - while (ibit >= ip1 && i2rev > ibit) { - i2rev -= ibit; - ibit >>= 1; - } - i2rev += ibit; - } - ifp1=ip1; - while (ifp1 < ip2) { - ifp2=ifp1 << 1; - theta=isign*6.28318530717959/(ifp2/ip1); - wtemp=sin(0.5*theta); - wpr = -2.0*wtemp*wtemp; - wpi=sin(theta); - wr=1.0; - wi=0.0; - for (i3=1;i3<=ifp1;i3+=ip1) { - for (i1=i3;i1<=i3+ip1-2;i1+=2) { - for (i2=i1;i2<=ip3;i2+=ifp2) { - k1=i2; - k2=k1+ifp1; - tempr=wr*data[k2]-wi*data[k2+1]; - tempi=wr*data[k2+1]+wi*data[k2]; - data[k2]=data[k1]-tempr; - data[k2+1]=data[k1+1]-tempi; - data[k1] += tempr; - data[k1+1] += tempi; - } - } - wr=(wtemp=wr)*wpr-wi*wpi+wr; - wi=wi*wpr+wtemp*wpi+wi; - } - ifp1=ifp2; - } - nprev *= n; - } -} - -#undef SWAP - -static void convolveWithGaussian(double *forceMap,int S,int /*s*/) -{ - static double *bf = NULL ; - - if(bf == NULL) - { - bf = new double[S*S*2] ; - - for(int i=0;i derivative is constant - bf[2*(i+S*j)+1] = 0 ; - } - - unsigned long nn[2] = {S,S}; - fourn(&bf[-1],&nn[-1],2,1) ; - } - - unsigned long nn[2] = {S,S}; - fourn(&forceMap[-1],&nn[-1],2,1) ; - - for(int i=0;i=0 && i=0 && j new_coords(_node_coords) ; - - for(uint32_t i=0;i<_network.n_nodes();++i) - if(i != _current_selected_node || !_dragging) - { - float x = _node_coords[i].x ; - float y = _node_coords[i].y ; - - calculateForces(i,forceMap,S,S,x,y,speedf,new_coords[i].x,new_coords[i].y); - } - - bool itemsMoved = false; - for(uint32_t i=0;i<_node_coords.size();++i) - { - if( fabsf(_node_coords[i].x - new_coords[i].x) > 1.0 || fabsf(_node_coords[i].y - new_coords[i].y) > 1.0) - itemsMoved = true; - - //std::cerr << "Old i = " << _node_coords[i].x << ", new = " << new_coords[i].x << std::endl; - _node_coords[i] = new_coords[i] ; - } - - if (!itemsMoved) { - // killTimer(timerId); - //#ifdef DEBUG_ELASTIC - std::cerr << "Killing timr" << std::endl ; - _nodes_need_recomputing = false ; - //#endif - timerId = 0; - } - else - { - updateGL() ; - usleep(2000) ; - } - } - else - updateGL() ; - -} - -void NetworkViewer::mouseMoveEvent(QMouseEvent *e) -{ - if(_dragging && _current_selected_node >= 0) - { - _node_coords[_current_selected_node].x = e->x() ; - _node_coords[_current_selected_node].y = height() - e->y() ; - - _nodes_need_recomputing = true ; - - updateGL() ; - } - - float x = e->x() ; - float y = height()-e->y() ; - - _current_displayed_node = -1 ; - - for(uint32_t i=0;i<_node_coords.size();++i) - if( pow(_node_coords[i].x-x,2)+pow(_node_coords[i].y-y,2) < 5*5) - { - _current_displayed_node = i; - break ; - } -} - -void NetworkViewer::mouseReleaseEvent(QMouseEvent *e) -{ - _dragging = false ; -} - -void NetworkViewer::mousePressEvent(QMouseEvent *e) -{ - float x = e->x() ; - float y = height() - e->y() ; - - // find which node is selected - - for(uint32_t i=0;i<_node_coords.size();++i) - if( pow(_node_coords[i].x - x,2)+pow(_node_coords[i].y - y,2) < 10*10 ) - { - if(e->button() == Qt::LeftButton) - { - _current_selected_node = i ; - _dragging = true ; - updateGL() ; - emit nodeSelected(i) ; - return ; - } - - if(e->button() == Qt::RightButton) - { - _current_acted_node = i ; - emit customContextMenuRequested(QPoint(e->x(),e->y())) ; - return ; - } - } - - _dragging = false ; - _current_selected_node = -1 ; -} - -void NetworkViewer::calculateForces(const Network::NodeId& node_id,const double *map,int W,int H,float x,float y,float /*speedf*/,float& new_x, float& new_y) -{ -#ifdef A_FAIRE - if (mouseGrabberItem() == this) - { - new_x = x ; - new_y = y ; - return; - } -#endif - - // Sum up all forces pushing this item away - qreal xforce = 0; - qreal yforce = 0; - - float dei=0.0f ; - float dej=0.0f ; - - static float *e = NULL ; - static const int KS = 5 ; - - if(e == NULL) - { - e = new float[(2*KS+1)*(2*KS+1)] ; - - for(int i=-KS;i<=KS;++i) - for(int j=-KS;j<=KS;++j) - e[i+KS+(2*KS+1)*(j+KS)] = exp( -(i*i+j*j)/30.0 ) ; // can be precomputed - } - - for(int i=-KS;i<=KS;++i) - for(int j=-KS;j<=KS;++j) - { - int X = std::min(W-1,std::max(0,(int)rint(x/(float)width()*W))) ; - int Y = std::min(H-1,std::max(0,(int)rint(y/(float)height()*H))) ; - - float val = map[2*((i+X+W)%W + W*((j+Y+H)%H))] ; - - dei += i * e[i+KS+(2*KS+1)*(j+KS)] * val ; - dej += j * e[i+KS+(2*KS+1)*(j+KS)] * val ; - } - - xforce = REPULSION_FACTOR * dei/25.0; - yforce = REPULSION_FACTOR * dej/25.0; - - // Now subtract all forces pulling items together - // - const std::set& neighbs(_network.neighbors(node_id)) ; - double weight = neighbs.size() + 1 ; - - for(std::set::const_iterator it(neighbs.begin());it!=neighbs.end();++it) - { - NodeCoord pos; - double w2 ; // This factor makes the edge length depend on connectivity, so clusters of friends tend to stay in the - // same location. - // - - pos.x = _node_coords[*it].x - x ; //mapFromItem(edge->destNode(), 0, 0); - pos.y = _node_coords[*it].y - y ; //mapFromItem(edge->destNode(), 0, 0); - - w2 = sqrtf(std::min(neighbs.size(),_network.neighbors(*it).size())) ; - - float dist = sqrtf(pos.x*pos.x + pos.y*pos.y) ; - float val = dist - NODE_DISTANCE * w2 ; - - xforce += 0.01*pos.x * val / weight; - yforce += 0.01*pos.y * val / weight; - } - - xforce -= FRICTION_FACTOR * _node_speeds[node_id].x ; - yforce -= FRICTION_FACTOR * _node_speeds[node_id].y ; - - // This term drags nodes away from the sides. - // - if(x < 15) xforce += 100.0/(x+0.1) ; - if(y < 15) yforce += 100.0/(y+0.1) ; - if(x > width()-15) xforce -= 100.0/(width()-x+0.1) ; - if(y > height()-15) yforce -= 100.0/(height()-y+0.1) ; - - // now time filter: - - _node_speeds[node_id].x += xforce / MASS_FACTOR; - _node_speeds[node_id].y += yforce / MASS_FACTOR; - - if(_node_speeds[node_id].x > 10) _node_speeds[node_id].x = 10.0f ; - if(_node_speeds[node_id].y > 10) _node_speeds[node_id].y = 10.0f ; - if(_node_speeds[node_id].x <-10) _node_speeds[node_id].x =-10.0f ; - if(_node_speeds[node_id].y <-10) _node_speeds[node_id].y =-10.0f ; - - new_x = x + _node_speeds[node_id].x ; - new_y = y + _node_speeds[node_id].y ; - - new_x = std::min(std::max(new_x, 10.0f), width() - 10.0f); - new_y = std::min(std::max(new_y, 10.0f), height() - 10.0f); -} - -void NetworkViewer::contextMenu(QPoint p) -{ - std::cerr << "Context menu request at point " << p.x() << " " << p.y() << std::endl; - - QMenu contextMnu ;//= ui.msgText->createStandardContextMenu(matrix.map(point)); - - contextMnu.addAction(action_ClientForHash); - - if(_current_acted_node == -1) - return ; - - std::cerr << "acting on node " << _network.node(_current_acted_node).id() << std::endl; - - // make a list of hashes provided by all nodes except this one - std::set managed_hashes ; - std::set provided_hashes ; - - for(uint32_t i=0;i<_network.n_nodes();++i) - if(i != _current_acted_node) - { - managed_hashes.insert( _network.node(i).managedHashes().begin(), _network.node(i).managedHashes().end()) ; - provided_hashes.insert( _network.node(i).providedHashes().begin(), _network.node(i).providedHashes().end()) ; - } - - if(!managed_hashes.empty()) - { - QMenu *Mnu2 = contextMnu.addMenu("Provide hash") ; - - for(std::set::const_iterator it(managed_hashes.begin());it!=managed_hashes.end();++it) - { - QAction* provide_hash_action = new QAction(QString::fromStdString((*it).toStdString()), Mnu2); - connect(provide_hash_action, SIGNAL(triggered()), this, SLOT(actionProvideHash())); - Mnu2->addAction(provide_hash_action); - } - } - if(!provided_hashes.empty()) - { - QMenu *Mnu2 = contextMnu.addMenu("Client for hash") ; - - for(std::set::const_iterator it(provided_hashes.begin());it!=provided_hashes.end();++it) - { - QAction* manage_hash_action = new QAction(QString::fromStdString((*it).toStdString()), Mnu2); - connect(manage_hash_action, SIGNAL(triggered()), this, SLOT(actionClientForHash())); - Mnu2->addAction(manage_hash_action); - } - } - contextMnu.addSeparator() ; - - // GRouter stuff - - contextMnu.addAction(action_ProvideGRKey); - - std::set provided_keys ; - - for(uint32_t i=0;i<_network.n_nodes();++i) - if(i != _current_acted_node) - provided_keys.insert( _network.node(i).providedGRKeys().begin(), _network.node(i).providedGRKeys().end()) ; - - if(!provided_keys.empty()) - { - QMenu *Mnu2 = contextMnu.addMenu("Send message to Key") ; - - for(std::set::const_iterator it(provided_keys.begin());it!=provided_keys.end();++it) - { - QAction* send_message_action = new QAction(QString::fromStdString((*it).toStdString()), Mnu2); - connect(send_message_action, SIGNAL(triggered()), this, SLOT(actionSendToGRKey())); - Mnu2->addAction(send_message_action); - } - } - // Execute! - - contextMnu.exec(mapToGlobal(p)); -} - -void NetworkViewer::actionClientForHash() -{ - if(_current_acted_node < 0) - return ; - - RsFileHash hash ; - - if(qobject_cast(sender())->text().length() == 40) //data().toString().toStdString(); - { - hash = RsFileHash(qobject_cast(sender())->text().toStdString()) ; - - std::cerr << "Managing existing hash " << hash << std::endl; - } - else - { - std::cerr << "Managing random hash..." << std::endl; - - hash = RsFileHash::random() ; - } - - - std::cerr << " current node = " << _current_acted_node << std::endl ; - std::cerr << " adding random hash = " << hash << std::endl; - - _network.node(_current_acted_node).manageFileHash(hash) ; - - updateGL() ; -} - -void NetworkViewer::actionProvideHash() -{ - QString hash = qobject_cast(sender())->text() ;//data().toString().toStdString(); - - if(_current_acted_node < 0) - return ; - - std::cerr << "Providing hash " << hash.toStdString() << std::endl; - _network.node(_current_acted_node).provideFileHash(RsFileHash(hash.toStdString())) ; - - updateGL() ; -} - -void NetworkViewer::actionSendToGRKey() -{ - if(_current_acted_node < 0) - return ; - - GRouterKeyId key_id ; - - if(qobject_cast(sender())->text().length() == 32) //data().toString().toStdString(); - { - key_id = GRouterKeyId(qobject_cast(sender())->text().toStdString()) ; - - std::cerr << "Sending to existing key " << key_id << std::endl; - } - - std::cerr << " current node = " << _current_acted_node << std::endl ; - std::cerr << " sending message = " << key_id << std::endl; - - _network.node(_current_acted_node).sendToGRKey(key_id) ; - - updateGL() ; -} - -void NetworkViewer::actionProvideGRKey() -{ - if(_current_acted_node < 0) - return ; - - GRouterKeyId key_id = GRouterKeyId::random(); - QString key = QString::fromStdString(key_id.toStdString()) ; - - std::cerr << "Providing new grouter key " << key_id << std::endl; - _network.node(_current_acted_node).provideGRKey(key_id) ; - - updateGL() ; -} - - diff --git a/libretroshare/src/tests/network_simulator/gui/NetworkViewer.h b/libretroshare/src/tests/network_simulator/gui/NetworkViewer.h deleted file mode 100644 index f06e493e2..000000000 --- a/libretroshare/src/tests/network_simulator/gui/NetworkViewer.h +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include - -// The network simulator GUI has the following functionalities: -// -// 1 - show the network graph -// * the graph should spread in space automatically. We should use the code from the NetworkView for that. -// * each edge will be drawn with a color that displays used bandwidth along the edge, or TR sent to the edge, etc. -// * individual tunnels should be shown, in order to see what shape they have -// -// 2 - show info about each node. One needs a node widget that gets updated with whatever is to be read from the current node -// -// 3 - buttons to re-initiate a new network, or reset the network. -// -// 4 - buttons to inject information into the network: -// * shared files in some nodes. Should be handled by derivign the component that the turtle router accesses for local searches. -// * file requests in other nodes. Eazy: one just needs to ask the turtle router of the node to handle the hash. -// -// 5 - perturbate the network -// * change the load of each node, and the delay when forwarding requests. -// -#include "nscore/Network.h" - -class NetworkViewer: public QGLViewer -{ - Q_OBJECT - - public: - NetworkViewer(QWidget *parent,Network& network) ; - - virtual void draw() ; - virtual void keyPressEvent(QKeyEvent *) {} - virtual void mousePressEvent(QMouseEvent *) ; - virtual void mouseReleaseEvent(QMouseEvent *) ; - virtual void mouseMoveEvent(QMouseEvent *) ; - - const Network& network() const { return _network ; } - Network& network() { return _network ; } - - signals: - void nodeSelected(int) ; - - public slots: - void timerEvent(QTimerEvent *) ; - void contextMenu(QPoint) ; - void actionClientForHash() ; - void actionProvideHash() ; - void actionSendToGRKey() ; - void actionProvideGRKey() ; - - private: - void calculateForces(const Network::NodeId& node_id,const double *map,int W,int H,float x,float y,float /*speedf*/,float& new_x, float& new_y) ; - - typedef struct - { - float x ; - float y ; - } NodeCoord ; - - Network& _network ; - - std::vector _node_coords ; - std::vector _node_speeds ; - - static const float MASS_FACTOR = 10 ; - static const float FRICTION_FACTOR = 15.8 ; - static const float REPULSION_FACTOR = 8 ; - static const float NODE_DISTANCE = 30.0 ; - - int timerId ; - - int _current_selected_node ; - int _current_displayed_node ; - int _current_acted_node ; - bool _dragging ; - bool _nodes_need_recomputing ; - - QAction *action_SendToGRKey ; - QAction *action_ProvideGRKey ; - QAction *action_ClientForHash ; - QAction *action_ProvideHash ; -}; - diff --git a/libretroshare/src/tests/network_simulator/gui/RsAutoUpdatePage.cpp b/libretroshare/src/tests/network_simulator/gui/RsAutoUpdatePage.cpp deleted file mode 100644 index 9cb849e7f..000000000 --- a/libretroshare/src/tests/network_simulator/gui/RsAutoUpdatePage.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include "RsAutoUpdatePage.h" - -bool RsAutoUpdatePage::_locked = false ; - -RsAutoUpdatePage::RsAutoUpdatePage(int ms_update_period, QWidget *parent, Qt::WindowFlags flags) - : QWidget(parent, flags) -{ - _timer = new QTimer ; - _timer->setInterval(ms_update_period); - _timer->setSingleShot(true); - - QObject::connect(_timer,SIGNAL(timeout()),this,SLOT(timerUpdate())) ; - - _timer->start() ; -} - -RsAutoUpdatePage::~RsAutoUpdatePage() -{ - if(_timer != NULL) - delete _timer ; - - _timer = NULL ; -} - -void RsAutoUpdatePage::showEvent(QShowEvent */*event*/) -{ - //std::cout << "RsAutoUpdatePage::showEvent() In show event !!" << std::endl ; - if(!_locked) - updateDisplay(); -} - -void RsAutoUpdatePage::timerUpdate() -{ - // only update when the widget is visible. - // - if(_locked == false && isVisible()) { - updateDisplay(); - update() ; // Qt flush - } - - _timer->start() ; -} - -void RsAutoUpdatePage::lockAllEvents() { _locked = true ; } -void RsAutoUpdatePage::unlockAllEvents() { _locked = false ; } -bool RsAutoUpdatePage::eventsLocked() { return _locked ; } diff --git a/libretroshare/src/tests/network_simulator/gui/RsAutoUpdatePage.h b/libretroshare/src/tests/network_simulator/gui/RsAutoUpdatePage.h deleted file mode 100644 index ea1b0c8c8..000000000 --- a/libretroshare/src/tests/network_simulator/gui/RsAutoUpdatePage.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include -#include - -// This class implement a basic RS functionality which is that widgets displayign info -// should update regularly. They also should update only when visible, to save CPU time. -// -// Using this class simply needs to derive your widget from RsAutoUpdateWidget -// and oveload the update() function with the actual code that updates the -// widget. -// -class QTimer ; - -class RsAutoUpdatePage: public QWidget -{ - Q_OBJECT - - public: - RsAutoUpdatePage(int ms_update_period = 1000, QWidget *parent = NULL, Qt::WindowFlags flags = 0) ; - virtual ~RsAutoUpdatePage() ; - - virtual void updateDisplay() {} - - static void lockAllEvents() ; - static void unlockAllEvents() ; - static bool eventsLocked() ; - - protected: - virtual void showEvent(QShowEvent *e) ; - - private slots: - void timerUpdate() ; - - private: - QTimer *_timer ; - - static bool _locked ; -}; - diff --git a/libretroshare/src/tests/network_simulator/gui/TurtleRouterStatistics.cpp b/libretroshare/src/tests/network_simulator/gui/TurtleRouterStatistics.cpp deleted file mode 100644 index b45ac9996..000000000 --- a/libretroshare/src/tests/network_simulator/gui/TurtleRouterStatistics.cpp +++ /dev/null @@ -1,318 +0,0 @@ -/**************************************************************** - * RetroShare is distributed under the following license: - * - * Copyright (C) 20011, RetroShare Team - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - ****************************************************************/ - -#include -#include -#include - -#include -#include - -#include -#include -#include "TurtleRouterStatistics.h" - -static const int MAX_TUNNEL_REQUESTS_DISPLAY = 10 ; - -class TRHistogram -{ - public: - TRHistogram(const std::vector& info) :_infos(info) {} - - QColor colorScale(float f) - { - if(f == 0) - return QColor::fromHsv(0,0,192) ; - else - return QColor::fromHsv((int)((1.0-f)*280),200,255) ; - } - - virtual void draw(QPainter *painter,int& ox,int& oy,const QString& title) - { - static const int MaxTime = 61 ; - static const int MaxDepth = 8 ; - static const int cellx = 7 ; - static const int celly = 12 ; - - int save_ox = ox ; - painter->setPen(QColor::fromRgb(0,0,0)) ; - painter->drawText(2+ox,celly+oy,title) ; - oy+=2+2*celly ; - - if(_infos.empty()) - return ; - - ox += 10 ; - std::map > hits ; - std::map > depths ; - std::map >::iterator it ; - - int max_hits = 1; - int max_depth = 1; - - for(uint32_t i=0;i<_infos.size();++i) - { - std::vector& h(hits[_infos[i].source_peer_id]) ; - std::vector& g(depths[_infos[i].source_peer_id]) ; - - if(h.size() <= _infos[i].age) - h.resize(MaxTime,0) ; - - if(g.empty()) - g.resize(MaxDepth,0) ; - - if(_infos[i].age < h.size()) - { - h[_infos[i].age]++ ; - if(h[_infos[i].age] > max_hits) - max_hits = h[_infos[i].age] ; - } - if(_infos[i].depth < g.size()) - { - g[_infos[i].depth]++ ; - - if(g[_infos[i].depth] > max_depth) - max_depth = g[_infos[i].depth] ; - } - } - - int max_bi = std::max(max_hits,max_depth) ; - int p=0 ; - - for(it=depths.begin();it!=depths.end();++it,++p) - for(int i=0;ifillRect(ox+MaxTime*cellx+20+i*cellx,oy+p*celly,cellx,celly,colorScale(it->second[i]/(float)max_bi)) ; - - painter->setPen(QColor::fromRgb(0,0,0)) ; - painter->drawRect(ox+MaxTime*cellx+20,oy,MaxDepth*cellx,p*celly) ; - - for(int i=0;idrawText(ox+i*cellx,oy+(p+1)*celly+4,QString::number(i)) ; - - p=0 ; - int great_total = 0 ; - - for(it=hits.begin();it!=hits.end();++it,++p) - { - int total = 0 ; - - for(int i=0;ifillRect(ox+i*cellx,oy+p*celly,cellx,celly,colorScale(it->second[i]/(float)max_bi)) ; - total += it->second[i] ; - } - - painter->setPen(QColor::fromRgb(0,0,0)) ; - painter->drawText(ox+MaxDepth*cellx+30+(MaxTime+1)*cellx,oy+(p+1)*celly,TurtleRouterStatistics::getPeerName(it->first)) ; - painter->drawText(ox+MaxDepth*cellx+30+(MaxTime+1)*cellx+120,oy+(p+1)*celly,"("+QString::number(total)+")") ; - great_total += total ; - } - - painter->drawRect(ox,oy,MaxTime*cellx,p*celly) ; - - for(int i=0;idrawText(ox+i*cellx,oy+(p+1)*celly+4,QString::number(i)) ; - for(int i=0;idrawText(ox+MaxTime*cellx+20+i*cellx,oy+(p+1)*celly+4,QString::number(i)) ; - painter->setPen(QColor::fromRgb(255,130,80)) ; - painter->drawText(ox+MaxDepth*cellx+30+(MaxTime+1)*cellx+120,oy+(p+1)*celly+4,"("+QString::number(great_total)+")"); - - oy += (p+1)*celly+6 ; - - painter->setPen(QColor::fromRgb(0,0,0)) ; - painter->drawText(ox,oy+celly,"("+QApplication::translate("TurtleRouterStatistics", "Age in seconds")+")"); - painter->drawText(ox+MaxTime*cellx+20,oy+celly,"("+QApplication::translate("TurtleRouterStatistics", "Depth")+")"); - - painter->drawText(ox+MaxDepth*cellx+30+(MaxTime+1)*cellx+120,oy+celly,"("+QApplication::translate("TurtleRouterStatistics", "total")+")"); - - oy += 3*celly ; - - // now, draw a scale - - int last_hts = -1 ; - int cellid = 0 ; - - for(int i=0;i<=10;++i) - { - int hts = (int)(max_bi*i/10.0) ; - - if(hts > last_hts) - { - painter->fillRect(ox+cellid*(cellx+22),oy,cellx,celly,colorScale(i/10.0f)) ; - painter->setPen(QColor::fromRgb(0,0,0)) ; - painter->drawRect(ox+cellid*(cellx+22),oy,cellx,celly) ; - painter->drawText(ox+cellid*(cellx+22)+cellx+4,oy+celly,QString::number(hts)) ; - last_hts = hts ; - ++cellid ; - } - } - - oy += celly*2 ; - - ox = save_ox ; - } - - private: - const std::vector& _infos ; -}; - -TurtleRouterStatistics::TurtleRouterStatistics(QWidget *parent) - : RsAutoUpdatePage(2000,parent) -{ - setupUi(this) ; - - _turtle = NULL ; - - _tunnel_statistics_F->setWidget( _tst_CW = new TurtleRouterStatisticsWidget() ) ; - _tunnel_statistics_F->setWidgetResizable(true); - _tunnel_statistics_F->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - _tunnel_statistics_F->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - _tunnel_statistics_F->viewport()->setBackgroundRole(QPalette::NoRole); - _tunnel_statistics_F->setFrameStyle(QFrame::NoFrame); - _tunnel_statistics_F->setFocusPolicy(Qt::NoFocus); -} - -TurtleRouterStatistics::~TurtleRouterStatistics() -{ -} - -void TurtleRouterStatistics::updateDisplay() -{ - if(_turtle == NULL) - return ; - - std::vector > hashes_info ; - std::vector > tunnels_info ; - std::vector search_reqs_info ; - std::vector tunnel_reqs_info ; - - _turtle->getInfo(hashes_info,tunnels_info,search_reqs_info,tunnel_reqs_info) ; - - //updateTunnelRequests(hashes_info,tunnels_info,search_reqs_info,tunnel_reqs_info) ; - _tst_CW->updateTunnelStatistics(hashes_info,tunnels_info,search_reqs_info,tunnel_reqs_info,_turtle) ; - _tst_CW->update(); -} - -QString TurtleRouterStatistics::getPeerName(const RsPeerId& peer_id) -{ - static std::map names ; - - std::map::const_iterator it = names.find(peer_id) ; - - if( it != names.end()) - return it->second ; - else - return (names[peer_id] = QString::fromStdString(peer_id.toStdString())) ; -} - -TurtleRouterStatisticsWidget::TurtleRouterStatisticsWidget(QWidget *parent) - : QWidget(parent) -{ - maxWidth = 200 ; - maxHeight = 0 ; -} - -void TurtleRouterStatisticsWidget::updateTunnelStatistics(const std::vector >& /*hashes_info*/, - const std::vector >& /*tunnels_info*/, - const std::vector& search_reqs_info, - const std::vector& tunnel_reqs_info, - const RsTurtle *turtle) - -{ - static const int cellx = 6 ; - static const int celly = 10+4 ; - - QPixmap tmppixmap(maxWidth, maxHeight); - tmppixmap.fill(this, 0, 0); - setFixedHeight(maxHeight); - - QPainter painter(&tmppixmap); - painter.initFrom(this); - - maxHeight = 500 ; - - // std::cerr << "Drawing into pixmap of size " << maxWidth << "x" << maxHeight << std::endl; - // draw... - int ox=5,oy=5 ; - - TRHistogram(search_reqs_info).draw(&painter,ox,oy,tr("Search requests repartition") + ":") ; - - painter.setPen(QColor::fromRgb(70,70,70)) ; - painter.drawLine(0,oy,maxWidth,oy) ; - oy += celly ; - - TRHistogram(tunnel_reqs_info).draw(&painter,ox,oy,tr("Tunnel requests repartition") + ":") ; - - // now give information about turtle traffic. - // - TurtleTrafficStatisticsInfo info ; - turtle->getTrafficStatistics(info) ; - - painter.setPen(QColor::fromRgb(70,70,70)) ; - painter.drawLine(0,oy,maxWidth,oy) ; - oy += celly ; - - painter.drawText(ox,oy+celly,tr("Turtle router traffic")+":") ; oy += celly*2 ; - painter.drawText(ox+2*cellx,oy+celly,tr("Tunnel requests Up")+"\t: " + speedString(info.tr_up_Bps) ) ; oy += celly ; - painter.drawText(ox+2*cellx,oy+celly,tr("Tunnel requests Dn")+"\t: " + speedString(info.tr_dn_Bps) ) ; oy += celly ; - painter.drawText(ox+2*cellx,oy+celly,tr("Incoming file data")+"\t: " + speedString(info.data_dn_Bps) ) ; oy += celly ; - painter.drawText(ox+2*cellx,oy+celly,tr("Outgoing file data")+"\t: " + speedString(info.data_up_Bps) ) ; oy += celly ; - painter.drawText(ox+2*cellx,oy+celly,tr("Forwarded data ")+"\t: " + speedString(info.unknown_updn_Bps) ) ; oy += celly ; - - QString prob_string ; - - for(uint i=0;i -#include -#include "ui_TurtleRouterStatistics.h" -#include "RsAutoUpdatePage.h" - -class TurtleRouterStatisticsWidget ; - -class TurtleRouterStatistics: public RsAutoUpdatePage, public Ui::TurtleRouterStatistics -{ - Q_OBJECT - - public: - TurtleRouterStatistics(QWidget *parent = NULL) ; - ~TurtleRouterStatistics(); - - // Cache for peer names. - static QString getPeerName(const RsPeerId& peer_id) ; - - void setTurtleRouter(const RsTurtle *turtle) { _turtle = turtle ; } - - virtual void updateDisplay() ; - private: - - TurtleRouterStatisticsWidget *_tst_CW ; - const RsTurtle *_turtle ; -} ; - -class TurtleRouterStatisticsWidget: public QWidget -{ - Q_OBJECT - - public: - TurtleRouterStatisticsWidget(QWidget *parent = NULL) ; - - virtual void paintEvent(QPaintEvent *event) ; - virtual void resizeEvent(QResizeEvent *event); - - void updateTunnelStatistics( const std::vector > >&, - const std::vector > >&, - const std::vector&, - const std::vector&, - const RsTurtle *turtle) ; - - private: - static QString speedString(float f) ; - - QPixmap pixmap ; - int maxWidth,maxHeight ; -}; - diff --git a/libretroshare/src/tests/network_simulator/gui/TurtleRouterStatistics.ui b/libretroshare/src/tests/network_simulator/gui/TurtleRouterStatistics.ui deleted file mode 100644 index 365d3f362..000000000 --- a/libretroshare/src/tests/network_simulator/gui/TurtleRouterStatistics.ui +++ /dev/null @@ -1,55 +0,0 @@ - - - TurtleRouterStatistics - - - - 0 - 0 - 611 - 408 - - - - Router Statistics - - - - :/images/rstray3.png:/images/rstray3.png - - - - - - Qt::Vertical - - - - QFrame::NoFrame - - - Qt::ScrollBarAlwaysOff - - - true - - - - - 0 - 0 - 593 - 390 - - - - - - - - - - - - - diff --git a/libretroshare/src/tests/network_simulator/gui/gui.pro b/libretroshare/src/tests/network_simulator/gui/gui.pro deleted file mode 100644 index 8cb01b4a2..000000000 --- a/libretroshare/src/tests/network_simulator/gui/gui.pro +++ /dev/null @@ -1,25 +0,0 @@ -TEMPLATE = app - -CONFIG *= qt qglviewer uic -QT *= xml opengl - -INCLUDEPATH *= ../../.. .. - -TARGET = NetworkSim -DESTDIR = ../bin - -PRE_TARGETDEPS = ../nscore/nscore.pro - -SOURCES = main.cpp NetworkViewer.cpp NetworkSimulatorGUI.cpp \ - TurtleRouterStatistics.cpp RsAutoUpdatePage.cpp GlobalRouterStatistics.cpp - -HEADERS = NetworkViewer.h NetworkSimulatorGUI.h \ - TurtleRouterStatistics.h RsAutoUpdatePage.h GlobalRouterStatistics.h - -FORMS = NetworkSimulatorGUI.ui TurtleRouterStatistics.ui GlobalRouterStatistics.ui - -LIBS *= ../../../lib/libretroshare.a \ - ../../../../../libbitdht/src/lib/libbitdht.a \ - ../../../../../openpgpsdk/src/lib/libops.a \ - ../lib/libnscore.a \ - -lsqlcipher -lgnome-keyring -lupnp -lssl -lcrypto -lbz2 -lixml diff --git a/libretroshare/src/tests/network_simulator/gui/main.cpp b/libretroshare/src/tests/network_simulator/gui/main.cpp deleted file mode 100644 index f6c1e1c22..000000000 --- a/libretroshare/src/tests/network_simulator/gui/main.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include -#include - -#include "nscore/Network.h" -#include "nscore/MonitoredRsPeers.h" - -#include - -#include "NetworkSimulatorGUI.h" - -int main(int argc, char *argv[]) -{ - feenableexcept(FE_INVALID) ; - feenableexcept(FE_DIVBYZERO) ; - -#ifndef DEBUG - try - { -#endif - argstream as(argc,argv) ; - bool show_gui = false; - int nb_nodes = 20 ; - float connexion_probability = 0.2 ; - - as >> option('i',"gui",show_gui,"show gui (vs. do the pipeline automatically)") - >> parameter('n',"nodes",nb_nodes,"number of nodes in the network",false) - >> parameter('p',"connexion probability",connexion_probability,"probability that two nodes are connected (exponential law)",false) - >> help() ; - - as.defaultErrorHandling() ; - - // 2 - call the full pipeline - - Network network ; - - network.initRandom(nb_nodes,connexion_probability) ; - - rsPeers = new MonitoredRsPeers(network) ; - - if(show_gui) - { - QApplication app(argc,argv) ; - - NetworkSimulatorGUI pgui(network); - pgui.show() ; - - return app.exec() ; - } - - return 0 ; -#ifndef DEBUG - } - catch(std::exception& e) - { - std::cerr << "Unhandled exception: " << e.what() << std::endl; - return 1 ; - } -#endif -} - diff --git a/libretroshare/src/tests/network_simulator/network_simulator.pro b/libretroshare/src/tests/network_simulator/network_simulator.pro deleted file mode 100644 index 8564c70fe..000000000 --- a/libretroshare/src/tests/network_simulator/network_simulator.pro +++ /dev/null @@ -1,2 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS = nscore gui diff --git a/libretroshare/src/tests/network_simulator/nscore/FakeComponents.h b/libretroshare/src/tests/network_simulator/nscore/FakeComponents.h deleted file mode 100644 index b54ed8681..000000000 --- a/libretroshare/src/tests/network_simulator/nscore/FakeComponents.h +++ /dev/null @@ -1,91 +0,0 @@ -#pragma once - -#include -#include -#include - -class FakeLinkMgr: public p3LinkMgrIMPL -{ - public: - FakeLinkMgr(const RsPeerId& own_id,const std::list& friends) - : p3LinkMgrIMPL(NULL,NULL),_own_id(own_id),_friends(friends) - { - } - - virtual const RsPeerId& getOwnId() { return _own_id ; } - virtual void getOnlineList(std::list& lst) { lst = _friends ; } - virtual uint32_t getLinkType(const RsPeerId&) { return RS_NET_CONN_TCP_ALL | RS_NET_CONN_SPEED_NORMAL; } - - virtual bool getPeerName(const RsPeerId &ssl_id, std::string &name) { name = ssl_id.toStdString() ; return true ;} - - private: - RsPeerId _own_id ; - std::list _friends ; -}; - -class FakePublisher: public pqiPublisher -{ - public: - virtual bool sendItem(RsRawItem *item) - { - _item_queue.push_back(item) ; - return true ; - } - - RsRawItem *outgoing() - { - if(_item_queue.empty()) - return NULL ; - - RsRawItem *item = _item_queue.front() ; - _item_queue.pop_front() ; - return item ; - } - - private: - std::list _item_queue ; -}; - -class FakePeerMgr: public p3PeerMgrIMPL -{ - public: - FakePeerMgr(const RsPeerId& own,const std::list& ids) - : p3PeerMgrIMPL(own,RsPgpId(),"no name","location name") - { - for(std::list::const_iterator it(ids.begin());it!=ids.end();++it) - _ids.insert(*it) ; - } - - virtual bool idFriend(const RsPeerId& ssl_id) { return _ids.find(ssl_id) != _ids.end() ; } - - virtual ServicePermissionFlags servicePermissionFlags(const RsPeerId& ssl_id) - { - return ~ServicePermissionFlags(0) ; - } - std::set _ids ; -}; - -class FakeServiceControl: public p3ServiceControl -{ - public: - FakeServiceControl(p3LinkMgr *lm) - : p3ServiceControl(lm),mLink(lm) - { - } - - virtual void getPeersConnected(const uint32_t serviceId, std::set &peerSet) - { - std::list ids ; - mLink->getOnlineList(ids) ; - - for(std::list::const_iterator it(ids.begin());it!=ids.end();++it) - peerSet.insert(*it) ; - } - - virtual bool checkFilter(uint32_t,const RsPeerId& id) - { - return true ; - } - p3LinkMgr *mLink; -}; - diff --git a/libretroshare/src/tests/network_simulator/nscore/MainLoop.cpp b/libretroshare/src/tests/network_simulator/nscore/MainLoop.cpp deleted file mode 100644 index 22e89127e..000000000 --- a/libretroshare/src/tests/network_simulator/nscore/MainLoop.cpp +++ /dev/null @@ -1,24 +0,0 @@ - -void NetworkLoop() -{ - while(true) - { - std::cerr<< "network loop: tick()" << std::endl; - - // Get items for each components and send them to their destination. - // - for(int i=0;in_nodes();++i) - { - RsRawItem *item ; - - while(item = network->node(i).outgoing()) - { - PeerNode& node = network->node_by_id(item->peerId()) - item->peerId(network->node(i)->id()) ; - - node.received(item) ; - } - } - usleep(500000) ; - } -} diff --git a/libretroshare/src/tests/network_simulator/nscore/MonitoredGRouterClient.cpp b/libretroshare/src/tests/network_simulator/nscore/MonitoredGRouterClient.cpp deleted file mode 100644 index 9371bbd29..000000000 --- a/libretroshare/src/tests/network_simulator/nscore/MonitoredGRouterClient.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "MonitoredGRouterClient.h" - -const uint32_t MonitoredGRouterClient::GROUTER_CLIENT_SERVICE_ID_00 = 0x0111 ; - -void MonitoredGRouterClient::receiveGRouterData(const GRouterKeyId& destination_key,const RsGRouterGenericDataItem *item) -{ - std::cerr << "received one global grouter item for key " << destination_key << std::endl; -} - -void MonitoredGRouterClient::provideKey(const GRouterKeyId& key_id) -{ - _grouter->registerKey(key_id,GROUTER_CLIENT_SERVICE_ID_00,"test grouter address") ; - - std::cerr << "Registered new key " << key_id << " for service " << std::hex << GROUTER_CLIENT_SERVICE_ID_00 << std::dec << std::endl; -} - -void MonitoredGRouterClient::sendMessage(const GRouterKeyId& destination_key_id) const -{ - RsGRouterGenericDataItem *item = new RsGRouterGenericDataItem ; - item->data_size = 1000 + (RSRandom::random_u32()%1000) ; - item->data_bytes = (unsigned char *)malloc(item->data_size) ; - - RSRandom::random_bytes(item->data_bytes,item->data_size) ; - GRouterMsgPropagationId propagation_id ; - - _grouter->sendData(destination_key_id,GROUTER_CLIENT_SERVICE_ID_00,item,propagation_id) ; -} diff --git a/libretroshare/src/tests/network_simulator/nscore/MonitoredGRouterClient.h b/libretroshare/src/tests/network_simulator/nscore/MonitoredGRouterClient.h deleted file mode 100644 index a778c8c37..000000000 --- a/libretroshare/src/tests/network_simulator/nscore/MonitoredGRouterClient.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include - -class MonitoredGRouterClient: public GRouterClientService -{ - public: - static const uint32_t GROUTER_CLIENT_SERVICE_ID_00 ; - - // Derived from grouterclientservice.h - // - virtual void connectToGlobalRouter(p3GRouter *p) { _grouter = p ; p->registerClientService(GROUTER_CLIENT_SERVICE_ID_00,this) ; } - virtual void receiveGRouterData(const GRouterKeyId& destination_key,const RsGRouterGenericDataItem *item); - - // Own functionality - // - void sendMessage(const GRouterKeyId& destination_key) const ; - void provideKey(const GRouterKeyId& key) ; - - private: - p3GRouter *_grouter ; -}; - diff --git a/libretroshare/src/tests/network_simulator/nscore/MonitoredRsPeers.cpp b/libretroshare/src/tests/network_simulator/nscore/MonitoredRsPeers.cpp deleted file mode 100644 index aa952ea68..000000000 --- a/libretroshare/src/tests/network_simulator/nscore/MonitoredRsPeers.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include "MonitoredRsPeers.h" - -MonitoredRsPeers::MonitoredRsPeers(const Network& net) - : p3Peers(NULL,NULL,NULL),_network(net) -{ -} - -bool MonitoredRsPeers::getPeerDetails(const std::string& str,RsPeerDetails& details) -{ - std::cerr << __PRETTY_FUNCTION__ << " called" << std::endl; -} diff --git a/libretroshare/src/tests/network_simulator/nscore/MonitoredRsPeers.h b/libretroshare/src/tests/network_simulator/nscore/MonitoredRsPeers.h deleted file mode 100644 index 4706cc316..000000000 --- a/libretroshare/src/tests/network_simulator/nscore/MonitoredRsPeers.h +++ /dev/null @@ -1,14 +0,0 @@ -#include - -class Network ; - -class MonitoredRsPeers: public p3Peers -{ - public: - MonitoredRsPeers(const Network& net) ; - - virtual bool getPeerDetails(const std::string& peer_id,RsPeerDetails& details) ; - - private: - const Network& _network ; -}; diff --git a/libretroshare/src/tests/network_simulator/nscore/MonitoredTurtleClient.cpp b/libretroshare/src/tests/network_simulator/nscore/MonitoredTurtleClient.cpp deleted file mode 100644 index 3ed946ac3..000000000 --- a/libretroshare/src/tests/network_simulator/nscore/MonitoredTurtleClient.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "MonitoredTurtleClient.h" - -bool MonitoredTurtleClient::handleTunnelRequest(const TurtleFileHash& hash,const RsPeerId& peer_id) -{ - std::map::const_iterator it( _local_files.find(hash) ) ; - - return (it != _local_files.end() ) ; -} - -void MonitoredTurtleClient::provideFileHash(const RsFileHash& hash) -{ - FileInfo& info( _local_files[hash] ) ; - - info.fname = "File 1" ; - info.size = 100000 ; - info.hash = hash ; -} - diff --git a/libretroshare/src/tests/network_simulator/nscore/MonitoredTurtleClient.h b/libretroshare/src/tests/network_simulator/nscore/MonitoredTurtleClient.h deleted file mode 100644 index bb03af705..000000000 --- a/libretroshare/src/tests/network_simulator/nscore/MonitoredTurtleClient.h +++ /dev/null @@ -1,17 +0,0 @@ -#include - -class MonitoredTurtleClient: public RsTurtleClientService -{ -public: - virtual void addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir) {} - virtual void removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) {} - virtual void connectToTurtleRouter(p3turtle*p) { p->registerTunnelService(this) ; } - - bool handleTunnelRequest(const TurtleFileHash& hash,const RsPeerId& peer_id); - void provideFileHash(const RsFileHash& hash); - void requestFileHash(const RsFileHash& hash) ; - -private: - std::map _local_files ; -}; - diff --git a/libretroshare/src/tests/network_simulator/nscore/Network.cpp b/libretroshare/src/tests/network_simulator/nscore/Network.cpp deleted file mode 100644 index a24d4a40c..000000000 --- a/libretroshare/src/tests/network_simulator/nscore/Network.cpp +++ /dev/null @@ -1,109 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include "Network.h" -#include "MonitoredTurtleClient.h" -#include "FakeComponents.h" - -bool Network::initRandom(uint32_t nb_nodes,float connexion_probability) -{ - _nodes.clear() ; - _neighbors.clear() ; - - std::vector ids ; - - _neighbors.resize(nb_nodes) ; - ids.resize(nb_nodes) ; - - for(uint32_t i=0;i friends ; - for(std::set::const_iterator it(_neighbors[i].begin());it!=_neighbors[i].end();++it) - friends.push_back( ids[*it] ) ; - - _nodes.push_back( new PeerNode( ids[i], friends )); - } - return true ; -} - -void Network::tick() -{ - //std::cerr<< "network loop: tick()" << std::endl; - - // Tick all nodes. - - for(uint32_t i=0;iPeerId() << " to " << Network::node(i).id() << std::endl; - - PeerNode& node = node_by_id(item->PeerId()) ; - item->PeerId(Network::node(i).id()) ; - - node.incoming(item) ; - } - } - } - catch(...) - { - } -} - -PeerNode& Network::node_by_id(const RsPeerId& id) -{ - std::map::const_iterator it = _node_ids.find(id) ; - - if(it == _node_ids.end()) - throw std::runtime_error("Error. Bad id passed to node_by_id ("+id.toStdString()+")") ; - - return node(it->second) ; -} - diff --git a/libretroshare/src/tests/network_simulator/nscore/Network.h b/libretroshare/src/tests/network_simulator/nscore/Network.h deleted file mode 100644 index adecc5665..000000000 --- a/libretroshare/src/tests/network_simulator/nscore/Network.h +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include "PeerNode.h" - -template class Graph -{ - public: - typedef uint32_t NodeId ; - - void symmetric_connect(uint32_t n1,uint32_t n2) ; - const std::set& neighbors(const NodeId& n) const { return _neighbors[n] ; } - - // number of nodes. - // - uint32_t n_nodes() const { return _nodes.size() ;} - const NODE_TYPE& node(int i) const { return *_nodes[i] ; } - NODE_TYPE& node(int i) { return *_nodes[i] ; } - - protected: - - std::vector _nodes ; - std::vector > _neighbors ; -}; - -class Network: public Graph -{ - public: - // inits the graph as random. Returns true if connected, false otherwise. - // - bool initRandom(uint32_t n_nodes, float connexion_probability) ; - - // ticks all services of all nodes. - // - void tick() ; - - PeerNode& node_by_id(const RsPeerId& node_id) ; - - private: - std::map _node_ids ; -}; - diff --git a/libretroshare/src/tests/network_simulator/nscore/PeerNode.cpp b/libretroshare/src/tests/network_simulator/nscore/PeerNode.cpp deleted file mode 100644 index 569a1347c..000000000 --- a/libretroshare/src/tests/network_simulator/nscore/PeerNode.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "PeerNode.h" -#include "FakeComponents.h" -#include "MonitoredTurtleClient.h" -#include "MonitoredGRouterClient.h" - -PeerNode::PeerNode(const RsPeerId& id,const std::list& friends) - : _id(id) -{ - // add a service server. - - p3LinkMgr *link_mgr = new FakeLinkMgr(id, friends) ; - p3PeerMgr *peer_mgr = new FakePeerMgr(id, friends) ; - - _publisher = new FakePublisher ; - p3ServiceControl *ctrl = new FakeServiceControl(link_mgr) ; - - _service_server = new p3ServiceServer(_publisher,ctrl); - - RsServicePermissions perms; - perms.mDefaultAllowed = true ; - perms.mServiceId = RS_SERVICE_TYPE_TURTLE ; - - ctrl->updateServicePermissions(RS_SERVICE_TYPE_TURTLE,perms) ; - - perms.mDefaultAllowed = true ; - perms.mServiceId = RS_SERVICE_TYPE_GROUTER ; - - ctrl->updateServicePermissions(RS_SERVICE_TYPE_GROUTER,perms) ; - - // Turtle business - - _service_server->addService(_turtle = new p3turtle(ctrl,link_mgr),true) ; - _turtle_client = new MonitoredTurtleClient ; - _turtle_client->connectToTurtleRouter(_turtle) ; - - // global router business. - // - - _service_server->addService(_grouter = new p3GRouter(ctrl,link_mgr),true) ; - _grouter_client = new MonitoredGRouterClient ; - _grouter_client->connectToGlobalRouter(_grouter) ; -} - -PeerNode::~PeerNode() -{ - delete _service_server ; -} - -void PeerNode::tick() -{ - //std::cerr << " ticking peer node " << _id << std::endl; - _service_server->tick() ; -} - -void PeerNode::incoming(RsRawItem *item) -{ - _service_server->recvItem(item) ; -} -RsRawItem *PeerNode::outgoing() -{ - return dynamic_cast(_publisher)->outgoing() ; -} - -void PeerNode::provideFileHash(const RsFileHash& hash) -{ - _provided_hashes.insert(hash) ; - _turtle_client->provideFileHash(hash) ; -} - -void PeerNode::manageFileHash(const RsFileHash& hash) -{ - _managed_hashes.insert(hash) ; - _turtle->monitorTunnels(hash,_turtle_client, false) ; -} -void PeerNode::sendToGRKey(const GRouterKeyId& key_id) -{ - _grouter_client->sendMessage(key_id) ; -} -void PeerNode::provideGRKey(const GRouterKeyId& key_id) -{ - _grouter_client->provideKey(key_id) ; - _provided_keys.insert(key_id); -} -void PeerNode::getTrafficInfo(NodeTrafficInfo& info) -{ - std::vector > hashes_info ; - std::vector > tunnels_info ; - std::vector search_reqs_info ; - std::vector tunnel_reqs_info ; - - _turtle->getInfo(hashes_info,tunnels_info,search_reqs_info,tunnel_reqs_info) ; - - for(uint32_t i=0;i -#include -#include - -class MonitoredTurtleClient ; -class MonitoredGRouterClient ; -class RsTurtle ; -class p3turtle ; -class p3GRouter ; -class pqiPublisher ; -class RsRawItem ; -class p3ServiceServer ; - -class PeerNode -{ - public: - struct NodeTrafficInfo - { - std::map local_src ; // peer id., tunnel id - std::map local_dst ; - }; - - PeerNode(const RsPeerId& id,const std::list& friends) ; - ~PeerNode() ; - - RsRawItem *outgoing() ; - void incoming(RsRawItem *) ; - - const RsPeerId& id() const { return _id ;} - - void tick() ; - - // Turtle-related methods - // - const RsTurtle *turtle_service() const { return _turtle ; } - p3GRouter *global_router_service() const { return _grouter ; } - - void manageFileHash(const RsFileHash& hash) ; - void provideFileHash(const RsFileHash& hash) ; - - const std::set& providedHashes() const { return _provided_hashes; } - const std::set& managedHashes() const { return _managed_hashes; } - - void getTrafficInfo(NodeTrafficInfo& trinfo) ; // - - // GRouter-related methods - // - void provideGRKey(const GRouterKeyId& key_id) ; - void sendToGRKey(const GRouterKeyId& key_id) ; - - const std::set& providedGRKeys() const { return _provided_keys; } - - private: - p3ServiceServer *_service_server ; - pqiPublisher *_publisher ; - RsPeerId _id ; - - // turtle stuff - // - p3turtle *_turtle ; - MonitoredTurtleClient *_turtle_client ; - - // grouter stuff - // - p3GRouter *_grouter ; - MonitoredGRouterClient *_grouter_client ; - - std::set _provided_hashes ; - std::set _managed_hashes ; - std::set _provided_keys ; -}; - diff --git a/libretroshare/src/tests/network_simulator/nscore/nscore.pro b/libretroshare/src/tests/network_simulator/nscore/nscore.pro deleted file mode 100644 index 5a3989a15..000000000 --- a/libretroshare/src/tests/network_simulator/nscore/nscore.pro +++ /dev/null @@ -1,20 +0,0 @@ -TEMPLATE = lib -CONFIG *= staticlib - -INCLUDEPATH *= ../../.. .. - -TARGET = nscore - -SOURCES = Network.cpp \ - PeerNode.cpp \ - MonitoredRsPeers.cpp \ - MonitoredTurtleClient.cpp \ - MonitoredGRouterClient.cpp - -HEADERS = Network.h \ - PeerNode.h \ - MonitoredRsPeers.h \ - MonitoredTurtleClient.h \ - MonitoredGRouterClient.h - -DESTDIR = ../lib diff --git a/libretroshare/src/tests/perform_all_auto_tests.sh b/libretroshare/src/tests/perform_all_auto_tests.sh deleted file mode 100755 index 648bf63c5..000000000 --- a/libretroshare/src/tests/perform_all_auto_tests.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh - -# This is the main script for performing all tests automatically. -# - in order to add new directories, just list them in the $subdirs variable below - -echo "****************************************" -echo "*** RetroShare automatic test suite. ***" -echo "****************************************" -echo "Performing all tests on subdirs." -echo "(Some tests take a few minutes. Be patient) " -echo -echo - -subdirs="util serialiser dbase upnp general pgp tcponudp" - -for dir in $subdirs; do - echo Tests for directory: $dir - cd $dir - ./perform_auto_tests.sh - cd .. -done - diff --git a/libretroshare/src/tests/pgp/test_certificate.cc b/libretroshare/src/tests/pgp/test_certificate.cc deleted file mode 100644 index 6659ea86a..000000000 --- a/libretroshare/src/tests/pgp/test_certificate.cc +++ /dev/null @@ -1,137 +0,0 @@ -#include -#include - -#include -#include -//#include -#include -#include -#include - -INITTEST() ; - -static std::string pgp_pwd_cb(void * /*hook*/, const char *uid_hint, const char * /*passphrase_info*/, int prev_was_bad) -{ -#define GPG_DEBUG2 -#ifdef GPG_DEBUG2 - fprintf(stderr, "pgp_pwd_callback() called.\n"); -#endif - std::string password; - - std::cerr << "SHould not be called!" << std::endl; - return password ; -} - -int main(int argc,char *argv[]) -{ - try - { - argstream as(argc,argv) ; - std::string keyfile ; - bool clean_cert = false ; - - as >> parameter('i',"input",keyfile,"input certificate file (old or new formats)",true) - >> option('c',"clean",clean_cert,"clean cert before parsing") - >> help() ; - - as.defaultErrorHandling() ; - - FILE *f = fopen(keyfile.c_str(),"rb") ; - - CHECK(f != NULL) ; - - std::string res ; - char c ; - - while( (c = fgetc(f)) != EOF) - res += c ; - - fclose(f) ; - - std::cerr << "Read this string from the file:" << std::endl; - std::cerr << "==========================================" << std::endl; - std::cerr << res << std::endl; - std::cerr << "==========================================" << std::endl; - - if(clean_cert) - { - std::string res2 ; - int err ; - - //res2 = cleanUpCertificate(res,err) ; - - //if(res2 == "") - // std::cerr << "Error while cleaning: " << err << std::endl; - //else - // res = res2 ; - - std::cerr << "Certificate after cleaning:" << std::endl; - std::cerr << "==========================================" << std::endl; - std::cerr << res << std::endl; - std::cerr << "==========================================" << std::endl; - } - std::cerr << "Parsing..." << std::endl; - - RsCertificate cert(res) ; - - std::cerr << "Output from certificate:" << std::endl; - - std::cerr << cert.toStdString_oldFormat() << std::endl ; - - std::cerr << "Output from certificate (new format):" << std::endl; - std::cerr << cert.toStdString() << std::endl ; - - std::string key_id ; - std::string name ; - std::list signers ; - - PGPHandler::setPassphraseCallback(pgp_pwd_cb) ; - PGPHandler handler("toto1","toto2","toto3","toto4") ; - handler.getGPGDetailsFromBinaryBlock(cert.pgp_key(),cert.pgp_key_size(),key_id,name,signers) ; - - CHECK(key_id == "660FB771727CE286") ; - CHECK(name == "Cyril-test (generated by Retroshare) ") ; - - std::cerr << "Details loaded from certificate:" << std::endl; - std::cerr << "PGP id\t: " << key_id << std::endl; - std::cerr << "Key name\t: " << name << std::endl; - std::cerr << "Signers\t:" << std::endl; - - bool found = false ; - - for(std::list::const_iterator it(signers.begin());it!=signers.end();++it) - { - std::cerr << " " << *it << std::endl; - - if(*it == key_id) - found = true ; - } - CHECK(found) ; - - // try to load the certificate. - - std::cerr << "Checking that the certificate is imported correctly" << std::endl; - - std::string error_string ; - PGPIdType found_id ; - - bool result = handler.LoadCertificateFromString(res,found_id,error_string) ; - - if(!result) - std::cerr << "Certificate error: " << error_string << std::endl; - else - std::cerr << "Certificate loaded correctly. Id = " << found_id.toStdString() << std::endl; - - CHECK(result) ; - - FINALREPORT("Test certificate parsing") ; - - return TESTRESULT(); - } - catch(std::exception& e) - { - std::cerr << "Exception never handled: " << e.what() << std::endl; - return 1 ; - } -} - diff --git a/libretroshare/src/tests/pgp/test_certificate.newformat.rsc b/libretroshare/src/tests/pgp/test_certificate.newformat.rsc deleted file mode 100644 index 9bcd0273b..000000000 --- a/libretroshare/src/tests/pgp/test_certificate.newformat.rsc +++ /dev/null @@ -1,15 +0,0 @@ -Af8AAAKHmQENBEyoe/MBCAC9rKm/ehp9Iv1XrOiKIyj1X5nJzQ660+OhmQf4lbJv -krcnvdrdcmlfZQfupWMXHo7A3+27lOpfTvA1xpO8Gze0bRbLsbpx2dARjLUzXJAI -FNCYzH5xlIixxOwgX3tinKfoP3WvZv+nYBac/HeAPUW8BVqx6Y6V/gM3c71XNf9u -hPgArN0jvLOeqAJY+lACJZYlAIw6Jt2FzarC+orWndkvrsgrWmdxkorfZKBfdNwd -f1YYrpUmGaf51x4DkrMWpfHxS8b6cgOmSN3LeAC8LCm5oEXPfNgaRehN9LKrSmcp -cPS2jvDipgGBx+nL7gytCREMJkJoxppXQpVt1whaFDJVABEBAAG0OkN5cmlsLXRl -c3QgKGdlbmVyYXRlZCBieSBSZXRyb3NoYXJlKSA8Y3lyaWwuc29sZXJAaW1hZy5m -cj6JATgEEwECACIFAkyoe/MCGy8GCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJ -EGYPt3FyfOKG+h0H/A+vvryYmGcGFl82D4M0mAPAlbjZFkGCB8qJJSFuor55GJ3V -8pBb4UK7jnLhQhqsdXxAawT9R5RzTDITWHkS4KVaFalOYLxQ8x4s31FWXUiprAvJ -AIVw9gnBC7kDLro2irCljZB5ro8fsg0SJ0ZFc4cZMPZxnMKm5ovC6WggbblyaHrR -rV8jhHFIR+RG9/nnw0PgvGOmV9f4Q0a/7E18AxdBXYMZSp7p/mwbQdkqgm7p73bg -7E2Zz/Fhg1/PguwjlDal+HyUEPDvcPG41NAKwpMeL78qVJTQcBzzo1Irqj5f5UFJ -p4/H7QDlEsz/ZGxXXq3PdAP5BICwiOD44G9dIUECBlLktZUcsQMGwKgAZxyxBAAG -BmxhcHRvcAUQXVLApuPC+s1X/RPnFumDgQ== diff --git a/libretroshare/src/tests/pgp/test_certificate.oldformat.rsc b/libretroshare/src/tests/pgp/test_certificate.oldformat.rsc deleted file mode 100644 index 501e4abd7..000000000 --- a/libretroshare/src/tests/pgp/test_certificate.oldformat.rsc +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: OpenPGP:SDK v0.9 - -mQENBEyoe/MBCAC9rKm/ehp9Iv1XrOiKIyj1X5nJzQ660+OhmQf4lbJvkrcnvdrd -cmlfZQfupWMXHo7A3+27lOpfTvA1xpO8Gze0bRbLsbpx2dARjLUzXJAIFNCYzH5x -lIixxOwgX3tinKfoP3WvZv+nYBac/HeAPUW8BVqx6Y6V/gM3c71XNf9uhPgArN0j -vLOeqAJY+lACJZYlAIw6Jt2FzarC+orWndkvrsgrWmdxkorfZKBfdNwdf1YYrpUm -Gaf51x4DkrMWpfHxS8b6cgOmSN3LeAC8LCm5oEXPfNgaRehN9LKrSmcpcPS2jvDi -pgGBx+nL7gytCREMJkJoxppXQpVt1whaFDJVABEBAAG0OkN5cmlsLXRlc3QgKGdl -bmVyYXRlZCBieSBSZXRyb3NoYXJlKSA8Y3lyaWwuc29sZXJAaW1hZy5mcj6JATgE -EwECACIFAkyoe/MCGy8GCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEGYPt3Fy -fOKG+h0H/A+vvryYmGcGFl82D4M0mAPAlbjZFkGCB8qJJSFuor55GJ3V8pBb4UK7 -jnLhQhqsdXxAawT9R5RzTDITWHkS4KVaFalOYLxQ8x4s31FWXUiprAvJAIVw9gnB -C7kDLro2irCljZB5ro8fsg0SJ0ZFc4cZMPZxnMKm5ovC6WggbblyaHrRrV8jhHFI -R+RG9/nnw0PgvGOmV9f4Q0a/7E18AxdBXYMZSp7p/mwbQdkqgm7p73bg7E2Zz/Fh -g1/PguwjlDal+HyUEPDvcPG41NAKwpMeL78qVJTQcBzzo1Irqj5f5UFJp4/H7QDl -Esz/ZGxXXq3PdAP5BICwiOD44G9dIUE= -=BWkb ------END PGP PUBLIC KEY BLOCK----- ---SSLID--5d52c0a6e3c2facd57fd13e716e98381;--LOCATION--laptop; ---LOCAL--192.168.0.103:7345;--EXT--82.228.181.149:7345; diff --git a/libretroshare/src/tests/pgp/test_certificate.sh b/libretroshare/src/tests/pgp/test_certificate.sh deleted file mode 100755 index e81d89f98..000000000 --- a/libretroshare/src/tests/pgp/test_certificate.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -./test_certificate -i test_certificate.oldformat.rsc && ./test_certificate -i test_certificate.newformat.rsc diff --git a/libretroshare/src/tests/pgp/test_identity_import.c b/libretroshare/src/tests/pgp/test_identity_import.c deleted file mode 100644 index 7fcd14066..000000000 --- a/libretroshare/src/tests/pgp/test_identity_import.c +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include - -#include -#include -//#include -#include -#include -#include - -INITTEST() ; - -static std::string pgp_pwd_cb(void * /*hook*/, const char *uid_hint, const char * /*passphrase_info*/, int prev_was_bad) -{ -#define GPG_DEBUG2 -#ifdef GPG_DEBUG2 - fprintf(stderr, "pgp_pwd_callback() called.\n"); -#endif - std::string password; - - std::cerr << "SHould not be called!" << std::endl; - return password ; -} - -int main(int argc,char *argv[]) -{ - try - { - argstream as(argc,argv) ; - std::string idfile ; - bool clean_cert = false ; - - as >> parameter('i',"input",idfile,"input retroshare identity file, ascii format",true) - >> help() ; - - as.defaultErrorHandling() ; - - PGPHandler handler("toto1","toto2","toto3","toto4") ; - - PGPIdType imported_key_id ; - std::string import_error_string ; - - bool res = handler.importGPGKeyPair(idfile,imported_key_id,import_error_string) ; - - handler.syncDatabase() ; - - if(!res) - std::cerr << "Identity Import error: " << import_error_string << std::endl; - - CHECK(res) ; - } - catch(std::exception& e) - { - std::cerr << "Exception never handled: " << e.what() << std::endl; - return 1 ; - } -} - diff --git a/libretroshare/src/tests/pgp/test_key_parsing.cc b/libretroshare/src/tests/pgp/test_key_parsing.cc deleted file mode 100644 index 8e4a8ff64..000000000 --- a/libretroshare/src/tests/pgp/test_key_parsing.cc +++ /dev/null @@ -1,64 +0,0 @@ -// COMPILE_LINE: g++ -o test_key_parsing test_key_parsing.cc -g -I../../../openpgpsdk/include -I../ -L../lib ../../../openpgpsdk/src/lib/libops.a -lssl -lcrypto -lbz2 -// -#include -#include - -extern "C" -{ - #include - #include - #include -} - -#include -#include - -INITTEST() ; - -int main(int argc,char *argv[]) -{ - try - { - // test PGPHandler - // - // 0 - init - - bool armoured = false ; - std::string keyfile ; - - argstream as(argc,argv) ; - - as >> parameter('i',"input-key",keyfile,"input key file.",true) - >> option('a',"armoured",armoured,"input is armoured") - >> help() ; - - as.defaultErrorHandling() ; - - ops_keyring_t *kr = (ops_keyring_t*)malloc(sizeof(ops_keyring_t)) ; - kr->nkeys = 0 ; - kr->nkeys_allocated = 0 ; - kr->keys = 0 ; - - CHECK(ops_false != ops_keyring_read_from_file(kr,armoured, keyfile.c_str())) ; - - for(int i=0;inkeys;++i) - { - ops_print_public_keydata(&kr->keys[i]) ; - ops_print_public_keydata_verbose(&kr->keys[i]) ; - ops_print_public_key(&kr->keys[i].key.pkey) ; - } - - ops_list_packets(const_cast(keyfile.c_str()),armoured,kr,NULL) ; - - FINALREPORT("Test key parsing") ; - - return TESTRESULT() ; - } - catch(std::exception& e) - { - std::cerr << "Caught exception: " << e.what() << std::endl; - return 1 ; - } -} - - diff --git a/libretroshare/src/tests/pgp/test_key_parsing.sh b/libretroshare/src/tests/pgp/test_key_parsing.sh deleted file mode 100644 index dd9ee9139..000000000 --- a/libretroshare/src/tests/pgp/test_key_parsing.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -./test_key_parsing -i test_pubring.gpg diff --git a/libretroshare/src/tests/pgp/test_pgp_handler.cc b/libretroshare/src/tests/pgp/test_pgp_handler.cc deleted file mode 100644 index b78adc5f5..000000000 --- a/libretroshare/src/tests/pgp/test_pgp_handler.cc +++ /dev/null @@ -1,397 +0,0 @@ -// COMPILE_LINE: g++ -o test_pgp_handler test_pgp_handler.cc -I../../../openpgpsdk/include -I../ -L../lib -lretroshare ../../../libbitdht/src/lib/libbitdht.a ../../../openpgpsdk/lib/libops.a -lgnome-keyring -lupnp -lssl -lcrypto -lbz2 -// -#include -#include -#include -#include -#include -#include -#include - -INITTEST() ; - -static std::string static_passphrase = "" ; -static std::string passphrase_callback(void *data,const char *uid_info,const char *what,int prev_was_bad) -{ - if(!static_passphrase.empty()) - return static_passphrase ; - - if(prev_was_bad) - std::cerr << "Bad passphrase." << std::endl; - - std::string wt = std::string("Please enter passphrase for key id ") + uid_info + " :"; - - return std::string(getpass(wt.c_str())) ; -} - -static std::string stringFromBytes(unsigned char *bytes,size_t len) -{ - static const char out[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' } ; - - std::string res ; - - for(uint32_t j = 0; j < len; j++) - { - res += out[ (bytes[j]>>4) ] ; - res += out[ bytes[j] & 0xf ] ; - } - - return res ; -} - -static std::string askForKeyId(PGPHandler& pgph) -{ - // 0 - print keys and key types - - std::list lst ; - pgph.availableGPGCertificatesWithPrivateKeys(lst) ; - - std::cerr << lst.size() << " available key pairs: " << std::endl; - int i=0 ; - - for(std::list::const_iterator it(lst.begin());it!=lst.end();++it,++i) - { - std::cerr << "(" << i << ") ID=" << (*it).toStdString() << ", type = " ; - - const PGPCertificateInfo *cert = pgph.getCertificateInfo(*it) ; - - switch(cert->_type) - { - case PGPCertificateInfo::PGP_CERTIFICATE_TYPE_DSA: std::cerr << "DSA" << std::endl; - break ; - case PGPCertificateInfo::PGP_CERTIFICATE_TYPE_RSA: std::cerr << "RSA" << std::endl; - break ; - default: std::cerr << "Unknown" << std::endl; - } - } - - if(i == 0) - throw std::runtime_error("No key pair available in supplied keyring.") ; - - // 1 - ask for which key to use. - - int num = -1 ; - - while(true) - { - std::cerr << "Please enter selected key number (0 - " << i-1 << ") : " ; - std::cerr.flush() ; - - char buf[10]; - fgets(buf,10,stdin) ; - - if(sscanf(buf,"%d",&num) == 1 && num >= 0 && num < i) - break ; - } - - // 2 - return the id string. - - std::list::const_iterator it(lst.begin()) ; - for(int i=0;i> option('1',"pgptype",test_pgpid_type,"Test pgp ID type") - >> option('2',"keyring-read",test_keyring_read,"Test keyring read") - >> option('3',"file-encryption",test_file_encryption,"Test file encryption. Needs -f, -i, -p and -s") - >> option('4',"keygen",test_gen_key,"Test key generation.") - >> option('5',"signature",test_signature,"Test signature.") - >> option('6',"output",test_output,"Test output.") - >> option('7',"memory-encryption",test_memory_encryption,"Test output.") - >> option('F',"fulltest",full_test,"Test everything.") - >> parameter('f',"file",file_to_encrypt,"File to encrypt. Used with -3",false) - >> parameter('p',"pubring",pubring_file,"Public keyring file.",false) - >> parameter('s',"secring",secring_file,"Secret keyring file.",false) - >> parameter('i',"keyid",key_id_string,"Key id to use. If not supplied, will be asked.",false) - >> help() ; - - as.defaultErrorHandling() ; - - if(!full_test) - if(test_pgpid_type + test_keyring_read + test_file_encryption + test_gen_key + test_signature + test_output + test_memory_encryption != 1) - { - std::cerr << "Options 1 to 6 are mutually exclusive." << std::endl; - return 1; - } - if(full_test || test_pgpid_type) - { - // test pgp ids. - // - std::string st("3e5b22140ef56abb") ; - PGPIdType id = PGPIdType(std::string(st)) ; - - //std::cerr << "Id is : " << std::hex << id.toUInt64() << std::endl; - std::cerr << "Id st : " << id.toStdString() << std::endl; - - CHECK(id.toStdString(false) == st) ; - } - - // test PGPHandler - // - // 0 - init - - std::string pubring = pubring_file.empty()?"pubring.gpg":pubring_file ; - std::string secring = secring_file.empty()?"secring.gpg":secring_file ; - - static const std::string trustdb = "trustdb.gpg" ; - static const std::string lockfile = "lock" ; - - PGPHandler::setPassphraseCallback(&passphrase_callback) ; - PGPHandler pgph(pubring,secring,trustdb,lockfile) ; - - std::string email_str("test@gmail.com") ; - std::string name_str("test") ; - std::string passw_str("test00") ; - PGPIdType cert_id ; ; - - if(full_test || test_gen_key) - { - std::cerr << "Now generating a new PGP certificate: " << std::endl; - std::cerr << " email: " << email_str << std::endl; - std::cerr << " passw: " << passw_str << std::endl; - std::cerr << " name : " << name_str << std::endl; - - PGPIdType newid ; - std::string errString ; - static_passphrase = passw_str ; - - bool res = pgph.GeneratePGPCertificate(name_str, email_str, passw_str, newid, errString) ; - - cert_id = newid ; - - CHECK(res) ; - - if(!res) - std::cerr << "Generation of certificate returned error: " << errString << std::endl; - else - std::cerr << "Certificate generation success. New id = " << newid.toStdString() << std::endl; - } - - if(full_test) - key_id_string = cert_id.toStdString(true) ; - - if(full_test || test_keyring_read) - { - pgph.printKeys() ; - - std::cerr << std::endl ; - std::cerr << std::endl ; - - std::cerr << "Looking for keys with complete secret/public key pair: " << std::endl; - - std::list lst ; - pgph.availableGPGCertificatesWithPrivateKeys(lst) ; - - bool found = false ; - - for(std::list::const_iterator it(lst.begin());it!=lst.end();++it) - { - std::cerr << "Found id : " << (*it).toStdString() << std::endl; - if(cert_id == *it) - found = true ; - } - CHECK(found) ; - } - - if(full_test || test_output) - { - PGPIdType id2( (key_id_string.empty())?askForKeyId(pgph):key_id_string) ; - - std::cerr << "Now extracting key " << id2.toStdString() << " from keyring:" << std::endl ; - std::string cert = pgph.SaveCertificateToString(id2,false) ; - - std::cerr << "Now, trying to re-read this cert from the string:" << std::endl; - - PGPIdType id3 ; - std::string error_string ; - pgph.LoadCertificateFromString(cert,id3,error_string) ; - - std::cerr << "Loaded cert id: " << id3.toStdString() << ", Error string=\"" << error_string << "\"" << std::endl; - - CHECK(id3 == id2) ; - - std::cerr << cert << std::endl; - } - - if(test_passphrase_callback) - { - std::cerr << "Testing password callback: " << std::endl; - std::string newid = "XXXXXXXXXXXXXXXX" ; - std::string pass = passphrase_callback(NULL,newid.c_str(),"Please enter password: ",false) ; - std::cerr << "Password = \"" << pass << "\"" << std::endl; - } - - if(full_test || test_signature) - { - if(key_id_string.empty()) - key_id_string = askForKeyId(pgph) ; - - PGPIdType key_id(key_id_string) ; - std::cerr << "Testing signature with keypair " << key_id_string << std::endl; - - static const size_t BUFF_LEN = 25 ; - unsigned char *test_bin = new unsigned char[BUFF_LEN] ; - for(size_t i=0;i -#include -#include -#include -#include - -INITTEST() ; - -static std::string passphrase_callback(void *data,const char *uid_info,const char *what,int prev_was_bad) -{ - return std::string(getpass(what)) ; -} - -static std::string stringFromBytes(unsigned char *bytes,size_t len) -{ - static const char out[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' } ; - - std::string res ; - - for(int j = 0; j < len; j++) - { - res += out[ (bytes[j]>>4) ] ; - res += out[ bytes[j] & 0xf ] ; - } - - return res ; -} - -int main(int argc,char *argv[]) -{ - // test pgp ids. - // - PGPIdType id("3e5b22140ef56abb") ; - - std::cerr << "Id st : " << id.toStdString() << std::endl; - - // test PGPHandler - // - // 0 - init - - static const std::string pubring = "pubring.gpg" ; - static const std::string secring = "secring.gpg" ; - static const std::string trustdb = "trustdb.gpg" ; - static const std::string lockfil = "lock" ; - - PGPHandler::setPassphraseCallback(&passphrase_callback) ; - PGPHandler pgph(pubring,secring,trustdb,lockfil) ; - - pgph.printKeys() ; - - FINALREPORT("Signature parsing") ; - - return TESTRESULT() ; -} - diff --git a/libretroshare/src/tests/pgp/test_pubring.gpg b/libretroshare/src/tests/pgp/test_pubring.gpg deleted file mode 100644 index 338dfe86b..000000000 Binary files a/libretroshare/src/tests/pgp/test_pubring.gpg and /dev/null differ diff --git a/libretroshare/src/tests/pqi/TestNotes.txt b/libretroshare/src/tests/pqi/TestNotes.txt deleted file mode 100644 index 6d6089e9b..000000000 --- a/libretroshare/src/tests/pqi/TestNotes.txt +++ /dev/null @@ -1,94 +0,0 @@ - -There are a huge amount of testing to be done here. - -Components and Tests. -============================================================ ------------------------------------------------------------- -Basic Components ------------------------------------------------------------- -pqinetwork.cc: net_test, net_test1, netiface_test -pqi_base.cc: no need. -pqimonitor.cc: no need. -p3notify.cc: no need. -pqisecurity.cc: no need. -pqiservice.cc: no need. -cleanupxpgp.cc to test. - ------------------------------------------------------------- -Serialisation Components ------------------------------------------------------------- -pqiarchive.cc: pqiarchive_test -pqibin.cc: pqiarchive_test -pqistreamer.cc -pqistore.cc - ------------------------------------------------------------- -SSL Network Components ------------------------------------------------------------- -pqiloopback.cc -pqissltunnel.cc -pqissludp.cc -pqissl.cc -pqiperson.cc -pqipersongrp.cc -pqisslpersongrp.cc -pqissllistener.cc - ------------------------------------------------------------- -Authentication Components ------------------------------------------------------------- -sslcert.cc -xpgpcert.cc -authgpg.cc -authssl.cc - ------------------------------------------------------------- -Manager Components ------------------------------------------------------------- -p3connmgr.cc -pqihandler.cc -p3dhtmgr.cc: dht_test -p3cfgmgr.cc - -============================================================ -Test Specifics -============================================================ ------------------------------------------------------------- -net_test ------------------------------------------------------------- -Tested Code: pqinetwork.cc, rsnet.cc -Description: -(1) Tests ntohll / htonll -(3) Tests socket binding. - ------------------------------------------------------------- -net_test1 ------------------------------------------------------------- -Tested Code: pqinetwork.cc, rsnet.cc -Description: -(1) isExternalNet() -(2) isPrivateNet() -(3) isLoopbackNet() -(5) isValidNet() - ------------------------------------------------------------- -pqiarchive_test ------------------------------------------------------------- -Tested Code: pqiarchive.cc pqibin.cc -Description : - Stores increasingly large packets into an archive file then retrieves them. - - NOTE: This tests packets up to size of 1Mb. This causes the test to FAIL - due to getRsPktMaxSize() returning 262142.... What to do? This needs to be fixed! - - see comments at serialiser/rsserial.cc line 448 - ------------------------------------------------------------- -dht_test ------------------------------------------------------------- -Tested Code : p3dhtmgr.cc -Description : - -This is a manual test of the DHT manager. needs to be -converted to an automatic test. - diff --git a/libretroshare/src/tests/pqi/conn_harness.cc b/libretroshare/src/tests/pqi/conn_harness.cc deleted file mode 100644 index 72da573d4..000000000 --- a/libretroshare/src/tests/pqi/conn_harness.cc +++ /dev/null @@ -1,284 +0,0 @@ -/* - * libretroshare/src/test/pqi testconnect.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * pqiperson acts as the wrapper for all connection methods to a single peer. - * - * This test creates, a pqiperson and simulates connections, disconnections. - * packets passing through. - * - */ - - -#include "conn_harness.h" -#include "pqi/pqibin.h" -#include -#include - -/******************************************************* - * - * Test structure - *****************/ - - -/* static test variables */ -uint32_t testCounter = 0; -pqiconnect *testConnectPointer[NUM_CONN_MAX]; -PQInterface *testConnectParent[NUM_CONN_MAX]; -uint32_t testConnectState[NUM_CONN_MAX]; -std::list testConnectTimes[NUM_CONN_MAX]; -std::list testConnectAddrs[NUM_CONN_MAX]; - -std::list testResetState[NUM_CONN_MAX]; -std::list testResetTimes[NUM_CONN_MAX]; - -uint32_t testConnectAction[NUM_CONN_MAX] = { 0 }; -rstime_t testConnectPeriod[NUM_CONN_MAX] = { 0 }; - -uint32_t defTestConnectAction = TST_ACTION_FAILED; - - -uint32_t findWhichConnect(pqiconnect *conn) -{ - int i; - for(i = 0; i < NUM_CONN_MAX; i++) - { - if (testConnectPointer[i] == conn) - { - return i; - } - } - // error. - std::cerr << "Connect Missing" << std::endl; - exit(1); - return 0; -} - -void addTestConnect(pqiconnect *pqi, PQInterface *parent) -{ - testConnectPointer[testCounter] = pqi; - testConnectParent[testCounter] = parent; - testConnectState[testCounter] = 0; - testCounter++; - if (testCounter > NUM_CONN_MAX) - { - std::cerr << "Too Many Connects" << std::endl; - exit(1); - } -} - -void resetTestConnects() -{ - testCounter = 0; - int i; - for(i = 0; i < NUM_CONN_MAX; i++) - { - testConnectAddrs[i].clear(); - testConnectTimes[i].clear(); - testResetState[i].clear(); - testResetTimes[i].clear(); - } -} - -/* setup callback actions */ -void setDefaultTestConnectAction(uint32_t action) -{ - defTestConnectAction = action; -} - -void forceConnect(uint32_t idx) -{ - /* flag as con */ -} - - -testConnect::testConnect(RsSerialiser *rss, NetBinInterface *ni_in) - :pqiconnect(rss, ni_in) -{ - -} - -testConnect::~testConnect() -{ - return; -} - - /* dummyConnect */ -int testConnect::connect(struct sockaddr_in raddr) -{ - int cidx = findWhichConnect(this); - rstime_t now = time(NULL); - - testConnectState[cidx] |= TST_STATE_CONNECT; - testConnectTimes[cidx].push_back(now); - testConnectAddrs[cidx].push_back(raddr); - testConnectAction[cidx] = defTestConnectAction; - - std::cerr << "testConnect[" << cidx << "].connect() called"; - std::cerr << std::endl; - return 0; -} - -int testConnect::listen() -{ - int cidx = findWhichConnect(this); - testConnectState[cidx] |= TST_STATE_LISTEN; - std::cerr << "testConnect[" << cidx << "].listen() called"; - std::cerr << std::endl; - return 1; -} - -int testConnect::stoplistening() -{ - int cidx = findWhichConnect(this); - testConnectState[cidx] &= ~TST_STATE_LISTEN; - std::cerr << "testConnect[" << cidx << "].stoplistening() called"; - std::cerr << std::endl; - return 1; -} - -int testConnect::reset() -{ - int cidx = findWhichConnect(this); - rstime_t now = time(NULL); - - // reset everything except listening. - testResetState[cidx].push_back(testConnectState[cidx]); - testResetTimes[cidx].push_back(now); - testConnectState[cidx] &= TST_STATE_LISTEN; - - std::cerr << "testConnect[" << cidx << "].reset() called"; - std::cerr << std::endl; - return 1; -} - -// leave this as is virtual int disconnect() { return ni -> reset(); } - -bool testConnect::connect_parameter(uint32_t type, uint32_t value) -{ - int cidx = findWhichConnect(this); - //testConnectState[cidx] |= TST_STATE_LISTEN; - std::cerr << "testConnect[" << cidx << "].connect_parameter() called"; - std::cerr << std::endl; - - /* sum up PERIOD and DELAY */ - if (type == NET_PARAM_CONNECT_DELAY) - { - std::cerr << "PARAMETER: DELAY: " << value; - std::cerr << std::endl; - - //testConnectPeriod[cidx] = value; - } - else if (type == NET_PARAM_CONNECT_PERIOD) - { - std::cerr << "PARAMETER: PERIOD: " << value; - std::cerr << std::endl; - - //testConnectPeriod[cidx] += value; - } - else if (type == NET_PARAM_CONNECT_TIMEOUT) - { - std::cerr << "PARAMETER: TIMEOUT: " << value; - std::cerr << std::endl; - - testConnectPeriod[cidx] = value; - //testConnectPeriod[cidx] += value; - } - std::cerr << "total testConnectPeriod: " << testConnectPeriod[cidx]; - std::cerr << std::endl; - - return true; -} - -int testConnect::getConnectAddress(struct sockaddr_in &raddr) -{ - int cidx = findWhichConnect(this); - if (testConnectAddrs[cidx].size() > 0) - { - raddr = testConnectAddrs[cidx].back(); - return 1; - } - std::cerr << "testConnect[" << cidx << "].getConnectAddress() called"; - std::cerr << std::endl; - return 0; -} - - -int testConnect::tick() -{ - int cidx = findWhichConnect(this); - - std::cerr << "testConnect[" << cidx << "].tick()"; - std::cerr << std::endl; - - if (testConnectState[cidx] & TST_STATE_CONNECT) - { - rstime_t now = time(NULL); - rstime_t cTime = testConnectTimes[cidx].back(); - if (now - cTime > testConnectPeriod[cidx]) - { - - std::cerr << "testConnect[" << cidx << "].tick() reached ConnectPeriod"; - std::cerr << " age: " << now - cTime << " period: " << testConnectPeriod[cidx]; - std::cerr << std::endl; - - PQInterface *connParent = testConnectParent[cidx]; - - testConnectState[cidx] &= ~TST_STATE_CONNECT; - /* do callback now */ - if (testConnectAction[cidx] == TST_ACTION_SUCCESS) - { - std::cerr << "testConnect[" << cidx << "].tick() CONNECTED callback"; - std::cerr << std::endl; - - testConnectState[cidx] &= ~TST_STATE_CONNECTED; - /* do callback */ - connParent -> notifyEvent(this->ni, NET_CONNECT_SUCCESS); - - } - else if (testConnectAction[cidx] == TST_ACTION_FAILED) - { - std::cerr << "testConnect[" << cidx << "].tick() FAILED callback"; - std::cerr << std::endl; - - /* do callback */ - connParent -> notifyEvent(this->ni, NET_CONNECT_FAILED); - - } - else - { - std::cerr << "testConnect[" << cidx << "].tick() no callback (BAD)"; - std::cerr << std::endl; - } - - } - } - return 0; -} - - - - - diff --git a/libretroshare/src/tests/pqi/conn_harness.h b/libretroshare/src/tests/pqi/conn_harness.h deleted file mode 100644 index 697faca99..000000000 --- a/libretroshare/src/tests/pqi/conn_harness.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef TEST_PQICONNECT_H -#define TEST_PQICONNECT_H - -/* - * libretroshare/src/test/pqi testconnect.h - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2007-2010 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "pqi/pqiperson.h" -//#include "pqi/pqibin.h" -#include "util/rsnet.h" - -/******************************************************* - * - * Test structure - *****************/ - - -#define NUM_CONN_MAX 50 - -#define TST_STATE_CONNECT 0x0001 -#define TST_STATE_LISTEN 0x0002 -#define TST_STATE_CONNECTED 0x0004 - -#define TST_ACTION_NONE 0x0000 -#define TST_ACTION_FAILED 0x0001 -#define TST_ACTION_SUCCESS 0x0002 - -/* static test variables */ -extern uint32_t testCounter; -extern pqiconnect *testConnectPointer[NUM_CONN_MAX]; -extern uint32_t testConnectState[NUM_CONN_MAX]; -extern std::list testConnectTimes[NUM_CONN_MAX]; -extern std::list testConnectAddrs[NUM_CONN_MAX]; - -extern std::list testResetState[NUM_CONN_MAX]; -extern std::list testResetTimes[NUM_CONN_MAX]; - -uint32_t findWhichConnect(pqiconnect *conn); -void addTestConnect(pqiconnect *pqi, PQInterface *parent); -void resetTestConnects(); - -void setDefaultTestConnectAction(uint32_t action); - -class testConnect: public pqiconnect -{ - public: - - testConnect(RsSerialiser *rss, NetBinInterface *ni_in); - virtual ~testConnect(); - - /* dummyConnect */ - virtual int tick(); - virtual int connect(struct sockaddr_in raddr); - virtual int listen(); - virtual int stoplistening(); - virtual int reset(); - virtual bool connect_parameter(uint32_t type, uint32_t value); - virtual int getConnectAddress(struct sockaddr_in &raddr); -}; // end of testConnect. - - -pqiperson *createTestPerson(std::string id, pqipersongrp *ppg); - - -#endif - diff --git a/libretroshare/src/tests/pqi/conn_test.cc b/libretroshare/src/tests/pqi/conn_test.cc deleted file mode 100644 index 57ffceafe..000000000 --- a/libretroshare/src/tests/pqi/conn_test.cc +++ /dev/null @@ -1,363 +0,0 @@ - - -#include "pqi/p3connmgr.h" - - -/***** Test for the new DHT system *****/ - - -#include "util/rsnet.h" -#include "util/rsthreads.h" -#include "util/rsprint.h" -#include "pqi/p3dhtmgr.h" -#include "pqi/p3connmgr.h" -#error secpolicy was removed, also remove it from test to fix compile -#include "pqi/pqisecurity.h" -#include "pqi/pqipersongrp.h" - -#include -#include - -#include "tcponudp/udpsorter.h" - -/***** Test Framework *****/ - -const int NumOfPeers = 10; -std::string peerIds[NumOfPeers] = - {"PEER01", - "PEER02", /* Always online, no notify */ - "PEER03", /* notify/online at 20sec */ - "PEER04", /* Always online, notify at 30 sec */ - "PEER05", - "PEER06", /* notify/online at 50sec */ - "PEER07", - "PEER08", - "PEER09", /* notify/online at 80sec */ - "PEER10"}; - -#define STUN_PORT 7777 - -std::string ownId = "OWNID-AAAA"; -rstime_t ownPublishTs; - -RsMutex frmMtx; -std::list searchIds; -std::list searchModes; - -std::map onlineMap; -std::map notifyMap; - -void initTestData() -{ - ownPublishTs = 0; - /* setup Peers that are online always */ - bool online; - uint32_t ts; - for(int i = 0; i < NumOfPeers; i++) - { - online = false; - if ((i == 1) || (i == 3)) - { - online = true; - } - onlineMap[peerIds[i]] = online; - - if ((i == 2) || (i == 3) || - (i == 5) || (i == 8)) - { - ts = i * 10; - notifyMap[ts] = peerIds[i]; - } - } -} - -void respondPublish() -{ - frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ - if (!ownPublishTs) - { - std::cerr << "Own ID first published!" << std::endl; - ownPublishTs = time(NULL); - } - frmMtx.unlock(); /* UNLOCK TEST FRAMEWORK MUTEX */ -} - -void respondSearch(p3DhtMgr *mgr, std::string id, uint32_t mode) -{ - std::cerr << "Checking for Search Results" << std::endl; - rstime_t now = time(NULL); - bool doNotify = false; - bool doOnline = false; - std::string notifyId; - - frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ - if ((mode == DHT_MODE_NOTIFY) && (ownPublishTs)) - { - /* */ - std::map::iterator it; - uint32_t delta_t = now - ownPublishTs; - it = notifyMap.begin(); - if (it != notifyMap.end()) - { - if (it->first <= delta_t) - { - notifyId = it->second; - onlineMap[notifyId] = true; - notifyMap.erase(it); - doNotify = true; - } - } - } - else if (mode == DHT_MODE_SEARCH) - { - - /* translate */ - std::map::iterator mit; - for(mit = onlineMap.begin(); (mit != onlineMap.end()) && - (RsUtil::HashId(mit->first, false) != id); mit++); - - if (mit != onlineMap.end()) - { - doOnline = mit->second; - } - } - - frmMtx.unlock(); /* UNLOCK TEST FRAMEWORK MUTEX */ - - uint32_t type = 0; - - struct sockaddr_in laddr; - inet_aton("10.0.0.129", &(laddr.sin_addr)); - laddr.sin_port = htons(7812); - laddr.sin_family = AF_INET; - - struct sockaddr_in raddr; - inet_aton("127.0.0.1", &(raddr.sin_addr)); - raddr.sin_port = htons(STUN_PORT); - raddr.sin_family = AF_INET; - - if (doNotify) - { - std::cerr << "Responding to Notify: id:" << notifyId << std::endl; - mgr->dhtResultNotify(RsUtil::HashId(notifyId, true)); - } - - if (doOnline) - { - std::cerr << "Responding to Search" << std::endl; - mgr->dhtResultSearch(id, laddr, raddr, type, ""); - } - -} - - -/***** Test Framework *****/ - -class DhtMgrTester: public p3DhtMgr -{ - - /* Implementation */ - public: - - DhtMgrTester(std::string id, pqiConnectCb *cb) - :p3DhtMgr(id, cb) - { - return; - } - - - - - - /* Blocking calls (only from thread) */ -virtual bool dhtPublish(std::string id, - struct sockaddr_in &laddr, struct sockaddr_in &raddr, - uint32_t type, std::string sign) -{ - std::cerr << "DhtMgrTester::dhtPublish() id: " << RsUtil::BinToHex(id); - std::cerr << " laddr: " << rs_inet_ntoa(laddr.sin_addr) << " lport: " << ntohs(laddr.sin_port); - std::cerr << " raddr: " << rs_inet_ntoa(raddr.sin_addr) << " rport: " << ntohs(raddr.sin_port); - std::cerr << " type: " << type << " sign: " << sign; - std::cerr << std::endl; - - respondPublish(); - - return true; -} - -virtual bool dhtNotify(std::string peerid, std::string ownid, std::string sign) -{ - std::cerr << "DhtMgrTester::dhtNotify() id: " << RsUtil::BinToHex(peerid) << ", ownId: " << RsUtil::BinToHex(ownId); - std::cerr << " sign: " << sign; - std::cerr << std::endl; - - return true; -} - -virtual bool dhtSearch(std::string id, uint32_t mode) -{ - std::cerr << "DhtMgrTester::dhtSearch(id: " << RsUtil::BinToHex(id) << ", mode: " << mode << ")" << std::endl; - - frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ - searchIds.push_back(id); - searchModes.push_back(mode); - frmMtx.unlock(); /* LOCK TEST FRAMEWORK MUTEX */ - - return true; -} - -}; - - -/* OVERLOAD THE ConnMgr - to insert peers */ -class p3TestConnMgr: public p3ConnectMgr -{ - public: - p3TestConnMgr(int mode) - :p3ConnectMgr(new p3DummyAuthMgr()), mTestMode(mode) { return; } - - protected: - /* must be virtual for testing */ -virtual void loadConfiguration() -{ - - /* setup own address */ - ownState.id = ownId; - ownState.name = "SELF NAME"; - ownState.localaddr.sin_family = AF_INET; - inet_aton("127.0.0.1", &(ownState.localaddr.sin_addr)); - ownState.localaddr.sin_port = htons(7812); - ownState.netMode = RS_NET_MODE_UDP; - ownState.visState = RS_VIS_STATE_STD; - - /* others not important */ - //ownState.state = 0; - //ownState.actions = 0; - - - if (mTestMode == 1) /* Add to Stun List */ - { - for(int i = 0; i < NumOfPeers; i++) - { - mStunList.push_back(peerIds[i]); - } - } - else if (mTestMode == 2) /* add to peers */ - { - /* add in as peers */ - //addPeer(); - for(int i = 0; i < NumOfPeers; i++) - { - if (i < 5) - { - mStunList.push_back(RsUtil::HashId(peerIds[i])); - } - else - { - addFriend(peerIds[i]); - } - } - } -} - - protected: - - uint32_t mTestMode; -}; - - -int main() -{ - rstime_t startTime = time(NULL); - /* setup system */ - initTestData(); - - /* setup a Stunner to respond to ConnMgr */ - - struct sockaddr_in saddr; - saddr.sin_family = AF_INET; - inet_aton("127.0.0.1", &(saddr.sin_addr)); - saddr.sin_port = htons(STUN_PORT); - UdpSorter stunner(saddr); /* starts a receiving thread */ - - p3TestConnMgr connMgr(2); - DhtMgrTester dhtTester(ownId, &connMgr); - - /* now add in some peers */ - connMgr.setDhtMgr(&dhtTester); - connMgr.setUpnpMgr(NULL); - - /************ ADD pqipersongrp as pqimonitor *****************/ -#error secpolicy was removed, should remove it from tests too - SecurityPolicy *pol = secpolicy_create(); - unsigned long flags = 0; - pqipersongrp *pqipg = new pqipersongrpDummy(pol, flags); - - connMgr.addMonitor(pqipg); - - /************ ADD pqipersongrp as pqimonitor *****************/ - - - /* startup dht */ - std::cerr << "Starting up DhtTester()" << std::endl; - dhtTester.start(); - - /* wait for a little before switching on */ -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - sleep(1); -#else - Sleep(1000); -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - std::cerr << "Switching on DhtTester()" << std::endl; - dhtTester.setDhtOn(true); - - /* wait loop */ - while(1) - { -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - sleep(1); -#else - Sleep(1000); -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - connMgr.tick(); - pqipg->tick(); - - /* handle async search */ - frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ - - std::string id; - uint32_t mode; - bool doRespond = false; - if (searchIds.size() > 0) - { - id = searchIds.front(); - mode = searchModes.front(); - doRespond = true; - searchIds.pop_front(); - searchModes.pop_front(); - } - - frmMtx.unlock(); /* UNLOCK TEST FRAMEWORK MUTEX */ - - if (doRespond) - { - respondSearch(&dhtTester, id, mode); - } - } -}; - - - - - - - - - - diff --git a/libretroshare/src/tests/pqi/dht_test.cc b/libretroshare/src/tests/pqi/dht_test.cc deleted file mode 100644 index ccfd117b5..000000000 --- a/libretroshare/src/tests/pqi/dht_test.cc +++ /dev/null @@ -1,310 +0,0 @@ - - -/***** Test for the new DHT system *****/ - - -#include "pqi/pqinetwork.h" - -#include "util/rsnet.h" -#include "util/rsthreads.h" -#include "util/rsprint.h" - -#include "pqi/p3dhtmgr.h" - -#include -#include - - -/***** Test Framework *****/ - -const int NumOfPeers = 10; -std::string peerIds[NumOfPeers] = - {"PEER01", - "PEER02", /* Always online, no notify */ - "PEER03", /* notify/online at 20sec */ - "PEER04", /* Always online, notify at 30 sec */ - "PEER05", - "PEER06", /* notify/online at 50sec */ - "PEER07", - "PEER08", - "PEER09", /* notify/online at 80sec */ - "PEER10"}; - -std::string ownId = "AAAA"; -rstime_t ownPublishTs; - -RsMutex frmMtx; -std::list searchIds; -std::list searchModes; - -std::map onlineMap; -std::map notifyMap; - -void initTestData() -{ - ownPublishTs = 0; - /* setup Peers that are online always */ - bool online; - uint32_t ts; - for(int i = 0; i < NumOfPeers; i++) - { - online = false; - if ((i == 1) || (i == 3)) - { - online = true; - } - onlineMap[peerIds[i]] = online; - - if ((i == 2) || (i == 3) || - (i == 5) || (i == 8)) - { - ts = i * 10; - notifyMap[ts] = peerIds[i]; - } - } -} - -void respondPublish() -{ - frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ - if (!ownPublishTs) - { - std::cerr << "Own ID first published!" << std::endl; - ownPublishTs = time(NULL); - } - frmMtx.unlock(); /* UNLOCK TEST FRAMEWORK MUTEX */ -} - -void respondSearch(p3DhtMgr *mgr, std::string id, uint32_t mode) -{ - std::cerr << "Checking for Search Results" << std::endl; - rstime_t now = time(NULL); - bool doNotify = false; - bool doOnline = false; - std::string notifyId; - - frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ - if ((mode == DHT_MODE_NOTIFY) && (ownPublishTs)) - { - /* */ - std::map::iterator it; - uint32_t delta_t = now - ownPublishTs; - it = notifyMap.begin(); - if (it != notifyMap.end()) - { - if (it->first <= delta_t) - { - notifyId = it->second; - onlineMap[notifyId] = true; - notifyMap.erase(it); - doNotify = true; - } - } - } - else if (mode == DHT_MODE_SEARCH) - { - /* translate */ - std::map::iterator mit; - for(mit = onlineMap.begin(); (mit != onlineMap.end()) && - (RsUtil::HashId(mit->first, false) != id); mit++); - - if (mit != onlineMap.end()) - { - doOnline = mit->second; - } - } - - frmMtx.unlock(); /* UNLOCK TEST FRAMEWORK MUTEX */ - - uint32_t type = 0; - - struct sockaddr_in laddr; - inet_aton("10.0.0.129", &(laddr.sin_addr)); - laddr.sin_port = htons(7812); - laddr.sin_family = AF_INET; - - struct sockaddr_in raddr; - inet_aton("10.0.0.19", &(raddr.sin_addr)); - raddr.sin_port = htons(7812); - raddr.sin_family = AF_INET; - - if (doNotify) - { - std::cerr << "Responding to Notify" << std::endl; - mgr->dhtResultNotify(RsUtil::HashId(notifyId, true)); - } - - if (doOnline) - { - std::cerr << "Responding to Search" << std::endl; - mgr->dhtResultSearch(id, laddr, raddr, type, ""); - } -} - - - - - - -/***** Test Framework *****/ - - - - -class DhtMgrTester: public p3DhtMgr -{ - - /* Implementation */ - public: - - DhtMgrTester(std::string id, pqiConnectCb *cb) - :p3DhtMgr(id, cb) - { - return; - } - - - /* Blocking calls (only from thread) */ -virtual bool dhtPublish(std::string id, - struct sockaddr_in &laddr, struct sockaddr_in &raddr, - uint32_t type, std::string sign) -{ - std::cerr << "DhtMgrTester::dhtPublish() id: " << RsUtil::BinToHex(id); - std::cerr << " laddr: " << rs_inet_ntoa(laddr.sin_addr) << " lport: " << ntohs(laddr.sin_port); - std::cerr << " raddr: " << rs_inet_ntoa(raddr.sin_addr) << " rport: " << ntohs(raddr.sin_port); - std::cerr << " type: " << type << " sign: " << sign; - std::cerr << std::endl; - - respondPublish(); - - return true; -} - -virtual bool dhtNotify(std::string peerid, std::string ownid, std::string sign) -{ - std::cerr << "DhtMgrTester::dhtNotify() id: " << RsUtil::BinToHex(peerid) << ", ownId: " << RsUtil::BinToHex(ownId); - std::cerr << " sign: " << sign; - std::cerr << std::endl; - - return true; -} - -virtual bool dhtSearch(std::string id, uint32_t mode) -{ - std::cerr << "DhtMgrTester::dhtSearch(id: " << RsUtil::BinToHex(id) << ", mode: " << mode << ")" << std::endl; - - frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ - searchIds.push_back(id); - searchModes.push_back(mode); - frmMtx.unlock(); /* LOCK TEST FRAMEWORK MUTEX */ - - return true; -} - -}; - -int main() -{ - rstime_t startTime = time(NULL); - bool haveOwnAddress = false; - /* setup system */ - initTestData(); - - pqiConnectCbDummy cbTester; - DhtMgrTester dhtTester(ownId, &cbTester); - - /* now add in some peers */ - - /* startup dht */ - std::cerr << "Starting up DhtTester()" << std::endl; - dhtTester.start(); - - /* wait for a little before switching on */ -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - sleep(1); -#else - Sleep(1000); -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - std::cerr << "Switching on DhtTester()" << std::endl; - dhtTester.enable(true); - - std::cerr << "Adding a List of Peers" << std::endl; - for(int i = 0; i < NumOfPeers; i++) - { - dhtTester.findPeer(peerIds[i]); - } - - - /* wait loop */ - while(1) - { - std::cerr << "Main waiting..." << std::endl; -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - sleep(3); -#else - Sleep(3000); -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - - /* handle async search */ - frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ - - std::string id; - uint32_t mode; - bool doRespond = false; - if (searchIds.size() > 0) - { - id = searchIds.front(); - mode = searchModes.front(); - doRespond = true; - searchIds.pop_front(); - searchModes.pop_front(); - } - - frmMtx.unlock(); /* UNLOCK TEST FRAMEWORK MUTEX */ - - if (doRespond) - { - respondSearch(&dhtTester, id, mode); - } - - if (!haveOwnAddress) - { - if (time(NULL) - startTime > 20) - { - std::cerr << "Setting Own Address!" << std::endl; - haveOwnAddress = true; - - uint32_t type = DHT_ADDR_UDP; - - struct sockaddr_in laddr; - inet_aton("10.0.0.111", &(laddr.sin_addr)); - laddr.sin_port = htons(7812); - laddr.sin_family = AF_INET; - - struct sockaddr_in raddr; - inet_aton("10.0.0.11", &(raddr.sin_addr)); - raddr.sin_port = htons(7812); - raddr.sin_family = AF_INET; - - dhtTester.setExternalInterface(laddr, raddr, type); - } - } - - } -}; - - - - - - - - - - diff --git a/libretroshare/src/tests/pqi/dnsresolver_test.cc b/libretroshare/src/tests/pqi/dnsresolver_test.cc deleted file mode 100644 index 2a20ecc90..000000000 --- a/libretroshare/src/tests/pqi/dnsresolver_test.cc +++ /dev/null @@ -1,83 +0,0 @@ - -/* - * "$Id:$" - * - * RetroShare C++ Interface. - * - * Copyright 2010-2011 by Cyril Soler - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - -#include "util/dnsresolver.h" - -#include -#include -#include - -int main() -{ - std::list names; - - DNSResolver *r = new DNSResolver ; - - names.push_back("cortinaire.inrialpes.fr") ; - names.push_back("www.google.com") ; - names.push_back("www.ego.cn") ; - names.push_back("free.fr") ; - - for(int i=0;i<5;++i) - { - for(std::list::const_iterator it = names.begin(); it != names.end(); it++) - { - in_addr addr ; - bool res = r->getIPAddressFromString(*it,addr) ; - - if(res) - std::cerr << "Lookup of " << *it << ": " << (res?"done":"pending") << ": addr = " << (void*)addr.s_addr << std::endl; - else - std::cerr << "Lookup of " << *it << ": " << (res?"done":"pending") << std::endl; - } - - std::cerr << std::endl; - usleep(200000) ; - } - - r->reset() ; - - for(int i=0;i<5;++i) - { - for(std::list::const_iterator it = names.begin(); it != names.end(); it++) - { - in_addr addr ; - bool res = r->getIPAddressFromString(*it,addr) ; - - if(res) - std::cerr << "Lookup of " << *it << ": " << (res?"done":"pending") << ": addr = " << (void*)addr.s_addr << std::endl; - else - std::cerr << "Lookup of " << *it << ": " << (res?"done":"pending") << std::endl ; - } - std::cerr << std::endl; - usleep(200000) ; - } - - delete r ; -} - diff --git a/libretroshare/src/tests/pqi/extaddrfinder_test.cc b/libretroshare/src/tests/pqi/extaddrfinder_test.cc deleted file mode 100644 index 550011d09..000000000 --- a/libretroshare/src/tests/pqi/extaddrfinder_test.cc +++ /dev/null @@ -1,37 +0,0 @@ -#include "util/utest.h" - -#include -#include "pqi/pqinetwork.h" - -#include -#include - -INITTEST(); - -int main() -{ - std::cerr << "Testing the ext address finder service. This might take up to 10 secs..." << std::endl ; - - ExtAddrFinder fnd ; - in_addr addr ; - uint32_t tries = 0 ; - - while(! fnd.hasValidIP( &addr )) - { - sleep(1) ; - - if(++tries > 20) - { - std::cerr << "Failed !" << std::endl ; - CHECK(false) ; - } - } - - std::cerr << "Found the following IP: " << inet_ntoa(addr) << std::endl ; - - FINALREPORT("extaddrfinder_test"); - - return TESTRESULT() ; -} - - diff --git a/libretroshare/src/tests/pqi/gpgme_tst.c b/libretroshare/src/tests/pqi/gpgme_tst.c deleted file mode 100644 index ec88a8439..000000000 --- a/libretroshare/src/tests/pqi/gpgme_tst.c +++ /dev/null @@ -1,76 +0,0 @@ - -#include "pqi/authgpg.h" - -const std::string key_path("./tmp/privkey.pem"); -const std::string passwd("8764"); -const std::string gpg_passwd("aaaa"); -const std::string name("Test X509"); -const std::string email("test@email.com"); -const std::string org("Org"); -const std::string loc("Loc"); -const std::string state("State"); -const std::string country("GB"); - -int main() -{ - /* Init the auth manager */ - - GPGAuthMgr mgr; - - - /* Select which GPG Keys we use */ - - /* print all keys */ - mgr.printKeys(); - - std::list idList; - mgr.availablePGPCertificates(idList); - - if (idList.size() < 1) - { - fprintf(stderr, "No GPG Certificate to use!\n"); - exit(1); - } - std::string id = idList.front(); - fprintf(stderr, "Using GPG Certificate:%s \n", id.c_str()); - - std::string noname; - mgr.GPGInit(id); - mgr.LoadGPGPassword(gpg_passwd); - - /* Init SSL library */ - mgr.InitAuth(NULL, NULL, NULL); - - /* then try to generate and sign a X509 certificate */ - int nbits_in = 2048; - std::string errString; - - /* Generate a Certificate Request */ - X509_REQ *req = GenerateX509Req(key_path, passwd, name, email, org, - loc, state, country, nbits_in, errString); - - // setup output. - BIO *bio_out = NULL; - bio_out = BIO_new(BIO_s_file()); - BIO_set_fp(bio_out,stdout,BIO_NOCLOSE); - - /* Print it out */ - int nmflag = 0; - int reqflag = 0; - - X509_REQ_print_ex(bio_out, req, nmflag, reqflag); - - X509 *x509 = mgr.SignX509Req(req, 100, gpg_passwd); - - X509_print_ex(bio_out, x509, nmflag, reqflag); - - BIO_flush(bio_out); - BIO_free(bio_out); - - /* now try to validate it */ - mgr.AuthX509(x509); - - //sleep(10); -} - - diff --git a/libretroshare/src/tests/pqi/net_test.cc b/libretroshare/src/tests/pqi/net_test.cc deleted file mode 100644 index ff7744141..000000000 --- a/libretroshare/src/tests/pqi/net_test.cc +++ /dev/null @@ -1,127 +0,0 @@ -/* - * libretroshare/src/test/pqi net_test.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2007-2010 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * NETWORKING Test to check Big/Little Endian behaviour - * as well as socket behaviour - * - */ - -#include "util/utest.h" - -#include "pqi/pqinetwork.h" -#include "util/rsnet.h" -#include -#include - - -bool test_byte_manipulation(); -bool test_local_address_manipulation(); - - -INITTEST(); - -int main(int argc, char **argv) -{ - std::cerr << "libretroshare:pqi " << argv[0] << std::endl; - - test_byte_manipulation(); - - FINALREPORT("libretroshare Net Basics Tests"); - return TESTRESULT(); -} - - /* test 1: byte manipulation */ -bool test_byte_manipulation() -{ - uint64_t num1 = 0x0000000000000000ffULL; /* 255 */ - uint64_t num2 = 0x00000000000000ff00ULL; /* */ - - uint64_t n_num1 = htonll(num1); - uint64_t n_num2 = htonll(num2); - - uint64_t h_num1 = ntohll(n_num1); - uint64_t h_num2 = ntohll(n_num2); - - std::ostringstream out; - out << std::hex; - out << "num1: " << num1 << " netOrder: " << n_num1 << " hostOrder: " << h_num1 << std::endl; - out << "num2: " << num2 << " netOrder: " << n_num2 << " hostOrder: " << h_num2 << std::endl; - - std::cerr << out.str(); - - CHECK( num1 == h_num1 ); - CHECK( num2 == h_num2 ); - - REPORT("Test Byte Manipulation"); - - return true; -} - -const char * loopback_addrstr = "127.0.0.1"; -const char * localnet1_addrstr = "192.168.0.1"; -const char * localnet2_addrstr = "10.0.0.1"; -const char * localnet3_addrstr = "10.5.63.78"; -const char * localnet4_addrstr = "192.168.74.91"; - -bool test_bind_addr(struct sockaddr_in addr); - -bool test_bind_addr(struct sockaddr_in addr) -{ - - int err; - - std::cerr << "test_bind_addr()"; - std::cerr << std::endl; - - std::cerr << "\tAddress Family: " << (int) addr.sin_family; - std::cerr << std::endl; - std::cerr << "\tAddress: " << rs_inet_ntoa(addr.sin_addr); - std::cerr << std::endl; - std::cerr << "\tPort: " << ntohs(addr.sin_port); - std::cerr << std::endl; - - int sockfd = unix_socket(PF_INET, SOCK_STREAM, 0); - CHECK( 0 < sockfd ); - - if (0 != (err = bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)))) - { - std::cerr << " Failed to Bind to Local Address!" << std::endl; - std::string out ; - showSocketError(out) ; - std::cerr << out << std::endl; - - FAILED("Couldn't Bind to socket"); - - return false; - } - - std::cerr << " Successfully Bound Socket to Address" << std::endl; - unix_close(sockfd); - - return true; -} - - diff --git a/libretroshare/src/tests/pqi/net_test1.cc b/libretroshare/src/tests/pqi/net_test1.cc deleted file mode 100644 index fe0f7e353..000000000 --- a/libretroshare/src/tests/pqi/net_test1.cc +++ /dev/null @@ -1,170 +0,0 @@ -/* - * libretroshare/src/pqi net_test.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * NETWORKING Test to check Big/Little Endian behaviour - * as well as socket behaviour - * - */ - -#include "pqi/pqinetwork.h" -#include "util/rsnet.h" -#include -#include -#include "util/utest.h" - -const char * loopback_addrstr = "127.0.0.1"; - -const char * localnet1_addrstr = "10.0.0.1"; -const char * localnet2_addrstr = "169.254.0.1"; -const char * localnet3_addrstr = "172.16.0.1"; -const char * localnet4_addrstr = "192.168.1.1"; - -const char * localnet5_addrstr = "10.4.28.34"; -const char * localnet6_addrstr = "169.254.1.81"; -const char * localnet7_addrstr = "172.20.9.201"; -const char * localnet8_addrstr = "192.168.1.254"; - -const char * external_addrstr = "74.125.19.99"; /* google */ -const char * invalid_addrstr = "AAA.BBB.256.256"; - -int test_isExternalNet(); -int test_isPrivateNet(); -int test_isLoopbackNet(); -int test_isValidNet(); - -INITTEST(); - -int main(int argc, char **argv) -{ - std::cerr << "net_test1" << std::endl; - - test_isExternalNet(); - test_isPrivateNet(); - test_isLoopbackNet(); - test_isValidNet(); - - FINALREPORT("net_test1"); - - return TESTRESULT(); -} - -int test_isExternalNet() -{ - struct in_addr loopback_addr; - struct in_addr localnet1_addr; - struct in_addr localnet2_addr; - struct in_addr localnet3_addr; - struct in_addr localnet4_addr; - struct in_addr external_addr; - struct in_addr invalid_addr; - struct in_addr invalid_addr2; - - inet_aton(loopback_addrstr, &loopback_addr); - inet_aton(localnet1_addrstr, &localnet1_addr); - inet_aton(localnet2_addrstr, &localnet2_addr); - inet_aton(localnet3_addrstr, &localnet3_addr); - inet_aton(localnet4_addrstr, &localnet4_addr); - inet_aton(external_addrstr, &external_addr); - invalid_addr.s_addr = 0; - invalid_addr2.s_addr = -1; - - CHECK(isExternalNet(&loopback_addr)==false); - CHECK(isExternalNet(&localnet1_addr)==false); - CHECK(isExternalNet(&localnet2_addr)==false); - CHECK(isExternalNet(&localnet3_addr)==false); - CHECK(isExternalNet(&localnet4_addr)==false); - CHECK(isExternalNet(&external_addr)==true); - CHECK(isExternalNet(&invalid_addr)==false); - CHECK(isExternalNet(&invalid_addr2)==false); - - REPORT("isExternalNet()"); - - return 1; -} - -int test_isPrivateNet() -{ - struct in_addr loopback_addr; - struct in_addr localnet1_addr; - struct in_addr localnet2_addr; - struct in_addr localnet3_addr; - struct in_addr localnet4_addr; - struct in_addr external_addr; - - inet_aton(loopback_addrstr, &loopback_addr); - inet_aton(localnet1_addrstr, &localnet1_addr); - inet_aton(localnet2_addrstr, &localnet2_addr); - inet_aton(localnet3_addrstr, &localnet3_addr); - inet_aton(localnet4_addrstr, &localnet4_addr); - inet_aton(external_addrstr, &external_addr); - - CHECK(isPrivateNet(&loopback_addr)==false); //loopback not considered a "private network" - CHECK(isPrivateNet(&localnet1_addr)==true); - CHECK(isPrivateNet(&localnet2_addr)==true); - CHECK(isPrivateNet(&localnet3_addr)==true); - CHECK(isPrivateNet(&localnet4_addr)==true); - CHECK(isPrivateNet(&external_addr)==false); - - REPORT("isPrivateNet()"); - - return 1; -} - -int test_isLoopbackNet() -{ - struct in_addr loopback_addr; - struct in_addr localnet1_addr; - struct in_addr external_addr; - - inet_aton(loopback_addrstr, &loopback_addr); - inet_aton(localnet1_addrstr, &localnet1_addr); - inet_aton(external_addrstr, &external_addr); - - CHECK(isLoopbackNet(&loopback_addr)==true); - CHECK(isLoopbackNet(&localnet1_addr)==false); - CHECK(isLoopbackNet(&external_addr)==false); - - REPORT("isLoopbackNet()"); - - return 1; -} - -int test_isValidNet() -{ - struct in_addr localnet1_addr; - struct in_addr invalid_addr; - - inet_aton(localnet1_addrstr, &localnet1_addr); - CHECK(isValidNet(&localnet1_addr)==true); - - CHECK(inet_aton(invalid_addrstr, &invalid_addr)==0); - std::cerr << rs_inet_ntoa(invalid_addr) << std::endl; - //CHECK(isValidNet(&invalid_addr)==false); - - REPORT("isValidNet()"); - - return 1; -} diff --git a/libretroshare/src/tests/pqi/p3connmgr_connect_test.cc b/libretroshare/src/tests/pqi/p3connmgr_connect_test.cc deleted file mode 100644 index 991fb99f3..000000000 --- a/libretroshare/src/tests/pqi/p3connmgr_connect_test.cc +++ /dev/null @@ -1,195 +0,0 @@ -/* - * libretroshare/src/test/pqi p3connmgr_test.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * p3connmgr test module. - * - * create a p3connmgr and run the following tests. - * 1) UDP test - * 2) UPNP test - * 3) ExtAddr test. - * 4) full reset in between. - * - */ - - -#include -#include -#include - - -#include "ppg_harness.h" -#include "conn_harness.h" - -#include "pqi/p3connmgr.h" -#include "pqi/authssltest.h" -#include "pqi/authgpgtest.h" - -#include "pqi/p3dhtmgr.h" -#include "upnp/upnphandler.h" - -#include "util/rsnet.h" -#include -#include -#include "util/utest.h" - -INITTEST(); - -/* generic startup test */ -#define MAX_TIME_SHORT_TEST 10 -#define MAX_TIME_BASIC_TEST 60 - -int run_connect_test(rstime_t timeout); - -/******************************************************* - * - * Test structure - *****************/ - -#define FLAG_UPNP 1 -#define FLAG_UDP 2 -#define FLAG_DHT 4 -#define FLAG_EXT 8 - -p3ConnectMgr *mConnMgr; -pqiNetAssistFirewall *mUpnpMgr = NULL; -p3DhtMgr *mDhtMgr = NULL; - -void createP3ConnMgr(std::string id, uint32_t testFlags) -{ - /* now add test children */ - { - std::cerr << "createP3ConnMgr()"; - std::cerr << std::endl; - } - - mConnMgr = new p3ConnectMgr(); - - mDhtMgr = NULL; //new p3DhtMgr(); - - /* setup status */ - //mConnMgr->setStatus(UPNP); -} - - -/* ACTUAL TEST */ -int main(int argc, char **argv) -{ - /* test p3connmgr net stuff */ - std::cerr << "p3connmgr_net_connect_test" << std::endl; - - // setup test authssl. - setAuthGPG(new AuthGPGtest()); - setAuthSSL(new AuthSSLtest()); - - createP3ConnMgr("abcd", 0); - pqiNetStatus status; - - setupPqiPersonGrpTH(); - - /* install ppg as a monitor */ - - mConnMgr->addMonitor(mPqiPersonGrpTH); - - - std::string peer1_gpgid = "PEERID0001_GPG__"; - std::string peer1_sslid = "PEERID0001_SSL__"; - - /* first test, add a single peer (no Addresses) */ - mConnMgr->addFriend(peer1_sslid, peer1_gpgid); - - run_connect_test(MAX_TIME_SHORT_TEST); - - mConnMgr->getNetStatus(status); - - CHECK(status.mLocalAddrOk == false); - CHECK(status.mExtAddrOk == false); - - // Check that there have been... 1 reset / 0 connects / 1 listen - // per connect. - - REPORT("p3connmgr_connect_test() SINGLE PEER - NO Addresses"); - /* second test, add addresses for peer */ - - rstime_t now = time(NULL); - - pqiIpAddrSet peer1_tst2_addrs; - pqiIpAddress paddr; - inet_aton("192.168.1.1", &(paddr.mAddr.sin_addr)); - paddr.mAddr.sin_port = htons(6411); - paddr.mSeenTime = now - 10; - peer1_tst2_addrs.mLocal.updateIpAddressList(paddr); - - inet_aton("192.168.1.2", &(paddr.mAddr.sin_addr)); - paddr.mAddr.sin_port = htons(6422); - paddr.mSeenTime = now - 20; - peer1_tst2_addrs.mLocal.updateIpAddressList(paddr); - - inet_aton("23.56.25.1", &(paddr.mAddr.sin_addr)); - paddr.mAddr.sin_port = htons(6511); - paddr.mSeenTime = now - 30; - peer1_tst2_addrs.mExt.updateIpAddressList(paddr); - - inet_aton("23.56.25.2", &(paddr.mAddr.sin_addr)); - paddr.mAddr.sin_port = htons(6522); - paddr.mSeenTime = now - 40; - peer1_tst2_addrs.mExt.updateIpAddressList(paddr); - - mConnMgr->updateAddressList(peer1_sslid, peer1_tst2_addrs); - mConnMgr->retryConnect(peer1_sslid); - - run_connect_test(MAX_TIME_BASIC_TEST); - - // Check that there have been: - // 0 Listens / 0 resets. - // 0 connect attempts on UDP - // 4 connect attempts on TCP - // 0 connect attempts on TUNNEL - REPORT("p3connmgr_connect_test() SINGLE PEER - 4 Addresses"); - - /* third test, add an second peer with addresses */ - - /* fourth test, setup default action as connect */ - setDefaultTestConnectAction(TST_ACTION_SUCCESS); -} - -/* Generic restart test */ -int run_connect_test(rstime_t timeout) -{ - /* tick */ - rstime_t start = time(NULL); - bool extAddr = false; - - while ((start > time(NULL) - timeout) && (!extAddr)) - { - mConnMgr->tick(); - tickPqiPersonGrpTH(); - - sleep(1); - } - return 1; -} - - diff --git a/libretroshare/src/tests/pqi/p3connmgr_reset_test.cc b/libretroshare/src/tests/pqi/p3connmgr_reset_test.cc deleted file mode 100644 index d5485101a..000000000 --- a/libretroshare/src/tests/pqi/p3connmgr_reset_test.cc +++ /dev/null @@ -1,320 +0,0 @@ -/* - * libretroshare/src/test/pqi p3connmgr_test.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * p3connmgr test module. - * - * create a p3connmgr and run the following tests. - * 1) UDP test - * 2) UPNP test - * 3) ExtAddr test. - * 4) full reset in between. - * - */ - - -#include -#include -#include - - - - -//#include "pqi/p3connmgr.h" -#include "pqi/authssltest.h" -#include "pqi/authgpgtest.h" - -#include "pqi/p3dhtmgr.h" -#include "upnp/upnphandler_linux.h" - -#include "util/rsnet.h" -#include -#include -#include "util/utest.h" - -INITTEST(); - -/* generic startup test */ -#define MAX_TIME_BASIC_TEST 40 -#define MAX_TIME_UPNP_TEST 700 /* seems to take a while */ - -#define RESTART_EXPECT_NO_EXT_ADDR 1 -#define RESTART_EXPECT_EXTFINDER_ADDR 2 -#define RESTART_EXPECT_UPNP_ADDR 3 -#define RESTART_EXPECT_DHT_ADDR 4 - -int test_p3connmgr_restart_test(uint32_t expectState, rstime_t timeout); - - -#define RESET_VIA_LOCAL_ADDR 1 -#define RESET_VIA_REMOTE_ADDR 2 - - -int force_reset(uint32_t method); - - -/******************************************************* - * - * Test structure - *****************/ - -#define FLAG_UPNP 1 -#define FLAG_UDP 2 -#define FLAG_DHT 4 -#define FLAG_EXT 8 - -p3ConnectMgr *mConnMgr; -pqiNetAssistFirewall *mUpnpMgr = NULL; -p3DhtMgr *mDhtMgr = NULL; - -void createP3ConnMgr(std::string id, uint32_t testFlags) -{ - /* now add test children */ - { - std::cerr << "createP3ConnMgr()"; - std::cerr << std::endl; - } - - mConnMgr = new p3ConnectMgr(); - - mDhtMgr = NULL; //new p3DhtMgr(); - - /* setup status */ - //mConnMgr->setStatus(UPNP); -} - -void add_upnp() -{ - pqiNetAssistFirewall *mUpnpMgr = new upnphandler(); - mDhtMgr = NULL; //new p3DhtMgr(); - - //mConnMgr->addNetAssistConnect(1, mDhtMgr); - mConnMgr->addNetAssistFirewall(1, mUpnpMgr); -} - -void disableUpnp() -{ - //mConnMgr-> -} - - -void enableUpnp() -{ - - - -} - -void disableExtFinder() -{ - //mConnMgr-> - mConnMgr->setIPServersEnabled(false); -} - - -void enableExtFinder() -{ - mConnMgr->setIPServersEnabled(true); -} - - -/* ACTUAL TEST */ -int main(int argc, char **argv) -{ - /* test p3connmgr net stuff */ - std::cerr << "p3connmgr_net_restart_test" << std::endl; - - // setup test authssl. - setAuthGPG(new AuthGPGtest()); - setAuthSSL(new AuthSSLtest()); - - createP3ConnMgr("abcd", 0); - pqiNetStatus status; - - - /* first test, no Upnp / ExtFinder -> expect no Ext Address */ - mConnMgr->setNetworkMode(AuthSSL::getAuthSSL()->OwnId(), RS_NET_MODE_UDP); - disableExtFinder(); - - mConnMgr->getNetStatus(status); - - CHECK(status.mLocalAddrOk == false); - CHECK(status.mExtAddrOk == false); - test_p3connmgr_restart_test(RESTART_EXPECT_NO_EXT_ADDR, MAX_TIME_BASIC_TEST); - - REPORT("test_p3connmgr_restart_test()"); - - /* second test, add ExtFinder -> expect Ext Address */ - enableExtFinder(); - mConnMgr->setNetworkMode(AuthSSL::getAuthSSL()->OwnId(), RS_NET_MODE_UDP); - force_reset(RESET_VIA_LOCAL_ADDR); - - CHECK(status.mLocalAddrOk == false); - CHECK(status.mExtAddrOk == false); - test_p3connmgr_restart_test(RESTART_EXPECT_EXTFINDER_ADDR, MAX_TIME_BASIC_TEST); - - /* third test. disable ExtFinder again -> expect No Ext Address */ - disableExtFinder(); - mConnMgr->setNetworkMode(AuthSSL::getAuthSSL()->OwnId(), RS_NET_MODE_UDP); - force_reset(RESET_VIA_LOCAL_ADDR); - CHECK(status.mLocalAddrOk == false); - CHECK(status.mExtAddrOk == false); - test_p3connmgr_restart_test(RESTART_EXPECT_NO_EXT_ADDR, MAX_TIME_BASIC_TEST); - - - /* fourth test. enable Upnp -> expect Upnp Ext Address */ - add_upnp(); - enableUpnp(); - mConnMgr->setNetworkMode(AuthSSL::getAuthSSL()->OwnId(), RS_NET_MODE_UPNP); - force_reset(RESET_VIA_LOCAL_ADDR); - CHECK(status.mLocalAddrOk == false); - CHECK(status.mExtAddrOk == false); - - - test_p3connmgr_restart_test(RESTART_EXPECT_UPNP_ADDR, MAX_TIME_UPNP_TEST); - /* fifth test. disable Upnp -> expect No Ext Address */ - disableUpnp(); - mConnMgr->setNetworkMode(AuthSSL::getAuthSSL()->OwnId(), RS_NET_MODE_UDP); - force_reset(RESET_VIA_LOCAL_ADDR); - CHECK(status.mLocalAddrOk == false); - CHECK(status.mExtAddrOk == false); - - test_p3connmgr_restart_test(RESTART_EXPECT_NO_EXT_ADDR, MAX_TIME_BASIC_TEST); - /* sixth test. enable both Ext and Upnp -> expect UpnP Ext Address (prefered) */ - enableExtFinder(); - enableUpnp(); - mConnMgr->setNetworkMode(AuthSSL::getAuthSSL()->OwnId(), RS_NET_MODE_UPNP); - force_reset(RESET_VIA_LOCAL_ADDR); - CHECK(status.mLocalAddrOk == false); - CHECK(status.mExtAddrOk == false); - - test_p3connmgr_restart_test(RESTART_EXPECT_UPNP_ADDR, MAX_TIME_UPNP_TEST); - REPORT("test_p3connmgr_restart_test()"); - - FINALREPORT("p3connmgr_net_restart_test"); - - return TESTRESULT(); -} - -/****************************************************** - * - */ - -int force_reset(uint32_t method) -{ - /* force reset network */ - struct sockaddr_in tst_addr; - inet_aton("123.45.2.2", &(tst_addr.sin_addr)); - tst_addr.sin_port = ntohs(8461); - - mConnMgr->setLocalAddress(AuthSSL::getAuthSSL()->OwnId(), tst_addr); - - return 1; -} - -/* Generic restart test */ -int test_p3connmgr_restart_test(uint32_t expectState, rstime_t timeout) -{ - /* force reset network */ - struct sockaddr_in tst_addr; - inet_aton("123.45.2.2", &(tst_addr.sin_addr)); - tst_addr.sin_port = ntohs(8461); - - mConnMgr->setLocalAddress(AuthSSL::getAuthSSL()->OwnId(), tst_addr); - - /* tick */ - rstime_t start = time(NULL); - bool extAddr = false; - - while ((start > time(NULL) - timeout) && (!extAddr)) - { - mConnMgr->tick(); - - pqiNetStatus status; - mConnMgr->getNetStatus(status); - std::cerr << "test_p3connmgr_restart_test() Age: " << time(NULL) - start; - std::cerr << " netStatus:"; - std::cerr << std::endl; - status.print(std::cerr); - - if (status.mExtAddrOk) - { - std::cerr << "test_p3connmgr_restart_test() Got ExtAddr. Finished Restart."; - std::cerr << std::endl; - extAddr = true; - } - sleep(1); - } - - std::cerr << "test_p3connmgr_restart_test() Test Mode: " << expectState << " Complete"; - std::cerr << std::endl; - - pqiNetStatus status; - mConnMgr->getNetStatus(status); - status.print(std::cerr); - if (status.mExtAddrOk) - { - CHECK(isValidNet(&(status.mExtAddr.sin_addr))); - } - CHECK(isValidNet(&(status.mLocalAddr.sin_addr))); - - /* check expectState */ - switch(expectState) - { - default: - case RESTART_EXPECT_NO_EXT_ADDR: - CHECK(status.mLocalAddrOk == true); - CHECK(status.mExtAddrOk == false); - CHECK(status.mExtAddrStableOk == false); - CHECK(status.mUpnpOk == false); - CHECK(status.mDhtOk == false); - break; - - case RESTART_EXPECT_EXTFINDER_ADDR: - CHECK(status.mLocalAddrOk == true); - CHECK(status.mExtAddrOk == true); - CHECK(status.mExtAddrStableOk == false); - CHECK(status.mUpnpOk == false); - break; - - case RESTART_EXPECT_UPNP_ADDR: - CHECK(status.mLocalAddrOk == true); - CHECK(status.mExtAddrOk == true); - CHECK(status.mExtAddrStableOk == true); - CHECK(status.mUpnpOk == true); - break; - - case RESTART_EXPECT_DHT_ADDR: - CHECK(status.mLocalAddrOk == true); - CHECK(status.mExtAddrOk == false); - CHECK(status.mUpnpOk == false); - CHECK(status.mDhtOk == true); - break; - } - - return 1; -} - - diff --git a/libretroshare/src/tests/pqi/pkt_test.cc b/libretroshare/src/tests/pqi/pkt_test.cc deleted file mode 100644 index 49f6edd47..000000000 --- a/libretroshare/src/tests/pqi/pkt_test.cc +++ /dev/null @@ -1,109 +0,0 @@ -/* - * libretroshare/src/tests/pqi pkt_tst.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2009-2010 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * pkt_tst. - * - * This is not testing serialisation.... so we only need 1 type of packet. - * using FileData packets - as these can have arbitary size. - */ - -#include "pkt_test.h" -#include - -uint8_t testdata[TEST_DATA_LEN]; - -void generate_test_data() -{ - srand(1); - - int i; - for(i = 0; i < TEST_DATA_LEN; i++) - { - testdata[i] = rand() % 256; - } -} - -bool check_data(void *data_in, int len) -{ - int i; - uint8_t *data = (uint8_t *) data_in; - - for(i = 0; i < len; i++) - { - if (data[i] != testdata[i]) - { - std::cerr << "check_data() Different Byte: " << i; - std::cerr << std::endl; - - return false; - } - } - return true; -} - -RsFileData *gen_packet(int datasize, std::string pid) -{ - /* generate some packets */ - RsFileData *data = new RsFileData(); - data->fd.file.filesize = TEST_PKT_SIZE; - data->fd.file.hash = TEST_PKT_HASH; - data->fd.file_offset = TEST_PKT_OFFSET; - data->fd.binData.setBinData(testdata, datasize); - data->PeerId(pid); - - return data; -} - -bool check_packet(RsFileData *pkt) -{ - if (pkt->fd.file.filesize != TEST_PKT_SIZE) - { - std::cerr << "check_packet() FileSize Different"; - std::cerr << std::endl; - - return false; - } - - if (pkt->fd.file.hash != TEST_PKT_HASH) - { - std::cerr << "check_packet() FileHash Different"; - std::cerr << std::endl; - - return false; - } - - if (pkt->fd.file_offset != TEST_PKT_OFFSET) - { - std::cerr << "check_packet() FileOffset Different"; - std::cerr << std::endl; - - return false; - } - - return check_data(pkt->fd.binData.bin_data, pkt->fd.binData.bin_len); -} - - diff --git a/libretroshare/src/tests/pqi/pkt_test.h b/libretroshare/src/tests/pqi/pkt_test.h deleted file mode 100644 index 072274574..000000000 --- a/libretroshare/src/tests/pqi/pkt_test.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef RS_TEST_PACKETS -#define RS_TEST_PACKETS -/* - * libretroshare/src/tests/pqi pkt_tst.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2009-2010 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * pkt_tst. - * - * This is not testing serialisation.... so we only need 1 type of packet. - * using FileData packets - as these can have arbitary size. - */ - -#include "serialiser/rsbaseitems.h" - -#define TEST_PKT_SIZE 1234567 -#define TEST_PKT_HASH "HASHTESTHASH" -#define TEST_PKT_OFFSET 1234 - -#define TEST_DATA_LEN (1024 * 1024) // MB - -void generate_test_data(); -bool check_data(void *data_in, int len); - -RsFileData *gen_packet(int datasize, std::string pid); -bool check_packet(RsFileData *pkt); - - -#endif diff --git a/libretroshare/src/tests/pqi/ppg_harness.cc b/libretroshare/src/tests/pqi/ppg_harness.cc deleted file mode 100644 index 58b89a971..000000000 --- a/libretroshare/src/tests/pqi/ppg_harness.cc +++ /dev/null @@ -1,141 +0,0 @@ -/* - * libretroshare/src/test/pqi pqiperson_test.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * pqiperson acts as the wrapper for all connection methods to a single peer. - * - * This test creates, a pqiperson and simulates connections, disconnections. - * packets passing through. - * - */ - - -#include "conn_harness.h" -#include "ppg_harness.h" - -#include "pqi/pqiperson.h" -#include "pqi/pqibin.h" - -#include "util/rsnet.h" -#include -#include - -/******************************************************* - * - * Test structure - *****************/ - - -pqiperson *createTestPerson(std::string id, pqipersongrp *ppg); - -pqipersongrpTestHarness *mPqiPersonGrpTH = NULL; - -void setupPqiPersonGrpTH() -{ - mPqiPersonGrpTH = new pqipersongrpTestHarness(NULL, 0); -} - -void tickPqiPersonGrpTH() -{ - mPqiPersonGrpTH->tick(); -} - - -pqipersongrpTestHarness::pqipersongrpTestHarness(SecurityPolicy *pol, unsigned long flags) - :pqipersongrp(pol, flags) -{ - return; -} - - /********* FUNCTIONS to OVERLOAD for specialisation ********/ -pqilistener *pqipersongrpTestHarness::createListener(struct sockaddr_in laddr) -{ - return new pqilistener(); -} - -pqiperson *pqipersongrpTestHarness::createPerson(std::string id, pqilistener *listener) -{ - return createTestPerson(id, this); -} - - /********* FUNCTIONS to OVERLOAD for specialisation ********/ - - - - -pqiperson *createTestPerson(std::string id, pqipersongrp *ppg) -{ - /* now add test children */ - { - std::cerr << "createTestPerson()"; - std::cerr << std::endl; - } - - pqiperson *pqip = new pqiperson(id, ppg); - - /* construct the serialiser .... - * Needs: - * * FileItem - * * FileData - * * ServiceGeneric - */ - - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsFileItemSerialiser()); - rss->addSerialType(new RsCacheItemSerialiser()); - rss->addSerialType(new RsServiceSerialiser()); - - NetBinDummy *dummy1 = new NetBinDummy(pqip, id, PQI_CONNECT_TCP); - pqiconnect *pqisc = new testConnect(rss, dummy1); - addTestConnect(pqisc, pqip); - pqip -> addChildInterface(PQI_CONNECT_TCP, pqisc); - - RsSerialiser *rss2 = new RsSerialiser(); - rss2->addSerialType(new RsFileItemSerialiser()); - rss2->addSerialType(new RsCacheItemSerialiser()); - rss2->addSerialType(new RsServiceSerialiser()); - - NetBinDummy *dummy2 = new NetBinDummy(pqip, id, PQI_CONNECT_TUNNEL); - pqiconnect *pqicontun = new testConnect(rss2, dummy2); - addTestConnect(pqicontun, pqip); - pqip -> addChildInterface(PQI_CONNECT_TUNNEL, pqicontun); - - - RsSerialiser *rss3 = new RsSerialiser(); - rss3->addSerialType(new RsFileItemSerialiser()); - rss3->addSerialType(new RsCacheItemSerialiser()); - rss3->addSerialType(new RsServiceSerialiser()); - - NetBinDummy *dummy3 = new NetBinDummy(pqip, id, PQI_CONNECT_UDP); - pqiconnect *pqiusc = new testConnect(rss3, dummy3); - addTestConnect(pqiusc, pqip); - pqip -> addChildInterface(PQI_CONNECT_UDP, pqiusc); - - return pqip; -} - - - - diff --git a/libretroshare/src/tests/pqi/ppg_harness.h b/libretroshare/src/tests/pqi/ppg_harness.h deleted file mode 100644 index 85e664548..000000000 --- a/libretroshare/src/tests/pqi/ppg_harness.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef PPG_HARNESS_TEST_H -#define PPG_HARNESS_TEST_H - -/* - * libretroshare/src/test/pqi ppg_harness.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * test harness for pqipersongrp / pqihandler. - */ - -#include "pqi/pqiperson.h" -#include "pqi/pqipersongrp.h" - -/******************************************************* - * - * Test structure - *****************/ - -void setupPqiPersonGrpTH(); -void tickPqiPersonGrpTH(); - -class pqipersongrpTestHarness; -extern pqipersongrpTestHarness *mPqiPersonGrpTH; - -class pqipersongrpTestHarness: public pqipersongrp -{ - public: - pqipersongrpTestHarness(SecurityPolicy *pol, unsigned long flags); - - protected: - - /********* FUNCTIONS to OVERLOAD for specialisation ********/ -virtual pqilistener *createListener(struct sockaddr_in laddr); -virtual pqiperson *createPerson(std::string id, pqilistener *listener); - - /********* FUNCTIONS to OVERLOAD for specialisation ********/ -}; - -#endif diff --git a/libretroshare/src/tests/pqi/pqiarchive_test.cc b/libretroshare/src/tests/pqi/pqiarchive_test.cc deleted file mode 100644 index abe88bab7..000000000 --- a/libretroshare/src/tests/pqi/pqiarchive_test.cc +++ /dev/null @@ -1,130 +0,0 @@ -/* - * libretroshare/src/tests/pqi pqiarchive_test.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2009-2010 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * pqiarchive test. - * - * This is not testing serialisation.... so we only need 1 type of packet. - * using FileData packets - as these can have arbitary size. - */ - -#include "pqi/pqiarchive.h" -#include "pqi/pqibin.h" - -#include "serialiser/rsbaseitems.h" - -#include "util/rsnet.h" -#include -#include -#include "util/utest.h" - -#include "pkt_test.h" - -INITTEST(); - -int test_pqiarchive_generate(); - -int main(int argc, char **argv) -{ - std::cerr << "pqiarchive_test" << std::endl; - - generate_test_data(); - - test_pqiarchive_generate(); - - FINALREPORT("pqiarchive_test"); - - return TESTRESULT(); -} - -const char *archive_fname = "/tmp/rs_tst_archive.tmp"; - -int test_pqiarchive_generate() -{ - - std::string pid = "123456789012345678901234567890ZZ"; - /* create a pqiarchive */ - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsFileItemSerialiser()); - - int flags = BIN_FLAGS_WRITEABLE; - BinInterface *bio_in = new BinFileInterface(archive_fname, flags); - - int bio_flagsin = flags; - pqiarchive *pqia = new pqiarchive(rss, bio_in, bio_flagsin); - CHECK(pqia != NULL); - - int i; - for(i = 10; i < TEST_DATA_LEN; i = (int) (i * 1.1)) - { - RsFileData *pkt = gen_packet(i, pid); - pqia->SendItem(pkt); - pqia->tick(); - } - - /* close it up */ - delete pqia; - - /* setup read */ - flags = BIN_FLAGS_READABLE; - - rss = new RsSerialiser(); - rss->addSerialType(new RsFileItemSerialiser()); - - bio_in = new BinFileInterface(archive_fname, flags); - bio_flagsin = flags; - pqia = new pqiarchive(rss, bio_in, bio_flagsin); - - for(i = 10; i < TEST_DATA_LEN; i = (int) (i * 1.1)) - //for(i = 10; i < TEST_DATA_LEN; i += 111) - { - RsItem *pkt = pqia->GetItem(); - pqia->tick(); - - /* check the packet */ - RsFileData *data = dynamic_cast(pkt); - CHECK(data != NULL); - if (data) - { - CHECK(data->fd.binData.bin_len == i); - CHECK(check_packet(data) == true); - delete data; - } - } - - /* if there are anymore packets -> error! */ - for(i = 0; i < 1000; i++) - { - RsItem *pkt = pqia->GetItem(); - CHECK(pkt == NULL); - } - - REPORT("pqiarchive_generate()"); - - return 1; -} - - - diff --git a/libretroshare/src/tests/pqi/pqiipset_test.cc b/libretroshare/src/tests/pqi/pqiipset_test.cc deleted file mode 100644 index 893fc5223..000000000 --- a/libretroshare/src/tests/pqi/pqiipset_test.cc +++ /dev/null @@ -1,157 +0,0 @@ -/* - * libretroshare/src/test/pqi pqiipset_test.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2007-2010 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * NETWORKING Test to check Big/Little Endian behaviour - * as well as socket behaviour - * - */ - -#include "util/utest.h" - -#include "pqi/pqiipset.h" -#include "pqi/pqinetwork.h" -#include "util/rsnet.h" -#include -#include - - -bool test_addr_list(); - - -INITTEST(); - -int main(int argc, char **argv) -{ - std::cerr << "libretroshare:pqi " << argv[0] << std::endl; - - test_addr_list(); - - FINALREPORT("libretroshare pqiipset Tests"); - return TESTRESULT(); -} - - /* test 1: byte manipulation */ -bool test_addr_list() -{ - pqiIpAddress addr; - pqiIpAddrList list; - - for(int i = 100; i < 150; i++) - { - std::ostringstream out; - out << "192.168.2." << i; - inet_aton(out.str().c_str(), &(addr.mAddr.sin_addr)); - addr.mAddr.sin_port = htons(7812); - addr.mSeenTime = time(NULL) - i; - - list.updateIpAddressList(addr); - - if (i < 100 + 4) - { - /* check that was added to the back */ - CHECK(list.mAddrs.back().mSeenTime == addr.mSeenTime); - CHECK(list.mAddrs.back().mAddr.sin_addr.s_addr == addr.mAddr.sin_addr.s_addr); - CHECK(list.mAddrs.back().mAddr.sin_port == addr.mAddr.sin_port); - } - else - { - /* check that wasn't added to the back */ - CHECK(list.mAddrs.back().mSeenTime != addr.mSeenTime); - CHECK(list.mAddrs.back().mAddr.sin_addr.s_addr != addr.mAddr.sin_addr.s_addr); - } - } - - /* print out the list */ - std::cerr << "IpAddressList (expect variation: 192.168.2.[100-103]:7812)"; - std::cerr << std::endl; - std::string out ; - list.printIpAddressList(out) ; - std::cerr << out << std::endl; - - const uint32_t expectedListSize = 4; - CHECK(list.mAddrs.size() == expectedListSize); - - rstime_t min_time = time(NULL) - expectedListSize + 100; - - /* expect the most recent ones to appear */ - std::list::iterator it; - for(it = list.mAddrs.begin(); it != list.mAddrs.end(); it++) - { - CHECK(it->mSeenTime < min_time); - } - - /* now add some with same address + port */ - { - std::ostringstream out; - out << "192.168.2.200"; - inet_aton(out.str().c_str(), &(addr.mAddr.sin_addr)); - addr.mAddr.sin_port = htons(8812); - } - - /* make sure it more recent than the previous ones */ - for(int i = 99; i > 89; i--) - { - addr.mSeenTime = time(NULL) - i; - list.updateIpAddressList(addr); - - /* check that was added to the front */ - CHECK(list.mAddrs.front().mSeenTime == addr.mSeenTime); - CHECK(list.mAddrs.front().mAddr.sin_addr.s_addr == addr.mAddr.sin_addr.s_addr); - CHECK(list.mAddrs.front().mAddr.sin_port == addr.mAddr.sin_port); - } - - /* print out the list */ - std::cerr << "IpAddressList (first item to be 192.168.2.200:8812)"; - std::cerr << std::endl; - list.printIpAddressList(out) ; - std::cerr << out<< std::endl; - - /* now add with the different ports */ - - for(int i = 70; i > 50; i--) - { - addr.mAddr.sin_port = htons(8000 + i); - addr.mSeenTime = time(NULL) - i; - - list.updateIpAddressList(addr); - - /* check that was added to the back */ - CHECK(list.mAddrs.front().mSeenTime == addr.mSeenTime); - CHECK(list.mAddrs.front().mAddr.sin_addr.s_addr == addr.mAddr.sin_addr.s_addr); - CHECK(list.mAddrs.front().mAddr.sin_port == addr.mAddr.sin_port); - - } - - std::cerr << "IpAddressList (expect same Ip, but variations in port)"; - std::cerr << std::endl; - list.printIpAddressList(out) ; - std::cerr << out < -#include -#include "util/utest.h" - -INITTEST(); - -int test_person_basic_reset(); -int test_person_basic_listen(); - - -int main(int argc, char **argv) -{ - std::cerr << "pqiperson_test" << std::endl; - - test_person_basic_reset(); - test_person_basic_listen(); - - FINALREPORT("pqiperson_test"); - - return TESTRESULT(); -} - -/****************************************************** - * - * tests() - * - **** ensure that functions call children - * pqiperson::reset() - * pqiperson::listen() - * pqiperson::stoplistening() - * - * - * pqiperson::connect(...) - * -> check that gets through to children. - * -> check that cannot have simultaneous connections. - * -> - * - */ - - -/******************************************************* - * - * Test structure - *****************/ - -#define NUM_CHILDREN 3 - -pqiperson *createTestPerson(std::string id, pqipersongrp *ppg) -{ - /* now add test children */ - { - std::cerr << "createTestPerson()"; - std::cerr << std::endl; - } - - pqiperson *pqip = new pqiperson(id, ppg); - - /* construct the serialiser .... - * Needs: - * * FileItem - * * FileData - * * ServiceGeneric - */ - - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsFileItemSerialiser()); - rss->addSerialType(new RsCacheItemSerialiser()); - rss->addSerialType(new RsServiceSerialiser()); - - NetBinDummy *dummy1 = new NetBinDummy(pqip, id, PQI_CONNECT_TCP); - pqiconnect *pqisc = new testConnect(rss, dummy1); - addTestConnect(pqisc); - pqip -> addChildInterface(PQI_CONNECT_TCP, pqisc); - - RsSerialiser *rss2 = new RsSerialiser(); - rss2->addSerialType(new RsFileItemSerialiser()); - rss2->addSerialType(new RsCacheItemSerialiser()); - rss2->addSerialType(new RsServiceSerialiser()); - - NetBinDummy *dummy2 = new NetBinDummy(pqip, id, PQI_CONNECT_TUNNEL); - pqiconnect *pqicontun = new testConnect(rss2, dummy2); - addTestConnect(pqicontun); - pqip -> addChildInterface(PQI_CONNECT_TUNNEL, pqicontun); - - - RsSerialiser *rss3 = new RsSerialiser(); - rss3->addSerialType(new RsFileItemSerialiser()); - rss3->addSerialType(new RsCacheItemSerialiser()); - rss3->addSerialType(new RsServiceSerialiser()); - - NetBinDummy *dummy3 = new NetBinDummy(pqip, id, PQI_CONNECT_UDP); - pqiconnect *pqiusc = new testConnect(rss3, dummy3); - addTestConnect(pqiusc); - pqip -> addChildInterface(PQI_CONNECT_UDP, pqiusc); - - return pqip; -} - - -/* First Sets of Tests are very basic: - * reset() - * connect() - * listen() / stoplistening() - * disconnect() - */ - -int test_person_basic_reset() -{ - /* reset test */ - resetTestConnects(); - - /* create test person */ - std::string id = "12345678901234567890123456789012"; - pqipersongrp *ppg = NULL; - pqiperson *person = createTestPerson(id, ppg); - - /* reset person */ - person->reset(); - - /* count number of resets */ - CHECK(NUM_CHILDREN == testCounter); - - int i; - for(i = 0; i < NUM_CHILDREN; i++) - { - CHECK(testResetTimes[i].size() == 1); - CHECK(testConnectState[i] == 0); - CHECK(testConnectTimes[i].size() == 0); - } - - /* clean up */ - delete person; - - REPORT("test_person_basic_reset()"); - - return 1; -} - - -int test_person_basic_listen() -{ - /* reset test */ - resetTestConnects(); - - /* create test person */ - std::string id = "12345678901234567890123456789012"; - pqipersongrp *ppg = NULL; - pqiperson *person = createTestPerson(id, ppg); - - /* reset person */ - person->listen(); - - /* count number of resets */ - CHECK(NUM_CHILDREN == testCounter); - - int i; - for(i = 0; i < NUM_CHILDREN; i++) - { - CHECK(testResetTimes[i].size() == 0); - CHECK(testConnectTimes[i].size() == 0); - CHECK(testConnectState[i] == TST_STATE_LISTEN); - } - - person->stoplistening(); - - for(i = 0; i < NUM_CHILDREN; i++) - { - CHECK(testResetTimes[i].size() == 0); - CHECK(testConnectTimes[i].size() == 0); - CHECK(testConnectState[i] == 0); - } - - /* clean up */ - delete person; - - REPORT("test_person_basic_listen()"); - - return 1; -} - - - - diff --git a/libretroshare/src/tests/pqi/pqipersongrp_test.cc b/libretroshare/src/tests/pqi/pqipersongrp_test.cc deleted file mode 100644 index d189c94fc..000000000 --- a/libretroshare/src/tests/pqi/pqipersongrp_test.cc +++ /dev/null @@ -1,266 +0,0 @@ -/* - * libretroshare/src/test/pqi pqiperson_test.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * pqiperson acts as the wrapper for all connection methods to a single peer. - * - * This test creates, a pqiperson and simulates connections, disconnections. - * packets passing through. - * - */ - - - - - - -#include "pqi/pqiperson.h" -#include "pqi/pqibin.h" - -#include "testconnect.h" - -#include "util/rsnet.h" -#include -#include -#include "util/utest.h" - -INITTEST(); - -int test_person_basic_reset(); -int test_person_basic_listen(); - - -int main(int argc, char **argv) -{ - std::cerr << "pqiperson_test" << std::endl; - - test_person_basic_reset(); - test_person_basic_listen(); - - FINALREPORT("pqiperson_test"); - - return TESTRESULT(); -} - -/****************************************************** - * - * tests() - * - **** ensure that functions call children - * pqiperson::reset() - * pqiperson::listen() - * pqiperson::stoplistening() - * - * - * pqiperson::connect(...) - * -> check that gets through to children. - * -> check that cannot have simultaneous connections. - * -> - * - */ - - -/******************************************************* - * - * Test structure - *****************/ - -#define NUM_CHILDREN 3 - -pqiperson *createTestPerson(std::string id, pqipersongrp *ppg); - -class pqipersongrpTestHarness: public pqipersongrp -{ - public: - pqipersongrpTestHarness(SecurityPolicy *pol, unsigned long flags) - :pqipersongrp(pol, flags) - { - return; - } - - protected: - - /********* FUNCTIONS to OVERLOAD for specialisation ********/ -virtual pqilistener *createListener(struct sockaddr_in laddr) -{ - return new pqilistener(laddr); -} - -virtual pqiperson *createPerson(std::string id, pqilistener *listener) -{ - return createTestPerson(id, this); -} - - /********* FUNCTIONS to OVERLOAD for specialisation ********/ -}; - - - - -pqiperson *createTestPerson(std::string id, pqipersongrp *ppg) -{ - /* now add test children */ - { - std::cerr << "createTestPerson()"; - std::cerr << std::endl; - } - - pqiperson *pqip = new pqiperson(id, ppg); - - /* construct the serialiser .... - * Needs: - * * FileItem - * * FileData - * * ServiceGeneric - */ - - RsSerialiser *rss = new RsSerialiser(); - rss->addSerialType(new RsFileItemSerialiser()); - rss->addSerialType(new RsCacheItemSerialiser()); - rss->addSerialType(new RsServiceSerialiser()); - - NetBinDummy *dummy1 = new NetBinDummy(pqip, id, PQI_CONNECT_TCP); - pqiconnect *pqisc = new testConnect(rss, dummy1); - addTestConnect(pqisc); - pqip -> addChildInterface(PQI_CONNECT_TCP, pqisc); - - RsSerialiser *rss2 = new RsSerialiser(); - rss2->addSerialType(new RsFileItemSerialiser()); - rss2->addSerialType(new RsCacheItemSerialiser()); - rss2->addSerialType(new RsServiceSerialiser()); - - NetBinDummy *dummy2 = new NetBinDummy(pqip, id, PQI_CONNECT_TUNNEL); - pqiconnect *pqicontun = new testConnect(rss2, dummy2); - addTestConnect(pqicontun); - pqip -> addChildInterface(PQI_CONNECT_TUNNEL, pqicontun); - - - RsSerialiser *rss3 = new RsSerialiser(); - rss3->addSerialType(new RsFileItemSerialiser()); - rss3->addSerialType(new RsCacheItemSerialiser()); - rss3->addSerialType(new RsServiceSerialiser()); - - NetBinDummy *dummy3 = new NetBinDummy(pqip, id, PQI_CONNECT_UDP); - pqiconnect *pqiusc = new testConnect(rss3, dummy3); - addTestConnect(pqiusc); - pqip -> addChildInterface(PQI_CONNECT_UDP, pqiusc); - - return pqip; -} - - -/* First Sets of Tests are very basic: - * reset() - * connect() - * listen() / stoplistening() - * disconnect() - */ - -int test_person_basic_reset() -{ - /* reset test */ - resetTestConnects(); - - /* create test person */ - std::string id = "12345678901234567890123456789012"; - - pqipersongrp *ppg = pqipersongrpTestHarness(NULL, 0); - - /* setup fake other bits */ - - - /* add peers - and watch it all happen! */ - - - - pqiperson *person = createTestPerson(id, ppg); - - /* reset person */ - person->reset(); - - /* count number of resets */ - CHECK(NUM_CHILDREN == testCounter); - - int i; - for(i = 0; i < NUM_CHILDREN; i++) - { - CHECK(testResetTimes[i].size() == 1); - CHECK(testConnectState[i] == 0); - CHECK(testConnectTimes[i].size() == 0); - } - - /* clean up */ - delete person; - - REPORT("test_person_basic_reset()"); - - return 1; -} - - -int test_person_basic_listen() -{ - /* reset test */ - resetTestConnects(); - - /* create test person */ - std::string id = "12345678901234567890123456789012"; - pqipersongrp *ppg = NULL; - pqiperson *person = createTestPerson(id, ppg); - - /* reset person */ - person->listen(); - - /* count number of resets */ - CHECK(NUM_CHILDREN == testCounter); - - int i; - for(i = 0; i < NUM_CHILDREN; i++) - { - CHECK(testResetTimes[i].size() == 0); - CHECK(testConnectTimes[i].size() == 0); - CHECK(testConnectState[i] == TST_STATE_LISTEN); - } - - person->stoplistening(); - - for(i = 0; i < NUM_CHILDREN; i++) - { - CHECK(testResetTimes[i].size() == 0); - CHECK(testConnectTimes[i].size() == 0); - CHECK(testConnectState[i] == 0); - } - - /* clean up */ - delete person; - - REPORT("test_person_basic_listen()"); - - return 1; -} - - - - diff --git a/libretroshare/src/tests/pqi/pqiqos_test.cc b/libretroshare/src/tests/pqi/pqiqos_test.cc deleted file mode 100644 index eea4846ae..000000000 --- a/libretroshare/src/tests/pqi/pqiqos_test.cc +++ /dev/null @@ -1,191 +0,0 @@ -#include "util/utest.h" - -#include -#include -#include -#include "serialiser/rsserial.h" -#include "util/rsrandom.h" -#include "pqi/pqiqos.h" - -INITTEST(); - -// Class of RsItem with ids to check order -// -class testRawItem: public RsItem -{ - public: - testRawItem() - : RsItem(0,0,0), _id(_static_id++) - { - } - - virtual void clear() {} - virtual std::ostream& print(std::ostream& o, uint16_t) { return o ; } - - static const uint32_t rs_rawitem_size = 10 ; - static uint64_t _static_id ; - uint64_t _id ; -}; -uint64_t testRawItem::_static_id = 1; - -int main() -{ - float alpha = 3 ; - int nb_levels = 10 ; - - ////////////////////////////////////////////// - // 1 - Test consistency of output and order // - ////////////////////////////////////////////// - { - pqiQoS qos(nb_levels,alpha) ; - - // 0 - Fill the queue with fake RsItem. - // - static const uint32_t pushed_items = 10000 ; - - for(uint32_t i=0;isetPriorityLevel(i % nb_levels) ; - - qos.in_rsItem(item,item->priority_level()) ; - } - std::cerr << "QOS is filled with: " << std::endl; - qos.print() ; - - // 1 - checks that all items eventually got out in the same order for - // items of equal priority - // - uint32_t poped = 0; - std::vector last_ids(nb_levels,0) ; - - while(testRawItem *item = static_cast(qos.out_rsItem())) - { - CHECK(last_ids[item->priority_level()] < item->_id) ; - - last_ids[item->priority_level()] = item->_id ; - delete item, ++poped ; - } - - std::cerr << "Push " << pushed_items << " items, poped " << poped << std::endl; - - if(pushed_items != poped) - { - std::cerr << "Queues are: " << std::endl; - qos.print() ; - } - CHECK(pushed_items == poped) ; - } - - ////////////////////////////////////////////////// - // 2 - tests proportionality // - ////////////////////////////////////////////////// - { - // Now we feed the QoS, and check that items get out with probability proportional - // to the priority - // - pqiQoS qos(nb_levels,alpha) ; - - std::cerr << "Feeding 10^6 packets to the QoS service." << std::endl; - for(int i=0;i<1000000;++i) - { - if(i%10000 == 0) - { - fprintf(stderr,"%1.2f %% completed.\r",i/(float)1000000*100.0f) ; - fflush(stderr) ; - } - testRawItem *item = new testRawItem ; - - switch(i%5) - { - case 0: item->setPriorityLevel( 1 ) ; break ; - case 1: item->setPriorityLevel( 4 ) ; break ; - case 2: item->setPriorityLevel( 6 ) ; break ; - case 3: item->setPriorityLevel( 7 ) ; break ; - case 4: item->setPriorityLevel( 8 ) ; break ; - } - - qos.in_rsItem(item,item->priority_level()) ; - } - - // Now perform stats on outputs for the 10000 first elements - - std::vector hist(nb_levels,0) ; - - for(uint32_t i=0;i<10000;++i) - { - testRawItem *item = static_cast(qos.out_rsItem()) ; - hist[item->priority_level()]++ ; - delete item ; - } - - std::cerr << "Histogram: " ; - for(uint32_t i=0;isetPriorityLevel(i%nb_levels) ; - qos.in_rsItem(item,item->priority_level()) ; - } - - // pop a random number of packets out - - std::vector last_ids(nb_levels,0) ; - - for(uint32_t i=0;i(qos.out_rsItem()) ; - - if(item == NULL) - { - std::cerr << "Null output !" << std::endl; - break ; - } - - CHECK(last_ids[item->priority_level()] < item->_id) ; - - last_ids[item->priority_level()] = item->_id ; - delete item ; - } - - // print some info - static rstime_t last = 0 ; - if(now > last) - { - qos.print() ; - last = now ; - } - } - } - - FINALREPORT("pqiqos_test"); - return TESTRESULT() ; -} - - diff --git a/libretroshare/src/tests/pqi/testconnect.cc b/libretroshare/src/tests/pqi/testconnect.cc deleted file mode 100644 index 0dc019c18..000000000 --- a/libretroshare/src/tests/pqi/testconnect.cc +++ /dev/null @@ -1,186 +0,0 @@ -/* - * libretroshare/src/test/pqi testconnect.cc - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****** - * pqiperson acts as the wrapper for all connection methods to a single peer. - * - * This test creates, a pqiperson and simulates connections, disconnections. - * packets passing through. - * - */ - - -#include "testconnect.h" -#include "pqi/pqibin.h" -#include -#include - -/******************************************************* - * - * Test structure - *****************/ - - -#define NUM_CONN_MAX 10 -#define NUM_CHILDREN 3 - -#define TST_STATE_CONNECT 0x0001 -#define TST_STATE_LISTEN 0x0002 - -/* static test variables */ -uint32_t testCounter = 0; -pqiconnect *testConnectPointer[NUM_CONN_MAX]; -uint32_t testConnectState[NUM_CONN_MAX]; -std::list testConnectTimes[NUM_CONN_MAX]; -std::list testConnectAddrs[NUM_CONN_MAX]; - -std::list testResetState[NUM_CONN_MAX]; -std::list testResetTimes[NUM_CONN_MAX]; - -uint32_t findWhichConnect(pqiconnect *conn) -{ - int i; - for(i = 0; i < NUM_CONN_MAX; i++) - { - if (testConnectPointer[i] == conn) - { - return i; - } - } - // error. - std::cerr << "Connect Missing" << std::endl; - exit(1); - return 0; -} - -void addTestConnect(pqiconnect *pqi) -{ - testConnectPointer[testCounter] = pqi; - testConnectState[testCounter] = 0; - testCounter++; - if (testCounter > NUM_CONN_MAX) - { - std::cerr << "Too Many Connects" << std::endl; - exit(1); - } -} - -void resetTestConnects() -{ - testCounter = 0; - int i; - for(i = 0; i < NUM_CONN_MAX; i++) - { - testConnectAddrs[i].clear(); - testConnectTimes[i].clear(); - testResetState[i].clear(); - testResetTimes[i].clear(); - } -} - - -testConnect::testConnect(RsSerialiser *rss, NetBinInterface *ni_in) - :pqiconnect(rss, ni_in) -{ - -} - -testConnect::~testConnect() -{ - return; -} - - /* dummyConnect */ -int testConnect::connect(struct sockaddr_in raddr) -{ - int cidx = findWhichConnect(this); - rstime_t now = time(NULL); - - testConnectState[cidx] |= TST_STATE_CONNECT; - testConnectTimes[cidx].push_back(now); - testConnectAddrs[cidx].push_back(raddr); - - std::cerr << "testConnect[" << cidx << "].connect() called"; - std::cerr << std::endl; - return 0; -} - -int testConnect::listen() -{ - int cidx = findWhichConnect(this); - testConnectState[cidx] |= TST_STATE_LISTEN; - std::cerr << "testConnect[" << cidx << "].listen() called"; - std::cerr << std::endl; - return 1; -} - -int testConnect::stoplistening() -{ - int cidx = findWhichConnect(this); - testConnectState[cidx] &= ~TST_STATE_LISTEN; - std::cerr << "testConnect[" << cidx << "].stoplistening() called"; - std::cerr << std::endl; - return 1; -} - -int testConnect::reset() -{ - int cidx = findWhichConnect(this); - rstime_t now = time(NULL); - - // reset everything except listening. - testResetState[cidx].push_back(testConnectState[cidx]); - testResetTimes[cidx].push_back(now); - testConnectState[cidx] &= TST_STATE_LISTEN; - - std::cerr << "testConnect[" << cidx << "].reset() called"; - std::cerr << std::endl; - return 1; -} - -// leave this as is virtual int disconnect() { return ni -> reset(); } - -bool testConnect::connect_parameter(uint32_t type, uint32_t value) -{ - int cidx = findWhichConnect(this); - //testConnectState[cidx] |= TST_STATE_LISTEN; - std::cerr << "testConnect[" << cidx << "].connect_parameter() called"; - std::cerr << std::endl; - return true; -} - -int testConnect::getConnectAddress(struct sockaddr_in &raddr) -{ - int cidx = findWhichConnect(this); - if (testConnectAddrs[cidx].size() > 0) - { - raddr = testConnectAddrs[cidx].back(); - return 1; - } - std::cerr << "testConnect[" << cidx << "].getConnectAddress() called"; - std::cerr << std::endl; - return 0; -} - diff --git a/libretroshare/src/tests/pqi/testconnect.h b/libretroshare/src/tests/pqi/testconnect.h deleted file mode 100644 index c0eda479c..000000000 --- a/libretroshare/src/tests/pqi/testconnect.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef TEST_PQICONNECT_H -#define TEST_PQICONNECT_H - -/* - * libretroshare/src/test/pqi testconnect.h - * - * 3P/PQI network interface for RetroShare. - * - * Copyright 2007-2010 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "pqi/pqiperson.h" -//#include "pqi/pqibin.h" -#include "util/rsnet.h" - -/******************************************************* - * - * Test structure - *****************/ - - -#define NUM_CONN_MAX 10 - -#define TST_STATE_CONNECT 0x0001 -#define TST_STATE_LISTEN 0x0002 - -/* static test variables */ -extern uint32_t testCounter; -extern pqiconnect *testConnectPointer[NUM_CONN_MAX]; -extern uint32_t testConnectState[NUM_CONN_MAX]; -extern std::list testConnectTimes[NUM_CONN_MAX]; -extern std::list testConnectAddrs[NUM_CONN_MAX]; - -extern std::list testResetState[NUM_CONN_MAX]; -extern std::list testResetTimes[NUM_CONN_MAX]; - -uint32_t findWhichConnect(pqiconnect *conn); -void addTestConnect(pqiconnect *pqi); -void resetTestConnects(); - -class testConnect: public pqiconnect -{ - public: - - testConnect(RsSerialiser *rss, NetBinInterface *ni_in); - virtual ~testConnect(); - - /* dummyConnect */ - virtual int connect(struct sockaddr_in raddr); - virtual int listen(); - virtual int stoplistening(); - virtual int reset(); - virtual bool connect_parameter(uint32_t type, uint32_t value); - virtual int getConnectAddress(struct sockaddr_in &raddr); -}; // end of testConnect. - - -pqiperson *createTestPerson(std::string id, pqipersongrp *ppg); - - -#endif - diff --git a/libretroshare/src/tests/printcache/main.cpp b/libretroshare/src/tests/printcache/main.cpp deleted file mode 100644 index 66354946a..000000000 --- a/libretroshare/src/tests/printcache/main.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * main.cpp - * - * Created on: 11 Apr 2011 - * Author: greyfox - */ - -#include -#include -#include - -#include -#include "pqi/pqistreamer.h" -#include "pqi/pqibin.h" -#include "serialiser/rsdistribitems.h" -#include "pqi/pqistore.h" - -int main(int argc, char **argv) -{ - try - { - argstream as(argc,argv) ; - bool full_print = false ; - - std::string cacheFileName; - - as >> parameter('f',"file",cacheFileName,"cache file name to read",true) - >> option('F',"full",full_print,"full dump of distrib items") - >> help() ; - - as.defaultErrorHandling() ; - - std::cout << "opening file: " << cacheFileName << std::endl; - // open file - BinInterface *bio = new BinFileInterface(cacheFileName.c_str(), BIN_FLAGS_READABLE); - RsSerialiser *rsSerialiser = new RsSerialiser(); - RsSerialType *serialType = new RsDistribSerialiser(); - rsSerialiser->addSerialType(serialType); - pqistore *store = new pqistore(rsSerialiser, "", bio, BIN_FLAGS_READABLE); - RsItem* item; - - std::set already ; - int signed_msgs = 0 ; - int distrib_msgs = 0 ; - int nb_duplicated = 0 ; - - // then print out contents to screen - while(NULL != (item = store->GetItem())) - { - - if(full_print) - item->print(std::cout, 0); - else - { - { - RsDistribMsg *i = dynamic_cast(item) ; - if(i!=NULL) - { - std::cerr << "Grp=" << i->grpId << ", parent=" << i->parentId << ", msgId=" << i->msgId ; - - if(already.find(i->msgId)!=already.end()) - { - std::cerr << " *** double ***" ; - ++nb_duplicated ; - } - else - already.insert(i->msgId) ; - - std::cerr << std::endl; - ++distrib_msgs ; - } - } - { - RsDistribSignedMsg *i = dynamic_cast(item) ; - if(i!=NULL) - { - std::cerr << "Grp=" << i->grpId << ", msgId=" << i->msgId << ", type=" << i->packet.tlvtype << ", len=" << i->packet.bin_len ; - - if(already.find(i->msgId)!=already.end()) - { - std::cerr << " *** double ***" ; - ++nb_duplicated ; - } - else - already.insert(i->msgId) ; - - std::cerr << std::endl; - - ++signed_msgs ; - } - } - } - } - - std::cerr << std::endl ; - std::cerr << "Signed messages (RsDistribMsg) : " << distrib_msgs << std::endl; - std::cerr << "Signed messages (RsDistribSignedMsg): " << signed_msgs << std::endl; - std::cerr << "Duplicate messages : " << nb_duplicated << std::endl; - - return 0; - } - catch(std::exception& e) - { - std::cerr << "Unhandled exception: " << e.what() << std::endl; - return 1 ; - } -} - - - diff --git a/libretroshare/src/tests/printcache/main_extended.cpp b/libretroshare/src/tests/printcache/main_extended.cpp deleted file mode 100644 index 2cdba7d8d..000000000 --- a/libretroshare/src/tests/printcache/main_extended.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - * main.cpp - * - * Created on: 11 Apr 2011 - * Author: greyfox - */ - -#include -#include -#include - -#include -#include "pqi/pqistreamer.h" -#include "pqi/pqibin.h" -#include "serialiser/rsdistribitems.h" -#include "pqi/pqistore.h" - -int storeMsg(std::map > &msgMap, std::string filename, - std::string grpId, std::string msgId); - -pqistore *BuildSerialiser(int type, std::string filename); - -int main(int argc, char **argv) -{ - - std::list fileList; - std::list::iterator fit; - - for(int i = 1; i < argc; i++) - { - fileList.push_back(argv[i]); - } - - std::map > msgMap; - std::map >::iterator mit; - - bool printInput = true; - bool printAll = true; - bool printSummary = true; - int distrib_msgs = 0; - int signed_msgs = 0; - - for(fit = fileList.begin(); fit != fileList.end(); fit++) - { - if (printInput) - { - std::cerr << "Loading File: " << *fit; - std::cerr << std::endl; - } - - /* process this file */ - pqistore *store = BuildSerialiser(0, *fit); - RsItem* item; - RsDistribMsg *distMsg; - RsDistribSignedMsg *signMsg; - - while(NULL != (item = store->GetItem())) - { - if (NULL != (distMsg = dynamic_cast(item))) - { - if (printInput) - { - std::cerr << "Grp = " << distMsg->grpId; - std::cerr << ", parent = " << distMsg->parentId; - std::cerr << ", msgId = " << distMsg->msgId; - std::cerr << std::endl; - } - storeMsg(msgMap, *fit, distMsg->grpId, distMsg->msgId); - ++distrib_msgs ; - } - if (NULL != (signMsg = dynamic_cast(item))) - { - if (printInput) - { - std::cerr << "Grp = " << signMsg->grpId; - std::cerr << ", msgId = " << signMsg->msgId; - std::cerr << ", type = " << signMsg->packet.tlvtype; - std::cerr << ", len = " << signMsg->packet.bin_len; - std::cerr << std::endl; - } - storeMsg(msgMap, *fit, signMsg->grpId, signMsg->msgId); - ++signed_msgs ; - } - } - - delete store; - } - for(mit = msgMap.begin(); mit != msgMap.end(); mit++) - { - bool print = printAll; - if (mit->second.size() > 1) - { - /* duplicates */ - print = true; - } - - if (print) - { - std::cerr << "MsgId: " << mit->first; - std::cerr << " in Files: "; - - std::list::iterator fit; - for(fit = mit->second.begin(); fit != mit->second.end(); fit++) - { - std::cerr << *fit << " "; - } - std::cerr << std::endl; - } - } - if (printSummary) - { - std::cerr << "# RsDistribMsg(s): " << distrib_msgs << std::endl; - std::cerr << "# RsDistribSignedMsg(s): " << signed_msgs << std::endl; - std::cerr << std::endl; - } -} - - -int storeMsg(std::map > &msgMap, std::string filename, - std::string grpId, std::string msgId) -{ - std::map >::iterator mit; - mit = msgMap.find(msgId); - if (mit == msgMap.end()) - { - std::list fileList; - fileList.push_back(filename); - msgMap[msgId] = fileList; - } - else - { - (mit->second).push_back(filename); - } - return 1; -} - - -pqistore *BuildSerialiser(int type, std::string filename) -{ - BinInterface *bio = new BinFileInterface(filename.c_str(), BIN_FLAGS_READABLE); - RsSerialiser *rsSerialiser = new RsSerialiser(); - RsSerialType *serialType = new RsDistribSerialiser(); - rsSerialiser->addSerialType(serialType); - - // can use type to add more serialiser types - //RsSerialType *serialType = new RsDistribSerialiser(); - //rsSerialiser->addSerialType(serialType); - - pqistore *store = new pqistore(rsSerialiser, "", bio, BIN_FLAGS_READABLE); - return store; -} - - diff --git a/libretroshare/src/tests/printcache/printcache.pro b/libretroshare/src/tests/printcache/printcache.pro deleted file mode 100644 index ed61aa4c9..000000000 --- a/libretroshare/src/tests/printcache/printcache.pro +++ /dev/null @@ -1,31 +0,0 @@ -TEMPLATE = app -CONFIG = debug - -#SOURCES = main.cpp -SOURCES = main_extended.cpp - -LIBS += ../../lib/libretroshare.a ../../../../libbitdht/src/lib/libbitdht.a ../../../../openpgpsdk/src/lib/libops.a -LIBS += -lssl -lcrypto -lupnp -lgnome-keyring -lixml -lbz2 - -INCLUDEPATH *= ../.. .. -linux { - #LIBS = -lstdc++ -lm -} -macx { - # ENABLE THIS OPTION FOR Univeral Binary BUILD. - # CONFIG += ppc x86 - # QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.4 - # CONFIG -= uitools - - LIBS += ../../lib/libretroshare.a - LIBS += -lssl -lcrypto -lz -lgpgme -lgpg-error -lassuan - LIBS += ../../../../../miniupnpc-1.0/libminiupnpc.a - LIBS += ../../../../libbitdht/src/lib/libbitdht.a - LIBS += -framework CoreFoundation - LIBS += -framework Security - - # LIBS += -framework CoreServices - - -} - diff --git a/libretroshare/src/tests/scripts/checks.mk b/libretroshare/src/tests/scripts/checks.mk deleted file mode 100644 index dcb19ff3f..000000000 --- a/libretroshare/src/tests/scripts/checks.mk +++ /dev/null @@ -1,25 +0,0 @@ -#Basic checks - -ifndef RS_TOP_DIR -dummy: - echo "RS_TOP_DIR is not defined in your makefile" -endif - -#ifndef SSL_DIR -#dummy: -# echo "you must define SSL_DIR before you can compile" -# -#endif - -ifneq ($(OS),Linux) - ifneq ($(OS),MacOSX) - ifndef PTHREADS_DIR -dummy: - echo "you must define PTHREADS_DIR before you can compile" - - endif - endif -endif - - - diff --git a/libretroshare/src/tests/scripts/config-cygwin.mk b/libretroshare/src/tests/scripts/config-cygwin.mk deleted file mode 100644 index ec4518f68..000000000 --- a/libretroshare/src/tests/scripts/config-cygwin.mk +++ /dev/null @@ -1,118 +0,0 @@ -ifneq ($(OS),Cygwin) -dummy: - echo "ERROR Cygwin configuration file included, but (OS != Cygwin) - -endif - -############ LINUX CONFIGURATION ######################## - -# flags for components.... -PQI_USE_XPGP = 1 -#PQI_USE_PROXY = 1 -#PQI_USE_CHANNELS = 1 -#USE_FILELOOK = 1 - -########################################################################### - -#### DrBobs Versions.... Please Don't Delete. -### Comment out if needed. -ALT_SRC_ROOT=/cygdrive/c/home/rmfern/prog/MinGW -SRC_ROOT=../../../.. - -PTHREADS_DIR=$(ALT_SRC_ROOT)/pthreads/pthreads.2 - -################### - -#ALT_SRC_ROOT=/cygdrive/c/RetroShareBuild/src -#SRC_ROOT=/cygdrive/c/RetroShareBuild/src - -#PTHREADS_DIR=$(ALT_SRC_ROOT)/pthreads-w32-2-8-0-release - -################### - -ZLIB_DIR=$(ALT_SRC_ROOT)/zlib-1.2.3 - -SSL_DIR=$(SRC_ROOT)/openssl-0.9.7g-xpgp-0.1c -UPNPC_DIR=$(SRC_ROOT)/miniupnpc-1.0 - -include $(RS_TOP_DIR)/scripts/checks.mk - -############ ENFORCE DIRECTORY NAMING ######################## - -CC = g++ -RM = /bin/rm -RANLIB = ranlib -LIBDIR = $(RS_TOP_DIR)/lib -LIBRS = $(LIBDIR)/libretroshare.a - -# Unix: Linux/Cygwin -INCLUDE = -I $(RS_TOP_DIR) - -ifdef PQI_DEBUG - CFLAGS = -Wall -g $(INCLUDE) -else - CFLAGS = -Wall -O2 $(INCLUDE) -endif - -ifdef PQI_USE_XPGP - INCLUDE += -I $(SSL_DIR)/include -endif - -ifdef PQI_USE_XPGP - CFLAGS += -DPQI_USE_XPGP -endif - -ifdef PQI_USE_PROXY - CFLAGS += -DPQI_USE_PROXY -endif - -ifdef PQI_USE_CHANNELS - CFLAGS += -DPQI_USE_CHANNELS -endif - -ifdef USE_FILELOOK - CFLAGS += -DUSE_FILELOOK -endif - - -RSCFLAGS = -Wall -g $(INCLUDE) - -######################################################################### -# OS Compile Options -######################################################################### - -# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) -BIOCC = gcc - -# Cygwin - ?same? as Linux flags -BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -m486 -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM - -######################################################################### -# OS specific Linking. -######################################################################### - -# for static pthread libs.... -WININC += -DPTW32_STATIC_LIB -WININC += -mno-cygwin -mwindows -fno-exceptions -WININC += -DWINDOWS_SYS - -WINLIB = -lws2_32 -luuid -lole32 -liphlpapi -WINLIB += -lcrypt32 -lwinmm - -CFLAGS += -I$(PTHREADS_DIR) $(WININC) -CFLAGS += -I$(ZLIB_DIR) - -LIBS = -L$(LIBDIR) -lretroshare -ifdef PQI_USE_XPGP - LIBS += -L$(SSL_DIR) -endif - -LIBS += -lssl -lcrypto -LIBS += -L$(UPNPC_DIR) -lminiupnpc -LIBS += -L$(ZLIB_DIR) -lz -LIBS += -L$(PTHREADS_DIR) -lpthreadGC2d -LIBS += $(WINLIB) - -RSCFLAGS += $(WININC) - - diff --git a/libretroshare/src/tests/scripts/config-linux.mk b/libretroshare/src/tests/scripts/config-linux.mk deleted file mode 100644 index c97a3c21e..000000000 --- a/libretroshare/src/tests/scripts/config-linux.mk +++ /dev/null @@ -1,78 +0,0 @@ - -ifneq ($(OS),Linux) -dummy: - echo "ERROR Linux configuration file included, but (OS != Linux) - -endif - -############ LINUX CONFIGURATION ######################## - -#UPNPC_DIR=../../../../miniupnpc-1.0 - -# Need to define miniupnpc version because API changed a little between v1.0 and 1.2 -# put 10 for 1.0 and 12 for 1.2 -DEFINES += -D_FILE_OFFSET_BITS=64 -DSQLITE_HAS_CODEC - -include $(RS_TOP_DIR)/tests/scripts/checks.mk - -############ ENFORCE DIRECTORY NAMING ######################## - -CC = g++ -RM = /bin/rm -RANLIB = ranlib -LIBDIR = $(RS_TOP_DIR)/lib -BITDIR = $(DHT_TOP_DIR)/lib -OPSDIR = $(OPS_TOP_DIR)/lib -LIBRS = $(LIBDIR)/libretroshare.a -BITDHT = $(BITDIR)/libbitdht.a -# Unix: Linux/Cygwin -INCLUDE = -I$(RS_TOP_DIR) -I$(OPS_TOP_DIR) -I$(DHT_TOP_DIR) -CFLAGS = -Wall -g $(INCLUDE) -I.. -#CFLAGS += -fprofile-arcs -ftest-coverage -CFLAGS += ${DEFINES} - -#ifdef PQI_USE_XPGP -# INCLUDE += -I $(SSL_DIR)/include -#endif -# -#ifdef PQI_USE_XPGP -# CFLAGS += -DPQI_USE_XPGP -#endif - -RSCFLAGS = -Wall -g $(INCLUDE) -######################################################################### -# OS Compile Options -######################################################################### - -# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) -BIOCC = gcc - -# march=i686 causes problems while 64Bit compiling, GCC tries to generate Output for a m64 machine, but the marchi686 -# doesnt allow the instructionfs for that. -# -# gcc docu: http://gcc.gnu.org/onlinedocs/gcc-4.0.3/gcc/i386-and-x86_002d64-Options.html#i386-and-x86_002d64-Options - -# Linux flags -BIOCFLAGS = -I $(SSL_DIR)/include ${DEFINES} -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM - -######################################################################### -# OS specific Linking. -######################################################################### - -LIBS = -L$(LIBDIR) -lretroshare -LIBS += -L$(BITDIR) -lbitdht -lgnome-keyring -LIBS += -L$(OPSDIR) -lops -LIBS += -lixml -lbz2 - -ifdef PQI_USE_XPGP - LIBS += -L$(SSL_DIR) - endif -LIBS += -lssl -lcrypto -lpthread -#LIBS += -L$(UPNPC_DIR) -lminiupnpc -LIBS += $(XLIB) -ldl -lz -LIBS += -lupnp -LIBS += -lsqlcipher - -RSLIBS = $(LIBS) - - diff --git a/libretroshare/src/tests/scripts/config-macosx.mk b/libretroshare/src/tests/scripts/config-macosx.mk deleted file mode 100644 index b13a471f0..000000000 --- a/libretroshare/src/tests/scripts/config-macosx.mk +++ /dev/null @@ -1,98 +0,0 @@ - -ifneq ($(OS),MacOSX) -dummy: - echo "ERROR MacOSX configuration file included, but (OS != MacOSX) - -endif - -############ LINUX CONFIGURATION ######################## - - -# FLAGS to decide if we want i386 Build or ppc Build -# -# - -# PPC is default -# Could define both for combined compilation... -# except might not work for bio_tou.c file! -# -# MAC_I386_BUILD = 1 -# MAC_PPC_BUILD = 1 - -MAC_I386_BUILD = 1 -#MAC_PPC_BUILD = 1 - -ifndef MAC_I386_BUILD - MAC_PPC_BUILD = 1 -endif - -UPNPC_DIR=../../../../../../src/miniupnpc-1.0 - -include $(RS_TOP_DIR)/tests/scripts/checks.mk - -############ ENFORCE DIRECTORY NAMING ######################## - -CC = g++ -RM = /bin/rm - -RANLIB = ranlib - -# Dummy ranlib -> can't do it until afterwards with universal binaries. -# RANLIB = ls -l - -OPSDIR = $(OPS_TOP_DIR)/lib -BITDIR = $(DHT_TOP_DIR)/lib -LIBDIR = $(RS_TOP_DIR)/lib -LIBRS = $(LIBDIR)/libretroshare.a - -OPT_DIR = /opt/local -OPT_INCLUDE = $(OPT_DIR)/include -OPT_LIBS = $(OPT_DIR)/lib - -INCLUDE = -I $(RS_TOP_DIR) -I $(OPT_INCLUDE) -#CFLAGS = -Wall -O3 -CFLAGS = -Wall -g - -# Flags for architecture builds. -ifdef MAC_I386_BUILD - CFLAGS += -arch i386 -endif - -ifdef MAC_PPC_BUILD - CFLAGS += -arch ppc -endif - -CFLAGS += $(INCLUDE) - -# This Line is for Universal BUILD for 10.4 + 10.5 -# (but unlikely to work unless Qt Libraries are build properly) -#CFLAGS += -isysroot /Developer/SDKs/MacOSX10.5.sdk - -# RSCFLAGS = -Wall -O3 $(INCLUDE) - -######################################################################### -# OS Compile Options -######################################################################### - -######################################################################### -# OS specific Linking. -######################################################################### - -LIBS = -Wl,-search_paths_first - -# for Univeral BUILD -# LIBS += -arch ppc -arch i386 -#LIBS += -Wl,-syslibroot,/Developer/SDKs/MacOSX10.5u.sdk - -LIBS = -L$(LIBDIR) -lretroshare -LIBS += -L$(BITDIR) -lbitdht -LIBS += -L$(OPSDIR) -lops -ifdef PQI_USE_XPGP - LIBS += -L$(SSL_DIR) - endif -LIBS += -lssl -lcrypto -lpthread -LIBS += -L$(UPNPC_DIR) -lminiupnpc -LIBS += $(XLIB) -ldl -lz - - - diff --git a/libretroshare/src/tests/scripts/config-mingw.mk b/libretroshare/src/tests/scripts/config-mingw.mk deleted file mode 100644 index c0040ac4e..000000000 --- a/libretroshare/src/tests/scripts/config-mingw.mk +++ /dev/null @@ -1,138 +0,0 @@ -#ifneq ($(OS),"Win ") -#dummy: -# echo "ERROR OS = $(OS)" -# echo "ERROR MinGW configuration file included, but (OS != Win) -# -#endif - -############ LINUX CONFIGURATION ######################## - -# flags for components.... -#PQI_USE_XPGP = 1 -#PQI_USE_PROXY = 1 -#PQI_USE_CHANNELS = 1 -#USE_FILELOOK = 1 - -########################################################################### - -#### DrBobs Versions.... Please Don't Delete. -### Comment out if needed. -SRC_ROOT_PKG=/home/Mark/prog/retroshare/package/rs-win-v0.5.0/src -SRC_ROOT_GPG=/local - -#ALT_SRC_ROOT=/cygdrive/c/home/rmfern/prog/MinGW -#SRC_ROOT=../../../.. - -PTHREADS_DIR=$(SRC_ROOT_PKG)/pthreads-w32-2-8-0/Pre-built.2 -ZLIB_DIR=$(SRC_ROOT_PKG)/zlib-1.2.3 -SSL_DIR=$(SRC_ROOT_PKG)/openssl-tmp -UPNPC_DIR=$(SRC_ROOT_PKG)/miniupnpc-1.3 - -########################################################################### - -#### Enable this section for compiling with MSYS/MINGW compile -#SRC_ROOT=/home/linux - -#SSL_DIR=$(SRC_ROOT)/OpenSSL -#GPGME_DIR=$(SRC_ROOT)/gpgme-1.1.8 -#GPG_ERROR_DIR=$(SRC_ROOT)/libgpg-error-1.7 - -#ZLIB_DIR=$(SRC_ROOT)/zlib-1.2.3 -#UPNPC_DIR=$(SRC_ROOT)/miniupnpc-1.0 -#PTHREADS_DIR=$(SRC_ROOT)/pthreads-w32-2-8-0-release - -include $(RS_TOP_DIR)/scripts/checks.mk - -############ ENFORCE DIRECTORY NAMING ####################################### - -CC = g++ -RM = /bin/rm -RANLIB = ranlib -LIBDIR = $(RS_TOP_DIR)/lib -LIBRS = $(LIBDIR)/libretroshare.a - -# Unix: Linux/Cygwin -INCLUDE = -I $(RS_TOP_DIR) - -ifdef PQI_DEBUG - CFLAGS = -Wall -g $(INCLUDE) -else - CFLAGS = -Wall -O2 $(INCLUDE) -endif - -# These aren't used anymore.... really. -ifdef PQI_USE_XPGP - CFLAGS += -DPQI_USE_XPGP -endif - -ifdef PQI_USE_PROXY - CFLAGS += -DPQI_USE_PROXY -endif - -ifdef PQI_USE_CHANNELS - CFLAGS += -DPQI_USE_CHANNELS -endif - -ifdef USE_FILELOOK - CFLAGS += -DUSE_FILELOOK -endif - - -# SSL / pthreads / Zlib -# included by default for Windows compilation. -INCLUDE += -I $(SSL_DIR)/include -INCLUDE += -I$(PTHREADS_DIR) -INCLUDE += -I$(ZLIB_DIR) - - -######################################################################### -# OS Compile Options -######################################################################### - -# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) -BIOCC = gcc - -# Cygwin - ?same? as Linux flags -BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -m486 -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM -BIOCFLAGS += -DWINDOWS_SYS - -######################################################################### -# OS specific Linking. -######################################################################### - -# for static pthread libs.... -#WININC += -DPTW32_STATIC_LIB -#WININC += -mno-cygwin -mwindows -fno-exceptions - -WININC += -DWINDOWS_SYS - -WINLIB = -lws2_32 -luuid -lole32 -liphlpapi -WINLIB += -lcrypt32 -lwinmm - -CFLAGS += -I$(SSL_DIR)/include -CFLAGS += -I$(PTHREADS_DIR)/include -CFLAGS += -I$(ZLIB_DIR) -CFLAGS += -I$(SRC_ROOT_GPG)/include - -### Enable this for GPGME and GPG ERROR dirs -#CFLAGS += -I$(GPGME_DIR)/src -#CFLAGS += -I$(GPG_ERROR_DIR)/src - -CFLAGS += $(WININC) - - - -LIBS = -L$(LIBDIR) -lretroshare - -LIBS += -L$(SSL_DIR) - -LIBS += -lssl -lcrypto -LIBS += -L$(UPNPC_DIR) -lminiupnpc -LIBS += -L$(ZLIB_DIR) -lz -LIBS += -L$(PTHREADS_DIR) -lpthreadGC2d -LIBS += $(WINLIB) - -#RSCFLAGS = -Wall -g $(INCLUDE) -#RSCFLAGS += $(WININC) - - diff --git a/libretroshare/src/tests/scripts/config.mk b/libretroshare/src/tests/scripts/config.mk deleted file mode 100644 index 951eca4c6..000000000 --- a/libretroshare/src/tests/scripts/config.mk +++ /dev/null @@ -1,27 +0,0 @@ - -# determine which operating system -# -########################################################################### -#Define OS. -# -OS = Linux -#OS = MacOSX -#OS = Cygwin -#OS = Win # MinGw. -########################################################################### - -ifeq ($(OS),Linux) - include $(RS_TOP_DIR)/tests/scripts/config-linux.mk -else - ifeq ($(OS),MacOSX) - include $(RS_TOP_DIR)/tests/scripts/config-macosx.mk - else - ifeq ($(OS),Cygwin) - include $(RS_TOP_DIR)/tests/scripts/config-cygwin.mk - else - include $(RS_TOP_DIR)/tests/scripts/config-mingw.mk - endif - endif -endif - -########################################################################### diff --git a/libretroshare/src/tests/scripts/regress.mk b/libretroshare/src/tests/scripts/regress.mk deleted file mode 100644 index 7d69df664..000000000 --- a/libretroshare/src/tests/scripts/regress.mk +++ /dev/null @@ -1,25 +0,0 @@ - -testoutputfiles = $(foreach tt,$(1),$(tt).tstout) - -%.tstout : %.sh % - -sh ./$< > $@ 2>&1 - -%.tstout : % - -./$< > $@ 2>&1 - -TESTOUT = $(call testoutputfiles,$(TESTS)) - -.phony : tests regress retest clobber - -tests: $(TESTS) - -regress: $(TESTOUT) - @-echo "--------------- SUCCESS (count):" - @-grep -c SUCCESS $(TESTOUT) - @-echo "--------------- FAILURE REPORTS:" - @-grep FAILURE $(TESTOUT) || echo no failures - @-echo "--------------- end" - -retest: - -/bin/rm $(TESTOUT) - diff --git a/libretroshare/src/tests/scripts/rules.mk b/libretroshare/src/tests/scripts/rules.mk deleted file mode 100644 index 3df30a488..000000000 --- a/libretroshare/src/tests/scripts/rules.mk +++ /dev/null @@ -1,24 +0,0 @@ - -# defines required / used. -# -# CFLAGS -# -# - -librs: $(RSOBJ) - $(AR) r $(LIBRS) $(RSOBJ) - $(RANLIB) $(LIBRS) - -.cc.o: - $(CC) $(CFLAGS) -c $< - -clean: - -/bin/rm -f $(RSOBJ) $(EXECOBJ) $(TESTOBJ) *.gcno *.gcda \ - *.gcov *.tstout $(TESTS) - -clobber: clean retest - -/bin/rm $(EXEC) $(TESTS) - - -include $(RS_TOP_DIR)/tests/scripts/regress.mk - diff --git a/libretroshare/src/tests/serialiser/TestNotes.txt b/libretroshare/src/tests/serialiser/TestNotes.txt deleted file mode 100644 index 90c459120..000000000 --- a/libretroshare/src/tests/serialiser/TestNotes.txt +++ /dev/null @@ -1,56 +0,0 @@ - -Few test still need to be done. Needs to be automated - -used support(.h/.cc) file for testing RsItems - -Components and Tests. -============================================================ ------------------------------------------------------------- -Basic Items ------------------------------------------------------------- -rsbaseitems.cc : needed -rsbaseserial.cc : needed -rsconfigitems.cc : needed -rsserial.cc : needed - - - - ------------------------------------------------------------- -Compound TLV Components ------------------------------------------------------------- - -rstlvaddrs.cc : needed -rstlvbase.cc : not finished, tlvbase_test -rstlvfileitem.cc : tlvtypes_test -rstlvimage.cc : tlvtypes_test -rstlvkeys.cc : tlvtypes_test -rstlvkvwide.cc : rstlvwidetest -rstlvtypes.cc : tlvtypes_test -rstlvutil.cc : no need - ------------------------------------------------------------- -Service Components ------------------------------------------------------------- -rstunnelitems.cc : rstunnelitem_test & rsturtleitem_test -rsdistribitem.cc : distribitem_test -rsmsgitem.cc : msgitem_test -rsdiscitems.cc : needed -rsrankitems.cc : needed -rsblogitems.cc : distribitem_test -rschannelitems.cc : distribitem_test -rsforumitems.cc : distribitem_test -rsstatusitems.cc : needed -rsgameitems.cc : TBC -rsphotoitems.cc : TBC - -============================================================ -Test Specifics -============================================================ - ------------------------------------------------------------- -Basic Components ------------------------------------------------------------- - - - diff --git a/libretroshare/src/tests/serialiser/distribitem_test.cc b/libretroshare/src/tests/serialiser/distribitem_test.cc deleted file mode 100644 index 3cc551f0f..000000000 --- a/libretroshare/src/tests/serialiser/distribitem_test.cc +++ /dev/null @@ -1,365 +0,0 @@ -/* - * libretroshare/src/serialiser: distribitem_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2010 by Christopher Evi-Parker. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include -#include "util/rstime.h" -#include "serialiser/rsdistribitems.h" -#include "serialiser/rschannelitems.h" -#include "serialiser/rsforumitems.h" -#include "serialiser/rsblogitems.h" -#include "retroshare/rsdistrib.h" -#include "serialiser/rstlvutil.h" -#include "util/utest.h" -#include "support.h" - -#include "distribitem_test.h" - -INITTEST() - -/** base rs distrib items **/ - - - - -RsSerialType* init_item(RsDistribGrp& grp) -{ - - rstime_t now = time(NULL); - - /* create Keys */ - - /* Create Group Description */ - - randString(SHORT_STR, grp.grpName); - randString(LARGE_STR, grp.grpDesc); - - grp.timestamp = now; - grp.grpFlags = (RS_DISTRIB_PRIVACY_MASK | RS_DISTRIB_AUTHEN_MASK); - grp.grpControlFlags = 0; - - init_item(grp.grpPixmap); - - /* set keys */ - - RsTlvSecurityKey publish_key; - - init_item(grp.adminKey); - init_item(publish_key); - init_item(grp.adminSignature); - - grp.publishKeys.keys[publish_key.keyId] = publish_key; - grp.publishKeys.groupId = grp.adminKey.keyId; - grp.grpId = grp.adminKey.keyId; - - init_item(grp.grpControlList); - - return new RsDistribSerialiser(); - -} - - -RsSerialType* init_item(RsDistribGrpKey& gk) -{ - - init_item(gk.key); - gk.grpId = gk.key.keyId; - - return new RsDistribSerialiser(); - -} - - -bool operator==(const RsDistribGrpKey& gk1, const RsDistribGrpKey& gk2) -{ - if(gk1.grpId != gk1.grpId) return false; - if(!(gk1.key == gk2.key)) return false; - - return true; -} - -RsSerialType* init_item(RsDistribSignedMsg& sMsg) -{ - - RsChannelMsg chMsg; - RsSerialType* ser = init_item(chMsg); - uint32_t chMsgSize = ser->size(&chMsg); - char* chMsgData = new char[chMsgSize]; - ser->serialise(&chMsg, chMsgData, &chMsgSize); - delete ser; - - sMsg.packet.setBinData(chMsgData, chMsgSize); - sMsg.flags = rand()%300; - randString(SHORT_STR, sMsg.grpId); - - return new RsDistribSerialiser(); -} - -bool operator==(const RsDistribSignedMsg& sMsg1,const RsDistribSignedMsg& sMsg2) -{ - - if(!(sMsg1.packet == sMsg2.packet)) return false; - if(sMsg1.grpId != sMsg2.grpId) return false; - if(sMsg1.flags != sMsg2.flags) return false; - - return true; -} - - -RsSerialType* init_item(RsChannelMsg& chMsg) -{ - randString(SHORT_STR, chMsg.grpId); - randString(LARGE_STR, chMsg.message); - randString(SHORT_STR, chMsg.subject); - randString(SHORT_STR, chMsg.threadId); - chMsg.timestamp = rand()%31452; - init_item(chMsg.thumbnail); - init_item(chMsg.attachment); - - return new RsChannelSerialiser(); -} - - -bool operator==(const RsChannelMsg& chMsg1,const RsChannelMsg& chMsg2) -{ - - if(chMsg1.grpId != chMsg2.grpId) return false; - if(chMsg1.message != chMsg2.message) return false; - if(!(chMsg1.attachment == chMsg2.attachment)) return false; - if(chMsg1.subject != chMsg2.subject) return false; - if(chMsg2.threadId != chMsg2.threadId) return false; - if(chMsg1.timestamp != chMsg2.timestamp) return false; - if(!(chMsg1.thumbnail.binData == chMsg2.thumbnail.binData)) return false; - if(chMsg1.thumbnail.image_type != chMsg2.thumbnail.image_type) return false; - - return true; -} - -RsSerialType* init_item(RsForumMsg& fMsg) -{ - - fMsg.timestamp = rand()%242; - randString(SHORT_STR, fMsg.grpId); - randString(LARGE_STR, fMsg.msg); - randString(SHORT_STR, fMsg.parentId); - randString(SHORT_STR, fMsg.srcId); - randString(SHORT_STR, fMsg.threadId); - randString(SHORT_STR, fMsg.title); - - return new RsForumSerialiser(); -} - - - -bool operator==(const RsForumMsg& fMsg1, const RsForumMsg& fMsg2) -{ - if(fMsg1.grpId != fMsg2.grpId) return false; - if(fMsg1.msg != fMsg2.msg) return false; - if(fMsg1.parentId != fMsg2.parentId) return false; - if(fMsg1.srcId != fMsg2.srcId) return false; - if(fMsg1.threadId != fMsg2.threadId) return false; - if(fMsg1.timestamp != fMsg2.timestamp) return false; - if(fMsg1.title != fMsg2.title) return false; - - return true; -} - -RsSerialType* init_item(RsBlogMsg& bMsg) -{ - bMsg.timestamp = rand()%223; - randString(SHORT_STR, bMsg.grpId); - randString(LARGE_STR, bMsg.message); - randString(SHORT_STR, bMsg.subject); - randString(SHORT_STR, bMsg.parentId); - randString(SHORT_STR, bMsg.threadId); - RsTlvImage image; - int nImages = rand()%5; - - for(int i=0; i < nImages; i++) - { - init_item(image); - bMsg.graphic_set.push_back(image); - } - - return new RsBlogSerialiser(); -} - - -bool operator==(const RsDistribGrp& g1, const RsDistribGrp& g2) -{ - - if(g1.grpCategory != g2.grpCategory) return false; - if(g1.grpControlFlags != g2.grpControlFlags) return false; - if(!(g1.grpControlList == g2.grpControlList)) return false; - if(g1.grpDesc != g2.grpDesc) return false; - if(g1.grpFlags != g2.grpFlags) return false; - if(g1.grpId != g2.grpId) return false; - if(g1.grpName != g2.grpName) return false; - if(g1.timestamp != g2.timestamp) return false; - - // admin key - - if(!(g1.adminKey == g2.adminKey)) return false; - if(!(g1.adminSignature == g2.adminSignature)) return false; - if(g1.grpPixmap.image_type != g2.grpPixmap.image_type) return false; - if(!(g1.grpPixmap.binData == g2.grpPixmap.binData)) return false; - - return true; -} - - - -RsSerialType* init_item(RsForumReadStatus& fRdStatus) -{ - randString(SHORT_STR, fRdStatus.forumId); - fRdStatus.save_type = rand()%42; - - std::map::iterator mit = fRdStatus.msgReadStatus.begin(); - - std::string id; - uint32_t status = 0; - - int numMaps = rand()%12; - - for(int i = 0; i < numMaps; i++) - { - randString(SHORT_STR, id); - status = rand()%23; - - fRdStatus.msgReadStatus.insert(std::pair(id, status)); - } - - return new RsForumSerialiser(); -} - -bool operator==(const RsForumReadStatus& frs1, const RsForumReadStatus& frs2) -{ - if(frs1.forumId != frs2.forumId) return false; - if(frs1.save_type != frs2.save_type) return false; - - if(frs1.msgReadStatus.size() != frs2.msgReadStatus.size()) return false; - - std::map::const_iterator mit - = frs1.msgReadStatus.begin(); - - - - for(;mit != frs1.msgReadStatus.end(); mit++) - { - if(mit->second != frs2.msgReadStatus.find(mit->first)->second) return false; - } - - return true; - -} - - - -RsSerialType* init_item(RsChannelReadStatus& fRdStatus) -{ - randString(SHORT_STR, fRdStatus.channelId); - fRdStatus.save_type = rand()%42; - - std::map::iterator mit = fRdStatus.msgReadStatus.begin(); - - std::string id; - uint32_t status = 0; - - int numMaps = rand()%12; - - for(int i = 0; i < numMaps; i++) - { - randString(SHORT_STR, id); - status = rand()%23; - - fRdStatus.msgReadStatus.insert(std::pair(id, status)); - } - - return new RsChannelSerialiser(); -} - -bool operator==(const RsChannelReadStatus& frs1, const RsChannelReadStatus& frs2) -{ - if(frs1.channelId != frs2.channelId) return false; - if(frs1.save_type != frs2.save_type) return false; - - if(frs1.msgReadStatus.size() != frs2.msgReadStatus.size()) return false; - - std::map::const_iterator mit - = frs1.msgReadStatus.begin(); - - - - for(;mit != frs1.msgReadStatus.end(); mit++) - { - if(mit->second != frs2.msgReadStatus.find(mit->first)->second) return false; - } - - return true; - -} - - -bool operator==(const RsBlogMsg& bMsg1,const RsBlogMsg& bMsg2) -{ - - if(bMsg1.timestamp != bMsg2.timestamp) return false; - if(bMsg1.grpId != bMsg2.grpId) return false; - if(bMsg1.message != bMsg2.message) return false; - if(bMsg1.subject != bMsg2.subject) return false; - if(bMsg1.threadId != bMsg2.threadId) return false; - if(bMsg1.parentId != bMsg2.parentId) return false; - - std::list::const_iterator it1 = bMsg1.graphic_set.begin(), - it2 = bMsg2.graphic_set.begin(); - - if(bMsg1.graphic_set.size() != bMsg2.graphic_set.size()) return false; - - for(; it1 != bMsg1.graphic_set.end() ; it1++, it2++) - { - if(!(*it1 == *it2)) return false; - } - - return true; -} - -int main(){ - - std::cerr << "RsDistribItem Tests" << std::endl; - - test_RsItem(); REPORT("Serialise/Deserialise RsDistribGrp"); - test_RsItem(); REPORT("Serialise/Deserialise RsDistribGrpKey"); - test_RsItem(); REPORT("Serialise/Deserialise RsDistribSignedMsg"); - test_RsItem(); REPORT("Serialise/Deserialise RsChannelMsg"); - test_RsItem(); REPORT("Serialise/Deserialise RsChannelReadStatus"); - test_RsItem(); REPORT("Serialise/Deserialise RsForumMsg"); - test_RsItem(); REPORT("Serialise/Deserialise RsForumReadStatus"); - test_RsItem(); REPORT("Serialise/Deserialise RsBlogMsg"); - - - FINALREPORT("RsDistribItem Tests"); - - return TESTRESULT(); -} - diff --git a/libretroshare/src/tests/serialiser/distribitem_test.h b/libretroshare/src/tests/serialiser/distribitem_test.h deleted file mode 100644 index 1eedfd643..000000000 --- a/libretroshare/src/tests/serialiser/distribitem_test.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef DISTRIBITEM_TEST_H_ -#define DISTRIBITEM_TEST_H_ - -/* - * libretroshare/src/serialiser: distribitem_test.h - * - * RetroShare Serialiser tests - * - * Copyright 2010 by Christopher Evi-Parker. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "serialiser/rsdistribitems.h" -#include "serialiser/rschannelitems.h" -#include "serialiser/rsforumitems.h" -#include "serialiser/rsblogitems.h" - - - -RsSerialType* init_item(RsDistribGrp&); -RsSerialType* init_item(RsDistribGrpKey&); -RsSerialType* init_item(RsDistribSignedMsg&); -RsSerialType* init_item(RsChannelMsg&); -RsSerialType* init_item(RsForumMsg&); -RsSerialType* init_item(RsForumReadStatus&); -RsSerialType* init_item(RsBlogMsg&); - -bool operator==(const RsDistribGrp& , const RsDistribGrp& ); -bool operator==(const RsDistribGrpKey& , const RsDistribGrpKey& ); -bool operator==(const RsDistribSignedMsg& , const RsDistribSignedMsg& ); -bool operator==(const RsChannelMsg& , const RsChannelMsg& ); -bool operator==(const RsForumMsg& , const RsForumMsg& ); -bool operator==(const RsForumReadStatus&, const RsForumReadStatus& ); -bool operator==(const RsBlogMsg& , const RsBlogMsg& ); - - - - -#endif /* DISTRIBITEM_TEST_H_ */ diff --git a/libretroshare/src/tests/serialiser/perform_auto_tests.sh b/libretroshare/src/tests/serialiser/perform_auto_tests.sh deleted file mode 100755 index e9857c4ec..000000000 --- a/libretroshare/src/tests/serialiser/perform_auto_tests.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh - -printresult() { - if test "$?" = "0"; then - echo ' 'PASSED - else - echo *FAILED* - fi -} - -# Warning: printresult needs to be called before anything else because it contains the -# result of the call to the test program, until the next command. - -exes="rsstatusitem_test \ - tlvbase_test \ - rsserial_test \ - tlvtypes_test \ - rsmsgitem_test \ - rstunnelitem_test \ - tlvrandom_test \ - rstlvwidetest \ - rsconfigitem_test \ - rsturtleitem_test \ - tlvitems_test \ - distribitem_test \ - tlvstack_test \ - tlvbase_test2" - -for exe in $exes; do - ./$exe > /dev/null 2>&1 ; result=`printresult`; echo "-- $exe \t test :" $result ; -done - - - diff --git a/libretroshare/src/tests/serialiser/rsbaseitem_test.cc b/libretroshare/src/tests/serialiser/rsbaseitem_test.cc deleted file mode 100644 index 4743e5248..000000000 --- a/libretroshare/src/tests/serialiser/rsbaseitem_test.cc +++ /dev/null @@ -1,191 +0,0 @@ - -/* - * libretroshare/src/serialiser: rsbaseitem_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****************************************************************** - * tlvfileitem test. - * - * - */ - -#include -#include -#include "serialiser/rstlvtypes.h" -#include "serialiser/rstlvutil.h" -#include "util/utest.h" - -INITTEST(); - -static int test_RsFileItem(); -static int test_RsFileData(); - -int main() -{ - std::cerr << "RsFile[Item/Data/...] Tests" << std::endl; - - test_RsFileItem(); - test_RsFileData(); - - FINALREPORT("RsTlvFile[Item/Data/...] Tests"); - - return TESTRESULT(); -} - -int test_RsTlvFileItem() -{ - - - - - RsTlvFileItem i1; - RsTlvFileItem i2; - - /* initialise */ - i1.filesize = 101010; - i1.hash = "ABCDEFEGHE"; - i1.name = "TestFile.txt"; - i1.pop = 12; - i1.age = 456; - - CHECK(test_SerialiseTlvItem(std::cerr, &i1, &i2)); - - /* check the data is the same */ - CHECK(i1.filesize == i2.filesize); - CHECK(i1.hash == i2.hash); - CHECK(i1.name == i2.name); - CHECK(i1.path == i2.path); - CHECK(i1.pop == i2.pop); - CHECK(i1.age == i2.age); - - /* do it again without optional data */ - i1.filesize = 123; - i1.name = ""; - i1.pop = 0; - i1.age = 0; - - CHECK(test_SerialiseTlvItem(std::cerr, &i1, &i2)); - - /* check the data is the same */ - CHECK(i1.filesize == i2.filesize); - CHECK(i1.hash == i2.hash); - CHECK(i1.name == i2.name); - CHECK(i1.path == i2.path); - CHECK(i1.pop == i2.pop); - CHECK(i1.age == i2.age); - - /* one more time - long file name, some optional data */ - i1.filesize = 123; - i1.name = "A Very Long File name that should fit in easily ??? with som $&%&^%* strange char (**$^%#&^$#*^%(&^ in there too!!!! ~~~!!$#(^$)$)(&%^)&\" oiyu thend"; - i1.pop = 666; - i1.age = 0; - - CHECK(test_SerialiseTlvItem(std::cerr, &i1, &i2)); - - /* check the data is the same */ - CHECK(i1.filesize == i2.filesize); - CHECK(i1.hash == i2.hash); - CHECK(i1.name == i2.name); - CHECK(i1.path == i2.path); - CHECK(i1.pop == i2.pop); - CHECK(i1.age == i2.age); - - REPORT("Serialise/Deserialise RsTlvFileItem"); - - return 1; -} - -int test_RsTlvFileSet() -{ - RsTlvFileSet s1; - RsTlvFileSet s2; - - int i = 0; - for(i = 0; i < 15; i++) - { - RsTlvFileItem fi; - fi.filesize = 16 + i * i; - fi.hash = "ABCDEF"; - std::ostringstream out; - out << "File" << i << "_inSet.txt"; - fi.name = out.str(); - if (i % 2 == 0) - { - fi.age = 10 * i; - } - else - { - fi.age = 0; - } - fi.pop = 0; - - s1.items.push_back(fi); - } - - CHECK(test_SerialiseTlvItem(std::cerr, &s1, &s2)); - - /* check the data is the same - TODO */ - - REPORT("Serialise/Deserialise RsTlvFileSet"); - - return 1; -} - - -int test_RsTlvFileData() -{ - RsTlvFileData d1; - RsTlvFileData d2; - - /* initialise */ - d1.file.filesize = 101010; - d1.file.hash = "ABCDEFEGHE"; - d1.file.name = ""; - d1.file.age = 0; - d1.file.pop = 0; - - char data[15]; - d1.binData.setBinData(data, 15); - - d1.file_offset = 222; - - CHECK(test_SerialiseTlvItem(std::cerr, &d1, &d2)); - - /* check the data is the same */ - CHECK(d1.file.filesize == d2.file.filesize); - CHECK(d1.file.hash == d2.file.hash); - CHECK(d1.file.name == d2.file.name); - CHECK(d1.file.path == d2.file.path); - CHECK(d1.file.pop == d2.file.pop); - CHECK(d1.file.age == d2.file.age); - - CHECK(d1.file_offset == d2.file_offset); - CHECK(d1.binData.bin_len == d2.binData.bin_len); - - REPORT("Serialise/Deserialise RsTlvFileData"); - - return 1; -} - - diff --git a/libretroshare/src/tests/serialiser/rsconfigitem_test.cc b/libretroshare/src/tests/serialiser/rsconfigitem_test.cc deleted file mode 100644 index 1ac41ae09..000000000 --- a/libretroshare/src/tests/serialiser/rsconfigitem_test.cc +++ /dev/null @@ -1,328 +0,0 @@ -/* - * libretroshare/src/tests/serialiser: rsconfigitemstest.cc - * - * RetroShare Serialiser tests. - * - * Copyright 2011 by Christopher Evi-Parker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "rsconfigitem_test.h" -#include "util/utest.h" -#include "support.h" - - - -INITTEST() - -RsSerialType* init_item(RsPeerNetItem& rpn) -{ - randString(SHORT_STR, rpn.dyndns); - randString(SHORT_STR, rpn.gpg_id); - randString(SHORT_STR, rpn.location); - randString(SHORT_STR, rpn.pid); - - rpn.lastContact = rand()%42424; - rpn.netMode = rand()%313190; - rpn.visState = rand()%63635; - - - inet_aton("10.0.0.111", &(rpn.currentlocaladdr.sin_addr)); - rpn.currentlocaladdr.sin_port = htons(1111); - - inet_aton("123.1.2.123", &(rpn.currentremoteaddr.sin_addr)); - rpn.currentremoteaddr.sin_port = htons(1234); - - RsTlvIpAddressInfo ipa1, ipa2; - - ipa1.addr = rpn.currentlocaladdr; - ipa1.seenTime = rand()%40149013; - ipa1.source = rand()%13423; - - ipa2.addr = rpn.currentremoteaddr; - ipa2.seenTime = rand()%40139013; - ipa2.source = rand()%1343443; - - rpn.extAddrList.addrs.push_back(ipa1); - rpn.extAddrList.addrs.push_back(ipa2); - - rpn.localAddrList.addrs.push_back(ipa1); - rpn.localAddrList.addrs.push_back(ipa2); - - - return new RsPeerConfigSerialiser(); -} - -RsSerialType* init_item(RsPeerOldNetItem& rpon) -{ - return new RsPeerConfigSerialiser(); -} - -RsSerialType* init_item(RsPeerGroupItem& rpgi){ - - rpgi.flag = rand()%134344; - randString(SHORT_STR, rpgi.id); - randString(SHORT_STR, rpgi.name); - std::string p1, p2, p3; - randString(SHORT_STR, p1); - randString(SHORT_STR, p2); - randString(SHORT_STR, p3); - - rpgi.peerIds.push_back(p1); - rpgi.peerIds.push_back(p2); - rpgi.peerIds.push_back(p3); - - return new RsPeerConfigSerialiser(); -} - -RsSerialType* init_item(CompressedChunkMap& map) -{ - map._map.clear() ; - for(uint32_t i=0;i<15;++i) - map._map.push_back(rand()) ; - - return new RsTurtleSerialiser(); -} - -RsSerialType* init_item(RsPeerStunItem& rpsi) -{ - std::string p1, p2, p3; - randString(SHORT_STR, p1); - randString(SHORT_STR, p2); - randString(SHORT_STR, p3); - - rpsi.stunList.ids.push_back(p1); - rpsi.stunList.ids.push_back(p2); - rpsi.stunList.ids.push_back(p3); - - rpsi.stunList.mType = TLV_TYPE_PEERSET; - - return new RsPeerConfigSerialiser(); -} -RsSerialType* init_item(RsCacheConfig& rcc) -{ - - rcc.cachesubid = rand()%2342; - rcc.cachetypeid = rand()%323; - rcc.recvd = rand()%2252243; - rcc.size = rand()%02203; - randString(SHORT_STR, rcc.hash); - randString(SHORT_STR, rcc.name); - randString(SHORT_STR, rcc.path); - randString(SHORT_STR, rcc.pid); - - return new RsCacheConfigSerialiser(); -} - -RsSerialType* init_item(RsFileTransfer& rft) -{ - - std::string p1, p2, p3; - randString(SHORT_STR, p1); - randString(SHORT_STR, p2); - randString(SHORT_STR, p3); - - rft.allPeerIds.ids.push_back(p1); - rft.allPeerIds.ids.push_back(p2); - rft.allPeerIds.ids.push_back(p3); - rft.allPeerIds.mType = TLV_TYPE_PEERSET; - -// -// rft.compressed_chunk_map._map.clear(); -// const int mapSize = 15; -// rft.compressed_chunk_map._map.resize(mapSize); -// for(int i=0; i& left, - const std::list& right) -{ - std::list::const_iterator cit1 = left.begin(), - cit2 = right.begin(); - - for(; cit1 != left.end() ; cit1++, cit2++){ - - if(*cit1 != *cit2) - return false; - } - - return true; -} - -bool operator!=(const sockaddr_in& left, const sockaddr_in& right) -{ - if(left.sin_addr.s_addr != right.sin_addr.s_addr) return true; - if(left.sin_port != right.sin_port) return true; - - return false; -} - -bool operator!=(const RsTlvIpAddressInfo& left, const RsTlvIpAddressInfo& right) -{ - - if(left.addr != right.addr) return true; - if(left.seenTime != right.seenTime) return true; - if(left.source != right.source) return true; - - return false; -} - - -bool operator==(const RsPeerOldNetItem& left, const RsPeerOldNetItem& right) -{ - return false; -} - -bool operator==(const RsPeerGroupItem& left, const RsPeerGroupItem& right) -{ - if(left.flag != right.flag) return false; - if(left.id != right.id) return false; - if(left.name != right.name) return false; - if(left.peerIds != right.peerIds) return false; - - return true; -} - -bool operator!=(const std::list& left, - const std::list& right) -{ - std::list::const_iterator cit1 = left.begin(), - cit2 = right.begin(); - - for(; cit1 != left.end(); cit1++, cit2++){ - - if(*cit1 != *cit2) - return true; - } - - return false; -} - -bool operator==(const RsPeerStunItem& left, const RsPeerStunItem& right) -{ - if(!(left.stunList == right.stunList)) return false; - - return true; -} - -//bool operator==(const RsTlvPeerIdSet& left, const RsTlvPeerIdSet& right) -//{ -// if(left.mType != right.mType) return false; -// -// std::list::iterator cit1 = left.ids.begin(), -// cit2 = right.ids.begin(); -// -// for(; cit1 != left.ids.end(); cit1++, cit2++){ -// -// if(*cit1 != *cit2) -// return false; -// } -// -// return true; -//} - -bool operator==(const RsCacheConfig& left, const RsCacheConfig& right) -{ - - if(left.cachesubid != right.cachesubid) return false; - if(left.cachetypeid != right.cachetypeid) return false; - if(left.hash != right.hash) return false; - if(left.path != right.path) return false; - if(left.pid != right.pid) return false; - if(left.recvd != right.recvd) return false; - if(left.size != right.size) return false; - - return true; -} - -bool operator==(const RsFileTransfer& left, const RsFileTransfer& right) -{ - - if(!(left.allPeerIds == right.allPeerIds)) return false; - if(left.cPeerId != right.cPeerId) return false; - if(left.chunk_strategy != right.chunk_strategy) return false; - if(left.compressed_chunk_map._map != right.compressed_chunk_map._map) return false; - if(left.crate != right.crate) return false; - if(!(left.file == right.file)) return false; - if(left.flags != right.flags) return false; - if(left.in != right.in) return false; - if(left.lrate != right.lrate) return false; - if(left.ltransfer != right.ltransfer) return false; - if(left.state != right.state) return false; - if(left.transferred != right.transferred) return false; - if(left.trate != right.trate) return false; - - return true; -} - - - -int main() -{ - - std::cerr << "RsConfigItems Tests" << std::endl; - - test_RsItem(); REPORT("Serialise/Deserialise RsPeerNetItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsPeerGroupItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsPeerStunItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsCacheConfig"); - test_RsItem(); REPORT("Serialise/Deserialise RsFileTransfer"); - - FINALREPORT("RsConfigItems Tests"); - - return TESTRESULT(); -} diff --git a/libretroshare/src/tests/serialiser/rsconfigitem_test.h b/libretroshare/src/tests/serialiser/rsconfigitem_test.h deleted file mode 100644 index 2571d5c30..000000000 --- a/libretroshare/src/tests/serialiser/rsconfigitem_test.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * libretroshare/src/serialiser: rsconfigitem_test.h - * - * RetroShare Serialiser tests. - * - * Copyright 2011 by Christopher Evi-Parker. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#ifndef RSCONFIGITEM_TEST_H_ -#define RSCONFIGITEM_TEST_H_ - -#include "serialiser/rsconfigitems.h" -#include "turtle/rsturtleitem.h" - -RsSerialType* init_item(CompressedChunkMap& map); -RsSerialType* init_item(RsPeerNetItem& ); -RsSerialType* init_item(RsPeerOldNetItem& ); -RsSerialType* init_item(RsPeerGroupItem& ); -RsSerialType* init_item(RsPeerStunItem& ); -RsSerialType* init_item(RsCacheConfig& ); -RsSerialType* init_item(RsFileTransfer& ); - -bool operator==(const RsPeerNetItem&, const RsPeerNetItem& ); -bool operator==(const RsPeerOldNetItem&, const RsPeerOldNetItem& ); -bool operator==(const RsPeerGroupItem&, const RsPeerGroupItem& ); -bool operator==(const RsPeerStunItem&, const RsPeerStunItem& ); -bool operator==(const RsCacheConfig&, const RsCacheConfig& ); -bool operator==(const RsFileTransfer&, const RsFileTransfer& ); - -bool operator==(const std::list&, - const std::list&); - -bool operator!=(const sockaddr_in&, const sockaddr_in&); -bool operator!=(const RsTlvIpAddressInfo&, const RsTlvIpAddressInfo& ); -bool operator!=(const std::list& left, - const std::list& right); -//bool operator==(const RsTlvPeerIdSet& left, const RsTlvPeerIdSet& right); -bool operator==(const RsTlvFileItem&, const RsTlvFileItem& ); - - - -#endif /* RSCONFIGITEM_TEST_H_ */ diff --git a/libretroshare/src/tests/serialiser/rsgrouteritem_test.cc b/libretroshare/src/tests/serialiser/rsgrouteritem_test.cc deleted file mode 100644 index 737b5155f..000000000 --- a/libretroshare/src/tests/serialiser/rsgrouteritem_test.cc +++ /dev/null @@ -1,217 +0,0 @@ -/* - * libretroshare/src/tests/serialiser: msgitem_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2010 by Christopher Evi-Parker. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include -#include - -#include "util/rsrandom.h" -#include "grouter/grouteritems.h" -#include "serialiser/rstlvutil.h" -#include "util/utest.h" -#include "support.h" -#include "rsmsgitem_test.h" - -INITTEST(); - -RsSerialType* init_item(RsGRouterGenericDataItem& cmi) -{ - cmi.data_size = lrand48()%1000 + 1000 ; - cmi.data_bytes = (uint8_t*)malloc(cmi.data_size) ; - RSRandom::random_bytes(cmi.data_bytes,cmi.data_size) ; - cmi.routing_id = RSRandom::random_u32() ; - - Sha1CheckSum cs ; - for(int i=0;i<5;++i) cs.fourbytes[i] = RSRandom::random_u32() ; - cmi.destination_key = cs ; - - return new RsGRouterSerialiser(); -} -RsSerialType* init_item(RsGRouterACKItem& cmi) -{ - cmi.mid = RSRandom::random_u32() ; - cmi.state = RSRandom::random_u32() ; - - return new RsGRouterSerialiser(); -} -RsSerialType* init_item(RsGRouterPublishKeyItem& cmi) -{ - cmi.diffusion_id = RSRandom::random_u32() ; - cmi.service_id = RSRandom::random_u32() ; - cmi.randomized_distance = RSRandom::random_f32() ; - - Sha1CheckSum cs ; - for(int i=0;i<5;++i) cs.fourbytes[i] = RSRandom::random_u32() ; - cmi.published_key = cs ; - cmi.description_string = "test key" ; - - return new RsGRouterSerialiser(); -} -RsSerialType* init_item(RsGRouterRoutingInfoItem& cmi) -{ - cmi.origin = SSLIdType::random() ; - cmi.received_time = RSRandom::random_u64() ; - cmi.status_flags = RSRandom::random_u32() ; - - cmi.data_item = new RsGRouterGenericDataItem ; - - uint32_t n = 10+(RSRandom::random_u32()%30) ; - - for(uint32_t i=0;i 0.001) return false; - if(cmiLeft.description_string != cmiRight.description_string) return false; - - return true ; -} -bool operator ==(const RsGRouterACKItem& cmiLeft,const RsGRouterACKItem& cmiRight) -{ - if(cmiLeft.mid != cmiRight.mid) return false; - if(cmiLeft.state != cmiRight.state) return false; - - return true; -} -bool operator ==(const RsGRouterMatrixCluesItem& cmiLeft,const RsGRouterMatrixCluesItem& cmiRight) -{ - if(!(cmiLeft.destination_key == cmiRight.destination_key)) return false; - if(cmiLeft.clues.size() != cmiRight.clues.size()) return false; - - std::list::const_iterator itl = cmiLeft.clues.begin() ; - std::list::const_iterator itr = cmiRight.clues.begin() ; - - while(itl != cmiLeft.clues.end()) - { - if( (*itl).friend_id != (*itr).friend_id) return false ; - if( (*itl).time_stamp != (*itr).time_stamp) return false ; - - ++itl ; - ++itr ; - } - - return true; -} -bool operator ==(const RsGRouterMatrixFriendListItem& cmiLeft,const RsGRouterMatrixFriendListItem& cmiRight) -{ - if(cmiLeft.reverse_friend_indices.size() != cmiRight.reverse_friend_indices.size()) return false; - - for(uint32_t i=0;i::const_iterator itl(cmiLeft.tried_friends.begin()) ; - std::list::const_iterator itr(cmiRight.tried_friends.begin()) ; - - while(itl != cmiLeft.tried_friends.end()) - { - if( (*itl).friend_id != (*itr).friend_id) return false ; - if( (*itl).time_stamp != (*itr).time_stamp) return false ; - - ++itl ; - ++itr ; - } - - if(!(*cmiLeft.data_item == *cmiRight.data_item)) return false ; - - return true; -} -int main() -{ - test_RsItem(); REPORT("Serialise/Deserialise RsGRouterGenericDataItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsGRouterACKItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsGRouterPublishKeyItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsGRouterRoutingInfoItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsGRouterMatrixFriendListItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsGRouterMatrixCluesItem"); - - std::cerr << std::endl; - - FINALREPORT("RsGRouter Tests"); - - return TESTRESULT(); -} - - - - - diff --git a/libretroshare/src/tests/serialiser/rsgrouteritem_test.h b/libretroshare/src/tests/serialiser/rsgrouteritem_test.h deleted file mode 100644 index 392792fa3..000000000 --- a/libretroshare/src/tests/serialiser/rsgrouteritem_test.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef MSGITEM_TEST_H_ -#define MSGITEM_TEST_H_ - -/* - * libretroshare/src/tests/serialiser: msgitem_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2010 by Christopher Evi-Parker. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#include -#include "serialiser/rsmsgitems.h" - - -RsSerialType* init_item(RsChatMsgItem& ); -RsSerialType* init_item(RsChatStatusItem& ); -RsSerialType* init_item(RsChatAvatarItem& ); -RsSerialType* init_item(RsMsgItem& ); -RsSerialType* init_item(RsMsgTagType& ); -RsSerialType* init_item(RsMsgTags& ); -RsSerialType* init_item(RsMsgSrcId& ); - -bool operator ==(const RsChatMsgItem& ,const RsChatMsgItem& ); -bool operator ==(const RsChatStatusItem& , const RsChatStatusItem& ); -bool operator ==(const RsChatAvatarItem&, const RsChatAvatarItem& ); -bool operator ==(const RsMsgTagType&, const RsMsgTagType& ); -bool operator ==(const RsMsgTags&, const RsMsgTags& ); -bool operator ==(const RsMsgItem&, const RsMsgItem& ); -bool operator ==(const RsMsgSrcId&, const RsMsgSrcId& ); - -#endif /* MSGITEM_TEST_H_ */ diff --git a/libretroshare/src/tests/serialiser/rsgxsupdateitem_test.cc b/libretroshare/src/tests/serialiser/rsgxsupdateitem_test.cc deleted file mode 100644 index aa858daf7..000000000 --- a/libretroshare/src/tests/serialiser/rsgxsupdateitem_test.cc +++ /dev/null @@ -1,110 +0,0 @@ -/* - * rsgxsupdateitem_test.cc - * - * Created on: 9 Dec 2013 - * Author: crispy - */ - -#include "support.h" -#include "rsgxsupdateitem_test.h" - -INITTEST(); - -RsSerialType* init_item(RsGxsGrpUpdateItem& i) -{ - i.clear(); - i.grpUpdateTS = rand()%2424; - randString(SHORT_STR, i.peerId); - return new RsGxsUpdateSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); -} - -RsSerialType* init_item(RsGxsMsgUpdateItem& i) -{ - i.clear(); - randString(SHORT_STR, i.peerId); - int numUpdates = rand()%123; - - std::string peer; - for(int j=0; j < numUpdates; j++) - { - randString(SHORT_STR, peer); - i.msgUpdateTS.insert(std::make_pair(peer, rand()%45)); - } - - return new RsGxsUpdateSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); -} - -RsSerialType* init_item(RsGxsServerGrpUpdateItem& i) -{ - i.clear(); - i.grpUpdateTS = rand()%2424; - - return new RsGxsUpdateSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); -} - -RsSerialType* init_item(RsGxsServerMsgUpdateItem& i) -{ - i.clear(); - randString(SHORT_STR, i.grpId); - i.msgUpdateTS = rand()%4252; - return new RsGxsUpdateSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); -} - -bool operator ==(const RsGxsGrpUpdateItem& l, const RsGxsGrpUpdateItem& r) -{ - bool ok = l.grpUpdateTS == r.grpUpdateTS; - ok &= l.peerId == r.peerId; - - return ok; -} - -bool operator ==(const RsGxsMsgUpdateItem& l, const RsGxsMsgUpdateItem& r) -{ - bool ok = l.peerId == r.peerId; - - const std::map& lUp = l.msgUpdateTS, rUp = r.msgUpdateTS; - - ok &= lUp.size() == rUp.size(); - - std::map::const_iterator lit = lUp.begin(), rit; - - for(; lit != lUp.end(); lit++) - { - std::string key = lit->first; - if((rit = rUp.find(key)) != rUp.end()) - ok &= lit->second == rit->second; - else - return false; - } - - return ok; -} - -bool operator ==(const RsGxsServerGrpUpdateItem& l, - const RsGxsServerGrpUpdateItem& r) -{ - return l.grpUpdateTS == r.grpUpdateTS; -} - -bool operator ==(const RsGxsServerMsgUpdateItem& l, - const RsGxsServerMsgUpdateItem& r) -{ - bool ok = l.grpId == r.grpId; - ok &= l.msgUpdateTS == r.msgUpdateTS; - return ok; -} - - -int main() -{ - std::cerr << "RsGxsUpdateItem Tests" << std::endl; - - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); REPORT("Serialise/Deserialise RsGxsGrpUpdateItem"); - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); REPORT("Serialise/Deserialise RsGxsMsgUpdateItem"); - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); REPORT("Serialise/Deserialise RsGxsServerGrpUpdateItem"); - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); REPORT("Serialise/Deserialise RsGxsServerMsgUpdateItem"); - - FINALREPORT("RsGxsUpdateItem Tests"); - - return TESTRESULT(); -} diff --git a/libretroshare/src/tests/serialiser/rsgxsupdateitem_test.h b/libretroshare/src/tests/serialiser/rsgxsupdateitem_test.h deleted file mode 100644 index 57a686241..000000000 --- a/libretroshare/src/tests/serialiser/rsgxsupdateitem_test.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * rsgxsupdateitem_test.h - * - * Created on: 9 Dec 2013 - * Author: crispy - */ - -#ifndef RSGXSUPDATEITEM_TEST_H_ -#define RSGXSUPDATEITEM_TEST_H_ - -#include "serialiser/rsgxsupdateitems.h" -#include "support.h" - - -RsSerialType* init_item(RsGxsGrpUpdateItem& i); -RsSerialType* init_item(RsGxsMsgUpdateItem& i); -RsSerialType* init_item(RsGxsServerGrpUpdateItem& i); -RsSerialType* init_item(RsGxsServerMsgUpdateItem& i); - -bool operator==(const RsGxsGrpUpdateItem& l, const RsGxsGrpUpdateItem& r); -bool operator==(const RsGxsMsgUpdateItem& l, const RsGxsMsgUpdateItem& r); -bool operator==(const RsGxsServerGrpUpdateItem& l, const RsGxsServerGrpUpdateItem& r); -bool operator==(const RsGxsServerMsgUpdateItem& l, const RsGxsServerMsgUpdateItem& r); - -#endif /* RSGXSUPDATEITEM_TEST_H_ */ diff --git a/libretroshare/src/tests/serialiser/rsmsgitem_test.cc b/libretroshare/src/tests/serialiser/rsmsgitem_test.cc deleted file mode 100644 index c964d97ba..000000000 --- a/libretroshare/src/tests/serialiser/rsmsgitem_test.cc +++ /dev/null @@ -1,366 +0,0 @@ -/* - * libretroshare/src/tests/serialiser: msgitem_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2010 by Christopher Evi-Parker. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include - -#include "util/rsrandom.h" -#include "serialiser/rsmsgitems.h" -#include "serialiser/rstlvutil.h" -#include "util/utest.h" -#include "support.h" -#include "rsmsgitem_test.h" - -INITTEST(); - -RsSerialType* init_item(RsChatMsgItem& cmi) -{ - cmi.chatFlags = rand()%34; - cmi.sendTime = rand()%422224; - randString(LARGE_STR, cmi.message); - - return new RsChatSerialiser(); -} -RsSerialType* init_item(RsChatLobbyListRequestItem& cmi) -{ - return new RsChatSerialiser(); -} -RsSerialType* init_item(RsChatLobbyListItem& cmi) -{ - int n = rand()%20 ; - - cmi.lobby_ids.resize(n) ; - cmi.lobby_names.resize(n) ; - cmi.lobby_topics.resize(n) ; - cmi.lobby_counts.resize(n) ; - - for(int i=0;i(&cmi)) ; - - cmi.msg_id = RSRandom::random_u64() ; - cmi.lobby_id = RSRandom::random_u64() ; - cmi.nick = "My nickname" ; - cmi.subpacket_id = rand()%256 ; - cmi.parent_msg_id = RSRandom::random_u64() ; - - return serial ; -} -RsSerialType *init_item(RsChatLobbyEventItem& cmi) -{ - cmi.event_type = rand()%256 ; - randString(20, cmi.string1); - - return new RsChatSerialiser(); -} - -RsSerialType* init_item(RsChatLobbyInviteItem& cmi) -{ - cmi.lobby_id = RSRandom::random_u64() ; - cmi.lobby_name = "Name of the lobby" ; - cmi.lobby_topic = "Topic of the lobby" ; - - return new RsChatSerialiser(); -} - -RsSerialType* init_item(RsPrivateChatMsgConfigItem& pcmi) -{ - randString(SHORT_STR, pcmi.configPeerId); - pcmi.chatFlags = rand()%34; - pcmi.configFlags = rand()%21; - pcmi.sendTime = rand()%422224; - randString(LARGE_STR, pcmi.message); - pcmi.recvTime = rand()%344443; - - return new RsChatSerialiser(); -} - -RsSerialType* init_item(RsChatStatusItem& csi) -{ - - randString(SHORT_STR, csi.status_string); - csi.flags = rand()%232; - - return new RsChatSerialiser(); - -} - -RsSerialType* init_item(RsChatAvatarItem& cai) -{ - std::string image_data; - randString(LARGE_STR, image_data); - cai.image_data = new unsigned char[image_data.size()]; - - memcpy(cai.image_data, image_data.c_str(), image_data.size()); - cai.image_size = image_data.size(); - - return new RsChatSerialiser(); -} - -RsSerialType* init_item(RsMsgItem& mi) -{ - init_item(mi.attachment); - init_item(mi.msgbcc); - init_item(mi.msgcc); - init_item(mi.msgto); - - randString(LARGE_STR, mi.message); - randString(SHORT_STR, mi.subject); - - mi.msgId = rand()%324232; - mi.recvTime = rand()%44252; - mi.sendTime = mi.recvTime; - mi.msgFlags = mi.recvTime; - - return new RsMsgSerialiser(true); -} - -RsSerialType* init_item(RsMsgTagType& mtt) -{ - mtt.rgb_color = rand()%5353; - mtt.tagId = rand()%24242; - randString(SHORT_STR, mtt.text); - - return new RsMsgSerialiser(); -} - - -RsSerialType* init_item(RsMsgTags& mt) -{ - mt.msgId = rand()%3334; - - int i; - for (i = 0; i < 10; i++) { - mt.tagIds.push_back(rand()%21341); - } - - return new RsMsgSerialiser(); -} - -RsSerialType* init_item(RsMsgSrcId& ms) -{ - ms.msgId = rand()%434; - randString(SHORT_STR, ms.srcId); - - return new RsMsgSerialiser(); -} - -RsSerialType* init_item(RsMsgParentId& ms) -{ - ms.msgId = rand()%354; - ms.msgParentId = rand()%476; - - return new RsMsgSerialiser(); -} - -bool operator ==(const RsChatLobbyListItem& cmiLeft,const RsChatLobbyListItem& cmiRight) -{ - if(cmiLeft.lobby_ids.size() != cmiRight.lobby_ids.size()) return false; - if(cmiLeft.lobby_names.size() != cmiRight.lobby_names.size()) return false; - if(cmiLeft.lobby_topics.size() != cmiRight.lobby_topics.size()) return false; - if(cmiLeft.lobby_counts.size() != cmiRight.lobby_counts.size()) return false; - - for(uint32_t i=0;i(); REPORT("Serialise/Deserialise RsChatMsgItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsChatLobbyMsgItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsChatLobbyInviteItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsChatLobbyEventItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsChatLobbyListRequestItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsChatLobbyListItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsChatStatusItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsChatAvatarItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsMsgItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsMsgTagType"); - test_RsItem(); REPORT("Serialise/Deserialise RsMsgTags"); - test_RsItem(); REPORT("Serialise/Deserialise RsMsgSrcId"); - test_RsItem(); REPORT("Serialise/Deserialise RsMsgParentId"); - - std::cerr << std::endl; - - FINALREPORT("RsMsgItem Tests"); - - return TESTRESULT(); -} - - - - - diff --git a/libretroshare/src/tests/serialiser/rsmsgitem_test.h b/libretroshare/src/tests/serialiser/rsmsgitem_test.h deleted file mode 100644 index 392792fa3..000000000 --- a/libretroshare/src/tests/serialiser/rsmsgitem_test.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef MSGITEM_TEST_H_ -#define MSGITEM_TEST_H_ - -/* - * libretroshare/src/tests/serialiser: msgitem_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2010 by Christopher Evi-Parker. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#include -#include "serialiser/rsmsgitems.h" - - -RsSerialType* init_item(RsChatMsgItem& ); -RsSerialType* init_item(RsChatStatusItem& ); -RsSerialType* init_item(RsChatAvatarItem& ); -RsSerialType* init_item(RsMsgItem& ); -RsSerialType* init_item(RsMsgTagType& ); -RsSerialType* init_item(RsMsgTags& ); -RsSerialType* init_item(RsMsgSrcId& ); - -bool operator ==(const RsChatMsgItem& ,const RsChatMsgItem& ); -bool operator ==(const RsChatStatusItem& , const RsChatStatusItem& ); -bool operator ==(const RsChatAvatarItem&, const RsChatAvatarItem& ); -bool operator ==(const RsMsgTagType&, const RsMsgTagType& ); -bool operator ==(const RsMsgTags&, const RsMsgTags& ); -bool operator ==(const RsMsgItem&, const RsMsgItem& ); -bool operator ==(const RsMsgSrcId&, const RsMsgSrcId& ); - -#endif /* MSGITEM_TEST_H_ */ diff --git a/libretroshare/src/tests/serialiser/rsnxsitems_test.cc b/libretroshare/src/tests/serialiser/rsnxsitems_test.cc deleted file mode 100644 index b2dab65e9..000000000 --- a/libretroshare/src/tests/serialiser/rsnxsitems_test.cc +++ /dev/null @@ -1,187 +0,0 @@ - -#include "support.h" - -#include "rsnxsitems_test.h" - -INITTEST(); - -#define NUM_BIN_OBJECTS 5 -#define NUM_SYNC_MSGS 8 -#define NUM_SYNC_GRPS 5 - -RsSerialType* init_item(RsNxsGrp& nxg) -{ - nxg.clear(); - - randString(SHORT_STR, nxg.grpId); - nxg.transactionNumber = rand()%23; - init_item(nxg.grp); - init_item(nxg.meta); - - return new RsNxsSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); -} - - -RsSerialType* init_item(RsNxsMsg& nxm) -{ - nxm.clear(); - - randString(SHORT_STR, nxm.msgId); - randString(SHORT_STR, nxm.grpId); - init_item(nxm.msg); - init_item(nxm.meta); - nxm.transactionNumber = rand()%23; - - return new RsNxsSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); -} - -RsSerialType* init_item(RsNxsSyncGrp& rsg) -{ - rsg.clear(); - rsg.flag = RsNxsSyncGrp::FLAG_USE_SYNC_HASH; - rsg.createdSince = rand()%2423; - randString(3124,rsg.syncHash); - - return new RsNxsSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); -} - -RsSerialType* init_item(RsNxsSyncMsg& rsgm) -{ - rsgm.clear(); - - rsgm.flag = RsNxsSyncMsg::FLAG_USE_SYNC_HASH; - rsgm.createdSince = rand()%24232; - rsgm.transactionNumber = rand()%23; - randString(SHORT_STR, rsgm.grpId); - randString(SHORT_STR, rsgm.syncHash); - - return new RsNxsSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); -} - -RsSerialType* init_item(RsNxsSyncGrpItem& rsgl) -{ - rsgl.clear(); - - rsgl.flag = RsNxsSyncGrpItem::FLAG_RESPONSE; - rsgl.transactionNumber = rand()%23; - rsgl.publishTs = rand()%23; - randString(SHORT_STR, rsgl.grpId); - - return new RsNxsSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); -} - -RsSerialType* init_item(RsNxsSyncMsgItem& rsgml) -{ - rsgml.clear(); - - rsgml.flag = RsNxsSyncGrpItem::FLAG_RESPONSE; - rsgml.transactionNumber = rand()%23; - randString(SHORT_STR, rsgml.grpId); - randString(SHORT_STR, rsgml.msgId); - - return new RsNxsSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); -} - -RsSerialType* init_item(RsNxsTransac& rstx){ - - rstx.clear(); - - rstx.timestamp = rand()%14141; - rstx.transactFlag = rand()%2424; - rstx.nItems = rand()%33132; - rstx.transactionNumber = rand()%242112; - - return new RsNxsSerialiser(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); -} - -bool operator==(const RsNxsGrp& l, const RsNxsGrp& r){ - - if(l.grpId != r.grpId) return false; - if(!(l.grp == r.grp) ) return false; - if(!(l.meta == r.meta) ) return false; - if(l.transactionNumber != r.transactionNumber) return false; - - return true; -} - -bool operator==(const RsNxsMsg& l, const RsNxsMsg& r){ - - if(l.msgId != r.msgId) return false; - if(l.grpId != r.grpId) return false; - if(! (l.msg == r.msg) ) return false; - if(! (l.meta == r.meta) ) return false; - if(l.transactionNumber != r.transactionNumber) return false; - - return true; -} - -bool operator==(const RsNxsSyncGrp& l, const RsNxsSyncGrp& r) -{ - - if(l.syncHash != r.syncHash) return false; - if(l.flag != r.flag) return false; - if(l.createdSince != r.createdSince) return false; - if(l.transactionNumber != r.transactionNumber) return false; - - return true; -} - -bool operator==(const RsNxsSyncMsg& l, const RsNxsSyncMsg& r) -{ - - if(l.flag != r.flag) return false; - if(l.createdSince != r.createdSince) return false; - if(l.syncHash != r.syncHash) return false; - if(l.grpId != r.grpId) return false; - if(l.transactionNumber != r.transactionNumber) return false; - - return true; -} - -bool operator==(const RsNxsSyncGrpItem& l, const RsNxsSyncGrpItem& r) -{ - if(l.flag != r.flag) return false; - if(l.publishTs != r.publishTs) return false; - if(l.grpId != r.grpId) return false; - if(l.transactionNumber != r.transactionNumber) return false; - - return true; -} - -bool operator==(const RsNxsSyncMsgItem& l, const RsNxsSyncMsgItem& r) -{ - if(l.flag != r.flag) return false; - if(l.grpId != r.grpId) return false; - if(l.msgId != r.msgId) return false; - if(l.transactionNumber != r.transactionNumber) return false; - - return true; -} - -bool operator==(const RsNxsTransac& l, const RsNxsTransac& r){ - - if(l.transactFlag != r.transactFlag) return false; - if(l.transactionNumber != r.transactionNumber) return false; - if(l.timestamp != r.timestamp) return false; - if(l.nItems != r.nItems) return false; - - - return true; -} - -int main() -{ - std::cerr << "RsNxsItem Tests" << std::endl; - - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); REPORT("Serialise/Deserialise RsGrpResp"); - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); REPORT("Serialise/Deserialise RsGrpMsgResp"); - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); REPORT("Serialise/Deserialise RsNxsSyncGrp"); - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); REPORT("Serialise/Deserialise RsNxsSyncMsg"); - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); REPORT("Serialise/Deserialise RsNxsSyncGrpItem"); - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); REPORT("Serialise/Deserialise RsNxsSyncMsgItem"); - test_RsItem(RS_SERVICE_TYPE_PLUGIN_SIMPLE_FORUM); REPORT("Serialise/Deserialise RsNxsTransac"); - - FINALREPORT("RsNxsItem Tests"); - - return TESTRESULT(); -} diff --git a/libretroshare/src/tests/serialiser/rsnxsitems_test.h b/libretroshare/src/tests/serialiser/rsnxsitems_test.h deleted file mode 100644 index 31dae24b7..000000000 --- a/libretroshare/src/tests/serialiser/rsnxsitems_test.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef RSNXSITEMS_TEST_H -#define RSNXSITEMS_TEST_H - -#include "serialiser/rsnxsitems.h" - - -RsSerialType* init_item(RsNxsGrp&); -RsSerialType* init_item(RsNxsMsg&); -RsSerialType* init_item(RsNxsSyncGrp&); -RsSerialType* init_item(RsNxsSyncMsg&); -RsSerialType* init_item(RsNxsSyncGrpItem&); -RsSerialType* init_item(RsNxsSyncMsgItem&); -RsSerialType* init_item(RsNxsTransac& ); - -bool operator==(const RsNxsGrp&, const RsNxsGrp&); -bool operator==(const RsNxsMsg&, const RsNxsMsg&); -bool operator==(const RsNxsSyncGrp&, const RsNxsSyncGrp&); -bool operator==(const RsNxsSyncMsg&, const RsNxsSyncMsg&); -bool operator==(const RsNxsSyncGrpItem&, const RsNxsSyncGrpItem&); -bool operator==(const RsNxsSyncMsgItem&, const RsNxsSyncMsgItem&); -bool operator==(const RsNxsTransac&, const RsNxsTransac& ); - - -#endif // RSNXSITEMS_TEST_H diff --git a/libretroshare/src/tests/serialiser/rsphotoitem_test.cc b/libretroshare/src/tests/serialiser/rsphotoitem_test.cc deleted file mode 100644 index fafd1650d..000000000 --- a/libretroshare/src/tests/serialiser/rsphotoitem_test.cc +++ /dev/null @@ -1,139 +0,0 @@ -/* - * libretroshare/src/test rsphotoitem_test.cc - * - * Test for photo item serialisation - * - * Copyright 2012-2012 by Christopher Evi-Parker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#include "rsphotoitem_test.h" - - -RsSerialType* init_item(RsGxsPhotoAlbumItem &album) -{ - RsPhotoAlbum& a = album.album; - - randString(SHORT_STR, a.mCaption); - randString(SHORT_STR, a.mCategory); - randString(SHORT_STR, a.mDescription); - randString(SHORT_STR, a.mHashTags); - randString(SHORT_STR, a.mOther); - randString(SHORT_STR, a.mPhotoPath); - randString(SHORT_STR, a.mPhotographer); - randString(SHORT_STR, a.mWhen); - randString(SHORT_STR, a.mWhere); - randString(SHORT_STR, a.mThumbnail.type); - std::string rStr; - randString(SHORT_STR, rStr); - - a.mThumbnail.data = new uint8_t[SHORT_STR]; - memcpy(a.mThumbnail.data, rStr.data(), SHORT_STR); - a.mThumbnail.size = SHORT_STR; - - return new RsGxsPhotoSerialiser(); -} - -RsSerialType* init_item(RsGxsPhotoPhotoItem &photo) -{ - - RsPhotoPhoto& p = photo.photo; - - randString(SHORT_STR, p.mCaption); - randString(SHORT_STR, p.mCategory); - randString(SHORT_STR, p.mDescription); - randString(SHORT_STR, p.mHashTags); - randString(SHORT_STR, p.mOther); - randString(SHORT_STR, p.mPhotographer); - randString(SHORT_STR, p.mWhen); - randString(SHORT_STR, p.mWhere); - randString(SHORT_STR, p.mThumbnail.type); - std::string rStr; - randString(SHORT_STR, rStr); - - p.mThumbnail.data = new uint8_t[SHORT_STR]; - memcpy(p.mThumbnail.data, rStr.data(), SHORT_STR); - p.mThumbnail.size = SHORT_STR; - - return new RsGxsPhotoSerialiser(); -} - - -bool operator == (RsGxsPhotoAlbumItem& l, RsGxsPhotoAlbumItem& r) -{ - RsPhotoAlbum& la = l.album; - RsPhotoAlbum& ra = r.album; - - if(la.mCaption != ra.mCaption) return false; - if(la.mCategory != ra.mCategory) return false; - if(la.mDescription != ra.mDescription) return false; - if(la.mHashTags != ra.mHashTags) return false; - if(la.mOther != ra.mOther) return false; - if(la.mPhotographer!= ra.mPhotographer) return false; - if(la.mPhotoPath != ra.mPhotoPath) return false; - if(la.mWhere != ra.mWhere) return false; - if(la.mWhen != ra.mWhen) return false; - if(!(la.mThumbnail == ra.mThumbnail)) return false; - - return true; -} - - - -bool operator == (RsGxsPhotoPhotoItem& l, RsGxsPhotoPhotoItem& r) -{ - RsPhotoPhoto& la = l.photo; - RsPhotoPhoto& ra = r.photo; - - if(la.mCaption != ra.mCaption) return false; - if(la.mCategory != ra.mCategory) return false; - if(la.mDescription != ra.mDescription) return false; - if(la.mHashTags != ra.mHashTags) return false; - if(la.mOther != ra.mOther) return false; - if(la.mPhotographer!= ra.mPhotographer) return false; - if(la.mWhere != ra.mWhere) return false; - if(la.mWhen != ra.mWhen) return false; - if(!(la.mThumbnail == ra.mThumbnail)) return false; - - return true; -} - -bool operator == (RsPhotoThumbnail& l, RsPhotoThumbnail& r) -{ - if(l.size != r.size) return false; - if(l.type != r.type) return false; - if(memcmp(l.data, r.data,l.size) != 0) return false; - - return true; -} - -INITTEST() - -int main() -{ - std::cerr << "RsPhotoItem Tests" << std::endl; - - test_RsItem(); REPORT("Serialise/Deserialise RsGxsPhotoAlbumItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsGxsPhotoPhotoItem"); - - FINALREPORT("RsPhotoItem Tests"); - - return TESTRESULT(); -} diff --git a/libretroshare/src/tests/serialiser/rsphotoitem_test.h b/libretroshare/src/tests/serialiser/rsphotoitem_test.h deleted file mode 100644 index cd726198e..000000000 --- a/libretroshare/src/tests/serialiser/rsphotoitem_test.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * libretroshare/src/test rsphotoitem_test.h - * - * Test for photo item serialisation - * - * Copyright 2012-2012 by Christopher Evi-Parker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#ifndef RSPHOTOITEM_TEST_H_ -#define RSPHOTOITEM_TEST_H_ - -#include "serialiser/rsphotov2items.h" -#include "support.h" - - - -RsSerialType* init_item(RsGxsPhotoAlbumItem& album); -RsSerialType* init_item(RsGxsPhotoPhotoItem& photo); - -bool operator == (RsGxsPhotoAlbumItem& l, RsGxsPhotoAlbumItem& r); -bool operator == (RsGxsPhotoPhotoItem& l, RsGxsPhotoPhotoItem& r); -bool operator == (RsPhotoThumbnail& l, RsPhotoThumbnail& r); - -#endif /* RSPHOTOITEM_TEST_H_ */ diff --git a/libretroshare/src/tests/serialiser/rsserial_test.cc b/libretroshare/src/tests/serialiser/rsserial_test.cc deleted file mode 100644 index e9193fee0..000000000 --- a/libretroshare/src/tests/serialiser/rsserial_test.cc +++ /dev/null @@ -1,136 +0,0 @@ - -/* - * libretroshare/src/serialiser: rsserial_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****************************************************************** - * tlvfileitem test. - * - * - */ - -#include -#include -#include "serialiser/rsserial.h" -#include "serialiser/rsbaseitems.h" -#include "serialiser/rstlvutil.h" -#include "util/utest.h" - -INITTEST(); - -static int test_RsFileItem(); -static int test_RsFileData(); - -int main() -{ - std::cerr << "RsFile[Item/Data/...] Tests" << std::endl; - - - test_RsFileItem(); - //test_RsFileData(); - - FINALREPORT("RsTlvFile[Item/Data/...] Tests"); - - return TESTRESULT(); -} - -int test_RsFileItem() -{ - /* make a serialisable FileItem */ - - RsSerialiser srl; - RsFileRequest rsfi; - - /* initialise */ - rsfi.file.filesize = 101010; - rsfi.file.hash = "ABCDEFEGHE"; - rsfi.file.name = "TestFile.txt"; - rsfi.file.pop = 12; - rsfi.file.age = 456; - - /* attempt to serialise it before we add it to the serialiser */ - - CHECK(0 == srl.size(&rsfi)); - -#define MAX_BUFSIZE 16000 - - char buffer[MAX_BUFSIZE]; - uint32_t sersize = MAX_BUFSIZE; - - CHECK(false == srl.serialise(&rsfi, (void *) buffer, &sersize)); - - - /* now add to serialiser */ - - RsFileItemSerialiser *rsfis = new RsFileItemSerialiser(); - srl.addSerialType(rsfis); - - uint32_t size = srl.size(&rsfi); - bool done = srl.serialise(&rsfi, (void *) buffer, &sersize); - - std::cerr << "test_RsFileItem() size: " << size << std::endl; - std::cerr << "test_RsFileItem() done: " << done << std::endl; - std::cerr << "test_RsFileItem() sersize: " << sersize << std::endl; - - std::cerr << "test_RsFileItem() serialised:" << std::endl; - displayRawPacket(std::cerr, (void *) buffer, sersize); - - CHECK(done == true); - - uint32_t sersize2 = sersize; - RsItem *output = srl.deserialise((void *) buffer, &sersize2); - - CHECK(output != NULL); - CHECK(sersize2 == sersize); - - RsFileRequest *outfi = dynamic_cast(output); - - CHECK(outfi != NULL); - - if (outfi) - { - /* check the data is the same */ - CHECK(rsfi.file.filesize == outfi->file.filesize); - CHECK(rsfi.file.hash == outfi->file.hash); - CHECK(rsfi.file.name == outfi->file.name); - CHECK(rsfi.file.path == outfi->file.path); - CHECK(rsfi.file.pop == outfi->file.pop); - CHECK(rsfi.file.age == outfi->file.age); - } - - sersize2 = MAX_BUFSIZE; - bool done2 = srl.serialise(outfi, (void *) &(buffer[16*8]), &sersize2); - - CHECK(sersize2 == sersize); - - displayRawPacket(std::cerr, (void *) buffer, 16 * 8 + sersize2); - - - REPORT("Serialise/Deserialise RsFileRequest"); - - return 1; -} - - - diff --git a/libretroshare/src/tests/serialiser/rsstatusitem_test.cc b/libretroshare/src/tests/serialiser/rsstatusitem_test.cc deleted file mode 100644 index db6d5c181..000000000 --- a/libretroshare/src/tests/serialiser/rsstatusitem_test.cc +++ /dev/null @@ -1,60 +0,0 @@ -/* - * libretroshare/src/tests/serialiser: rsstatusitem_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2010 by Christopher Evi-Parker. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#include "support.h" -#include "rsstatusitem_test.h" - -INITTEST(); - -RsSerialType* init_item(RsStatusItem& rsi) -{ - - rsi.sendTime = rand()%5353; - rsi.status = rand()%2032; - return new RsStatusSerialiser(); -} - -bool operator ==(RsStatusItem& rsi1, RsStatusItem& rsi2) -{ - // note: recv time is not serialised - - if(rsi1.sendTime != rsi2.sendTime) return false; - if(rsi1.status != rsi2.status) return false; - - return true; -} - - -int main() -{ - - std::cerr << "RsStatusItem Tests" << std::endl; - - test_RsItem(); REPORT("Serialise/Deserialise RsStatusItem"); - FINALREPORT("RsStatusItem Tests"); - - return TESTRESULT(); -} diff --git a/libretroshare/src/tests/serialiser/rsstatusitem_test.h b/libretroshare/src/tests/serialiser/rsstatusitem_test.h deleted file mode 100644 index cf25c5429..000000000 --- a/libretroshare/src/tests/serialiser/rsstatusitem_test.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef RSSTATUS_TEST_H_ -#define RSSTATUS_TEST_H_ - -/* - * libretroshare/src/tests/serialiser: rsstatusitem_test.h - * - * RetroShare Serialiser. - * - * Copyright 2010 by Christopher Evi-Parker. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "serialiser/rsstatusitems.h" - -RsSerialType* init_item(RsStatusItem& ); - -bool operator ==(RsStatusItem& , RsStatusItem& ); - -#endif /* RSSTATUS_TEST_H_ */ diff --git a/libretroshare/src/tests/serialiser/rstlvutil.cc b/libretroshare/src/tests/serialiser/rstlvutil.cc deleted file mode 100644 index 51d1fe1c5..000000000 --- a/libretroshare/src/tests/serialiser/rstlvutil.cc +++ /dev/null @@ -1,187 +0,0 @@ - -/* - * libretroshare/src/serialiser: rstlvutil.cc - * - * RetroShare Serialiser. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -/* some utility functions mainly for debugging - * - * - * - */ - -#include "serialiser/rstlvutil.h" - -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvitem.h" -#include "util/rsstring.h" -#include "util/utest.h" - -#include -#include - -#if 0 -/* print out a packet */ -#include -#include - - -#endif - -void displayRawPacket(std::ostream &out, void *data, uint32_t size) -{ - uint32_t i; - std::string sout; - rs_sprintf(sout, "DisplayRawPacket: Size: %ld", size); - - for(i = 0; i < size; i++) - { - if (i % 16 == 0) - { - sout += "\n"; - } - rs_sprintf_append(sout, "%02x:", (int) (((unsigned char *) data)[i])); - } - - out << sout << std::endl; -} - - -#define WHOLE_64K_SIZE 65536 - -int test_SerialiseTlvItem(std::ostream &str, RsTlvItem *in, RsTlvItem *out) -{ - uint16_t initsize = in->TlvSize(); - uint32_t serialOffset = 0; - uint32_t deserialOffset = 0; - - str << "test_SerialiseTlvItem() Testing ... Print/Serialise/Deserialise"; - str << std::endl; - - - /* some space to serialise into */ - unsigned char serbuffer[WHOLE_64K_SIZE]; - - CHECK(in->SetTlv(serbuffer, WHOLE_64K_SIZE, &serialOffset)); - - CHECK(serialOffset == initsize); /* check that the offset matches the size */ - CHECK(in->TlvSize() == initsize); /* check size hasn't changed */ - - REPORT("Serialise RsTlvItem"); - - /* now we try to read it back in! */ - CHECK(out->GetTlv(serbuffer, serialOffset, &deserialOffset)); - - /* again check sizes */ - CHECK(serialOffset == deserialOffset); - CHECK(deserialOffset == initsize); - CHECK(out->TlvSize() == initsize); - - str << "Class In/Serialised/Out!" << std::endl; - in->print(str, 0); - displayRawPacket(str, serbuffer, serialOffset); - out->print(str, 0); - - /* Can't check the actual data -> should add function */ - REPORT("DeSerialise RsTlvFileItem"); - - /* print it out */ - - - return 1; -} - -/* This function checks the TLV header, and steps on to the next one - */ - -bool test_StepThroughTlvStack(std::ostream &str, void *data, int size) -{ - uint32_t offset = 0; - uint32_t index = 0; - while (offset + 4 <= size) - { - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[offset]) ); - uint16_t tlvsize = GetTlvSize( &(((uint8_t *) data)[offset]) ); - str << "Tlv Entry[" << index << "] => Offset: " << offset; - str << " Type: " << tlvtype; - str << " Size: " << tlvsize; - str << std::endl; - - offset += tlvsize; - } - CHECK(offset == size); /* we match up exactly */ - - REPORT("Step Through RsTlvStack"); - return 1; -} - - -int test_CreateTlvStack(std::ostream &str, - std::vector items, void *data, uint32_t *totalsize) -{ - /* (1) select a random item - * (2) check size -> if okay serialise onto the end - * (3) loop!. - */ - uint32_t offset = 0; - uint32_t count = 0; - - while(1) - { - int idx = (int) (items.size() * (rand() / (RAND_MAX + 1.0))); - uint32_t tlvsize = items[idx] -> TlvSize(); - - if (offset + tlvsize > *totalsize) - { - *totalsize = offset; - return count; - } - - str << "Stack[" << count << "]"; - str << " Offset: " << offset; - str << " TlvSize: " << tlvsize; - str << std::endl; - - /* serialise it */ - items[idx] -> SetTlv(data, *totalsize, &offset); - items[idx] -> print(str, 10); - count++; - } - *totalsize = offset; - return 0; -} - -int test_TlvSet(std::vector items, int maxsize) -{ - int totalsize = maxsize; - void *data = malloc(totalsize); - uint32_t size = totalsize; - - test_CreateTlvStack(std::cerr, items, data, &size); - test_StepThroughTlvStack(std::cerr, data, size); - - return 1; -} - - diff --git a/libretroshare/src/tests/serialiser/rstlvutil.h b/libretroshare/src/tests/serialiser/rstlvutil.h deleted file mode 100644 index 910c494d3..000000000 --- a/libretroshare/src/tests/serialiser/rstlvutil.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef RS_TLV_UTIL_H -#define RS_TLV_UTIL_H - -/* - * libretroshare/src/serialiser: rstlvutil.h - * - * RetroShare Serialiser. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/* some utility functions mainly for debugging - */ - -#include -#include -#include - -class RsTlvItem; - -/* print out a packet */ -void displayRawPacket(std::ostream &out, void *data, uint32_t size); -int test_SerialiseTlvItem(std::ostream &str, RsTlvItem *in, RsTlvItem *out); - - -bool test_StepThroughTlvStack(std::ostream &str, void *data, int size); -int test_CreateTlvStack(std::ostream &str, - std::vector items, void *data, int totalsize); -int test_TlvSet(std::vector items, int maxsize); - -#endif diff --git a/libretroshare/src/tests/serialiser/rstlvwidetest.cc b/libretroshare/src/tests/serialiser/rstlvwidetest.cc deleted file mode 100644 index 91f663387..000000000 --- a/libretroshare/src/tests/serialiser/rstlvwidetest.cc +++ /dev/null @@ -1,88 +0,0 @@ -/* - * libretroshare/src/serialiser: rstlvkvwidetest.cc - * - * RetroShare Serialiser. - * - * Copyright 2007-2008 by Chris Parker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#include -#include -#include -#include "serialiser/rstlvkvwide.h" -#include "serialiser/rstlvutil.h" -#include "util/utest.h" - - -INITTEST(); - - /* define utility functions to test out with */ - - //static int testRstlvWide(); -static int testRsTlvWideSet(); - -int main() -{ - std::cerr << "RsTlvWideTest[Item/Data/...] Tests" << std::endl; - - testRsTlvWideSet(); - - FINALREPORT("RsTlvWideTest[Item/Data/...] Tests"); - - return TESTRESULT(); -} - -int testRsTlvWideSet() -{ - RsTlvKeyValueWideSet i1, i2; // one to set and other to get - RsTlvKeyValueWide i_pair; // input pair - RsTlvFileItem hello; - - std::string randString("it should work now."); - int j, k; - - std::cerr << "entering loop now" << std::endl; - /* store a 15 random pairs */ - - for(int i = 0; i < 15 ; i++) - { - j = rand() % 4; - k = rand() % 4; - std::cerr << "j: " << j << " k: " << k << std::endl; - i_pair.wKey.assign(randString.begin(), randString.end()); - std::cerr << "loop count:" << i << std::endl; - i_pair.wValue.assign(randString.begin(), randString.end()); - std::cerr << "loop count:" << i << std::endl; - i1.wPairs.push_back(i_pair); - - i_pair.TlvClear(); - } - - std::cerr << "out of loop now" << std::endl; - - CHECK(test_SerialiseTlvItem(std::cerr, &i1, &i2)); - - /*check that the data is the same*/ - - REPORT("Serialize/Deserialize RsTlvKeyValueWideSet"); - - return 1; -} diff --git a/libretroshare/src/tests/serialiser/rstunnelitem_test.cc b/libretroshare/src/tests/serialiser/rstunnelitem_test.cc deleted file mode 100644 index 88de02517..000000000 --- a/libretroshare/src/tests/serialiser/rstunnelitem_test.cc +++ /dev/null @@ -1,108 +0,0 @@ - -/* - * libretroshare/src/serialiser: rstunnelitems_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2007-2008 by Cyril Soler - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****************************************************************** - */ - -#include -#include -#include -#include -#include "util/utest.h" -#include "support.h" - - - -RsTunnelSerialiser* init_item(RsTunnelDataItem& item) -{ - uint32_t S = rand()%20000 ; - item.encoded_data = malloc(S) ; - item.encoded_data_len = S ; - for(uint32_t i=0;i(); REPORT("Serialise/Deserialise RsTunnelDataItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsTunnelHandshakeItem"); - } - - FINALREPORT("RstunnelItem Tests"); - - return TESTRESULT(); -} - - diff --git a/libretroshare/src/tests/serialiser/rsturtleitem_test.cc b/libretroshare/src/tests/serialiser/rsturtleitem_test.cc deleted file mode 100644 index e7030818f..000000000 --- a/libretroshare/src/tests/serialiser/rsturtleitem_test.cc +++ /dev/null @@ -1,255 +0,0 @@ - -/* - * libretroshare/src/serialiser: rsturtleitems_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2007-2008 by Cyril Soler - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****************************************************************** - */ - -#include -#include -#include "turtle/rsturtleitem.h" -#include "ft/ftturtlefiletransferitem.h" -#include -#include "support.h" -#include "util/utest.h" - -INITTEST(); - -RsSerialType* init_item(CompressedChunkMap& map) -{ - map._map.clear() ; - for(uint32_t i=0;i<15;++i) - map._map.push_back(rand()) ; - - return new RsTurtleSerialiser(); -} -bool operator==(const CompressedChunkMap& m1,const CompressedChunkMap& m2) -{ - if(m1._map.size() != m2._map.size()) return false ; - - for(uint32_t i=0;i::const_iterator i1(it1.result.begin()) ; - std::list::const_iterator i2(it2.result.begin()) ; - - for(;i1!=it1.result.end() && i2!=it2.result.end();++i1,++i2) - if( !(*i1 == *i2)) - return false ; - - return true ; -} - -int main() -{ - std::cerr << "RsTurtleItem Tests" << std::endl; - - for(uint32_t i=0;i<20;++i) - { - test_RsItem(); REPORT("Serialise/Deserialise RsTurtleFileMapRequestItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsTurtleFileMapItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsTurtleFileDataItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsTurtleFileRequestItem"); - test_RsItem(); REPORT("Serialise/Deserialise RsTurtleTunnelOkItem "); - test_RsItem(); REPORT("Serialise/Deserialise RsTurtleOpenTunnelItem "); - test_RsItem(); REPORT("Serialise/Deserialise RsTurtleSearchResultItem "); - test_RsItem(); REPORT("Serialise/Deserialise RsTurtleStringSearchRequestItem "); - test_RsItem(); REPORT("Serialise/Deserialise RsTurtleRegExpSearchRequestItem "); - } - - FINALREPORT("RsturtleItem Tests"); - - return TESTRESULT(); -} - - diff --git a/libretroshare/src/tests/serialiser/support.cc b/libretroshare/src/tests/serialiser/support.cc deleted file mode 100644 index 9fbda2e1f..000000000 --- a/libretroshare/src/tests/serialiser/support.cc +++ /dev/null @@ -1,294 +0,0 @@ -/* - * libretroshare/src/serialiser: t_support.h.cc - * - * RetroShare Serialiser tests. - * - * Copyright 2007-2008 by Christopher Evi-Parker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include - -#include "support.h" -#include "serialiser/rstlvbase.h" - -void randString(const uint32_t length, std::string& outStr) -{ - char alpha = 'a'; - char* stringData = NULL; - - stringData = new char[length]; - - for(uint32_t i=0; i != length; i++) - stringData[i] = alpha + (rand() % 26); - - outStr.assign(stringData, length); - delete[] stringData; - - return; -} - -void randString(const uint32_t length, std::wstring& outStr) -{ - wchar_t alpha = L'a'; - wchar_t* stringData = NULL; - - stringData = new wchar_t[length]; - - for(uint32_t i=0; i != length; i++) - stringData[i] = (alpha + (rand() % 26)); - - outStr.assign(stringData, length); - delete[] stringData; - - return; -} - -bool operator==(const RsTlvSecurityKey& sk1, const RsTlvSecurityKey& sk2) -{ - - if(sk1.startTS != sk2.startTS) return false; - if(sk1.endTS != sk2.endTS) return false; - if(sk1.keyFlags != sk2.keyFlags) return false; - if(sk1.keyId != sk2.keyId) return false; - if(!(sk1.keyData == sk1.keyData)) return false; - - return true; -} - -bool operator==(const RsTlvKeySignature& ks1, const RsTlvKeySignature& ks2) -{ - - if(ks1.keyId != ks2.keyId) return false; - if(!(ks1.signData == ks2.signData)) return false; - - return true; -} - -bool operator==(const RsTlvKeySignatureSet& kss1, const RsTlvKeySignatureSet& kss2) -{ - const std::map& set1 = kss1.keySignSet, - &set2 = kss2.keySignSet; - - if(set1.size() != set2.size()) return false; - - std::map::const_iterator it1 = set1.begin(), it2; - - for(; it1 != set1.end(); it1++) - { - SignType st1 = it1->first; - - if( (it2 =set2.find(st1)) == set2.end()) - return false; - - if(!(it1->second == it2->second)) - return false; - - } - - return true; -} - -bool operator==(const RsTlvPeerIdSet& pids1, const RsTlvPeerIdSet& pids2) -{ - std::list::const_iterator it1 = pids1.ids.begin(), - it2 = pids2.ids.begin(); - - - for(; ((it1 != pids1.ids.end()) && (it2 != pids2.ids.end())); it1++, it2++) - { - if(*it1 != *it2) return false; - } - - return true; - -} - - -void init_item(RsTlvImage& im) -{ - std::string imageData; - randString(LARGE_STR, imageData); - im.binData.setBinData(imageData.c_str(), imageData.size()); - im.image_type = RSTLV_IMAGE_TYPE_PNG; - - return; -} - -bool operator==(const RsTlvBinaryData& bd1, const RsTlvBinaryData& bd2) -{ - if(bd1.tlvtype != bd2.tlvtype) return false; - if(bd1.bin_len != bd2.bin_len) return false; - - unsigned char *bin1 = (unsigned char*)(bd1.bin_data), - *bin2 = (unsigned char*)(bd2.bin_data); - - for(uint32_t i=0; i < bd1.bin_len; bin1++, bin2++, i++) - { - if(*bin1 != *bin2) - return false; - } - - return true; -} - - -void init_item(RsTlvSecurityKey& sk) -{ - int randnum = rand()%313131; - - sk.endTS = randnum; - sk.keyFlags = randnum; - sk.startTS = randnum; - randString(SHORT_STR, sk.keyId); - - std::string randomStr; - randString(LARGE_STR, randomStr); - - sk.keyData.setBinData(randomStr.c_str(), randomStr.size()); - - return; -} - -void init_item(RsTlvKeySignature& ks) -{ - randString(SHORT_STR, ks.keyId); - - std::string signData; - randString(LARGE_STR, signData); - - ks.signData.setBinData(signData.c_str(), signData.size()); - - return; -} -void init_item(RsTlvKeySignatureSet &kss) -{ - int numSign = rand()%21; - - for(int i=0; i < numSign; i++) - { - RsTlvKeySignature sign; - SignType sType = rand()%2452; - init_item(sign); - kss.keySignSet.insert(std::make_pair(sType, sign)); - } -} - - -bool operator==(const RsTlvImage& img1, const RsTlvImage& img2) -{ - if(img1.image_type != img2.image_type) return false; - if(!(img1.binData == img2.binData)) return false; - - return true; - -} - -/** channels, forums and blogs **/ - -void init_item(RsTlvHashSet& hs) -{ - for(int i=0; i < 10; i++) - hs.ids.push_back(RsFileHash::random()); - - return; -} - -void init_item(RsTlvPeerIdSet& ps) -{ - for(int i=0; i < 10; i++) - ps.ids.push_back(RsPeerId::random()); - - return; -} - -bool operator==(const RsTlvHashSet& hs1,const RsTlvHashSet& hs2) -{ - std::list::const_iterator it1 = hs1.ids.begin(), - it2 = hs2.ids.begin(); - - for(; ((it1 != hs1.ids.end()) && (it2 != hs2.ids.end())); it1++, it2++) - { - if(*it1 != *it2) return false; - } - - return true; -} - -void init_item(RsTlvFileItem& fi) -{ - fi.age = rand()%200; - fi.filesize = rand()%34030313; - fi.hash = RsFileHash::random(); - randString(SHORT_STR, fi.name); - randString(SHORT_STR, fi.path); - fi.piecesize = rand()%232; - fi.pop = rand()%2354; - init_item(fi.hashset); - - return; -} - -void init_item(RsTlvBinaryData& bd){ - bd.TlvClear(); - std::string data; - randString(LARGE_STR, data); - bd.setBinData(data.data(), data.length()); -} - -void init_item(RsTlvFileSet& fSet){ - - randString(LARGE_STR, fSet.comment); - randString(SHORT_STR, fSet.title); - RsTlvFileItem fi1, fi2; - init_item(fi1); - init_item(fi2); - fSet.items.push_back(fi1); - fSet.items.push_back(fi2); - - return; -} - -bool operator==(const RsTlvFileSet& fs1,const RsTlvFileSet& fs2) -{ - if(fs1.comment != fs2.comment) return false; - if(fs1.title != fs2.title) return false; - - std::list::const_iterator it1 = fs1.items.begin(), - it2 = fs2.items.begin(); - - for(; ((it1 != fs1.items.end()) && (it2 != fs2.items.end())); it1++, it2++) - if(!(*it1 == *it2)) return false; - - return true; -} - -bool operator==(const RsTlvFileItem& fi1,const RsTlvFileItem& fi2) -{ - if(fi1.age != fi2.age) return false; - if(fi1.filesize != fi2.filesize) return false; - if(fi1.hash != fi2.hash) return false; - if(!(fi1.hashset == fi2.hashset)) return false; - if(fi1.name != fi2.name) return false; - if(fi1.path != fi2.path) return false; - if(fi1.piecesize != fi2.piecesize) return false; - if(fi1.pop != fi2.pop) return false; - - return true; -} diff --git a/libretroshare/src/tests/serialiser/support.h b/libretroshare/src/tests/serialiser/support.h deleted file mode 100644 index c9b5eea77..000000000 --- a/libretroshare/src/tests/serialiser/support.h +++ /dev/null @@ -1,234 +0,0 @@ -#ifndef SUPPORT_H_ -#define SUPPORT_H_ - -/* - * libretroshare/src/tests/serialiser: - * - * RetroShare Serialiser tests. - * - * Copyright 2007-2008 by Christopher Evi-Parker, Cyril Soler - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include -#include -#include - -#include "util/utest.h" -#include "serialiser/rsserial.h" -#include "serialiser/rstlvutil.h" -#include "serialiser/rstlvkeys.h" -#include "serialiser/rstlvbinary.h" -#include "serialiser/rstlvfileitem.h" -#include "serialiser/rstlvidset.h" -#include "serialiser/rstlvimage.h" - - - -/** - * This contains functions that may be useful for testing throughout the - * retroshare's serialiser - * package, if you find a function you keep using everywhere, might be a good idea to add it here - */ - - -#define SHORT_STR 100 -#define LARGE_STR 1000 - -void randString(const uint32_t, std::string&); -void randString(const uint32_t, std::wstring&); - - -/* for testing compound tlv items */ - -void init_item(RsTlvSecurityKey&); -void init_item(RsTlvKeySignature&); -void init_item(RsTlvKeySignatureSet&); -void init_item(RsTlvBinaryData&); -void init_item(RsTlvFileItem&); -void init_item(RsTlvFileSet&); -void init_item(RsTlvHashSet&); -void init_item(RsTlvPeerIdSet&); -void init_item(RsTlvImage&); -void init_item(RsTlvPeerIdSet&); - -bool operator==(const RsTlvSecurityKey&, const RsTlvSecurityKey& ); -bool operator==(const RsTlvKeySignature&, const RsTlvKeySignature& ); -bool operator==(const RsTlvBinaryData&, const RsTlvBinaryData&); -bool operator==(const RsTlvFileItem&, const RsTlvFileItem&); -bool operator==(const RsTlvFileSet&, const RsTlvFileSet& ); -bool operator==(const RsTlvHashSet&, const RsTlvHashSet&); -bool operator==(const RsTlvImage&, const RsTlvImage& ); -bool operator==(const RsTlvPeerIdSet& , const RsTlvPeerIdSet& ); -bool operator==(const RsTlvKeySignatureSet& , const RsTlvKeySignatureSet& ); - - - -/*! - * This templated test function which allows you to test - * retroshare serialiser items (except compound tlv items) - * you the function must implement a function - * - * 'RsSerialType* init_item(YourRsItem& rs_item)' - * which returns valid serialiser that - * can serialiser rs_item. You also need to implement an operator - * - * Also need to implement a function - * 'bool operator =(YourRsItem& rs_itemL, YourRsItem& rs_temR)' - * which allows this function to test for equality between both parameters. - * rs_temR is the result of deserialising the left operand (1st parameter). - * not YourRsItem in specifier in about functions should be a derived type from RsItem - * - * @param T the item you want to test - */ - -template int test_RsItem() -{ - /* make a serialisable RsTurtleItem */ - - RsSerialiser srl; - - /* initialise */ - T rsfi ; - RsSerialType *rsfis = init_item(rsfi) ; - - /* attempt to serialise it before we add it to the serialiser */ - - CHECK(0 == srl.size(&rsfi)); - - static const uint32_t MAX_BUFSIZE = 22000 ; - - char *buffer = new char[MAX_BUFSIZE]; - uint32_t sersize = MAX_BUFSIZE; - - CHECK(false == srl.serialise(&rsfi, (void *) buffer, &sersize)); - - /* now add to serialiser */ - - srl.addSerialType(rsfis); - - uint32_t size = srl.size(&rsfi); - bool done = srl.serialise(&rsfi, (void *) buffer, &sersize); - - std::cerr << "test_Item() size: " << size << std::endl; - std::cerr << "test_Item() done: " << done << std::endl; - std::cerr << "test_Item() sersize: " << sersize << std::endl; - - std::cerr << "test_Item() serialised:" << std::endl; - //displayRawPacket(std::cerr, (void *) buffer, sersize); - - CHECK(done == true); - - uint32_t sersize2 = sersize; - RsItem *output = srl.deserialise((void *) buffer, &sersize2); - - CHECK(output != NULL); - CHECK(sersize2 == sersize); - - T *outfi = dynamic_cast(output); - - CHECK(outfi != NULL); - - if(!(*outfi == rsfi)) - { - std::cerr << "Items differ: "<< std::endl; - outfi->print(std::cerr,0) ; - rsfi.print(std::cerr,0) ; - } - if (outfi) - CHECK(*outfi == rsfi) ; - - - sersize2 = MAX_BUFSIZE; - bool done2 = srl.serialise(outfi, (void *) &(buffer[16*8]), &sersize2); - - CHECK(done2) ; - CHECK(sersize2 == sersize); - -// displayRawPacket(std::cerr, (void *) buffer, 16 * 8 + sersize2); - - delete[] buffer ; - //delete rsfis; - - return 1; -} - -template int test_RsItem(uint16_t servtype) -{ - /* make a serialisable RsTurtleItem */ - - RsSerialiser srl; - - /* initialise */ - T rsfi(servtype) ; - RsSerialType *rsfis = init_item(rsfi) ; // deleted on destruction of srl - - /* attempt to serialise it before we add it to the serialiser */ - - CHECK(0 == srl.size(&rsfi)); - - static const uint32_t MAX_BUFSIZE = 22000 ; - - char *buffer = new char[MAX_BUFSIZE]; - uint32_t sersize = MAX_BUFSIZE; - - CHECK(false == srl.serialise(&rsfi, (void *) buffer, &sersize)); - - /* now add to serialiser */ - - srl.addSerialType(rsfis); - - uint32_t size = srl.size(&rsfi); - bool done = srl.serialise(&rsfi, (void *) buffer, &sersize); - - std::cerr << "test_Item() size: " << size << std::endl; - std::cerr << "test_Item() done: " << done << std::endl; - std::cerr << "test_Item() sersize: " << sersize << std::endl; - - std::cerr << "test_Item() serialised:" << std::endl; - //displayRawPacket(std::cerr, (void *) buffer, sersize); - - CHECK(done == true); - - uint32_t sersize2 = sersize; - RsItem *output = srl.deserialise((void *) buffer, &sersize2); - - CHECK(output != NULL); - CHECK(sersize2 == sersize); - - T *outfi = dynamic_cast(output); - - CHECK(outfi != NULL); - - if (outfi) - CHECK(*outfi == rsfi) ; - - sersize2 = MAX_BUFSIZE; - bool done2 = srl.serialise(outfi, (void *) &(buffer[16*8]), &sersize2); - - CHECK(done2) ; - CHECK(sersize2 == sersize); - -// displayRawPacket(std::cerr, (void *) buffer, 16 * 8 + sersize2); - - delete[] buffer ; - - return 1; -} -#endif /* SUPPORT_H_ */ diff --git a/libretroshare/src/tests/serialiser/tlvbase_test.cc b/libretroshare/src/tests/serialiser/tlvbase_test.cc deleted file mode 100644 index 1f0e92def..000000000 --- a/libretroshare/src/tests/serialiser/tlvbase_test.cc +++ /dev/null @@ -1,195 +0,0 @@ - -/* - * libretroshare/src/serialiser: tlvbase_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2007-2008 by Horatio. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - - -#include -#include -#include -#include - -#include "serialiser/rstlvbase.h" -#include "util/utest.h" -#include "util/rsnet.h" - -INITTEST(); - -static int test_RsTlvBase(); -int main() -{ - std::cerr << " RsTlvBase Tests" < -//#include "serialiser/rstlvtypes.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvutil.h" -#include "util/utest.h" -#include "util/rsnet.h" - -INITTEST(); - -static int test_RsTlvString(); -static int test_RsTlvUInt32(); -static int test_RsTlvIPAddr(); - -int main() -{ - std::cerr << "RsTlvBase Tests" << std::endl; - - test_RsTlvString(); - test_RsTlvUInt32(); - test_RsTlvIPAddr(); - - FINALREPORT("RsTlvBase Tests"); - - return TESTRESULT(); -} - -int test_RsTlvUInt32() -{ - return 1; -} - -int test_OneString(std::string input, uint16_t type); - -int test_RsTlvString() -{ - std::string nullString; - std::string oneString = "1"; - std::string shortString = "ab cd"; - std::string longString = "abcd efgh ijkl mnop qrst uvw"; - - std::cerr << "test_RsTlvString() Testing" << std::endl; - test_OneString(nullString, 1234); - test_OneString(oneString, 12); - test_OneString(shortString, 79); - test_OneString(longString, 7654); - - REPORT("Serialise RsTlvFileItem"); - - return 1; -} - - -int test_OneString(std::string input, uint16_t type) -{ - /* an array to work from */ - char tlvdata[2048]; - std::string OutString; - - std::cerr << "test_OneString() Testing ... Print/Serialise/Deserialise"; - std::cerr << std::endl; - /* start with SetTlvString() */ - - uint16_t initsize = GetTlvStringSize(input); - uint32_t outOffset = 0; - uint32_t inOffset = 0; - - std::cerr << "Serialising: " << input << std::endl; - CHECK(SetTlvString((void*)tlvdata, 2048, &outOffset, type, input)); - std::cerr << "Init Size: " << initsize << std::endl; - std::cerr << "Serialised Size: " << outOffset << std::endl; - displayRawPacket(std::cerr, tlvdata, outOffset); - - CHECK(outOffset == initsize); /* check that the offset matches the size */ - - std::cerr << "DeSerialising" << std::endl; - - /* fails if type is wrong! */ - CHECK(0 == GetTlvString((void*)tlvdata, outOffset, &inOffset, type-1, OutString)); - CHECK(GetTlvString((void*)tlvdata, outOffset, &inOffset, type, OutString)); - - CHECK(initsize == inOffset); /* check that the offset matches the size */ - CHECK(input == OutString); /* check that strings match */ - std::cerr << "Deserialised: Size: " << inOffset << std::endl; - std::cerr << "Deserialised: String: " << OutString << std::endl; - - REPORT("Serialise OneString"); - - return 1; -} - -int test_IpAddr(struct sockaddr_in *addr, uint16_t type); - -static int test_RsTlvIPAddr() -{ - struct sockaddr_in addr; - - inet_aton("10.0.0.111", &(addr.sin_addr)); - addr.sin_port = htons(1111); - - test_IpAddr(&addr, 1234); - - inet_aton("255.255.255.1", &(addr.sin_addr)); - addr.sin_port = htons(9999); - - test_IpAddr(&addr, 1234); - - inet_aton("128.255.255.1", &(addr.sin_addr)); - addr.sin_port = htons(1); - - test_IpAddr(&addr, 1234); - - return 1; -} - -int test_IpAddr(struct sockaddr_in *addr, uint16_t type) -{ - /* an array to work from */ - char tlvdata[2048]; - struct sockaddr_in outaddr; - - std::cerr << "test_IpAddr() Testing ... Print/Serialise/Deserialise"; - std::cerr << std::endl; - /* start with SetTlvString() */ - - uint16_t initsize = GetTlvIpAddrPortV4Size(); - uint32_t outOffset = 0; - uint32_t inOffset = 0; - - std::cerr << "Serialising IPAddr: " << inet_ntoa(addr->sin_addr) << std::endl; - std::cerr << " Port : " << ntohs(addr->sin_port) << std::endl; - - CHECK(SetTlvIpAddrPortV4((void*)tlvdata, 2048, &outOffset, type, addr)); - std::cerr << "Init Size: " << initsize << std::endl; - std::cerr << "Serialised Size: " << outOffset << std::endl; - displayRawPacket(std::cerr, tlvdata, outOffset); - - CHECK(outOffset == initsize); /* check that the offset matches the size */ - - std::cerr << "DeSerialising" << std::endl; - - /* fails if type is wrong! */ - CHECK(0 == GetTlvIpAddrPortV4((void*)tlvdata, outOffset, &inOffset, type-1, &outaddr)); - CHECK(GetTlvIpAddrPortV4((void*)tlvdata, outOffset, &inOffset, type, &outaddr)); - - CHECK(initsize == inOffset); /* check that the offset matches the size */ - CHECK(addr->sin_addr.s_addr == outaddr.sin_addr.s_addr); /* check that IP match */ - CHECK(addr->sin_port == outaddr.sin_port); /* check that Port match */ - std::cerr << "Deserialised: Size: " << inOffset << std::endl; - std::cerr << "Deserialised IPAddr: " << inet_ntoa(outaddr.sin_addr) << std::endl; - std::cerr << " Port : " << ntohs(outaddr.sin_port) << std::endl; - - REPORT("Serialise OneIP/Port"); - - return 1; -} - - - diff --git a/libretroshare/src/tests/serialiser/tlvitems_test.cc b/libretroshare/src/tests/serialiser/tlvitems_test.cc deleted file mode 100644 index 5d88338bb..000000000 --- a/libretroshare/src/tests/serialiser/tlvitems_test.cc +++ /dev/null @@ -1,89 +0,0 @@ - -/* - * libretroshare/src/serialiser: tlvitems_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****************************************************************** - * tlvfileitem test. - * - * - */ - -#include -#include -#include "serialiser/rstlvbinary.h" -#include "serialiser/rstlvutil.h" -#include "util/utest.h" - -INITTEST(); - -static int test_RsTlvBinData(); -static int test_RsTlvStepping(); - -int main() -{ - std::cerr << "RsTlvItems Tests" << std::endl; - - test_RsTlvBinData(); - - FINALREPORT("RsTlvItems Tests"); - - return TESTRESULT(); -} - -#define BIN_LEN 65536 /* bigger than 64k */ - -int test_RsTlvBinData() -{ - RsTlvBinaryData d1(1023); - RsTlvBinaryData d2(1023); - - char data[BIN_LEN] = {0}; - int i, j; - for(i = 0; i < BIN_LEN; i++) - { - data[i] = i%13; - } - - for(j = 1; j < BIN_LEN; j *= 2) - { - d1.setBinData(data, j); - CHECK(test_SerialiseTlvItem(std::cerr, &d1, &d2)); - - CHECK(d1.bin_len == d2.bin_len); - CHECK(0 == memcmp(d1.bin_data, d2.bin_data, d1.bin_len)); - } - - REPORT("Serialise/Deserialise RsTlvBinData"); - - return 1; -} - -int test_RsTlvStepping() -{ - - - return 1; -} - diff --git a/libretroshare/src/tests/serialiser/tlvkey_test.cc b/libretroshare/src/tests/serialiser/tlvkey_test.cc deleted file mode 100644 index 23c87a715..000000000 --- a/libretroshare/src/tests/serialiser/tlvkey_test.cc +++ /dev/null @@ -1,36 +0,0 @@ - - -#include "support.h" -#include "serialiser/rstlvkeys.h" - -INITTEST(); - -bool test_RsTlvKeySignatureSet(); - -int main() -{ - test_RsTlvKeySignatureSet(); REPORT("test_RsTlvKeySignatureSet()"); - - FINALREPORT("RsTlvKey Test"); -} - - - -bool test_RsTlvKeySignatureSet() -{ - RsTlvKeySignatureSet set; - - init_item(set); - - char data[set.TlvSize()]; - uint32_t offset = 0; - set.SetTlv(data, set.TlvSize(), &offset); - - RsTlvKeySignatureSet setConfirm; - - offset = 0; - setConfirm.GetTlv(data, set.TlvSize(), &offset); - - CHECK(setConfirm == set); - -} diff --git a/libretroshare/src/tests/serialiser/tlvrandom_test.cc b/libretroshare/src/tests/serialiser/tlvrandom_test.cc deleted file mode 100644 index bed1525f7..000000000 --- a/libretroshare/src/tests/serialiser/tlvrandom_test.cc +++ /dev/null @@ -1,194 +0,0 @@ - -/* - * libretroshare/src/serialiser: tlvrandom_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2009 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****************************************************************** - * tlvrandom_test. - * - * This test is designed to attempt to break the TLV serialiser. - * - * To do this we throw random data at the serialisers and try to decode it. - * As the serialiser will only attempt to deserialise if the tlvtype matches - * we cheat a little, and make this match - to increase to actual deserialise - * attempts. - * - * This test runs for 30 seconds and attempts to do as - * many deserialisation as possible. - */ - -#include "util/rstime.h" -#include -#include -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvkeys.h" -#include "serialiser/rstlvutil.h" -#include "serialiser/rstlvbinary.h" -#include "serialiser/rstlvidset.h" -#include "serialiser/rstlvfileitem.h" -#include "serialiser/rstlvkeyvalue.h" -#include "serialiser/rstlvimage.h" - -#include "util/utest.h" - -INITTEST(); - -#define TEST_LENGTH 10 - -static int test_TlvRandom(void *data, uint32_t len, uint32_t offset); - -int main() -{ - std::cerr << "TlvRandom Tests" << std::endl; - - /* random data array to work through */ - uint32_t dsize = 10000000; - uint32_t i; - uint8_t *data = (uint8_t *) malloc(dsize); - - if (!data) - { - std::cerr << "Failed to allocate array"; - std::cerr << std::endl; - exit(1); - } - - rstime_t startTs = time(NULL); - rstime_t endTs = startTs + TEST_LENGTH; - - srand(startTs); - for(i = 0; i < dsize; i++) - { - data[i] = rand() % 256; - } - - std::cerr << "TlvRandom Tests: setup data." << std::endl; - - int count = 0; - for(i = 0; endTs > time(NULL); i += 2) - { - uint32_t len = dsize - i; - count += test_TlvRandom(&(data[i]), len, i); - - std::cerr << "Run: " << count << " tests"; - std::cerr << std::endl; - } - - FINALREPORT("RsTlvItems Tests"); - - return TESTRESULT(); -} - -#define BIN_LEN 523456 /* bigger than 64k */ - -bool test_TlvItem(RsTlvItem *item, void *data, uint32_t size, uint32_t offset); -bool test_SetTlvItem(RsTlvItem *item, uint16_t type, void *data, uint32_t size, uint32_t offset); - - -int test_TlvRandom(void *data, uint32_t len, uint32_t offset) -{ - uint32_t tmpoffset = 0; - - /* List of all the TLV types it could be! */ - RsTlvSecurityKey skey; - RsTlvSecurityKeySet skeyset; - RsTlvKeySignature keysign; - - RsTlvBinaryData bindata(TLV_TYPE_IMAGE); - - RsTlvFileItem fileitem; - RsTlvFileSet fileset; - RsTlvFileData filedata; - - RsTlvPeerIdSet peerset; - RsTlvServiceIdSet servset; - - RsTlvKeyValue kv; - RsTlvKeyValueSet kvset; - - RsTlvImage image; - - /* try to decode - with all types first */ - std::cerr << "test_TlvRandom:: Testing Files " << std::endl; - CHECK(test_TlvItem(&bindata, data, len, offset)); - CHECK(test_TlvItem(&fileitem, data, len, offset)); - CHECK(test_TlvItem(&fileset, data, len, offset)); - CHECK(test_TlvItem(&filedata, data, len, offset)); - std::cerr << "test_TlvRandom:: Testing Sets " << std::endl; - CHECK(test_TlvItem(&peerset, data, len, offset)); - CHECK(test_TlvItem(&servset, data, len, offset)); - CHECK(test_TlvItem(&kv, data, len, offset)); - CHECK(test_TlvItem(&kvset, data, len, offset)); - std::cerr << "test_TlvRandom:: Testing Keys " << std::endl; - CHECK(test_TlvItem(&skey, data, len, offset)); - CHECK(test_TlvItem(&skeyset, data, len, offset)); - CHECK(test_TlvItem(&keysign, data, len, offset)); - - /* now set the type correctly before decoding */ - std::cerr << "test_TlvRandom:: Testing Files (TYPESET)" << std::endl; - CHECK(test_SetTlvItem(&bindata, TLV_TYPE_IMAGE, data, len, offset)); - CHECK(test_SetTlvItem(&fileitem,TLV_TYPE_FILEITEM, data, len, offset)); - CHECK(test_SetTlvItem(&fileset, TLV_TYPE_FILESET, data, len, offset)); - CHECK(test_SetTlvItem(&filedata, TLV_TYPE_FILEDATA, data, len, offset)); - std::cerr << "test_TlvRandom:: Testing Sets (TYPESET)" << std::endl; - CHECK(test_SetTlvItem(&peerset, TLV_TYPE_PEERSET, data, len, offset)); - CHECK(test_SetTlvItem(&servset, TLV_TYPE_SERVICESET, data, len, offset)); - CHECK(test_SetTlvItem(&kv, TLV_TYPE_KEYVALUE, data, len, offset)); - CHECK(test_SetTlvItem(&kvset, TLV_TYPE_KEYVALUESET, data, len, offset)); - std::cerr << "test_TlvRandom:: Testing Keys (TYPESET)" << std::endl; - CHECK(test_SetTlvItem(&skey, TLV_TYPE_SECURITYKEY, data, len, offset)); - CHECK(test_SetTlvItem(&skeyset, TLV_TYPE_SECURITYKEYSET, data, len, offset)); - CHECK(test_SetTlvItem(&keysign, TLV_TYPE_KEYSIGNATURE, data, len, offset)); - - return 26; /* number of tests */ -} - -bool test_TlvItem(RsTlvItem *item, void *data, uint32_t size, uint32_t offset) -{ - uint32_t tmp_offset = offset; - if (item->GetTlv(data, size, &tmp_offset)) - { - std::cerr << "TLV decoded Random!"; - std::cerr << std::endl; - item->print(std::cerr, 20); - return false; - } - else - { - std::cerr << "TLV failed to decode"; - std::cerr << std::endl; - return true; - } -} - -bool test_SetTlvItem(RsTlvItem *item, uint16_t type, void *data, uint32_t size, uint32_t offset) -{ - /* set TLV type first! */ - void *typedata = (((uint8_t *) data) + offset); - SetTlvType(typedata, size - offset, type); - - return test_TlvItem(item, data, size, offset); -} - - diff --git a/libretroshare/src/tests/serialiser/tlvstack_test.cc b/libretroshare/src/tests/serialiser/tlvstack_test.cc deleted file mode 100644 index 36527ef8a..000000000 --- a/libretroshare/src/tests/serialiser/tlvstack_test.cc +++ /dev/null @@ -1,105 +0,0 @@ - -/* - * libretroshare/src/serialiser: tlvstack_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/****************************************************************** - * tlvfileitem test. - * - * - */ - -#include -#include "serialiser/rstlvfileitem.h" -#include "serialiser/rstlvbinary.h" -#include "serialiser/rstlvutil.h" -#include "util/utest.h" - -INITTEST(); - -static int test_RsTlvStack(); - -int main() -{ - std::cerr << "RsTlvItem Stack Tests" << std::endl; - - test_RsTlvStack(); - - FINALREPORT("RsTlvItem Stack Tests"); - - return TESTRESULT(); -} - - -#define BIN_LEN 53 - -int test_RsTlvStack() -{ - - /* now create a set of TLV items for the random generator */ - - RsTlvBinaryData *bd1 = new RsTlvBinaryData(123); - RsTlvBinaryData *bd2 = new RsTlvBinaryData(125); - - char data[BIN_LEN] = {0}; - int i; - for(i = 0; i < BIN_LEN; i++) - { - data[i] = i%13; - } - - bd1->setBinData(data, 5); - bd2->setBinData(data, 21); - - RsTlvFileItem *fi1 = new RsTlvFileItem(); - RsTlvFileItem *fi2 = new RsTlvFileItem(); - - /* initialise */ - fi1->filesize = 101010; - fi1->hash = "ABCDEFEGHE"; - fi1->name = "TestFile.txt"; - fi1->pop = 12; - fi1->age = 456; - - fi2->filesize = 101010; - fi2->hash = "ABCDEFEGHE"; - fi2->name = "TestFile.txt"; - fi2->pop = 0; - fi2->age = 0;; - - std::vector items; - items.resize(4); - items[0] = bd1; - items[1] = bd2; - items[2] = fi1; - items[3] = fi2; - - test_TlvSet(items, 1024); - - REPORT("Serialise/Deserialise RsTlvBinData"); - - return 1; -} - - diff --git a/libretroshare/src/tests/serialiser/tlvtypes_test.cc b/libretroshare/src/tests/serialiser/tlvtypes_test.cc deleted file mode 100644 index e32dfe0fc..000000000 --- a/libretroshare/src/tests/serialiser/tlvtypes_test.cc +++ /dev/null @@ -1,386 +0,0 @@ -/* - * libretroshare/src/serialiser: tlvfileitem_test.cc - * - * RetroShare Serialiser. - * - * Copyright 2007-2008 by Robert Fernie, Chris Evi-Parker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#include -#include -#include "serialiser/rstlvbinary.h" -#include "serialiser/rstlvfileitem.h" -#include "serialiser/rstlvstring.h" -#include "serialiser/rstlvidset.h" -#include "serialiser/rstlvkeyvalue.h" -#include "serialiser/rstlvimage.h" -#include "serialiser/rstlvutil.h" -#include "serialiser/rstlvbase.h" -#include "util/utest.h" - -INITTEST(); - -#define RAND_SEED 1352534 - -static int test_RsTlvBinData(); -static int test_RsTlvFileItem(); -static int test_RsTlvFileSet(); -static int test_RsTlvFileData(); -static int test_RsTlvStringSet(); -static int test_RsTlvPeerIdSet(); -static int test_RsTlvServiceIdSet(); -static int test_RsTlvKeyValue(); -static int test_RsTlvKeyValueSet(); -static int test_RsTlvHashSet(); -static int test_RsTlvImage(); - - - -int main() -{ - std::cerr << "RsTlvTypes[Item/Data/...] Tests" << std::endl; - - srand(RAND_SEED); - - test_RsTlvFileItem(); - test_RsTlvFileData(); - test_RsTlvFileSet(); - test_RsTlvPeerIdSet(); - test_RsTlvServiceIdSet(); - test_RsTlvKeyValue(); - test_RsTlvKeyValueSet(); - test_RsTlvBinData(); - test_RsTlvImage(); - test_RsTlvHashSet(); - - FINALREPORT("RsTlvTypes[Item/Data/...] Tests"); - - return TESTRESULT(); -} - -int test_RsTlvFileItem() -{ - RsTlvFileItem i1; - RsTlvFileItem i2; - - /* initialise */ - i1.filesize = 101010; - i1.hash = "ABCDEFEGHE"; - i1.name = "TestFile.txt"; - i1.pop = 12; - i1.age = 456; - - CHECK(test_SerialiseTlvItem(std::cerr, &i1, &i2)); - - /* check the data is the same */ - CHECK(i1.filesize == i2.filesize); - CHECK(i1.hash == i2.hash); - CHECK(i1.name == i2.name); - CHECK(i1.path == i2.path); - CHECK(i1.pop == i2.pop); - CHECK(i1.age == i2.age); - - /* do it again without optional data */ - i1.filesize = 123; - i1.name = ""; - i1.pop = 0; - i1.age = 0; - - CHECK(test_SerialiseTlvItem(std::cerr, &i1, &i2)); - - /* check the data is the same */ - CHECK(i1.filesize == i2.filesize); - CHECK(i1.hash == i2.hash); - CHECK(i1.name == i2.name); - CHECK(i1.path == i2.path); - CHECK(i1.pop == i2.pop); - CHECK(i1.age == i2.age); - - /* one more time - long file name, some optional data */ - i1.filesize = 123; - i1.name = "A Very Long File name that should fit in easily ??? with som $&%&^%* strange char (**$^%#&^$#*^%(&^ in there too!!!! ~~~!!$#(^$)$)(&%^)&\" oiyu thend"; - i1.pop = 666; - i1.age = 0; - - CHECK(test_SerialiseTlvItem(std::cerr, &i1, &i2)); - - /* check the data is the same */ - CHECK(i1.filesize == i2.filesize); - CHECK(i1.hash == i2.hash); - CHECK(i1.name == i2.name); - CHECK(i1.path == i2.path); - CHECK(i1.pop == i2.pop); - CHECK(i1.age == i2.age); - - REPORT("Serialise/Deserialise RsTlvFileItem"); - - return 1; -} - -int test_RsTlvFileSet() -{ - RsTlvFileSet s1; - RsTlvFileSet s2; - - int i = 0; - for(i = 0; i < 15; i++) - { - RsTlvFileItem fi; - fi.filesize = 16 + i * i; - fi.hash = "ABCDEF"; - std::ostringstream out; - out << "File" << i << "_inSet.txt"; - fi.name = out.str(); - if (i % 2 == 0) - { - fi.age = 10 * i; - } - else - { - fi.age = 0; - } - fi.pop = 0; - - s1.items.push_back(fi); - } - - CHECK(test_SerialiseTlvItem(std::cerr, &s1, &s2)); - - /* check the data is the same - TODO */ - - REPORT("Serialise/Deserialise RsTlvFileSet"); - - return 1; -} - - -int test_RsTlvFileData() -{ - RsTlvFileData d1; - RsTlvFileData d2; - - /* initialise */ - d1.file.filesize = 101010; - d1.file.hash = "ABCDEFEGHE"; - d1.file.name = ""; - d1.file.age = 0; - d1.file.pop = 0; - - char data[15]; - d1.binData.setBinData(data, 15); - - d1.file_offset = 222; - - CHECK(test_SerialiseTlvItem(std::cerr, &d1, &d2)); - - /* check the data is the same */ - CHECK(d1.file.filesize == d2.file.filesize); - CHECK(d1.file.hash == d2.file.hash); - CHECK(d1.file.name == d2.file.name); - CHECK(d1.file.path == d2.file.path); - CHECK(d1.file.pop == d2.file.pop); - CHECK(d1.file.age == d2.file.age); - - CHECK(d1.file_offset == d2.file_offset); - CHECK(d1.binData.bin_len == d2.binData.bin_len); - - REPORT("Serialise/Deserialise RsTlvFileData"); - - return 1; -} - - -int test_RsTlvPeerIdSet() -{ - - RsTlvPeerIdSet i1, i2; // one to set and other to get - - RsPeerId testId; - - std::string randString[5]; - randString[0] = "e$424!ļæ½!ļæ½"; - randString[1] = "e~:@L{L{KHKG"; - randString[2] = "e{@O**/*/*"; - randString[3] = "e?<HGļæ½!ļæ½%$"; - randString[4] = "e>HGļæ½!ļæ½%$"; - randString[4] = "e>addFriend(fakePeer); -} - -ServiceTest::~ServiceTest() -{ - // release resources - delete mConnMgr; - delete mPersonGrp; - delete mPeers; -} - - - - - - diff --git a/libretroshare/src/tests/services/servicetest.h b/libretroshare/src/tests/services/servicetest.h deleted file mode 100644 index ca24e9f0e..000000000 --- a/libretroshare/src/tests/services/servicetest.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * libretroshare/src/tests/services Service_Test.h - * - * RetroShare Service Testing - * - * Copyright 2010 by Chris Evi-Parker. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#ifndef SERVICE_TEST_H_ -#define SERVICE_TEST_H_ - -#include "pqi/p3connmgr.h" -#include "rsserver/p3peers.h" -#include "dbase/cachestrapper.h" -#include "pqi/pqipersongrp.h" - - - - -/*! - * A convenience class from which tests derive from - * This enables user to test in shallow manner the public methods - * of a service - */ -class ServiceTest { - -public: - ServiceTest(); - virtual ~ServiceTest(); - - /*! - * all tests of service should be implemented here - */ - virtual void runTests() = 0; - - /*! - * use this to populate the service with messages - */ - void sendItem(RsItem* item); - -protected: - - - p3ConnectMgr* mConnMgr; - CacheStrapper *mCs; - CacheTransfer *mCt; - p3Peers* mPeers; - pqipersongrp* mPersonGrp; - - std::string fakePeer; // ssl id of fake receiving peer - -}; - - - -#endif /* SERVICE_TEST_H_ */ diff --git a/libretroshare/src/tests/tcponudp/bidir_tou.cc b/libretroshare/src/tests/tcponudp/bidir_tou.cc deleted file mode 100644 index 5075130d9..000000000 --- a/libretroshare/src/tests/tcponudp/bidir_tou.cc +++ /dev/null @@ -1,402 +0,0 @@ -/* - * "$Id: pair_tou.cc,v 1.3 2007-02-18 21:46:50 rmf24 Exp $" - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2004-2006 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - - -#include -#include - -// for printing sockaddr -#include "udp/udpstack.h" - -#include "tcponudp/tou.h" -#include "tcponudp/udppeer.h" -#include "tcponudp/udprelay.h" - -#include "util/bdnet.h" - -#include "util/rsrandom.h" - -#include -#include -#include - - -/* - * This test creates the same stacks as are used in RS. - * This additionally tests the "checkFns" for the other UdpReceivers, which could potentially be modifying the data. - * obviously they shouldn't! - * - */ - -void usage(char *name) -{ - std::cerr << "Usage: " << name; - std::cerr << " [-pco] "; - std::cerr << " "; - std::cerr << std::endl; - exit(1); - return; -} - -int main(int argc, char **argv) -{ - int c; - bool isProxy = false; - bool toConnect = false; - bool stayOpen = false; - - int totalwbytes = 0; - int totalmbytes = 0; - int totalrbytes = 0; - - while(-1 != (c = getopt(argc, argv, "pco"))) - { - switch (c) - { - case 'p': - isProxy = true; - break; - case 'c': - toConnect = true; - break; - case 'o': - stayOpen = true; - break; - default: - usage(argv[0]); - break; - } - } - - if (argc-optind < 4) - { - usage(argv[0]); - return 1; - } - - /* setup the local/remote addresses. - */ - struct sockaddr_in laddr; - struct sockaddr_in raddr; - - laddr.sin_family = AF_INET; - raddr.sin_family = AF_INET; - - if ((!bdnet_inet_aton(argv[optind], &(laddr.sin_addr))) || - (!bdnet_inet_aton(argv[optind+2], &(raddr.sin_addr)))) - { - std::cerr << "Invalid addresses!" << std::endl; - usage(argv[0]); - } - - laddr.sin_port = htons(atoi(argv[optind+1])); - raddr.sin_port = htons(atoi(argv[optind+3])); - - std::cerr << "Local Address: " << laddr << std::endl; - std::cerr << "Remote Address: " << raddr << std::endl; - - std::cerr << "Creating with Lossy Udp Layers for further testing"; - std::cerr << std::endl; - - UdpStack *udpStack1 = new UdpStack(UDP_TEST_LOSSY_LAYER,laddr); - UdpStack *udpStack2 = new UdpStack(UDP_TEST_LOSSY_LAYER,raddr); - - UdpSubReceiver *udpReceivers[4]; - int udpTypes[4]; - - // NOTE DHT is too hard to add at the moment. - - UdpRelayReceiver *mRelay1 = new UdpRelayReceiver(udpStack1); - udpReceivers[1] = mRelay1; - udpTypes[1] = TOU_RECEIVER_TYPE_UDPRELAY; - udpStack1->addReceiver(udpReceivers[1]); - - udpReceivers[0] = new UdpPeerReceiver(udpStack1); - udpTypes[0] = TOU_RECEIVER_TYPE_UDPPEER; - udpStack1->addReceiver(udpReceivers[0]); - - // STACK 2. - UdpRelayReceiver *mRelay2 = new UdpRelayReceiver(udpStack2); - udpReceivers[3] = mRelay2; - udpTypes[3] = TOU_RECEIVER_TYPE_UDPRELAY; - udpStack2->addReceiver(udpReceivers[3]); - - udpReceivers[2] = new UdpPeerReceiver(udpStack2); - udpTypes[2] = TOU_RECEIVER_TYPE_UDPPEER; - udpStack2->addReceiver(udpReceivers[2]); - - tou_init((void **) udpReceivers, udpTypes, 4); - - - int sockfd = tou_socket(0, TOU_RECEIVER_TYPE_UDPPEER, 0); - int sockfd2 = tou_socket(2, TOU_RECEIVER_TYPE_UDPPEER, 0); - if ((sockfd <= 0) || (sockfd2 <= 0)) - { - std::cerr << "Failed to open socket!: "; - std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl; - std::cerr << "Socket Error:" << tou_errno(sockfd2) << std::endl; - return -1; - } - std::cerr << "Sockets Created: " << sockfd << " & " << sockfd2 << std::endl; - - std::cerr << "Socket Non-Blocking" << std::endl; - - std::cerr << "Socket1 Bound to: " << laddr << std::endl; - std::cerr << "Socket2 Bound to: " << raddr << std::endl; - - int err = 0; - - // listening. - if (1) // socket2. - { - std::cerr << "Socket2 Listening " << std::endl; - /* listen */ - err = tou_listenfor(sockfd2, - (struct sockaddr *) &laddr, sizeof(laddr)); - } - - - if (1) // only one program. - { - std::cerr << "Socket1 Connecting to: " << raddr << std::endl; - err = tou_connect(sockfd, (struct sockaddr *) &raddr, sizeof(raddr), 30); - if (err < 0) - { - errno = tou_errno(sockfd); - if (errno != EINPROGRESS) - { - std::cerr << "Cannot Connect!: " << errno << std::endl; - return 1; - } - } - } - - bool sock1Connected = false; - bool sock2Connected = false; - - while((!sock1Connected) || (!sock2Connected)) - { - usleep(1000); - - - /* sock1 */ - if((!sock1Connected) && (0 == (err = tou_connected(sockfd)))) - { - std::cerr << "Waiting for Connect (Sock1)!" << std::endl; - } - if ((!sock1Connected) && (err < 0)) - { - std::cerr << "Connect Failed" << std::endl; - return 1; - } - else if (!sock1Connected) - { - // else connected! - sock1Connected = true; - } - - /* accept - sock2 */ - struct sockaddr_in inaddr; - socklen_t addrlen = sizeof(inaddr); - int nsock = -1; - - if ((!sock2Connected) && (0 > (nsock = tou_accept(sockfd2, - (struct sockaddr *) &inaddr, &addrlen)))) - { - errno = tou_errno(sockfd2); - if (errno != EAGAIN) - { - std::cerr << "Cannot Connect!: " << errno << std::endl; - return 1; - } - else - { - std::cerr << "Waiting for Connect (Sock2)!" << std::endl; - } - } - else if (nsock > 0) - { - /* connected */ - sock2Connected = true; - sockfd2 = nsock; - std::cerr << "Socket Accepted from: " << inaddr << std::endl; - } - } - - std::cerr << "Socket Connected" << std::endl; - -#define MAX_READ 20000 - - /* send data */ - int bufsize = MAX_READ; - char buffer[MAX_READ]; - char middata[MAX_READ]; - char data[MAX_READ]; - int readsize = 0; - int midsize = 0; - - bdnet_fcntl(0, F_SETFL, O_NONBLOCK); - bdnet_fcntl(1,F_SETFL,O_NONBLOCK); - - rstime_t lastRead = time(NULL); - bool doneWrite = false; - bool doneRead = false; - bool blockread = false; - bool blockmid = false; - - while((!doneWrite) || (!doneRead)) - { - /* read -> write_socket... */ - usleep(10); - - if (blockread != true) - { - int readbuf = 1 + RSRandom::random_u32() % (MAX_READ - 1); - readsize = read(0, buffer, readbuf); - if (readsize) - { - //std::cerr << "read " << readsize << " / " << readbuf; - //std::cerr << std::endl; - } - } - if ((readsize == 0) && (!doneWrite)) - { - /* eof */ - doneWrite = true; - std::cerr << "Write Done Total: " << totalwbytes; - std::cerr << std::endl; - } - /* now we write */ - if ((readsize > 0) && (-1 == tou_write(sockfd, buffer, readsize))) - { - //std::cerr << "Blocked Write "; - //std::cerr << "Error: " << tou_errno(sockfd); - //std::cerr << std::endl; - blockread = true; - } - else - { - blockread = false; - totalwbytes += readsize; - - if (readsize) - { - std::cerr << "Written: " << readsize << ", Total: " << totalwbytes; - std::cerr << " Total In Transit: " << totalwbytes - totalrbytes; - std::cerr << std::endl; - } - } - - /*************** Here we read it in, and send it back out... - * so the data is flowing both ways through the UDP connection - * - *****/ - - - if (!blockmid) - { - /* read from socket 2, and write back to socket 2 */ - - int readmidbuf = 1 + RSRandom::random_u32() % (MAX_READ - 1); - if (0 < (midsize = tou_read(sockfd2, middata, readmidbuf))) - { - //std::cerr << "MidRead: " << mid << " Total: " << totalrbytes; - //std::cerr << " In Transit: " << totalwbytes - totalrbytes; - //std::cerr << std::endl; - } - } - - /* now we write */ - if ((midsize > 0) && (-1 == tou_write(sockfd2, middata, midsize))) - { - //std::cerr << "Blocked Write "; - //std::cerr << "Error: " << tou_errno(sockfd); - //std::cerr << std::endl; - blockmid = true; - } - else - { - blockmid = false; - - if (midsize > 0) - { - totalmbytes += midsize; - - std::cerr << "MidRead: " << midsize << ", Total: " << totalmbytes; - std::cerr << " => Transit => : " << totalwbytes - totalmbytes; - std::cerr << " <= Transit <= : " << totalmbytes - totalrbytes; - std::cerr << std::endl; - } - } - - /***** READ FROM FIRST SOCKET *****/ - - int ret = 0; - int readbuf2 = 1 + RSRandom::random_u32() % (MAX_READ - 1); - if (0 < (ret = tou_read(sockfd, data, readbuf2))) - { - //std::cerr << "TF(" << ret << ")" << std::endl; - write(1, data, ret); - totalrbytes += ret; - - std::cerr << "Read: " << ret << " Total: " << totalrbytes; - std::cerr << " Total In Transit: " << totalwbytes - totalrbytes; - std::cerr << std::endl; - - lastRead = time(NULL); - } - else if ((ret == 0) && (!doneRead)) - { - doneRead = true; - std::cerr << "Read Done Total: " << totalrbytes; - std::cerr << std::endl; - } - else - { - //std::cerr << "Blocked Read: " << "Error: " << tou_errno(sockfd); - //std::cerr << std::endl; -#define TIMEOUT 15 - if ((!doneRead) && (time(NULL) - lastRead > TIMEOUT)) - { - doneRead = true; - std::cerr << "TIMEOUT: Read Done Total: " << totalrbytes; - std::cerr << std::endl; - } - } - - - } - - /* this is blocking??? */ - tou_close(sockfd); - tou_close(sockfd2); - - std::cerr << "Transfer Complete: " << totalwbytes << " bytes"; - std::cerr << std::endl; - return 1; -} - diff --git a/libretroshare/src/tests/tcponudp/bidir_tou.sh b/libretroshare/src/tests/tcponudp/bidir_tou.sh deleted file mode 100755 index 048dd67b4..000000000 --- a/libretroshare/src/tests/tcponudp/bidir_tou.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh -# Script to Test the udp_server code. - -EXEC=./bidir_tou -DATAFILE=../../lib/libretroshare.a - -TMPOUTPUT=tmpoutput$$ -EXPECTEDPERIOD=10 - -$EXEC 127.0.0.1 4401 127.0.0.1 4032 < $DATAFILE > $TMPOUTPUT - -if diff -s $DATAFILE $TMPOUTPUT -then - echo "SUCCESS" -else - echo "FAILURE to accurately transfer DATA" -fi - -rm $TMPOUTPUT - diff --git a/libretroshare/src/tests/tcponudp/internal_tou.cc b/libretroshare/src/tests/tcponudp/internal_tou.cc deleted file mode 100644 index 353fecedc..000000000 --- a/libretroshare/src/tests/tcponudp/internal_tou.cc +++ /dev/null @@ -1,632 +0,0 @@ -/* - * "$Id: internal_tou.cc,v 1.2 2007-02-18 21:46:50 rmf24 Exp $" - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2004-2006 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -/********************************************************** - * There appears (was) to be an elusive bug in the tou internals. - * most likely to be in the packing and unpacking of the - * data queues. - * - * This test is designed to load the queues up and then - * transfer the data, repeatly with different size packets. - * - * to do this effectively we need to access the TcpStream - * objects, instead of the tou.h interface. - * - */ - -#include - -// for printing sockaddr -#include "udplayer.h" -#include "tcpstream.h" - -#include "tou.h" -#include "tou_net.h" - -#include -#include -#include - - -/* This is a simple test to ensure that the tou behaviour - * is almost identical to a standard tcp socket. - * - * In this version we open 2 sockets, and attempt to - * communicate with ourselves.... - * - */ - -int setup_socket(struct sockaddr_in addr); -int connect_socket_pair(int fd1, int fd2, - struct sockaddr_in addr1, struct sockaddr_in addr2); -int send_data_via_pair(int sockfd1, int sockfd2, char *data, int size); - -void usage(char *name) -{ - std::cerr << "Usage: " << name; - std::cerr << " [-pco] "; - std::cerr << " "; - std::cerr << std::endl; - exit(1); - return; -} - -int main(int argc, char **argv) -{ - int c; - bool isProxy = false; - bool toConnect = false; - bool stayOpen = false; - int i,j; - - while(-1 != (c = getopt(argc, argv, "pco"))) - { - switch (c) - { - case 'p': - isProxy = true; - break; - case 'c': - toConnect = true; - break; - case 'o': - stayOpen = true; - break; - default: - usage(argv[0]); - break; - } - } - - if (argc-optind < 4) - { - usage(argv[0]); - return 1; - } - - // tounet_init(); - - - /* setup the local/remote addresses. - */ - struct sockaddr_in laddr; - struct sockaddr_in raddr; - - laddr.sin_family = AF_INET; - raddr.sin_family = AF_INET; - - if ((!tounet_inet_aton(argv[optind], &(laddr.sin_addr))) || - (!tounet_inet_aton(argv[optind+2], &(raddr.sin_addr)))) - { - std::cerr << "Invalid addresses!" << std::endl; - usage(argv[0]); - } - - unsigned short laddr_port = atoi(argv[optind+1]); - unsigned short raddr_port = atoi(argv[optind+3]); - - laddr.sin_port = htons(laddr_port); - raddr.sin_port = htons(raddr_port); - - /* so create the Udp/Tcp components */ - //UdpLayer udp1(laddr); - //UdpLayer udp2(raddr); - LossyUdpLayer udp1(laddr, 0.10); - LossyUdpLayer udp2(raddr, 0.10); - - /* check that they are okay */ - if ((!udp1.okay()) || (!udp2.okay())) - { - std::cerr << "Trouble opening udp ports!"; - std::cerr << std::endl; - return 1; - } - - TcpStream tcp1(&udp1); - TcpStream tcp2(&udp2); - - udp1.setRemoteAddr(raddr); - udp2.setRemoteAddr(laddr); - tcp1.connect(); // start the connection. - - /* now connect them */ - while ((!tcp1.isConnected()) || (!tcp2.isConnected())) - { - usleep(10000); /* 10 ms */ - tcp1.tick(); - tcp2.tick(); - } - - std::cerr << "Connection Established!" << std::endl; - - for(i = 0; i < 10; i++) - { - - int size = 1024000; - char rnddata1[size]; - char rnddata2[size]; - - for(j = 0; j < size; j++) - { - rnddata1[j] = (unsigned char) (255.0 * - rand() / (RAND_MAX + 1.0)); - - rnddata2[j] = (unsigned char) (255.0 * - rand() / (RAND_MAX + 1.0)); - } - - /* for each iteration, we want to - * (1) fill up the outgoing buffers with stuff - */ - - int sent1 = 0; - int sent2 = 0; - int fill1, fill2; - int MaxSend = 1000000; - - while((fill1 = tcp1.write_allowed()) && (sent1 < MaxSend)) - { - /* fill with a random little bit more */ - int psize = (int) ((i + 1.0) * 255.0 * - rand() / (RAND_MAX + 1.0)); - - /* don't overload */ - if (psize > fill1) - { - std::cerr << "LAST FILL1" << std::endl; - psize = fill1; - } - - int ret = tcp1.write(&(rnddata1[sent1]), psize); - - if (ret) - { - sent1 += ret; - std::cerr << "Filled tcp1 with " << ret << " more bytes, total:"; - std::cerr << sent1 << " was allowed: " << fill1; - std::cerr << std::endl; - } - - //tcp1.status(std::cerr); - - } - std::cerr << "Tcp1 full with " << sent1 << " bytes "; - std::cerr << std::endl; - - while((fill2 = tcp2.write_allowed()) && (sent2 < MaxSend)) - { - /* fill with a random little bit more */ - /* slightly larger sizes */ - int psize = (int) ((i + 1.0) * 1255.0 * - rand() / (RAND_MAX + 1.0)); - - /* don't overload */ - if (psize > fill2) - { - std::cerr << "LAST FILL2" << std::endl; - psize = fill2; - } - - int ret = tcp2.write(&(rnddata2[sent2]), psize); - - if (ret) - { - sent2 += ret; - std::cerr << "Filled tcp2 with " << ret << " more bytes, total:"; - std::cerr << sent2 << " was allowed: " << fill2; - std::cerr << std::endl; - } - - //tcp2.status(std::cerr); - - } - std::cerr << "Tcp2 full with " << sent2 << " bytes "; - std::cerr << std::endl; - - /* for every second iteration, fill up the read buffer before starting */ - if (i % 2 == 0) - { - for(j = 0; j < 100; j++) - { - tcp1.tick(); - tcp2.tick(); - } - } - - /* now we read/tick and empty */ - int read1 = 0; - int read2 = 0; - - while(read1 < sent2) - { - tcp1.tick(); - tcp2.tick(); - - /* fill with a random little bit more */ - /* This one has a small read, while tcp2 has a large read */ - int psize = (int) ((i + 1.0) * 100.0 * - rand() / (RAND_MAX + 1.0)); - - /* limit to what we have! */ - if (psize > sent2 - read1) - { - std::cerr << "LAST READ1" << std::endl; - psize = sent2 - read1; - } - - char rbuf[psize]; - int rsize = psize; - - int ret = tcp1.read(rbuf, rsize); - if (0 < ret) - { - /* check the data */ - for(j = 0; j < ret; j++) - { - if (rnddata2[read1 + j] != rbuf[j]) - { - std::cerr << "Error Data Mismatch @ read1:" << read1; - std::cerr << " + j:" << j << " rsize: " << rsize; - std::cerr << " Index: " << read1 + j; - std::cerr << std::endl; - - int badoffset = read1 + j; - for(int k = -10; k < 10; k++) - { - printf("Orig: %02x, Trans: %02x\n", - (unsigned char) rnddata2[badoffset+k], - (unsigned char) rbuf[j + k]); - } - - - exit(1); - } - } - read1 += ret; - } - else - { - std::cerr << "Read Error: " << ret << std::endl; - } - std::cerr << "Requested " << psize << ", got " << ret << " bytes" << std::endl; - std::cerr << "Read " << read1 << " of " << sent2 << " bytes" << std::endl; - } - - sleep(2); - - - while(read2 < sent1) - { - tcp1.tick(); - tcp2.tick(); - - /* fill with a random little bit more */ - int psize = (int) ((i + 1.0) * 10000.0 * - rand() / (RAND_MAX + 1.0)); - - /* limit to what we have! */ - if (psize > sent1 - read2) - { - std::cerr << "LAST READ2" << std::endl; - psize = sent1 - read2; - } - - char rbuf[psize]; - int rsize = psize; - - int ret = tcp2.read(rbuf, rsize); - if (0 < ret) - { - /* check the data */ - for(j = 0; j < ret; j++) - { - if (rnddata1[read2 + j] != rbuf[j]) - { - std::cerr << "Error Data Mismatch @ read2:" << read2; - std::cerr << " + j:" << j << " rsize: " << rsize; - std::cerr << " Index: " << read2 + j; - std::cerr << std::endl; - exit(1); - } - } - read2 += ret; - } - else - { - std::cerr << "Read Error: " << ret << std::endl; - } - std::cerr << "Requested " << psize << ", got " << ret << " bytes" << std::endl; - std::cerr << "Read " << read2 << " of " << sent1 << " bytes" << std::endl; - } - - std::cerr << "Iteration " << i + 1 << " finished correctly!" << std::endl; - sleep(5); - - } - return 1; -} - -int setup_socket(struct sockaddr_in addr) -{ - int sockfd = tou_socket(PF_INET, SOCK_STREAM, 0); - - if (sockfd <= 0) - { - std::cerr << "Failed to open socket!: "; - std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl; - return -1; - } - - std::cerr << "Socket Created: " << sockfd << std::endl; - - int err = tou_bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)); - - if (err < 0) - { - std::cerr << "Error: Cannot bind socket: "; - std::cerr << err << std::endl; - return -1; - } - - std::cerr << "Socket1 Bound to: " << addr << std::endl; - return sockfd; -} - -int connect_socket_pair(int fd1, int fd2, - struct sockaddr_in addr1, struct sockaddr_in addr2) -{ - std::cerr << "Socket2 Listening " << std::endl; - /* listen */ - int err = tou_listenfor(fd2, (struct sockaddr *) &addr1, sizeof(addr1)); - int err_num; - - if (err < 0) - { - err_num = tou_errno(fd2); - if (err_num != EINPROGRESS) - { - std::cerr << "Cannot Listen!: " << err_num << std::endl; - return -1; - } - } - - - std::cerr << "Socket1 Connecting to: " << addr2 << std::endl; - err = tou_connect(fd1, (struct sockaddr *) &addr2, sizeof(addr2)); - if (err < 0) - { - err_num = tou_errno(fd1); - if (err_num != EINPROGRESS) - { - std::cerr << "Cannot Connect!: " << err_num << std::endl; - return -1; - } - } - - bool sock1Connected = false; - bool sock2Connected = false; - - while((!sock1Connected) || (!sock2Connected)) - { - sleep(1); - - /* sock1 */ - if((!sock1Connected) && (0 == (err = tou_connected(fd1)))) - { - std::cerr << "Waiting for Connect (Sock1)!" << std::endl; - } - - if ((!sock1Connected) && (err < 0)) - { - std::cerr << "Connect Failed" << std::endl; - return 1; - } - else if (!sock1Connected) - { - // else connected! - sock1Connected = true; - } - - /* accept - sock2 */ - struct sockaddr_in inaddr; - socklen_t addrlen = sizeof(inaddr); - int nsock = -1; - - if ((!sock2Connected) && (0 > (nsock = tou_accept(fd2, - (struct sockaddr *) &inaddr, &addrlen)))) - { - errno = tou_errno(fd2); - if (errno != EAGAIN) - { - std::cerr << "Cannot Connect!: " << errno << std::endl; - return 1; - } - else - { - std::cerr << "Waiting for Connect (Sock2)!" << std::endl; - } - } - else if (nsock > 0) - { - /* connected */ - sock2Connected = true; - fd2 = nsock; - std::cerr << "Socket Accepted from: " << inaddr << std::endl; - } - } - - std::cerr << "Socket Connected" << std::endl; - - return 1; -} - - -/* This transmits into sockfd1, and check to see that we recv - * it back from sockfd2 - */ - -int send_data_via_pair(int sockfd1, int sockfd2, char *data, int size) -{ - /* what we recvd */ - char *recvd = (char *) malloc(size * 2); - int recvdsize = 0; - int sent = 0; - int sendsize = 0; - - int ts_start = time(NULL); - - int minsends = 100; /* min of 100 sends to complete all data */ - /* ensure we don't end up sending nothing */ - if (minsends * 10 > size) - { - minsends = size / 10; - } - - bool doneWrite = false; - bool doneRead = false; - while((!doneWrite) || (!doneRead)) - { - /* have a little break */ - //usleep(10000); /* 0.01 sec */ - //usleep(250000); /* 0.25 sec */ - usleep(500000); /* 0.50 sec */ - /* decide how much to send */ - sendsize = (int) (((float) (size / minsends)) * - (rand() / (RAND_MAX + 1.0))); - - /* limit send */ - if (sent + sendsize > size) - { - sendsize = size - sent; - } - /* if we've finished */ - if (sent == size) - { - /* eof */ - std::cerr << "Write Done!" << std::endl; - doneWrite = true; - sendsize = 0; - } - - /* now we write */ - if ((sendsize > 0)&&(-1==tou_write(sockfd1,&(data[sent]),sendsize))) - { - std::cerr << "Write Error: " << tou_errno(sockfd1) << std::endl; - if (tou_errno(sockfd1) != EAGAIN) - { - std::cerr << "FATAL ERROR ending transfer" << std::endl; - doneRead = true; - doneWrite = true; - } - - } - else - { - sent += sendsize; - } - - int ret = 0; - int readsize = (int) (((float) (size / minsends)) * - (rand() / (RAND_MAX + 1.0))); - - if (readsize > size - recvdsize) - readsize = size - recvdsize; - - if (0 < (ret = tou_read(sockfd2, &(recvd[recvdsize]), readsize))) - { - std::cerr << "TF(" << ret << ")" << std::endl; - recvdsize += ret; - } - else if (ret == 0) - { - doneRead = true; - std::cerr << "Read Done! (ret:0)" << std::endl; - } - else - { - std::cerr << "Read Error: " << tou_errno(sockfd2) << std::endl; - std::cerr << "Read " << recvdsize << "/" << size; - std::cerr << " attempted: " << readsize << std::endl; - if (tou_errno(sockfd2) != EAGAIN) - { - std::cerr << "FATAL ERROR ending transfer" << std::endl; - doneRead = true; - doneWrite = true; - } - - } - - if (recvdsize == size) - { - doneRead = true; - std::cerr << "Read Done!" << std::endl; - } - - } - - /* we have transmitted it all, so - * check the data - */ - - int i; - int diffCount = 0; - for(i = 0; i < size; i++) - { - if (recvd[i] != data[i]) - { - diffCount++; - if (diffCount < 10) - { - std::cerr << "Error Byte:" << i << " is different"; - std::cerr << std::endl; - } - } - } - if (diffCount) - { - std::cerr << "Errors (" << diffCount << "/" << size << ") in tranmission ... Exiting!"; - std::cerr << std::endl; - exit(1); - } - - int ts_end = time(NULL); - double rough_rate = size / (double) (ts_end - ts_start); - - std::cerr << "Successful Data Tranmission: " << size << " in " << ts_end-ts_start << " secs"; - std::cerr << std::endl; - std::cerr << "Approximate Rate: " << rough_rate / 1000.0 << " kbytes/sec"; - std::cerr << std::endl; - - return 1; -} - - - - - - - - diff --git a/libretroshare/src/tests/tcponudp/largefile_tou.cc b/libretroshare/src/tests/tcponudp/largefile_tou.cc deleted file mode 100644 index 1bf0bebca..000000000 --- a/libretroshare/src/tests/tcponudp/largefile_tou.cc +++ /dev/null @@ -1,502 +0,0 @@ -/* - * "$Id: largefile_tou.cc,v 1.2 2007-02-18 21:46:50 rmf24 Exp $" - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2004-2006 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - - -/********************************************************** - * This test is designed to test large data blocks/files - * running to tou. Currently we see occasional errors - * every 1/2 -> 1 MB of transfer.... - * - * This test will continually fill the output buffer, - * and then empty the receive one. To ensure the - * whole system gets a good workout. - * - */ - -#include - -// for printing sockaddr -#include "udplayer.h" - -#include "tou.h" -#include "tou_net.h" - -#include -#include -#include - -int setup_socket(struct sockaddr_in addr); -int connect_socket_pair(int fd1, int fd2, - struct sockaddr_in addr1, struct sockaddr_in addr2); -int send_data_via_pair(int sockfd1, int sockfd2, char *data, int size); - -void usage(char *name) -{ - std::cerr << "Usage: " << name; - std::cerr << " [-pco] "; - std::cerr << " "; - std::cerr << std::endl; - exit(1); - return; -} - -int main(int argc, char **argv) -{ - int c; - bool isProxy = false; - bool toConnect = false; - bool stayOpen = false; - int i,j; - - while(-1 != (c = getopt(argc, argv, "pco"))) - { - switch (c) - { - case 'p': - isProxy = true; - break; - case 'c': - toConnect = true; - break; - case 'o': - stayOpen = true; - break; - default: - usage(argv[0]); - break; - } - } - - if (argc-optind < 4) - { - usage(argv[0]); - return 1; - } - - tounet_init(); - - - /* setup the local/remote addresses. - */ - struct sockaddr_in laddr; - struct sockaddr_in raddr; - - laddr.sin_family = AF_INET; - raddr.sin_family = AF_INET; - - if ((!tounet_inet_aton(argv[optind], &(laddr.sin_addr))) || - (!tounet_inet_aton(argv[optind+2], &(raddr.sin_addr)))) - { - std::cerr << "Invalid addresses!" << std::endl; - usage(argv[0]); - } - - unsigned short laddr_port = atoi(argv[optind+1]); - unsigned short raddr_port = atoi(argv[optind+3]); - - for(i = 0; i < 10; i++) - { - laddr.sin_port = htons(laddr_port); - raddr.sin_port = htons(raddr_port); - //laddr.sin_port = htons(laddr_port + i); - //raddr.sin_port = htons(raddr_port + i); - - std::cerr << "Interation: " << i << std::endl; - - - /* setup the sockets */ - int sockfd1 = setup_socket(laddr); - int sockfd2 = setup_socket(raddr); - - if ((sockfd1 < 0) || (sockfd2 < 0)) - { - std::cerr << "Failed to setup sockets!"; - std::cerr << std::endl; - return -1; - } - - std::cerr << "Local Address: " << laddr; - std::cerr << " fd: " << sockfd1 << std::endl; - std::cerr << "Remote Address: " << raddr; - std::cerr << " fd: " << sockfd2 << std::endl; - - /* connect */ - int err = connect_socket_pair(sockfd1, sockfd2, laddr, raddr); - if (err < 0) - { - std::cerr << "Failed to connect sockets!"; - std::cerr << std::endl; - return -1; - } - - /* send the data */ - int size = 3093237; - char rnddata[size]; - - int data_loops = (i+1) * (i+1); - for(int k = 0; k < data_loops; k++) - { - std::cerr << "Send Iteration: " << k+1 << " of " << data_loops << std::endl; - for(j = 0; j < size; j++) - { - rnddata[j] = (unsigned char) (255.0 * - rand() / (RAND_MAX + 1.0)); - } - send_data_via_pair(sockfd1, sockfd2, rnddata, size); - std::cerr << "Send Iteration: " << k+1 << " of " << data_loops << std::endl; - sleep(2); - } - - std::cerr << "Completed Successful transfer of " << size * data_loops << " bytes"; - std::cerr << std::endl; - - sleep(10); - std::cerr << "closing sockfd1: " << sockfd1 << std::endl; - tou_close(sockfd1); - - std::cerr << "closing sockfd2: " << sockfd2 << std::endl; - tou_close(sockfd2); - - - } - return 1; -} - -int setup_socket(struct sockaddr_in addr) -{ - int sockfd = tou_socket(PF_INET, SOCK_STREAM, 0); - - if (sockfd <= 0) - { - std::cerr << "Failed to open socket!: "; - std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl; - return -1; - } - - std::cerr << "Socket Created: " << sockfd << std::endl; - - int err = tou_bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)); - - if (err < 0) - { - std::cerr << "Error: Cannot bind socket: "; - std::cerr << err << std::endl; - return -1; - } - - std::cerr << "Socket1 Bound to: " << addr << std::endl; - return sockfd; -} - -int connect_socket_pair(int fd1, int fd2, - struct sockaddr_in addr1, struct sockaddr_in addr2) -{ - std::cerr << "Socket2 Listening " << std::endl; - /* listen */ - int err = tou_listenfor(fd2, (struct sockaddr *) &addr1, sizeof(addr1)); - int err_num; - - if (err < 0) - { - err_num = tou_errno(fd2); - if (err_num != EINPROGRESS) - { - std::cerr << "Cannot Listen!: " << err_num << std::endl; - return -1; - } - } - - - std::cerr << "Socket1 Connecting to: " << addr2 << std::endl; - err = tou_connect(fd1, (struct sockaddr *) &addr2, sizeof(addr2), 30); - if (err < 0) - { - err_num = tou_errno(fd1); - if (err_num != EINPROGRESS) - { - std::cerr << "Cannot Connect!: " << err_num << std::endl; - return -1; - } - } - - bool sock1Connected = false; - bool sock2Connected = false; - - while((!sock1Connected) || (!sock2Connected)) - { - sleep(1); - - /* sock1 */ - if((!sock1Connected) && (0 == (err = tou_connected(fd1)))) - { - std::cerr << "Waiting for Connect (Sock1)!" << std::endl; - } - - if ((!sock1Connected) && (err < 0)) - { - std::cerr << "Connect Failed" << std::endl; - return 1; - } - else if (!sock1Connected) - { - // else connected! - sock1Connected = true; - } - - /* accept - sock2 */ - struct sockaddr_in inaddr; - socklen_t addrlen = sizeof(inaddr); - int nsock = -1; - - if ((!sock2Connected) && (0 > (nsock = tou_accept(fd2, - (struct sockaddr *) &inaddr, &addrlen)))) - { - errno = tou_errno(fd2); - if (errno != EAGAIN) - { - std::cerr << "Cannot Connect!: " << errno << std::endl; - return 1; - } - else - { - std::cerr << "Waiting for Connect (Sock2)!" << std::endl; - } - } - else if (nsock > 0) - { - /* connected */ - sock2Connected = true; - fd2 = nsock; - std::cerr << "Socket Accepted from: " << inaddr << std::endl; - } - } - - std::cerr << "Socket Connected" << std::endl; - - return 1; -} - - -/* This transmits into sockfd1, and check to see that we recv - * it back from sockfd2 - */ - -int send_data_via_pair(int sockfd1, int sockfd2, char *data, int size) -{ - /* what we recvd */ - char *recvd = (char *) malloc(size * 2); - int recvdsize = 0; - int sent = 0; - int sendsize = 0; - - int ts_start = time(NULL); - - int minsends = 100; /* min of 100 sends to complete all data */ - /* ensure we don't end up sending nothing */ - if (minsends * 10 > size) - { - minsends = size / 10; - } - - bool doneWrite = false; - bool doneRead = false; - - int maxtransfer = (int) (size / minsends) + (int) (((float) (size / minsends)) * - (rand() / (RAND_MAX + 1.0))); - /* allow the transfer ratio read/write to vary between 0.4->1,5. */ - double tf_ratio = 0.4 + 1.1 * (rand() / (RAND_MAX + 1.0)); - - while((!doneWrite) || (!doneRead)) - { - /* have a little break */ - //usleep(10000); /* 0.01 sec */ - usleep(20000); /* 0.02 sec */ - //usleep(250000); /* 0.25 sec */ - //usleep(500000); /* 0.50 sec */ - /* decide how much to send */ - sendsize = (int) (((float) (maxtransfer)) * - (rand() / (RAND_MAX + 1.0))); - - /* limit send */ - if (sent + sendsize > size) - { - std::cerr << "Last WRITE!" << std::endl; - sendsize = size - sent; - } - /* if we've finished */ - if (sent == size) - { - /* eof */ - std::cerr << "Write Done!" << std::endl; - doneWrite = true; - sendsize = 0; - } - - /* now we write */ - if ((sendsize > 0)&&(-1==tou_write(sockfd1,&(data[sent]),sendsize))) - { - std::cerr << "Write Error: " << tou_errno(sockfd1) << std::endl; - if (tou_errno(sockfd1) != EAGAIN) - { - std::cerr << "FATAL ERROR ending transfer" << std::endl; - doneRead = true; - doneWrite = true; - } - - } - else - { - sent += sendsize; - } - - int ret = 0; - - // read size about 1/4 of write to exercise the buffers. - int readsize = (int) (((float) (maxtransfer)) * tf_ratio * - (rand() / (RAND_MAX + 1.0))); - - if (readsize > size - recvdsize) - { - std::cerr << "Last READ!" << std::endl; - readsize = size - recvdsize; - } - - if (0 < (ret = tou_read(sockfd2, &(recvd[recvdsize]), readsize))) - { - std::cerr << "TF(" << ret << ")" << std::endl; - - /* check the data at this point */ - - int i; - int diffCount = 0; - int init_err = 0; - for(i = 0; i < ret; i++) - { - if (recvd[recvdsize + i] != data[recvdsize + i]) - { - if (!diffCount) - { - init_err = i; - } - diffCount++; - if (diffCount < 10) - { - std::cerr << "Error Byte:" << recvdsize + i << " is different"; - std::cerr << std::endl; - } - } - } - if (diffCount) - { - std::cerr << "Errors (" << diffCount << "/" << ret << ") in read, "; - std::cerr << std::endl; - std::cerr << " At Blk Start: " << recvdsize << " offset: " << init_err; - std::cerr << " ==> At index: " << recvdsize + init_err << "... Exiting!"; - std::cerr << std::endl; - exit(1); - } - else - { - std::cerr << "Checked (" << recvdsize << "+ 0 => " << ret << ") Okay" << std::endl; - } - - recvdsize += ret; - } - else if (ret == 0) - { - //doneRead = true; - std::cerr << "Read Done? (ret:0)" << std::endl; - } - else - { - std::cerr << "Read Error: " << tou_errno(sockfd2) << std::endl; - std::cerr << "Read " << recvdsize << "/" << size; - std::cerr << " attempted: " << readsize << std::endl; - if (tou_errno(sockfd2) != EAGAIN) - { - std::cerr << "FATAL ERROR ending transfer" << std::endl; - doneRead = true; - doneWrite = true; - } - - } - - if (recvdsize == size) - { - doneRead = true; - std::cerr << "Read Done!" << std::endl; - } - - } - - /* we have transmitted it all, so - * check the data - */ - - int i; - int diffCount = 0; - for(i = 0; i < size; i++) - { - if (recvd[i] != data[i]) - { - diffCount++; - if (diffCount < 10) - { - std::cerr << "Error Byte:" << i << " is different"; - std::cerr << std::endl; - } - } - } - if (diffCount) - { - std::cerr << "Errors (" << diffCount << "/" << size << ") in tranmission ... Exiting!"; - std::cerr << std::endl; - exit(1); - } - - int ts_end = time(NULL); - double rough_rate = size / (double) (ts_end - ts_start); - - std::cerr << "Successful Data Tranmission: " << size << " in " << ts_end-ts_start << " secs"; - std::cerr << std::endl; - std::cerr << "Approximate Rate: " << rough_rate / 1000.0 << " kbytes/sec"; - std::cerr << std::endl; - std::cerr << "Transfer Ratio: " << tf_ratio; - std::cerr << std::endl; - - free(recvd); - - return 1; -} - - - - - - - - diff --git a/libretroshare/src/tests/tcponudp/pair_tou.cc b/libretroshare/src/tests/tcponudp/pair_tou.cc deleted file mode 100644 index 945c6ac31..000000000 --- a/libretroshare/src/tests/tcponudp/pair_tou.cc +++ /dev/null @@ -1,508 +0,0 @@ -/* - * "$Id: pair_tou.cc,v 1.3 2007-02-18 21:46:50 rmf24 Exp $" - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2004-2006 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - - -#include -#include - -//#define USE_TCP_SOCKET - -// for printing sockaddr -#include "udp/udpstack.h" - -#ifndef USE_TCP_SOCKET - #include "tcponudp/tou.h" - #include "tcponudp/udppeer.h" -#endif - -#include "util/bdnet.h" - -#include -#include -#include - - -/* This is a simple test to ensure that the tou behaviour - * is almost identical to a standard tcp socket. - * - * In this version we open 2 sockets, and attempt to - * communicate with ourselves.... - * - */ - -int Check_Socket(int fd); - -void usage(char *name) -{ - std::cerr << "Usage: " << name; - std::cerr << " [-pco] "; - std::cerr << " "; - std::cerr << std::endl; - exit(1); - return; -} - -int main(int argc, char **argv) -{ - int c; - bool isProxy = false; - bool toConnect = false; - bool stayOpen = false; - - int totalwbytes = 0; - int totalrbytes = 0; - - while(-1 != (c = getopt(argc, argv, "pco"))) - { - switch (c) - { - case 'p': - isProxy = true; - break; - case 'c': - toConnect = true; - break; - case 'o': - stayOpen = true; - break; - default: - usage(argv[0]); - break; - } - } - - if (argc-optind < 4) - { - usage(argv[0]); - return 1; - } - - /* setup the local/remote addresses. - */ - struct sockaddr_in laddr; - struct sockaddr_in raddr; - - laddr.sin_family = AF_INET; - raddr.sin_family = AF_INET; - - if ((!bdnet_inet_aton(argv[optind], &(laddr.sin_addr))) || - (!bdnet_inet_aton(argv[optind+2], &(raddr.sin_addr)))) - { - std::cerr << "Invalid addresses!" << std::endl; - usage(argv[0]); - } - - laddr.sin_port = htons(atoi(argv[optind+1])); - raddr.sin_port = htons(atoi(argv[optind+3])); - - std::cerr << "Local Address: " << laddr << std::endl; - std::cerr << "Remote Address: " << raddr << std::endl; - - UdpStack *udpStack1 = new UdpStack(laddr); - UdpStack *udpStack2 = new UdpStack(raddr); - - UdpSubReceiver *udpReceivers[2]; - int udpTypes[2]; - - udpReceivers[0] = new UdpPeerReceiver(udpStack1); - udpTypes[0] = TOU_RECEIVER_TYPE_UDPPEER; - udpStack1->addReceiver(udpReceivers[0]); - - udpReceivers[1] = new UdpPeerReceiver(udpStack2); - udpTypes[1] = TOU_RECEIVER_TYPE_UDPPEER; - udpStack2->addReceiver(udpReceivers[1]); - - tou_init((void **) udpReceivers, udpTypes, 2); - - -#ifdef USE_TCP_SOCKET - int sockfd = socket(PF_INET, SOCK_STREAM, 0); - int sockfd2 = socket(PF_INET, SOCK_STREAM, 0); -#else - int sockfd = tou_socket(0, TOU_RECEIVER_TYPE_UDPPEER, 0); - int sockfd2 = tou_socket(1, TOU_RECEIVER_TYPE_UDPPEER, 0); -#endif - if ((sockfd <= 0) || (sockfd2 <= 0)) - { - std::cerr << "Failed to open socket!: "; -#ifdef USE_TCP_SOCKET - std::cerr << "Socket Error:" << errno << std::endl; -#else - std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl; - std::cerr << "Socket Error:" << tou_errno(sockfd2) << std::endl; -#endif - return -1; - } - std::cerr << "Sockets Created: " << sockfd << " & " << sockfd2 << std::endl; - - - /* make nonblocking */ -#ifdef USE_TCP_SOCKET - int err = fcntl(sockfd,F_SETFD,O_NONBLOCK); - int err2 = fcntl(sockfd2,F_SETFD,O_NONBLOCK); -#else - int err = 0; - int err2 = 0; -#endif - if ((err < 0) || (err2 < 0)) - { - std::cerr << "Error: Cannot make socket NON-Blocking: "; - std::cerr << err << std::endl; - return -1; - } - - std::cerr << "Socket Non-Blocking" << std::endl; - -#ifdef USE_TCP_SOCKET - err = bind(sockfd, (struct sockaddr *) &laddr, sizeof(laddr)); - err2 = bind(sockfd2, (struct sockaddr *) &raddr, sizeof(raddr)); - if ((err < 0) || (err2 < 0)) - { - std::cerr << "Error: Cannot bind socket: "; - std::cerr << err << std::endl; - return -1; - } -#else - // No more Bind in tou. - //err = tou_bind(sockfd, (struct sockaddr *) &laddr, sizeof(laddr)); - //err2 = tou_bind(sockfd2, (struct sockaddr *) &raddr, sizeof(raddr)); -#endif - - std::cerr << "Socket1 Bound to: " << laddr << std::endl; - std::cerr << "Socket2 Bound to: " << raddr << std::endl; - - // listening. - if (1) // socket2. - { - std::cerr << "Socket2 Listening " << std::endl; - /* listen */ -#ifdef USE_TCP_SOCKET - err = listen(sockfd2, 1); -#else - err = tou_listenfor(sockfd2, - (struct sockaddr *) &laddr, sizeof(laddr)); -#endif - } - - - if (1) // only one program. - { - std::cerr << "Socket1 Connecting to: " << raddr << std::endl; -#ifdef USE_TCP_SOCKET - err = connect(sockfd, (struct sockaddr *) &raddr, sizeof(raddr)); -#else - err = tou_connect(sockfd, (struct sockaddr *) &raddr, sizeof(raddr), 30); -#endif - if (err < 0) - { -#ifndef USE_TCP_SOCKET - errno = tou_errno(sockfd); -#endif - if (errno != EINPROGRESS) - { - std::cerr << "Cannot Connect!: " << errno << std::endl; - return 1; - } - } - } - - bool sock1Connected = false; - bool sock2Connected = false; - - while((!sock1Connected) || (!sock2Connected)) - { - sleep(1); - - - /* sock1 */ -#ifdef USE_TCP_SOCKET - if((!sock1Connected) && (0 == (err = Check_Socket(sockfd)))) -#else - if((!sock1Connected) && (0 == (err = tou_connected(sockfd)))) -#endif - { - std::cerr << "Waiting for Connect (Sock1)!" << std::endl; - } - if ((!sock1Connected) && (err < 0)) - { - std::cerr << "Connect Failed" << std::endl; - return 1; - } - else if (!sock1Connected) - { - // else connected! - sock1Connected = true; - } - - /* accept - sock2 */ - struct sockaddr_in inaddr; - socklen_t addrlen = sizeof(inaddr); - int nsock = -1; - -#ifdef USE_TCP_SOCKET - if ((!sock2Connected) && (0 > (nsock = accept(sockfd2, - (struct sockaddr *) &inaddr, &addrlen)))) -#else - if ((!sock2Connected) && (0 > (nsock = tou_accept(sockfd2, - (struct sockaddr *) &inaddr, &addrlen)))) -#endif - { -#ifndef USE_TCP_SOCKET - errno = tou_errno(sockfd2); -#endif - if (errno != EAGAIN) - { - std::cerr << "Cannot Connect!: " << errno << std::endl; - return 1; - } - else - { - std::cerr << "Waiting for Connect (Sock2)!" << std::endl; - } - } - else if (nsock > 0) - { - /* connected */ - sock2Connected = true; - sockfd2 = nsock; - std::cerr << "Socket Accepted from: " << inaddr << std::endl; - } - } - - std::cerr << "Socket Connected" << std::endl; - - /* send data */ - int bufsize = 1511; - char buffer[bufsize]; - char data[bufsize]; - int readsize = 0; - - bdnet_fcntl(0, F_SETFL, O_NONBLOCK); - bdnet_fcntl(1,F_SETFL,O_NONBLOCK); - - bool doneWrite = false; - bool doneRead = false; - bool blockread = false; - while((!doneWrite) || (!doneRead)) - { - /* read -> write_socket... */ - sleep(1); - if (blockread != true) - { - readsize = read(0, buffer, bufsize); - } - if (readsize == 0) - { - /* eof */ - doneWrite = true; - } - /* now we write */ -#ifdef USE_TCP_SOCKET - if ((readsize > 0) && (-1 == write(sockfd, buffer, readsize))) -#else - if ((readsize > 0) && (-1 == tou_write(sockfd, buffer, readsize))) -#endif - { - //std::cerr << "Blocked Write!" << std::endl; -#ifndef USE_TCP_SOCKET - //std::cerr << "Error: " << tou_errno(sockfd) << std::endl; -#endif - blockread = true; - } - else - { - blockread = false; - totalwbytes += readsize; - } - - int ret = 0; -#ifdef USE_TCP_SOCKET - if (0 < (ret = read(sockfd2, data, bufsize))) -#else - if (0 < (ret = tou_read(sockfd2, data, bufsize))) -#endif - - { - std::cerr << "TF(" << ret << ")" << std::endl; - write(1, data, ret); - totalrbytes += ret; - } - else if (ret == 0) - { - doneRead = true; - } - else - { - //std::cerr << "Blocked Read!" << std::endl; -#ifndef USE_TCP_SOCKET - //std::cerr << "Error: " << tou_errno(sockfd) << std::endl; -#endif - } - - - } - -#ifdef USE_TCP_SOCKET - close(sockfd); - close(sockfd2); -#else - /* this is blocking??? */ - tou_close(sockfd); - tou_close(sockfd2); -#endif - - std::cerr << "Transfer Complete: " << totalwbytes << " bytes"; - std::cerr << std::endl; - return 1; -} - -#ifdef USE_TCP_SOCKET - - -int Check_Socket(int fd) -{ - std::cerr << "Check_Socket()" << std::endl; - - std::cerr << "1) Checking with Select()" << std::endl; - - fd_set ReadFDs, WriteFDs, ExceptFDs; - FD_ZERO(&ReadFDs); - FD_ZERO(&WriteFDs); - FD_ZERO(&ExceptFDs); - - FD_SET(fd, &ReadFDs); - FD_SET(fd, &WriteFDs); - FD_SET(fd, &ExceptFDs); - - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 0; - - int sr = 0; - if (0 > (sr = select(fd + 1, - &ReadFDs, &WriteFDs, &ExceptFDs, &timeout))) - { - std::cerr << "Check_Socket() Select ERROR: " << sr << std::endl; - return -1; - } - - if (FD_ISSET(fd, &ExceptFDs)) - { - std::cerr << "Check_Socket() Exception on socket!" << std::endl; - return -1; - } - - if (FD_ISSET(fd, &WriteFDs)) - { - std::cerr << "Check_Socket() Can Write!" << std::endl; - } - else - { - // not ready return 0; - std::cerr << "Check_Socket() Cannot Write!" << std::endl; - std::cerr << "Check_Socket() Socket Not Ready!" << std::endl; - return 0; - } - - if (FD_ISSET(fd, &ReadFDs)) - { - std::cerr << "Check_Socket() Can Read!" << std::endl; - } - else - { - std::cerr << "Check_Socket() Cannot Read!" << std::endl; - std::cerr << "Check_Socket() Socket Not Ready!" << std::endl; - return 0; - } - - std::cerr << "Select() Tests indicate Socket Good!" << std::endl; - std::cerr << "2) Checking with getsockopt()" << std::endl; - - int err = 1; - socklen_t optlen = 4; - if (0==getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &optlen)) - { - std::cerr << "Check_Socket() getsockopt returned :" << err; - std::cerr << ", optlen:" << optlen; - std::cerr << std::endl; - - if (err == 0) - { - std::cerr << "Check_Socket() getsockopt"; - std::cerr << " Indicates TCP Connection Complete:"; - std::cerr << std::endl; - return 1; - } - else if (err == EINPROGRESS) - { - std::cerr << "Check_Socket() getsockopt"; - std::cerr << " Indicates TCP Connection INPROGRESS"; - std::cerr << std::endl; - return 0; - } - else if ((err == ENETUNREACH) || (err == ETIMEDOUT)) - { - std::cerr << "Check_Socket() getsockopt"; - std::cerr << " Indicates TCP Connection ENETUNREACH/ETIMEDOUT"; - std::cerr << std::endl; - return -1; - } - else if ((err == EHOSTUNREACH) || (err == EHOSTDOWN)) - { - std::cerr << "Check_Socket() getsockopt"; - std::cerr << " Indicates TCP Connection ENETUNREACH/ETIMEDOUT"; - std::cerr << std::endl; - return -1; - } - else - { - std::cerr << "Check_Socket() getsockopt"; - std::cerr << " Indicates Other Error: " << err; - std::cerr << std::endl; - return -1; - } - - - } - else - { - std::cerr << "Check_Socket() getsockopt"; - std::cerr << " FAILED "; - std::cerr << std::endl; - return -1; - } -} - - -#else - -int Check_Socket(int fd) -{ - return 0; -} - -#endif diff --git a/libretroshare/src/tests/tcponudp/reset_tou.cc b/libretroshare/src/tests/tcponudp/reset_tou.cc deleted file mode 100644 index 3faa8851c..000000000 --- a/libretroshare/src/tests/tcponudp/reset_tou.cc +++ /dev/null @@ -1,453 +0,0 @@ -/* - * "$Id: reset_tou.cc,v 1.4 2007-02-18 21:46:50 rmf24 Exp $" - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2004-2006 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - - -/********************************************************** - * This test is designed to ensure that tou networking - * can be reset, and restarted. - * - */ - -#include - -// for printing sockaddr -#include "udplayer.h" - -#include "tou.h" -#include "tou_net.h" - -#include -#include -#include - - -/* This is a simple test to ensure that the tou behaviour - * is almost identical to a standard tcp socket. - * - * In this version we open 2 sockets, and attempt to - * communicate with ourselves.... - * - */ - -int setup_socket(struct sockaddr_in addr); -int connect_socket_pair(int fd1, int fd2, - struct sockaddr_in addr1, struct sockaddr_in addr2); -int send_data_via_pair(int sockfd1, int sockfd2, char *data, int size); - -void usage(char *name) -{ - std::cerr << "Usage: " << name; - std::cerr << " [-pco] "; - std::cerr << " "; - std::cerr << std::endl; - exit(1); - return; -} - -int main(int argc, char **argv) -{ - int c; - bool isProxy = false; - bool toConnect = false; - bool stayOpen = false; - int i,j; - - while(-1 != (c = getopt(argc, argv, "pco"))) - { - switch (c) - { - case 'p': - isProxy = true; - break; - case 'c': - toConnect = true; - break; - case 'o': - stayOpen = true; - break; - default: - usage(argv[0]); - break; - } - } - - if (argc-optind < 4) - { - usage(argv[0]); - return 1; - } - - tounet_init(); - - - /* setup the local/remote addresses. - */ - struct sockaddr_in laddr; - struct sockaddr_in raddr; - - laddr.sin_family = AF_INET; - raddr.sin_family = AF_INET; - - if ((!tounet_inet_aton(argv[optind], &(laddr.sin_addr))) || - (!tounet_inet_aton(argv[optind+2], &(raddr.sin_addr)))) - { - std::cerr << "Invalid addresses!" << std::endl; - usage(argv[0]); - } - - unsigned short laddr_port = atoi(argv[optind+1]); - unsigned short raddr_port = atoi(argv[optind+3]); - - for(i = 0; i < 10; i++) - { - laddr.sin_port = htons(laddr_port); - raddr.sin_port = htons(raddr_port); - //laddr.sin_port = htons(laddr_port + i); - //raddr.sin_port = htons(raddr_port + i); - - std::cerr << "Interation: " << i << std::endl; - - - /* setup the sockets */ - int sockfd1 = setup_socket(laddr); - int sockfd2 = setup_socket(raddr); - - if ((sockfd1 < 0) || (sockfd2 < 0)) - { - std::cerr << "Failed to setup sockets!"; - std::cerr << std::endl; - return -1; - } - - std::cerr << "Local Address: " << laddr; - std::cerr << " fd: " << sockfd1 << std::endl; - std::cerr << "Remote Address: " << raddr; - std::cerr << " fd: " << sockfd2 << std::endl; - - /* connect */ - int err = connect_socket_pair(sockfd1, sockfd2, laddr, raddr); - if (err < 0) - { - std::cerr << "Failed to connect sockets!"; - std::cerr << std::endl; - return -1; - } - - /* send the data */ - int size = 102400; - char rnddata[size]; - - int data_loops = (i+1) * (i+1); - for(int k = 0; k < data_loops; k++) - { - std::cerr << "Send Iteration: " << k+1 << " of " << data_loops << std::endl; - for(j = 0; j < size; j++) - { - rnddata[j] = (unsigned char) (255.0 * - rand() / (RAND_MAX + 1.0)); - } - send_data_via_pair(sockfd1, sockfd2, rnddata, size); - std::cerr << "Send Iteration: " << k+1 << " of " << data_loops << std::endl; - sleep(2); - } - - std::cerr << "Completed Successful transfer of " << size * data_loops << " bytes"; - std::cerr << std::endl; - - sleep(10); - std::cerr << "closing sockfd1: " << sockfd1 << std::endl; - tou_close(sockfd1); - - std::cerr << "closing sockfd2: " << sockfd2 << std::endl; - tou_close(sockfd2); - - - } - return 1; -} - -int setup_socket(struct sockaddr_in addr) -{ - int sockfd = tou_socket(PF_INET, SOCK_STREAM, 0); - - if (sockfd <= 0) - { - std::cerr << "Failed to open socket!: "; - std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl; - return -1; - } - - std::cerr << "Socket Created: " << sockfd << std::endl; - - int err = tou_bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)); - - if (err < 0) - { - std::cerr << "Error: Cannot bind socket: "; - std::cerr << err << std::endl; - return -1; - } - - std::cerr << "Socket1 Bound to: " << addr << std::endl; - return sockfd; -} - -int connect_socket_pair(int fd1, int fd2, - struct sockaddr_in addr1, struct sockaddr_in addr2) -{ - std::cerr << "Socket2 Listening " << std::endl; - /* listen */ - int err = tou_listenfor(fd2, (struct sockaddr *) &addr1, sizeof(addr1)); - int err_num; - - if (err < 0) - { - err_num = tou_errno(fd2); - if (err_num != EINPROGRESS) - { - std::cerr << "Cannot Listen!: " << err_num << std::endl; - return -1; - } - } - - - std::cerr << "Socket1 Connecting to: " << addr2 << std::endl; - err = tou_connect(fd1, (struct sockaddr *) &addr2, sizeof(addr2), 30); - if (err < 0) - { - err_num = tou_errno(fd1); - if (err_num != EINPROGRESS) - { - std::cerr << "Cannot Connect!: " << err_num << std::endl; - return -1; - } - } - - bool sock1Connected = false; - bool sock2Connected = false; - - while((!sock1Connected) || (!sock2Connected)) - { - sleep(1); - - /* sock1 */ - if((!sock1Connected) && (0 == (err = tou_connected(fd1)))) - { - std::cerr << "Waiting for Connect (Sock1)!" << std::endl; - } - - if ((!sock1Connected) && (err < 0)) - { - std::cerr << "Connect Failed" << std::endl; - return 1; - } - else if (!sock1Connected) - { - // else connected! - sock1Connected = true; - } - - /* accept - sock2 */ - struct sockaddr_in inaddr; - socklen_t addrlen = sizeof(inaddr); - int nsock = -1; - - if ((!sock2Connected) && (0 > (nsock = tou_accept(fd2, - (struct sockaddr *) &inaddr, &addrlen)))) - { - errno = tou_errno(fd2); - if (errno != EAGAIN) - { - std::cerr << "Cannot Connect!: " << errno << std::endl; - return 1; - } - else - { - std::cerr << "Waiting for Connect (Sock2)!" << std::endl; - } - } - else if (nsock > 0) - { - /* connected */ - sock2Connected = true; - fd2 = nsock; - std::cerr << "Socket Accepted from: " << inaddr << std::endl; - } - } - - std::cerr << "Socket Connected" << std::endl; - - return 1; -} - - -/* This transmits into sockfd1, and check to see that we recv - * it back from sockfd2 - */ - -int send_data_via_pair(int sockfd1, int sockfd2, char *data, int size) -{ - /* what we recvd */ - char *recvd = (char *) malloc(size * 2); - int recvdsize = 0; - int sent = 0; - int sendsize = 0; - - int ts_start = time(NULL); - - int minsends = 100; /* min of 100 sends to complete all data */ - /* ensure we don't end up sending nothing */ - if (minsends * 10 > size) - { - minsends = size / 10; - } - - bool doneWrite = false; - bool doneRead = false; - while((!doneWrite) || (!doneRead)) - { - /* have a little break */ - //usleep(10000); /* 0.01 sec */ - //usleep(250000); /* 0.25 sec */ - usleep(500000); /* 0.50 sec */ - /* decide how much to send */ - sendsize = (int) (((float) (size / minsends)) * - (rand() / (RAND_MAX + 1.0))); - - /* limit send */ - if (sent + sendsize > size) - { - sendsize = size - sent; - } - /* if we've finished */ - if (sent == size) - { - /* eof */ - std::cerr << "Write Done!" << std::endl; - doneWrite = true; - sendsize = 0; - } - - /* now we write */ - if ((sendsize > 0)&&(-1==tou_write(sockfd1,&(data[sent]),sendsize))) - { - std::cerr << "Write Error: " << tou_errno(sockfd1) << std::endl; - if (tou_errno(sockfd1) != EAGAIN) - { - std::cerr << "FATAL ERROR ending transfer" << std::endl; - doneRead = true; - doneWrite = true; - } - - } - else - { - sent += sendsize; - } - - int ret = 0; - int readsize = (int) (((float) (size / minsends)) * - (rand() / (RAND_MAX + 1.0))); - - if (readsize > size - recvdsize) - readsize = size - recvdsize; - - if (0 < (ret = tou_read(sockfd2, &(recvd[recvdsize]), readsize))) - { - std::cerr << "TF(" << ret << ")" << std::endl; - recvdsize += ret; - } - else if (ret == 0) - { - doneRead = true; - std::cerr << "Read Done! (ret:0)" << std::endl; - } - else - { - std::cerr << "Read Error: " << tou_errno(sockfd2) << std::endl; - std::cerr << "Read " << recvdsize << "/" << size; - std::cerr << " attempted: " << readsize << std::endl; - if (tou_errno(sockfd2) != EAGAIN) - { - std::cerr << "FATAL ERROR ending transfer" << std::endl; - doneRead = true; - doneWrite = true; - } - - } - - if (recvdsize == size) - { - doneRead = true; - std::cerr << "Read Done!" << std::endl; - } - - } - - /* we have transmitted it all, so - * check the data - */ - - int i; - int diffCount = 0; - for(i = 0; i < size; i++) - { - if (recvd[i] != data[i]) - { - diffCount++; - if (diffCount < 10) - { - std::cerr << "Error Byte:" << i << " is different"; - std::cerr << std::endl; - } - } - } - if (diffCount) - { - std::cerr << "Errors (" << diffCount << "/" << size << ") in tranmission ... Exiting!"; - std::cerr << std::endl; - exit(1); - } - - int ts_end = time(NULL); - double rough_rate = size / (double) (ts_end - ts_start); - - std::cerr << "Successful Data Tranmission: " << size << " in " << ts_end-ts_start << " secs"; - std::cerr << std::endl; - std::cerr << "Approximate Rate: " << rough_rate / 1000.0 << " kbytes/sec"; - std::cerr << std::endl; - - return 1; -} - - - - - - - - diff --git a/libretroshare/src/tests/tcponudp/stacks_tou.cc b/libretroshare/src/tests/tcponudp/stacks_tou.cc deleted file mode 100644 index ece3915b4..000000000 --- a/libretroshare/src/tests/tcponudp/stacks_tou.cc +++ /dev/null @@ -1,354 +0,0 @@ -/* - * "$Id: pair_tou.cc,v 1.3 2007-02-18 21:46:50 rmf24 Exp $" - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2004-2006 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - - -#include -#include - -// for printing sockaddr -#include "udp/udpstack.h" - -#include "tcponudp/tou.h" -#include "tcponudp/udppeer.h" -#include "tcponudp/udprelay.h" - -#include "util/bdnet.h" - -#include "util/rsrandom.h" - -#include -#include -#include - - -/* - * This test creates the same stacks as are used in RS. - * This additionally tests the "checkFns" for the other UdpReceivers, which could potentially be modifying the data. - * obviously they shouldn't! - * - */ - -void usage(char *name) -{ - std::cerr << "Usage: " << name; - std::cerr << " [-pco] "; - std::cerr << " "; - std::cerr << std::endl; - exit(1); - return; -} - -int main(int argc, char **argv) -{ - int c; - bool isProxy = false; - bool toConnect = false; - bool stayOpen = false; - - int totalwbytes = 0; - int totalrbytes = 0; - - while(-1 != (c = getopt(argc, argv, "pco"))) - { - switch (c) - { - case 'p': - isProxy = true; - break; - case 'c': - toConnect = true; - break; - case 'o': - stayOpen = true; - break; - default: - usage(argv[0]); - break; - } - } - - if (argc-optind < 4) - { - usage(argv[0]); - return 1; - } - - /* setup the local/remote addresses. - */ - struct sockaddr_in laddr; - struct sockaddr_in raddr; - - laddr.sin_family = AF_INET; - raddr.sin_family = AF_INET; - - if ((!bdnet_inet_aton(argv[optind], &(laddr.sin_addr))) || - (!bdnet_inet_aton(argv[optind+2], &(raddr.sin_addr)))) - { - std::cerr << "Invalid addresses!" << std::endl; - usage(argv[0]); - } - - laddr.sin_port = htons(atoi(argv[optind+1])); - raddr.sin_port = htons(atoi(argv[optind+3])); - - std::cerr << "Local Address: " << laddr << std::endl; - std::cerr << "Remote Address: " << raddr << std::endl; - - std::cerr << "Creating with Lossy Udp Layers for further testing"; - std::cerr << std::endl; - - UdpStack *udpStack1 = new UdpStack(UDP_TEST_LOSSY_LAYER,laddr); - UdpStack *udpStack2 = new UdpStack(UDP_TEST_LOSSY_LAYER,raddr); - - UdpSubReceiver *udpReceivers[4]; - int udpTypes[4]; - - // NOTE DHT is too hard to add at the moment. - - UdpRelayReceiver *mRelay1 = new UdpRelayReceiver(udpStack1); - udpReceivers[1] = mRelay1; - udpTypes[1] = TOU_RECEIVER_TYPE_UDPRELAY; - udpStack1->addReceiver(udpReceivers[1]); - - udpReceivers[0] = new UdpPeerReceiver(udpStack1); - udpTypes[0] = TOU_RECEIVER_TYPE_UDPPEER; - udpStack1->addReceiver(udpReceivers[0]); - - // STACK 2. - UdpRelayReceiver *mRelay2 = new UdpRelayReceiver(udpStack2); - udpReceivers[3] = mRelay2; - udpTypes[3] = TOU_RECEIVER_TYPE_UDPRELAY; - udpStack2->addReceiver(udpReceivers[3]); - - udpReceivers[2] = new UdpPeerReceiver(udpStack2); - udpTypes[2] = TOU_RECEIVER_TYPE_UDPPEER; - udpStack2->addReceiver(udpReceivers[2]); - - tou_init((void **) udpReceivers, udpTypes, 4); - - - int sockfd = tou_socket(0, TOU_RECEIVER_TYPE_UDPPEER, 0); - int sockfd2 = tou_socket(2, TOU_RECEIVER_TYPE_UDPPEER, 0); - if ((sockfd <= 0) || (sockfd2 <= 0)) - { - std::cerr << "Failed to open socket!: "; - std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl; - std::cerr << "Socket Error:" << tou_errno(sockfd2) << std::endl; - return -1; - } - std::cerr << "Sockets Created: " << sockfd << " & " << sockfd2 << std::endl; - - std::cerr << "Socket Non-Blocking" << std::endl; - - std::cerr << "Socket1 Bound to: " << laddr << std::endl; - std::cerr << "Socket2 Bound to: " << raddr << std::endl; - - int err = 0; - - // listening. - if (1) // socket2. - { - std::cerr << "Socket2 Listening " << std::endl; - /* listen */ - err = tou_listenfor(sockfd2, - (struct sockaddr *) &laddr, sizeof(laddr)); - } - - - if (1) // only one program. - { - std::cerr << "Socket1 Connecting to: " << raddr << std::endl; - err = tou_connect(sockfd, (struct sockaddr *) &raddr, sizeof(raddr), 30); - if (err < 0) - { - errno = tou_errno(sockfd); - if (errno != EINPROGRESS) - { - std::cerr << "Cannot Connect!: " << errno << std::endl; - return 1; - } - } - } - - bool sock1Connected = false; - bool sock2Connected = false; - - while((!sock1Connected) || (!sock2Connected)) - { - usleep(1000); - - - /* sock1 */ - if((!sock1Connected) && (0 == (err = tou_connected(sockfd)))) - { - std::cerr << "Waiting for Connect (Sock1)!" << std::endl; - } - if ((!sock1Connected) && (err < 0)) - { - std::cerr << "Connect Failed" << std::endl; - return 1; - } - else if (!sock1Connected) - { - // else connected! - sock1Connected = true; - } - - /* accept - sock2 */ - struct sockaddr_in inaddr; - socklen_t addrlen = sizeof(inaddr); - int nsock = -1; - - if ((!sock2Connected) && (0 > (nsock = tou_accept(sockfd2, - (struct sockaddr *) &inaddr, &addrlen)))) - { - errno = tou_errno(sockfd2); - if (errno != EAGAIN) - { - std::cerr << "Cannot Connect!: " << errno << std::endl; - return 1; - } - else - { - std::cerr << "Waiting for Connect (Sock2)!" << std::endl; - } - } - else if (nsock > 0) - { - /* connected */ - sock2Connected = true; - sockfd2 = nsock; - std::cerr << "Socket Accepted from: " << inaddr << std::endl; - } - } - - std::cerr << "Socket Connected" << std::endl; - -#define MAX_READ 20000 - - /* send data */ - int bufsize = MAX_READ; - char buffer[MAX_READ]; - char data[MAX_READ]; - int readsize = 0; - - bdnet_fcntl(0, F_SETFL, O_NONBLOCK); - bdnet_fcntl(1,F_SETFL,O_NONBLOCK); - - rstime_t lastRead = time(NULL); - bool doneWrite = false; - bool doneRead = false; - bool blockread = false; - - while((!doneWrite) || (!doneRead)) - { - /* read -> write_socket... */ - usleep(10); - - if (blockread != true) - { - int readbuf = 1 + RSRandom::random_u32() % (MAX_READ - 1); - readsize = read(0, buffer, readbuf); - if (readsize) - { - //std::cerr << "read " << readsize << " / " << readbuf; - //std::cerr << std::endl; - } - } - if ((readsize == 0) && (!doneWrite)) - { - /* eof */ - doneWrite = true; - std::cerr << "Write Done Total: " << totalwbytes; - std::cerr << std::endl; - } - /* now we write */ - if ((readsize > 0) && (-1 == tou_write(sockfd, buffer, readsize))) - { - //std::cerr << "Blocked Write "; - //std::cerr << "Error: " << tou_errno(sockfd); - //std::cerr << std::endl; - blockread = true; - } - else - { - blockread = false; - totalwbytes += readsize; - - if (readsize) - { - std::cerr << "Written: " << readsize << ", Total: " << totalwbytes; - std::cerr << " In Transit: " << totalwbytes - totalrbytes; - std::cerr << std::endl; - } - } - - int ret = 0; - int readbuf2 = 1 + RSRandom::random_u32() % (MAX_READ - 1); - if (0 < (ret = tou_read(sockfd2, data, readbuf2))) - { - //std::cerr << "TF(" << ret << ")" << std::endl; - write(1, data, ret); - totalrbytes += ret; - - std::cerr << "Read: " << ret << " Total: " << totalrbytes; - std::cerr << " In Transit: " << totalwbytes - totalrbytes; - std::cerr << std::endl; - - lastRead = time(NULL); - } - else if ((ret == 0) && (!doneRead)) - { - doneRead = true; - std::cerr << "Read Done Total: " << totalrbytes; - std::cerr << std::endl; - } - else - { - //std::cerr << "Blocked Read: " << "Error: " << tou_errno(sockfd); - //std::cerr << std::endl; -#define TIMEOUT 15 - if ((!doneRead) && (time(NULL) - lastRead > TIMEOUT)) - { - doneRead = true; - std::cerr << "TIMEOUT: Read Done Total: " << totalrbytes; - std::cerr << std::endl; - } - } - - - } - - /* this is blocking??? */ - tou_close(sockfd); - tou_close(sockfd2); - - std::cerr << "Transfer Complete: " << totalwbytes << " bytes"; - std::cerr << std::endl; - return 1; -} - diff --git a/libretroshare/src/tests/tcponudp/stacks_tou.sh b/libretroshare/src/tests/tcponudp/stacks_tou.sh deleted file mode 100755 index 7715e769d..000000000 --- a/libretroshare/src/tests/tcponudp/stacks_tou.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh -# Script to Test the udp_server code. - -EXEC=./stacks_tou -DATAFILE=./stacks_tou - -TMPOUTPUT=tmpoutput$$ -EXPECTEDPERIOD=10 - -$EXEC 127.0.0.1 4401 127.0.0.1 4032 < $DATAFILE > $TMPOUTPUT - -if diff -s $DATAFILE $TMPOUTPUT -then - echo "SUCCESS" -else - echo "FAILURE to accurately transfer DATA" -fi - -rm $TMPOUTPUT - diff --git a/libretroshare/src/tests/tcponudp/test_tou.cc b/libretroshare/src/tests/tcponudp/test_tou.cc deleted file mode 100644 index 17035f631..000000000 --- a/libretroshare/src/tests/tcponudp/test_tou.cc +++ /dev/null @@ -1,531 +0,0 @@ -/* - * "$Id: test_tou.cc,v 1.3 2007-02-18 21:46:50 rmf24 Exp $" - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2004-2006 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - - -#include -#include - -//#define USE_TCP_SOCKET 1 - -// for printing sockaddr -#include "udp/udpstack.h" - -#ifndef USE_TCP_SOCKET - #include "tcponudp/tou.h" - #include "tcponudp/udppeer.h" -#endif - -/* shouldn't do this - but for convenience - * using tou_net.h for universal fns - * generally this should be only internal to libtou.h - * - * This includes the whole networking interface - */ - -#include "util/bdnet.h" - -/* These three includes appear to work in both W & L. - * and they shouldn't!!!! maybe cygwin is allowing it... - * will only use them for tou test fns. - * - * they appear to provide getopt + read/write in windows. - */ - -#include -#include -#include - -/* This is a simple test to ensure that the tou behaviour - * is almost identical to a standard tcp socket. - * - */ - -int Check_Socket(int fd); - -void usage(char *name) -{ - std::cerr << "Usage: " << name; - std::cerr << " [-pco] "; - std::cerr << " "; - std::cerr << std::endl; - exit(1); - return; -} - -int main(int argc, char **argv) -{ - int c; - bool isProxy = false; - bool toConnect = false; - bool stayOpen = false; - - int totalwbytes = 0; - int totalrbytes = 0; - - while(-1 != (c = getopt(argc, argv, "pco"))) - { - switch (c) - { - case 'p': - isProxy = true; - break; - case 'c': - toConnect = true; - break; - case 'o': - stayOpen = true; - break; - default: - usage(argv[0]); - break; - } - } - - if (argc-optind < 4) - { - usage(argv[0]); - return 1; - } - - - /* setup the local/remote addresses. - */ - struct sockaddr_in laddr; - struct sockaddr_in raddr; - - laddr.sin_family = AF_INET; - raddr.sin_family = AF_INET; - - if ((!bdnet_inet_aton(argv[optind], &(laddr.sin_addr))) || - (!bdnet_inet_aton(argv[optind+2], &(raddr.sin_addr)))) - { - std::cerr << "Invalid addresses!" << std::endl; - usage(argv[0]); - } - - laddr.sin_port = htons(atoi(argv[optind+1])); - raddr.sin_port = htons(atoi(argv[optind+3])); - - std::cerr << "Local Address: " << laddr << std::endl; - std::cerr << "Remote Address: " << raddr << std::endl; - - - - -#ifdef USE_TCP_SOCKET - int sockfd = socket(PF_INET, SOCK_STREAM, 0); -#else - - UdpStack udps(laddr); - - UdpSubReceiver *udpReceivers[1]; - int udpTypes[1]; - - udpReceivers[0] = new UdpPeerReceiver(&udps); - udpTypes[0] = TOU_RECEIVER_TYPE_UDPPEER; - udps.addReceiver(udpReceivers[0]); - - tou_init((void **) udpReceivers, udpTypes, 1); - - int sockfd = tou_socket(0, TOU_RECEIVER_TYPE_UDPPEER, 0); -#endif - if (sockfd < 0) - { - std::cerr << "Failed to open socket!: "; -#ifdef USE_TCP_SOCKET - std::cerr << "Socket Error:" << errno << std::endl; -#else - std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl; -#endif - return -1; - } - std::cerr << "Socket Created" << std::endl; - - - /* make nonblocking */ -#ifdef USE_TCP_SOCKET - int err = bdnet_fcntl(sockfd,F_SETFL,O_NONBLOCK); -#else - int err = 0; -#endif - if (err < 0) - { - std::cerr << "Error: Cannot make socket NON-Blocking: "; - std::cerr << err << std::endl; - return -1; - } - - std::cerr << "Socket Non-Blocking" << std::endl; - -#ifdef USE_TCP_SOCKET - err = bind(sockfd, (struct sockaddr *) &laddr, sizeof(laddr)); - if (err < 0) - { - std::cerr << "Error: Cannot bind socket: "; - std::cerr << err << std::endl; - return -1; - } - std::cerr << "Socket Bound to: " << laddr << std::endl; -#else - err = tou_bind(sockfd, (struct sockaddr *) &laddr, sizeof(laddr)); - if (err < 0) - { - std::cerr << "As expected, cannot bind a tou socket"; - std::cerr << err << std::endl; - //return -1; - } -#endif - - - if (toConnect) - { - std::cerr << "Socket Connecting to: " << raddr << std::endl; -#ifdef USE_TCP_SOCKET - err = connect(sockfd, (struct sockaddr *) &raddr, sizeof(raddr)); -#else - err = tou_connect(sockfd, (struct sockaddr *) &raddr, sizeof(raddr), 30); -#endif - if (err < 0) - { -#ifndef USE_TCP_SOCKET - errno = tou_errno(sockfd); -#endif - if (errno != EINPROGRESS) - { - std::cerr << "Cannot Connect!" << std::endl; - return 1; - } -#ifdef USE_TCP_SOCKET - while(0 == (err = Check_Socket(sockfd))) -#else - while(0 == (err = tou_connected(sockfd))) -#endif - { - std::cerr << "Waiting for Connect!" << std::endl; - sleep(1); - } - if (err < 0) - { - std::cerr << "Connect Failed" << std::endl; - return 1; - } - // else connected! - } - } - else - { - std::cerr << "Socket Listening " << std::endl; - /* listen */ -#ifdef USE_TCP_SOCKET - err = listen(sockfd, 1); -#else - //err = tou_listen(sockfd, 1); - err = tou_listenfor(sockfd, - (struct sockaddr *) &raddr, sizeof(raddr)); -#endif - - /* accept */ - struct sockaddr_in inaddr; - socklen_t addrlen = sizeof(inaddr); - int nsock; - -#ifdef USE_TCP_SOCKET - while(0 > (nsock = accept(sockfd, - (struct sockaddr *) &inaddr, &addrlen))) -#else - while(0 > (nsock = tou_accept(sockfd, - (struct sockaddr *) &inaddr, &addrlen))) -#endif - { -#ifndef USE_TCP_SOCKET - errno = tou_errno(sockfd); -#endif - if (errno != EAGAIN) - { - std::cerr << "Cannot Connect!" << std::endl; - return 1; - } - sleep(1); - } - /* changed sockfd */ - sockfd = nsock; - std::cerr << "Socket Accepted from: " << inaddr << std::endl; - } - - std::cerr << "Socket Connected" << std::endl; - - if (toConnect) - { - /* send data */ - int bufsize = 15011; - char buffer[bufsize]; - int readsize = 0; - - bdnet_fcntl(0, F_SETFL, O_NONBLOCK); - - bool done = false; - bool blockread = false; - while(!done) - { - //sleep(1); - //usleep(10000); - usleep(100); - if (blockread != true) - { - readsize = read(0, buffer, bufsize); - } - if (readsize == 0) - { - /* eof */ - done = true; - } - else if ((readsize == -1) && ( EAGAIN == errno )) - { - continue; - } - - - /* now we write */ -#ifdef USE_TCP_SOCKET - if (-1 == write(sockfd, buffer, readsize)) -#else - if (-1 == tou_write(sockfd, buffer, readsize)) -#endif - { - //std::cerr << "Blocked Write!" << std::endl; -#ifndef USE_TCP_SOCKET - //std::cerr << "Error: " << tou_errno(sockfd) << std::endl; -#endif - blockread = true; - } - else - { - blockread = false; - totalwbytes += readsize; - } - } - -#ifdef USE_TCP_SOCKET - close(sockfd); -#else - /* this is blocking??? */ - tou_close(sockfd); -#endif - - std::cerr << "Transfer Complete: " << totalwbytes << " bytes"; - std::cerr << std::endl; - - // ACTUALLY tou_close() is not blocking... - // and kills the connection instantly. - // The transfer will fail if there is any data left in the send queue (which there is in most cases). - // Interestingly.. if we slow the transmit and speed up the recv, - // Then it can succeed. - // - // The settings are done to make this fail. - - return 1; - } - - /* recv data */ - int bufsize = 1523; - char data[bufsize]; - bdnet_fcntl(1,F_SETFL,O_NONBLOCK); - while(1) - { - //sleep(1); - //usleep(10000); - //usleep(1000); - usleep(100); - int writesize = bufsize; - int ret; - -#ifdef USE_TCP_SOCKET - if (0 < (ret = read(sockfd, data, writesize))) -#else - if (0 < (ret = tou_read(sockfd, data, writesize))) -#endif - - { - std::cerr << "TF(" << ret << ")" << std::endl; - write(1, data, ret); - totalrbytes += ret; - } - else if (ret == 0) - { - break; - } - else - { - //std::cerr << "Blocked Read!" << std::endl; -#ifndef USE_TCP_SOCKET - //std::cerr << "Error: " << tou_errno(sockfd) << std::endl; -#endif - - } - } - -#ifdef USE_TCP_SOCKET - close(sockfd); -#else - tou_close(sockfd); -#endif - - std::cerr << "Transfer complete :" << totalrbytes; - std::cerr << " bytes" << std::endl; - close(1); - - return 1; -} - - - -#ifdef USE_TCP_SOCKET - - -int Check_Socket(int fd) -{ - std::cerr << "Check_Socket()" << std::endl; - - std::cerr << "1) Checking with Select()" << std::endl; - - fd_set ReadFDs, WriteFDs, ExceptFDs; - FD_ZERO(&ReadFDs); - FD_ZERO(&WriteFDs); - FD_ZERO(&ExceptFDs); - - FD_SET(fd, &ReadFDs); - FD_SET(fd, &WriteFDs); - FD_SET(fd, &ExceptFDs); - - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 0; - - int sr = 0; - if (0 > (sr = select(fd + 1, - &ReadFDs, &WriteFDs, &ExceptFDs, &timeout))) - { - std::cerr << "Check_Socket() Select ERROR: " << sr << std::endl; - return -1; - } - - if (FD_ISSET(fd, &ExceptFDs)) - { - std::cerr << "Check_Socket() Exception on socket!" << std::endl; - return -1; - } - - if (FD_ISSET(fd, &WriteFDs)) - { - std::cerr << "Check_Socket() Can Write!" << std::endl; - } - else - { - // not ready return 0; - std::cerr << "Check_Socket() Cannot Write!" << std::endl; - std::cerr << "Check_Socket() Socket Not Ready!" << std::endl; - return 0; - } - - if (FD_ISSET(fd, &ReadFDs)) - { - std::cerr << "Check_Socket() Can Read!" << std::endl; - } - else - { - std::cerr << "Check_Socket() Cannot Read!" << std::endl; - std::cerr << "Check_Socket() Socket Not Ready!" << std::endl; - return 0; - } - - std::cerr << "Select() Tests indicate Socket Good!" << std::endl; - std::cerr << "2) Checking with getsockopt()" << std::endl; - - int err = 1; - socklen_t optlen = 4; - if (0==getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &optlen)) - { - std::cerr << "Check_Socket() getsockopt returned :" << err; - std::cerr << ", optlen:" << optlen; - std::cerr << std::endl; - - if (err == 0) - { - std::cerr << "Check_Socket() getsockopt"; - std::cerr << " Indicates TCP Connection Complete:"; - std::cerr << std::endl; - return 1; - } - else if (err == EINPROGRESS) - { - std::cerr << "Check_Socket() getsockopt"; - std::cerr << " Indicates TCP Connection INPROGRESS"; - std::cerr << std::endl; - return 0; - } - else if ((err == ENETUNREACH) || (err == ETIMEDOUT)) - { - std::cerr << "Check_Socket() getsockopt"; - std::cerr << " Indicates TCP Connection ENETUNREACH/ETIMEDOUT"; - std::cerr << std::endl; - return -1; - } - else if ((err == EHOSTUNREACH) || (err == EHOSTDOWN)) - { - std::cerr << "Check_Socket() getsockopt"; - std::cerr << " Indicates TCP Connection ENETUNREACH/ETIMEDOUT"; - std::cerr << std::endl; - return -1; - } - else - { - std::cerr << "Check_Socket() getsockopt"; - std::cerr << " Indicates Other Error: " << err; - std::cerr << std::endl; - return -1; - } - - - } - else - { - std::cerr << "Check_Socket() getsockopt"; - std::cerr << " FAILED "; - std::cerr << std::endl; - return -1; - } -} - - -#else - -int Check_Socket(int fd) -{ - return 0; -} - -#endif diff --git a/libretroshare/src/tests/tcponudp/test_tou.sh b/libretroshare/src/tests/tcponudp/test_tou.sh deleted file mode 100755 index 3ae4f0896..000000000 --- a/libretroshare/src/tests/tcponudp/test_tou.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh -# Script to Test the udp_server code. - -EXEC=./test_tou -TMPOUTPUT=tmpoutput$$ -EXPECTEDPERIOD=10 -# launches one instance in server mode. -$EXEC 127.0.0.1 4001 127.0.0.1 4002 > $TMPOUTPUT & -#2> udp_server1.cerr & - -# launch a second in connect mode. -$EXEC -c 127.0.0.1 4002 127.0.0.1 4001 < $EXEC -# 2> udp_server2.cerr -# pipe a bunch of data through. -# make sure the data is the same. - -# print success / failure. -sleep $EXPECTEDPERIOD -killall $EXEC - -if diff -s $EXEC $TMPOUTPUT -then - echo "SUCCESS" -else - echo "FAILURE to accurately transfer DATA" -fi - -#rm udp_server1.cerr -#rm udp_server2.cerr -rm $TMPOUTPUT - - diff --git a/libretroshare/src/tests/tcponudp/timed_tou.cc b/libretroshare/src/tests/tcponudp/timed_tou.cc deleted file mode 100644 index 5c89d88e9..000000000 --- a/libretroshare/src/tests/tcponudp/timed_tou.cc +++ /dev/null @@ -1,338 +0,0 @@ -/* - * "$Id: pair_tou.cc,v 1.3 2007-02-18 21:46:50 rmf24 Exp $" - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2004-2006 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - - -#include -#include - -// for printing sockaddr -#include "udp/udpstack.h" - -#include "tcponudp/tou.h" -#include "tcponudp/udppeer.h" -#include "tcponudp/udprelay.h" - -#include "util/bdnet.h" - -#include "util/rsrandom.h" - -#include -#include -#include - - -/* - * This test creates the same stacks as are used in RS. - * This additionally tests the "checkFns" for the other UdpReceivers, which could potentially be modifying the data. - * obviously they shouldn't! - * - */ - -void usage(char *name) -{ - std::cerr << "Usage: " << name; - std::cerr << " [-pco] "; - std::cerr << " "; - std::cerr << std::endl; - exit(1); - return; -} - -int main(int argc, char **argv) -{ - int c; - bool isProxy = false; - bool toConnect = false; - bool stayOpen = false; - - int totalwbytes = 0; - int totalmbytes = 0; - int totalrbytes = 0; - - while(-1 != (c = getopt(argc, argv, "pco"))) - { - switch (c) - { - case 'p': - isProxy = true; - break; - case 'c': - toConnect = true; - break; - case 'o': - stayOpen = true; - break; - default: - usage(argv[0]); - break; - } - } - - if (argc-optind < 4) - { - usage(argv[0]); - return 1; - } - - /* setup the local/remote addresses. - */ - struct sockaddr_in laddr; - struct sockaddr_in raddr; - - laddr.sin_family = AF_INET; - raddr.sin_family = AF_INET; - - if ((!bdnet_inet_aton(argv[optind], &(laddr.sin_addr))) || - (!bdnet_inet_aton(argv[optind+2], &(raddr.sin_addr)))) - { - std::cerr << "Invalid addresses!" << std::endl; - usage(argv[0]); - } - - laddr.sin_port = htons(atoi(argv[optind+1])); - raddr.sin_port = htons(atoi(argv[optind+3])); - - std::cerr << "Local Address: " << laddr << std::endl; - std::cerr << "Remote Address: " << raddr << std::endl; - - std::cerr << "Creating with Lossy Udp Layers for further testing"; - std::cerr << std::endl; - - UdpStack *udpStack1 = new UdpStack(UDP_TEST_TIMED_LAYER,laddr); - sleep(1); - UdpStack *udpStack2 = new UdpStack(UDP_TEST_TIMED_LAYER,raddr); - - UdpSubReceiver *udpReceivers[4]; - int udpTypes[4]; - - // NOTE DHT is too hard to add at the moment. - - UdpRelayReceiver *mRelay1 = new UdpRelayReceiver(udpStack1); - udpReceivers[1] = mRelay1; - udpTypes[1] = TOU_RECEIVER_TYPE_UDPRELAY; - udpStack1->addReceiver(udpReceivers[1]); - - udpReceivers[0] = new UdpPeerReceiver(udpStack1); - udpTypes[0] = TOU_RECEIVER_TYPE_UDPPEER; - udpStack1->addReceiver(udpReceivers[0]); - - // STACK 2. - UdpRelayReceiver *mRelay2 = new UdpRelayReceiver(udpStack2); - udpReceivers[3] = mRelay2; - udpTypes[3] = TOU_RECEIVER_TYPE_UDPRELAY; - udpStack2->addReceiver(udpReceivers[3]); - - udpReceivers[2] = new UdpPeerReceiver(udpStack2); - udpTypes[2] = TOU_RECEIVER_TYPE_UDPPEER; - udpStack2->addReceiver(udpReceivers[2]); - - tou_init((void **) udpReceivers, udpTypes, 4); - - - int sockfd = tou_socket(0, TOU_RECEIVER_TYPE_UDPPEER, 0); - int sockfd2 = tou_socket(2, TOU_RECEIVER_TYPE_UDPPEER, 0); - if ((sockfd <= 0) || (sockfd2 <= 0)) - { - std::cerr << "Failed to open socket!: "; - std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl; - std::cerr << "Socket Error:" << tou_errno(sockfd2) << std::endl; - return -1; - } - std::cerr << "Sockets Created: " << sockfd << " & " << sockfd2 << std::endl; - - std::cerr << "Socket Non-Blocking" << std::endl; - - std::cerr << "Socket1 Bound to: " << laddr << std::endl; - std::cerr << "Socket2 Bound to: " << raddr << std::endl; - - int err = 0; - - std::cerr << "Socket1 Connecting to: " << raddr << std::endl; - err = tou_connect(sockfd, (struct sockaddr *) &raddr, sizeof(raddr), 30); - - std::cerr << "Socket2 Connecting to: " << raddr << std::endl; - err = tou_connect(sockfd2, (struct sockaddr *) &laddr, sizeof(laddr), 30); - - while((!tou_connected(sockfd)) && (!tou_connected(sockfd2))) - { - usleep(100000); - std::cerr << "."; - } - - std::cerr << "Socket Connected" << std::endl; - -#define MAX_READ 20000 - - /* send data */ - int bufsize = MAX_READ; - char buffer[MAX_READ]; - char middata[MAX_READ]; - char data[MAX_READ]; - int readsize = 0; - int midsize = 0; - - bdnet_fcntl(0, F_SETFL, O_NONBLOCK); - bdnet_fcntl(1,F_SETFL,O_NONBLOCK); - - rstime_t lastRead = time(NULL); - bool doneWrite = false; - bool doneRead = false; - bool blockread = false; - bool blockmid = false; - - while((!doneWrite) || (!doneRead)) - { - /* read -> write_socket... */ - usleep(10); - - if (blockread != true) - { - int readbuf = 1 + RSRandom::random_u32() % (MAX_READ - 1); - readsize = read(0, buffer, readbuf); - if (readsize) - { - //std::cerr << "read " << readsize << " / " << readbuf; - //std::cerr << std::endl; - } - } - if ((readsize == 0) && (!doneWrite)) - { - /* eof */ - doneWrite = true; - std::cerr << "Write Done Total: " << totalwbytes; - std::cerr << std::endl; - } - /* now we write */ - if ((readsize > 0) && (-1 == tou_write(sockfd, buffer, readsize))) - { - //std::cerr << "Blocked Write "; - //std::cerr << "Error: " << tou_errno(sockfd); - //std::cerr << std::endl; - blockread = true; - } - else - { - blockread = false; - totalwbytes += readsize; - - if (readsize) - { - std::cerr << "Written: " << readsize << ", Total: " << totalwbytes; - std::cerr << " Total In Transit: " << totalwbytes - totalrbytes; - std::cerr << std::endl; - } - } - - /*************** Here we read it in, and send it back out... - * so the data is flowing both ways through the UDP connection - * - *****/ - - - if (!blockmid) - { - /* read from socket 2, and write back to socket 2 */ - - int readmidbuf = 1 + RSRandom::random_u32() % (MAX_READ - 1); - if (0 < (midsize = tou_read(sockfd2, middata, readmidbuf))) - { - //std::cerr << "MidRead: " << mid << " Total: " << totalrbytes; - //std::cerr << " In Transit: " << totalwbytes - totalrbytes; - //std::cerr << std::endl; - } - } - - /* now we write */ - if ((midsize > 0) && (-1 == tou_write(sockfd2, middata, midsize))) - { - //std::cerr << "Blocked Write "; - //std::cerr << "Error: " << tou_errno(sockfd); - //std::cerr << std::endl; - blockmid = true; - } - else - { - blockmid = false; - - if (midsize > 0) - { - totalmbytes += midsize; - - std::cerr << "MidRead: " << midsize << ", Total: " << totalmbytes; - std::cerr << " => Transit => : " << totalwbytes - totalmbytes; - std::cerr << " <= Transit <= : " << totalmbytes - totalrbytes; - std::cerr << std::endl; - } - } - - /***** READ FROM FIRST SOCKET *****/ - - int ret = 0; - int readbuf2 = 1 + RSRandom::random_u32() % (MAX_READ - 1); - if (0 < (ret = tou_read(sockfd, data, readbuf2))) - { - //std::cerr << "TF(" << ret << ")" << std::endl; - write(1, data, ret); - totalrbytes += ret; - - std::cerr << "Read: " << ret << " Total: " << totalrbytes; - std::cerr << " Total In Transit: " << totalwbytes - totalrbytes; - std::cerr << std::endl; - - lastRead = time(NULL); - } - else if ((ret == 0) && (!doneRead)) - { - doneRead = true; - std::cerr << "Read Done Total: " << totalrbytes; - std::cerr << std::endl; - } - else - { - //std::cerr << "Blocked Read: " << "Error: " << tou_errno(sockfd); - //std::cerr << std::endl; -#define TIMEOUT 15 - if ((!doneRead) && (time(NULL) - lastRead > TIMEOUT)) - { - doneRead = true; - std::cerr << "TIMEOUT: Read Done Total: " << totalrbytes; - std::cerr << std::endl; - } - } - - - } - - /* this is blocking??? */ - tou_close(sockfd); - tou_close(sockfd2); - - std::cerr << "Transfer Complete: " << totalwbytes << " bytes"; - std::cerr << std::endl; - return 1; -} - diff --git a/libretroshare/src/tests/tcponudp/timed_tou.sh b/libretroshare/src/tests/tcponudp/timed_tou.sh deleted file mode 100755 index 4d2f7816c..000000000 --- a/libretroshare/src/tests/tcponudp/timed_tou.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh -# Script to Test the udp_server code. - -EXEC=./timed_tou -DATAFILE=./timed_tou - -TMPOUTPUT=tmpoutput$$ -EXPECTEDPERIOD=10 - -$EXEC 127.0.0.1 4401 127.0.0.1 4032 < $DATAFILE > $TMPOUTPUT - -if diff -s $DATAFILE $TMPOUTPUT -then - echo "SUCCESS" -else - echo "FAILURE to accurately transfer DATA" -fi - -rm $TMPOUTPUT - diff --git a/libretroshare/src/tests/tcponudp/udp_server.cc b/libretroshare/src/tests/tcponudp/udp_server.cc deleted file mode 100644 index 1f720561a..000000000 --- a/libretroshare/src/tests/tcponudp/udp_server.cc +++ /dev/null @@ -1,285 +0,0 @@ -/* - * "$Id: udp_server.cc,v 1.4 2007-02-18 21:46:50 rmf24 Exp $" - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2004-2006 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - - -#include "udp/udpstack.h" -#include "tcponudp/udppeer.h" -#include "tcponudp/tcpstream.h" -#include "tcponudp/tou.h" - -#include - -#include -#include -#include - -void usage(char *name) -{ - std::cerr << "Usage: " << name; - std::cerr << " [-pco] "; - std::cerr << " "; - std::cerr << std::endl; - exit(1); - return; -} - -int main(int argc, char **argv) -{ - int c; - bool isProxy = false; - bool toConnect = false; - bool stayOpen = false; - - while(-1 != (c = getopt(argc, argv, "f:pco"))) - { - switch (c) - { - case 'p': - isProxy = true; - break; - case 'c': - toConnect = true; - break; - case 'o': - stayOpen = true; - break; - case 'f': - /* this can only work when the define below exists in tcpstream */ -#ifdef DEBUG_TCP_STREAM_EXTRA - setupBinaryCheck(std::string(optarg)); -#else - std::cerr << "Binary Check no Enabled!" << std::endl; -#endif - break; - default: - usage(argv[0]); - break; - } - } - - if (argc-optind < 4) - { - usage(argv[0]); - return 1; - } - /* setup the local/remote addresses. - */ - - - struct sockaddr_in laddr; - struct sockaddr_in raddr; - - laddr.sin_family = AF_INET; - raddr.sin_family = AF_INET; - - if ((!bdnet_inet_aton(argv[optind], &(laddr.sin_addr))) || - (!bdnet_inet_aton(argv[optind+2], &(raddr.sin_addr)))) - { - std::cerr << "Invalid addresses!" << std::endl; - usage(argv[0]); - } - - laddr.sin_port = htons(atoi(argv[optind+1])); - raddr.sin_port = htons(atoi(argv[optind+3])); - - std::cerr << "Local Address: " << laddr << std::endl; - std::cerr << "Remote Address: " << raddr << std::endl; - - UdpStack udps(laddr); - UdpPeerReceiver *upr = new UdpPeerReceiver(&udps); - udps.addReceiver(upr); - - if (!udps.okay()) - { - std::cerr << "UdpSorter not Okay (Cannot Open Local Address): " << laddr << std::endl; - exit(1); - } - - TcpStream tcp(upr); - upr->addUdpPeer(&tcp, raddr); - - if (toConnect) - { - tcp.connect(raddr, 30); - } - else - { - tcp.listenfor(raddr); - } - - while(!tcp.isConnected()) - { - sleep(1); - std::cerr << "Waiting for TCP to Connect!" << std::endl; - udps.status(std::cerr); - tcp.status(std::cerr); - tcp.tick(); - } - std::cerr << "TCP Connected***************************" << std::endl; - udps.status(std::cerr); - tcp.status(std::cerr); - std::cerr << "TCP Connected***************************" << std::endl; - - int count = 1; - - if (toConnect) - { - /* send data */ - int bufsize = 51; - char buffer[bufsize]; - int readsize = 0; - - bdnet_fcntl(0, F_SETFL, O_NONBLOCK); - - bool done = false; - bool blockread = false; - while(!done) - { - //sleep(1); - //usleep(100000); - usleep(1000); - if (blockread != true) - { - readsize = read(0, buffer, bufsize); - } - if (readsize == 0) - { - /* eof */ - done = true; - } - else if ((readsize == -1) && ( EAGAIN == errno )) - { - continue; - } - - /* now we write */ - if (-1 == tcp.write(buffer, readsize)) - blockread = true; - else - blockread = false; - - - tcp.tick(); - if (count++ % 10 == 0) - { - std::cerr << "******************************************" << std::endl; - tcp.status(std::cerr); - } - } - - tcp.closeWrite(); - - while(!tcp.widle()) - { - //sleep(1); - usleep(100000); - //usleep(1000); - tcp.tick(); - if (count++ % 10 == 0) - { - std::cerr << "Waiting for Idle()" << std::endl; - std::cerr << "******************************************" << std::endl; - tcp.status(std::cerr); - } - } - - std::cerr << "Transfer Complete: " << tcp.wbytes() << " bytes"; - std::cerr << std::endl; - return 1; - } - - /* recv data */ - int bufsize = 1523; - char data[bufsize]; - bdnet_fcntl(1,F_SETFL,O_NONBLOCK); - while(1) - { - //sleep(1); - usleep(100000); - //usleep(1000); - //int writesize = bufsize; - int ret; - if (0 < (ret = tcp.read(data, bufsize))) - { - std::cerr << "TF(" << ret << ")" << std::endl; - write(1, data, ret); - } - else if (ret == 0) - { - /* completed transfer */ - std::cerr << "Transfer complete :" << tcp.rbytes(); - std::cerr << " bytes" << std::endl; - break; - } - - tcp.tick(); - if (count++ % 10 == 0) - { - std::cerr << "******************************************" << std::endl; - tcp.status(std::cerr); - } - if ((!stayOpen) && tcp.ridle()) - { - std::cerr << "Transfer Idle after " << tcp.rbytes(); - std::cerr << " bytes" << std::endl; - close(1); - break; - } - } - - tcp.closeWrite(); - - /* tick for a bit */ - while((stayOpen) || (!tcp.ridle())) - { - tcp.tick(); - //sleep(1); - usleep(100000); - //usleep(1000); - if (count++ % 10 == 0) - { - std::cerr << "Waiting for Idle()" << std::endl; - std::cerr << "******************************************" << std::endl; - tcp.status(std::cerr); - } - } - - - if ((!stayOpen) && tcp.ridle()) - { - //std::cerr << "Transfer complete :" << tcp.rbytes(); - //std::cerr << " bytes" << std::endl; - close(1); - return 1; - } - - return 1; -} - - - - diff --git a/libretroshare/src/tests/tcponudp/udp_server.sh b/libretroshare/src/tests/tcponudp/udp_server.sh deleted file mode 100755 index 8bbd55887..000000000 --- a/libretroshare/src/tests/tcponudp/udp_server.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh -# Script to Test the udp_server code. - -EXEC=./udp_server -TMPOUTPUT=tmpoutput$$ -EXPECTEDPERIOD=10 -# launches one instance in server mode. -$EXEC 127.0.0.1 4001 127.0.0.1 4002 > $TMPOUTPUT & -#2> udp_server1.cerr & - -# launch a second in connect mode. -$EXEC -c 127.0.0.1 4002 127.0.0.1 4001 < $EXEC -# 2> udp_server2.cerr -# pipe a bunch of data through. -# make sure the data is the same. - -# print success / failure. -sleep $EXPECTEDPERIOD -killall $EXEC - -if diff -s $EXEC $TMPOUTPUT -then - echo "SUCCESS" -else - echo "FAILURE to accurately transfer DATA" -fi - -#rm udp_server1.cerr -#rm udp_server2.cerr -rm $TMPOUTPUT - - diff --git a/libretroshare/src/tests/tcponudp/udpsock_test.cc b/libretroshare/src/tests/tcponudp/udpsock_test.cc deleted file mode 100644 index bc9aeaf86..000000000 --- a/libretroshare/src/tests/tcponudp/udpsock_test.cc +++ /dev/null @@ -1,92 +0,0 @@ -/* - * libretroshare/src/tcponudp: udpsock_test.cc - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "udptestfn.h" -#include "udp/udplayer.h" -#include - -#define MAX_PEERS 16 - -int main(int argc, char **argv) -{ - /* get local and remote addresses */ - struct sockaddr_in local; - struct sockaddr_in peers[MAX_PEERS]; - int numpeers = 0; - int i,j; - - local.sin_family = AF_INET; - inet_aton("127.0.0.1", &(local.sin_addr)); - local.sin_port = htons(8767); - - for(i = 0; i < MAX_PEERS; i++) - { - peers[i].sin_family = AF_INET; - inet_aton("127.0.0.1", &(peers[i].sin_addr)); - peers[i].sin_port = htons(8768); - } - - if (argc < 3) - { - std::cerr << "Usage: " << argv[0] << " [ udp_server1.cerr & - -$EXEC 6002 6001 6003 6004 6005 & -$EXEC 6003 6002 6001 6004 6005 & -$EXEC 6004 6002 6003 6001 6005 & -$EXEC 6005 6002 6003 6004 6001 & - -## print success / failure. -sleep $EXPECTEDPERIOD -killall $EXEC - -# -#if diff -s $EXEC $TMPOUTPUT -#then -# echo "SUCCESS" -#else -# echo "FAILURE to accurately transfer DATA" -#fi -# -##rm udp_server1.cerr -##rm udp_server2.cerr -#rm $TMPOUTPUT -## -### diff --git a/libretroshare/src/tests/tcponudp/udpsort_test.cc b/libretroshare/src/tests/tcponudp/udpsort_test.cc deleted file mode 100644 index a4d025a2a..000000000 --- a/libretroshare/src/tests/tcponudp/udpsort_test.cc +++ /dev/null @@ -1,94 +0,0 @@ -/* - * libretroshare/src/tcponudp: udpsort_test.cc - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "udptestfn.h" -#include "udp/udpstack.h" -#include "tcponudp/udppeer.h" - -#define MAX_PEERS 16 - -int main(int argc, char **argv) -{ - /* get local and remote addresses */ - struct sockaddr_in local; - struct sockaddr_in peers[MAX_PEERS]; - int numpeers = 0; - int i,j; - - local.sin_family = AF_INET; - inet_aton("127.0.0.1", &(local.sin_addr)); - local.sin_port = htons(8767); - - for(i = 0; i < MAX_PEERS; i++) - { - peers[i].sin_family = AF_INET; - inet_aton("127.0.0.1", &(peers[i].sin_addr)); - peers[i].sin_port = htons(8768); - } - - if (argc < 3) - { - std::cerr << "Usage: " << argv[0] << " [addUdpPeer(pt, peers[i-2]); - } - - int size = 12; - void *data = malloc(size); - int ttl = 64; - - /* push packets to the peer */ - for(i = 0; i < 60; i++) - { - sleep(1); - for(j = 0; j < numpeers; j++) - { - udps.sendPkt(data, size, peers[j], ttl); - } - } - return 1; -} - - - diff --git a/libretroshare/src/tests/tcponudp/udpsort_test.sh b/libretroshare/src/tests/tcponudp/udpsort_test.sh deleted file mode 100755 index c6023e93b..000000000 --- a/libretroshare/src/tests/tcponudp/udpsort_test.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh -# Script to Test the udp_server code. - -EXEC=./udpsort_test -TMPOUTPUT=tmpoutput$$ -EXPECTEDPERIOD=10 -$EXEC 6001 6002 6003 6004 6005 & -#2> udp_server1.cerr & - -$EXEC 6002 6001 6003 6004 6005 & -$EXEC 6003 6002 6001 6004 6005 & -$EXEC 6004 6002 6003 6001 6005 & -$EXEC 6005 6002 6003 6004 6001 & - -## print success / failure. -sleep $EXPECTEDPERIOD -killall $EXEC - -# -#if diff -s $EXEC $TMPOUTPUT -#then -# echo "SUCCESS" -#else -# echo "FAILURE to accurately transfer DATA" -#fi -# -##rm udp_server1.cerr -##rm udp_server2.cerr -#rm $TMPOUTPUT -## -### diff --git a/libretroshare/src/tests/tcponudp/udptestfn.cc b/libretroshare/src/tests/tcponudp/udptestfn.cc deleted file mode 100644 index 12c7bd264..000000000 --- a/libretroshare/src/tests/tcponudp/udptestfn.cc +++ /dev/null @@ -1,49 +0,0 @@ -/* - * libretroshare/src/tcponudp: udptestfn.cc - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "udptestfn.h" - -int UdpRecvTest::recvPkt(void *data, int size, struct sockaddr_in &from) -{ - /* print packet information */ - std::cerr << "UdpRecvTest::recvPkt(" << size << ") from: " << from; - std::cerr << std::endl; - return -1; -} - -UdpPeerTest::UdpPeerTest(struct sockaddr_in &addr) - :raddr(addr) -{ - return; -} - -void UdpPeerTest::recvPkt(void *data, int size) -{ - /* print packet information */ - std::cerr << "UdpPeerTest::recvPkt(" << size << ") from: " << raddr; - std::cerr << std::endl; -} - - diff --git a/libretroshare/src/tests/tcponudp/udptestfn.h b/libretroshare/src/tests/tcponudp/udptestfn.h deleted file mode 100644 index d25a23223..000000000 --- a/libretroshare/src/tests/tcponudp/udptestfn.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * libretroshare/src/tcponudp: udptestfn.h - * - * TCP-on-UDP (tou) network interface for RetroShare. - * - * Copyright 2007-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "udp/udplayer.h" -#include "udp/udpstack.h" -#include "tcponudp/udppeer.h" - -//#include "udpsorter.h" - -#ifndef TOU_UDP_TEST_FN_H -#define TOU_UDP_TEST_FN_H - -class UdpRecvTest: public UdpReceiver -{ - public: -virtual int recvPkt(void *data, int size, struct sockaddr_in &from); -virtual int status(std::ostream&) { return 0; } -}; - - -class UdpPeerTest: public UdpPeer -{ - public: - UdpPeerTest(struct sockaddr_in &addr); -virtual void recvPkt(void *data, int size); - - struct sockaddr_in raddr; -}; - - -#endif diff --git a/libretroshare/src/tests/upnp/upnpforward.cc b/libretroshare/src/tests/upnp/upnpforward.cc deleted file mode 100644 index 50394d3f1..000000000 --- a/libretroshare/src/tests/upnp/upnpforward.cc +++ /dev/null @@ -1,114 +0,0 @@ -/* - * libretroshare/src/upnp: upnpforward.cc - * - * Upnp Manual Test for RetroShare. - * - * Copyright 2012 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/* - * A Upnp utility to forward a port, specified on the commandline. - */ - -#ifdef WIN32 -#include "util/rswin.h" -#endif - -#include "util/utest.h" -#include "upnp/upnphandler_linux.h" - -INITTEST() ; - -#include - -void usage(char *name) -{ - std::cerr << "Usage: " << name << " [-i ] [-e ]"; - std::cerr << std::endl; -} - -int main(int argc, char **argv) -{ - int c; - uint16_t internalPort = 7812; - uint16_t externalPort = 7812; - -#ifdef PTW32_STATIC_LIB - pthread_win32_process_attach_np(); -#endif - -#ifdef WIN32 - // Windows Networking Init. - WORD wVerReq = MAKEWORD(2,2); - WSADATA wsaData; - - if (0 != WSAStartup(wVerReq, &wsaData)) - { - std::cerr << "Failed to Startup Windows Networking"; - std::cerr << std::endl; - } - else - { - std::cerr << "Started Windows Networking"; - std::cerr << std::endl; - } - -#endif - - - while(-1 != (c = getopt(argc, argv, "i:e:"))) - { - switch (c) - { - case 'i': - internalPort = atoi(optarg); - break; - case 'e': - externalPort = atoi(optarg); - break; - default: - usage(argv[0]); - break; - } - } - - - /* create a upnphandler object */ - //pqiNetAssistFirewall *upnp; - upnphandler *upnp; - - upnp = new upnphandler(); - - /* setup */ - upnp->setInternalPort(internalPort); - upnp->setExternalPort(externalPort); - - /* launch thread */ - upnp->enable(true); - - /* give it a chance to work its magic. */ - sleep(30); - - FINALREPORT("upnpforward") ; - return TESTRESULT(); -} - - - diff --git a/libretroshare/src/tests/util/aes_test.cc b/libretroshare/src/tests/util/aes_test.cc deleted file mode 100644 index cb0d00447..000000000 --- a/libretroshare/src/tests/util/aes_test.cc +++ /dev/null @@ -1,115 +0,0 @@ - -/* - * "$Id: dirtest.cc,v 1.1 2007-02-19 20:08:30 rmf24 Exp $" - * - * RetroShare C++ Interface. - * - * Copyright 2012-2012 by Cyril Soler - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - -#include "util/rsaes.h" -#include "util/utest.h" -#include - -#include -#include -#include -#include - -void printHelp(int argc,char *argv[]) -{ - std::cerr << argv[0] << ": tests AES encryption/decryption functions." << std::endl; - std::cerr << "Usage: " << argv[0] << std::endl ; -} - -void printHex(unsigned char *data,uint32_t length) -{ - static const char outh[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' } ; - static const char outl[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' } ; - - for(uint32_t j = 0; j < length; j++) - { - std::cerr << outh[ (data[j]>>4) ] ; - std::cerr << outh[ data[j] & 0xf ] ; - } -} - - -INITTEST() ; - -int main(int argc,char *argv[]) -{ - std::string inputfile ; - argstream as(argc,argv) ; - - as >> help() ; - - as.defaultErrorHandling() ; - - std::cerr << "Testing AES crypt" << std::endl; - - std::string source_string = "This is a very secret string, but ultimately it will always be decyphered" ; - std::cerr << "Input string: length=" << source_string.length() << ", s=\"" << source_string << "\"" << std::endl; - - unsigned char key_data[16] ; - unsigned char salt[8] ; - - for(int i=0;i<16;++i) - key_data[i] = lrand48() & 0xff ; - - std::cerr << "Key: " ; printHex(key_data,16); - std::cerr << std::endl; - - for(int i=5;i - -#include -#include "util/rscompress.h" -#include "util/rsdir.h" -#include "util/utest.h" -#include "util/argstream.h" - -#include -#include -#include -#include - -void printHelp(int argc,char *argv[]) -{ - std::cerr << argv[0] << ": tests AES encryption/decryption functions." << std::endl; - std::cerr << "Usage: " << argv[0] << std::endl ; -} - -bool compareStrings(const std::string& s1,const std::string& s2) -{ - uint32_t L = std::min(s1.length(),s2.length()) ; - - for(int i=0;i>4) ] ; - std::cerr << outh[ data[j] & 0xf ] ; - } -} - -INITTEST() ; - -int main(int argc,char *argv[]) -{ - std::string inputfile ; - argstream as(argc,argv) ; - - as >> help() ; - - as.defaultErrorHandling() ; - - std::cerr << "Testing RsCompress" << std::endl; - - std::string source_string = "This is a very secret string, but ultimately it will always be decyphered \ - ar cqs libretroshare.a temp/linux-g++-64/obj/p3bitdht.o \ - temp/linux-g++-64/obj/p3bitdht_interface.o \ - temp/linux-g++-64/obj/p3bitdht_peers.o \ - temp/linux-g++-64/obj/p3bitdht_peernet.o \ - temp/linux-g++-64/obj/p3bitdht_relay.o \ - temp/linux-g++-64/obj/connectstatebox.o temp/linux-g++-64/obj/udppeer.o \ - temp/linux-g++-64/obj/tcppacket.o temp/linux-g++-64/obj/tcpstream.o \ - temp/linux-g++-64/obj/tou.o temp/linux-g++-64/obj/bss_tou.o \ - temp/linux-g++-64/obj/udpstunner.o temp/linux-g++-64/obj/udprelay.o \ - temp/linux-g++-64/obj/cachestrapper.o temp/linux-g++-64/obj/fimonitor.o \ - temp/linux-g++-64/obj/findex.o temp/linux-g++-64/obj/fistore.o \ - temp/linux-g++-64/obj/rsexpr.o temp/linux-g++-64/obj/ftchunkmap.o \ - temp/linux-g++-64/obj/ftcontroller.o \ - temp/linux-g++-64/obj/ftdatamultiplex.o temp/linux-g++-64/obj/ftdbase.o \ - temp/linux-g++-64/obj/ftextralist.o temp/linux-g++-64/obj/ftfilecreator.o \ - temp/linux-g++-64/obj/ftfileprovider.o \ - temp/linux-g++-64/obj/ftfilesearch.o temp/linux-g++-64/obj/ftserver.o \ - temp/linux-g++-64/obj/fttransfermodule.o \ - temp/linux-g++-64/obj/ftturtlefiletransferitem.o \ - temp/linux-g++-64/obj/authgpg.o temp/linux-g++-64/obj/authssl.o \ - temp/linux-g++-64/obj/pgphandler.o temp/linux-g++-64/obj/pgpkeyutil.o \ - temp/linux-g++-64/obj/rscertificate.o temp/linux-g++-64/obj/p3cfgmgr.o \ - temp/linux-g++-64/obj/p3peermgr.o temp/linux-g++-64/obj/p3linkmgr.o \ - temp/linux-g++-64/obj/p3netmgr.o temp/linux-g++-64/obj/p3notify.o \ - temp/linux-g++-64/obj/pqiqos.o temp/linux-g++-64/obj/pqiarchive.o \ - temp/linux-g++-64/obj/pqibin.o temp/linux-g++-64/obj/pqihandler.o \ - temp/linux-g++-64/obj/p3historymgr.o temp/linux-g++-64/obj/pqiipset.o \ - temp/linux-g++-64/obj/pqiloopback.o temp/linux-g++-64/obj/pqimonitor.o \ - temp/linux-g++-64/obj/pqinetwork.o temp/linux-g++-64/obj/pqiperson.o \ - temp/linux-g++-64/obj/pqipersongrp.o temp/linux-g++-64/obj/pqisecurity.o \ - temp/linux-g++-64/obj/pqiservice.o temp/linux-g++-64/obj/pqissl.o \ - temp/linux-g++-64/obj/pqissllistener.o \ - temp/linux-g++-64/obj/pqisslpersongrp.o temp/linux-g++-64/obj/pqissludp.o \ - temp/linux-g++-64/obj/pqisslproxy.o temp/linux-g++-64/obj/pqistore.o \ - temp/linux-g++-64/obj/pqistreamer.o \ - temp/linux-g++-64/obj/pqithreadstreamer.o \ - temp/linux-g++-64/obj/pqiqosstreamer.o temp/linux-g++-64/obj/sslfns.o \ - temp/linux-g++-64/obj/pqinetstatebox.o \ - temp/linux-g++-64/obj/p3face-config.o temp/linux-g++-64/obj/p3face-msgs.o \ - temp/linux-g++-64/obj/p3face-server.o temp/linux-g++-64/obj/p3history.o \ - temp/linux-g++-64/obj/p3msgs.o temp/linux-g++-64/obj/p3peers.o \ - temp/linux-g++-64/obj/p3status.o temp/linux-g++-64/obj/rsinit.o \ - temp/linux-g++-64/obj/rsloginhandler.o temp/linux-g++-64/obj/rstypes.o \ - temp/linux-g++-64/obj/p3serverconfig.o \ - temp/linux-g++-64/obj/pluginmanager.o temp/linux-g++-64/obj/dlfcn_win32.o \ - temp/linux-g++-64/obj/rspluginitems.o \ - temp/linux-g++-64/obj/rsbaseserial.o \ - temp/linux-g++-64/obj/rsfiletransferitems.o \ - temp/linux-g++-64/obj/rsserviceserialiser.o \ - temp/linux-g++-64/obj/rsconfigitems.o \ - temp/linux-g++-64/obj/rshistoryitems.o temp/linux-g++-64/obj/rsmsgitems.o \ - temp/linux-g++-64/obj/rsserial.o temp/linux-g++-64/obj/rsstatusitems.o \ - temp/linux-g++-64/obj/rstlvaddrs.o temp/linux-g++-64/obj/rstlvbase.o \ - temp/linux-g++-64/obj/rstlvfileitem.o temp/linux-g++-64/obj/rstlvimage.o \ - temp/linux-g++-64/obj/rstlvkeys.o temp/linux-g++-64/obj/rstlvkvwide.o \ - temp/linux-g++-64/obj/rstlvtypes.o temp/linux-g++-64/obj/rstlvutil.o \ - temp/linux-g++-64/obj/rstlvdsdv.o temp/linux-g++-64/obj/rsdsdvitems.o \ - temp/linux-g++-64/obj/rstlvbanlist.o \ - temp/linux-g++-64/obj/rsbanlistitems.o \ - temp/linux-g++-64/obj/rsbwctrlitems.o \ - temp/linux-g++-64/obj/rsdiscovery2items.o \ - temp/linux-g++-64/obj/rsheartbeatitems.o \ - temp/linux-g++-64/obj/rsrttitems.o temp/linux-g++-64/obj/p3chatservice.o \ - temp/linux-g++-64/obj/p3msgservice.o temp/linux-g++-64/obj/p3service.o \ - temp/linux-g++-64/obj/p3statusservice.o temp/linux-g++-64/obj/p3dsdv.o \ - temp/linux-g++-64/obj/p3banlist.o temp/linux-g++-64/obj/p3bwctrl.o \ - temp/linux-g++-64/obj/p3discovery2.o temp/linux-g++-64/obj/p3heartbeat.o \ - temp/linux-g++-64/obj/p3rtt.o temp/linux-g++-64/obj/p3turtle.o \ - temp/linux-g++-64/obj/rsturtleitem.o \ - temp/linux-g++-64/obj/folderiterator.o temp/linux-g++-64/obj/rsdebug.o \ - temp/linux-g++-64/obj/rscompress.o temp/linux-g++-64/obj/smallobject.o \ - temp/linux-g++-64/obj/rsdir.o temp/linux-g++-64/obj/rsdiscspace.o \ - temp/linux-g++-64/obj/rsnet.o temp/linux-g++-64/obj/rsnet_ss.o \ - temp/linux-g++-64/obj/extaddrfinder.o temp/linux-g++-64/obj/dnsresolver.o \ - temp/linux-g++-64/obj/rsprint.o temp/linux-g++-64/obj/rsstring.o \ - temp/linux-g++-64/obj/rsthreads.o temp/linux-g++-64/obj/rsversion.o \ - temp/linux-g++-64/obj/rswin.o temp/linux-g++-64/obj/rsaes.o \ - temp/linux-g++-64/obj/rsrandom.o temp/linux-g++-64/obj/rstickevent.o \ - temp/linux-g++-64/obj/UPnPBase.o \ - temp/linux-g++-64/obj/upnphandler_linux.o \ - temp/linux-g++-64/obj/rsnxsitems.o temp/linux-g++-64/obj/rsdataservice.o \ - temp/linux-g++-64/obj/rsgenexchange.o \ - temp/linux-g++-64/obj/rsgxsnetservice.o temp/linux-g++-64/obj/rsgxsdata.o \ - temp/linux-g++-64/obj/rsgxsitems.o \ - temp/linux-g++-64/obj/rsgxsdataaccess.o temp/linux-g++-64/obj/retrodb.o \ - temp/linux-g++-64/obj/contentvalue.o temp/linux-g++-64/obj/rsdbbind.o \ - temp/linux-g++-64/obj/gxssecurity.o temp/linux-g++-64/obj/gxstokenqueue.o \ - temp/linux-g++-64/obj/rsgxsnetutils.o temp/linux-g++-64/obj/rsgxsutil.o \ - temp/linux-g++-64/obj/p3idservice.o temp/linux-g++-64/obj/rsgxsiditems.o \ - temp/linux-g++-64/obj/p3gxscircles.o \ - temp/linux-g++-64/obj/rsgxscircleitems.o \ - temp/linux-g++-64/obj/p3gxsforums.o \ - temp/linux-g++-64/obj/rsgxsforumitems.o \ - temp/linux-g++-64/obj/p3gxschannels.o temp/linux-g++-64/obj/p3gxscommon.o \ - temp/linux-g++-64/obj/rsgxscommentitems.o \ - temp/linux-g++-64/obj/rsgxschannelitems.o temp/linux-g++-64/obj/p3wiki.o \ - temp/linux-g++-64/obj/rswikiitems.o temp/linux-g++-64/obj/p3wire.o \ - temp/linux-g++-64/obj/rswireitems.o temp/linux-g++-64/obj/p3posted.o \ - temp/linux-g++-64/obj/rsposteditems.o \ - temp/linux-g++-64/obj/p3photoservice.o \ - temp/linux-g++-64/obj/rsphotoitems.o" ; - - for(int i=0;i<5;++i) - source_string = source_string+source_string ; - - source_string = source_string.substr(0,550000) ; - - for(int i=0;i - -int processpath(std::string path); - -int main() -{ - - std::string path1 = "/home/tst1//test2///test3/"; - std::string path2 = "home2/tst4//test5///test6"; - std::string path3 = "//home3"; - std::string path4 = "//"; - std::string path5 = "/a/b/c/d/"; - std::string path6 = "a//b/c//d"; - - processpath(path1); - processpath(path2); - processpath(path3); - processpath(path4); - processpath(path5); - processpath(path6); - - return 1; -} - - -int processpath(std::string path) -{ - std::string pathtogo = path; - while(pathtogo != "") - { - std::string basedir = RsDirUtil::getRootDir(pathtogo); - std::string rempath = RsDirUtil::removeRootDir(pathtogo); - std::string topdir = RsDirUtil::getTopDir(pathtogo); - std::string remtoppath = RsDirUtil::removeTopDir(pathtogo); - - std::cerr << "Processing: \"" << pathtogo << "\"" << std::endl; - std::cerr << "\tRootDir : \"" << basedir << "\"" << std::endl; - std::cerr << "\tRemaining: \"" << rempath << "\"" << std::endl; - std::cerr << "\tTopDir : \"" << topdir << "\"" << std::endl; - std::cerr << "\tRemaining(Top): \"" << remtoppath << "\"" << std::endl; - std::cerr << std::endl; - - pathtogo = rempath; - } - return 1; -} - - - - - diff --git a/libretroshare/src/tests/util/dirtest.cc b/libretroshare/src/tests/util/dirtest.cc deleted file mode 100644 index 862a77913..000000000 --- a/libretroshare/src/tests/util/dirtest.cc +++ /dev/null @@ -1,107 +0,0 @@ - -/* - * "$Id: dirtest.cc,v 1.1 2007-02-19 20:08:30 rmf24 Exp $" - * - * RetroShare C++ Interface. - * - * Copyright 2004-2007 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - -#include "util/rsdir.h" -#include "util/utest.h" - -#include -#include -#include - -bool testRsDirUtils(std::string path); - -INITTEST() ; - -int main() -{ - - std::list dirs; - std::list::iterator it; - dirs.push_back("/incoming/htuyr/file.txt"); - dirs.push_back("/incoming/htuyr/file.txt "); - dirs.push_back("/incoming/htuyr/file.txt/"); - dirs.push_back("/incoming/htuyr/file.txt//"); - dirs.push_back("/incoming/htuyr//file.txt//"); - dirs.push_back("/incoming/htuyr//file .txt"); - dirs.push_back("/incoming/htuyr/Q"); - dirs.push_back("/incoming/htuyr/Q//"); - dirs.push_back("/incoming/htuyr/Q/"); - dirs.push_back("/incoming/htuyr/Q/text"); - dirs.push_back("/home/tst1//test2///test3/"); - dirs.push_back("home2/tst4//test5///test6"); - dirs.push_back("//home3"); - dirs.push_back("//"); - dirs.push_back("A"); - dirs.push_back("ABC"); - dirs.push_back("////ABC////"); - dirs.push_back("A/B/C"); - - for(it = dirs.begin(); it != dirs.end(); it++) - { - testRsDirUtils(*it); - } - - FINALREPORT("dirtest"); - - return TESTRESULT() ; -} - -bool testRsDirUtils(std::string path) -{ - - std::cerr << "RsUtilTest input: [" << path << "]"; - std::cerr << std::endl; - - std::string top = RsDirUtil::getTopDir(path); - std::string root = RsDirUtil::getRootDir(path); - std::string topdirs = RsDirUtil::removeRootDir(path); - std::string topdirs2 = RsDirUtil::removeRootDirs(path, root); - std::string restdirs ; - RsDirUtil::removeTopDir(path,restdirs); - std::list split; - std::list::iterator it; - RsDirUtil::breakupDirList(path, split); - - std::cerr << "\tTop: [" << top << "]"; - std::cerr << std::endl; - std::cerr << "\tRest: [" << restdirs << "]"; - std::cerr << std::endl; - - std::cerr << "\tRoot: [" << root << "]"; - std::cerr << std::endl; - std::cerr << "\tRemoveRoot: [" << topdirs << "]"; - std::cerr << std::endl; - std::cerr << "\tSplit Up "; - for(it = split.begin(); it != split.end(); it++) - { - std::cerr << ":" << (*it); - } - std::cerr << std::endl; - std::cerr << std::endl; - return true; -} diff --git a/libretroshare/src/tests/util/sha1_test.cc b/libretroshare/src/tests/util/sha1_test.cc deleted file mode 100644 index 84481aec5..000000000 --- a/libretroshare/src/tests/util/sha1_test.cc +++ /dev/null @@ -1,104 +0,0 @@ - -/* - * "$Id: dirtest.cc,v 1.1 2007-02-19 20:08:30 rmf24 Exp $" - * - * RetroShare C++ Interface. - * - * Copyright 2012-2012 by Cyril Soler - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - - -#include "util/rsdir.h" -#include "util/utest.h" -#include - -#include -#include -#include -#include - -void printHelp(int argc,char *argv[]) -{ - std::cerr << argv[0] << ": test RS sha1sum class implementation." << std::endl; - std::cerr << "Usage: " << argv[0] << " [test file]" << std::endl ; -} - -INITTEST() ; - -int main(int argc,char *argv[]) -{ - std::string inputfile ; - argstream as(argc,argv) ; - - as >> parameter('i',"input",inputfile,"input file name to hash",false) - >> help() ; - - as.defaultErrorHandling() ; - - if(inputfile.empty()) - inputfile = argv[0] ; - - FILE *f = RsDirUtil::rs_fopen(inputfile.c_str(),"r") ; - - CHECK(f != NULL) ; - - std::cerr << "Testing sha1" << std::endl; - uint32_t SIZE = 1024*1024 ; - unsigned char *buf = new unsigned char[SIZE] ; - int len = fread(buf,1,SIZE,f) ; - - std::cerr << "Read " << len << " bytes" << std::endl; - - Sha1CheckSum sum = RsDirUtil::sha1sum(buf,len) ; - { - std::cerr << std::hex << sum.fourbytes[0] << std::endl; - std::cerr << "New method : " << sum.toStdString() << std::endl; - } - - std::string hash ; - uint64_t size ; - RsDirUtil::getFileHash(inputfile.c_str(),hash,size) ; - - std::cerr << "Old method : " << hash << std::endl; - CHECK(hash == sum.toStdString()) ; - - Sha1CheckSum H(hash) ; - std::cerr << "Hashed transformed: " << H.toStdString() << std::endl; - CHECK(hash == H.toStdString()) ; - - std::cerr << "Computing all chunk hashes:" << std::endl; - - fseek(f,0,SEEK_SET) ; - int n=0 ; - - while(len = fread(buf,1,SIZE,f)) - { - Sha1CheckSum sum = RsDirUtil::sha1sum(buf,len) ; - std::cerr << "Chunk " << n << ": " << sum.toStdString() << std::endl; - n++; - } - - fclose(f) ; - - FINALREPORT("Sha1Test") ; - return TESTRESULT() ; -} - diff --git a/libretroshare/src/tests/util/test_fifo.cpp b/libretroshare/src/tests/util/test_fifo.cpp deleted file mode 100644 index 822117e5d..000000000 --- a/libretroshare/src/tests/util/test_fifo.cpp +++ /dev/null @@ -1,138 +0,0 @@ -// COMPILE_LINE: g++ test_fifo.cpp -o test_fifo -lstdc++ -I.. -// -// This is a test program for fifo previewing of files. -// Usage: -// test_fifo -i [movie file] -// -// The program creates a named pipe /tmp/fifo.avi on Linux, \\.\pipe\fifo.avi on Windows to be played with e.g. mplayer -// On Windows the mplayer needs the argument -noidx, because the pipe is not seekable -// -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#ifdef WIN32 -#include -#endif - -#ifdef WIN32 -#define myFIFO TEXT("\\\\.\\pipe\\fifo.avi") -#else -#define myFIFO "/tmp/fifo.avi" -#endif - -int main(int argc,char *argv[]) -{ - try - { - std::string movie_name ; - - argstream as(argc,argv) ; - - as >> parameter('i',"input",movie_name,"file name of the movie to preview",true) - >> help() ; - - as.defaultErrorHandling() ; - - -#ifdef WIN32 - HANDLE fifo = CreateNamedPipe(myFIFO, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE | PIPE_WAIT , 2, 1024, 1024, 2000, NULL); -#else - int status, num, fifo; - umask(0); - if (mkfifo(myFIFO, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)) - throw std::runtime_error("Cannot create fifo") ; - - fifo = open(myFIFO, O_WRONLY); - - std::cerr << "Opening fifo = " << fifo << " with file name " << myFIFO << std::endl; -#endif - -#ifdef WIN32 - if(fifo == INVALID_HANDLE_VALUE) -#else - if(fifo < 0) -#endif - { - printf("\nCan't open fifo: %s \n", strerror(errno)); - return 0; - } - -#ifdef WIN32 - printf("pipe=%p\n", fifo); - - printf("connect...\n"); - bool connected = ConnectNamedPipe(fifo, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); - if (!connected) { - printf("ConnectNamedPipe failed. error=%ld\n", GetLastError()); - return -1; - } - printf("...connected\n"); -#endif - - static const int SIZE = 1024*1024 ; // 1 MB - - void *membuf = malloc(SIZE) ; - FILE *f = fopen(movie_name.c_str(),"rb") ; - int chunk = 0; - - if(f == NULL) - throw std::runtime_error("Cannot open movie to stream into fifo") ; - - while(true) - { - int n = fread(membuf, 1, SIZE, f) ; - - if(n == 0) - break ; - -#ifdef WIN32 - DWORD dwNumberOfBytesWritten; - if (!WriteFile(fifo, membuf, n, &dwNumberOfBytesWritten, NULL) || dwNumberOfBytesWritten != (DWORD) n) { - printf("WriteFile failed. error=%ld\n", GetLastError()); -#else - if(write(fifo,membuf,SIZE) != n) { -#endif - throw std::runtime_error("Could not write chunk to fifo") ; - } - - std::cerr << "Streamed chunk " << chunk << std::endl; - if(n < SIZE) - break ; - - chunk++ ; - } - - fclose(f) ; - free(membuf) ; - -#ifdef WIN32 -// FlushFileBuffers(fifo); - DisconnectNamedPipe(fifo); -#endif - - std::cerr << "Sleeping 60 sec." << std::endl; -#ifdef WIN32 - Sleep(60000) ; - CloseHandle(fifo); -#else - sleep(60) ; - close(fifo) ; -#endif - - return 0 ; - } - catch(std::exception& e) - { - std::cerr << "Exception caught: " << e.what() << std::endl; - } -} - - diff --git a/libretroshare/src/tests/util/testcontentvalue.cpp b/libretroshare/src/tests/util/testcontentvalue.cpp deleted file mode 100644 index 17993aaab..000000000 --- a/libretroshare/src/tests/util/testcontentvalue.cpp +++ /dev/null @@ -1,374 +0,0 @@ - -#include - -#include "retrodb.h" -#include "utest.h" - -bool operator==(const ContentValue& lCV, ContentValue& rCV){ - - std::map leftKtMap, rightKtMap; - lCV.getKeyTypeMap(leftKtMap); - rCV.getKeyTypeMap(rightKtMap); - - return (leftKtMap == rightKtMap); -} - - -/*! - * Test content value ability to take a set of data and ability to get it out - * For all data types - */ -void testEnterAndRetrieve(); - -/*! - * Check to see if copy constructor intialises - * 'this' correctly - */ -void testCopyConstructor(); - -/*! - * check that key type map returned is consistent - * with data contained in ContentValue - */ -void testGetKeyTypeMap(); - -/*! - * Test the clearing functionality - */ -void testClear(); - -/*! - * check errors are meaningful - */ -void testErrors(); - -/*! - * enter the same key twice and ensure previous data gets overwritten - * - */ -void testSameKey(); - - -INITTEST(); - -int main(){ - - testEnterAndRetrieve(); - testCopyConstructor(); - testClear(); - testSameKey(); - testGetKeyTypeMap(); - testErrors(); - - FINALREPORT("TEST_CONTENT_VALUE"); -} - - -void testSameKey(){ - - - ContentValue cv; - - // test data - - std::string src = "adalkjalfalfalfkal"; - const char* data = src.data(); - uint32_t data_len = src.length(); - std::string data_key = "private_key"; - cv.put(data_key, data_len, data); - - std::string other_src = "daldko5202402224"; - data_len = other_src.length(); - data = other_src.data(); - - cv.put(data_key, data_len, data); - - uint32_t val_len; - char* val; - cv.getAsData(data_key, val_len, val); - std::string str_val(val, val_len); - - - CHECK(str_val == other_src); - - // now check string - - std::string key = "peer"; - cv.put(key, std::string("sexy_girl")); - cv.put(key, std::string("manly man")); - - std::string val_str; - cv.getAsString(key, val_str); - - CHECK(val_str == "manly man"); - - // and double - - cv.put(key, 4.); - cv.put(key, 32.); - double val_d; - cv.getAsDouble(key, val_d); - CHECK(val_d == 32.); - - // and int64 - int64_t large(20420492040123); - cv.put(key, large); - cv.put(key, large+34); - int64_t val_i64; - cv.getAsInt64(key, val_i64); - - CHECK(val_i64 == large+34); - - // and bool - - cv.put(key, false); - cv.put(key, true); - bool bool_val = false; - cv.getAsBool(key, bool_val); - - CHECK(bool_val == true); - - // and int32 - - int32_t medium = 20432123; - cv.put(key, medium); - cv.put(key, medium+34); - int32_t val_i32; - cv.getAsInt32(key, val_i32); - - CHECK(val_i32 == medium+34); - - REPORT("testSameKey()"); -} - - -void testErrors(){ - - - ContentValue cv; - int32_t val_32; - int64_t val_64; - char* data; - uint32_t data_len; - std::string val_str; - bool val_bool; - double val_d; - CHECK(!cv.getAsInt32("dda", val_32)); - CHECK(!cv.getAsInt64("dda", val_64)); - CHECK(!cv.getAsData("ds", data_len, data)); - CHECK(!cv.getAsString("d3536356336356356s", val_str)); - CHECK(!cv.getAsBool("d424s", val_bool)); - CHECK(!cv.getAsDouble("daads", val_d)); - - REPORT("testErrors()"); -} - -void testEnterAndRetrieve(){ - - // INT 32 - int32_t value32 = 1, retval32; - std::string key = "one"; - - ContentValue cv; - cv.put(key, value32); - - cv.getAsInt32(key, retval32); - CHECK(value32 == retval32); - - // INT 64 - int64_t value64 = 423425242, retval64; - key = "int64"; - cv.put(key, value64); - cv.getAsInt64(key, retval64); - CHECK(value64 == retval64); - - - // Double - double dvalue = 3.5, retvaldbl; - key = "double"; - cv.put(key, dvalue); - cv.getAsDouble(key, retvaldbl); - CHECK(dvalue == retvaldbl ); - - // BLOB - uint32_t data_len = 45, get_len = 0; - - char* src = new char[data_len]; - char* get_src = NULL; - memset(src, '$', data_len); - key = "data"; - cv.put(key, data_len, src); - - cv.getAsData(key, get_len, get_src); - - bool fine = true; - - CHECK(get_len = data_len); - - if(data_len == get_len){ - - for(int i=0; i < data_len; i++){ - - if(src[i] != get_src[i]) - fine &= false; - - } - } - - delete[] src; - CHECK(fine); - - // STRING - std::string strVal = "whoo", getVal(""); - key = "string"; - cv.put(key, strVal); - cv.getAsString(key, getVal); - - CHECK(getVal == strVal); - - - // BOOL - bool mefalse = false, retvalBool; - key = "bool"; - cv.put(key, mefalse); - cv.getAsBool(key, retvalBool); - CHECK(mefalse == retvalBool); - - cv.clear(); - - REPORT("testEnterAndRetrieve()"); -} - -void testGetKeyTypeMap(){ - - ContentValue cv; - std::string key1="key1", key2="key2", key3="key3", key4="key4"; - std::string key1_val; - int32_t key2_val = 42; - double key3_val = 23; - int64_t key4_val = 42052094224; - - cv.put(key1, key1_val); - cv.put(key2, key2_val); - cv.put(key3, key3_val); - cv.put(key4, key4_val); - - std::map kvMap; - - cv.getKeyTypeMap(kvMap); - - CHECK(kvMap.size() == 4); - CHECK(kvMap[key1] == ContentValue::STRING_TYPE); - CHECK(kvMap[key2] == ContentValue::INT32_TYPE); - CHECK(kvMap[key3] == ContentValue::DOUBLE_TYPE); - CHECK(kvMap[key4] == ContentValue::INT64_TYPE); - - REPORT("testGetKeyTypeMap()"); -} - -void testCopyConstructor(){ - - ContentValue cv1; - - // INT 32 - int value32 = 1; - std::string key = "one"; - - cv1.put(key, value32); - - // INT 64 - int64_t value64 = 423425242; - key = "int64"; - cv1.put(key, value64); - - // Double - double dvalue = 3.5; - key = "double"; - cv1.put(key, dvalue); - - // BLOB - uint32_t data_len = 45; - char* src = new char[data_len]; - - memset(src, '$', data_len); - key = "data"; - cv1.put(key, data_len, src); - - - delete[] src; - - // STRING - std::string strVal = "whoo"; - key = "string"; - cv1.put(key, strVal); - - // BOOL - bool mefalse = false; - key = "bool"; - cv1.put(key, mefalse); - - ContentValue cv2(cv1); - - CHECK(cv1 == cv2); - - cv1.clear(); - cv2.clear(); - - REPORT("testCopyConstructor()"); -} - - -void testClear(){ - - ContentValue cv1; - - // INT 32 - int value32 = 1; - std::string key = "one"; - - cv1.put(key, value32); - - // INT 64 - int64_t value64 = 423425242; - key = "int64"; - cv1.put(key, value64); - - // Double - double dvalue = 3.5; - key = "double"; - cv1.put(key, dvalue); - - // BLOB - uint32_t data_len = 45; - char* src = new char[data_len]; - - memset(src, '$', data_len); - key = "data"; - cv1.put(key, data_len, src); - - - delete[] src; - - // STRING - std::string strVal = "whoo"; - key = "string"; - cv1.put(key, strVal); - - // BOOL - bool mefalse = false; - key = "bool"; - cv1.put(key, mefalse); - - std::map ktMap; - - cv1.getKeyTypeMap(ktMap); - CHECK(ktMap.size() > 0); - - cv1.clear(); - - cv1.getKeyTypeMap(ktMap); - CHECK(ktMap.size() == 0); - - REPORT("testClear()"); - -} diff --git a/libretroshare/src/tests/util/testretrocursor.cpp b/libretroshare/src/tests/util/testretrocursor.cpp deleted file mode 100644 index 78d77e483..000000000 --- a/libretroshare/src/tests/util/testretrocursor.cpp +++ /dev/null @@ -1,127 +0,0 @@ - -#include -#include -#include -#include "util/rstime.h" - -#include "retrodb.h" -#include "utest.h" - - -#define INT32_KEY "day" -#define INT64_KEY "pub_key" -#define DATA_KEY "data" -#define DOUBLE_KEY "a_double" -#define STRING_KEY "a_string" -#define BOOL_KEY "a_bool" - -#define DB_FILE_NAME "RetroDb" - -static RetroDb* mDb = NULL; - -void createRetroDb(); -void destroyRetroDb(); - -INITTEST(); -// mainly test ability to move up and down result set - - -void testTraverseResult(); - - -int main() { - - testTraverseResult(); - - FINALREPORT("RETRO CURSOR TEST"); - return 0; -} - - - -void createRetroDb(){ - - if(mDb) - destroyRetroDb(); - - - remove(DB_FILE_NAME); // account for interrupted tests - mDb = new RetroDb(DB_FILE_NAME, RetroDb::OPEN_READWRITE_CREATE); -} - -void destroyRetroDb(){ - if(mDb == NULL) - return; - - mDb->closeDb(); - delete mDb; - mDb = NULL; - int rc = remove(DB_FILE_NAME); - std::cerr << "remove code: " << rc << std::endl; - - if(rc !=0){ - perror("Could not delete db: "); - - } -} - - -void testTraverseResult(){ - - - createRetroDb(); - - bool statementExecuted = mDb->execSQL("CREATE TABLE retroDB(day INTEGER PRIMARY KEY ASC, pub_key INT, data BLOB, a_double REAL, a_string VARCHAR(255), a_bool INT);"); - CHECK(statementExecuted); - - ContentValue cv; - - cv.put(INT32_KEY, (int32_t)20); - int64_t large_num = 32432242344423; - cv.put(INT64_KEY, large_num); - std::string str = "3dajaojaljfacjlafĀ£%Ā£^%\"%\"%$"; - const char* data = str.data(); - int size = str.size(); - cv.put(DATA_KEY, size, data); - cv.put(DOUBLE_KEY, 3.14); - cv.put(STRING_KEY, "hello precious"); - cv.put(BOOL_KEY, false); - - bool insertExecuted = mDb->sqlInsert("retroDB", "", cv); - cv.put(INT32_KEY, (int32_t)21); - insertExecuted &= mDb->sqlInsert("retroDB", "", cv); - cv.put(INT32_KEY, (int32_t)2); - insertExecuted &= mDb->sqlInsert("retroDB", "", cv); - cv.put(INT32_KEY, (int32_t)204); - insertExecuted &= mDb->sqlInsert("retroDB", "", cv); - cv.put(INT32_KEY, (int32_t)22); - insertExecuted &= mDb->sqlInsert("retroDB", "", cv); - - CHECK(insertExecuted); - - std::list columns; - columns.push_back(INT32_KEY); columns.push_back(INT64_KEY); columns.push_back(DOUBLE_KEY); - columns.push_back(DATA_KEY); columns.push_back(BOOL_KEY); columns.push_back(STRING_KEY); - std::string orderBy = std::string(INT32_KEY) + " ASC"; - RetroCursor* cursor = mDb->sqlQuery("retroDB", columns, "", orderBy); - - CHECK(cursor->getResultCount() == 5); - cursor->moveToFirst(); - CHECK(cursor->getPosition() == 0); - - cursor->moveToLast(); - CHECK(cursor->getPosition() == cursor->getResultCount()); - - cursor->moveToFirst(); - - CHECK(cursor->getInt32(0) == 2); - cursor->moveToNext(); - cursor->moveToNext(); - - CHECK(cursor->getInt32(0) == 21); - - delete cursor; - - REPORT("testTraverseResult()"); - destroyRetroDb(); -} diff --git a/libretroshare/src/tests/util/testretrodb.cpp b/libretroshare/src/tests/util/testretrodb.cpp deleted file mode 100644 index 37b9d7d84..000000000 --- a/libretroshare/src/tests/util/testretrodb.cpp +++ /dev/null @@ -1,352 +0,0 @@ - -#include -#include -#include -#include "util/rstime.h" - -#include "retrodb.h" -#include "utest.h" - - -#define DAY_KEY "day" -#define PUB_KEY "pub_key" -#define DATA_KEY "data" -#define DOUBLE_KEY "a_double" - -#define DB_FILE_NAME "RetroDb" - -static RetroDb* mDb = NULL; - -void createRetroDb(); -void destroyRetroDb(); - -void testSqlExec(); -void testSqlUpdate(); -void testSqlInsert(); -void testSqlDelete(); -void testSqlQuery(); -void testBinaryInsertion(); - -INITTEST(); - -int main(){ - - testSqlExec(); - testBinaryInsertion(); - testSqlInsert(); - testSqlUpdate(); - testSqlDelete(); - testSqlQuery(); - - FINALREPORT("RETRO DB TEST"); - return 0; -} - -void createRetroDb(){ - - if(mDb) - destroyRetroDb(); - - - remove(DB_FILE_NAME); // account for interrupted tests - mDb = new RetroDb(DB_FILE_NAME, RetroDb::OPEN_READWRITE_CREATE); -} - -void destroyRetroDb(){ - if(mDb == NULL) - return; - - mDb->closeDb(); - delete mDb; - mDb = NULL; - int rc = remove(DB_FILE_NAME); - std::cerr << "remove code: " << rc << std::endl; - - if(rc !=0){ - perror("Could not delete db: "); - - } -} - -void testSqlExec(){ - - createRetroDb(); - - // create simple table - bool statementExecuted = mDb->execSQL("CREATE TABLE retroDB(day INTEGER PRIMARY KEY ASC, pub_key, data);"); - statementExecuted &= mDb->execSQL("INSERT INTO retroDB(day, pub_key, data) VALUES(1,2,3);"); - statementExecuted &= mDb->execSQL("INSERT INTO retroDB(day, pub_key, data) VALUES(3,4525624,4524);"); - - CHECK(statementExecuted); - - // now check if you can retrieve records - std::list columns; - columns.push_back("day"); - columns.push_back("pub_key"); - columns.push_back("data"); - - std::string selection, orderBy; - RetroCursor* c = mDb->sqlQuery("retroDB", columns, selection, orderBy); - - - CHECK(c->getResultCount() == 2); - - // got to first record - c->moveToFirst(); - int32_t first =c->getInt32(0), second = c->getInt32(1), - third = c->getInt32(2); - - - CHECK(first == 1); - CHECK(second == 2); - CHECK(third == 3); - - // get 2nd record - c->moveToNext(); - - first =c->getInt32(0), second = c->getInt32(1), - third = c->getInt32(2); - - CHECK(first == 3); - CHECK(second == 4525624); - CHECK(third == 4524); - - delete c; - - REPORT("testSqlExec()"); - destroyRetroDb(); -} - -void testBinaryInsertion(){ - - createRetroDb(); - // create simple table - bool statementExecuted = mDb->execSQL("CREATE TABLE retroDB(day INTEGER PRIMARY KEY ASC, data BLOB);"); - statementExecuted &= mDb->execSQL("INSERT INTO retroDB(day, data) VALUES(1, 'dafadfad%$£%^£%%\"$R\"$\"$\"');"); - - // now check if you can retrieve records - std::list columns; - columns.push_back("day"); - columns.push_back("data"); - - std::string selection, orderBy; - RetroCursor* c = mDb->sqlQuery("retroDB", columns, selection, orderBy); - - c->moveToFirst(); - int first = c->getInt32(0); - uint32_t size; - const char* data = (const char*)c->getData(1, size); - std::string str = "dafadfad%$£%^£%%\"$R\"$\"$\""; - const char* data_comp = str.data(); - bool binCompare = ok; - - for(int i=0; i < 24 ; i++) - binCompare &= data[i] == data_comp[i]; - - CHECK(first == 1); - CHECK(binCompare); - - delete c; - REPORT("testBinaryInsertion()"); - destroyRetroDb(); -} - - - - -void testSqlUpdate(){ - - createRetroDb(); - - bool statementExecuted = mDb->execSQL("CREATE TABLE retroDB(day INTEGER PRIMARY KEY ASC, data BLOB, peerId VARCHAR(255), time INT);"); - CHECK(statementExecuted); - - std::string data = "dadJOOodaodaoro20r2-0r20002ri02fgi3t0***"; - ContentValue cv; - - cv.put("day", (int32_t)20); - std::string peerid = "TheRetroSquad"; - cv.put("peerId", peerid); - cv.put("data", data.size(), data.data()); - int64_t now = time(NULL); - cv.put("time", now); - bool insertExecuted = mDb->sqlInsert("retroDB", "", cv); - - CHECK(insertExecuted); - - // now check entry is fine - - std::list columns; - columns.push_back("day"); columns.push_back("peerId"); columns.push_back("data"); columns.push_back("time"); - - RetroCursor* c = mDb->sqlQuery("retroDB", columns, "", ""); - - CHECK(c->getResultCount() == 1); - std::string result; - c->moveToFirst(); - c->getString(1, result); - - CHECK(result == peerid); - - delete c; - c = NULL; - - // now make an update and see if this is reflected - - int64_t now_plus = now+203; - cv.put("time", now_plus); - bool update = mDb->sqlUpdate("retroDB", "", cv); - CHECK(update); - c = mDb->sqlQuery("retroDB", columns, "", ""); - c->moveToFirst(); - int64_t now_plus_compare = c->getDouble(3); - - CHECK(now_plus_compare == now_plus); - - // now attempt an update which should find no valid record - - - delete c; - - REPORT("testSqlUpdate()"); - destroyRetroDb(); -} - -void testSqlInsert(){ - - createRetroDb(); - - bool statementExecuted = mDb->execSQL("CREATE TABLE retroDB(day INTEGER PRIMARY KEY ASC, a_double DOUBLE, data BLOB);"); - CHECK(statementExecuted); - - ContentValue cv; - - cv.put("day", (int32_t)20); - std::string str = "3dajaojaljfacjlaf£%£^%\"%\"%$"; - const char* data = str.data(); - int size = 27; - cv.put(DATA_KEY, size, data); - cv.put(DOUBLE_KEY, 3.14); - bool insertExecuted = mDb->sqlInsert("retroDB", "", cv); - - std::list columns; - columns.push_back("day"); columns.push_back("a_double"); columns.push_back("data"); - RetroCursor* cursor = mDb->sqlQuery("retroDB", columns, "", ""); - - CHECK(cursor != NULL); - - cursor->moveToFirst(); - - CHECK(20 == cursor->getInt32(0)); - CHECK(3.14 == cursor->getDouble(1)); - - CHECK(insertExecuted); - - delete cursor; - FINALREPORT("testSqlInsert()"); - destroyRetroDb(); -} - -void testSqlQuery(){ - // test ordering of data and selection clause - - - createRetroDb(); - - // create simple table - bool statementExecuted = mDb->execSQL("CREATE TABLE retroDB(priority INTEGER PRIMARY KEY ASC, name VARCHAR(255), friends, games INTEGER);"); - statementExecuted &= mDb->execSQL("INSERT INTO retroDB(priority, name, friends, games) VALUES(4,'sammy',2,30);"); - statementExecuted &= mDb->execSQL("INSERT INTO retroDB(priority, name, friends, games) VALUES(2,'davy',6,9);"); - statementExecuted &= mDb->execSQL("INSERT INTO retroDB(priority, name, friends, games) VALUES(6,'pammy',2,4);"); - statementExecuted &= mDb->execSQL("INSERT INTO retroDB(priority, name, friends, games) VALUES(5,'tommy',3,4534);"); - statementExecuted &= mDb->execSQL("INSERT INTO retroDB(priority, name, friends, games) VALUES(9,'jonny',3,44);"); - - CHECK(statementExecuted); - - std::list columns; - columns.push_back("name"); - std::string selection = "games <= 31"; - std::string orderBy = "priority DESC"; - - - // output should be by name: pammy, sammy and davy - RetroCursor* cursor = mDb->sqlQuery("retroDB", columns,selection, orderBy); - - cursor->moveToFirst(); - std::string name; - cursor->getString(0,name); - CHECK(name == "pammy"); - - cursor->moveToNext(); - cursor->getString(0,name); - CHECK(name == "sammy"); - - cursor->moveToNext(); - cursor->getString(0,name); - CHECK(name == "davy"); - - - delete cursor; - FINALREPORT("testSqlQuery()"); - destroyRetroDb(); - return; -} - -void testSqlDelete(){ - - createRetroDb(); - - bool statementExecuted = mDb->execSQL("CREATE TABLE retroDB(day INTEGER PRIMARY KEY ASC, a_double DOUBLE, data BLOB);"); - CHECK(statementExecuted); - - ContentValue cv; - - cv.put("day", (int32_t)20); - std::string str = "3dajaojaljfacjlaf£%£^%\"%\"%$"; - const char* data = str.data(); - uint32_t size = str.size(); - cv.put(DATA_KEY, size, data); - cv.put(DOUBLE_KEY, 3.14); - - // insert to records - bool insertExecuted = mDb->sqlInsert("retroDB", "", cv); - cv.put("day", (int32_t(5))); - CHECK(insertExecuted); - mDb->sqlInsert("retroDB", "", cv); - - - // now check that their are two records in the db - std::list columns; - columns.push_back("day"); columns.push_back("a_double"); columns.push_back("data"); - RetroCursor* cursor = mDb->sqlQuery("retroDB", columns, "", ""); - CHECK(cursor->getResultCount() == 2); - delete cursor; - // now remove a record and search for the removed record, query should return no records - mDb->sqlDelete("retroDB", "day=5", ""); - - - cursor = mDb->sqlQuery("retroDB", columns, "day=5", ""); - CHECK(cursor->getResultCount() == 0); - delete cursor; - - // now check for the remaining record - cursor = mDb->sqlQuery("retroDB", columns, "day=20", ""); - CHECK(cursor->getResultCount() == 1); - cursor->moveToFirst(); - - // verify there is no data corruption - const char* data_comp1 = (const char*)cursor->getData(2, size); - const char* data_comp2 = str.data(); - - bool binCompare = true; - - for(int i=0; i < str.size() ; i++) - binCompare &= data_comp1[i] == data_comp2[i]; - - CHECK(binCompare); - - delete cursor; - - FINALREPORT("testSqlDelete()"); - destroyRetroDb(); -} diff --git a/libretroshare/src/tor/AddOnionCommand.cpp b/libretroshare/src/tor/AddOnionCommand.cpp deleted file mode 100644 index e06bb3ede..000000000 --- a/libretroshare/src/tor/AddOnionCommand.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2016, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "AddOnionCommand.h" -#include "HiddenService.h" -#include "CryptoKey.h" -#include "StrUtil.h" - -using namespace Tor; - -AddOnionCommand::AddOnionCommand(HiddenService *service) - : m_service(service), mSucceeded([](){}), mFailed([](int){}) -{ - assert(m_service); -} - -bool AddOnionCommand::isSuccessful() const -{ - return statusCode() == 250 && m_errorMessage.empty(); -} - -ByteArray AddOnionCommand::build() -{ - ByteArray out("ADD_ONION"); - - if (m_service->privateKey().isLoaded()) { - out += " "; - out += m_service->privateKey().bytes(); - } else { - //out += " NEW:RSA1024"; // this is v2. For v3, use NEW:BEST, or NEW:ED25519-V3 - //out += " NEW:ED25519-V3"; // this is v3. - out += " NEW:BEST"; // this is v3, but without control of key type. Generates a RSA1024 key on older Tor versions. - } - - for(const HiddenService::Target& target: m_service->targets()) - { - out += " Port="; - out += RsUtil::NumberToString(target.servicePort); - out += ","; - out += target.targetAddress; - out += ":"; - out += RsUtil::NumberToString(target.targetPort); - } - - out.append("\r\n"); - return out; -} - -void AddOnionCommand::onReply(int statusCode, const ByteArray &data) -{ - TorControlCommand::onReply(statusCode, data); - if (statusCode != 250) { - m_errorMessage = data.toString(); - return; - } - - const ByteArray keyPrefix("PrivateKey="); - const ByteArray sidPrefix("ServiceID="); - - if(data.startsWith(sidPrefix)) - { - ByteArray service_id = data.mid(sidPrefix.size()); - m_service->setServiceId(service_id); - } - - if (data.startsWith(keyPrefix)) - { - ByteArray keyData(data.mid(keyPrefix.size())); - CryptoKey key; - - if (!key.loadFromTorMessage(keyData)) { - m_errorMessage = "Key structure check failed"; - return; - } - - m_service->setPrivateKey(key); - } -} - -void AddOnionCommand::onFinished(int statusCode) -{ - TorControlCommand::onFinished(statusCode); - if (isSuccessful()) - mSucceeded(); - else - mFailed(statusCode); -} - - diff --git a/libretroshare/src/tor/AddOnionCommand.h b/libretroshare/src/tor/AddOnionCommand.h deleted file mode 100644 index 4b20de986..000000000 --- a/libretroshare/src/tor/AddOnionCommand.h +++ /dev/null @@ -1,66 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2016, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include "TorControlCommand.h" - -namespace Tor -{ - -class HiddenService; - -class AddOnionCommand : public TorControlCommand -{ -public: - AddOnionCommand(HiddenService *service); - - ByteArray build(); - - std::string errorMessage() const { return m_errorMessage; } - bool isSuccessful() const; - - void set_succeeded_callback(const std::function& f) { mSucceeded=f;} - void set_failed_callback(const std::function& f) { mFailed=f;} - -protected: - HiddenService *m_service; - std::string m_errorMessage; - - std::function mSucceeded; - std::function mFailed; - - virtual void onReply(int statusCode, const ByteArray &data); - virtual void onFinished(int statusCode); -}; - -} diff --git a/libretroshare/src/tor/AuthenticateCommand.cpp b/libretroshare/src/tor/AuthenticateCommand.cpp deleted file mode 100644 index ab510c24b..000000000 --- a/libretroshare/src/tor/AuthenticateCommand.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "AuthenticateCommand.h" - -using namespace Tor; - -AuthenticateCommand::AuthenticateCommand() -{ -} - -ByteArray AuthenticateCommand::build(const ByteArray& data) -{ - if (data.isNull()) - return ByteArray("AUTHENTICATE\r\n"); - - return ByteArray("AUTHENTICATE ") + data.toHex() + "\r\n"; -} - -void AuthenticateCommand::onReply(int statusCode, const ByteArray &data) -{ - TorControlCommand::onReply(statusCode, data); - m_statusMessage = data.toString(); -} - -void AuthenticateCommand::onFinished(int statusCode) -{ - if (statusCode == 515) { - m_statusMessage = "Authentication failed - incorrect password"; - } - else if (statusCode != 250) - { - if (m_statusMessage.empty()) - m_statusMessage = "Authentication failed (error " + RsUtil::NumberToString(statusCode) + ")"; - } - TorControlCommand::onFinished(statusCode); -} diff --git a/libretroshare/src/tor/AuthenticateCommand.h b/libretroshare/src/tor/AuthenticateCommand.h deleted file mode 100644 index 1d520ea22..000000000 --- a/libretroshare/src/tor/AuthenticateCommand.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include "bytearray.h" -#include "TorControlCommand.h" - -namespace Tor -{ - -class AuthenticateCommand : public TorControlCommand -{ -public: - AuthenticateCommand(); - - ByteArray build(const ByteArray& data = ByteArray()); - - bool isSuccessful() const { return statusCode() == 250; } - std::string errorMessage() const { return m_statusMessage; } - -protected: - virtual void onReply(int statusCode, const ByteArray &data); - virtual void onFinished(int statusCode); - -private: - std::string m_statusMessage; -}; - -} diff --git a/libretroshare/src/tor/CryptoKey.cpp b/libretroshare/src/tor/CryptoKey.cpp deleted file mode 100644 index 802caaf0c..000000000 --- a/libretroshare/src/tor/CryptoKey.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "CryptoKey.h" - -#include -#include -#include - -#include "stdio.h" -#include "util/rsdebug.h" -#include "util/rsrandom.h" -#include "util/rsdir.h" -#include "retroshare/rsids.h" -#include "bytearray.h" - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) -void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q) -{ - *p = r->p; - *q = r->q; -} -#define RSA_bits(o) (BN_num_bits((o)->n)) -#endif - -CryptoKey::CryptoKey() -{ -} - -CryptoKey::~CryptoKey() -{ - clear(); -} - -void CryptoKey::clear() -{ - key_data.clear(); -} - -bool CryptoKey::loadFromFile(const std::string& path) -{ - FILE *file = fopen(path.c_str(),"r"); - - if (!file) - { - RsWarn() << "Failed to open Tor key file " << path << ": errno = " << errno ; - return false; - } - - ByteArray data ; - int c; - while(EOF != (c=fgetc(file))) - data.push_back((unsigned char)c); - - fclose(file); - - if(data.startsWith("-----BEGIN RSA PRIVATE KEY-----")) - { - std::cerr << "Note: Reading/converting Tor v2 key format." << std::endl; - - // This to be compliant with old format. New format is oblivious to the type of key so we dont need a header - data = data.replace(ByteArray("-----BEGIN RSA PRIVATE KEY-----"),ByteArray()); - data = data.replace(ByteArray("-----END RSA PRIVATE KEY-----"),ByteArray()); - data = data.replace(ByteArray("\n"),ByteArray()); - data = data.replace(ByteArray("\t"),ByteArray()); - - data = ByteArray("RSA1024:")+data; - } - - std::cerr << "Have read the following key: " << std::endl; - std::cerr << data.toString() << std::endl; - - key_data = data; - - return true; -} - -bool CryptoKey::loadFromTorMessage(const ByteArray& b) -{ - // note: We should probably check the structure a bit more, for security. - - std::cerr << "Loading new key:" << std::endl; - - if(b.startsWith("RSA1024")) - std::cerr << " type: RSA-1024 (Tor v2)" << std::endl; - else if(b.startsWith("ED25519-V3")) - std::cerr << " type: ED25519-V3 (Tor v3)" << std::endl; - else if(b.indexOf(':')) - { - std::cerr << " unknown type, or bad syntax in key: \"" << b.left(b.indexOf(':')).toString() << "\". Not accepted." << std::endl; - return false; - } - - key_data = b; - return true; -} - -/* Cryptographic hash of a password as expected by Tor's HashedControlPassword */ -ByteArray torControlHashedPassword(const ByteArray &password) -{ - ByteArray salt(8); - RsRandom::random_bytes(&salt[0],8); - - uint32_t count = ((uint32_t)16 + (96 & 15)) << ((96 >> 4) + 6); - - SHA_CTX hash; - SHA1_Init(&hash); - - ByteArray tmp = salt + password; - while (count) - { - int c = std::min((size_t)count, tmp.size()); - SHA1_Update(&hash, reinterpret_cast(tmp.data()), c); - count -= c; - } - - unsigned char md[20]; - SHA1_Final(md, &hash); - - /* 60 is the hex-encoded value of 96, which is a constant used by Tor's algorithm. */ - return ByteArray("16:") + salt.toHex().toUpper() + ByteArray("60") + ByteArray(md, 20).toHex().toUpper(); -} diff --git a/libretroshare/src/tor/CryptoKey.h b/libretroshare/src/tor/CryptoKey.h deleted file mode 100644 index ab6fb320f..000000000 --- a/libretroshare/src/tor/CryptoKey.h +++ /dev/null @@ -1,64 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include "bytearray.h" - -class CryptoKey -{ -public: - enum KeyType { - PrivateKey, - PublicKey - }; - - enum KeyFormat { - PEM, - DER - }; - - CryptoKey(); - ~CryptoKey(); - - bool loadFromFile(const std::string &path); - void clear(); - - const ByteArray bytes() const { return key_data; } - bool loadFromTorMessage(const ByteArray& b); - bool isLoaded() const { return !key_data.isNull(); } - -private: - ByteArray key_data; -}; - -ByteArray torControlHashedPassword(const ByteArray &password); diff --git a/libretroshare/src/tor/GetConfCommand.cpp b/libretroshare/src/tor/GetConfCommand.cpp deleted file mode 100644 index 02f903b4a..000000000 --- a/libretroshare/src/tor/GetConfCommand.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "GetConfCommand.h" -#include "StrUtil.h" - -using namespace Tor; - -GetConfCommand::GetConfCommand(Type t) - : type(t) -{ -} - -ByteArray GetConfCommand::build(const std::string &key) -{ - return build(std::list { key } ); -} - -ByteArray GetConfCommand::build(const std::list &keys) -{ - ByteArray out; - if (type == GetConf) { - out = "GETCONF"; - } else if (type == GetInfo) { - out = "GETINFO"; - } else { - assert(false); - return out; - } - - for(const ByteArray &key: keys) { - out.push_back(' '); - out.append(key); - } - - out.append("\r\n"); - return out; -} - -void GetConfCommand::onReply(int statusCode, const ByteArray &data) -{ - TorControlCommand::onReply(statusCode, data); - if (statusCode != 250) - return; - - int kep = data.indexOf('='); - std::string key = data.mid(0, kep).toString(); - std::string value; - if (kep >= 0) - value = unquotedString(data.mid(kep + 1)).toString(); - - m_lastKey = key; - m_results[key].push_back(value); -} - -void GetConfCommand::onDataLine(const ByteArray &data) -{ - if (m_lastKey.empty()) { - RsWarn() << "torctrl: Unexpected data line in GetConf command"; - return; - } - m_results[m_lastKey].push_back(data.toString()); -} - -void GetConfCommand::onDataFinished() -{ - m_lastKey.clear(); -} - -std::list GetConfCommand::get(const std::string& key) const -{ - auto it = m_results.find(key); - - if(it != m_results.end()) - return it->second; - else - return std::list(); -} - diff --git a/libretroshare/src/tor/GetConfCommand.h b/libretroshare/src/tor/GetConfCommand.h deleted file mode 100644 index d3ca3bfc3..000000000 --- a/libretroshare/src/tor/GetConfCommand.h +++ /dev/null @@ -1,68 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include -#include "TorControlCommand.h" - -namespace Tor -{ - -class GetConfCommand : public TorControlCommand -{ -public: - enum Type { - GetConf, - GetInfo - }; - const Type type; - - GetConfCommand(Type type); - - ByteArray build(const std::string &key); - ByteArray build(const std::list &keys); - - const std::map > &results() const { return m_results; } - std::list get(const std::string &key) const; - -protected: - virtual void onReply(int statusCode, const ByteArray &data); - virtual void onDataLine(const ByteArray &data); - virtual void onDataFinished(); - -private: - std::map > m_results; - std::string m_lastKey; -}; - -} diff --git a/libretroshare/src/tor/HiddenService.cpp b/libretroshare/src/tor/HiddenService.cpp deleted file mode 100644 index a6b083eae..000000000 --- a/libretroshare/src/tor/HiddenService.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "HiddenService.h" -#include "TorControl.h" -#include "CryptoKey.h" -#include "util/rsdir.h" - -#include - -using namespace Tor; - -HiddenService::HiddenService(HiddenServiceClient *client) - : m_status(NotCreated), m_client(client) -{ -} - -HiddenService::HiddenService(HiddenServiceClient *client,const std::string& path) - : m_dataPath(path), m_status(NotCreated), m_client(client) -{ - /* Set the initial status and, if possible, load the hostname */ - if(RsDirUtil::fileExists(m_dataPath + "/private_key")) - { - loadPrivateKey(); - if (!m_hostname.empty()) - m_status = Offline; - } -} - -HiddenService::HiddenService(HiddenServiceClient *client,const CryptoKey &privateKey, const std::string &path) - : m_dataPath(path), m_status(NotCreated), m_client(client) -{ - setPrivateKey(privateKey); - m_status = Offline; -} - -void HiddenService::setStatus(Status newStatus) -{ - if (m_status == newStatus) - return; - - Status old = m_status; - m_status = newStatus; - - if(m_client) - m_client->hiddenServiceStatusChanged(m_status,old); //emit statusChanged(m_status, old); - - if (m_status == Online) - if(m_client) - m_client->hiddenServiceOnline(); //emit serviceOnline(); -} - -void HiddenService::addTarget(const Target &target) -{ - m_targets.push_back(target); -} - -void HiddenService::addTarget(uint16_t servicePort, std::string targetAddress, uint16_t targetPort) -{ - Target t = { targetAddress, servicePort, targetPort }; - m_targets.push_back(t); -} - -void HiddenService::setServiceId(const ByteArray& sid) -{ - m_service_id = sid; - m_hostname = sid.toString() + ".onion"; - - if(m_client) - m_client->hiddenServiceHostnameChanged(); // emit hostnameChanged(); -} -void HiddenService::setPrivateKey(const CryptoKey &key) -{ - if (m_privateKey.isLoaded()) { - RsErr() << "Cannot change the private key on an existing HiddenService"; - return; - } - - m_privateKey = key; - - if(m_client) - m_client->hiddenServicePrivateKeyChanged(); //emit privateKeyChanged(); -} - -bool HiddenService::loadPrivateKey() -{ - if (m_privateKey.isLoaded() || m_dataPath.empty()) - return false; - - bool ok = m_privateKey.loadFromFile(m_dataPath + "/private_key"); - - if (!ok) { - RsWarn() << "Failed to load hidden service key"; - return false; - } - - // Also load the onion address stored in "hostname" file. This is not needed, except for early display - // of the onion address, since the onion address will be re-computed by Tor (to the same value) when the - // service is published. - - std::ifstream i((m_dataPath + "/hostname").c_str()); - - if(i) - { - std::string s; - i >> s; - if(ByteArray(s).endsWith(ByteArray(".onion"))) - { - m_hostname = s; - m_service_id = s.substr(0,s.length() - std::string(".onion").length()); - - RsDbg() << "Read existing hostname: " << m_hostname; - } - i.close(); - } - - if(m_client) - m_client->hiddenServicePrivateKeyChanged(); // emit privateKeyChanged(); - - return true; -} - -void HiddenService::servicePublished() -{ - loadPrivateKey(); - - if (m_hostname.empty()) { - std::cerr << "Failed to read hidden service hostname" << std::endl; - return; - } - - std::cerr << "Hidden service published successfully" << std::endl; - setStatus(Online); -} - diff --git a/libretroshare/src/tor/HiddenService.h b/libretroshare/src/tor/HiddenService.h deleted file mode 100644 index 604d8083f..000000000 --- a/libretroshare/src/tor/HiddenService.h +++ /dev/null @@ -1,109 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include "CryptoKey.h" -#include "bytearray.h" - -namespace Tor -{ - -// This class is used to receive synchroneous notifications from the hidden service. -// Each client should implement its own notification handling. - -class HiddenServiceClient -{ -public: - virtual void hiddenServiceStatusChanged(int /* newStatus */, int /* oldStatus */) =0; - virtual void hiddenServiceOnline() =0; - virtual void hiddenServicePrivateKeyChanged() =0; - virtual void hiddenServiceHostnameChanged() =0; -}; - -class HiddenService -{ - friend class TorControl; - -public: - struct Target - { - std::string targetAddress; - uint16_t servicePort, targetPort; - }; - - enum Status - { - NotCreated = -1, /* Service has not been created yet */ - Offline = 0, /* Data exists, but service is not published */ - Online /* Published */ - }; - - HiddenService(HiddenServiceClient *client); - HiddenService(HiddenServiceClient *client, const std::string &dataPath); - HiddenService(HiddenServiceClient *client, const CryptoKey &privateKey, const std::string &dataPath = std::string()); - - Status status() const { return m_status; } - - const std::string& hostname() const { return m_hostname; } - const std::string serviceId() const { return m_service_id.toString(); } - const std::string& dataPath() const { return m_dataPath; } - - CryptoKey privateKey() { return m_privateKey; } - void setPrivateKey(const CryptoKey &privateKey); - void setServiceId(const ByteArray &sid); - - const std::list &targets() const { return m_targets; } - void addTarget(const Target &target); - void addTarget(uint16_t servicePort, std::string targetAddress, uint16_t targetPort); - - void servicePublished(); - -private: - std::string m_dataPath; - std::list m_targets; - std::string m_hostname; - Status m_status; - CryptoKey m_privateKey; - ByteArray m_service_id; - - bool loadPrivateKey(); - void setStatus(Status newStatus); - - HiddenServiceClient *m_client; - - // make the object non copyable - HiddenService(const HiddenService&) {} - HiddenService& operator=(const HiddenService&) { return *this ; } -}; - -} diff --git a/libretroshare/src/tor/PendingOperation.cpp b/libretroshare/src/tor/PendingOperation.cpp deleted file mode 100644 index ec6a9b6fd..000000000 --- a/libretroshare/src/tor/PendingOperation.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include "PendingOperation.h" - -PendingOperation::PendingOperation() - : m_finished(false),mFinishedCallback([](){}), mSuccessCallback([](){}),mErrorCallback([](const std::string&){}) -{ -} - -bool PendingOperation::isFinished() const -{ - return m_finished; -} - -bool PendingOperation::isSuccess() const -{ - return m_finished && m_errorMessage.empty(); -} - -bool PendingOperation::isError() const -{ - return m_finished && !m_errorMessage.empty(); -} - -std::string PendingOperation::errorMessage() const -{ - return m_errorMessage; -} - -void PendingOperation::finishWithError(const std::string &message) -{ - if (message.empty()) - m_errorMessage = "Unknown Error"; - m_errorMessage = message; - - if (!m_finished) { - m_finished = true; - - mErrorCallback(m_errorMessage); - mFinishedCallback(); - } -} - -void PendingOperation::finishWithSuccess() -{ - assert(m_errorMessage.empty()); - - if (!m_finished) { - m_finished = true; - - if (isSuccess()) - mSuccessCallback(); - - mFinishedCallback(); - } -} - diff --git a/libretroshare/src/tor/PendingOperation.h b/libretroshare/src/tor/PendingOperation.h deleted file mode 100644 index cec170f9e..000000000 --- a/libretroshare/src/tor/PendingOperation.h +++ /dev/null @@ -1,74 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include -#include - -/* Represents an asynchronous operation for reporting status - * - * This class is used for asynchronous operations that report a - * status and errors when finished, particularly for exposing them - * to QML. - * - * Subclass PendingOperation to implement your operation's logic. - * You also need to handle the object's lifetime, for example by - * calling deleteLater() when finished() is emitted. - * - * PendingOperation will emit finished() and one of success() or - * error() when completed. - */ -class PendingOperation -{ -public: - PendingOperation(); - - bool isFinished() const; - bool isSuccess() const; - bool isError() const; - std::string errorMessage() const; - - void finishWithError(const std::string &errorMessage); - void finishWithSuccess(); - - void set_finished_callback(const std::function& f) { mFinishedCallback = f; } -private: - bool m_finished; - std::string m_errorMessage; - - std::function mFinishedCallback; - std::function mSuccessCallback; - std::function mErrorCallback; - -}; - diff --git a/libretroshare/src/tor/ProtocolInfoCommand.cpp b/libretroshare/src/tor/ProtocolInfoCommand.cpp deleted file mode 100644 index cdb7d648b..000000000 --- a/libretroshare/src/tor/ProtocolInfoCommand.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ProtocolInfoCommand.h" -#include "TorControl.h" -#include "StrUtil.h" - -using namespace Tor; - -ProtocolInfoCommand::ProtocolInfoCommand(TorControl *m) - : manager(m),m_authMethods(0) -{ -} - -ByteArray ProtocolInfoCommand::build() -{ - return ByteArray("PROTOCOLINFO 1\r\n"); -} - -void ProtocolInfoCommand::onReply(int statusCode, const ByteArray &data) -{ - TorControlCommand::onReply(statusCode, data); - if (statusCode != 250) - return; - - if (data.startsWith("AUTH ")) - { - std::list tokens = splitQuotedStrings(data.mid(5), ' '); - - for(ByteArray token: tokens) - { - if (token.startsWith("METHODS=")) - { - std::list textMethods = unquotedString(token.mid(8)).split(','); - - for (std::list::iterator it = textMethods.begin(); it != textMethods.end(); ++it) - { - if (*it == "NULL") - m_authMethods |= AuthNull; - else if (*it == "HASHEDPASSWORD") - m_authMethods |= AuthHashedPassword; - else if (*it == "COOKIE") - m_authMethods |= AuthCookie; - } - } - else if (token.startsWith("COOKIEFILE=")) - { - m_cookieFile = unquotedString(token.mid(11)).toString(); - } - } - } - else if (data.startsWith("VERSION Tor=")) - { - m_torVersion = unquotedString(data.mid(12, data.indexOf(' ', 12))).toString(); - } -} diff --git a/libretroshare/src/tor/ProtocolInfoCommand.h b/libretroshare/src/tor/ProtocolInfoCommand.h deleted file mode 100644 index b90e2fe7c..000000000 --- a/libretroshare/src/tor/ProtocolInfoCommand.h +++ /dev/null @@ -1,72 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include "TorControlCommand.h" -#include "retroshare/rsflags.h" - -namespace Tor -{ - -class TorControl; - -class ProtocolInfoCommand : public TorControlCommand -{ -public: - enum - { - AuthUnknown = 0x0, - AuthNull = 0x1, - AuthHashedPassword = 0x2, - AuthCookie = 0x4 - }; - typedef uint8_t AuthMethod; - - ProtocolInfoCommand(TorControl *manager); - ByteArray build(); - - AuthMethod authMethods() const { return m_authMethods; } - std::string torVersion() const { return m_torVersion; } - std::string cookieFile() const { return m_cookieFile; } - -protected: - virtual void onReply(int statusCode, const ByteArray &data); - -private: - TorControl *manager; - AuthMethod m_authMethods; - std::string m_torVersion; - std::string m_cookieFile; -}; - -} diff --git a/libretroshare/src/tor/SetConfCommand.cpp b/libretroshare/src/tor/SetConfCommand.cpp deleted file mode 100644 index 463305731..000000000 --- a/libretroshare/src/tor/SetConfCommand.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "SetConfCommand.h" -#include "StrUtil.h" - -using namespace Tor; - -SetConfCommand::SetConfCommand() - : m_resetMode(false), mConfSucceeded([](){}), mConfFailed([](int){}) -{ -} - -void SetConfCommand::setResetMode(bool enabled) -{ - m_resetMode = enabled; -} - -bool SetConfCommand::isSuccessful() const -{ - return statusCode() == 250; -} - -ByteArray SetConfCommand::build(const std::string &key, const std::string &value) -{ - return build(std::list > { std::make_pair(key, value) } ); -} - -ByteArray SetConfCommand::build(const std::list >& data) -{ - ByteArray out(m_resetMode ? "RESETCONF" : "SETCONF"); - - for (auto& p:data) - { - out += " " ; - out += p.first; - - if (!p.second.empty()) - { - out += "=" ; - out += quotedString(p.second); - } - } - - out.append("\r\n"); - return out; -} - -void SetConfCommand::onReply(int statusCode, const ByteArray &data) -{ - TorControlCommand::onReply(statusCode, data); - if (statusCode != 250) - m_errorMessage = data.toString(); -} - -void SetConfCommand::onFinished(int statusCode) -{ - TorControlCommand::onFinished(statusCode); - if (isSuccessful()) - mConfSucceeded(); - else - mConfFailed(statusCode); -} - diff --git a/libretroshare/src/tor/SetConfCommand.h b/libretroshare/src/tor/SetConfCommand.h deleted file mode 100644 index bf7713038..000000000 --- a/libretroshare/src/tor/SetConfCommand.h +++ /dev/null @@ -1,68 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include -#include "TorControlCommand.h" - -namespace Tor -{ - -class SetConfCommand : public TorControlCommand -{ -public: - SetConfCommand(); - - void setResetMode(bool resetMode); - - ByteArray build(const std::string &key, const std::string &value); - ByteArray build(const std::list > &data); - - std::string errorMessage() const { return m_errorMessage; } - bool isSuccessful() const; - - void set_ConfSucceeded_callback(const std::function& f) { mConfSucceeded=f; } - void set_ConfFailed_callback (const std::function& f){ mConfFailed=f; } - -protected: - std::string m_errorMessage; - bool m_resetMode; - - std::function mConfSucceeded; - std::function mConfFailed; - - virtual void onReply(int statusCode, const ByteArray &data); - virtual void onFinished(int statusCode); -}; - -} diff --git a/libretroshare/src/tor/StrUtil.cpp b/libretroshare/src/tor/StrUtil.cpp deleted file mode 100644 index 558013fef..000000000 --- a/libretroshare/src/tor/StrUtil.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "StrUtil.h" - -ByteArray quotedString(const ByteArray &string) -{ - ByteArray out; - out.reserve(string.size() * 2); - - out.push_back('"'); - - for (ByteArray::size_type i = 0; i < string.size(); ++i) - { - switch (string[i]) - { - case '"': - out.append("\\\""); - break; - case '\\': - out.append("\\\\"); - break; - default: - out.push_back(string[i]); - break; - } - } - - out.push_back('"'); - return out; -} - -ByteArray unquotedString(const ByteArray& string) -{ - if (string.size() < 2 || string[0] != '"') - return string; - - ByteArray out; - out.reserve(string.size() - 2); - - for (ByteArray::size_type i = 1; i < string.size(); ++i) - { - switch (string[i]) - { - case '\\': - if (++i < string.size()) - out.push_back(string[i]); - break; - case '"': - return out; - default: - out.push_back(string[i]); - } - } - - return out; -} - -std::list splitQuotedStrings(const ByteArray &input, char separator) -{ - std::list out; - bool inquote = false; - ByteArray::size_type start = 0; - - for (ByteArray::size_type i = 0; i < input.size(); ++i) - { - switch (input[i]) - { - case '"': - inquote = !inquote; - break; - case '\\': - if (inquote) - ++i; - break; - } - - if (!inquote && input[i] == separator) - { - out.push_back(input.mid(start, i - start)); - start = i+1; - } - } - - if (start < input.size()) - out.push_back(input.mid(start)); - - return out; -} diff --git a/libretroshare/src/tor/StrUtil.h b/libretroshare/src/tor/StrUtil.h deleted file mode 100644 index 8f986a9a8..000000000 --- a/libretroshare/src/tor/StrUtil.h +++ /dev/null @@ -1,47 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef STRINGUTIL_H -#define STRINGUTIL_H - -#include - -#include "bytearray.h" - -ByteArray quotedString(const ByteArray &string); - -/* Return the unquoted contents of a string, either until an end quote or an unescaped separator character. */ -ByteArray unquotedString(const ByteArray &string); - -std::list splitQuotedStrings(const ByteArray& input, char separator); - -#endif // STRINGUTIL_H diff --git a/libretroshare/src/tor/TorControl.cpp b/libretroshare/src/tor/TorControl.cpp deleted file mode 100644 index 9b456036b..000000000 --- a/libretroshare/src/tor/TorControl.cpp +++ /dev/null @@ -1,793 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include "util/rsdir.h" - -#include "retroshare/rstor.h" -#include "TorControl.h" -#include "TorControlSocket.h" -#include "HiddenService.h" -#include "ProtocolInfoCommand.h" -#include "AuthenticateCommand.h" -#include "SetConfCommand.h" -#include "GetConfCommand.h" -#include "AddOnionCommand.h" -#include "StrUtil.h" -#include "PendingOperation.h" - -class nullstream: public std::ostream {}; - -static std::ostream& torctrldebug() -{ - static nullstream null ; - - if(true) - return std::cerr << time(NULL) << ":TOR CONTROL: " ; - else - return null ; -} - -#define torCtrlDebug torctrldebug - -using namespace Tor; - -TorControl::TorControl() - : mControlPort(0),mSocksPort(0),mStatus(NotConnected), mTorStatus(TorUnknown),mHasOwnership(false) -{ - mSocket = new TorControlSocket(this); -} - -TorControl::~TorControl() -{ - delete(mSocket); -} - -static RsTorConnectivityStatus torConnectivityStatus(Tor::TorControl::Status t) -{ - switch(t) - { - default: - case TorControl::Error: return RsTorConnectivityStatus::ERROR; - case TorControl::NotConnected: return RsTorConnectivityStatus::NOT_CONNECTED; - case TorControl::Connecting: return RsTorConnectivityStatus::CONNECTING; - case TorControl::SocketConnected: return RsTorConnectivityStatus::SOCKET_CONNECTED; - case TorControl::Authenticating: return RsTorConnectivityStatus::AUTHENTICATING; - case TorControl::Authenticated: return RsTorConnectivityStatus::AUTHENTICATED; - case TorControl::HiddenServiceReady: return RsTorConnectivityStatus::HIDDEN_SERVICE_READY; - case TorControl::Unknown: return RsTorConnectivityStatus::UNKNOWN; - } -} -static RsTorStatus torStatus(Tor::TorControl::TorStatus t) -{ - switch(t) - { - default: - case TorControl::TorUnknown: return RsTorStatus::UNKNOWN; - case TorControl::TorOffline: return RsTorStatus::OFFLINE; - case TorControl::TorReady: return RsTorStatus::READY; - } -} - -void TorControl::setStatus(TorControl::Status n) -{ - if (n == mStatus) - return; - - TorControl::Status old = mStatus; - mStatus = n; - - if (old == TorControl::Error) - mErrorMessage.clear(); - - std::cerr << "Setting status to s=" << mStatus << " val=" << (int)torConnectivityStatus(mStatus) << std::endl; - - if(rsEvents) - { - auto ev = std::make_shared(); - - ev->mTorManagerEventType = RsTorManagerEventCode::TOR_STATUS_CHANGED; - ev->mTorStatus = ::torStatus(mTorStatus); - ev->mTorConnectivityStatus = torConnectivityStatus(mStatus); - - rsEvents->sendEvent(ev); - } - mStatusChanged_callback(mStatus, old); -} - -void TorControl::setTorStatus(TorControl::TorStatus n) -{ - if (n == mTorStatus) - return; - - RsDbg() << "Setting TorStatus=" << n ; - mTorStatus = n; - - if(rsEvents) - { - auto ev = std::make_shared(); - - ev->mTorManagerEventType = RsTorManagerEventCode::TOR_STATUS_CHANGED; - ev->mTorStatus = ::torStatus(mTorStatus); - ev->mTorConnectivityStatus = torConnectivityStatus(mStatus); - - rsEvents->sendEvent(ev); - } -} - -void TorControl::setError(const std::string &message) -{ - mErrorMessage = message; - setStatus(TorControl::Error); - - RsWarn() << "torctrl: Error:" << mErrorMessage; -} - -TorControl::Status TorControl::status() const -{ - return mStatus; -} - -TorControl::TorStatus TorControl::torStatus() const -{ - return mTorStatus; -} - -std::string TorControl::torVersion() const -{ - return mTorVersion; -} - -std::string TorControl::errorMessage() const -{ - return mErrorMessage; -} - -bool TorControl::hasConnectivity() const -{ - return torStatus() == TorReady && !mSocksAddress.empty(); -} - -std::string TorControl::socksAddress() const -{ - return mSocksAddress; -} - -uint16_t TorControl::socksPort() const -{ - return mSocksPort; -} - -std::list TorControl::hiddenServices() const -{ - return mServices; -} - -std::map TorControl::bootstrapStatus() const -{ - return mBootstrapStatus; -} - -void TorControl::setAuthPassword(const ByteArray &password) -{ - mAuthPassword = password; -} - -void TorControl::connect(const std::string &address, uint16_t port) -{ - if (status() > Connecting) - { - torCtrlDebug() << "Ignoring TorControl::connect due to existing connection" << std::endl; - return; - } - - mTorAddress = address; - mControlPort = port; - setTorStatus(TorUnknown); - - if(mSocket->isRunning()) - mSocket->fullstop(); - - setStatus(Connecting); - - if(mSocket->connectToHost(address, port)) - { - setStatus(SocketConnected); - setTorStatus(TorOffline); // connected and running, but not yet ready - } -} - -void TorControl::reconnect() -{ - assert(!mTorAddress.empty() && mControlPort); - - if (mTorAddress.empty() || !mControlPort || status() >= Connecting) - return; - - setStatus(Connecting); - mSocket->connectToHost(mTorAddress, mControlPort); -} - -void TorControl::authenticateReply(TorControlCommand *sender) -{ - AuthenticateCommand *command = dynamic_cast(sender); - assert(command); - assert(mStatus == TorControl::Authenticating); - if (!command) - return; - - if (!command->isSuccessful()) { - setError(command->errorMessage()); - return; - } - - torCtrlDebug() << "torctrl: Authentication successful" << std::endl; - setStatus(TorControl::Authenticated); - - TorControlCommand *clientEvents = new TorControlCommand; - clientEvents->set_replyLine_callback([this](int code, const ByteArray &data) { statusEvent(code,data);}); - - mSocket->registerEvent(ByteArray("STATUS_CLIENT"), clientEvents); - - getTorInfo(); - publishServices(); - - // XXX Fix old configurations that would store unwanted options in torrc. - // This can be removed some suitable amount of time after 1.0.4. - if (mHasOwnership) - saveConfiguration(); -} - - -void TorControl::authenticate() -{ - assert(mStatus == TorControl::SocketConnected); - - setStatus(TorControl::Authenticating); - torCtrlDebug() << "torctrl: Connected socket; querying information for authentication" << std::endl; - - ProtocolInfoCommand *command = new ProtocolInfoCommand(this); - - command->set_finished_callback( [this](TorControlCommand *sender) { protocolInfoReply(sender); }); - command->set_replyLine_callback([this](int code, const ByteArray &data) { statusEvent(code,data); }); - - mSocket->sendCommand(command, command->build()); -} - -void TorControl::socketDisconnected() -{ - /* Clear some internal state */ - mTorVersion.clear(); - mSocksAddress.clear(); - mSocksPort = 0; - setTorStatus(TorControl::TorUnknown); - - /* This emits the disconnected() signal as well */ - setStatus(TorControl::NotConnected); -} - -void TorControl::socketError(const std::string& s) -{ - setError("Connection failed: " + s); -} - -void TorControl::protocolInfoReply(TorControlCommand *sender) -{ - ProtocolInfoCommand *info = dynamic_cast(sender); - if (!info) - return; - - mTorVersion = info->torVersion(); - - if (mStatus == TorControl::Authenticating) - { - AuthenticateCommand *auth = new AuthenticateCommand; - - auth->set_finished_callback( [this](TorControlCommand *sender) { authenticateReply(sender); }); - - ByteArray data; - ProtocolInfoCommand::AuthMethod methods = info->authMethods(); - - if(methods & ProtocolInfoCommand::AuthNull) - { - torCtrlDebug() << "torctrl: Using null authentication" << std::endl; - data = auth->build(); - } - else if ((methods & ProtocolInfoCommand::AuthCookie) && !info->cookieFile().empty()) - { - std::string cookieFile = info->cookieFile(); - std::string cookieError; - torCtrlDebug() << "torctrl: Using cookie authentication with file" << cookieFile << std::endl; - - FILE *f = fopen(cookieFile.c_str(),"r"); - - if(f) - { - std::string cookie; - char c; - while((c=getc(f))!=EOF) - cookie += c; - fclose(f); - - /* Simple test to avoid a vulnerability where any process listening on what we think is - * the control port could trick us into sending the contents of an arbitrary file */ - if (cookie.size() == 32) - data = auth->build(cookie); - else - cookieError = "Unexpected file size"; - } - else - cookieError = "Cannot open file " + cookieFile + ". errno=" + RsUtil::NumberToString(errno); - - if (!cookieError.empty() || data.isNull()) - { - /* If we know a password and password authentication is allowed, try using that instead. - * This is a strange corner case that will likely never happen in a normal configuration, - * but it has happened. */ - if ((methods & ProtocolInfoCommand::AuthHashedPassword) && !mAuthPassword.empty()) - { - torCtrlDebug() << "torctrl: Unable to read authentication cookie file:" << cookieError << std::endl; - goto usePasswordAuth; - } - - setError("Unable to read authentication cookie file: " + cookieError); - delete auth; - return; - } - } - else if ((methods & ProtocolInfoCommand::AuthHashedPassword) && !mAuthPassword.empty()) - { - usePasswordAuth: - torCtrlDebug() << "torctrl: Using hashed password authentication with AuthPasswd=\"" << mAuthPassword.toString() << "\"" << std::endl; - data = auth->build(mAuthPassword); - } - else - { - if (methods & ProtocolInfoCommand::AuthHashedPassword) - setError("Tor requires a control password to connect, but no password is configured."); - else - setError("Tor is not configured to accept any supported authentication methods."); - delete auth; - return; - } - - mSocket->sendCommand(auth, data); - } -} - -void TorControl::getTorInfo() -{ - assert(isConnected()); - - GetConfCommand *command = new GetConfCommand(GetConfCommand::GetInfo); - //connect(command, &TorControlCommand::finished, this, &TorControl::getTorInfoReply); - command->set_finished_callback( [this](TorControlCommand *sender) { getTorInfoReply(sender); }); - command->set_replyLine_callback([this](int code, const ByteArray &data) { statusEvent(code,data); }); - - std::list keys{ "status/circuit-established","status/bootstrap-phase" }; - - keys.push_back("net/listeners/socks"); - - mSocket->sendCommand(command, command->build(keys)); -} - -void TorControl::getTorInfoReply(TorControlCommand *sender) -{ - GetConfCommand *command = dynamic_cast(sender); - if (!command) - return; - - std::list listenAddresses = splitQuotedStrings(command->get("net/listeners/socks").front(), ' '); - - for (const auto& add:listenAddresses) { - ByteArray value = unquotedString(add); - int sepp = value.indexOf(':'); - std::string address(value.mid(0, sepp).toString()); - uint16_t port = (uint16_t)value.mid(sepp+1).toInt(); - - /* Use the first address that matches the one used for this control connection. If none do, - * just use the first address and rely on the user to reconfigure if necessary (not a problem; - * their setup is already very customized) */ - if (mSocksAddress.empty() || address == mSocket->peerAddress()) { - mSocksAddress = address; - mSocksPort = port; - if (address == mSocket->peerAddress()) - break; - } - } - - /* It is not immediately an error to have no SOCKS address; when DisableNetwork is set there won't be a - * listener yet. To handle that situation, we'll try to read the socks address again when TorReady state - * is reached. */ - if (!mSocksAddress.empty()) { - torCtrlDebug() << "torctrl: SOCKS address is " << mSocksAddress << ":" << mSocksPort << std::endl; - - if(rsEvents) - { - auto ev = std::make_shared(); - - ev->mTorManagerEventType = RsTorManagerEventCode::TOR_CONNECTIVITY_CHANGED; - ev->mTorConnectivityStatus = torConnectivityStatus(mStatus); - ev->mTorStatus = ::torStatus(mTorStatus); - rsEvents->sendEvent(ev); - } - } - - if (ByteArray(command->get("status/circuit-established").front()).toInt() == 1) - { - torCtrlDebug() << "torctrl: Tor indicates that circuits have been established; state is TorReady" << std::endl; - setTorStatus(TorControl::TorReady); - } -// else -// setTorStatus(TorControl::TorOffline); - - auto bootstrap = command->get("status/bootstrap-phase"); - if (!bootstrap.empty()) - updateBootstrap(splitQuotedStrings(bootstrap.front(), ' ')); -} - -void TorControl::addHiddenService(HiddenService *service) -{ - if (std::find(mServices.begin(),mServices.end(),service) != mServices.end()) - return; - - mServices.push_back(service); -} - -void TorControl::publishServices() -{ - torCtrlDebug() << "Publish Services... " ; - - assert(isConnected()); - if (mServices.empty()) - { - std::cerr << "No service regstered!" << std::endl; - return; - } - std::cerr << std::endl; - - if (torVersionAsNewAs("0.2.7")) { - for(HiddenService *service: mServices) - { - if (service->hostname().empty()) - torCtrlDebug() << "torctrl: Creating a new hidden service" << std::endl; - else - torCtrlDebug() << "torctrl: Publishing hidden service: " << service->hostname() << std::endl; - AddOnionCommand *onionCommand = new AddOnionCommand(service); - //protocolInfoReplyQObject::connect(onionCommand, &AddOnionCommand::succeeded, service, &HiddenService::servicePublished); - onionCommand->set_succeeded_callback( [this,service]() { checkHiddenService(service) ; }); - mSocket->sendCommand(onionCommand, onionCommand->build()); - } - } else { - torCtrlDebug() << "torctrl: Using legacy SETCONF hidden service configuration for tor" << mTorVersion << std::endl; - SetConfCommand *command = new SetConfCommand; - std::list > torConfig; - - for(HiddenService *service: mServices) - { - if (service->dataPath().empty()) - continue; - - if (service->privateKey().isLoaded() && !RsDirUtil::fileExists(service->dataPath() + "/private_key")) { - // This case can happen if tor is downgraded after the profile is created - RsWarn() << "Cannot publish ephemeral hidden services with this version of tor; skipping"; - continue; - } - - torCtrlDebug() << "torctrl: Configuring hidden service at" << service->dataPath() << std::endl; - - torConfig.push_back(std::make_pair("HiddenServiceDir", service->dataPath())); - - const std::list &targets = service->targets(); - for (auto tit:targets) - { - std::string target = RsUtil::NumberToString(tit.servicePort) + " " - +tit.targetAddress + ":" - +RsUtil::NumberToString(tit.targetPort); - torConfig.push_back(std::make_pair("HiddenServicePort", target)); - } - - command->set_ConfSucceeded_callback( [this,service]() { checkHiddenService(service); }); - //QObject::connect(command, &SetConfCommand::setConfSucceeded, service, &HiddenService::servicePublished); - } - - if (!torConfig.empty()) - mSocket->sendCommand(command, command->build(torConfig)); - } -} - -void TorControl::checkHiddenService(HiddenService *service) -{ - service->servicePublished(); - - if(service->status() == HiddenService::Online) - { - RsDbg() << "Hidden service published and ready!" ; - - setStatus(TorControl::HiddenServiceReady); - } -} - -void TorControl::shutdown() -{ - if (!hasOwnership()) { - RsWarn() << "torctrl: Ignoring shutdown command for a tor instance I don't own"; - return; - } - - mSocket->sendCommand(ByteArray("SIGNAL SHUTDOWN\r\n")); -} - -void TorControl::shutdownSync() -{ - if (!hasOwnership()) { - RsWarn() << "torctrl: Ignoring shutdown command for a tor instance I don't own"; - return; - } - - shutdown(); - while (mSocket->moretowrite(0)) - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - - mSocket->close(); -} - -void TorControl::statusEvent(int /* code */, const ByteArray &data) -{ - std::list tokens = splitQuotedStrings(data.trimmed(), ' '); - if (tokens.size() < 3) - return; - - const ByteArray& tok2 = *(++(++tokens.begin())); - torCtrlDebug() << "torctrl: status event:" << data.trimmed().toString() << " tok2=\"" << tok2.toString() << "\"" << std::endl; - - if (tok2 == "CIRCUIT_ESTABLISHED") - setTorStatus(TorControl::TorReady); - else if (tok2 == "CIRCUIT_NOT_ESTABLISHED") - setTorStatus(TorControl::TorOffline); - else if (tok2 == "BOOTSTRAP") - { - tokens.pop_front(); - updateBootstrap(tokens); - } -} - -void TorControl::updateBootstrap(const std::list &data) -{ - std::cerr << "********** Updating bootstrap status ************" << std::endl; - mBootstrapStatus.clear(); - // WARN or NOTICE - mBootstrapStatus["severity"] = (*data.begin()).toString(); - - auto dat = data.begin(); - ++dat; - - for(;dat!=data.end();++dat) { // for(int i = 1; i < data.size(); i++) { - int equals = (*dat).indexOf('='); - ByteArray key = (*dat).mid(0, equals); - ByteArray value; - - if (equals >= 0) - value = unquotedString((*dat).mid(equals + 1)); - - mBootstrapStatus[key.toLower().toString()] = value.toString(); - } - - if(rsEvents) - { - auto ev = std::make_shared(); - - ev->mTorManagerEventType = RsTorManagerEventCode::BOOTSTRAP_STATUS_CHANGED; - ev->mTorConnectivityStatus = torConnectivityStatus(mStatus); - ev->mTorStatus = ::torStatus(mTorStatus); - rsEvents->sendEvent(ev); - } -} - -TorControlCommand *TorControl::getConfiguration(const std::string& options) -{ - GetConfCommand *command = new GetConfCommand(GetConfCommand::GetConf); - command->set_replyLine_callback([this](int code, const ByteArray &data) { statusEvent(code,data); }); - mSocket->sendCommand(command, command->build(options)); - - return command; -} - -TorControlCommand *TorControl::setConfiguration(const std::list >& options) -{ - SetConfCommand *command = new SetConfCommand; - command->setResetMode(true); - mSocket->sendCommand(command, command->build(options)); - - return command; -} - -namespace Tor { - -class SaveConfigOperation : public PendingOperation -{ -public: - SaveConfigOperation() - : PendingOperation(), command(0) - { - } - - void start(TorControlSocket *socket) - { - assert(!command); - command = new GetConfCommand(GetConfCommand::GetInfo); - command->set_finished_callback([this](TorControlCommand *sender){ configTextReply(sender); }); - - socket->sendCommand(command, command->build(std::list { "config-text" , "config-file" } )); - } - - void configTextReply(TorControlCommand * /*sender*/) - { - assert(command); - if (!command) - return; - - auto lpath = command->get("config-file"); - std::string path = (lpath.empty()?std::string():lpath.front()); - - if (path.empty()) { - finishWithError("Cannot write torrc without knowing its path"); - return; - } - - // Out of paranoia, refuse to write any file not named 'torrc', or if the - // file doesn't exist - - auto filename = RsDirUtil::getFileName(path); - - if(filename != "torrc" || !RsDirUtil::fileExists(path)) - { - finishWithError("Refusing to write torrc to unacceptable path " + path); - return; - } - - std::ofstream file(path); - - if (!file.is_open()) { - finishWithError("Failed opening torrc file for writing: permissions error?"); - return; - } - - // Remove these keys when writing torrc; they are set at runtime and contain - // absolute paths or port numbers - static const char *bannedKeys[] = { - "ControlPortWriteToFile", - "DataDirectory", - "HiddenServiceDir", - "HiddenServicePort", - 0 - }; - - auto configText = command->get("config-text") ; - - for(const auto& value: configText) - { - ByteArray line(value); - - bool skip = false; - for (const char **key = bannedKeys; *key; key++) { - if (line.startsWith(*key)) { - skip = true; - break; - } - } - if (skip) - continue; - - file << line.toString() << std::endl; - } - - file.close(); - - torCtrlDebug() << "torctrl: Wrote torrc file" << std::endl; - finishWithSuccess(); - } - -private: - GetConfCommand *command; -}; - -} - -PendingOperation *TorControl::saveConfiguration() -{ - if (!hasOwnership()) { - RsWarn() << "torctrl: Ignoring save configuration command for a tor instance I don't own"; - return 0; - } - - SaveConfigOperation *operation = new SaveConfigOperation(); - - operation->set_finished_callback( [operation]() { delete operation; }); - operation->start(mSocket); - - return operation; -} - -bool TorControl::hasOwnership() const -{ - return mHasOwnership; -} - -void TorControl::takeOwnership() -{ - mHasOwnership = true; - mSocket->sendCommand(ByteArray("TAKEOWNERSHIP\r\n")); - - // Reset PID-based polling - std::list > options; - options.push_back(std::make_pair("__OwningControllerProcess",std::string())); - setConfiguration(options); -} - -bool TorControl::torVersionAsNewAs(const std::string& match) const -{ - auto split = ByteArray(torVersion()).split(ByteArray(".-")); - auto matchSplit = ByteArray(match).split(ByteArray(".-")); - - int split_size = split.size(); - auto b_split(split.begin()); - auto b_matchsplit(matchSplit.begin()); - - for(int i=0;;) - { - int currentVal,matchVal; - bool ok1 = RsUtil::StringToInt((*b_split).toString(),currentVal); - bool ok2 = RsUtil::StringToInt((*b_matchsplit).toString(),matchVal); - - if (!ok1 || !ok2) - return false; - if (currentVal > matchVal) - return true; - if (currentVal < matchVal) - return false; - - ++i; - - if(i >= split_size) - return false; - - ++b_split; - ++b_matchsplit; - } - - // Versions are equal, up to the length of match - return true; -} - - diff --git a/libretroshare/src/tor/TorControl.h b/libretroshare/src/tor/TorControl.h deleted file mode 100644 index be73aa3f4..000000000 --- a/libretroshare/src/tor/TorControl.h +++ /dev/null @@ -1,152 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include - -#include "PendingOperation.h" -#include "bytearray.h" -#include "TorControlSocket.h" - - -namespace Tor -{ - -class HiddenService; -class TorControlSocket; -class TorControlCommand; - -class TorControl : public TorControlSocketClient -{ -public: - enum Status - { - Error = 0x00, - NotConnected = 0x01, - Connecting = 0x02, - SocketConnected = 0x03, - Authenticating = 0x04, - Authenticated = 0x05, - HiddenServiceReady = 0x06, - Unknown = 0x07 - }; - - enum TorStatus - { - TorUnknown = 0x00, - TorOffline = 0x01, - TorReady = 0x02 - }; - - explicit TorControl(); - virtual ~TorControl(); - - /* Information */ - Status status() const; - TorStatus torStatus() const; - std::string torVersion() const; - bool torVersionAsNewAs(const std::string &version) const; - std::string errorMessage() const; - - bool hasConnectivity() const; - std::string socksAddress() const; - uint16_t socksPort() const; - - /* Authentication */ - void setAuthPassword(const ByteArray& password); - - /* Connection */ - bool isConnected() const { return status() >= Authenticated; } - void connect(const std::string &address, uint16_t port); - void authenticate(); - - /* Ownership means that tor is managed by this socket, and we - * can shut it down, own its configuration, etc. */ - bool hasOwnership() const; - void takeOwnership(); - - /* Hidden Services */ - std::list hiddenServices() const; - void addHiddenService(HiddenService *service); - - std::map bootstrapStatus() const; - TorControlCommand *getConfiguration(const std::string &options); - TorControlCommand *setConfiguration(const std::list > &options); - PendingOperation *saveConfiguration(); - - void set_statusChanged_callback(const std::function& f) { mStatusChanged_callback = f ;} - void set_connected_callback(const std::function& f) { mConnected_callback = f ;} - void set_disconnected_callback(const std::function& f) { mDisconnected_callback = f ;} - - virtual void socketError(const std::string &s) override; - - /* Instruct Tor to shutdown */ - void shutdown(); - /* Call shutdown(), and wait synchronously for the command to be written */ - void shutdownSync(); - - void reconnect(); - - void getTorInfo(); -private: - TorControlSocket *mSocket; - std::string mTorAddress; - std::string mErrorMessage; - std::string mTorVersion; - ByteArray mAuthPassword; - std::string mSocksAddress; - std::list mServices; - uint16_t mControlPort, mSocksPort; - TorControl::Status mStatus; - TorControl::TorStatus mTorStatus; - std::map mBootstrapStatus; - bool mHasOwnership; - - void checkHiddenService(HiddenService *service); - void getTorInfoReply(TorControlCommand *sender); - void setStatus(TorControl::Status n); - void statusEvent(int code, const ByteArray &data); - void setTorStatus(TorControl::TorStatus n); - void updateBootstrap(const std::list& data); - void setError(const std::string& message); - void publishServices(); - void protocolInfoReply(TorControlCommand *sender); - void socketDisconnected(); - void authenticateReply(TorControlCommand *sender); - - std::function mStatusChanged_callback; - std::function mConnected_callback; - std::function mDisconnected_callback; -}; - -} diff --git a/libretroshare/src/tor/TorControlCommand.cpp b/libretroshare/src/tor/TorControlCommand.cpp deleted file mode 100644 index 42c98d96a..000000000 --- a/libretroshare/src/tor/TorControlCommand.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "TorControlCommand.h" - -using namespace Tor; - -TorControlCommand::TorControlCommand() - : m_finalStatus(0), - mReplyLine ( std::function([](int, const ByteArray &){})), - mFinished ( std::function([](TorControlCommand*){})) -{ -} - -void TorControlCommand::onReply(int statusCode, const ByteArray &data) -{ - mReplyLine(statusCode, data); -} - -void TorControlCommand::onFinished(int statusCode) -{ - m_finalStatus = statusCode; - mFinished(this); -} - -void TorControlCommand::onDataLine(const ByteArray &/*data*/) -{ -} - -void TorControlCommand::onDataFinished() -{ - RsWarn() << "torctrl: Unexpected data response for command"; -} - diff --git a/libretroshare/src/tor/TorControlCommand.h b/libretroshare/src/tor/TorControlCommand.h deleted file mode 100644 index 8dee6aadb..000000000 --- a/libretroshare/src/tor/TorControlCommand.h +++ /dev/null @@ -1,73 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include -#include "bytearray.h" - -namespace Tor -{ - -class ProtocolInfoCommand; - -class TorControlCommand -{ - friend class TorControlSocket; - -public: - TorControlCommand(); - virtual ~TorControlCommand()=default; - - int statusCode() const { return m_finalStatus; } - - void set_replyLine_callback( const std::function& f) { mReplyLine=f ; } - void set_finished_callback( const std::function& f) { mFinished=f; }; - -public: - virtual void onReply(int statusCode, const ByteArray &data); - virtual void onFinished(int statusCode); - virtual void onDataLine(const ByteArray &data); - virtual void onDataFinished(); - -private: - int m_finalStatus; - - // Disable copy - TorControlCommand(const TorControlCommand&){} - TorControlCommand& operator=(const TorControlCommand&){ return *this; } - - std::function mReplyLine; - std::function mFinished; -}; - -} diff --git a/libretroshare/src/tor/TorControlSocket.cpp b/libretroshare/src/tor/TorControlSocket.cpp deleted file mode 100644 index 19b373f67..000000000 --- a/libretroshare/src/tor/TorControlSocket.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "TorControlSocket.h" -#include "TorControlCommand.h" - -using namespace Tor; - -TorControlSocket::TorControlSocket(TorControlSocketClient *client) - : RsThreadedTcpSocket(),currentCommand(0), inDataReply(false),mClient(client) -{ -} - -TorControlSocket::~TorControlSocket() -{ - clear(); -} - -bool TorControlSocket::connectToHost(const std::string& tcp_address,uint16_t tcp_port) -{ - if(RsTcpSocket::connect(tcp_address,tcp_port)) - { - start("TorControlSocket"); - return true; - } - else - return false; - -} -std::string TorControlSocket::peerAddress() const -{ - if(connectionState() == State::CONNECTED) - return connectAddress(); - else - return std::string(); -} -void TorControlSocket::sendCommand(TorControlCommand *command, const ByteArray& data) -{ - assert(data.endsWith(ByteArray("\r\n"))); - - commandQueue.push_back(command); - senddata((void*)data.data(),data.size()); - - std::cerr << "[TOR CTRL] Sent: \"" << data.trimmed().toString() << "\"" << std::endl; -} - -void TorControlSocket::registerEvent(const ByteArray &event, TorControlCommand *command) -{ - eventCommands.insert(std::make_pair(event, command)); - - ByteArray data("SETEVENTS"); - for(auto it:eventCommands) - { - data += ' '; - data += it.first; - } - data += "\r\n"; - - sendCommand(data); -} - -void TorControlSocket::clear() -{ - for(auto cmd:commandQueue) delete cmd; - commandQueue.clear(); - - for(auto cmd:eventCommands) delete cmd.second; - eventCommands.clear(); - - inDataReply = false; - currentCommand = 0; -} - -void TorControlSocket::setError(const std::string &message) -{ - m_errorMessage = message; - mClient->socketError(message); - abort(); -} - -ByteArray TorControlSocket::readline(int s) -{ - ByteArray b(s); - int real_size; - - if(! (real_size = RsTcpSocket::readline(b.data(),s))) - return ByteArray(); - else - { - b.resize(real_size); - return b; - } -} - -void TorControlSocket::process() -{ - for (;;) { - if (!moretoread(0)) - return; - - ByteArray line = readline(5120); - - if(line.empty()) // This happens when the incoming buffer isn't empty yet doesn't have a full line already. - { - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - continue; - } - - if (!line.endsWith(ByteArray("\r\n"))) { - setError("Invalid control message syntax"); - return; - } - line.chop(2); - - if (inDataReply) { - if (line == ".") { - inDataReply = false; - if (currentCommand) - currentCommand->onDataFinished(); - currentCommand = 0; - } else { - if (currentCommand) - currentCommand->onDataLine(line); - } - continue; - } - - if (line.size() < 4) { - setError("Invalid control message syntax"); - return; - } - - int statusCode = line.left(3).toInt(); - char type = line[3]; - bool isFinalReply = (type == ' '); - inDataReply = (type == '+'); - - // Trim down to just data - line = line.mid(4); - - if (!isFinalReply && !inDataReply && type != '-') { - setError("Invalid control message syntax"); - return; - } - - // 6xx replies are asynchronous responses - if (statusCode >= 600 && statusCode < 700) { - if (!currentCommand) { - int space = line.indexOf(' '); - if (space > 0) - { - auto it = eventCommands.find(line.mid(0, space).toString()); - - if(it != eventCommands.end()) - currentCommand = it->second; - } - - if (!currentCommand) { - RsWarn() << "torctrl: Ignoring unknown event"; - continue; - } - } - - currentCommand->onReply(statusCode, line); - if (isFinalReply) { - currentCommand->onFinished(statusCode); - currentCommand = 0; - } - continue; - } - - if (commandQueue.empty()) { - RsWarn() << "torctrl: Received unexpected data"; - continue; - } - - TorControlCommand *command = commandQueue.front(); - if (command) - command->onReply(statusCode, line); - - if (inDataReply) { - currentCommand = command; - } else if (isFinalReply) { - commandQueue.pop_front(); - if (command) { - command->onFinished(statusCode); - delete command; // should we "delete later" ? - } - } - } -} - -int TorControlSocket::tick() -{ - bool rw = RsTcpSocket::tick(); - - if(moretoread(0)) - process(); - - if(!rw) - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); // temporisation when nothing happens - - return 0; // not sure about what we should return here. -} diff --git a/libretroshare/src/tor/TorControlSocket.h b/libretroshare/src/tor/TorControlSocket.h deleted file mode 100644 index 40437ed76..000000000 --- a/libretroshare/src/tor/TorControlSocket.h +++ /dev/null @@ -1,87 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include "pqi/rstcpsocket.h" -#include "bytearray.h" - -namespace Tor -{ - -class TorControlCommand; - -class TorControlSocketClient -{ -public: - virtual void socketError(const std::string& s) = 0; -}; - -class TorControlSocket : public RsThreadedTcpSocket -{ -public: - explicit TorControlSocket(TorControlSocketClient *client); - virtual ~TorControlSocket(); - - std::string errorMessage() const { return m_errorMessage; } - - bool connectToHost(const std::string& tcp_address,uint16_t tcp_port); - void registerEvent(const ByteArray &event, TorControlCommand *handler); - - void sendCommand(const ByteArray& data) { sendCommand(0, data); } - void sendCommand(TorControlCommand *command, const ByteArray &data); - - ByteArray readline(int s); - - // threaded TcpSocket - - virtual int tick() override; - - std::string peerAddress() const; - - const std::string& errorString() const { return m_errorMessage ;} - - void process(); - void clear(); - -private: - std::list commandQueue; - std::map eventCommands; - std::string m_errorMessage; - TorControlCommand *currentCommand; - bool inDataReply; - TorControlSocketClient *mClient; - - void setError(const std::string& message); -}; - -} diff --git a/libretroshare/src/tor/TorManager.cpp b/libretroshare/src/tor/TorManager.cpp deleted file mode 100644 index 7fa275c5a..000000000 --- a/libretroshare/src/tor/TorManager.cpp +++ /dev/null @@ -1,879 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include - -// This works on linux only. I have no clue how to do that on windows. Anyway, this -// is only needed for an assert that should normaly never be triggered. - -#if !defined(_WIN32) && !defined(__MINGW32__) -#include -#endif - -#include "util/rsdir.h" -#include "retroshare/rsinit.h" - -#include "TorManager.h" -#include "TorProcess.h" -#include "TorControl.h" -#include "CryptoKey.h" -#include "HiddenService.h" -#include "GetConfCommand.h" - -using namespace Tor; - -static TorManager *rsTor = nullptr; - -namespace Tor -{ - -class TorManagerPrivate : public TorProcessClient -{ -public: - TorManager *q; - TorProcess *process; - TorControl *control; - std::string dataDir; - std::string hiddenServiceDir; - std::list logMessages; - std::string errorMessage; - bool configNeeded; - - HiddenService *hiddenService ; - - explicit TorManagerPrivate(TorManager *parent = 0); - virtual ~TorManagerPrivate(); - - std::string torExecutablePath() const; - bool createDataDir(const std::string &path); - bool createDefaultTorrc(const std::string &path); - - void setError(const std::string &errorMessage); - - virtual void processStateChanged(int state) override; - virtual void processErrorChanged(const std::string &errorMessage) override; - virtual void processLogMessage(const std::string &message) override; - -//public slots: - void controlStatusChanged(int status); - void getConfFinished(TorControlCommand *sender); -}; - -} - -TorManager::TorManager() - : d(new TorManagerPrivate(this)) -{ -} - -TorManager::~TorManager() -{ - delete(d); -} - -TorManagerPrivate::TorManagerPrivate(TorManager *parent) - : q(parent) - , process(0) - , control(new TorControl()) - , configNeeded(false) - , hiddenService(NULL) -{ - control->set_statusChanged_callback([this](int new_status,int /*old_status*/) { controlStatusChanged(new_status); }); -} - -TorManagerPrivate::~TorManagerPrivate() -{ - delete(control); -} - -TorManager *TorManager::instance() -{ - static TorManager *p = 0; - if (!p) - p = new TorManager(); - return p; -} - -TorControl *TorManager::control() -{ - return d->control; -} - -TorProcess *TorManager::process() -{ - return d->process; -} - -std::string TorManager::torDataDirectory() const -{ - return d->dataDir; -} - -void TorManager::setTorDataDirectory(const std::string &path) -{ - assert(RsDirUtil::checkCreateDirectory(std::string(path))); - - d->dataDir = path; - - if (!d->dataDir.empty() && !ByteArray(d->dataDir).endsWith('/')) - d->dataDir += '/'; -} - -std::string TorManager::hiddenServiceDirectory() const -{ - return d->hiddenServiceDir; -} -void TorManager::setHiddenServiceDirectory(const std::string &path) -{ - d->hiddenServiceDir = path; - - if (!d->hiddenServiceDir.empty() && !(d->hiddenServiceDir.back() == '/')) - d->hiddenServiceDir += '/'; -} - -static bool test_listening_port(const std::string& /*address*/,uint16_t port) -{ - int sockfd; - struct sockaddr_in serv_addr ; - - /* First call to socket() function */ - sockfd = socket(AF_INET, SOCK_STREAM, 0); - - if (sockfd < 0) - return false; - - /* Initialize socket structure */ - memset((char *) &serv_addr, 0,sizeof(serv_addr)); - - serv_addr.sin_family = AF_INET; - serv_addr.sin_addr.s_addr = INADDR_ANY; - serv_addr.sin_port = htons(port); - - /* Now bind the host address using bind() call.*/ - if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { - perror("ERROR on binding"); - close(sockfd); - return false; - } - unix_fcntl_nonblock(sockfd); - int res = listen(sockfd,5); - - close(sockfd); - - if(!res) - return true; - - return false; -} -bool TorManager::setupHiddenService() -{ - if(d->hiddenService != NULL) - { - RsErr() << "TorManager: setupHiddenService() called twice! Not doing anything this time." ; - return true ; - } - - std::string keyData ;//= m_settings->read("serviceKey").toString(); - std::string legacyDir = d->hiddenServiceDir; - - RsDbg() << "TorManager: setting up hidden service." << std::endl; - - if(legacyDir.empty()) - { - RsErr() << "legacy dir not set! Cannot proceed." ; - return false ; - } - - RsDbg() << "Using legacy dir: " << legacyDir ; - auto key_path = RsDirUtil::makePath(legacyDir,"/private_key"); - - if (!legacyDir.empty() && RsDirUtil::fileExists(key_path)) - { - std::cerr << "Attempting to load key from legacy filesystem format from file \"" << key_path << "\"" << std::endl; - - d->hiddenService = new Tor::HiddenService(this,legacyDir); - - if(!d->hiddenService->privateKey().bytes().empty()) - { - RsDbg() << "Got key from legacy dir: " ; - RsDbg() << d->hiddenService->privateKey().bytes().toHex().toString() ; - } - else - RsWarn() << "Failed to load existing hidden service. Creating a new one." ; - } - else - { - d->hiddenService = new Tor::HiddenService(this,legacyDir); - - RsDbg() << "Creating new hidden service." << std::endl; - } - - assert(d->hiddenService); - - // Generally, these are not used, and we bind to localhost and port 0 - // for an automatic (and portable) selection. - - std::string address = "127.0.0.1"; // we only listen from localhost - unsigned short hidden_service_port = 7934;//(quint16)m_settings->read("localListenPort").toInt(); - - do - { - hidden_service_port = 1025 + (RsRandom::random_u32() >> 17); - - std::cerr << "Testing listening address:port " << address << ":" << hidden_service_port ; - std::cerr.flush(); - } - while(!test_listening_port(address,hidden_service_port)); - - std::cerr << ": OK - Adding hidden service to TorControl." << std::endl; - - // Note: 9878 is quite arbitrary, but since each RS node generates its own hidden service, all of them - // can use the same port without any conflict. - - d->hiddenService->addTarget(9878, "127.0.0.1",hidden_service_port); - control()->addHiddenService(d->hiddenService); - - return true ; -} - -void TorManager::hiddenServiceStatusChanged(int new_status,int old_status) -{ - std::cerr << "Hidden service status changed from " << old_status << " to " << new_status << std::endl; - - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mTorManagerEventType = RsTorManagerEventCode::TOR_STATUS_CHANGED; - ev->mTorConnectivityStatus = RsTorConnectivityStatus::HIDDEN_SERVICE_READY; - ev->mTorStatus = RsTorStatus::READY; - - rsEvents->sendEvent(ev); - } -} - -void TorManager::hiddenServicePrivateKeyChanged() -{ - if(!d->hiddenService) - return ; - - std::string key = d->hiddenService->privateKey().bytes().toString(); - - std::ofstream s(d->hiddenServiceDir + "/private_key"); - -#ifdef TO_REMOVE - s << "-----BEGIN RSA PRIVATE KEY-----" << endl; - - for(int i=0;ihiddenService) - return ; - - std::string outfile2_name = RsDirUtil::makePath(d->hiddenServiceDir,"/hostname") ; - std::ofstream of(outfile2_name); - - std::string hostname(d->hiddenService->hostname()); - - of << hostname << std::endl; - of.close(); - - std::cerr << "Hidden service hostname changed: " << hostname << std::endl; -} - -bool TorManager::configurationNeeded() const -{ - return d->configNeeded; -} - -const std::list& TorManager::logMessages() const -{ - return d->logMessages; -} - -bool TorManager::hasError() const -{ - return !d->errorMessage.empty(); -} - -std::string TorManager::errorMessage() const -{ - return d->errorMessage; -} - -bool TorManager::startTorManager() -{ - if (!d->errorMessage.empty()) { - d->errorMessage.clear(); - - //emit errorChanged(); // not needed because there's no error to handle - } - -#ifdef TODO - SettingsObject settings("tor"); - - // If a control port is defined by config or environment, skip launching tor - if (!settings.read("controlPort").isUndefined() || - !qEnvironmentVariableIsEmpty("TOR_CONTROL_PORT")) - { - QHostAddress address(settings.read("controlAddress").toString()); - quint16 port = (quint16)settings.read("controlPort").toInt(); - QByteArray password = settings.read("controlPassword").toString().toLatin1(); - - if (!qEnvironmentVariableIsEmpty("TOR_CONTROL_HOST")) - address = QHostAddress(qgetenv("TOR_CONTROL_HOST")); - - if (!qEnvironmentVariableIsEmpty("TOR_CONTROL_PORT")) { - bool ok = false; - port = qgetenv("TOR_CONTROL_PORT").toUShort(&ok); - if (!ok) - port = 0; - } - - if (!qEnvironmentVariableIsEmpty("TOR_CONTROL_PASSWD")) - password = qgetenv("TOR_CONTROL_PASSWD"); - - if (!port) { - d->setError("Invalid control port settings from environment or configuration"); - return false; - } - - if (address.isNull()) - address = QHostAddress::LocalHost; - - d->control->setAuthPassword(password); - d->control->connect(address, port); - } - else -#endif - { - // Launch a bundled Tor instance - std::string executable = d->torExecutablePath(); - - std::cerr << "Executable path: " << executable << std::endl; - - if (executable.empty()) { - d->setError("Cannot find tor executable"); - return false; - } - - if (!d->process) { - d->process = new TorProcess(d); - - // QObject::connect(d->process, SIGNAL(stateChanged(int)), d, SLOT(processStateChanged(int))); - // QObject::connect(d->process, SIGNAL(errorMessageChanged(std::string)), d, SLOT(processErrorChanged(std::string))); - // QObject::connect(d->process, SIGNAL(logMessage(std::string)), d, SLOT(processLogMessage(std::string))); - } - - if (!RsDirUtil::checkCreateDirectory(d->dataDir)) - { - d->setError(std::string("Cannot write data location: ") + d->dataDir); - return false; - } - - std::string defaultTorrc = RsDirUtil::makePath(d->dataDir,"default_torrc"); - - if (!RsDirUtil::fileExists(defaultTorrc) && !d->createDefaultTorrc(defaultTorrc)) - { - d->setError("Cannot write data files: "+defaultTorrc); - return false; - } - - std::string torrc = RsDirUtil::makePath(d->dataDir,"torrc"); - uint64_t file_size; - - bool torrc_exists = RsDirUtil::checkFile(torrc,file_size); - - if(!torrc_exists || torrc.size() == 0) - { - d->configNeeded = true; - - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mTorManagerEventType = RsTorManagerEventCode::CONFIGURATION_NEEDED; - ev->mTorConnectivityStatus = RsTorConnectivityStatus::UNKNOWN; - ev->mTorStatus = RsTorStatus::UNKNOWN; - rsEvents->sendEvent(ev); - } - //emit configurationNeededChanged(); - } - - std::cerr << "Starting Tor process:" << std::endl; - std::cerr << " Tor executable path: " << executable << std::endl; - std::cerr << " Tor data directory : " << d->dataDir << std::endl; - std::cerr << " Tor default torrc : " << defaultTorrc << std::endl; - - d->process->setExecutable(executable); - d->process->setDataDir(d->dataDir); - d->process->setDefaultTorrc(defaultTorrc); - } - - std::cerr << "Starting Tor manager thread:" << std::endl; - RsThread::start("TorManager"); - return true ; -} - -void TorManager::run() -{ - d->process->start(); - - while(!shouldStop()) - { - threadTick(); - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - } - - d->control->shutdownSync(); - d->process->stop(); - - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mTorManagerEventType = RsTorManagerEventCode::TOR_MANAGER_STOPPED; - rsEvents->sendEvent(ev); - } -} - -void TorManager::threadTick() -{ - d->process->tick(); - - if(d->process->state() != TorProcess::Ready) - return; - - switch(d->control->status()) - { - case TorControl::Unknown: - case TorControl::Connecting: - break; - - case TorControl::NotConnected: - RsDbg() << "Connecting to tor process at " << d->process->controlHost() << ":" << d->process->controlPort() << "..." ; - d->control->connect(d->process->controlHost(),d->process->controlPort()); - break; - - case TorControl::SocketConnected: - RsDbg() << "Connection established." ; - - if(d->hiddenService == nullptr) - { - RsDbg() << "Setting up hidden service" ; - setupHiddenService(); - } - - d->control->setAuthPassword(d->process->controlPassword()); - d->control->authenticate(); - break; - - case TorControl::Authenticating: - RsDbg() << "Authenticating..." ; - break; - - case TorControl::Authenticated: - - RsDbg() << "Authenticated. Looking for hidden services."; - break; - - case TorControl::HiddenServiceReady: - if(d->control->torStatus() < TorControl::TorReady) - { - d->control->getTorInfo(); // forces TorControl to check its state. - std::this_thread::sleep_for(std::chrono::seconds(1)); - } - break; - - case TorControl::Error: - d->control->shutdown(); - d->control->reconnect(); - break; - } -} - -bool TorManager::getProxyServerInfo(std::string& proxy_server_adress,uint16_t& proxy_server_port) -{ - proxy_server_adress = control()->socksAddress(); - proxy_server_port = control()->socksPort(); - - return proxy_server_port > 1023 ; -} - -bool TorManager::getHiddenServiceInfo(std::string& service_id,std::string& service_onion_address,uint16_t& service_port, std::string& service_target_address,uint16_t& target_port) -{ - auto hidden_services = control()->hiddenServices(); - - if(hidden_services.empty()) - return false ; - - // Only return the first one. - - for(auto it(hidden_services.begin());it!=hidden_services.end();++it) - { - service_onion_address = (*it)->hostname(); - service_id = (*it)->serviceId(); - - for(auto it2((*it)->targets().begin());it2!=(*it)->targets().end();++it2) - { - service_port = (*it2).servicePort ; - service_target_address = (*it2).targetAddress ; - target_port = (*it2).targetPort; - break ; - } - break ; - } - return true ; -} - -void TorManagerPrivate::processStateChanged(int state) -{ - RsInfo() << "state: " << state << " passwd=\"" << process->controlPassword().toString() << "\" " << process->controlHost() - << ":" << process->controlPort() << std::endl; - - if (state == TorProcess::Ready) { - control->setAuthPassword(process->controlPassword()); - control->connect(process->controlHost(), process->controlPort()); - } -} - -void TorManagerPrivate::processErrorChanged(const std::string &errorMessage) -{ - std::cerr << "tor error:" << errorMessage << std::endl; - setError(errorMessage); -} - -void TorManagerPrivate::processLogMessage(const std::string &message) -{ - std::cerr << "tor:" << message << std::endl; - if (logMessages.size() >= 50) - logMessages.pop_front(); - - auto p = message.find_first_of('\n'); - - logMessages.push_back((p==std::string::npos)?message:message.substr(0,p)); -} - -void TorManagerPrivate::controlStatusChanged(int status) -{ - if (status == TorControl::Authenticated) { - if (!configNeeded) { - // If DisableNetwork is 1, trigger configurationNeeded - auto cmd = control->getConfiguration("DisableNetwork"); - cmd->set_finished_callback( [this](TorControlCommand *sender) { getConfFinished(sender) ; }); - } - - if (process) { - // Take ownership via this control socket - control->takeOwnership(); - } - } -} - -void TorManagerPrivate::getConfFinished(TorControlCommand *sender) -{ - GetConfCommand *command = dynamic_cast(sender); - if (!command) - return; - - int n; - - for(auto str:command->get("DisableNetwork")) - if(RsUtil::StringToInt(str,n) && n==1 && !configNeeded) - { - configNeeded = true; - - if(rsEvents) - { - auto ev = std::make_shared(); - ev->mTorManagerEventType = RsTorManagerEventCode::CONFIGURATION_NEEDED; - ev->mTorConnectivityStatus = RsTorConnectivityStatus::UNKNOWN; - ev->mTorStatus = RsTorStatus::UNKNOWN; - rsEvents->sendEvent(ev); - } - } -} - -std::string TorManagerPrivate::torExecutablePath() const -{ - std::string path; -#ifdef TODO - SettingsObject settings("tor"); - path = settings.read("executablePath").toString(); - - if (!path.isEmpty() && QFile::exists(path)) - return path; -#endif - -#ifdef WINDOWS_SYS - std::string filename("/tor/tor.exe"); -#else - std::string filename("/tor"); -#endif - - path = RsDirUtil::getDirectory(RsInit::executablePath()); - std::string tor_exe_path = RsDirUtil::makePath(path,filename); - - if (RsDirUtil::fileExists(tor_exe_path)) - return tor_exe_path; - -#ifdef BUNDLED_TOR_PATH - path = BUNDLED_TOR_PATH; - tor_exe_path = RsDirUtil::makePath(path,filename); - - if (RsDirUtil::fileExists(tor_exe_path)) - return tor_exe_path; -#endif - -#ifdef __APPLE__ - // on MacOS, try traditional brew installation path - - path = "/usr/local/opt/tor/bin" ; - tor_exe_path = RsDirUtil::makePath(path,filename); - - if (RsDirUtil::fileExists(tor_exe_path)) - return tor_exe_path; -#endif - -#ifdef __linux__ - // On linux try system-installed tor /usr/bin/tor - - if(RsDirUtil::fileExists("/usr/bin/tor")) - return std::string("/usr/bin/tor"); -#endif - - RsErr() << "Could not find Tor executable anywhere!" ; - // Try $PATH - return filename.substr(1); -} - -bool TorManagerPrivate::createDataDir(const std::string &path) -{ - return RsDirUtil::checkCreateDirectory(path); -} - -bool TorManagerPrivate::createDefaultTorrc(const std::string &path) -{ - static const char defaultTorrcContent[] = - "SocksPort auto\n" - "AvoidDiskWrites 1\n" -// "DisableNetwork 1\n" // (cyril) I removed this because it prevents Tor to bootstrap. - "__ReloadTorrcOnSIGHUP 0\n"; - - FILE *f = fopen(path.c_str(),"w"); - - if (!f) - return false; - - fprintf(f,"%s",defaultTorrcContent); - - fclose(f); - return true; -} - -void TorManagerPrivate::setError(const std::string &message) -{ - errorMessage = message; - - if(rsEvents) - { - auto ev = std::make_shared(); - - ev->mTorManagerEventType = RsTorManagerEventCode::TOR_MANAGER_ERROR; - ev->mErrorMessage = message; - rsEvents->sendEvent(ev); - } - //emit q->errorChanged(); -} - -bool RsTor::isTorAvailable() -{ - return !instance()->d->torExecutablePath().empty(); -} - -bool RsTor::getHiddenServiceInfo(std::string& service_id, - std::string& service_onion_address, - uint16_t& service_port, - std::string& service_target_address, - uint16_t& target_port) -{ - std::string sid; - std::string soa; - std::string sta; - - if(!instance()->getHiddenServiceInfo(sid,soa,service_port,sta,target_port)) - return false; - - service_id = sid; - service_onion_address = soa; - service_target_address = sta; - - return true; -} - -std::list RsTor::logMessages() -{ - return instance()->logMessages(); -} - -std::string RsTor::socksAddress() -{ - return instance()->control()->socksAddress(); -} -uint16_t RsTor::socksPort() -{ - return instance()->control()->socksPort(); -} - -RsTorStatus RsTor::torStatus() -{ - TorControl::TorStatus ts = instance()->control()->torStatus(); - - switch(ts) - { - case TorControl::TorOffline: return RsTorStatus::OFFLINE; - case TorControl::TorReady: return RsTorStatus::READY; - - default: - case TorControl::TorUnknown: return RsTorStatus::UNKNOWN; - } -} - -RsTorConnectivityStatus RsTor::torConnectivityStatus() -{ - TorControl::Status ts = instance()->control()->status(); - - switch(ts) - { - default: - case Tor::TorControl::Error : return RsTorConnectivityStatus::ERROR; - case Tor::TorControl::NotConnected : return RsTorConnectivityStatus::NOT_CONNECTED; - case Tor::TorControl::Authenticating: return RsTorConnectivityStatus::AUTHENTICATING; - case Tor::TorControl::Connecting: return RsTorConnectivityStatus::CONNECTING; - case Tor::TorControl::Authenticated : return RsTorConnectivityStatus::AUTHENTICATED; - case Tor::TorControl::HiddenServiceReady : return RsTorConnectivityStatus::HIDDEN_SERVICE_READY; - } -} - -bool RsTor::setupHiddenService() -{ - return instance()->setupHiddenService(); -} - -RsTorHiddenServiceStatus RsTor::getHiddenServiceStatus(std::string& service_id) -{ - service_id.clear(); - auto list = instance()->control()->hiddenServices(); - - if(list.empty()) - return RsTorHiddenServiceStatus::NOT_CREATED; - - service_id = (*list.begin())->serviceId(); - - switch((*list.begin())->status()) - { - default: - case Tor::HiddenService::NotCreated: return RsTorHiddenServiceStatus::NOT_CREATED; - case Tor::HiddenService::Offline : return RsTorHiddenServiceStatus::OFFLINE; - case Tor::HiddenService::Online : return RsTorHiddenServiceStatus::ONLINE; - } -} - -std::map RsTor::bootstrapStatus() -{ - return instance()->control()->bootstrapStatus(); -} - -bool RsTor::hasError() -{ - return instance()->hasError(); -} -std::string RsTor::errorMessage() -{ - return instance()->errorMessage(); -} - -void RsTor::getProxyServerInfo(std::string& server_address, uint16_t& server_port) -{ - std::string qserver_address; - instance()->getProxyServerInfo(qserver_address,server_port); - - server_address = qserver_address; -} - -bool RsTor::start() -{ - return instance()->startTorManager(); -} - -void RsTor::stop() -{ - if (rsTor) { - if (rsTor->isRunning()) { - rsTor->fullstop(); - } - delete(rsTor); - rsTor= nullptr; - } -} - -void RsTor::setTorDataDirectory(const std::string& dir) -{ - instance()->setTorDataDirectory(dir); -} -void RsTor::setHiddenServiceDirectory(const std::string& dir) -{ - instance()->setHiddenServiceDirectory(dir); -} - -TorManager *RsTor::instance() -{ -#if !defined(_WIN32) && !defined(__MINGW32__) - assert(getpid() == syscall(SYS_gettid));// make sure we're not in a thread -#endif - - if(rsTor == nullptr) - rsTor = new TorManager; - - return rsTor; -} diff --git a/libretroshare/src/tor/TorManager.h b/libretroshare/src/tor/TorManager.h deleted file mode 100644 index a96370bc7..000000000 --- a/libretroshare/src/tor/TorManager.h +++ /dev/null @@ -1,97 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// This code has been further modified to fit Retroshare context. - -#pragma once - -#include "retroshare/rstor.h" -#include "HiddenService.h" - -namespace Tor -{ - -class TorProcess; -class TorControl; -class TorManagerPrivate; - -/* Run/connect to an instance of Tor according to configuration, and manage - * UI interaction, first time configuration, etc. */ - -class TorManager : public HiddenServiceClient, public RsThread, public RsTor -{ -public: - static TorManager *instance(); - virtual ~TorManager(); - - TorProcess *process(); - TorControl *control(); - - std::string torDataDirectory() const; - void setTorDataDirectory(const std::string &path); - - std::string hiddenServiceDirectory() const; - void setHiddenServiceDirectory(const std::string &path); - - // Starts a hidden service, loading it from the config directory that has been set earlier. - bool setupHiddenService() ; - - // True on first run or when the Tor configuration wizard needs to be shown - bool configurationNeeded() const; - - const std::list& logMessages() const; - - bool hasError() const; - std::string errorMessage() const; - - bool getHiddenServiceInfo(std::string& service_id,std::string& service_onion_address,uint16_t& service_port, std::string& service_target_address,uint16_t& target_port); - bool getProxyServerInfo(std::string &proxy_server_adress, uint16_t& proxy_server_port); - - bool startTorManager(); - - virtual void hiddenServiceOnline() override {} // do nothing here. - virtual void hiddenServicePrivateKeyChanged() override; - virtual void hiddenServiceHostnameChanged() override; - virtual void hiddenServiceStatusChanged(int new_status, int old_status) override; - - // Thread stuff - - virtual void run() override; - void threadTick() ; - -private: - explicit TorManager(); - TorManagerPrivate *d; - friend class RsTor; -}; - -} diff --git a/libretroshare/src/tor/TorProcess.cpp b/libretroshare/src/tor/TorProcess.cpp deleted file mode 100644 index b7b66da90..000000000 --- a/libretroshare/src/tor/TorProcess.cpp +++ /dev/null @@ -1,510 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include - -#include "util/rsdir.h" -#include "util/rsfile.h" -#include "pqi/pqifdbin.h" - -#include "TorProcess.h" -#include "CryptoKey.h" - -#ifdef WINDOWS_SYS -#include "util/rsstring.h" - -#include -#define pipe(fds) _pipe(fds, 1024, _O_BINARY) -#endif - -using namespace Tor; - -static const int INTERVAL_BETWEEN_CONTROL_PORT_READ_TRIES = 5; // try every 5 secs. - -TorProcess::TorProcess(TorProcessClient *client) - : m_client(client), mState(TorProcess::NotStarted), mControlPort(0), mLastTryReadControlPort(0) -{ - mControlPortReadNbTries=0; - -} - -TorProcess::~TorProcess() -{ - if (state() > NotStarted) - stop(); -} - -std::string TorProcess::executable() const -{ - return mExecutable; -} - -void TorProcess::setExecutable(const std::string &path) -{ - mExecutable = path; -} - -std::string TorProcess::dataDir() const -{ - return mDataDir; -} - -void TorProcess::setDataDir(const std::string &path) -{ - mDataDir = path; -} - -std::string TorProcess::defaultTorrc() const -{ - return mDefaultTorrc; -} - -void TorProcess::setDefaultTorrc(const std::string &path) -{ - mDefaultTorrc = path; -} - -std::list TorProcess::extraSettings() const -{ - return mExtraSettings; -} - -void TorProcess::setExtraSettings(const std::list &settings) -{ - mExtraSettings = settings; -} - -TorProcess::State TorProcess::state() const -{ - return mState; -} - -std::string TorProcess::errorMessage() const -{ - return mErrorMessage; -} - -// Does a popen, but dup all file descriptors (STDIN STDOUT and STDERR) to the -// FDs supplied by the parent process - -int popen3(int fd[3],const std::vector& args,TorProcessHandle& pid) -{ - RsErr() << "Launching Tor in background..." ; - - int i, e; - int p[3][2]; - // set all the FDs to invalid - for(i=0; i<3; i++) - p[i][0] = p[i][1] = -1; - // create the pipes - for(int i=0; i<3; i++) - if(pipe(p[i])) - goto error; - -#ifdef WINDOWS_SYS - // Set up members of the PROCESS_INFORMATION structure. - PROCESS_INFORMATION pi; - ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); - - // Set up members of the STARTUPINFO structure. - // This structure specifies the STDIN and STDOUT handles for redirection. - STARTUPINFO si; - ZeroMemory(&si, sizeof(STARTUPINFO)); - si.cb = sizeof(STARTUPINFO); - si.hStdInput = (HANDLE) _get_osfhandle(p[STDIN_FILENO][0]); - si.hStdOutput = (HANDLE) _get_osfhandle(p[STDOUT_FILENO][1]); - si.hStdError = (HANDLE) _get_osfhandle(p[STDERR_FILENO][1]); - si.wShowWindow = SW_HIDE; - si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; - - if (si.hStdInput != INVALID_HANDLE_VALUE && - si.hStdOutput != INVALID_HANDLE_VALUE && - si.hStdError != INVALID_HANDLE_VALUE) { - // build commandline - std::string cmd; - for (std::vector::const_iterator it = args.begin(); it != args.end(); ++it) { - if (it != args.begin()) { - cmd += " "; - } - cmd += *it; - } - - std::wstring wcmd; - if (!librs::util::ConvertUtf8ToUtf16(cmd, wcmd)) { - goto error; - } - - WINBOOL success = CreateProcess(nullptr, - (LPWSTR) wcmd.c_str(), // command line - nullptr, // process security attributes - nullptr, // primary thread security attributes - TRUE, // handles are inherited - 0, // creation flags - nullptr, // use parent's environment - nullptr, // use parent's current directory - &si, // STARTUPINFO pointer - &pi); // receives PROCESS_INFORMATION - - if (success) { - pid = pi.hProcess; - - CloseHandle(pi.hThread); - - fd[STDIN_FILENO] = p[STDIN_FILENO][1]; - close(p[STDIN_FILENO][0]); - fd[STDOUT_FILENO] = p[STDOUT_FILENO][0]; - close(p[STDOUT_FILENO][1]); - fd[STDERR_FILENO] = p[STDERR_FILENO][0]; - close(p[STDERR_FILENO][1]); - - // success - return 0; - } - } - - // fall through error - -#else - { - const char *arguments[args.size()+1]; - int n=0; - - // We first pushed everything into a vector of strings to save the pointers obtained from string returning methods - // by the time the process is launched. - - for(uint32_t i=0;i(arguments)); - - // if we are there, then we failed to launch our program - perror("Could not launch"); - fprintf(stderr," \"%s\"\n",*arguments); - } - } -#endif - -error: - e = errno; - // preserve original error - RsErr() << "An error occurred while trying to launch tor in background." ; - for(i=0; i<3; i++) { - close(p[i][0]); - close(p[i][1]); - } - errno = e; - return -1; -} - -void TorProcess::start() -{ - if (state() > NotStarted) - return; - - mErrorMessage.clear(); - - if (mExecutable.empty() || mDataDir.empty()) { - mErrorMessage = "Tor executable and data directory not specified"; - mState = Failed; - - if(m_client) m_client->processStateChanged(mState); // emit stateChanged(d->state); - if(m_client) m_client->processErrorChanged(mErrorMessage); // emit errorMessageChanged(d->errorMessage); - return; - } - - if (!ensureFilesExist()) { - mState = Failed; - if(m_client) m_client->processErrorChanged(mErrorMessage);// emit errorMessageChanged(d->errorMessage); - if(m_client) m_client->processStateChanged(mState);// emit stateChanged(d->state); - return; - } - - ByteArray password = controlPassword(); - ByteArray hashedPassword = torControlHashedPassword(password); - - if (password.empty() || hashedPassword.empty()) { - mErrorMessage = "Random password generation failed"; - mState = Failed; - if(m_client) m_client->processErrorChanged(mErrorMessage);// emit errorMessageChanged(d->errorMessage); - if(m_client) m_client->processStateChanged(mState); // emit stateChanged(d->state); - } - else - RsDbg() << "Using ControlPasswd=\"" << password.toString() << "\", hashed version=\"" << hashedPassword.toString() << "\"" ; - - mState = Starting; - - if(m_client) m_client->processStateChanged(mState);// emit stateChanged(d->state); - - if (RsDirUtil::fileExists(controlPortFilePath())) - RsDirUtil::removeFile(controlPortFilePath()); - - mControlPort = 0; - mControlHost.clear(); - - // Launch the process - - std::vector args; - - args.push_back(mExecutable); - - if (!mDefaultTorrc.empty()) - { - args.push_back("--defaults-torrc"); - args.push_back(mDefaultTorrc); - } - - args.push_back("-f"); - args.push_back(torrcPath()); - - args.push_back("DataDirectory") ; - args.push_back(mDataDir); - - args.push_back("HashedControlPassword") ; - args.push_back(hashedPassword.toString()); - - args.push_back("ControlPort") ; - args.push_back("auto"); - - args.push_back("ControlPortWriteToFile"); - args.push_back(controlPortFilePath()); - - args.push_back("__OwningControllerProcess") ; - args.push_back(RsUtil::NumberToString(getpid())); - - for(auto s:mExtraSettings) - args.push_back(s); - - int fd[3]; // File descriptors array - - if(popen3(fd,args,mTorProcessId)) - { - RsErr() << "Could not start Tor process. errno=" << errno ; - mState = Failed; - return; // stop the control thread - } - - RsFileUtil::set_fd_nonblock(fd[STDOUT_FILENO]); - RsFileUtil::set_fd_nonblock(fd[STDERR_FILENO]); - - mStdOutFD = new RsFdBinInterface(fd[STDOUT_FILENO], false); - mStdErrFD = new RsFdBinInterface(fd[STDERR_FILENO], false); -} - -void TorProcess::tick() -{ - mStdOutFD->tick(); - mStdErrFD->tick(); - - unsigned char buff[1024]; - int s; - - if((s=mStdOutFD->readline(buff,1024))) logMessage(std::string((char*)buff,s)); - if((s=mStdErrFD->readline(buff,1024))) logMessage(std::string((char*)buff,s)); - - if(!mStdOutFD->isactive() && !mStdErrFD->isactive()) - { - RsErr() << "Tor process died. Exiting TorControl process." ; - stop(); - return; - } - time_t now = time(nullptr); - - if(mControlPortReadNbTries <= 10 && (mControlPort==0 || mControlHost.empty()) && mLastTryReadControlPort + INTERVAL_BETWEEN_CONTROL_PORT_READ_TRIES < now) - { - mLastTryReadControlPort = now; - - if(tryReadControlPort()) - { - mState = Ready; - m_client->processStateChanged(mState);// stateChanged(mState); - } - else if(mControlPortReadNbTries > 10) - { - mState = Failed; - m_client->processStateChanged(mState);// stateChanged(mState); - } - } -} - -void TorProcess::stop() -{ - if (state() < Starting) - return; - - while(mState == Starting) - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - -#ifdef WINDOWS_SYS - TerminateProcess (mTorProcessId, 0); -#else - kill(mTorProcessId,SIGTERM); -#endif - - RsInfo() << "Tor process has been normally terminated. Exiting."; - - mState = NotStarted; - - if(m_client) m_client->processStateChanged(mState);// emit stateChanged(d->state); -} - -void TorProcess::stateChanged(int newState) -{ - if(m_client) - m_client->processStateChanged(newState); -} -void TorProcess::errorMessageChanged(const std::string& errorMessage) -{ - if(m_client) - m_client->processErrorChanged(errorMessage); -} -void TorProcess::logMessage(const std::string& message) -{ - if(m_client) - m_client->processLogMessage(message); -} - -ByteArray TorProcess::controlPassword() -{ - if (mControlPassword.empty()) - mControlPassword = RsRandom::printable(16); - - return mControlPassword; -} - -std::string TorProcess::controlHost() -{ - return mControlHost; -} - -unsigned short TorProcess::controlPort() -{ - return mControlPort; -} - -bool TorProcess::ensureFilesExist() -{ - if(!RsDirUtil::checkCreateDirectory(mDataDir)) - { - mErrorMessage = "Cannot create Tor data directory: " + mDataDir; - return false; - } - - if (!RsDirUtil::fileExists(torrcPath())) - { - FILE *f = RsDirUtil::rs_fopen(torrcPath().c_str(),"w"); - - if(!f) - { - mErrorMessage = "Cannot create Tor configuration file: " + torrcPath(); - return false; - } - else - fclose(f); - } - - return true; -} - -std::string TorProcess::torrcPath() const -{ - return RsDirUtil::makePath(mDataDir,"torrc"); -} - -std::string TorProcess::controlPortFilePath() const -{ - return RsDirUtil::makePath(mDataDir,"control-port"); -} - -bool TorProcess::tryReadControlPort() -{ - FILE *file = RsDirUtil::rs_fopen(controlPortFilePath().c_str(),"r"); - RsDbg() << "Trying to read control port" ; - - if(file) - { - char *line = nullptr; - size_t tmp_buffsize = 0; - - size_t size = RsFileUtil::rs_getline(&line,&tmp_buffsize,file); - ByteArray data = ByteArray((unsigned char*)line,size).trimmed(); - free(line); - - fclose(file); - - int p; - if (data.startsWith("PORT=") && (p = data.lastIndexOf(':')) > 0) { - mControlHost = data.mid(5, p - 5).toString(); - mControlPort = data.mid(p+1).toInt(); - - if (!mControlHost.empty() && mControlPort > 0) - { - RsDbg() << "Got control host/port = " << mControlHost << ":" << mControlPort ; - return true; - } - } - } - return false; -} diff --git a/libretroshare/src/tor/TorProcess.h b/libretroshare/src/tor/TorProcess.h deleted file mode 100644 index 9069e13cb..000000000 --- a/libretroshare/src/tor/TorProcess.h +++ /dev/null @@ -1,140 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TORPROCESS_H -#define TORPROCESS_H - -#include "bytearray.h" -#include "util/rsthreads.h" - -class RsFdBinInterface ; - -#ifdef WINDOWS_SYS - #define TorProcessHandle HANDLE -#else - #define TorProcessHandle pid_t -#endif - -namespace Tor -{ - -class TorProcessPrivate; - -// This class is used to inherit calls from the TorProcess - -class TorProcessClient -{ -public: - virtual void processStateChanged(int) = 0; - virtual void processErrorChanged(const std::string&) = 0; - virtual void processLogMessage(const std::string&) = 0; -}; - -/* Launches and controls a Tor instance with behavior suitable for bundling - * an instance with the application. */ -class TorProcess -{ -public: - enum State { - Failed = -1, - NotStarted, - Starting, - Connecting, - Ready - }; - - explicit TorProcess(TorProcessClient *client); - virtual ~TorProcess(); - - std::string executable() const; - void setExecutable(const std::string &path); - - std::string dataDir() const; - void setDataDir(const std::string &path); - - std::string defaultTorrc() const; - void setDefaultTorrc(const std::string &path); - - std::list extraSettings() const; - void setExtraSettings(const std::list &settings); - - State state() const; - std::string errorMessage() const; - std::string controlHost(); - unsigned short controlPort(); - ByteArray controlPassword(); - - void stateChanged(int newState); - void errorMessageChanged(const std::string &errorMessage); - void logMessage(const std::string &message); - - void start(); - void stop(); - void tick(); - -private: - TorProcessClient *m_client; - - std::string mExecutable; - std::string mDataDir; - std::string mDefaultTorrc; - std::list mExtraSettings; - TorProcess::State mState; - std::string mErrorMessage; - std::string mControlHost; - unsigned short mControlPort; - ByteArray mControlPassword; - - int controlPortAttempts; - - std::string torrcPath() const; - std::string controlPortFilePath() const; - bool ensureFilesExist(); - - TorProcessHandle mTorProcessId; - time_t mLastTryReadControlPort ; - int mControlPortReadNbTries ; - - void processStarted(); - void processFinished(); - void processError(std::string error); - void processReadable(); - bool tryReadControlPort(); - - RsFdBinInterface *mStdOutFD; - RsFdBinInterface *mStdErrFD; -}; - -} - -#endif - diff --git a/libretroshare/src/tor/TorTypes.h b/libretroshare/src/tor/TorTypes.h deleted file mode 100644 index 393e6a849..000000000 --- a/libretroshare/src/tor/TorTypes.h +++ /dev/null @@ -1,142 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace Tor -{ - -class NonCopiable { -public: - NonCopiable(){} - virtual ~NonCopiable()=default; -private: - NonCopiable(const NonCopiable& nc) {} - virtual NonCopiable& operator=(const NonCopiable& nc) { return *this ; } -}; - -class TorByteArray: public std::vector -{ -public: - TorByteArray(const unsigned char *data,uint32_t len) - { - clear(); - for(uint32_t i=0;i size()) - return false; - - for(uint32_t i=0;i size()) - return false; - - for(uint32_t i=0;i size()) - throw std::runtime_error("Length out of range in TorByteArray::mid()"); - - TorByteArray b; - for(uint32_t i=0;i<(uint32_t)length;++i) - b.push_back(data()[i+start]); - - return b; - } - - static TorByteArray number(uint64_t n) - { - std::ostringstream o; - o << n ; - return TorByteArray(o.str()); - } -}; - -typedef std::string TorHostAddress; -} diff --git a/libretroshare/src/tor/Useful.h b/libretroshare/src/tor/Useful.h deleted file mode 100644 index cdead13e7..000000000 --- a/libretroshare/src/tor/Useful.h +++ /dev/null @@ -1,66 +0,0 @@ -/* Ricochet - https://ricochet.im/ - * Copyright (C) 2014, John Brooks - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * * Neither the names of the copyright owners nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include "util/rsdebug.h" - -/* Print a warning for bug conditions, and assert on a debug build. - * - * This should be used in place of Q_ASSERT for bug conditions, along - * with a proper error case for release-mode builds. For example: - * - * if (!connection || !user) { - * BUG() << "Request" << request << "should have a connection and user"; - * return false; - * } - * - * Do not confuse bugs with actual error cases; BUG() should never be - * triggered unless the code or logic is wrong. - */ -#if !defined(QT_NO_DEBUG) || defined(QT_FORCE_ASSERTS) -# define BUG() Explode(__FILE__,__LINE__), RsWarn() << "BUG:" -namespace { -class Explode -{ -public: - const char *file; - int line; - Explode(const char *file, int line) : file(file), line(line) { } - ~Explode() { - RsErr() << "something broke! in file " << file << line; - } -}; -} -#else -# define BUG() qWarning() << "BUG:" -#endif diff --git a/libretroshare/src/tor/bytearray.h b/libretroshare/src/tor/bytearray.h deleted file mode 100644 index e81db0a17..000000000 --- a/libretroshare/src/tor/bytearray.h +++ /dev/null @@ -1,195 +0,0 @@ -#pragma once - -#include -#include - -#include -#include -#include -#include - -#include "util/rsprint.h" -#include "util/rsdebug.h" - -// This class re-implements QByteArray from Qt library. - -class ByteArray: public std::vector -{ -public: - ByteArray() =default; - explicit ByteArray(int n) : std::vector(n) {} - explicit ByteArray(const unsigned char *d,int n) : std::vector(n) { memcpy(data(),d,n); } - virtual ~ByteArray() =default; - - ByteArray(const std::string& c) { resize(c.size()); memcpy(data(),c.c_str(),c.size()); } - const ByteArray& operator=(const std::string& c) { resize(c.size()); memcpy(data(),c.c_str(),c.size()); return *this; } - - bool isNull() const { return empty(); } - ByteArray toHex() const { return ByteArray(RsUtil::BinToHex(data(),size(),0)); } - std::string toString() const { std::string res; for(auto c:*this) res += c; return res; } - - ByteArray operator+(const ByteArray& b) const { auto res(*this); for(unsigned char c:b) res.push_back(c); return res; } - ByteArray operator+(const std::string& b) const { return operator+(ByteArray(b)); } - - void append(const ByteArray& b) { for(auto c:b) push_back(c); } - void append(const char *b) { for(uint32_t n=0;b[n]!=0;++n) push_back(b[n]); } - - template void append(const T) = delete;// Prevents any implicit when calling the preceding functions which actually causes real bugs. - - ByteArray& operator+=(char b) { push_back(b); return *this; } - ByteArray& operator+=(const ByteArray& b) { for(auto c:b) push_back(c); return *this; } - ByteArray& operator+=(const char *b) { for(uint32_t n=0;b[n]!=0;++n) push_back(b[n]); return *this;} - - ByteArray left(uint32_t l) const { auto res = *this; res.resize(std::min((uint32_t)size(),l)); return res; } - ByteArray toUpper() const { auto res = *this; for(uint32_t i=0;i='a') res[i] += int('A')-int('a'); return res; } - ByteArray toLower() const { auto res = *this; for(uint32_t i=0;i='A') res[i] += int('a')-int('A'); return res; } - - int toInt() const - { - std::istringstream is(toString().c_str()); - - int res = -1; - is >> res ; - - return res; - } - bool endsWith(const ByteArray& b) const { return size() >= b.size() && !memcmp(&data()[size()-b.size()],b.data(),b.size()); } - bool endsWith(char b) const { return size() > 0 && back()==b; } - bool startsWith(const ByteArray& b) const { return b.size() <= size() && !strncmp((char*)b.data(),(char*)data(),std::min(size(),b.size())); } - bool startsWith(const char *b) const - { - for(uint32_t n=0;b[n]!=0;++n) - if(n >= size() || b[n]!=(*this)[n]) - return false; - - return true; - } - - bool operator==(const char *b) const - { - uint32_t n; - for(n=0;b[n]!=0;++n) - if(n >= size() || b[n]!=(*this)[n]) - return false; - - return n==size(); - } - - ByteArray mid(uint32_t n,int s=-1) const - { - ByteArray res((s>=0)?s:(size()-n)); - memcpy(res.data(),&data()[n],res.size()); - return res; - } - - int indexOf(unsigned char c,int from=0) const - { - for(uint32_t i=from;i split(unsigned char sep) - { - std::list res; - ByteArray current_block; - - for(uint32_t i=0;i split(const ByteArray& sep) - { - std::list res; - ByteArray current_block; - - for(uint32_t i=0;i=0;--i) - if(operator[](i) == s) - return i; - - return -1; - } -}; diff --git a/libretroshare/src/turtle/p3turtle.cc b/libretroshare/src/turtle/p3turtle.cc deleted file mode 100644 index 934b5915d..000000000 --- a/libretroshare/src/turtle/p3turtle.cc +++ /dev/null @@ -1,2519 +0,0 @@ -/******************************************************************************* - * libretroshare/src/turtle: p3turtle.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2009-2018 Cyril Soler * - * Copyright (C) 2018-2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -//#define P3TURTLE_DEBUG - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "rsserver/p3face.h" -#include "crypto/rscrypto.h" - -#include "pqi/authssl.h" -#include "pqi/p3linkmgr.h" -#include "retroshare/rspeers.h" - -#include "ft/ftserver.h" -#include "ft/ftdatamultiplex.h" -#include "ft/ftcontroller.h" - -#include "p3turtle.h" -#include "util/cxx17retrocompat.h" -#include "util/rsdebug.h" -#include "util/rsprint.h" -#include "util/rsrandom.h" -#include "pqi/pqinetwork.h" - -#ifdef TUNNEL_STATISTICS -static std::vector TS_tunnel_length(8,0) ; -static std::map > > TS_request_time_stamps ; -static std::map > TS_request_bounces ; -void TS_dumpState() ; -#endif - -#define TURTLE_DEBUG() std::cerr << time(NULL) << " : TURTLE : " << __FUNCTION__ << " : " -#define TURTLE_ERROR() std::cerr << "(EE) TURTLE ERROR : " - -// These number may be quite important. I setup them with sensible values, but -// an in-depth test would be better to get an idea of what the ideal values -// could ever be. -// -// update of 14-03-11: -// - I raised the cache time for tunnel requests. This avoids inconsistencies such as: -// * tunnel requests bouncing back while the original request is not in the cache anymore -// * special case of this for own file transfer: an outgoing tunnel is built with no end. -// - changed tunnel speed estimate time lapse to 5 secs. Too small a value favors high variations. -// - the max number of tunnel requests per second is now enforced. It was before defaulting to -// QUEUE_LENGTH*0.1, meaning 0.5. I set it to 0.1. -// -// update of 19-04-12: -// - The total number of TR per second emmited from self will be MAX_TUNNEL_REQS_PER_SECOND / TIME_BETWEEN_TUNNEL_MANAGEMENT_CALLS = 0.5 -// - I updated forward probabilities to higher values, and min them to 1/nb_connected_friends to prevent blocking tunnels. -// -static const rstime_t TUNNEL_REQUESTS_LIFE_TIME = 600 ; /// life time for tunnel requests in the cache. -static const rstime_t TUNNEL_REQUESTS_RESULT_TIME = 20 ; /// maximum time during which we process/forward results for known tunnel requests -static const rstime_t SEARCH_REQUESTS_LIFE_TIME = 600 ; /// life time for search requests in the cache -static const rstime_t SEARCH_REQUESTS_RESULT_TIME = 20 ; /// maximum time during which we process/forward results for known search requests -static const rstime_t REGULAR_TUNNEL_DIGGING_TIME = 300 ; /// maximum interval between two tunnel digging campaigns. -static const rstime_t MAXIMUM_TUNNEL_IDLE_TIME = 60 ; /// maximum life time of an unused tunnel. -static const rstime_t EMPTY_TUNNELS_DIGGING_TIME = 50 ; /// look into tunnels regularly every 50 sec. -static const rstime_t TUNNEL_SPEED_ESTIMATE_LAPSE = 5 ; /// estimate tunnel speed every 5 seconds -static const rstime_t TUNNEL_CLEANING_LAPS_TIME = 10 ; /// clean tunnels every 10 secs -static const rstime_t TIME_BETWEEN_TUNNEL_MANAGEMENT_CALLS = 2 ; /// Tunnel management calls every 2 secs. -static const uint32_t MAX_TUNNEL_REQS_PER_SECOND = 1 ; /// maximum number of tunnel requests issued per second. Was 0.5 before -static const uint32_t MAX_ALLOWED_SR_IN_CACHE = 120 ; /// maximum number of search requests allowed in cache. That makes 2 per sec. -static const uint32_t TURTLE_SEARCH_RESULT_MAX_HITS_FILES =5000 ; /// maximum number of search results forwarded back to the source. -static const uint32_t TURTLE_SEARCH_RESULT_MAX_HITS_DEFAULT = 100 ; /// default maximum number of search results forwarded back source. - -static const float depth_peer_probability[7] = { 1.0f,0.99f,0.9f,0.7f,0.6f,0.5,0.4f } ; - -static const int TUNNEL_REQUEST_PACKET_SIZE = 50 ; -static const int MAX_TR_FORWARD_PER_SEC = 20 ; -static const int MAX_TR_FORWARD_PER_SEC_UPPER_LIMIT = 30 ; -static const int MAX_TR_FORWARD_PER_SEC_LOWER_LIMIT = 10 ; -static const int DISTANCE_SQUEEZING_POWER = 8 ; - -#define HEX_PRINT(a) std::hex << a << std::dec - -p3turtle::p3turtle(p3ServiceControl *sc,p3LinkMgr *lm) - :p3Service(), p3Config(), mServiceControl(sc), mLinkMgr(lm), mTurtleMtx("p3turtle") -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - _own_id = sc->getOwnId() ; - - if(_own_id.isNull()) - { - std::cerr << "OwnId is null, as returned by the p3ServiceControl object in turtle router. Can't go on!" << std::endl; - exit(-1) ; - } - _turtle_routing_enabled = true ; - _turtle_routing_session_enabled = true; - - _random_bias = RSRandom::random_u32() ; - _serialiser = new RsTurtleSerialiser() ; - - addSerialType(_serialiser); - - _last_clean_time = 0 ; - _last_tunnel_management_time = 0 ; - _last_tunnel_campaign_time = 0 ; - _last_tunnel_speed_estimate_time = 0 ; - - _traffic_info.reset() ; - _max_tr_up_rate = MAX_TR_FORWARD_PER_SEC ; - _service_type = getServiceInfo().mServiceType ; -} - -const std::string TURTLE_APP_NAME = "turtle"; -const uint16_t TURTLE_APP_MAJOR_VERSION = 1; -const uint16_t TURTLE_APP_MINOR_VERSION = 0; -const uint16_t TURTLE_MIN_MAJOR_VERSION = 1; -const uint16_t TURTLE_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3turtle::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_TURTLE, - TURTLE_APP_NAME, - TURTLE_APP_MAJOR_VERSION, - TURTLE_APP_MINOR_VERSION, - TURTLE_MIN_MAJOR_VERSION, - TURTLE_MIN_MINOR_VERSION); -} - -void p3turtle::getItemNames(std::map& names) const -{ - names.clear(); - - names[RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST ] = "Filename substring search request"; - names[RS_TURTLE_SUBTYPE_GENERIC_SEARCH_REQUEST ] = "Generic search request"; - names[RS_TURTLE_SUBTYPE_FT_SEARCH_RESULT ] = "File search result"; - names[RS_TURTLE_SUBTYPE_GENERIC_SEARCH_RESULT ] = "Generic search result"; - names[RS_TURTLE_SUBTYPE_OPEN_TUNNEL ] = "Tunnel request"; - names[RS_TURTLE_SUBTYPE_TUNNEL_OK ] = "Tunnel response"; - names[RS_TURTLE_SUBTYPE_FILE_REQUEST ] = "Data request"; - names[RS_TURTLE_SUBTYPE_FILE_DATA ] = "Data chunk"; - names[RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST ] = "Filename RegExp search request"; - names[RS_TURTLE_SUBTYPE_GENERIC_DATA ] = "Generic data"; - names[RS_TURTLE_SUBTYPE_FILE_MAP ] = "Chunk map"; - names[RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST ] = "Chunk map request"; - names[RS_TURTLE_SUBTYPE_CHUNK_CRC ] = "Chunk CRC"; - names[RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST ] = "Chunk CRC request"; -} - -void p3turtle::setEnabled(bool b) -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - _turtle_routing_enabled = b; - - if(b) - std::cerr << "Enabling turtle routing" << std::endl; - else - std::cerr << "Disabling turtle routing" << std::endl; - - IndicateConfigChanged() ; -} -bool p3turtle::enabled() const -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - return _turtle_routing_enabled ; -} - - -void p3turtle::setSessionEnabled(bool b) -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - _turtle_routing_session_enabled = b; - - if(b) - std::cerr << "Enabling turtle routing for this Session" << std::endl; - else - std::cerr << "Disabling turtle routing for this Session" << std::endl; -} - -bool p3turtle::sessionEnabled() const -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - return _turtle_routing_session_enabled ; -} - - -int p3turtle::tick() -{ - // Handle tunnel trafic - // - handleIncoming(); // handle incoming packets - - rstime_t now = time(NULL) ; - -#ifdef TUNNEL_STATISTICS - static rstime_t last_now = now ; - if(now - last_now > 2) - std::cerr << "******************* WARNING: now - last_now = " << now - last_now << std::endl; - last_now = now ; -#endif - - bool should_autowash,should_estimatespeed ; - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - should_autowash = now > TUNNEL_CLEANING_LAPS_TIME+_last_clean_time ; - should_estimatespeed = now >= TUNNEL_SPEED_ESTIMATE_LAPSE + _last_tunnel_speed_estimate_time ; - } - - // Tunnel management: - // - we digg new tunnels at least every 5 min (300 sec). - // - we digg new tunnels each time a new peer connects - // - we digg new tunnels each time a new hash is asked for - // - if(now >= _last_tunnel_management_time+TIME_BETWEEN_TUNNEL_MANAGEMENT_CALLS) // call every second - { -#ifdef P3TURTLE_DEBUG - std::cerr << "Calling tunnel management." << std::endl ; -#endif - if(_turtle_routing_enabled && _turtle_routing_session_enabled) - manageTunnels() ; - - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - _last_tunnel_management_time = now ; - - // Update traffic statistics. The constants are important: they allow a smooth variation of the - // traffic speed, which is used to moderate tunnel requests statistics. - // - _traffic_info = _traffic_info*0.9 + _traffic_info_buffer* (0.1 / (float)TIME_BETWEEN_TUNNEL_MANAGEMENT_CALLS) ; - _traffic_info_buffer.reset() ; - } - } - - // Clean every 10 sec. - // - if(should_autowash) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "Calling autowash." << std::endl ; -#endif - autoWash() ; // clean old/unused tunnels and file hashes, as well as search and tunnel requests. - - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - _last_clean_time = now ; - } - - if(should_estimatespeed) - { - estimateTunnelSpeeds() ; - - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - _last_tunnel_speed_estimate_time = now ; - } - -#ifdef TUNNEL_STATISTICS - // Dump state for debugging, every 20 sec. - // - static rstime_t TS_last_dump = time(NULL) ; - - if(now > 20+TS_last_dump) - { - TS_last_dump = now ; - TS_dumpState() ; - } -#endif - -#ifdef P3TURTLE_DEBUG - // Dump state for debugging, every 20 sec. - // - static rstime_t last_dump = time(NULL) ; - - if(now > 20+last_dump) - { - last_dump = now ; - dumpState() ; - } -#endif - return 0 ; -} - -// -----------------------------------------------------------------------------------// -// ------------------------------ Tunnel maintenance. ------------------------------ // -// -----------------------------------------------------------------------------------// -// - -// adds a virtual peer to the list that is communicated ot ftController. -// -void p3turtle::locked_addDistantPeer(const TurtleFileHash&,TurtleTunnelId tid) -{ - unsigned char tmp[RsPeerId::SIZE_IN_BYTES] ; - memset(tmp,0,RsPeerId::SIZE_IN_BYTES) ; - - assert(sizeof(tid) == 4) ; - - for(int i=0;i<4;++i) - tmp[i] = uint8_t( (tid >> ((3-i)*8)) & 0xff ) ; - - RsPeerId virtual_peer_id(tmp) ; - - _virtual_peers[virtual_peer_id] = tid ; -#ifdef P3TURTLE_DEBUG - assert(_local_tunnels.find(tid)!=_local_tunnels.end()) ; -#endif - _local_tunnels[tid].vpid = virtual_peer_id ; -} - -void p3turtle::getSourceVirtualPeersList(const TurtleFileHash& hash,std::list& list) -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - list.clear() ; - - std::map::const_iterator it = _incoming_file_hashes.find(hash) ; - - if(it != _incoming_file_hashes.end()) - for(uint32_t i=0;isecond.tunnels.size();++i) - { - std::map::const_iterator it2 = _local_tunnels.find( it->second.tunnels[i] ) ; - - if(it2 != _local_tunnels.end()) - { - pqipeer vp ; - vp.id = it2->second.vpid ; - vp.name = "Virtual (distant) peer" ; - vp.state = RS_PEER_S_CONNECTED ; - vp.actions = RS_PEER_CONNECTED ; - list.push_back(vp) ; - } - else - std::cerr << "(EE) getSourceVirtualPeersList(): no tunnels for incoming file hash " << hash << ": weird!"<< std::endl; - } -} - -// This method handles digging new tunnels as needed. -// New tunnels are dug when: -// - new peers have connected. The resulting tunnels should be checked against doubling. -// - new hashes are submitted for handling. -// -class hashPairComparator -{ - public: - virtual bool operator()(const std::pair& p1,const std::pair& p2) const - { - return p1.second < p2.second ; - } -}; -void p3turtle::manageTunnels() -{ - // Collect hashes for which tunnel digging is necessary / recommended. Hashes get in the list for two reasons: - // - the hash has no tunnel -> tunnel digging every EMPTY_TUNNELS_DIGGING_TIME seconds - // - the hash hasn't been tunneled for more than REGULAR_TUNNEL_DIGGING_TIME seconds, even if downloading. - // - // Candidate hashes are sorted, by olderness. The older gets tunneled first. At most MAX_TUNNEL_REQS_PER_SECOND are - // treated at once, as this method is called every second. - // Note: Because REGULAR_TUNNEL_DIGGING_TIME is larger than EMPTY_TUNNELS_DIGGING_TIME, files being downloaded get - // re-tunneled in priority. As this happens less, they don't obliterate tunneling for files that have no tunnels yet. - - std::vector > hashes_to_digg ; - rstime_t now = time(NULL) ; - - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - // digg new tunnels if no tunnels are available and force digg new tunnels at regular (large) interval - // - for(std::map::const_iterator it(_incoming_file_hashes.begin());it!=_incoming_file_hashes.end();++it) - { - // get total tunnel speed. - // - uint32_t total_speed = 0 ; - for(uint32_t i=0;isecond.tunnels.size();++i) - total_speed += _local_tunnels[it->second.tunnels[i]].speed_Bps ; - - static const float grow_speed = 1.0f ; // speed at which the time increases. - - float tunnel_keeping_factor = (std::max(1.0f,(float)total_speed/(float)(50*1024)) - 1.0f)*grow_speed + 1.0f ; - -#ifdef P3TURTLE_DEBUG - std::cerr << "Total speed = " << total_speed << ", tunel factor = " << tunnel_keeping_factor << " new time = " << rstime_t(REGULAR_TUNNEL_DIGGING_TIME*tunnel_keeping_factor) << std::endl; -#endif - - if( (it->second.tunnels.empty() && now >= it->second.last_digg_time+EMPTY_TUNNELS_DIGGING_TIME) - || (it->second.use_aggressive_mode && now >= it->second.last_digg_time + rstime_t(REGULAR_TUNNEL_DIGGING_TIME*tunnel_keeping_factor))) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "pushed hash " << it->first << ", for digging. Old = " << now - it->second.last_digg_time << std::endl; -#endif - hashes_to_digg.push_back(std::pair(it->first,it->second.last_digg_time)) ; - } - } - } -#ifdef TUNNEL_STATISTICS - std::cerr << hashes_to_digg.size() << " hashes candidate for tunnel digging." << std::endl; -#endif - - std::sort(hashes_to_digg.begin(),hashes_to_digg.end(),hashPairComparator()) ; - - for(unsigned int i=0;i::iterator it(_local_tunnels.begin());it!=_local_tunnels.end();++it) - { - TurtleTunnel& tunnel(it->second) ; - - float speed_estimate = tunnel.transfered_bytes / float(TUNNEL_SPEED_ESTIMATE_LAPSE) ; - tunnel.speed_Bps = 0.75*tunnel.speed_Bps + 0.25*speed_estimate ; - tunnel.transfered_bytes = 0 ; - } -} - -void p3turtle::autoWash() -{ -#ifdef P3TURTLE_DEBUG - std::cerr << " In autowash." << std::endl ; -#endif - // Remove hashes that are marked as such. - // - - std::vector > > services_vpids_to_remove ; - - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - for(std::set::const_iterator hit(_hashes_to_remove.begin());hit!=_hashes_to_remove.end();++hit) - { - std::map::iterator it(_incoming_file_hashes.find(*hit)) ; - - if(it == _incoming_file_hashes.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: asked to stop monitoring file hash " << *hit << ", but this hash is actually not handled by the turtle router." << std::endl ; -#endif - continue ; - } - - // copy the list of tunnels to remove. -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: stopping monitoring for file hash " << *hit << ", and closing " << it->second.tunnels.size() << " tunnels (" ; -#endif - std::vector tunnels_to_remove ; - - for(std::vector::const_iterator it2(it->second.tunnels.begin());it2!=it->second.tunnels.end();++it2) - { -#ifdef P3TURTLE_DEBUG - std::cerr << HEX_PRINT(*it2) << "," ; -#endif - tunnels_to_remove.push_back(*it2) ; - } -#ifdef P3TURTLE_DEBUG - std::cerr << ")" << std::endl ; -#endif - for(unsigned int k=0;k::iterator it(_search_requests_origins.begin());it!=_search_requests_origins.end();) - if(now > (rstime_t)(it->second.time_stamp + SEARCH_REQUESTS_LIFE_TIME)) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " removed search request " << HEX_PRINT(it->first) << ", timeout." << std::endl ; -#endif - std::map::iterator tmp(it) ; - ++tmp ; - _search_requests_origins.erase(it) ; - it = tmp ; - } - else - ++it; - } - - // Tunnel requests - // - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - for(std::map::iterator it(_tunnel_requests_origins.begin());it!=_tunnel_requests_origins.end();) - if(now > (rstime_t)(it->second.time_stamp + TUNNEL_REQUESTS_LIFE_TIME)) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " removed tunnel request " << HEX_PRINT(it->first) << ", timeout." << std::endl ; -#endif - std::map::iterator tmp(it) ; - ++tmp ; - _tunnel_requests_origins.erase(it) ; - it = tmp ; - } - else - ++it ; - } - - // Tunnels. - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - std::vector tunnels_to_close ; - - for(std::map::iterator it(_local_tunnels.begin());it!=_local_tunnels.end();++it) - if(now > (rstime_t)(it->second.time_stamp + MAXIMUM_TUNNEL_IDLE_TIME)) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " removing tunnel " << HEX_PRINT(it->first) << ": timeout." << std::endl ; -#endif - tunnels_to_close.push_back(it->first) ; - } - - for(unsigned int i=0;iremoveVirtualPeer(services_vpids_to_remove[i].second.first,services_vpids_to_remove[i].second.second) ; - } -} - -void p3turtle::forceReDiggTunnels(const TurtleFileHash& hash) -{ - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - if( _incoming_file_hashes.find(hash) == _incoming_file_hashes.end()) - { - std::cerr << "(EE) p3turtle::forceReDiggTunnels(): hash " << hash << " is not currently handled by turtle." << std::endl; - return ; - } - } - - diggTunnel(hash) ; -} - -void p3turtle::locked_closeTunnel(TurtleTunnelId tid,std::vector > >& sources_to_remove) -{ - // This is closing a given tunnel, removing it from file sources, and from the list of tunnels of its - // corresponding file hash. In the original turtle4privacy paradigm, they also send back and forward - // tunnel closing commands. In our case, this is not necessary, because if a tunnel is closed somewhere, its - // source is not going to be used and the tunnel will eventually disappear. - // - std::map::iterator it(_local_tunnels.find(tid)) ; - - if(it == _local_tunnels.end()) - { - std::cerr << "p3turtle: was asked to close tunnel " << reinterpret_cast(tid) << ", which actually doesn't exist." << std::endl ; - return ; - } -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: Closing tunnel " << HEX_PRINT(tid) << std::endl ; -#endif - - if(it->second.local_src == _own_id) // this is a starting tunnel. We thus remove - // - the virtual peer from the vpid list - // - the tunnel id from the file hash - // - the virtual peer from the file sources in the file transfer controller. - { - TurtleTunnelId tid = it->first ; - TurtleVirtualPeerId vpid = it->second.vpid ; - TurtleFileHash hash = it->second.hash ; - -#ifdef P3TURTLE_DEBUG - std::cerr << " Tunnel is a starting point. Also removing:" << std::endl ; - std::cerr << " Virtual Peer Id " << vpid << std::endl ; - std::cerr << " Associated file source." << std::endl ; -#endif - std::pair hash_vpid(hash,vpid) ; - - // Let's be cautious. Normally we should never be here without consistent information, - // but still, this happens, rarely. - // - if(_virtual_peers.find(vpid) != _virtual_peers.end()) - _virtual_peers.erase(_virtual_peers.find(vpid)) ; - - std::map::iterator it(_incoming_file_hashes.find(hash)) ; - - if(it != _incoming_file_hashes.end()) - { - std::vector& tunnels(it->second.tunnels) ; - - // Remove tunnel id from it's corresponding hash. For security we - // go through the whole tab, although the tunnel id should only be listed once - // in this tab. - // - for(unsigned int i=0;i >(it->second.service,hash_vpid)) ; - } - } - else if(it->second.local_dst == _own_id) // This is a ending tunnel. We also remove the virtual peer id - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Tunnel is a ending point. Also removing associated outgoing hash." ; -#endif - std::map::iterator itHash = _outgoing_tunnel_client_services.find(tid); - - if(itHash != _outgoing_tunnel_client_services.end()) - { - TurtleVirtualPeerId vpid = it->second.vpid ; - TurtleFileHash hash = it->second.hash ; - - std::pair hash_vpid(hash,vpid) ; - - sources_to_remove.push_back(std::pair >(itHash->second,hash_vpid)) ; - - _outgoing_tunnel_client_services.erase(itHash) ; - - // Also remove the associated virtual peer - // - if(_virtual_peers.find(vpid) != _virtual_peers.end()) - _virtual_peers.erase(_virtual_peers.find(vpid)) ; - } - } - - _local_tunnels.erase(it) ; -} - -void p3turtle::stopMonitoringTunnels(const RsFileHash& hash) -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: Marking hash " << hash << " to be removed during autowash." << std::endl ; -#endif - // We don't do the deletion in this process, because it can cause a race with tunnel management. - _hashes_to_remove.insert(hash) ; -} - -// -----------------------------------------------------------------------------------// -// -------------------------------- Config functions ------------------------------ // -// -----------------------------------------------------------------------------------// -// -RsSerialiser *p3turtle::setupSerialiser() -{ - RsSerialiser *rss = new RsSerialiser ; - rss->addSerialType(new RsTurtleSerialiser) ; - rss->addSerialType(new RsGeneralConfigSerialiser()); - - return rss ; -} - -bool p3turtle::saveList(bool& cleanup, std::list& lst) -{ -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: saving list..." << std::endl ; -#endif - cleanup = true ; - - RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; - RsTlvKeyValue kv; - kv.key = "TURTLE_CONFIG_MAX_TR_RATE" ; - rs_sprintf(kv.value, "%g", _max_tr_up_rate); - vitem->tlvkvs.pairs.push_back(kv) ; - - kv.key = "TURTLE_ENABLED" ; - kv.value = _turtle_routing_enabled?"TRUE":"FALSE" ; - - vitem->tlvkvs.pairs.push_back(kv) ; - - lst.push_back(vitem) ; - - return true ; -} - -bool p3turtle::loadList(std::list& load) -{ -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: loading list..." << std::endl ; -#endif - for(std::list::const_iterator it(load.begin());it!=load.end();++it) - { - RsConfigKeyValueSet *vitem = dynamic_cast(*it) ; - - if(vitem != NULL) - for(std::list::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) - { - if(kit->key == "TURTLE_CONFIG_MAX_TR_RATE") - { - int val ; - if (sscanf(kit->value.c_str(), "%d", &val) == 1) - { - setMaxTRForwardRate(val) ; - std::cerr << "Setting max TR forward rate to " << val << std::endl ; - } - } - if(kit->key == "TURTLE_ENABLED") - { - _turtle_routing_enabled = (kit->value == "TRUE") ; - - if(!_turtle_routing_enabled) - std::cerr << "WARNING: turtle routing has been disabled. You can enable it again in config->server->turtle router." << std::endl; - } - } - - delete *it ; - } - load.clear() ; - return true ; -} -int p3turtle::getMaxTRForwardRate() const -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - return _max_tr_up_rate ; -} - - -void p3turtle::setMaxTRForwardRate(int val) -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - if(val > MAX_TR_FORWARD_PER_SEC_UPPER_LIMIT || val < MAX_TR_FORWARD_PER_SEC_LOWER_LIMIT) - std::cerr << "Warning: MAX_TR_FORWARD_PER_SEC value " << val << " read in config file is off limits [" << MAX_TR_FORWARD_PER_SEC_LOWER_LIMIT << "..." << MAX_TR_FORWARD_PER_SEC_UPPER_LIMIT << "]. Ignoring!" << std::endl; - else - { - _max_tr_up_rate = val ; - std::cerr << "p3turtle: Set max tr up rate to " << val << std::endl; - } - IndicateConfigChanged() ; -} - - -// -----------------------------------------------------------------------------------// -// -------------------------------- Helper functions ------------------------------ // -// -----------------------------------------------------------------------------------// -// -uint32_t p3turtle::generateRandomRequestId() -{ - return RSRandom::random_u32() ; -} - -uint32_t p3turtle::generatePersonalFilePrint(const TurtleFileHash& hash,uint32_t seed,bool b) -{ - // whatever cooking from the file hash and OwnId that cannot be recovered. - // The only important thing is that the saem couple (hash,SSL id) produces the same tunnel - // id. The result uses a boolean to allow generating non symmetric tunnel ids. - - std::string buff(hash.toStdString() + _own_id.toStdString()) ; - uint32_t res = seed ; - uint32_t decal = 0 ; - - for(int i=0;i<(int)buff.length();++i) - { - res += 7*buff[i] + decal ; - - if(b) - decal = decal*44497+15641+(res%86243) ; - else - decal = decal*86243+15649+(res%44497) ; - } - - return res ; -} -// -----------------------------------------------------------------------------------// -// -------------------------------- Global routing. -------------------------------- // -// -----------------------------------------------------------------------------------// -// -int p3turtle::handleIncoming() -{ - int nhandled = 0; - // While messages read - // - RsItem *item = NULL; - - while(NULL != (item = recvItem())) - { - nhandled++; - - if(!(_turtle_routing_enabled && _turtle_routing_session_enabled)) - delete item ; - else - { - RsTurtleGenericTunnelItem *gti = dynamic_cast(item) ; - - if(gti != NULL) - routeGenericTunnelItem(gti) ; /// Generic packets, that travel through established tunnels. - else /// These packets should be destroyed by the client. - { - /// Special packets that require specific treatment, because tunnels do not exist for these packets. - /// These packets are destroyed here, after treatment. - // - switch(item->PacketSubType()) - { - case RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST: - case RS_TURTLE_SUBTYPE_GENERIC_SEARCH_REQUEST: - case RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST: handleSearchRequest(dynamic_cast(item)) ; - break ; - - case RS_TURTLE_SUBTYPE_GENERIC_SEARCH_RESULT : - case RS_TURTLE_SUBTYPE_FT_SEARCH_RESULT : handleSearchResult(dynamic_cast(item)) ; - break ; - - case RS_TURTLE_SUBTYPE_OPEN_TUNNEL : handleTunnelRequest(dynamic_cast(item)) ; - break ; - - case RS_TURTLE_SUBTYPE_TUNNEL_OK : handleTunnelResult(dynamic_cast(item)) ; - break ; - - default: - std::cerr << "p3turtle::handleIncoming: Unknown packet subtype " << item->PacketSubType() << std::endl ; - } - delete item; - } - } - } - - return nhandled; -} - -// -----------------------------------------------------------------------------------// -// -------------------------------- Search handling. ------------------------------- // -// -----------------------------------------------------------------------------------// -// -void p3turtle::handleSearchRequest(RsTurtleSearchRequestItem *item) -{ - Dbg3() << __PRETTY_FUNCTION__ << " " << *item << std::endl; - - // take a look at the item and test against inconsistent values - // - If the item destimation is - -#ifdef P3TURTLE_DEBUG - std::cerr << "Received search request from peer " << item->PeerId() << ": " << std::endl ; - item->print(std::cerr,0) ; -#endif - - uint32_t item_size = RsTurtleSerialiser().size(item); - - if(item_size > TURTLE_MAX_SEARCH_REQ_ACCEPTED_SERIAL_SIZE) - { - RsWarn() << __PRETTY_FUNCTION__ - << " Got a turtle search item with arbitrary large size from " - << item->PeerId() << " of size " << item_size << " and depth " - << item->depth << ". This is not allowed => dropping." - << std::endl; - return; - } - - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - if(_search_requests_origins.size() > MAX_ALLOWED_SR_IN_CACHE) - { - RsWarn() << __PRETTY_FUNCTION__ << " More than " - << MAX_ALLOWED_SR_IN_CACHE << " search request in cache. " - << "A peer is probably trying to flood your network See " - "the depth charts to find him." << std::endl; - return; - } - - if( _search_requests_origins.find(item->request_id) != - _search_requests_origins.end() ) - { - /* If the item contains an already handled search request, give up. - * This happens when the same search request gets relayed by - * different peers */ - return; - } - } - - // Perform local search off-mutex,because this might call some services that are above turtle in the mutex chain. - - uint32_t search_result_count = 0; - uint32_t max_allowed_hits = TURTLE_SEARCH_RESULT_MAX_HITS_DEFAULT; - - if(item->PeerId() != _own_id) // is the request not coming from us? - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Request not from us. Performing local search" << std::endl ; -#endif - std::list search_results ; - - performLocalSearch(item,search_result_count,search_results,max_allowed_hits) ; - - for(auto it(search_results.begin());it!=search_results.end();++it) - { - (*it)->request_id = item->request_id ; - (*it)->PeerId(item->PeerId()) ; - -#ifdef P3TURTLE_DEBUG - std::cerr << " sending back search result for request " << item->request_id << " to back to peer " << item->PeerId() << std::endl ; -#endif - sendItem(*it) ; - } - } - - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - // This is a new request. Let's add it to the request map, and forward it to - // open peers. - - TurtleSearchRequestInfo& req( _search_requests_origins[item->request_id] ) ; - req.origin = item->PeerId() ; - req.time_stamp = time(NULL) ; - req.depth = item->depth ; - req.result_count = search_result_count; - req.keywords = item->GetKeywords() ; - req.service_id = item->serviceId() ; - req.max_allowed_hits = max_allowed_hits; - - // if enough has been sent back already, do not sarch further - -#ifdef P3TURTLE_DEBUG - std::cerr << " result count = " << req.result_count << std::endl; -#endif - if(req.result_count >= max_allowed_hits) - return ; - - // If search depth not too large, also forward this search request to all other peers. - // - // We use a random factor on the depth test that is biased by a mix between the session id and the partial tunnel id - // to scramble a possible search-by-depth attack. - // - bool random_bypass = (item->depth >= TURTLE_MAX_SEARCH_DEPTH && (((_random_bias ^ item->request_id)&0x7)==2)) ; - bool random_dshift = (item->depth == 1 && (((_random_bias ^ item->request_id)&0x7)==6)) ; - - if(item->depth < TURTLE_MAX_SEARCH_DEPTH || random_bypass) - { - std::set onlineIds ; - mServiceControl->getPeersConnected(_service_type, onlineIds); -#ifdef P3TURTLE_DEBUG - std::cerr << " Looking for online peers" << std::endl ; -#endif - - for(std::set::const_iterator it(onlineIds.begin());it!=onlineIds.end();++it) - { -// if(!mServiceControl->isPeerConnected(RS_SERVICE_TYPE_TURTLE,*it)) -// continue ; - - uint32_t linkType = mLinkMgr->getLinkType(*it); - - if ((linkType & RS_NET_CONN_SPEED_TRICKLE) || (linkType & RS_NET_CONN_SPEED_LOW)) // don't forward searches to slow link types (e.g relay peers)! - continue ; - - if(*it != item->PeerId()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Forwarding request to peer = " << *it << std::endl ; -#endif - // Copy current item and modify it. - RsTurtleSearchRequestItem *fwd_item = item->clone() ; - - // increase search depth, except in some rare cases, to prevent correlation between - // TR sniffing and friend names. The strategy is to not increase depth if the depth - // is 1: - // If B receives a TR of depth 1 from A, B cannot deduice that A is downloading the - // file, since A might have shifted the depth. - // - if(!random_dshift) - ++(fwd_item->depth) ; - - fwd_item->PeerId(*it) ; - - sendItem(fwd_item) ; - } - } - } -#ifdef P3TURTLE_DEBUG - else - std::cout << " Dropping this item, as search depth is " << item->depth << std::endl ; -#endif -} - -// This function should be removed in the future, when file search will also use generic search items. - -void p3turtle::performLocalSearch( - RsTurtleSearchRequestItem *item, uint32_t& req_result_count, - std::list& search_results, - uint32_t& max_allowed_hits ) -{ - Dbg3() << __PRETTY_FUNCTION__ << " " << item << std::endl; - - RsTurtleFileSearchRequestItem* ftsearch = - dynamic_cast(item); - - if(ftsearch != NULL) - { - performLocalSearch_files( - ftsearch, req_result_count, search_results, - max_allowed_hits ); - return ; - } - - RsTurtleGenericSearchRequestItem *gnsearch = dynamic_cast(item) ; - - if(gnsearch != NULL) - { - performLocalSearch_generic(gnsearch,req_result_count,search_results,max_allowed_hits) ; - return ; - } -} - -void p3turtle::performLocalSearch_generic(RsTurtleGenericSearchRequestItem *item, uint32_t& /*req_result_count*/, std::list& result,uint32_t& max_allowed_hits) -{ - unsigned char *search_result_data = NULL ; - uint32_t search_result_data_len = 0 ; - - RsTurtleClientService *client = NULL ; - - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - auto it = _registered_services.find(item->service_id) ; - - if(it == _registered_services.end()) - return ; - - client = it->second ; - } - - if(client->receiveSearchRequest(item->search_data,item->search_data_len,search_result_data,search_result_data_len,max_allowed_hits)) - { - RsTurtleGenericSearchResultItem *result_item = new RsTurtleGenericSearchResultItem ; - - result_item->result_data = search_result_data ; - result_item->result_data_len = search_result_data_len ; - - result.push_back(result_item) ; - } -} - -void p3turtle::performLocalSearch_files( - RsTurtleFileSearchRequestItem *item, uint32_t& req_result_count, - std::list& result, - uint32_t& max_allowed_hits ) -{ - Dbg3() << __PRETTY_FUNCTION__ << " " << *item << std::endl; - - std::list initialResults ; - item->search(initialResults) ; - -#ifdef P3TURTLE_DEBUG - std::cerr << initialResults.size() << " matches found." << std::endl ; -#endif - result.clear() ; - RsTurtleFTSearchResultItem *res_item = NULL ; - uint32_t item_size = 0 ; - - static const uint32_t RSTURTLE_MAX_SEARCH_RESPONSE_SIZE = 10000 ; - max_allowed_hits = TURTLE_SEARCH_RESULT_MAX_HITS_FILES; - - for(auto it(initialResults.begin());it!=initialResults.end();++it) - { - if(res_item == NULL) - { - res_item = new RsTurtleFTSearchResultItem ; - item_size = 0 ; - - result.push_back(res_item) ; - } - res_item->result.push_back(*it); - - // Let's chop search results items into several chunks of finite size to avoid exceeding streamer's capacity. - // - ++req_result_count ; // increase hit number for this particular search request. - - item_size += 8 /* size */ + it->hash.serial_size() + it->name.size() ; - - if(item_size > RSTURTLE_MAX_SEARCH_RESPONSE_SIZE || req_result_count >= max_allowed_hits) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Sending back chunk of size " << item_size << ", for " << res_item->result.size() << " elements." << std::endl ; -#endif - res_item = NULL ; // forces creation of a new item. - } - } - - Dbg3() << __PRETTY_FUNCTION__ << " found " << req_result_count << " results" - << std::endl; -} - -void p3turtle::handleSearchResult(RsTurtleSearchResultItem *item) -{ - // Filter out banned hashes from the result. - - RsTurtleFTSearchResultItem *ftsr_tmp = dynamic_cast(item) ; - - if(ftsr_tmp != NULL) - { - for(auto it(ftsr_tmp->result.begin());it!=ftsr_tmp->result.end();) - if( rsFiles->isHashBanned((*it).hash) ) - { - std::cerr << "(II) filtering out banned hash " << (*it).hash << " from turtle result " << std::hex << item->request_id << std::dec << std::endl; - it = ftsr_tmp->result.erase(it); - } - else - ++it; - - if(ftsr_tmp->result.empty()) - return ; - } - - // Then handle the result - - std::list > results_to_notify_off_mutex ; - - { - RS_STACK_MUTEX(mTurtleMtx); - // Find who actually sent the corresponding request. - // - std::map::iterator it = _search_requests_origins.find(item->request_id) ; - -#ifdef P3TURTLE_DEBUG - std::cerr << "Received search result:" << std::endl ; - item->print(std::cerr,0) ; -#endif - if(it == _search_requests_origins.end()) - { - // This is an error: how could we receive a search result corresponding to a search item we - // have forwarded but that it not in the list ?? - - std::cerr << __PRETTY_FUNCTION__ << ": search result for request " << std::hex << item->request_id << std::dec << " has no peer direction!" << std::endl ; - return ; - } - - // Is this result too old? - // Search Requests younger than SEARCH_REQUESTS_LIFE_TIME are kept in the cache, so that they are not duplicated if they bounce in the network - // Nevertheless results received for Search Requests older than SEARCH_REQUESTS_RESULT_TIME are considered obsolete and discarded - if (time(NULL) > it->second.time_stamp + SEARCH_REQUESTS_RESULT_TIME) - { -#ifdef P3TURTLE_DEBUG - RsDbg() << "TURTLE p3turtle::handleSearchResult Search Request is known, but result arrives too late, dropping"; -#endif - return; - } - - // Is this result's target actually ours ? - - if(it->second.origin == _own_id) - { - it->second.result_count += item->count() ; - - auto it2 = _registered_services.find(it->second.service_id) ; - - if(it2 != _registered_services.end()) - results_to_notify_off_mutex.push_back(std::make_pair(item,it2->second)) ; - else - std::cerr << "(EE) cannot find client service for ID " << std::hex << it->second.service_id << std::dec << ": search result item will be dropped." << std::endl; - } - else - { // Nope, so forward it back. -#ifdef P3TURTLE_DEBUG - std::cerr << " Forwarding result back to " << it->second.origin << std::endl; -#endif - // We update the total count forwarded back, and chop it to TURTLE_SEARCH_RESULT_MAX_HITS. - - uint32_t n = item->count(); // not so good! - - if(it->second.result_count >= it->second.max_allowed_hits) - { - std::cerr << "(WW) exceeded turtle search result to forward. Req=" << std::hex << item->request_id << std::dec - << " already forwarded: " << it->second.result_count << ", max_allowed: " << it->second.max_allowed_hits << ": dropping item with " << n << " elements." << std::endl; - return ; - } - - if(it->second.result_count + n > it->second.max_allowed_hits) - { - for(uint32_t i=it->second.result_count + n; i>it->second.max_allowed_hits;--i) - item->pop() ; - - it->second.result_count = it->second.max_allowed_hits ; - } - else - it->second.result_count += n ; - - RsTurtleSearchResultItem *fwd_item = item->duplicate(); - - // Normally here, we should setup the forward adress, so that the owner's - // of the files found can be further reached by a tunnel. - - fwd_item->PeerId(it->second.origin) ; - - sendItem(fwd_item) ; - } - } // mTurtleMtx end - - // now we notify clients off-mutex. - - for(auto it(results_to_notify_off_mutex.begin());it!=results_to_notify_off_mutex.end();++it) - { - // Hack to use the old search result handling in ftServer. Normally ftServer should use the new method with serialized result. - -#warning make sure memory is correctly deleted here - RsTurtleFTSearchResultItem *ftsr = dynamic_cast(it->first) ; - - if(ftsr!=NULL) - { - ftServer *client = dynamic_cast((*it).second) ; - - if(!client) - { - std::cerr << "(EE) received turtle FT search result but the service is not a ftServer!!" << std::endl; - continue; - } - //RsServer::notify()->notifyTurtleSearchResult(ftsr->request_id,ftsr->result) ; - - client->ftReceiveSearchResult(ftsr); - continue ; - } - - RsTurtleGenericSearchResultItem *gnsr = dynamic_cast(it->first) ; - - if(gnsr!=NULL) - (*it).second->receiveSearchResult(gnsr->request_id,gnsr->result_data,gnsr->result_data_len) ; - } -} - -// -----------------------------------------------------------------------------------// -// --------------------------------- File Transfer. -------------------------------- // -// -----------------------------------------------------------------------------------// - -// Routing of turtle tunnel items in a generic manner. Most tunnel packets will -// use this function, except packets designed for contructing the tunnels and -// searching, namely TurtleSearchRequests/Results and OpenTunnel/TunnelOkItems -// -// Only packets coming from handleIncoming() end up here, so this function is -// able to catch the transiting traffic. -// -void p3turtle::routeGenericTunnelItem(RsTurtleGenericTunnelItem *item) -{ -#ifdef P3TURTLE_DEBUG - std::cerr << "p3Turtle: treating generic tunnel item:" << std::endl ; - item->print(std::cerr,1) ; -#endif - - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - // look for the tunnel id. - // - std::map::iterator it(_local_tunnels.find(item->tunnelId())) ; - - if(it == _local_tunnels.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: got file map with unknown tunnel id " << HEX_PRINT(item->tunnelId()) << std::endl ; -#endif - delete item; - return ; - } - - TurtleTunnel& tunnel(it->second) ; - - // Only file data transfer updates tunnels time_stamp field, to avoid maintaining tunnel that are incomplete. - if(item->shouldStampTunnel()) - tunnel.time_stamp = time(NULL) ; - - tunnel.transfered_bytes += RsTurtleSerialiser().size(item); - - if(item->PeerId() == tunnel.local_dst) - item->setTravelingDirection(RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ; - else if(item->PeerId() == tunnel.local_src) - item->setTravelingDirection(RsTurtleGenericTunnelItem::DIRECTION_SERVER) ; - else - { - std::cerr << "(EE) p3turtle::routeGenericTunnelItem(): item mismatches tunnel src/dst ids." << std::endl; - std::cerr << "(EE) tunnel.local_src = " << tunnel.local_src << std::endl; - std::cerr << "(EE) tunnel.local_dst = " << tunnel.local_dst << std::endl; - std::cerr << "(EE) item->PeerId() = " << item->PeerId() << std::endl; - std::cerr << "(EE) This item is probably lost while tunnel route got redefined. Deleting this item." << std::endl ; - delete item ; - return ; - } - - // Let's figure out whether this packet is for us or not. - - if(item->PeerId() == tunnel.local_dst && tunnel.local_src != _own_id) //direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT && - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Forwarding generic item to peer " << tunnel.local_src << std::endl ; -#endif - item->PeerId(tunnel.local_src) ; - - _traffic_info_buffer.unknown_updn_Bps += RsTurtleSerialiser().size(item) ; - - // This has been disabled for compilation reasons. Not sure we actually need it. - // - //if(dynamic_cast(item) != NULL) - // item->setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FORWARD_FILE_DATA) ; - - sendItem(item) ; - return ; - } - - if(item->PeerId() == tunnel.local_src && tunnel.local_dst != _own_id) //direction == RsTurtleGenericTunnelItem::DIRECTION_SERVER && - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Forwarding generic item to peer " << tunnel.local_dst << std::endl ; -#endif - item->PeerId(tunnel.local_dst) ; - - _traffic_info_buffer.unknown_updn_Bps += RsTurtleSerialiser().size(item); - - sendItem(item) ; - return ; - } - - // item is for us. Use the locked region to record the data. - - _traffic_info_buffer.data_dn_Bps += RsTurtleSerialiser().size(item); - } - - // The packet was not forwarded, so it is for us. Let's treat it. - // This is done off-mutex, to avoid various deadlocks - // - - handleRecvGenericTunnelItem(item) ; - - delete item ; -} - -void p3turtle::handleRecvGenericTunnelItem(RsTurtleGenericTunnelItem *item) -{ -#ifdef P3TURTLE_DEBUG - std::cerr << "p3Turtle: received Generic tunnel item:" << std::endl ; - item->print(std::cerr,1) ; -#endif - RsFileHash hash ; - RsPeerId vpid ; - RsTurtleClientService *service ; - - if(!getTunnelServiceInfo(item->tunnelId(),vpid,hash,service)) - return ; - - service->receiveTurtleData(item,hash,vpid,item->travelingDirection()) ; -} - -bool p3turtle::getTunnelServiceInfo(TurtleTunnelId tunnel_id,RsPeerId& vpid,RsFileHash& hash,RsTurtleClientService *& service) -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it2(_local_tunnels.find(tunnel_id)) ; - - if(it2 == _local_tunnels.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: unknown tunnel id " << std::hex << tunnel_id << std::dec << std::endl ; -#endif - return false; - } - - TurtleTunnel& tunnel(it2->second) ; - -#ifdef P3TURTLE_DEBUG - assert(!tunnel.hash.isNull()) ; - - std::cerr << " This is an endpoint for this file map." << std::endl ; - std::cerr << " Forwarding data to the multiplexer." << std::endl ; - std::cerr << " using peer_id=" << tunnel.vpid << ", hash=" << tunnel.hash << std::endl ; -#endif - // We should check that there is no backward call to the turtle router! - // - vpid = tunnel.vpid ; - hash = tunnel.hash ; - - // Now sort out the case of client vs. server side items. - // - if(tunnel.local_src == _own_id) - { - std::map::const_iterator it = _incoming_file_hashes.find(hash) ; - - if(it == _incoming_file_hashes.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle::handleRecvGenericTunnelItem(): hash " << hash << " for client side tunnel endpoint " << std::hex << tunnel_id << std::dec << " has been removed (probably a late response)! Dropping the item. " << std::endl; -#endif - return false; - } - - service = it->second.service ; - } - else if(tunnel.local_dst == _own_id) - { - std::map::const_iterator it = _outgoing_tunnel_client_services.find(tunnel_id) ; - - if(it == _outgoing_tunnel_client_services.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle::handleRecvGenericTunnelItem(): hash " << tunnel.hash << " for server side tunnel endpoint " << std::hex << tunnel_id << std::dec << " has been removed (probably a late response)! Dropping the item. " << std::endl; -#endif - return false; - } - - service = it->second; - } - else - { - std::cerr << "p3turtle::handleRecvGenericTunnelItem(): hash " << hash << " for tunnel " << std::hex << it2->first << std::dec << ". Tunnel is not a end-point or a starting tunnel!! This is a serious consistency error." << std::endl; - return false ; - } - - return true ; -} -// Send a data request into the correct tunnel for the given file hash -// -void p3turtle::sendTurtleData(const RsPeerId& virtual_peer_id,RsTurtleGenericTunnelItem *item) -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - // get the proper tunnel for this file hash and peer id. - std::map::const_iterator it(_virtual_peers.find(virtual_peer_id)) ; - - if(it == _virtual_peers.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle::senddataRequest: cannot find virtual peer " << virtual_peer_id << " in VP list." << std::endl ; -#endif - delete item ; - return ; - } - TurtleTunnelId tunnel_id = it->second ; - std::map::iterator it2( _local_tunnels.find(tunnel_id) ) ; - - if(it2 == _local_tunnels.end()) - { - std::cerr << "p3turtle::client asked to send a packet through tunnel that has previously been deleted. Not a big issue unless it happens in masses." << std::endl; - delete item ; - return ; - } - TurtleTunnel& tunnel(it2->second) ; - - item->tunnel_id = tunnel_id ; // we should randomly select a tunnel, or something more clever. - - uint32_t ss = RsTurtleSerialiser().size(item); - - if(item->shouldStampTunnel()) - tunnel.time_stamp = time(NULL) ; - - tunnel.transfered_bytes += ss ; - - if(tunnel.local_src == _own_id) - { - item->setTravelingDirection(RsTurtleGenericTunnelItem::DIRECTION_SERVER) ; - item->PeerId(tunnel.local_dst) ; - _traffic_info_buffer.data_dn_Bps += ss ; - } - else if(tunnel.local_dst == _own_id) - { - item->setTravelingDirection(RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ; - item->PeerId(tunnel.local_src) ; - _traffic_info_buffer.data_up_Bps += ss ; - } - else - { - std::cerr << "p3Turtle::sendTurtleData(): asked to send a packet into a tunnel that is not registered. Dropping packet." << std::endl ; - delete item ; - return ; - } - -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: sending service packet to virtual peer id " << virtual_peer_id << ", hash=0x" << tunnel.hash << ", tunnel = " << HEX_PRINT(item->tunnel_id) << ", next peer=" << tunnel.local_dst << std::endl ; -#endif - sendItem(item) ; -} - -bool p3turtle::isTurtlePeer(const RsPeerId& peer_id) const -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - return _virtual_peers.find(peer_id) != _virtual_peers.end() ; -} - -RsPeerId p3turtle::getTurtlePeerId(TurtleTunnelId tid) const -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - std::map::const_iterator it( _local_tunnels.find(tid) ) ; - -#ifdef P3TURTLE_DEBUG - assert(it!=_local_tunnels.end()) ; - assert(!it->second.vpid.isNull()) ; -#endif - - return it->second.vpid ; -} - -bool p3turtle::isOnline(const RsPeerId& peer_id) const -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - // we could do something mre clever here... - // - return _virtual_peers.find(peer_id) != _virtual_peers.end() ; -} - - -// -----------------------------------------------------------------------------------// -// -------------------------------- Tunnel handling. ------------------------------- // -// -----------------------------------------------------------------------------------// -// - -TurtleRequestId p3turtle::diggTunnel(const TurtleFileHash& hash) -{ -#ifdef P3TURTLE_DEBUG - std::cerr << "DiggTunnel: performing tunnel request. OwnId = " << _own_id << " for hash=" << hash << std::endl ; -#endif - TurtleRequestId id = generateRandomRequestId() ; - - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - // Store the request id, so that we can find the hash back when we get the response. - // - _incoming_file_hashes[hash].last_request = id ; - _incoming_file_hashes[hash].last_digg_time = time(NULL) ; - } - - // Form a tunnel request packet that simulates a request from us. - // - RsTurtleOpenTunnelItem *item = new RsTurtleOpenTunnelItem ; - - item->PeerId(_own_id) ; - item->file_hash = hash ; - item->request_id = id ; - item->partial_tunnel_id = generatePersonalFilePrint(hash,_random_bias,true) ; - item->depth = 0 ; - - // send it - -#ifdef TUNNEL_STATISTICS - TS_request_bounces[item->request_id].clear() ; // forces initialization -#endif - handleTunnelRequest(item) ; - delete item ; - - return id ; -} - -void p3turtle::handleTunnelRequest(RsTurtleOpenTunnelItem *item) -{ -#ifdef P3TURTLE_DEBUG - std::cerr << "Received tunnel request from peer " << item->PeerId() << ": " << std::endl ; - item->print(std::cerr,0) ; -#endif - - // check first if the hash is in the ban list. If so, drop the request. - - if(rsFiles->isHashBanned(item->file_hash)) - { - std::cerr << "(II) Rejecting tunnel request to ban hash " << item->file_hash << std::endl; - return ; - } - -#ifdef TUNNEL_STATISTICS - if(TS_request_bounces.find(item->request_id) != TS_request_bounces.end()) - TS_request_bounces[item->request_id].push_back(time(NULL)) ; -#endif - // TR forwarding. We must pay attention not to flood the network. The policy is to force a statistical behavior - // according to the followin grules: - // - below a number of tunnel request forwards per second MAX_TR_FORWARD_PER_SEC, we keep the traffic - // - if we get close to that limit, we drop long tunnels first with a probability that is larger for long tunnels - // - // Variables involved: - // distance_to_maximum : in [0,inf] is the proportion of the current up TR speed with respect to the maximum allowed speed. This is estimated - // as an average between the average number of TR over the 60 last seconds and the current TR up speed. - // corrected_distance : in [0,inf] is a squeezed version of distance: small values become very small and large values become very large. - // depth_peer_probability : basic probability of forwarding when the speed limit is reached. - // forward_probability : final probability of forwarding the packet, per peer. - // - // When the number of peers increases, the speed limit is reached faster, but the behavior per peer is the same. - // - - float forward_probability ; - - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - _traffic_info_buffer.tr_dn_Bps += RsTurtleSerialiser().size(item); - - float distance_to_maximum = std::min(100.0f,_traffic_info.tr_up_Bps/(float)(TUNNEL_REQUEST_PACKET_SIZE*_max_tr_up_rate)) ; - float corrected_distance = pow(distance_to_maximum,DISTANCE_SQUEEZING_POWER) ; - forward_probability = pow(depth_peer_probability[std::min((uint16_t)6,item->depth)],corrected_distance) ; -#ifdef P3TURTLE_DEBUG - std::cerr << "Forwarding probability: depth=" << item->depth << ", distance to max speed=" << distance_to_maximum << ", corrected=" << corrected_distance << ", prob.=" << forward_probability << std::endl; -#endif - } - - // If the item contains an already handled tunnel request, give up. This - // happens when the same tunnel request gets relayed by different peers. We - // have to be very careful here, not to call ftController while mTurtleMtx is - // locked. - // - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it = _tunnel_requests_origins.find(item->request_id) ; - - if(it != _tunnel_requests_origins.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " This is a bouncing request. Ignoring and deleting item." << std::endl ; -#endif - return ; - } - // This is a new request. Let's add it to the request map, and forward - // it to open peers, while the mutex is locked, so no-one can trigger the - // lock before the data is consistent. - - TurtleTunnelRequestInfo& req( _tunnel_requests_origins[item->request_id] ) ; - req.origin = item->PeerId() ; - req.time_stamp = time(NULL) ; - req.depth = item->depth ; - -#ifdef TUNNEL_STATISTICS - std::cerr << "storing tunnel request " << (void*)(item->request_id) << std::endl ; - - ++TS_tunnel_length[item->depth] ; - TS_request_time_stamps[item->file_hash].push_back(std::pair(time(NULL),item->request_id)) ; -#endif - } - - // If it's not for us, perform a local search. If something found, forward the search result back. - // We're off-mutex here. - - bool found = false ; - //std::string info ; - RsTurtleClientService *service = NULL ; - - if(item->PeerId() != _own_id) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Request not from us. Performing local search" << std::endl ; -#endif - found = performLocalHashSearch(item->file_hash,item->PeerId(),service) ; - } - - { - if(found) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Local hash found. Sending tunnel ok to origin (" << item->PeerId() << ")." << std::endl ; -#endif - // Send back tunnel ok to the same guy - // - RsTurtleTunnelOkItem *res_item = new RsTurtleTunnelOkItem ; - TurtleVirtualPeerId vpid ; - - res_item->request_id = item->request_id ; - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - res_item->tunnel_id = item->partial_tunnel_id ^ generatePersonalFilePrint(item->file_hash,_random_bias,false) ; - - res_item->PeerId(item->PeerId()) ; - - TurtleTunnelId t_id = res_item->tunnel_id ; // save it because sendItem deletes the item - - sendItem(res_item) ; - - // Note in the tunnels list that we have an ending tunnel here. - TurtleTunnel tt ; - tt.local_src = item->PeerId() ; - tt.hash = item->file_hash ; - tt.local_dst = _own_id ; // this means us - tt.time_stamp = time(NULL) ; - tt.transfered_bytes = 0 ; - tt.speed_Bps = 0.0f ; - - _local_tunnels[t_id] = tt ; - - // We add a virtual peer for that tunnel+hash combination. - // - locked_addDistantPeer(item->file_hash,t_id) ; - - // Store some info string about the tunnel. - // - _outgoing_tunnel_client_services[t_id] = service ; - - vpid = _local_tunnels[t_id].vpid; - } - - // Notify the client service that there's a new virtual peer id available as a client. - // - service->addVirtualPeer(item->file_hash,vpid,RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ; - - // We return straight, because when something is found, there's no need to digg a tunnel further. - // - - return ; - } -#ifdef P3TURTLE_DEBUG - else - std::cerr << " No hash found locally, or local file not allowed for distant peers. Forwarding. " << std::endl ; -#endif - } - - // If search depth not too large, also forward this search request to all other peers. - // - bool random_bypass = (item->depth >= TURTLE_MAX_SEARCH_DEPTH && (((_random_bias ^ item->partial_tunnel_id)&0x7)==2)) ; - bool random_dshift = (item->depth == 1 && (((_random_bias ^ item->partial_tunnel_id)&0x7)==6)) ; - - // Multi-tunneling trick: consistently perturbate the half-tunnel id: - // - the tunnel id will now be unique for a given route - // - allows a better balance of bandwidth for a given transfer - // - avoid the waste of items that get lost when re-routing a tunnel - -#ifdef P3TURTLE_DEBUG - std::cerr << "Perturbating partial tunnel id. Original=" << std::hex << item->partial_tunnel_id ; -#endif - item->partial_tunnel_id = generatePersonalFilePrint(item->file_hash,item->partial_tunnel_id ^ _random_bias,true) ; - -#ifdef P3TURTLE_DEBUG - std::cerr << " new=" << item->partial_tunnel_id << std::dec << std::endl; -#endif - - if(item->depth < TURTLE_MAX_SEARCH_DEPTH || random_bypass) - { - std::set onlineIds ; - mServiceControl->getPeersConnected(_service_type, onlineIds); - -// for(std::set::iterator it(onlineIds.begin());it!=onlineIds.end();) -// if(!mServiceControl->isPeerConnected(RS_SERVICE_PERM_TURTLE,*it)) -// { -// std::set::iterator tmp = it++ ; -// onlineIds.erase(tmp) ; -// } -// else -// ++it ; - - int nb_online_ids = onlineIds.size() ; - - if(forward_probability * nb_online_ids < 1.0f && nb_online_ids > 0) - { - forward_probability = 1.0f / nb_online_ids ; - - // Setting forward_probability to 1/nb_online_ids forces at most one TR up per TR dn. But if we are overflooded by - // TR dn, we still need to control them to avoid flooding the pqiHandler outqueue. So we additionally moderate the - // forward probability so as to reduct the output rate accordingly. - // - if(_traffic_info.tr_dn_Bps / (float)TUNNEL_REQUEST_PACKET_SIZE > _max_tr_up_rate) - forward_probability *= _max_tr_up_rate*TUNNEL_REQUEST_PACKET_SIZE / (float)_traffic_info.tr_dn_Bps ; - } - -#ifdef P3TURTLE_DEBUG - std::cerr << " Forwarding tunnel request: Looking for online peers" << std::endl ; -#endif - - for(std::set::const_iterator it(onlineIds.begin());it!=onlineIds.end();++it) - { - uint32_t linkType = mLinkMgr->getLinkType(*it); - - if ((linkType & RS_NET_CONN_SPEED_TRICKLE) || (linkType & RS_NET_CONN_SPEED_LOW)) // don't forward tunnel requests to slow link types (e.g relay peers)! - continue ; - - if(*it != item->PeerId() && RSRandom::random_f32() <= forward_probability) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Forwarding request to peer = " << *it << std::endl ; -#endif - // Copy current item and modify it. - RsTurtleOpenTunnelItem *fwd_item = new RsTurtleOpenTunnelItem(*item) ; - - // increase search depth, except in some rare cases, to prevent correlation between - // TR sniffing and friend names. The strategy is to not increase depth if the depth - // is 1: - // If B receives a TR of depth 1 from A, B cannot deduice that A is downloading the - // file, since A might have shifted the depth. - // - if(!random_dshift) - ++(fwd_item->depth) ; // increase tunnel depth - - fwd_item->PeerId(*it) ; - - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - _traffic_info_buffer.tr_up_Bps += RsTurtleSerialiser().size(fwd_item); - } - - sendItem(fwd_item) ; - } - } - } -#ifdef P3TURTLE_DEBUG - else - std::cout << " Dropping this item, as tunnel depth is " << item->depth << std::endl ; -#endif -} - -void p3turtle::handleTunnelResult(RsTurtleTunnelOkItem *item) -{ - bool new_tunnel = false ; - TurtleFileHash new_hash ; - RsPeerId new_vpid ; - RsTurtleClientService *service = NULL ; - - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - // Find who actually sent the corresponding turtle tunnel request. - // - std::map::iterator it = _tunnel_requests_origins.find(item->request_id) ; -#ifdef P3TURTLE_DEBUG - std::cerr << "Received tunnel result:" << std::endl ; - item->print(std::cerr,0) ; -#endif - - if(it == _tunnel_requests_origins.end()) - { - // This is an error: how could we receive a tunnel result corresponding to a tunnel item we - // have forwarded but that it not in the list ?? Actually that happens, when tunnel requests - // get too old, before the tunnelOk item gets back. But this is quite unusual. - -#ifdef P3TURTLE_DEBUG - std::cerr << __PRETTY_FUNCTION__ << ": tunnel result has no peer direction!" << std::endl ; -#endif - return ; - } - if(it->second.responses.find(item->tunnel_id) != it->second.responses.end()) - { - std::cerr << "p3turtle: ERROR: received a tunnel response twice. That should not happen." << std::endl; - return ; - } - else - it->second.responses.insert(item->tunnel_id) ; - - // store tunnel info. - bool found = (_local_tunnels.find(item->tunnel_id) != _local_tunnels.end()) ; - TurtleTunnel& tunnel(_local_tunnels[item->tunnel_id]) ; - - if(found) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "Tunnel id " << HEX_PRINT(item->tunnel_id) << " is already there. Not storing." << std::endl ; -#endif - } - else - { - tunnel.local_src = it->second.origin ; - tunnel.local_dst = item->PeerId() ; - tunnel.hash.clear() ; - tunnel.time_stamp = time(NULL) ; - tunnel.transfered_bytes = 0 ; - tunnel.speed_Bps = 0.0f ; - -#ifdef P3TURTLE_DEBUG - std::cerr << " storing tunnel info. src=" << tunnel.local_src << ", dst=" << tunnel.local_dst << ", id=" << item->tunnel_id << std::endl ; -#endif - } - - // Is this result too old? - // Tunnel Requests younger than TUNNEL_REQUESTS_LIFE_TIME are kept in the cache, so that they are not duplicated if they bounce in the network - // Nevertheless results received for Tunnel Requests older than TUNNEL_REQUESTS_RESULT_TIME are considered obsolete and discarded - if (time(NULL) > it->second.time_stamp + TUNNEL_REQUESTS_RESULT_TIME) - { -#ifdef P3TURTLE_DEBUG - RsDbg() << "TURTLE p3turtle::handleTunnelResult Tunnel Request is known, but result arrives too late, dropping"; -#endif - return; - } - - // Is this result's target actually ours ? - - if(it->second.origin == _own_id) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Tunnel starting point. Storing id=" << HEX_PRINT(item->tunnel_id) << " for hash (unknown) and tunnel request id " << it->second.origin << std::endl; -#endif - // Tunnel is ending here. Add it to the list of tunnels for the given hash. - - // 1 - find which file hash issued this request. This is not costly, - // because there is not too much file hashes to be active at a time, - // and this mostly prevents from sending the hash back in the tunnel. - -#ifdef P3TURTLE_DEBUG - bool ext_found = false ; -#endif - for(std::map::iterator it(_incoming_file_hashes.begin());it!=_incoming_file_hashes.end();++it) - if(it->second.last_request == item->request_id) - { -#ifdef P3TURTLE_DEBUG - ext_found = true ; -#endif - - { - // add the tunnel uniquely - bool found = false ; - - for(unsigned int j=0;jsecond.tunnels.size();++j) - if(it->second.tunnels[j] == item->tunnel_id) - found = true ; - - if(!found) - it->second.tunnels.push_back(item->tunnel_id) ; - - tunnel.hash = it->first ; // because it's a local tunnel - - // Adds a virtual peer to the list of online peers. - // We do this later, because of the mutex protection. - // - new_tunnel = true ; - new_hash = it->first ; - service = it->second.service ; - - locked_addDistantPeer(new_hash,item->tunnel_id) ; - new_vpid = _local_tunnels[item->tunnel_id].vpid ; // save it for off-mutex usage. - } - } -#ifdef P3TURTLE_DEBUG - if(!ext_found) - std::cerr << "p3turtle: error. Could not find hash that emmitted tunnel request " << reinterpret_cast(item->tunnel_id) << std::endl ; -#endif - } - else - { // Nope, forward it back. -#ifdef P3TURTLE_DEBUG - std::cerr << " Forwarding result back to " << it->second.origin << std::endl; -#endif - RsTurtleTunnelOkItem *fwd_item = new RsTurtleTunnelOkItem(*item) ; // copy the item - fwd_item->PeerId(it->second.origin) ; - - sendItem(fwd_item) ; - } - } - - // A new tunnel has been created. Add the corresponding virtual peer to the list, and - // notify the file transfer controller for the new file source. This should be done off-mutex - // so we deported this code here. - // - if(new_tunnel && service != NULL) - service->addVirtualPeer(new_hash,new_vpid,RsTurtleGenericTunnelItem::DIRECTION_SERVER) ; -} - -// -----------------------------------------------------------------------------------// -// ------------------------------ IO with libretroshare ----------------------------// -// -----------------------------------------------------------------------------------// -// - - -void RsTurtleStringSearchRequestItem::search( - std::list& result ) const -{ - /* call to core */ - std::list initialResults; - std::list words ; - - // to do: split search string into words. - words.push_back(match_string) ; - -#ifdef P3TURTLE_DEBUG - std::cerr << "Performing rsFiles->search()" << std::endl ; -#endif - // now, search! - rsFiles->SearchKeywords( - words, initialResults, - RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_SEARCHABLE, PeerId() ); - -#ifdef P3TURTLE_DEBUG - std::cerr << initialResults.size() << " matches found." << std::endl ; -#endif - result.clear() ; - - for(auto& it: std::as_const(initialResults)) - { - // retain only file type - if (it.type == DIR_TYPE_DIR) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Skipping directory " << it->name << std::endl ; -#endif - continue; - } - - TurtleFileInfo i; - i.hash = it.hash; - i.size = it.size; - i.name = it.name; - - result.push_back(i); - } -} -void RsTurtleRegExpSearchRequestItem::search(std::list& result) const -{ - /* call to core */ - std::list initialResults; - - // to do: split search string into words. - RsRegularExpression::Expression *exp = RsRegularExpression::LinearizedExpression::toExpr(expr) ; - - if(exp == NULL) - return ; - -#ifdef P3TURTLE_DEBUG - std::cerr << "Local search on exp: " << exp->toStdString() << std::endl; -#endif - - // now, search! - rsFiles->SearchBoolExp(exp,initialResults,RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_SEARCHABLE,PeerId()); - - result.clear() ; - - for(std::list::const_iterator it(initialResults.begin());it!=initialResults.end();++it) - { - // retain only file type - if (it->type == DIR_TYPE_DIR) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Skipping directory " << it->name << std::endl ; -#endif - continue; - } - TurtleFileInfo i ; - i.hash = it->hash ; - i.size = it->size ; - i.name = it->name ; - - result.push_back(i) ; - } - delete exp ; -} - -TurtleRequestId p3turtle::turtleSearch(const std::string& string_to_match) -{ - // generate a new search id. - - TurtleRequestId id = generateRandomRequestId() ; - - // Form a request packet that simulates a request from us. - // - RsTurtleStringSearchRequestItem *item = new RsTurtleStringSearchRequestItem ; - -#ifdef P3TURTLE_DEBUG - std::cerr << "performing search. OwnId = " << _own_id << std::endl ; -#endif - - item->PeerId(_own_id) ; - item->match_string = string_to_match ; - item->request_id = id ; - item->depth = 0 ; - - // send it - - handleSearchRequest(item) ; - - delete item ; - - return id ; -} -TurtleRequestId p3turtle::turtleSearch(const RsRegularExpression::LinearizedExpression& expr) -{ - // generate a new search id. - - TurtleRequestId id = generateRandomRequestId() ; - - // Form a request packet that simulates a request from us. - // - RsTurtleRegExpSearchRequestItem *item = new RsTurtleRegExpSearchRequestItem ; - -#ifdef P3TURTLE_DEBUG - std::cerr << "performing search. OwnId = " << _own_id << std::endl ; -#endif - - item->PeerId(_own_id) ; - item->expr = expr ; - item->request_id = id ; - item->depth = 0 ; - - // send it - - handleSearchRequest(item) ; - - delete item ; - - return id ; -} - -TurtleRequestId p3turtle::turtleSearch(unsigned char *search_bin_data,uint32_t search_bin_data_len,RsTurtleClientService *client_service) -{ - // generate a new search id. - - TurtleRequestId id = generateRandomRequestId() ; - - // Form a request packet that simulates a request from us. - // - RsTurtleGenericSearchRequestItem item ; - -#ifdef P3TURTLE_DEBUG - std::cerr << "performing search. OwnId = " << _own_id << std::endl ; -#endif - - item.PeerId(_own_id) ; - item.service_id = client_service->serviceId(); - item.search_data = search_bin_data ; - item.search_data_len = search_bin_data_len ; - item.request_id = id ; - item.depth = 0 ; - - // send it - - handleSearchRequest(&item) ; - - return id ; -} - -void p3turtle::monitorTunnels(const RsFileHash& hash,RsTurtleClientService *client_service,bool allow_multi_tunnels) -{ - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - // First, check if the hash is tagged for removal (there's a delay) - - if(_hashes_to_remove.erase(hash) > 0) - { -#ifdef P3TURTLE_DEBUG - TURTLE_DEBUG() << "p3turtle: File hash " << hash << " Was scheduled for removal. Canceling the removal." << std::endl ; -#endif - } - - // Then, check if the hash is already there - // - if(_incoming_file_hashes.find(hash) != _incoming_file_hashes.end()) // download already asked. - { -#ifdef P3TURTLE_DEBUG - TURTLE_DEBUG() << "p3turtle: File hash " << hash << " already in pool. Returning." << std::endl ; -#endif - return ; - } -#ifdef P3TURTLE_DEBUG - TURTLE_DEBUG() << "p3turtle: Received order for turtle download fo hash " << hash << std::endl ; -#endif - - // No tunnels at start, but this triggers digging new tunnels. - // - _incoming_file_hashes[hash].tunnels.clear(); - _incoming_file_hashes[hash].use_aggressive_mode = allow_multi_tunnels ; - - // also should send associated request to the file transfer module. - _incoming_file_hashes[hash].last_digg_time = RSRandom::random_u32()%10 ; - _incoming_file_hashes[hash].service = client_service ; - } -} - - -// RsTurtleGxsSearchResultGroupSummaryItem *gxs_sr_gs = dynamic_cast(item) ; -// -// if(gxs_sr_gs != NULL) -// { -// RsServer::notify()->notifyTurtleSearchResult(gxs_sr_gs->request_id,gxs_sr_gs->result) ; -// return ; -// } -// RsTurtleGxsSearchResultGroupDataItem *gxs_sr_gd = dynamic_cast(item) ; -// -// if(gxs_sr_gd != NULL) -// { -//#warning MISSING CODE HERE TO HANDLE ENCRYPTED INCOMING GROUP DATA. -// //RsServer::notify()->notifyTurtleSearchResult(gxs_sr_gd->request_id,gxs_sr_gd->encrypted_nxs_group) ; -// return ; -// } - -/// Warning: this function should never be called while the turtle mutex is locked. -/// Otherwize this is a possible source of cross-lock with the File mutex. -// -bool p3turtle::performLocalHashSearch(const TurtleFileHash& hash,const RsPeerId& peer_id,RsTurtleClientService *& service) -{ - std::map client_map ; - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - if(_registered_services.empty()) - { - std::cerr << "Turtle router has no services registered. Tunnel requests cannot be handled." << std::endl; - return false ; - } - - client_map = _registered_services ; - } - - for(auto it(client_map.begin());it!=client_map.end();++it) - if( (*it).second->handleTunnelRequest(hash,peer_id)) - { - service = it->second ; - return true ; - } - - return false ; -} - - -void p3turtle::registerTunnelService(RsTurtleClientService *service) -{ - std::cerr << "p3turtle: registered new tunnel service with ID=" << std::hex << service->serviceId() << std::dec << " and pointer " << (void*)service << std::endl; - - _registered_services[service->serviceId()] = service ; - _serialiser->registerClientService(service) ; -} - -static std::string printFloatNumber(float num,bool friendly=false) -{ - if(friendly) - { - char tmp[100] ; - std::string units[4] = { "B/s","KB/s","MB/s","GB/s" } ; - - int k=0 ; - while(num >= 800.0f && k<4) - num /= 1024.0f,++k; - - sprintf(tmp,"%3.2f %s",num,units[k].c_str()) ; - return std::string(tmp) ; - } - else - { - std::string out ; - rs_sprintf(out, "%g", num) ; - return out ; - } -} -static std::string printNumber(uint64_t num,bool hex=false) -{ - if(hex) - { - char tmp[100] ; - - if(num < (((uint64_t)1)<<32)) - sprintf(tmp,"%08x", uint32_t(num)) ; - else - sprintf(tmp,"%08x%08x", uint32_t(num >> 32),uint32_t(num & ( (((uint64_t)1)<<32)-1 ))) ; - return std::string(tmp) ; - } - else - { - std::string out ; - rs_sprintf(out, "%lld", num) ; - return out ; - } -} - -void p3turtle::getTrafficStatistics(TurtleTrafficStatisticsInfo& info) const -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - info = _traffic_info ; - - float distance_to_maximum = std::min(100.0f,info.tr_up_Bps/(float)(TUNNEL_REQUEST_PACKET_SIZE*_max_tr_up_rate)) ; - info.forward_probabilities.clear() ; - - std::set onlineIds ; - mServiceControl->getPeersConnected(_service_type, onlineIds); - - int nb_online_ids = onlineIds.size() ; - - for(int i=0;i<=6;++i) - { - float corrected_distance = pow(distance_to_maximum,DISTANCE_SQUEEZING_POWER) ; - float forward_probability = pow(depth_peer_probability[i],corrected_distance) ; - - if(forward_probability * nb_online_ids < 1.0f && nb_online_ids > 0) - { - forward_probability = 1.0f / nb_online_ids ; - - if(_traffic_info.tr_dn_Bps / (float)TUNNEL_REQUEST_PACKET_SIZE > _max_tr_up_rate) - forward_probability *= _max_tr_up_rate*TUNNEL_REQUEST_PACKET_SIZE / (float)_traffic_info.tr_dn_Bps ; - } - - info.forward_probabilities.push_back(forward_probability) ; - } -} - -std::string p3turtle::getPeerNameForVirtualPeerId(const RsPeerId& virtual_peer_id) -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - std::string name = "unknown"; - std::map::const_iterator it(_virtual_peers.find(virtual_peer_id)) ; - if(it != _virtual_peers.end()) - { - std::map::iterator it2( _local_tunnels.find(it->second) ) ; - if(it2 != _local_tunnels.end()) - { - if(it2->second.local_src == _own_id) - mLinkMgr->getPeerName(it2->second.local_dst,name); - else - mLinkMgr->getPeerName(it2->second.local_src,name); - } - } - return name; -} - -bool p3turtle::encryptData(const unsigned char *clear_data,uint32_t clear_data_size,uint8_t *encryption_master_key,RsTurtleGenericDataItem *& encrypted_item) -{ - unsigned char *encrypted_data = NULL ; - uint32_t encrypted_data_len = 0 ; - - if(!librs::crypto::encryptAuthenticateData(clear_data,clear_data_size,encryption_master_key,encrypted_data,encrypted_data_len)) - { - delete encrypted_item ; - return false ; - } - encrypted_item = new RsTurtleGenericDataItem ; - - encrypted_item->data_bytes = encrypted_data ; - encrypted_item->data_size = encrypted_data_len ; - return true; -} - -bool p3turtle::decryptItem(const RsTurtleGenericDataItem* encrypted_item, uint8_t *encryption_master_key, unsigned char *& decrypted_data, uint32_t& decrypted_data_size) -{ - return librs::crypto::decryptAuthenticateData((unsigned char*)encrypted_item->data_bytes,encrypted_item->data_size,encryption_master_key,decrypted_data,decrypted_data_size); -} - -void p3turtle::getInfo( std::vector >& hashes_info, - std::vector >& tunnels_info, - std::vector& search_reqs_info, - std::vector& tunnel_reqs_info) const -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - rstime_t now = time(NULL) ; - - hashes_info.clear() ; - - for(std::map::const_iterator it(_incoming_file_hashes.begin());it!=_incoming_file_hashes.end();++it) - { - hashes_info.push_back(std::vector()) ; - - std::vector& hashes(hashes_info.back()) ; - - hashes.push_back(it->first.toStdString()) ; - //hashes.push_back(it->second.name) ; - hashes.push_back("Name not available") ; - hashes.push_back(printNumber(it->second.tunnels.size())) ; - //hashes.push_back(printNumber(now - it->second.time_stamp)+" secs ago") ; - } - - tunnels_info.clear(); - - for(std::map::const_iterator it(_local_tunnels.begin());it!=_local_tunnels.end();++it) - { - tunnels_info.push_back(std::vector()) ; - std::vector& tunnel(tunnels_info.back()) ; - - tunnel.push_back(printNumber(it->first,true)) ; - - std::string name; - if(mLinkMgr->getPeerName(it->second.local_src,name)) - tunnel.push_back(name) ; - else - tunnel.push_back(it->second.local_src.toStdString()) ; - - if(mLinkMgr->getPeerName(it->second.local_dst,name)) - tunnel.push_back(name) ; - else - tunnel.push_back(it->second.local_dst.toStdString()); - - tunnel.push_back(it->second.hash.toStdString()) ; - tunnel.push_back(printNumber(now-it->second.time_stamp) + " secs ago") ; - tunnel.push_back(printFloatNumber(it->second.speed_Bps,false)) ; // - } - - search_reqs_info.clear(); - - for(std::map::const_iterator it(_search_requests_origins.begin());it!=_search_requests_origins.end();++it) - { - TurtleSearchRequestDisplayInfo info ; - - info.request_id = it->first ; - info.source_peer_id = it->second.origin ; - info.age = now - it->second.time_stamp ; - info.depth = it->second.depth ; - info.keywords = it->second.keywords ; - info.hits = it->second.result_count ; - - search_reqs_info.push_back(info) ; - } - - tunnel_reqs_info.clear(); - - for(std::map::const_iterator it(_tunnel_requests_origins.begin());it!=_tunnel_requests_origins.end();++it) - { - TurtleTunnelRequestDisplayInfo info ; - - info.request_id = it->first ; - info.source_peer_id = it->second.origin ; - info.age = now - it->second.time_stamp ; - info.depth = it->second.depth ; - - tunnel_reqs_info.push_back(info) ; - } -} - -#ifdef P3TURTLE_DEBUG -void p3turtle::dumpState() -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - rstime_t now = time(NULL) ; - - std::cerr << std::endl ; - std::cerr << "********************** Turtle router dump ******************" << std::endl ; - std::cerr << " Active incoming file hashes: " << _incoming_file_hashes.size() << std::endl ; - for(std::map::const_iterator it(_incoming_file_hashes.begin());it!=_incoming_file_hashes.end();++it) - { - std::cerr << " hash=0x" << it->first << ", tunnel ids =" ; - for(std::vector::const_iterator it2(it->second.tunnels.begin());it2!=it->second.tunnels.end();++it2) - std::cerr << " " << HEX_PRINT(*it2) ; - //std::cerr << ", last_req=" << (void*)it->second.last_request << ", time_stamp = " << it->second.time_stamp << "(" << now-it->second.time_stamp << " secs ago)" << std::endl ; - } - std::cerr << " Active outgoing file hashes: " << _outgoing_tunnel_client_services.size() << std::endl ; - for(std::map::const_iterator it(_outgoing_tunnel_client_services.begin());it!=_outgoing_tunnel_client_services.end();++it) - std::cerr << " TID=0x" << it->first << std::endl ; - - std::cerr << " Local tunnels:" << std::endl ; - for(std::map::const_iterator it(_local_tunnels.begin());it!=_local_tunnels.end();++it) - std::cerr << " " << HEX_PRINT(it->first) << ": from=" - << it->second.local_src << ", to=" << it->second.local_dst - << ", hash=0x" << it->second.hash << ", ts=" << it->second.time_stamp << " (" << now-it->second.time_stamp << " secs ago)" - << ", peer id =" << it->second.vpid << std::endl ; - - std::cerr << " buffered request origins: " << std::endl ; - std::cerr << " Search requests: " << _search_requests_origins.size() << std::endl ; - - for(std::map::const_iterator it(_search_requests_origins.begin());it!=_search_requests_origins.end();++it) - std::cerr << " " << HEX_PRINT(it->first) << ": from=" << it->second.origin - << ", ts=" << it->second.time_stamp << " (" << now-it->second.time_stamp - << " secs ago)" - << it->second.result_count << " hits" << std::endl ; - - std::cerr << " Tunnel requests: " << _tunnel_requests_origins.size() << std::endl ; - for(std::map::const_iterator it(_tunnel_requests_origins.begin());it!=_tunnel_requests_origins.end();++it) - std::cerr << " " << HEX_PRINT(it->first) << ": from=" << it->second.origin - << ", ts=" << it->second.time_stamp << " (" << now-it->second.time_stamp - << " secs ago)" << std::endl ; - - std::cerr << " Virtual peers:" << std::endl ; - for(std::map::const_iterator it(_virtual_peers.begin());it!=_virtual_peers.end();++it) - std::cerr << " id=" << it->first << ", tunnel=" << HEX_PRINT(it->second) << std::endl ; - std::cerr << " Online peers: " << std::endl ; -// for(std::list::const_iterator it(_online_peers.begin());it!=_online_peers.end();++it) -// std::cerr << " id=" << it->id << ", name=" << it->name << ", state=" << it->state << ", actions=" << it->actions << std::endl ; -} -#endif - -#ifdef TUNNEL_STATISTICS -void p3turtle::TS_dumpState() -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - rstime_t now = time(NULL) ; - std::cerr << "Dumping tunnel statistics:" << std::endl; - - std::cerr << "TR Bounces: " << TS_request_bounces.size() << std::endl; - for(std::map >::const_iterator it(TS_request_bounces.begin());it!=TS_request_bounces.end();++it) - { - std::cerr << (void*)it->first << ": " ; - for(uint32_t i=0;isecond.size();++i) - std::cerr << it->second[i] - it->second[0] << " " ; - std::cerr << std::endl; - } - std::cerr << "TR in cache: " << _tunnel_requests_origins.size() << std::endl; - std::cerr << "TR by size: " ; - for(int i=0;i<8;++i) - std::cerr << "N(" << i << ")=" << TS_tunnel_length[i] << ", " ; - std::cerr << std::endl; - - std::cerr << "Total different requested files: " << TS_request_time_stamps.size() << std::endl; - for(std::map > >::const_iterator it(TS_request_time_stamps.begin());it!=TS_request_time_stamps.end();++it) - { - std::cerr << "hash = " << it->first << ": seconds ago: " ; - float average = 0 ; - for(uint32_t i=std::max(0,(int)it->second.size()-25);isecond.size();++i) - { - std::cerr << now - it->second[i].first << " (" << (void*)it->second[i].second << ") " ; - - if(i>0) - average += it->second[i].first - it->second[i-1].first ; - } - - if(it->second.size()>1) - std::cerr << ", average delay=" << average/(float)(it->second.size()-1) << std::endl; - else - std::cerr << std::endl; - } -} -#endif diff --git a/libretroshare/src/turtle/p3turtle.h b/libretroshare/src/turtle/p3turtle.h deleted file mode 100644 index 6c0b0012d..000000000 --- a/libretroshare/src/turtle/p3turtle.h +++ /dev/null @@ -1,473 +0,0 @@ -/******************************************************************************* - * libretroshare/src/turtle: p3turtle.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009-2018 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -//====================================== General setup of the router ===================================// -// -// This class implements the turtle hopping router. It basically serves as -// - a cache of turtle tunnels which are the communicating ways between distant peers. -// - turtle tunnels are either end-point tunnels, or transitory points, in which case items are just -// re-serialized and passed on along the tunnel. -// - turtle tunnels are dug on request when calling diggTurtleTunnel(const std::string& hash) -// this command lets a trace in each peer along the tunnel of where -// packets come from and where they should go. Doing so, once a tunnel is -// dug, packets are directly forwarded to the correct peer. -// - an entry point for search request from the interface -// - search results, as they come back, are forwarded upwards with some additional info: -// - depth // depth of the file. setup to 1 for immediate friends and 2 for long distance friends. -// - hash // hash of the file found -// - name // name of the file found -// - search request id. // -// -// - when downloading: -// - for a given hash, a set of starting tunnels is maintained. Transitory -// tunnels are also maintained for other hashes as requested by distant -// peers. -// -//============================================= Operations =============================================// -// -// A download session works as follows: -// Initiation: -// 1 - the user searches for files (turtle search), and selects one and clicks download. -// 2 - In parallel: -// - the ft module gets a request, and searches for peers to provide this using its search modules. -// - the turtle router is informed that a turtle download will happen with the given hash, so -// it initiates tunnels for this hash. -// In a loop: -// 3 - the ft module asks the hash to the turtle searchModule, and sends file requests to the pqi -// interface of this module. -// 4 - the turtle pqi interface forwards these requests to the turtle router, which sends them to -// the correct peers, selecting randomly among all the possible tunnels for this hash. -// 5 - when a file data packet gets back, the turtle router forwards it back to the file transfer module. -// -//================================ connection to the file transfer module ===============================// -// -// The turtle router should provide the ft module with the necessary interface for asking files, and -// retreiving data: -// - a search module that responds with a given fake peer id for hash request for which it has tunnels. -// - a pqi interface to ask for file data -// - p3turtle sends back file data packets to the file transfer module -// -//========================================== Tunnel usage rules ========================================// -// -// Tunnels should be used according to their capacity. This is an unsolved problem as for now. -// -//======================================= Tunnel maintenance rules =====================================// -// -// P3turtle should derive from pqihandler, just as p3disc, so that newly connected peers should trigger -// asking for new tunnels, and disconnecting peers should produce a close tunnel packet. To simplify this, -// I maintain a time stamp in tunnels, that is updated each time a file data packet travels in the tunnel. -// Doing so, if a tunnel is not used for some time, it just disapears. Additional rules apply: -// -// - when a peer A connects: -// - initiate new tunnels for all active file hashes (go through the list of hashes) by -// asking to A, for the same hash and the same source. Only report tunnels for which the destination -// endpoint is different, which should not happen in fact, because of bouncing gards. -// -// - when a peer A disconnects. -// - do nothing. -// -// - when receive open tunnel from A -// - check whether it's a bouncing request. If yes, give up. -// - check hash against local files. -// if > 0 -// return tunnel ok item. No need to go forward, as sub tunnels are not useful. -// else -// forward request to peers, notting source and hashes. -// -// - when receive tunnel ok from A -// - no need to check whether we already have this tunnel, as bouncing gards prevent this. -// - leave a trace for the tunnel, and send (forward) backward. -// -// Ids management: -// - tunnel ids should be identical for requests between 2 same peers for the same file hash. -// - tunnel ids should be asymetric -// - tunnel requests should never be identical, to allow searching multiple times for the same string. -// So: -// - when issuing an open tunnel order, -// - a random request id is generated and used for packet routing -// - a partial tunnel id is build, which is unique to the pair (source,file hash) -// - when tunnel_ok is sent back, the tunnel id is completed so that it is unique to the -// triplet (source, destination, file hash). -// -// For these needs, tunnels are represented by: -// - their file hash. Each tunnel is only designed for transferring a single and same file. -// - their local endpoints id. These are the ids of the peers in direction to the source and destination. -// - the tunnel id, which is unique to the triple hash+global source+global destination. -// - there is a difference between source and destination in tunnels. The source is the file asker, the -// destination is the file provider. This helps sorting tunnels. -// - a timestamp, used for cleaning unused tunnels. -// -// The turtle router has: -// - a list of search requests and where to bounce them back. -// - a list of tunnel digging requests and where to bounce them, back. -// - a list of active file hashes, for which is should constantly maintain tunnels. -// - a list of active tunnels, some being transitory, some being endpoints. -// -// Turtle router entries: -// - a function for performing turtle search -// - a function for handling tunnels for a given file hash. -// -// Questions: -// - should tunnels be re-used ? nope. The only useful case would be when two peers are exchanging files, which happens quite rarely. -// - -#include -#include -#include - -#include "pqi/pqinetwork.h" -#include "pqi/pqi.h" -#include "pqi/pqimonitor.h" -#include "ft/ftcontroller.h" -#include "pqi/p3cfgmgr.h" -#include "services/p3service.h" -#include "ft/ftsearch.h" -#include "retroshare/rsturtle.h" -#include "rsturtleitem.h" -#include "turtleclientservice.h" -#include "turtlestatistics.h" - -//#define TUNNEL_STATISTICS - -class ftServer ; -class p3LinkMgr; -class ftDataMultiplex; -class RsSerialiser; - -static const int TURTLE_MAX_SEARCH_DEPTH = 6 ; -static const int TURTLE_MAX_SEARCH_REQ_ACCEPTED_SERIAL_SIZE = 200 ; - -// This classes are used to keep trace of requests (searches and tunnels). -// -class TurtleSearchRequestInfo -{ - public: - TurtlePeerId origin ; // where the request came from. - uint32_t time_stamp ; // last time the tunnel was actually used. Used for cleaning old tunnels. - int depth ; // depth of the request. Used to optimize tunnel length. - uint32_t result_count; // responses to this request. Useful to avoid spamming tunnel responses. - std::string keywords; - uint16_t service_id; // ID of the client service who issues the request. This is null if the request does not have a local origin. - uint32_t max_allowed_hits;// Max number of hits allowed for this search. This actually depends on the type of search (files, GXS groups, GXS group data, etc) -}; -class TurtleTunnelRequestInfo -{ - public: - TurtlePeerId origin ; // where the request came from. - uint32_t time_stamp ; // last time the tunnel was actually used. Used for cleaning old tunnels. - int depth ; // depth of the request. Used to optimize tunnel length. - std::set responses; // responses to this request. Useful to avoid spamming tunnel responses. -}; - -class TurtleTunnel -{ - public: - /* For all tunnels */ - - TurtlePeerId local_src ; // where packets come from. Direction to the source. - TurtlePeerId local_dst ; // where packets should go. Direction to the destination. - uint32_t time_stamp ; // last time the tunnel was actually used. Used for cleaning old tunnels. - uint32_t transfered_bytes ; // total bytes transferred in this tunnel. - float speed_Bps ; // speed of the traffic through the tunnel - - /* For ending/starting tunnels only. */ - - TurtleFileHash hash; // Hash of the file for this tunnel - TurtleVirtualPeerId vpid; // Virtual peer id for this tunnel. -}; - -// This class keeps trace of the activity for the file hashes the turtle router is asked to monitor. -// - -class TurtleHashInfo -{ - public: - std::vector tunnels ; // list of active tunnel ids for this file hash - TurtleRequestId last_request ; // last request for the tunnels of this hash - rstime_t last_digg_time ; // last time the tunnel digging happenned. - RsTurtleClientService *service ; // client service to which items should be sent. Never NULL. - bool use_aggressive_mode ; // allow to re-digg tunnels even when some are already available -}; - -// Subclassing: -// -// Class | Brings what | Usage -// -----------+------------------+------------------------------------------------------ -// p3Service | sendItem() | handle packet sending/receiving to/from friend peers. -// pqiMonitor | configChanged() | handle who's connecting/disconnecting to dig new tunnels -// RsTurtle | start/stop file()| brings interface for turtle service -// ftSearch | search() | used to allow searching for monitored files. -// p3Config | ConfigChanged() | used to load/save .cfg file for turtle variales. -// -----------+------------------+------------------------------------------------------ -// -class p3turtle: public p3Service, public RsTurtle, public p3Config -{ - public: - p3turtle(p3ServiceControl *sc,p3LinkMgr *lm) ; - virtual RsServiceInfo getServiceInfo(); - - // Enables/disable the service. Still ticks, but does nothing. Default is true. - // - virtual void setEnabled(bool) ; - virtual bool enabled() const ; - - // This is temporary, used by Operating Mode. - // Turtle operates when both enabled() && sessionEnabled() are true. - virtual void setSessionEnabled(bool); - virtual bool sessionEnabled() const; - - // Lauches a search request through the pipes, and immediately returns - // the request id, which will be further used by the gui to store results - // as they come back. - // - // The first two methods are old style search requests for FT, while the 3rd one is using a generic search data type, that is only to - // be deserialized by the service. The memory ownership is kept by the calling function. Similarly, the search response will be a - // generic data type that is to be deserialized by the client service. - // - // Eventually, search requests will use the generic system - // even for FT. We need to keep the old method for a while for backward compatibility. - // - virtual TurtleRequestId turtleSearch(const RsRegularExpression::LinearizedExpression& expr) ; - virtual TurtleRequestId turtleSearch(const std::string& string_to_match) ; - virtual TurtleRequestId turtleSearch(unsigned char *search_bin_data,uint32_t search_bin_data_len,RsTurtleClientService *client_service) ; - - // Initiates tunnel handling for the given file hash. tunnels. Launches - // an exception if an error occurs during the initialization process. The - // turtle router itself does not initiate downloads, it only maintains - // tunnels for the given hash. The download should be driven by the file - // transfer module. Maybe this function can do the whole thing: - // - initiate tunnel handling - // - send the file request to the file transfer module - // - populate the file transfer module with the adequate pqi interface and search module. - // - // This function should be called in addition to ftServer::FileRequest() so that the turtle router - // automatically provide tunnels for the file to download. - // - virtual void monitorTunnels(const RsFileHash& file_hash,RsTurtleClientService *client_service, bool allow_multi_tunnels) ; - - /// This should be called when canceling a file download, so that the turtle router stops - /// handling tunnels for this file. - /// - virtual void stopMonitoringTunnels(const RsFileHash& file_hash) ; - - /// This is provided to turtle clients to force the TR to ask tunnels again. To be used wisely: - /// too many tunnel requests will kill the network. This might be useful to speed-up the re-establishment - /// of tunnels that have become irresponsive. - - virtual void forceReDiggTunnels(const TurtleFileHash& hash) ; - - /// Adds a client tunnel service. This means that the service will be added - /// to the list of services that might respond to tunnel requests. - /// Example tunnel services include: - /// - /// p3ChatService: tunnels correspond to private distant chatting - /// ftServer : tunnels correspond to file data transfer - /// - virtual void registerTunnelService(RsTurtleClientService *service) ; - - virtual std::string getPeerNameForVirtualPeerId(const RsPeerId& virtual_peer_id); - - /// get info about tunnels - virtual void getInfo(std::vector >&, - std::vector >&, - std::vector&, - std::vector&) const ; - - virtual void getTrafficStatistics(TurtleTrafficStatisticsInfo& info) const ; - - /************* from p3service *******************/ - - /// This function does many things: - /// - It handles incoming and outgoing packets - /// - it sorts search requests and forwards search results upward. - /// - it cleans unused (tunnel+search) requests. - /// - it maintains the pool of tunnels, for each request file hash. - /// - virtual int tick(); - - virtual void getItemNames(std::map& names) const; - - /************* from p3Config *******************/ - virtual RsSerialiser *setupSerialiser() ; - virtual bool saveList(bool& cleanup, std::list&) ; - virtual bool loadList(std::list& /*load*/) ; - - /************* Communication with clients *******************/ - /// Does the turtle router manages tunnels to this peer ? (this is not a - /// real id, but a fake one, that the turtle router is capable of connecting with a tunnel id). - virtual bool isTurtlePeer(const RsPeerId& peer_id) const ; - - /// sets/gets the max number of forwarded tunnel requests per second. - virtual void setMaxTRForwardRate(int max_tr_up_rate) ; - virtual int getMaxTRForwardRate() const ; - - /// Examines the peer id, finds the turtle tunnel in it, and respond yes if the tunnel is ok and operational. - bool isOnline(const RsPeerId& peer_id) const ; - - /// Returns a unique peer id, corresponding to the given tunnel. - RsPeerId getTurtlePeerId(TurtleTunnelId tid) const ; - - /// returns the list of virtual peers for all tunnels. - void getSourceVirtualPeersList(const TurtleFileHash& hash,std::list& list) ; - - /// Send a data request into the correct tunnel for the given file hash - void sendTurtleData(const RsPeerId& virtual_peer_id, RsTurtleGenericTunnelItem *item) ; - - /// Encrypts/decrypts an item, using a autenticated construction + chacha20, based on the given 32 bytes master key. - /// Input values are not touched (memory is not released). Memory ownership of outputs is left to the client. - /// - static bool encryptData(const unsigned char *clear_data,uint32_t clear_data_size,uint8_t *encryption_master_key,RsTurtleGenericDataItem *& encrypted_item); - static bool decryptItem(const RsTurtleGenericDataItem *item, uint8_t* encryption_master_key, unsigned char *& decrypted_data,uint32_t& decrypted_data_size); - - private: - //--------------------------- Admin/Helper functions -------------------------// - - /// Generates a cyphered combination of ownId() and file hash - uint32_t generatePersonalFilePrint(const TurtleFileHash&,uint32_t seed,bool) ; - - /// Generates a random uint32_t number. - uint32_t generateRandomRequestId() ; - - /// Auto cleaning of unused tunnels, search requests and tunnel requests. - void autoWash() ; - - //------------------------------ Tunnel handling -----------------------------// - - /// initiates tunnels from here to any peers having the given file hash - TurtleRequestId diggTunnel(const TurtleFileHash& hash) ; - - /// adds info related to a new virtual peer. - void locked_addDistantPeer(const TurtleFileHash&, TurtleTunnelId) ; - - /// estimates the speed of the traffic into tunnels. - void estimateTunnelSpeeds() ; - - //----------------------------- Routing functions ----------------------------// - - /// Handle tunnel digging for current file hashes - void manageTunnels() ; - - /// Closes a given tunnel. Should be called with mutex set. - /// The hashes and peers to remove (by calling - /// ftController::removeFileSource() are happended to the supplied vector - /// so that they can be removed off the turtle mutex. - void locked_closeTunnel(TurtleTunnelId tid,std::vector > >& peers_to_remove) ; - - /// Main routing function - int handleIncoming(); - - /// Generic routing function for all tunnel packets that derive from RsTurtleGenericTunnelItem - void routeGenericTunnelItem(RsTurtleGenericTunnelItem *item) ; - - /// specific routing functions for handling particular packets. - void handleRecvGenericTunnelItem(RsTurtleGenericTunnelItem *item); - bool getTunnelServiceInfo(TurtleTunnelId, RsPeerId& virtual_peer_id, RsFileHash& hash, RsTurtleClientService*&) ; - - // following functions should go to ftServer - void handleSearchRequest(RsTurtleSearchRequestItem *item); - void handleSearchResult(RsTurtleSearchResultItem *item); - void handleTunnelRequest(RsTurtleOpenTunnelItem *item); - void handleTunnelResult(RsTurtleTunnelOkItem *item); - - //------ Functions connecting the turtle router to other components.----------// - - /// Performs a search calling local cache and search structure. - void performLocalSearch (RsTurtleSearchRequestItem *item, uint32_t& req_result_count,std::list& result,uint32_t& max_allowed_hits) ; - void performLocalSearch_files (RsTurtleFileSearchRequestItem *item, uint32_t& req_result_count, std::list& result, uint32_t &max_allowed_hits) ; - void performLocalSearch_generic(RsTurtleGenericSearchRequestItem *item, uint32_t& req_result_count, std::list& result, uint32_t &max_allowed_hits) ; - - /// Returns true if the file with given hash is hosted locally, and accessible in anonymous mode the supplied peer. - virtual bool performLocalHashSearch(const TurtleFileHash& hash,const RsPeerId& client_peer_id,RsTurtleClientService *& service); - - //--------------------------- Local variables --------------------------------// - - /* data */ - p3ServiceControl *mServiceControl; - p3LinkMgr *mLinkMgr; - RsTurtleSerialiser *_serialiser ; - RsPeerId _own_id ; - - mutable RsMutex mTurtleMtx; - - /// keeps trace of who emmitted a given search request - std::map _search_requests_origins ; - - /// keeps trace of who emmitted a tunnel request - std::map _tunnel_requests_origins ; - - /// stores adequate tunnels for each file hash locally managed - std::map _incoming_file_hashes ; - - /// stores file info for each file we provide. - std::map _outgoing_tunnel_client_services ; - - /// local tunnels, stored by ids (Either transiting or ending). - std::map _local_tunnels ; - - /// Peers corresponding to each tunnel. - std::map _virtual_peers ; - - /// Hashes marked to be deleted. - std::set _hashes_to_remove ; - - /// List of client services that have regitered. - std::map _registered_services ; - - rstime_t _last_clean_time ; - rstime_t _last_tunnel_management_time ; - rstime_t _last_tunnel_campaign_time ; - rstime_t _last_tunnel_speed_estimate_time ; - - std::list _online_peers; - - /// used to force digging new tunnels - //bool _force_digg_new_tunnels ; - - /// used as a bias to introduce randomness in a consistent way, for - /// altering tunnel request depths, and tunnel re-routing actions. - /// - uint32_t _random_bias ; - - // Used to collect statistics on turtle traffic. - // - TurtleTrafficStatisticsInfoOp _traffic_info ; // used for recording speed - TurtleTrafficStatisticsInfoOp _traffic_info_buffer ; // used as a buffer to collect bytes - - float _max_tr_up_rate ; - bool _turtle_routing_enabled ; - bool _turtle_routing_session_enabled ; - - // p3ServiceControl service type - - uint32_t _service_type ; - - RS_SET_CONTEXT_DEBUG_LEVEL(1) - -#ifdef P3TURTLE_DEBUG - // debug function - void dumpState() ; -#endif -#ifdef TUNNEL_STATISTICS - void TS_dumpState(); -#endif -}; diff --git a/libretroshare/src/turtle/rsturtleitem.cc b/libretroshare/src/turtle/rsturtleitem.cc deleted file mode 100644 index f0128d04a..000000000 --- a/libretroshare/src/turtle/rsturtleitem.cc +++ /dev/null @@ -1,256 +0,0 @@ -/******************************************************************************* - * libretroshare/src/turtle: rsturtleitem.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009-2018 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef WINDOWS_SYS -#include -#endif -#include -#include "turtletypes.h" -#include "rsturtleitem.h" -#include "turtleclientservice.h" - -#include "serialiser/rstypeserializer.h" - -//#define P3TURTLE_DEBUG -// -----------------------------------------------------------------------------------// -// -------------------------------- Serialization. --------------------------------- // -// -----------------------------------------------------------------------------------// -// - -RsItem *RsTurtleSerialiser::create_item(uint16_t service,uint8_t item_subtype) const -{ - if (RS_SERVICE_TYPE_TURTLE != service) - { -#ifdef P3TURTLE_DEBUG - std::cerr << " Wrong type !!" << std::endl ; -#endif - return NULL; /* wrong type */ - } - - switch(getRsItemSubType(item_subtype)) - { - case RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST : return new RsTurtleStringSearchRequestItem(); - case RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST : return new RsTurtleRegExpSearchRequestItem(); - case RS_TURTLE_SUBTYPE_FT_SEARCH_RESULT : return new RsTurtleFTSearchResultItem(); - case RS_TURTLE_SUBTYPE_OPEN_TUNNEL : return new RsTurtleOpenTunnelItem(); - case RS_TURTLE_SUBTYPE_TUNNEL_OK : return new RsTurtleTunnelOkItem(); - case RS_TURTLE_SUBTYPE_GENERIC_DATA : return new RsTurtleGenericDataItem(); - case RS_TURTLE_SUBTYPE_GENERIC_FAST_DATA : return new RsTurtleGenericFastDataItem(); - case RS_TURTLE_SUBTYPE_GENERIC_SEARCH_REQUEST : return new RsTurtleGenericSearchRequestItem(); - case RS_TURTLE_SUBTYPE_GENERIC_SEARCH_RESULT : return new RsTurtleGenericSearchResultItem(); - - default: - break ; - } - // now try all client services - // - RsItem *item = NULL ; - - for(uint32_t i=0;i<_client_services.size();++i) - if((_client_services[i]->serializer() != NULL) && (item = _client_services[i]->serializer()->create_item(service,item_subtype)) != NULL) - return item ; - - std::cerr << "Unknown packet type in RsTurtle (not even handled by client services)!" << std::endl ; - return NULL ; -} - -std::string RsTurtleGenericSearchRequestItem::GetKeywords() -{ - return std::string("Generic search : " + RsUtil::BinToHex(search_data,search_data_len,10)); -} - -void RsTurtleStringSearchRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,TLV_TYPE_STR_VALUE,match_string,"match_string") ; - RsTypeSerializer::serial_process(j,ctx,request_id,"request_id") ; - RsTypeSerializer::serial_process(j,ctx,depth ,"depth") ; -} -void RsTurtleRegExpSearchRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,request_id,"request_id") ; - RsTypeSerializer::serial_process(j,ctx,depth,"depth") ; - RsTypeSerializer::serial_process(j,ctx,expr,"expr") ; -} -void RsTurtleGenericSearchRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,request_id,"request_id") ; - RsTypeSerializer::serial_process(j,ctx,depth,"depth") ; - RsTypeSerializer::serial_process(j,ctx,service_id,"service_id") ; - RsTypeSerializer::serial_process(j,ctx,request_type,"request_type") ; - - RsTypeSerializer::TlvMemBlock_proxy prox(search_data,search_data_len) ; - RsTypeSerializer::serial_process(j,ctx,prox,"search_data") ; -} -RsTurtleSearchRequestItem *RsTurtleGenericSearchRequestItem::clone() const -{ - return new RsTurtleGenericSearchRequestItem(*this) ; -} - -RsTurtleGenericSearchRequestItem::RsTurtleGenericSearchRequestItem(const RsTurtleGenericSearchRequestItem& it) - : RsTurtleSearchRequestItem(it) -{ - search_data_len = it.search_data_len ; - search_data = (unsigned char*)rs_malloc(it.search_data_len) ; - service_id = it.service_id ; - request_type = it.request_type ; - - memcpy(search_data,it.search_data,it.search_data_len) ; -} - -template<> uint32_t RsTypeSerializer::serial_size(const RsRegularExpression::LinearizedExpression& r) -{ - uint32_t s = 0 ; - - s += 4 ; // number of strings - - for(unsigned int i=0;i bool RsTypeSerializer::deserialize(const uint8_t data[],uint32_t size,uint32_t& offset,RsRegularExpression::LinearizedExpression& expr) -{ - uint32_t saved_offset = offset ; - - uint32_t n =0 ; - bool ok = true ; - - ok &= getRawUInt32(data,size,&offset,&n) ; - - if(ok) expr._tokens.resize(n) ; - - for(uint32_t i=0;i bool RsTypeSerializer::serialize(uint8_t data[],uint32_t size,uint32_t& offset,const RsRegularExpression::LinearizedExpression& expr) -{ - uint32_t saved_offset = offset ; - - bool ok = true ; - - ok &= setRawUInt32(data,size,&offset,expr._tokens.size()) ; - - for(unsigned int i=0;i void RsTypeSerializer::print_data(const std::string& n, const RsRegularExpression::LinearizedExpression& expr) -{ - std::cerr << " [RegExpr ] " << n << ", tokens=" << expr._tokens.size() << " ints=" << expr._ints.size() << " strings=" << expr._strings.size() << std::endl; -} - -RS_TYPE_SERIALIZER_TO_JSON_NOT_IMPLEMENTED_DEF(RsRegularExpression::LinearizedExpression) -RS_TYPE_SERIALIZER_FROM_JSON_NOT_IMPLEMENTED_DEF(RsRegularExpression::LinearizedExpression) - -void RsTurtleFTSearchResultItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,request_id,"request_id") ; - - // This depth was previously a member of SearchResult parent class that was set to be always 0. It's removed, but we have to stay backward compatible. - uint16_t depth_retrocompat_unused_placeholder = 0 ; - RsTypeSerializer::serial_process(j,ctx,depth_retrocompat_unused_placeholder,"depth") ; - - RsTypeSerializer::serial_process (j,ctx,result ,"result") ; -} -void RsTurtleGenericSearchResultItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,request_id,"request_id") ; - - // This depth was previously a member of SearchResult parent class that was set to be always 0. It's removed, but we have to stay backward compatible. - uint16_t depth_retrocompat_unused_placeholder = 0 ; - RsTypeSerializer::serial_process(j,ctx,depth_retrocompat_unused_placeholder,"depth") ; - - RsTypeSerializer::TlvMemBlock_proxy prox(result_data,result_data_len) ; - RsTypeSerializer::serial_process(j,ctx,prox,"search_data") ; -} -RsTurtleSearchResultItem *RsTurtleGenericSearchResultItem::duplicate() const -{ - RsTurtleGenericSearchResultItem *sr = new RsTurtleGenericSearchResultItem ; - - sr->result_data = (unsigned char*)rs_malloc(result_data_len) ; - memcpy(sr->result_data,result_data,result_data_len) ; - sr->result_data_len = result_data_len ; - sr->request_id = request_id ; - return sr ; -} - -void RsTurtleOpenTunnelItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process (j,ctx,file_hash ,"file_hash") ; - RsTypeSerializer::serial_process(j,ctx,request_id ,"request_id") ; - RsTypeSerializer::serial_process(j,ctx,partial_tunnel_id,"partial_tunnel_id") ; - RsTypeSerializer::serial_process(j,ctx,depth ,"depth") ; -} - -void RsTurtleTunnelOkItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,tunnel_id ,"tunnel_id") ; - RsTypeSerializer::serial_process(j,ctx,request_id,"request_id") ; -} - -void RsTurtleGenericDataItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,tunnel_id ,"tunnel_id") ; - RsTypeSerializer::TlvMemBlock_proxy prox(data_bytes,data_size) ; - RsTypeSerializer::serial_process(j,ctx,prox,"data bytes") ; -} -void RsTurtleGenericFastDataItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) -{ - RsTypeSerializer::serial_process(j,ctx,tunnel_id ,"tunnel_id") ; - RsTypeSerializer::TlvMemBlock_proxy prox(data_bytes,data_size) ; - RsTypeSerializer::serial_process(j,ctx,prox,"data bytes") ; -} diff --git a/libretroshare/src/turtle/rsturtleitem.h b/libretroshare/src/turtle/rsturtleitem.h deleted file mode 100644 index db029cc64..000000000 --- a/libretroshare/src/turtle/rsturtleitem.h +++ /dev/null @@ -1,387 +0,0 @@ -/******************************************************************************* - * libretroshare/src/turtle: rsturtleitem.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2009-2018 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include "rsitems/rsserviceids.h" -#include "rsitems/rsitem.h" -#include "rsitems/itempriorities.h" - -#include "serialiser/rsserial.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rsbaseserial.h" - -#include "retroshare/rsturtle.h" -#include "retroshare/rsexpr.h" -#include "retroshare/rstypes.h" -#include "turtle/turtletypes.h" - -#include "serialiser/rsserializer.h" - -const uint8_t RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST = 0x01 ; -const uint8_t RS_TURTLE_SUBTYPE_FT_SEARCH_RESULT = 0x02 ; -const uint8_t RS_TURTLE_SUBTYPE_OPEN_TUNNEL = 0x03 ; -const uint8_t RS_TURTLE_SUBTYPE_TUNNEL_OK = 0x04 ; -const uint8_t RS_TURTLE_SUBTYPE_FILE_REQUEST = 0x07 ; -const uint8_t RS_TURTLE_SUBTYPE_FILE_DATA = 0x08 ; -const uint8_t RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST = 0x09 ; -const uint8_t RS_TURTLE_SUBTYPE_GENERIC_DATA = 0x0a ; -const uint8_t RS_TURTLE_SUBTYPE_GENERIC_SEARCH_REQUEST = 0x0b ; -const uint8_t RS_TURTLE_SUBTYPE_GENERIC_SEARCH_RESULT = 0x0c ; -const uint8_t RS_TURTLE_SUBTYPE_FILE_MAP = 0x10 ; -const uint8_t RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST = 0x11 ; -// const uint8_t RS_TURTLE_SUBTYPE_FILE_CRC = 0x12 ; // unused -// const uint8_t RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST = 0x13 ; -const uint8_t RS_TURTLE_SUBTYPE_CHUNK_CRC = 0x14 ; -const uint8_t RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST = 0x15 ; -const uint8_t RS_TURTLE_SUBTYPE_GENERIC_FAST_DATA = 0x16 ; - - -class TurtleSearchRequestInfo ; - -/***********************************************************************************/ -/* Basic Turtle Item Class */ -/***********************************************************************************/ - -class RsTurtleItem: public RsItem -{ - public: - RsTurtleItem(uint8_t turtle_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_TURTLE,turtle_subtype) {} -}; - -/***********************************************************************************/ -/* Turtle Search Item classes */ -/* Specific packets */ -/***********************************************************************************/ - -// Class hierarchy is -// -// RsTurtleItem -// | -// +---- RsTurtleSearchRequestItem -// | | -// | +---- RsTurtleFileSearchRequestItem -// | | | -// | | +---- RsTurtleStringSearchRequestItem -// | | | -// | | +---- RsTurtleReqExpSearchRequestItem -// | | -// | +---- RsTurtleGenericSearchRequestItem -// | -// +---- RsTurtleSearchResultItem -// | -// +---- RsTurtleFTSearchResultItem -// | -// +---- RsTurtleGenericSearchResultItem -// - -class RsTurtleSearchResultItem ; - -class RsTurtleSearchRequestItem: public RsTurtleItem -{ - public: - RsTurtleSearchRequestItem(uint32_t subtype) : RsTurtleItem(subtype), request_id(0), depth(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_SEARCH_REQUEST) ;} - virtual ~RsTurtleSearchRequestItem() {} - - virtual RsTurtleSearchRequestItem *clone() const = 0 ; // used for cloning in routing methods - - virtual std::string GetKeywords() = 0; - virtual uint16_t serviceId() const= 0 ; - - uint32_t request_id ; // randomly generated request id. - uint16_t depth ; // Used for limiting search depth. -}; - -class RsTurtleFileSearchRequestItem: public RsTurtleSearchRequestItem -{ - public: - RsTurtleFileSearchRequestItem(uint32_t subtype) : RsTurtleSearchRequestItem(subtype) {} - virtual ~RsTurtleFileSearchRequestItem() {} - - virtual uint16_t serviceId() const { return RS_SERVICE_TYPE_FILE_TRANSFER ; } - virtual void search(std::list &) const =0; -}; - -class RsTurtleStringSearchRequestItem: public RsTurtleFileSearchRequestItem -{ - public: - RsTurtleStringSearchRequestItem() : RsTurtleFileSearchRequestItem(RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST) {} - virtual ~RsTurtleStringSearchRequestItem() {} - - virtual void search(std::list &) const ; - - std::string match_string ; // string to match - std::string GetKeywords() { return match_string; } - - virtual RsTurtleSearchRequestItem *clone() const { return new RsTurtleStringSearchRequestItem(*this) ; } - - void clear() { match_string.clear() ; } - - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -class RsTurtleRegExpSearchRequestItem: public RsTurtleFileSearchRequestItem -{ - public: - RsTurtleRegExpSearchRequestItem() : RsTurtleFileSearchRequestItem(RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST) {} - virtual ~RsTurtleRegExpSearchRequestItem() {} - - RsRegularExpression::LinearizedExpression expr ; // Reg Exp in linearised mode - - std::string GetKeywords() - { - RsRegularExpression::Expression *ex = RsRegularExpression::LinearizedExpression::toExpr(expr); - std::string exs = ex->toStdString(); - delete ex; - return exs; - } - - virtual void search(std::list &) const ; - - virtual RsTurtleSearchRequestItem *clone() const { return new RsTurtleRegExpSearchRequestItem(*this) ; } - void clear() { expr = RsRegularExpression::LinearizedExpression(); } - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -class RsTurtleGenericSearchRequestItem: public RsTurtleSearchRequestItem -{ - public: - RsTurtleGenericSearchRequestItem() - : RsTurtleSearchRequestItem(RS_TURTLE_SUBTYPE_GENERIC_SEARCH_REQUEST), - service_id(0), - search_data_len(0), - request_type(0), - search_data(nullptr) - {} - virtual ~RsTurtleGenericSearchRequestItem() { clear(); } - - uint16_t service_id ; // service to search - uint32_t search_data_len ; - uint8_t request_type ; // type of request. This is used to limit the number of responses. - unsigned char *search_data ; - - std::string GetKeywords() ; - virtual uint16_t serviceId() const { return service_id ; } - - virtual RsTurtleSearchRequestItem *clone() const ; - virtual uint32_t requestType() const { return request_type; } - - void clear() { free(search_data); search_data=NULL; search_data_len=0; } - - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); - - private: - RsTurtleGenericSearchRequestItem(const RsTurtleGenericSearchRequestItem&); // make the object non copi-able. - RsTurtleGenericSearchRequestItem& operator=(const RsTurtleGenericSearchRequestItem&) { return *this;} -}; -class RsTurtleSearchResultItem: public RsTurtleItem -{ - public: - RsTurtleSearchResultItem(uint8_t subtype) : RsTurtleItem(subtype), request_id(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_SEARCH_RESULT) ;} - - TurtleSearchRequestId request_id ; // Randomly generated request id. - - virtual uint32_t count() const =0; - virtual void pop() =0; - - virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)=0; - virtual RsTurtleSearchResultItem *duplicate() const =0; -}; - -class RsTurtleFTSearchResultItem: public RsTurtleSearchResultItem -{ - public: - RsTurtleFTSearchResultItem() : RsTurtleSearchResultItem(RS_TURTLE_SUBTYPE_FT_SEARCH_RESULT){} - - std::list result ; - - void clear() { result.clear() ; } - uint32_t count() const { return result.size() ; } - virtual void pop() { result.pop_back() ;} - virtual RsTurtleSearchResultItem *duplicate() const { return new RsTurtleFTSearchResultItem(*this) ; } - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -class RsTurtleGenericSearchResultItem: public RsTurtleSearchResultItem -{ - public: - RsTurtleGenericSearchResultItem() - : RsTurtleSearchResultItem(RS_TURTLE_SUBTYPE_GENERIC_SEARCH_RESULT), - result_data(nullptr), - result_data_len(0) - {} - virtual ~RsTurtleGenericSearchResultItem() {} - - uint32_t count() const { return result_data_len/50 ; } // This is a blind size estimate. We should probably use the actual size to limit search results. - virtual void pop() {} - - unsigned char *result_data ; - uint32_t result_data_len ; - - virtual RsTurtleSearchResultItem *duplicate() const ; - void clear() { free(result_data); result_data=NULL; result_data_len=0; } - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -/***********************************************************************************/ -/* Turtle Tunnel Item classes */ -/***********************************************************************************/ - -class RsTurtleOpenTunnelItem: public RsTurtleItem -{ - public: - RsTurtleOpenTunnelItem() : RsTurtleItem(RS_TURTLE_SUBTYPE_OPEN_TUNNEL), request_id(0), partial_tunnel_id(0), depth(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_OPEN_TUNNEL) ;} - - TurtleFileHash file_hash ; // hash to match - uint32_t request_id ; // randomly generated request id. - uint32_t partial_tunnel_id ; // uncomplete tunnel id. Will be completed at destination. - uint16_t depth ; // Used for limiting search depth. - - void clear() { file_hash.clear() ;} - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -class RsTurtleTunnelOkItem: public RsTurtleItem -{ - public: - RsTurtleTunnelOkItem() : RsTurtleItem(RS_TURTLE_SUBTYPE_TUNNEL_OK), tunnel_id(0), request_id(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_TUNNEL_OK) ;} - - uint32_t tunnel_id ; // id of the tunnel. Should be identical for a tunnel between two same peers for the same hash. - uint32_t request_id ; // randomly generated request id corresponding to the intial request. - - void clear() {} - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -/***********************************************************************************/ -/* Generic turtle packets for tunnels */ -/***********************************************************************************/ - -class RsTurtleGenericTunnelItem: public RsTurtleItem -{ - public: - RsTurtleGenericTunnelItem(uint8_t sub_packet_id) : RsTurtleItem(sub_packet_id), direction(0), tunnel_id(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_GENERIC_ITEM);} - virtual ~RsTurtleGenericTunnelItem() {} - - typedef uint32_t Direction ; - static const Direction DIRECTION_CLIENT = 0x001 ; - static const Direction DIRECTION_SERVER = 0x002 ; - - /// Does this packet stamps tunnels when it passes through ? - /// This is used for keeping trace weither tunnels are active or not. - - virtual bool shouldStampTunnel() const = 0 ; - - /// All tunnels derived from RsTurtleGenericTunnelItem should have a tunnel id to - /// indicate which tunnel they are travelling through. - - virtual TurtleTunnelId tunnelId() const { return tunnel_id ; } - - /// Indicate weither the packet is a client packet (goign back to the - /// client) or a server packet (going to the server. Typically file - /// requests are server packets, whereas file data are client packets. - - virtual Direction travelingDirection() const { return direction ; } - virtual void setTravelingDirection(Direction d) { direction = d; } - - Direction direction ; // This does not need to be serialised. It's only used by the client services, optionnally, - // and is set by the turtle router according to which direction the item travels. - - uint32_t tunnel_id ; // Id of the tunnel to travel through -}; - -/***********************************************************************************/ -/* Specific Turtle Transfer items */ -/***********************************************************************************/ - -// This item can be used by any service to pass-on arbitrary data into a tunnel. -// -class RsTurtleGenericDataItem: public RsTurtleGenericTunnelItem -{ - public: - RsTurtleGenericDataItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_GENERIC_DATA), data_size(0), data_bytes(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_GENERIC_DATA);} - virtual ~RsTurtleGenericDataItem() { if(data_bytes != NULL) free(data_bytes) ; } - - virtual bool shouldStampTunnel() const { return true ; } - - uint32_t data_size ; - void *data_bytes ; - - void clear() - { - free(data_bytes) ; - data_bytes = NULL ; - data_size = 0; - } - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; - -// Same, but with a fact priority. Can rather be used for e.g. distant chat. -// -class RsTurtleGenericFastDataItem: public RsTurtleGenericTunnelItem -{ - public: - RsTurtleGenericFastDataItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_GENERIC_FAST_DATA), data_size(0), data_bytes(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_GENERIC_FAST_DATA);} - virtual ~RsTurtleGenericFastDataItem() { if(data_bytes != NULL) free(data_bytes) ; } - - virtual bool shouldStampTunnel() const { return true ; } - - uint32_t data_size ; - void *data_bytes ; - - void clear() - { - free(data_bytes) ; - data_bytes = NULL ; - data_size = 0; - } - protected: - void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); -}; -/***********************************************************************************/ -/* Turtle Serialiser class */ -/***********************************************************************************/ - -class RsTurtleSerialiser: public RsServiceSerializer -{ - public: - RsTurtleSerialiser() : RsServiceSerializer(RS_SERVICE_TYPE_TURTLE) {} - - virtual RsItem *create_item(uint16_t service,uint8_t item_subtype) const; - - // This is used by the turtle router to add services to its serialiser. - // Client services are only used for deserialising, since the serialisation is - // performed using the overloaded virtual functions above. - // - void registerClientService(RsTurtleClientService *service) { _client_services.push_back(service) ; } - - private: - std::vector _client_services ; -}; - diff --git a/libretroshare/src/turtle/turtleclientservice.h b/libretroshare/src/turtle/turtleclientservice.h deleted file mode 100644 index 55525ae3c..000000000 --- a/libretroshare/src/turtle/turtleclientservice.h +++ /dev/null @@ -1,171 +0,0 @@ -/******************************************************************************* - * libretroshare/src/turtle: rsturtleclientservice.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013-2018 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include - -#include "serialiser/rsserial.h" -#include "turtle/rsturtleitem.h" -#include "util/rsdebug.h" - -struct RsItem; -class p3turtle ; - -/** This class is the parent class for any service that will use the turtle - * router to distribute its packets. - * Typical representative clients include: - * p3ChatService: opens tunnels to distant peers for chatting - * ftServer: searches and open tunnels to distant sources for file - * transfer - */ -class RsTurtleClientService -{ - public: - /*! - * \brief serviceId - * Returns the ID of the client service. This is used to pass the ID to search requests, from the client services - * \return - * The service ID. - */ - - virtual uint16_t serviceId() const - { - std::cerr << "!!!!!! Received request for service ID in turtle router client, but the client service is not handling it !!!!!!!" << std::endl ; - return 0 ; - } - - /*! - * \brief handleTunnelRequest - Handling of tunnel request for the given hash. To be derived by the service in order to tell the turtle router - whether the service handles this hash or not. Most of the time, it's a search in a predefined list. - - * \return true if the service - */ - virtual bool handleTunnelRequest(const RsFileHash& /*hash*/,const RsPeerId& /*peer_id*/) { return false ; } - - /*! - * \brief receiveTurtleData - * This method is called by the turtle router to send data that comes out of a turtle tunnel, and should - * be overloaded by the client service. - * The turtle router stays responsible for the memory management of data. Most of the time the - * data chunk is a serialized item to be de-serialized by the client service. - * - * Parameters: - * virtual_peer_id : name of the tunnel that sent the data - * data : memory chunk for the data - * size : size of data - * item->direction : direction of travel: - * RsTurtleGenericTunnelItem::DIRECTION_CLIENT: the service is acting as a client - * RsTurtleGenericTunnelItem::DIRECTION_CLIENT: the service is acting as a server - * - * Most of the time this parameter is not used by services, except when some info (such as chunk maps, chat items, etc) go - * both ways, and their nature cannot suffice to determine where they should be handled. - * - * By default (if not overloaded), the method will just free the data, as any subclass should do as well. - * Note: p3turtle stays owner of the item, so the client should not delete it! - */ - virtual void receiveTurtleData(const RsTurtleGenericTunnelItem * /* item */,const RsFileHash& /*hash*/,const RsPeerId& /*virtual_peer_id*/,RsTurtleGenericTunnelItem::Direction /*direction*/) - { - std::cerr << "!!!!!! Received Data from turtle router, but the client service is not handling it !!!!!!!!!!" << std::endl ; - } - - /*! - * This method is called by the turtle router to notify the client of a - * search request in the form generic data. - * The returned result contains the serialised generic result returned by the - * client service. - * The turtle router keeps the memory ownership over search_request_data - * \param search_request_data generic serialized search data - * \param search_request_data_len length of the serialized search data - * \param search_result_data generic serialized search result data - * \param search_result_data_len length of the serialized search result data - * \param max_allowed_hits max number of hits allowed to be sent back and - * forwarded - * \return true if matching results are available, false otherwise. - */ - virtual bool receiveSearchRequest( - unsigned char *search_request_data, uint32_t search_request_data_len, - unsigned char *& search_result_data, uint32_t& search_result_data_len, - uint32_t& max_allows_hits ) - { - /* Suppress unused warning this way and not commenting the param names - * so doxygen match documentation against params */ - (void) search_request_data; (void) search_request_data_len; - (void) search_result_data; (void) search_result_data_len; - (void) max_allows_hits; - - RS_WARN( "Received search request from turtle router, but the client " - "is not handling it!" ); - return false; - } - - /*! - * \brief receiveSearchResult - * This method is called by the turtle router to notify the client of a search result. The result is serialized for the current class to read. - * - * \param search_result_data result data. Memory ownership is owned by the turtle router. So do not delete! - * \param search_result_data length of result data - */ - virtual void receiveSearchResult(TurtleSearchRequestId /* request_id */,unsigned char * /*search_result_data*/,uint32_t /*search_result_data_len*/) - { - std::cerr << "!!!!!! Received search result from turtle router, but the client service who requested it is not handling it !!!!!!!!!!" << std::endl ; - } - - /*! - * \brief serializer - * Method for creating specific items of the client service. The - * method has a default behavior of not doing anything, since most client - * services might only use the generic item already provided by the turtle - * router: RsTurtleGenericDataItem - * - * \return the client's serializer is returned - */ - virtual RsServiceSerializer *serializer() { return NULL ; } - - /*! - * \brief addVirtualPeer - * These methods are called by the turtle router to notify the client in order to add/remove virtual peers when tunnels are created/deleted - * These methods must be overloaded, because a service which does not care about tunel being openned or closed is not supposed to need tunnels. - * - * \param hash hash that the tunnel responds to - * \param virtual_peer_id virtual peer id provided by turtle to allow the client to send data into this tunnel. This peer is related to the tunnel itself - * rather than to its destination. As such, multiple peer ids may actually send data to the same computer because multiple tunnels - * arrive at the same location. - * \param dir dir indicates which side the cient will be talking to: CLIENT means that the client is the server. SERVER means that the client acts - * as a client (and therefore actually requested the tunnel). - */ - virtual void addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir) = 0 ; - virtual void removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) = 0 ; - - /*! - * \brief connectToTurtleRouter - * This function must be overloaded by the client. It should do two things: - * 1 - keep a pointer to the turtle router, so as to be able to send data (e.g. store pt into a local variable) - * 2 - call pt->registerTunnelService(this), so that the TR knows that service and can send back information to it. - * - * \param pt A pointer to the turtle router. - */ - virtual void connectToTurtleRouter(p3turtle *pt) = 0 ; -}; - - diff --git a/libretroshare/src/turtle/turtlestatistics.h b/libretroshare/src/turtle/turtlestatistics.h deleted file mode 100644 index 5aaeda676..000000000 --- a/libretroshare/src/turtle/turtlestatistics.h +++ /dev/null @@ -1,51 +0,0 @@ -#include - -class TurtleTrafficStatisticsInfoOp: public TurtleTrafficStatisticsInfo -{ - public: - TurtleTrafficStatisticsInfoOp() - { - reset() ; - } - - void reset() - { - unknown_updn_Bps = 0.0f ; - data_up_Bps = 0.0f ; - data_dn_Bps = 0.0f ; - tr_up_Bps = 0.0f ; - tr_dn_Bps = 0.0f ; - total_up_Bps = 0.0f ; - total_dn_Bps = 0.0f ; - } - - TurtleTrafficStatisticsInfoOp operator*(float f) const - { - TurtleTrafficStatisticsInfoOp i(*this) ; - - i.unknown_updn_Bps *= f ; - i.data_up_Bps *= f ; - i.data_dn_Bps *= f ; - i.tr_up_Bps *= f ; - i.tr_dn_Bps *= f ; - i.total_up_Bps *= f ; - i.total_dn_Bps *= f ; - - return i ; - } - TurtleTrafficStatisticsInfoOp operator+(const TurtleTrafficStatisticsInfoOp& j) const - { - TurtleTrafficStatisticsInfoOp i(*this) ; - - i.unknown_updn_Bps += j.unknown_updn_Bps ; - i.data_up_Bps += j.data_up_Bps ; - i.data_dn_Bps += j.data_dn_Bps ; - i.tr_up_Bps += j.tr_up_Bps ; - i.tr_dn_Bps += j.tr_dn_Bps ; - i.total_up_Bps += j.total_up_Bps ; - i.total_dn_Bps += j.total_dn_Bps ; - - return i ; - } -}; - diff --git a/libretroshare/src/turtle/turtletypes.h b/libretroshare/src/turtle/turtletypes.h deleted file mode 100644 index 56fd78f8b..000000000 --- a/libretroshare/src/turtle/turtletypes.h +++ /dev/null @@ -1,36 +0,0 @@ -/******************************************************************************* - * libretroshare/src/turtle: rsturtletypes.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013-2018 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include "retroshare/rsturtle.h" - -typedef RsPeerId TurtlePeerId ; -typedef RsPeerId TurtleVirtualPeerId ; -typedef RsFileHash TurtleFileHash ; -typedef std::string TurtleFileName ; - -typedef TurtleRequestId TurtleSearchRequestId ; - -typedef uint32_t TurtleTunnelRequestId ; -typedef uint32_t TurtleTunnelId ; - - diff --git a/libretroshare/src/unfinished/db_acadeeb.h b/libretroshare/src/unfinished/db_acadeeb.h deleted file mode 100644 index 806422a30..000000000 --- a/libretroshare/src/unfinished/db_acadeeb.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * libretroshare/src/gxp: gxp_apps.h - * - * General Exchange Protocol interface for RetroShare. - * - * Copyright 2011-2011 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#ifndef RS_ACADEE_H -#define RS_ACADEE_H - -/******* - * Stores a Bibliography of Academic Articles, with links to allow you to access the actual article. - * The data fields, should contain enough information to - * - extract full biblio (bibtex or ris formats). - * - read abstract. - * - review / rating of the article - * - references to similar papers, and bibliography. - * - keywords, and the like. - * - * It will be possible to have multiple identical / similar / different descriptions of the same article. - * The class will have to handle this: sorting and matching as best it can. - * - ****/ - -class gxp::Paper -{ - /* fields from ris */ - std::string reftype; - std::string journal; - std::string title; - std::string issuetitle; - uint32_t volume; - uint32_t issue; - std::string publisher; - std::string serialnumber; - std::string url; - std::list authors; - rstime_t date; - uint32_t startpage; - uint32_t endpage; - std::string language; - - std::string abstract; - - // KeyWords <- go into hashtags (parent class) - //References & Similar Papers <- go into links (parent class) -}; - - -class rsAcadee: public rsGmxp -{ - public: - - /* we want to access the */ - - - - -}; - - -#endif /* RS_GXP_H */ - - diff --git a/libretroshare/src/unfinished/db_wire.h b/libretroshare/src/unfinished/db_wire.h deleted file mode 100644 index cac3f2747..000000000 --- a/libretroshare/src/unfinished/db_wire.h +++ /dev/null @@ -1,50 +0,0 @@ - -#include "gxp_service.h" - -class db_wire -{ - /* external interface for accessing the info */ - - /** Note this could get very busy with a large number of tweeters. - * need some other method of getting data - */ - - getTweeters(std::list &tweeterIds); - { - getGroups(); - } - - getTweetRange(GxpTimeStamp, GxpTimeStamp, std::list &tweetIds); - { - getTimeRange(); - } - - getTweetRangeSource(GxpTimeStamp, GxpTimeStamp, std::string tweeterId, std::list &tweetIds); - { - getGroupTimeRange(); - } - - getTweet(std::string id, TweetData &tweet); - { - StackLock(); - - RsGxpItem *getMsg_locked(id); - - // translate message into TweetData. - - } - - // Default - getProfile(std::string id, TweetData &tweet); - - /* returns a search code, which is used to id later delivery */ - int searchTweets(GxpSearchCondition cond, std::list); - - /* returns a search code, which is used to id later delivery */ - int fetchPendingSearchResults(int searchId, std::list); - - int cancelSearch(int searchId, std::list); - -}; - - diff --git a/libretroshare/src/unfinished/mail/directmailservice.cc b/libretroshare/src/unfinished/mail/directmailservice.cc deleted file mode 100644 index aa28a7cca..000000000 --- a/libretroshare/src/unfinished/mail/directmailservice.cc +++ /dev/null @@ -1,254 +0,0 @@ -/* - * libretroshare/src/services directmailservice.cc - * - * Services for RetroShare. - * - * Copyright 2014 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#include "services/mail/directmailservice.h" - -#include "util/rsdebug.h" - -//#define MSG_DEBUG 1 - -const int directmailzone = 54319; - -using namespace Rs::Mail; - - -DirectMailService::DirectMailService(p3ServiceControl *sc) - :MailTransport(DEFAULT_MAX_MESSAGE_SIZE, RS_SERVICE_TYPE_DIRECT_MAIL), - p3Service(), mServiceCtrl(sc), mMsgMtx("DirectMailService") -{ - mSerialiser = new RsMailTransportSerialiser(RS_SERVICE_TYPE_DIRECT_MAIL); - addSerialType(mSerialiser); -} - -const std::string MSGDIRECT_APP_NAME = "msgdirect"; -const uint16_t MSGDIRECT_APP_MAJOR_VERSION = 1; -const uint16_t MSGDIRECT_APP_MINOR_VERSION = 0; -const uint16_t MSGDIRECT_MIN_MAJOR_VERSION = 1; -const uint16_t MSGDIRECT_MIN_MINOR_VERSION = 0; - -RsServiceInfo DirectMailService::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_DIRECT_MAIL, - MSGDIRECT_APP_NAME, - MSGDIRECT_APP_MAJOR_VERSION, - MSGDIRECT_APP_MINOR_VERSION, - MSGDIRECT_MIN_MAJOR_VERSION, - MSGDIRECT_MIN_MINOR_VERSION); -} - - -bool DirectMailService::CanSend(const RsTlvMailAddress &addr) -{ - /* we can send if MessageAddress is a peerID, - * and the peer ID is a friend. - */ - if (addr.mAddressType == ADDRESS_TYPE_PEER_ID) - { - return true; - } - return false; -} - -bool DirectMailService::sendMail(RsMailChunkItem *item) -{ - // set the right serviceId. - item->setPacketService(RS_SERVICE_TYPE_DIRECT_MAIL); - if (!attemptToSend(item)) - { - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - mOutgoingMsgs.push_back(item); - } - return true; -} - -RsMailChunkItem *DirectMailService::recvMail() -{ - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - if (!mIncomingMsgs.empty()) - { - RsMailChunkItem *item = mIncomingMsgs.front(); - mIncomingMsgs.pop_front(); - return item; - } - return NULL; -} - -RsPeerId convertAddressToPeerId(RsMailAckItem *item) -{ - RsPeerId id; - return id; -} - -bool DirectMailService::sendMailAck(RsMailAckItem *item) -{ - // set the right serviceId. - item->setPacketService(RS_SERVICE_TYPE_DIRECT_MAIL); - item->PeerId(convertAddressToPeerId(item)); - if (!attemptToSend(item)) - { - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - mOutgoingMsgs.push_back(item); - } - return true; -} - -RsMailAckItem *DirectMailService::recvMailAck() -{ - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - if (!mIncomingAckMsgs.empty()) - { - RsMailAckItem *item = mIncomingAckMsgs.front(); - mIncomingMsgs.pop_front(); - - return item; - } - return NULL; -} - - -int DirectMailService::tick() -{ - rslog(RSL_DEBUG_BASIC, directmailzone, - "DirectMailService::tick()"); - - incomingMsgs(); - return 0; -} - - -int DirectMailService::status() -{ - rslog(RSL_DEBUG_BASIC, directmailzone, - "DirectMailService::status()"); - - return 1; -} - -void DirectMailService::statusChange(const std::list &plist) -{ - /* should do it properly! */ - /* only do this when a new peer is connected */ - bool newPeers = false; - std::list::const_iterator it; - for(it = plist.begin(); it != plist.end(); it++) - { - if (it->actions & RS_SERVICE_PEER_CONNECTED) - { - newPeers = true; - } - } - - if (newPeers) - { - checkOutgoingMessages(); - } -} - - -int DirectMailService::incomingMsgs() -{ - RsItem *item; - int i = 0; - - while((item = recvItem()) != NULL) - { - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - RsMailChunkItem *mi = dynamic_cast(item); - RsMailAckItem *mai = dynamic_cast(item); - if (mi) - { - mIncomingMsgs.push_back(mi); - } - else if (mai) - { - mIncomingAckMsgs.push_back(mai); - } - else - { - std::cerr << "DirectMailService::incomingMsgs() Unknown incoming Msg"; - std::cerr << std::endl; - delete item; - } - ++i; - } - return i; -} - -// This is a Local copy of an Outgoing message - either SentBox or Draft. -bool DirectMailService::attemptToSend(RsItem *mi) -{ - RsPeerId pid = mi->PeerId(); - if (mServiceCtrl->isPeerConnected(getServiceInfo().mServiceType, pid)) - { - sendItem(mi); - return true; - } - - return false; -} - -void DirectMailService::checkOutgoingMessages() -{ - /* iterate through the outgoing queue and attempt to send. - */ - - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - std::list::iterator mit; - for(mit = mOutgoingMsgs.begin(); mit != mOutgoingMsgs.end(); mit++) - { - if (attemptToSend(*mit)) - { - /* actually sent the message */ - mit = mOutgoingMsgs.erase(mit); - } - else - { - mit++; - } - } -} - -bool DirectMailService::haveIncomingMail() -{ - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ - - if (!mIncomingMsgs.empty()) - { - return true; - } - - if (!mIncomingAckMsgs.empty()) - { - return true; - } - return false; -} - - diff --git a/libretroshare/src/unfinished/mail/directmailservice.h b/libretroshare/src/unfinished/mail/directmailservice.h deleted file mode 100644 index 7d6ce0d19..000000000 --- a/libretroshare/src/unfinished/mail/directmailservice.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * libretroshare/src/services/mail directmailservice.h - * - * Services for RetroShare. - * - * Copyright 2014 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#ifndef DIRECT_MAIL_SERVICE_HEADER -#define DIRECT_MAIL_SERVICE_HEADER - -#include "services/mail/mailtransport.h" -#include "services/p3service.h" - -#include "pqi/pqiservicemonitor.h" - -#include "util/rsthreads.h" - - -namespace Rs -{ -namespace Mail -{ - -class DirectMailService: public MailTransport, public p3Service, public pqiServiceMonitor -{ - -public: - DirectMailService(p3ServiceControl *sc); - virtual RsServiceInfo getServiceInfo(); - - /******* MailTransport Interface ********************************************************/ - - virtual bool CanSend(const RsTlvMailAddress &addr); - virtual bool haveIncomingMail(); - - virtual bool sendMail(RsMailChunkItem *msg); - virtual RsMailChunkItem *recvMail(); - virtual bool sendMailAck(RsMailAckItem *ack); - virtual RsMailAckItem *recvMailAck(); - - /******* MsgTransport Interface ********************************************************/ - - int tick(); - int status(); - - /*** Overloaded from pqiMonitor ***/ - virtual void statusChange(const std::list &plist); - /*** Overloaded from pqiMonitor ***/ - -private: - - int incomingMsgs(); - void checkOutgoingMessages(); - bool attemptToSend(RsItem *item); - - p3ServiceControl *mServiceCtrl; - - /* Mutex Required for stuff below */ - RsMutex mMsgMtx; - RsMailTransportSerialiser *mSerialiser ; - - /* outgoing messages */ - std::list mOutgoingMsgs; - - /* incoming msgs */ - std::list mIncomingMsgs; - std::list mIncomingAckMsgs; -}; - -} // namspace Msg -} // namspace Rs - -#endif // DIRECT_MESSAGE_SERVICE_HEADER diff --git a/libretroshare/src/unfinished/mail/mailtransport.cc b/libretroshare/src/unfinished/mail/mailtransport.cc deleted file mode 100644 index f342c9fd3..000000000 --- a/libretroshare/src/unfinished/mail/mailtransport.cc +++ /dev/null @@ -1,56 +0,0 @@ -/* - * libretroshare/src/services/mail mailtransport.cc - * - * Services for RetroShare. - * - * Copyright 2014 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "services/mail/mailtransport.h" - -using namespace Rs::Mail; - -MailTransport::MailTransport(uint32_t max_size, uint16_t transport_type) -:mEnabled(true), mMaxSize(max_size), mTransportType(transport_type) -{ - return; -} - -bool MailTransport::isEnabled() -{ - return mEnabled; -} - -void MailTransport::setEnabled(bool enabled) -{ - mEnabled = enabled; -} - -uint32_t MailTransport::getMaxSize() -{ - return mMaxSize; -} - -uint16_t MailTransport::getTransportType() -{ - return mTransportType; -} - - diff --git a/libretroshare/src/unfinished/mail/mailtransport.h b/libretroshare/src/unfinished/mail/mailtransport.h deleted file mode 100644 index 0c6abac08..000000000 --- a/libretroshare/src/unfinished/mail/mailtransport.h +++ /dev/null @@ -1,77 +0,0 @@ -#pragma once -#ifndef RS_MAIL_TRANSPORT_HEADER -#define RS_MAIL_TRANSPORT_HEADER -/* - * libretroshare/src/services/mail mailtransport.h - * - * Services for RetroShare. - * - * Copyright 2014 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#include "serialiser/rsmailtransportitems.h" - - -namespace Rs -{ -namespace Mail -{ - -const uint32_t DEFAULT_MAX_MESSAGE_SIZE = (64 * 1024); - -// To decide how this will work! -const uint32_t ADDRESS_TYPE_PEER_ID = 0x001; -const uint32_t ADDRESS_TYPE_GXS_ID = 0x002; -const uint32_t ADDRESS_TYPE_EMAIL_ID = 0x003; - - -class MailTransport -{ -public: - MailTransport(uint32_t max_size, uint16_t transport_type); - virtual ~MailTransport(); - - virtual bool CanSend(const RsTlvMailAddress &addr) = 0; - virtual bool haveIncomingMail() = 0; - - virtual bool sendMail(RsMailChunkItem *msg) = 0; - virtual RsMailChunkItem *recvMail() = 0; - virtual bool sendMailAck(RsMailAckItem *ack) = 0; - virtual RsMailAckItem *recvMailAck() = 0; - - virtual bool isEnabled(); - virtual void setEnabled(bool enabled); - - uint32_t getMaxSize(); - uint16_t getTransportType(); - -private: - - bool mEnabled; - uint32_t mMaxSize; - uint16_t mTransportType; -}; - - -} // namespace Mail -} // namespace Rs - -#endif diff --git a/libretroshare/src/unfinished/p3portservice.cc b/libretroshare/src/unfinished/p3portservice.cc deleted file mode 100644 index af4b24a73..000000000 --- a/libretroshare/src/unfinished/p3portservice.cc +++ /dev/null @@ -1,123 +0,0 @@ -/* - * "$Id: p3PortService.cc,v 1.24 2007-05-05 16:10:06 rmf24 Exp $" - * - * Other Bits for RetroShare. - * - * Copyright 2004-2006 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#include "services/p3portservice.h" -#include "serialiser/rsserviceids.h" - -p3PortService::p3PortService(p3ConnectMgr *cm) - :p3Service(RS_SERVICE_TYPE_PORT), mConnMgr(cm), mEnabled(false) -{ - /* For Version 1, we'll just use the very simple RsRawItem packets - * which are handled in the RsServiceSerialiser - */ - addSerialType(new RsServiceSerialiser()); -} - -int p3PortService::tick() -{ -#ifdef PORT_DEBUG - std::cerr << "p3PortService::tick()"; - std::cerr << std::endl; -#endif - - /* discard data if not enabled */ - if (!mEnabled) - { - RsItem *i; - while(NULL != (i = recvItem())) - { - delete i; - } - } - - /* Rough list of what might happen (once the sockets are opened!) */ - - - /* check for data on sockets */ - //int sockfd; - RsRawItem *item; - - //while(0 < (len = recv(sockfd, ....))) ... etc. - { - - /* example of how to package data up - * We use RsRawItem as it'll handle a single binary chunk. - * This is enough for version 1.... but versions 2 + 3 will - * need their own serialiser. - * - * */ - - /* input data TODO! */ - void *data=NULL; - uint32_t len=0; - - uint32_t packetId = (((uint32_t) RS_PKT_VERSION_SERVICE) << 24) + - (((uint32_t) RS_SERVICE_TYPE_PORT) << 8); - - /* create Packet for RS Transport */ - RsRawItem *item = new RsRawItem(packetId, len); - void *item_data = item->getRawData(); - memcpy(item_data, data, len); - - /* set the correct peer destination. */ - item->PeerId(mPeerId); - - /* send data */ - sendItem(item); - - /* no delete -> packet cleaned up by RS internals */ - } - - - /* get any incoming data */ - while(NULL != (item = (RsRawItem*) recvItem())) - { - /* unpackage data */ - std::string src = item->PeerId(); -// void *item_data = item->getRawData(); -// uint32_t item_len = item->getRawLength(); - - /* push out to the socket .... */ - // send(sockfd, item_len, item_data....) - - /* cleanup packet */ - delete item; - } - - return 0; -} - -bool p3PortService::enablePortForwarding(uint32_t port, std::string peerId) -{ - mPort = port; - mPeerId = peerId; - mEnabled = true; - - return true; -} - - - diff --git a/libretroshare/src/unfinished/p3portservice.h b/libretroshare/src/unfinished/p3portservice.h deleted file mode 100644 index b1ef089f9..000000000 --- a/libretroshare/src/unfinished/p3portservice.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * libretroshare/src/services: p3portservice.h - * - * Services for RetroShare. - * - * Copyright 2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -#ifndef SERVICE_PORT_FORWARD_HEADER -#define SERVICE_PORT_FORWARD_HEADER - -/* - * The start of a port forwarding service. - * - * This is just a very rough example of what might be required for version 1. - * - * FIRST VERSION: - * - * listen to a single port and send data with a single RS peer. - * - * - * SECOND VERSION: - * - * enable multiple port forwardings. - * - * each forwarding consists of a 'port, peerId & Connection Id'. - * - * THIRD VERSION: - * - * add broadcast/multicast forwardings. - * i.e. data gets sent to multiple peers. - * - * each forwarding with then consist of 'port, connectionId + list of peerIds' - * NOTE: version 3 needs some thought - might require a master host - * which distributes to all others.... or other more complicated systems. - * - */ - -#include -#include - -#include "serialiser/rsbaseitems.h" -#include "services/p3service.h" -#include "pqi/p3connmgr.h" - - -class p3PortService: public p3Service -{ - public: - p3PortService(p3ConnectMgr *cm); - - /* example setup functions */ -bool enablePortForwarding(uint32_t port, std::string peerId); - - /* overloaded */ -virtual int tick(); - - private: - - p3ConnectMgr *mConnMgr; - - bool mEnabled; - bool mPeerOnline; - - uint32_t mPort; - std::string mPeerId; - -}; - -#endif // SERVICE_PORT_FORWARD_HEADER diff --git a/libretroshare/src/unfinished/p3tunnel.cc b/libretroshare/src/unfinished/p3tunnel.cc deleted file mode 100644 index 50a10b56e..000000000 --- a/libretroshare/src/unfinished/p3tunnel.cc +++ /dev/null @@ -1,347 +0,0 @@ -/* - * libretroshare/src/services: p3tunnel.cc - * - * Services for RetroShare. - * - * Copyright 2004-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - - -//#include "retroshare/rsiface.h" -//#include "retroshare/rsinit.h" /* for PGPSSL flag */ -//#include "retroshare/rspeers.h" -#include "services/p3tunnel.h" -#include "pqi/pqissltunnel.h" - -#include "pqi/authssl.h" -#include "pqi/p3connmgr.h" - -#include - -#include "util/rsdebug.h" -#include "util/rsprint.h" -#include "util/rsversion.h" - -#define TUNNEL_HANDSHAKE_INIT 1 -#define TUNNEL_HANDSHAKE_ACK 2 -#define TUNNEL_HANDSHAKE_REFUSE 0 - - p3tunnel::p3tunnel(p3ConnectMgr *cm, pqipersongrp *perGrp) -:p3Service(RS_SERVICE_TYPE_TUNNEL), mConnMgr(cm), mPqiPersonGrp(perGrp) -{ - RsStackMutex stack(mTunnelMtx); /********** STACK LOCKED MTX ******/ - - ownId = mConnMgr->getOwnId(); - std::cerr << "ownId : " << mConnMgr->getOwnId() << std::endl; - addSerialType(new RsTunnelSerialiser()); - - return; -} - -void p3tunnel::statusChange(const std::list &plist) { -} - -int p3tunnel::tick() -{ - return handleIncoming(); -} - -int p3tunnel::handleIncoming() -{ - RsItem *item = NULL; - -#ifdef P3TUNNEL_DEBUG - //std::cerr << "p3tunnel::handleIncoming() called." << std::endl; -#endif - - int nhandled = 0; - // While messages read - while(NULL != (item = recvItem())) - { - if (!mConnMgr->getTunnelConnection()) { - //no tunnel allowed, just drop the packet - continue; - } - - RsTunnelDataItem *tdi = NULL; - RsTunnelHandshakeItem *thi = NULL; - - { -#ifdef P3TUNNEL_DEBUG - std::string out = "p3tunnel::handleIncoming() Received Message!\n"; - item -> print_string(out); - std::cerr << out; -#endif - } - - if (NULL != (tdi = dynamic_cast (item))) { - recvTunnelData(tdi); - nhandled++; - } else if (NULL != (thi = dynamic_cast (item))) { - recvTunnelHandshake(thi); - nhandled++; - } - delete item; - } - return nhandled; -} - -/*************************************************************************************/ -/* Output Network Msgs */ -/*************************************************************************************/ -void p3tunnel::sendTunnelData(std::string destPeerId, std::string relayPeerId, void *data, int data_length) { - sendTunnelDataPrivate(relayPeerId, ownId,relayPeerId, destPeerId, data, data_length); -} - - -void p3tunnel::sendTunnelDataPrivate(std::string to, std::string sourcePeerId, std::string relayPeerId, std::string destPeerId, void *data, int data_length) { - if (!mConnMgr->getTunnelConnection()) { - //no tunnel allowed, just drop the request - return; - } - - RsStackMutex stack(mTunnelMtx); /********** STACK LOCKED MTX ******/ - - // Then send message. - { -#ifdef P3TUNNEL_DEBUG - std::string out = "p3tunnel::sendTunnelDataPrivate() Constructing a RsTunnelItem Message!\n"; - out += "Sending to: " + to; - std::cerr << out << std::endl; -#endif - } - - // Construct a message - RsTunnelDataItem *rdi = new RsTunnelDataItem(); - rdi->destPeerId = destPeerId; - rdi->sourcePeerId = sourcePeerId; - rdi->relayPeerId = relayPeerId; - rdi->encoded_data_len = data_length; - - if(data_length > 0) - { - rdi->encoded_data = (void*)malloc(data_length); - memcpy(rdi->encoded_data, data, data_length); - } - - rdi->PeerId(to); - -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::sendTunnelDataPrivate() data_length : "<< data_length << std::endl; -#endif - /* send msg */ - sendItem(rdi); -} - -void p3tunnel::pingTunnelConnection(std::string relayPeerId, std::string destPeerId) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::pingTunnelConnection() sending ping with relay id : " << relayPeerId << std::endl; - std::cerr << "ownId : " << ownId << std::endl; - std::cerr << "destPeerId : " << destPeerId << std::endl; -#endif - this->sendTunnelDataPrivate(relayPeerId, ownId, relayPeerId, destPeerId, NULL, 0); -} - -void p3tunnel::initiateHandshake(std::string relayPeerId, std::string destPeerId) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::initiateHandshake() initiating handshake with relay id : " << relayPeerId << std::endl; - std::cerr << "ownId : " << ownId << std::endl; - std::cerr << "destPeerId : " << destPeerId << std::endl; -#endif - // Construct a message - RsTunnelHandshakeItem *rhi = new RsTunnelHandshakeItem(); - rhi->destPeerId = destPeerId; - rhi->sourcePeerId = ownId; - rhi->relayPeerId = relayPeerId; - rhi->connection_accepted = TUNNEL_HANDSHAKE_INIT; - rhi->sslCertPEM = AuthSSL::getAuthSSL()->SaveOwnCertificateToString(); - - rhi->PeerId(relayPeerId); - - /* send msg */ - sendItem(rhi); -} - -/*************************************************************************************/ -/* Input Network Msgs */ -/*************************************************************************************/ -void p3tunnel::recvTunnelHandshake(RsTunnelHandshakeItem *item) -{ -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::recvTunnelHandshake() From: " << item->PeerId() << std::endl; -#endif - - RsPeerDetails pd; - if (!AuthSSL::getAuthSSL()->LoadDetailsFromStringCert(item->sslCertPEM, pd)) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::recvTunnelHandshake() cert is not valid. This might be a intrusion attempt." << std::endl; -#endif - return; - } - - if (item->sourcePeerId != pd.id) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::recvTunnelHandshake() cert is not issued from the source id of the tunnel. This might be a intrusion attempt." << std::endl; -#endif - return; - } - - //compare the peer id from the item sender to the ids in the item. - if (item->PeerId() == item->sourcePeerId && ownId == item->relayPeerId) { - if (mConnMgr->isOnline(item->destPeerId)) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::recvTunnelHandshake() relaying packet." << std::endl; -#endif - //relaying the handshake - RsTunnelHandshakeItem* forwardItem = new RsTunnelHandshakeItem(); - forwardItem->sourcePeerId = item->sourcePeerId; - forwardItem->relayPeerId = item->relayPeerId; - forwardItem->destPeerId = item->destPeerId; - forwardItem->connection_accepted = item->connection_accepted; - forwardItem->sslCertPEM = item->sslCertPEM; - forwardItem->PeerId(item->destPeerId); - sendItem(forwardItem); - } else { - //sending back refuse - //not implemented -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::recvTunnelHandshake() not relaying packet because destination is offline." << std::endl; -#endif - } - } else if (item->PeerId() == item->relayPeerId && ownId == item->destPeerId) { - if (item->connection_accepted == TUNNEL_HANDSHAKE_INIT || item->connection_accepted == TUNNEL_HANDSHAKE_ACK) { - //check if we accept connection - if (!mConnMgr->isFriend(pd.id)) { - //send back a refuse - // not implemented - } else { - if (item->connection_accepted == TUNNEL_HANDSHAKE_INIT) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::recvTunnelHandshake() sending back acknowledgement to " << item->sourcePeerId << std::endl; -#endif - //send back acknowledgement - RsTunnelHandshakeItem* ack = new RsTunnelHandshakeItem(); - ack->sourcePeerId = ownId; - ack->relayPeerId = item->relayPeerId; - ack->destPeerId = item->sourcePeerId; - ack->connection_accepted = TUNNEL_HANDSHAKE_ACK; - ack->sslCertPEM = AuthSSL::getAuthSSL()->SaveOwnCertificateToString(); - ack->PeerId(item->relayPeerId); - sendItem(ack); - } - - //open the local tunnel connection -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::recvTunnelHandshake() opening localy the tunnel connection emulation." << std::endl; -#endif - pqiperson *pers = mPqiPersonGrp->getPeer(item->sourcePeerId); - pqissltunnel *pqicon = (pqissltunnel *)(((pqiconnect *) pers->getKid(PQI_CONNECT_TUNNEL))->ni); - pqicon->IncommingHanshakePacket(item->relayPeerId); - } - } - } -} - - -void p3tunnel::recvTunnelData(RsTunnelDataItem *item) -{ -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::recvPeerConnectRequest() From: " << item->PeerId() << std::endl; -#endif - - //compare the peer id from the item sender to the ids in the item. - if (item->PeerId() == item->sourcePeerId && ownId == item->relayPeerId) { - privateRecvTunnelDataRelaying(item); - } else if (item->PeerId() == item->relayPeerId && ownId == item->destPeerId) { - privateRecvTunnelDataDestination(item); - } -} - -void p3tunnel::privateRecvTunnelDataRelaying(RsTunnelDataItem *item) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::privateRecvTunnelDataRelaying() I am relaying, let's see if it's possible to send the packet to destination." << std::endl; -#endif - if (!mConnMgr->isFriend(item->sourcePeerId) || !mConnMgr->isFriend(item->destPeerId)) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::privateRecvTunnelDataDestination() not trusting relay or dest peer. Aborting." << std::endl; -#endif - return; - } - if (mConnMgr->isOnline(item->destPeerId)) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::privateRecvTunnelDataRelaying() I am relaying, relay the packet to destination." << std::endl; -#endif - sendTunnelDataPrivate(item->destPeerId, item->sourcePeerId, ownId, item->destPeerId, item->encoded_data, item->encoded_data_len); - return; - } -} - -void p3tunnel::privateRecvTunnelDataDestination(RsTunnelDataItem *item) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::privateRecvTunnelDataDestination() I am the destination Id, let's make some checks and read the packet." << std::endl; -#endif - - if (!mConnMgr->isFriend(item->sourcePeerId) || !mConnMgr->isFriend(item->relayPeerId)) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::privateRecvTunnelDataDestination() not trusting relay or source peer. Aborting." << std::endl; -#endif - return; - } - - if (!mConnMgr->isOnline(item->relayPeerId)) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::privateRecvTunnelDataDestination() relay peer is not connected, connection impossible. Aborting." << std::endl; -#endif - return; - } - - pqiperson *pers = mPqiPersonGrp->getPeer(item->sourcePeerId); - if (pers == NULL) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::privateRecvTunnelDataDestination() tunnel connection not found. Aborting." << std::endl; -#endif - return; - } - - pqissltunnel *pqicon = (pqissltunnel *)(((pqiconnect *) pers->getKid(PQI_CONNECT_TUNNEL))->ni); - if (pqicon == NULL || !pqicon->isactive()) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::privateRecvTunnelDataDestination() tunnel connection not found. Aborting." << std::endl; -#endif - return; - } - - //send the packet to the net emulation layer - if (item->encoded_data_len == 0) { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::privateRecvTunnelDataDestination() receiving a ping packet, activating connection and sending back acknowlegment." << std::endl; -#endif - pqissltunnel *pqicon = (pqissltunnel *)(((pqiconnect *) pers->getKid(PQI_CONNECT_TUNNEL))->ni); - pqicon->IncommingPingPacket(); - } else { -#ifdef P3TUNNEL_DEBUG - std::cerr << "p3tunnel::privateRecvTunnelDataDestination() receiving a data packet, transfer it to the pqissltunnel connection." << std::endl; - std::cerr << "p3tunnel::privateRecvTunnelDataDestination() getRsItemSize(item->encoded_data) : " << getRsItemSize(item->encoded_data) << std::endl; -#endif - pqissltunnel *pqicon = (pqissltunnel *)(((pqiconnect *) pers->getKid(PQI_CONNECT_TUNNEL))->ni); - pqicon->addIncomingPacket(item->encoded_data, item->encoded_data_len); - } - return; -} diff --git a/libretroshare/src/unfinished/p3tunnel.h b/libretroshare/src/unfinished/p3tunnel.h deleted file mode 100644 index ec5a03896..000000000 --- a/libretroshare/src/unfinished/p3tunnel.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * libretroshare/src/services: p3tunnel.h - * - * Services for RetroShare. - * - * Copyright 2004-2008 by Robert Fernie. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#ifndef MRK_PQI_TUNNEL_H -#define MRK_PQI_TUNNEL_H - -// The AutoDiscovery Class - -#include "pqi/pqipersongrp.h" - -// system specific network headers -#include "pqi/pqi.h" - -class p3ConnectMgr; - -#include "pqi/pqimonitor.h" -#include "services/p3service.h" -#include "serialiser/rstunnelitems.h" -#include "pqi/authssl.h" - -class p3tunnel: public p3Service, public pqiMonitor -{ - public: - -virtual void statusChange(const std::list &plist); - - p3tunnel(p3ConnectMgr *cm, pqipersongrp *persGrp); - -int tick(); - -void sendTunnelData(std::string destPeerId, std::string relayPeerId, void *data, int data_length); - -void pingTunnelConnection(std::string relayPeerId, std::string destPeerId); -void initiateHandshake(std::string relayPeerId, std::string destPeerId); - - private: - -void sendTunnelDataPrivate(std::string to, std::string sourcePeerId, std::string relayPeerId, std::string destPeerId, void *data, int data_length); - -void privateRecvTunnelDataRelaying(RsTunnelDataItem *item); //invoked when I am relaying -void privateRecvTunnelDataDestination(RsTunnelDataItem *item); //invoked when I am the destination of the tunnel - - /* Network Input */ -int handleIncoming(); -void recvTunnelData(RsTunnelDataItem *item); -void recvTunnelHandshake(RsTunnelHandshakeItem *item); - - - private: - - p3ConnectMgr *mConnMgr; - pqipersongrp *mPqiPersonGrp; - std::string ownId; - - - /* data */ - RsMutex mTunnelMtx; -}; - -#endif // MRK_PQI_TUNNEL_H diff --git a/libretroshare/src/unfinished/rstlvdsdv.cc b/libretroshare/src/unfinished/rstlvdsdv.cc deleted file mode 100644 index da3abe8c5..000000000 --- a/libretroshare/src/unfinished/rstlvdsdv.cc +++ /dev/null @@ -1,419 +0,0 @@ - -/* - * libretroshare/src/serialiser: rstlvtypes.cc - * - * RetroShare Serialiser. - * - * Copyright 2007-2008 by Robert Fernie, Chris Parker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -#include "rstlvdsdv.h" -#include "rsbaseserial.h" - - -/************************************* RsTlvDsdvEndPoint ************************************/ - -RsTlvDsdvEndPoint::RsTlvDsdvEndPoint() - :RsTlvItem(), idType(0) -{ - return; -} - -void RsTlvDsdvEndPoint::TlvClear() -{ - idType = 0; - anonChunk.clear(); - serviceId.clear(); -} - -uint32_t RsTlvDsdvEndPoint::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header + 4 + str + str */ - - s += 4; // idType; - s += GetTlvStringSize(anonChunk); - s += GetTlvStringSize(serviceId); - - return s; - -} - -bool RsTlvDsdvEndPoint::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - /* add mandatory parts first */ - - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_DSDV_ENDPOINT, tlvsize); - - ok &= setRawUInt32(data, tlvend, offset, idType); - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_GENID, anonChunk); - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_HASH_SHA1, serviceId); - return ok; - -} - - -bool RsTlvDsdvEndPoint::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_DSDV_ENDPOINT) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - ok &= getRawUInt32(data, tlvend, offset, &(idType)); - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_GENID, anonChunk); - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_HASH_SHA1, serviceId); - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvDsdvEndPoint::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; - -} - - -std::ostream &RsTlvDsdvEndPoint::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvDsdvEndPoint", indent); - uint16_t int_Indent = indent + 2; - - printIndent(out, int_Indent); - out << "idType:" << idType; - out << std::endl; - - printIndent(out, int_Indent); - out << "AnonChunk:" << anonChunk; - out << std::endl; - - printIndent(out, int_Indent); - out << "ServiceId:" << serviceId; - out << std::endl; - - printEnd(out, "RsTlvDsdvEndPoint", indent); - return out; -} - - -/************************************* RsTlvDsdvEntry ************************************/ - -RsTlvDsdvEntry::RsTlvDsdvEntry() - :RsTlvItem(), sequence(0), distance(0) -{ - return; -} - -void RsTlvDsdvEntry::TlvClear() -{ - endPoint.TlvClear(); - sequence = 0; - distance = 0; -} - -uint32_t RsTlvDsdvEntry::TlvSize() const -{ - uint32_t s = TLV_HEADER_SIZE; /* header + EndPoint.Size + 4 + 4 */ - - s += endPoint.TlvSize(); - s += 4; // sequence; - s += 4; // distance; - - return s; - -} - -bool RsTlvDsdvEntry::SetTlv(void *data, uint32_t size, uint32_t *offset) const -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - /* add mandatory parts first */ - - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_DSDV_ENTRY, tlvsize); - - ok &= endPoint.SetTlv(data, size, offset); - ok &= setRawUInt32(data, tlvend, offset, sequence); - ok &= setRawUInt32(data, tlvend, offset, distance); - - return ok; - -} - - -bool RsTlvDsdvEntry::GetTlv(void *data, uint32_t size, uint32_t *offset) -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_DSDV_ENTRY) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - ok &= endPoint.GetTlv(data, size, offset); - ok &= getRawUInt32(data, tlvend, offset, &(sequence)); - ok &= getRawUInt32(data, tlvend, offset, &(distance)); - - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvDsdvEntry::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; - -} - - -std::ostream &RsTlvDsdvEntry::print(std::ostream &out, uint16_t indent) const -{ - printBase(out, "RsTlvDsdvEntry", indent); - uint16_t int_Indent = indent + 2; - - endPoint.print(out, int_Indent); - - printIndent(out, int_Indent); - out << "Sequence:" << sequence; - out << std::endl; - - printIndent(out, int_Indent); - out << "Distance:" << distance; - out << std::endl; - - printEnd(out, "RsTlvDsdvEntry", indent); - return out; -} - - -/************************************* RsTlvDsdvEntrySet ************************************/ - -#if 0 -RsTlvDsdvEntrySet::RsTlvDsdvEntrySet() -{ - -} - -void RsTlvDsdvEntrySet::TlvClear() -{ - entries.clear(); -} - -uint32_t RsTlvDsdvEntrySet::TlvSize() -{ - - uint32_t s = TLV_HEADER_SIZE; /* header */ - - std::list::iterator it; - - - if(!entries.empty()) - { - - for(it = entries.begin(); it != entries.end() ; ++it) - s += it->TlvSize(); - - } - - return s; -} - -bool RsTlvDsdvEntrySet::SetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ -{ - /* must check sizes */ - uint32_t tlvsize = TlvSize(); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) - return false; /* not enough space */ - - bool ok = true; - - /* start at data[offset] */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_DSDV_ENTRY_SET , tlvsize); - - if(!entries.empty()) - { - std::list::iterator it; - - for(it = entries.begin(); it != entries.end() ; ++it) - ok &= it->SetTlv(data, size, offset); - } - - - return ok; - -} - - -bool RsTlvDsdvEntrySet::GetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ -{ - if (size < *offset + TLV_HEADER_SIZE) - return false; - - uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); - uint32_t tlvend = *offset + tlvsize; - - if (size < tlvend) /* check size */ - return false; /* not enough space */ - - if (tlvtype != TLV_TYPE_DSDV_ENTRY_SET) /* check type */ - return false; - - bool ok = true; - - /* ready to load */ - TlvClear(); - - /* skip the header */ - (*offset) += TLV_HEADER_SIZE; - - /* while there is TLV */ - while((*offset) + 2 < tlvend) - { - /* get the next type */ - uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); - - switch(tlvsubtype) - { - case TLV_TYPE_DSDV_ENTRY: - { - RsTlvDsdvEntry entry; - ok &= entry.GetTlv(data, size, offset); - if (ok) - { - entries.push_back(entry); - } - } - break; - default: - ok &= SkipUnknownTlv(data, tlvend, offset); - break; - - } - - if (!ok) - break; - } - - - - /*************************************************************************** - * NB: extra components could be added (for future expansion of the type). - * or be present (if this code is reading an extended version). - * - * We must chew up the extra characters to conform with TLV specifications - ***************************************************************************/ - if (*offset != tlvend) - { -#ifdef TLV_DEBUG - std::cerr << "RsTlvDsdvEntrySet::GetTlv() Warning extra bytes at end of item"; - std::cerr << std::endl; -#endif - *offset = tlvend; - } - - return ok; -} - -// prints out contents of RsTlvDsdvEntrySet -std::ostream &RsTlvDsdvEntrySet::print(std::ostream &out, uint16_t indent) -{ - printBase(out, "RsTlvDsdvEntrySet", indent); - uint16_t int_Indent = indent + 2; - - std::list::iterator it; - for(it = entries.begin(); it != entries.end() ; ++it) - it->print(out, int_Indent); - - printEnd(out, "RsTlvDsdvEntrySet", indent); - return out; -} - - -#endif - - diff --git a/libretroshare/src/unfinished/rstlvdsdv.h b/libretroshare/src/unfinished/rstlvdsdv.h deleted file mode 100644 index b815bb4ed..000000000 --- a/libretroshare/src/unfinished/rstlvdsdv.h +++ /dev/null @@ -1,88 +0,0 @@ -#pragma once - -/* - * libretroshare/src/serialiser: rstlvdsdv.h - * - * RetroShare Serialiser. - * - * Copyright 2011 by Robert Fernie - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License Version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - * - * Please report all bugs and problems to "retroshare@lunamutt.com". - * - */ - -/******************************************************************* - * These are the Compound TLV structures that must be (un)packed. - ******************************************************************/ - -#include "serialiser/rstlvitem.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvlist.h" - -#define RSDSDV_MAX_ROUTE_TABLE 1000 - -class RsTlvDsdvEndPoint: public RsTlvItem -{ - public: - RsTlvDsdvEndPoint(); -virtual ~RsTlvDsdvEndPoint() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - uint32_t idType; - std::string anonChunk; - std::string serviceId; -}; - -class RsTlvDsdvEntry: public RsTlvItem -{ - public: - RsTlvDsdvEntry(); -virtual ~RsTlvDsdvEntry() { return; } -virtual uint32_t TlvSize() const; -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const; -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); -virtual std::ostream &print(std::ostream &out, uint16_t indent) const; - - RsTlvDsdvEndPoint endPoint; - uint32_t sequence; - uint32_t distance; -}; - -typedef t_RsTlvList RsTlvDsdvEntrySet; - -#if 0 -class RsTlvDsdvEntrySet: public RsTlvItem -{ - public: - RsTlvDsdvEntrySet(); -virtual ~RsTlvDsdvEntrySet() { return; } -virtual uint32_t TlvSize(); -virtual void TlvClear(); -virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset); /* serialise */ -virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); /* deserialise */ -virtual std::ostream &print(std::ostream &out, uint16_t indent); - - std::list entries; -}; - -#endif - diff --git a/libretroshare/src/unused/p3dsdv.cc b/libretroshare/src/unused/p3dsdv.cc deleted file mode 100644 index 53880111b..000000000 --- a/libretroshare/src/unused/p3dsdv.cc +++ /dev/null @@ -1,910 +0,0 @@ -/******************************************************************************* - * libretroshare/src/unused: p3dsdv.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include -#include -#include "util/rstime.h" - -//#include "serialiser/rsdsdvitems.h" -#include "services/p3dsdv.h" -#include "pqi/p3linkmgr.h" -#include "util/rsrandom.h" - -#include - -/**** - * #define DEBUG_DSDV 1 - ****/ -#define DEBUG_DSDV 1 - -/* DEFINE INTERFACE POINTER! */ -RsDsdv *rsDsdv = NULL; - -/***** - * Routing Services are provided for any service or peer that wants to access / receive info - * over the internal network. - * - * This is going to be based loosely on Ben's Algorithm... - * Each Service / Peer is identified by a HASH. - * This HASH is disguised by a temporary ANON-CHUNK. - * DSDVID = Sha1(ANONCHUNK + HASH). - * - * Each peer can advertise as many Services as they want. - * The Anon-chunk should be rotated regularly to hide it well. - * period to be defined. - * - * - * Once this Routing table has been established, Routes can be created - in a similar manner to turtle paths. - * (Send Path request (Path Id + Origin + Destination))... path is established. - * - * Then we can do Onion Routing etc, on top of this. - * - ****/ - -p3Dsdv::p3Dsdv(p3ServiceControl *sc) - :p3Service(), /* p3Config(CONFIG_TYPE_DSDV), */ mDsdvMtx("p3Dsdv"), mServiceCtrl(sc) -{ - addSerialType(new RsDsdvSerialiser()); - - mSentTablesTime = 0; - mSentIncrementTime = 0; -} - -const std::string DSDV_APP_NAME = "dsdv"; -const uint16_t DSDV_APP_MAJOR_VERSION = 1; -const uint16_t DSDV_APP_MINOR_VERSION = 0; -const uint16_t DSDV_MIN_MAJOR_VERSION = 1; -const uint16_t DSDV_MIN_MINOR_VERSION = 0; - -RsServiceInfo p3Dsdv::getServiceInfo() -{ - return RsServiceInfo(RS_SERVICE_TYPE_DSDV, - DSDV_APP_NAME, - DSDV_APP_MAJOR_VERSION, - DSDV_APP_MINOR_VERSION, - DSDV_MIN_MAJOR_VERSION, - DSDV_MIN_MINOR_VERSION); -} - - - -int p3Dsdv::tick() -{ - processIncoming(); - sendTables(); - - return 0; -} - -int p3Dsdv::status() -{ - return 1; -} - -#define DSDV_BROADCAST_PERIOD (60*10) // 10 Minutes. -#define DSDV_MIN_INCREMENT_PERIOD 5 -#define DSDV_DISCARD_PERIOD (DSDV_BROADCAST_PERIOD * 2) - -int p3Dsdv::sendTables() -{ - rstime_t now = time(NULL); - rstime_t tt, it; - bool updateRequired = false; - { - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - tt = mSentTablesTime; - it = mSentIncrementTime; - updateRequired = mSignificantChanges; - } - - if (now - tt > DSDV_BROADCAST_PERIOD) - { - -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::sendTables() Broadcast Time"; - std::cerr << std::endl; -#endif - selectStableRoutes(); - clearOldRoutes(); - - generateRoutingTables(false); - - printDsdvTable(std::cerr); - - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - mSentTablesTime = now; - mSentIncrementTime = now; - - return true ; - } - - /* otherwise send incremental changes */ - if ((updateRequired) && (now - it > DSDV_MIN_INCREMENT_PERIOD)) - { - selectStableRoutes(); - - generateRoutingTables(true); - - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - mSentIncrementTime = now; - } - - return true; -} - -#define RSDSDV_SEQ_INCREMENT 2 - -void p3Dsdv::advanceLocalSequenceNumbers() -{ - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - - rstime_t now = time(NULL); - - std::map::iterator it; - for(it = mTable.begin(); it != mTable.end(); ++it) - { - RsDsdvTableEntry &v = (it->second); - if (v.mOwnSource) - { - v.mStableRoute.mSequence += RSDSDV_SEQ_INCREMENT; - v.mStableRoute.mReceived = now; - } - } -} - -void p3Dsdv::clearSignificantChangesFlags() -{ - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - - std::map::iterator it; - for(it = mTable.begin(); it != mTable.end(); ++it) - { - RsDsdvTableEntry &v = (it->second); - if (v.mFlags & RSDSDV_FLAGS_SIGNIFICANT_CHANGE) - { - v.mFlags &= ~RSDSDV_FLAGS_SIGNIFICANT_CHANGE; - } - } - mSignificantChanges = false; -} - - -int p3Dsdv::generateRoutingTables(bool incremental) -{ - /* we ping our peers */ - /* who is online? */ - std::set idList; - mServiceCtrl->getPeersConnected(getServiceInfo().mServiceType, idList); - -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::generateRoutingTables(" << incremental << ")"; - std::cerr << std::endl; -#endif - - if (!incremental) - { - /* now clear significant flag */ - advanceLocalSequenceNumbers(); - } - - /* prepare packets */ - std::set::iterator it; - for(it = idList.begin(); it != idList.end(); ++it) - { -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::generateRoutingTables() For: " << *it; - std::cerr << std::endl; -#endif - - generateRoutingTable(*it, incremental); - } - - - /* now clear significant flag */ - clearSignificantChangesFlags(); - return 1; -} - - -int p3Dsdv::generateRoutingTable(const RsPeerId &peerId, bool incremental) -{ - RsDsdvRouteItem *dsdv = new RsDsdvRouteItem(); - dsdv->PeerId(peerId); - - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - - std::map::iterator it; - for(it = mTable.begin(); it != mTable.end(); ++it) - { - RsDsdvTableEntry &v = (it->second); - - /* discard/ignore criterion */ - if (!v.mIsStable) - { - continue; - } - - if (v.mStableRoute.mDistance >= RSDSDV_MAX_DISTANCE) - { - continue; - } - - if (incremental) - { - if (v.mFlags & RSDSDV_FLAGS_SIGNIFICANT_CHANGE) - { - // Done elsewhere. - //v.mFlags &= ~SIGNIFICANT_CHANGE; - } - else - { - /* ignore non-significant changes */ - continue; - } - } - - RsTlvDsdvEntry entry; - - entry.endPoint.idType = v.mDest.mIdType; - entry.endPoint.anonChunk = v.mDest.mAnonChunk; - entry.endPoint.serviceId = v.mDest.mHash; - entry.sequence = v.mStableRoute.mSequence; - entry.distance = v.mStableRoute.mDistance; - - //dsdv->routes.entries.push_back(entry); - dsdv->routes.mList.push_back(entry); - - //if (dsdv->routes.entries.size() > RSDSDV_MAX_ROUTE_TABLE) - if (dsdv->routes.mList.size() > RSDSDV_MAX_ROUTE_TABLE) - { - sendItem(dsdv); - dsdv = new RsDsdvRouteItem(); - dsdv->PeerId(peerId); - } - } - sendItem(dsdv); - return 1; -} - - -/**************************************************************************** - ****************************************************************************/ - -int p3Dsdv::processIncoming() -{ - /* for each packet - pass to specific handler */ - RsItem *item = NULL; - while(NULL != (item = recvItem())) - { - switch(item->PacketSubType()) - { - default: - break; - case RS_PKT_SUBTYPE_DSDV_ROUTE: - { - handleDSDV((RsDsdvRouteItem *) item); - } - break; - } - - /* clean up */ - delete item; - } - return true ; -} - - -int p3Dsdv::handleDSDV(RsDsdvRouteItem *dsdv) -{ - /* iterate over the entries */ - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - - rstime_t now = time(NULL); - -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::handleDSDV() Received Pkt from: " << dsdv->PeerId(); - std::cerr << std::endl; - //dsdv->print(std::cerr); - //std::cerr << std::endl; -#endif - - std::list::iterator it; - //for(it = dsdv->routes.entries.begin(); it != dsdv->routes.entries.end(); ++it) - for(it = dsdv->routes.mList.begin(); it != dsdv->routes.mList.end(); ++it) - { - /* check for existing */ - RsTlvDsdvEntry &entry = *it; - uint32_t realDistance = entry.distance + 1; // metric. - - - /* find the entry */ - std::map::iterator tit; - tit = mTable.find(entry.endPoint.serviceId); - if (tit == mTable.end()) - { -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::handleDSDV() Adding Entry for New ServiceId: "; - std::cerr << entry.endPoint.serviceId; - std::cerr << std::endl; -#endif - /* new entry! */ - RsDsdvTableEntry v; - v.mDest.mIdType = entry.endPoint.idType; - v.mDest.mAnonChunk = entry.endPoint.anonChunk; - v.mDest.mHash = entry.endPoint.serviceId; - - /* add as a possible route */ - RsDsdvRoute newRoute; - - newRoute.mNextHop = dsdv->PeerId(); - newRoute.mReceived = now; - newRoute.mSequence = entry.sequence; - newRoute.mDistance = realDistance; - newRoute.mValidSince = now; - - v.mAllRoutes[dsdv->PeerId()] = newRoute; - v.mIsStable = false; - - v.mFlags = RSDSDV_FLAGS_NEW_ROUTE; - v.mOwnSource = false; - v.mMatched = false; - - // store in table. - mTable[v.mDest.mHash] = v; - } - else - { - RsDsdvTableEntry &v = tit->second; - if (v.mOwnSource) - { -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::handleDSDV() Ignoring OwnSource Entry:"; - std::cerr << entry.endPoint.serviceId; - std::cerr << std::endl; -#endif - continue; // Ignore if we are source. - } - - /* look for this in mAllRoutes */ - std::map::iterator rit; - rit = v.mAllRoutes.find(dsdv->PeerId()); - if (rit == v.mAllRoutes.end()) - { - /* add a new entry in */ - RsDsdvRoute newRoute; - - newRoute.mNextHop = dsdv->PeerId(); - newRoute.mReceived = now; - newRoute.mSequence = entry.sequence; - newRoute.mDistance = realDistance; - newRoute.mValidSince = now; - - v.mAllRoutes[dsdv->PeerId()] = newRoute; - - /* if we've just added it in - can't be stable one */ -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::handleDSDV() Adding NewRoute Entry:"; - std::cerr << entry.endPoint.serviceId; - std::cerr << std::endl; -#endif - } - else - { - if (rit->second.mSequence >= entry.sequence) - { -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::handleDSDV() Ignoring OLDSEQ Entry:"; - std::cerr << entry.endPoint.serviceId; - std::cerr << std::endl; -#endif - /* ignore same/old sequence number??? */ - continue; - } -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::handleDSDV() Updating Entry:"; - std::cerr << entry.endPoint.serviceId; - std::cerr << std::endl; -#endif - - /* update seq,dist,etc */ - if (rit->second.mSequence + 2 < entry.sequence) - { - /* skipped a sequence number - reset timer */ - rit->second.mValidSince = now; - } - - //rit->second.mNextHop; // unchanged. - rit->second.mReceived = now; - rit->second.mSequence = entry.sequence; - rit->second.mDistance = realDistance; - - /* if consistent route... maintain */ - if ((v.mIsStable) && - (rit->second.mNextHop == v.mStableRoute.mNextHop)) - { - v.mStableRoute = rit->second; - } - else - { - /* otherwise we need to wait - see if we get new update */ - } - } - } - } - return 1; -} - - -int p3Dsdv::selectStableRoutes() -{ - /* iterate over the entries */ - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - - rstime_t now = time(NULL); - -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::selectStableRoutes()"; - std::cerr << std::endl; -#endif - - /* find the entry */ - std::map::iterator tit; - for(tit = mTable.begin(); tit != mTable.end(); ++tit) - { - -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::selectStableRoutes() For Entry: "; - std::cerr << tit->second; - std::cerr << std::endl; -#endif - if (tit->second.mOwnSource) - { -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::selectStableRoutes() OwnSource... Ignoring"; - std::cerr << std::endl; -#endif - continue; // Ignore if we are source. - } - - std::map::iterator rit; - uint32_t newest = 0; - RsPeerId newestId; - uint32_t closest = RSDSDV_MAX_DISTANCE + 1; - RsPeerId closestId; - rstime_t closestAge = 0; - - /* find newest sequence number */ - for(rit = tit->second.mAllRoutes.begin(); - rit != tit->second.mAllRoutes.end(); ++rit) - { - if ((now - rit->second.mReceived <= DSDV_DISCARD_PERIOD) && - (rit->second.mSequence >= newest)) - { - newest = rit->second.mSequence; - newestId = rit->first; - - /* also becomes default for closest (later) */ - closest = rit->second.mDistance; - closestId = rit->first; - closestAge = now - rit->second.mValidSince; - } - } - - if (closest >= RSDSDV_MAX_DISTANCE + 1) - { -#ifdef DEBUG_DSDV - std::cerr << "\tNo Suitable Route"; - std::cerr << std::endl; -#endif - tit->second.mIsStable = false; - continue; - } - - uint32_t currseq = newest - (newest % 2); // remove 'kill'=ODD Seq. - -#ifdef DEBUG_DSDV - std::cerr << "\t Newest Seq: " << newest << " from: " << newestId; - std::cerr << std::endl; -#endif - - /* find closest distance - with valid seq & max valid time */ - for(rit = tit->second.mAllRoutes.begin(); - rit != tit->second.mAllRoutes.end(); ++rit) - { - /* Maximum difference in Sequence number is 2*DISTANCE - * Otherwise it must be old. - */ - if (rit->second.mSequence + rit->second.mDistance * 2 < currseq) - { -#ifdef DEBUG_DSDV - std::cerr << "\t\tIgnoring OLD SEQ Entry: " << rit->first; - std::cerr << std::endl; -#endif - - continue; // ignore. - } - - /* if we haven't received an update in ages - old */ - if (now - rit->second.mReceived > DSDV_DISCARD_PERIOD) - { -#ifdef DEBUG_DSDV - std::cerr << "\t\tIgnoring OLD TIME Entry: " << rit->first; - std::cerr << std::endl; -#endif - - continue; // ignore. - } - - if (rit->second.mDistance < closest) - { - closest = rit->second.mDistance; - closestId = rit->first; - closestAge = now - rit->second.mValidSince; -#ifdef DEBUG_DSDV - std::cerr << "\t\tUpdating to Closer Entry: " << rit->first; - std::cerr << std::endl; -#endif - } - else if ((rit->second.mDistance == closest) && - (closestAge < now - rit->second.mValidSince)) - { - /* have a more stable (older) one */ - closest = rit->second.mDistance; - closestId = rit->first; - closestAge = now - rit->second.mValidSince; -#ifdef DEBUG_DSDV - std::cerr << "\t\tUpdating to Stabler Entry: " << rit->first; - std::cerr << std::endl; -#endif - } - else - { -#ifdef DEBUG_DSDV - std::cerr << "\t\tIgnoring Distant Entry: " << rit->first; - std::cerr << std::endl; -#endif - } - - } - - tit->second.mIsStable = true; - rit = tit->second.mAllRoutes.find(closestId); - tit->second.mStableRoute = rit->second; - tit->second.mFlags &= ~RSDSDV_FLAGS_NEW_ROUTE; - -#ifdef DEBUG_DSDV - std::cerr << "\tStable Route: " << tit->second.mStableRoute; - std::cerr << std::endl; -#endif - } - return 1; -} - - - - -int p3Dsdv::clearOldRoutes() -{ - /* iterate over the entries */ - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::clearOldRoutes()"; - std::cerr << std::endl; -#endif - - /* find the entry */ - std::map::iterator it, it2; - for(it = mTable.begin(); it != mTable.end(); ++it) - { - if (it->second.mOwnSource) - { - continue; - } - - if (it->second.mIsStable) - { - continue; - } - - if (it->second.mFlags & RSDSDV_FLAGS_NEW_ROUTE) - { - continue; - } - - /* backstep iterator for loop, and delete original */ - it2 = it; - it--; - -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::clearOldRoutes() Deleting OLD ServiceId: " << it2->first; - std::cerr << std::endl; -#endif - mTable.erase(it2); - } - return 1; -} - - -/*************** pqiMonitor callback ***********************/ -void p3Dsdv::statusChange(const std::list &plist) -{ - std::list::const_iterator it; - for(it = plist.begin(); it != plist.end(); ++it) - { - /* only care about disconnected / not friends cases */ - if ( 1 ) - { - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - - - - - - } - } -} - -int p3Dsdv::addTestService() -{ - RsDsdvId testId; - - int rndhash1[SHA_DIGEST_LENGTH / 4]; - int rndhash2[SHA_DIGEST_LENGTH / 4]; - std::string realHash; - std::string seedHash; - - for(int i = 0; i < SHA_DIGEST_LENGTH / 4; i++) - { - rndhash1[i] = RSRandom::random_u32(); - rndhash2[i] = RSRandom::random_u32(); - } - - for(int i = 0; i < SHA_DIGEST_LENGTH; i++) - { - rs_sprintf_append(realHash, "%02x", (uint32_t) ((uint8_t *) rndhash1)[i]); - rs_sprintf_append(seedHash, "%02x", (uint32_t) ((uint8_t *) rndhash2)[i]); - } - - - uint8_t sha_hash[SHA_DIGEST_LENGTH]; - memset(sha_hash,0,SHA_DIGEST_LENGTH*sizeof(uint8_t)) ; - SHA_CTX *sha_ctx = new SHA_CTX; - SHA1_Init(sha_ctx); - - SHA1_Update(sha_ctx, realHash.c_str(), realHash.length()); - SHA1_Update(sha_ctx, seedHash.c_str(), seedHash.length()); - SHA1_Final(sha_hash, sha_ctx); - delete sha_ctx; - - for(int i = 0; i < SHA_DIGEST_LENGTH; i++) - { - rs_sprintf_append(testId.mHash, "%02x", (uint32_t) (sha_hash)[i]); - } - - testId.mIdType = RSDSDV_IDTYPE_TEST; - testId.mAnonChunk = seedHash; - - addDsdvId(&testId, realHash); - return 1; -} - - -int p3Dsdv::addDsdvId(RsDsdvId *id, std::string realHash) -{ - - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::addDsdvId() ID: " << *id << " RealHash: " << realHash; - std::cerr << std::endl; -#endif - - rstime_t now = time(NULL); - - /* check for duplicate */ - std::map::iterator it; - it = mTable.find(id->mHash); - if (it != mTable.end()) - { - /* error */ - std::cerr << "p3Dsdv::addDsdvId() ERROR Duplicate ID"; - std::cerr << std::endl; - - return 0; - } - - /* new entry! */ - RsDsdvTableEntry v; - v.mDest = *id; - - v.mStableRoute.mNextHop = mServiceCtrl->getOwnId(); - v.mStableRoute.mReceived = now; - v.mStableRoute.mValidSince = now; - v.mStableRoute.mSequence = 0; - v.mStableRoute.mDistance = 0; - v.mIsStable = true; - - v.mFlags = RSDSDV_FLAGS_OWN_SERVICE; - v.mOwnSource = true; - v.mMatched = true; - v.mMatchedHash = realHash; - - // store in table. - mTable[v.mDest.mHash] = v; - - return 1; -} - - - - -int p3Dsdv::dropDsdvId(RsDsdvId *id) -{ - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - -#ifdef DEBUG_DSDV - std::cerr << "p3Dsdv::dropDsdvId() ID: " << *id; - std::cerr << std::endl; -#endif - - /* This should send out an infinity packet... and flag for deletion */ - - std::map::iterator it; - it = mTable.find(id->mHash); - if (it == mTable.end()) - { - /* error */ - std::cerr << "p3Dsdv::addDsdvId() ERROR Unknown ID"; - std::cerr << std::endl; - - return 0; - } - - mTable.erase(it); - - return 1; -} - - -int p3Dsdv::printDsdvTable(std::ostream &out) -{ - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - - /* iterate over the entries */ - std::map::iterator it; - for(it = mTable.begin(); it != mTable.end(); ++it) - { - RsDsdvTableEntry &v = it->second; - out << v; - out << std::endl; - } - return 1; -} - -/*****************************************/ - -uint32_t p3Dsdv::getLocalServices(std::list &hashes) -{ - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - - /* iterate over the entries */ - std::map::iterator it; - for(it = mTable.begin(); it != mTable.end(); ++it) - { - if (it->second.mOwnSource) - { - hashes.push_back(it->first); - } - } - return 1; -} - - -uint32_t p3Dsdv::getAllServices(std::list &hashes) -{ - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - - /* iterate over the entries */ - std::map::iterator it; - for(it = mTable.begin(); it != mTable.end(); ++it) - { - hashes.push_back(it->first); - } - return 1; -} - - -int p3Dsdv::getDsdvEntry(const std::string &hash, RsDsdvTableEntry &entry) -{ - RsStackMutex stack(mDsdvMtx); /****** LOCKED MUTEX *******/ - - /* iterate over the entries */ - std::map::iterator it; - it = mTable.find(hash); - if (it == mTable.end()) - { - return 0; - } - - entry = it->second; - - return 1; -} - -std::ostream &operator<<(std::ostream &out, const RsDsdvId &id) -{ - out << "[Type: " << id.mIdType << " AMZ: " << id.mAnonChunk << " THASH: " << id.mHash; - out << "]"; - - return out; -} - - -std::ostream &operator<<(std::ostream &out, const RsDsdvRoute &route) -{ - rstime_t now = time(NULL); - out << "< Seq: " << route.mSequence << " Dist: " << route.mDistance; - out << " NextHop: " << route.mNextHop; - out << " recvd: " << now-route.mReceived; - out << " validSince: " << now-route.mValidSince; - out << " >"; - - return out; -} - -std::ostream &operator<<(std::ostream &out, const RsDsdvTableEntry &entry) -{ - out << "DSDV Route for: " << entry.mDest << std::endl; - if (entry.mIsStable) - { - out << "\tStable: " << entry.mStableRoute << std::endl; - } - else - { - out << "\tNo Stable Route" << std::endl; - } - - out << "\tOwnSource: " << entry.mOwnSource; - out << " Flags: " << entry.mFlags; - if (entry.mMatched) - { - out << " Matched: " << entry.mMatchedHash; - } - else - { - out << " Non Matched"; - } - out << std::endl; - if (entry.mAllRoutes.size() > 0) - { - out << "\tAll Routes:" << std::endl; - } - - std::map::const_iterator it; - for(it = entry.mAllRoutes.begin(); it != entry.mAllRoutes.end(); ++it) - { - out << "\t\t" << it->second << std::endl; - } - return out; -} - - diff --git a/libretroshare/src/unused/p3dsdv.h b/libretroshare/src/unused/p3dsdv.h deleted file mode 100644 index 049ed8695..000000000 --- a/libretroshare/src/unused/p3dsdv.h +++ /dev/null @@ -1,118 +0,0 @@ -/******************************************************************************* - * libretroshare/src/unused: p3dsdv.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef SERVICE_RSDSDV_HEADER -#define SERVICE_RSDSDV_HEADER - -#include -#include - -#include "serialiser/rsdsdvitems.h" -#include "services/p3service.h" -#include "pqi/p3cfgmgr.h" -#include "pqi/pqimonitor.h" - -#include "retroshare/rsdsdv.h" - -class p3ServiceControl; - - -#define RSDSDV_MAX_DISTANCE 3 -#define RSDSDV_MAX_SEND_TABLE 100 - -//!The RS DSDV service. - /** - * - * Finds RS wide paths to Services and Peers. - */ - -class p3Dsdv: public RsDsdv, public p3Service /* , public p3Config */, public pqiServiceMonitor -{ - public: - p3Dsdv(p3ServiceControl *cm); -virtual RsServiceInfo getServiceInfo(); - - /*** internal librs interface ****/ - -int addDsdvId(RsDsdvId *id, std::string realHash); -int dropDsdvId(RsDsdvId *id); -int printDsdvTable(std::ostream &out); - -int addTestService(); - - private: - -int sendTables(); -void advanceLocalSequenceNumbers(); -void clearSignificantChangesFlags(); - - -int generateRoutingTables(bool incremental); -int generateRoutingTable(const RsPeerId &peerId, bool incremental); - -int processIncoming(); - -int handleDSDV(RsDsdvRouteItem *dsdv); - -int selectStableRoutes(); -int clearOldRoutes(); - - public: - - /***** overloaded from rsDsdv *****/ - -virtual uint32_t getLocalServices(std::list &hashes); -virtual uint32_t getAllServices(std::list &hashes); -virtual int getDsdvEntry(const std::string &hash, RsDsdvTableEntry &entry); - - /***** overloaded from p3Service *****/ - /*! - * Process stuff. - */ - - virtual int tick(); - virtual int status(); - - /*************** pqiMonitor callback ***********************/ - virtual void statusChange(const std::list &plist); - - /************* from p3Config *******************/ - //virtual RsSerialiser *setupSerialiser() ; - //virtual bool saveList(bool& cleanup, std::list&) ; - //virtual void saveDone(); - //virtual bool loadList(std::list& load) ; - - private: - RsMutex mDsdvMtx; - - std::map mTable; - - rstime_t mSentTablesTime; - rstime_t mSentIncrementTime; - - bool mSignificantChanges; - - p3ServiceControl *mServiceCtrl; - -}; - -#endif // SERVICE_RSDSDV_HEADER - diff --git a/libretroshare/src/unused/pqiarchive.cc b/libretroshare/src/unused/pqiarchive.cc deleted file mode 100644 index df7c57f02..000000000 --- a/libretroshare/src/unused/pqiarchive.cc +++ /dev/null @@ -1,419 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiarchive.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -/* This is dependent on the sslroot at the moment. - * -> as we need to create/restore references to the Person. - * -> and store the signatures to do this. - */ - -/******************************************************************* - * pqiarchive provides an archive stream. - * This stores RsItem + Person Reference + Timestamp, - * - * and allows Objects to be replayed or restored, - * independently of the rest of the pqi system. - * - */ - -#ifdef SUSPENDED_UNUSED_CODE - -#include "pqi/pqiarchive.h" -#include "serialiser/rsserial.h" -#include -#include - -#include "util/rsdebug.h" -#include "util/rsstring.h" -#include "util/rstime.h" - -const int pqiarchivezone = 9326; - -struct pqiarchive_header -{ - uint32_t type; - uint32_t length; - uint32_t ts; - uint8_t personSig[PQI_PEERID_LENGTH]; -}; - -const int PQIARCHIVE_TYPE_PQITEM = 0x0001; - -/* PeerId of PQInterface is not important ... as we are archiving - * packets from other people... - */ - -pqiarchive::pqiarchive(RsSerialiser *rss, BinInterface *bio_in, int bio_flags_in) - :PQInterface(""), rsSerialiser(rss), bio(bio_in), bio_flags(bio_flags_in), - nextPkt(NULL), nextPktTS(0), firstPktTS(0), initTS(0),realTime(false) -{ - pqioutput(PQL_DEBUG_ALL, pqiarchivezone, "pqiarchive::pqiarchive() Initialisation!\n"); - - if (!bio_in) - { - pqioutput(PQL_ALERT, pqiarchivezone, "pqiarchive::pqiarchive() NULL bio, FATAL ERROR!\n"); - exit(1); - } - - return; -} - -pqiarchive::~pqiarchive() -{ - pqioutput(PQL_DEBUG_ALL, pqiarchivezone, "pqiarchive::~pqiarchive() Destruction!\n"); - - if (bio_flags & BIN_FLAGS_NO_CLOSE) - { - pqioutput(PQL_DEBUG_ALL, pqiarchivezone, "pqiarchive::~pqiarchive() Not Closing BinInterface!\n"); - } - else if (bio) - { - pqioutput(PQL_DEBUG_ALL, pqiarchivezone, "pqiarchive::~pqiarchive() Deleting BinInterface!\n"); - - delete bio; - } - - if (rsSerialiser) - delete rsSerialiser; - - if (nextPkt) - { - delete nextPkt; - } - return; -} - - -// Get/Send Items. -int pqiarchive::SendItem(RsItem *si) -{ - { - std::string out = "pqiarchive::SendItem()\n"; - si -> print_string(out); - pqioutput(PQL_DEBUG_BASIC, pqiarchivezone, out); - } - - // check if this is a writing bio. - - if (!(bio_flags & BIN_FLAGS_WRITEABLE)) - { - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete si; - return -1; - } - -// std::cerr << "SendItem: si->PeerId()=" << si->PeerId() << std::endl ; - - int ret = writePkt(si); - return ret; /* 0 - failure, 1 - success*/ -} - -RsItem *pqiarchive::GetItem() -{ - pqioutput(PQL_DEBUG_ALL, pqiarchivezone, "pqiarchive::GetItem()"); - - // check if this is a reading bio. - if (!(bio_flags & BIN_FLAGS_READABLE)) - { - pqioutput(PQL_DEBUG_BASIC, pqiarchivezone, "pqiarchive::GetItem() Error Not Readable"); - return NULL; - } - - // load if we dont have a packet. - if (!nextPkt) - { - if (!readPkt(&nextPkt, &nextPktTS)) - { - pqioutput(PQL_DEBUG_BASIC, pqiarchivezone, "pqiarchive::GetItem() Failed to ReadPkt"); - return NULL; - } - } - - if (!nextPkt) return NULL; - - - /* if realtime - check delta */ - bool rtnPkt = true; - if ((realTime) && (initTS)) - { - int delta = time(NULL) - initTS; - int delta2 = nextPktTS - firstPktTS; - if (delta >= delta2) - { - rtnPkt = true; - } - else - { - rtnPkt = false; - } - } - - if (rtnPkt) - { - if (!initTS) - { - /* first read! */ - initTS = time(NULL); - firstPktTS = nextPktTS; - } - RsItem *outPkt = nextPkt; - nextPkt = NULL; - - if (outPkt != NULL) - { - std::string out = "pqiarchive::GetItem() Returning:\n"; - outPkt -> print_string(out); - pqioutput(PQL_DEBUG_BASIC, pqiarchivezone, out); - } - return outPkt; - } - return NULL; -} - -// // PQInterface -int pqiarchive::tick() -{ - return 0; -} - -int pqiarchive::status() -{ - pqioutput(PQL_DEBUG_ALL, pqiarchivezone, "pqiarchive::status()"); - return 0; -} - -// -/**************** HANDLE OUTGOING TRANSLATION + TRANSMISSION ******/ - -int pqiarchive::writePkt(RsItem *pqi) -{ -// std::cerr << "writePkt, pqi->peerId()=" << pqi->PeerId() << std::endl ; - pqioutput(PQL_DEBUG_ALL, pqiarchivezone, "pqiarchive::writePkt()"); - - uint32_t pktsize = rsSerialiser->size(pqi); - void *ptr = malloc(pktsize); - if (!(rsSerialiser->serialise(pqi, ptr, &pktsize))) - { - std::string out = "pqiarchive::writePkt() Null Pkt generated!\nCaused By:\n"; - pqi -> print_string(out); - pqioutput(PQL_ALERT, pqiarchivezone, out); - - free(ptr); - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete pqi; - return 0; - } - - /* extract the extra details */ - uint32_t len = getRsItemSize(ptr); - if (len != pktsize) - { - std::string out; - rs_sprintf(out, "pqiarchive::writePkt() Length MisMatch: len: %lu != pktsize: %lu\nCaused By:\n", len, pktsize); - pqi -> print_string(out); - pqioutput(PQL_ALERT, pqiarchivezone, out); - - free(ptr); - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete pqi; - return 0; - } - - - if (!(bio->cansend(0))) - { - std::string out = "pqiarchive::writePkt() BIO cannot write!\nDiscarding:\n"; - pqi -> print_string(out); - pqioutput(PQL_ALERT, pqiarchivezone, out); - - free(ptr); - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete pqi; - - return 0; - } - - // using the peerid from the item. - if (pqi->PeerId().length() != PQI_PEERID_LENGTH) - { - std::string out = "pqiarchive::writePkt() Invalid peerId Length!\n"; - rs_sprintf_append(out, "Found %ld instead of %ld\n", pqi->PeerId().length(), PQI_PEERID_LENGTH); - out += "pqi->PeerId() = " + pqi->PeerId() + "\nCaused By:\n"; - pqi -> print_string(out); - pqioutput(PQL_ALERT, pqiarchivezone, out); - - free(ptr); - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete pqi; - return 0; - } - - std::string out = "Writing Pkt Header\n"; - struct pqiarchive_header hdr; - hdr.type = PQIARCHIVE_TYPE_PQITEM; - hdr.length = len; - hdr.ts = time(NULL); - memcpy(hdr.personSig, pqi->PeerId().c_str(), PQI_PEERID_LENGTH); - - // write packet header. - if (sizeof(hdr) != bio->senddata(&hdr, sizeof(hdr))) - { - out += "Trouble writing header!\n"; - pqioutput(PQL_ALERT, pqiarchivezone, out); - - free(ptr); - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete pqi; - - return 0; - } - - out += "Writing Pkt Body\n"; - - // write packet. - if ((int) len != bio->senddata(ptr, len)) - { - out += "Problems with Send Data!\n"; - pqioutput(PQL_ALERT, pqiarchivezone, out); - - free(ptr); - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete pqi; - - return 0; - } - - out += " Success!"; - pqioutput(PQL_DEBUG_BASIC, pqiarchivezone, out); - - free(ptr); - if (!(bio_flags & BIN_FLAGS_NO_DELETE)) - delete pqi; - - return 1; -} - -/* Reads a single packet from the input stream - * gets the timestamp as well. - * - */ - -int pqiarchive::readPkt(RsItem **item_out, long *ts_out) -{ - pqioutput(PQL_DEBUG_ALL, pqiarchivezone, "pqiarchive::readPkt()"); - - if ((!(bio->isactive())) || (!(bio->moretoread(0)))) - { - return 0; - } - - // header - struct pqiarchive_header hdr; - - // enough space to read any packet. - int maxlen = getRsPktMaxSize(); - void *block = malloc(maxlen); - - // initial read size: basic packet. - int blen = getRsPktBaseSize(); - - int tmplen; - - /* read in the header */ - if (sizeof(hdr) != bio->readdata(&hdr, sizeof(hdr))) - { - /* error */ - pqioutput(PQL_WARNING, pqiarchivezone, - "pqiarchive::readPkt() bad read(1)"); - - free(block); - return 0; - } - - /* we have the header */ - - // read the basic block (minimum packet size) - if (blen != (tmplen = bio->readdata(block, blen))) - { - pqioutput(PQL_WARNING, pqiarchivezone, - "pqiarchive::readPkt() bad read(2)"); - - free(block); - return 0; - } - - // workout how much more to read. - int extralen = getRsItemSize(block) - blen; - if (extralen > 0) - { - void *extradata = (void *) (((char *) block) + blen); - if (extralen != (tmplen = bio->readdata(extradata, extralen))) - { - - std::string out; - rs_sprintf(out, "pqiarchive::readPkt() Error Completing Read (read %d/%d)\n", tmplen, extralen); - pqioutput(PQL_ALERT, pqiarchivezone, out); - - free(block); - return 0; - } - } - - // create packet, based on header. - //std::cerr << "Read Data Block -> Incoming Pkt("; - //std::cerr << blen + extralen << ")" << std::endl; - uint32_t readbytes = extralen + blen; - - RsItem *item = rsSerialiser->deserialise(block, &readbytes); - free(block); - - if (item == NULL) - { - pqioutput(PQL_ALERT, pqiarchivezone, - "pqiarchive::readPkt() Failed to create Item from archive!"); - return 0; - } - - /* Cannot detect bad ids here anymore.... - * but removed dependancy on the sslroot! - */ - - std::string peerId = ""; - for(int i = 0; i < PQI_PEERID_LENGTH; i++) - { - peerId += hdr.personSig[i]; - } - item->PeerId(peerId); - - *item_out = item; - *ts_out = hdr.ts; - - return 1; -} - -/**** Hashing Functions ****/ -std::string pqiarchive::gethash() -{ - return bio->gethash(); -} -#endif - - diff --git a/libretroshare/src/unused/pqiarchive.h b/libretroshare/src/unused/pqiarchive.h deleted file mode 100644 index 4c2a82a96..000000000 --- a/libretroshare/src/unused/pqiarchive.h +++ /dev/null @@ -1,78 +0,0 @@ -/******************************************************************************* - * libretroshare/src/pqi: pqiarchive.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifdef SUSPENDED_UNUSED_CODE - -#ifndef MRK_PQI_ARCHIVE_STREAMER_HEADER -#define MRK_PQI_ARCHIVE_STREAMER_HEADER - -#include "pqi/pqi.h" - -#include - -/******************************************************************* - * pqiarchive provides an archive stream. - * This stores RsItem + Person Reference + Timestamp, - * - * and allows Objects to be replayed or restored, - * independently of the rest of the pqi system. - * - */ - -class pqiarchive: public PQInterface -{ -public: - pqiarchive(RsSerialiser *rss, BinInterface *bio_in, int bio_flagsin); -virtual ~pqiarchive(); - -// PQInterface -virtual int SendItem(RsItem *); -virtual RsItem *GetItem(); - -virtual int tick(); -virtual int status(); - -virtual void setRealTime(bool r) { realTime = r; } - -std::string gethash(); - - private: -int writePkt(RsItem *item); -int readPkt(RsItem **item_out, long *ts); - - // Serialiser - RsSerialiser *rsSerialiser; - // Binary Interface for IO, initialisated at startup. - BinInterface *bio; - unsigned int bio_flags; // only BIN_NO_CLOSE at the moment. - - // Temp Storage for transient data..... - RsItem *nextPkt; - long nextPktTS; /* timestamp associated with nextPkt */ - long firstPktTS; /* timestamp associated with first read Pkt */ - long initTS; /* clock timestamp at first read */ - - bool realTime; -}; - - -#endif //MRK_PQI_ARCHIVE_STREAMER_HEADER -#endif //SUSPENDED_UNUSED_CODE diff --git a/libretroshare/src/unused/rscompress.cc b/libretroshare/src/unused/rscompress.cc deleted file mode 100644 index e3aa0f849..000000000 --- a/libretroshare/src/unused/rscompress.cc +++ /dev/null @@ -1,196 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rscompress.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include -#include -#include -#include -#include -#include "rscompress.h" -#include "zlib.h" -#include "util/rsmemory.h" - -// 16K buffer size. -// -static const unsigned int CHUNK = 16384u ; - -bool RsCompress::compress_memory_chunk(const uint8_t *input_mem,const uint32_t input_size,uint8_t *& output_mem,uint32_t& output_size) -{ - - uint32_t remaining_input = input_size ; - uint32_t output_offset = 0 ; - uint32_t input_offset = 0 ; - output_size = 1024 ; - output_mem = (uint8_t*)rs_malloc(output_size) ; - - if(!output_mem) - return false ; - - int ret, flush; - unsigned have; - int level = 9 ; - z_stream strm; - unsigned char in[CHUNK]; - unsigned char out[CHUNK]; - /* allocate deflate state */ - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - - ret = deflateInit(&strm, level); - if (ret != Z_OK) - return false; - - /* compress until end of file */ - do - { - uint32_t available_in = std::min(CHUNK,remaining_input) ; - memcpy(in,input_mem+input_offset,available_in) ; - strm.avail_in = available_in ; - remaining_input -= available_in ; - input_offset += available_in ; - - flush = /*feof(source)*/ remaining_input ? Z_NO_FLUSH: Z_FINISH ; - strm.next_in = in; - - /* run deflate() on input until output buffer not full, finish - compression if all of source has been read in */ - do - { - strm.avail_out = CHUNK; - strm.next_out = out; - ret = deflate(&strm, flush); /* no bad return value */ - assert(ret != Z_STREAM_ERROR); /* state not clobbered */ - have = CHUNK - strm.avail_out; - - if(output_size < have+output_offset) - { - //std::cerr << "Growing outputbuffer from " << output_size << " to " << have+output_offset << std::endl; - output_mem = (uint8_t*)realloc(output_mem,have+output_offset) ; - output_size = have+output_offset ; - } - - memcpy(output_mem+output_offset,out,have) ; - output_offset += have ; - - //std::cerr << "Copying " << have << " bytes to output. New offset=" << output_offset << std::endl; - } while (strm.avail_out == 0); - assert(strm.avail_in == 0); /* all input will be used */ - - /* done when last data in file processed */ - } while (flush != Z_FINISH); - assert(ret == Z_STREAM_END); /* stream will be complete */ - - /* clean up and return */ - (void)deflateEnd(&strm); - - output_size = output_offset ; - - return true ; -} - -bool RsCompress::uncompress_memory_chunk(const uint8_t *input_mem,const uint32_t input_size,uint8_t *& output_mem,uint32_t& output_size) -{ - uint32_t remaining_input = input_size ; - output_size = input_size ; - uint32_t output_offset = 0 ; - uint32_t input_offset = 0 ; - output_mem = (uint8_t*)rs_malloc(output_size) ; - - if(!output_mem) - return false ; - - int ret; - unsigned have; - z_stream strm; - unsigned char in[CHUNK]; - unsigned char out[CHUNK]; - - /* allocate inflate state */ - memset(&strm,0,sizeof(strm)) ; - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.next_in = Z_NULL; - strm.next_out = Z_NULL; - - ret = inflateInit(&strm); - if (ret != Z_OK) - return ret; - - /* decompress until deflate stream ends or end of file */ - do - { - uint32_t available_in = std::min(CHUNK,remaining_input) ; - memcpy(in,input_mem+input_offset,available_in) ; - strm.avail_in = available_in ; - remaining_input -= available_in ; - input_offset += available_in ; - - if (strm.avail_in == 0) - break; - - strm.next_in = in; - /* run inflate() on input until output buffer not full */ - do { - strm.avail_out = CHUNK; - strm.next_out = out; - - ret = inflate(&strm, Z_NO_FLUSH); - assert(ret != Z_STREAM_ERROR); /* state not clobbered */ - switch (ret) { - case Z_NEED_DICT: - ret = Z_DATA_ERROR; /* and fall through */ - /* fallthrough */ - case Z_DATA_ERROR: - case Z_MEM_ERROR: - (void)inflateEnd(&strm); - return ret; - } - - - have = CHUNK - strm.avail_out; - - if(output_size < have+output_offset) - { - output_mem = (uint8_t*)realloc(output_mem,have+output_offset) ; - output_size = have+output_offset ; - } - - memcpy(output_mem+output_offset,out,have) ; - output_offset += have ; - - } while (strm.avail_out == 0); - /* done when inflate() says it's done */ - } while (ret != Z_STREAM_END); - - /* clean up and return */ - (void)inflateEnd(&strm); - - output_size = output_offset ; - return ret == Z_STREAM_END ; -} - - - - - - diff --git a/libretroshare/src/unused/rscompress.h b/libretroshare/src/unused/rscompress.h deleted file mode 100644 index 96b9e2092..000000000 --- a/libretroshare/src/unused/rscompress.h +++ /dev/null @@ -1,30 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rscompress.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -class RsCompress -{ - public: - static bool compress_memory_chunk(const uint8_t *input_mem,const uint32_t input_size,uint8_t *& output_mem,uint32_t& output_size) ; - static bool uncompress_memory_chunk(const uint8_t *input_mem,const uint32_t input_size,uint8_t *& output_mem,uint32_t& output_size) ; -}; - diff --git a/libretroshare/src/unused/rsdsdv.h b/libretroshare/src/unused/rsdsdv.h deleted file mode 100644 index 308a1c779..000000000 --- a/libretroshare/src/unused/rsdsdv.h +++ /dev/null @@ -1,103 +0,0 @@ -/******************************************************************************* - * libretroshare/src/unused: rsdsdv.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RETROSHARE_DSDV_INTERFACE_H -#define RETROSHARE_DSDV_INTERFACE_H - -#include -#include -#include - -/* The Main Interface Class - for information about your Peers */ -class RsDsdv; -extern RsDsdv *rsDsdv; - - -#define RSDSDV_IDTYPE_PEER 0x0001 -#define RSDSDV_IDTYPE_SERVICE 0x0002 -#define RSDSDV_IDTYPE_TEST 0x0100 - -#define RSDSDV_FLAGS_SIGNIFICANT_CHANGE 0x0001 -#define RSDSDV_FLAGS_STABLE_ROUTE 0x0002 -#define RSDSDV_FLAGS_NEW_ROUTE 0x0004 -#define RSDSDV_FLAGS_OWN_SERVICE 0x0008 - - -class RsDsdvId -{ - public: - - uint32_t mIdType; - std::string mAnonChunk; - std::string mHash; -}; - -class RsDsdvRoute -{ - public: - - RsPeerId mNextHop; - uint32_t mSequence; - uint32_t mDistance; - rstime_t mReceived; - rstime_t mValidSince; - -}; - -class RsDsdvTableEntry -{ - public: - - RsDsdvId mDest; - bool mIsStable; - RsDsdvRoute mStableRoute; - //RsDsdvRoute mFreshestRoute; - - std::map mAllRoutes; - - uint32_t mFlags; - - /* if we've matched it to someone */ - std::string mMatchedHash; - bool mMatched; - bool mOwnSource; -}; - -std::ostream &operator<<(std::ostream &out, const RsDsdvId &id); -std::ostream &operator<<(std::ostream &out, const RsDsdvRoute &route); -std::ostream &operator<<(std::ostream &out, const RsDsdvTableEntry &entry); - - -class RsDsdv -{ - public: - - RsDsdv() { return; } -virtual ~RsDsdv() { return; } - -virtual uint32_t getLocalServices(std::list &hashes) = 0; -virtual uint32_t getAllServices(std::list &hashes) = 0; -virtual int getDsdvEntry(const std::string &hash, RsDsdvTableEntry &entry) = 0; - -}; - -#endif - diff --git a/libretroshare/src/unused/rsdsdvitems.cc b/libretroshare/src/unused/rsdsdvitems.cc deleted file mode 100644 index 073ebe669..000000000 --- a/libretroshare/src/unused/rsdsdvitems.cc +++ /dev/null @@ -1,349 +0,0 @@ -/******************************************************************************* - * libretroshare/src/unused: rsdsdvitems.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "serialiser/rsbaseserial.h" -#include "serialiser/rsdsdvitems.h" -#include "serialiser/rstlvdsdv.h" - -/*** -#define RSSERIAL_DEBUG 1 -***/ - -#include - -/*************************************************************************/ - -RsDsdvRouteItem::~RsDsdvRouteItem() -{ - return; -} - -void RsDsdvRouteItem::clear() -{ - routes.TlvClear(); -} - -std::ostream &RsDsdvRouteItem::print(std::ostream &out, uint16_t indent) -{ - printRsItemBase(out, "RsDsdvRouteItem", indent); - uint16_t int_Indent = indent + 2; - routes.print(out, int_Indent); - - printRsItemEnd(out, "RsDsdvRouteItem", indent); - return out; -} - - -uint32_t RsDsdvSerialiser::sizeRoute(RsDsdvRouteItem *item) -{ - uint32_t s = 8; /* header */ - s += item->routes.TlvSize(); - - return s; -} - -/* serialise the data to the buffer */ -bool RsDsdvSerialiser::serialiseRoute(RsDsdvRouteItem *item, void *data, uint32_t *pktsize) -{ - uint32_t tlvsize = sizeRoute(item); - uint32_t offset = 0; - - if (*pktsize < tlvsize) - return false; /* not enough space */ - - *pktsize = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - -#ifdef RSSERIAL_DEBUG - std::cerr << "RsDsdvSerialiser::serialiseRoute() Header: " << ok << std::endl; - std::cerr << "RsDsdvSerialiser::serialiseRoute() Size: " << tlvsize << std::endl; -#endif - - /* skip the header */ - offset += 8; - - /* add mandatory parts first */ - ok &= item->routes.SetTlv(data, tlvsize, &offset); - - if (offset != tlvsize) - { - ok = false; -#ifdef RSSERIAL_DEBUG - std::cerr << "RsDsdvSerialiser::serialiseRoute() Size Error! " << std::endl; -#endif - } - - return ok; -} - -RsDsdvRouteItem *RsDsdvSerialiser::deserialiseRoute(void *data, uint32_t *pktsize) -{ - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t tlvsize = getRsItemSize(data); - - uint32_t offset = 0; - - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (RS_SERVICE_TYPE_DSDV != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_DSDV_ROUTE != getRsItemSubType(rstype))) - { - return NULL; /* wrong type */ - } - - if (*pktsize < tlvsize) /* check size */ - return NULL; /* not enough data */ - - /* set the packet length */ - *pktsize = tlvsize; - - bool ok = true; - - /* ready to load */ - RsDsdvRouteItem *item = new RsDsdvRouteItem(); - item->clear(); - - /* skip the header */ - offset += 8; - - /* add mandatory parts first */ - ok &= item->routes.GetTlv(data, tlvsize, &offset); - - if (offset != tlvsize) - { - /* error */ - delete item; - return NULL; - } - - if (!ok) - { - delete item; - return NULL; - } - - return item; -} - -/*************************************************************************/ - -RsDsdvDataItem::~RsDsdvDataItem() -{ - return; -} - -void RsDsdvDataItem::clear() -{ - src.TlvClear(); - dest.TlvClear(); - ttl = 0; - data.TlvClear(); -} - -std::ostream &RsDsdvDataItem::print(std::ostream &out, uint16_t indent) -{ - printRsItemBase(out, "RsDsdvDataItem", indent); - uint16_t int_Indent = indent + 2; - src.print(out, int_Indent); - dest.print(out, int_Indent); - - printIndent(out, int_Indent); - out << "TTL: " << ttl << std::endl; - - data.print(out, int_Indent); - - printRsItemEnd(out, "RsDsdvDataItem", indent); - return out; -} - - -uint32_t RsDsdvSerialiser::sizeData(RsDsdvDataItem *item) -{ - uint32_t s = 8; /* header */ - s += item->src.TlvSize(); - s += item->dest.TlvSize(); - s += 4; - s += item->data.TlvSize(); - - return s; -} - -/* serialise the data to the buffer */ -bool RsDsdvSerialiser::serialiseData(RsDsdvDataItem *item, void *data, uint32_t *pktsize) -{ - uint32_t tlvsize = sizeData(item); - uint32_t offset = 0; - - if (*pktsize < tlvsize) - return false; /* not enough space */ - - *pktsize = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); - -#ifdef RSSERIAL_DEBUG - std::cerr << "RsDsdvSerialiser::serialiseData() Header: " << ok << std::endl; - std::cerr << "RsDsdvSerialiser::serialiseData() Size: " << tlvsize << std::endl; -#endif - - /* skip the header */ - offset += 8; - - /* add mandatory parts first */ - ok &= item->src.SetTlv(data, tlvsize, &offset); - ok &= item->dest.SetTlv(data, tlvsize, &offset); - ok &= setRawUInt32(data, tlvsize, &offset, item->ttl); - ok &= item->data.SetTlv(data, tlvsize, &offset); - - if (offset != tlvsize) - { - ok = false; -#ifdef RSSERIAL_DEBUG - std::cerr << "RsDsdvSerialiser::serialiseData() Size Error! " << std::endl; -#endif - } - - return ok; -} - -RsDsdvDataItem *RsDsdvSerialiser::deserialiseData(void *data, uint32_t *pktsize) -{ - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - uint32_t tlvsize = getRsItemSize(data); - - uint32_t offset = 0; - - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (RS_SERVICE_TYPE_DSDV != getRsItemService(rstype)) || - (RS_PKT_SUBTYPE_DSDV_DATA != getRsItemSubType(rstype))) - { - return NULL; /* wrong type */ - } - - if (*pktsize < tlvsize) /* check size */ - return NULL; /* not enough data */ - - /* set the packet length */ - *pktsize = tlvsize; - - bool ok = true; - - /* ready to load */ - RsDsdvDataItem *item = new RsDsdvDataItem(); - item->clear(); - - /* skip the header */ - offset += 8; - - /* add mandatory parts first */ - ok &= item->src.GetTlv(data, tlvsize, &offset); - ok &= item->dest.GetTlv(data, tlvsize, &offset); - ok &= getRawUInt32(data, tlvsize, &offset, &(item->ttl)); - ok &= item->data.GetTlv(data, tlvsize, &offset); - - if (offset != tlvsize) - { - /* error */ - delete item; - return NULL; - } - - if (!ok) - { - delete item; - return NULL; - } - - return item; -} - -/*************************************************************************/ - -uint32_t RsDsdvSerialiser::size(RsItem *i) -{ - RsDsdvRouteItem *dri; - RsDsdvDataItem *ddi; - - if (NULL != (dri = dynamic_cast(i))) - { - return sizeRoute(dri); - } - if (NULL != (ddi = dynamic_cast(i))) - { - return sizeData(ddi); - } - return 0; -} - -bool RsDsdvSerialiser::serialise(RsItem *i, void *data, uint32_t *pktsize) -{ - RsDsdvRouteItem *dri; - RsDsdvDataItem *ddi; - - if (NULL != (dri = dynamic_cast(i))) - { - return serialiseRoute(dri, data, pktsize); - } - if (NULL != (ddi = dynamic_cast(i))) - { - return serialiseData(ddi, data, pktsize); - } - return false; -} - -RsItem *RsDsdvSerialiser::deserialise(void *data, uint32_t *pktsize) -{ - /* get the type and size */ - uint32_t rstype = getRsItemId(data); - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || - (RS_SERVICE_TYPE_DSDV != getRsItemService(rstype))) - { - return NULL; /* wrong type */ - } - - switch(getRsItemSubType(rstype)) - { - case RS_PKT_SUBTYPE_DSDV_ROUTE: - return deserialiseRoute(data, pktsize); - break; - case RS_PKT_SUBTYPE_DSDV_DATA: - return deserialiseData(data, pktsize); - break; - default: - return NULL; - break; - } -} - -/*************************************************************************/ - - - diff --git a/libretroshare/src/unused/rsdsdvitems.h b/libretroshare/src/unused/rsdsdvitems.h deleted file mode 100644 index 856a06b92..000000000 --- a/libretroshare/src/unused/rsdsdvitems.h +++ /dev/null @@ -1,105 +0,0 @@ -/******************************************************************************* - * libretroshare/src/unused: rsdsdvitems.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2011 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_DSDV_ITEMS_H -#define RS_DSDV_ITEMS_H - -#include - -#include "rsitems/rsserviceids.h" -#include "serialiser/rsserial.h" -#include "serialiser/rstlvbase.h" -#include "serialiser/rstlvbinary.h" -#include "serialiser/rstlvdsdv.h" - -/**************************************************************************/ - -#define RS_PKT_SUBTYPE_DSDV_ROUTE 0x01 -#define RS_PKT_SUBTYPE_DSDV_DATA 0x02 - -class RsDsdvRouteItem: public RsItem -{ - public: - RsDsdvRouteItem() - :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_DSDV, - RS_PKT_SUBTYPE_DSDV_ROUTE) - { - setPriorityLevel(QOS_PRIORITY_RS_DSDV_ROUTE); - return; - } -virtual ~RsDsdvRouteItem(); -virtual void clear(); -std::ostream &print(std::ostream &out, uint16_t indent = 0); - - RsTlvDsdvEntrySet routes; -}; - -class RsDsdvDataItem: public RsItem -{ - public: - RsDsdvDataItem() - :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_DSDV, - RS_PKT_SUBTYPE_DSDV_DATA), data(TLV_TYPE_BIN_GENERIC) - { - setPriorityLevel(QOS_PRIORITY_RS_DSDV_DATA); - return; - } -virtual ~RsDsdvDataItem(); -virtual void clear(); -std::ostream &print(std::ostream &out, uint16_t indent = 0); - - RsTlvDsdvEndPoint src; - RsTlvDsdvEndPoint dest; - uint32_t ttl; - RsTlvBinaryData data; -}; - -class RsDsdvSerialiser: public RsSerialType -{ - public: - RsDsdvSerialiser() - :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_DSDV) - { return; } -virtual ~RsDsdvSerialiser() - { return; } - -virtual uint32_t size(RsItem *); -virtual bool serialise (RsItem *item, void *data, uint32_t *size); -virtual RsItem * deserialise(void *data, uint32_t *size); - - private: - -virtual uint32_t sizeRoute(RsDsdvRouteItem *); -virtual bool serialiseRoute(RsDsdvRouteItem *item, void *data, uint32_t *size); -virtual RsDsdvRouteItem *deserialiseRoute(void *data, uint32_t *size); - -virtual uint32_t sizeData(RsDsdvDataItem *); -virtual bool serialiseData(RsDsdvDataItem *item, void *data, uint32_t *size); -virtual RsDsdvDataItem *deserialiseData(void *data, uint32_t *size); - - -}; - -/**************************************************************************/ - -#endif /* RS_DSDV_ITEMS_H */ - - diff --git a/libretroshare/src/use_libretroshare.pri b/libretroshare/src/use_libretroshare.pri deleted file mode 100644 index 7ceda74ba..000000000 --- a/libretroshare/src/use_libretroshare.pri +++ /dev/null @@ -1,120 +0,0 @@ -# SPDX-FileCopyrightText: (C) 2004-2019 Retroshare Team -# SPDX-License-Identifier: CC0-1.0 - -RS_SRC_PATH=$$clean_path($${PWD}/../../) -RS_BUILD_PATH=$$clean_path($${OUT_PWD}/../../) - -DEPENDPATH *= $$clean_path($${RS_SRC_PATH}/libretroshare/src/) -INCLUDEPATH *= $$clean_path($${RS_SRC_PATH}/libretroshare/src) - -equals(TARGET, retroshare):equals(TEMPLATE, lib){ -} else { - LIBS *= -L$$clean_path($${RS_BUILD_PATH}/libretroshare/src/lib/) -lretroshare - win32-g++|win32-clang-g++:!isEmpty(QMAKE_SH):libretroshare_shared { - # Windows msys2 - LIBRETROSHARE_TARGET=libretroshare.dll.a - } else { - LIBRETROSHARE_TARGET=libretroshare.a - } - PRE_TARGETDEPS *= $$clean_path($${RS_BUILD_PATH}/libretroshare/src/lib/$${LIBRETROSHARE_TARGET}) -} - -!include("../../openpgpsdk/src/use_openpgpsdk.pri"):error("Including") - -bitdht { - !include("../../libbitdht/src/use_libbitdht.pri"):error("Including") -} - -# when rapidjson is mainstream on all distribs, we will not need the sources -# anymore in the meantime, they are part of the RS directory so that it is -# always possible to find them -RAPIDJSON_AVAILABLE = $$system(pkg-config --atleast-version 1.1 RapidJSON && echo yes) -isEmpty(RAPIDJSON_AVAILABLE) { - message("using rapidjson from submodule") - INCLUDEPATH *= $$clean_path($${PWD}/../../supportlibs/rapidjson/include) -} else { - message("using system rapidjson") -} - - -sLibs = -mLibs = $$RS_SQL_LIB ssl crypto $$RS_THREAD_LIB $$RS_UPNP_LIB -dLibs = - -rs_jsonapi { - no_rs_cross_compiling { - RESTBED_SRC_PATH=$$clean_path($${RS_SRC_PATH}/supportlibs/restbed) - RESTBED_BUILD_PATH=$$clean_path($${RS_BUILD_PATH}/supportlibs/restbed) - INCLUDEPATH *= $$clean_path($${RESTBED_BUILD_PATH}/include/) - DEPENDPATH *= $$clean_path($${RESTBED_BUILD_PATH}/include/) - QMAKE_LIBDIR *= $$clean_path($${RESTBED_BUILD_PATH}/) - # Using sLibs would fail as librestbed.a is generated at compile-time - LIBS *= -L$$clean_path($${RESTBED_BUILD_PATH}/) -lrestbed - } else:sLibs *= restbed - - win32-g++|win32-clang-g++:dLibs *= wsock32 -} - -linux-* { - mLibs += dl -} - -rs_deep_channels_index | rs_deep_files_index | rs_deep_forums_index { - mLibs += xapian - win32-g++|win32-clang-g++:mLibs += rpcrt4 -} - -rs_deep_files_index_ogg { - mLibs += vorbisfile -} - -rs_deep_files_index_flac { - mLibs += FLAC++ -} - -rs_deep_files_index_taglib { - mLibs += tag -} - -rs_broadcast_discovery { - no_rs_cross_compiling { - UDP_DISCOVERY_SRC_PATH=$$clean_path($${RS_SRC_PATH}/supportlibs/udp-discovery-cpp/) - UDP_DISCOVERY_BUILD_PATH=$$clean_path($${RS_BUILD_PATH}/supportlibs/udp-discovery-cpp/) - INCLUDEPATH *= $$clean_path($${UDP_DISCOVERY_SRC_PATH}) - DEPENDPATH *= $$clean_path($${UDP_DISCOVERY_BUILD_PATH}) - QMAKE_LIBDIR *= $$clean_path($${UDP_DISCOVERY_BUILD_PATH}) - # Using sLibs would fail as libudp-discovery.a is generated at compile-time - LIBS *= -L$$clean_path($${UDP_DISCOVERY_BUILD_PATH}) -ludp-discovery - } else:sLibs *= udp-discovery - - win32-g++|win32-clang-g++:dLibs *= wsock32 -} - -rs_sam3_libsam3 { - LIBSAM3_SRC_PATH=$$clean_path($${RS_SRC_PATH}/supportlibs/libsam3/) - LIBSAM3_BUILD_PATH=$$clean_path($${RS_BUILD_PATH}/supportlibs/libsam3/) - INCLUDEPATH *= $$clean_path($${LIBSAM3_SRC_PATH}/src/libsam3/) - DEPENDPATH *= $$clean_path($${LIBSAM3_BUILD_PATH}) - QMAKE_LIBDIR *= $$clean_path($${LIBSAM3_BUILD_PATH}) - LIBS *= -L$$clean_path($${LIBSAM3_BUILD_PATH}) -lsam3 -} - -static { - sLibs *= $$mLibs -} else { - dLibs *= $$mLibs -} - -LIBS += $$linkStaticLibs(sLibs) -PRE_TARGETDEPS += $$pretargetStaticLibs(sLibs) - -LIBS += $$linkDynamicLibs(dLibs) - -android-* { - INCLUDEPATH *= $$clean_path($${RS_SRC_PATH}/supportlibs/jni.hpp/include/) -} - -################################### Pkg-Config Stuff ############################# -!isEmpty(PKGCONFIG) { - LIBS *= $$system(pkg-config --libs $$PKGCONFIG) -} diff --git a/libretroshare/src/util/argstream.h b/libretroshare/src/util/argstream.h deleted file mode 100644 index ede11ec2e..000000000 --- a/libretroshare/src/util/argstream.h +++ /dev/null @@ -1,847 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: argstream.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004 Xavier Decoret * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef ARGSTREAM_H -#define ARGSTREAM_H - - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace -{ - class argstream; - - template - class ValueHolder; - - template - argstream& operator>> (argstream&, const ValueHolder&); - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - // Interface of ValueHolder - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - template - class ValueHolder - { - public: - ValueHolder(char s, - const char* l, - T& b, - const char *valueName, - const char* desc, - bool mandatory); - ValueHolder(const char* l, - T& b, - const char *valueName, - const char* desc, - bool mandatory); - ValueHolder(char s, - T& b, - const char *valueName, - const char* desc, - bool mandatory); - friend argstream& operator>><>(argstream& s,const ValueHolder& v); - std::string name() const; - std::string description() const; - private: - std::string shortName_; - std::string longName_; - T* value_; - std::string valueName_; - T initialValue_; - std::string description_; - bool mandatory_; - }; - template - inline ValueHolder - parameter(char s, - const char* l, - T& b, - const char* desc="", - bool mandatory = true) - { - return ValueHolder(s,l,b,"value",desc,mandatory); - } - template - inline ValueHolder - parameter(char s, - const char* l, - T& b, - const char* valueName="value", - const char* desc="", - bool mandatory = true) - { - return ValueHolder(s,l,b,valueName,desc,mandatory); - } - template - inline ValueHolder - parameter(char s, - T& b, - const char* valueName="value", - const char* desc="", - bool mandatory = true) - { - return ValueHolder(s,b,valueName,desc,mandatory); - } - template - inline ValueHolder - parameter(const char* l, - T& b, - const char* valueName="value", - const char* desc="", - bool mandatory = true) - { - return ValueHolder(l,b,valueName,desc,mandatory); - } - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - // Interface of OptionHolder - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - class OptionHolder - { - public: - inline OptionHolder(char s, - const char* l, - bool& b, - const char* desc); - inline OptionHolder(const char* l, - bool& b, - const char* desc); - inline OptionHolder(char s, - bool& b, - const char* desc); - friend argstream& operator>>(argstream& s,const OptionHolder& v); - inline std::string name() const; - inline std::string description() const; - protected: - inline OptionHolder(char s, - const char* l, - const char* desc); - friend OptionHolder help(char s, - const char* l, - const char* desc); - - private: - std::string shortName_; - std::string longName_; - bool* value_; - std::string description_; - }; - inline OptionHolder - option(char s, - const char* l, - bool& b, - const char* desc="") - { - return OptionHolder(s,l,b,desc); - } - inline OptionHolder - option(char s, - bool& b, - const char* desc="") - { - return OptionHolder(s,b,desc); - } - inline OptionHolder - option(const char* l, - bool& b, - const char* desc="") - { - return OptionHolder(l,b,desc); - } - inline OptionHolder - help(char s, - const char* l, - const char* desc) - { - return OptionHolder(s,l,desc); - } - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - // Interface of ValuesHolder - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - template - class ValuesHolder - { - public: - ValuesHolder(const O& o, - const char* desc, - int len); - template friend argstream& operator>>(argstream& s,const ValuesHolder& v); - std::string name() const; - std::string description() const; - typedef T value_type; - private: - mutable O value_; - std::string description_; - int len_; - char letter_; - }; - template - inline ValuesHolder - values(const O& o, - const char* desc="", - int len=-1) - { - return ValuesHolder(o,desc,len); - } - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - // Interface of ValueParser - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - template - class ValueParser - { - public: - inline T operator()(const std::string& s) const - { - std::istringstream is(s); - T t; - is>>t; - return t; - } - }; - // We need to specialize for string otherwise parsing of a value that - // contains space (for example a string with space passed in quotes on the - // command line) would parse only the first element of the value!!! - template <> - class ValueParser - { - public: - inline std::string operator()(const std::string& s) const - { - return s; - } - }; - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - // Interface of argstream - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - class argstream - { - public: - inline argstream(int argc,char** argv); - inline argstream(const char* c); - template - friend argstream& operator>>(argstream& s,const ValueHolder& v); - friend inline argstream& operator>>(argstream& s,const OptionHolder& v); - template - friend argstream& operator>>(argstream& s,const ValuesHolder& v); - - inline bool helpRequested() const; - inline bool isOk() const; - inline std::string errorLog() const; - inline std::string usage(bool skipCommandLine = false) const; - inline bool defaultErrorHandling(bool ignoreUnused=false,bool skipCommandLine=false) const; - static inline char uniqueLetter(); - protected: - void parse(int argc,char** argv); - private: - typedef std::list::iterator value_iterator; - typedef std::pair help_entry; - std::string progName_; - std::map options_; - std::list values_; - bool minusActive_; - bool isOk_; - std::deque argHelps_; - std::string cmdLine_; - std::deque errors_; - bool helpRequested_; - }; - //************************************************************ - // Implementation of ValueHolder - //************************************************************ - template - ValueHolder::ValueHolder(char s, - const char* l, - T& v, - const char* valueName, - const char* desc, - bool mandatory) - : shortName_(1,s), - longName_(l), - value_(&v), - valueName_(valueName), - initialValue_(v), - description_(desc), - mandatory_(mandatory) - { - } - template - ValueHolder::ValueHolder(const char* l, - T& v, - const char* valueName, - const char* desc, - bool mandatory) - : longName_(l), - value_(&v), - valueName_(valueName), - initialValue_(v), - description_(desc), - mandatory_(mandatory) - { - } - template - ValueHolder::ValueHolder(char s, - T& v, - const char* valueName, - const char* desc, - bool mandatory) - : shortName_(1,s), - value_(&v), - valueName_(valueName), - initialValue_(v), - description_(desc), - mandatory_(mandatory) - { - } - template - std::string - ValueHolder::name() const - { - std::ostringstream os; - if (!shortName_.empty()) os<<'-'< - std::string - ValueHolder::description() const - { - std::ostringstream os; - os< - //************************************************************ - template - ValuesHolder::ValuesHolder(const O& o, - const char* desc, - int len) - : value_(o), - description_(desc), - len_(len) - { - letter_ = argstream::uniqueLetter(); - } - template - std::string - ValuesHolder::name() const - { - std::ostringstream os; - os< - std::string - ValuesHolder::description() const - { - return description_; - } - //************************************************************ - // Implementation of argstream - //************************************************************ - inline - argstream::argstream(int argc,char** argv) - : progName_(argv[0]), - minusActive_(true), - isOk_(true), - helpRequested_(false) - { - parse(argc,argv); - } - inline - argstream::argstream(const char* c) - : progName_(""), - minusActive_(true), - isOk_(true) - { - std::string s(c); - // Build argc, argv from s. We must add a dummy first element for - // progName because parse() expects it!! - std::deque args; - args.push_back(""); - std::istringstream is(s); - while (is.good()) - { - std::string t; - is>>t; - args.push_back(t); - } - char* pargs[args.size()]; - char** p = pargs; - for (std::deque::const_iterator - iter = args.begin(); - iter != args.end();++iter) - { - *p++ = const_cast(iter->c_str()); - } - parse(args.size(),pargs); - } - inline void - argstream::parse(int argc,char** argv) - { - // Run thru all arguments. - // * it has -- in front : it is a long name option, if remainder is empty, - // it is an error - // * it has - in front : it is a sequence of short name options, if - // remainder is empty, deactivates option (- will - // now be considered a char). - // * if any other char, or if option was deactivated - // : it is a value. Values are split in parameters - // (immediately follow an option) and pure values. - // Each time a value is parsed, if the previously parsed argument was an - // option, then the option is linked to the value in case of it is a - // option with parameter. The subtle point is that when several options - // are given with short names (ex: -abc equivalent to -a -b -c), the last - // parsed option is -c). - // Since we use map for option, any successive call overides the previous - // one: foo -a -b -a hello is equivalent to foo -b -a hello - // For values it is not true since we might have several times the same - // value. - value_iterator* lastOption = NULL; - for (char** a = argv,**astop=a+argc;++a!=astop;) - { - std::string s(*a); - if (minusActive_ && s[0] == '-') - { - if (s.size() > 1 && s[1] == '-') - { - if (s.size() == 2) - { - minusActive_ = false; - continue; - } - lastOption = &(options_[s.substr(2)] = values_.end()); - } - else - { - if (s.size() > 1) - { - // Parse all chars, if it is a minus we have an error - for (std::string::const_iterator cter = s.begin(); - ++cter != s.end();) - { - if (*cter == '-') - { - isOk_ = false; - std::ostringstream os; - os<<"- in the middle of a switch "<::const_iterator - iter = options_.begin();iter != options_.end();++iter) - { - std::cout<<"DEBUG: option "<first; - if (iter->second != values_.end()) - { - std::cout<<" -> "<<*(iter->second); - } - std::cout<::const_iterator - iter = values_.begin();iter != values_.end();++iter) - { - std::cout<<"DEBUG: value "<<*iter<::const_iterator - iter = argHelps_.begin();iter != argHelps_.end();++iter) - { - if (lmaxfirst.size()) lmax = iter->first.size(); - } - for (std::deque::const_iterator - iter = argHelps_.begin();iter != argHelps_.end();++iter) - { - os<<'\t'<first<first.size(),' ') - <<" : "<second<<'\n'; - } - return os.str(); - } - inline std::string - argstream::errorLog() const - { - std::string s; - for(std::deque::const_iterator iter = errors_.begin(); - iter != errors_.end();++iter) - { - s += *iter; - s += '\n'; - } - return s; - } - inline char - argstream::uniqueLetter() - { - static unsigned int c = 'a'; - return c++; - } - template - argstream& - operator>>(argstream& s,const ValueHolder& v) - { - // Search in the options if there is any such option defined either with a - // short name or a long name. If both are found, only the last one is - // used. -#ifdef ARGSTREAM_DEBUG - std::cout<<"DEBUG: searching "<::iterator iter = - s.options_.find(v.shortName_); - if (iter == s.options_.end()) - { - iter = s.options_.find(v.longName_); - } - if (iter != s.options_.end()) - { - // If we find counterpart for value holder on command line, either it - // has an associated value in which case we assign it, or it has not, in - // which case we have an error. - if (iter->second != s.values_.end()) - { -#ifdef ARGSTREAM_DEBUG - std::cout<<"DEBUG: found value "<<*(iter->second)< p; - *(v.value_) = p(*(iter->second)); - // The option and its associated value are removed, the subtle thing - // is that someother options might have this associated value too, - // which we must invalidate. - s.values_.erase(iter->second); - for (std::map::iterator - jter = s.options_.begin();jter != s.options_.end();++jter) - { - if (jter->second == iter->second) - { - jter->second = s.values_.end(); - } - } - s.options_.erase(iter); - } - else - { - s.isOk_ = false; - std::ostringstream os; - os<<"No value following switch "<first - <<" on command line"; - s.errors_.push_back(os.str()); - } - } - else - { - if (v.mandatory_) - { - s.isOk_ = false; - std::ostringstream os; - os<<"Mandatory parameter "; - if (!v.shortName_.empty()) os<<'-'<>(argstream& s,const OptionHolder& v) - { - // Search in the options if there is any such option defined either with a - // short name or a long name. If both are found, only the last one is - // used. -#ifdef ARGSTREAM_DEBUG - std::cout<<"DEBUG: searching "<::iterator iter = - s.options_.find(v.shortName_); - if (iter == s.options_.end()) - { - iter = s.options_.find(v.longName_); - } - if (iter != s.options_.end()) - { - // If we find counterpart for value holder on command line then the - // option is true and if an associated value was found, it is ignored - if (v.value_ != NULL) - { - *(v.value_) = true; - } - else - { - s.helpRequested_ = true; - } - // The option only is removed - s.options_.erase(iter); - } - else - { - if (v.value_ != NULL) - { - *(v.value_) = false; - } - else - { - s.helpRequested_ = false; - } - } - return s; - } - template - argstream& - operator>>(argstream& s,const ValuesHolder& v) - { - s.argHelps_.push_back(argstream::help_entry(v.name(),v.description())); - { - std::ostringstream os; - os<<' '<::iterator first = s.values_.begin(); - // We add to the iterator as much values as we can, limited to the length - // specified (if different of -1) - int n = v.len_ != -1?v.len_:s.values_.size(); - while (first != s.values_.end() && n-->0) - { - // Read the value from the string *first - ValueParser p; - *(v.value_++) = p(*first ); - s.argHelps_.push_back(argstream::help_entry(v.name(),v.description())); - // The value we just removed was maybe "remembered" by an option so we - // remove it now. - for (std::map::iterator - jter = s.options_.begin();jter != s.options_.end();++jter) - { - if (jter->second == first) - { - jter->second = s.values_.end(); - } - } - ++first; - } - // Check if we have enough values - if (n != 0) - { - s.isOk_ = false; - std::ostringstream os; - os<<"Expecting "< * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include -#include - -#include "contentvalue.h" - - - - -const uint8_t ContentValue::BOOL_TYPE = 1; -const uint8_t ContentValue::DATA_TYPE = 2; -const uint8_t ContentValue::STRING_TYPE = 3; -const uint8_t ContentValue::DOUBLE_TYPE = 4; -const uint8_t ContentValue::INT32_TYPE = 5; -const uint8_t ContentValue::INT64_TYPE = 6; - - -/**************** content value implementation ******************/ - -typedef std::pair KeyTypePair; - -ContentValue::ContentValue(){ - -} - -ContentValue::~ContentValue(){ - // release resources held in data - clearData(); -} - -ContentValue::ContentValue(const ContentValue &from){ - - std::map keyTypeMap; - from.getKeyTypeMap(keyTypeMap); - std::map::const_iterator cit = - keyTypeMap.begin(); - - uint8_t type = 0; - std::string currKey; - std::string val = ""; - char *src = NULL; - uint32_t data_len = 0; - - for(; cit != keyTypeMap.end(); ++cit){ - - type = cit->second; - currKey = cit->first; - - switch(type){ - - case INT32_TYPE: - { - int32_t value = 0; - if (from.getAsInt32(currKey, value)) - put(currKey, value); - break; - } - case INT64_TYPE: - { - int64_t value = 0; - if (from.getAsInt64(currKey, value)) - put(currKey, value); - break; - } - case STRING_TYPE: - { - if (from.getAsString(currKey, val)) - put(currKey, val); - break; - } - case BOOL_TYPE: - { - bool value = false; - if (from.getAsBool(currKey, value)) - put(currKey, value); - break; - } - case DATA_TYPE: - { - if (from.getAsData(currKey, data_len, src)) - put(currKey, data_len, src); - break; - } - case DOUBLE_TYPE: - { - double value = 0; - if (from.getAsDouble(currKey, value)) - put(currKey, value); - break; - } - default: - std::cerr << "ContentValue::ContentValue(ContentValue &from):" - << "Error! Unrecognised data type!" << std::endl; - break; - } - } -} - -void ContentValue::put(const std::string &key, bool value){ - - if(mKvSet.find(key) != mKvSet.end()) - removeKeyValue(key); - - mKvSet.insert(KeyTypePair(key, BOOL_TYPE)); - mKvBool.insert(std::pair(key, value)); -} - -void ContentValue::put(const std::string &key, const std::string &value){ - - if(mKvSet.find(key) != mKvSet.end()) - removeKeyValue(key); - - mKvSet.insert(KeyTypePair(key, STRING_TYPE)); - mKvString.insert(std::pair(key, value)); -} - -void ContentValue::put(const std::string &key, double value){ - - if(mKvSet.find(key) != mKvSet.end()) - removeKeyValue(key); - - mKvSet.insert(KeyTypePair(key,DOUBLE_TYPE)); - mKvDouble.insert(std::pair(key, value)); -} - -void ContentValue::put(const std::string &key, int32_t value){ - - if(mKvSet.find(key) != mKvSet.end()) - removeKeyValue(key); - - mKvSet.insert(KeyTypePair(key, INT32_TYPE)); - mKvInt32.insert(std::pair(key, value)); -} - -void ContentValue::put(const std::string &key, int64_t value){ - - if(mKvSet.find(key) != mKvSet.end()) - removeKeyValue(key); - - mKvSet.insert(KeyTypePair(key, INT64_TYPE)); - mKvInt64.insert(std::pair(key, value)); -} - -void ContentValue::put(const std::string &key, uint32_t len, const char* value){ - - - // release memory from old key value if key - // exists - if(mKvSet.find(key) != mKvSet.end()) { - removeKeyValue(key); - } - - mKvSet.insert(KeyTypePair(key, DATA_TYPE)); - char* dest = NULL; - - // len is zero then just put a NULL entry - if(len != 0){ - dest = new char[len]; - memcpy(dest, value, len); - } - - mKvData.insert(std::pair > - (key, std::pair(len, dest))); - //delete[] dest; //Deleted by clearData() - // cppcheck-suppress memleak -} - -bool ContentValue::getAsBool(const std::string &key, bool& value) const{ - - std::map::const_iterator it; - if((it = mKvBool.find(key)) == mKvBool.end()) - return false; - - value = it->second; - return true; -} - -bool ContentValue::getAsInt32(const std::string &key, int32_t& value) const{ - - std::map::const_iterator it; - if((it = mKvInt32.find(key)) == mKvInt32.end()) - return false; - - value = it->second; - return true; -} - -bool ContentValue::getAsInt64(const std::string &key, int64_t& value) const{ - - std::map::const_iterator it; - if((it = mKvInt64.find(key)) == mKvInt64.end()) - return false; - - value = it->second; - return true; -} - -bool ContentValue::getAsString(const std::string &key, std::string &value) const{ - - std::map::const_iterator it; - if((it = mKvString.find(key)) == mKvString.end()) - return false; - - value = it->second; - return true; -} - -bool ContentValue::getAsData(const std::string& key, uint32_t &len, char*& value) const{ - - std::map >::const_iterator it; - if((it = mKvData.find(key)) == mKvData.end()) - return false; - - const std::pair &kvRef = it->second; - - len = kvRef.first; - value = kvRef.second; - return true; -} - -bool ContentValue::getAsDouble(const std::string &key, double& value) const{ - - std::map::const_iterator it; - if((it = mKvDouble.find(key)) == mKvDouble.end()) - return false; - - value = it->second; - return true; -} - -bool ContentValue::removeKeyValue(const std::string &key){ - - std::map::iterator mit; - - if((mit = mKvSet.find(key)) == mKvSet.end()) - return false; - - if(mit->second == BOOL_TYPE) - mKvBool.erase(key); - - if(mit->second == INT64_TYPE) - mKvInt64.erase(key); - - if(mit->second == DATA_TYPE){ - delete[] (mKvData[key].second); - mKvData.erase(key); - } - - if(mit->second == DOUBLE_TYPE) - mKvDouble.erase(key); - - if(mit->second == STRING_TYPE) - mKvString.erase(key); - - if(mit->second == INT32_TYPE) - mKvInt32.erase(key); - - - mKvSet.erase(key); - return true; -} - - -void ContentValue::getKeyTypeMap(std::map &keySet) const { - keySet = mKvSet; -} - -void ContentValue::clear(){ - mKvSet.clear(); - mKvBool.clear(); - mKvDouble.clear(); - mKvString.clear(); - mKvInt32.clear(); - mKvInt64.clear(); - clearData(); -} - -bool ContentValue::empty() const{ - return mKvSet.empty(); -} - -void ContentValue::clearData(){ - - std::map >::iterator - mit = mKvData.begin(); - - for(; mit != mKvData.end(); ++mit){ - - if(mit->second.first != 0) - delete[] (mit->second.second); - } - - mKvData.clear(); -} - - - diff --git a/libretroshare/src/util/contentvalue.h b/libretroshare/src/util/contentvalue.h deleted file mode 100644 index 23ee55eca..000000000 --- a/libretroshare/src/util/contentvalue.h +++ /dev/null @@ -1,187 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: contentvalue.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 Christopher Evi-Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef CONTENTVALUE_H -#define CONTENTVALUE_H - -#include -#include -#include - -/*! - * @brief Convenience container for making additions to databases - * This class provides a means of holding column values to insert into a database - */ -class ContentValue { - -public: - - static const uint8_t INT32_TYPE; - static const uint8_t INT64_TYPE; - static const uint8_t DOUBLE_TYPE; - static const uint8_t STRING_TYPE; - static const uint8_t DATA_TYPE; - static const uint8_t BOOL_TYPE; - - ContentValue(); - - /*! - * copy constructor that copys the key value set from another \n - * ContentValue object to this one - * makes a deep copy of raw data - * @param from ContentValue instance to copy key value set from - */ - ContentValue(const ContentValue& from);//const damit die ƤuƟere klasse einen konstruktor com compielr bekommt - - /*! - * - * - * - */ - ~ContentValue(); - - /*! - * Adds a value to the set - * @param key the name of the value to put - * @param value the data for the value to put - * @warning cast string literals explicitly as string, observed string literal \n - * being casted to bool instead e.g. string("hello") rather than "hello" - */ - void put(const std::string& key, const std::string& value); - - /*! - * Adds a value to the set - * @param key the name of the value to put - * @param value the data for the value to put - */ - void put(const std::string& key, bool value); - - /*! - * Adds a value to the set - * @param key the name of the value to put - * @param value the data for the value to put - */ - void put(const std::string& key, int64_t value); - - /*! - * Adds a value to the set - * @param key the name of the value to put - * @param value the data for the value to put - */ - void put(const std::string& key, int32_t value); - - /*! - * Adds a value to the set - * @param key the name of the value to put - * @param value the data for the value to put - */ - void put(const std::string& key, double value); - - /*! - * Adds a value to the set - * Takes a private copy of data - * @param key the name of the value to put - * @param value the data for the value to put - */ - void put(const std::string& key, uint32_t len, const char* value); - - - /*! - * get value as 32 bit signed integer - * @param key the value to get - */ - bool getAsInt32(const std::string& key, int32_t& value) const; - - /*! - * get value as 64 bit signed integer - * @param key the value to get - */ - bool getAsInt64(const std::string& key, int64_t& value) const; - - /*! - * get value as bool - * @param key the value to get - */ - bool getAsBool(const std::string& key, bool& value) const; - - /*! - * get as value double - * @param key the value to get - */ - bool getAsDouble(const std::string& key, double& value) const; - - /*! - * get as value as string - * @param key the value to get - * @param value the data retrieved - */ - bool getAsString(const std::string& key, std::string& value) const; - - /*! - * get as value as raw data - * @warning Deep copy of data reference should be made, if this instance ContentValue \n - * is destroyed pointer returned (value) is pointing to invalid memory - * @param key the value to get - */ - bool getAsData(const std::string&, uint32_t& len, char*& value) const; - - /*! - * @param keySet the is set with key to type pairs contained in the ContentValue instance - */ - void getKeyTypeMap(std::map& keySet) const; - - /*! - * @param key the key of the key value pair to remove - * @return true if key was found and removed, false otherwise - */ - bool removeKeyValue(const std::string& key); - - /*! - * clears this data structure of all its key value pairs held - */ - void clear(); - - /*! - * checks if internal kv map is empty - */ - bool empty() const; - -private: - - /*! - * release memory resource associated with mKvData - */ - void clearData(); - -private: - - std::map mKvInt32; - std::map mKvInt64; - std::map mKvDouble; - std::map mKvString; - std::map > mKvData; - std::map mKvBool; - - std::map mKvSet; - -}; - -#endif // CONTENTVALUE_H diff --git a/libretroshare/src/util/cxx11retrocompat.h b/libretroshare/src/util/cxx11retrocompat.h deleted file mode 100644 index f210cf87b..000000000 --- a/libretroshare/src/util/cxx11retrocompat.h +++ /dev/null @@ -1,33 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: cxx11retrocompat.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2017 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#if defined(__GNUC__) && !defined(__clang__) -# define GCC_VERSION (__GNUC__*10000+__GNUC_MINOR__*100+__GNUC_PATCHLEVEL__) -# if GCC_VERSION < 40700 -# define override -# define final -# endif // GCC version < 40700 -# if GCC_VERSION < 40600 -# define nullptr NULL -# endif // GCC_VERSION < 40600 -#endif // defined(__GNUC__) && !defined(__clang__) diff --git a/libretroshare/src/util/cxx14retrocompat.h b/libretroshare/src/util/cxx14retrocompat.h deleted file mode 100644 index e7e7d9e99..000000000 --- a/libretroshare/src/util/cxx14retrocompat.h +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************* - * * - * libretroshare < C++14 retro-compatibility helpers * - * * - * Copyright (C) 2020 Gioacchino Mazzurco * - * Copyright (C) 2020 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#if __cplusplus < 201402L - -#include - -namespace std -{ -template using decay_t = typename decay::type; - -template -using enable_if_t = typename enable_if::type; - -template -using remove_const_t = typename remove_const::type; -} -#endif // __cplusplus < 201402L diff --git a/libretroshare/src/util/cxx17retrocompat.h b/libretroshare/src/util/cxx17retrocompat.h deleted file mode 100644 index 58cdfe84c..000000000 --- a/libretroshare/src/util/cxx17retrocompat.h +++ /dev/null @@ -1,35 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: cxx17retrocompat.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#if __cplusplus < 201703L - -#include - -namespace std -{ -using namespace std; -template constexpr typename add_const::type& as_const(T& t) noexcept -{ return t; } -template void as_const(const T&&) = delete; -} -#endif // __cplusplus < 201703L diff --git a/libretroshare/src/util/cxx23retrocompat.h b/libretroshare/src/util/cxx23retrocompat.h deleted file mode 100644 index cd96b7cbf..000000000 --- a/libretroshare/src/util/cxx23retrocompat.h +++ /dev/null @@ -1,34 +0,0 @@ -/******************************************************************************* - * RetroShare C++23 backwards compatibility utilities * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include - -#if ! defined(__cpp_lib_to_underlying) -namespace std -{ -template -constexpr underlying_type_t to_underlying(Enum e) noexcept -{ return static_cast>(e); } -} -#endif // ! defined(__cpp_lib_to_underlying) diff --git a/libretroshare/src/util/dnsresolver.cc b/libretroshare/src/util/dnsresolver.cc deleted file mode 100644 index 7ce9edee6..000000000 --- a/libretroshare/src/util/dnsresolver.cc +++ /dev/null @@ -1,202 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: dnsresolver.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2017 Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "dnsresolver.h" - -#include "pqi/pqinetwork.h" -#include "util/rsnet.h" - - -#ifndef WIN32 -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include "util/rstime.h" - -const rstime_t MAX_TIME_BEFORE_RETRY = 300 ; /* seconds before retrying an ip address */ -const rstime_t MAX_KEEP_DNS_ENTRY = 3600 ; /* seconds during which a DNS entry is considered valid */ - -void *solveDNSEntries(void *p) -{ - bool more_to_go = true ; - DNSResolver *dnsr = (DNSResolver*)p ; - - while(more_to_go) - { - // get an address request - rstime_t now = time(NULL) ; - more_to_go = false ; - - std::string next_call = "" ; - - { - RsStackMutex mut(dnsr->_rdnsMtx) ; - - if(dnsr->_addr_map != NULL) - for(std::map::iterator it(dnsr->_addr_map->begin());it!=dnsr->_addr_map->end() && next_call.empty();++it) - { - switch(it->second.state) - { - case DNSResolver::DNS_SEARCHING: - case DNSResolver::DNS_HAVE: break ; - - case DNSResolver::DNS_LOOKUP_ERROR: if(it->second.last_lookup_time + MAX_TIME_BEFORE_RETRY > now) - continue ; - /* fallthrough */ //Not really, but to suppress warning. - case DNSResolver::DNS_DONT_HAVE: next_call = it->first ; - it->second.state = DNSResolver::DNS_SEARCHING ; - it->second.last_lookup_time = now ; - more_to_go = true ; - break ; - } - } - else - return NULL; // the thread has been deleted. Return. - } - - if(!next_call.empty()) - { - in_addr in ; - - bool succeed = rsGetHostByName(next_call.c_str(),in); - - { - RsStackMutex mut(dnsr->_rdnsMtx) ; - - DNSResolver::AddrInfo &info = (*dnsr->_addr_map)[next_call]; - - if(succeed) - { - info.state = DNSResolver::DNS_HAVE ; - // IPv4 for the moment. - struct sockaddr_in *addrv4p = (struct sockaddr_in *) &(info.addr); - addrv4p->sin_family = AF_INET; - addrv4p->sin_addr= in ; - addrv4p->sin_port = htons(0); - - std::cerr << "LOOKUP succeeded: " << next_call.c_str() << " => " << rs_inet_ntoa(addrv4p->sin_addr) << std::endl; - } - else - { - info.state = DNSResolver::DNS_LOOKUP_ERROR ; - - std::cerr << "DNSResolver: lookup error for address \"" << next_call.c_str() << "\"" << std::endl; - } - } - } - } - - { - RsStackMutex mut(dnsr->_rdnsMtx) ; - *(dnsr->_thread_running) = false ; - } - return NULL ; -} - -void DNSResolver::start_request() -{ - { - RsStackMutex mut(_rdnsMtx) ; - *_thread_running = true ; - } - - void *data = (void *)this; - pthread_t tid ; - - if(! pthread_create(&tid, 0, &solveDNSEntries, data)) - pthread_detach(tid); /* so memory is reclaimed in linux */ - else - std::cerr << "(EE) Could not start DNS resolver thread!" << std::endl; -} - -void DNSResolver::reset() -{ - RsStackMutex mut(_rdnsMtx) ; - - *_thread_running = false ; - _addr_map->clear(); -} - -bool DNSResolver::getIPAddressFromString(const std::string& server_name,struct sockaddr_storage &addr) -{ - sockaddr_storage_clear(addr); - bool running = false; - { - RsStackMutex mut(_rdnsMtx) ; - - std::map::iterator it(_addr_map->find(server_name)) ; - rstime_t now = time(NULL) ; - AddrInfo *addr_info ; - - if(it != _addr_map->end()) - { - // check that the address record is not too old - - if(it->second.last_lookup_time + MAX_KEEP_DNS_ENTRY > now && it->second.state == DNSResolver::DNS_HAVE) - { - addr = it->second.addr ; - return true ; - } - else - addr_info = &it->second ; - } - else - addr_info = &(*_addr_map)[server_name] ; - - // We don't have it. Let's push it into the names to lookup for, except if we're already into it. - - if(addr_info->state != DNSResolver::DNS_SEARCHING) - addr_info->state = DNSResolver::DNS_DONT_HAVE ; - - running = *_thread_running ; - } - - if(!running) - start_request(); - - return false ; -} - -DNSResolver::~DNSResolver() -{ - RsStackMutex mut(_rdnsMtx) ; - - delete _addr_map ; - _addr_map = NULL ; - delete _thread_running ; -} - -DNSResolver::DNSResolver() : _rdnsMtx("DNSResolver") -{ - RsStackMutex mut(_rdnsMtx) ; - - _addr_map = new std::map() ; - _thread_running = new bool ; - *_thread_running = false ; -} - diff --git a/libretroshare/src/util/dnsresolver.h b/libretroshare/src/util/dnsresolver.h deleted file mode 100644 index 042654f4e..000000000 --- a/libretroshare/src/util/dnsresolver.h +++ /dev/null @@ -1,63 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: dnsresolver.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2017 Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include "pqi/pqinetwork.h" - -#ifndef WIN32 -#include -#endif - -#include -#include - -#include "util/rsthreads.h" -#include "util/rstime.h" - -struct sockaddr ; - -class DNSResolver -{ - public: - DNSResolver() ; - ~DNSResolver() ; - - bool getIPAddressFromString(const std::string& server_name,struct sockaddr_storage &addr) ; - - void start_request() ; - void reset() ; - - private: - enum { DNS_DONT_HAVE,DNS_SEARCHING, DNS_HAVE, DNS_LOOKUP_ERROR } ; - - struct AddrInfo - { - uint32_t state ; // state: Looked-up, not found, have - rstime_t last_lookup_time ; // last lookup time - struct sockaddr_storage addr ; - }; - friend void *solveDNSEntries(void *p) ; - - RsMutex _rdnsMtx ; - bool *_thread_running ; - std::map *_addr_map ; -}; diff --git a/libretroshare/src/util/exampletst.c b/libretroshare/src/util/exampletst.c deleted file mode 100644 index e96cd037e..000000000 --- a/libretroshare/src/util/exampletst.c +++ /dev/null @@ -1,40 +0,0 @@ - -#include "utest.h" - -#include - -/* must define the global variables */ -INITTEST(); - -int main(int argc, char **argv) -{ - int a = 2; - int b = 3; - int c = 2; - - CHECK( a == c ); - - REPORT( "Initial Tests"); - - CHECK( (0 == strcmp("123", "123")) ); - - REPORT( "Successful Tests"); - - CHECK( a == b ); - CHECK( (0 == strcmp("123", "12345")) ); - - REPORT( "Failed Tests" ); - - CHECK( 1 ); - CHECK( a == c ); - - REPORT( "Later Successful Tests"); - - - FINALREPORT( "Example Tests" ); - - return TESTRESULT(); -} - - - diff --git a/libretroshare/src/util/extaddrfinder.cc b/libretroshare/src/util/extaddrfinder.cc deleted file mode 100644 index 03b9f33a9..000000000 --- a/libretroshare/src/util/extaddrfinder.cc +++ /dev/null @@ -1,278 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: extaddrfinder.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2017 Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -//#define EXTADDRSEARCH_DEBUG - -#include "extaddrfinder.h" - -#include "pqi/pqinetwork.h" -#include "rsdebug.h" -#include "util/rsstring.h" -#include "util/rsmemory.h" - -#ifndef WIN32 -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include "util/rstime.h" - -#include - -const uint32_t MAX_IP_STORE = 300; /* seconds ip address timeout */ - -class ZeroInt -{ -public: - ZeroInt() : n(0) {} - uint32_t n ; -}; - -void ExtAddrFinder::run() -{ - - std::vector res ; - - for(auto& it : _ip_servers) - { - std::string ip = ""; - rsGetHostByNameSpecDNS(it,"myip.opendns.com",ip,2); - if(ip != "") - res.push_back(ip) ; -#ifdef EXTADDRSEARCH_DEBUG - RS_DBG("ip found through DNS ", it, ": \"", ip, "\""); -#endif - } - - if(res.empty()) - { - reset(); - return ; - } - - std::map addrV4_votes; - std::map addrV6_votes; - std::string all_addrV4_Found; - std::string all_addrV6_Found; - - for(auto curRes : res) - { - sockaddr_storage addr; - sockaddr_storage_clear(addr); - bool validIP = sockaddr_storage_inet_pton(addr, curRes) - && sockaddr_storage_isValidNet(addr); - bool isIPv4 = sockaddr_storage_ipv6_to_ipv4(addr); - if( validIP && isIPv4 ) - { - addr.ss_family = AF_INET; - addrV4_votes[addr].n++ ; - all_addrV4_Found += sockaddr_storage_tostring(addr) + "\n"; - } - else if( validIP && !isIPv4) - { - addr.ss_family = AF_INET6; - addrV6_votes[addr].n++ ; - all_addrV6_Found += sockaddr_storage_tostring(addr) + "\n"; - } - else - RS_ERR("Invalid addresse reported: ", curRes) ; - - } - - if( (0 == addrV4_votes.size()) && (0 == addrV6_votes.size()) ) - { - RS_ERR("Could not find any external address."); - reset(); - return ; - } - - if( 1 < addrV4_votes.size() ) - RS_ERR("Multiple external IPv4 addresses reported: " - , all_addrV4_Found ) ; - - if( 1 < addrV6_votes.size() ) - RS_ERR("Multiple external IPv6 addresses reported: " - , all_addrV6_Found ) ; - - { - RS_STACK_MUTEX(mAddrMtx); - - mSearching = false ; - mFoundTS = time(NULL) ; - - // Only save more reported address if not only once. - uint32_t admax = 0 ; - sockaddr_storage_clear(mAddrV4); - for (auto it : addrV4_votes) - if (admax < it.second.n) - { - mAddrV4 = it.first ; - mFoundV4 = true ; - admax = it.second.n ; - } - - admax = 0 ; - sockaddr_storage_clear(mAddrV6); - for (auto it : addrV6_votes) - if (admax < it.second.n) - { - mAddrV6 = it.first ; - mFoundV6 = true ; - admax = it.second.n ; - } - - } - - return ; -} - -void ExtAddrFinder::start_request() -{ - if (!isRunning()) - start("ExtAddrFinder"); -} - -bool ExtAddrFinder::hasValidIPV4(struct sockaddr_storage &addr) -{ -#ifdef EXTADDRSEARCH_DEBUG - RS_DBG("Getting ip."); -#endif - - { - RS_STACK_MUTEX(mAddrMtx) ; - if(mFoundV4) - { -#ifdef EXTADDRSEARCH_DEBUG - RS_DBG("Has stored ip responding with this ip:", sockaddr_storage_iptostring(mAddrV4)) ; -#endif - sockaddr_storage_copyip(addr,mAddrV4); // just copy the IP so we dont erase the port. - } - } - - testTimeOut(); - - RS_STACK_MUTEX(mAddrMtx) ; - return mFoundV4; -} - -bool ExtAddrFinder::hasValidIPV6(struct sockaddr_storage &addr) -{ -#ifdef EXTADDRSEARCH_DEBUG - RS_DBG("Getting ip."); -#endif - - { - RS_STACK_MUTEX(mAddrMtx) ; - if(mFoundV6) - { -#ifdef EXTADDRSEARCH_DEBUG - RS_DBG("Has stored ip responding with this ip:", sockaddr_storage_iptostring(mAddrV6)) ; -#endif - sockaddr_storage_copyip(addr,mAddrV6); // just copy the IP so we dont erase the port. - } - } - - testTimeOut(); - - RS_STACK_MUTEX(mAddrMtx) ; - return mFoundV6; -} - -void ExtAddrFinder::testTimeOut() -{ - bool timeOut; - { - RS_STACK_MUTEX(mAddrMtx) ; - //timeout the current ip - timeOut = (mFoundTS + MAX_IP_STORE < time(NULL)); - } - if(timeOut || mFirstTime) {//launch a research - if( mAddrMtx.trylock()) - { - if(!mSearching) - { -#ifdef EXTADDRSEARCH_DEBUG - RS_DBG("No stored ip: Initiating new search."); -#endif - mSearching = true ; - start_request() ; - } -#ifdef EXTADDRSEARCH_DEBUG - else - RS_DBG("Already searching."); -#endif - mFirstTime = false; - mAddrMtx.unlock(); - } -#ifdef EXTADDRSEARCH_DEBUG - else - RS_DBG("(Note) Could not acquire lock. Busy."); -#endif - } -} - -void ExtAddrFinder::reset(bool firstTime /*=false*/) -{ -#ifdef EXTADDRSEARCH_DEBUG - RS_DBG("firstTime=", firstTime); -#endif - RS_STACK_MUTEX(mAddrMtx) ; - - mSearching = false ; - mFoundV4 = false ; - mFoundV6 = false ; - mFirstTime = firstTime; - mFoundTS = time(nullptr); - sockaddr_storage_clear(mAddrV4); - sockaddr_storage_clear(mAddrV6); -} - -ExtAddrFinder::~ExtAddrFinder() -{ -#ifdef EXTADDRSEARCH_DEBUG - RS_DBG("Deleting ExtAddrFinder."); -#endif -} - -ExtAddrFinder::ExtAddrFinder() : mAddrMtx("ExtAddrFinder") -{ -#ifdef EXTADDRSEARCH_DEBUG - RS_DBG("Creating new ExtAddrFinder."); -#endif - reset( true ); - -//https://unix.stackexchange.com/questions/22615/how-can-i-get-my-external-ip-address-in-a-shell-script - //Enter direct ip so local DNS cannot change it. - //DNS servers must recognize "myip.opendns.com" - _ip_servers.push_back(std::string( "208.67.222.222" )) ;//resolver1.opendns.com - _ip_servers.push_back(std::string( "208.67.220.220" )) ;//resolver2.opendns.com - _ip_servers.push_back(std::string( "208.67.222.220" )) ;//resolver3.opendns.com - _ip_servers.push_back(std::string( "208.67.220.222" )) ;//resolver4.opendns.com - _ip_servers.push_back(std::string( "2620:119:35::35" )) ;//resolver1.opendns.com - _ip_servers.push_back(std::string( "2620:119:53::53" )) ;//resolver2.opendns.com -} diff --git a/libretroshare/src/util/extaddrfinder.h b/libretroshare/src/util/extaddrfinder.h deleted file mode 100644 index 1a2360bab..000000000 --- a/libretroshare/src/util/extaddrfinder.h +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: extaddrfinder.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2017 Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include - -#include "util/rsthreads.h" -#include "util/rsnet.h" -#include "util/rstime.h" - -struct sockaddr ; - -class ExtAddrFinder: public RsThread -{ - public: - ExtAddrFinder() ; - ~ExtAddrFinder() ; - - bool hasValidIPV4(struct sockaddr_storage &addr) ; - bool hasValidIPV6(struct sockaddr_storage &addr) ; - void getIPServersList(std::list& ip_servers) { ip_servers = _ip_servers ; } - - void start_request() ; - - void reset(bool firstTime = false) ; - - private: - virtual void run(); - void testTimeOut(); - - RsMutex mAddrMtx; - bool mSearching; - bool mFoundV4; - bool mFoundV6; - bool mFirstTime; - rstime_t mFoundTS; - struct sockaddr_storage mAddrV4; - struct sockaddr_storage mAddrV6; - std::list _ip_servers; -}; diff --git a/libretroshare/src/util/folderiterator.cc b/libretroshare/src/util/folderiterator.cc deleted file mode 100644 index df3203ba2..000000000 --- a/libretroshare/src/util/folderiterator.cc +++ /dev/null @@ -1,260 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: folderiterator.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2017 Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include -#include -#include -#include -#include -#include "util/rstime.h" - -#ifdef WINDOWS_SYS -#include "util/rswin.h" -#endif - -#include "folderiterator.h" -#include "rsstring.h" - -//#define DEBUG_FOLDER_ITERATOR 1 - -namespace librs { namespace util { - - -FolderIterator::FolderIterator( - const std::string& folderName, bool allow_symlinks, - bool allow_files_from_the_future ): - mFolderName(folderName), mAllowSymLinks(allow_symlinks), - mAllowFilesFromTheFuture(allow_files_from_the_future) -{ - is_open = false ; - validity = false ; - mFileModTime = 0; - mFolderModTime = 0; - mFileSize = 0; - mType = TYPE_UNKNOWN; - - // Grab the last modification time for the directory - - struct stat64 buf ; - -#ifdef WINDOWS_SYS - std::wstring wfullname; - librs::util::ConvertUtf8ToUtf16(folderName, wfullname); - if ( 0 == _wstati64(wfullname.c_str(), &buf)) -#else - if ( 0 == stat64(folderName.c_str(), &buf)) -#endif - { - mFolderModTime = buf.st_mtime ; - } - - // Now open directory content and read the first entry - -#ifdef WINDOWS_SYS - std::wstring utf16Name; - if(! ConvertUtf8ToUtf16(folderName, utf16Name)) { - validity = false; - return; - } - - utf16Name += L"/*.*"; - - // FindFirstFileW does the "next" operation, so after calling it, we need to read the information - // for the current entry. - - handle = FindFirstFileW(utf16Name.c_str(), &fileInfo); - is_open = validity = handle != INVALID_HANDLE_VALUE; - - bool should_skip ; - validity = validity && updateFileInfo(should_skip); - - if(validity && should_skip) - next(); -#else - // On linux, we need to call "next()" once the dir is openned. next() will call updateFileInfo() itself. - - handle = opendir(folderName.c_str()); - is_open = validity = handle != NULL; - next(); -#endif -} - -FolderIterator::~FolderIterator() -{ - closedir(); -} - -void FolderIterator::next() -{ - bool should_skip = false ; - - while(readdir()) - if(updateFileInfo(should_skip) && !should_skip) - return ; - - #ifdef DEBUG_FOLDER_ITERATOR - std::cerr << "End of directory." << std::endl; -#endif - - mType = TYPE_UNKNOWN ; - mFileSize = 0 ; - mFileModTime = 0; - validity = false ; -} - -bool FolderIterator::updateFileInfo(bool& should_skip) -{ - should_skip = false; -#ifdef WINDOWS_SYS - ConvertUtf16ToUtf8(fileInfo.cFileName, mFileName) ; -#else - mFileName = ent->d_name ; -#endif - - if(mFileName == "." || mFileName == "..") - { - should_skip = true ; - return true ; - } - - mFullPath = mFolderName + "/" + mFileName ; - -#warning cyril soler: should we take care of symbolic links on windows? -#ifndef WINDOWS_SYS - if( ent->d_type == DT_LNK) - { - if(!mAllowSymLinks) - { - std::cerr << "(II) Skipping symbolic link " << mFullPath << std::endl; - should_skip = true ; - return true ; - } - } - else if( ent->d_type != DT_DIR && ent->d_type != DT_REG && ent->d_type != DT_UNKNOWN) // DT_UNKNOWN is reported by mounted dirs, by services such as sshfs. - { - std::cerr << "(II) Skipping file of unknown type " << std::dec << (int)ent->d_type << std::dec << ": " << mFullPath << std::endl; - should_skip = true ; - return true ; - } -#endif - - struct stat64 buf ; - -#ifdef DEBUG_FOLDER_ITERATOR - std::cerr << "FolderIterator: next. Looking into file " << mFileName ; -#endif - -#ifdef WINDOWS_SYS - std::wstring wfullname; - librs::util::ConvertUtf8ToUtf16(mFullPath, wfullname); - if ( 0 == _wstati64(wfullname.c_str(), &buf)) -#else - if ( 0 == stat64(mFullPath.c_str(), &buf)) -#endif - { - mFileModTime = buf.st_mtime ; - - if(buf.st_mtime > time(NULL) && !mAllowFilesFromTheFuture) - { - std::cerr << "(II) skipping file with modification time in the future: " << mFullPath << std::endl; - should_skip = true ; - return true ; - } - - if (S_ISDIR(buf.st_mode)) - { -#ifdef DEBUG_FOLDER_ITERATOR - std::cerr << ": is a directory" << std::endl; -#endif - - mType = TYPE_DIR ; - mFileSize = 0 ; - mFileModTime = buf.st_mtime; - - return true; - } - - if (S_ISREG(buf.st_mode)) - { -#ifdef DEBUG_FOLDER_ITERATOR - std::cerr << ": is a file" << std::endl; -#endif - - mType = TYPE_FILE ; - mFileSize = buf.st_size; - mFileModTime = buf.st_mtime; - - return true; - } - } - -#ifdef DEBUG_FOLDER_ITERATOR - std::cerr << ": is unknown skipping" << std::endl; -#endif - - mType = TYPE_UNKNOWN ; - mFileSize = 0 ; - mFileModTime = 0; - - return false; -} - -bool FolderIterator::readdir() -{ - if(!validity) - return false; - -#ifdef WINDOWS_SYS - return FindNextFileW(handle, &fileInfo) != 0; -#else - ent = ::readdir(handle); - return ent != NULL; -#endif -} - -rstime_t FolderIterator::dir_modtime() const { return mFolderModTime ; } - -const std::string& FolderIterator::file_fullpath() { return mFullPath ; } -const std::string& FolderIterator::file_name() { return mFileName ; } -uint64_t FolderIterator::file_size() { return mFileSize ; } -rstime_t FolderIterator::file_modtime() { return mFileModTime ; } -uint8_t FolderIterator::file_type() { return mType ; } - -bool FolderIterator::closedir() -{ - validity = false; - - if(!is_open) - return true ; - - is_open = false ; - -#ifdef WINDOWS_SYS - return FindClose(handle) != 0; -#else - return ::closedir(handle) == 0; -#endif -} - - - - -} } // librs::util diff --git a/libretroshare/src/util/folderiterator.h b/libretroshare/src/util/folderiterator.h deleted file mode 100644 index 5a853eae3..000000000 --- a/libretroshare/src/util/folderiterator.h +++ /dev/null @@ -1,103 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: folderiterator.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2017 Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef FOLDERITERATOR_H -#define FOLDERITERATOR_H - - -#include -#include -#include - -#ifdef WINDOWS_SYS - #include - #include - #include - #include -#else - #include -#endif - -#include "util/rstime.h" - -namespace librs { namespace util { - - -class FolderIterator -{ -public: - FolderIterator( - const std::string& folderName, bool allow_symlinks, - bool allow_files_from_the_future = true ); - ~FolderIterator(); - - enum { TYPE_UNKNOWN = 0x00, - TYPE_FILE = 0x01, - TYPE_DIR = 0x02 - }; - - // info about current parent directory - rstime_t dir_modtime() const ; - - // info about directory content - - bool isValid() const { return validity; } - bool readdir(); - void next(); - - bool closedir(); - - const std::string& file_name() ; - const std::string& file_fullpath() ; - uint64_t file_size() ; - uint8_t file_type() ; - rstime_t file_modtime() ; - -private: - bool is_open; - bool validity; - -#ifdef WINDOWS_SYS - HANDLE handle; - bool isFirstCall; - _WIN32_FIND_DATAW fileInfo; -#else - DIR* handle; - struct dirent* ent; -#endif - bool updateFileInfo(bool &should_skip) ; - - rstime_t mFileModTime ; - rstime_t mFolderModTime ; - uint64_t mFileSize ; - uint8_t mType ; - std::string mFileName ; - std::string mFullPath ; - std::string mFolderName ; - bool mAllowSymLinks; - bool mAllowFilesFromTheFuture; -}; - - -} } // librs::util - - -#endif // FOLDERITERATOR_H diff --git a/libretroshare/src/util/i2pcommon.cpp b/libretroshare/src/util/i2pcommon.cpp deleted file mode 100644 index 524219eb3..000000000 --- a/libretroshare/src/util/i2pcommon.cpp +++ /dev/null @@ -1,269 +0,0 @@ -#include "i2pcommon.h" - -#include "util/rsbase64.h" -#include "util/rsdebug.h" - -namespace i2p { - -std::string keyToBase32Addr(const std::string &key) -{ - std::string copy(key); - - // replace I2P specific chars - std::replace(copy.begin(), copy.end(), '~', '/'); - // replacing the - with a + is not necessary, as RsBase64 can handle base64url encoding, too - // std::replace(copy.begin(), copy.end(), '-', '+'); - - // decode - std::vector bin; - RsBase64::decode(copy, bin); - - // hash - std::vector sha256 = RsUtil::BinToSha256(bin); - // encode - std::string out = Radix32::encode(sha256); - - // i2p uses lowercase - std::transform(out.begin(), out.end(), out.begin(), ::tolower); - out.append(".b32.i2p"); - - return out; -} - -const std::string makeOption(const std::string &lhs, const int8_t &rhs) { - return lhs + "=" + std::to_string(rhs); -} - -uint16_t readTwoBytesBE(std::vector::const_iterator &p) -{ - uint16_t val = 0; - val += *p++; - val <<= 8; - val += *p++; - return val; -} - -std::string publicKeyFromPrivate(std::string const &priv) -{ - /* - * https://geti2p.net/spec/common-structures#destination - * https://geti2p.net/spec/common-structures#keysandcert - * https://geti2p.net/spec/common-structures#certificate - */ - if (priv.length() < privKeyMinLenth_b64) { - RS_WARN("key to short!"); - return std::string(); - } - - // creat a copy to work on, need to convert it to standard base64 - auto priv_copy(priv); - std::replace(priv_copy.begin(), priv_copy.end(), '~', '/'); - // replacing the - with a + is not necessary, as RsBase64 can handle base64url encoding, too - // std::replace(copy.begin(), copy.end(), '-', '+'); - - // get raw data - std::vector dataPriv; - RsBase64::decode(priv_copy, dataPriv); - - auto p = dataPriv.cbegin(); - RS_DBG("dataPriv.size ", dataPriv.size()); - - size_t publicKeyLen = 256 + 128; // default length (bytes) - uint8_t certType = 0; - uint16_t len = 0; - uint16_t signingKeyType = 0; - uint16_t cryptKeyType = 0; - - // only used for easy break - do { - try { - // jump to certificate - p += publicKeyLen; - - // try to read type and length - certType = *p++; - len = readTwoBytesBE(p); - - // only 0 and 5 are used / valid at this point - // check for == 0 - if (certType == static_cast::type>(CertType::Null)) { - /* - * CertType.Null - * type null is followed by 0x00 0x00 - * so len has to be 0! - */ - RS_DBG("cert is CertType.Null"); - publicKeyLen += 3; // add 0x00 0x00 0x00 - - if (len != 0) - // weird - RS_DBG("cert is CertType.Null but len != 0"); - - break; - } - - // check for != 5 - if (certType != static_cast::type>(CertType::Key)) { - // unsupported - RS_DBG("cert type ", certType, " is unsupported"); - return std::string(); - } - - RS_DBG("cert is CertType.Key"); - publicKeyLen += 7; // = 1 + 2 + 2 + 2 = 7 bytes - - /* - * "Key certificates were introduced in release 0.9.12. Prior to that release, all PublicKeys were 256-byte ElGamal keys, and all SigningPublicKeys were 128-byte DSA-SHA1 keys." - * --> there is space for 256+128 bytes, longer keys are splitted and appended to the certificate - * We don't need to bother with the splitting here as only the lenght is important! - */ - - // Signing Public Key - // likely 7 - signingKeyType = readTwoBytesBE(p); - - RS_DBG("signing pubkey type ", signingKeyType); - if (signingKeyType >= 3 && signingKeyType <= 6) { - RS_DBG("signing pubkey type ", certType, " has oversize"); - // calculate oversize - - if (signingKeyType >= signingKeyLengths.size()) { - // just in case - RS_DBG("signing pubkey type ", certType, " cannot be found in size data!"); - return std::string(); - } - - auto values = signingKeyLengths[signingKeyType]; - if (values.first <= 128) { - // just in case, it's supposed to be larger! - RS_DBG("signing pubkey type ", certType, " is oversize but size calculation would underflow!"); - return std::string(); - } - - publicKeyLen += values.first - 128; // 128 = default DSA key length = the space that can be used before the key must be splitted - } - - // Crypto Public Key - // likely 0 - cryptKeyType = readTwoBytesBE(p); - RS_DBG("crypto pubkey type ", cryptKeyType); - // info: these are all smaller than the default 256 bytes, so no oversize calculation is needed - - break; - } catch (const std::out_of_range &e) { - RS_DBG("hit an exception! ", e.what()); - return std::string(); - } - } while(false); - - std::string pub; - auto data2 = std::vector(dataPriv.cbegin(), dataPriv.cbegin() + publicKeyLen); - RsBase64::encode(data2.data(), data2.size(), pub, false, false); - - return pub; -} - -bool getKeyTypes(const std::string &key, std::string &signingKey, std::string &cryptoKey) -{ - if (key.length() < pubKeyMinLenth_b64) { - RS_WARN("key to short!"); - return false; - } - - // creat a copy to work on, need to convert it to standard base64 - auto key_copy(key); - std::replace(key_copy.begin(), key_copy.end(), '~', '/'); - // replacing the - with a + is not necessary, as RsBase64 can handle base64url encoding, too - // std::replace(copy.begin(), copy.end(), '-', '+'); - - // get raw data - std::vector data; - RsBase64::decode(key_copy, data); - - auto p = data.cbegin(); - - constexpr size_t publicKeyLen = 256 + 128; // default length (bytes) - uint8_t certType = 0; - uint16_t signingKeyType = 0; - uint16_t cryptKeyType = 0; - - // try to read types - try { - // jump to certificate - p += publicKeyLen; - - // try to read type and skip length - certType = *p++; - p += 2; - - // only 0 and 5 are used / valid at this point - // check for == 0 - if (certType == static_cast::type>(CertType::Null)) { - RS_DBG("cert is CertType.Null"); - - signingKey = "DSA_SHA1"; - cryptoKey = "ElGamal"; - return true; - } - - // check for != 5 - if (certType != static_cast::type>(CertType::Key)) { - // unsupported - RS_DBG("cert type ", certType, " is unsupported"); - return false; - } - - RS_DBG("cert is CertType.Key"); - - // Signing Public Key - // likely 7 - signingKeyType = readTwoBytesBE(p); - RS_DBG("signing pubkey type ", signingKeyType); - - // Crypto Public Key - // likely 0 - cryptKeyType = readTwoBytesBE(p); - RS_DBG("crypto pubkey type ", cryptKeyType); - } catch (const std::out_of_range &e) { - RS_DBG("hit an exception! ", e.what()); - return false; - } - - // now convert to string (this would be easier with c++17) -#define HELPER(a, b, c) \ - case static_cast::type>(a::c): \ - b = #c; \ - break; - - switch (signingKeyType) { - HELPER(SigningKeyType, signingKey, DSA_SHA1) - HELPER(SigningKeyType, signingKey, ECDSA_SHA256_P256) - HELPER(SigningKeyType, signingKey, ECDSA_SHA384_P384) - HELPER(SigningKeyType, signingKey, ECDSA_SHA512_P521) - HELPER(SigningKeyType, signingKey, RSA_SHA256_2048) - HELPER(SigningKeyType, signingKey, RSA_SHA384_3072) - HELPER(SigningKeyType, signingKey, RSA_SHA512_4096) - HELPER(SigningKeyType, signingKey, EdDSA_SHA512_Ed25519) - HELPER(SigningKeyType, signingKey, EdDSA_SHA512_Ed25519ph) - HELPER(SigningKeyType, signingKey, RedDSA_SHA512_Ed25519) - default: - RsWarn("unkown signing key type:", signingKeyType); - return false; - } - - switch (cryptKeyType) { - HELPER(CryptoKeyType, cryptoKey, ElGamal) - HELPER(CryptoKeyType, cryptoKey, P256) - HELPER(CryptoKeyType, cryptoKey, P384) - HELPER(CryptoKeyType, cryptoKey, P521) - HELPER(CryptoKeyType, cryptoKey, X25519) - default: - RsWarn("unkown crypto key type:", cryptKeyType); - return false; - } -#undef HELPER - - return true; -} - -} // namespace i2p diff --git a/libretroshare/src/util/i2pcommon.h b/libretroshare/src/util/i2pcommon.h deleted file mode 100644 index f0da0322b..000000000 --- a/libretroshare/src/util/i2pcommon.h +++ /dev/null @@ -1,255 +0,0 @@ -#ifndef I2PCOMMON_H -#define I2PCOMMON_H - -#include -#include -#include -#include - -#include "util/rsrandom.h" -#include "util/radix32.h" -#include "util/rsbase64.h" -#include "util/rsprint.h" -#include "util/rsdebug.h" - -/* - * This header provides common code for i2p related code, namely BOB and SAM3 support. - */ - -namespace i2p { - -static constexpr int8_t kDefaultLength = 3; // i2p default -static constexpr int8_t kDefaultQuantity = 3; // i2p default + 1 -static constexpr int8_t kDefaultVariance = 0; -static constexpr int8_t kDefaultBackupQuantity = 0; - -/** - * @brief The address struct - * This structure is a container for any i2p address/key. The public key is used for addressing and can be (optionally) hashed to generate the .b32.i2p address. - */ -struct address { - std::string base32; - std::string publicKey; - std::string privateKey; - - void clear() { - base32.clear(); - publicKey.clear(); - privateKey.clear(); - } -}; - -/** - * @brief The settings struct - * Common structure with all settings that are shared between any i2p backends - */ -struct settings { - bool enable; - struct address address; - - // connection parameter - int8_t inLength; - int8_t inQuantity; - int8_t inVariance; - int8_t inBackupQuantity; - - int8_t outLength; - int8_t outQuantity; - int8_t outVariance; - int8_t outBackupQuantity; - - void initDefault() { - enable = false; - address.clear(); - - inLength = kDefaultLength; - inQuantity = kDefaultQuantity; - inVariance = kDefaultVariance; - inBackupQuantity = kDefaultBackupQuantity; - - outLength = kDefaultLength; - outQuantity = kDefaultQuantity; - outVariance = kDefaultVariance; - outBackupQuantity = kDefaultBackupQuantity; - } -}; - -/* - Type Type Code Payload Length Total Length Notes - Null 0 0 3 - HashCash 1 varies varies Experimental, unused. Payload contains an ASCII colon-separated hashcash string. - Hidden 2 0 3 Experimental, unused. Hidden routers generally do not announce that they are hidden. - Signed 3 40 or 72 43 or 75 Experimental, unused. Payload contains a 40-byte DSA signature, optionally followed by the 32-byte Hash of the signing Destination. - Multiple 4 varies varies Experimental, unused. Payload contains multiple certificates. - Key 5 4+ 7+ Since 0.9.12. See below for details. -*/ -enum class CertType : uint8_t { - Null = 0, - HashCash = 1, - Hidden = 2, - Signed = 3, - Multiple = 4, - Key = 5 -}; - -/* - * public - Type Type Code Total Public Key Length Since Usage - DSA_SHA1 0 128 0.9.12 Legacy Router Identities and Destinations, never explicitly set - ECDSA_SHA256_P256 1 64 0.9.12 Older Destinations - ECDSA_SHA384_P384 2 96 0.9.12 Rarely if ever used for Destinations - ECDSA_SHA512_P521 3 132 0.9.12 Rarely if ever used for Destinations - RSA_SHA256_2048 4 256 0.9.12 Offline only; never used in Key Certificates for Router Identities or Destinations - RSA_SHA384_3072 5 384 0.9.12 Offline only; never used in Key Certificates for Router Identities or Destinations - RSA_SHA512_4096 6 512 0.9.12 Offline only; never used in Key Certificates for Router Identities or Destinations - EdDSA_SHA512_Ed25519 7 32 0.9.15 Recent Router Identities and Destinations - EdDSA_SHA512_Ed25519ph 8 32 0.9.25 Offline only; never used in Key Certificates for Router Identities or Destinations - reserved (GOST) 9 64 Reserved, see proposal 134 - reserved (GOST) 10 128 Reserved, see proposal 134 - RedDSA_SHA512_Ed25519 11 32 0.9.39 For Destinations and encrypted leasesets only; never used for Router Identities - reserved 65280-65534 Reserved for experimental use - reserved 65535 Reserved for future expansion - - * private - Type Length (bytes) Since Usage - DSA_SHA1 20 Legacy Router Identities and Destinations - ECDSA_SHA256_P256 32 0.9.12 Recent Destinations - ECDSA_SHA384_P384 48 0.9.12 Rarely used for Destinations - ECDSA_SHA512_P521 66 0.9.12 Rarely used for Destinations - RSA_SHA256_2048 512 0.9.12 Offline signing, never used for Router Identities or Destinations - RSA_SHA384_3072 768 0.9.12 Offline signing, never used for Router Identities or Destinations - RSA_SHA512_4096 1024 0.9.12 Offline signing, never used for Router Identities or Destinations - EdDSA_SHA512_Ed25519 32 0.9.15 Recent Router Identities and Destinations - EdDSA_SHA512_Ed25519ph 32 0.9.25 Offline signing, never used for Router Identities or Destinations - RedDSA_SHA512_Ed25519 32 0.9.39 For Destinations and encrypted leasesets only, never used for Router Identities - */ -enum class SigningKeyType : uint16_t { - DSA_SHA1 = 0, - ECDSA_SHA256_P256 = 1, - ECDSA_SHA384_P384 = 2, - ECDSA_SHA512_P521 = 3, - RSA_SHA256_2048 = 4, - RSA_SHA384_3072 = 5, - RSA_SHA512_4096 = 6, - EdDSA_SHA512_Ed25519 = 7, - EdDSA_SHA512_Ed25519ph = 8, - RedDSA_SHA512_Ed25519 = 11 -}; - -/* - * public - Type Type Code Total Public Key Length Usage - ElGamal 0 256 All Router Identities and Destinations - P256 1 64 Reserved, see proposal 145 - P384 2 96 Reserved, see proposal 145 - P521 3 132 Reserved, see proposal 145 - X25519 4 32 Not for use in key certs. See proposal 144 - reserved 65280-65534 Reserved for experimental use - reserved 65535 Reserved for future expansion - - * private - Type Length (bytes) Since Usage - ElGamal 256 All Router Identities and Destinations - P256 32 TBD Reserved, see proposal 145 - P384 48 TBD Reserved, see proposal 145 - P521 66 TBD Reserved, see proposal 145 - X25519 32 0.9.38 Little-endian. See proposal 144 -*/ -enum class CryptoKeyType : uint16_t { - ElGamal = 0, - P256 = 1, - P384 = 2, - P521 = 3, - X25519 = 4 -}; - -static const std::array, 5> cryptoKeyLengths { - /*CryptoKeyType::ElGamal*/ std::make_pair(256, 256), - /*CryptoKeyType::P256, */ std::make_pair( 64, 32), - /*CryptoKeyType::P384, */ std::make_pair( 96, 48), - /*CryptoKeyType::P521, */ std::make_pair(132, 66), - /*CryptoKeyType::X25519,*/ std::make_pair( 32, 32), -}; - -static const std::array, 12> signingKeyLengths { - /*SigningKeyType::DSA_SHA1, */ std::make_pair(128, 128), - /*SigningKeyType::ECDSA_SHA256_P256, */ std::make_pair( 64, 32), - /*SigningKeyType::ECDSA_SHA384_P384, */ std::make_pair( 96, 48), - /*SigningKeyType::ECDSA_SHA512_P521, */ std::make_pair(132, 66), - /*SigningKeyType::RSA_SHA256_2048, */ std::make_pair(256, 512), - /*SigningKeyType::RSA_SHA384_3072, */ std::make_pair(384, 768), - /*SigningKeyType::RSA_SHA512_4096, */ std::make_pair(512,1024), - /*SigningKeyType::EdDSA_SHA512_Ed25519 */ std::make_pair( 32, 32), - /*SigningKeyType::EdDSA_SHA512_Ed25519ph */ std::make_pair( 32, 32), - /*reserved (GOST) */ std::make_pair( 64, 0), - /*reserved (GOST) */ std::make_pair(128, 0), - /*SigningKeyType::RedDSA_SHA512_Ed25519 */ std::make_pair( 32, 32), -}; - -/* - * Key length infos: - * - * BOB private key - * len b64: 884 - * len pln: 663 - * - * BOB public key / destination - * len b64: 516 - * len pln: 387 - * - * SAMv3 private key - * len b64: 908 - * len pln: 679 - * - * SAMv3 public key - * len b64: 516 - * len pln: 387 - * - * Example: - * in bytes, public key only - * 384 (Key) + 3 (Null certificate) = 387 bytes - * 384 (Key) + 7 (key certificate) = 391 bytes - * - * in bytes public + private key - * 384 (Key) + 3 (Null certificate) + 256 (ElGamal) + 20 (DSA_SHA1) = 663 bytes - * 384 (Key) + 7 (key certificate) + 256 (ElGamal) + 32 (EdDSA_SHA512_Ed25519) = 679 bytes - */ -constexpr size_t pubKeyMinLenth_b64 = 516; -constexpr size_t pubKeyMinLenth_bin = 387; -constexpr size_t privKeyMinLenth_b64 = 884; -constexpr size_t privKeyMinLenth_bin = 663; - -/** - * @brief makeOption Creates the string "lhs=rhs" used by BOB and SAM. Converts rhs - * @param lhs option to set - * @param rhs value to set - * @return concatenated string - */ -const std::string makeOption(const std::string &lhs, const int8_t &rhs); - -/** - * @brief keyToBase32Addr generated a base32 address (.b32.i2p) from a given public key - * @param key public key - * @return generated base32 address - */ -std::string keyToBase32Addr(const std::string &key); - -/** - * @brief publicKeyFromPrivate parses the private key and calculates the lenght of the public key - * @param priv private key (which includes the public key) to read - * @return public key used for addressing - */ -std::string publicKeyFromPrivate(const std::string &priv); - -/** - * @brief getKeyTypes returns the name of the utilized algorithms used by the key - * @param key public key - * @param signingKey name of the signing key, e.g. DSA_SHA1 - * @param cryptoKey name of the crpyto key, e.g. ElGamal - * @return true on success, false otherwise - */ -bool getKeyTypes(const std::string &key, std::string &signingKey, std::string &cryptoKey); - -} // namespace i2p - -#endif // I2PCOMMON_H diff --git a/libretroshare/src/util/radix32.h b/libretroshare/src/util/radix32.h deleted file mode 100644 index 46219da17..000000000 --- a/libretroshare/src/util/radix32.h +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: radix32.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2015 Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RADIX32_H -#define RADIX32_H - -#include -#include -#include -#include - -class Radix32 -{ -public: - static std::string encode(const std::vector &in) { - return encode(in.data(), in.size()); - } - - static std::string encode(const uint8_t *data, size_t len) { - std::string out = ""; - - size_t pos = 1; - uint8_t bits = 8, index; - uint16_t tmp = data[0]; // need min. 16 bits here - while (bits > 0 || pos < len) { - if (bits < 5) { - if (pos < len) { - tmp <<= 8; - tmp |= data[pos++] & 0xFF; - bits += 8; - } else { // last byte - tmp <<= (5 - bits); - bits = 5; - } - } - - bits -= 5; - index = (tmp >> bits) & 0x1F; - out.push_back(bintoasc()[index]); - } - - // append padding - while(out.length() % 4 != 0) - out.push_back('='); - - return out; - } - -private: - static const inline char *bintoasc() { static const char bta[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; return bta ; } -}; - -#endif // RADIX32_H diff --git a/libretroshare/src/util/radix64.h b/libretroshare/src/util/radix64.h deleted file mode 100644 index 53dd7c256..000000000 --- a/libretroshare/src/util/radix64.h +++ /dev/null @@ -1,200 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: radix64.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2015 Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -#include "util/rsdeprecate.h" - -/** @deprecated use RsBase64 instead which supports also URL safe encoding */ -class RS_DEPRECATED_FOR(RsBase64) Radix64 -{ -public: - static std::vector decode(const std::string& buffer) - { - char val; - int c = 0, c2;/* init c because gcc is not clever - enough for the continue */ - int idx; - size_t buffer_pos = 0; - - radix64_init(); - - std::vector buf ; - idx = 0; - val = 0; - - for (buffer_pos = 0; buffer_pos < buffer.length(); buffer_pos++) - { - c = buffer[buffer_pos]; - -again: - if (c == '\n' || c == ' ' || c == '\r' || c == '\t') - continue; - else if (c == '=') - { - /* pad character: stop */ - /* some mailers leave quoted-printable - * encoded characters so we try to - * workaround this */ - if (buffer_pos + 2 < buffer.length()) - { - int cc1, cc2, cc3; - cc1 = buffer[buffer_pos]; - cc2 = buffer[buffer_pos + 1]; - cc3 = buffer[buffer_pos + 2]; - - if (isxdigit((unsigned char)cc1) && isxdigit((unsigned char)cc2) && strchr("=\n\r\t ", cc3)) - { - /* well it seems to be the case - - * adjust */ - c = - isdigit((unsigned char)cc1) ? (cc1 - - '0') - : (toupper((unsigned char)cc1) - 'A' + 10); - c <<= 4; - c |= - isdigit((unsigned char)cc2) ? (cc2 - - '0') - : (toupper((unsigned char)cc2) - 'A' + 10); - buffer_pos += 2; - goto again; - } - } - - if (idx == 1) - buf.push_back(val) ;// buf[n++] = val; - break; - } - else if ((c = asctobin()[(c2 = c)]) == 255) - { - /* invalid radix64 character %02x skipped\n", c2; */ - continue; - } - - switch (idx) - { - case 0: - val = c << 2; - break; - case 1: - val |= (c >> 4) & 3; - buf.push_back(val);//buf[n++] = val; - val = (c << 4) & 0xf0; - break; - case 2: - val |= (c >> 2) & 15; - buf.push_back(val);//buf[n++] = val; - val = (c << 6) & 0xc0; - break; - case 3: - val |= c & 0x3f; - buf.push_back(val);//buf[n++] = val; - break; - } - idx = (idx + 1) % 4; - } - - //idx = idx; - - return buf ; - } - - /**************** - * create a radix64 encoded string. - */ - static void encode( - const unsigned char* data, size_t len, std::string& out_string ) - { - char *buffer, *p; - - radix64_init(); - - size_t size = (len + 2) / 3 * 4 +1; - buffer = p = new char[size] ; - - for (; len >= 3; len -= 3, data += 3) - { - *p++ = bintoasc()[(data[0] >> 2) & 077]; - *p++ = - bintoasc()[ - (((data[0] << 4) & 060) | - ((data[1] >> 4) & 017)) & 077]; - *p++ = - bintoasc()[ - (((data[1] << 2) & 074) | - ((data[2] >> 6) & 03)) & 077]; - *p++ = bintoasc()[data[2] & 077]; - } - if (len == 2) - { - *p++ = bintoasc()[(data[0] >> 2) & 077]; - *p++ = - bintoasc()[ - (((data[0] << 4) & 060) | - ((data[1] >> 4) & 017)) & 077]; - *p++ = bintoasc()[((data[1] << 2) & 074)]; - *p++ = '=' ; - } - else if (len == 1) - { - *p++ = bintoasc()[(data[0] >> 2) & 077]; - *p++ = bintoasc()[(data[0] << 4) & 060]; - *p++ = '=' ; - *p++ = '=' ; - } - //*p = 0; - out_string = std::string(buffer,p-buffer) ; - delete[] buffer ; - } - - private: - static inline char *bintoasc() { static char bta[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; return bta ; } - static inline uint8_t *asctobin() { static uint8_t s[256]; return s ; } /* runtime radix64_initd */ - static int& is_radix64_initd() { static int is_inited = false ; return is_inited ; } - - /* hey, guess what: this is a read-only table. - * we don't _care_ if multiple threads get to initialise it - * at the same time, _except_ that is_radix64_initd=1 _must_ - * be done at the end... - */ - static bool radix64_init() - { - if (is_radix64_initd()) - return true; - - int i; - char *s; - - /* build the helpapr_table_t for radix64 to bin conversion */ - for (i = 0; i < 256; i++) - asctobin()[i] = 255; /* used to detect invalid characters */ - for (s = bintoasc(), i = 0; *s; s++, i++) - asctobin()[(int)*s] = i; - - is_radix64_initd() = 1; - return true ; - } -}; diff --git a/libretroshare/src/util/retrodb.cc b/libretroshare/src/util/retrodb.cc deleted file mode 100644 index c9b3566ff..000000000 --- a/libretroshare/src/util/retrodb.cc +++ /dev/null @@ -1,865 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: retrodb.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Christopher Evi-Parker * - * Copyright (C) 2019 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include -#include -#include -#include -#include - -#include "util/rstime.h" -#include "util/retrodb.h" -#include "util/rsdbbind.h" -#include "util/stacktrace.h" -#include "util/rsdir.h" - -//#define RETRODB_DEBUG - -const int RetroDb::OPEN_READONLY = SQLITE_OPEN_READONLY; -const int RetroDb::OPEN_READWRITE = SQLITE_OPEN_READWRITE; -const int RetroDb::OPEN_READWRITE_CREATE = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; - -RetroDb::RetroDb(const std::string& dbPath, int flags, const std::string& key): - mDb(nullptr), mKey(key) -{ - bool alreadyExists = RsDirUtil::fileExists(dbPath); - - int rc = sqlite3_open_v2(dbPath.c_str(), &mDb, flags, nullptr); - if(rc) - { - RsErr() << __PRETTY_FUNCTION__ << " Can't open database, Error: " - << rc << " " << sqlite3_errmsg(mDb) << std::endl; - closeDb(); - print_stacktrace(); - return; - } - - if(alreadyExists) - { - /* If the database has been created by a RetroShare compiled without - * SQLCipher, open it as a plain SQLite database instead of failing - * miserably. If RetroShare has been compiled without SQLCipher but the - * database seems encrypted print a meaningful error message instead of - * crashing miserably. - * At some point we could implement a migration SQLite <-> SQLCipher - * mecanism and suggest it to the user, or give the option to the user - * to choice between plain SQLite or SQLCipher database, is some cases - * such as encrypted FS it might make sense to keep SQLite even if - * SQLCipher is availble for performance, as encryption is already - * provided at FS level. */ - - rc = sqlite3_exec( mDb, "PRAGMA schema_version;", - nullptr, nullptr, nullptr ); - if( rc == SQLITE_OK ) - { -#ifndef NO_SQLCIPHER - RsWarn() << __PRETTY_FUNCTION__ << " The database is not encrypted: " - << dbPath << std::endl; -#endif // ndef NO_SQLCIPHER - - return; - } - else - { -#ifdef NO_SQLCIPHER - RsErr() << __PRETTY_FUNCTION__ << " Error quering schema version." - << " Are you trying to open an encrypted database without " - << "compiling SQLCipher support?" << std::endl << std::endl; - print_stacktrace(); - closeDb(); -#else // def NO_SQLCIPHER - RsInfo() << __PRETTY_FUNCTION__ << " The database seems encrypted: " - << dbPath << std::endl; -#endif // def NO_SQLCIPHER - } - } - -#ifndef NO_SQLCIPHER - if(!mKey.empty()) - { - rc = sqlite3_key(mDb, mKey.c_str(), static_cast(mKey.size())); - - if(rc) - { - RsErr() << __PRETTY_FUNCTION__ << " Can't key database: " << rc - << " " << sqlite3_errmsg(mDb) << std::endl; - closeDb(); - return; - } - } - - char* err = nullptr; - rc = sqlite3_exec(mDb, "PRAGMA cipher_migrate;", nullptr, nullptr, &err); - if (rc != SQLITE_OK) - { - RsErr() << __PRETTY_FUNCTION__ << " Error upgrading database, error " - << "code: " << rc << " " << err << std::endl; - sqlite3_free(err); - } - - // Test DB for correct sqlcipher version - if(sqlite3_exec( - mDb, "PRAGMA user_version;", - nullptr, nullptr, nullptr ) != SQLITE_OK) - { - RsWarn() << __PRETTY_FUNCTION__ << " Failed to open database: " - << dbPath << std::endl; - - //Reopening the database with correct settings - closeDb(); - if(!rc) rc = sqlite3_open_v2(dbPath.c_str(), &mDb, flags, nullptr); - if(!rc && !mKey.empty()) - rc = sqlite3_key(mDb, mKey.c_str(), static_cast(mKey.size())); - if(!rc) - rc = sqlite3_exec( mDb, "PRAGMA kdf_iter = 64000;", - nullptr, nullptr, nullptr ); - if (!rc && (sqlite3_exec( mDb, "PRAGMA user_version;", - nullptr, nullptr, nullptr ) == SQLITE_OK)) - { - RsInfo() << __PRETTY_FUNCTION__ << " Re-trying with settings for " - << "sqlcipher version 3 successed" << std::endl; - } - else - { - RsErr() << __PRETTY_FUNCTION__ << " Re-trying with settings for " - << "sqlcipher version 3 failed, giving up" << std::endl; - closeDb(); - return; - } - } -#endif // ndef NO_SQLCIPHER -} - -RetroDb::~RetroDb() { closeDb(); } - -void RetroDb::closeDb() -{ - // no-op if mDb is nullptr (https://www.sqlite.org/c3ref/close.html) - int rc = sqlite3_close(mDb); - mDb = nullptr; - - Dbg2() << __PRETTY_FUNCTION__ << " sqlite3_close return: " << rc - << std::endl; -} - -#define TIME_LIMIT 3 - -bool RetroDb::execSQL(const std::string &query){ - - // prepare statement - sqlite3_stmt* stm = NULL; - -#ifdef RETRODB_DEBUG - std::cerr << "Query: " << query << std::endl; -#endif - - int rc = sqlite3_prepare_v2(mDb, query.c_str(), query.length(), &stm, NULL); - - // check if there are any errors - if(rc != SQLITE_OK){ - std::cerr << "RetroDb::execSQL(): Error preparing statement\n"; - std::cerr << "Error code: " << sqlite3_errmsg(mDb) - << std::endl; - return false; - } - - - rstime_t stamp = time(NULL); - bool timeOut = false, ok = false; - - while(!timeOut){ - - rc = sqlite3_step(stm); - - if(rc == SQLITE_DONE){ - ok = true; - break; - } - - if(rc != SQLITE_BUSY){ - ok = false; - break; - } - - if(time(NULL) > stamp + TIME_LIMIT) - { - ok = false; - timeOut = true; - } - // TODO add sleep so not to waste - // precious cycles - } - - if(!ok){ - - if(rc == SQLITE_BUSY){ - std::cerr << "RetroDb::execSQL()\n" ; - std::cerr << "SQL timed out!" << std::endl; - }else{ - std::cerr << "RetroDb::execSQL(): Error executing statement (code: " << rc << ")\n"; - std::cerr << "Sqlite Error msg: " << sqlite3_errmsg(mDb) - << std::endl; - std::cerr << "RetroDb::execSQL() Query: " << query << std::endl; - } - } - - // finalise statement or else db cannot be closed - sqlite3_finalize(stm); - return ok; -} - -RetroCursor* RetroDb::sqlQuery(const std::string& tableName, const std::list& columns, - const std::string& selection, const std::string& orderBy){ - - if(tableName.empty() || columns.empty()){ - std::cerr << "RetroDb::sqlQuery(): No table or columns given" << std::endl; - return NULL; - } - - std::string columnSelection; // the column names to return - sqlite3_stmt* stmt = NULL; - std::list::const_iterator it = columns.begin(); - - for(; it != columns.end(); ++it){ - if (it != columns.begin()) { - columnSelection += ","; - } - - columnSelection += *it; - } - - // construct query - // SELECT columnSelection FROM tableName WHERE selection - std::string sqlQuery = "SELECT " + columnSelection + " FROM " + - tableName; - - // add selection clause if present - if(!selection.empty()) - sqlQuery += " WHERE " + selection; - - - // add 'order by' clause if present - if(!orderBy.empty()) - sqlQuery += " ORDER BY " + orderBy + ";"; - else - sqlQuery += ";"; - -#ifdef RETRODB_DEBUG - std::cerr << "RetroDb::sqlQuery(): " << sqlQuery << std::endl; -#endif - - sqlite3_prepare_v2(mDb, sqlQuery.c_str(), sqlQuery.length(), &stmt, NULL); - return (new RetroCursor(stmt)); -} - -bool RetroDb::isOpen() const { - return (mDb==NULL ? false : true); -} - -bool RetroDb::sqlInsert(const std::string &table, const std::string& /* nullColumnHack */, const ContentValue &cv){ - - std::map keyTypeMap; - cv.getKeyTypeMap(keyTypeMap); - std::map::iterator mit = keyTypeMap.begin(); - - // build columns part of insertion - std::string qColumns = table + "("; - - for(; mit != keyTypeMap.end(); ++mit){ - - qColumns += mit->first; - - ++mit; - - // add comma if more columns left - if(mit == keyTypeMap.end()) - qColumns += ")"; // close bracket if at end - else - qColumns += ","; - - --mit; - } - - // build values part of insertion - std::string qValues; - std::list paramBindings; - buildInsertQueryValue(keyTypeMap, cv, qValues, paramBindings); - - // complete insertion query - std::string sqlQuery = "INSERT INTO " + qColumns + " " + qValues; - - bool ok = execSQL_bind(sqlQuery, paramBindings); - -#ifdef RETRODB_DEBUG - std::cerr << "RetroDb::sqlInsert(): " << sqlQuery << std::endl; -#endif - - return ok; -} - -std::string RetroDb::getKey() const -{ - return mKey; -} - -bool RetroDb::beginTransaction() -{ - if (!isOpen()) { - return false; - } - - return execSQL("BEGIN;"); -} - -bool RetroDb::commitTransaction() -{ - if (!isOpen()) { - return false; - } - - return execSQL("COMMIT;"); -} -bool RetroDb::rollbackTransaction() -{ - if (!isOpen()) { - return false; - } - - return execSQL("ROLLBACK;"); -} - -bool RetroDb::execSQL_bind(const std::string &query, std::list ¶mBindings){ - - // prepare statement - sqlite3_stmt* stm = NULL; - -#ifdef RETRODB_DEBUG - std::cerr << "Query: " << query << std::endl; -#endif - - int rc = sqlite3_prepare_v2(mDb, query.c_str(), query.length(), &stm, NULL); - - // check if there are any errors - if(rc != SQLITE_OK){ - std::cerr << "RetroDb::execSQL_bind(): Error preparing statement\n"; - std::cerr << "Error code: " << sqlite3_errmsg(mDb) - << std::endl; - return false; - } - - std::list::iterator lit = paramBindings.begin(); - - for(; lit != paramBindings.end(); ++lit){ - RetroBind* rb = *lit; - - if(!rb->bind(stm)) - { - std::cerr << "\nBind failed for index: " << rb->getIndex() - << std::endl; - } - - delete rb; - rb = NULL; - } - - uint32_t delta = 3; - rstime_t stamp = time(NULL), now = 0; - bool timeOut = false, ok = false; - - while(!timeOut){ - - rc = sqlite3_step(stm); - - if(rc == SQLITE_DONE){ - ok = true; - break; - } - - if(rc != SQLITE_BUSY){ - ok = false; - break; - } - - now = time(NULL); - delta = stamp - now; - - if(delta > TIME_LIMIT){ - ok = false; - timeOut = true; - } - // TODO add sleep so not to waste - // precious cycles - } - - if(!ok){ - - if(rc == SQLITE_BUSY){ - std::cerr << "RetroDb::execSQL_bind()\n" ; - std::cerr << "SQL timed out!" << std::endl; - }else{ - std::cerr << "RetroDb::execSQL_bind(): Error executing statement (code: " << rc << ")\n"; - std::cerr << "Sqlite Error msg: " << sqlite3_errmsg(mDb) - << std::endl; - std::cerr << "RetroDb::execSQL_bind() Query: " << query << std::endl; - } - } - - // finalise statement or else db cannot be closed - sqlite3_finalize(stm); - return ok; -} - -void RetroDb::buildInsertQueryValue(const std::map keyTypeMap, - const ContentValue& cv, std::string& parameter, - std::list& paramBindings) -{ - std::map::const_iterator mit = keyTypeMap.begin(); - - parameter = "VALUES("; - int index = 0; - for(mit=keyTypeMap.begin(); mit!=keyTypeMap.end(); ++mit) - { - - uint8_t type = mit->second; - std::string key = mit->first; - - RetroBind* rb = NULL; - if(ContentValue::BOOL_TYPE == type) - { - bool value; - cv.getAsBool(key, value); - rb = new RsBoolBind(value, ++index); - } - else if( ContentValue::DOUBLE_TYPE == type) - { - double value; - cv.getAsDouble(key, value); - rb = new RsDoubleBind(value, ++index); - } - else if( ContentValue::DATA_TYPE == type) - { - char* value; - uint32_t len; - cv.getAsData(key, len, value); - rb = new RsBlobBind(value, len, ++index); - } - else if ( ContentValue::STRING_TYPE == type) - { - std::string value; - cv.getAsString(key, value); - rb = new RsStringBind(value, ++index); - } - else if ( ContentValue::INT32_TYPE == type) - { - int32_t value = 0; - cv.getAsInt32(key, value); - rb = new RsInt32Bind(value, ++index); - } - else if( ContentValue::INT64_TYPE == type) - { - int64_t value = 0; - cv.getAsInt64(key, value); - rb = new RsInt64bind(value, ++index); - } - - if(rb) - { - paramBindings.push_back(rb); - - ++mit; - - if(mit == keyTypeMap.end()) - parameter += "?"; - else - parameter += "?,"; - - --mit; - } - } - - parameter += ")"; - - -} - -void RetroDb::buildUpdateQueryValue(const std::map keyTypeMap, - const ContentValue& cv, std::string& parameter, - std::list& paramBindings) -{ - std::map::const_iterator mit = keyTypeMap.begin(); - - int index = 0; - for(mit=keyTypeMap.begin(); mit!=keyTypeMap.end(); ++mit) - { - - uint8_t type = mit->second; - std::string key = mit->first; - - RetroBind* rb = NULL; - if(ContentValue::BOOL_TYPE == type) - { - bool value; - cv.getAsBool(key, value); - rb = new RsBoolBind(value, ++index); - } - else if( ContentValue::DOUBLE_TYPE == type) - { - double value; - cv.getAsDouble(key, value); - rb = new RsDoubleBind(value, ++index); - } - else if( ContentValue::DATA_TYPE == type) - { - char* value; - uint32_t len; - cv.getAsData(key, len, value); - rb = new RsBlobBind(value, len, ++index); - } - else if ( ContentValue::STRING_TYPE == type) - { - std::string value; - cv.getAsString(key, value); - rb = new RsStringBind(value, ++index); - } - else if ( ContentValue::INT32_TYPE == type) - { - int32_t value = 0; - cv.getAsInt32(key, value); - rb = new RsInt32Bind(value, ++index); - } - else if( ContentValue::INT64_TYPE == type) - { - int64_t value = 0; - cv.getAsInt64(key, value); - rb = new RsInt64bind(value, ++index); - } - - if(rb) - { - paramBindings.push_back(rb); - - ++mit; - - if(mit == keyTypeMap.end()) - parameter += key + "=?"; - else - parameter += key + "=?,"; - - --mit; - } - } - -} - -bool RetroDb::sqlDelete(const std::string &tableName, const std::string &whereClause, const std::string &/*whereArgs*/){ - - std::string sqlQuery = "DELETE FROM " + tableName; - - if(!whereClause.empty()){ - sqlQuery += " WHERE " + whereClause + ";"; - }else - sqlQuery += ";"; - - return execSQL(sqlQuery); -} - - -bool RetroDb::sqlUpdate(const std::string &tableName, std::string whereClause, const ContentValue& cv){ - - std::string sqlQuery = "UPDATE " + tableName + " SET "; - - - std::map keyTypeMap; - std::map::iterator mit; - cv.getKeyTypeMap(keyTypeMap); - - // build SET part of update - std::string qValues; - std::list paramBindings; - buildUpdateQueryValue(keyTypeMap, cv, qValues, paramBindings); - - if(qValues.empty()) - return false; - else - sqlQuery += qValues; - - // complete update - if(!whereClause.empty()){ - sqlQuery += " WHERE " + whereClause + ";"; - } - else{ - sqlQuery += ";"; - } - - // execute query - return execSQL_bind(sqlQuery, paramBindings); -} - -bool RetroDb::tableExists(const std::string &tableName) -{ - if (!isOpen()) { - return false; - } - - std::string sqlQuery = "PRAGMA table_info(" + tableName + ");"; - - bool result = false; - sqlite3_stmt* stmt = NULL; - - int rc = sqlite3_prepare_v2(mDb, sqlQuery.c_str(), sqlQuery.length(), &stmt, NULL); - if (rc == SQLITE_OK) { - rc = sqlite3_step(stmt); - switch (rc) { - case SQLITE_ROW: - result = true; - break; - case SQLITE_DONE: - break; - default: - std::cerr << "RetroDb::tableExists(): Error executing statement (code: " << rc << ")" - << std::endl; - return false; - } - } else { - std::cerr << "RetroDb::tableExists(): Error preparing statement\n"; - std::cerr << "Error code: " << sqlite3_errmsg(mDb) - << std::endl; - } - - if (stmt) { - sqlite3_finalize(stmt); - } - - return result; -} - -/********************** RetroCursor ************************/ - -RetroCursor::RetroCursor(sqlite3_stmt *stmt) - : mStmt(NULL) { - - open(stmt); -} - -RetroCursor::~RetroCursor(){ - - // finalise statement - if(mStmt){ - sqlite3_finalize(mStmt); - } -} - -bool RetroCursor::moveToFirst(){ - -#ifdef RETRODB_DEBUG - std::cerr << "RetroCursor::moveToFirst()\n"; -#endif - - if(!isOpen()) - return false; - - // reset statement - int rc = sqlite3_reset(mStmt); - - if(rc != SQLITE_OK){ - -#ifdef RETRODB_DEBUG - std::cerr << "Error code: " << rc << std::endl; -#endif - - return false; - } - - rc = sqlite3_step(mStmt); - - if(rc == SQLITE_ROW){ - return true; - } - -#ifdef RETRODB_DEBUG - std::cerr << "Error code: " << rc << std::endl; -#endif - - return false; -} - -bool RetroCursor::moveToLast(){ - -#ifdef RETRODB_DEBUG - std::cerr << "RetroCursor::moveToLast()\n"; -#endif - - if(!isOpen()) - return -1; - - // go to begining - int rc = sqlite3_reset(mStmt); - - if(rc != SQLITE_OK) - return false; - - rc = sqlite3_step(mStmt); - - while(rc == SQLITE_ROW){ - rc = sqlite3_step(mStmt); - } - - if(rc != SQLITE_DONE){ - std::cerr << "Error executing statement (code: " << rc << ")\n" - << std::endl; - return false; - - }else{ - return true; - } -} - -int RetroCursor::columnCount() const { - - if(isOpen()) - return sqlite3_data_count(mStmt); - else - return -1; -} - -bool RetroCursor::isOpen() const { - return !(mStmt == NULL); -} - -bool RetroCursor::close(){ - - if(!isOpen()) - return false; - - - int rc = sqlite3_finalize(mStmt); - mStmt = NULL; - - return (rc == SQLITE_OK); -} - -bool RetroCursor::open(sqlite3_stmt *stm){ - -#ifdef RETRODB_DEBUG - std::cerr << "RetroCursor::open() \n"; -#endif - - if(isOpen()) - close(); - - mStmt = stm; - - // ensure statement is valid - int rc = sqlite3_reset(mStmt); - - if(rc == SQLITE_OK){ - return true; - } - else{ - std::cerr << "Error Opening cursor (code: " << rc << ")\n"; - close(); - return false; - } - -} - -bool RetroCursor::moveToNext(){ - -#ifdef RETRODB_DEBUG - std::cerr << "RetroCursor::moveToNext()\n"; -#endif - - if(!isOpen()) - return false; - - int rc = sqlite3_step(mStmt); - - if(rc == SQLITE_ROW){ - return true; - - }else if(rc == SQLITE_DONE){ // no more results - return false; - } - else if(rc == SQLITE_BUSY){ // should not enter here - std::cerr << "RetroDb::moveToNext()\n" ; - std::cerr << "Busy!, possible multiple accesses to Db" << std::endl - << "serious error"; - - return false; - - }else{ - std::cerr << "Error executing statement (code: " << rc << ")\n"; - return false; - } -} - -int32_t RetroCursor::getInt32(int columnIndex){ - return sqlite3_column_int(mStmt, columnIndex); -} - -int64_t RetroCursor::getInt64(int columnIndex){ - return sqlite3_column_int64(mStmt, columnIndex); -} - -bool RetroCursor::getBool(int columnIndex){ - return sqlite3_column_int(mStmt, columnIndex); -} - -double RetroCursor::getDouble(int columnIndex){ - return sqlite3_column_double(mStmt, columnIndex); -} - -void RetroCursor::getString(int columnIndex, std::string &str){ - str.clear(); - char* raw_str = (char*)sqlite3_column_text(mStmt, columnIndex); - if(raw_str != NULL) - { - str.assign(raw_str); -#ifdef RADIX_STRING - char* buffer = NULL; - size_t buffLen; - Radix64::decode(str, buffer, buffLen); - str.clear(); - if(buffLen != 0) - { - str.assign(buffer, buffLen); - delete[] buffer; - } - else - str.clear(); -#endif - } - else - { - str.clear(); - } -} - -const void* RetroCursor::getData(int columnIndex, uint32_t &datSize){ - - const void* val = sqlite3_column_blob(mStmt, columnIndex); - datSize = sqlite3_column_bytes(mStmt, columnIndex); - - return val; -} - diff --git a/libretroshare/src/util/retrodb.h b/libretroshare/src/util/retrodb.h deleted file mode 100644 index b48415152..000000000 --- a/libretroshare/src/util/retrodb.h +++ /dev/null @@ -1,322 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: retrodb.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012 Christopher Evi-Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#ifdef NO_SQLCIPHER -#include -#else -#include -#endif - -#include -#include -#include -#include - -#include "util/rsdebug.h" -#include "util/rsdbbind.h" -#include "util/contentvalue.h" - -class RetroCursor; - -/*! - * RetroDb provide a means for Retroshare's core and \n - * services to maintain an easy to use random access file via a database \n - * It models itself after android's sqlite functionality \n - * This is essentially unashamedly a clone of Android's SQLiteDatabase interface - */ -class RetroDb -{ -public: - - /*! - * @param dbPath path to data base file - * @param flags determine where to open read only or read/write - */ - RetroDb(const std::string& dbPath, int flags, const std::string& key = ""); - - /*! - * closes db if it is not already closed - */ - ~RetroDb(); - - /*! - * @return key used to encrypt database - */ - std::string getKey() const; - - /*! - * opens sqlite data base - * @param dbPath - * @param flags - * @return false if failed to open, true otherwise - */ - bool openDb(const std::string& dbPath, int flags = OPEN_READONLY); - - /*! - * close the database - */ - void closeDb(); - - /*! - * - * @return false if database is not open, true otherwise - */ - bool isOpen() const; - - /* modifying db */ -public: - - /*! - * Start transaction - * @return true/false - */ - bool beginTransaction(); - - /*! - * Commit transaction - * @return true/false - */ - bool commitTransaction(); - - /*! - * Rollback transaction - * @return true/false - */ - bool rollbackTransaction(); - - /*! - * To a make query which do not return a result \n - * below are the type of queries this method should be used for \n - * ALTER TABLE \n - * CREATE or DROP table / trigger / view / index / virtual table \n - * REINDEX \n - * RELEASE \n - * SAVEPOINT \n - * PRAGMA that returns no data \n - * @param query SQL query - * @return false if there was an sqlite error, true otherwise - */ - bool execSQL(const std::string& query); - - /*! - * inserts a row in a database table - * @param table table you want to insert content values into - * @param nullColumnHack SQL doesn't allow inserting a completely \n - * empty row without naming at least one column name - * @param cv hold entries to insert - * @return true if insertion successful, false otherwise - */ - bool sqlInsert(const std::string& table,const std::string& nullColumnHack, const ContentValue& cv); - - /*! - * update row in a database table - * @param tableName the table on which to apply the UPDATE - * @param whereClause formatted as where statement without 'WHERE' itself - * @param cv Values used to replace current values in accessed record - * @return true if update was successful, false otherwise - */ - bool sqlUpdate(const std::string& tableName, const std::string whereClause, const ContentValue& cv); - - /*! - * Query the given table, returning a Cursor over the result set - * @param tableName the table name - * @param columns list columns that should be returned and their order (the list's order) - * @param selection A filter declaring which rows to return, formatted as \n - * an SQL WHERE clause (excluding the WHERE itself). Passing null will \n - * return all rows for the given table. - * @param order the rows, formatted as an SQL ORDER BY clause (excluding the ORDER BY itself) - * @return cursor over result set, this allocated resource should be free'd after use \n - * column order is in list order. - */ - RetroCursor* sqlQuery(const std::string& tableName, const std::list& columns, - const std::string& selection, const std::string& orderBy); - - /*! - * delete row in an sql table - * @param tableName the table on which to apply the DELETE - * @param whereClause formatted as where statement without 'WHERE' itself - * @return false - */ - bool sqlDelete(const std::string& tableName, const std::string& whereClause, const std::string& whereArgs); - - /*! - * TODO - * defragment database, should be done on databases if many modifications have occured - */ - void vacuum(); - - /*! - * Check if table exist in database - * @param tableName table to check - * @return true/false - */ - bool tableExists(const std::string& tableName); - -public: - - static const int OPEN_READONLY; - static const int OPEN_READWRITE; - static const int OPEN_READWRITE_CREATE; - -private: - - bool execSQL_bind(const std::string &query, std::list& blobs); - - /*! - * Build the "VALUE" part of an insertiong sql query - * @param parameter contains place holder query - * @param paramBindings - */ - void buildInsertQueryValue(const std::map keyMap, const ContentValue& cv, - std::string& parameter, std::list& paramBindings); - - /*! - * Build the "VALUE" part of an insertiong sql query - * @param parameter contains place holder query - * @param paramBindings - */ - void buildUpdateQueryValue(const std::map keyMap, const ContentValue& cv, - std::string& parameter, std::list& paramBindings); - -private: - - sqlite3* mDb; - const std::string mKey; - - RS_SET_CONTEXT_DEBUG_LEVEL(3) -}; - -/*! - * Exposes result set from retrodb query - */ -class RetroCursor { - -public: - - /*! - * Initialises a null cursor - * @warning cursor takes ownership of statement passed to it - */ - RetroCursor(sqlite3_stmt*); - - ~RetroCursor(); - - /*! - * move to first row of results - * @return false if no results - */ - bool moveToFirst(); - - /*! - * move to next row of results - * @return false if no further results - */ - bool moveToNext(); - - /*! - * move to last row of results - * @return false if no result, true otherwise - */ - bool moveToLast(); - - /* data retrieval */ - - /*! - * @return true if cursor is open and active, false otherwise - */ - bool isOpen() const; - - /*! - * cursor is closed, statement used to open cursor is deleted - * @return false if error on close (was already closed, error occured) - */ - bool close(); - - /*! - * - * @return -1 if cursor is in error, otherwise number of columns in result - */ - int32_t columnCount() const ; - - /*! - * Current statement is closed and discarded (finalised) - * before actual opening occurs - * @param stm statement to open cursor on - * @return true if cursor is successfully opened - */ - bool open(sqlite3_stmt* stm); - -public: - /*! - * Returns the value of the requested column as a String. - * @param columnIndex the zero-based index of the target column. - * @return the value of the column as 32 bit integer - */ - int32_t getInt32(int columnIndex); - - /*! - * Returns the value of the requested column as a String. - * @param columnIndex the zero-based index of the target column. - * @return the value of the column as 64 bit integer - */ - int64_t getInt64(int columnIndex); - - /*! - * Returns the value of the requested column as a String. - * @param columnIndex the zero-based index of the target column. - * @return the value of the column as 64 bit float - */ - double getDouble(int columnIndex); - - /*! - * Returns the value of the requested column as a String. - * @param columnIndex the zero-based index of the target column. - * @return the value of the column as bool - */ - bool getBool(int columnIndex); - - /*! - * Returns the value of the requested column as a String. - * @param columnIndex the zero-based index of the target column. - * @return the value of the column as a string - */ - void getString(int columnIndex, std::string& str); - - /*! - * Returns the value of the requested column as a String. - * data returned must be copied, as it is freed after RetroDb - * is closed or destroyed - * @param columnIndex the zero-based index of the target column. - * @return the value of the column as pointer to raw data - */ - const void* getData(int columnIndex, uint32_t& datSize); - - template - inline void getStringT(int columnIndex, T &str){ - std::string temp; - getString(columnIndex, temp); - str = T(temp); - } -private: - sqlite3_stmt* mStmt; -}; diff --git a/libretroshare/src/util/rsbase64.cc b/libretroshare/src/util/rsbase64.cc deleted file mode 100644 index f62c40cef..000000000 --- a/libretroshare/src/util/rsbase64.cc +++ /dev/null @@ -1,198 +0,0 @@ -/******************************************************************************* - * * - * libretroshare base64 encoding utilities * - * * - * Copyright (C) 2015 Retroshare Team * - * Copyright (C) 2020 Gioacchino Mazzurco * - * Copyright (C) 2020 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "util/rsbase64.h" -#include "util/rsdebug.h" - -#if __cplusplus < 201703L -/* Solve weird undefined reference error with C++ < 17 see: - * https://stackoverflow.com/questions/8016780/undefined-reference-to-static-constexpr-char - */ -/*static*/ decltype(RsBase64::bDict) constexpr RsBase64::bDict; -/*static*/ decltype(RsBase64::uDict) constexpr RsBase64::uDict; -/*static*/ decltype(RsBase64::rDict) constexpr RsBase64::rDict; -/*static*/ decltype(RsBase64::sPad) constexpr RsBase64::sPad; -#endif - -/*static*/ void RsBase64::encode( - rs_view_ptr data, size_t len, std::string& outString, - bool padding, bool urlSafe ) -{ - if(!data || !len) - { - outString.clear(); - return; - } - - const char* sDict = urlSafe ? uDict : bDict; - - // Workaround if input and output are the same buffer. - bool inplace = (outString.data() == reinterpret_cast(data)); - std::string tBuff; - std::string& outStr = inplace ? tBuff : outString; - - auto encSize = encodedSize(len, padding); - outStr.resize(encSize); - char* p = &outStr[0]; - - for (; len >= 3; len -= 3, data += 3) - { - *p++ = sDict[ (data[0] >> 2) & 077 ]; - *p++ = sDict[ - (((data[0] << 4) & 060) | ((data[1] >> 4) & 017)) & 077 ]; - *p++ = sDict[ - (((data[1] << 2) & 074) | ((data[2] >> 6) & 03)) & 077 ]; - *p++ = sDict[ data[2] & 077 ]; - } - if (len == 2) - { - *p++ = sDict[ (data[0] >> 2) & 077 ]; - *p++ = sDict[ - (((data[0] << 4) & 060) | ((data[1] >> 4) & 017)) & 077 ]; - *p++ = sDict[ ((data[1] << 2) & 074) ]; - if(padding) *p++ = sPad; - } - else if (len == 1) - { - *p++ = sDict[ (data[0] >> 2) & 077 ]; - *p++ = sDict[ (data[0] << 4) & 060 ]; - if(padding) { *p++ = sPad; *p++ = sPad; } - } - - if(inplace) outString = tBuff; -} - -/*static*/ std::error_condition RsBase64::decode( - const std::string& encoded, std::vector& decoded ) -{ - size_t decSize; std::error_condition ec; - std::tie(decSize, ec) = decodedSize(encoded); - if(!decSize || ec) return ec; - - size_t encSize = encoded.size(); - decoded.resize(decSize); - - for (size_t i = 0, o = 0; i < encSize; i += 4, o += 3) - { - char input0 = encoded[i + 0]; - char input1 = encoded[i + 1]; - - /* At the end of the string, missing bytes 2 and 3 are considered - * padding '=' */ - char input2 = i + 2 < encoded.size() ? encoded[i + 2] : sPad; - char input3 = i + 3 < encSize ? encoded[i + 3] : sPad; - - // If any unknown characters appear, it's an error. - if(!( isBase64Char(input0) && isBase64Char(input1) && - isBase64Char(input2) && isBase64Char(input3) )) - return std::errc::argument_out_of_domain; - - /* If padding appears anywhere but the last 1 or 2 characters, or if - * it appears but encoded.size() % 4 != 0, it's an error. */ - bool at_end = (i + 4 >= encSize); - if ( (input0 == sPad) || (input1 == sPad) || - ( input2 == sPad && !at_end ) || - ( input2 == sPad && input3 != sPad ) || - ( input3 == sPad && !at_end) ) - return std::errc::illegal_byte_sequence; - - uint32_t b0 = rDict[static_cast(input0)] & 0x3f; - uint32_t b1 = rDict[static_cast(input1)] & 0x3f; - uint32_t b2 = rDict[static_cast(input2)] & 0x3f; - uint32_t b3 = rDict[static_cast(input3)] & 0x3f; - - uint32_t stream = (b0 << 18) | (b1 << 12) | (b2 << 6) | b3; - decoded[o + 0] = (stream >> 16) & 0xFF; - if (input2 != sPad) decoded[o + 1] = (stream >> 8) & 0xFF; - /* If there are any stale bits in this from input1, the text is - * malformed. */ - else if (((stream >> 8) & 0xFF) != 0) - return std::errc::invalid_argument; - - if (input3 != sPad) decoded[o + 2] = (stream >> 0) & 0xFF; - /* If there are any stale bits in this from input2, the text is - * malformed. */ - else if (((stream >> 0) & 0xFF) != 0) - return std::errc::invalid_argument; - } - - return std::error_condition(); -} - -/*static*/ size_t RsBase64::encodedSize(size_t decodedSize, bool padding) -{ - if(!decodedSize) return 0; - - // Thanks https://stackoverflow.com/a/45401395 - if(padding) return ceilDivision(decodedSize, 3) * 4; - return ceilDivision(decodedSize * 8, 6); -} - -/*static*/ std::tuple RsBase64::decodedSize( - const std::string& input ) -{ - const auto success = [](size_t val) - { return std::make_tuple(val, std::error_condition()); }; - - if(input.empty()) return success(0); - - auto mod = input.size() % 4; - if(mod == 1) std::make_tuple(0, std::errc::invalid_argument); - - size_t padded_size = ((input.size() + 3) / 4) * 3; - if (mod >= 2 || (mod == 0 && input[input.size() - 1] == sPad)) - { - /* If the last byte is '=', or the input size % 4 is 2 or 3 (thus - * there are implied '='s), then the actual size is 1-2 bytes - * smaller. */ - if ( mod == 2 || (mod == 0 && input[input.size() - 2] == sPad) ) - { - /* If the second-to-last byte is also '=', or the input - * size % 4 is 2 (implying a second '='), then the actual size - * is 2 bytes smaller. */ - return success(padded_size - 2); - } - else - { - /* Otherwise it's just the last character and the actual size is - * 1 byte smaller. */ - return success(padded_size - 1); - } - } - return success(padded_size); -} - -/*static*/ size_t RsBase64::stripInvalid( - const std::string& in, std::string& out ) -{ - size_t strippedCnt = 0; - auto inSize = in.size(); - out.resize(inSize); - for(size_t i = 0; i < inSize; ++i) - { - if(isBase64Char(in[i])) out[i-strippedCnt] = in[i]; - else ++strippedCnt; - } - out.resize(inSize-strippedCnt); - return strippedCnt; -} diff --git a/libretroshare/src/util/rsbase64.h b/libretroshare/src/util/rsbase64.h deleted file mode 100644 index 819870089..000000000 --- a/libretroshare/src/util/rsbase64.h +++ /dev/null @@ -1,144 +0,0 @@ -/******************************************************************************* - * * - * libretroshare base64 encoding utilities * - * * - * Copyright (C) 2015 Retroshare Team * - * Copyright (C) 2020 Gioacchino Mazzurco * - * Copyright (C) 2020 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include -#include - -#include "util/rsmemory.h" - -/** - * Implement methods to encode e decode to base64 format as per RFC 4648 - * This implementation support also the file name and URL safe base64url format - * @see https://tools.ietf.org/html/rfc4648#section-5 - */ -class RsBase64 -{ -public: - /// Enable base64url by default - static constexpr bool DEFAULT_URL_SAFE = true; - - /// Disable padding by default - static constexpr bool DEFAULT_PADDING = false; - - /** - * @brief Encode arbitrary data to base64 - * @param[in] data pointer to the input data buffer - * @param[in] len lenght of the input buffer - * @param[out] outString storage for the resulting base64 encoded string - * @param[in] padding set to true to enable padding to 32 bits - * @param[in] urlSafe pass true for base64url format, false for base64 format - */ - static void encode( - rs_view_ptr data, size_t len, - std::string& outString, - bool padding = DEFAULT_PADDING, bool urlSafe = DEFAULT_URL_SAFE ); - - /** - * @brief Decode data from a base64 encoded string - * @param[in] encoded encoded string - * @param[out] decoded storage for decoded data - * @return success or error details - */ - static std::error_condition decode( - const std::string& encoded, std::vector& decoded ); - - /** - * Remove invalid characters from base64 encoded string. - * Often when copy and pasting from one progam to another long base64 - * strings, new lines, spaces or other characters end up polluting the - * original text. This function is useful to cleanup the pollution before - * attempting to decode the message. - * @param in input string - * @param out storage for cleaned string. In-place operation in supported so - * the same input string may be passed. - * @return count of stripped invalid characters - */ - static size_t stripInvalid(const std::string& in, std::string& out); - - /** - * Calculate how much bytes are needed to store the base64 encoded version - * of some data. - * @param decodedSize size of the original decoded data - * @param padding true to enable base64 padding - * @return how much bytes would take to store the encoded version - */ - static size_t encodedSize( - size_t decodedSize, bool padding = DEFAULT_PADDING ); - - /** - * @brief Calculate how much space is needed to store the decoded version of - * a base64 encoded string - * @param input encoded string - * @return decoded size, plus error information on failure - */ - static std::tuple decodedSize( - const std::string& input ); - -private: - /// base64 conversion table - static constexpr char bDict[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - /// base64url conversion table - static constexpr char uDict[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; - - /// This reverse table supports both base64 and base64url - static constexpr int8_t rDict[256] = { - /* index +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 */ - /* 0 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /* 16 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /* 32 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63, - /* 48 */ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 0, -1, -1, - /* 64 */ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - /* 80 */ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, - /* 96 */ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - /* 112 */ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, - /* 128 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /* 144 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /* 160 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /* 176 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /* 192 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /* 208 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /* 224 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - /* 240 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - }; - - /// base64 padding character - static constexpr char sPad = '='; - - /** Check if given character is valid either for base64 or for base64url - * @param c character to check - * @return true if valid false otherwise - */ - static inline bool isBase64Char(char c) - { return rDict[static_cast(c)] >= 0; } - - /** Perform ceil division without floating point operations */ - static inline size_t ceilDivision(size_t dividend, size_t divisor) - { return (dividend + divisor - 1) / divisor; } -}; diff --git a/libretroshare/src/util/rsdbbind.cc b/libretroshare/src/util/rsdbbind.cc deleted file mode 100644 index db5233ba8..000000000 --- a/libretroshare/src/util/rsdbbind.cc +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsbdbind.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 Christopher Evi-Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "rsdbbind.h" - -RsDoubleBind::RsDoubleBind(double value, int index) - : RetroBind(DOUBLE, index), mValue(value) {} - -RsStringBind::RsStringBind(const std::string& value, int index) - : RetroBind(STRING, index), mValue(value) {} - -RsInt32Bind::RsInt32Bind(int32_t value, int index) - : RetroBind(INT32, index), mValue(value) {} - -RsInt64bind::RsInt64bind(int64_t value, int index) - : RetroBind(INT64, index), mValue(value) {} - -RsBoolBind::RsBoolBind(bool value, int index) - : RetroBind(BOOL, index), mValue(value) {} - -RsBlobBind::RsBlobBind(char* data, uint32_t dataLen, int index) - : RetroBind(BLOB, index), mData(data), mDataLen(dataLen) {} - -bool RsDoubleBind::bind(sqlite3_stmt* const stm) const -{ - return (SQLITE_OK == sqlite3_bind_double(stm, getIndex(), mValue)); -} - -bool RsStringBind::bind(sqlite3_stmt* const stm) const -{ - return (SQLITE_OK == sqlite3_bind_text(stm, getIndex(), mValue.c_str(), mValue.size(), SQLITE_TRANSIENT)); -} - -bool RsInt32Bind::bind(sqlite3_stmt* const stm) const -{ - return (SQLITE_OK == sqlite3_bind_int(stm, getIndex(), mValue)); -} - -bool RsInt64bind::bind(sqlite3_stmt* const stm) const -{ - return (SQLITE_OK == sqlite3_bind_int64(stm, getIndex(), mValue)); -} - -bool RsBoolBind::bind(sqlite3_stmt* const stm) const -{ - return (SQLITE_OK == sqlite3_bind_int(stm, getIndex(), mValue ? 1 : 0)); -} - -bool RsBlobBind::bind(sqlite3_stmt* const stm) const -{ - return (SQLITE_OK == sqlite3_bind_blob(stm, getIndex(), mData, mDataLen, SQLITE_TRANSIENT)); -} - diff --git a/libretroshare/src/util/rsdbbind.h b/libretroshare/src/util/rsdbbind.h deleted file mode 100644 index aa41e5b3e..000000000 --- a/libretroshare/src/util/rsdbbind.h +++ /dev/null @@ -1,101 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsbdbind.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 Christopher Evi-Parker * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RSDBBIND_H_ -#define RSDBBIND_H_ - -#include -#include - -#ifdef NO_SQLCIPHER -#include -#else -#include -#endif - -class RetroBind -{ -public: - - enum BindType { BLOB=1, STRING, INT32, INT64, DOUBLE, BOOL } ; - RetroBind(const BindType& type, int index) : mIndex(index), mType(type) {} - - virtual bool bind(sqlite3_stmt* const stm) const = 0; - BindType getType() const { return mType; } - inline int getIndex() const { return mIndex;} - virtual ~RetroBind() {} - -private: - int mIndex; - BindType mType; -}; - -class RsDoubleBind : public RetroBind -{ -public: - RsDoubleBind(double value, int index); - bool bind(sqlite3_stmt* const stm) const; - double mValue; -}; - -class RsStringBind : public RetroBind -{ -public: - RsStringBind(const std::string& value, int index); - bool bind(sqlite3_stmt* const stm) const ; - std::string mValue; -}; - -class RsInt32Bind : public RetroBind -{ -public: - RsInt32Bind(int32_t value, int index); - bool bind(sqlite3_stmt* const stm) const ; - int32_t mValue; -}; - -class RsInt64bind : public RetroBind -{ -public: - RsInt64bind(int64_t value, int index); - bool bind(sqlite3_stmt* const stm) const ; - int64_t mValue; -}; - -class RsBoolBind : public RetroBind -{ -public: - RsBoolBind(bool value, int index); - bool bind(sqlite3_stmt* const stm) const ; - bool mValue; -}; - -class RsBlobBind : public RetroBind -{ -public: - RsBlobBind(char* data, uint32_t dataLen, int index); - bool bind(sqlite3_stmt* const stm) const; - char* mData; - uint32_t mDataLen; -}; - - -#endif /* RSDBBIND_H_ */ diff --git a/libretroshare/src/util/rsdebug.cc b/libretroshare/src/util/rsdebug.cc deleted file mode 100644 index b87dc2c37..000000000 --- a/libretroshare/src/util/rsdebug.cc +++ /dev/null @@ -1,264 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsdebug.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2008 Robert Fernie * - * Copyright (C) 2020-2021 Gioacchino Mazzurco * - * Copyright (C) 2020-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include - -#include "util/rsdebug.h" - -std::ostream &operator<<(std::ostream& out, const std::error_condition& err) -{ - return out << " error: " << err.value() << " " << err.message() - << " category: " << err.category().name(); -} - -std::string rsErrorNotInCategory(int errNum, const std::string& categoryName) -{ - return "Error message for error: " + std::to_string(errNum) + - " not available in category: " + categoryName; -} - -std::error_condition rs_errno_to_condition(int errno_code) -{ return std::make_error_condition(static_cast(errno_code)); } - - -std::ostream& hex_dump(std::ostream& os, const void *buffer, - std::size_t bufsize, bool showPrintableChars /*= true*/) -{ - if (buffer == nullptr) { - return os; - } - auto oldFormat = os.flags(); - auto oldFillChar = os.fill(); - constexpr std::size_t maxline{8}; - // create a place to store text version of string - char renderString[maxline+1]; - char *rsptr{renderString}; - // convenience cast - const unsigned char *buf{reinterpret_cast(buffer)}; - - for (std::size_t linecount=maxline; bufsize; --bufsize, ++buf) { - os << std::setw(2) << std::setfill('0') << std::hex - << static_cast(*buf) << ' '; - *rsptr++ = std::isprint(*buf) ? *buf : '.'; - if (--linecount == 0) { - *rsptr++ = '\0'; // terminate string - if (showPrintableChars) { - os << " | " << renderString; - } - os << '\n'; - rsptr = renderString; - linecount = std::min(maxline, bufsize); - } - } - // emit newline if we haven't already - if (rsptr != renderString) { - if (showPrintableChars) { - for (*rsptr++ = '\0'; rsptr != &renderString[maxline+1]; ++rsptr) { - os << " "; - } - os << " | " << renderString; - } - os << '\n'; - } - - os.fill(oldFillChar); - os.flags(oldFormat); - return os; -} - -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -/// All the following lines are DEPRECATED!! - -#include -#include - -#include "util/rsthreads.h" -#include "util/rsdir.h" -#include "util/rstime.h" - -const int RS_DEBUG_STDERR = 1; /* stuff goes to stderr */ -const int RS_DEBUG_LOGFILE = 2; /* stuff goes to logfile */ -const int RS_DEBUG_LOGCRASH = 3; /* minimal logfile stored after crashes */ -const int RS_DEBUG_LOGC_MAX = 100000; /* max length of crashfile log */ -const int RS_DEBUG_LOGC_MIN_SAVE = 100; /* min length of crashfile log */ - -static RsLog::logLvl defaultLevel = RsLog::Warning; -static FILE *ofd = stderr; - -static int debugMode = RS_DEBUG_STDERR; -static int lineCount = 0; -static std::string crashfile; -static int debugTS = 0; - -static RsMutex logMtx("logMtx"); - -int locked_setDebugFile(const char *fname); - -int setDebugCrashMode(const char *cfile) -{ - RsStackMutex stack(logMtx); /******** LOCKED ****************/ - crashfile = cfile; - /* if the file exists - then we crashed, save it */ - FILE *tmpin = RsDirUtil::rs_fopen(crashfile.c_str(), "r"); - if (tmpin) - { - /* see how long it is */ - fseek(tmpin, 0, SEEK_END); - if (ftell(tmpin) > RS_DEBUG_LOGC_MIN_SAVE) - { - std::string crashfile_save = crashfile + "-save"; - fprintf(stderr, "Detected Old Crash File: %s\n", crashfile.c_str()); - fprintf(stderr, "Copying to: %s\n", crashfile_save.c_str()); - - /* go back to the start */ - fseek(tmpin, 0, SEEK_SET); - - FILE *tmpout = RsDirUtil::rs_fopen(crashfile_save.c_str(), "w"); - int da_size = 10240; - char dataarray[da_size]; /* 10k */ - unsigned int da_read = 0; - - if (!tmpout) - { - fprintf(stderr, "Failed to open CrashSave\n"); - fclose(tmpin); - return -1; - } - while(0 != (da_read = fread(dataarray, 1, da_size, tmpin))) - { - if (da_read != fwrite(dataarray, 1, da_read, tmpout)) - { - fprintf(stderr, "Failed writing to CrashSave\n"); - fclose(tmpout); - fclose(tmpin); - return -1; - } - } - fclose(tmpout); - fclose(tmpin); - } - else - { - fprintf(stderr, "Negligable Old CrashLog, ignoring\n"); - fclose(tmpin); - } - } - - if (0 < locked_setDebugFile(crashfile.c_str())) - { - fprintf(stderr, "Switching To CrashLog Mode!\n"); - debugMode = RS_DEBUG_LOGCRASH; - lineCount = 0; - debugTS = time(NULL); - } - return 1; -} - -int setDebugFile(const char *fname) -{ - RsStackMutex stack(logMtx); /******** LOCKED ****************/ - return locked_setDebugFile(fname); -} - -int locked_setDebugFile(const char *fname) -{ - if (NULL != (ofd = RsDirUtil::rs_fopen(fname, "w"))) - { - fprintf(stderr, "Logging redirected to %s\n", fname); - debugMode = RS_DEBUG_LOGFILE; - return 1; - } - else - { - ofd = stderr; - debugMode = RS_DEBUG_STDERR; - fprintf(stderr, "Logging redirect to %s FAILED\n", fname); - return -1; - } -} - -int setOutputLevel(RsLog::logLvl lvl) -{ - RsStackMutex stack(logMtx); /******** LOCKED ****************/ - return defaultLevel = lvl; -} - -void rslog(const RsLog::logLvl lvl, RsLog::logInfo *info, const std::string &msg) -{ - // skipp when log level is set to 'None' - // NB: when default is set to 'None' the later check will always fail -> no need to check it here - if(info->lvl == RsLog::None) - return; - - bool process = info->lvl == RsLog::Default ? (lvl <= defaultLevel) : lvl <= info->lvl; - if(!process) - return; - - { - RS_STACK_MUTEX(logMtx); - time_t t = time(NULL); // Don't use rstime_t here or ctime break on windows - - if (debugMode == RS_DEBUG_LOGCRASH) - { - if (lineCount > RS_DEBUG_LOGC_MAX) - { - /* restarting logging */ - fprintf(stderr, "Rolling over the CrashLog\n"); - fclose(ofd); - ofd = NULL; - if (0 < locked_setDebugFile(crashfile.c_str())) - { - fprintf(ofd, "Debug CrashLog:"); - fprintf(ofd, " retroShare uptime %ld secs\n", - t-debugTS); - - debugMode = RS_DEBUG_LOGCRASH; - lineCount = 0; - } - else - { - fprintf(stderr, "Rollover Failed!\n"); - } - } - } - - std::string timestr = ctime(&t); - std::string timestr2 = timestr.substr(0,timestr.length()-1); - /* remove the endl */ - fprintf(ofd, "(%s Z: %s, lvl: %u): %s \n", - timestr2.c_str(), info->name.c_str(), (unsigned int)info->lvl, msg.c_str()); - fflush(ofd); - - fprintf(stdout, "(%s Z: %s, lvl: %u): %s \n", - timestr2.c_str(), info->name.c_str(), (unsigned int)info->lvl, msg.c_str()); - lineCount++; - } -} -/// All the lines before are DEPRECATED!! -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// diff --git a/libretroshare/src/util/rsdebug.h b/libretroshare/src/util/rsdebug.h deleted file mode 100644 index 25d1f1969..000000000 --- a/libretroshare/src/util/rsdebug.h +++ /dev/null @@ -1,372 +0,0 @@ -/******************************************************************************* - * RetroShare debugging utilities * - * * - * Copyright (C) 2004-2008 Robert Fernie * - * Copyright (C) 2019-2021 Gioacchino Mazzurco * - * Copyright (C) 2020-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include - -#ifdef __ANDROID__ -# include -#else // def __ANDROID__ -# include -# include -# include -#endif // def __ANDROID__ - - -#include "util/rsjson.h" - - -#ifdef __ANDROID__ -enum class RsLoggerCategories -{ - DEBUG = ANDROID_LOG_DEBUG, - INFO = ANDROID_LOG_INFO, - WARNING = ANDROID_LOG_WARN, - ERROR = ANDROID_LOG_ERROR, - FATAL = ANDROID_LOG_FATAL -}; -#else // def __ANDROID__ -enum class RsLoggerCategories -{ - DEBUG = 'D', - INFO = 'I', - WARNING = 'W', - ERROR = 'E', - FATAL = 'F' -}; -#endif // def __ANDROID__ - - -/** Stream helper for std::error_condition */ -std::ostream &operator<<(std::ostream& out, const std::error_condition& err); - -/** Provide unkown error message for all error categories to avoid duplicating - * the message around */ -std::string rsErrorNotInCategory(int errNum, const std::string& categoryName); - -/** Convert C errno codes to modern C++11 std::error_condition, this is quite - * useful to use toghether with C functions used around the code like `malloc`, - * `socket` etc to let errors bubble up comprensibly to upper layers C++11 code - */ -std::error_condition rs_errno_to_condition(int errno_code); - - -template -struct t_RsLogger : std::ostringstream -{ - t_RsLogger() { setPrefix(); } - ~t_RsLogger() { flush(); } - - /** Offer variadic style, this doesn't supports things like std::endl as - * paramether but when used toghether with conditional debugging macros - * reduces binary size as paramethers of suppressed calls are not evaluated - * and literally disappear in preprocessing fase @see RsDbg */ - template - explicit inline t_RsLogger(Args&&... args) - { - setPrefix(); - - /* Combine initializer list and comma operator so the compiler unpack - * template arguments and feed our own stream without recursion - * see https://stackoverflow.com/a/27375675 */ - using expander = int[]; - (void) expander {0, (void((*this) << std::forward(args)), 0)...}; - } - - /** Dump buffer stream to log */ - void flush() - { -#ifdef __ANDROID__ - __android_log_write( - static_cast(CATEGORY), - "RetroShare", str().c_str() ); -#else // def __ANDROID__ - (*this) << std::endl; - std::cerr << str(); -#endif // def __ANDROID__ - str() = ""; - } - -private: -#ifdef __ANDROID__ - inline void setPrefix() {} -#else // def __ANDROID__ - void setPrefix() - { - using namespace std::chrono; - const auto now = system_clock::now(); - const auto sec = time_point_cast(now); - const auto msec = duration_cast(now - sec); - (*this) << static_cast(CATEGORY) << " " - << sec.time_since_epoch().count() << "." - << std::setfill('0') << std::setw(3) << msec.count() << " "; - } -#endif // def __ANDROID__ -}; - - -/** - * Comfortable debug message logging, supports both variadic style and chaining - * style like std::cerr. - * Can be easly and selectively disabled at compile time. - * To reduce generated binary size and performance impact when debugging is - * disabled without too many \#ifdef around the code combining the variadic - * style with the leveled debugging macros is the way to go. - * - * To selectively debug your file you just need to include the header of desired - * debugging level (0 to 4) -@code{.cpp} -#include "util/rsdebuglevel2.h" -@endcode - * Then where you want to print debug messages use -@code{.cpp} -RS_DBG0("Hello 0 ", "my debug ", my_variable) << " message " << variable2; -RS_DBG1("Hello 1 ", "my debug ", my_variable) << " message " << variable2; -RS_DBG2("Hello 2 ", "my debug ", my_variable) << " message " << variable2; -RS_DBG3("Hello 3 ", "my debug ", my_variable) << " message " << variable2; -RS_DBG4("Hello 4 ", "my debug ", my_variable) << " message " << variable2; -@endcode - * To change the debugging level just include a different level header like - * `util/rsdebuglevel1.h`, debug messages with lower or equal level then the - * included header will be printed, the others will not. - * Remember then on messages with debug level higher then the included the - * paramethers you pass as macro arguments (variadic style) will disappear in - * the preprocessing phase, so their evaluation will not be included in the - * final binary and not executed at runtime, instead the paramether passed with - * `<<` (chaining style) will be in the compiled binary and evaluated at runtime - * even if are not printed, due to how C++ is made it is not possible to avoid - * this, so we suggest to use variadic style for debug messages. - */ -using RsDbg = t_RsLogger; -#define RS_DBG(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -/** - * Comfortable log information reporting helper, supports chaining like - * std::cerr. - * To report an information message you can just write: -@code{.cpp} -RsInfo() << __PRETTY_FUNCTION__ << "My information message" << std::cerr; -@endcode - */ -using RsInfo = t_RsLogger; -#define RS_INFO(...) RsInfo(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -/// Similar to @see RsInfo but for warning messages -using RsWarn = t_RsLogger; -#define RS_WARN(...) RsWarn(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -/// Similar to @see RsInfo but for error messages -using RsErr = t_RsLogger; -#define RS_ERR(...) RsErr(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -/** Similar to @see RsInfo but for fatal errors (the ones which cause RetroShare - * to terminate) messages */ -using RsFatal = t_RsLogger; -#define RS_FATAL(...) RsFatal(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - - -/** - * Keeps compatible syntax with RsDbg but explicitely do nothing in a way that - * any modern compiler should be smart enough to optimize out all the function - * calls. - */ -struct RsNoDbg -{ - inline RsNoDbg() = default; - template inline explicit RsNoDbg(Args...) {} - - /** This match most of the types, but might be not enough for templated - * types */ - template - inline RsNoDbg& operator<<(const T&) { return *this; } - - /// needed for manipulators and things like std::endl - inline RsNoDbg& operator<<(std::ostream& (*/*pf*/)(std::ostream&)) - { return *this; } - - /** Do nothing. Just for code compatibility with other logging classes */ - inline void flush() {} -}; - - -//From https://codereview.stackexchange.com/a/165162 -/** - * @brief hex_dump: Send Hexadecimal Dump to stream - * @param os: Output Stream - * @param buffer: Buffer to send - * @param bufsize: Buffer's size - * @param showPrintableChars: If must send printable Char too - * @return - * basic string: - * 61 62 63 64 65 66 31 32 | abcdef12 - * 33 34 35 36 00 7a 79 78 | 3456.zyx - * 77 76 75 39 38 37 36 35 | wvu98765 - * 34 45 64 77 61 72 64 00 | 4Edward. - * - * wide string: - * 41 00 00 00 20 00 00 00 | A... ... - * 77 00 00 00 69 00 00 00 | w...i... - * 64 00 00 00 65 00 00 00 | d...e... - * 20 00 00 00 73 00 00 00 | ...s... - * 74 00 00 00 72 00 00 00 | t...r... - * 69 00 00 00 6e 00 00 00 | i...n... - * 67 00 00 00 2e 00 00 00 | g....... - * - * a double - * 49 92 24 49 92 24 09 40 | I.$I.$.@ - */ -std::ostream& hex_dump(std::ostream& os, const void *buffer, - std::size_t bufsize, bool showPrintableChars = true); - -/** - * @brief The hexDump struct - * Enable to print dump calling like that: - * const char test[] = "abcdef123456\0zyxwvu987654Edward"; - * RsDbg()< * - * Copyright (C) 2020 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -// #pragma once // This is commented out on purpose! - -#include - -#undef RS_DEBUG_LEVEL -#define RS_DEBUG_LEVEL 0 - -#undef RS_DBG0 -#define RS_DBG0(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG1 -#define RS_DBG1(...) RsNoDbg("") - -#undef RS_DBG2 -#define RS_DBG2(...) RsNoDbg("") - -#undef RS_DBG3 -#define RS_DBG3(...) RsNoDbg("") - -#undef RS_DBG4 -#define RS_DBG4(...) RsNoDbg("") diff --git a/libretroshare/src/util/rsdebuglevel1.h b/libretroshare/src/util/rsdebuglevel1.h deleted file mode 100644 index 7e968e402..000000000 --- a/libretroshare/src/util/rsdebuglevel1.h +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************* - * RetroShare debugging level * - * * - * Copyright (C) 2020 Gioacchino Mazzurco * - * Copyright (C) 2020 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -// #pragma once // This is commented out on purpose! - -#include - -#undef RS_DEBUG_LEVEL -#define RS_DEBUG_LEVEL 1 - -#undef RS_DBG0 -#define RS_DBG0(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG1 -#define RS_DBG1(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG2 -#define RS_DBG2(...) RsNoDbg() - -#undef RS_DBG3 -#define RS_DBG3(...) RsNoDbg() - -#undef RS_DBG4 -#define RS_DBG4(...) RsNoDbg() diff --git a/libretroshare/src/util/rsdebuglevel2.h b/libretroshare/src/util/rsdebuglevel2.h deleted file mode 100644 index 2cbf1a224..000000000 --- a/libretroshare/src/util/rsdebuglevel2.h +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************* - * RetroShare debugging level * - * * - * Copyright (C) 2020 Gioacchino Mazzurco * - * Copyright (C) 2020 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -// #pragma once // This is commented out on purpose! - -#include - -#undef RS_DEBUG_LEVEL -#define RS_DEBUG_LEVEL 2 - -#undef RS_DBG0 -#define RS_DBG0(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG1 -#define RS_DBG1(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG2 -#define RS_DBG2(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG3 -#define RS_DBG3(...) RsNoDbg() - -#undef RS_DBG4 -#define RS_DBG4(...) RsNoDbg() diff --git a/libretroshare/src/util/rsdebuglevel3.h b/libretroshare/src/util/rsdebuglevel3.h deleted file mode 100644 index 53bcbfe9f..000000000 --- a/libretroshare/src/util/rsdebuglevel3.h +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************* - * RetroShare debugging level * - * * - * Copyright (C) 2020 Gioacchino Mazzurco * - * Copyright (C) 2020 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -// #pragma once // This is commented out on purpose! - -#include - -#undef RS_DEBUG_LEVEL -#define RS_DEBUG_LEVEL 3 - -#undef RS_DBG0 -#define RS_DBG0(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG1 -#define RS_DBG1(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG2 -#define RS_DBG2(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG3 -#define RS_DBG3(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG4 -#define RS_DBG4(...) RsNoDbg() diff --git a/libretroshare/src/util/rsdebuglevel4.h b/libretroshare/src/util/rsdebuglevel4.h deleted file mode 100644 index f8697cad8..000000000 --- a/libretroshare/src/util/rsdebuglevel4.h +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************* - * RetroShare debugging level * - * * - * Copyright (C) 2020 Gioacchino Mazzurco * - * Copyright (C) 2020 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -// #pragma once // This is commented out on purpose! - -#include - -#undef RS_DEBUG_LEVEL -#define RS_DEBUG_LEVEL 4 - -#undef RS_DBG0 -#define RS_DBG0(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG1 -#define RS_DBG1(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG2 -#define RS_DBG2(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG3 -#define RS_DBG3(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) - -#undef RS_DBG4 -#define RS_DBG4(...) RsDbg(__PRETTY_FUNCTION__, " ", __VA_ARGS__) diff --git a/libretroshare/src/util/rsdeprecate.h b/libretroshare/src/util/rsdeprecate.h deleted file mode 100644 index 560f91c44..000000000 --- a/libretroshare/src/util/rsdeprecate.h +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsdebug.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2016 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) -# define RS_DEPRECATED __attribute__((__deprecated__)) -#elif defined(_MSC_VER) && (_MSC_VER >= 1300) -# define RS_DEPRECATED __declspec(deprecated) -#else -# define RS_DEPRECATED -#endif - -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) -# define RS_DEPRECATED_FOR(f) __attribute__((__deprecated__("Use '" #f "' instead"))) -#elif defined(_MSC_FULL_VER) && (_MSC_FULL_VER > 140050320) -# define RS_DEPRECATED_FOR(f) __declspec(deprecated("is deprecated. Use '" #f "' instead")) -#else -# define RS_DEPRECATED_FOR(f) RS_DEPRECATED -#endif diff --git a/libretroshare/src/util/rsdir.cc b/libretroshare/src/util/rsdir.cc deleted file mode 100644 index 54cffa533..000000000 --- a/libretroshare/src/util/rsdir.cc +++ /dev/null @@ -1,1446 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsdir.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2007 Robert Fernie * - * Copyright (C) 2020-2021 Gioacchino Mazzurco * - * Copyright (C) 2020-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -// Includes for directory creation. -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "util/rsdir.h" -#include "util/rsstring.h" -#include "util/rsrandom.h" -#include "util/rstime.h" -#include "util/rsmemory.h" -#include "util/folderiterator.h" -#include "retroshare/rstypes.h" -#include "retroshare/rsnotify.h" -#include "rsthreads.h" - -#include "rs_android/largefile_retrocompat.hpp" - -#if defined(WIN32) || defined(__CYGWIN__) -#include "util/rsstring.h" -#include "wtypes.h" -#include -#else -#include -#endif - -#ifndef __GLIBC__ -#define canonicalize_file_name(p) realpath(p, NULL) -#endif - -#ifdef WINDOWS_SYS -#define FIND_OF_DIRECTORY_SEPARATOR "/\\\0" -#else -#define FIND_OF_DIRECTORY_SEPARATOR '/' -#endif - - -/**** - * #define RSDIR_DEBUG 1 - ****/ - -#if __cplusplus < 201703L -bool std::filesystem::create_directories(const std::string& path) -{ - for( std::string::size_type lastIndex = 0; lastIndex < std::string::npos; - lastIndex = path.find_first_of(FIND_OF_DIRECTORY_SEPARATOR, lastIndex) ) - { - std::string&& curDir = path.substr(0, ++lastIndex); - if(!RsDirUtil::checkCreateDirectory(curDir)) - { - RsErr() << __PRETTY_FUNCTION__ << " failure creating: " << curDir - << " of: " << path << std::endl; - return false; - } - } - return true; -} -#else -# include -#endif // __cplusplus < 201703L - -std::string RsDirUtil::getFileName(const std::string& full_file_path) -{ - std::string::size_type n = full_file_path.find_last_of(FIND_OF_DIRECTORY_SEPARATOR); - - if(n == std::string::npos) - return full_file_path; - else - return full_file_path.substr(n+1); -} - -std::string RsDirUtil::getDirectory(const std::string& full_file_path) -{ - std::string::size_type n = full_file_path.find_last_of(FIND_OF_DIRECTORY_SEPARATOR); - - if(n == std::string::npos) - return std::string(); - else - return full_file_path.substr(0,n); -} -std::string RsDirUtil::getTopDir(const std::string& dir) -{ - std::string top; - - /* find the subdir: [/][dir1.../][/] - */ - int i,j; - int len = dir.length(); - for(j = len - 1; (j > 0) && RsDirUtil::isDirectorySeparator(dir[j]); j--) ; - for(i = j; (i > 0) && !RsDirUtil::isDirectorySeparator(dir[i]); i--) ; - - if (RsDirUtil::isDirectorySeparator(dir[i])) - i++; - - for(; i <= j; i++) - { - top += dir[i]; - } - - return top; -} - -const char *RsDirUtil::scanf_string_for_uint(int bytes) -{ - const char *strgs[3] = { "%u","%lu","%llu" } ; - - //std::cerr << "RsDirUtil::scanf_string_for_uint(): returning for bytes=" << bytes << std::endl; - - if(sizeof(unsigned int) == bytes) - return strgs[0] ; - if(sizeof(long unsigned int) == bytes) - return strgs[1] ; - if(sizeof(long long unsigned int) == bytes) - return strgs[2] ; - - std::cerr << "RsDirUtil::scanf_string_for_uint(): no corresponding scan string for "<< bytes << " bytes. This will probably cause inconsistencies." << std::endl; - return strgs[0] ; -} - -bool RsDirUtil::splitDirFromFile(const std::string& full_path,std::string& dir, std::string& file) -{ - std::string::size_type i = full_path.find_last_of(FIND_OF_DIRECTORY_SEPARATOR, full_path.size()-1); - - if(i == std::string::npos) // '/' not found! - { - file = full_path ; - dir = "." ; - return true ; - } - - dir.assign(full_path,0,i+1) ; - file.assign(full_path,i+1,full_path.size()) ; - - return true ; -} - -void RsDirUtil::removeTopDir(const std::string& dir, std::string& path) -{ - path.clear(); - - /* remove the subdir: [/][dir1.../][/] - */ - int j = dir.find_last_not_of(FIND_OF_DIRECTORY_SEPARATOR); - int i = dir.find_last_of(FIND_OF_DIRECTORY_SEPARATOR, j); - - /* remove any more slashes */ - if (i > 0) - { - i = dir.find_last_not_of(FIND_OF_DIRECTORY_SEPARATOR, i); - } - - if (i > 0) - { - path.assign(dir, 0, i + 1); - } -} - -std::string RsDirUtil::getRootDir(const std::string& dir) -{ - std::string root; - - /* find the subdir: [/]root[/...] - */ - int i,j; - int len = dir.length(); - for(i = 0; (i < len) && RsDirUtil::isDirectorySeparator(dir[i]); i++) ; - for(j = i; (j < len) && !RsDirUtil::isDirectorySeparator(dir[j]); j++) ; - if (i == j) - return root; /* empty */ - for(; i < j; i++) - { - root += dir[i]; - } - return root; -} - -std::string RsDirUtil::removeRootDir(const std::string& path) -{ - unsigned int i, j; - unsigned int len = path.length(); - std::string output; - - /* chew leading '/'s */ - for(i = 0; (i < len) && RsDirUtil::isDirectorySeparator(path[i]); i++) ; - if (i == len) - return output; /* empty string */ - - for(j = i; (j < len) && !RsDirUtil::isDirectorySeparator(path[j]); j++) ; /* run to next '/' */ - for(; (j < len) && RsDirUtil::isDirectorySeparator(path[j]); j++) ; /* chew leading '/'s */ - - for(; j < len; j++) - { - output += path[j]; - } - - return output; -} - -std::string RsDirUtil::removeRootDirs(const std::string& path, const std::string& root) -{ - /* too tired */ - std::string notroot; - - unsigned int i = 0, j = 0; - - /* catch empty data */ - if ((root.length() < 1) || (path.length() < 1)) - return notroot; - - if (RsDirUtil::isDirectorySeparator(path[0]) && !RsDirUtil::isDirectorySeparator(root[0])) - { - i++; - } - - for(; (i < path.length()) && (j < root.length()) && (path[i] == root[j]); i++, j++) ; - - /* should have consumed root. */ - if (j == root.length()) - { - //std::cerr << "matched root!" << std::endl; - } - else - { - //std::cerr << "failed i: " << i << ", j: " << j << std::endl; - //std::cerr << "root: " << root << " path: " << path << std::endl; - return notroot; - } - - if (RsDirUtil::isDirectorySeparator(path[i])) - { - i++; - } - - for(; i < path.length(); i++) - { - notroot += path[i]; - } - - //std::cerr << "Found NotRoot: " << notroot << std::endl; - - return notroot; -} - - - -int RsDirUtil::breakupDirList(const std::string& path, - std::list &subdirs) -{ - int start = 0; - unsigned int i; - for(i = 0; i < path.length(); i++) - { - if (RsDirUtil::isDirectorySeparator(path[i])) - { - if (i - start > 0) - { - subdirs.push_back(path.substr(start, i-start)); - } - start = i+1; - } - } - // get the final one. - if (i - start > 0) - { - subdirs.push_back(path.substr(start, i-start)); - } - return 1; -} - -/**** Copied and Tweaked from ftcontroller ***/ -bool RsDirUtil::fileExists(const std::string& filename) -{ -#ifdef WINDOWS_SYS - std::wstring wfilename; - librs::util::ConvertUtf8ToUtf16(filename, wfilename); - return ( _waccess( wfilename.c_str(), F_OK ) != -1 ); -#else - return ( access( filename.c_str(), F_OK ) != -1 ); -#endif -} - -bool RsDirUtil::moveFile(const std::string& source,const std::string& dest) -{ - Dbg3() << __PRETTY_FUNCTION__<< " source: " << source - << " dest: " << dest << std::endl; - - std::string dest_dir ; - std::string dest_file ; - - splitDirFromFile(dest, dest_dir, dest_file); - - if(!checkDirectory(dest_dir)) - { - if(!std::filesystem::create_directories(dest_dir)) - { - RsErr() << __PRETTY_FUNCTION__ << " failure creating directory: " - << dest_dir << std::endl; - return false; - } - } - - // First try a rename - if(renameFile(source,dest)) - { - Dbg3() << __PRETTY_FUNCTION__ << " plain rename worked" << std::endl; - return true; - } - - /* If not, try to copy. The src and dest probably belong to different file - * systems */ - if(!copyFile(source,dest)) - { - RsErr() << __PRETTY_FUNCTION__ << " failure copying file" << std::endl; - return false; - } - - // delete the original - if(!removeFile(source)) - { - RsErr() << __PRETTY_FUNCTION__ << " failure deleting original file" - << std::endl; - return false; - } - - return true; -} - -bool RsDirUtil::removeFile(const std::string& filename) -{ -#ifdef CONTROL_DEBUG - std::cerr << "deleting original file " << source << std::endl ; -#endif - -#ifdef WINDOWS_SYS - std::wstring filenameW; - librs::util::ConvertUtf8ToUtf16(filename,filenameW); - - if(0 != DeleteFileW(filenameW.c_str())) -#else - if(0 == remove(filename.c_str())) -#endif - return true ; - else - { - std::cerr << "(EE) File erase error while removing file " << filename << ". Read-only file system ?" << std::endl; - return false ; - } -} - -/**** Copied and Tweaked from ftcontroller ***/ -bool RsDirUtil::copyFile(const std::string& source,const std::string& dest) -{ -#ifdef WINDOWS_SYS - std::wstring sourceW; - std::wstring destW; - librs::util::ConvertUtf8ToUtf16(source,sourceW); - librs::util::ConvertUtf8ToUtf16(dest,destW); - - return (CopyFileW(sourceW.c_str(), destW.c_str(), FALSE) != 0); - -#else - FILE *in = fopen64(source.c_str(),"rb") ; - - if(in == NULL) - { - return false ; - } - - FILE *out = fopen64(dest.c_str(),"wb") ; - - if(out == NULL) - { - fclose (in); - return false ; - } - - size_t s=0; - size_t T=0; - - static const int BUFF_SIZE = 10485760 ; // 10 MB buffer to speed things up. - RsTemporaryMemory buffer(BUFF_SIZE) ; - - if(!buffer) - { - fclose(in) ; - fclose(out) ; - return false ; - } - - bool bRet = true; - - while( (s = fread(buffer,1,BUFF_SIZE,in)) > 0) - { - size_t t = fwrite(buffer,1,s,out) ; - T += t ; - - if(t != s) - { - bRet = false ; - break; - } - } - - fclose(in) ; - fclose(out) ; - - return bRet ; - -#endif - -} - - -bool RsDirUtil::checkFile(const std::string& filename,uint64_t& file_size,bool disallow_empty_file) -{ - int val; - mode_t st_mode; -#ifdef WINDOWS_SYS - std::wstring wfilename; - librs::util::ConvertUtf8ToUtf16(filename, wfilename); - struct _stat buf; - val = _wstat(wfilename.c_str(), &buf); - st_mode = buf.st_mode; -#else - struct stat64 buf; - val = stat64(filename.c_str(), &buf); - st_mode = buf.st_mode; -#endif - if (val == -1) - { -#ifdef RSDIR_DEBUG - std::cerr << "RsDirUtil::checkFile() "; - std::cerr << filename << " doesn't exist" << std::endl; -#endif - return false; - } - else if (!S_ISREG(st_mode)) - { - // Some other type - error. -#ifdef RSDIR_DEBUG - std::cerr << "RsDirUtil::checkFile() "; - std::cerr << filename << " is not a Regular File" << std::endl; -#endif - return false; - } - - file_size = buf.st_size ; - - if(disallow_empty_file && buf.st_size == 0) - return false ; - - return true; -} - -rstime_t RsDirUtil::lastWriteTime( - const std::string& path, - std::error_condition& errc ) -{ - if(!fileExists(path)) - { - errc = std::errc::no_such_file_or_directory; - return 0; - } - -#ifdef WINDOWS_SYS - struct _stati64 buf; - std::wstring wPath; - librs::util::ConvertUtf8ToUtf16(path, wPath); - if ( 0 == _wstati64(wPath.c_str(), &buf)) -#else - struct stat64 buf; - if ( 0 == stat64(path.c_str(), &buf)) -#endif - { - /* errc output param is guaranted to be meaningful only if an error - * happens so is not strictly necessary but we clean it anyway just - * in case */ - errc = std::error_condition(); - return buf.st_mtime; - } - - errc = std::error_condition(errno, std::generic_category()); - return 0; -} - -bool RsDirUtil::checkDirectory(const std::string& dir) -{ - int val; - mode_t st_mode; -#ifdef WINDOWS_SYS - std::wstring wdir; - librs::util::ConvertUtf8ToUtf16(dir, wdir); - struct _stat buf; - val = _wstat(wdir.c_str(), &buf); - st_mode = buf.st_mode; -#else - struct stat buf; - val = stat(dir.c_str(), &buf); - st_mode = buf.st_mode; -#endif - if (val == -1) - { -#ifdef RSDIR_DEBUG - std::cerr << "RsDirUtil::checkDirectory() "; - std::cerr << dir << " doesn't exist" << std::endl; -#endif - return false; - } - else if (!S_ISDIR(st_mode)) - { - // Some other type - error. -#ifdef RSDIR_DEBUG - std::cerr << "RsDirUtil::checkDirectory() "; - std::cerr << dir << " is not Directory" << std::endl; -#endif - return false; - } - return true; -} - - -bool RsDirUtil::checkCreateDirectory(const std::string& dir) -{ - Dbg3() << __PRETTY_FUNCTION__ << " " << dir << std::endl; - -#ifdef WINDOWS_SYS - std::wstring wdir; - librs::util::ConvertUtf8ToUtf16(dir, wdir); - _WDIR *direc = _wopendir(wdir.c_str()); - if (!direc) -#else - DIR *direc = opendir(dir.c_str()); - if (!direc) -#endif - { - // directory don't exist. create. -/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // UNIX - if (-1 == mkdir(dir.c_str(), 0777)) -#else // WIN - if (-1 == _wmkdir(wdir.c_str())) -#endif -/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - { -#ifdef RSDIR_DEBUG - std::cerr << "check_create_directory() Fatal Error et oui--"; - std::cerr < &keepFiles) -{ - for(librs::util::FolderIterator it(cleandir,false);it.isValid();it.next()) - if(it.file_type() == librs::util::FolderIterator::TYPE_FILE && (keepFiles.end() == std::find(keepFiles.begin(), keepFiles.end(), it.file_name()))) - remove( (cleandir + "/" + it.file_name()).c_str() ) ; - - return true; -} - -/* slightly nicer helper function */ -bool RsDirUtil::hashFile(const std::string& filepath, - std::string &name, RsFileHash &hash, uint64_t &size) -{ - if (getFileHash(filepath, hash, size)) - { - /* extract file name */ - name = RsDirUtil::getTopDir(filepath); - return true; - } - return false; -} - - -#include -#include - -/* Function to hash, and get details of a file */ -bool RsDirUtil::getFileHash(const std::string& filepath, RsFileHash &hash, uint64_t &size, RsThread *thread /*= NULL*/) -{ - FILE *fd; - - if (NULL == (fd = RsDirUtil::rs_fopen(filepath.c_str(), "rb"))) - return false; - - int len; - SHA_CTX *sha_ctx = new SHA_CTX; - unsigned char sha_buf[SHA_DIGEST_LENGTH]; - - static const uint32_t HASH_BUFFER_SIZE = 1024*1024*10 ;// allocate a 10MB buffer. Too small a buffer will cause multiple HD hits and slow down the hashing process. - RsTemporaryMemory gblBuf(HASH_BUFFER_SIZE) ; - //unsigned char gblBuf[512]; - - /* determine size */ - fseeko64(fd, 0, SEEK_END); - size = ftello64(fd); - fseeko64(fd, 0, SEEK_SET); - - /* check if thread is running */ - bool isRunning = thread ? thread->isRunning() : true; - int runningCheckCount = 0; - - SHA1_Init(sha_ctx); - while(isRunning && (len = fread(gblBuf,1, HASH_BUFFER_SIZE, fd)) > 0) - { - SHA1_Update(sha_ctx, gblBuf, len); - - if (thread && ++runningCheckCount > (10 * 1024)) { - /* check all 50MB if thread is running */ - isRunning = thread->isRunning(); - runningCheckCount = 0; - } - } - - /* Thread has ended */ - if (isRunning == false) - { - delete sha_ctx; - fclose(fd); - return false; - } - - /* reading failed for some reason */ - if (ferror(fd)) - { - delete sha_ctx; - fclose(fd); - return false; - } - - SHA1_Final(&sha_buf[0], sha_ctx); - - hash = Sha1CheckSum(sha_buf); - - delete sha_ctx; - fclose(fd); - return true; -} - -/* Function to hash, and get details of a file */ -Sha1CheckSum RsDirUtil::sha1sum(const unsigned char *data, uint32_t size) -{ - SHA_CTX sha_ctx ; - - if(SHA_DIGEST_LENGTH != 20) - throw std::runtime_error("Warning: can't compute Sha1Sum with sum size != 20") ; - - SHA1_Init(&sha_ctx); - while(size > 512) - { - SHA1_Update(&sha_ctx, data, 512); - data = &data[512] ; - size -= 512 ; - } - SHA1_Update(&sha_ctx, data, size); - - unsigned char sha_buf[SHA_DIGEST_LENGTH]; - SHA1_Final(&sha_buf[0], &sha_ctx); - - return Sha1CheckSum(sha_buf) ; -} - -Sha256CheckSum RsDirUtil::sha256sum(const unsigned char *data, uint32_t size) -{ - SHA256_CTX sha_ctx ; - - if(SHA256_DIGEST_LENGTH != 32) - throw std::runtime_error("Warning: can't compute Sha2561Sum with sum size != 32") ; - - SHA256_Init(&sha_ctx); - while(size > 512) - { - SHA256_Update(&sha_ctx, data, 512); - data = &data[512] ; - size -= 512 ; - } - SHA256_Update(&sha_ctx, data, size); - - unsigned char sha_buf[SHA256_DIGEST_LENGTH]; - SHA256_Final(&sha_buf[0], &sha_ctx); - - return Sha256CheckSum(sha_buf) ; -} -bool RsDirUtil::saveStringToFile(const std::string &file, const std::string &str) -{ - std::ofstream out(file.c_str(), std::ios_base::out | std::ios_base::binary); - if(!out.is_open()) - { - std::cerr << "RsDirUtil::saveStringToFile() ERROR: can't open file " << file << std::endl; - return false; - } - out << str; - return true; -} - -bool RsDirUtil::loadStringFromFile(const std::string &file, std::string &str) -{ - std::ifstream in(file.c_str(), std::ios_base::in | std::ios_base::binary); - if(!in.is_open()) - { - std::cerr << "RsDirUtil::loadStringFromFile() ERROR: can't open file " << file << std::endl; - return false; - } - std::stringstream buffer; - buffer << in.rdbuf(); - str = buffer.str(); - return true; -} - -bool RsDirUtil::renameFile(const std::string& from, const std::string& to) -{ - int loops = 0; - -#ifdef WINDOWS_SYS - std::wstring f; - librs::util::ConvertUtf8ToUtf16(from, f); - std::wstring t; - librs::util::ConvertUtf8ToUtf16(to, t); - - while (!MoveFileEx(f.c_str(), t.c_str(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) -#else - std::string f(from),t(to) ; - - while (rename(from.c_str(), to.c_str()) < 0) -#endif - { -#ifdef WIN32 - if (GetLastError() != ERROR_ACCESS_DENIED) -#else - if (errno != EACCES) -#endif - /* set errno? */ - return false ; - rstime::rs_usleep(100 * 1000); // 100 msec - - if (loops >= 30) - return false ; - - loops++; - } - - return true ; -} - -#ifdef UNUSED_CODE -// not used -bool RsDirUtil::createBackup (const std::string& sFilename, unsigned int nCount) -{ -#ifdef WINDOWS_SYS - if (GetFileAttributesA (sFilename.c_str ()) == -1) { - // file doesn't exist - return true; - } - - // search last backup - int nLast; - for (nLast = nCount; nLast >= 1; nLast--) { - std::ostringstream sStream; // please do not use std::ostringstream - sStream << sFilename << nLast << ".bak"; - - if (GetFileAttributesA (sStream.str ().c_str ()) != -1) { - break; - } - } - - // delete max backup - if (nLast == nCount) { - std::ostringstream sStream; // please do not use std::ostringstream - sStream << sFilename << nCount << ".bak"; - if (DeleteFileA (sStream.str ().c_str ()) == FALSE) { - getPqiNotify()->AddSysMessage (0, RS_SYS_WARNING, "File delete error", "Error while deleting file " + sStream.str ()); - return false; - } - nLast--; - } - - // rename backups - for (int nIndex = nLast; nIndex >= 1; nIndex--) { - std::ostringstream sStream; // please do not use std::ostringstream - sStream << sFilename << nIndex << ".bak"; - std::ostringstream sStream1; // please do not use std::ostringstream - sStream1 << sFilename << nIndex + 1 << ".bak"; - - if (renameFile (sStream.str (), sStream1.str ()) == false) { - getPqiNotify()->AddSysMessage (0, RS_SYS_WARNING, "File rename error", "Error while renaming file " + sStream.str () + " to " + sStream1.str ()); - return false; - } - } - - // copy backup - std::ostringstream sStream; // please do not use std::ostringstream - sStream << sFilename << 1 << ".bak"; - if (CopyFileA (sFilename.c_str (), sStream.str ().c_str (), FALSE) == FALSE) { - getPqiNotify()->AddSysMessage (0, RS_SYS_WARNING, "File rename error", "Error while renaming file " + sFilename + " to " + sStream.str ()); - return false; - } -#else - /* remove unused parameter warnings */ - (void) sFilename; - (void) nCount; -#endif - return true; -} -#endif - -FILE *RsDirUtil::rs_fopen(const char* filename, const char* mode) -{ -#ifdef WINDOWS_SYS - std::wstring wfilename; - librs::util::ConvertUtf8ToUtf16(filename, wfilename); - std::wstring wmode; - librs::util::ConvertUtf8ToUtf16(mode, wmode); - - return _wfopen(wfilename.c_str(), wmode.c_str()); -#else - return fopen64(filename, mode); -#endif -} - -std::string RsDirUtil::convertPathToUnix(std::string path) -{ - for (unsigned int i = 0; i < path.length(); i++) - { - if (path[i] == '\\') - path[i] = '/'; - } - return path; -} - -bool RsDirUtil::isDirectorySeparator(const char &c) -{ - if (c == '/') { - return true; - } - -#ifdef WINDOWS_SYS - if (c == '\\') { - return true; - } -#endif - - return false; -} - -std::string RsDirUtil::makePath(const std::string &path1, const std::string &path2) -{ - std::string path = path1; - - if (path.empty() == false && !RsDirUtil::isDirectorySeparator(*path.rbegin())) { - path += "/"; - } - path += path2; - - return path; -} - -int RsDirUtil::createLockFile(const std::string& lock_file_path, rs_lock_handle_t &lock_handle) -{ - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS -// Suspended. The user should make sure he's not already using the file descriptor. -// if(lock_handle != -1) -// close(lock_handle); - - // open the file in write mode, create it if necessary, truncate it (it should be empty) - lock_handle = open(lock_file_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - - if(lock_handle == -1) - { - std::cerr << "Could not open lock file " << lock_file_path.c_str() << std::flush; - perror(NULL); - return 2; - } - - // see "man fcntl" for the details, in short: non blocking lock creation on the whole file contents - struct flock lockDetails; - lockDetails.l_type = F_WRLCK; - lockDetails.l_whence = SEEK_SET; - lockDetails.l_start = 0; - lockDetails.l_len = 0; - - if(fcntl(lock_handle, F_SETLK, &lockDetails) == -1) - { - int fcntlErr = errno; - std::cerr << "Could not request lock on file " << lock_file_path.c_str() << std::flush; - perror(NULL); - - // there's no lock so let's release the file handle immediately - close(lock_handle); - lock_handle = -1; - - if(fcntlErr == EACCES || fcntlErr == EAGAIN) - return 1; - else - return 2; - } - - // Write to lock file our pid - std::string ourPID = std::to_string(::getpid()); - write(lock_handle, ourPID.c_str(), sizeof(char)*ourPID.size() ); - - return 0; -#else -// Suspended. The user should make sure he's not already using the file descriptor. -// -// if (lock_handle) { -// CloseHandle(lock_handle); -// } - - std::wstring wlockFile; - librs::util::ConvertUtf8ToUtf16(lock_file_path, wlockFile); - - // open the file in write mode, create it if necessary - lock_handle = CreateFile(wlockFile.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); - - if (lock_handle == INVALID_HANDLE_VALUE) - { - DWORD lasterror = GetLastError(); - - std::cerr << "Could not open lock file " << lock_file_path.c_str() << std::endl; - std::cerr << "Last error: " << lasterror << std::endl << std::flush; - perror(NULL); - - if (lasterror == ERROR_SHARING_VIOLATION || lasterror == ERROR_ACCESS_DENIED) - return 1; - - return 2; - } - - return 0; -#endif - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -} - -void RsDirUtil::releaseLockFile(rs_lock_handle_t lockHandle) -{ - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - if(lockHandle != -1) - { - close(lockHandle); - lockHandle = -1; - } -#else - if(lockHandle) - { - CloseHandle(lockHandle); - lockHandle = 0; - } -#endif - /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -} - -RsStackFileLock::RsStackFileLock(const std::string& file_path) -{ - while(RsDirUtil::createLockFile(file_path,_file_handle)) - { - std::cerr << "Cannot acquire file lock " << file_path << ", waiting 1 sec." << std::endl; - rstime::rs_usleep(1 * 1000 * 1000) ; // 1 sec - } -#ifdef RSDIR_DEBUG - std::cerr << "Acquired file handle " << _file_handle << ", lock file:" << file_path << std::endl; -#endif -} -RsStackFileLock::~RsStackFileLock() -{ - RsDirUtil::releaseLockFile(_file_handle) ; -#ifdef RSDIR_DEBUG - std::cerr << "Released file lock with handle " << _file_handle << std::endl; -#endif -} - -#if 0 // NOT ENABLED YET! -/************************* WIDE STRING ***************************/ -/************************* WIDE STRING ***************************/ -/************************* WIDE STRING ***************************/ - -std::wstring RsDirUtil::getWideTopDir(std::wstring dir) -{ - std::wstring top; - - /* find the subdir: [/][dir1.../][/] - */ - int i,j; - int len = dir.length(); - for(j = len - 1; (j > 0) && RsDirUtil::isDirectorySeparator(dir[j]); j--); - for(i = j; (i > 0) && !RsDirUtil::isDirectorySeparator(dir[i]); i--); - - if (RsDirUtil::isDirectorySeparator(dir[i])) - i++; - - for(; i <= j; i++) - { - top += dir[i]; - } - - return top; -} - -std::wstring RsDirUtil::removeWideTopDir(std::wstring dir) -{ - std::wstring rest; - - /* remove the subdir: [/][dir1.../][/] - */ - int i,j; - int len = dir.length(); - for(j = len - 1; (j > 0) && RsDirUtil::isDirectorySeparator(dir[j]); j--); - for(i = j; (i >= 0) && !RsDirUtil::isDirectorySeparator(dir[i]); i--); - - /* remove any more slashes */ - for(; (i >= 0) && RsDirUtil::isDirectorySeparator(dir[i]); i--); - - for(j = 0; j <= i; j++) - { - rest += dir[j]; - } - - return rest; -} - -std::wstring RsDirUtil::getWideRootDir(std::wstring dir) -{ - std::wstring root; - - /* find the subdir: [/]root[/...] - */ - int i,j; - int len = dir.length(); - for(i = 0; (i < len) && RsDirUtil::isDirectorySeparator(dir[i]); i++); - for(j = i; (j < len) && !RsDirUtil::isDirectorySeparator(dir[j]); j++); - if (i == j) - return root; /* empty */ - for(; i < j; i++) - { - root += dir[i]; - } - return root; -} - -std::wstring RsDirUtil::removeWideRootDir(std::wstring path) -{ - unsigned int i, j; - unsigned int len = path.length(); - std::wstring output; - - /* chew leading '/'s */ - for(i = 0; (i < len) && RsDirUtil::isDirectorySeparator(path[i]); i++); - if (i == len) - return output; /* empty string */ - - for(j = i; (j < len) && !RsDirUtil::isDirectorySeparator(path[j]); j++); /* run to next '/' */ - for(; (j < len) && RsDirUtil::isDirectorySeparator(path[j]); j++); /* chew leading '/'s */ - - for(; j < len; j++) - { - output += path[j]; - } - - return output; -} - -std::wstring RsDirUtil::removeWideRootDirs(std::wstring path, std::wstring root) -{ - /* too tired */ - std::wstring notroot; - - unsigned int i = 0, j = 0; - - /* catch empty data */ - if ((root.length() < 1) || (path.length() < 1)) - return notroot; - - if (RsDirUtil::isDirectorySeparator(path[0]) && !RsDirUtil::isDirectorySeparator(root[0])) - { - i++; - } - - for(; (i < path.length()) && (j < root.length()) && (path[i] == root[j]); i++, j++); - - /* should have consumed root. */ - if (j == root.length()) - { - //std::cerr << "matched root!" << std::endl; - } - else - { - //std::cerr << "failed i: " << i << ", j: " << j << std::endl; - //std::cerr << "root: " << root << " path: " << path << std::endl; - return notroot; - } - - if (RsDirUtil::isDirectorySeparator(path[i])) - { - i++; - } - - for(; i < path.length(); i++) - { - notroot += path[i]; - } - - //std::cerr << "Found NotRoot: " << notroot << std::endl; - - return notroot; -} - - - -int RsDirUtil::breakupWideDirList(std::wstring path, - std::list &subdirs) -{ - int start = 0; - unsigned int i; - for(i = 0; i < path.length(); i++) - { - if (RsDirUtil::isDirectorySeparator(path[i])) - { - if (i - start > 0) - { - subdirs.push_back(path.substr(start, i-start)); - } - start = i+1; - } - } - // get the final one. - if (i - start > 0) - { - subdirs.push_back(path.substr(start, i-start)); - } - return 1; -} - - - -bool RsDirUtil::checkWideDirectory(std::wstring dir) -{ - struct stat buf; - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - std::string d(dir.begin(), dir.end()); - int val = stat(d.c_str(), &buf); - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - if (val == -1) - { -#ifdef RSDIR_DEBUG - std::cerr << "RsDirUtil::checkDirectory() "; - std::cerr << d << " doesn't exist" << std::endl; -#endif - return false; - } - else if (!S_ISDIR(buf.st_mode)) - { - // Some other type - error. -#ifdef RSDIR_DEBUG - std::cerr << "RsDirUtil::checkDirectory() "; - std::cerr << d << " is not Directory" << std::endl; -#endif - return false; - } - return true; -} - - -bool RsDirUtil::checkWideCreateDirectory(std::wstring dir) -{ - struct stat buf; - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - std::string d(dir.begin(), dir.end()); - int val = stat(d.c_str(), &buf); - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - if (val == -1) - { - // directory don't exist. create. -/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS // UNIX - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - if (-1 == mkdir(d.c_str(), 0777)) - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ -#else // WIN - if (-1 == mkdir(d.c_str())) -#endif -/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ - - { -#ifdef RSDIR_DEBUG - std::cerr << "check_create_directory() Fatal Error --"; - std::cerr < - -bool RsDirUtil::cleanupWideDirectory(std::wstring cleandir, std::list keepFiles) -{ - - /* check for the dir existance */ - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - std::string cd(cleandir.begin(), cleandir.end()); - DIR *dir = opendir(cd.c_str()); - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - std::list::const_iterator it; - - if (!dir) - { - return false; - } - - struct dirent *dent; - struct stat buf; - - while(NULL != (dent = readdir(dir))) - { - /* check entry type */ - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - std::string fname(dent -> d_name); - std::wstring wfname(fname.begin(), fname.end()); - std::string fullname = cd + "/" + fname; - - if (-1 != stat(fullname.c_str(), &buf)) - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - { - /* only worry about files */ - if (S_ISREG(buf.st_mode)) - { - /* check if we should keep it */ - if (keepFiles.end() == (it = std::find(keepFiles.begin(), keepFiles.end(), wfname))) - { - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - /* can remove */ - remove(fullname.c_str()); - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - } - } - } - } - /* close directory */ - closedir(dir); - - return true; -} - -/* slightly nicer helper function */ -bool RsDirUtil::hashWideFile(std::wstring filepath, - std::wstring &name, std::string &hash, uint64_t &size) -{ - if (getWideFileHash(filepath, hash, size)) - { - /* extract file name */ - name = RsDirUtil::getWideTopDir(filepath); - return true; - } - return false; -} - - -#include -#include -#include - -/* Function to hash, and get details of a file */ -bool RsDirUtil::getWideFileHash(std::wstring filepath, - std::string &hash, uint64_t &size) -{ - FILE *fd; - int len; - SHA_CTX *sha_ctx = new SHA_CTX; - unsigned char sha_buf[SHA_DIGEST_LENGTH]; - unsigned char gblBuf[512]; - - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - std::string fp(filepath.begin(), filepath.end()); - - if (NULL == (fd = fopen64(fp.c_str(), "rb"))) - return false; - - /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ - - /* determine size */ - fseeko64(fd, 0, SEEK_END); - size = ftello64(fd); - fseeko64(fd, 0, SEEK_SET); - - SHA1_Init(sha_ctx); - while((len = fread(gblBuf,1, 512, fd)) > 0) - { - SHA1_Update(sha_ctx, gblBuf, len); - } - - /* reading failed for some reason */ - if (ferror(fd)) - { - delete sha_ctx; - fclose(fd); - return false; - } - - SHA1_Final(&sha_buf[0], sha_ctx); - - std::ostringstream tmpout; // please do not use std::ostringstream - for(int i = 0; i < SHA_DIGEST_LENGTH; i++) - { - tmpout << std::setw(2) << std::setfill('0') << std::hex << (unsigned int) (sha_buf[i]); - } - hash = tmpout.str(); - - delete sha_ctx; - fclose(fd); - return true; -} - -bool RsDirUtil::renameWideFile(const std::wstring& from, const std::wstring& to) -{ - int loops = 0; - -#if defined(WIN32) || defined(MINGW) || defined(__CYGWIN__) -#ifdef WIN_CROSS_UBUNTU - std::wstring f,t ; - for(int i=0;i= 30) - return false ; - - loops++; - } - - return true ; -} - - -#endif // WIDE STUFF NOT ENABLED YET! diff --git a/libretroshare/src/util/rsdir.h b/libretroshare/src/util/rsdir.h deleted file mode 100644 index c50caaf87..000000000 --- a/libretroshare/src/util/rsdir.h +++ /dev/null @@ -1,193 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsdir.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2007 Robert Fernie * - * Copyright (C) 2020-2021 Gioacchino Mazzurco * - * Copyright (C) 2020-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#pragma once - -#include -#include -#include -#include -#include - -class RsThread; - -#include "retroshare/rstypes.h" -#include "util/rsmemory.h" - -#ifndef WINDOWS_SYS -typedef int rs_lock_handle_t; -#else -typedef /*HANDLE*/ void *rs_lock_handle_t; -#endif - -// This is a scope guard on a given file. Works like a mutex. Is blocking. -// We could do that in another way: derive RsMutex into RsLockFileMutex, and -// use RsStackMutex on it transparently. Only issue: this will cost little more -// because of the multiple inheritance. -// -class RsStackFileLock -{ - public: - RsStackFileLock(const std::string& file_path) ; - ~RsStackFileLock() ; - - private: - rs_lock_handle_t _file_handle ; -}; - -namespace RsDirUtil { - -// Returns the name of the directory on top of the given path (as opposed to the full path to that directory) -std::string getTopDir(const std::string&); -std::string getRootDir(const std::string&); -std::string removeRootDir(const std::string& path); -void removeTopDir(const std::string& dir, std::string &path); -std::string removeRootDirs(const std::string& path, const std::string& root); - -// Returns the filename at the end of the path. An empty string is returned if the path is a directory path. -std::string getFileName(const std::string& full_file_path); - -// Returns the directory (full path) that contains the given path (filename or directory). -// If a directory is supplied, the same path is returned. -std::string getDirectory(const std::string& full_file_path); - -// Renames file from to file to. Files should be on the same file system. -// returns true if succeed, false otherwise. -bool renameFile(const std::string& from,const std::string& to) ; -//bool createBackup (const std::string& sFilename, unsigned int nCount = 5); - -// returns the CRC32 of the data of length len -// -uint32_t rs_CRC32(const unsigned char *data,uint32_t len) ; - -// Returns %u, %lu, or %llu, depending on the size of unsigned int, unsigned long and unsigned long long on the current system. -// Use as; -// sscanf(string, RsDirUtil::scanf_string_for_uint( sizeof(X) ), &X) ; -// -const char *scanf_string_for_uint(int bytes) ; - -int breakupDirList(const std::string& path, std::list &subdirs); - -/** Splits the path into parent directory and file. File can be empty if - * full_path is a dir ending with '/' if full_path does not contain a directory, - * then dir will be "." and file will be full_path */ -bool splitDirFromFile( const std::string& full_path, - std::string& dir, std::string& file ); - -bool copyFile(const std::string& source,const std::string& dest); - -/** Move file. If destination directory doesn't exists create it. */ -bool moveFile(const std::string& source, const std::string& dest); - -bool removeFile(const std::string& file); -bool fileExists(const std::string& file); -bool checkFile(const std::string& filename,uint64_t& file_size,bool disallow_empty_file = false); - -/** - * @brief Retrieve file last modification time - * @param path path of the file - * @param errc optional storage for error details - * @return 0 on error, file modification time represented as unix epoch otherwise. - */ -rstime_t lastWriteTime( - const std::string& path, - std::error_condition& errc = RS_DEFAULT_STORAGE_PARAM(std::error_condition) ); - -bool checkDirectory(const std::string& dir); - -/*! - * \brief checkCreateDirectory - * \param dir - * \return false when the directory does not exist and could not be created. - */ -bool checkCreateDirectory(const std::string& dir); - -// Removes all symbolic links along the path and computes the actual location of the file/dir passed as argument. - -std::string removeSymLinks(const std::string& path) ; - -bool cleanupDirectory(const std::string& dir, const std::set &keepFiles); -bool cleanupDirectoryFaster(const std::string& dir, const std::set &keepFiles); - -bool hashFile(const std::string& filepath, std::string &name, RsFileHash &hash, uint64_t &size); -bool getFileHash(const std::string& filepath,RsFileHash &hash, uint64_t &size, RsThread *thread = NULL); - -Sha1CheckSum sha1sum(const uint8_t *data,uint32_t size) ; -Sha256CheckSum sha256sum(const uint8_t *data,uint32_t size) ; - -bool saveStringToFile(const std::string& file, const std::string& str); -bool loadStringFromFile(const std::string& file, std::string& str); - -// Creates a lock file with given path, and returns the lock handle -// returns: -// 0: Success -// 1: Another instance already has the lock -// 2 : Unexpected error -int createLockFile(const std::string& lock_file_path, rs_lock_handle_t& lock_handle) ; - -// Removes the lock file with specified handle. -void releaseLockFile(rs_lock_handle_t lockHandle) ; - -std::wstring getWideTopDir(std::wstring); -std::wstring getWideRootDir(std::wstring); -std::wstring removeWideRootDir(std::wstring path); -std::wstring removeWideTopDir(std::wstring dir); -std::wstring removeWideRootDirs(std::wstring path, std::wstring root); - -// Renames file from to file to. Files should be on the same file system. -// returns true if succeed, false otherwise. -bool renameWideFile(const std::wstring& from,const std::wstring& to) ; - -int breakupWideDirList(std::wstring path, - std::list &subdirs); - -bool checkWideDirectory(std::wstring dir); -bool checkWideCreateDirectory(std::wstring dir); -bool cleanupWideDirectory(std::wstring dir, std::list keepFiles); - -bool hashWideFile(std::wstring filepath,std::wstring &name, RsFileHash &hash, uint64_t &size); - -bool getWideFileHash(std::wstring filepath, RsFileHash &hash, uint64_t &size); - -FILE *rs_fopen(const char* filename, const char* mode); - -std::string convertPathToUnix(std::string path); -bool isDirectorySeparator(const char &c); - -/** Concatenate two path pieces putting '/' separator between them only if - * needed */ -std::string makePath(const std::string &path1, const std::string &path2); - -RS_SET_CONTEXT_DEBUG_LEVEL(1); -} - -#if __cplusplus < 201703L -namespace std -{ -namespace filesystem -{ -bool create_directories(const std::string& path); -} -} -#endif // __cplusplus < 201703L diff --git a/libretroshare/src/util/rsdiscspace.cc b/libretroshare/src/util/rsdiscspace.cc deleted file mode 100644 index a394cd4e5..000000000 --- a/libretroshare/src/util/rsdiscspace.cc +++ /dev/null @@ -1,223 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsdiscspace.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010-2010 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include -#include -#include "util/rstime.h" -#include "rsserver/p3face.h" -#include "retroshare/rsfiles.h" -#include "retroshare/rsiface.h" -#include "retroshare/rsinit.h" -#include "rsdiscspace.h" -#include - -#ifdef __ANDROID__ -# include -#endif - -#ifdef WIN32 -# include -#elif defined(__ANDROID__) && (__ANDROID_API__ < 21) -# include -# define statvfs64 statfs -# warning statvfs64 is not supported with android platform < 21 falling back to statfs that is untested (may misbehave) -#else -# include -#endif - -#define DELAY_BETWEEN_CHECKS 2 - -/* - * #define DEBUG_RSDISCSPACE - */ - -rstime_t RsDiscSpace::_last_check[RS_DIRECTORY_COUNT] = { 0,0,0,0 } ; -uint32_t RsDiscSpace::_size_limit_mb = 100 ; -uint32_t RsDiscSpace::_current_size[RS_DIRECTORY_COUNT] = { 10000,10000,10000,10000 } ; -bool RsDiscSpace::_last_res[RS_DIRECTORY_COUNT] = { true,true,true,true }; -RsMutex RsDiscSpace::_mtx("RsDiscSpace") ; -std::string RsDiscSpace::_partials_path = "" ; -std::string RsDiscSpace::_download_path = "" ; - -bool RsDiscSpace::crossSystemDiskStats(const char *file, uint64_t& free_blocks, uint64_t& block_size) -{ -#if defined(WIN32) || defined(MINGW) || defined(__CYGWIN__) - - DWORD dwFreeClusters; - DWORD dwBytesPerSector; - DWORD dwSectorPerCluster; - DWORD dwTotalClusters; - -#ifdef WIN_CROSS_UBUNTU - wchar_t szDrive[4]; - szDrive[0] = file[0] ; - szDrive[1] = file[1] ; - szDrive[2] = file[2] ; -#else - char szDrive[4] = ""; - - char *pszFullPath = _fullpath (NULL, file, 0); - if (pszFullPath == 0) { - std::cerr << "Size estimate failed for drive (_fullpath) " << std::endl ; - return false; - } - _splitpath (pszFullPath, szDrive, NULL, NULL, NULL); - free (pszFullPath); -#endif - szDrive[3] = 0; - - if (!GetDiskFreeSpaceA (szDrive, &dwSectorPerCluster, &dwBytesPerSector, &dwFreeClusters, &dwTotalClusters)) - { - std::cerr << "Size estimate failed for drive " << szDrive << std::endl ; - return false; - } - - free_blocks = dwFreeClusters ; - block_size = dwSectorPerCluster * dwBytesPerSector ; -#else -#ifdef __APPLE__ - struct statvfs buf; - - if (0 != statvfs (file, &buf)) - { - std::cerr << "Size estimate failed for file " << file << std::endl ; - return false; - } - - - free_blocks = buf.f_bavail; - block_size = buf.f_frsize ; -#else - struct statvfs64 buf; - - if (0 != statvfs64 (file, &buf)) - { - std::cerr << "Size estimate failed for file " << file << std::endl ; - return false; - } - - - free_blocks = buf.f_bavail; - block_size = buf.f_bsize ; -#endif - -#endif - return true ; -} - -void RsDiscSpace::setDownloadPath(const std::string& path) -{ - RsStackMutex m(_mtx) ; // Locked - _download_path = path ; -} - -void RsDiscSpace::setPartialsPath(const std::string& path) -{ - RsStackMutex m(_mtx) ; // Locked - _partials_path = path ; -} - -bool RsDiscSpace::checkForDiscSpace(RsDiscSpace::DiscLocation loc) -{ - RsStackMutex m(_mtx) ; // Locked - - if( (_partials_path == "" && loc == RS_PARTIALS_DIRECTORY) || (_download_path == "" && loc == RS_DOWNLOAD_DIRECTORY)) - throw std::runtime_error("Download path and partial path not properly set in RsDiscSpace. Please call RsDiscSpace::setPartialsPath() and RsDiscSpace::setDownloadPath()") ; - - rstime_t now = time(NULL) ; - - if(_last_check[loc]+DELAY_BETWEEN_CHECKS < now) - { - uint64_t free_blocks,block_size ; - int rs = false; - -#ifdef DEBUG_RSDISCSPACE - std::cerr << "Size determination:" << std::endl ; -#endif - switch(loc) - { - case RS_DOWNLOAD_DIRECTORY: rs = crossSystemDiskStats(_download_path.c_str(),free_blocks,block_size) ; -#ifdef DEBUG_RSDISCSPACE - std::cerr << " path = " << _download_path << std::endl ; -#endif - break ; - - case RS_PARTIALS_DIRECTORY: rs = crossSystemDiskStats(_partials_path.c_str(),free_blocks,block_size) ; -#ifdef DEBUG_RSDISCSPACE - std::cerr << " path = " << _partials_path << std::endl ; -#endif - break ; - - case RS_CONFIG_DIRECTORY: rs = crossSystemDiskStats(RsAccounts::AccountDirectory().c_str(),free_blocks,block_size) ; -#ifdef DEBUG_RSDISCSPACE - std::cerr << " path = " << RsInit::RsConfigDirectory() << std::endl ; -#endif - break ; - - case RS_PGP_DIRECTORY: rs = crossSystemDiskStats(RsAccounts::PGPDirectory().c_str(),free_blocks,block_size) ; -#ifdef DEBUG_RSDISCSPACE - std::cerr << " path = " << RsInit::RsPGPDirectory() << std::endl ; -#endif - break ; - } - - if(!rs) - { - std::cerr << "Determination of free disc space failed ! Be careful !" << std::endl ; - return true ; - } - _last_check[loc] = now ; - - // Now compute the size in megabytes - // - _current_size[loc] = uint32_t(block_size * free_blocks / (uint64_t)(1024*1024)) ; // on purpose integer division - -#ifdef DEBUG_RSDISCSPACE - std::cerr << " blocks available = " << free_blocks << std::endl ; - std::cerr << " blocks size = " << block_size << std::endl ; - std::cerr << " free MBs = " << _current_size[loc] << std::endl ; -#endif - } - - bool res = _current_size[loc] > _size_limit_mb ; - - if(_last_res[loc] && !res) - RsServer::notify()->notifyDiskFull(loc,_size_limit_mb) ; - - _last_res[loc] = res ; - - return res ; -} - -void RsDiscSpace::setFreeSpaceLimit(uint32_t size_in_mb) -{ - RsStackMutex m(_mtx) ; // Locked - - _size_limit_mb = size_in_mb ; -} - -uint32_t RsDiscSpace::freeSpaceLimit() -{ - RsStackMutex m(_mtx) ; // Locked - - return _size_limit_mb ; -} - diff --git a/libretroshare/src/util/rsdiscspace.h b/libretroshare/src/util/rsdiscspace.h deleted file mode 100644 index 834561e6a..000000000 --- a/libretroshare/src/util/rsdiscspace.h +++ /dev/null @@ -1,61 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsdiscspace.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010-2010 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -class RsDiscSpace -{ - public: - typedef uint32_t DiscLocation ; - - // Returns false is the disc space is lower than the given size limit, true otherwise. - // When the size limit is reached, this class calls notify to warn the user (possibly - // with a popup window). - // - static bool checkForDiscSpace(DiscLocation loc) ; - - // Allow the user to specify his own size limit. Should not be too low, especially not 0 MB ;-) - // 10MB to 100MB are sensible values. - // - static void setFreeSpaceLimit(uint32_t mega_bytes) ; - static uint32_t freeSpaceLimit() ; - - static void setPartialsPath(const std::string& path) ; - static void setDownloadPath(const std::string& path) ; - private: - static bool crossSystemDiskStats(const char *file, uint64_t& free_blocks, uint64_t& block_size) ; - - static RsMutex _mtx ; - - static rstime_t _last_check[RS_DIRECTORY_COUNT] ; - static uint32_t _size_limit_mb ; - static uint32_t _current_size[RS_DIRECTORY_COUNT] ; - static bool _last_res[RS_DIRECTORY_COUNT] ; - - static std::string _partials_path ; - static std::string _download_path ; -}; - diff --git a/libretroshare/src/util/rsdnsutils.cc b/libretroshare/src/util/rsdnsutils.cc deleted file mode 100644 index f6bef0de3..000000000 --- a/libretroshare/src/util/rsdnsutils.cc +++ /dev/null @@ -1,361 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsdnsutils.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2021 Phenom * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -//#define DEBUG_SPEC_DNS 1 - -#include "util/rsnet.h" - -#include "util/rsdebug.h" -#include "util/rsthreads.h" -#include "util/rsstring.h" - -#ifdef WINDOWS_SYS -#else -#include -#endif - -//https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2 -constexpr uint16_t DNSC_IN = 1; //Internet (IN) -//https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4 -constexpr uint16_t DNST_A = 1; //Ipv4 address -constexpr uint16_t DNST_AAAA =28; //Ipv6 address - -///Need to pack as we use sizeof them. (avoid padding) -#pragma pack(1) -//DNS header structure -struct DNS_HEADER -{ - unsigned short id; // identification number - - //Header flags https://www.bind9.net/dns-header-flags - unsigned char rd :1; //bit 07 Recursion Desired, indicates if the client means a recursive query - unsigned char tc :1; //bit 06 TrunCation, indicates that this message was truncated due to excessive length - unsigned char aa :1; //bit 05 Authoritative Answer, in a response, indicates if the DNS server is authoritative for the queried hostname - unsigned char opcode :4;//bit 01-04 The type can be QUERY (standard query, 0), IQUERY (inverse query, 1), or STATUS (server status request, 2) - unsigned char qr :1; //bit 00 Indicates if the message is a query (0) or a reply (1) - - unsigned char rcode :4; //bit 12-15 Response Code can be NOERROR (0), FORMERR (1, Format error), SERVFAIL (2), NXDOMAIN (3, Nonexistent domain), etc. - unsigned char cd :1; //bit 11 Checking Disabled [RFC 4035][RFC 6840][RFC Errata 4927] used by DNSSEC - unsigned char ad :1; //bit 10 Authentic Data [RFC 4035][RFC 6840][RFC Errata 4924] used by DNSSEC - unsigned char z :1; //bit 09 Zero, reserved for future use - unsigned char ra :1; //bit 08 Recursion Available [RFC 1035] in a response, indicates if the replying DNS server supports recursion - - unsigned short q_count; // number of question entries - unsigned short ans_count; // number of answer entries - unsigned short auth_count; // number of authority resource records entries - unsigned short add_count; // number of additional resource record entries -}; -//// OpCode text https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-5 -//static const char *opcodetext[] = { "QUERY", "IQUERY", "STATUS", -// "RESERVED3", "NOTIFY", "UPDATE", -// "STATEFUL", "RESERVED7", "RESERVED8", -// "RESERVED9", "RESERVED10", "RESERVED11", -// "RESERVED12", "RESERVED13", "RESERVED14", -// "RESERVED15" }; -//// RCode text https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6 -//static const char *rcodetext[] = { "NOERROR", "FORMERR", "SERVFAIL", -// "NXDOMAIN", "NOTIMP", "REFUSED", -// "YXDOMAIN", "YXRRSET", "NXRRSET", -// "NOTAUTH", "NOTZONE", "DSOTYPENI", -// "RESERVED12", "RESERVED13", "RESERVED14", -// "RESERVED15", "BADVERS", "BADKEY", -// "BADTIME", "BADMODE", "BADNAME", -// "BADALG", "BADTRUNC", "BADCOOKIE"}; - -//Constant sized fields of query structure -//https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml -struct QUESTION -{ - unsigned short qtype; //https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4 - unsigned short qclass; //https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2 -}; - -//Constant sized fields of the resource record structure -struct RR_DATA -{ - unsigned short rtype; //https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4 - unsigned short rclass; //https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2 - unsigned int rttl; //Time To Live is the number of seconds left before the information expires. (32bits integer, so maximum 140 years) - unsigned short data_len;//Lenght of following data -}; -#pragma pack() - -bool rsGetHostByNameSpecDNS(const std::string& servername, const std::string& hostname, std::string& returned_addr, int timeout_s /*= -1*/) -{ -#ifdef DEBUG_SPEC_DNS - RS_DBG("servername=", servername, " hostname=", hostname); -#endif - - if (strlen(servername.c_str()) > 256) - { - RS_ERR("servername is too long > 256 chars: ", servername); - return false; - } - if (strlen(hostname.c_str()) > 256) - { - RS_ERR("hostname is too long > 256 chars: ", hostname); - return false; - } - - sockaddr_storage serverAddr; - bool validServer = sockaddr_storage_inet_pton(serverAddr, servername) - && sockaddr_storage_isValidNet(serverAddr); - bool isIPV4 = validServer && sockaddr_storage_ipv6_to_ipv4(serverAddr); - - if (!validServer) - { - in_addr in ; - if (!rsGetHostByName(servername, in)) - { - RS_ERR("servername is on an unknow format: ", servername); - return false; - } - - validServer = sockaddr_storage_inet_pton(serverAddr, rs_inet_ntoa(in)) - && sockaddr_storage_isValidNet(serverAddr); - isIPV4 = validServer && sockaddr_storage_ipv6_to_ipv4(serverAddr); - - if (!validServer) - { - RS_ERR("rsGetHostByName return bad answer: ", rs_inet_ntoa(in)); - return false; - } - } - - sockaddr_storage_setport( serverAddr, 53); - - //Set the DNS structure to standard queries - unsigned char buf[65536]; - struct DNS_HEADER* dns = (struct DNS_HEADER *)&buf; - dns->id = static_cast(htons(getpid())); //Transaction Id - //dns flags = 0x0100 Standard Query - dns->qr = 0; //Query/Response: Message is a query - dns->opcode = 0; //OpCode: Standard query - dns->aa = 0; //Authoritative: Server is not an authority for domain - dns->tc = 0; //TrunCated: Message is not truncated - dns->rd = 1; //Recursion Desired: Do query recursively - dns->ra = 0; //Recursion Available: Server cannot do recursive queries - dns->z = 0; //Z: reserved - dns->ad = 0; //Authentic Data: Answer/authority portion was not authenticated by the server - dns->cd = 0; //Checking Disabled: Unacceptable - dns->rcode = 0; //Response Code: No error - - dns->q_count = htons(1); //1 Question - dns->ans_count = 0; //0 Answer - dns->auth_count = 0; //0 Authority RRs - dns->add_count = 0; //0 Additional RRs - size_t curSendSize = sizeof(struct DNS_HEADER); - - //Point to the query server name portion - unsigned char* qname =static_cast(&buf[curSendSize]); - //First byte is Label Type: https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-10 - qname[0] = 0x04; //One Label with Normal label lower 6 bits is the length of the label - memcpy(&qname[1],hostname.c_str(),strlen(hostname.c_str())); - size_t qnameSize = strlen((const char*)qname); - // Format Hostname like www.google.com to 3www6google3com - { - size_t last = qnameSize; - for(size_t i = qnameSize-1 ; i > 0 ; i--) - if(qname[i]=='.') - { - qname[i]=last-i-1; - last = i; - } - } - curSendSize += qnameSize +1; //With \0 terminator - - //Point to the query constant portion - struct QUESTION* qinfo =(struct QUESTION*)&buf[curSendSize]; - qinfo->qtype = htons(isIPV4 ? DNST_A : DNST_AAAA); //Type: A / AAAA(Host Address) - qinfo->qclass = htons(DNSC_IN); //Class: IN - curSendSize += sizeof(struct QUESTION); - -#ifdef DEBUG_SPEC_DNS - RS_DBG("Sending Packet:\n", hexDump(buf, curSendSize)); -#endif - int s = socket(serverAddr.ss_family , SOCK_DGRAM , IPPROTO_UDP); //UDP packet for DNS queries - if(s<0) - { - RS_ERR("Could not open socket."); - return false; - } - - if (timeout_s > -1) - rs_setSockTimeout(s, true, timeout_s); - - ssize_t send_size = sendto( s, (char*)buf, curSendSize, 0 - , (struct sockaddr*)&serverAddr - , isIPV4 ? sizeof(sockaddr_in) - : sizeof(sockaddr_in6) - ); - if( send_size < 0) - { - RS_ERR("Send Failed with size = ", send_size); - close(s); - return false; - } - -#ifdef DEBUG_SPEC_DNS - RS_DBG("Waiting answer..."); -#endif - //****************************************************************************************// - //--- Receive the answer ---// - //****************************************************************************************// - socklen_t sa_size = static_cast(isIPV4 ? sizeof(sockaddr_in) - : sizeof(sockaddr_in6) - ); - ssize_t rec_size=recvfrom( s,(char*)buf , 65536 , 0 - , (struct sockaddr*)&serverAddr - , &sa_size - ); - close(s); // No more need of this socket, close it. - if(rec_size <= 0) - { - RS_ERR("Receive Failed"); - return false; - } -#ifdef DEBUG_SPEC_DNS - RS_DBG("Received:\n", hexDump(buf, rec_size)); -#endif - - - if (rec_size< static_cast(sizeof(struct DNS_HEADER)) ) - { - RS_ERR("Request received too small to get DNSHeader."); - return false; - } -#ifdef DEBUG_SPEC_DNS - //Point to the header portion - dns = (struct DNS_HEADER*) buf; - RS_DBG("The response contains :\n" - ,ntohs(dns->q_count) , " Questions.\n" - ,ntohs(dns->ans_count) , " Answers.\n" - ,ntohs(dns->auth_count) , " Authoritative Servers.\n" - ,ntohs(dns->add_count) , " Additional records."); -#endif - size_t curRecSize = sizeof(struct DNS_HEADER); - - - if (rec_size< static_cast(curRecSize + 1 + sizeof(struct QUESTION)) ) - { - RS_ERR("Request received too small to get Question return."); - return false; - } - //Point to the query portion - unsigned char* qnameRecv =static_cast(&buf[curRecSize]); - if (memcmp(qname,qnameRecv,qnameSize + 1 + sizeof(struct QUESTION)) ) - { - RS_ERR("Request received different from that sent."); - return false; - } - curRecSize += qnameSize + 1 + sizeof(struct QUESTION); - - if (rec_size< static_cast(curRecSize + 2) ) - { - RS_ERR("Request received too small to get Answer return."); - return false; - } - //Point to the Answer portion - unsigned char* reader = &buf[curRecSize]; - - size_t rLabelSize=0; - if((reader[0]&0xC0) == 0) - { - //Normal label lower 6 bits is the length of the label - rLabelSize=(reader[0]&~(0xC0)*256) + reader[1]; - } - else if ((reader[0]&0xC0) == 0xC0) - { - //Compressed label the lower 6 bits and the 8 bits from next octet form a pointer to the compression target. - //Don't need to read it, maybe the same as in Query - rLabelSize=0; - } - else - { - RS_ERR("Answer received with unmanaged label format."); - return false; - } - curRecSize += 2 + rLabelSize; - - if (rec_size< static_cast(curRecSize + sizeof(struct RR_DATA)) ) - { - RS_ERR("Request received too small to get Data return."); - return false; - } - //Point to the query portion - struct RR_DATA* rec_data = (struct RR_DATA *)&buf[curRecSize]; - if (rec_data->rtype!=qinfo->qtype) - { - RS_ERR("Answer's type received different from query sent."); - return false; - } - if (rec_data->rclass!=qinfo->qclass) - { - RS_ERR("Answer's class received different from query sent."); - return false; - } - curRecSize += sizeof(struct RR_DATA); - - if (rec_size< static_cast(curRecSize + ntohs(rec_data->data_len)) ) - { - RS_ERR("Request received too small to get Full Data return."); - return false; - } - - //Retrieve Address - if(ntohs(rec_data->data_len)==4) - { - if (isIPV4) - { - in_addr ipv4Add; - ipv4Add.s_addr=*(in_addr_t*)&buf[curRecSize]; -#ifdef DEBUG_SPEC_DNS - RS_DBG("Retrieve address: ", rs_inet_ntoa(ipv4Add)); -#endif - returned_addr = rs_inet_ntoa(ipv4Add); - return true; - } - } - else if(ntohs(rec_data->data_len)==16) - { - if (!isIPV4) - { - in6_addr ipv6Add; - ipv6Add =*(in6_addr*)&buf[curRecSize]; - - struct sockaddr_storage ss; - sockaddr_storage_clear(ss); - sockaddr_in6 addr_ipv6; - addr_ipv6.sin6_addr = ipv6Add; - sockaddr_storage_setipv6(ss,&addr_ipv6); - -#ifdef DEBUG_SPEC_DNS - RS_DBG("Retrieve address: ", sockaddr_storage_iptostring(ss).c_str()); -#endif - returned_addr = sockaddr_storage_iptostring(ss); - return true; - } - } - - RS_ERR("Retrieve unmanaged data size=", ntohs(rec_data->data_len)); - return false; -} diff --git a/libretroshare/src/util/rsendian.h b/libretroshare/src/util/rsendian.h deleted file mode 100644 index d27c374ff..000000000 --- a/libretroshare/src/util/rsendian.h +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************* - * * - * libretroshare endiannes utilities * - * * - * Copyright (C) 2020 Gioacchino Mazzurco * - * Copyright (C) 2020 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -/** - * @file - * This file provide convenient integer endiannes conversion utilities. - * Instead of providing them with different names for each type (a la C htonl, - * htons, ntohl, ntohs ), which make them uncomfortable to use, expose a - * templated function `rs_endian_fix` to reorder integers bytes representation - * when sending or receiving from the network. */ - -/* enforce LITTLE_ENDIAN on Windows */ -#ifdef WINDOWS_SYS -# define BYTE_ORDER 1234 -# define LITTLE_ENDIAN 1234 -# define BIG_ENDIAN 4321 -#else -#include -#endif - -template inline INTTYPE rs_endian_fix(INTTYPE val) -{ -#if BYTE_ORDER == LITTLE_ENDIAN - INTTYPE swapped = 0; - for (size_t i = 0; i < sizeof(INTTYPE); ++i) - swapped |= (val >> (8*(sizeof(INTTYPE)-i-1)) & 0xFF) << (8*i); - return swapped; -#else - return val; -#endif -}; - -#ifndef BYTE_ORDER -# error "ENDIAN determination Failed (BYTE_ORDER not defined)" -#endif - -#if !(BYTE_ORDER == BIG_ENDIAN || BYTE_ORDER == LITTLE_ENDIAN) -# error "ENDIAN determination Failed (unkown BYTE_ORDER value)" -#endif diff --git a/libretroshare/src/util/rsexpr.cc b/libretroshare/src/util/rsexpr.cc deleted file mode 100644 index dff5a5fa5..000000000 --- a/libretroshare/src/util/rsexpr.cc +++ /dev/null @@ -1,320 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare: rsexpr.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2007-2008 by Kashif Kaleem * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "retroshare/rsexpr.h" -#include "retroshare/rstypes.h" -#include -#include - -/****************************************************************************************** -eval functions of relational expressions. - -******************************************************************************************/ - -namespace RsRegularExpression -{ -template<> -void RelExpression::linearize(LinearizedExpression& e) const -{ - e._ints.push_back(Op) ; - e._ints.push_back(LowerValue) ; - e._ints.push_back(HigherValue) ; -} - - -bool DateExpression::eval(const ExpFileEntry& file) -{ - return evalRel(file.file_modtime()); -} - -bool SizeExpressionMB::eval(const ExpFileEntry& file) -{ - return evalRel((int)(file.file_size()/(uint64_t)(1024*1024))); -} - -bool SizeExpression::eval(const ExpFileEntry& file) -{ - return evalRel(file.file_size()); -} - -bool PopExpression::eval(const ExpFileEntry& file) -{ - return evalRel(file.file_popularity()); -} - -/****************************************************************************************** -Code for evaluating string expressions - -******************************************************************************************/ - -bool NameExpression::eval(const ExpFileEntry& file) -{ - return evalStr(file.file_name()); -} - -bool PathExpression::eval(const ExpFileEntry& file) -{ - return evalStr(file.file_parent_path()); -} - -bool ExtExpression::eval(const ExpFileEntry& file) -{ - std::string ext; - /*Get the part of the string after the last instance of . in the filename */ - size_t index = file.file_name().find_last_of('.'); - if (index != std::string::npos) { - ext = file.file_name().substr(index+1); - if (ext != "" ){ - return evalStr(ext); - } - } - return false; -} - -bool HashExpression::eval(const ExpFileEntry& file){ - return evalStr(file.file_hash().toStdString()); -} - -/*Check whether two strings are 'equal' to each other*/ -static bool StrEquals(const std::string & str1, const std::string & str2, - bool IgnoreCase ){ - if ( str1.size() != str2.size() ){ - return false; - } else if (IgnoreCase) { - std::equal( str1.begin(), str1.end(), - str2.begin(), CompareCharIC() ); - } - return std::equal( str1.begin(), str1.end(), - str2.begin()); -} - -/*Check whether one string contains the other*/ -static bool StrContains( const std::string & str1, const std::string & str2, - bool IgnoreCase){ - - std::string::const_iterator iter ; - if (IgnoreCase) { - iter = std::search( str1.begin(), str1.end(), - str2.begin(), str2.end(), CompareCharIC() ); - } else { - iter = std::search( str1.begin(), str1.end(), - str2.begin(), str2.end()); - } - - return ( iter != str1.end() ); -} - - -std::string StringExpression::toStdStringWithParam(const std::string& varstr) const -{ - std::string strlist ; - for (auto iter = terms.begin(); iter != terms.end(); ++iter ) - strlist += *iter + " "; - - if(!strlist.empty()) - strlist.resize(strlist.size()-1); //strlist.pop_back(); // pops the last ",". c++11 is needed for pop_back() - - switch(Op) - { - case ContainsAllStrings: return varstr + " CONTAINS ALL "+strlist ; - case ContainsAnyStrings: if(terms.size() == 1) - return varstr + " CONTAINS "+strlist ; - else - return varstr + " CONTAINS ONE OF "+strlist ; - case EqualsString: if(terms.size() == 1) - return varstr + " IS "+strlist ; - else - return varstr + " IS ONE OF "+strlist ; - - default: - return "" ; - } -} - -bool StringExpression :: evalStr ( const std::string &str ){ - std::list::iterator iter; - switch (Op) { - case ContainsAllStrings: - for ( iter = terms.begin(); iter != terms.end(); ++iter ) { - if ( StrContains (str, *iter, IgnoreCase) == false ){ - return false; - } - } - return true; - break; - case ContainsAnyStrings: - for ( iter = terms.begin(); iter != terms.end(); ++iter ) { - if ( StrContains (str,*iter, IgnoreCase) == true ) { - return true; - } - } - break; - case EqualsString: - for ( iter = terms.begin(); iter != terms.end(); ++iter ) { - if ( StrEquals (str,*iter, IgnoreCase) == true ) { - return true; - } - } - break; - default: - return false; - } - return false; -} - -/************************************************************************* - * linearization code - *************************************************************************/ - -void CompoundExpression::linearize(LinearizedExpression& e) const -{ - e._tokens.push_back(LinearizedExpression::EXPR_COMP) ; - e._ints.push_back(Op) ; - - Lexp->linearize(e) ; - Rexp->linearize(e) ; -} - -void StringExpression::linearize(LinearizedExpression& e) const -{ - e._ints.push_back(Op) ; - e._ints.push_back(IgnoreCase) ; - e._ints.push_back(terms.size()) ; - - for(std::list::const_iterator it(terms.begin());it!=terms.end();++it) - e._strings.push_back(*it) ; -} - -Expression *LinearizedExpression::toExpr(const LinearizedExpression& e) -{ - int i=0,j=0,k=0 ; - return toExpr(e,i,j,k) ; -} - -void LinearizedExpression::readStringExpr(const LinearizedExpression& e,int& n_ints,int& n_strings,std::list& strings,bool& b,StringOperator& op) -{ - op = static_cast(e._ints[n_ints++]) ; - b = e._ints[n_ints++] ; - int n = e._ints[n_ints++] ; - - strings.clear() ; - for(int i=0;i::const_iterator i = this->_strings.begin(); i != this->_strings.end(); ++i) - { - str += *i; - str += " "; - } - return str; -} - -Expression *LinearizedExpression::toExpr(const LinearizedExpression& e,int& n_tok,int& n_ints,int& n_strings) -{ - LinearizedExpression::token tok = static_cast(e._tokens[n_tok++]) ; - - switch(tok) - { - case EXPR_DATE: { - RelOperator op = static_cast(e._ints[n_ints++]) ; - int lv = e._ints[n_ints++] ; - int hv = e._ints[n_ints++] ; - - return new DateExpression(op,lv,hv) ; - } - - case EXPR_POP: { - RelOperator op = static_cast(e._ints[n_ints++]) ; - int lv = e._ints[n_ints++] ; - int hv = e._ints[n_ints++] ; - - return new PopExpression(op,lv,hv) ; - } - case EXPR_SIZE: { - RelOperator op = static_cast(e._ints[n_ints++]) ; - int lv = e._ints[n_ints++] ; - int hv = e._ints[n_ints++] ; - - return new SizeExpression(op,lv,hv) ; - } - case EXPR_HASH: { - std::list strings ; - StringOperator op ; - bool b ; - - readStringExpr(e,n_ints,n_strings,strings,b,op) ; - return new HashExpression(op,strings) ; - } - case EXPR_NAME: { - std::list strings ; - StringOperator op ; - bool b ; - - readStringExpr(e,n_ints,n_strings,strings,b,op) ; - - return new NameExpression(op,strings,b) ; - } - case EXPR_PATH: { - std::list strings ; - StringOperator op ; - bool b ; - - readStringExpr(e,n_ints,n_strings,strings,b,op) ; - - return new ExtExpression(op,strings,b) ; - } - case EXPR_EXT: { - std::list strings ; - StringOperator op ; - bool b ; - - readStringExpr(e,n_ints,n_strings,strings,b,op) ; - - return new ExtExpression(op,strings,b) ; - } - case EXPR_COMP: { - LogicalOperator op = static_cast(e._ints[n_ints++]) ; - - Expression *e1 = toExpr(e,n_tok,n_ints,n_strings) ; - Expression *e2 = toExpr(e,n_tok,n_ints,n_strings) ; - - return new CompoundExpression(op,e1,e2) ; - } - case EXPR_SIZE_MB: { - RelOperator op = static_cast(e._ints[n_ints++]) ; - int lv = e._ints[n_ints++] ; - int hv = e._ints[n_ints++] ; - - return new SizeExpressionMB(op,lv,hv) ; - } - default: - std::cerr << "No expression match the current value " << tok << std::endl ; - return NULL ; - } -} - - -} diff --git a/libretroshare/src/util/rsfile.cc b/libretroshare/src/util/rsfile.cc deleted file mode 100644 index 6d3f7b1ab..000000000 --- a/libretroshare/src/util/rsfile.cc +++ /dev/null @@ -1,107 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsfile.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2021 Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "util/rsfile.h" - -#ifdef WINDOWS_SYS -#include -#include -#include -#include -#else -#include -#endif - -int RsFileUtil::set_fd_nonblock(int fd) -{ - int ret = 0; - -/******************* OS SPECIFIC PART ******************/ -#ifdef WINDOWS_SYS - DWORD mode = PIPE_NOWAIT; - WINBOOL result = SetNamedPipeHandleState((HANDLE) _get_osfhandle(fd), &mode, nullptr, nullptr); - - if (!result) { - ret = -1; - } -#else // ie UNIX - int flags = fcntl(fd, F_GETFL); - ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK); -#endif - - return ret; -} - -ssize_t RsFileUtil::rs_getline(char **lineptr, size_t *n, FILE *stream) -{ -/******************* OS SPECIFIC PART ******************/ -#ifdef WINDOWS_SYS - if (lineptr == nullptr || n == nullptr || stream == nullptr) { - errno = EINVAL; - return -1; - } - - if (*lineptr == nullptr || *n < 1) { - *n = BUFSIZ; - *lineptr = (char*) malloc(*n); - if (*lineptr == nullptr) { - *n = 0; - return -1; - } - } - - char *ptr = *lineptr; - while (true) { - int c = fgetc(stream); - if (c == -1) { - if (feof(stream)) { - *ptr = '\0'; - return (ssize_t) (ptr - *lineptr); - } - return -1; - } - - *ptr = c; - ++ptr; - - if (c == '\n') { - *ptr = '\0'; - return ptr - *lineptr; - } - if (ptr + 2 >= *lineptr + *n) { - size_t new_size = *n * 2; - ssize_t diff = ptr - *lineptr; - - char *new_lineptr = (char*) realloc(*lineptr, new_size); - if (new_lineptr == nullptr) { - return -1; - } - - *lineptr = new_lineptr; - *n = new_size; - ptr = new_lineptr + diff; - } - } -#else // ie UNIX - return getline(lineptr, n, stream); -#endif -} diff --git a/libretroshare/src/util/rsfile.h b/libretroshare/src/util/rsfile.h deleted file mode 100644 index 9a23b6a4c..000000000 --- a/libretroshare/src/util/rsfile.h +++ /dev/null @@ -1,32 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsfile.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2021 Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#pragma once - -#include - -namespace RsFileUtil { - -int set_fd_nonblock(int fd); -ssize_t rs_getline(char **lineptr, size_t *n, FILE *stream); - -} diff --git a/libretroshare/src/util/rsinitedptr.h b/libretroshare/src/util/rsinitedptr.h deleted file mode 100644 index 09aaa871a..000000000 --- a/libretroshare/src/util/rsinitedptr.h +++ /dev/null @@ -1,52 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsinitedptr.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2010-2010 by Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#pragma once -/** -helper class to store a pointer -it is usefull because it initialises itself to NULL - -usage: -replace - type* ptr; -with - inited_ptr ptr; - -this class can -- get assigned a pointer -- be dereferenced -- be converted back to a pointer -*/ -namespace RsUtil{ -template class inited_ptr{ -public: - inited_ptr(): _ptr(NULL){} - inited_ptr(const inited_ptr& other): _ptr(other._ptr){} - inited_ptr& operator= (const inited_ptr& other){ _ptr = other._ptr; return *this;} - inited_ptr& operator= (T* ptr){ _ptr = ptr; return *this;} - operator T* () const { return _ptr;} - T* operator ->() const { return _ptr;} - T& operator *() const { return *_ptr;} -private: - T* _ptr; -}; -}//namespace RsUtil diff --git a/libretroshare/src/util/rsjson.cc b/libretroshare/src/util/rsjson.cc deleted file mode 100644 index 8af1cf942..000000000 --- a/libretroshare/src/util/rsjson.cc +++ /dev/null @@ -1,61 +0,0 @@ -/******************************************************************************* - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include -#include -#include - -#include "util/rsjson.h" - -inline int getJsonManipulatorStatePosition() -{ - static int p = std::ios_base::xalloc(); - return p; -} - -std::ostream& compactJSON(std::ostream &out) -{ - out.iword(getJsonManipulatorStatePosition()) = 1; - return out; -} - -std::ostream& prettyJSON(std::ostream &out) -{ - out.iword(getJsonManipulatorStatePosition()) = 0; - return out; -} - -std::ostream& operator<<(std::ostream &out, const RsJson &jDoc) -{ - rapidjson::StringBuffer buffer; buffer.Clear(); - if(out.iword(getJsonManipulatorStatePosition())) - { - rapidjson::Writer writer(buffer); - jDoc.Accept(writer); - } - else - { - rapidjson::PrettyWriter writer(buffer); - jDoc.Accept(writer); - } - - return out << buffer.GetString(); -} diff --git a/libretroshare/src/util/rsjson.h b/libretroshare/src/util/rsjson.h deleted file mode 100644 index 13073f3b2..000000000 --- a/libretroshare/src/util/rsjson.h +++ /dev/null @@ -1,51 +0,0 @@ -/******************************************************************************* - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include - -/** - * Use this type for JSON documents representations in RetroShare code - */ -typedef rapidjson::Document RsJson; - -/** - * Print out RsJson to a stream, use std::ostringstream to get the string - * @param[out] out output stream - * @param[in] jDoc JSON document to print - * @return same output stream passed as out parameter - */ -std::ostream& operator<<(std::ostream &out, const RsJson &jDoc); - -/** - * Stream manipulator to print RsJson in compact format - * @param[out] out output stream - * @return same output stream passed as out parameter - */ -std::ostream& compactJSON(std::ostream &out); - -/** - * Stream manipulator to print RsJson in human readable format - * @param[out] out output stream - * @return same output stream passed as out parameter - */ -std::ostream& prettyJSON(std::ostream &out); diff --git a/libretroshare/src/util/rskbdinput.cc b/libretroshare/src/util/rskbdinput.cc deleted file mode 100644 index ac8309e5a..000000000 --- a/libretroshare/src/util/rskbdinput.cc +++ /dev/null @@ -1,130 +0,0 @@ -/******************************************************************************* - * libretroshare/src/retroshare/util/rskbdinput.cc * - * * - * Copyright (C) 2019 Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef __ANDROID__ - -#include -#include - -#ifdef WINDOWS_SYS -#include -#include - -#define PASS_MAX 512 - -namespace RsUtil { -std::string rs_getpass(const std::string& prompt,bool /*no_echo*/) -{ - static char getpassbuf [PASS_MAX + 1]; - size_t i = 0; - int c; - - if (!prompt.empty()) { - std::cerr << prompt ; - std::cerr.flush(); - } - - for (;;) { - c = _getch (); - if (c == '\r') { - getpassbuf [i] = '\0'; - break; - } - else if (i < PASS_MAX) { - getpassbuf[i++] = c; - } - - if (i >= PASS_MAX) { - getpassbuf [i] = '\0'; - break; - } - } - - if (!prompt.empty()) { - std::cerr << "\r\n" ; - std::cerr.flush(); - } - - return std::string(getpassbuf); -} -} -#else - -#include -#include -#include -#include -#include - -static int getch() -{ - int ch; - struct termios t_old, t_new; - - tcgetattr(STDIN_FILENO, &t_old); - t_new = t_old; - t_new.c_lflag &= ~(ICANON | ECHO); - tcsetattr(STDIN_FILENO, TCSANOW, &t_new); - - ch = getchar(); - - tcsetattr(STDIN_FILENO, TCSANOW, &t_old); - return ch; -} - -namespace RsUtil { - -std::string rs_getpass(const std::string& prompt, bool no_echo) -{ - const char BACKSPACE=127; - const char RETURN=10; - - std::string password; - unsigned char ch=0; - - std::cout < * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include - -namespace RsUtil { - - std::string rs_getpass(const std::string& prompt,bool no_echo=true) ; - -} diff --git a/libretroshare/src/util/rsmemcache.h b/libretroshare/src/util/rsmemcache.h deleted file mode 100644 index 53d5efa27..000000000 --- a/libretroshare/src/util/rsmemcache.h +++ /dev/null @@ -1,492 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsmemcache.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_UTIL_MEM_CACHE -#define RS_UTIL_MEM_CACHE - -#include -#include "util/rstime.h" -#include -#include -#include - -/************************************************************************************/ -/************************************************************************************/ -/************************************************************************************/ - -/* Generic Memoory Cache - * - * This is probably crude and crap to start with. - * Want Least Recently Used (LRU) discard policy, without having to search whole cache. - * Use two maps: - * - mDataMap[key] => data. - * - mLruMap[AccessTS] => key (multimap) - */ - -/*** - * #define DEBUG_RSMEMCACHE 1 - ***/ - -#define DEFAULT_MEM_CACHE_SIZE 100 - -template class RsMemCache -{ -public: - - RsMemCache(uint32_t max_size = DEFAULT_MEM_CACHE_SIZE, std::string name = "UnknownMemCache") - :mDataCount(0), mMaxSize(max_size), mName(name) - { - clearStats(); - return; - } - - bool is_cached(const Key &key) const; - bool fetch(const Key &key, Value &data); - - // Like map[] installs empty one if non-existent. - - Value& ref(const Key &key); - Value& operator[](const Key& key) { return ref(key); } - - bool store(const Key &key, const Value &data); - bool erase(const Key &key); // clean up cache. - - bool resize(); // should be called periodically to cleanup old entries. - - // Apply a method of a given class ClientClass to all cached data. Can be useful... - - template bool applyToAllCachedEntries(ClientClass& c,bool (ClientClass::*method)(Value&)); - - uint32_t size() const { return mDataMap.size() ; } - void printStats(std::ostream& out); -private: - - bool update_lrumap(const Key &key, rstime_t old_ts, rstime_t new_ts); - bool discard_LRU(int count_to_clear); - - // internal class. - class cache_data - { - public: - cache_data() { return; } - cache_data(Key in_key, Value in_data, rstime_t in_ts) - :key(in_key), data(in_data), ts(in_ts) { return; } - Key key; - Value data; - rstime_t ts; - }; - - - std::map mDataMap; - std::multimap mLruMap; - uint32_t mDataCount; - uint32_t mMaxSize; - std::string mName; - - // some statistics. - void clearStats(); - - mutable uint32_t mStats_inserted; - mutable uint32_t mStats_dropped; - mutable uint32_t mStats_iscached; - mutable uint32_t mStats_cachemiss; - mutable uint32_t mStats_access; - mutable uint32_t mStats_accessmiss; -}; - - -template bool RsMemCache::is_cached(const Key &key) const -{ - typename std::map::const_iterator it; - it = mDataMap.find(key); - if (it == mDataMap.end()) - { -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::is_cached(" << key << ") false"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - - mStats_cachemiss++; - return false; - } -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::is_cached(" << key << ") false"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - mStats_iscached++; - return true; - -} - -template template bool RsMemCache::applyToAllCachedEntries(ClientClass& c, bool (ClientClass::*method)(Value&)) -{ - bool res = true ; - - for(typename std::map::iterator it(mDataMap.begin());it!=mDataMap.end();++it) - res = res && ((c.*method)(it->second.data)) ; - - return res ; -} - -template bool RsMemCache::fetch(const Key &key, Value& data) -{ -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::fetch()"; - std::cerr << std::endl; - printStats(std::cerr); -#endif // DEBUG_RSMEMCACHE - - typename std::map::iterator it; - it = mDataMap.find(key); - if (it == mDataMap.end()) - { -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::fetch(" << key << ") false"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - - mStats_accessmiss++; - return false; - } - -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::fetch(" << key << ") OK"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - - data = it->second.data; - - /* update ts on data */ - rstime_t old_ts = it->second.ts; - rstime_t new_ts = time(NULL); - it->second.ts = new_ts; - - update_lrumap(key, old_ts, new_ts); - - mStats_access++; - return true; -} - - -template bool RsMemCache::erase(const Key &key) -{ -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::erase()"; - std::cerr << std::endl; - printStats(std::cerr); -#endif // DEBUG_RSMEMCACHE - - typename std::map::iterator it; - it = mDataMap.find(key); - if (it == mDataMap.end()) - { -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::erase(" << key << ") false"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - - mStats_accessmiss++; - return false; - } - -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::erase(" << key << ") OK"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - - - /* get timestamps */ - rstime_t old_ts = it->second.ts; - rstime_t new_ts = 0; - - // remove from lru. - mDataMap.erase(it); - update_lrumap(key, old_ts, new_ts); - mDataCount--; - - mStats_access++; - return true; -} - - - -template Value &RsMemCache::ref(const Key &key) -{ -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::ref()"; - std::cerr << std::endl; - printStats(std::cerr); -#endif // DEBUG_RSMEMCACHE - - typename std::map::iterator it; - it = mDataMap.find(key); - if (it == mDataMap.end()) - { -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::ref(" << key << ") ERROR missing Key inserting Empty Data in LRU slot"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - - // insert operation. - rstime_t new_ts = 0; - Value data; - mDataMap[key] = cache_data(key, data, new_ts); - mDataCount++; - - update_lrumap(key, 0, new_ts); - it = mDataMap.find(key); - - mStats_accessmiss++; - } - else - { -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::ref(" << key << ") OK"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - - /* update ts on data */ - rstime_t old_ts = it->second.ts; - rstime_t new_ts = time(NULL); - it->second.ts = new_ts; - - update_lrumap(key, old_ts, new_ts); - - mStats_access++; - } - return it->second.data; -} - -template bool RsMemCache::store(const Key &key, const Value &data) -{ -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::store()"; - std::cerr << std::endl; - printStats(std::cerr); -#endif // DEBUG_RSMEMCACHE - - /* update lrumap entry */ - rstime_t old_ts = 0; - rstime_t new_ts = time(NULL); - - // For consistency - typename std::map::const_iterator it; - it = mDataMap.find(key); - if (it != mDataMap.end()) - { - // ERROR. -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::store() WARNING overriding existing entry"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - - old_ts = it->second.ts; - } - else - { - mDataCount++; - } - - mDataMap[key] = cache_data(key, data, new_ts); - - update_lrumap(key, old_ts, new_ts); - - mStats_inserted++; - return true; -} - - -template bool RsMemCache::update_lrumap(const Key &key, rstime_t old_ts, rstime_t new_ts) -{ - if (old_ts == 0) - { -#ifdef DEBUG_RSMEMCACHE - std::cerr << "p3IdService::locked_cache_update_lrumap(" << key << ") just insert!"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - - /* new insertion */ - mLruMap.insert(std::make_pair(new_ts, key)); - return true; - } - - /* find old entry */ - typename std::multimap::iterator mit; - typename std::multimap::iterator sit = mLruMap.lower_bound(old_ts); - typename std::multimap::iterator eit = mLruMap.upper_bound(old_ts); - - for(mit = sit; mit != eit; ++mit) - { - if (mit->second == key) - { - mLruMap.erase(mit); -#ifdef DEBUG_RSMEMCACHE - std::cerr << "p3IdService::locked_cache_update_lrumap(" << key << ") rm old"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - - if (new_ts != 0) // == 0, means remove. - { -#ifdef DEBUG_RSMEMCACHE - std::cerr << "p3IdService::locked_cache_update_lrumap(" << key << ") added new_ts"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - mLruMap.insert(std::make_pair(new_ts, key)); - } - return true; - } - } -#ifdef DEBUG_RSMEMCACHE - std::cerr << "p3IdService::locked_cache_update_lrumap(" << key << ") ERROR"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - - return false; -} - -template bool RsMemCache::resize() -{ -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::resize()"; - std::cerr << std::endl; - printStats(std::cerr); -#endif // DEBUG_RSMEMCACHE - - int count_to_clear = 0; - { - // consistency check. - if ((mDataMap.size() != mDataCount) || - (mLruMap.size() != mDataCount)) - { - // ERROR. - std::cerr << "RsMemCache::resize() CONSISTENCY ERROR"; - std::cerr << std::endl; - std::cerr << "\tmDataMap.size() = " << mDataMap.size(); - std::cerr << std::endl; - std::cerr << "\tmLruMap.size() = " << mLruMap.size(); - std::cerr << std::endl; - std::cerr << "\tmDataCount = " << mDataCount; - std::cerr << std::endl; - } - - if (mDataCount > mMaxSize) - { - count_to_clear = mDataCount - mMaxSize; -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::resize() to_clear: " << count_to_clear; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - } - } - - if (count_to_clear > 0) - { - discard_LRU(count_to_clear); - } - return true; -} - - - -template bool RsMemCache::discard_LRU(int count_to_clear) -{ - while(count_to_clear > 0) - { - typename std::multimap::iterator mit = mLruMap.begin(); - if (mit != mLruMap.end()) - { - Key key = mit->second; - mLruMap.erase(mit); - - /* now clear from real cache */ - //std::map >::iterator it; - typename std::map::iterator it; - it = mDataMap.find(key); - if (it == mDataMap.end()) - { - // ERROR - std::cerr << "RsMemCache::discard_LRU(): ERROR Missing key: " << key; - std::cerr << std::endl; - return false; - } - else - { -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::discard_LRU() removing: " << key; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - mDataMap.erase(it); - mDataCount--; - mStats_dropped++; - } - } - else - { - // No More Data, ERROR. -#ifdef DEBUG_RSMEMCACHE - std::cerr << "RsMemCache::discard_LRU(): INFO more more cache data"; - std::cerr << std::endl; -#endif // DEBUG_RSMEMCACHE - - return true; - } - count_to_clear--; - } - return true; -} - -// These aren't templated functions. -template void RsMemCache::printStats(std::ostream &out) -{ - typename std::multimap::iterator mit = mLruMap.begin(); - rstime_t age = 0; - if (mit != mLruMap.end()) - { - age = time(NULL) - mit->first; - } - - out << "RsMemCache<" << mName << ">::printStats() Size: " << mDataCount << " Size2: " << mDataMap.size() << " Size3: " << mLruMap.size() << " MaxSize: " << mMaxSize << " LRU Age: " << age; - out << std::endl; - - out << "\tInsertions: " << mStats_inserted << " Drops: " << mStats_dropped; - out << std::endl; - - out << "\tCache Hits: " << mStats_iscached << " Misses: " << mStats_cachemiss; - out << std::endl; - - out << "\tAccess Hits: " << mStats_access << " Misses: " << mStats_accessmiss; - out << std::endl; -} - -template void RsMemCache::clearStats() -{ - mStats_inserted = 0; - mStats_dropped = 0; - mStats_iscached = 0; - mStats_cachemiss = 0; - mStats_access = 0; - mStats_accessmiss = 0; -} - - - - -#endif // RS_UTIL_MEM_CACHE diff --git a/libretroshare/src/util/rsmemory.h b/libretroshare/src/util/rsmemory.h deleted file mode 100644 index 8afc48cf7..000000000 --- a/libretroshare/src/util/rsmemory.h +++ /dev/null @@ -1,219 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsmemory.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2012 Cyril Soler * - * Copyright (C) 2019-2021 Gioacchino Mazzurco * - * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include - -#include "util/stacktrace.h" -#include "util/rsdebug.h" - -/** - * @brief Shorthand macro to declare optional functions output parameters - * To define an optional output paramether use the following syntax - * -\code{.cpp} -bool myFunnyFunction( - int mandatoryParamether, - BigType& myOptionalOutput = RS_DEFAULT_STORAGE_PARAM(BigType) ) -\endcode - * - * The function caller then can call myFunnyFunction either passing - * myOptionalOutput parameter or not. - * @see RsGxsChannels methods for real usage examples. - * - * @details - * When const references are used to pass function parameters it is easy do make - * those params optional by defining a default value in the function - * declaration, because a temp is accepted as default parameter in those cases. - * It is not as simple when one want to make optional a non-const reference - * parameter that is usually used as output, in that case as a temp is in theory - * not acceptable. - * Yet it is possible to overcome that limitation with the following trick: - * If not passed as parameter the storage for the output parameter can be - * dinamically allocated directly by the function call, to avoid leaking memory - * on each function call the pointer to that storage is made unique so once the - * function returns it goes out of scope and is automatically deleted. - * About performance overhead: std::unique_ptr have very good performance and - * modern compilers may be even able to avoid the dynamic allocation in this - * case, any way the allocation would only happen if the parameter is not - * passed, so any effect on performace would happen only in case where the - * function is called without the parameter. - */ -#define RS_DEFAULT_STORAGE_PARAM(Type,...) *std::unique_ptr(new Type(__VA_ARGS__)) - -/** @brief Safely dynamic cast between std::unique_ptr of different types - * std::unique_ptr semantic rely on the invariant that only one instance own - * the object, when casting between differents types one would be tempted to do - * it in a one liner that easly end up breaking that condition ending up in a - * double delete and crash or in a silent memleak. - * With this function one can do that with same comfort of a plain dynamic_cast, - * plus the std::unique_ptr safety. - * @param[inout] src reference to source pointer. If the cast is successfull it - * is released, otherwise it is left untouched. - * @param[out] dst reference to destination pointer. If the cast is successful - * it get reseated to the object address, otherwise it is left untouched. - * @return true on success, false otherwise - */ -template -bool rs_unique_cast( - std::unique_ptr& src, std::unique_ptr& dst ) -{ - T_DST* dstPtr = dynamic_cast(src.get()); - if(dstPtr) - { - src.release(); - dst.reset(dstPtr); - return true; - } - return false; -} - -/** Mark a pointer as non-owned aka it must not be deleted/freed in that context. - * If a function take an `rs_view_ptr` as paramether it means that she will not - * own (aka free/delete) the passed memory, instead the caller is in charge of - * managing it. If a function return an `rs_view_ptr` it means the memory is - * managed internally and the caller should not call free/delete on it. - * @see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1408r0.pdf */ -template using rs_view_ptr = T*; - -/** Mark a pointer as owned aka the receiving context is in charge of dealing - * with it by free/delete once finished. - * If a function take an `rs_owner_ptr` as paramether it means that she will own - * (aka free/delete when finished using it) the passed memory, instead the - * caller is NOT in charge of managing it. - * If a function return an `rs_owner_ptr` it means the memory is NOT managed - * internally and the caller should call free/delete on it once finished using - * it. - * @see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1408r0.pdf */ -template using rs_owner_ptr = T*; - - -/// 1Gb should be enough for everything! -static constexpr size_t SAFE_MEMALLOC_THRESHOLD = 1024*1024*1024; - -/** Comfortable templated safer malloc, just use it specifing the type of the - * pointer to be returned without need of ugly casting the returned pointer - * `uint8_t* ptr = rs_malloc(40);` - * @param[in] size number of bytes to allocate - * @param[out] ec optional storage for error details. Value is meaningful only - * whem nullptr is returned. - * @return nullptr on error, pointer to the allocated chuck of memory on success - */ -template rs_owner_ptr rs_malloc( - size_t size, - rs_view_ptr ec = nullptr ) -{ - if(size == 0) - { - if(!ec) - { - RS_ERR("A chunk of size 0 was requested"); - print_stacktrace(); - exit(static_cast(std::errc::invalid_argument)); - } - - *ec = std::errc::invalid_argument; - return nullptr; - } - - if(size > SAFE_MEMALLOC_THRESHOLD) - { - if(!ec) - { - RS_ERR( "A chunk of size larger than ", SAFE_MEMALLOC_THRESHOLD, - " was requested" ); - exit(static_cast(std::errc::argument_out_of_domain)); - } - - *ec = std::errc::argument_out_of_domain; - return nullptr; - } - - void* mem = malloc(size); - if(!mem) - { - if(!ec) - { - RS_ERR( "Allocation failed for a chunk of ", size, - " bytes with: ", errno); - print_stacktrace(); - exit(errno); - } - - *ec = rs_errno_to_condition(errno); - return nullptr; - } - - return static_cast>(mem); -} - - -/** @deprecated use std::unique_ptr instead -// This is a scope guard to release the memory block when going of of the current scope. -// Can be very useful to auto-delete some memory on quit without the need to call free each time. -// -// Usage: -// -// { -// TemporaryMemoryHolder mem(size) ; -// -// if(mem != NULL) -// [ do something ] ; -// -// memcopy(mem, some_other_memory, size) ; -// -// [do something] -// -// } // mem gets freed automatically -*/ -class RS_DEPRECATED_FOR("std::unique_ptr") RsTemporaryMemory -{ -public: - explicit RsTemporaryMemory(size_t s) - { - _mem = (unsigned char *)rs_malloc(s) ; - - if(_mem) - _size = s ; - else - _size = 0 ; - } - - operator unsigned char *() { return _mem ; } - - size_t size() const { return _size ; } - - ~RsTemporaryMemory() { free(_mem); } - -private: - unsigned char *_mem ; - size_t _size ; - - // make it noncopyable - RsTemporaryMemory& operator=(const RsTemporaryMemory&) { return *this ;} - RsTemporaryMemory(const RsTemporaryMemory&) {} -}; diff --git a/libretroshare/src/util/rsnet.cc b/libretroshare/src/util/rsnet.cc deleted file mode 100644 index a0d6f7447..000000000 --- a/libretroshare/src/util/rsnet.cc +++ /dev/null @@ -1,190 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsnet.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 Robert Fernie * - * Copyright 2015-2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "util/rsnet.h" -#include "util/rsthreads.h" -#include "util/rsstring.h" -#include "util/rsmemory.h" - -#ifdef WINDOWS_SYS -#else -#include -#endif - -#include - -/* enforce LITTLE_ENDIAN on Windows */ -#ifdef WINDOWS_SYS - #define BYTE_ORDER 1234 - #define LITTLE_ENDIAN 1234 - #define BIG_ENDIAN 4321 -#endif - -#ifndef ntohll -uint64_t ntohll(uint64_t x) -{ -#ifdef BYTE_ORDER - #if BYTE_ORDER == BIG_ENDIAN - return x; - #elif BYTE_ORDER == LITTLE_ENDIAN - - uint32_t top = (uint32_t) (x >> 32); - uint32_t bot = (uint32_t) (0x00000000ffffffffULL & x); - - uint64_t rev = ((uint64_t) ntohl(top)) | (((uint64_t) ntohl(bot)) << 32); - - return rev; - #else - #error "ENDIAN determination Failed" - #endif -#else - #error "ENDIAN determination Failed (BYTE_ORDER not defined)" -#endif - -} -#endif -#ifndef htonll -uint64_t htonll(uint64_t x) -{ - return ntohll(x); -} -#endif - -void sockaddr_clear(struct sockaddr_in *addr) -{ - memset(addr, 0, sizeof(struct sockaddr_in)); - addr->sin_family = AF_INET; -} - -bool rsGetHostByName(const std::string& hostname, in_addr& returned_addr) -{ - addrinfo hint; memset(&hint, 0, sizeof(hint)); - hint.ai_family = AF_INET; - addrinfo* info = nullptr; - int res = getaddrinfo(hostname.c_str(), nullptr, &hint, &info); - - bool ok = true; - if(res > 0 || !info || !info->ai_addr) - { - std::cerr << __PRETTY_FUNCTION__ << "(EE) getaddrinfo returned error " - << res << " on string \"" << hostname << "\"" << std::endl; - returned_addr.s_addr = 0; - ok = false; - } - else - returned_addr.s_addr = ((sockaddr_in*)info->ai_addr)->sin_addr.s_addr; - - if(info) freeaddrinfo(info); - - return ok; -} - -bool isValidNet(const struct in_addr *addr) -{ - // invalid address. - if((*addr).s_addr == INADDR_NONE) - return false; - if((*addr).s_addr == 0) - return false; - // should do more tests. - return true; -} - - -bool isLoopbackNet(const struct in_addr *addr) -{ - in_addr_t taddr = ntohl(addr->s_addr); - return (taddr == (127 << 24 | 1)); -} - -bool isPrivateNet(const struct in_addr *addr) -{ - in_addr_t taddr = ntohl(addr->s_addr); - - if ( (taddr>>24 == 10) || // 10.0.0.0/8 - (taddr>>20 == (172<<4 | 16>>4)) || // 172.16.0.0/12 - (taddr>>16 == (192<<8 | 168)) || // 192.168.0.0/16 - (taddr>>16 == (169<<8 | 254)) ) // 169.254.0.0/16 - return true; - - return false; -} - -bool isLinkLocalNet(const struct in_addr *addr) -{ - in_addr_t taddr = ntohl(addr->s_addr); - if ( taddr>>16 == (169<<8 | 254) ) return true; // 169.254.0.0/16 - - return false; -} - -bool isExternalNet(const struct in_addr *addr) -{ - if (!isValidNet(addr)) - { - return false; - } - if (isLoopbackNet(addr)) - { - return false; - } - if (isPrivateNet(addr)) - { - return false; - } - return true; -} - -std::ostream &operator<<(std::ostream &out, const struct sockaddr_in &addr) -{ - out << "[" << rs_inet_ntoa(addr.sin_addr) << ":"; - out << htons(addr.sin_port) << "]"; - return out; -} - -std::ostream& operator<<(std::ostream& o, const sockaddr_storage& addr) -{ return o << sockaddr_storage_tostring(addr); } - -/* thread-safe version of inet_ntoa */ - -std::string rs_inet_ntoa(struct in_addr in) -{ - std::string str; - uint8_t *bytes = (uint8_t *) &(in.s_addr); - rs_sprintf(str, "%u.%u.%u.%u", (int) bytes[0], (int) bytes[1], (int) bytes[2], (int) bytes[3]); - return str; -} - -int rs_setSockTimeout( int sockfd, bool forReceive /*= true*/ - , int timeout_Sec /*= 0*/, int timeout_uSec /*= 0*/) -{ -#ifdef WINDOWS_SYS - DWORD timeout = timeout_Sec * 1000 + timeout_uSec; -#else - struct timeval timeout; - timeout.tv_sec = timeout_Sec; - timeout.tv_usec = timeout_uSec; -#endif - return setsockopt( sockfd, SOL_SOCKET, forReceive ? SO_RCVTIMEO : SO_SNDTIMEO - , (const char*)&timeout, sizeof timeout); -} diff --git a/libretroshare/src/util/rsnet.h b/libretroshare/src/util/rsnet.h deleted file mode 100644 index 33dff1c9e..000000000 --- a/libretroshare/src/util/rsnet.h +++ /dev/null @@ -1,184 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsnet.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 Robert Fernie * - * Copyright 2015-2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_UNIVERSAL_NETWORK_HEADER -#define RS_UNIVERSAL_NETWORK_HEADER - -#include -#include /* Included because GCC4.4 wants it */ -#include /* Included because GCC4.4 wants it */ -#include - -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#ifndef WINDOWS_SYS - -#include -#include -#include -#include - -#include -#include - -#else - -#include -typedef uint32_t in_addr_t; - -int inet_aton(const char *name, struct in_addr *addr); - -// Missing defines in MinGW -#ifndef MSG_WAITALL -#define MSG_WAITALL 8 -#endif - -#endif -/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ - -/** - * Workaround for binary compatibility between Windows XP (which miss - * IPV6_V6ONLY define), and newer Windows that has it. - * @see http://lua-users.org/lists/lua-l/2013-04/msg00191.html - */ -#ifndef IPV6_V6ONLY -# define IPV6_V6ONLY 27 -#endif - -/* 64 bit conversions */ -#ifndef ntohll -uint64_t ntohll(uint64_t x); -#endif -#ifndef htonll -uint64_t htonll(uint64_t x); -#endif - -/* blank a network address */ -void sockaddr_clear(struct sockaddr_in *addr); - -/* determine network type (moved from pqi/pqinetwork.cc) */ -bool isValidNet(const struct in_addr *addr); -bool isLoopbackNet(const struct in_addr *addr); -bool isPrivateNet(const struct in_addr *addr); -bool isLinkLocalNet(const struct in_addr *addr); -bool isExternalNet(const struct in_addr *addr); - -// uses a re-entrant version of gethostbyname -bool rsGetHostByName(const std::string& hostname, in_addr& returned_addr) ; - -/** - * @brief Get hostName address using specific DNS server. - * Using it allow to direct ask our Address to IP, so no need to have a DNS (IPv4 or IPv6). - * If we ask to a IPv6 DNS Server, it respond for our IPv6 address. - * @param servername: Address or name of DNS Server. - * @param hostname: HosteName to get IP ("myip.opendns.com" to get own). - * @param returned_addr: returned IP of hostname. - * @param timeout_s: Timeout in sec to wait server response. - * @return True in success. - */ -bool rsGetHostByNameSpecDNS(const std::string& servername, const std::string& hostname, std::string& returned_addr, int timeout_s = -1); - -std::ostream& operator<<(std::ostream& o, const sockaddr_in&); -std::ostream& operator<<(std::ostream& o, const sockaddr_storage&); - -/* thread-safe version of inet_ntoa */ -std::string rs_inet_ntoa(struct in_addr in); - - -/***************************/ -// sockaddr_storage fns. - -int rs_bind(int fd, const sockaddr_storage& addr); - -void sockaddr_storage_clear(struct sockaddr_storage &addr); - -// mods. -bool sockaddr_storage_zeroip(struct sockaddr_storage &addr); - -/** - * @brief Use this function to copy sockaddr_storage. - * - * POSIX does not require that objects of type sockaddr_storage can be copied - * as aggregates thus it is unsafe to aggregate copy ( operator = ) - * sockaddr_storage and unexpected behaviors may happens due to padding - * and alignment. - * - * @see https://sourceware.org/bugzilla/show_bug.cgi?id=20111 - * @see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71120 - */ -bool sockaddr_storage_copy(const sockaddr_storage& src, sockaddr_storage& dst); - -bool sockaddr_storage_copyip(struct sockaddr_storage &dst, const struct sockaddr_storage &src); -uint16_t sockaddr_storage_port(const struct sockaddr_storage &addr); -bool sockaddr_storage_setport(struct sockaddr_storage &addr, uint16_t port); - -bool sockaddr_storage_setipv4(struct sockaddr_storage &addr, const sockaddr_in *addr_ipv4); -bool sockaddr_storage_setipv6(struct sockaddr_storage &addr, const sockaddr_in6 *addr_ipv6); - -bool sockaddr_storage_inet_pton( sockaddr_storage &addr, - const std::string& ipStr ); -bool sockaddr_storage_ipv4_aton(struct sockaddr_storage &addr, const char *name); - -bool sockaddr_storage_ipv4_setport(struct sockaddr_storage &addr, const uint16_t port); - -bool sockaddr_storage_ipv4_to_ipv6(sockaddr_storage &addr); -bool sockaddr_storage_ipv6_to_ipv4(sockaddr_storage &addr); - -// comparisons. -bool operator<(const struct sockaddr_storage &a, const struct sockaddr_storage &b); - -bool sockaddr_storage_same(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2); -bool sockaddr_storage_samefamily(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2); -bool sockaddr_storage_sameip(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2); - -// string, -std::string sockaddr_storage_tostring(const struct sockaddr_storage &addr); -bool sockaddr_storage_fromString(const std::string& str, sockaddr_storage &addr); -std::string sockaddr_storage_familytostring(const struct sockaddr_storage &addr); -std::string sockaddr_storage_iptostring(const struct sockaddr_storage &addr); -std::string sockaddr_storage_porttostring(const struct sockaddr_storage &addr); -void sockaddr_storage_dump(const sockaddr_storage & addr, std::string * outputString = NULL); - -// net checks. -bool sockaddr_storage_isnull(const struct sockaddr_storage &addr); -bool sockaddr_storage_isValidNet(const struct sockaddr_storage &addr); -bool sockaddr_storage_isLoopbackNet(const struct sockaddr_storage &addr); -bool sockaddr_storage_isPrivateNet(const struct sockaddr_storage &addr); -bool sockaddr_storage_isLinkLocalNet(const struct sockaddr_storage &addr); -bool sockaddr_storage_ipv6_isLinkLocalNet(const sockaddr_storage &addr); -bool sockaddr_storage_isExternalNet(const struct sockaddr_storage &addr); - -bool sockaddr_storage_inet_ntop(const sockaddr_storage &addr, std::string &dst); - -int rs_setsockopt( int sockfd, int level, int optname, - const uint8_t *optval, uint32_t optlen ); - -/** - * @brief Set socket Timeout. - * @param sockfd: The socket to manage. - * @param forReceive: True for Receive, False for Send. - * @param timeout_Sec: Timeout second part. - * @param timeout_uSec: Timeout micro second part. - * @return 0 on success, -1 for errors. - */ -int rs_setSockTimeout( int sockfd, bool forReceive = true, int timeout_Sec = 0, int timeout_uSec = 0); - -#endif /* RS_UNIVERSAL_NETWORK_HEADER */ diff --git a/libretroshare/src/util/rsnet_ss.cc b/libretroshare/src/util/rsnet_ss.cc deleted file mode 100644 index 795ad6512..000000000 --- a/libretroshare/src/util/rsnet_ss.cc +++ /dev/null @@ -1,1285 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsnet_ss.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2004-2006 Robert Fernie * - * Copyright 2015-2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "util/rsurl.h" - -#include -#include -#include - -#ifdef WINDOWS_SYS -# include -/** Provides Linux like accessor for in6_addr.s6_addr16 for Windows. - * Yet Windows doesn't provide 32 bits accessors so there is no way to use - * in6_addr.s6_addr32 crossplatform. - */ -# define s6_addr16 u.Word -#else -# include -# include -# include -# ifdef __APPLE__ -/// Provides Linux like accessor for in6_addr.s6_addr16 for Mac. -# define s6_addr16 __u6_addr.__u6_addr16 -#endif // __APPLE__ -#endif // WINDOWS_SYS - -#include "util/rsnet.h" -#include "util/rsstring.h" -#include "pqi/pqinetwork.h" -#include "util/stacktrace.h" - -/***************************** Internal Helper Fns ******************************/ - -/******************************** Casting **************************************/ -struct sockaddr_in *to_ipv4_ptr(struct sockaddr_storage &addr); -struct sockaddr_in6 *to_ipv6_ptr(struct sockaddr_storage &addr); - -const struct sockaddr_in *to_const_ipv4_ptr(const struct sockaddr_storage &addr); -const struct sockaddr_in6 *to_const_ipv6_ptr(const struct sockaddr_storage &addr); - - -/******************************** Set / Clear ***********************************/ - -bool sockaddr_storage_ipv4_zeroip(struct sockaddr_storage &addr); -bool sockaddr_storage_ipv4_copyip(struct sockaddr_storage &dst, const struct sockaddr_storage &src); - -uint16_t sockaddr_storage_ipv4_port(const struct sockaddr_storage &addr); -bool sockaddr_storage_ipv4_setport(struct sockaddr_storage &addr, uint16_t port); - -bool sockaddr_storage_ipv6_zeroip(struct sockaddr_storage &addr); -bool sockaddr_storage_ipv6_copyip(struct sockaddr_storage &dst, const struct sockaddr_storage &src); - -uint16_t sockaddr_storage_ipv6_port(const struct sockaddr_storage &addr); -bool sockaddr_storage_ipv6_setport(struct sockaddr_storage &addr, uint16_t port); - -/******************************** Comparisions **********************************/ - -bool sockaddr_storage_ipv4_lessthan(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2); -bool sockaddr_storage_ipv4_same(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2); -bool sockaddr_storage_ipv4_sameip(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2); - -bool sockaddr_storage_ipv6_lessthan(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2); -bool sockaddr_storage_ipv6_same(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2); -bool sockaddr_storage_ipv6_sameip(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2); - - -/********************************* Output ***********************************/ -std::string sockaddr_storage_ipv4_iptostring(const struct sockaddr_storage &addr); -std::string sockaddr_storage_ipv6_iptostring(const struct sockaddr_storage &addr); - -/********************************* Net Checks ***********************************/ -bool sockaddr_storage_ipv4_isnull(const struct sockaddr_storage &addr); -bool sockaddr_storage_ipv4_isValidNet(const struct sockaddr_storage &addr); -bool sockaddr_storage_ipv4_isLoopbackNet(const struct sockaddr_storage &addr); -bool sockaddr_storage_ipv4_isPrivateNet(const struct sockaddr_storage &addr); -bool sockaddr_storage_ipv4_isExternalNet(const struct sockaddr_storage &addr); - -bool sockaddr_storage_ipv6_isnull(const struct sockaddr_storage &addr); -bool sockaddr_storage_ipv6_isValidNet(const struct sockaddr_storage &addr); -bool sockaddr_storage_ipv6_isLoopbackNet(const struct sockaddr_storage &addr); -bool sockaddr_storage_ipv6_isPrivateNet(const struct sockaddr_storage &addr); -bool sockaddr_storage_ipv6_isExternalNet(const struct sockaddr_storage &addr); - - -/***************************/ - -/******************************** Socket Fns ***********************************/ -// Standard bind, on OSX anyway will not accept a longer socklen for IPv4. -// so hidding details behind function. -int rs_bind(int fd, const sockaddr_storage& addr) -{ -#ifdef SS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << std::endl; -#endif - - socklen_t len = 0; - switch (addr.ss_family) - { - case AF_INET: - len = sizeof(struct sockaddr_in); - break; - case AF_INET6: - len = sizeof(struct sockaddr_in6); - break; - } - - return bind(fd, reinterpret_cast(&addr), len); -} - - - - -/******************************** Set / Clear ***********************************/ - -void sockaddr_storage_clear(struct sockaddr_storage &addr) -{ - memset(&addr, 0, sizeof(addr)); -} - -// mods. -bool sockaddr_storage_zeroip(struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_zeroip()"; - std::cerr << std::endl; -#endif - - switch(addr.ss_family) - { - case AF_INET: - return sockaddr_storage_ipv4_zeroip(addr); - break; - case AF_INET6: - return sockaddr_storage_ipv6_zeroip(addr); - break; - default: - std::cerr << "sockaddr_storage_zeroip() invalid addr.ss_family clearing whole address"; - std::cerr << std::endl; - sockaddr_storage_clear(addr); - break; - } - return false; -} - -bool sockaddr_storage_copyip(struct sockaddr_storage &dst, const struct sockaddr_storage &src) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_copyip()" << std::endl; -#endif - - switch(src.ss_family) - { - case AF_INET: - return sockaddr_storage_ipv4_copyip(dst, src); - break; - case AF_INET6: - return sockaddr_storage_ipv6_copyip(dst, src); - break; - default: -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_copyip() Unknown ss_family: " << src.ss_family << std::endl; -#endif - break; - } - return false; -} - - -uint16_t sockaddr_storage_port(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_port()" << std::endl; -#endif - switch(addr.ss_family) - { - case AF_INET: - return sockaddr_storage_ipv4_port(addr); - case AF_INET6: - return sockaddr_storage_ipv6_port(addr); - default: - std::cerr << "sockaddr_storage_port() invalid addr.ss_family" << std::endl; -#ifdef SS_DEBUG - sockaddr_storage_dump(addr); - print_stacktrace(); -#endif - break; - } - return 0; -} - -bool sockaddr_storage_setport(struct sockaddr_storage &addr, uint16_t port) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_setport()" << std::endl; -#endif - - switch(addr.ss_family) - { - case AF_INET: - return sockaddr_storage_ipv4_setport(addr, port); - break; - case AF_INET6: - return sockaddr_storage_ipv6_setport(addr, port); - break; - default: - std::cerr << "sockaddr_storage_setport() invalid addr.ss_family" << std::endl; - break; - } - return false; -} - - -bool sockaddr_storage_setipv4(struct sockaddr_storage &addr, const sockaddr_in *addr_ipv4) -{ -#ifdef SS_DEBUG - RS_ERR(); -#endif - - sockaddr_storage_clear(addr); - struct sockaddr_in *ipv4_ptr = to_ipv4_ptr(addr); - - ipv4_ptr->sin_family = AF_INET; - ipv4_ptr->sin_addr = addr_ipv4->sin_addr; - ipv4_ptr->sin_port = addr_ipv4->sin_port; - - return true; -} - -bool sockaddr_storage_setipv6(struct sockaddr_storage &addr, const sockaddr_in6 *addr_ipv6) -{ -#ifdef SS_DEBUG - RS_ERR(); -#endif - - sockaddr_storage_clear(addr); - struct sockaddr_in6 *ipv6_ptr = to_ipv6_ptr(addr); - - ipv6_ptr->sin6_family = AF_INET6; - ipv6_ptr->sin6_addr = addr_ipv6->sin6_addr; - ipv6_ptr->sin6_port = addr_ipv6->sin6_port; - - return true; -} - -#ifdef WINDOWS_SYS -#ifndef InetPtonA -int inet_pton(int af, const char *src, void *dst) -{ - sockaddr_storage ss; - int size = sizeof(ss); - char src_copy[INET6_ADDRSTRLEN+1]; - - ZeroMemory(&ss, sizeof(ss)); - /* stupid non-const API */ - strncpy (src_copy, src, INET6_ADDRSTRLEN+1); - src_copy[INET6_ADDRSTRLEN] = 0; - - if (WSAStringToAddressA(src_copy, af, NULL, (sockaddr *)&ss, &size) == 0) - { - switch(af) - { - case AF_INET: - *(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr; - return 1; - case AF_INET6: - *(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr; - return 1; - } - } - return 0; -} -#endif -#endif - -bool sockaddr_storage_inet_pton( sockaddr_storage &addr, - const std::string& ipStr ) -{ -#ifdef SS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << std::endl; -#endif - - struct sockaddr_in6 * addrv6p = (struct sockaddr_in6 *) &addr; - struct sockaddr_in * addrv4p = (struct sockaddr_in *) &addr; - - if ( 1 == inet_pton(AF_INET6, ipStr.c_str(), &(addrv6p->sin6_addr)) ) - { - addr.ss_family = AF_INET6; - return true; - } - else if ( 1 == inet_pton(AF_INET, ipStr.c_str(), &(addrv4p->sin_addr)) ) - { - addr.ss_family = AF_INET; - return sockaddr_storage_ipv4_to_ipv6(addr); - } - - return false; -} - - -bool sockaddr_storage_ipv4_aton(struct sockaddr_storage &addr, const char *name) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_aton()"; - std::cerr << std::endl; -#endif - - struct sockaddr_in *ipv4_ptr = to_ipv4_ptr(addr); - ipv4_ptr->sin_family = AF_INET; - return (1 == inet_aton(name, &(ipv4_ptr->sin_addr))); -} - -bool sockaddr_storage_ipv4_to_ipv6(sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << std::endl; -#endif - - if ( addr.ss_family == AF_INET6 ) return true; - - if ( addr.ss_family == AF_INET ) - { - sockaddr_in & addr_ipv4 = (sockaddr_in &) addr; - sockaddr_in6 & addr_ipv6 = (sockaddr_in6 &) addr; - - uint32_t ip = addr_ipv4.sin_addr.s_addr; - uint16_t port = addr_ipv4.sin_port; - - sockaddr_storage_clear(addr); - addr_ipv6.sin6_family = AF_INET6; - addr_ipv6.sin6_port = port; - addr_ipv6.sin6_addr.s6_addr16[5] = htons(0xffff); - memmove( reinterpret_cast(&(addr_ipv6.sin6_addr.s6_addr16[6])), - reinterpret_cast(&ip), 4 ); - return true; - } - - return false; -} - -bool sockaddr_storage_ipv6_to_ipv4(sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << std::endl; -#endif - - if ( addr.ss_family == AF_INET ) return true; - - if ( addr.ss_family == AF_INET6 ) - { - sockaddr_in6 & addr_ipv6 = (sockaddr_in6 &) addr; - bool ipv4m = addr_ipv6.sin6_addr.s6_addr16[5] == htons(0xffff); - for ( int i = 0; ipv4m && i < 5 ; ++i ) - ipv4m &= addr_ipv6.sin6_addr.s6_addr16[i] == htons(0x0000); - - if(ipv4m) - { - uint32_t ip; - memmove( reinterpret_cast(&ip), - reinterpret_cast(&(addr_ipv6.sin6_addr.s6_addr16[6])), - 4 ); - uint16_t port = addr_ipv6.sin6_port; - - sockaddr_in & addr_ipv4 = (sockaddr_in &) addr; - - sockaddr_storage_clear(addr); - addr_ipv4.sin_family = AF_INET; - addr_ipv4.sin_port = port; - addr_ipv4.sin_addr.s_addr = ip; - - return true; - } - } - - return false; -} - - -/******************************** Comparisions **********************************/ - -bool operator<(const struct sockaddr_storage &a, const struct sockaddr_storage &b) -{ - if (!sockaddr_storage_samefamily(a, b)) - { - return (a.ss_family < b.ss_family); - } - - switch(a.ss_family) - { - case AF_INET: - return sockaddr_storage_ipv4_lessthan(a, b); - break; - case AF_INET6: - return sockaddr_storage_ipv6_lessthan(a, b); - break; - default: -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_operator<() INVALID Family - error"; - std::cerr << std::endl; -#endif - break; - } - return false; -} - - -bool sockaddr_storage_same(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_same()"; - std::cerr << std::endl; -#endif - - if (!sockaddr_storage_samefamily(addr, addr2)) - return false; - - switch(addr.ss_family) - { - case AF_INET: - return sockaddr_storage_ipv4_same(addr, addr2); - break; - case AF_INET6: - return sockaddr_storage_ipv6_same(addr, addr2); - break; - default: -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_same() INVALID Family - error"; - std::cerr << std::endl; -#endif - break; - } - return false; -} - - -bool sockaddr_storage_samefamily(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_samefamily()"; - std::cerr << std::endl; -#endif - - return (addr.ss_family == addr2.ss_family); -} - -bool sockaddr_storage_sameip(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_sameip()"; - std::cerr << std::endl; -#endif - - if (!sockaddr_storage_samefamily(addr, addr2)) - return false; - - switch(addr.ss_family) - { - case AF_INET: - return sockaddr_storage_ipv4_sameip(addr, addr2); - break; - case AF_INET6: - return sockaddr_storage_ipv6_sameip(addr, addr2); - break; - default: -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_sameip() INVALID Family - error"; - std::cerr << std::endl; -#endif - break; - } - return false; -} - -/********************************* Output ***********************************/ - -std::string sockaddr_storage_tostring(const struct sockaddr_storage &addr) -{ - RsUrl url; - - switch(addr.ss_family) - { - case AF_INET: - url.setScheme("ipv4"); - break; - case AF_INET6: - url.setScheme("ipv6"); - break; - default: - return "AF_INVALID"; - } - - url.setHost(sockaddr_storage_iptostring(addr)) - .setPort(sockaddr_storage_port(addr)); - - return url.toString(); -} - -bool sockaddr_storage_fromString(const std::string& str, sockaddr_storage &addr) -{ - RsUrl url(str); - bool valid = sockaddr_storage_inet_pton(addr, url.host()); - if(url.hasPort()) sockaddr_storage_setport(addr, url.port()); - return valid; -} - -void sockaddr_storage_dump(const sockaddr_storage & addr, std::string * outputString) -{ - // This function must not rely on others sockaddr_storage_* - - std::stringstream output; - output << "sockaddr_storage_dump(addr) "; - - switch (addr.ss_family) - { - case AF_INET: - { - const sockaddr_in * in = (const sockaddr_in *) & addr; - output << "addr.ss_family = AF_INET"; - output << " in->sin_addr = "; - output << inet_ntoa(in->sin_addr); - output << " in->sin_port = "; - output << in->sin_port; - break; - } - case AF_INET6: - { - const sockaddr_in6 * in6 = (const sockaddr_in6 *) & addr; - std::string addrStr = "INVALID_IPV6"; - sockaddr_storage_inet_ntop(addr, addrStr); - output << "addr.ss_family = AF_INET6"; - output << " in6->sin6_addr = "; - output << addrStr; - output << " in6->sin6_scope_id = "; - output << in6->sin6_scope_id; - output << " in6->sin6_port = "; - output << in6->sin6_port; - break; - } - default: - { - output << "unknown addr.ss_family "; - const uint8_t * buf = reinterpret_cast(&addr); - for( uint32_t i = 0; i < sizeof(addr); ++i ) - output << std::setw(2) << std::setfill('0') << std::hex << +buf[i]; - /* The unary +buf[i] operation forces a no-op type conversion to an int - * with the correct sign */ - } - } - - if(outputString) - { - outputString->append(output.str() + "\n"); -#ifdef SS_DEBUG - std::cerr << output.str() << std::endl; -#endif - } - else - std::cerr << output.str() << std::endl; -} - -std::string sockaddr_storage_familytostring(const struct sockaddr_storage &addr) -{ - std::string output; - switch(addr.ss_family) - { - case AF_INET: - output = "IPv4"; - break; - case AF_INET6: - output = "IPv6"; - break; - default: - output = "AF_INVALID"; -#ifdef SS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " Got invalid address!" - << std::endl; - sockaddr_storage_dump(addr); - print_stacktrace(); -#endif - break; - } - return output; -} - -std::string sockaddr_storage_iptostring(const struct sockaddr_storage &addr) -{ - std::string output; - switch(addr.ss_family) - { - case AF_INET: - output = sockaddr_storage_ipv4_iptostring(addr); - break; - case AF_INET6: - output = sockaddr_storage_ipv6_iptostring(addr); - break; - default: - output = "INVALID_IP"; - std::cerr << __PRETTY_FUNCTION__ << " Got invalid IP!" << std::endl; -#ifdef SS_DEBUG - sockaddr_storage_dump(addr); - print_stacktrace(); -#endif - break; - } - return output; -} - -std::string sockaddr_storage_porttostring(const struct sockaddr_storage &addr) -{ - std::string output; - uint16_t port = sockaddr_storage_port(addr); - rs_sprintf(output, "%u", port); - return output; -} - - -/********************************* Net Checks ***********************************/ -bool sockaddr_storage_isnull(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_isnull()"; - std::cerr << std::endl; -#endif - - if (addr.ss_family == 0) - return true; - - switch(addr.ss_family) - { - case AF_INET: - return sockaddr_storage_ipv4_isnull(addr); - break; - case AF_INET6: - return sockaddr_storage_ipv6_isnull(addr); - break; - default: - return true; - break; - } - return true; -} - -bool sockaddr_storage_isValidNet(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_isValidNet()" << std::endl; -#endif - - switch(addr.ss_family) - { - case AF_INET: - return sockaddr_storage_ipv4_isValidNet(addr); - case AF_INET6: - return sockaddr_storage_ipv6_isValidNet(addr); - default: -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_isValidNet() INVALID Family" << std::endl; - sockaddr_storage_dump(addr); -#endif - break; - } - return false; -} - -bool sockaddr_storage_isLoopbackNet(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_isLoopbackNet()"; - std::cerr << std::endl; -#endif - - switch(addr.ss_family) - { - case AF_INET: - return sockaddr_storage_ipv4_isLoopbackNet(addr); - break; - case AF_INET6: - return sockaddr_storage_ipv6_isLoopbackNet(addr); - break; - default: -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_isLoopbackNet() INVALID Family - error: " << sockaddr_storage_iptostring(addr); - std::cerr << std::endl; -#endif - break; - } - return false; -} - - -bool sockaddr_storage_isPrivateNet(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_isPrivateNet()"; - std::cerr << std::endl; -#endif - - switch(addr.ss_family) - { - case AF_INET: - return sockaddr_storage_ipv4_isPrivateNet(addr); - break; - case AF_INET6: - return sockaddr_storage_ipv6_isPrivateNet(addr); - break; - default: -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_isPrivateNet() INVALID Family - error: " << sockaddr_storage_iptostring(addr); - std::cerr << std::endl; -#endif - break; - } - return false; -} - -bool sockaddr_storage_isLinkLocalNet(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << std::endl; -#endif - - switch(addr.ss_family) - { - case AF_INET: - return isLinkLocalNet(&(to_const_ipv4_ptr(addr)->sin_addr)); - case AF_INET6: - return sockaddr_storage_ipv6_isLinkLocalNet(addr); - default: -#ifdef SS_DEBUG - std::cerr << __PRETTY_FUNCTION__ <<" INVALID Family:" << std::endl; - sockaddr_storage_dump(addr); -#endif - break; - } - - return false; -} - -bool sockaddr_storage_ipv6_isLinkLocalNet(const sockaddr_storage &addr) -{ - if(addr.ss_family != AF_INET6) return false; - - const sockaddr_in6 * addr6 = (const sockaddr_in6 *) &addr; - uint16_t mask = htons(0xffc0); - uint16_t llPrefix = htons(0xfe80); - return ((addr6->sin6_addr.s6_addr16[0] & mask ) == llPrefix); -} - - -bool sockaddr_storage_isExternalNet(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_isExternalNet()"; - std::cerr << std::endl; -#endif - - switch(addr.ss_family) - { - case AF_INET: - return sockaddr_storage_ipv4_isExternalNet(addr); - break; - case AF_INET6: - return sockaddr_storage_ipv6_isExternalNet(addr); - break; - default: -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_isExternalNet() INVALID Family - error"; - std::cerr << std::endl; -#endif - break; - } - return false; -} - - - - - -/***************************** Internal Helper Fns ******************************/ - - -/******************************** Casting **************************************/ - -struct sockaddr_in *to_ipv4_ptr(struct sockaddr_storage &addr) -{ - struct sockaddr_in *ipv4_ptr = (struct sockaddr_in *) &addr; - return ipv4_ptr; -} - -struct sockaddr_in6 *to_ipv6_ptr(struct sockaddr_storage &addr) -{ - struct sockaddr_in6 *ipv6_ptr = (struct sockaddr_in6 *) &addr; - return ipv6_ptr; -} - -const struct sockaddr_in *to_const_ipv4_ptr(const struct sockaddr_storage &addr) -{ - const struct sockaddr_in *ipv4_ptr = (const struct sockaddr_in *) &addr; - return ipv4_ptr; -} - -const struct sockaddr_in6 *to_const_ipv6_ptr(const struct sockaddr_storage &addr) -{ - const struct sockaddr_in6 *ipv6_ptr = (const struct sockaddr_in6 *) &addr; - return ipv6_ptr; -} - - -/******************************** Set / Clear ***********************************/ - -bool sockaddr_storage_copy(const sockaddr_storage& src, sockaddr_storage& dst) -{ - if(&src == &dst) return true; - - switch(src.ss_family) - { - case AF_INET: - { - sockaddr_storage_clear(dst); - const sockaddr_in& ins(reinterpret_cast(src)); - sockaddr_in& ind(reinterpret_cast(dst)); - - ind.sin_family = AF_INET; - ind.sin_addr.s_addr = ins.sin_addr.s_addr; - ind.sin_port = ins.sin_port; - - return true; - } - case AF_INET6: - { - sockaddr_storage_clear(dst); - const sockaddr_in6& ins6(reinterpret_cast(src)); - sockaddr_in6& ind6(reinterpret_cast(dst)); - - ind6.sin6_family = AF_INET6; - for(int i=0; i<8; ++i) - ind6.sin6_addr.s6_addr16[i] = ins6.sin6_addr.s6_addr16[i]; - ind6.sin6_flowinfo = ins6.sin6_flowinfo; - ind6.sin6_port = ins6.sin6_port; - ind6.sin6_scope_id = ins6.sin6_scope_id; - - return true; - } - default: -#ifdef SS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " Attempt to copy unknown family! " - << src.ss_family << " defaulting to memmove!" << std::endl; - sockaddr_storage_dump(src); - print_stacktrace(); -#endif // SS_DEBUG - memmove(&dst, &src, sizeof(sockaddr_storage)); - return true; - } -} - -bool sockaddr_storage_ipv4_zeroip(struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_zeroip()"; - std::cerr << std::endl; -#endif - - struct sockaddr_in *ipv4_ptr = to_ipv4_ptr(addr); - memset(&(ipv4_ptr->sin_addr), 0, sizeof(ipv4_ptr->sin_addr)); - return true; -} - - -bool sockaddr_storage_ipv4_copyip(struct sockaddr_storage &dst, const struct sockaddr_storage &src) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_copyip()"; - std::cerr << std::endl; -#endif - - struct sockaddr_in *dst_ptr = to_ipv4_ptr(dst); - const struct sockaddr_in *src_ptr = to_const_ipv4_ptr(src); - - dst_ptr->sin_family = AF_INET; - memcpy(&(dst_ptr->sin_addr), &(src_ptr->sin_addr), sizeof(src_ptr->sin_addr)); - return true; -} - -uint16_t sockaddr_storage_ipv4_port(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_port()"; - std::cerr << std::endl; -#endif - - const struct sockaddr_in *ipv4_ptr = to_const_ipv4_ptr(addr); - uint16_t port = ntohs(ipv4_ptr->sin_port); - return port; -} - -bool sockaddr_storage_ipv4_setport(struct sockaddr_storage &addr, uint16_t port) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_setport()"; - std::cerr << std::endl; -#endif - - struct sockaddr_in *ipv4_ptr = to_ipv4_ptr(addr); - ipv4_ptr->sin_port = htons(port); - return true; -} - -bool sockaddr_storage_ipv6_zeroip(struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv6_zeroip()"; - std::cerr << std::endl; -#endif - - struct sockaddr_in6 *ipv6_ptr = to_ipv6_ptr(addr); - memset(&(ipv6_ptr->sin6_addr), 0, sizeof(ipv6_ptr->sin6_addr)); - return true; -} - -bool sockaddr_storage_ipv6_copyip(struct sockaddr_storage &dst, const struct sockaddr_storage &src) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv6_copyip()" << std::endl; -#endif - - struct sockaddr_in6 *dst_ptr = to_ipv6_ptr(dst); - const struct sockaddr_in6 *src_ptr = to_const_ipv6_ptr(src); - - dst_ptr->sin6_family = AF_INET6; - memcpy(&(dst_ptr->sin6_addr), &(src_ptr->sin6_addr), sizeof(src_ptr->sin6_addr)); - return true; -} - -uint16_t sockaddr_storage_ipv6_port(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv6_port()"; - std::cerr << std::endl; -#endif - - const struct sockaddr_in6 *ipv6_ptr = to_const_ipv6_ptr(addr); - uint16_t port = ntohs(ipv6_ptr->sin6_port); - return port; -} - -bool sockaddr_storage_ipv6_setport(struct sockaddr_storage &addr, uint16_t port) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv6_setport()"; - std::cerr << std::endl; -#endif - - struct sockaddr_in6 *ipv6_ptr = to_ipv6_ptr(addr); - ipv6_ptr->sin6_port = htons(port); - return true; -} - - -/******************************** Comparisions **********************************/ - -bool sockaddr_storage_ipv4_lessthan(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_lessthan()"; - std::cerr << std::endl; -#endif - - const struct sockaddr_in *ptr1 = to_const_ipv4_ptr(addr); - const struct sockaddr_in *ptr2 = to_const_ipv4_ptr(addr2); - - if (ptr1->sin_addr.s_addr == ptr2->sin_addr.s_addr) - { - return ptr1->sin_port < ptr2->sin_port; - } - return (ptr1->sin_addr.s_addr < ptr2->sin_addr.s_addr); -} - -bool sockaddr_storage_ipv4_same(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_same()"; - std::cerr << std::endl; -#endif - - const struct sockaddr_in *ptr1 = to_const_ipv4_ptr(addr); - const struct sockaddr_in *ptr2 = to_const_ipv4_ptr(addr2); - - return (ptr1->sin_addr.s_addr == ptr2->sin_addr.s_addr) && - (ptr1->sin_port == ptr2->sin_port); -} - -bool sockaddr_storage_ipv4_sameip(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_sameip()"; - std::cerr << std::endl; -#endif - - const struct sockaddr_in *ptr1 = to_const_ipv4_ptr(addr); - const struct sockaddr_in *ptr2 = to_const_ipv4_ptr(addr2); - - return (ptr1->sin_addr.s_addr == ptr2->sin_addr.s_addr); -} - -// IPV6 -bool sockaddr_storage_ipv6_lessthan(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv6_lessthan()"; - std::cerr << std::endl; -#endif - - const struct sockaddr_in6 *ptr1 = to_const_ipv6_ptr(addr); - const struct sockaddr_in6 *ptr2 = to_const_ipv6_ptr(addr2); - - uint32_t *ip6addr1 = (uint32_t *) ptr1->sin6_addr.s6_addr; - uint32_t *ip6addr2 = (uint32_t *) ptr2->sin6_addr.s6_addr; - for(int i = 0; i < 4; i++) - { - if (ip6addr1[i] == ip6addr2[i]) - { - continue; - } - - return (ip6addr1[i] < ip6addr2[i]); - } - - return (ptr1->sin6_port < ptr2->sin6_port); -} - -bool sockaddr_storage_ipv6_same(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv6_same()"; - std::cerr << std::endl; -#endif - const struct sockaddr_in6 *ptr1 = to_const_ipv6_ptr(addr); - const struct sockaddr_in6 *ptr2 = to_const_ipv6_ptr(addr2); - - return sockaddr_storage_ipv6_sameip(addr, addr2) && (ptr1->sin6_port == ptr2->sin6_port); -} - -bool sockaddr_storage_ipv6_sameip(const struct sockaddr_storage &addr, const struct sockaddr_storage &addr2) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv6_sameip()"; - std::cerr << std::endl; -#endif - - const struct sockaddr_in6 *ptr1 = to_const_ipv6_ptr(addr); - const struct sockaddr_in6 *ptr2 = to_const_ipv6_ptr(addr2); - - uint32_t *ip6addr1 = (uint32_t *) ptr1->sin6_addr.s6_addr; - uint32_t *ip6addr2 = (uint32_t *) ptr2->sin6_addr.s6_addr; - - for(int i = 0; i < 4; i++) - { - if (ip6addr1[i] != ip6addr2[i]) - { - return false; - } - } - return true; -} - -/********************************* Output ***********************************/ -std::string sockaddr_storage_ipv4_iptostring(const struct sockaddr_storage &addr) -{ - const struct sockaddr_in *ptr = to_const_ipv4_ptr(addr); - std::string output; - output = rs_inet_ntoa(ptr->sin_addr); - return output; -} - -std::string sockaddr_storage_ipv6_iptostring(const struct sockaddr_storage & addr) -{ - std::string addrStr; - sockaddr_storage_inet_ntop(addr, addrStr); - return addrStr; -} - - -/********************************* Net Checks ***********************************/ -bool sockaddr_storage_ipv4_isnull(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_isnull()"; - std::cerr << std::endl; -#endif - - const struct sockaddr_in *ptr1 = to_const_ipv4_ptr(addr); - if (ptr1->sin_family != AF_INET) - { - return true; - } - if ((ptr1->sin_addr.s_addr == 0) || (ptr1->sin_addr.s_addr == 1)) - { - return true; - } - return false; -} - -bool sockaddr_storage_ipv4_isValidNet(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_isValidNet()"; - std::cerr << std::endl; -#endif - - const struct sockaddr_in *ptr1 = to_const_ipv4_ptr(addr); - if (ptr1->sin_family != AF_INET) - { - return false; - } - return isValidNet(&(ptr1->sin_addr)); -} - - -bool sockaddr_storage_ipv4_isLoopbackNet(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_isLoopbackNet()"; - std::cerr << std::endl; -#endif - - - const struct sockaddr_in *ptr1 = to_const_ipv4_ptr(addr); - if (ptr1->sin_family != AF_INET) - { - return false; - } - return isLoopbackNet(&(ptr1->sin_addr)); -} - -bool sockaddr_storage_ipv4_isPrivateNet(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_isPrivateNet()"; - std::cerr << std::endl; -#endif - - - const struct sockaddr_in *ptr1 = to_const_ipv4_ptr(addr); - if (ptr1->sin_family != AF_INET) - { - return false; - } - return isPrivateNet(&(ptr1->sin_addr)); -} - -bool sockaddr_storage_ipv4_isExternalNet(const struct sockaddr_storage &addr) -{ -#ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv4_isExternalNet()"; - std::cerr << std::endl; -#endif - - const struct sockaddr_in *ptr1 = to_const_ipv4_ptr(addr); - if (ptr1->sin_family != AF_INET) - { - return false; - } - return isExternalNet(&(ptr1->sin_addr)); -} - - -bool sockaddr_storage_ipv6_isnull(const struct sockaddr_storage& addr) -{ - const sockaddr_in6& addr6 = reinterpret_cast(addr); - - uint16_t nZero = htons(0); // anyway 0 should be the same in host and net - bool isZero = (addr6.sin6_addr.s6_addr16[7] == nZero); - for (int i=0; isZero && i<7; ++i) - isZero &= (addr6.sin6_addr.s6_addr16[i] == nZero); - - return nZero; -} - -bool sockaddr_storage_ipv6_isValidNet(const struct sockaddr_storage& addr) -{ - return !sockaddr_storage_ipv6_isnull(addr); -} - -bool sockaddr_storage_ipv6_isLoopbackNet(const struct sockaddr_storage& addr) -{ - const sockaddr_in6& addr6 = reinterpret_cast(addr); - bool isLoopBack = (addr6.sin6_addr.s6_addr16[7] == htons(0x0001)); - uint16_t nZero = htons(0); // anyway 0 should be the same in host and net - for (int i=0; isLoopBack && i<7; ++i) - isLoopBack &= (addr6.sin6_addr.s6_addr16[i] == nZero); - -#ifdef SS_DEBUG - std::cerr << __PRETTY_FUNCTION__ << " " << sockaddr_storage_tostring(addr) - << " " << isLoopBack << std::endl; -#endif - - return isLoopBack; -} - -bool sockaddr_storage_ipv6_isPrivateNet(const struct sockaddr_storage &/*addr*/) -{ - /* It is unlikely that we end up connecting to an IPv6 address behind NAT - * W.R.T. RS it is probably better to consider all IPv6 as internal/local - * addresses as direct connection should be always possible. */ - - return true; -} - -bool sockaddr_storage_ipv6_isExternalNet(const struct sockaddr_storage &/*addr*/) -{ - /* It is unlikely that we end up connecting to an IPv6 address behind NAT - * W.R.T. RS it is probably better to consider all IPv6 as internal/local - * addresses as direct connection should be always possible. */ - - return false; -} - -bool sockaddr_storage_inet_ntop (const sockaddr_storage &addr, std::string &dst) -{ - bool success = false; - char ipStr[255]; - -#ifdef WINDOWS_SYS - // Use WSAAddressToString instead of InetNtop because the latter is missing - // on XP and is present only on Vista and newers - wchar_t wIpStr[255]; - long unsigned int len = 255; - sockaddr_storage tmp; - sockaddr_storage_clear(tmp); - sockaddr_storage_copyip(tmp, addr); - sockaddr * sptr = (sockaddr *) &tmp; - success = (0 == WSAAddressToString( sptr, sizeof(sockaddr_storage), NULL, wIpStr, &len )); - wcstombs(ipStr, wIpStr, len); -#else // WINDOWS_SYS - switch(addr.ss_family) - { - case AF_INET: - { - const struct sockaddr_in * addrv4p = (const struct sockaddr_in *) &addr; - success = inet_ntop( addr.ss_family, (const void *) &(addrv4p->sin_addr), ipStr, INET_ADDRSTRLEN ); - } - break; - case AF_INET6: - { - const struct sockaddr_in6 * addrv6p = (const struct sockaddr_in6 *) &addr; - success = inet_ntop( addr.ss_family, (const void *) &(addrv6p->sin6_addr), ipStr, INET6_ADDRSTRLEN ); - } - break; - } -#endif // WINDOWS_SYS - - dst = ipStr; - return success; -} - -int rs_setsockopt( int sockfd, int level, int optname, - const uint8_t *optval, uint32_t optlen ) -{ -#ifdef WINDOWS_SYS - return setsockopt( sockfd, level, optname, - reinterpret_cast(optval), optlen ); -#else - return setsockopt( sockfd, level, optname, - reinterpret_cast(optval), optlen ); -#endif // WINDOWS_SYS -} diff --git a/libretroshare/src/util/rsprint.cc b/libretroshare/src/util/rsprint.cc deleted file mode 100644 index 5410ab0d0..000000000 --- a/libretroshare/src/util/rsprint.cc +++ /dev/null @@ -1,183 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsprint.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008-2008 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "util/rsprint.h" -#include "util/rsstring.h" -#include -#include -#include -#include -#include - -#ifdef WINDOWS_SYS -#include "util/rstime.h" -#include -#endif - -std::string RsUtil::NumberToString(uint64_t n,bool hex) -{ - std::ostringstream os ; - - if(hex) - os << std::hex ; - - os << n ; - os.flush() ; - - return os.str(); -} - -bool RsUtil::StringToInt(const std::string& s,int& n) -{ - if(sscanf(s.c_str(),"%d",&n) == 1) - return true; - else - return false; -} -std::string RsUtil::BinToHex(const std::string &bin) -{ - return BinToHex(bin.c_str(), bin.length()); -} - -std::string RsUtil::BinToHex(const unsigned char *arr, const uint32_t len,uint32_t max_len) -{ - if(max_len > 0) - return BinToHex((char*)arr,std::min(max_len,len)) + ((len > max_len)?"...":"") ; - else - return BinToHex((char*)arr,len) ; -} -std::string RsUtil::BinToHex(const char *arr, const uint32_t len) -{ - std::string out; - - for(uint32_t j = 0; j < len; j++) - { - rs_sprintf_append(out, "%02x", (int32_t) (((const uint8_t *) arr)[j])); - } - - return out; -} - -std::string RsUtil::HashId(const std::string &id, bool reverse) -{ - std::string hash; - std::string tohash; - if (reverse) - { - std::string::const_reverse_iterator rit; - for(rit = id.rbegin(); rit != id.rend(); ++rit) - { - tohash += (*rit); - } - } - else - { - tohash = id; - } - - SHA_CTX *sha_ctx = new SHA_CTX; - uint8_t sha_hash[SHA_DIGEST_LENGTH]; - - SHA1_Init(sha_ctx); - SHA1_Update(sha_ctx, tohash.c_str(), tohash.length()); - SHA1_Final(sha_hash, sha_ctx); - - for(uint16_t i = 0; i < SHA_DIGEST_LENGTH; i++) - { - hash += sha_hash[i]; - } - - /* cleanup */ - delete sha_ctx; - - return hash; -} - -static int toHalfByte(char u,bool& ok) -{ - if(u >= 'a' && u <= 'f') return u-'a' + 0xa; - if(u >= 'A' && u <= 'F') return u-'A' + 0xa; - if(u >= '0' && u <= '9') return u-'0' + 0x0; - - ok = false ; - - return 0; -} - -bool RsUtil::HexToBin(const std::string& input,unsigned char *data, const uint32_t len) -{ - if(input.size() & 1) - return false ; - - if(len != input.size()/2) - return false ; - - bool ok = true ; - - for(uint32_t i=0;(i RsUtil::BinToSha256(const std::vector &in) -{ - std::vector out; - - SHA256_CTX *sha_ctx = new SHA256_CTX; - uint8_t sha_hash[SHA256_DIGEST_LENGTH] = {0}; - - SHA256_Init(sha_ctx); - SHA256_Update(sha_ctx, in.data(), in.size()); - SHA256_Final(sha_hash, sha_ctx); - - for(uint16_t i = 0; i < SHA256_DIGEST_LENGTH; i++) - { - out.push_back(sha_hash[i]); - } - - /* cleanup */ - delete sha_ctx; - return out; -} diff --git a/libretroshare/src/util/rsprint.h b/libretroshare/src/util/rsprint.h deleted file mode 100644 index bdfcb942b..000000000 --- a/libretroshare/src/util/rsprint.h +++ /dev/null @@ -1,50 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsprint.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2008-2008 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RSUTIL_PRINTFNS_H -#define RSUTIL_PRINTFNS_H - -#include -#include -#include - -namespace RsUtil { - -std::string BinToHex(const std::string &bin); -std::string BinToHex(const char *arr, const uint32_t len); - -// proxy function. When max_len>0 and len>max_len, only the first "max_len" bytes are writen to the string and "..." is happened. - -std::string BinToHex(const unsigned char *arr, const uint32_t len, uint32_t max_len=0); -bool HexToBin(const std::string& input,unsigned char *data, const uint32_t len); -std::string NumberToString(uint64_t n, bool hex=false); - -// Returns in n the int that can be read in the string. Returns false when no int is fond. -bool StringToInt(const std::string& s,int& n); - -std::string HashId(const std::string &id, bool reverse = false); -std::vector BinToSha256(const std::vector &in); - -//std::string AccurateTimeString(); - -} - -#endif diff --git a/libretroshare/src/util/rsrandom.cc b/libretroshare/src/util/rsrandom.cc deleted file mode 100644 index 96a24b140..000000000 --- a/libretroshare/src/util/rsrandom.cc +++ /dev/null @@ -1,150 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsrandom.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2010 Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "rsrandom.h" - -#include -#include -#include -#include - -uint32_t RsRandom::index = RsRandom::N; -std::vector RsRandom::MT(RsRandom::N,0u); -RsMutex RsRandom::rndMtx("RsRandom"); - -/* According to our tests (cyril+thunder), on both Windows and Linux does - * RAND_bytes init itself automatically at first call, from system-based - * unpredictable values, so that seeding is not even needed. - * This call still adds some randomness (not much actually, but it's always good - * to have anyway) */ -#ifdef WINDOWS_SYS -# include "util/rstime.h" -# ifdef WIN_PTHREADS_H -static bool auto_seed = RsRandom::seed( - (time(nullptr) + - static_cast(pthread_self()) *0x1293fe)^0x18e34a12 ); -# else // def WIN_PTHREADS_H -static bool auto_seed = RsRandom::seed( - (time(nullptr) + - static_cast(pthread_self().p)*0x1293fe)^0x18e34a12 ); -# endif // def WIN_PTHREADS_H -#endif - -bool RsRandom::seed(uint32_t s) -{ - RS_STACK_MUTEX(rndMtx); - - MT.resize(N,0) ; // because MT might not be already resized - - uint32_t j ; - MT[0]= s & 0xffffffffUL; - for (j=1; j> 30)) + j) & 0xffffffffUL ; - - // This *does not* replace the internal seed state of RAND_bytes(), but only *adds* entropy to the random pool - // So calling this method with the same value twice does not guarranty that the output of the random bytes - // will be the same. - - RAND_seed((unsigned char *)&MT[0],N*sizeof(uint32_t)) ; - locked_next_state() ; - - return true ; -} - -void RsRandom::random_bytes(unsigned char *data,uint32_t size) -{ - RAND_bytes(data,size) ; -} -void RsRandom::locked_next_state() -{ - RAND_bytes((unsigned char *)&MT[0],N*sizeof(uint32_t)) ; - index = 0 ; -} - -uint32_t RsRandom::random_u32() -{ - uint32_t y; - - { - RS_STACK_MUTEX(rndMtx); - - index++ ; - - if(index >= N) - locked_next_state(); - - y = MT[index] ; - } - -#ifdef UNNECESSARY_CODE - // Tempering - y ^= (y >> 11); - y ^= (y << 7 ) & 0x9d2c5680UL; - y ^= (y << 15) & 0xefc60000UL; - y ^= (y >> 18); -#endif - - return y; -} - -uint64_t RsRandom::random_u64() -{ - return ((uint64_t)random_u32() << 32ul) + random_u32() ; -} - -float RsRandom::random_f32() -{ - return random_u32() / (float)(~(uint32_t)0) ; -} - -double RsRandom::random_f64() -{ - return random_u64() / (double)(~(uint64_t)0) ; -} - -/*static*/ std::string RsRandom::alphaNumeric(uint32_t length) -{ - std::string s; - while(s.size() < length) - { - uint8_t rChar; random_bytes(&rChar, 1); rChar = rChar % 123; - /* if(isalnum(val)) isalnum result may vary depend on locale!! */ - if( (rChar >= 48 && rChar <= 57) /* 0-9 */ || - (rChar >= 65 && rChar <= 90) /* A-Z */ || - (rChar >= 97 && rChar <= 122) /* a-z */ ) - s += static_cast(rChar); - } - - return s; -} - -/*static*/ std::string RsRandom::printable(uint32_t length) -{ - std::string res; - RsTemporaryMemory mem(length); - random_bytes(mem,length); - - for(uint32_t i=0; i * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - - -#include -#include - -#include "util/rsthreads.h" -#include "util/rsdeprecate.h" - -/** - * RsRandom provide a random number generator that is - * - thread safe - * - platform independent - * - fast - * - CRYPTOGRAPHICALLY SAFE, because it is based on openssl random number - * generator - */ -class RsRandom -{ -public: - static uint32_t random_u32(); - static uint64_t random_u64(); - static float random_f32(); - static double random_f64(); - - static bool seed(uint32_t s); - - static void random_bytes(uint8_t* data, uint32_t length); - - /// Return a random alphanumeric *[0-9,A-Z,a-z] string of the given lenght - static std::string alphaNumeric(uint32_t length); - - /** Return a random printable string of the given lenght */ - static std::string printable(uint32_t length); - - /** This return a printable string not an alphanumeric one @deprecated */ - RS_DEPRECATED_FOR("RsRandom::printable") - static inline std::string random_alphaNumericString(uint32_t length) - { return printable(length); } - -private: - static RsMutex rndMtx; - - static const uint32_t N = 1024; - - static void locked_next_state(); - static uint32_t index; - static std::vector MT; -}; - -/// @deprecated this alias is provided only for code retro-compatibility -using RSRandom RS_DEPRECATED_FOR(RsRandom) = RsRandom; diff --git a/libretroshare/src/util/rsrecogn.cc b/libretroshare/src/util/rsrecogn.cc deleted file mode 100644 index 5cc0a5e09..000000000 --- a/libretroshare/src/util/rsrecogn.cc +++ /dev/null @@ -1,656 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsrandom.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2013 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "pqi/pqi_base.h" - -#include "util/rsrecogn.h" -#include "util/radix64.h" -#include "util/rsstring.h" -#include "util/rsdir.h" - -#include "gxs/gxssecurity.h" - -#include -#include - -/*** - * #define DEBUG_RECOGN 1 - ***/ - -#define DEBUG_RECOGN 1 - -static std::string RecognKey = "MIICCgKCAgEA4/i2fy+zR27/H8fzphM8mR/Nz+yXjMJTtqKlCvEMQlyk7lKzDbKifNjGSiAXjSv3b9TRgMtje7hfEhs3//Oeu4KsCf6sz17aj2StBF579IdJTSUPDwq6jCsZ6NDEYpG8xz3FVV+Ac8q5Vpr/+jdg23ta09zq4aV8VIdIsroVOmZQqjwPcmQK57iWHd538i/XBtc2rnzbYq5bprnmtAKdx55gXVXDfALa0s6yR0HYvCaWguMEJhMIKWfi/9PEgLgwF9OmRwywc2TU/EdvYJo8fYHLfGk0PnYBuL1oSnn3cwAAef02W2JyCzQ84g30tLSUk+hC1LLi+iYj3x7IRR4q7Rlf/FYv/Q5fvjRtPT9eqM6fKyJ9ZO4NjlrSPFGydNbgABzP6WMhBzFjUkEKS27bGmr8Qxdj3Zp0TvR2IkyM6oM+6YknuM4RndUEgC1ZxtoIhugMjm6HdMQmoaHNK3kXewgQB90HHqzKA/J1gok3NcqL8Yls5g0LHepVHsU4cuaIqQr5yr665ZTLU2oqn1HIdkgydBYYUt6G3eWJKXYRbDhWPthGo/HK+W+iw6cTGWxzlCZS40EU9efxz4mDuhow67jOe704lBP3kiYXu05Y5uspaYnuvrvIwaRWBYapyR9UmKktnY8xJYrZvrcZgCovAbiodTzWeYg37xjFfGgYNI8CAwEAAQ=="; - -#define NUM_RECOGN_SIGN_KEYS 3 -static std::string RecognSigningKeys[NUM_RECOGN_SIGN_KEYS] = -{ - "AvMxAwAAA5YQMAAAABAANAAAAAoAAAABEEAAAAFMAKQAAAAmYjI2ZTUyNGFlZjczYmY3Y2MyMzUwNTc0ZTMyMjcxZWEAAAAAUl8ogFRAXAABEAAAARQwggEKAoIBAQCyblJK73O/fMI1BXTjInHqIWma62Z2r3K7/giT6Xm3k+lyNokvpR+I45XdEvPRmFVZmTU7XT2n3YiPDLe7y2r9fnYiLvBCdu+FBaVv5UQG8nvFGMLKbhdyRpOSBgDc+Y+8plMPn8jqgfNhLROMowmvDJQkJQjlm80d/9wj+VZ+tLiPPo8uOlghqNhdXDGK7HnfeLrJyD8kLEW7+4huaxR8IsLgjzuK8rovGLYCBcnx4TXvtbEeafJBBBt8S/GPeUaB1rxWpVV6fi+oBU6cvjbEqPzSalIrwNPyqlj+1SbL1jGEGEr1XIMzDa96SVsJ0F93lS3H9c8HdvByAifgzbPZAgMBAAEQUAAAAjIApAAAACZlM2Y4YjY3ZjJmYjM0NzZlZmYxZmM3ZjNhNjEzM2M5OQEgAAACBp1w449QGjchVotgHvGWRh18zpsDUHRv8PlRX1vXy8FMstTrnRjaDofFitmpJm8K6F1t/9jviCdB+BCvRzAS4SxER49YCBp04xZfX7c03xdq/e27jYRds2w6YHTiEgNi5v1cyWhrwDcCdefXRnHTH1UOw3jOoWnlnmM6jEsL39XI5fvsog9z8GxcG54APKA7JgiqhgMcrKRwNk74XJAzcjB6FS8xaV2gzpZZLNZ1TU+tJoLSiRqTU8UiAGbAR85lYLT5Ozdd2C+bTQ9f6vltz8bpzicJzxGCIsYtSL44InQsO/Oar9IgZu8QE4pTuunGJhVqEZru7ZN+oV+wXt51n+24SS0sNgNKVUFS74RfvsFi67CrXSWTOI8bVS0Lvv3EMWMdSF9dHGbdCFnp2/wqbW/4Qz7XYF4lcu9gLe4UtIrZ6TkAvBtnSfvTTdXj7kD6oHDjrUCjHPxdhz3BLRbj1wENZsoS3QDl22Ts7dbO8wHjutsS3/zx4DLlADoFlU8p7HJaCdrsq20P4WCeQJb6JbbLpGRAccKAidAPHMxQ4fr3b+GtjxpLJtXaytr4CPSXsCt4TloE9g5yCE6n/2UxQACp8Guh9l2MXmrD7qEGexhYqFB/OG84u3vL+gskmsKXTEqi2SiSmhvzta2p2hGCLCKRQeYbn+4TsIQfgWtYNQvC", - "AvMxAwAAA5YQMAAAABAANAAAAAoAAAACEEAAAAFMAKQAAAAmYjY0OTJkODMzNTI5ZjMxMGM1MmRjMDc3ZjBmZDgyMjcAAAAAUl8ogFRAXAABEAAAARQwggEKAoIBAQC2SS2DNSnzEMUtwHfw/YInm/XLXEUMktyZTmyMWACBbEfmU6aztT3vxz6UHoCBYtKkzKrfDZLvXe0a5TRLMmK+yfl5IzIVUPdqTg6FF3Bx/GXdj4v/ZP6lAuqY5YeI4wPcKldrrIJ9DTUdhZhgdtgDtxGvrXZ8eFjcl9zM+QEykYKMwfnTCixzVOPCCo3q1lJO13NmlhVQDO+f9vvTZsYDCcZHMqlKZWcCEyY1ZpQiCqlsL8wN6tKxMuSQO8EGdH/tNzsGHwCoZq6EEL7SX/pmc2ABjpDQTLixgXwJtCpw8Fwj1xiavsFFbqSLu3SjUCcrMz9f8U5p2ROyv//lWxsXAgMBAAEQUAAAAjIApAAAACZlM2Y4YjY3ZjJmYjM0NzZlZmYxZmM3ZjNhNjEzM2M5OQEgAAACBksDPQ93PdZBGCEnKXcQsdB4yBA9NpImVR81JZdPmWlTwZGAXGJwt4EkBcz+xdey84JDujVtHJUzIL9Ws/Jq5MuXHr0tP5ebah1GCQF2/Ov7sctUk3UPBxeroon7gZQhuzaIJVhl0rzwWriFUbTu7H7g9eaTHMvyfUg+S0Z2p+e0+PdL5rfGOJJZ6+NJCXxxbQ//cF4s0PAzkjAuwDmC+OiUiU5V6fY4XtRMCEI7w+UCj+wQn2Wu1Wc7xVM9uow13rGaLPYkWZ/9v+wNhg0KCsVfKGhkAGGzGyKI9LAppFVTu52pBlRu9Ung7VkhF0JC2aadYKKFl99wCbsGqUYN/gtfgHYCV24LNVah2dAy8CI9UmHdWk1kIwWazbPTYKLfpYCTFxqEqXqo3ijLf0YPsfhIvCQpc5VHAvLJlDm0RFKwzK6N9Zu9s9IvJHzIpaAAHCQJPtYxPwWMdt83njGo9wu1+aVkl5Sb5X8N16AybbnQ7fCBqJruGBM0LHtWVbHEiEygD7OStzyhT5rXKZSQYMA9I2CvK1t7qfDXDM40k8SVQ5CrS9R8x1wqQbe+DqNJ9tMfbUmN0xrO/w2pTl/4edKW30TShW/fr3vCWpVq8gcm3CVFSZUaC4T9wqH96K6KgIPbmg1Hk158pxXYXopEv6ZxR7UTPxKB0O22aIHB6UQ5", - "AvMxAwAAA5YQMAAAABAANAAAAAoAAAABEEAAAAFMAKQAAAAmOTdhNTJkMThjMDBjYWE3YmZlYmQ4NTg0MDJkMzBhY2QAAAAAUl8ogFRAXAABEAAAARQwggEKAoIBAQCXpS0YwAyqe/69hYQC0wrNz7eUHAmJfR5EV7NVFQeOxtTlFwbdvRMK8ZpfqEoRhIPXAYCc9Dv3F7WcmcFer8d50EWhlK7rCQScaRdwL1UmF1dUY8bR8QxhJOUgwmrlzeKOHi2DJ3/9AXm7NJR8XMJgHEQQwi3z/aQsWrwCUA0mk68C8a3vjLtcMj5XBuNXRtGZ9zFjiI9Xt19y0iIKdYpfzOnJTKVETcjH7XPBBbJETWkrEyToHXPjcfhESAbJDOoyfQQbxHMQNE7no7owN08LoWX2kOSGtl2m6JbE2OEdJig83a6U3PDYfYM5LCfsAJEIroYhB3qZJDE98zGC8jihAgMBAAEQUAAAAjIApAAAACZlM2Y4YjY3ZjJmYjM0NzZlZmYxZmM3ZjNhNjEzM2M5OQEgAAACBiwl7oRPJzLlwDd8AzVolFQH1ZS+MWLA4B1eHCjCXSMn+zS0Su6CrpC6/vLwECaKSfNZ8y7T2fNDPJHMLmc1F6jJkdNZq3TZGNRgJx24OF3G5MU6mAH7DBsz7muFto+URTJl9CdJviIyQAn5E+R4Gp531RJdKlbqJl/gWuQMVem+eo3elpVEn8Ckg0yvFaFdhGFTOPyrXOZ6fI0pdCX0SH2q/vAIxGDRzaSYmsR0Y+oYZs0AeRnZD9iEh1v17xnVEdSoLZmZbjlLXXgqhbdXGik6ZoXQg3bTfl5D1j8Tk/d/CXqf0SUKBnIafaNgUeQSMY95M3k3vjPQN7vHdXmg19GnqQmBnGq45qdKI7+0Erfhl4po1z6yVvx9JfIMIDOsKwO3U/As5zbO2BYso0pUP4+gndissfDfqlPRni3orA0tlV6NuLmXi1wkHCu8HQ8WOqEUlWDJNLNpHW5OmgjMFqlIPt7hX5jlc9eXd4oMyaqXm1Tg8Cgbh5DYaT9A7He47+QhqYlPygqK9Fm0ZnH3Yz51cm3p2tRB1JU7qH9h5UqLLKJMBuIx7e9L5ieTfzKmTw6tqpIpHpiR/8bSQlKkw2LxikFy3OXL5obY1t9sWk35BNZQqcqflI6mkPrvGQKwN+co8GjUon5/Y1HSM6ursaJtkD8dz+oXVyWAokkuD7QZ", - - -}; - - - -EVP_PKEY *RsRecogn::loadMasterKey() -{ - /* load master signing key */ - std::vector decoded = Radix64::decode(RecognKey); - - const unsigned char *keyptr2 = decoded.data(); - long keylen2 = decoded.size(); - - RSA *rsakey = d2i_RSAPublicKey(NULL, &(keyptr2), keylen2); - - if (!rsakey) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::loadMasterKeys() failed rsakey load"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - return NULL; - } - - - EVP_PKEY *signKey = EVP_PKEY_new(); - EVP_PKEY_assign_RSA(signKey, rsakey); - - return signKey; -} - - -bool RsRecogn::loadSigningKeys(std::map &signMap) -{ - - EVP_PKEY *signKey = loadMasterKey(); - RsGxsRecognSerialiser recognSerialiser; - - if (!signKey) - { - std::cerr << "RsRecogn::loadSigningKeys() missing Master Key"; - return false; - } - - - rstime_t now = time(NULL); - - for(int i = 0; i < NUM_RECOGN_SIGN_KEYS; i++) - { - std::vector signerbuf = Radix64::decode(RecognSigningKeys[i]); - - uint32_t pktsize = signerbuf.size(); - RsItem *pktitem = recognSerialiser.deserialise(signerbuf.data(), &pktsize); - RsGxsRecognSignerItem *item = dynamic_cast(pktitem); - - if (!item) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::loadSigningKeys() failed to deserialise SignerItem from string \"" << RecognSigningKeys[i] << "\""; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - continue; - } - -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::loadSigningKeys() SignerItem: "; - std::cerr << std::endl; - item->print(std::cerr); -#endif // DEBUG_RECOGN - - /* check dates */ - if ((item->key.startTS > (unsigned) now) || (item->key.endTS < (unsigned) now)) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::loadSigningKeys() failed timestamp"; - std::cerr << std::endl; - std::cerr << "RsRecogn::loadSigningKeys() key.startTS: " << item->key.startTS; - std::cerr << std::endl; - std::cerr << "RsRecogn::loadSigningKeys() now: " << now; - std::cerr << std::endl; - std::cerr << "RsRecogn::loadSigningKeys() key.endTS: " << item->key.endTS; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - delete item; - continue; - } - - /* check signature */ - RsTlvKeySignature signature = item->sign; - item->sign.TlvShallowClear(); - - unsigned int siglen = signature.signData.bin_len; - unsigned char *sigbuf = (unsigned char *) signature.signData.bin_data; - - /* store in */ - uint32_t datalen = recognSerialiser.size(item); - - RsTemporaryMemory data(datalen) ; - - if(!data) - return false ; - - uint32_t pktlen = datalen; - int signOk = 0; - - if (recognSerialiser.serialise(item, data, &pktlen)) - { - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - - EVP_VerifyInit(mdctx, EVP_sha1()); - EVP_VerifyUpdate(mdctx, data, pktlen); - signOk = EVP_VerifyFinal(mdctx, sigbuf, siglen, signKey); - - EVP_MD_CTX_destroy(mdctx); - - item->sign = signature; - signature.TlvShallowClear(); - - if (signOk) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::loadSigningKeys() signature ok"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - RsGxsId signerId = item->key.keyId; - signMap[signerId] = item; - } - } - - if (!signOk) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::loadSigningKeys() signature failed"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - delete item; - } - } - - /* clean up */ - EVP_PKEY_free(signKey); - return true; -} - - - -bool RsRecogn::validateTagSignature(RsGxsRecognSignerItem *signer, RsGxsRecognTagItem *item) -{ - if (item->sign.keyId != signer->key.keyId) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::validateTagSignature() keyId mismatch"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - return false; - } - - const unsigned char *keyptr = (const unsigned char *) signer->key.keyData.bin_data; - long keylen = signer->key.keyData.bin_len; - - /* extract admin key */ - RSA *rsakey = d2i_RSAPublicKey(NULL, &(keyptr), keylen); - if (!rsakey) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::validateTagSignature() failed extract signkey"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - return false; - } - - /* check signature */ - RsTlvKeySignature signature = item->sign; - item->sign.TlvShallowClear(); - - unsigned int siglen = signature.signData.bin_len; - unsigned char *sigbuf = (unsigned char *) signature.signData.bin_data; - - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - EVP_PKEY *signKey = EVP_PKEY_new(); - EVP_PKEY_assign_RSA(signKey, rsakey); - - - /* store in */ - RsGxsRecognSerialiser serialiser; - - uint32_t datalen = serialiser.size(item); - - RsTemporaryMemory data(datalen) ; - - if(!data) - return false ; - - int signOk = 0; - - uint32_t pktlen = datalen; - if (serialiser.serialise(item, data, &pktlen)) - { - - EVP_VerifyInit(mdctx, EVP_sha1()); - EVP_VerifyUpdate(mdctx, data, pktlen); - signOk = EVP_VerifyFinal(mdctx, sigbuf, siglen, signKey); -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::validateTagSignature() sign_result: " << signOk; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - } - else - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::validateTagSignature() failed to serialise"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - } - - // Clean up. - item->sign = signature; - signature.TlvShallowClear(); - - EVP_MD_CTX_destroy(mdctx); - EVP_PKEY_free(signKey); - - return (signOk == 1); -} - - -bool rsa_sanity_check(RSA *rsa) -{ - std::cerr << "rsa_sanity_check()"; - std::cerr << std::endl; - - if (!rsa) - { - std::cerr << "rsa_sanity_check() RSA == NULL"; - std::cerr << std::endl; - return false; - } - - RSA *pubkey = RSAPublicKey_dup(rsa); - - std::string signId = RsRecogn::getRsaKeyId(rsa); - std::string signId2 = RsRecogn::getRsaKeyId(pubkey); - - bool ok = true; - if (signId != signId2) - { - std::cerr << "rsa_sanity_check() ERROR SignId Failure"; - std::cerr << std::endl; - ok = false; - } - - if (1 != RSA_check_key(rsa)) - { - std::cerr << "rsa_sanity_check() ERROR RSA key is not private"; - std::cerr << std::endl; - ok = false; - } - -#if 0 - if (1 == RSA_check_key(pubkey)) - { - std::cerr << "rsa_sanity_check() ERROR RSA dup key is private"; - std::cerr << std::endl; - ok = false; - } -#endif - - RSA_free(pubkey); - - if (!ok) - { - exit(1); - } - - return true; -} - - -#warning csoler: this code should be using GxsSecurity signature code. Not some own made signature call. - -bool RsRecogn::signTag(EVP_PKEY *signKey, RsGxsRecognTagItem *item) -{ - RsGxsRecognSerialiser serialiser; - - RSA *rsa = EVP_PKEY_get1_RSA(signKey); - std::string signId = getRsaKeyId(rsa); - rsa_sanity_check(rsa); - RSA_free(rsa); - - item->sign.TlvClear(); - - /* write out the item for signing */ - uint32_t len = serialiser.size(item); - char *buf = new char[len]; - if (!serialiser.serialise(item, buf, &len)) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::signTag() Failed serialise TagItem:"; - std::cerr << std::endl; - item->print(std::cerr); -#endif // DEBUG_RECOGN - delete []buf; - return false; - } - - /* calc and check signature */ - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - - EVP_SignInit(mdctx, EVP_sha1()); - EVP_SignUpdate(mdctx, buf, len); - - unsigned int siglen = EVP_PKEY_size(signKey); - unsigned char sigbuf[siglen]; - EVP_SignFinal(mdctx, sigbuf, &siglen, signKey); - - /* save signature */ - item->sign.signData.setBinData(sigbuf, siglen); - item->sign.keyId = RsGxsId(signId); - - /* clean up */ - EVP_MD_CTX_destroy(mdctx); - delete []buf; - - return true; -} - -#warning csoler: this code should be using GxsSecurity signature code. Not some own made signature call. - -bool RsRecogn::signSigner(EVP_PKEY *signKey, RsGxsRecognSignerItem *item) -{ - std::cerr << "RsRecogn::signSigner()"; - std::cerr << std::endl; - - RsGxsRecognSerialiser serialiser; - - std::cerr << "RsRecogn::signSigner() Checking Key"; - std::cerr << std::endl; - - RSA *rsa = EVP_PKEY_get1_RSA(signKey); - std::string signId = getRsaKeyId(rsa); - rsa_sanity_check(rsa); - RSA_free(rsa); - - std::cerr << "RsRecogn::signSigner() Key Okay"; - std::cerr << std::endl; - - item->sign.TlvClear(); - - /* write out the item for signing */ - uint32_t len = serialiser.size(item); - char *buf = new char[len]; - if (!serialiser.serialise(item, buf, &len)) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::signSigner() Failed serialise SignerItem:"; - std::cerr << std::endl; - item->print(std::cerr); -#endif // DEBUG_RECOGN - delete []buf; - return false; - } - - /* calc and check signature */ - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - - EVP_SignInit(mdctx, EVP_sha1()); - EVP_SignUpdate(mdctx, buf, len); - - unsigned int siglen = EVP_PKEY_size(signKey); - unsigned char sigbuf[siglen]; - EVP_SignFinal(mdctx, sigbuf, &siglen, signKey); - - /* save signature */ - item->sign.signData.setBinData(sigbuf, siglen); - item->sign.keyId = RsGxsId(signId); - - /* clean up */ - EVP_MD_CTX_destroy(mdctx); - delete []buf; - - return true; -} - -#warning csoler: this code should be using GxsSecurity signature code. Not some own made signature call. - -bool RsRecogn::signTagRequest(EVP_PKEY *signKey, RsGxsRecognReqItem *item) -{ - std::cerr << "RsRecogn::signTagRequest()"; - std::cerr << std::endl; - - RsGxsRecognSerialiser serialiser; - - RSA *rsa = EVP_PKEY_get1_RSA(signKey); - std::string signId = getRsaKeyId(rsa); - rsa_sanity_check(rsa); - RSA_free(rsa); - - item->sign.TlvClear(); - - /* write out the item for signing */ - uint32_t len = serialiser.size(item); - char *buf = new char[len]; - if (!serialiser.serialise(item, buf, &len)) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::signTagRequest() Failed serialise Tag Request:"; - std::cerr << std::endl; - item->print(std::cerr); -#endif // DEBUG_RECOGN - delete []buf; - return false; - } - - /* calc and check signature */ - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - - EVP_SignInit(mdctx, EVP_sha1()); - EVP_SignUpdate(mdctx, buf, len); - - unsigned int siglen = EVP_PKEY_size(signKey); - unsigned char sigbuf[siglen]; - EVP_SignFinal(mdctx, sigbuf, &siglen, signKey); - - /* save signature */ - item->sign.signData.setBinData(sigbuf, siglen); - item->sign.keyId = RsGxsId(signId); - - /* clean up */ - EVP_MD_CTX_destroy(mdctx); - delete []buf; - - return true; -} - - -bool RsRecogn::itemToRadix64(RsItem *item, std::string &radstr) -{ - RsGxsRecognSerialiser serialiser; - - /* write out the item for signing */ - uint32_t len = serialiser.size(item); - - RsTemporaryMemory buf(len) ; - - if (!serialiser.serialise(item, buf, &len)) - { - return false; - } - - radstr.clear(); - Radix64::encode(buf, len, radstr); - - return true; -} - - -std::string RsRecogn::getRsaKeyId(RSA *pubkey) -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - int len = BN_num_bytes(pubkey -> n); - unsigned char tmp[len]; - BN_bn2bin(pubkey -> n, tmp); -#else - const BIGNUM *nn=NULL ; - RSA_get0_key(pubkey,&nn,NULL,NULL) ; - - int len = BN_num_bytes(nn); - unsigned char tmp[len]; - BN_bn2bin(nn, tmp); -#endif - - return RsDirUtil::sha1sum(tmp,len).toStdString(); - -#ifdef OLD_VERSION_REMOVED - // (cyril) I removed this because this is cryptographically insane, as it allows to easily forge a RSA key with the same ID. - - // copy first CERTSIGNLEN bytes... - if (len > CERTSIGNLEN) - { - len = CERTSIGNLEN; - } - - std::string id; - for(uint32_t i = 0; i < CERTSIGNLEN; i++) - { - rs_sprintf_append(id, "%02x", (uint16_t) (((uint8_t *) (tmp))[i])); - } - - return id; -#endif -} - - - -RsGxsRecognTagItem *RsRecogn::extractTag(const std::string &encoded) -{ - // Decode from Radix64 encoded Packet. - uint32_t pktsize; - - std::vector buffer = Radix64::decode(encoded); - pktsize = buffer.size(); - - if( buffer.empty() ) - return NULL; - - RsGxsRecognSerialiser serialiser; - RsItem *item = serialiser.deserialise(buffer.data(), &pktsize); - - if (!item) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::extractTag() ERROR Deserialise failed"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - return NULL; - } - - RsGxsRecognTagItem *tagitem = dynamic_cast(item); - - if (!tagitem) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::extractTag() ERROR Not TagItem, is: "; - std::cerr << std::endl; - item->print(std::cerr); -#endif // DEBUG_RECOGN - delete item; - } - - return tagitem; -} - - -bool RsRecogn::createTagRequest(const RsTlvPrivateRSAKey &key, const RsGxsId &id, const std::string &nickname, uint16_t tag_class, uint16_t tag_type, const std::string &comment, std::string &tag) -{ - EVP_PKEY *signKey = EVP_PKEY_new(); - RSA *rsakey = d2i_RSAPrivateKey(NULL, (const unsigned char **)&key.keyData.bin_data, key.keyData.bin_len); - - if (!rsakey) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::createTagRequest() Failed to extract key"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - return false; - } - - if (!EVP_PKEY_assign_RSA(signKey, rsakey)) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::createTagRequest() Failed to assign key"; - std::cerr << std::endl; -#endif // DEBUG_RECOGN - return false; - } - - RsGxsRecognReqItem *item = new RsGxsRecognReqItem(); - - item->issued_at = time(NULL); - item->period = 365 * 24 * 3600; - item->tag_class = tag_class; - item->tag_type = tag_type; - - item->nickname = nickname; - item->identity = id; - item->comment = comment; - - bool signOk = RsRecogn::signTagRequest(signKey,item); - EVP_PKEY_free(signKey); - - if (!signOk) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::createTagRequest() Failed to sign Tag Request:"; - std::cerr << std::endl; - item->print(std::cerr); -#endif // DEBUG_RECOGN - delete item; - return false; - } - - /* write out the item for signing */ - RsGxsRecognSerialiser serialiser; - uint32_t len = serialiser.size(item); - RsTemporaryMemory buf(len) ; - bool serOk = serialiser.serialise(item, buf, &len); - - if (serOk) - { - Radix64::encode(buf, len, tag); - } - - if (!serOk) - { -#ifdef DEBUG_RECOGN - std::cerr << "RsRecogn::createTagRequest() Failed serialise Tag Request:"; - std::cerr << std::endl; - item->print(std::cerr); -#endif // DEBUG_RECOGN - delete item; - return false; - } - - delete item; - return serOk; -} - - diff --git a/libretroshare/src/util/rsrecogn.h b/libretroshare/src/util/rsrecogn.h deleted file mode 100644 index 7cc33ec76..000000000 --- a/libretroshare/src/util/rsrecogn.h +++ /dev/null @@ -1,57 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsrandom.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2013 Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#ifndef RSUTIL_RECOGN_H -#define RSUTIL_RECOGN_H - -#include -#include -#include -#include - -#include "rsitems/rsgxsrecognitems.h" -#include "retroshare/rsgxsifacetypes.h" - -namespace RsRecogn { - -EVP_PKEY * loadMasterKey(); -bool loadSigningKeys(std::map &signMap); -bool validateTagSignature(RsGxsRecognSignerItem *signer, RsGxsRecognTagItem *item); - -bool signTag(EVP_PKEY *signKey, RsGxsRecognTagItem *item); -bool signSigner(EVP_PKEY *signKey, RsGxsRecognSignerItem *item); -bool signTagRequest(EVP_PKEY *signKey, RsGxsRecognReqItem *item); - -bool itemToRadix64(RsItem *item, std::string &radstr); - -std::string getRsaKeyId(RSA *pubkey); - -RsGxsRecognTagItem *extractTag(const std::string &encoded); - -bool createTagRequest(const RsTlvPrivateRSAKey &key, - const RsGxsId &id, const std::string &nickname, - uint16_t tag_class, uint16_t tag_type, - const std::string &comment, std::string &tag); - -} - -#endif diff --git a/libretroshare/src/util/rssharedptr.h b/libretroshare/src/util/rssharedptr.h deleted file mode 100644 index ca54f85b2..000000000 --- a/libretroshare/src/util/rssharedptr.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * rssharedptr.h - * - * Created on: 16 Apr 2014 - * Author: crispy - */ - -#ifndef RSSHAREDPTR_H_ -#define RSSHAREDPTR_H_ - -#include - -/*! - * Not thread safe!! - * And also has a memory leak. Do not use (csoler, 24 Jul 2017). - */ -template -class RsSharedPtr -{ -public: - - RsSharedPtr() : mShared(NULL), mCount(NULL), mSharedPtrMutex(NULL){} - - RsSharedPtr(T* shared) - : mShared(shared), mCount(new int(0)), mSharedPtrMutex(new RsMutex("SharedMutex")) - { - mCount++; - } - - RsSharedPtr(const RsSharedPtr& rsp) - { - rsp.lock(); - mShared = rsp.mShared; - mCount = rsp.mCount; - mCount++; - mSharedPtrMutex = rsp.mSharedPtrMutex; - rsp.unlock(); - - } - - void operator=(const RsSharedPtr& rsp) - { - rsp.lock(); - mSharedPtrMutex = rsp.mSharedPtrMutex; - DecrementAndDeleteIfLast(); - mShared = rsp.mShared; - RepointAndIncrement(rsp.mCount); - - mSharedPtrMutex->unlock(); - } - - T* release() { - - lock(); - - mCount--; T* temp = mShared; mShared = NULL; - - unlock(); - - return temp; - } - T* get() { return mShared; } - - T& operator*(){ return *mShared; } - T* operator->(){ return mShared; } - - ~RsSharedPtr() - { - lock(); - DecrementAndDeleteIfLast(); - unlock(); - } -private: - - void DecrementAndDeleteIfLast() - { - mCount--; - if(mCount == 0 && mShared != NULL) - { - delete mShared; - delete mCount; - } - - mShared = NULL; - mCount = NULL; - } - - void RepointAndIncrement(int* count) - { - mCount = count; - mCount++; - - } - - void lock() const { mSharedPtrMutex->lock(); } - void unlock() const { mSharedPtrMutex->unlock(); } - -private: - - T* mShared; - int* mCount; - RsMutex* mSharedPtrMutex; - -}; - -template -RsSharedPtr rs_make_shared(T* ptr){ return RsSharedPtr(ptr); } - -#endif /* RSSHAREDPTR_H_ */ diff --git a/libretroshare/src/util/rsstd.h b/libretroshare/src/util/rsstd.h deleted file mode 100644 index 2cf3ae31d..000000000 --- a/libretroshare/src/util/rsstd.h +++ /dev/null @@ -1,37 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsstd.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2015 Retroshare Team * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RSSTD_H_ -#define RSSTD_H_ - -namespace rsstd { - -template -void delete_all(_IIter iter_begin, _IIter iter_end) -{ - for (_IIter it = iter_begin; it != iter_end; ++it) { - delete(*it); - } -} - -} - -#endif // RSSTD_H_ diff --git a/libretroshare/src/util/rsstring.cc b/libretroshare/src/util/rsstring.cc deleted file mode 100644 index 6dcb8bd21..000000000 --- a/libretroshare/src/util/rsstring.cc +++ /dev/null @@ -1,334 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsstd.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (c) 2010, Thomas Kister * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "rsstring.h" - -#ifdef WINDOWS_SYS -#include -#include -#else -#include -#include -#include -#endif -#include -#include - -namespace librs { namespace util { - -bool ConvertUtf8ToUtf16(const std::string& source, std::wstring& dest) -{ - if (source.empty()) { - dest.clear(); - return true; - } - -#ifdef WINDOWS_SYS - int nbChars = MultiByteToWideChar(CP_UTF8, 0, source.c_str(), -1, 0, 0); - if(nbChars == 0) { - return false; - } - - wchar_t* utf16Name = new wchar_t[nbChars]; - if( MultiByteToWideChar(CP_UTF8, 0, source.c_str(), -1, utf16Name, nbChars) == 0) { - delete[] utf16Name; - return false; - } - - dest = utf16Name; - delete[] utf16Name; -#else - std::vector res; - std::string::size_type len = source.length(); - - unsigned int i = 0; - unsigned long temp; - - while (i < len) { - char src = source[i]; - if ((src & 0x80) == 0) { // ASCII : 0000 0000-0000 007F 0xxxxxxx - temp = src; - ++i; - } else if ((src & 0xE0) == 0xC0) { // 0000 0080-0000 07FF 110xxxxx 10xxxxxx - temp = (src & 0x1F); - temp <<= 6; - temp += (source[i + 1] & 0x3F); - i += 2; - } else if ((src & 0xF0) == 0xE0) { // 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx - temp = (src & 0x0F); - temp <<= 6; - temp += (source[i + 1] & 0x3F); - temp <<= 6; - temp += (source[i + 2] & 0x3F); - i += 3; - } else if ((src & 0xF8) == 0xF0) { // 0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - temp = (src & 0x07); - temp <<= 6; - temp += (source[i + 1] & 0x3F); - temp <<= 6; - temp += (source[i + 2] & 0x3F); - temp <<= 6; - temp += (source[i + 3] & 0x3F); - i += 4; - } else if ((src & 0xFC) == 0xF8) { // 0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - temp = (src & 0x03); - temp <<= 6; - temp += (source[i + 1] & 0x3F); - temp <<= 6; - temp += (source[i + 2] & 0x3F); - temp <<= 6; - temp += (source[i + 3] & 0x3F); - temp <<= 6; - temp += (source[i + 4] & 0x3F); - i += 5; - } else if ((src & 0xFE) == 0xFC) { // 0400 0000-7FFF FFFF 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - temp = (src & 0x01); - temp <<= 6; - temp += (source[i + 1] & 0x3F); - temp <<= 6; - temp += (source[i + 2] & 0x3F); - temp <<= 6; - temp += (source[i + 3] & 0x3F); - temp <<= 6; - temp += (source[i + 4] & 0x3F); - temp <<= 6; - temp += (source[i + 5] & 0x3F); - i += 6; - } else { - temp = '?'; - } - // Need to transform to UTF-16 > handle surrogates - if (temp > 0xFFFF) { - // First high surrogate - res.push_back(0xD800 + wchar_t(temp >> 10)); - // Now low surrogate - res.push_back(0xDC00 + wchar_t(temp & 0x3FF)); - } else { - res.push_back(wchar_t(temp)); - } - } - // Check whether first wchar_t is the BOM 0xFEFF - if (res[0] == 0xFEFF) { - dest.append(&res[1], res.size() - 1); - } else { - dest.append(&res[0], res.size()); - } -#endif - - return true; -} - -bool ConvertUtf16ToUtf8(const std::wstring& source, std::string& dest) -{ -#ifdef WINDOWS_SYS - int nbChars = WideCharToMultiByte(CP_UTF8, 0, source.c_str(), -1, 0, 0, 0, 0); - if(nbChars == 0) { - return false; - } - - char* utf8Name = new char[nbChars]; - if( WideCharToMultiByte(CP_UTF8, 0, source.c_str(), -1, utf8Name, nbChars, 0, 0) == 0) { - delete[] utf8Name; - return false; - } - - dest = utf8Name; - delete[] utf8Name; -#else - std::vector res; - - std::wstring::size_type len = source.length(); - unsigned int i = 0; - unsigned long temp; - - while (i < len) { - if ((source[i] & 0xD800) == 0xD800) { // surrogate - temp = (source[i] - 0xD800); - temp <<= 10; - temp += (source[i + 1] - 0xDC00); - i += 2; - } else { - temp = source[i]; - ++i; - } - if (temp < 0x00000080) { // ASCII : 0000 0000-0000 007F 0xxxxxxx - res.push_back(char(temp)); - } else if (temp < 0x00000800) { // 0000 0080-0000 07FF 110xxxxx 10xxxxxx - res.push_back(char(0xC0 | (temp >> 6))); - res.push_back(char(0x80 | (temp & 0x3F))); - } else if (temp < 0x00010000) { // 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx - res.push_back(char(0xE0 | (temp >> 12))); - res.push_back(char(0x80 | ((temp >> 6) & 0x3F))); - res.push_back(char(0x80 | (temp & 0x3F))); - } else if (temp < 0x00200000) { // 0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - res.push_back(char(0xF0 | (temp >> 18))); - res.push_back(char(0x80 | ((temp >> 12) & 0x3F))); - res.push_back(char(0x80 | ((temp >> 6) & 0x3F))); - res.push_back(char(0x80 | (temp & 0x3F))); - } else if (temp < 0x04000000) { // 0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - res.push_back(char(0xF8 | (temp >> 24))); - res.push_back(char(0x80 | ((temp >> 18) & 0x3F))); - res.push_back(char(0x80 | ((temp >> 12) & 0x3F))); - res.push_back(char(0x80 | ((temp >> 6) & 0x3F))); - res.push_back(char(0x80 | (temp & 0x3F))); - } else if (temp < 0x80000000) { // 0400 0000-7FFF FFFF 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - res.push_back(char(0xFC | (temp >> 30))); - res.push_back(char(0x80 | ((temp >> 24) & 0x3F))); - res.push_back(char(0x80 | ((temp >> 18) & 0x3F))); - res.push_back(char(0x80 | ((temp >> 12) & 0x3F))); - res.push_back(char(0x80 | ((temp >> 6) & 0x3F))); - res.push_back(char(0x80 | (temp & 0x3F))); - } - } - - dest.append(&res[0], res.size()); -#endif - - return true; -} - -#if 0 -bool is_alphanumeric(char c) -{ - return (c>='0' && c<='9') || (c>='a' && c<='z') || (c>='A' && c<='Z'); -} - -bool is_alphanumeric(const std::string& s) -{ - for( uint32_t i=0; i < s.size(); ++i) - if(!is_alphanumeric(s[i])) return false; - return true; -} -#endif - -} } // librs::util - -#ifdef WINDOWS_SYS -// asprintf() and vasprintf() are missing in Win32 -static int vasprintf(char **sptr, const char *fmt, va_list argv) -{ - int wanted = __mingw_vsnprintf(*sptr = NULL, 0, fmt, argv); - if ((wanted > 0) && ((*sptr = (char*) malloc(wanted + 1)) != NULL)) { - return __mingw_vsprintf(*sptr, fmt, argv); - } - - return wanted; -} - -//static int asprintf(char **sptr, const char *fmt, ...) -//{ -// int retval; -// va_list argv; -// va_start( argv, fmt ); -// retval = vasprintf(sptr, fmt, argv); -// va_end(argv); -// return retval; -//} -#endif - -int rs_sprintf_args(std::string &str, const char *fmt, va_list ap) -{ - char *buffer = NULL; - - int retval = vasprintf(&buffer, fmt, ap); - - if (retval >= 0) { - if (buffer) { - str = buffer; - free(buffer); - } else { - str.clear(); - } - } else { - str.clear(); - } - - return retval; -} - -int rs_sprintf(std::string &str, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - int retval = rs_sprintf_args(str, fmt, ap); - va_end(ap); - - return retval; -} - -int rs_sprintf_append_args(std::string &str, const char *fmt, va_list ap) -{ - char *buffer = NULL; - - int retval = vasprintf(&buffer, fmt, ap); - - if (retval >= 0) { - if (buffer) { - str.append(buffer); - free(buffer); - } - } - - return retval; -} - -int rs_sprintf_append(std::string &str, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - int retval = rs_sprintf_append_args(str, fmt, ap); - va_end(ap); - - return retval; -} - -void stringToUpperCase(const std::string& s, std::string &upper) -{ - upper = s ; - - for(uint32_t i=0;i 96 && upper[i] < 123) - upper[i] -= 97-65 ; -} - -void stringToLowerCase(const std::string& s, std::string &lower) -{ - lower = s ; - - for(uint32_t i=0;i 64 && lower[i] < 91) - lower[i] += 97-65 ; -} - - - -bool isHexaString(const std::string& s) -{ - for(uint32_t i=0;i= 'A' && s[i] <= 'F') || (s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'f'))) - return false ; - - return true ; -} - - diff --git a/libretroshare/src/util/rsstring.h b/libretroshare/src/util/rsstring.h deleted file mode 100644 index b3fd2553c..000000000 --- a/libretroshare/src/util/rsstring.h +++ /dev/null @@ -1,57 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsstd.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (c) 2010, Thomas Kister * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RSSTRING_H_ -#define RSSTRING_H_ - -#include -#include - -namespace librs { - namespace util { - - bool ConvertUtf8ToUtf16(const std::string& source, std::wstring& dest); - bool ConvertUtf16ToUtf8(const std::wstring& source, std::string& dest); -#if 0 - bool is_alphanumeric(char c) ; - bool is_alphanumeric(const std::string& s); -#endif -} } // librs::util - -#ifdef WIN32 -#define INT64FMT "%I64d" -#define UINT64FMT "%I64u" -#else -#define INT64FMT "%lld" -#define UINT64FMT "%llu" -#endif - -int rs_sprintf_args(std::string &str, const char *fmt, va_list ap); -int rs_sprintf(std::string &str, const char *fmt, ...); -int rs_sprintf_append_args(std::string &str, const char *fmt, va_list ap); -int rs_sprintf_append(std::string &str, const char *fmt, ...); - -void stringToUpperCase(const std::string& s, std::string &upper); -void stringToLowerCase(const std::string& s, std::string &lower); - -bool isHexaString(const std::string& s); - -#endif // RSSTRING_H_ diff --git a/libretroshare/src/util/rsthreads.cc b/libretroshare/src/util/rsthreads.cc deleted file mode 100644 index 519ab129f..000000000 --- a/libretroshare/src/util/rsthreads.cc +++ /dev/null @@ -1,334 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsthreads.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2007 Robert Fernie * - * Copyright (C) 2016-2021 Gioacchino Mazzurco * - * Copyright (C) 2019-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -#include "rsthreads.h" - -#include "util/rsdebug.h" - -#include -#include -#include -#include - -#ifdef RS_MUTEX_DEBUG -#include -#include -#endif - -#ifdef __APPLE__ -int __attribute__((weak)) pthread_setname_np(const char *__buf) ; -int RS_pthread_setname_np(pthread_t /*__target_thread*/, const char *__buf) { - return pthread_setname_np(__buf); -} -#else -#ifndef __WIN64__ -int __attribute__((weak)) pthread_setname_np(pthread_t __target_thread, const char *__buf) ; -#endif //__WIN64__ -int RS_pthread_setname_np(pthread_t __target_thread, const char *__buf) { - return pthread_setname_np(__target_thread, __buf); -} -#endif //__APPLE__ - - -/******* - * #define DEBUG_THREADS 1 - * #define RSMUTEX_ABORT 1 // Catch wrong pthreads mode. - *******/ -#define THREAD_DEBUG RsDbg() << "[this=" << static_cast(this) \ - << ", caller thread ID: " << std::hex << pthread_self() << ", thread ID: " \ - << mTid << std::dec << "] " - -#ifdef RSMUTEX_ABORT - #include -#endif - -#ifdef DEBUG_THREADS - #include -#endif - -/*static*/ void* RsThread::rsthread_init(void* p) -{ - RsThread* thread = reinterpret_cast(p); - if(!thread) return nullptr; - - /* Using pthread_detach(...) the thread resources will be automatically - * freed when this function return, so there is no need for pthread_join() - * later. */ - pthread_detach(pthread_self()); - -#ifdef DEBUG_THREADS - std::cerr << "[Thread ID:" << std::hex << pthread_self() << std::dec - << "] thread is started. Calling wrapRun()..." << std::endl; -#endif - - thread->wrapRun(); - return nullptr; -} - -void RsThread::resetTid() -{ -#ifdef WINDOWS_SYS - memset (&mTid, 0, sizeof(mTid)); -#else - mTid = pthread_t(); //Thread identifiers should be considered opaque and can be null. -#endif -} - -RsThread::RsThread() : mInitMtx("RsThread"), mHasStopped(true), - mShouldStop(false), mLastTid() -#ifdef RS_THREAD_FORCE_STOP - , mStopTimeout(0) -#endif -{ resetTid(); } - -bool RsThread::isRunning() { return !mHasStopped; } - -bool RsThread::shouldStop() { return mShouldStop; } - -void RsThread::askForStop() -{ - /* Call onStopRequested() only once even if askForStop() is called multiple - * times */ - if(!mShouldStop.exchange(true)) onStopRequested(); -} - -void RsThread::wrapRun() -{ - {RS_STACK_MUTEX(mInitMtx);} // Waiting Init done. - run(); - resetTid(); - mHasStopped = true; -} - -void RsThread::fullstop() -{ - askForStop(); - waitWhileStopping(); -} - -void RsThread::waitWhileStopping() -{ -#ifdef RS_THREAD_FORCE_STOP - const rstime_t stopRequTS = time(nullptr); -#endif - - const pthread_t callerTid = pthread_self(); - if(pthread_equal(mTid, callerTid)) - { - RsErr() << __PRETTY_FUNCTION__ << " called by same thread. This should " - << "never happen! this: " << static_cast(this) - << std::hex << ", callerTid: " << callerTid - << ", mTid: " << mTid << std::dec - << ", mFullName: " << mFullName << std::endl; - print_stacktrace(); - return; - } - - // Wait for the thread being stopped - auto i = 1; - while(!mHasStopped) - { - std::this_thread::sleep_for(std::chrono::milliseconds(200)); - ++i; - if(!(i%5)) - RsDbg() << __PRETTY_FUNCTION__ << " " << i*0.2 << " seconds passed" - << " waiting for thread: " << std::hex << mLastTid - << std::dec << " " << mFullName << " to stop" << std::endl; - -#ifdef RS_THREAD_FORCE_STOP - if(mStopTimeout && time(nullptr) > stopRequTS + mStopTimeout) - { - RsErr() << __PRETTY_FUNCTION__ << " thread mLastTid: " << std::hex - << mLastTid << " mTid: " << mTid << std::dec << " " - << mFullName - << " ignored our nice stop request for more then " - << mStopTimeout - << " seconds, will be forcefully stopped. " - << "Please submit a report to RetroShare developers" - << std::endl; - - const auto terr = pthread_cancel(mTid); - if(terr == 0) mHasStopped = true; - else - { - RsErr() << __PRETTY_FUNCTION__ << " pthread_cancel(" - << std::hex << mTid << std::dec <<") returned " - << terr << " " << rs_errno_to_condition(terr) - << std::endl; - print_stacktrace(); - } - - break; - } -#endif // def RS_THREAD_FORCE_STOP - } -} - -bool RsThread::start(const std::string& threadName) -{ - // Atomically check if the thread was already started and set it as running - if(mHasStopped.exchange(false)) - { - RS_STACK_MUTEX(mInitMtx); // Block thread starting to run - - mShouldStop = false; - int pError = pthread_create( - &mTid, nullptr, &rsthread_init, static_cast(this) ); - if(pError) - { - RS_ERR( "pthread_create could not create new thread: ", threadName, - rs_errno_to_condition(pError) ); - mHasStopped = true; - print_stacktrace(); - return false; - } - - /* Store an extra copy of thread id for debugging */ - mLastTid = mTid; - - /* Store thread full name as PThread is not able to keep it entirely */ - mFullName = threadName; - - /* Set PThread thread name which is restricted to 16 characters - * including the terminating null byte */ - if(pthread_setname_np && !threadName.empty()) - RS_pthread_setname_np(mTid, threadName.substr(0, 15).c_str()); - - return true; - } - - RsErr() << __PRETTY_FUNCTION__ << " attempt to start already running thread" - << std::endl; - print_stacktrace(); - return false; -} - -RsQueueThread::RsQueueThread(uint32_t min, uint32_t max, double relaxFactor ) - :mMinSleep(min), mMaxSleep(max), mRelaxFactor(relaxFactor) -{ - mLastSleep = (uint32_t)mMinSleep ; - mLastWork = time(NULL) ; -} - -void RsQueueThread::threadTick() -{ - bool doneWork = false; - while(workQueued() && doWork()) - { - doneWork = true; - } - time_t now = time(NULL); - if (doneWork) - { - mLastWork = now; - mLastSleep = (uint32_t) (mMinSleep + (mLastSleep - mMinSleep) / 2.0); -#ifdef DEBUG_TICKING - THREAD_DEBUG << "RsQueueThread::data_tick() done work: sleeping for: " << mLastSleep << " ms" << std::endl; -#endif - - } - else - { - uint32_t deltaT = now - mLastWork; - double frac = deltaT / mRelaxFactor; - - mLastSleep += (uint32_t) - ((mMaxSleep-mMinSleep) * (frac + 0.05)); - if (mLastSleep > mMaxSleep) - { - mLastSleep = mMaxSleep; - } -#ifdef DEBUG_TICKING - THREAD_DEBUG << "RsQueueThread::data_tick() no work: sleeping for: " << mLastSleep << " ms" << std::endl; -#endif - } - - std::this_thread::sleep_for(std::chrono::milliseconds(mLastSleep)); -} - -void RsMutex::unlock() -{ - _thread_id = 0; - pthread_mutex_unlock(&realMutex); -} - -void RsMutex::lock() -{ - int err = pthread_mutex_lock(&realMutex); - if( err != 0) - { - RsErr() << __PRETTY_FUNCTION__ << "pthread_mutex_lock returned: " - << rs_errno_to_condition(err) -#ifdef RS_MUTEX_DEBUG - << " name: " << name() -#endif - << std::endl; - - print_stacktrace(); - -#ifdef RSMUTEX_ABORT - abort(); -#endif - } - - _thread_id = pthread_self(); -} - -#ifdef RS_MUTEX_DEBUG -double RsStackMutex::getCurrentTS() -{ - -#ifndef WINDOWS_SYS - struct timeval cts_tmp; - gettimeofday(&cts_tmp, NULL); - double cts = (cts_tmp.tv_sec) + ((double) cts_tmp.tv_usec) / 1000000.0; -#else - struct _timeb timebuf; - _ftime( &timebuf); - double cts = (timebuf.time) + ((double) timebuf.millitm) / 1000.0; -#endif - return cts; -} -#endif - - -RsThread::~RsThread() -{ - if(!mHasStopped) - { - RsErr() << __PRETTY_FUNCTION__ << " deleting thread: " << mLastTid - << " " << mFullName << " that is still " - << "running! Something seems very wrong here and RetroShare is " - << "likely to crash because of this." << std::endl; - print_stacktrace(); - - /* Last resort attempt to stop the thread in a less pathological state. - * Don't call fullstop() as it rely on virtual methods that at this - * point are not anymore the one from inerithing classes causing - * compilers to output a warning */ - waitWhileStopping(); - } -} - -RsQueueThread::~RsQueueThread() = default; diff --git a/libretroshare/src/util/rsthreads.h b/libretroshare/src/util/rsthreads.h deleted file mode 100644 index edec70472..000000000 --- a/libretroshare/src/util/rsthreads.h +++ /dev/null @@ -1,343 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rsthreads.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (C) 2004-2006 Robert Fernie * - * Copyright (C) 2016-2021 Gioacchino Mazzurco * - * Copyright (C) 2019-2021 AsociaciĆ³n Civil Altermundi * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "util/rsmemory.h" -#include "util/rsdeprecate.h" - -#ifdef RS_THREAD_FORCE_STOP -# include "util/rstime.h" -#endif - -/** - * @brief Provide mutexes that keep track of the owner. Based on pthread mutex. - */ -class RsMutex -{ -public: - - RsMutex(const std::string& name) : _thread_id(0) -#ifdef RS_MUTEX_DEBUG - , _name(name) -#endif - { - pthread_mutex_init(&realMutex, nullptr); - -#ifndef RS_MUTEX_DEBUG - (void) name; // remove unused parameter warnings -#endif - } - - ~RsMutex() { pthread_mutex_destroy(&realMutex); } - - inline const pthread_t& owner() const { return _thread_id; } - - void lock(); - void unlock(); - bool trylock() { return (0 == pthread_mutex_trylock(&realMutex)); } - -#ifdef RS_MUTEX_DEBUG - const std::string& name() const { return _name ; } -#endif - -private: - pthread_mutex_t realMutex; - pthread_t _thread_id; - -#ifdef RS_MUTEX_DEBUG - std::string _name; -#endif -}; - -/** - * @def RS_STACK_MUTEX(m) - * This macro allows you to trace which mutex in the code is locked and for how - * much time. You can use this as follows: - * @code - * { - * RS_STACK_MUTEX(myMutex); - * do_something(); - * } - * @endcode - */ -#define RS_STACK_MUTEX(m) \ - RsStackMutex __local_retroshare_stack_mutex_##m( \ - m, __PRETTY_FUNCTION__, __FILE__, __LINE__ ) - -/** - * Provide mutexes that automatically lock/unlock on creation/destruction and - * have powerfull debugging facilities (if RS_MUTEX_DEBUG is defined at - * compiletime). - * In most of the cases you should not use this directly instead - * @see RS_STACK_MUTEX(m) - */ -class RsStackMutex -{ -public: - - explicit RsStackMutex(RsMutex& mtx): mMtx(mtx) - { - mMtx.lock(); -#ifdef RS_MUTEX_DEBUG - double ts = getCurrentTS(); - _time_stamp = ts; - _lineno = 0; - _info = "[no info]"; -#endif - } - - RsStackMutex(RsMutex &mtx, const char *function_name, const char *file_name, - int lineno) : mMtx(mtx) -#ifdef RS_MUTEX_DEBUG - , _info(std::string(function_name)+" in file "+file_name), _lineno(lineno) -#endif - { -#ifdef RS_MUTEX_DEBUG - double ts = getCurrentTS(); - _time_stamp = ts; - pthread_t owner = mMtx.owner(); -#else - // remove unused parameter warnings - (void) function_name; (void) file_name; (void) lineno; -#endif - - mMtx.lock(); - -#ifdef RS_MUTEX_DEBUG - ts = getCurrentTS(); - - if(ts - _time_stamp > 1.0) - std::cerr << "Mutex " << (void*)&mMtx << " \"" << mtx.name() << "\"" - << " waited for " << ts - _time_stamp - << " seconds in thread " << pthread_self() - << " for locked thread " << owner << ". in " << _info - << ":" << _lineno << std::endl; - _time_stamp = ts ; // This is to re-init the locking time without accounting for how much we waited. -#endif - } - - ~RsStackMutex() - { - mMtx.unlock(); - -#ifdef RS_MUTEX_DEBUG - double ts = getCurrentTS(); - - if(ts - _time_stamp > 1.0) - std::cerr << "Mutex " << (void*)&mMtx << " \"" << mMtx.name() - << "\"" << " locked for " << ts - _time_stamp - << " seconds in thread " << pthread_self() - << ". in " << _info << ":" << _lineno << std::endl; -#endif - } - -private: - RsMutex &mMtx; - -#ifdef RS_MUTEX_DEBUG - static double getCurrentTS(); - double _time_stamp; - std::string _info; - int _lineno; -#endif -}; - - - -/// @brief Offer basic threading functionalities. -class RsThread -{ -public: - RsThread(); - virtual ~RsThread(); - - /** - * @brief start the thread and call run() on it. - * @param threadName string containing the name of the thread used for - * debugging purposes, @note inside PThread it is - * truncated to 16 characters including \0 at the end of - * the string. - * @return false on error, true otherwise - */ - bool start(const std::string& threadName = ""); - - /** - * @brief Check if thread is running. - * @return true if the thread is still running, false otherwise. - */ - bool isRunning(); - - /** - * @brief Check if the thread should stop. - * Expecially useful for subclasses which implement a @see run() method - * which may take lot of time before returning when not asked, to check if - * stop has been requested and therefore interrupting the execution ASAP - * returning in a coherent state. - * @return true if the thread received a stopping order. - */ - bool shouldStop(); - - /** - * @brief Asyncronously ask the thread to stop. - * The real stop will happen when the @see run() method finish. - */ - void askForStop(); - - /** - * Call @see askForStop() then wait it has really stopped before returning. - * It must not be called in the same thread, as it would not wait for the - * effective stop to occur as it would cause a deadlock. - */ - void fullstop(); - - /** - * Execute given function on a detached thread without blocking the caller - * execution. - * This can be generalized with variadic template, ATM it is enough to wrap - * any kind of function call or job into a lambda which get no paramethers - * and return nothing but can capture - * This can be easly optimized later by using a thread pool - */ - static void async(const std::function& fn) - { std::thread(fn).detach(); } - - /** @return RsThread full name */ - const std::string& threadName() { return mFullName; } - -protected: - /** - * This method must be implemented by sublasses, will be called once the - * thread is started. Should return on request, use @see shouldStop() to - * check if stop has been requested. - */ - virtual void run() = 0; - - /** - * This method is meant to be overridden by subclasses with long running - * @see run() method and is executed asyncronously when @see askForStop() - * is called, any task necessary to stop the thread (aka inducing @see run() - * to return in a coherent state) should be done in the overridden version - * of this method, @see JsonApiServer for an usage example. */ - virtual void onStopRequested() {} - -#ifdef RS_THREAD_FORCE_STOP - /** Set last resort timeout to forcefully kill thread if it didn't stop - * nicely, one should never use this, still we needed to introduce this - * to investigate some bugs in external libraries */ - void setStopTimeout(rstime_t timeout) { mStopTimeout = timeout; } -#endif - -private: - /** Call @see run() setting the appropriate flags around it*/ - void wrapRun(); - - /** Wait the thread while it is stopping */ - void waitWhileStopping(); - - /** To be sure Init (pthread_setname_np) is done before continue thread. - * Else can finish before and crash. */ - RsMutex mInitMtx; - - /// True if thread is stopped, false otherwise - std::atomic mHasStopped; - - /// True if stop has been requested - std::atomic mShouldStop; - - /// Passed as argument for pthread_create(), call start() - static void *rsthread_init(void*); - - /// Store the id of the corresponding pthread - pthread_t mTid; - void resetTid(); - - /** Store thread full name for debugging because PThread is limited to 15 - * char thread names */ - std::string mFullName; - - /** Store a copy of thread id which is never reset to 0 after initialization - * due to RsThread functioning. After RsThread initialization this member is - * only re-written with a new tread id in start(...). - * This is useful for debugging because mTid is reset at the end of wrapRun - * and that might happens concurrently (or just before) a debug message - * being printed, thus causing the debug message to print a mangled value.*/ - pthread_t mLastTid; - -#ifdef RS_THREAD_FORCE_STOP - /// @see setStopTimeout - rstime_t mStopTimeout; -#endif -}; - -/** - * Provide a detached execution loop that continuously call data_tick() once the - * thread is started - */ -class RsTickingThread: public RsThread -{ -public: - - /** - * Subclasses must implement this method, it will be called in a loop once - * the thread is started, so repetitive work (like checking if data is - * available on a socket) should be done here, at the end of this method - * sleep_for(...) or similar function should be called or the CPU will - * be used as much as possible also if there is nothing to do. - */ - virtual void threadTick() = 0; - -private: - /// Implement the run loop and continuously call threadTick() in it - void run() override { while(!shouldStop()) threadTick(); } -}; - -// TODO: Used just one time, is this really an useful abstraction? -class RsQueueThread: public RsTickingThread -{ -public: - RsQueueThread(uint32_t min, uint32_t max, double relaxFactor); - ~RsQueueThread() override; - -protected: - virtual bool workQueued() = 0; - virtual bool doWork() = 0; - - void threadTick() override; /// @see RsTickingThread - -private: - uint32_t mMinSleep; /* ms */ - uint32_t mMaxSleep; /* ms */ - uint32_t mLastSleep; /* ms */ - time_t mLastWork; /* secs */ - float mRelaxFactor; -}; diff --git a/libretroshare/src/util/rstickevent.cc b/libretroshare/src/util/rstickevent.cc deleted file mode 100644 index d596d417c..000000000 --- a/libretroshare/src/util/rstickevent.cc +++ /dev/null @@ -1,199 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rstickevent.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include "util/rstickevent.h" - -#include -#include - -//#define DEBUG_EVENTS 1 - -void RsTickEvent::tick_events() -{ -#ifdef DEBUG_EVENTS - std::cerr << "RsTickEvent::tick_events() Event List:"; - std::cerr << std::endl; -#endif - - rstime_t now = time(NULL); - { - RsStackMutex stack(mEventMtx); /********** STACK LOCKED MTX ******/ - -#ifdef DEBUG_EVENTS - if (!mEvents.empty()) - { - std::multimap::iterator it; - - for(it = mEvents.begin(); it != mEvents.end(); ++it) - { - std::cerr << "\tEvent type: "; - std::cerr << it->second << " in " << it->first - now << " secs"; - std::cerr << std::endl; - } - } -#endif - - if (mEvents.empty()) - { - return; - } - - /* all events in the future */ - if (mEvents.begin()->first > now) - { - return; - } - } - - std::list toProcess; - std::list::iterator it; - - { - RsStackMutex stack(mEventMtx); /********** STACK LOCKED MTX ******/ - while((!mEvents.empty()) && (mEvents.begin()->first <= now)) - { - std::multimap::iterator it = mEvents.begin(); - uint32_t event_type = it->second.mEventType; - toProcess.push_back(it->second); - mEvents.erase(it); - - count_adjust_locked(event_type, -1); - note_event_locked(event_type); - } - } - - for(it = toProcess.begin(); it != toProcess.end(); ++it) - { -#ifdef DEBUG_EVENTS - std::cerr << "RsTickEvent::tick_events() calling handle_event("; - std::cerr << it->mEventType << ", " << it->mEventLabel << ")"; - std::cerr << std::endl; -#endif // DEBUG_EVENTS - handle_event(it->mEventType, it->mEventLabel); - } -} - -void RsTickEvent::schedule_now(uint32_t event_type) -{ - std::string elabel; - RsTickEvent::schedule_in(event_type, 0, elabel); -} - - -void RsTickEvent::schedule_now(uint32_t event_type, const std::string &elabel) -{ - RsTickEvent::schedule_in(event_type, 0, elabel); -} - -void RsTickEvent::schedule_event(uint32_t event_type, rstime_t when, const std::string &elabel) -{ - RsStackMutex stack(mEventMtx); /********** STACK LOCKED MTX ******/ - mEvents.insert(std::make_pair(when, EventData(event_type, elabel))); - - count_adjust_locked(event_type, 1); -} - -void RsTickEvent::schedule_in(uint32_t event_type, uint32_t in_secs) -{ - std::string elabel; - RsTickEvent::schedule_in(event_type, in_secs, elabel); -} - - -void RsTickEvent::schedule_in(uint32_t event_type, uint32_t in_secs, const std::string &elabel) -{ -#ifdef DEBUG_EVENTS - std::cerr << "RsTickEvent::schedule_in(" << event_type << ", " << elabel << ") in " << in_secs << " secs"; - std::cerr << std::endl; -#endif // DEBUG_EVENTS - - rstime_t event_time = time(NULL) + in_secs; - RsTickEvent::schedule_event(event_type, event_time, elabel); -} - - -void RsTickEvent::handle_event(uint32_t event_type, const std::string &elabel) -{ - std::cerr << "RsTickEvent::handle_event(" << event_type << ", " << elabel; - std::cerr << ") ERROR Not Handled"; - std::cerr << std::endl; -} - - -int32_t RsTickEvent::event_count(uint32_t event_type) -{ - RsStackMutex stack(mEventMtx); /********** STACK LOCKED MTX ******/ - std::map::iterator it; - - it = mEventCount.find(event_type); - if (it == mEventCount.end()) - { - return 0; - } - - return it->second; -} - - -bool RsTickEvent::prev_event_ago(uint32_t event_type, int32_t &age) -{ - RsStackMutex stack(mEventMtx); /********** STACK LOCKED MTX ******/ - std::map::iterator it; - - it = mPreviousEvent.find(event_type); - if (it == mPreviousEvent.end()) - { - return false; - } - - age = time(NULL) - it->second; - return true; -} - - -void RsTickEvent::count_adjust_locked(uint32_t event_type, int32_t change) -{ - std::map::iterator it; - - it = mEventCount.find(event_type); - if (it == mEventCount.end()) - { - mEventCount[event_type] = 0; - it = mEventCount.find(event_type); - } - - it->second += change; - if (it->second < 0) - { - std::cerr << "RsTickEvent::count_adjust() ERROR: COUNT < 0"; - std::cerr << std::endl; - - it->second = 0; - } -} - - -void RsTickEvent::note_event_locked(uint32_t event_type) -{ - mPreviousEvent[event_type] = time(NULL); -} - - diff --git a/libretroshare/src/util/rstickevent.h b/libretroshare/src/util/rstickevent.h deleted file mode 100644 index 7f2c9188c..000000000 --- a/libretroshare/src/util/rstickevent.h +++ /dev/null @@ -1,81 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rstickevent.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2012-2012 by Robert Fernie * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#ifndef RS_UTIL_TICK_EVENT -#define RS_UTIL_TICK_EVENT - - -/* - * - * A simple event queue... to avoid having to continually write separate one. - */ - -#include -#include "util/rstime.h" - -#include "util/rsthreads.h" - -class RsTickEvent -{ - public: - RsTickEvent():mEventMtx("TickEventMtx") { return; } - -void tick_events(); - -void schedule_now(uint32_t event_type); -void schedule_now(uint32_t event_type, const std::string &elabel); - -void schedule_event(uint32_t event_type, rstime_t when, const std::string &elabel); - -void schedule_in(uint32_t event_type, uint32_t in_secs); -void schedule_in(uint32_t event_type, uint32_t in_secs, const std::string &elabel); - -int32_t event_count(uint32_t event_type); -bool prev_event_ago(uint32_t event_type, int32_t &age); - - protected: - - // Overloaded to handle the events. -virtual void handle_event(uint32_t event_type, const std::string &event_label); - - private: - - class EventData - { - public: - EventData() :mEventType(0) { return; } - EventData(uint32_t etype) :mEventType(etype) { return; } - EventData(uint32_t etype, std::string elabel) :mEventLabel(elabel), mEventType(etype) { return; } - - std::string mEventLabel; - uint32_t mEventType; - }; - -void count_adjust_locked(uint32_t event_type, int32_t change); -void note_event_locked(uint32_t event_type); - - RsMutex mEventMtx; - std::map mEventCount; - std::map mPreviousEvent; - std::multimap mEvents; -}; - -#endif // RS_UTIL_TICK_EVENT diff --git a/libretroshare/src/util/rstime.cc b/libretroshare/src/util/rstime.cc deleted file mode 100644 index d2180775e..000000000 --- a/libretroshare/src/util/rstime.cc +++ /dev/null @@ -1,78 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rstime.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013-2013 by Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include -#include -#include -#include - -#include "rstime.h" - -namespace rstime { - -int rs_usleep(uint32_t micro_seconds) -{ - while(micro_seconds >= 1000000) - { - // usleep cannot be called with 1000000 or more. - - usleep(500000) ; - usleep(500000) ; - - micro_seconds -= 1000000 ; - } - usleep(micro_seconds) ; - - return 0 ; -} - -RsScopeTimer::RsScopeTimer(const std::string& name) -{ - _name = name ; - start(); -} - -RsScopeTimer::~RsScopeTimer() -{ - if (!_name.empty()) - { - std::cerr << "Time for \"" << _name << "\": " << duration() << std::endl; - } -} - -double RsScopeTimer::currentTime() -{ - timeval tv ; - gettimeofday(&tv,NULL) ; - return (tv.tv_sec % 10000) + tv.tv_usec/1000000.0f ; // the %1000 is here to allow double precision to cover the decimals. -} - -void RsScopeTimer::start() -{ - _seconds = currentTime(); -} - -double RsScopeTimer::duration() -{ - return currentTime() - _seconds; -} - -} diff --git a/libretroshare/src/util/rstime.h b/libretroshare/src/util/rstime.h deleted file mode 100644 index c17f2a5c7..000000000 --- a/libretroshare/src/util/rstime.h +++ /dev/null @@ -1,84 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rstime.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright 2013 Cyril Soler * - * Copyright 2018 Gioacchino Mazzurco * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#ifdef WINDOWS_SYS -#include -#else -#include -#endif -#include // Added for comfort of users of this util header -#include "util/rsdeprecate.h" - -/** - * Safer alternative to time_t. - * As time_t have not same lenght accross platforms, even though representation - * is not guaranted to be the same but we found it being number of seconds since - * the epoch for time points in all platforms we could test, or plain seconds - * for intervals. - * Still in some platforms it's 32bit long and in other 64bit long. - * To avoid uncompatibility due to different serialzation format use this - * reasonably safe alternative instead. - */ -typedef int64_t rstime_t; - -// Do we really need this? Our names have rs prefix to avoid pollution already! -namespace rstime { - -/** - * @deprecated { std::this_thread::sleep_for or - * std::this_thread::sleep_until instead } - * @brief This is a cross-system definition of usleep, which accepts any - * 32 bits number of micro-seconds. - */ -RS_DEPRECATED_FOR("std::this_thread::sleep_for") -int rs_usleep(uint32_t micro_seconds); - - /* Use this class to measure and display time duration of a given environment: - - { - RsScopeTimer timer("callToMeasure()") ; - - callToMeasure() ; - } - - */ - - class RsScopeTimer - { - public: - RsScopeTimer(const std::string& name); - ~RsScopeTimer(); - - void start(); - double duration(); - - static double currentTime(); - - private: - std::string _name ; - double _seconds ; - }; - -} diff --git a/libretroshare/src/util/rsurl.cc b/libretroshare/src/util/rsurl.cc deleted file mode 100644 index 5da7bbaf4..000000000 --- a/libretroshare/src/util/rsurl.cc +++ /dev/null @@ -1,304 +0,0 @@ -/* - * RetroShare - * Copyright (C) 2018-2019 Gioacchino Mazzurco - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - - -#include -#include -#include -#include -#include - -#include "rsurl.h" -#include "serialiser/rstypeserializer.h" -#include "util/rsnet.h" - -using namespace std; - -RsUrl::RsUrl() : mPort(0), mHasPort(false) {} - -RsUrl::RsUrl(const std::string& urlStr) : mPort(0), mHasPort(false) -{ fromString(urlStr); } - -RsUrl::RsUrl(const sockaddr_storage& addr): mPort(0), mHasPort(false) -{ - switch(addr.ss_family) - { - case AF_INET: setScheme("ipv4"); break; - case AF_INET6: setScheme("ipv6"); break; - default: - { - std::string addrDump; - sockaddr_storage_dump(addr, &addrDump); - RsErr() << __PRETTY_FUNCTION__ << " got invalid addr: " << addrDump - << std::endl; - return; - } - } - - setHost(sockaddr_storage_iptostring(addr)); - setPort(sockaddr_storage_port(addr)); -} - -RsUrl& RsUrl::fromString(const std::string& urlStr) -{ - size_t endI = urlStr.size()-1; - - size_t schemeEndI = urlStr.find(schemeSeparator); - if(schemeEndI >= endI) - { - mScheme = urlStr; - return *this; - } - - mScheme = urlStr.substr(0, schemeEndI); - - size_t hostBeginI = schemeEndI + 3; - if(hostBeginI >= endI) return *this; - - bool hasSquareBr = (urlStr[hostBeginI] == ipv6WrapOpen[0]); - size_t hostEndI; - if(hasSquareBr) - { - if(++hostBeginI >= endI) return *this; - hostEndI = urlStr.find(ipv6WrapClose, hostBeginI); - mHost = urlStr.substr(hostBeginI, hostEndI - hostBeginI); - ++hostEndI; - } - else - { - hostEndI = urlStr.find(pathSeparator, hostBeginI); - hostEndI = min(hostEndI, urlStr.find(portSeparator, hostBeginI)); - hostEndI = min(hostEndI, urlStr.find(querySeparator, hostBeginI)); - hostEndI = min(hostEndI, urlStr.find(fragmentSeparator, hostBeginI)); - - mHost = urlStr.substr(hostBeginI, hostEndI - hostBeginI); - } - - if( hostEndI >= endI ) return *this; - - mHasPort = (sscanf(&urlStr[hostEndI], ":%hu", &mPort) == 1); - - size_t pathBeginI = urlStr.find(pathSeparator, hostBeginI); - size_t pathEndI = string::npos; - if(pathBeginI < endI) - { - pathEndI = urlStr.find(querySeparator, pathBeginI); - pathEndI = min(pathEndI, urlStr.find(fragmentSeparator, pathBeginI)); - mPath = UrlDecode(urlStr.substr(pathBeginI, pathEndI - pathBeginI)); - if(pathEndI >= endI) return *this; - } - - size_t queryBeginI = urlStr.find(querySeparator, hostBeginI); - size_t queryEndI = urlStr.find(fragmentSeparator, hostBeginI); - if(queryBeginI < endI) - { - string qStr = urlStr.substr(queryBeginI+1, queryEndI-queryBeginI-1); - - size_t kPos = 0; - size_t assPos = qStr.find(queryAssign); - do - { - size_t vEndPos = qStr.find(queryFieldSep, assPos); - mQuery.insert( std::make_pair( qStr.substr(kPos, assPos-kPos), - UrlDecode(qStr.substr(assPos+1, vEndPos-assPos-1)) - ) ); - kPos = vEndPos+1; - assPos = qStr.find(queryAssign, vEndPos); - } - while(assPos < endI); - - if(queryEndI >= endI) return *this; - } - - size_t fragmentBeginI = urlStr.find(fragmentSeparator, hostBeginI); - if(fragmentBeginI < endI) - mFragment = UrlDecode(urlStr.substr(++fragmentBeginI)); - - return *this; -} - -std::string RsUrl::toString() const -{ - std::string urlStr(mScheme); - urlStr += schemeSeparator; - - if(!mHost.empty()) - { - if(mHost.find(ipv6Separator) != string::npos && - mHost[0] != ipv6WrapOpen[0] ) - urlStr += ipv6WrapOpen + mHost + ipv6WrapClose; - else urlStr += mHost; - } - - if(mHasPort) urlStr += portSeparator + std::to_string(mPort); - - urlStr += UrlEncode(mPath, pathSeparator); - - bool hasQuery = !mQuery.empty(); - if(hasQuery) urlStr += querySeparator; - for(auto&& kv : mQuery) - { - urlStr += kv.first; - urlStr += queryAssign; - urlStr += UrlEncode(kv.second); - urlStr += queryFieldSep; - } - if(hasQuery) urlStr.pop_back(); - - if(!mFragment.empty()) urlStr += fragmentSeparator + UrlEncode(mFragment); - - return urlStr; -} - -const std::string& RsUrl::scheme() const { return mScheme; } -RsUrl& RsUrl::setScheme(const std::string& scheme) -{ - mScheme = scheme; - return *this; -} - -const std::string& RsUrl::host() const { return mHost; } -RsUrl& RsUrl::setHost(const std::string& host) -{ - mHost = host; - return *this; -} - -bool RsUrl::hasPort() const { return mHasPort; } -uint16_t RsUrl::port(uint16_t def) const -{ - if(mHasPort) return mPort; - return def; -} -RsUrl& RsUrl::setPort(uint16_t port) -{ - mPort = port; - mHasPort = true; - return *this; -} -RsUrl& RsUrl::unsetPort() -{ - mPort = 0; - mHasPort = false; - return *this; -} - -const std::string& RsUrl::path() const { return mPath; } -RsUrl& RsUrl::setPath(const std::string& path) -{ - mPath = path; - return *this; -} - -const std::map& RsUrl::query() const -{ return mQuery; } -RsUrl& RsUrl::setQuery(const std::map& query) -{ - mQuery = query; - return *this; -} -RsUrl& RsUrl::setQueryKV(const std::string& key, const std::string& value) -{ - mQuery.insert(std::make_pair(key, value)); - return *this; -} -RsUrl& RsUrl::delQueryK(const std::string& key) -{ - mQuery.erase(key); - return *this; -} -bool RsUrl::hasQueryK(const std::string& key) -{ return (mQuery.find(key) != mQuery.end()); } -rs_view_ptr RsUrl::getQueryV(const std::string& key) -{ - if(hasQueryK(key)) return &(mQuery.find(key)->second); - return nullptr; -} - -const std::string& RsUrl::fragment() const { return mFragment; } -RsUrl& RsUrl::setFragment(const std::string& fragment) -{ - mFragment = fragment; - return *this; -} - -/*static*/ std::string RsUrl::UrlEncode( const std::string& str, - const std::string& ignore ) -{ - ostringstream escaped; - escaped.fill('0'); - escaped << hex; - - for (string::value_type c : str) - { - // Keep alphanumeric and other accepted characters intact - if ( isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~' - || ignore.find(c) != string::npos ) - { - escaped << c; - continue; - } - - // Any other characters are percent-encoded - escaped << uppercase; - escaped << '%' << setw(2) << int((unsigned char) c); - escaped << nouppercase; - } - - return escaped.str(); -} - -/*static*/ std::string RsUrl::UrlDecode(const std::string& str) -{ - ostringstream decoded; - - size_t len = str.size(); - size_t boundary = len-2; // % Encoded char must be at least 2 hex char - for (size_t i = 0; i < len; ++i) - { - if(str[i] == '%' && i < boundary) - { - decoded << static_cast(std::stoi( - str.substr(++i, 2), nullptr, 16 )); - ++i; - } - else decoded << str[i]; - } - - return decoded.str(); -} - -void RsUrl::serial_process( RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx ) -{ - std::string urlString = toString(); - RS_SERIAL_PROCESS(urlString); - fromString(urlString); -} - -/*static*/ const std::string RsUrl::schemeSeparator("://"); -/*static*/ const std::string RsUrl::ipv6WrapOpen("["); -/*static*/ const std::string RsUrl::ipv6Separator(":"); -/*static*/ const std::string RsUrl::ipv6WrapClose("]"); -/*static*/ const std::string RsUrl::portSeparator(":"); -/*static*/ const std::string RsUrl::pathSeparator("/"); -/*static*/ const std::string RsUrl::querySeparator("?"); -/*static*/ const std::string RsUrl::queryAssign("="); -/*static*/ const std::string RsUrl::queryFieldSep("&"); -/*static*/ const std::string RsUrl::fragmentSeparator("#"); - diff --git a/libretroshare/src/util/rsurl.h b/libretroshare/src/util/rsurl.h deleted file mode 100644 index 6e6d124c3..000000000 --- a/libretroshare/src/util/rsurl.h +++ /dev/null @@ -1,114 +0,0 @@ -#pragma once -/* - * RetroShare - * Copyright (C) 2018 Gioacchino Mazzurco - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#include -#include - -#include "util/rsmemory.h" -#include "serialiser/rsserializable.h" - -struct sockaddr_storage; - -/** - * Very simplistic and minimal URL helper class for RetroShare, after looking - * for a small and self-contained C/C++ URL parsing and manipulation library, - * haven't found nothing satisfactory except for implementation like QUrl that - * rely on bigger library. - * ATM this implementation is not standard compliant and doesn't aim to be. - * Improvements to this are welcome. - * - * Anyway this should support most common URLs of the form - * scheme://host[:port][/path][?query][#fragment] - */ -struct RsUrl : RsSerializable -{ - RsUrl(); - explicit RsUrl(const std::string& urlStr); - explicit RsUrl(const sockaddr_storage& ssas); - - RsUrl& fromString(const std::string& urlStr); - std::string toString() const; - - const std::string& scheme() const; - RsUrl& setScheme(const std::string& scheme); - - const std::string& host() const; - RsUrl& setHost(const std::string& host); - - bool hasPort() const; - uint16_t port(uint16_t def = 0) const; - RsUrl& setPort(uint16_t port); - RsUrl& unsetPort(); - - const std::string& path() const; - RsUrl& setPath(const std::string& path); - - const std::map& query() const; - RsUrl& setQuery(const std::map& query); - RsUrl& setQueryKV(const std::string& key, const std::string& value); - RsUrl& delQueryK(const std::string& key); - bool hasQueryK(const std::string& key); - rs_view_ptr getQueryV(const std::string& key); - - const std::string& fragment() const; - RsUrl& setFragment(const std::string& fragment); - - static std::string UrlEncode(const std::string& str, - const std::string& ignoreChars = ""); - static std::string UrlDecode(const std::string& str); - - inline bool operator<(const RsUrl& rhs) const - { return toString() < rhs.toString(); } - inline bool operator>(const RsUrl& rhs) const - { return toString() > rhs.toString(); } - inline bool operator<=(const RsUrl& rhs) const - { return toString() <= rhs.toString(); } - inline bool operator>=(const RsUrl& rhs) const - { return toString() >= rhs.toString(); } - inline bool operator==(const RsUrl& rhs) const - { return toString() == rhs.toString(); } - inline bool operator!=(const RsUrl& rhs) const - { return toString() != rhs.toString(); } - - /// @see RsSerializable - virtual void serial_process(RsGenericSerializer::SerializeJob j, - RsGenericSerializer::SerializeContext& ctx); - - static const std::string schemeSeparator; - static const std::string ipv6WrapOpen; - static const std::string ipv6Separator; - static const std::string ipv6WrapClose; - static const std::string portSeparator; - static const std::string pathSeparator; - static const std::string querySeparator; - static const std::string queryAssign; - static const std::string queryFieldSep; - static const std::string fragmentSeparator; - -private: - - std::string mScheme; - std::string mHost; - uint16_t mPort; - bool mHasPort; - std::string mPath; - std::map mQuery; - std::string mFragment; -}; - diff --git a/libretroshare/src/util/rswin.h b/libretroshare/src/util/rswin.h deleted file mode 100644 index 07709a052..000000000 --- a/libretroshare/src/util/rswin.h +++ /dev/null @@ -1,55 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: rswin.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (c) 2010, Thomas Kister * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ - -/** - * This file provides helper functions for the windows environment - */ - - -#ifndef RSWIN_H_ -#define RSWIN_H_ - -#ifdef WINDOWS_SYS - -#include -#include - -// For win32 systems (tested on MingW+Ubuntu) -#undef stat64 -#define stat64 _stati64 - -// Should be in Iphlpapi.h, but mingw doesn't seem to have these -// Values copied directly from: -// http://msdn.microsoft.com/en-us/library/aa366845(v=vs.85).aspx -// (Title: MIB_IPADDRROW structure) - -#ifndef MIB_IPADDR_DISCONNECTED -#define MIB_IPADDR_DISCONNECTED 0x0008 // Address is on disconnected interface -#endif - -#ifndef MIB_IPADDR_DELETED -#define MIB_IPADDR_DELETED 0x0040 // Address is being deleted -#endif - -#endif // WINDOWS_SYS - -#endif // RSWIN_H_ diff --git a/libretroshare/src/util/smallobject.cc b/libretroshare/src/util/smallobject.cc deleted file mode 100644 index 5559e2af6..000000000 --- a/libretroshare/src/util/smallobject.cc +++ /dev/null @@ -1,349 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: smallobject.cc * - * * - * libretroshare: retroshare core library * - * * - * Copyright (c) 2011, Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#include -#include "smallobject.h" -#include "util/rsthreads.h" -#include "util/rsmemory.h" - -using namespace RsMemoryManagement ; - -RsMutex SmallObject::_mtx("SmallObject") ; -SmallObjectAllocator SmallObject::_allocator(RsMemoryManagement::MAX_SMALL_OBJECT_SIZE) ; - -void Chunk::init(size_t blockSize,unsigned char blocks) -{ - _data = new unsigned char[blockSize*blocks] ; - _firstAvailableBlock = 0 ; - _blocksAvailable = blocks ; - - // Inits the first byte of each block to point to the next available block - // - unsigned char *p = _data ; - - for(unsigned char i=0;i= 2) ; - - unsigned char *result = _data + _firstAvailableBlock*blockSize ; - - // Grab id of next available block from the block being allocated. - - // Always the case because the first available block is the first, so the next - // available block is given by *result. - // - _firstAvailableBlock = *result ; - --_blocksAvailable ; - - return result ; -} - -void Chunk::deallocate(void *p,size_t blockSize) -{ - assert(p >= _data) ; - - unsigned char *toRelease = static_cast(p) ; - - // alignment check - - assert( (toRelease - _data) % blockSize == 0 ) ; - - *toRelease = _firstAvailableBlock ; - _firstAvailableBlock = static_cast( (toRelease - _data)/blockSize) ; - - // truncation check - - assert(_firstAvailableBlock == (toRelease - _data)/blockSize); - - ++_blocksAvailable ; -} - -void Chunk::printStatistics(int blockSize) const -{ - std::cerr << " blocksAvailable : " << (int)_blocksAvailable << std::endl; - std::cerr << " firstBlockAvailable: " << (int)_firstAvailableBlock << std::endl; - std::cerr << " blocks : " << (void*)_data << " to " << (void*)(_data+BLOCKS_PER_CHUNK*blockSize) << std::endl; -} - -FixedAllocator::FixedAllocator(size_t bytes) -{ - _blockSize = bytes ; - _numBlocks = BLOCKS_PER_CHUNK ; - _allocChunk = -1 ; - _deallocChunk = -1 ; -} -FixedAllocator::~FixedAllocator() -{ - for(uint32_t i=0;i<_chunks.size();++i) - { - _chunks[i]->free() ; - delete _chunks[i] ; - } -} - -void *FixedAllocator::allocate() -{ - if(_allocChunk < 0 || _chunks[_allocChunk]->_blocksAvailable == 0) - { - // find availabel memory in this chunk - // - uint32_t i ; - _allocChunk = -1 ; - for(i=0;i<_chunks.size();++i) - if(_chunks[i]->_blocksAvailable > 0) // found a chunk - { - _allocChunk = i ; - break ; - } - if( _allocChunk < 0 ) - { - _chunks.reserve(_chunks.size()+1) ; - Chunk *newChunk = new Chunk; - - if(newChunk == NULL) - { - std::cerr << "RsMemoryManagement: ran out of memory !" << std::endl; - exit(-1) ; - } - newChunk->init(_blockSize,_numBlocks) ; - _chunks.push_back(newChunk) ; - - _allocChunk = _chunks.size()-1 ; - _deallocChunk = _chunks.size()-1 ; - } - - } - assert(_chunks[_allocChunk] != NULL) ; - assert(_chunks[_allocChunk]->_blocksAvailable > 0) ; - - return _chunks[_allocChunk]->allocate(_blockSize) ; -} -void FixedAllocator::deallocate(void *p) -{ - if(_deallocChunk < 0 || !chunkOwnsPointer(*_chunks[_deallocChunk],p)) - { - // find the chunk that contains this pointer. Perform a linear search. - - _deallocChunk = -1 ; - - for(uint32_t i=0;i<_chunks.size();++i) - if(chunkOwnsPointer(*_chunks[i],p)) - { - _deallocChunk = i ; - break ; - } - } - assert(_chunks[_deallocChunk] != NULL) ; - - _chunks[_deallocChunk]->deallocate(p,_blockSize) ; - - if(_chunks[_deallocChunk]->_blocksAvailable == BLOCKS_PER_CHUNK) - { - _chunks[_deallocChunk]->free() ; - delete _chunks[_deallocChunk] ; - - _chunks[_deallocChunk] = _chunks.back() ; - if(_allocChunk == _deallocChunk) _allocChunk = -1 ; - if(_allocChunk == ((int)_chunks.size())-1) _allocChunk = _deallocChunk ; - _deallocChunk = -1 ; - _chunks.pop_back(); - } -} -uint32_t FixedAllocator::currentSize() const -{ - uint32_t res = 0 ; - - for(uint32_t i=0;i<_chunks.size();++i) - res += (_numBlocks - _chunks[i]->_blocksAvailable) * _blockSize ; - - return res ; -} -void FixedAllocator::printStatistics() const -{ - std::cerr << " numBLocks=" << (int)_numBlocks << std::endl; - std::cerr << " blockSize=" << (int)_blockSize << std::endl; - std::cerr << " Number of chunks: " << _chunks.size() << std::endl; - for(uint32_t i=0;i<_chunks.size();++i) - _chunks[i]->printStatistics(_blockSize) ; -} - -SmallObjectAllocator::SmallObjectAllocator(size_t maxObjectSize) - : _maxObjectSize(maxObjectSize) -{ - RsStackMutex m(SmallObject::_mtx) ; - - _lastAlloc = NULL ; - _lastDealloc = NULL ; - _active = true ; -} - -SmallObjectAllocator::~SmallObjectAllocator() -{ - RsStackMutex m(SmallObject::_mtx) ; - - //std::cerr << __PRETTY_FUNCTION__ << " not deleting. Leaving it to the system." << std::endl; - - _active = false ; - - uint32_t still_allocated = 0 ; - - for(std::map::const_iterator it(_pool.begin());it!=_pool.end();++it) - still_allocated += it->second->currentSize() ; - //delete it->second ; - - std::cerr << "Memory still in use at end of program: " << still_allocated << " bytes." << std::endl; -} - -void *SmallObjectAllocator::allocate(size_t bytes) -{ - if(bytes > _maxObjectSize) - return rs_malloc(bytes) ; - else if(_lastAlloc != NULL && _lastAlloc->blockSize() == bytes) - return _lastAlloc->allocate() ; - else - { - std::map::iterator it(_pool.find(bytes)) ; - - if(it == _pool.end()) - { - _pool[bytes] = new FixedAllocator(bytes) ; - it = _pool.find(bytes) ; - } - _lastAlloc = it->second ; - - return it->second->allocate() ; - } -} - -void SmallObjectAllocator::deallocate(void *p,size_t bytes) -{ - if(bytes > _maxObjectSize) - free(p) ; - else if(_lastDealloc != NULL && _lastDealloc->blockSize() == bytes) - _lastDealloc->deallocate(p) ; - else - { - std::map::iterator it(_pool.find(bytes)) ; - - if(it == _pool.end()) - { - _pool[bytes] = new FixedAllocator(bytes) ; - it = _pool.find(bytes) ; - } - it->second->deallocate(p) ; - _lastDealloc = it->second ; - } -} - -void SmallObjectAllocator::printStatistics() const -{ - std::cerr << "RsMemoryManagement Statistics:" << std::endl; - std::cerr << " Total Fixed-size allocators: " << _pool.size() << std::endl; - std::cerr << "Pool" << std::endl; - - for(std::map::const_iterator it(_pool.begin());it!=_pool.end();++it) - { - std::cerr << " Allocator for size " << it->first << " : " << std::endl; - std::cerr << " Last Alloc: " << _lastAlloc << std::endl; - std::cerr << " Last Dealloc: " << _lastDealloc << std::endl; - it->second->printStatistics() ; - } -} - -void *SmallObject::operator new(size_t size) -{ -#ifdef DEBUG_MEMORY - bool print=false ; - { - RsStackMutex m(_mtx) ; - static rstime_t last_time = 0 ; - rstime_t now = time(NULL) ; - if(now > last_time + 20) - { - last_time = now ; - print=true ; - } - } - if(print) - printStatistics() ; -#endif - - RsStackMutex m(_mtx) ; - - // This should normally not happen. But that prevents a crash when quitting, since we cannot prevent the constructor - // of an object to call operator new(), nor to handle the case where it returns NULL. - // The memory will therefore not be deleted if that happens. We thus print a warning. - - if(_allocator._active) - return _allocator.allocate(size) ; - else - { - std::cerr << "(EE) allocating " << size << " bytes of memory that cannot be deleted. This is a bug, except if it happens when closing Retroshare" << std::endl; - return malloc(size) ; - } - -#ifdef DEBUG_MEMORY - std::cerr << "new RsItem: " << p << ", size=" << size << std::endl; -#endif -} - -void SmallObject::operator delete(void *p,size_t size) -{ - RsStackMutex m(_mtx) ; - - if(!_allocator._active) - return ; - - _allocator.deallocate(p,size) ; -#ifdef DEBUG_MEMORY - std::cerr << "del RsItem: " << p << ", size=" << size << std::endl; -#endif -} - -void SmallObject::printStatistics() -{ - RsStackMutex m(_mtx) ; - - if(!_allocator._active) - return ; - - _allocator.printStatistics() ; -} - -void RsMemoryManagement::printStatistics() -{ - SmallObject::printStatistics(); -} - - diff --git a/libretroshare/src/util/smallobject.h b/libretroshare/src/util/smallobject.h deleted file mode 100644 index 452037ac6..000000000 --- a/libretroshare/src/util/smallobject.h +++ /dev/null @@ -1,116 +0,0 @@ -/******************************************************************************* - * libretroshare/src/util: smallobject.h * - * * - * libretroshare: retroshare core library * - * * - * Copyright (c) 2011, Cyril Soler * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include - -#include -#include - -#include - -namespace RsMemoryManagement -{ - static const int MAX_SMALL_OBJECT_SIZE = 128 ; - static const unsigned char BLOCKS_PER_CHUNK = 255 ; - - struct Chunk - { - void init(size_t blockSize,unsigned char blocks); - void free() ; - - void *allocate(size_t); - void deallocate(void *p,size_t blockSize); - - unsigned char *_data ; - unsigned char _firstAvailableBlock ; - unsigned char _blocksAvailable ; - - void printStatistics(int blockSize) const ; - }; - - class FixedAllocator - { - public: - FixedAllocator(size_t bytes) ; - virtual ~FixedAllocator() ; - - void *allocate(); - void deallocate(void *p) ; - inline size_t blockSize() const { return _blockSize ; } - - inline bool chunkOwnsPointer(const Chunk& c,void *p) const - { - return intptr_t(p) >= intptr_t(c._data) && (intptr_t(static_cast(p))-intptr_t(c._data))/intptr_t(_blockSize)< intptr_t( _numBlocks ); - } - - void printStatistics() const ; - uint32_t currentSize() const; - private: - size_t _blockSize ; - unsigned char _numBlocks ; - std::vector _chunks ; - int _allocChunk ; // last chunk that provided allocation. -1 if not inited - int _deallocChunk ; // last chunk that provided de-allocation. -1 if not inited - }; - - class SmallObjectAllocator - { - public: - SmallObjectAllocator(size_t maxObjectSize) ; - virtual ~SmallObjectAllocator() ; - - void *allocate(size_t numBytes) ; - void deallocate(void *p,size_t size) ; - - void printStatistics() const ; - - bool _active ; - private: - std::map _pool ; - FixedAllocator *_lastAlloc ; - FixedAllocator *_lastDealloc ; - size_t _maxObjectSize ; - }; - - class SmallObject - { - public: - static void *operator new(size_t size) ; - static void operator delete(void *p,size_t size) ; - - static void printStatistics() ; - - virtual ~SmallObject() {} - - private: - static SmallObjectAllocator _allocator ; - static RsMutex _mtx; - - friend class SmallObjectAllocator ; - }; - - extern void printStatistics() ; -} - - diff --git a/libretroshare/src/util/stacktrace.h b/libretroshare/src/util/stacktrace.h deleted file mode 100644 index cb7dc4e71..000000000 --- a/libretroshare/src/util/stacktrace.h +++ /dev/null @@ -1,312 +0,0 @@ -/******************************************************************************* - * libretroshare * - * * - * Copyright (C) 2016-2018 Gioacchino Mazzurco * - * Copyright (C) 2008 Timo Bingmann http://idlebox.net/ * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License as * - * published by the Free Software Foundation, either version 3 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public License * - * along with this program. If not, see . * - * * - *******************************************************************************/ -#pragma once - -#include -#include -#include - -#ifdef __ANDROID__ -# include "util/rsdebug.h" -#endif - -/** - * @brief Print a backtrace to FILE* out. - * @param[in] demangle true to demangle C++ symbols requires malloc working, in - * some patological cases like a SIGSEGV received during a malloc this would - * cause deadlock so pass false if you may be in such situation (like in a - * SIGSEGV handler ) - * @param[in] out output file - * @param[in] maxFrames maximum number of stack frames you want to bu printed - */ -static inline void print_stacktrace( - bool demangle = true, FILE *out = stderr, unsigned int maxFrames = 63 ); - - -#if defined(__linux__) && defined(__GLIBC__) - -#include -#include - -static inline void print_stacktrace( - bool demangle, FILE* out, unsigned int maxFrames ) -{ - if(!out) - { - fprintf(stderr, "print_stacktrace invalid output file!\n"); - return; - } - - fprintf(out, "stack trace:\n"); - - // storage array for stack trace address data - void* addrlist[maxFrames+1]; - - // retrieve current stack addresses - int addrlen = backtrace(addrlist, sizeof(addrlist) / sizeof(void*)); - - if (addrlen == 0) - { - fprintf(out, " \n"); - return; - } - - if(!demangle) - { - int outFd = fileno(out); - if(outFd < 0) - { - fprintf(stderr, "print_stacktrace invalid output file descriptor!\n"); - return; - } - - backtrace_symbols_fd(addrlist, addrlen, outFd); - return; - } - - // resolve addresses into strings containing "filename(function+address)", - // this array must be free()-ed - char** symbollist = backtrace_symbols(addrlist, addrlen); - - // allocate string which will be filled with the demangled function name - size_t funcnamesize = 256; - char* funcname = (char*)malloc(funcnamesize); - - // iterate over the returned symbol lines. skip the first, it is the - // address of this function. - for (int i = 1; i < addrlen; i++) - { - char *begin_name = 0, *begin_offset = 0, *end_offset = 0; - - /* find parentheses and +address offset surrounding the mangled - * name: ./module(function+0x15c) [0x8048a6d] */ - for (char *p = symbollist[i]; *p; ++p) - { - if (*p == '(') begin_name = p; - else if (*p == '+') begin_offset = p; - else if (*p == ')' && begin_offset) - { - end_offset = p; - break; - } - } - - if ( begin_name && begin_offset && end_offset - && begin_name < begin_offset ) - { - *begin_name++ = '\0'; - *begin_offset++ = '\0'; - *end_offset = '\0'; - - // mangled name is now in [begin_name, begin_offset) and caller - // offset in [begin_offset, end_offset). now apply - // __cxa_demangle(): - - int status; - char* ret = abi::__cxa_demangle( - begin_name, funcname, &funcnamesize, &status ); - if (status == 0) - { - funcname = ret; // use possibly realloc()-ed string - fprintf( out, " %s : %s+%s\n", - symbollist[i], funcname, begin_offset ); - } - else - { - // demangling failed. Output function name as a C function with - // no arguments. - fprintf( out, " %s : %s()+%s\n", - symbollist[i], begin_name, begin_offset ); - } - } - else - { - // couldn't parse the line? print the whole line. - fprintf(out, " %s\n", symbollist[i]); - } - } - - free(funcname); - free(symbollist); -} -#elif defined(__ANDROID__) // defined(__linux__) && defined(__GLIBC__) - -/* Inspired by the solution proposed by Louis Semprini on this thread - * https://stackoverflow.com/questions/8115192/android-ndk-getting-the-backtrace/35586148 - */ - -#include -#include -#include - -struct RsAndroidBacktraceState -{ - void** current; - void** end; -}; - -static inline _Unwind_Reason_Code android_unwind_callback( - struct _Unwind_Context* context, void* arg ) -{ - RsAndroidBacktraceState* state = static_cast(arg); - uintptr_t pc = _Unwind_GetIP(context); - if(pc) - { - if (state->current == state->end) return _URC_END_OF_STACK; - - *state->current++ = reinterpret_cast(pc); - } - return _URC_NO_REASON; -} - -static inline void print_stacktrace( - bool demangle, FILE* /*out*/, unsigned int /*maxFrames*/) -{ - constexpr int max = 5000; - void* buffer[max]; - - RsAndroidBacktraceState state; - state.current = buffer; - state.end = buffer + max; - - _Unwind_Backtrace(android_unwind_callback, &state); - - RsDbg() << std::endl << std::endl - << 0 << " " << buffer[0] << " " << __PRETTY_FUNCTION__ << std::endl; - - // Skip first frame which is print_stacktrace - int count = static_cast(state.current - buffer); - for(int idx = 1; idx < count; ++idx) - { - const void* addr = buffer[idx]; - - /* Ignore null addresses. - * They sometimes happen when using _Unwind_Backtrace() - * with compiler optimizations, when the Link Register is overwritten by - * the inner stack frames. */ - if(!addr) continue; - - /* Ignore duplicate addresses. - * They sometimes happen when using _Unwind_Backtrace() with compiler - * optimizations. */ - if(addr == buffer[idx-1]) continue; - - Dl_info info; - if( !(dladdr(addr, &info) && info.dli_sname) ) - { - RsDbg() << idx << " " << addr << " " << info.dli_fname - << " symbol not found" << std::endl; - continue; - } - - if(demangle) - { - int status = 0; - char* demangled = __cxxabiv1::__cxa_demangle( - info.dli_sname, nullptr, nullptr, &status ); - - if(demangled && (status == 0)) - RsDbg() << idx << " " << addr << " " << demangled << std::endl; - else - RsDbg() << idx << " " << addr << " " - << (info.dli_sname ? info.dli_sname : info.dli_fname) - << " __cxa_demangle failed with: " << status - << std::endl; - - free(demangled); - } - else RsDbg() << idx << " " << addr << " " - << (info.dli_sname ? info.dli_sname : info.dli_fname) - << std::endl; - } - - RsDbg() << std::endl << std::endl; -} - -#else // defined(__linux__) && defined(__GLIBC__) - -static inline void print_stacktrace( - bool /*demangle*/, FILE* out, unsigned int /*max_frames*/ ) -{ - /** Notify the user which signal was caught. We use printf, because this - * is the most basic output function. Once you get a crash, it is - * possible that more complex output systems like streams and the like - * may be corrupted. So we make the most basic call possible to the - * lowest level, most standard print function. */ - fprintf(out, "print_stacktrace Not implemented yet for this platform\n"); -} -#endif // defined(__linux__) && defined(__GLIBC__) - -/** - * @brief CrashStackTrace catch crash signals and print stack trace - * Inspired too https://oroboro.com/stack-trace-on-crash/ - */ -struct CrashStackTrace -{ - CrashStackTrace() - { - signal(SIGABRT, &CrashStackTrace::abortHandler); - signal(SIGSEGV, &CrashStackTrace::abortHandler); - signal(SIGILL, &CrashStackTrace::abortHandler); - signal(SIGFPE, &CrashStackTrace::abortHandler); -#ifdef SIGBUS - signal(SIGBUS, &CrashStackTrace::abortHandler); -#endif - } - - [[ noreturn ]] - static void abortHandler(int signum) - { - // associate each signal with a signal name string. - const char* name = nullptr; - switch(signum) - { - case SIGABRT: name = "SIGABRT"; break; - case SIGSEGV: name = "SIGSEGV"; break; - case SIGILL: name = "SIGILL"; break; - case SIGFPE: name = "SIGFPE"; break; -#ifdef SIGBUS - case SIGBUS: name = "SIGBUS"; break; -#endif - } - -#ifndef __ANDROID__ - /** Notify the user which signal was caught. We use printf, because this - * is the most basic output function. Once you get a crash, it is - * possible that more complex output systems like streams and the like - * may be corrupted. So we make the most basic call possible to the - * lowest level, most standard print function. */ - if(name) - fprintf(stderr, "Caught signal %d (%s)\n", signum, name); - else - fprintf(stderr, "Caught signal %d\n", signum); -#else // ndef __ANDROID__ - /** On Android the best we can to is to rely on RS debug utils */ - RsFatal() << __PRETTY_FUNCTION__ << " Caught signal " << signum << " " - << (name ? name : "") << std::endl; -#endif - - print_stacktrace(false); - - exit(-signum); - } -}; - diff --git a/libretroshare/src/util/utest.h b/libretroshare/src/util/utest.h deleted file mode 100644 index 1ebd9875a..000000000 --- a/libretroshare/src/util/utest.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _UNIT_TEST_MACROS_H__ -#define _UNIT_TEST_MACROS_H__ - -#include - -#define TFAILURE( s ) printf( "FAILURE: " __FILE__ ":%-4d %s\n", __LINE__, s ) -#define TSUCCESS( s ) printf( "SUCCESS: " __FILE__ ":%-4d %s\n", __LINE__, s ) - -/* careful with this line (no protection) */ -#define INITTEST() int ok = 1; int gok = 1; - -/* declare the variables */ -extern int ok; -extern int gok; - -#define CHECK( b ) do { if ( ! (b) ) { ok = 0; TFAILURE( #b ); } } while(0) -#define FAILED( s ) do { ok = 0; TFAILURE( s ); } while(0) -#define REPORT( s ) do { if ( ! (ok) ) { ok = 0; TFAILURE( s ); } else { TSUCCESS( s );} gok &= ok; ok = 1; } while(0) -#define REPORT2( b, s ) do { if ( ! (b) ) { ok = 0; TFAILURE( s ); } else { TSUCCESS( s );} gok &= ok; ok = 1; } while(0) -#define FINALREPORT( s ) do { gok &= ok; ok = 1; if ( ! (gok) ) { TFAILURE( s ); } else { TSUCCESS( s );} } while(0) -#define TESTRESULT() (!gok) - -#endif diff --git a/openpgpsdk b/openpgpsdk new file mode 160000 index 000000000..101f77c32 --- /dev/null +++ b/openpgpsdk @@ -0,0 +1 @@ +Subproject commit 101f77c326b70e13c27056f8860d04626bbeb462 diff --git a/openpgpsdk/CMakeLists.txt b/openpgpsdk/CMakeLists.txt deleted file mode 100644 index 32dd86c6a..000000000 --- a/openpgpsdk/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -# RetroShare decentralized communication platform -# -# Copyright (C) 2021 Gioacchino Mazzurco -# Copyright (C) 2021 AsociaciĆ³n Civil Altermundi -# -# SPDX-License-Identifier: CC0-1.0 - -cmake_minimum_required (VERSION 3.12.0) -project(openpgpsdk) - -find_package(ZLIB REQUIRED) -find_package(BZip2 REQUIRED) -find_package(OpenSSL REQUIRED) - -file(GLOB SOURCES src/openpgpsdk/*.c) -add_library(${PROJECT_NAME} ${SOURCES}) - -target_include_directories( - ${PROJECT_NAME} - PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src - PRIVATE ${OPENSSL_INCLUDE_DIR} - PRIVATE ${BZIP2_INCLUDE_DIRS} - PRIVATE ${ZLIB_INCLUDE_DIRS} ) - -target_link_libraries( - ${PROJECT_NAME} - OpenSSL::SSL OpenSSL::Crypto BZip2::BZip2 ZLIB::ZLIB ) diff --git a/openpgpsdk/src/openpgpsdk.pro b/openpgpsdk/src/openpgpsdk.pro deleted file mode 100644 index 79aeeec2d..000000000 --- a/openpgpsdk/src/openpgpsdk.pro +++ /dev/null @@ -1,144 +0,0 @@ -# SPDX-FileCopyrightText: (C) 2004-2019 Retroshare Team -# SPDX-License-Identifier: CC0-1.0 - -!include("../../retroshare.pri"): error("Could not include file ../../retroshare.pri") - -TEMPLATE = lib -CONFIG += staticlib - -DEFINES *= OPENSSL_NO_IDEA - -QMAKE_CXXFLAGS *= -Werror -W - -TARGET = ops -DESTDIR = lib - -!include(use_openpgpsdk.pri):error("Including") - -#################################### Windows ##################################### - -linux-* { - OBJECTS_DIR = temp/linux/obj -} - -win32-g++|win32-clang-g++ { - - HEADERS += openpgpsdk/opsstring.h - SOURCES += openpgpsdk/opsstring.c - - DEFINES *= WIN32_LEAN_AND_MEAN - - # Switch off optimization for release version - QMAKE_CXXFLAGS_RELEASE -= -O2 - QMAKE_CXXFLAGS_RELEASE += -O0 - QMAKE_CFLAGS_RELEASE -= -O2 - QMAKE_CFLAGS_RELEASE += -O0 - - mLibs = bz2 z ssl crypto - static { - LIBS += $$linkStaticLibs(mLibs) - PRE_TARGETDEPS += $$pretargetStaticLibs(mLibs) - } else { - LIBS += $$linkDynamicLibs(mLibs) - } -} - - -macx { - for(lib, LIB_DIR):LIBS += -L"$$lib" - for(bin, BIN_DIR):LIBS += -L"$$bin" - DEFINES += OPENSSL_NO_CAMELLIA -} - -# Input -HEADERS += openpgpsdk/writer.h \ - openpgpsdk/writer_armoured.h \ - openpgpsdk/version.h \ - openpgpsdk/validate.h \ - openpgpsdk/util.h \ - openpgpsdk/types.h \ - openpgpsdk/streamwriter.h \ - openpgpsdk/std_print.h \ - openpgpsdk/signature.h \ - openpgpsdk/readerwriter.h \ - openpgpsdk/random.h \ - openpgpsdk/partial.h \ - openpgpsdk/packet-show.h \ - openpgpsdk/packet-show-cast.h \ - openpgpsdk/packet-parse.h \ - openpgpsdk/packet.h \ - openpgpsdk/memory.h \ - openpgpsdk/literal.h \ - openpgpsdk/lists.h \ - openpgpsdk/keyring.h \ - openpgpsdk/hash.h \ - openpgpsdk/final.h \ - openpgpsdk/defs.h \ - openpgpsdk/errors.h \ - openpgpsdk/crypto.h \ - openpgpsdk/create.h \ - openpgpsdk/configure.h \ - openpgpsdk/compress.h \ - openpgpsdk/callback.h \ - openpgpsdk/accumulate.h \ - openpgpsdk/armour.h \ - openpgpsdk/parse_local.h \ - openpgpsdk/keyring_local.h \ - openpgpsdk/opsdir.h - -SOURCES += openpgpsdk/accumulate.c \ - openpgpsdk/compress.c \ - openpgpsdk/create.c \ - openpgpsdk/crypto.c \ - openpgpsdk/errors.c \ - openpgpsdk/fingerprint.c \ - openpgpsdk/hash.c \ - openpgpsdk/keyring.c \ - openpgpsdk/lists.c \ - openpgpsdk/memory.c \ - openpgpsdk/openssl_crypto.c \ - openpgpsdk/packet-parse.c \ - openpgpsdk/packet-print.c \ - openpgpsdk/packet-show.c \ - openpgpsdk/random.c \ - openpgpsdk/reader.c \ - openpgpsdk/reader_armoured.c \ - openpgpsdk/reader_encrypted_se.c \ - openpgpsdk/reader_encrypted_seip.c \ - openpgpsdk/reader_fd.c \ - openpgpsdk/reader_hashed.c \ - openpgpsdk/reader_mem.c \ - openpgpsdk/readerwriter.c \ - openpgpsdk/signature.c \ - openpgpsdk/symmetric.c \ - openpgpsdk/util.c \ - openpgpsdk/validate.c \ - openpgpsdk/writer.c \ - openpgpsdk/writer_armour.c \ - openpgpsdk/writer_partial.c \ - openpgpsdk/writer_literal.c \ - openpgpsdk/writer_encrypt.c \ - openpgpsdk/writer_encrypt_se_ip.c \ - openpgpsdk/writer_fd.c \ - openpgpsdk/writer_memory.c \ - openpgpsdk/writer_skey_checksum.c \ - openpgpsdk/writer_stream_encrypt_se_ip.c \ - openpgpsdk/opsdir.c - - -################################# Android ##################################### - -android-* { - -## Add this here because static library are very sensible to order in -## command line - LIBS += -L$$NATIVE_LIBS_TOOLCHAIN_PATH/sysroot/usr/lib/ -lssl - INCLUDEPATH += $$NATIVE_LIBS_TOOLCHAIN_PATH/sysroot/usr/include - DEPENDPATH += $$NATIVE_LIBS_TOOLCHAIN_PATH/sysroot/usr/include - PRE_TARGETDEPS += $$NATIVE_LIBS_TOOLCHAIN_PATH/sysroot/usr/lib/libssl.a - - LIBS += -L$$NATIVE_LIBS_TOOLCHAIN_PATH/sysroot/usr/lib/ -lcrypto - INCLUDEPATH += $$NATIVE_LIBS_TOOLCHAIN_PATH/sysroot/usr/include - DEPENDPATH += $$NATIVE_LIBS_TOOLCHAIN_PATH/sysroot/usr/include - PRE_TARGETDEPS += $$NATIVE_LIBS_TOOLCHAIN_PATH/sysroot/usr/lib/libcrypto.a -} diff --git a/openpgpsdk/src/openpgpsdk/accumulate.c b/openpgpsdk/src/openpgpsdk/accumulate.c deleted file mode 100644 index 025e08e74..000000000 --- a/openpgpsdk/src/openpgpsdk/accumulate.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include -#include -#include "keyring_local.h" -#include "parse_local.h" -#include -#include -#include - -#include - -typedef struct - { - ops_keyring_t *keyring; - } accumulate_arg_t; - -/** - * \ingroup Core_Callbacks - */ -static ops_parse_cb_return_t accumulate_cb(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo) -{ - accumulate_arg_t *arg=ops_parse_cb_get_arg(cbinfo); - const ops_parser_content_union_t *content=&content_->content; - ops_keyring_t *keyring=arg->keyring; - ops_keydata_t *cur=NULL; - const ops_public_key_t *pkey; - - if(keyring->nkeys >= 0) - cur=&keyring->keys[keyring->nkeys]; - - switch(content_->tag) - { - case OPS_PTAG_CT_PUBLIC_KEY: - case OPS_PTAG_CT_SECRET_KEY: - case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY: - // printf("New key\n"); - ++keyring->nkeys; - EXPAND_ARRAY(keyring,keys); - - if(content_->tag == OPS_PTAG_CT_PUBLIC_KEY) - pkey=&content->public_key; - else - pkey=&content->secret_key.public_key; - - memset(&keyring->keys[keyring->nkeys],'\0', sizeof keyring->keys[keyring->nkeys]); - - ops_keyid(keyring->keys[keyring->nkeys].key_id,pkey); - ops_fingerprint(&keyring->keys[keyring->nkeys].fingerprint,pkey); - - keyring->keys[keyring->nkeys].type=content_->tag; - - if(content_->tag == OPS_PTAG_CT_PUBLIC_KEY) - keyring->keys[keyring->nkeys].key.pkey=*pkey; - else - keyring->keys[keyring->nkeys].key.skey=content->secret_key; - return OPS_KEEP_MEMORY; - - case OPS_PTAG_CT_USER_ID: - // printf("User ID: %s\n",content->user_id.user_id); - if (!cur) - { - OPS_ERROR(cbinfo->errors,OPS_E_P_NO_USERID, "No user id found"); - return OPS_KEEP_MEMORY; - } - ops_add_userid_to_keydata(cur, &content->user_id); - free(content->user_id.user_id); - return OPS_KEEP_MEMORY; - - case OPS_PARSER_PACKET_END: - if(!cur) - return OPS_RELEASE_MEMORY; - ops_add_packet_to_keydata(cur, &content->packet); - free(content->packet.raw); - return OPS_KEEP_MEMORY; - - case OPS_PARSER_ERROR: - fprintf(stderr,"Error: %s\n",content->error.error); - break; - - case OPS_PARSER_ERRCODE: - switch(content->errcode.errcode) - { - default: - fprintf(stderr,"parse error: %s\n", ops_errcode(content->errcode.errcode)); - } - break; - - default: - break; - } - - // XXX: we now exclude so many things, we should either drop this or - // do something to pass on copies of the stuff we keep - return ops_parse_stacked_cb(content_,cbinfo); -} - -/** - * \ingroup Core_Parse - * - * Parse packets from an input stream until EOF or error. - * - * Key data found in the parsed data is added to #keyring. - * - * \param keyring Pointer to an existing keyring - * \param parse_info Options to use when parsing -*/ - -int ops_parse_and_accumulate(ops_keyring_t *keyring, - ops_parse_info_t *parse_info) - { - int rtn; - - accumulate_arg_t arg; - - if(parse_info->rinfo.accumulate) - { - fprintf(stderr,"Structural error: parse_info->rinfo.accumulate should be ops_false" ) ; - return 0 ; // error - } - //assert(!parse_info->rinfo.accumulate); - - memset(&arg,'\0',sizeof arg); - - arg.keyring=keyring; - /* Kinda weird, but to do with counting, and we put it back after */ - --keyring->nkeys; - - ops_parse_cb_push(parse_info,accumulate_cb,&arg); - - parse_info->rinfo.accumulate=ops_true; - - rtn=ops_parse(parse_info,ops_false); - ++keyring->nkeys; - - return rtn; - } - -static void dump_one_keydata(const ops_keydata_t *key) - { - unsigned n; - - printf("Key ID: "); - hexdump(key->key_id,8); - - printf("\nFingerpint: "); - hexdump(key->fingerprint.fingerprint,key->fingerprint.length); - - printf("\n\nUIDs\n====\n\n"); - for(n=0 ; n < key->nuids ; ++n) - printf("%s\n",key->uids[n].user_id); - - printf("\nPackets\n=======\n"); - for(n=0 ; n < key->npackets ; ++n) - { - printf("\n%03d: ",n); - hexdump(key->packets[n].raw,key->packets[n].length); - } - printf("\n\n"); - } - -// XXX: not a maintained part of the API - use ops_keyring_list() -/** ops_dump_keyring -*/ -void ops_dump_keyring(const ops_keyring_t *keyring) - { - int n; - - for(n=0 ; n < keyring->nkeys ; ++n) - dump_one_keydata(&keyring->keys[n]); - } diff --git a/openpgpsdk/src/openpgpsdk/accumulate.h b/openpgpsdk/src/openpgpsdk/accumulate.h deleted file mode 100644 index eeadb4011..000000000 --- a/openpgpsdk/src/openpgpsdk/accumulate.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_ACCUMULATE_H -#define OPS_ACCUMULATE_H -#endif - -#include "keyring.h" -#include "packet-parse.h" - -int ops_parse_and_accumulate(ops_keyring_t *keyring, - ops_parse_info_t *parse_info); diff --git a/openpgpsdk/src/openpgpsdk/armour.h b/openpgpsdk/src/openpgpsdk/armour.h deleted file mode 100644 index b2f3a8d69..000000000 --- a/openpgpsdk/src/openpgpsdk/armour.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __OPS_ARMOUR_H__ -#define __OPS_ARMOUR_H__ - -#include "packet-parse.h" -#include "signature.h" - -unsigned ops_crc24(unsigned checksum,unsigned char c); - -void ops_reader_push_dearmour(ops_parse_info_t *parse_info); - -void ops_reader_pop_dearmour(ops_parse_info_t *parse_info); -ops_boolean_t ops_writer_push_clearsigned(ops_create_info_t *info, - ops_create_signature_t *sig); -void ops_writer_push_armoured_message(ops_create_info_t *info); -ops_boolean_t ops_writer_switch_to_armoured_signature(ops_create_info_t *info); - -typedef enum - { - OPS_PGP_MESSAGE=1, - OPS_PGP_PUBLIC_KEY_BLOCK, - OPS_PGP_PRIVATE_KEY_BLOCK, - OPS_PGP_MULTIPART_MESSAGE_PART_X_OF_Y, - OPS_PGP_MULTIPART_MESSAGE_PART_X, - OPS_PGP_SIGNATURE - } ops_armor_type_t; - -void ops_writer_push_armoured(ops_create_info_t *info, ops_armor_type_t type); - -#define CRC24_INIT 0xb704ceL - -#endif /* __OPS_ARMOUR_H__ */ - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/callback.h b/openpgpsdk/src/openpgpsdk/callback.h deleted file mode 100644 index 399c3d118..000000000 --- a/openpgpsdk/src/openpgpsdk/callback.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __OPS_CALLBACK_H__ -#define __OPS_CALLBACK_H__ - -#define CB(cbinfo,t,pc) do { (pc)->tag=(t); if(ops_parse_cb((pc),(cbinfo)) == OPS_RELEASE_MEMORY) ops_parser_content_free(pc); } while(0) -/*#define CB(cbinfo,t,pc) do { (pc)->tag=(t); if((cbinfo)->cb(pc,(cbinfo)) == OPS_RELEASE_MEMORY) ops_parser_content_free(pc); } while(0)*/ -//#define CB(cbinfo,t,pc) do { (pc)->tag=(t); if((cbinfo)->cb(pc,(cbinfo)) == OPS_RELEASE_MEMORY) ops_parser_content_free(pc); } while(0) - -#define CBP(info,t,pc) CB(&(info)->cbinfo,t,pc) - -#define ERR(cbinfo,err,code) do { content.content.error.error=err; content.tag=OPS_PARSER_ERROR; ops_parse_cb(&content,(cbinfo)); OPS_ERROR(errors,code,err); return -1; } while(0) - /*#define ERR(err) do { content.content.error.error=err; content.tag=OPS_PARSER_ERROR; ops_parse_cb(&content,cbinfo); return -1; } while(0)*/ - -#define ERRP(info,err) do { C.error.error=err; CBP(info,OPS_PARSER_ERROR,&content); return ops_false; } while(0) - - -#endif /*__OPS_CALLBACK_H__*/ diff --git a/openpgpsdk/src/openpgpsdk/compress.c b/openpgpsdk/src/openpgpsdk/compress.c deleted file mode 100644 index afe3db6ac..000000000 --- a/openpgpsdk/src/openpgpsdk/compress.c +++ /dev/null @@ -1,614 +0,0 @@ -/* - * Copyright (c) 2005-2009 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer, Alasdair Mackintosh. - * The Contributors have asserted their moral rights under the - * UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include - -#include -#include -#include -#include -#include "parse_local.h" -#include -#include - -static const int debug = 0; - -#define DECOMPRESS_BUFFER 1024 -#define COMPRESS_BUFFER 32768 - -typedef struct - { - ops_compression_type_t type; - ops_region_t *region; - unsigned char in[DECOMPRESS_BUFFER]; - unsigned char out[DECOMPRESS_BUFFER]; - z_stream zstream; // ZIP and ZLIB - size_t offset; - int inflate_ret; - } z_decompress_arg_t; - -typedef struct - { - ops_compression_type_t type; - ops_region_t *region; - char in[DECOMPRESS_BUFFER]; - char out[DECOMPRESS_BUFFER]; - bz_stream bzstream; // BZIP2 - size_t offset; - int inflate_ret; - } bz_decompress_arg_t; - -typedef struct - { - z_stream stream; - unsigned char *src; - unsigned char *dst; - size_t bytes_in; - size_t bytes_out; - } compress_arg_t; - -// \todo remove code duplication between this and bzip2_compressed_data_reader -static int zlib_compressed_data_reader(void *dest,size_t length, - ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo) -{ - z_decompress_arg_t *arg=ops_reader_get_arg(rinfo); - - if(! (arg->type==OPS_C_ZIP || arg->type==OPS_C_ZLIB) ) // ASSERT(arg->type==OPS_C_ZIP || arg->type==OPS_C_ZLIB); - { - fprintf(stderr,"zlib_compressed_data_reader: unexpected compress format %d\n",arg->type) ; - return -1 ; - } - - //ops_parser_content_t content; - int saved=length; - - if(/*arg->region->indeterminate && */ arg->inflate_ret == Z_STREAM_END - && arg->zstream.next_out == &arg->out[arg->offset]) - return 0; - - if(arg->region->length_read == arg->region->length) - { - if(arg->inflate_ret != Z_STREAM_END) - OPS_ERROR(cbinfo->errors, OPS_E_P_DECOMPRESSION_ERROR, - "Compressed data didn't end when region ended."); - /* - else - return 0; - www.zlib.org - */ - } - - while(length > 0) - { - unsigned len; - - if(&arg->out[arg->offset] == arg->zstream.next_out) - { - int ret; - - arg->zstream.next_out=arg->out; - arg->zstream.avail_out=sizeof arg->out; - arg->offset=0; - if(arg->zstream.avail_in == 0) - { - unsigned n=arg->region->length; - - if(!arg->region->indeterminate) - { - n-=arg->region->length_read; - if(n > sizeof arg->in) - n=sizeof arg->in; - } - else - n=sizeof arg->in; - - if(!ops_stacked_limited_read(arg->in,n,arg->region, - errors,rinfo,cbinfo)) - return -1; - - arg->zstream.next_in=arg->in; - arg->zstream.avail_in=arg->region->indeterminate - ? arg->region->last_read : n; - } - - ret=inflate(&arg->zstream,Z_SYNC_FLUSH); - if(ret == Z_STREAM_END) - { - if(!arg->region->indeterminate - && arg->region->length_read != arg->region->length) - OPS_ERROR(cbinfo->errors,OPS_E_P_DECOMPRESSION_ERROR, - "Compressed stream ended before packet end."); - } - else if(ret != Z_OK) - { - fprintf(stderr,"ret=%d\n",ret); - OPS_ERROR(cbinfo->errors,OPS_E_P_DECOMPRESSION_ERROR, arg->zstream.msg); - } - arg->inflate_ret=ret; - } - - if(!(arg->zstream.next_out > &arg->out[arg->offset])) // ASSERT(arg->zstream.next_out > &arg->out[arg->offset]); - { - fprintf(stderr,"decompression error: next packet is too large.\n"); - return -1 ; - } - len=arg->zstream.next_out-&arg->out[arg->offset]; - if(len > length) - len=length; - memcpy(dest,&arg->out[arg->offset],len); - arg->offset+=len; - length-=len; - } - - return saved; -} - -// \todo remove code duplication between this and zlib_compressed_data_reader -static int bzip2_compressed_data_reader(void *dest,size_t length, - ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo) -{ - bz_decompress_arg_t *arg=ops_reader_get_arg(rinfo); - - if(!(arg->type==OPS_C_BZIP2)) // ASSERT(arg->type==OPS_C_BZIP2); - { - fprintf(stderr,"bzip2_compressed_data_reader: unexpected compress format %d\n",arg->type) ; - return -1 ; - } - - //ops_parser_content_t content; - int saved=length; - - if(arg->inflate_ret == BZ_STREAM_END - && arg->bzstream.next_out == &arg->out[arg->offset]) - return 0; - - if(arg->region->length_read == arg->region->length) - { - if(arg->inflate_ret != BZ_STREAM_END) - OPS_ERROR(cbinfo->errors, OPS_E_P_DECOMPRESSION_ERROR, - "Compressed data didn't end when region ended."); - } - - while(length > 0) - { - unsigned len; - - if(&arg->out[arg->offset] == arg->bzstream.next_out) - { - int ret; - - arg->bzstream.next_out=(char *) arg->out; - arg->bzstream.avail_out=sizeof arg->out; - arg->offset=0; - if(arg->bzstream.avail_in == 0) - { - unsigned n=arg->region->length; - - if(!arg->region->indeterminate) - { - n-=arg->region->length_read; - if(n > sizeof arg->in) - n=sizeof arg->in; - } - else - n=sizeof arg->in; - - if(!ops_stacked_limited_read(arg->in, n, arg->region, errors, - rinfo, cbinfo)) - return -1; - - arg->bzstream.next_in=arg->in; - arg->bzstream.avail_in=arg->region->indeterminate - ? arg->region->last_read : n; - } - - ret=BZ2_bzDecompress(&arg->bzstream); - if(ret == BZ_STREAM_END) - { - if(!arg->region->indeterminate - && arg->region->length_read != arg->region->length) - OPS_ERROR(cbinfo->errors, OPS_E_P_DECOMPRESSION_ERROR, - "Compressed stream ended before packet end."); - } - else if(ret != BZ_OK) - { - OPS_ERROR_1(cbinfo->errors, OPS_E_P_DECOMPRESSION_ERROR, - "Invalid return %d from BZ2_bzDecompress", ret); - } - arg->inflate_ret=ret; - } - if(!(arg->bzstream.next_out > &arg->out[arg->offset])) // ASSERT(arg->bzstream.next_out > &arg->out[arg->offset]); - { - fprintf(stderr,"bzip2_compressed_data_reader: unexpected size in compressed packet.\n") ; - return -1 ; - } - len=arg->bzstream.next_out-&arg->out[arg->offset]; - if(len > length) - len=length; - memcpy(dest,&arg->out[arg->offset],len); - arg->offset+=len; - length-=len; - } - - return saved; -} - -/** - * \ingroup Core_Compress - * - * \param *region Pointer to a region - * \param *parse_info How to parse - * \param type Which compression type to expect -*/ - -int ops_decompress(ops_region_t *region,ops_parse_info_t *parse_info, - ops_compression_type_t type) - { - z_decompress_arg_t z_arg; - bz_decompress_arg_t bz_arg; - int ret; - - switch (type) - { - case OPS_C_ZIP: - case OPS_C_ZLIB: - memset(&z_arg,'\0',sizeof z_arg); - - z_arg.region=region; - z_arg.offset=0; - z_arg.type=type; - - z_arg.zstream.next_in=Z_NULL; - z_arg.zstream.avail_in=0; - z_arg.zstream.next_out=z_arg.out; - z_arg.zstream.zalloc=Z_NULL; - z_arg.zstream.zfree=Z_NULL; - z_arg.zstream.opaque=Z_NULL; - break; - - case OPS_C_BZIP2: - memset(&bz_arg,'\0',sizeof bz_arg); - - bz_arg.region=region; - bz_arg.offset=0; - bz_arg.type=type; - - bz_arg.bzstream.next_in=NULL; - bz_arg.bzstream.avail_in=0; - bz_arg.bzstream.next_out=bz_arg.out; - bz_arg.bzstream.bzalloc=NULL; - bz_arg.bzstream.bzfree=NULL; - bz_arg.bzstream.opaque=NULL; - break; - - default: - OPS_ERROR_1(&parse_info->errors, OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG, - "Compression algorithm %d is not yet supported", type); - return 0; - } - - switch(type) - { - case OPS_C_ZIP: - ret=inflateInit2(&z_arg.zstream,-15); - break; - - case OPS_C_ZLIB: - ret=inflateInit(&z_arg.zstream); - break; - - case OPS_C_BZIP2: - /* - OPS_ERROR_1(&parse_info->errors, OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG, "Compression algorithm %s is not yet supported", "BZIP2"); - return 0; - */ - ret=BZ2_bzDecompressInit(&bz_arg.bzstream, 1, 0); - break; - - default: - OPS_ERROR_1(&parse_info->errors, OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG, - "Compression algorithm %d is not yet supported", type); - return 0; - } - - switch (type) - { - case OPS_C_ZIP: - case OPS_C_ZLIB: - if(ret != Z_OK) - { - OPS_ERROR_1(&parse_info->errors, OPS_E_P_DECOMPRESSION_ERROR, - "Cannot initialise ZIP or ZLIB stream " - "for decompression: error=%d", ret); - return 0; - } - ops_reader_push(parse_info,zlib_compressed_data_reader,NULL,&z_arg); - break; - - case OPS_C_BZIP2: - if (ret != BZ_OK) - { - OPS_ERROR_1(&parse_info->errors, OPS_E_P_DECOMPRESSION_ERROR, - "Cannot initialise BZIP2 stream " - "for decompression: error=%d", ret); - return 0; - } - ops_reader_push(parse_info,bzip2_compressed_data_reader,NULL,&bz_arg); - break; - - default: - OPS_ERROR_1(&parse_info->errors, OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG, - "Compression algorithm %d is not yet supported", type); - return 0; - } - - ret=ops_parse(parse_info,ops_true); - - ops_reader_pop(parse_info); - - return ret; - } - -/** -\ingroup Core_WritePackets -\brief Writes Compressed packet -\param data Data to write out -\param len Length of data -\param cinfo Write settings -\return ops_true if OK; else ops_false -*/ - -ops_boolean_t ops_write_compressed(const unsigned char *data, - const unsigned int len, - ops_create_info_t *cinfo) -{ - int r=0; - int sz_in=0; - int sz_out=0; - compress_arg_t* compress=ops_mallocz(sizeof *compress); - - // compress the data - const int level=Z_DEFAULT_COMPRESSION; // \todo allow varying levels - compress->stream.zalloc=Z_NULL; - compress->stream.zfree=Z_NULL; - compress->stream.opaque=NULL; - - // all other fields set to zero by use of ops_mallocz - - if (deflateInit(&compress->stream,level) != Z_OK) - { - // can't initialise - - fprintf(stderr,"ops_write_compressed: can't initialise compression engine\n") ; - return ops_false ; - } - - // do necessary transformation - // copy input to maintain const'ness of src - - if(!(compress->src==NULL)) // ASSERT(compress->src==NULL); - { - fprintf(stderr,"ops_write_compressed: compress->src should be NULL\n") ; - return ops_false ; - } - if(!(compress->dst==NULL)) // ASSERT(compress->dst==NULL); - { - fprintf(stderr,"ops_write_compressed: compress->dst should be NULL\n") ; - return ops_false ; - } - - sz_in=len * sizeof (unsigned char); - sz_out= (sz_in * 1.01) + 12; // from zlib webpage - compress->src=ops_mallocz(sz_in); - compress->dst=ops_mallocz(sz_out); - memcpy(compress->src,data,len); - - // setup stream - compress->stream.next_in=compress->src; - compress->stream.avail_in=sz_in; - compress->stream.total_in=0; - - compress->stream.next_out=compress->dst; - compress->stream.avail_out=sz_out; - compress->stream.total_out=0; - - r=deflate(&compress->stream, Z_FINISH); - - if(!(r==Z_STREAM_END)) // ASSERT(r==Z_STREAM_END); // need to loop if not - { - fprintf(stderr,"ops_write_compressed: compression failed.\n") ; - return ops_false ; - } - - // write it out - return (ops_write_ptag(OPS_PTAG_CT_COMPRESSED, cinfo) - && ops_write_length(1+compress->stream.total_out, cinfo) - && ops_write_scalar(OPS_C_ZLIB,1,cinfo) - && ops_write(compress->dst, compress->stream.total_out,cinfo)); -} - - -// Writes out the header for the compressed packet. Invoked by the -// partial stream writer. Note that writing the packet tag and the -// packet length is handled by the partial stream writer. -static ops_boolean_t write_compressed_header(ops_create_info_t *info, - void *header_data) - { - OPS_USED(header_data); - // Write the compression type. Currently we just use ZLIB - ops_write_scalar(OPS_C_ZLIB, 1, info); - return ops_true; - } - -static void zlib_error(ops_error_t **errors, z_stream *stream, int error) - { - OPS_ERROR_2(errors,OPS_E_FAIL, - "Error from compression stream %d (%s)", error, - stream->msg == NULL ? "Unknown" : stream->msg); - } - -static ops_boolean_t stream_compress_writer(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo) - { - // ZLib doesn't like being asked to compress nothing, so return if - // we are given no input. - if (length == 0) - return ops_true; - if (debug) - fprintf(stderr, "Compressing %u bytes\n", length); - compress_arg_t* compress = ops_writer_get_arg(winfo); - compress->bytes_in += length; - compress->stream.next_in = (void*) src; - compress->stream.avail_in = length; - ops_boolean_t result = ops_true; - do - { - compress->stream.next_out = compress->dst; - compress->stream.avail_out = COMPRESS_BUFFER; - int retcode = deflate(&compress->stream, Z_NO_FLUSH); - if (retcode != Z_OK) - { - zlib_error(errors, &compress->stream, retcode); - deflateEnd(&compress->stream); - return ops_false; - } - unsigned bytes_to_write = COMPRESS_BUFFER - compress->stream.avail_out; - if (debug) - fprintf(stderr, "bytes_to_write = %u\n", bytes_to_write); - compress->bytes_out += bytes_to_write; - result = ops_stacked_write(compress->dst, bytes_to_write, errors, - winfo); - } - while (result && compress->stream.avail_out == 0); - - return result; - } - -static ops_boolean_t stream_compress_finaliser(ops_error_t **errors, - ops_writer_info_t *winfo) - { - compress_arg_t* compress = ops_writer_get_arg(winfo); - compress->stream.next_in = NULL; - compress->stream.avail_in = 0; - int retcode = Z_OK; - int output_size = COMPRESS_BUFFER; - ops_boolean_t result = ops_true; - do - { - compress->stream.next_out = compress->dst; - compress->stream.avail_out = output_size; - retcode = deflate(&compress->stream, Z_FINISH); - if (retcode != Z_STREAM_END && retcode != Z_OK) - { - zlib_error(errors, &compress->stream, retcode); - deflateEnd(&compress->stream); - return ops_false; - } - int bytes_to_write = output_size - compress->stream.avail_out; - if (debug) - fprintf(stderr, "At end, bytes_to_write = %u\n", bytes_to_write); - compress->bytes_out += bytes_to_write; - result = ops_stacked_write(compress->dst, bytes_to_write, errors, - winfo); - - // If deflate returns Z_OK after we have asked to flush, it means - // that there was not enough space in the output buffer. Increase - // the buffer size and try again. - if (retcode != Z_STREAM_END) - { - if (debug) - fprintf(stderr, "Reallocating %u\n", output_size * 2); - output_size *= 2; - compress->dst = realloc(compress->dst, output_size); - } - } - while (result && retcode != Z_STREAM_END); - - int error = deflateEnd(&compress->stream); - if (error != Z_OK) - { - zlib_error(errors, &compress->stream, error); - return ops_false; - } - return result; - } - -static void stream_compress_destroyer(ops_writer_info_t *winfo) - { - compress_arg_t* compress = ops_writer_get_arg(winfo); - if (debug) - fprintf(stderr, "Compressed %zu to %zu\n", compress->bytes_in, - compress->bytes_out); - free(compress->dst); - free(compress); - } - -/** -\ingroup Core_WritePackets -\brief Pushes a compressed writer onto the stack. Data written - will be encoded as a compressed packet. -\param cinfo Write settings -*/ -ops_boolean_t ops_writer_push_compressed(ops_create_info_t *cinfo) -{ - // This is a streaming writer, so we don't know the length in - // advance. Use a partial writer to handle the partial body - // packet lengths. - ops_writer_push_partial(COMPRESS_BUFFER, - cinfo, OPS_PTAG_CT_COMPRESSED, - write_compressed_header, NULL); - - // Create arg to be used with this writer - // Remember to free this in the destroyer - compress_arg_t *compress = ops_mallocz(sizeof *compress); - - compress->dst = malloc(COMPRESS_BUFFER); - const int level=Z_DEFAULT_COMPRESSION; // \todo allow varying levels - compress->stream.zalloc=Z_NULL; - compress->stream.zfree=Z_NULL; - compress->stream.opaque=NULL; - compress->stream.avail_out = COMPRESS_BUFFER; - // all other fields set to zero by use of ops_mallocz - - if (deflateInit(&compress->stream, level) != Z_OK) - // can't initialise. Is there a better way to handle this? - return ops_false ; - - // And push writer on stack - ops_writer_push(cinfo, stream_compress_writer, stream_compress_finaliser, - stream_compress_destroyer, compress); - - return ops_true ; -} - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/compress.h b/openpgpsdk/src/openpgpsdk/compress.h deleted file mode 100644 index 04d124e41..000000000 --- a/openpgpsdk/src/openpgpsdk/compress.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include "packet-parse.h" - -int ops_decompress(ops_region_t *region,ops_parse_info_t *parse_info, - ops_compression_type_t type); - -ops_boolean_t ops_write_compressed(const unsigned char* data, - const unsigned int len, - ops_create_info_t *cinfo); - -ops_boolean_t ops_writer_push_compressed(ops_create_info_t *cinfo); diff --git a/openpgpsdk/src/openpgpsdk/configure.h b/openpgpsdk/src/openpgpsdk/configure.h deleted file mode 100644 index 63051b316..000000000 --- a/openpgpsdk/src/openpgpsdk/configure.h +++ /dev/null @@ -1,15 +0,0 @@ -/* generated by configure from include/openpgpsdk/configure.h.template. Don't edit. */ - -#define HAVE_ALLOCA_H 0 -#define TIME_T_FMT "%ld" - -/* for silencing unused parameter warnings */ -#define OPS_USED(x) (x)=(x) - -/* for tests, flag to tell gpg not to use blocking randomness */ -#define GNUPG_QUICK_RANDOM "--quick-random" - -/* Avoid a bunch of #ifs */ -#ifndef O_BINARY -# define O_BINARY 0 -#endif diff --git a/openpgpsdk/src/openpgpsdk/create.c b/openpgpsdk/src/openpgpsdk/create.c deleted file mode 100644 index b4fe548a7..000000000 --- a/openpgpsdk/src/openpgpsdk/create.c +++ /dev/null @@ -1,1396 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include - -#include -#include -#include -#include -#include -#include -#include "keyring_local.h" -#include -#include -#include -#include -#include -#include -#ifndef WIN32 -#include -#endif -#include - -#include -#include - -static int debug=0; - -/** - * \ingroup Core_Create - * \param length - * \param type - * \param info - * \return ops_true if OK, otherwise ops_false - */ - -ops_boolean_t ops_write_ss_header(unsigned length,ops_content_tag_t type, - ops_create_info_t *info) - { - return ops_write_length(length,info) - && ops_write_scalar(type-OPS_PTAG_SIGNATURE_SUBPACKET_BASE,1,info); - } - -/* XXX: the general idea of _fast_ is that it doesn't copy stuff - * the safe (i.e. non _fast_) version will, and so will also need to - * be freed. */ - -/** - * \ingroup Core_Create - * - * ops_fast_create_user_id() sets id->user_id to the given user_id. - * This is fast because it is only copying a char*. However, if user_id - * is changed or freed in the future, this could have injurious results. - * \param id - * \param user_id - */ - -void ops_fast_create_user_id(ops_user_id_t *id,unsigned char *user_id) - { - id->user_id=user_id; - } - -/** - * \ingroup Core_WritePackets - * \brief Writes a User Id packet - * \param id - * \param info - * \return ops_true if OK, otherwise ops_false - */ -ops_boolean_t ops_write_struct_user_id(ops_user_id_t *id, - ops_create_info_t *info) - { - return ops_write_ptag(OPS_PTAG_CT_USER_ID,info) - && ops_write_length(strlen((char *)id->user_id),info) - && ops_write(id->user_id,strlen((char *)id->user_id),info); - } - -/** - * \ingroup Core_WritePackets - * \brief Write a User Id packet. - * \param user_id - * \param info - * - * \return return value from ops_write_struct_user_id() - */ -ops_boolean_t ops_write_user_id(const unsigned char *user_id, - ops_create_info_t *info) - { - ops_user_id_t id; - - id.user_id=(unsigned char *)user_id; - return ops_write_struct_user_id(&id,info); - } - -/** -\ingroup Core_MPI -*/ -static unsigned mpi_length(const BIGNUM *bn) -{ - return 2+(BN_num_bits(bn)+7)/8; -} - -static unsigned public_key_length(const ops_public_key_t *key) -{ - switch(key->algorithm) - { - case OPS_PKA_RSA: return mpi_length(key->key.rsa.n) - +mpi_length(key->key.rsa.e); - - case OPS_PKA_DSA: return mpi_length(key->key.dsa.p) - +mpi_length(key->key.dsa.q) - +mpi_length(key->key.dsa.g) - +mpi_length(key->key.dsa.y); - case OPS_PKA_ELGAMAL: - return mpi_length(key->key.elgamal.p) - +mpi_length(key->key.elgamal.g) - +mpi_length(key->key.elgamal.y) ; - - default: - fprintf(stderr,"Bad algorithm type in key: %d\n",key->algorithm) ; - assert(!"unknown key algorithm"); - } - /* not reached */ - return 0; -} - -static unsigned secret_key_length(const ops_secret_key_t *key) -{ - int l; - - switch(key->public_key.algorithm) - { - case OPS_PKA_RSA: l=mpi_length(key->key.rsa.d) - +mpi_length(key->key.rsa.p) - +mpi_length(key->key.rsa.q) - +mpi_length(key->key.rsa.u); - break ; - - case OPS_PKA_DSA: l=mpi_length(key->key.dsa.x); - break; - - default: - assert(!"unknown key algorithm"); - } - - return l+public_key_length(&key->public_key); -} - -/** - * \ingroup Core_Create - * \param key - * \param time - * \param n - * \param e -*/ -void ops_fast_create_rsa_public_key(ops_public_key_t *key,time_t time, - BIGNUM *n,BIGNUM *e) - { - key->version=4; - key->creation_time=time; - key->algorithm=OPS_PKA_RSA; - key->key.rsa.n=n; - key->key.rsa.e=e; - } - -/* Note that we support v3 keys here because they're needed for - * for verification - the writer doesn't allow them, though */ -static ops_boolean_t write_public_key_body(const ops_public_key_t *key, - ops_create_info_t *info) -{ - if(!(ops_write_scalar(key->version,1,info) && ops_write_scalar(key->creation_time,4,info))) - return ops_false; - - if(key->version != 4 && !ops_write_scalar(key->days_valid,2,info)) - return ops_false; - - if(!ops_write_scalar(key->algorithm,1,info)) - return ops_false; - - switch(key->algorithm) - { - case OPS_PKA_DSA: - return ops_write_mpi(key->key.dsa.p,info) - && ops_write_mpi(key->key.dsa.q,info) - && ops_write_mpi(key->key.dsa.g,info) - && ops_write_mpi(key->key.dsa.y,info); - - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: - return ops_write_mpi(key->key.rsa.n,info) - && ops_write_mpi(key->key.rsa.e,info); - - case OPS_PKA_ELGAMAL: - return ops_write_mpi(key->key.elgamal.p,info) - && ops_write_mpi(key->key.elgamal.g,info) - && ops_write_mpi(key->key.elgamal.y,info); - - default: - fprintf(stderr, "Unknown algorithm %d\n", key->algorithm); - assert(0); - break; - } - - /* not reached */ - return ops_false; -} - -/* Note that we support v3 keys here because they're needed for - * for verification - the writer doesn't allow them, though */ -static ops_boolean_t write_secret_key_body(const ops_secret_key_t *key, - const unsigned char* passphrase, - const size_t pplen, - ops_create_info_t *info) -{ - /* RFC4880 Section 5.5.3 Secret-Key Packet Formats */ - - ops_crypt_t crypt; - ops_hash_t hash; - unsigned char hashed[OPS_SHA1_HASH_SIZE]; - unsigned char session_key[CAST_KEY_LENGTH]; - unsigned int done=0; - unsigned int i=0; - - if(!write_public_key_body(&key->public_key,info)) - return ops_false; - - assert(key->s2k_usage==OPS_S2KU_ENCRYPTED_AND_HASHED); /* = 254 */ - if(!ops_write_scalar(key->s2k_usage,1,info)) - return ops_false; - - assert(key->algorithm==OPS_SA_CAST5); - if (!ops_write_scalar(key->algorithm,1,info)) - return ops_false; - - assert(key->s2k_specifier==OPS_S2KS_SIMPLE - || key->s2k_specifier==OPS_S2KS_SALTED); // = 1 \todo could also be iterated-and-salted - if (!ops_write_scalar(key->s2k_specifier,1,info)) - return ops_false; - - assert(key->hash_algorithm==OPS_HASH_SHA1); - if (!ops_write_scalar(key->hash_algorithm,1,info)) - return ops_false; - - switch(key->s2k_specifier) - { - case OPS_S2KS_SIMPLE: - // nothing more to do - break; - - case OPS_S2KS_SALTED: - // 8-octet salt value - ops_random((void *)&key->salt[0],OPS_SALT_SIZE); - if (!ops_write(key->salt, OPS_SALT_SIZE, info)) - return ops_false; - break; - - /* \todo - case OPS_S2KS_ITERATED_AND_SALTED: - // 8-octet salt value - // 1-octet count - break; - */ - - default: - fprintf(stderr,"invalid/unsupported s2k specifier %d\n", - key->s2k_specifier); - assert(0); - } - - if (!ops_write(&key->iv[0],ops_block_size(key->algorithm),info)) - return ops_false; - - /* create the session key for encrypting the algorithm-specific fields */ - - switch(key->s2k_specifier) - { - case OPS_S2KS_SIMPLE: - case OPS_S2KS_SALTED: - // RFC4880: section 3.7.1.1 and 3.7.1.2 - - done=0; - for (i=0; donehash_algorithm); - hash.init(&hash); - - // preload if iterating - for (j=0; js2k_specifier==OPS_S2KS_SALTED) - { hash.add(&hash, key->salt, OPS_SALT_SIZE); } - - hash.add(&hash, passphrase, pplen); - hash.finish(&hash, hashed); - - // if more in hash than is needed by session key, use the - // leftmost octets - memcpy(session_key+(i*SHA_DIGEST_LENGTH), hashed, use); - done += use; - assert(done<=CAST_KEY_LENGTH); - } - - break; - - /* \todo - case OPS_S2KS_ITERATED_AND_SALTED: - // 8-octet salt value - // 1-octet count - break; - */ - - default: - fprintf(stderr,"invalid/unsupported s2k specifier %d\n", - key->s2k_specifier); - assert(0); - } - - /* use this session key to encrypt */ - - ops_crypt_any(&crypt,key->algorithm); - crypt.set_iv(&crypt, key->iv); - crypt.set_key(&crypt, session_key); - ops_encrypt_init(&crypt); - - if (debug) - { - unsigned int i=0; - fprintf(stderr,"\nWRITING:\niv="); - for (i=0; ialgorithm); i++) - { - fprintf(stderr, "%02x ", key->iv[i]); - } - fprintf(stderr,"\n"); - - fprintf(stderr,"key="); - for (i=0; ipublic_key.algorithm) - { - case OPS_PKA_DSA: - return ops_write_mpi(key->key.dsa.x,info); - - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: - - if(!ops_write_mpi(key->key.rsa.d,info) - || !ops_write_mpi(key->key.rsa.p,info) - || !ops_write_mpi(key->key.rsa.q,info) - || !ops_write_mpi(key->key.rsa.u,info)) - { - if (debug) - { fprintf(stderr,"4 x mpi not written - problem\n"); } - return ops_false; - } - - break; - - // case OPS_PKA_ELGAMAL: - // return ops_write_mpi(key->key.elgamal.x,info); - - default: - assert(0); - break; - } - - if(!ops_write(key->checkhash, OPS_CHECKHASH_SIZE, info)) - return ops_false; - - ops_writer_pop(info); - - free(crypt.encrypt_key) ; - free(crypt.decrypt_key) ; - - return ops_true; -} - - -/** - \ingroup HighLevel_KeyWrite - - \brief Writes a transferable PGP public key to the given output stream. - - \param keydata Key to be written - \param armoured Flag is set for armoured output - \param info Output stream - - Example code: - \code - void example(const ops_keydata_t* keydata) - { - ops_boolean_t armoured=ops_true; - char* filename="/tmp/testkey.asc"; - - int fd; - ops_boolean_t overwrite=ops_true; - ops_create_info_t* cinfo; - - fd=ops_setup_file_write(&cinfo, filename, overwrite); - ops_write_transferable_public_key(keydata,armoured,cinfo); - ops_teardown_file_write(cinfo,fd); - } - \endcode -*/ - -ops_boolean_t ops_write_transferable_public_key(const ops_keydata_t *keydata, - ops_boolean_t armoured, - ops_create_info_t *info) -{ - ops_boolean_t rtn; - unsigned int i=0,j=0; - - if (armoured) - { ops_writer_push_armoured(info, OPS_PGP_PUBLIC_KEY_BLOCK); } - - // public key - rtn=ops_write_struct_public_key(&keydata->key.skey.public_key,info); - if (rtn!=ops_true) - return rtn; - - // TODO: revocation signatures go here - - // user ids and corresponding signatures - for (i=0; inuids; i++) - { - ops_user_id_t* uid=&keydata->uids[i]; - - rtn=ops_write_struct_user_id(uid, info); - - if (!rtn) - return rtn; - - // find signature for this packet if it exists - for (j=0; jnsigs; j++) - { - sigpacket_t* sig=&keydata->sigs[i]; - if (!strcmp((char *)sig->userid->user_id, (char *)uid->user_id)) - { - rtn=ops_write(sig->packet->raw, sig->packet->length, info); - if (!rtn) - return !rtn; - } - } - } - - // TODO: user attributes and corresponding signatures - - // subkey packets and corresponding signatures and optional revocation - - if (armoured) - { - writer_info_finalise(&info->errors, &info->winfo); - ops_writer_pop(info); - } - - return rtn; -} - -ops_boolean_t ops_write_transferable_public_key_from_packet_data(const ops_keydata_t *keydata, - ops_boolean_t armoured, - ops_create_info_t *info) -{ - ops_boolean_t rtn = ops_true; - unsigned int i=0; - - if (armoured) - { ops_writer_push_armoured(info, OPS_PGP_PUBLIC_KEY_BLOCK); } - - for(i=0;inpackets;++i) - if(!ops_write(keydata->packets[i].raw, keydata->packets[i].length, info)) - return ops_false ; - - if (armoured) - { - writer_info_finalise(&info->errors, &info->winfo); - ops_writer_pop(info); - } - - return rtn; -} - -ops_boolean_t ops_write_transferable_secret_key_from_packet_data(const ops_keydata_t *keydata, - ops_boolean_t armoured, - ops_create_info_t *info) -{ - ops_boolean_t rtn = ops_true; - unsigned int i=0; - - if(keydata->type != OPS_PTAG_CT_ENCRYPTED_SECRET_KEY) - { - fprintf(stderr,"Can only output encrypted secret keys from raw packet data. Current type is %d\n",keydata->type) ; - return ops_false ; - } - if (armoured) - { ops_writer_push_armoured(info, OPS_PGP_PRIVATE_KEY_BLOCK); } - - for(i=0;inpackets;++i) - if(!ops_write(keydata->packets[i].raw, keydata->packets[i].length, info)) - return ops_false ; - - if (armoured) - { - writer_info_finalise(&info->errors, &info->winfo); - ops_writer_pop(info); - } - - return rtn; -} -/** - \ingroup HighLevel_KeyWrite - - \brief Writes a transferable PGP secret key to the given output stream. - - \param keydata Key to be written - \param passphrase - \param pplen - \param armoured Flag is set for armoured output - \param info Output stream - - Example code: - \code - void example(const ops_keydata_t* keydata) - { - const unsigned char* passphrase=NULL; - const size_t passphraselen=0; - ops_boolean_t armoured=ops_true; - - int fd; - char* filename="/tmp/testkey.asc"; - ops_boolean_t overwrite=ops_true; - ops_create_info_t* cinfo; - - fd=ops_setup_file_write(&cinfo, filename, overwrite); - ops_write_transferable_secret_key(keydata,passphrase,pplen,armoured,cinfo); - ops_teardown_file_write(cinfo,fd); - } - \endcode -*/ - -ops_boolean_t ops_write_transferable_secret_key(const ops_keydata_t *keydata, const unsigned char* passphrase, const size_t pplen, ops_boolean_t armoured, ops_create_info_t *info) - { - ops_boolean_t rtn; - unsigned int i=0,j=0; - - if (armoured) - { ops_writer_push_armoured(info,OPS_PGP_PRIVATE_KEY_BLOCK); } - - // public key - rtn=ops_write_struct_secret_key(&keydata->key.skey,passphrase,pplen,info); - if (rtn!=ops_true) - return rtn; - - // TODO: revocation signatures go here - - // user ids and corresponding signatures - for (i=0; inuids; i++) - { - ops_user_id_t* uid=&keydata->uids[i]; - - rtn=ops_write_struct_user_id(uid, info); - - if (!rtn) - return rtn; - - // find signature for this packet if it exists - for (j=0; jnsigs; j++) - { - sigpacket_t* sig=&keydata->sigs[i]; - if (!strcmp((char *)sig->userid->user_id, (char *)uid->user_id)) - { - rtn=ops_write(sig->packet->raw, sig->packet->length, info); - if (!rtn) - return !rtn; - } - } - } - - // TODO: user attributes and corresponding signatures - - // subkey packets and corresponding signatures and optional revocation - - if (armoured) - { - writer_info_finalise(&info->errors, &info->winfo); - ops_writer_pop(info); - } - - return rtn; - } - -/** - * \ingroup Core_WritePackets - * \brief Writes a Public Key packet - * \param key - * \param info - * \return ops_true if OK, otherwise ops_false - */ -ops_boolean_t ops_write_struct_public_key(const ops_public_key_t *key, - ops_create_info_t *info) -{ - assert(key->version == 4); - - if(key->algorithm != OPS_PKA_RSA) - { - fprintf(stderr,"\nUnhandled key algorithm %d\n",key->algorithm); - return ops_false ; - } - - return ops_write_ptag(OPS_PTAG_CT_PUBLIC_KEY,info) - && ops_write_length(1+4+1+public_key_length(key),info) - && write_public_key_body(key,info); -} - -/** - * \ingroup Core_WritePackets - * \brief Writes one RSA public key packet. - * \param time Creation time - * \param n RSA public modulus - * \param e RSA public encryption exponent - * \param info Writer settings - * - * \return ops_true if OK, otherwise ops_false - */ - -ops_boolean_t ops_write_rsa_public_key(time_t time,const BIGNUM *n, - const BIGNUM *e, - ops_create_info_t *info) - { - ops_public_key_t key; - - ops_fast_create_rsa_public_key(&key,time,DECONST(BIGNUM,n), - DECONST(BIGNUM,e)); - return ops_write_struct_public_key(&key,info); - } - -/** - * \ingroup Core_Create - * \param out - * \param key - * \param make_packet - */ - -void ops_build_public_key(ops_memory_t *out,const ops_public_key_t *key, - ops_boolean_t make_packet) - { - ops_create_info_t *info; - - info=ops_create_info_new(); - - ops_memory_init(out,128); - ops_writer_set_memory(info,out); - - write_public_key_body(key,info); - - if(make_packet) - ops_memory_make_packet(out,OPS_PTAG_CT_PUBLIC_KEY); - - ops_create_info_delete(info); - } - -/** - * \ingroup Core_Create - * - * Create an RSA secret key structure. If a parameter is marked as - * [OPTIONAL], then it can be omitted and will be calculated from - * other parameters - or, in the case of e, will default to 0x10001. - * - * Parameters are _not_ copied, so will be freed if the structure is - * freed. - * - * \param key The key structure to be initialised. - * \param time - * \param d The RSA parameter d (=e^-1 mod (p-1)(q-1)) [OPTIONAL] - * \param p The RSA parameter p - * \param q The RSA parameter q (q > p) - * \param u The RSA parameter u (=p^-1 mod q) [OPTIONAL] - * \param n The RSA public parameter n (=p*q) [OPTIONAL] - * \param e The RSA public parameter e */ - -void ops_fast_create_rsa_secret_key(ops_secret_key_t *key,time_t time, - BIGNUM *d,BIGNUM *p,BIGNUM *q,BIGNUM *u, - BIGNUM *n,BIGNUM *e) - { - ops_fast_create_rsa_public_key(&key->public_key,time,n,e); - - // XXX: calculate optionals - key->key.rsa.d=d; - key->key.rsa.p=p; - key->key.rsa.q=q; - key->key.rsa.u=u; - - key->s2k_usage=OPS_S2KU_NONE; - - // XXX: sanity check and add errors... - } - -/** - * \ingroup Core_WritePackets - * \brief Writes a Secret Key packet. - * \param key The secret key - * \param passphrase The passphrase - * \param pplen Length of passphrase - * \param info - * \return ops_true if OK; else ops_false - */ -ops_boolean_t ops_write_struct_secret_key(const ops_secret_key_t *key, - const unsigned char* passphrase, - const size_t pplen, - ops_create_info_t *info) - { - int length=0; - - assert(key->public_key.version == 4); - - // Ref: RFC4880 Section 5.5.3 - - // public_key, excluding MPIs - length += 1+4+1+1; - - // s2k usage - length+=1; - - switch (key->s2k_usage) - { - case OPS_S2KU_NONE: - // nothing to add - break; - - case OPS_S2KU_ENCRYPTED_AND_HASHED: // 254 - case OPS_S2KU_ENCRYPTED: // 255 - - // Ref: RFC4880 Section 3.7 - length+=1; // s2k_specifier - - switch(key->s2k_specifier) - { - case OPS_S2KS_SIMPLE: - length+=1; // hash algorithm - break; - - case OPS_S2KS_SALTED: - length+=1+8; // hash algorithm + salt - break; - - case OPS_S2KS_ITERATED_AND_SALTED: - length+=1+8+1; // hash algorithm, salt + count - break; - - default: - assert(0); - } - break; - - default: - assert(0); - } - - // IV - if (key->s2k_usage != 0) - { - length += ops_block_size(key->algorithm); - } - - // checksum or hash - switch (key->s2k_usage) - { - case 0: - case 255: - length += 2; - break; - - case 254: - length += 20; - break; - - default: - assert(0); - } - - // secret key and public key MPIs - length += secret_key_length(key); - - return ops_write_ptag(OPS_PTAG_CT_SECRET_KEY,info) - // && ops_write_length(1+4+1+1+secret_key_length(key)+2,info) - && ops_write_length(length,info) - && write_secret_key_body(key,passphrase,pplen,info); - } - -/** - * \ingroup InternalAPI - * - * \brief Initialise a temporary info structure that can be used for - * writing to a writer's parent. - * - * This is used by writers who want to use the various ops_write functions - * in order to write to the parent writer. - * Example code: - * \code - * ops_boolean_t writer(const unsigned char *src, - * unsigned length, - * ops_error_t **errors, - * ops_writer_info_t *winfo) { - * ops_create_info_t parent; - * ops_prepare_parent_info(&parent, winfo, errors); - * - * // The ptag will be written to the parent writer - * ops_write_ptag(OPS_PTAG_CT_LITERAL_DATA, &parent); - * - * // The data is written to the parent. This line is - // equivalent to: - * // ops_stacked_write(src, length, errors, winfo); - * ops_boolean_t result = ops_write(src, length, info); - * ops_move_errors(&parent_info, errors); - * return result; - * \endcode - * - * \note It is the responsiblity of the caller to assign space for the parent - * structure, typically on the stack. IOn order to report errors correctly, - * use ops_move_errors() after the write operation. - * - * \see ops_move_errors - */ -void ops_prepare_parent_info(ops_create_info_t *parent_info, - ops_writer_info_t *winfo) - { - parent_info->winfo = *winfo->next; - parent_info->errors = NULL; - } - -/** - * \ingroup Core_Create - * - * \brief Create a new ops_create_info_t structure. - * - * \return the new structure. - * \note It is the responsiblity of the caller to call ops_create_info_delete(). - * \sa ops_create_info_delete() - */ -ops_create_info_t *ops_create_info_new(void) - { return ops_mallocz(sizeof(ops_create_info_t)); } - -/** - * \ingroup Core_Create - * \brief Delete an ops_create_info_t strucut and associated resources. - * - * Delete an ops_create_info_t structure. If a writer is active, then - * that is also deleted. - * - * \param info the structure to be deleted. - */ -void ops_create_info_delete(ops_create_info_t *info) - { - writer_info_delete(&info->winfo); - free(info); - } - -/** - \ingroup Core_Create - \brief Calculate the checksum for a session key - \param session_key Session Key to use - \param cs Checksum to be written - \return ops_true if OK; else ops_false -*/ -ops_boolean_t ops_calc_session_key_checksum(ops_pk_session_key_t *session_key, - unsigned char cs[2]) - { - unsigned int i=0; - unsigned long checksum=0; - - if (!ops_is_sa_supported(session_key->symmetric_algorithm)) - return ops_false; - - for (i=0; isymmetric_algorithm); i++) - { - checksum+=session_key->key[i]; - } - checksum = checksum % 65536; - - cs[0]=checksum >> 8; - cs[1]=checksum & 0xFF; - - return ops_true; - // fprintf(stderr,"\nm buf checksum: "); - // fprintf(stderr," %2x",cs[0]); - // fprintf(stderr," %2x\n",cs[1]); - } - -static ops_boolean_t create_unencoded_m_buf(ops_pk_session_key_t *session_key, - unsigned char *m_buf) - { - int i=0; - // unsigned long checksum=0; - - // m_buf is the buffer which will be encoded in PKCS#1 block - // encoding to form the "m" value used in the - // Public Key Encrypted Session Key Packet - // as defined in RFC Section 5.1 "Public-Key Encrypted Session Key Packet" - - m_buf[0]=session_key->symmetric_algorithm; - - assert(session_key->symmetric_algorithm == OPS_SA_CAST5); - for (i=0; ikey[i]; - } - - return(ops_calc_session_key_checksum(session_key, m_buf+1+CAST_KEY_LENGTH)); - } - -/** -\ingroup Core_Create -\brief implementation of EME-PKCS1-v1_5-ENCODE, as defined in OpenPGP RFC -\param M -\param mLen -\param pkey -\param EM -\return ops_true if OK; else ops_false -*/ -ops_boolean_t encode_m_buf(const unsigned char *M, size_t mLen, - const ops_public_key_t *pkey, - unsigned char* EM -) - { - unsigned int k; - unsigned i; - - // implementation of EME-PKCS1-v1_5-ENCODE, as defined in OpenPGP RFC - - if(pkey->algorithm != OPS_PKA_RSA) - { - fprintf(stderr,"\nUnhandled key algorithm %d\n",pkey->algorithm); - return ops_false ; - } - - k=BN_num_bytes(pkey->key.rsa.n); - assert(mLen <= k-11); - if (mLen > k-11) - { - fprintf(stderr,"message too long\n"); - return ops_false; - } - - // these two bytes defined by RFC - EM[0]=0x00; - EM[1]=0x02; - - // add non-zero random bytes of length k - mLen -3 - for(i=2 ; i < k-mLen-1 ; ++i) - do - ops_random(EM+i, 1); - while(EM[i] == 0); - - assert (i >= 8+2); - - EM[i++]=0; - - memcpy(EM+i, M, mLen); - - - if (debug) - { - unsigned int i=0; - fprintf(stderr,"Encoded Message: \n"); - for (i=0; ikey.rsa.n); - unsigned char* encoded_m_buf = ops_mallocz(sz_encoded_m_buf); - - ops_pk_session_key_t *session_key=ops_mallocz(sizeof *session_key); - - assert(key->type == OPS_PTAG_CT_PUBLIC_KEY); - session_key->version=OPS_PKSK_V3; - memcpy(session_key->key_id, key->key_id, sizeof session_key->key_id); - - if (debug) - { - unsigned int i=0; - fprintf(stderr,"Encrypting for RSA key id : "); - for (i=0; ikey_id; i++) - fprintf(stderr,"%2x ", key->key_id[i]); - fprintf(stderr,"\n"); - } - - assert(key->key.pkey.algorithm == OPS_PKA_RSA); - session_key->algorithm=key->key.pkey.algorithm; - - // \todo allow user to specify other algorithm - session_key->symmetric_algorithm=OPS_SA_CAST5; - ops_random(session_key->key, CAST_KEY_LENGTH); - - if (debug) - { - unsigned int i=0; - fprintf(stderr,"CAST5 session key created (len=%d):\n ", - CAST_KEY_LENGTH); - for (i=0; ikey[i]); - fprintf(stderr,"\n"); - } - - if (create_unencoded_m_buf(session_key, &unencoded_m_buf[0])==ops_false) - { - free(encoded_m_buf); - return NULL; - } - - if (debug) - { - unsigned int i=0; - printf("unencoded m buf:\n"); - for (i=0; iparameters)) - { - free (encoded_m_buf); - return NULL; - } - - free(encoded_m_buf); - return session_key; - } - -/** -\ingroup Core_WritePackets -\brief Writes Public Key Session Key packet -\param info Write settings -\param pksk Public Key Session Key to write out -\return ops_true if OK; else ops_false -*/ -ops_boolean_t ops_write_pk_session_key(ops_create_info_t *info, - ops_pk_session_key_t *pksk) - { - assert(pksk); - assert(pksk->algorithm == OPS_PKA_RSA); - - return ops_write_ptag(OPS_PTAG_CT_PK_SESSION_KEY, info) - && ops_write_length(1 + 8 + 1 - + BN_num_bytes(pksk->parameters.rsa.encrypted_m) - + 2, info) - && ops_write_scalar(pksk->version, 1, info) - && ops_write(pksk->key_id, 8, info) - && ops_write_scalar(pksk->algorithm, 1, info) - && ops_write_mpi(pksk->parameters.rsa.encrypted_m, info) - //?? && ops_write_scalar(0, 2, info); - ; - } - -/** -\ingroup Core_WritePackets -\brief Writes MDC packet -\param hashed Hash for MDC -\param info Write settings -\return ops_true if OK; else ops_false -*/ - -ops_boolean_t ops_write_mdc(const unsigned char *hashed, - ops_create_info_t* info) - { - // write it out - return ops_write_ptag(OPS_PTAG_CT_MDC, info) - && ops_write_length(OPS_SHA1_HASH_SIZE,info) - && ops_write(hashed, OPS_SHA1_HASH_SIZE, info); - } - -/** -\ingroup Core_WritePackets -\brief Writes Literal Data packet from buffer -\param data Buffer to write out -\param maxlen Max length of buffer -\param type Literal Data Type -\param info Write settings -\return ops_true if OK; else ops_false -*/ -ops_boolean_t ops_write_literal_data_from_buf(const unsigned char *data, - const int maxlen, - const ops_literal_data_type_t type, - ops_create_info_t *info) - { - /* - * RFC4880 does not specify a meaning for filename or date. - * It is implementation-dependent. - * We will not implement them. - */ - // \todo do we need to check text data for line endings ? - return ops_write_ptag(OPS_PTAG_CT_LITERAL_DATA, info) - && ops_write_length(1+1+4+maxlen,info) - && ops_write_scalar(type, 1, info) - && ops_write_scalar(0, 1, info) - && ops_write_scalar(0, 4, info) - && ops_write(data, maxlen, info); - } - -/** -\ingroup Core_WritePackets -\brief Writes Literal Data packet from contents of file -\param filename Name of file to read from -\param type Literal Data Type -\param info Write settings -\return ops_true if OK; else ops_false -*/ - -ops_boolean_t -ops_write_literal_data_from_file(const char *filename, - const ops_literal_data_type_t type, - ops_create_info_t *info) - { - size_t initial_size=1024; - int fd=0; - ops_boolean_t rtn; - unsigned char buf[1024]; - ops_memory_t* mem=NULL; - size_t len=0; - - fd=ops_open(filename,O_RDONLY | O_BINARY, 0); - - if (fd < 0) - return ops_false; - - mem=ops_memory_new(); - ops_memory_init(mem,initial_size); - for (;;) - { - ssize_t n=0; - n=read(fd,buf,1024); - if (!n) - break; - if (n == -1) - { - close(fd); - ops_memory_free(mem); - return ops_false; - } - ops_memory_add(mem, &buf[0], n); - } - close(fd); - - // \todo do we need to check text data for line endings ? - len=ops_memory_get_length(mem); - rtn=ops_write_ptag(OPS_PTAG_CT_LITERAL_DATA, info) - && ops_write_length(1+1+4+len,info) - && ops_write_scalar(type, 1, info) - && ops_write_scalar(0, 1, info) // filename - && ops_write_scalar(0, 4, info) // date - && ops_write(ops_memory_get_data(mem), len, info); - - ops_memory_free(mem); - return rtn; - } - -/** - \ingroup HighLevel_General - - \brief Reads contents of file into new ops_memory_t struct. - - \param filename Filename to read from - \param errnum Pointer to error - \return new ops_memory_t pointer containing the contents of the file - - \note If there was an error opening the file or reading from it, - errnum is set to the cause - - \note It is the caller's responsibility to call ops_memory_free(mem) -*/ - -ops_memory_t* ops_write_mem_from_file(const char *filename, int* errnum) - { - size_t initial_size=1024; - int fd=0; - unsigned char buf[1024]; - ops_memory_t* mem=NULL; - - *errnum=0; - - fd=ops_open(filename,O_RDONLY | O_BINARY, 0); - - if (fd < 0) - { - *errnum=errno; - return ops_false; - } - - mem=ops_memory_new(); - ops_memory_init(mem,initial_size); - for (;;) - { - ssize_t n=0; - n=read(fd,buf,1024); - if (n<0) - { - *errnum=errno; - break; - } - if (!n) - break; - ops_memory_add(mem, &buf[0], n); - } - close(fd); - return mem; - } - -/** - \ingroup HighLevel_General - - \brief Reads contents of buffer into file - - \param filename Filename to write to - \param buf Buffer to write to file - \param len Size of buffer - \param overwrite Flag to set whether to overwrite an existing file - \return 1 if OK; 0 if error -*/ - -int ops_write_file_from_buf(const char *filename, const char* buf, - const size_t len, const ops_boolean_t overwrite) - { - int fd=0; - size_t n=0; - int flags=0; - - flags=O_WRONLY | O_CREAT; - if (overwrite==ops_true) - flags |= O_TRUNC; - else - flags |= O_EXCL; - - flags |= O_BINARY; - - fd=ops_open(filename,flags, 0600); - if (fd < 0) - { - perror(NULL); - return 0; - } - - n=write(fd,buf,len); - if (n!=len) - return 0; - - if(!close(fd)) - return 1; - - return 0; - } - -/** -\ingroup Core_WritePackets -\brief Write Symmetrically Encrypted packet -\param data Data to encrypt -\param len Length of data -\param info Write settings -\return ops_true if OK; else ops_false -\note Hard-coded to use AES256 -*/ -ops_boolean_t ops_write_symmetrically_encrypted_data(const unsigned char *data, - const int len, - ops_create_info_t *info) - { - int done=0; - ops_crypt_t crypt_info; - int encrypted_sz=0;// size of encrypted data - unsigned char *encrypted=NULL; // buffer to write encrypted data to - - // \todo assume AES256 for now - ops_crypt_any(&crypt_info, OPS_SA_AES_256); - ops_encrypt_init(&crypt_info); - - encrypted_sz=len+crypt_info.blocksize+2; - encrypted=ops_mallocz(encrypted_sz); - - done=ops_encrypt_se(&crypt_info, encrypted, data, len); - assert(done==len); - // printf("len=%d, done: %d\n", len, done); - - return ops_write_ptag(OPS_PTAG_CT_SE_DATA, info) - && ops_write_length(1+encrypted_sz,info) - && ops_write(data, len, info); - } - -/** -\ingroup Core_WritePackets -\brief Write a One Pass Signature packet -\param skey Secret Key to use -\param hash_alg Hash Algorithm to use -\param sig_type Signature type -\param info Write settings -\return ops_true if OK; else ops_false -*/ -ops_boolean_t ops_write_one_pass_sig(const ops_secret_key_t* skey, - const ops_hash_algorithm_t hash_alg, - const ops_sig_type_t sig_type, - ops_create_info_t* info) - { - unsigned char keyid[OPS_KEY_ID_SIZE]; - if (debug) - fprintf(stderr, "calling ops_keyid in write_one_pass_sig: " - "this calls sha1_init\n"); - ops_keyid(keyid,&skey->public_key); - - return ops_write_ptag(OPS_PTAG_CT_ONE_PASS_SIGNATURE, info) - && ops_write_length(1+1+1+1+8+1, info) - && ops_write_scalar (3, 1, info) // version - && ops_write_scalar (sig_type, 1, info) - && ops_write_scalar (hash_alg, 1, info) - && ops_write_scalar (skey->public_key.algorithm, 1, info) - && ops_write(keyid, 8, info) - && ops_write_scalar (1, 1, info); - } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/create.h b/openpgpsdk/src/openpgpsdk/create.h deleted file mode 100644 index aaeec0d51..000000000 --- a/openpgpsdk/src/openpgpsdk/create.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_CREATE_H -#define OPS_CREATE_H - -#include -#include -#include -#include -#include -#include -#include - -/** - * \ingroup Create - * This struct contains the required information about how to write this stream - */ -struct ops_create_info - { - ops_writer_info_t winfo; - ops_error_t *errors; /*!< an error stack */ - }; - -void ops_prepare_parent_info(ops_create_info_t *parent_info, - ops_writer_info_t *winfo); -ops_create_info_t *ops_create_info_new(void); -void ops_create_info_delete(ops_create_info_t *info); - -ops_memory_t* ops_write_mem_from_file(const char *filename, int* errnum); -int ops_write_file_from_buf(const char *filename, const char* buf, const size_t len, const ops_boolean_t overwrite); - -ops_boolean_t ops_calc_session_key_checksum(ops_pk_session_key_t *session_key, unsigned char *cs); -void ops_build_public_key(ops_memory_t *out,const ops_public_key_t *key, - ops_boolean_t make_packet); -ops_boolean_t ops_write_struct_user_id(ops_user_id_t *id, - ops_create_info_t *info); -ops_boolean_t ops_write_struct_public_key(const ops_public_key_t *key, - ops_create_info_t *info); - -ops_boolean_t ops_write_ss_header(unsigned length,ops_content_tag_t type, - ops_create_info_t *info); -ops_boolean_t ops_write_struct_secret_key(const ops_secret_key_t *key, - const unsigned char* passphrase, - const size_t pplen, - ops_create_info_t *info); -ops_boolean_t ops_write_one_pass_sig(const ops_secret_key_t* skey, - const ops_hash_algorithm_t hash_alg, - const ops_sig_type_t sig_type, - ops_create_info_t* info); -ops_boolean_t ops_write_literal_data_from_buf(const unsigned char *data, - const int maxlen, - const ops_literal_data_type_t type, - ops_create_info_t *info); -ops_pk_session_key_t *ops_create_pk_session_key(const ops_keydata_t *key); -ops_boolean_t ops_write_pk_session_key(ops_create_info_t *info, - ops_pk_session_key_t *pksk); -ops_boolean_t ops_write_transferable_public_key(const ops_keydata_t *key, ops_boolean_t armoured, ops_create_info_t *info); -ops_boolean_t ops_write_transferable_secret_key(const ops_keydata_t *key, const unsigned char* passphrase, const size_t pplen, ops_boolean_t armoured, ops_create_info_t *info); -ops_boolean_t ops_write_transferable_public_key_from_packet_data(const ops_keydata_t *keydata, ops_boolean_t armoured, ops_create_info_t *info); -ops_boolean_t ops_write_transferable_secret_key_from_packet_data(const ops_keydata_t *keydata, ops_boolean_t armoured, ops_create_info_t *info); - - -#endif /*OPS_CREATE_H*/ - -// eof diff --git a/openpgpsdk/src/openpgpsdk/crypto.c b/openpgpsdk/src/openpgpsdk/crypto.c deleted file mode 100644 index 86acebaca..000000000 --- a/openpgpsdk/src/openpgpsdk/crypto.c +++ /dev/null @@ -1,558 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include -#include "parse_local.h" - -#include -#include -#include - -#include -#include - -/** -\ingroup Core_MPI -\brief Decrypt and unencode MPI -\param buf Buffer in which to write decrypted unencoded MPI -\param buflen Length of buffer -\param encmpi -\param skey -\return length of MPI -\note only RSA at present -*/ -int ops_decrypt_and_unencode_mpi(unsigned char *buf, unsigned buflen, - const BIGNUM *encmpi, - const ops_secret_key_t *skey) - { - unsigned char encmpibuf[8192]; - unsigned char mpibuf[8192]; - unsigned mpisize; - int n; - int i; - - mpisize=BN_num_bytes(encmpi); - /* MPI can't be more than 65,536 */ - - if(!(mpisize <= sizeof encmpibuf)) // ASSERT(mpisize <= sizeof encmpibuf); - { - fprintf(stderr,"ops_decrypt_and_unencode_mpi: number size too large (%d bytes!).\n",mpisize) ; - return -1 ; - } - - BN_bn2bin(encmpi, encmpibuf); - - if(!(skey->public_key.algorithm == OPS_PKA_RSA)) // ASSERT(skey->public_key.algorithm == OPS_PKA_RSA); - { - fprintf(stderr,"ops_decrypt_and_unencode_mpi: encryption algorithm %02x is not supported. Sorry.\n",skey->public_key.algorithm) ; - return -1 ; - } - - /* - fprintf(stderr,"\nDECRYPTING\n"); - fprintf(stderr,"encrypted data : "); - for (i=0; i<16; i++) - fprintf(stderr,"%2x ", encmpibuf[i]); - fprintf(stderr,"\n"); - */ - - n=ops_rsa_private_decrypt(mpibuf, encmpibuf, (BN_num_bits(encmpi)+7)/8, - &skey->key.rsa, &skey->public_key.key.rsa); - -// if(n == -1) // assert(n != -1); -// return ops_false ; - - /* - fprintf(stderr,"decrypted encoded m buf : "); - for (i=0; i<16; i++) - fprintf(stderr,"%2x ", mpibuf[i]); - fprintf(stderr,"\n"); - */ - - if(n <= 0) - return -1; - - /* - printf(" decrypted=%d ",n); - hexdump(mpibuf,n); - printf("\n"); - */ - - // Decode EME-PKCS1_V1_5 (RFC 2437). - - if(mpibuf[0] != 0 || mpibuf[1] != 2) - return ops_false; - - // Skip the random bytes. - for(i=2 ; i < n && mpibuf[i] ; ++i) - ; - - if(i == n || i < 10) - return ops_false; - - // Skip the zero - ++i; - - // this is the unencoded m buf - if((unsigned)(n-i) <= buflen) - memcpy(buf, mpibuf+i, n-i); - - /* - printf("decoded m buf:\n"); - int j; - for (j=0; jkey.rsa.n))) // ASSERT(sz_encoded_m_buf==(size_t) BN_num_bytes(pkey->key.rsa.n)); - return ops_false ; - - unsigned char encmpibuf[8192]; - int n=0; - - n=ops_rsa_public_encrypt(encmpibuf, encoded_m_buf, sz_encoded_m_buf, &pkey->key.rsa); - - //if(!(n!=-1)) // ASSERT(n!=-1); - // return ops_false ; - - if(n <= 0) - return ops_false; - - skp->rsa.encrypted_m=BN_bin2bn(encmpibuf, n, NULL); - - /* - fprintf(stderr,"encrypted mpi buf : "); - int i; - for (i=0; i<16; i++) - fprintf(stderr,"%2x ", encmpibuf[i]); - fprintf(stderr,"\n"); - */ - - return ops_true; -} - -#define MAXBUF 1024 - -static ops_parse_cb_return_t -callback_write_parsed(const ops_parser_content_t *content_, - ops_parse_cb_info_t *cbinfo); - -/** -\ingroup HighLevel_Crypto -Encrypt a file -\param input_filename Name of file to be encrypted -\param output_filename Name of file to write to. If NULL, name is constructed from input_filename -\param pub_key Public Key to encrypt file for -\param use_armour Write armoured text, if set -\param allow_overwrite Allow output file to be overwrwritten if it exists -\return ops_true if OK; else ops_false -*/ -ops_boolean_t ops_encrypt_file(const char* input_filename, - const char* output_filename, - const ops_keydata_t *pub_key, - const ops_boolean_t use_armour, - const ops_boolean_t allow_overwrite) - { - int fd_in=0; - int fd_out=0; - - ops_create_info_t *cinfo; -#ifdef WIN32 - fd_in=ops_open(input_filename, O_RDONLY | O_BINARY, 0); -#else - fd_in=ops_open(input_filename, O_RDONLY, 0); -#endif - if(fd_in < 0) - { - perror(input_filename); - return ops_false; - } - - fd_out=ops_setup_file_write(&cinfo, output_filename, allow_overwrite); - if (fd_out < 0) - return ops_false; - - // set armoured/not armoured here - if (use_armour) - ops_writer_push_armoured_message(cinfo); - - // Push the encrypted writer - ops_writer_push_stream_encrypt_se_ip(cinfo, pub_key); - ops_writer_push_literal(cinfo); - - // Do the writing - - unsigned buffer[10240]; - for (;;) - { - int n=0; - - n=read(fd_in, buffer, sizeof buffer); - if (!n) - break; - - if(n < 0) - return ops_false ; - - // FIXME: apparently writing can't fail. - ops_write(buffer, n, cinfo); - } - - - // tidy up - close(fd_in); - ops_teardown_file_write(cinfo, fd_out); - - return ops_true; - } - -/** - \ingroup HighLevel_Crypto - Encrypt a compressed, signed stream. - \param cinfo the structure describing where the output will be written. - \param public_key the key used to encrypt the data - \param secret_key the key used to sign the data. If NULL, the data - will not be signed - \param compress If true, compress the stream before encrypting - \param use_armour Write armoured text, if set - \see ops_setup_file_write - - Example Code: - \code - const char* filename = "armour_nocompress_sign.asc"; - ops_create_info_t *info; - int fd = ops_setup_file_write(&info, filename, ops_true); - if (fd < 0) { - fprintf(stderr, "Cannot write to %s\n", filename); - return -1; - } - ops_encrypt_stream(info, public_key, secret_key, ops_false, ops_true); - ops_write(cleartext, strlen(cleartext), info); - ops_writer_close(info); - ops_create_info_delete(info); - \endcode -*/ -extern ops_boolean_t ops_encrypt_stream(ops_create_info_t* cinfo, - const ops_keydata_t* public_key, - const ops_secret_key_t* secret_key, - const ops_boolean_t compress, - const ops_boolean_t use_armour) -{ - if (use_armour) - ops_writer_push_armoured_message(cinfo); - - ops_writer_push_stream_encrypt_se_ip(cinfo, public_key); - - if(compress) - if(!ops_writer_push_compressed(cinfo)) - return ops_false ; - - if (secret_key != NULL) - ops_writer_push_signed(cinfo, OPS_SIG_BINARY, secret_key); - else - ops_writer_push_literal(cinfo); - - return ops_true ; -} - -/** - \ingroup HighLevel_Crypto - \brief Decrypt a chunk of memory, containing a encrypted stream. - \param input_filename Name of file to be decrypted - \param output_filename Name of file to write to. If NULL, the filename is constructed from the input filename, following GPG conventions. - \param keyring Keyring to use - \param use_armour Expect armoured text, if set - \param allow_overwrite Allow output file to overwritten, if set. - \param cb_get_passphrase Callback to use to get passphrase -*/ - -ops_boolean_t ops_decrypt_memory(const unsigned char *encrypted_memory,int em_length, - unsigned char **decrypted_memory,int *out_length, - ops_keyring_t* keyring, - const ops_boolean_t use_armour, - ops_parse_cb_t* cb_get_passphrase) -{ - ops_parse_info_t *pinfo=NULL; - - // setup for reading from given input file - - ops_memory_t *input_mem = ops_memory_new() ; - ops_memory_add(input_mem,encrypted_memory,em_length) ; - - ops_setup_memory_read(&pinfo, input_mem, NULL, callback_write_parsed, ops_false); - - if (pinfo == NULL) - { - perror("cannot create memory read"); - return ops_false; - } - - // setup memory chunk - - ops_memory_t *output_mem; - - ops_setup_memory_write(&pinfo->cbinfo.cinfo, &output_mem,0) ; - - if (output_mem == NULL) - { - perror("Cannot create output memory"); - ops_teardown_memory_read(pinfo, input_mem); - return ops_false; - } - - // \todo check for suffix matching armour param - - // setup keyring and passphrase callback - pinfo->cbinfo.cryptinfo.keyring=keyring; - pinfo->cbinfo.cryptinfo.cb_get_passphrase=cb_get_passphrase; - - // Set up armour/passphrase options - - if (use_armour) - ops_reader_push_dearmour(pinfo); - - // Do it - - ops_boolean_t res = ops_parse_and_print_errors(pinfo); - - // Unsetup - - if (use_armour) - ops_reader_pop_dearmour(pinfo); - - // copy output memory to supplied buffer. - // - *out_length = ops_memory_get_length(output_mem) ; - *decrypted_memory = ops_mallocz(*out_length) ; - memcpy(*decrypted_memory,ops_memory_get_data(output_mem),*out_length) ; - - ops_teardown_memory_write(pinfo->cbinfo.cinfo, output_mem); - ops_teardown_memory_read(pinfo, input_mem); - - return res ; -} - -/** - \ingroup HighLevel_Crypto - \brief Decrypt a file. - \param input_filename Name of file to be decrypted - \param output_filename Name of file to write to. If NULL, the filename is constructed from the input filename, following GPG conventions. - \param keyring Keyring to use - \param use_armour Expect armoured text, if set - \param allow_overwrite Allow output file to overwritten, if set. - \param cb_get_passphrase Callback to use to get passphrase -*/ - -ops_boolean_t ops_decrypt_file(const char* input_filename, - const char* output_filename, - ops_keyring_t* keyring, - const ops_boolean_t use_armour, - const ops_boolean_t allow_overwrite, - ops_parse_cb_t* cb_get_passphrase) -{ - int fd_in=0; - int fd_out=0; - char* myfilename=NULL; - - // - ops_parse_info_t *pinfo=NULL; - - // setup for reading from given input file - fd_in=ops_setup_file_read(&pinfo, input_filename, - NULL, - callback_write_parsed, - ops_false); - if (fd_in < 0) - { - perror(input_filename); - return ops_false; - } - - // setup output filename - - if (output_filename) - { - fd_out=ops_setup_file_write(&pinfo->cbinfo.cinfo, output_filename, - allow_overwrite); - - if (fd_out < 0) - { - perror(output_filename); - ops_teardown_file_read(pinfo, fd_in); - return ops_false; - } - } - else - { - int suffixlen=4; - char *defaultsuffix=".decrypted"; - const char *suffix=input_filename+strlen(input_filename)-suffixlen; - if (!strcmp(suffix, ".gpg") || !strcmp(suffix, ".asc")) - { - myfilename=ops_mallocz(strlen(input_filename)-suffixlen+1); - strncpy(myfilename, input_filename, - strlen(input_filename)-suffixlen); - } - else - { - unsigned filenamelen=strlen(input_filename)+strlen(defaultsuffix)+1; - myfilename=ops_mallocz(filenamelen); - snprintf(myfilename, filenamelen, "%s%s", input_filename, - defaultsuffix); - } - - fd_out=ops_setup_file_write(&pinfo->cbinfo.cinfo, myfilename, - allow_overwrite); - - if (fd_out < 0) - { - perror(myfilename); - free(myfilename); - ops_teardown_file_read(pinfo, fd_in); - return ops_false; - } - - free (myfilename); - } - - // \todo check for suffix matching armour param - - // setup for writing decrypted contents to given output file - - // setup keyring and passphrase callback - pinfo->cbinfo.cryptinfo.keyring=keyring; - pinfo->cbinfo.cryptinfo.cb_get_passphrase=cb_get_passphrase; - - // Set up armour/passphrase options - - if (use_armour) - ops_reader_push_dearmour(pinfo); - - // Do it - - ops_boolean_t res = ops_parse_and_print_errors(pinfo); - - // Unsetup - - if (use_armour) - ops_reader_pop_dearmour(pinfo); - - ops_teardown_file_write(pinfo->cbinfo.cinfo, fd_out); - ops_teardown_file_read(pinfo, fd_in); - // \todo cleardown crypt - - return res; -} -static ops_parse_cb_return_t -callback_write_parsed(const ops_parser_content_t *content_, - ops_parse_cb_info_t *cbinfo) -{ - ops_parser_content_union_t* content - =(ops_parser_content_union_t *)&content_->content; - static ops_boolean_t skipping; - // ops_boolean_t write=ops_true; - - OPS_USED(cbinfo); - - // ops_print_packet(content_); - - if(content_->tag != OPS_PTAG_CT_UNARMOURED_TEXT && skipping) - { - puts("...end of skip"); - skipping=ops_false; - } - - switch(content_->tag) - { - case OPS_PTAG_CT_UNARMOURED_TEXT: - printf("OPS_PTAG_CT_UNARMOURED_TEXT\n"); - if(!skipping) - { - puts("Skipping..."); - skipping=ops_true; - } - fwrite(content->unarmoured_text.data, 1, - content->unarmoured_text.length, stdout); - break; - - case OPS_PTAG_CT_PK_SESSION_KEY: - return callback_pk_session_key(content_, cbinfo); - break; - - case OPS_PARSER_CMD_GET_SECRET_KEY: - return callback_cmd_get_secret_key(content_, cbinfo); - break; - - case OPS_PARSER_CMD_GET_SK_PASSPHRASE: - case OPS_PARSER_CMD_GET_SK_PASSPHRASE_PREV_WAS_BAD: - // return callback_cmd_get_secret_key_passphrase(content_,cbinfo); - return cbinfo->cryptinfo.cb_get_passphrase(content_, cbinfo); - break; - - case OPS_PTAG_CT_LITERAL_DATA_BODY: - return callback_literal_data(content_, cbinfo); - break; - - case OPS_PTAG_CT_ARMOUR_HEADER: - case OPS_PTAG_CT_ARMOUR_TRAILER: - case OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY: - case OPS_PTAG_CT_COMPRESSED: - case OPS_PTAG_CT_LITERAL_DATA_HEADER: - case OPS_PTAG_CT_SE_IP_DATA_BODY: - case OPS_PTAG_CT_SE_IP_DATA_HEADER: - case OPS_PTAG_CT_SE_DATA_BODY: - case OPS_PTAG_CT_SE_DATA_HEADER: - - // Ignore these packets - // They're handled in ops_parse_one_packet() - // and nothing else needs to be done - break; - - default: - // return callback_general(content_,cbinfo); - break; - // fprintf(stderr,"Unexpected packet tag=%d (0x%x)\n",content_->tag, - // content_->tag); - } - - return OPS_RELEASE_MEMORY; -} - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/crypto.h b/openpgpsdk/src/openpgpsdk/crypto.h deleted file mode 100644 index 25bffa073..000000000 --- a/openpgpsdk/src/openpgpsdk/crypto.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_CRYPTO_H -#define OPS_CRYPTO_H - -#include "keyring.h" -#include "util.h" -#include "packet.h" -#include "packet-parse.h" -#include -#include -#include - -#if OPENSSL_VERSION_NUMBER < 0x00908030L -# define OPENSSL_NO_CAMELLIA -#endif - -#define OPS_MIN_HASH_SIZE 16 - -typedef void ops_hash_init_t(ops_hash_t *hash); -typedef void ops_hash_add_t(ops_hash_t *hash,const unsigned char *data, - unsigned length); -typedef unsigned ops_hash_finish_t(ops_hash_t *hash,unsigned char *out); - -/** _ops_hash_t */ -struct _ops_hash_t - { - ops_hash_algorithm_t algorithm; - size_t size; - const char *name; - ops_hash_init_t *init; - ops_hash_add_t *add; - ops_hash_finish_t *finish; - void *data; - }; - -typedef void ops_crypt_set_iv_t(ops_crypt_t *crypt, - const unsigned char *iv); -typedef void ops_crypt_set_key_t(ops_crypt_t *crypt, - const unsigned char *key); -typedef void ops_crypt_init_t(ops_crypt_t *crypt); -typedef void ops_crypt_resync_t(ops_crypt_t *crypt); -typedef void ops_crypt_block_encrypt_t(ops_crypt_t *crypt,void *out, - const void *in); -typedef void ops_crypt_block_decrypt_t(ops_crypt_t *crypt,void *out, - const void *in); -typedef void ops_crypt_cfb_encrypt_t(ops_crypt_t *crypt,void *out, - const void *in, size_t count); -typedef void ops_crypt_cfb_decrypt_t(ops_crypt_t *crypt,void *out, - const void *in, size_t count); -typedef void ops_crypt_finish_t(ops_crypt_t *crypt); - -/** _ops_crypt_t */ -struct _ops_crypt_t - { - ops_symmetric_algorithm_t algorithm; - size_t blocksize; - size_t keysize; - ops_crypt_set_iv_t *set_iv; /* Call this before decrypt init! */ - ops_crypt_set_key_t *set_key; /* Call this before init! */ - ops_crypt_init_t *base_init; - ops_crypt_resync_t *decrypt_resync; - // encrypt/decrypt one block - ops_crypt_block_encrypt_t *block_encrypt; - ops_crypt_block_decrypt_t *block_decrypt; - - // Standard CFB encrypt/decrypt (as used by Sym Enc Int Prot packets) - ops_crypt_cfb_encrypt_t *cfb_encrypt; - ops_crypt_cfb_decrypt_t *cfb_decrypt; - - ops_crypt_finish_t *decrypt_finish; - unsigned char iv[OPS_MAX_BLOCK_SIZE]; - unsigned char civ[OPS_MAX_BLOCK_SIZE]; - unsigned char siv[OPS_MAX_BLOCK_SIZE]; /* Needed for weird v3 resync */ - unsigned char key[OPS_MAX_KEY_SIZE]; - size_t num; /* Offset - see openssl _encrypt doco */ - void *encrypt_key; - void *decrypt_key; - }; - -void ops_crypto_init(void); -void ops_crypto_finish(void); -void ops_hash_md5(ops_hash_t *hash); -void ops_hash_sha1(ops_hash_t *hash); -void ops_hash_sha256(ops_hash_t *hash); -void ops_hash_sha512(ops_hash_t *hash); -void ops_hash_sha384(ops_hash_t *hash); -void ops_hash_sha224(ops_hash_t *hash); -void ops_hash_any(ops_hash_t *hash,ops_hash_algorithm_t alg); -ops_hash_algorithm_t ops_hash_algorithm_from_text(const char *hash); -const char *ops_text_from_hash(ops_hash_t *hash); -unsigned ops_hash_size(ops_hash_algorithm_t alg); -unsigned ops_hash(unsigned char *out,ops_hash_algorithm_t alg,const void *in, - size_t length); - -void ops_hash_add_int(ops_hash_t *hash,unsigned n,unsigned length); - -ops_boolean_t ops_dsa_verify(const unsigned char *hash,size_t hash_length, - const ops_dsa_signature_t *sig, - const ops_dsa_public_key_t *dsa); -int ops_rsa_public_decrypt(unsigned char *out,const unsigned char *in, - size_t length,const ops_rsa_public_key_t *rsa); -int ops_rsa_public_encrypt(unsigned char *out,const unsigned char *in, - size_t length,const ops_rsa_public_key_t *rsa); -int ops_rsa_private_encrypt(unsigned char *out,const unsigned char *in, - size_t length,const ops_rsa_secret_key_t *srsa, - const ops_rsa_public_key_t *rsa); -int ops_rsa_private_decrypt(unsigned char *out,const unsigned char *in, - size_t length,const ops_rsa_secret_key_t *srsa, - const ops_rsa_public_key_t *rsa); - -unsigned ops_block_size(ops_symmetric_algorithm_t alg); -unsigned ops_key_size(ops_symmetric_algorithm_t alg); - -int ops_decrypt_data(ops_content_tag_t tag,ops_region_t *region, - ops_parse_info_t *parse_info); - -int ops_crypt_any(ops_crypt_t *decrypt,ops_symmetric_algorithm_t alg); -void ops_decrypt_init(ops_crypt_t *decrypt); -void ops_encrypt_init(ops_crypt_t *encrypt); -size_t ops_decrypt_se(ops_crypt_t *decrypt,void *out,const void *in, - size_t count); -size_t ops_encrypt_se(ops_crypt_t *encrypt,void *out,const void *in, - size_t count); -size_t ops_decrypt_se_ip(ops_crypt_t *decrypt,void *out,const void *in, - size_t count); -size_t ops_encrypt_se_ip(ops_crypt_t *encrypt,void *out,const void *in, - size_t count); -ops_boolean_t ops_is_sa_supported(ops_symmetric_algorithm_t alg); - -void ops_reader_push_decrypt(ops_parse_info_t *pinfo,ops_crypt_t *decrypt, - ops_region_t *region); -void ops_reader_pop_decrypt(ops_parse_info_t *pinfo); - -// Hash everything that's read -void ops_reader_push_hash(ops_parse_info_t *pinfo,ops_hash_t *hash); -void ops_reader_pop_hash(ops_parse_info_t *pinfo); - -int ops_decrypt_and_unencode_mpi(unsigned char *buf,unsigned buflen,const BIGNUM *encmpi, - const ops_secret_key_t *skey); -ops_boolean_t ops_rsa_encrypt_mpi(const unsigned char *buf, const size_t buflen, - const ops_public_key_t *pkey, - ops_pk_session_key_parameters_t *spk); - - -// Encrypt everything that's written -struct ops_key_data; -void ops_writer_push_encrypt(ops_create_info_t *info, - const struct ops_key_data *key); - -ops_boolean_t ops_encrypt_file(const char* input_filename, const char* output_filename, const ops_keydata_t *pub_key, const ops_boolean_t use_armour, const ops_boolean_t allow_overwrite); -ops_boolean_t ops_decrypt_file(const char* input_filename, const char* output_filename, ops_keyring_t *keyring, const ops_boolean_t use_armour, const ops_boolean_t allow_overwrite,ops_parse_cb_t* cb_get_passphrase); -extern ops_boolean_t ops_encrypt_stream(ops_create_info_t* cinfo, const ops_keydata_t* public_key, const ops_secret_key_t* secret_key, const ops_boolean_t compress, const ops_boolean_t use_armour); -ops_boolean_t ops_decrypt_memory(const unsigned char *encrypted_memory,int em_length, unsigned char **decrypted_memory,int *out_length, ops_keyring_t* keyring, const ops_boolean_t use_armour, ops_parse_cb_t* cb_get_passphrase) ; -// Keys -ops_boolean_t ops_rsa_generate_keypair(const int numbits, const unsigned long e, ops_keydata_t* keydata); -ops_keydata_t* ops_rsa_create_selfsigned_keypair(const int numbits, const unsigned long e, ops_user_id_t * userid); - -int ops_dsa_size(const ops_dsa_public_key_t *dsa); -DSA_SIG* ops_dsa_sign(unsigned char* hashbuf, unsigned hashsize, const ops_dsa_secret_key_t *sdsa, const ops_dsa_public_key_t *dsa); -#endif diff --git a/openpgpsdk/src/openpgpsdk/defs.h b/openpgpsdk/src/openpgpsdk/defs.h deleted file mode 100644 index e4f8b48ba..000000000 --- a/openpgpsdk/src/openpgpsdk/defs.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_DEFS_H -#define OPS_DEFS_H - -#define OPS_ARMOURED ops_true -#define OPS_UNARMOURED ops_false - -#define OPS_OVERWRITE_YES ops_true -#define OPS_OVERWRITE_NO ops_false - -#define OPS_ACCUMULATE_YES ops_true -#define OPS_ACCUMULATE_NO ops_false - -#endif /* OPS_DEFS_H */ diff --git a/openpgpsdk/src/openpgpsdk/errors.c b/openpgpsdk/src/openpgpsdk/errors.c deleted file mode 100644 index 2de42341b..000000000 --- a/openpgpsdk/src/openpgpsdk/errors.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - * \brief Error Handling - */ - -#include -#include - -#include -#include -#include -#include - -#ifdef WIN32 -#define vsnprintf _vsnprintf -#endif - -#include -#include - -#define ERRNAME(code) { code, #code } - -static ops_errcode_name_map_t errcode_name_map[] = - { - ERRNAME(OPS_E_OK), - ERRNAME(OPS_E_FAIL), - ERRNAME(OPS_E_SYSTEM_ERROR), - ERRNAME(OPS_E_UNIMPLEMENTED), - - ERRNAME(OPS_E_R), - ERRNAME(OPS_E_R_READ_FAILED), - ERRNAME(OPS_E_R_EARLY_EOF), - ERRNAME(OPS_E_R_BAD_FORMAT), - ERRNAME(OPS_E_R_UNCONSUMED_DATA), - - ERRNAME(OPS_E_W), - ERRNAME(OPS_E_W_WRITE_FAILED), - ERRNAME(OPS_E_W_WRITE_TOO_SHORT), - - ERRNAME(OPS_E_P), - ERRNAME(OPS_E_P_NOT_ENOUGH_DATA), - ERRNAME(OPS_E_P_UNKNOWN_TAG), - ERRNAME(OPS_E_P_PACKET_CONSUMED), - ERRNAME(OPS_E_P_MPI_FORMAT_ERROR), - - ERRNAME(OPS_E_C), - - ERRNAME(OPS_E_V), - ERRNAME(OPS_E_V_BAD_SIGNATURE), - ERRNAME(OPS_E_V_NO_SIGNATURE), - ERRNAME(OPS_E_V_UNKNOWN_SIGNER), - - ERRNAME(OPS_E_ALG), - ERRNAME(OPS_E_ALG_UNSUPPORTED_SYMMETRIC_ALG), - ERRNAME(OPS_E_ALG_UNSUPPORTED_PUBLIC_KEY_ALG), - ERRNAME(OPS_E_ALG_UNSUPPORTED_SIGNATURE_ALG), - ERRNAME(OPS_E_ALG_UNSUPPORTED_HASH_ALG), - - ERRNAME(OPS_E_PROTO), - ERRNAME(OPS_E_PROTO_BAD_SYMMETRIC_DECRYPT), - ERRNAME(OPS_E_PROTO_UNKNOWN_SS), - ERRNAME(OPS_E_PROTO_CRITICAL_SS_IGNORED), - ERRNAME(OPS_E_PROTO_BAD_PUBLIC_KEY_VRSN), - ERRNAME(OPS_E_PROTO_BAD_SIGNATURE_VRSN), - ERRNAME(OPS_E_PROTO_BAD_ONE_PASS_SIG_VRSN), - ERRNAME(OPS_E_PROTO_BAD_PKSK_VRSN), - ERRNAME(OPS_E_PROTO_DECRYPTED_MSG_WRONG_LEN), - ERRNAME(OPS_E_PROTO_BAD_SK_CHECKSUM), - - { 0x00, NULL }, /* this is the end-of-array marker */ - }; - -/** - * \ingroup Core_Errors - * \brief returns error code name - * \param errcode - * \return error code name or "Unknown" - */ -char *ops_errcode(const ops_errcode_t errcode) - { - return(ops_str_from_map((int) errcode, (ops_map_t *) errcode_name_map)); - } - -/** - * \ingroup Core_Errors - * \brief Pushes the given error on the given errorstack - * \param errstack Error stack to use - * \param errcode Code of error to push - * \param sys_errno System errno (used if errcode=OPS_E_SYSTEM_ERROR) - * \param file Source filename where error occurred - * \param line Line in source file where error occurred - * \param fmt Comment - * - */ - -void ops_push_error(ops_error_t **errstack,ops_errcode_t errcode,int sys_errno, - const char *file,int line,const char *fmt,...) - { - // first get the varargs and generate the comment - char *comment; - int maxbuf=128; - va_list args; - ops_error_t *err; - - comment=malloc(maxbuf+1); - assert(comment); - - va_start(args, fmt); - vsnprintf(comment,maxbuf+1,fmt,args); - va_end(args); - - // alloc a new error and add it to the top of the stack - - err=malloc(sizeof(ops_error_t)); - assert(err); - - err->next=*errstack; - *errstack=err; - - // fill in the details - err->errcode=errcode; - err->sys_errno=sys_errno; - err->file=file; - err->line=line; - - err->comment=comment; - } - -/** -\ingroup Core_Errors -\brief print this error -\param err Error to print -*/ -void ops_print_error(ops_error_t *err) - { - printf("%s:%d: ",err->file,err->line); - if(err->errcode==OPS_E_SYSTEM_ERROR) - printf("system error %d returned from %s()\n",err->sys_errno, - err->comment); - else - printf("%s, %s\n",ops_errcode(err->errcode),err->comment); - } - -/** -\ingroup Core_Errors -\brief Print all errors on stack -\param errstack Error stack to print -*/ -void ops_print_errors(ops_error_t *errstack) - { - ops_error_t *err; - - for(err=errstack ; err!=NULL ; err=err->next) - ops_print_error(err); - } - -/** -\ingroup Core_Errors -\brief Return true if given error is present anywhere on stack -\param errstack Error stack to check -\param errcode Error code to look for -\return 1 if found; else 0 -*/ -int ops_has_error(ops_error_t *errstack, ops_errcode_t errcode) - { - ops_error_t *err; - for (err=errstack; err!=NULL; err=err->next) - { - if (err->errcode==errcode) - return 1; - } - return 0; - } - -/** -\ingroup Core_Errors -\brief Frees all errors on stack -\param errstack Error stack to free -*/ -void ops_free_errors(ops_error_t *errstack) -{ - ops_error_t *next; - while(errstack!=NULL) { - next=errstack->next; - free(errstack->comment); - free(errstack); - errstack=next; - } -} - -/** -\ingroup InternalAPI -\brief Moves errors from a create info structure to another error stack. - -The error stack wil be moved from the source structure to the destination -stack. If the destination already has errors defined, the errors will -be appended. -*/ -void ops_move_errors(ops_create_info_t *source, ops_error_t **dest) - { - if (*dest == NULL) - *dest = source->errors; - else - { - ops_error_t *last = *dest; - while(last->next != NULL) - last = last->next; - last->next = source->errors; - } - source->errors = NULL; - } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/errors.h b/openpgpsdk/src/openpgpsdk/errors.h deleted file mode 100644 index 6ff958c2d..000000000 --- a/openpgpsdk/src/openpgpsdk/errors.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_ERRORS -#define OPS_ERRORS - -#include "openpgpsdk/types.h" -#include - -/** error codes */ -// Remember to add names to map in errors.c -typedef enum - { - OPS_E_OK=0x0000, /* no error */ - OPS_E_FAIL=0x0001, /* general error */ - OPS_E_SYSTEM_ERROR=0x0002, /* system error, look at errno for details */ - OPS_E_UNIMPLEMENTED=0x0003, /* feature not yet implemented */ - - /* reader errors */ - OPS_E_R=0x1000, /* general reader error */ - OPS_E_R_READ_FAILED =OPS_E_R+1, - OPS_E_R_EARLY_EOF =OPS_E_R+2, - OPS_E_R_BAD_FORMAT =OPS_E_R+3, // For example, malformed armour - OPS_E_R_UNSUPPORTED =OPS_E_R+4, - OPS_E_R_UNCONSUMED_DATA =OPS_E_R+5, - - /* writer errors */ - OPS_E_W=0x2000, /* general writer error */ - OPS_E_W_WRITE_FAILED = OPS_E_W+1, - OPS_E_W_WRITE_TOO_SHORT = OPS_E_W+2, - - /* parser errors */ - OPS_E_P=0x3000, /* general parser error */ - OPS_E_P_NOT_ENOUGH_DATA =OPS_E_P+1, - OPS_E_P_UNKNOWN_TAG =OPS_E_P+2, - OPS_E_P_PACKET_CONSUMED =OPS_E_P+3, - OPS_E_P_MPI_FORMAT_ERROR =OPS_E_P+4, - OPS_E_P_PACKET_NOT_CONSUMED =OPS_E_P+5, - OPS_E_P_DECOMPRESSION_ERROR =OPS_E_P+6, - OPS_E_P_NO_USERID =OPS_E_P+7, - - /* creator errors */ - OPS_E_C=0x4000, /* general creator error */ - - /* validation errors */ - OPS_E_V=0x5000, /* general validation error */ - OPS_E_V_BAD_SIGNATURE =OPS_E_V+1, - OPS_E_V_NO_SIGNATURE =OPS_E_V+2, - OPS_E_V_UNKNOWN_SIGNER =OPS_E_V+3, - OPS_E_V_BAD_HASH =OPS_E_V+4, - - /* Algorithm support errors */ - OPS_E_ALG=0x6000, /* general algorithm error */ - OPS_E_ALG_UNSUPPORTED_SYMMETRIC_ALG =OPS_E_ALG+1, - OPS_E_ALG_UNSUPPORTED_PUBLIC_KEY_ALG =OPS_E_ALG+2, - OPS_E_ALG_UNSUPPORTED_SIGNATURE_ALG =OPS_E_ALG+3, - OPS_E_ALG_UNSUPPORTED_HASH_ALG =OPS_E_ALG+4, - OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG =OPS_E_ALG+5, - - /* Protocol errors */ - OPS_E_PROTO=0x7000, /* general protocol error */ - OPS_E_PROTO_BAD_SYMMETRIC_DECRYPT =OPS_E_PROTO+2, - OPS_E_PROTO_UNKNOWN_SS =OPS_E_PROTO+3, - OPS_E_PROTO_CRITICAL_SS_IGNORED =OPS_E_PROTO+4, - OPS_E_PROTO_BAD_PUBLIC_KEY_VRSN =OPS_E_PROTO+5, - OPS_E_PROTO_BAD_SIGNATURE_VRSN =OPS_E_PROTO+6, - OPS_E_PROTO_BAD_ONE_PASS_SIG_VRSN =OPS_E_PROTO+7, - OPS_E_PROTO_BAD_PKSK_VRSN =OPS_E_PROTO+8, - OPS_E_PROTO_DECRYPTED_MSG_WRONG_LEN =OPS_E_PROTO+9, - OPS_E_PROTO_BAD_SK_CHECKSUM =OPS_E_PROTO+10, - } ops_errcode_t; - -/** ops_errcode_name_map_t */ -typedef ops_map_t ops_errcode_name_map_t; - -/** one entry in a linked list of errors */ -typedef struct ops_error - { - ops_errcode_t errcode; - int sys_errno; /*!< irrelevent unless errcode == OPS_E_SYSTEM_ERROR */ - char *comment; - const char *file; - int line; - struct ops_error *next; - } ops_error_t; - -char *ops_errcode(const ops_errcode_t errcode); - -void ops_push_error(ops_error_t **errstack,ops_errcode_t errcode,int sys_errno, - const char *file,int line,const char *comment,...); -void ops_print_error(ops_error_t *err); -void ops_print_errors(ops_error_t *errstack); -void ops_free_errors(ops_error_t *errstack); -int ops_has_error(ops_error_t *errstack, ops_errcode_t errcode); -void ops_move_errors(ops_create_info_t *source, ops_error_t **errstack); - -#define OPS_SYSTEM_ERROR_1(err,code,syscall,fmt,arg) do { ops_push_error(err,OPS_E_SYSTEM_ERROR,errno,__FILE__,__LINE__,syscall); ops_push_error(err,code,0,__FILE__,__LINE__,fmt,arg); } while(0) -#define OPS_MEMORY_ERROR(err) {fprintf(stderr, "Memory error\n");} // \todo placeholder for better error handling -#define OPS_ERROR(err,code,fmt) do { ops_push_error(err,code,0,__FILE__,__LINE__,fmt); } while(0) -#define OPS_ERROR_1(err,code,fmt,arg) do { ops_push_error(err,code,0,__FILE__,__LINE__,fmt,arg); } while(0) -#define OPS_ERROR_2(err,code,fmt,arg,arg2) do { ops_push_error(err,code,0,__FILE__,__LINE__,fmt,arg,arg2); } while(0) -#define OPS_ERROR_3(err,code,fmt,arg,arg2,arg3) do { ops_push_error(err,code,0,__FILE__,__LINE__,fmt,arg,arg2,arg3); } while(0) -#define OPS_ERROR_4(err,code,fmt,arg,arg2,arg3,arg4) do { ops_push_error(err,code,0,__FILE__,__LINE__,fmt,arg,arg2,arg3,arg4); } while(0) - -#endif /* OPS_ERRORS */ diff --git a/openpgpsdk/src/openpgpsdk/final.h b/openpgpsdk/src/openpgpsdk/final.h deleted file mode 100644 index 404391d2f..000000000 --- a/openpgpsdk/src/openpgpsdk/final.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* A header that is always included last, for things that need to come last */ - -#ifdef DMALLOC -# include -#endif - diff --git a/openpgpsdk/src/openpgpsdk/fingerprint.c b/openpgpsdk/src/openpgpsdk/fingerprint.c deleted file mode 100644 index 61702f292..000000000 --- a/openpgpsdk/src/openpgpsdk/fingerprint.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include -#include -#include - -#include -#if HAVE_ALLOCA_H -# include -#endif - -#ifdef WIN32 -#define alloca _alloca -#endif - -#include - -static int debug=0; - -/** - * \ingroup Core_Keys - * \brief Calculate a public key fingerprint. - * \param fp Where to put the calculated fingerprint - * \param key The key for which the fingerprint is calculated - */ - -void ops_fingerprint(ops_fingerprint_t *fp,const ops_public_key_t *key) - { - if(key->version == 2 || key->version == 3) - { - unsigned char *bn; - int n; - ops_hash_t md5; - - assert(key->algorithm == OPS_PKA_RSA - || key->algorithm == OPS_PKA_RSA_ENCRYPT_ONLY - || key->algorithm == OPS_PKA_RSA_SIGN_ONLY ); - - ops_hash_md5(&md5); - md5.init(&md5); - - n=BN_num_bytes(key->key.rsa.n); - bn=alloca(n); - BN_bn2bin(key->key.rsa.n,bn); - md5.add(&md5,bn,n); - - n=BN_num_bytes(key->key.rsa.e); - bn=alloca(n); - BN_bn2bin(key->key.rsa.e,bn); - md5.add(&md5,bn,n); - - md5.finish(&md5,fp->fingerprint); - fp->length=16; - } - else - { - ops_memory_t *mem=ops_memory_new(); - ops_hash_t sha1; - size_t l; - - ops_build_public_key(mem,key,ops_false); - - if (debug) - { fprintf(stderr,"--- creating key fingerprint\n"); } - - ops_hash_sha1(&sha1); - sha1.init(&sha1); - - l=ops_memory_get_length(mem); - - ops_hash_add_int(&sha1,0x99,1); - ops_hash_add_int(&sha1,l,2); - sha1.add(&sha1,ops_memory_get_data(mem),l); - sha1.finish(&sha1,fp->fingerprint); - - if (debug) - { fprintf(stderr,"--- finished creating key fingerprint\n"); } - - fp->length=20; - - ops_memory_free(mem); - } - } - -/** - * \ingroup Core_Keys - * \brief Calculate the Key ID from the public key. - * \param keyid Space for the calculated ID to be stored - * \param key The key for which the ID is calculated - */ - -void ops_keyid(unsigned char keyid[8],const ops_public_key_t *key) - { - if(key->version == 2 || key->version == 3) - { - unsigned char bn[8192]; - unsigned n=BN_num_bytes(key->key.rsa.n); - - assert(n <= sizeof bn); - assert(key->algorithm == OPS_PKA_RSA - || key->algorithm == OPS_PKA_RSA_ENCRYPT_ONLY - || key->algorithm == OPS_PKA_RSA_SIGN_ONLY ); - BN_bn2bin(key->key.rsa.n,bn); - memcpy(keyid,bn+n-8,8); - } - else - { - ops_fingerprint_t fingerprint; - - ops_fingerprint(&fingerprint,key); - memcpy(keyid,fingerprint.fingerprint+fingerprint.length-8,8); - } - } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/hash.c b/openpgpsdk/src/openpgpsdk/hash.c deleted file mode 100644 index 5154f46ac..000000000 --- a/openpgpsdk/src/openpgpsdk/hash.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include - -#include - -static int debug=0; - -/** -\ingroup Core_Hashes -\brief Add to the hash -\param hash Hash to add to -\param n Int to add -\param length Length of int in bytes -*/ -void ops_hash_add_int(ops_hash_t *hash,unsigned n,unsigned length) - { - while(length--) - { - unsigned char c[1]; - - c[0]=n >> (length*8); - hash->add(hash,c,1); - } - } - -/** -\ingroup Core_Hashes -\brief Setup hash for given hash algorithm -\param hash Hash to set up -\param alg Hash algorithm to use -*/ -void ops_hash_any(ops_hash_t *hash,ops_hash_algorithm_t alg) - { - switch(alg) - { - case OPS_HASH_MD5: - ops_hash_md5(hash); - break; - - case OPS_HASH_SHA1: - ops_hash_sha1(hash); - break; - - case OPS_HASH_SHA256: - ops_hash_sha256(hash); - break; - - case OPS_HASH_SHA384: - ops_hash_sha384(hash); - break; - - case OPS_HASH_SHA512: - ops_hash_sha512(hash); - break; - - case OPS_HASH_SHA224: - ops_hash_sha224(hash); - break; - - default: - assert(0); - } - } - -/** -\ingroup Core_Hashes -\brief Returns size of hash for given hash algorithm -\param alg Hash algorithm to use -\return Size of hash algorithm in bytes -*/ -unsigned ops_hash_size(ops_hash_algorithm_t alg) - { - switch(alg) - { - case OPS_HASH_MD5: - return 16; - - case OPS_HASH_SHA1: - return 20; - - case OPS_HASH_SHA256: - return 32; - - case OPS_HASH_SHA224: - return 28; - - case OPS_HASH_SHA512: - return 64; - - case OPS_HASH_SHA384: - return 48; - - default: - assert(0); - } - - return 0; - } - -/** -\ingroup Core_Hashes -\brief Returns hash enum corresponding to given string -\param hash Text name of hash algorithm i.e. "SHA1" -\returns Corresponding enum i.e. OPS_HASH_SHA1 -*/ -ops_hash_algorithm_t ops_hash_algorithm_from_text(const char *hash) - { - if(!strcmp(hash,"SHA1")) - return OPS_HASH_SHA1; - else if(!strcmp(hash,"MD5")) - return OPS_HASH_MD5; - else if (!strcmp(hash,"SHA256")) - return OPS_HASH_SHA256; - /* - else if (!strcmp(hash,"SHA224")) - return OPS_HASH_SHA224; - */ - else if (!strcmp(hash,"SHA512")) - return OPS_HASH_SHA512; - else if (!strcmp(hash,"SHA384")) - return OPS_HASH_SHA384; - - return OPS_HASH_UNKNOWN; - } - -/** -\ingroup Core_Hashes -\brief Hash given data -\param out Where to write the hash -\param alg Hash algorithm to use -\param in Data to hash -\param length Length of data -\return Size of hash created -*/ -unsigned ops_hash(unsigned char *out,ops_hash_algorithm_t alg,const void *in, - size_t length) - { - ops_hash_t hash; - - ops_hash_any(&hash,alg); - hash.init(&hash); - hash.add(&hash,in,length); - return hash.finish(&hash,out); - } - -/** -\ingroup Core_Hashes -\brief Calculate hash for MDC packet -\param preamble Preamble to hash -\param sz_preamble Size of preamble -\param plaintext Plaintext to hash -\param sz_plaintext Size of plaintext -\param hashed Resulting hash -*/ -void ops_calc_mdc_hash(const unsigned char* preamble, const size_t sz_preamble, const unsigned char* plaintext, const unsigned int sz_plaintext, unsigned char *hashed) - { - ops_hash_t hash; - unsigned char c[1]; - - if (debug) - { - unsigned int i=0; - fprintf(stderr,"ops_calc_mdc_hash():\n"); - - fprintf(stderr,"\npreamble: "); - for (i=0; i -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "keyring_local.h" -#include "parse_local.h" - -#include -#include -#ifndef WIN32 -#include -#include -#endif -#include -#include - -#include -#include - -/** - \ingroup HighLevel_Keyring - - \brief Creates a new ops_keydata_t struct - - \return A new ops_keydata_t struct, initialised to zero. - - \note The returned ops_keydata_t struct must be freed after use with ops_keydata_free. -*/ - -ops_keydata_t *ops_keydata_new(void) - { return ops_mallocz(sizeof(ops_keydata_t)); } - - -// Frees the content of a keydata structure, but not the keydata itself. -static void keydata_internal_free(ops_keydata_t *keydata) - { - unsigned n; - - for(n=0 ; n < keydata->nuids ; ++n) - ops_user_id_free(&keydata->uids[n]); - free(keydata->uids); - keydata->uids=NULL; - keydata->nuids=0; - - for(n=0 ; n < keydata->npackets ; ++n) - ops_packet_free(&keydata->packets[n]); - free(keydata->packets); - keydata->packets=NULL; - keydata->npackets=0; - -/* for(n=0;nnsigs;++n) - { - ops_user_id_free(keydata->sigs[n].userid) ; - ops_packet_free(keydata->sigs[n].packet) ; - }*/ - free(keydata->sigs) ; - - if(keydata->type == OPS_PTAG_CT_PUBLIC_KEY) - ops_public_key_free(&keydata->key.pkey); - else - ops_secret_key_free(&keydata->key.skey); - - } - -/** - \ingroup HighLevel_Keyring - - \brief Frees keydata and its memory - - \param keydata Key to be freed. - - \note This frees the keydata itself, as well as any other memory - alloc-ed by it. -*/ -void ops_keydata_free(ops_keydata_t *keydata) - { - keydata_internal_free(keydata); - free(keydata); - } - -// \todo check where userid pointers are copied -/** -\ingroup Core_Keys -\brief Copy user id, including contents -\param dst Destination User ID -\param src Source User ID -\note If dst already has a user_id, it will be freed. -*/ -void ops_copy_userid(ops_user_id_t* dst, const ops_user_id_t* src) - { - int len=strlen((char *)src->user_id); - if (dst->user_id) - free(dst->user_id); - dst->user_id=ops_mallocz(len+1); - - memcpy(dst->user_id, src->user_id, len); - } -// \todo check where pkt pointers are copied -/** -\ingroup Core_Keys -\brief Copy packet, including contents -\param dst Destination packet -\param src Source packet -\note If dst already has a packet, it will be freed. -*/ -void ops_copy_packet(ops_packet_t* dst, const ops_packet_t* src) - { - if (dst->raw) - free(dst->raw); - dst->raw=ops_mallocz(src->length); - - dst->length=src->length; - memcpy(dst->raw, src->raw, src->length); - } - - - -/** -\ingroup Core_Keys -\brief Copies entire key data -\param dst Destination key where to copy -\param src Source key to copy -*/ -void ops_keydata_copy(ops_keydata_t *dst,const ops_keydata_t *src) -{ - unsigned n; - - keydata_internal_free(dst) ; - memset(dst,0,sizeof(ops_keydata_t)) ; - - dst->uids = (ops_user_id_t*)ops_mallocz(src->nuids * sizeof(ops_user_id_t)) ; - dst->nuids = src->nuids ; - dst->nuids_allocated = src->nuids ; - - for(n=0 ; n < src->nuids ; ++n) - ops_copy_userid(&dst->uids[n],&src->uids[n]) ; - - dst->packets = (ops_packet_t*)ops_mallocz(src->npackets * sizeof(ops_packet_t)) ; - dst->npackets = src->npackets ; - dst->npackets_allocated = src->npackets ; - - for(n=0 ; n < src->npackets ; ++n) - ops_copy_packet(&(dst->packets[n]),&(src->packets[n])); - - dst->nsigs = src->nsigs ; - dst->sigs = (sigpacket_t*)ops_mallocz(src->nsigs * sizeof(sigpacket_t)) ; - dst->nsigs_allocated = src->nsigs ; - - for(n=0 ; n < src->nsigs ; ++n) - { - dst->sigs[n].userid = (ops_user_id_t*)ops_mallocz(sizeof(ops_user_id_t)) ; - dst->sigs[n].packet = (ops_packet_t*)ops_mallocz(sizeof(ops_packet_t)) ; - - ops_copy_userid(dst->sigs[n].userid,src->sigs[n].userid) ; - ops_copy_packet(dst->sigs[n].packet,src->sigs[n].packet) ; - } - - dst->key_id[0] = src->key_id[0] ; - dst->key_id[1] = src->key_id[1] ; - dst->key_id[2] = src->key_id[2] ; - dst->key_id[3] = src->key_id[3] ; - dst->key_id[4] = src->key_id[4] ; - dst->key_id[5] = src->key_id[5] ; - dst->key_id[6] = src->key_id[6] ; - dst->key_id[7] = src->key_id[7] ; - dst->type = src->type ; - dst->key = src->key ; - dst->fingerprint = src->fingerprint ; - - if(src->type == OPS_PTAG_CT_PUBLIC_KEY) - ops_public_key_copy(&dst->key.pkey,&src->key.pkey); - else - ops_secret_key_copy(&dst->key.skey,&src->key.skey); -} - - -/** - \ingroup HighLevel_KeyGeneral - - \brief Returns the public key in the given keydata. - \param keydata - - \return Pointer to public key - - \note This is not a copy, do not free it after use. -*/ - -const ops_public_key_t * -ops_get_public_key_from_data(const ops_keydata_t *keydata) - { - if(keydata->type == OPS_PTAG_CT_PUBLIC_KEY) - return &keydata->key.pkey; - return &keydata->key.skey.public_key; - } - -/** -\ingroup HighLevel_KeyGeneral - -\brief Check whether this is a secret key or not. -*/ - -ops_boolean_t ops_is_key_secret(const ops_keydata_t *data) - { return data->type != OPS_PTAG_CT_PUBLIC_KEY; } - -/** - \ingroup HighLevel_KeyGeneral - - \brief Returns the secret key in the given keydata. - - \note This is not a copy, do not free it after use. - - \note This returns a const. If you need to be able to write to this pointer, use ops_get_writable_secret_key_from_data -*/ - -const ops_secret_key_t * -ops_get_secret_key_from_data(const ops_keydata_t *data) - { - if(data->type != OPS_PTAG_CT_SECRET_KEY) - return NULL; - - return &data->key.skey; - } - -/** - \ingroup HighLevel_KeyGeneral - - \brief Returns the secret key in the given keydata. - - \note This is not a copy, do not free it after use. - - \note If you do not need to be able to modify this key, there is an equivalent read-only function ops_get_secret_key_from_data. -*/ - -ops_secret_key_t * -ops_get_writable_secret_key_from_data(ops_keydata_t *data) - { - if (data->type != OPS_PTAG_CT_SECRET_KEY) - return NULL; - - return &data->key.skey; - } - -typedef struct - { - const ops_keydata_t *key; - char *pphrase; - ops_secret_key_t *skey; - } decrypt_arg_t; - -static ops_parse_cb_return_t decrypt_cb(const ops_parser_content_t *content_, - ops_parse_cb_info_t *cbinfo) - { - const ops_parser_content_union_t *content=&content_->content; - decrypt_arg_t *arg=ops_parse_cb_get_arg(cbinfo); - - OPS_USED(cbinfo); - - switch(content_->tag) - { - case OPS_PARSER_PTAG: - case OPS_PTAG_CT_USER_ID: - case OPS_PTAG_CT_SIGNATURE: - case OPS_PTAG_CT_SIGNATURE_HEADER: - case OPS_PTAG_CT_SIGNATURE_FOOTER: - case OPS_PTAG_CT_TRUST: - break; - - case OPS_PARSER_CMD_GET_SK_PASSPHRASE: - *content->secret_key_passphrase.passphrase=arg->pphrase; - return OPS_KEEP_MEMORY; - - case OPS_PARSER_ERRCODE: - switch(content->errcode.errcode) - { - case OPS_E_P_MPI_FORMAT_ERROR: - /* Generally this means a bad passphrase */ - fprintf(stderr,"Bad passphrase!\n"); - goto done; - - case OPS_E_P_PACKET_CONSUMED: - /* And this is because of an error we've accepted */ - goto done; - - default: - fprintf(stderr,"parse error: %s\n", - ops_errcode(content->errcode.errcode)); - assert(0); - break; - } - - break; - - case OPS_PARSER_ERROR: - printf("parse error: %s\n",content->error.error); - assert(0); - break; - - case OPS_PTAG_CT_SECRET_KEY: - arg->skey=malloc(sizeof *arg->skey); - *arg->skey=content->secret_key; - return OPS_KEEP_MEMORY; - - case OPS_PARSER_PACKET_END: - // nothing to do - break; - - default: - fprintf(stderr,"Unexpected tag %d (0x%x)\n",content_->tag, - content_->tag); - assert(0); - } - - done: - return OPS_RELEASE_MEMORY; - } - -/** -\ingroup Core_Keys -\brief Decrypts secret key from given keydata with given passphrase -\param key Key from which to get secret key -\param pphrase Passphrase to use to decrypt secret key -\return secret key -*/ -ops_secret_key_t *ops_decrypt_secret_key_from_data(const ops_keydata_t *key, - const char *pphrase) - { - ops_parse_info_t *pinfo; - decrypt_arg_t arg; - - memset(&arg,'\0',sizeof arg); - arg.key=key; - arg.pphrase=strdup(pphrase); - - pinfo=ops_parse_info_new(); - - ops_keydata_reader_set(pinfo,key); - ops_parse_cb_set(pinfo,decrypt_cb,&arg); - pinfo->rinfo.accumulate=ops_true; - - ops_parse(pinfo,ops_false); - - ops_parse_info_delete(pinfo); - - return arg.skey; - } - -/** -\ingroup Core_Keys -\brief Set secret key in content -\param content Content to be set -\param key Keydata to get secret key from -*/ -void ops_set_secret_key(ops_parser_content_union_t* content,const ops_keydata_t *key) - { - *content->get_secret_key.secret_key=&key->key.skey; - } - -/** -\ingroup Core_Keys -\brief Get Key ID from keydata -\param key Keydata to get Key ID from -\return Pointer to Key ID inside keydata -*/ -const unsigned char* ops_get_key_id(const ops_keydata_t *key) - { - return key->key_id; - } - -/** -\ingroup Core_Keys -\brief How many User IDs in this key? -\param key Keydata to check -\return Num of user ids -*/ -unsigned ops_get_user_id_count(const ops_keydata_t *key) - { - return key->nuids; - } - -/** -\ingroup Core_Keys -\brief Get indexed user id from key -\param key Key to get user id from -\param index Which key to get -\return Pointer to requested user id -*/ -const unsigned char* ops_get_user_id(const ops_keydata_t *key, unsigned index) - { - return key->uids[index].user_id; - } - -/** - \ingroup HighLevel_Supported - \brief Checks whether key's algorithm and type are supported by OpenPGP::SDK - \param keydata Key to be checked - \return ops_true if key algorithm and type are supported by OpenPGP::SDK; ops_false if not -*/ - -ops_boolean_t ops_is_key_supported(const ops_keydata_t *keydata) -{ - if(keydata->type == OPS_PTAG_CT_PUBLIC_KEY) - { - if(keydata->key.pkey.algorithm == OPS_PKA_RSA) - return ops_true; - } - return ops_false; -} - - -/** - \ingroup HighLevel_KeyringFind - - \brief Returns key inside a keyring, chosen by index - - \param keyring Pointer to existing keyring - \param index Index of required key - - \note Index starts at 0 - - \note This returns a pointer to the original key, not a copy. You do not need to free the key after use. - - \return Pointer to the required key; or NULL if index too large. - - Example code: - \code - void example(const ops_keyring_t* keyring) - { - ops_keydata_t* keydata=NULL; - keydata=ops_keyring_get_key_by_index(keyring, 0); - ... - } - \endcode -*/ - -const ops_keydata_t* ops_keyring_get_key_by_index(const ops_keyring_t *keyring, int index) - { - if (index >= keyring->nkeys) - return NULL; - return &keyring->keys[index]; - } - -/** -\ingroup Core_Keys -\brief Add User ID to keydata -\param keydata Key to which to add User ID -\param userid User ID to add -\return Pointer to new User ID -*/ -ops_user_id_t* ops_add_userid_to_keydata(ops_keydata_t* keydata, const ops_user_id_t* userid) - { - ops_user_id_t* new_uid=NULL; - - EXPAND_ARRAY(keydata, uids); - - // initialise new entry in array - new_uid=&keydata->uids[keydata->nuids]; - - new_uid->user_id=NULL; - - // now copy it - ops_copy_userid(new_uid,userid); - keydata->nuids++; - - return new_uid; - } - -/** -\ingroup Core_Keys -\brief Add packet to key -\param keydata Key to which to add packet -\param packet Packet to add -\return Pointer to new packet -*/ -ops_packet_t* ops_add_packet_to_keydata(ops_keydata_t* keydata, const ops_packet_t* packet) - { - ops_packet_t* new_pkt=NULL; - - EXPAND_ARRAY(keydata, packets); - - // initialise new entry in array - new_pkt=&keydata->packets[keydata->npackets]; - new_pkt->length=0; - new_pkt->raw=NULL; - - // now copy it - ops_copy_packet(new_pkt, packet); - keydata->npackets++; - - return new_pkt; - } - -/** -\ingroup Core_Keys -\brief Add signed User ID to key -\param keydata Key to which to add signed User ID -\param user_id User ID to add -\param sigpacket Packet to add -*/ -void ops_add_signed_userid_to_keydata(ops_keydata_t* keydata, const ops_user_id_t* user_id, const ops_packet_t* sigpacket) - { - //int i=0; - ops_user_id_t * uid=NULL; - ops_packet_t * pkt=NULL; - - uid=ops_add_userid_to_keydata(keydata, user_id); - pkt=ops_add_packet_to_keydata(keydata, sigpacket); - - /* - * add entry in sigs array to link the userid and sigpacket - */ - - // and add ptr to it from the sigs array - EXPAND_ARRAY(keydata, sigs); - - // setup new entry in array - - keydata->sigs[keydata->nsigs].userid=uid; - keydata->sigs[keydata->nsigs].packet=pkt; - - keydata->nsigs++; - } - -/** -\ingroup Core_Keys -\brief Add selfsigned User ID to key -\param keydata Key to which to add user ID -\param userid Self-signed User ID to add -\return ops_true if OK; else ops_false -*/ -ops_boolean_t ops_add_selfsigned_userid_to_keydata(ops_keydata_t* keydata, ops_user_id_t* userid) - { - ops_packet_t sigpacket; - - ops_memory_t* mem_userid=NULL; - ops_create_info_t* cinfo_userid=NULL; - - ops_memory_t* mem_sig=NULL; - ops_create_info_t* cinfo_sig=NULL; - - ops_create_signature_t *sig=NULL; - - /* - * create signature packet for this userid - */ - - // create userid pkt - ops_setup_memory_write(&cinfo_userid, &mem_userid, 128); - ops_write_struct_user_id(userid, cinfo_userid); - - // create sig for this pkt - - sig=ops_create_signature_new(); - ops_signature_start_key_signature(sig, &keydata->key.skey.public_key, userid, OPS_CERT_POSITIVE); - ops_signature_add_creation_time(sig,time(NULL)); - ops_signature_add_issuer_key_id(sig,keydata->key_id); - ops_signature_add_primary_user_id(sig, ops_true); - ops_signature_hashed_subpackets_end(sig); - - ops_setup_memory_write(&cinfo_sig, &mem_sig, 128); - ops_write_signature(sig,&keydata->key.skey.public_key,&keydata->key.skey, cinfo_sig); - - // add this packet to keydata - - sigpacket.length=ops_memory_get_length(mem_sig); - sigpacket.raw=ops_memory_get_data(mem_sig); - - // add userid to keydata - ops_add_signed_userid_to_keydata(keydata, userid, &sigpacket); - - // cleanup - ops_create_signature_delete(sig); - ops_create_info_delete(cinfo_userid); - ops_create_info_delete(cinfo_sig); - ops_memory_free(mem_userid); - ops_memory_free(mem_sig); - - return ops_true; - } - -/** -\ingroup Core_Keys -\brief Add signature to given key -\return ops_true if OK; else ops_false -*/ -ops_boolean_t ops_sign_key(ops_keydata_t* keydata, const unsigned char *signers_key_id,ops_secret_key_t *signers_key) -{ -/* ops_memory_t* mem_userid=NULL; */ - ops_memory_t* mem_sig=NULL; - ops_create_info_t* cinfo_sig=NULL; - - ops_create_signature_t *sig=NULL; - - /* - * create signature packet for this userid - */ - - // create sig for this pkt - - sig=ops_create_signature_new(); - ops_signature_start_key_signature(sig, &keydata->key.skey.public_key, &keydata->uids[0], OPS_CERT_GENERIC); - ops_signature_add_creation_time(sig,time(NULL)); - ops_signature_add_issuer_key_id(sig,signers_key_id); - ops_signature_hashed_subpackets_end(sig); - - ops_setup_memory_write(&cinfo_sig, &mem_sig, 128); - ops_write_signature(sig,&signers_key->public_key,signers_key, cinfo_sig); - - // add this packet to keydata - - ops_packet_t sigpacket; - sigpacket.length=ops_memory_get_length(mem_sig); - sigpacket.raw=ops_memory_get_data(mem_sig); - - // add userid to keydata - ops_add_packet_to_keydata(keydata, &sigpacket); - - // cleanup - ops_create_signature_delete(sig); - ops_create_info_delete(cinfo_sig); - ops_memory_free(mem_sig); - - return ops_true; -} -/** -\ingroup Core_Keys -\brief Initialise ops_keydata_t -\param keydata Keydata to initialise -\param type OPS_PTAG_CT_PUBLIC_KEY or OPS_PTAG_CT_SECRET_KEY -*/ -void ops_keydata_init(ops_keydata_t* keydata, const ops_content_tag_t type) - { - assert(keydata->type==OPS_PTAG_CT_RESERVED); - assert(type==OPS_PTAG_CT_PUBLIC_KEY || type==OPS_PTAG_CT_SECRET_KEY); - - keydata->type=type; - } - -/** - Example Usage: - \code - - // definition of variables - ops_keyring_t keyring; - char* filename="~/.gnupg/pubring.gpg"; - - // Read keyring from file - ops_keyring_read_from_file(&keyring,filename); - - // do actions using keyring - ... - - // Free memory alloc-ed in ops_keyring_read_from_file() - ops_keyring_free(keyring); - \endcode -*/ - -static ops_parse_cb_return_t -cb_keyring_read(const ops_parser_content_t *content_, - ops_parse_cb_info_t *cbinfo); - -/** - \ingroup HighLevel_KeyringRead - - \brief Reads a keyring from a file - - \param keyring Pointer to an existing ops_keyring_t struct - \param armour ops_true if file is armoured; else ops_false - \param filename Filename of keyring to be read - - \return ops true if OK; ops_false on error - - \note Keyring struct must already exist. - - \note Can be used with either a public or secret keyring. - - \note You must call ops_keyring_free() after usage to free alloc-ed memory. - - \note If you call this twice on the same keyring struct, without calling - ops_keyring_free() between these calls, you will introduce a memory leak. - - \sa ops_keyring_read_from_mem() - \sa ops_keyring_free() - - Example code: - \code - ops_keyring_t* keyring=ops_mallocz(sizeof *keyring); - ops_boolean_t armoured=ops_false; - ops_keyring_read_from_file(keyring, armoured, "~/.gnupg/pubring.gpg"); - ... - ops_keyring_free(keyring); - free (keyring); - - \endcode -*/ - -ops_boolean_t ops_keyring_read_from_file(ops_keyring_t *keyring, const ops_boolean_t armour, const char *filename) - { - ops_parse_info_t *pinfo; - int fd; - ops_boolean_t res = ops_true; - - pinfo=ops_parse_info_new(); - - // add this for the moment, - // \todo need to fix the problems with reading signature subpackets later - - // ops_parse_options(pinfo,OPS_PTAG_SS_ALL,OPS_PARSE_RAW); - ops_parse_options(pinfo,OPS_PTAG_SS_ALL,OPS_PARSE_PARSED); - - fd=ops_open(filename,O_RDONLY | O_BINARY, 0); - - if(fd < 0) - { - ops_parse_info_delete(pinfo); - perror(filename); - return ops_false; - } - - ops_reader_set_fd(pinfo,fd); - - ops_parse_cb_set(pinfo,cb_keyring_read,NULL); - - if (armour) - { ops_reader_push_dearmour(pinfo); } - - if ( ops_parse_and_accumulate(keyring,pinfo) == 0 ) { - res = ops_false; - } - else - { - res = ops_true; - } - ops_print_errors(ops_parse_info_get_errors(pinfo)); - - if (armour) - ops_reader_pop_dearmour(pinfo); - - close(fd); - - ops_parse_info_delete(pinfo); - - return res; - } - -/** - \ingroup HighLevel_KeyringRead - - \brief Reads a keyring from memory - - \param keyring Pointer to existing ops_keyring_t struct - \param armour ops_true if file is armoured; else ops_false - \param mem Pointer to a ops_memory_t struct containing keyring to be read - - \return ops true if OK; ops_false on error - - \note Keyring struct must already exist. - - \note Can be used with either a public or secret keyring. - - \note You must call ops_keyring_free() after usage to free alloc-ed memory. - - \note If you call this twice on the same keyring struct, without calling - ops_keyring_free() between these calls, you will introduce a memory leak. - - \sa ops_keyring_read_from_file - \sa ops_keyring_free - - Example code: - \code - ops_memory_t* mem; // Filled with keyring packets - ops_keyring_t* keyring=ops_mallocz(sizeof *keyring); - ops_boolean_t armoured=ops_false; - ops_keyring_read_from_mem(keyring, armoured, mem); - ... - ops_keyring_free(keyring); - free (keyring); - \endcode -*/ -ops_boolean_t ops_keyring_read_from_mem(ops_keyring_t *keyring, const ops_boolean_t armour, ops_memory_t* mem) - { - ops_parse_info_t *pinfo=NULL; - ops_boolean_t res = ops_true; - - ops_setup_memory_read(&pinfo, mem, NULL, cb_keyring_read, - OPS_ACCUMULATE_NO); - ops_parse_options(pinfo,OPS_PTAG_SS_ALL,OPS_PARSE_PARSED); - - if (armour) - { ops_reader_push_dearmour(pinfo); } - - if ( ops_parse_and_accumulate(keyring,pinfo) == 0 ) - { - res = ops_false; - } - else - { - res = ops_true; - } - ops_print_errors(ops_parse_info_get_errors(pinfo)); - - if (armour) - ops_reader_pop_dearmour(pinfo); - - // don't call teardown_memory_read because memory was passed - // in. But we need to free the parse_info object allocated by - // ops_setup_memory_read(). - ops_parse_info_delete(pinfo); - - return res; - } - -/** - \ingroup HighLevel_KeyringRead - - \brief Frees keyring's contents (but not keyring itself) - - \param keyring Keyring whose data is to be freed - - \note This does not free keyring itself, just the memory alloc-ed in it. - */ -void ops_keyring_free(ops_keyring_t *keyring) - { - int i; - - for (i = 0; i < keyring->nkeys; i++) - keydata_internal_free(&keyring->keys[i]); - - free(keyring->keys); - keyring->keys=NULL; - keyring->nkeys=0; - keyring->nkeys_allocated=0; - } - -void ops_keyring_remove_key(ops_keyring_t *keyring,int index) -{ - if(index > keyring->nkeys-1) - { - fprintf(stderr,"ops_keyring_remove_key: ERROR: cannot remove key with index %d > %d.",index,keyring->nkeys-1) ; - return ; - } - - if(index < keyring->nkeys-1) - ops_keydata_copy(&keyring->keys[index],&keyring->keys[keyring->nkeys-1]) ; - - keydata_internal_free(&keyring->keys[keyring->nkeys-1]) ; - keyring->nkeys-- ; - - // keyring->nkeys_allocated is left untouched intentionnaly. -} - -/** - \ingroup HighLevel_KeyringFind - - \brief Finds key in keyring from its Key ID - - \param keyring Keyring to be searched - \param keyid ID of required key - - \return Pointer to key, if found; NULL, if not found - - \note This returns a pointer to the key inside the given keyring, not a copy. Do not free it after use. - - Example code: - \code - void example(ops_keyring_t* keyring) - { - ops_keydata_t* keydata=NULL; - unsigned char keyid[OPS_KEY_ID_SIZE]; // value set elsewhere - keydata=ops_keyring_find_key_by_id(keyring,keyid); - ... - } - \endcode -*/ -const ops_keydata_t * -ops_keyring_find_key_by_id(const ops_keyring_t *keyring, - const unsigned char keyid[OPS_KEY_ID_SIZE]) - { - int n; - - if (!keyring) - return NULL; - - for(n=0 ; n < keyring->nkeys ; ++n) - { - if(!memcmp(keyring->keys[n].key_id,keyid,OPS_KEY_ID_SIZE)) - return &keyring->keys[n]; - } - - return NULL; - } - -/** - \ingroup HighLevel_KeyringFind - - \brief Finds key from its User ID - - \param keyring Keyring to be searched - \param userid User ID of required key - - \return Pointer to Key, if found; NULL, if not found - - \note This returns a pointer to the key inside the keyring, not a copy. Do not free it. - - Example code: - \code - void example(ops_keyring_t* keyring) - { - ops_keydata_t* keydata=NULL; - keydata=ops_keyring_find_key_by_userid(keyring,"user@domain.com"); - ... - } - \endcode -*/ -const ops_keydata_t * -ops_keyring_find_key_by_userid(const ops_keyring_t *keyring, - const char *userid) - { - int n=0; - unsigned int i=0; - - if (!keyring) - return NULL; - - for(n=0 ; n < keyring->nkeys ; ++n) - { - for(i=0; ikeys[n].nuids; i++) - { - //printf("[%d][%d] userid %s\n",n,i,keyring->keys[n].uids[i].user_id); - if(!strncmp((char *)keyring->keys[n].uids[i].user_id,userid,strlen(userid))) - return &keyring->keys[n]; - } - } - - //printf("end: n=%d,i=%d\n",n,i); - return NULL; - } - -/** - \ingroup HighLevel_KeyringList - - \brief Prints all keys in keyring to stdout. - - \param keyring Keyring to use - - \return none - - Example code: - \code - void example() - { - ops_keyring_t* keyring=ops_mallocz(sizeof *keyring); - ops_boolean_t armoured=ops_false; - ops_keyring_read_from_file(keyring, armoured, "~/.gnupg/pubring.gpg"); - - ops_keyring_list(keyring); - - ops_keyring_free(keyring); - free (keyring); - } - \endcode -*/ - -void -ops_keyring_list(const ops_keyring_t* keyring) - { - int n; - unsigned int i; - ops_keydata_t* key; - - printf ("%d keys\n", keyring->nkeys); - for(n=0,key=&keyring->keys[n] ; n < keyring->nkeys ; ++n,++key) - { - for(i=0; inuids; i++) - { - if (ops_is_key_secret(key)) - ops_print_secret_keydata(key); - else - ops_print_public_keydata(key); - } - - } - } - -/* Static functions */ - -static ops_parse_cb_return_t -cb_keyring_read(const ops_parser_content_t *content_, - ops_parse_cb_info_t *cbinfo) -{ - OPS_USED(cbinfo); - - switch(content_->tag) - { - case OPS_PARSER_PTAG: - case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY: // we get these because we didn't prompt - case OPS_PTAG_CT_SIGNATURE_HEADER: - case OPS_PTAG_CT_SIGNATURE_FOOTER: - case OPS_PTAG_CT_SIGNATURE: - case OPS_PTAG_CT_TRUST: - case OPS_PARSER_ERRCODE: - break; - - default: - ; - } - - return OPS_RELEASE_MEMORY; -} - -/** - \ingroup HighLevel_KeyringList - - \brief Saves keyring to specified file - - \param keyring Keyring to save - \param armoured Save in ascii armoured format - \param output filename - - \return ops_true is anything when ok -*/ - -ops_boolean_t ops_write_keyring_to_file(const ops_keyring_t *keyring,ops_boolean_t armoured,const char *filename,ops_boolean_t write_all_packets) -{ - ops_create_info_t *info; - int fd = ops_setup_file_write(&info, filename, ops_true); - - if (fd < 0) - { - fprintf(stderr,"ops_write_keyring(): ERROR: Cannot write to %s\n",filename ) ; - return ops_false ; - } - - int i; - for(i=0;inkeys;++i) -// if(keyring->keys[i].key.pkey.algorithm == OPS_PKA_RSA) - if(write_all_packets) - ops_write_transferable_public_key_from_packet_data(&keyring->keys[i],armoured,info) ; - else - ops_write_transferable_public_key(&keyring->keys[i],armoured,info) ; -// else -// { -// fprintf(stdout, "ops_write_keyring: not writing key. Algorithm not handled: ") ; -// ops_print_public_keydata(&keyring->keys[i]); -// fprintf(stdout, "\n") ; -// } - - ops_teardown_file_write(info, fd); - - return ops_true ; -} - -/*\@}*/ - -// eof diff --git a/openpgpsdk/src/openpgpsdk/keyring.h b/openpgpsdk/src/openpgpsdk/keyring.h deleted file mode 100644 index 028416cec..000000000 --- a/openpgpsdk/src/openpgpsdk/keyring.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_KEYRING_H -#define OPS_KEYRING_H - -#include "packet.h" -#include "memory.h" - -typedef struct ops_keydata ops_keydata_t; - -/** \struct ops_keyring_t - * A keyring - */ - -typedef struct - { - int nkeys; // while we are constructing a key, this is the offset - int nkeys_allocated; - ops_keydata_t *keys; - } ops_keyring_t; - -const ops_keydata_t * -ops_keyring_find_key_by_id(const ops_keyring_t *keyring, - const unsigned char keyid[OPS_KEY_ID_SIZE]); -const ops_keydata_t * -ops_keyring_find_key_by_userid(const ops_keyring_t *keyring, - const char* userid); -void ops_keydata_free(ops_keydata_t *key); -void ops_keydata_copy(ops_keydata_t *dst,const ops_keydata_t *src); -void ops_keyring_free(ops_keyring_t *keyring); -void ops_dump_keyring(const ops_keyring_t *keyring); -const ops_public_key_t * -ops_get_public_key_from_data(const ops_keydata_t *data); -ops_boolean_t ops_is_key_secret(const ops_keydata_t *data); -const ops_secret_key_t * -ops_get_secret_key_from_data(const ops_keydata_t *data); -ops_secret_key_t * -ops_get_writable_secret_key_from_data(ops_keydata_t *data); -ops_secret_key_t *ops_decrypt_secret_key_from_data(const ops_keydata_t *key, - const char *pphrase); - -ops_boolean_t ops_keyring_read_from_file(ops_keyring_t *keyring, const ops_boolean_t armour, const char *filename); -ops_boolean_t ops_keyring_read_from_mem(ops_keyring_t *keyring, const ops_boolean_t armour, ops_memory_t *mem); -ops_boolean_t ops_write_keyring_to_file(const ops_keyring_t *keyring,ops_boolean_t armoured,const char *filename,ops_boolean_t write_all_packets); - -char *ops_malloc_passphrase(char *passphrase); -char *ops_get_passphrase(void); - -void ops_keyring_list(const ops_keyring_t* keyring); - -void ops_set_secret_key(ops_parser_content_union_t* content,const ops_keydata_t *key); - -const unsigned char* ops_get_key_id(const ops_keydata_t *key); -unsigned ops_get_user_id_count(const ops_keydata_t *key); -const unsigned char* ops_get_user_id(const ops_keydata_t *key, unsigned index); -ops_boolean_t ops_is_key_supported(const ops_keydata_t *key); -const ops_keydata_t* ops_keyring_get_key_by_index(const ops_keyring_t *keyring, int index); -void ops_keyring_remove_key(ops_keyring_t *keyring,int index) ; - -ops_user_id_t* ops_add_userid_to_keydata(ops_keydata_t* keydata, const ops_user_id_t* userid); -ops_packet_t* ops_add_packet_to_keydata(ops_keydata_t* keydata, const ops_packet_t* packet); -void ops_add_signed_userid_to_keydata(ops_keydata_t* keydata, const ops_user_id_t* userid, const ops_packet_t* packet); - -ops_boolean_t ops_add_selfsigned_userid_to_keydata(ops_keydata_t* keydata, ops_user_id_t* userid); -ops_boolean_t ops_sign_key(ops_keydata_t* keydata_to_sign, const unsigned char *signers_key_id,ops_secret_key_t *signers_decrypted_private_key); - -ops_keydata_t *ops_keydata_new(void); -void ops_keydata_init(ops_keydata_t* keydata, const ops_content_tag_t type); - -#endif diff --git a/openpgpsdk/src/openpgpsdk/keyring_local.h b/openpgpsdk/src/openpgpsdk/keyring_local.h deleted file mode 100644 index 5c3860f35..000000000 --- a/openpgpsdk/src/openpgpsdk/keyring_local.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include - -#define DECLARE_ARRAY(type,arr) unsigned n##arr; unsigned n##arr##_allocated; type *arr -#define EXPAND_ARRAY(str,arr) do if(str->n##arr == str->n##arr##_allocated) \ - { \ - str->n##arr##_allocated=str->n##arr##_allocated*2+10; \ - str->arr=realloc(str->arr,str->n##arr##_allocated*sizeof *str->arr); \ - } while(0) - -/** ops_keydata_key_t - */ -typedef union - { - ops_public_key_t pkey; - ops_secret_key_t skey; - } ops_keydata_key_t; - - -/** sigpacket_t */ -typedef struct - { - ops_user_id_t* userid; - ops_packet_t* packet; - } sigpacket_t; - -// XXX: gonna have to expand this to hold onto subkeys, too... -/** \struct ops_keydata - * \todo expand to hold onto subkeys - */ -struct ops_keydata - { - DECLARE_ARRAY(ops_user_id_t,uids); - DECLARE_ARRAY(ops_packet_t,packets); - DECLARE_ARRAY(sigpacket_t, sigs); - unsigned char key_id[8]; - ops_fingerprint_t fingerprint; - ops_content_tag_t type; - ops_keydata_key_t key; - }; diff --git a/openpgpsdk/src/openpgpsdk/lists.c b/openpgpsdk/src/openpgpsdk/lists.c deleted file mode 100644 index 5be1e2e2c..000000000 --- a/openpgpsdk/src/openpgpsdk/lists.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * \file - * - * Set of functions to manage a dynamic list - */ - -#include - -#include - -#include - -/** - * \ingroup Core_Lists - * \brief Initialises ulong list - * \param *list Pointer to existing list structure - */ -void ops_ulong_list_init(ops_ulong_list_t *list) - { - list->size=0; - list->used=0; - list->ulongs=NULL; - } - -/** - * \ingroup Core_Lists - * \brief Frees allocated memory in ulong list. Does not free *list itself. - * \param *list - */ -void ops_ulong_list_free(ops_ulong_list_t *list) - { - if (list->ulongs) - free(list->ulongs); - ops_ulong_list_init(list); - } - -/** - * \ingroup Core_Lists - * \brief Resizes ulong list. - * - * We only resize in one direction - upwards. - * Algorithm used : double the current size then add 1 - * - * \param *list Pointer to list - * \return 1 if success, else 0 - */ - -static unsigned int ops_ulong_list_resize(ops_ulong_list_t *list) - { - - int newsize=0; - - newsize=list->size*2 + 1; - list->ulongs=realloc(list->ulongs,newsize*sizeof *list->ulongs); - if (list->ulongs) - { - list->size=newsize; - return 1; - } - else - { - /* xxx - realloc failed. error message? - rachel */ - return 0; - } - } - -/** - * \ingroup Core_Lists - * Adds entry to ulong list - * - * \param *list - * \param *ulong - * - * \return 1 if success, else 0 - */ -unsigned int ops_ulong_list_add(ops_ulong_list_t *list, unsigned long *ulong) - { - if (list->size==list->used) - if (!ops_ulong_list_resize(list)) - return 0; - - list->ulongs[list->used]=*ulong; - list->used++; - return 1; - } - diff --git a/openpgpsdk/src/openpgpsdk/lists.h b/openpgpsdk/src/openpgpsdk/lists.h deleted file mode 100644 index 520b1d432..000000000 --- a/openpgpsdk/src/openpgpsdk/lists.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_LISTS_H -#define OPS_LISTS_H - -/** ops_ulong_list_t */ -typedef struct - { - unsigned int size;/* num of array slots allocated */ - unsigned int used; /* num of array slots currently used */ - unsigned long *ulongs; - } ops_ulong_list_t; - -void ops_ulong_list_init(ops_ulong_list_t *list); -void ops_ulong_list_free(ops_ulong_list_t *list); -unsigned int ops_ulong_list_add(ops_ulong_list_t *list, unsigned long *ulong); - -#endif /* OPS_LISTS_H */ diff --git a/openpgpsdk/src/openpgpsdk/literal.h b/openpgpsdk/src/openpgpsdk/literal.h deleted file mode 100644 index 8b1c30e6b..000000000 --- a/openpgpsdk/src/openpgpsdk/literal.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2005-2009 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __OPS_LITERAL_H__ -#define __OPS_LITERAL_H__ - - -ops_boolean_t write_literal_header(ops_create_info_t *info, - void *header_data); - -void ops_writer_push_literal(ops_create_info_t *info); -void ops_writer_push_literal_with_opts(ops_create_info_t *info, - unsigned int buf_size); - -#endif /* __OPS_LITERAL_H__ */ - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/memory.c b/openpgpsdk/src/openpgpsdk/memory.c deleted file mode 100644 index 4093e5657..000000000 --- a/openpgpsdk/src/openpgpsdk/memory.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include -#include - -#include - -struct ops_memory - { - unsigned char *buf; - size_t length; - size_t allocated; - }; - -/** -\ingroup HighLevel_Memory -\brief Memory to initialise -\param mem memory to initialise -\param initial_size Size to initialise to -*/ -void ops_memory_init(ops_memory_t *mem,size_t initial_size) - { - mem->length=0; - if(mem->buf) - { - if(mem->allocated < initial_size) - { - mem->buf=realloc(mem->buf,initial_size); - mem->allocated=initial_size; - } - return; - } - mem->buf=malloc(initial_size); - mem->allocated=initial_size; - } - -/** -\ingroup HighLevel_Memory -\brief Pad memory to required length -\param mem Memory to use -\param length New size -*/ -void ops_memory_pad(ops_memory_t *mem,size_t length) - { - assert(mem->allocated >= mem->length); - if(mem->allocated < mem->length+length) - { - mem->allocated=mem->allocated*2+length; - mem->buf=realloc(mem->buf,mem->allocated); - } - assert(mem->allocated >= mem->length+length); - } - -/** -\ingroup HighLevel_Memory -\brief Add data to memory -\param mem Memory to which to add -\param src Data to add -\param length Length of data to add -*/ -void ops_memory_add(ops_memory_t *mem,const unsigned char *src,size_t length) - { - ops_memory_pad(mem,length); - memcpy(mem->buf+mem->length,src,length); - mem->length+=length; - } - -// XXX: this could be refactored via the writer, but an awful lot of -// hoops to jump through for 2 lines of code! -void ops_memory_place_int(ops_memory_t *mem,unsigned offset,unsigned n, - size_t length) - { - assert(mem->allocated >= offset+length); - - while(length--) - mem->buf[offset++]=n >> (length*8); - } - -/** - * \ingroup HighLevel_Memory - * \brief Retains allocated memory and set length of stored data to zero. - * \param mem Memory to clear - * \sa ops_memory_release() - * \sa ops_memory_free() - */ -void ops_memory_clear(ops_memory_t *mem) - { mem->length=0; } - -/** -\ingroup HighLevel_Memory -\brief Free memory and associated data -\param mem Memory to free -\note This does not free mem itself -\sa ops_memory_clear() -\sa ops_memory_free() -*/ -void ops_memory_release(ops_memory_t *mem) - { - free(mem->buf); - mem->buf=NULL; - mem->length=0; - } - -void ops_memory_make_packet(ops_memory_t *out,ops_content_tag_t tag) - { - size_t extra; - - if(out->length < 192) - extra=1; - else if(out->length < 8384) - extra=2; - else - extra=5; - - ops_memory_pad(out,extra+1); - memmove(out->buf+extra+1,out->buf,out->length); - - out->buf[0]=OPS_PTAG_ALWAYS_SET|OPS_PTAG_NEW_FORMAT|tag; - - if(out->length < 192) - out->buf[1]=out->length; - else if(out->length < 8384) - { - out->buf[1]=((out->length-192) >> 8)+192; - out->buf[2]=out->length-192; - } - else - { - out->buf[1]=0xff; - out->buf[2]=out->length >> 24; - out->buf[3]=out->length >> 16; - out->buf[4]=out->length >> 8; - out->buf[5]=out->length; - } - - out->length+=extra+1; - } - -/** - \ingroup HighLevel_Memory - \brief Create a new zeroed ops_memory_t - \return Pointer to new ops_memory_t - \note Free using ops_memory_free() after use. - \sa ops_memory_free() -*/ - -ops_memory_t *ops_memory_new() - { return ops_mallocz(sizeof(ops_memory_t)); } - -/** - \ingroup HighLevel_Memory - \brief Free memory ptr and associated memory - \param mem Memory to be freed - \sa ops_memory_release() - \sa ops_memory_clear() -*/ - -void ops_memory_free(ops_memory_t *mem) - { - ops_memory_release(mem); - free(mem); - } - -/** - \ingroup HighLevel_Memory - \brief Get length of data stored in ops_memory_t struct - \return Number of bytes in data -*/ -size_t ops_memory_get_length(const ops_memory_t *mem) - { return mem->length; } - -/** - \ingroup HighLevel_Memory - \brief Get data stored in ops_memory_t struct - \return Pointer to data -*/ -void *ops_memory_get_data(ops_memory_t *mem) - { return mem->buf; } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/memory.h b/openpgpsdk/src/openpgpsdk/memory.h deleted file mode 100644 index 3fa098026..000000000 --- a/openpgpsdk/src/openpgpsdk/memory.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include "packet.h" - -#ifndef OPS_MEMORY_H -#define OPS_MEMORY_H - -/** ops_memory_t - */ -typedef struct ops_memory ops_memory_t; - -ops_memory_t *ops_memory_new(void); -void ops_memory_free(ops_memory_t *mem); -void ops_memory_init(ops_memory_t *mem,size_t initial_size); -void ops_memory_pad(ops_memory_t *mem,size_t length); -void ops_memory_add(ops_memory_t *mem,const unsigned char *src,size_t length); -void ops_memory_place_int(ops_memory_t *mem,unsigned offset,unsigned n, - size_t length); -void ops_memory_make_packet(ops_memory_t *out,ops_content_tag_t tag); -void ops_memory_clear(ops_memory_t *mem); -void ops_memory_release(ops_memory_t *mem); - -void ops_writer_set_memory(ops_create_info_t *info,ops_memory_t *mem); - -size_t ops_memory_get_length(const ops_memory_t *mem); -void *ops_memory_get_data(ops_memory_t *mem); - -#endif diff --git a/openpgpsdk/src/openpgpsdk/openssl_crypto.c b/openpgpsdk/src/openpgpsdk/openssl_crypto.c deleted file mode 100644 index 086dad77a..000000000 --- a/openpgpsdk/src/openpgpsdk/openssl_crypto.c +++ /dev/null @@ -1,913 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include "keyring_local.h" -#include - -#include - -static int debug=0; - -void test_secret_key(const ops_secret_key_t *skey) - { - RSA* test=RSA_new(); - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - test->n=BN_dup(skey->public_key.key.rsa.n); - test->e=BN_dup(skey->public_key.key.rsa.e); - test->d=BN_dup(skey->key.rsa.d); - - test->p=BN_dup(skey->key.rsa.p); - test->q=BN_dup(skey->key.rsa.q); -#else - RSA_set0_key(test, - BN_dup(skey->public_key.key.rsa.n), - BN_dup(skey->public_key.key.rsa.e), - BN_dup(skey->key.rsa.d)); - - RSA_set0_factors(test, BN_dup(skey->key.rsa.p), BN_dup(skey->key.rsa.q)); -#endif - - assert(RSA_check_key(test)==1); - RSA_free(test); - } - -static void md5_init(ops_hash_t *hash) - { - assert(!hash->data); - hash->data=malloc(sizeof(MD5_CTX)); - MD5_Init(hash->data); - } - -static void md5_add(ops_hash_t *hash,const unsigned char *data,unsigned length) - { - MD5_Update(hash->data,data,length); - } - -static unsigned md5_finish(ops_hash_t *hash,unsigned char *out) - { - MD5_Final(out,hash->data); - free(hash->data); - hash->data=NULL; - return 16; - } - -static ops_hash_t md5={OPS_HASH_MD5,MD5_DIGEST_LENGTH,"MD5",md5_init,md5_add, - md5_finish,NULL}; - -/** - \ingroup Core_Crypto - \brief Initialise to MD5 - \param hash Hash to initialise -*/ -void ops_hash_md5(ops_hash_t *hash) - { - *hash=md5; - } - -static void sha1_init(ops_hash_t *hash) - { - if (debug) - { - fprintf(stderr,"***\n***\nsha1_init\n***\n"); - } - assert(!hash->data); - hash->data=malloc(sizeof(SHA_CTX)); - SHA1_Init(hash->data); - } - -static void sha1_add(ops_hash_t *hash,const unsigned char *data, - unsigned length) - { - if (debug) - { - unsigned int i=0; - fprintf(stderr,"adding %d to hash:\n ", length); - for (i=0; idata,data,length); - } - -static unsigned sha1_finish(ops_hash_t *hash,unsigned char *out) - { - SHA1_Final(out,hash->data); - if (debug) - { - unsigned i=0; - fprintf(stderr,"***\n***\nsha1_finish\n***\n"); - for (i=0; idata); - hash->data=NULL; - return SHA_DIGEST_LENGTH; - } - -static ops_hash_t sha1={OPS_HASH_SHA1,SHA_DIGEST_LENGTH,"SHA1",sha1_init, - sha1_add,sha1_finish,NULL}; - -/** - \ingroup Core_Crypto - \brief Initialise to SHA1 - \param hash Hash to initialise -*/ -void ops_hash_sha1(ops_hash_t *hash) - { - *hash=sha1; - } - -static void sha256_init(ops_hash_t *hash) - { - if (debug) - { - fprintf(stderr,"***\n***\nsha256_init\n***\n"); - } - assert(!hash->data); - hash->data=malloc(sizeof(SHA256_CTX)); - SHA256_Init(hash->data); - } - -static void sha256_add(ops_hash_t *hash,const unsigned char *data, - unsigned length) - { - if (debug) - { - unsigned int i=0; - fprintf(stderr,"adding %d to hash:\n ", length); - for (i=0; idata,data,length); - } - -static unsigned sha256_finish(ops_hash_t *hash,unsigned char *out) - { - SHA256_Final(out,hash->data); - if (debug) - { - unsigned i=0; - fprintf(stderr,"***\n***\nsha1_finish\n***\n"); - for (i=0; idata); - hash->data=NULL; - return SHA256_DIGEST_LENGTH; - } - -static ops_hash_t sha256={OPS_HASH_SHA256,SHA256_DIGEST_LENGTH,"SHA256",sha256_init, - sha256_add,sha256_finish,NULL}; - -void ops_hash_sha256(ops_hash_t *hash) - { - *hash=sha256; - } - -/* - * SHA384 - */ - -static void sha384_init(ops_hash_t *hash) - { - if (debug) - { - fprintf(stderr,"***\n***\nsha384_init\n***\n"); - } - assert(!hash->data); - hash->data=malloc(sizeof(SHA512_CTX)); - SHA384_Init(hash->data); - } - -static void sha384_add(ops_hash_t *hash,const unsigned char *data, - unsigned length) - { - if (debug) - { - unsigned int i=0; - fprintf(stderr,"adding %d to hash:\n ", length); - for (i=0; idata,data,length); - } - -static unsigned sha384_finish(ops_hash_t *hash,unsigned char *out) - { - SHA384_Final(out,hash->data); - if (debug) - { - unsigned i=0; - fprintf(stderr,"***\n***\nsha1_finish\n***\n"); - for (i=0; idata); - hash->data=NULL; - return SHA384_DIGEST_LENGTH; - } - -static ops_hash_t sha384={OPS_HASH_SHA384,SHA384_DIGEST_LENGTH,"SHA384",sha384_init, - sha384_add,sha384_finish,NULL}; - -void ops_hash_sha384(ops_hash_t *hash) - { - *hash=sha384; - } - -/* - * SHA512 - */ - -static void sha512_init(ops_hash_t *hash) - { - if (debug) - { - fprintf(stderr,"***\n***\nsha512_init\n***\n"); - } - assert(!hash->data); - hash->data=malloc(sizeof(SHA512_CTX)); - SHA512_Init(hash->data); - } - -static void sha512_add(ops_hash_t *hash,const unsigned char *data, - unsigned length) - { - if (debug) - { - unsigned int i=0; - fprintf(stderr,"adding %d to hash:\n ", length); - for (i=0; idata,data,length); - } - -static unsigned sha512_finish(ops_hash_t *hash,unsigned char *out) - { - SHA512_Final(out,hash->data); - if (debug) - { - unsigned i=0; - fprintf(stderr,"***\n***\nsha1_finish\n***\n"); - for (i=0; idata); - hash->data=NULL; - return SHA512_DIGEST_LENGTH; - } - -static ops_hash_t sha512={OPS_HASH_SHA512,SHA512_DIGEST_LENGTH,"SHA512",sha512_init, - sha512_add,sha512_finish,NULL}; - -void ops_hash_sha512(ops_hash_t *hash) - { - *hash=sha512; - } - -/* - * SHA224 - */ - -static void sha224_init(ops_hash_t *hash) - { - if (debug) - { - fprintf(stderr,"***\n***\nsha1_init\n***\n"); - } - assert(!hash->data); - hash->data=malloc(sizeof(SHA256_CTX)); - SHA224_Init(hash->data); - } - -static void sha224_add(ops_hash_t *hash,const unsigned char *data, - unsigned length) - { - if (debug) - { - unsigned int i=0; - fprintf(stderr,"adding %d to hash:\n ", length); - for (i=0; idata,data,length); - } - -static unsigned sha224_finish(ops_hash_t *hash,unsigned char *out) - { - SHA224_Final(out,hash->data); - if (debug) - { - unsigned i=0; - fprintf(stderr,"***\n***\nsha1_finish\n***\n"); - for (i=0; idata); - hash->data=NULL; - return SHA224_DIGEST_LENGTH; - } - -static ops_hash_t sha224={OPS_HASH_SHA224,SHA224_DIGEST_LENGTH,"SHA224",sha224_init, - sha224_add,sha224_finish,NULL}; - -void ops_hash_sha224(ops_hash_t *hash) - { - *hash=sha224; - } - -ops_boolean_t already_said = ops_false ; - -ops_boolean_t ops_dsa_verify(const unsigned char *hash,size_t hash_length, - const ops_dsa_signature_t *sig, - const ops_dsa_public_key_t *dsa) - { - DSA_SIG *osig; - DSA *odsa; - int ret; - - osig=DSA_SIG_new(); - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - osig->r=sig->r; - osig->s=sig->s; -#else - DSA_SIG_set0(osig,BN_dup(sig->r),BN_dup(sig->s)) ; -#endif - - if(BN_num_bits(dsa->q) != 160) - { - if(!already_said) - { - fprintf(stderr,"(WW) ops_dsa_verify: openssl does only supports 'q' of 160 bits. Current is %d bits.\n",BN_num_bits(dsa->q)) ; - already_said=ops_true ; - } - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - osig->r=NULL; // in this case, the values are not copied. - osig->s=NULL; -#endif - - DSA_SIG_free(osig); - return ops_false ; - } - - odsa=DSA_new(); -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - odsa->p=dsa->p; - odsa->q=dsa->q; - odsa->g=dsa->g; - - odsa->pub_key=dsa->y; -#else - DSA_set0_pqg(odsa,BN_dup(dsa->p),BN_dup(dsa->q),BN_dup(dsa->g)); - DSA_set0_key(odsa,BN_dup(dsa->y),NULL) ; -#endif - - if (debug) - { - fprintf(stderr,"hash passed in:\n"); - unsigned i; - for (i=0; iq)); - unsigned int qlen=BN_num_bytes(dsa->q); - - if (qlen < hash_length) - hash_length=qlen; - // ret=DSA_do_verify(hash,hash_length,osig,odsa); - ret=DSA_do_verify(hash,hash_length,osig,odsa); - if (debug) - { - fprintf(stderr,"ret=%d\n",ret); - } - - if(ret < 0) - { - ERR_load_crypto_strings() ; - unsigned long err = 0 ; - while((err = ERR_get_error()) > 0) - fprintf(stderr,"DSA_do_verify(): ERR = %ld. lib error:\"%s\", func_error:\"%s\", reason:\"%s\"\n",err,ERR_lib_error_string(err),ERR_func_error_string(err),ERR_reason_error_string(err)) ; - //assert(ret >= 0); - return ops_false ; - } - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - osig->r=NULL; - osig->s=NULL; - - odsa->p=NULL; - odsa->q=NULL; - odsa->g=NULL; - odsa->pub_key=NULL; -#endif - - DSA_free(odsa); - DSA_SIG_free(osig); - - return ret != 0; - } - -/** - \ingroup Core_Crypto - \brief Recovers message digest from the signature - \param out Where to write decrypted data to - \param in Encrypted data - \param length Length of encrypted data - \param rsa RSA public key - \return size of recovered message digest -*/ -int ops_rsa_public_decrypt(unsigned char *out,const unsigned char *in, - size_t length,const ops_rsa_public_key_t *rsa) - { - RSA *orsa; - int n; - - orsa=RSA_new(); -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - orsa->n=rsa->n; - orsa->e=rsa->e; -#else - RSA_set0_key(orsa,BN_dup(rsa->n),BN_dup(rsa->e),NULL) ; -#endif - - n=RSA_public_decrypt(length,in,out,orsa,RSA_NO_PADDING); - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - orsa->n=orsa->e=NULL; -#endif - RSA_free(orsa); - - return n; - } - -/** - \ingroup Core_Crypto - \brief Signs data with RSA - \param out Where to write signature - \param in Data to sign - \param length Length of data - \param srsa RSA secret key - \param rsa RSA public key - \return number of bytes decrypted -*/ -int ops_rsa_private_encrypt(unsigned char *out,const unsigned char *in, - size_t length,const ops_rsa_secret_key_t *srsa, - const ops_rsa_public_key_t *rsa) - { - RSA *orsa; - int n; - - orsa=RSA_new(); -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - orsa->n=rsa->n; // XXX: do we need n? - orsa->d=srsa->d; - orsa->p=srsa->q; - orsa->q=srsa->p; - - /* debug */ - orsa->e=rsa->e; - - // If this isn't set, it's very likely that the programmer hasn't - // decrypted the secret key. RSA_check_key segfaults in that case. - // Use ops_decrypt_secret_key_from_data() to do that. - assert(orsa->d); -#else - RSA_set0_key(orsa,BN_dup(rsa->n),BN_dup(rsa->e),BN_dup(srsa->d)) ; - RSA_set0_factors(orsa,BN_dup(srsa->p),BN_dup(srsa->q)); -#endif - - assert(RSA_check_key(orsa) == 1); - /* end debug */ - - // WARNING: this function should *never* be called for direct encryption, because of the padding. - // It's actually only called in the signature function now, where an adapted padding is placed. - - n=RSA_private_encrypt(length,in,out,orsa,RSA_NO_PADDING); - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - orsa->n=orsa->d=orsa->p=orsa->q=NULL; - orsa->e=NULL; -#endif - RSA_free(orsa); - - return n; - } - -/** -\ingroup Core_Crypto -\brief Decrypts RSA-encrypted data -\param out Where to write the plaintext -\param in Encrypted data -\param length Length of encrypted data -\param srsa RSA secret key -\param rsa RSA public key -\return size of recovered plaintext -*/ -int ops_rsa_private_decrypt(unsigned char *out,const unsigned char *in, - size_t length,const ops_rsa_secret_key_t *srsa, - const ops_rsa_public_key_t *rsa) - { - RSA *orsa; - int n; - char errbuf[1024]; - - orsa=RSA_new(); -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - orsa->n=rsa->n; // XXX: do we need n? - orsa->d=srsa->d; - orsa->p=srsa->q; - orsa->q=srsa->p; - orsa->e=rsa->e; -#else - RSA_set0_key(orsa,BN_dup(rsa->n),BN_dup(rsa->e),BN_dup(srsa->d)) ; - RSA_set0_factors(orsa,BN_dup(srsa->p),BN_dup(srsa->q)); -#endif - - /* debug */ - assert(RSA_check_key(orsa) == 1); - /* end debug */ - - n=RSA_private_decrypt(length,in,out,orsa,RSA_NO_PADDING); - - // printf("ops_rsa_private_decrypt: n=%d\n",n); - - errbuf[0]='\0'; - if (n==-1) - { - unsigned long err=ERR_get_error(); - ERR_error_string(err,&errbuf[0]); - fprintf(stderr,"openssl error : %s\n",errbuf); - } -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - orsa->n=orsa->d=orsa->p=orsa->q=NULL; - orsa->e=NULL; -#endif - RSA_free(orsa); - - return n; - } - -/** - \ingroup Core_Crypto - \brief RSA-encrypts data - \param out Where to write the encrypted data - \param in Plaintext - \param length Size of plaintext - \param rsa RSA Public Key -*/ -int ops_rsa_public_encrypt(unsigned char *out,const unsigned char *in, - size_t length,const ops_rsa_public_key_t *rsa) - { - RSA *orsa; - int n; - - // printf("ops_rsa_public_encrypt: length=%ld\n", length); - - orsa=RSA_new(); -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - orsa->n=rsa->n; - orsa->e=rsa->e; -#else - RSA_set0_key(orsa,BN_dup(rsa->n),BN_dup(rsa->e),NULL); -#endif - - // printf("len: %ld\n", length); - // ops_print_bn("n: ", orsa->n); - // ops_print_bn("e: ", orsa->e); - n=RSA_public_encrypt(length,in,out,orsa,RSA_NO_PADDING); - - if (n==-1) - { - BIO *fd_out; - fd_out=BIO_new_fd(fileno(stderr), BIO_NOCLOSE); - ERR_print_errors(fd_out); - BIO_free(fd_out) ; - } - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - orsa->n=orsa->e=NULL; -#endif - RSA_free(orsa); - - return n; - } - -/** - \ingroup Core_Crypto - \brief initialises openssl - \note Would usually call ops_init() instead - \sa ops_init() -*/ -void ops_crypto_init() - { -#ifdef DMALLOC - CRYPTO_malloc_debug_init(); - CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL); - CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); -#endif - } - -/** - \ingroup Core_Crypto - \brief Finalise openssl - \note Would usually call ops_finish() instead - \sa ops_finish() -*/ -void ops_crypto_finish() - { - CRYPTO_cleanup_all_ex_data(); - // FIXME: what should we do instead (function is deprecated)? - // ERR_remove_state(0); -#ifdef DMALLOC - CRYPTO_mem_leaks_fp(stderr); -#endif - } - -/** - \ingroup Core_Hashes - \brief Get Hash name - \param hash Hash struct - \return Hash name -*/ -const char *ops_text_from_hash(ops_hash_t *hash) - { return hash->name; } - -/** - \ingroup HighLevel_KeyGenerate - \brief Generates an RSA keypair - \param numbits Modulus size - \param e Public Exponent - \param keydata Pointer to keydata struct to hold new key - \return ops_true if key generated successfully; otherwise ops_false - \note It is the caller's responsibility to call ops_keydata_free(keydata) -*/ -ops_boolean_t ops_rsa_generate_keypair(const int numbits, const unsigned long e, - ops_keydata_t* keydata) - { - ops_secret_key_t *skey=NULL; - RSA *rsa=RSA_new(); - BN_CTX *ctx=BN_CTX_new(); - BIGNUM *ebn=BN_new(); - - ops_keydata_init(keydata,OPS_PTAG_CT_SECRET_KEY); - skey=ops_get_writable_secret_key_from_data(keydata); - - // generate the key pair - - BN_set_word(ebn,e); - RSA_generate_key_ex(rsa,numbits,ebn,NULL); - - // populate ops key from ssl key - - skey->public_key.version=4; - skey->public_key.creation_time=time(NULL); - skey->public_key.days_valid=0; - skey->public_key.algorithm= OPS_PKA_RSA; - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - skey->public_key.key.rsa.n=BN_dup(rsa->n); - skey->public_key.key.rsa.e=BN_dup(rsa->e); - skey->key.rsa.d=BN_dup(rsa->d); -#else - const BIGNUM *nn=NULL,*ee=NULL,*dd=NULL ; - - RSA_get0_key(rsa,&nn,&ee,&dd) ; - - skey->public_key.key.rsa.n=BN_dup(nn) ; - skey->public_key.key.rsa.e=BN_dup(ee) ; - skey->key.rsa.d=BN_dup(dd) ; -#endif - - skey->s2k_usage=OPS_S2KU_ENCRYPTED_AND_HASHED; - skey->s2k_specifier=OPS_S2KS_SALTED; - //skey->s2k_specifier=OPS_S2KS_SIMPLE; - skey->algorithm=OPS_SA_CAST5; // \todo make param - skey->hash_algorithm=OPS_HASH_SHA1; // \todo make param - skey->octet_count=0; - skey->checksum=0; - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - skey->key.rsa.p=BN_dup(rsa->p); - skey->key.rsa.q=BN_dup(rsa->q); - skey->key.rsa.u=BN_mod_inverse(NULL,rsa->p, rsa->q, ctx); -#else - const BIGNUM *pp=NULL,*qq=NULL ; - - RSA_get0_factors(rsa,&pp,&qq) ; - - skey->key.rsa.p=BN_dup(pp); - skey->key.rsa.q=BN_dup(qq); - - skey->key.rsa.u=BN_mod_inverse(NULL,pp,qq, ctx); -#endif - assert(skey->key.rsa.u); - BN_CTX_free(ctx); - - RSA_free(rsa); - - ops_keyid(keydata->key_id, &keydata->key.skey.public_key); - ops_fingerprint(&keydata->fingerprint, &keydata->key.skey.public_key); - - // Generate checksum - - ops_create_info_t *cinfo=NULL; - ops_memory_t *mem=NULL; - - ops_setup_memory_write(&cinfo, &mem, 128); - - ops_push_skey_checksum_writer(cinfo, skey); - - switch(skey->public_key.algorithm) - { - // case OPS_PKA_DSA: - // return ops_write_mpi(key->key.dsa.x,info); - - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: - if(!ops_write_mpi(skey->key.rsa.d,cinfo) - || !ops_write_mpi(skey->key.rsa.p,cinfo) - || !ops_write_mpi(skey->key.rsa.q,cinfo) - || !ops_write_mpi(skey->key.rsa.u,cinfo)) - return ops_false; - break; - - // case OPS_PKA_ELGAMAL: - // return ops_write_mpi(key->key.elgamal.x,info); - - default: - assert(0); - break; - } - - // close rather than pop, since its the only one on the stack - ops_writer_close(cinfo); - ops_teardown_memory_write(cinfo, mem); - - // should now have checksum in skey struct - - // test - if (debug) - test_secret_key(skey); - - return ops_true; - } - -/** - \ingroup HighLevel_KeyGenerate - \brief Creates a self-signed RSA keypair - \param numbits Modulus size - \param e Public Exponent - \param userid User ID - \return The new keypair or NULL - - \note It is the caller's responsibility to call ops_keydata_free(keydata) - \sa ops_rsa_generate_keypair() - \sa ops_keydata_free() -*/ -ops_keydata_t* ops_rsa_create_selfsigned_keypair(const int numbits, const unsigned long e, ops_user_id_t * userid) - { - ops_keydata_t *keydata=NULL; - - keydata=ops_keydata_new(); - - if (ops_rsa_generate_keypair(numbits, e, keydata) != ops_true - || ops_add_selfsigned_userid_to_keydata(keydata, userid) != ops_true) - { - ops_keydata_free(keydata); - return NULL; - } - - return keydata; - } - -/* -int ops_dsa_size(const ops_dsa_public_key_t *dsa) - { - int size; - DSA *odsa; - odsa=DSA_new(); - odsa->p=dsa->p; - odsa->q=dsa->q; - odsa->g=dsa->g; - odsa->pub_key=dsa->y; - - DSAparams_print_fp(stderr, odsa); - size=DSA_size(odsa); - - odsa->p=odsa->q=odsa->g=odsa->pub_key=odsa->priv_key=NULL; - DSA_free(odsa); - - return size; - } -*/ - -DSA_SIG* ops_dsa_sign(unsigned char* hashbuf, unsigned hashsize, const ops_dsa_secret_key_t *sdsa, const ops_dsa_public_key_t *dsa) - { - DSA *odsa; - DSA_SIG *dsasig; - - odsa=DSA_new(); -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - odsa->p=dsa->p; - odsa->q=dsa->q; - odsa->g=dsa->g; - odsa->pub_key=dsa->y; - odsa->priv_key=sdsa->x; -#else - DSA_set0_pqg(odsa,BN_dup(dsa->p),BN_dup(dsa->q),BN_dup(dsa->g)); - DSA_set0_key(odsa,BN_dup(dsa->y),BN_dup(sdsa->x)); -#endif - - dsasig=DSA_do_sign(hashbuf,hashsize,odsa); - -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - odsa->p=odsa->q=odsa->g=odsa->pub_key=odsa->priv_key=NULL; -#endif - DSA_free(odsa); - - return dsasig; - } - -// eof diff --git a/openpgpsdk/src/openpgpsdk/opsdir.c b/openpgpsdk/src/openpgpsdk/opsdir.c deleted file mode 100644 index b966f090f..000000000 --- a/openpgpsdk/src/openpgpsdk/opsdir.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "opsdir.h" -#ifdef WIN32 -#include "opsstring.h" -#endif -#include - -int ops_open(const char* filename, int flag, int pmode) -{ -#ifdef WIN32 - wchar_t *wfilename = ConvertUtf8ToUtf16(filename); - if (!wfilename) - { - return -1; - } - - int result = _wopen(wfilename, flag, pmode); - free(wfilename); - - return result; -#else - return open(filename, flag, pmode); -#endif -} diff --git a/openpgpsdk/src/openpgpsdk/opsdir.h b/openpgpsdk/src/openpgpsdk/opsdir.h deleted file mode 100644 index 78f7ad8e8..000000000 --- a/openpgpsdk/src/openpgpsdk/opsdir.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef OPUTIL_H -#define OPUTIL_H - -int ops_open(const char* filename, int flag, int pmode); - -#endif diff --git a/openpgpsdk/src/openpgpsdk/opsstring.c b/openpgpsdk/src/openpgpsdk/opsstring.c deleted file mode 100644 index 6a0e2b072..000000000 --- a/openpgpsdk/src/openpgpsdk/opsstring.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "opsstring.h" - -#ifdef WIN32 -wchar_t *ConvertUtf8ToUtf16(const char* source) -{ - if (!source) { - return NULL; - } - -#ifdef WIN32 - int nbChars = MultiByteToWideChar(CP_UTF8, 0, source, -1, 0, 0); - if (nbChars == 0) { - return NULL; - } - - wchar_t* utf16Name = (wchar_t*) malloc(nbChars * sizeof(wchar_t)); - if (MultiByteToWideChar(CP_UTF8, 0, source, -1, utf16Name, nbChars) == 0) { - free(utf16Name); - return NULL; - } - - return utf16Name; -#else - // currently only for WIN32 - // convert code from rsstring.cc - return NULL; -#endif -} - -char* ConvertUtf16ToUtf8(const wchar_t *source) -{ - if (!source) { - return NULL; - } - -#ifdef WIN32 - int nbChars = WideCharToMultiByte(CP_UTF8, 0, source, -1, 0, 0, 0, 0); - if (nbChars == 0) { - return NULL; - } - - char* utf8Name = (char*) malloc(nbChars * sizeof(char)); - if (WideCharToMultiByte(CP_UTF8, 0, source, -1, utf8Name, nbChars, 0, 0) == 0) { - free(utf8Name); - return NULL; - } - - return utf8Name; -#else - // currently only for WIN32 - // convert code from rsstring.cc - return NULL; -#endif -} -#endif diff --git a/openpgpsdk/src/openpgpsdk/opsstring.h b/openpgpsdk/src/openpgpsdk/opsstring.h deleted file mode 100644 index 3bbaed494..000000000 --- a/openpgpsdk/src/openpgpsdk/opsstring.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef OPSSTRING_H -#define OPSSTRING_H - -#ifdef WIN32 -#include -#endif - -#ifdef WIN32 -// currently only for WIN32 - -// Convert strings between UTF8 and UTF16 -// Don't forget to free the returned string. -wchar_t* ConvertUtf8ToUtf16(const char *source); -char* ConvertUtf16ToUtf8(const wchar_t* source); -#endif - -#endif // OPSSTRING_H diff --git a/openpgpsdk/src/openpgpsdk/packet-parse.c b/openpgpsdk/src/openpgpsdk/packet-parse.c deleted file mode 100644 index e641eae41..000000000 --- a/openpgpsdk/src/openpgpsdk/packet-parse.c +++ /dev/null @@ -1,3477 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - * \brief Parser for OpenPGP packets - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "parse_local.h" - -#include -#include -#include -#ifndef WIN32 -#include -#endif -#include -#include - -#include - -static int debug=0; -static const size_t MAX_RECURSIVE_COMPRESSION_DEPTH = 32 ; - -/** - * limited_read_data reads the specified amount of the subregion's data - * into a data_t structure - * - * \param data Empty structure which will be filled with data - * \param len Number of octets to read - * \param subregion - * \param pinfo How to parse - * - * \return 1 on success, 0 on failure - */ -static int limited_read_data(ops_data_t *data,unsigned int len, - ops_region_t *subregion,ops_parse_info_t *pinfo) -{ - data->len = len; - - if(!(subregion->length-subregion->length_read >= len)) // ASSERT(subregion->length-subregion->length_read >= len); - { - fprintf(stderr,"Data length error: announced size %d larger than expected size %d. Giving up.",len,subregion->length-subregion->length_read) ; - return 0 ; - } - - data->contents=malloc(data->len); - if (!data->contents) - return 0; - - if (!ops_limited_read(data->contents, data->len,subregion,&pinfo->errors, - &pinfo->rinfo,&pinfo->cbinfo)) - return 0; - - return 1; -} - -/** - * read_data reads the remainder of the subregion's data - * into a data_t structure - * - * \param data - * \param subregion - * \param pinfo - * - * \return 1 on success, 0 on failure - */ -static int read_data(ops_data_t *data,ops_region_t *subregion, - ops_parse_info_t *pinfo) - { - int len; - - len=subregion->length-subregion->length_read; - - if ( len >= 0 ) { - return(limited_read_data(data,len,subregion,pinfo)); - } - return 0; - } - -/** - * Reads the remainder of the subregion as a string. - * It is the user's responsibility to free the memory allocated here. - */ - -static int read_unsigned_string(unsigned char **str,ops_region_t *subregion, - ops_parse_info_t *pinfo) - { - int len=0; - - len=subregion->length-subregion->length_read; - - *str=malloc(len+1); - if(!(*str)) - return 0; - - if(len && !ops_limited_read(*str,len,subregion,&pinfo->errors, - &pinfo->rinfo,&pinfo->cbinfo)) - return 0; - - /*! ensure the string is NULL-terminated */ - - (*str)[len]='\0'; - - return 1; - } - -static int read_string(char **str, ops_region_t *subregion, ops_parse_info_t *pinfo) - { - return (read_unsigned_string((unsigned char **)str, subregion, pinfo)); - } - -void ops_init_subregion(ops_region_t *subregion,ops_region_t *region) - { - memset(subregion,'\0',sizeof *subregion); - subregion->parent=region; - } - -/*! macro to save typing */ -#define C content.content - -/* XXX: replace ops_ptag_t with something more appropriate for limiting - reads */ - -/** - * low-level function to read data from reader function - * - * Use this function, rather than calling the reader directly. - * - * If the accumulate flag is set in *pinfo, the function - * adds the read data to the accumulated data, and updates - * the accumulated length. This is useful if, for example, - * the application wants access to the raw data as well as the - * parsed data. - * - * This function will also try to read the entire amount asked for, but not - * if it is over INT_MAX. Obviously many callers will know that they - * never ask for that much and so can avoid the extra complexity of - * dealing with return codes and filled-in lengths. - * - * \param *dest - * \param *plength - * \param flags - * \param *pinfo - * - * \return OPS_R_OK - * \return OPS_R_PARTIAL_READ - * \return OPS_R_EOF - * \return OPS_R_EARLY_EOF - * - * \sa #ops_reader_ret_t for details of return codes - */ - -static int sub_base_read(void *dest,size_t length,ops_error_t **errors, - ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo) -{ - size_t n; - - /* reading more than this would look like an error */ - if(length > INT_MAX) - length=INT_MAX; - - for(n=0 ; n < length ; ) - { - int r=rinfo->reader((char*)dest+n,length-n,errors,rinfo,cbinfo); - - if(!(r <= (int)(length-n))) // ASSERT(r <= (int)(length-n)) - { - fprintf(stderr,"sub_base_read: error in length. Read %d, remaining length is %d",r,(int)(length-n)) ; - return -1 ; - } - - // XXX: should we save the error and return what was read so far? - // - if(r < 0) - return r; - - if(r == 0) - break; - - n+=r; - } - - if(n == 0) - return 0; - - if(rinfo->accumulate) - { - if(!(rinfo->asize >= rinfo->alength)) // ASSERT(rinfo->asize >= rinfo->alength) - { - fprintf(stderr,"sub_base_read: error in accumulated length.") ; - return -1 ; - } - - if(rinfo->alength+n > rinfo->asize) - { - rinfo->asize=rinfo->asize*2+n; - rinfo->accumulated=realloc(rinfo->accumulated,rinfo->asize); - } - if(!(rinfo->asize >= rinfo->alength+n)) // ASSERT(rinfo->asize >= rinfo->alength+n) - { - fprintf(stderr,"sub_base_read: error in accumulated length.") ; - return -1 ; - } - - memcpy(rinfo->accumulated+rinfo->alength,dest,n); - } - // we track length anyway, because it is used for packet offsets - rinfo->alength+=n; - // and also the position - rinfo->position+=n; - - return n; -} - -int ops_stacked_read(void *dest,size_t length,ops_error_t **errors, - ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo) - { return sub_base_read(dest,length,errors,rinfo->next,cbinfo); } - -/* This will do a full read so long as length < MAX_INT */ -static int base_read(unsigned char *dest,size_t length, - ops_parse_info_t *pinfo) - { - return sub_base_read(dest,length,&pinfo->errors,&pinfo->rinfo, - &pinfo->cbinfo); - } - -/* Read a full size_t's worth. If the return is < than length, then - * *last_read tells you why - < 0 for an error, == 0 for EOF */ - -static size_t full_read(unsigned char *dest,size_t length,int *last_read, - ops_error_t **errors,ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo) - { - size_t t; - int r=0; /* preset in case some loon calls with length == 0 */ - - for(t=0 ; t < length ; ) - { - r=sub_base_read(dest+t,length-t,errors,rinfo,cbinfo); - - if(r <= 0) - { - *last_read=r; - return t; - } - - t+=r; - } - - *last_read=r; - - return t; - } - - - -/** Read a scalar value of selected length from reader. - * - * Read an unsigned scalar value from reader in Big Endian representation. - * - * This function does not know or care about packet boundaries. It - * also assumes that an EOF is an error. - * - * \param *result The scalar value is stored here - * \param *reader Our reader - * \param length How many bytes to read - * \return ops_true on success, ops_false on failure - */ -static ops_boolean_t _read_scalar(unsigned *result,unsigned length, - ops_parse_info_t *pinfo) - { - unsigned t=0; - - if(! (length <= sizeof(*result))) // ASSERT(length <= sizeof(*result)) - { - fprintf(stderr,"_read_scalar: length to read is larger than buffer size.") ; - return ops_false ; - } - - while(length--) - { - unsigned char c[1]; - int r; - - r=base_read(c,1,pinfo); - if(r != 1) - return ops_false; - t=(t << 8)+c[0]; - } - - *result=t; - return ops_true; - } - -/** - * \ingroup Core_ReadPackets - * \brief Read bytes from a region within the packet. - * - * Read length bytes into the buffer pointed to by *dest. - * Make sure we do not read over the packet boundary. - * Updates the Packet Tag's ops_ptag_t::length_read. - * - * If length would make us read over the packet boundary, or if - * reading fails, we call the callback with an error. - * - * Note that if the region is indeterminate, this can return a short - * read - check region->last_read for the length. EOF is indicated by - * a success return and region->last_read == 0 in this case (for a - * region of known length, EOF is an error). - * - * This function makes sure to respect packet boundaries. - * - * \param dest The destination buffer - * \param length How many bytes to read - * \param region Pointer to packet region - * \param errors Error stack - * \param rinfo Reader info - * \param cbinfo Callback info - * \return ops_true on success, ops_false on error - */ -ops_boolean_t ops_limited_read(unsigned char *dest,size_t length, - ops_region_t *region,ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo) -{ - size_t r; - int lr; - - if(!region->indeterminate && region->length_read+length > region->length) - { - OPS_ERROR(errors,OPS_E_P_NOT_ENOUGH_DATA,"Not enough data"); - return ops_false; - } - - r=full_read(dest,length,&lr,errors,rinfo,cbinfo); - - if(lr < 0) - { - OPS_ERROR(errors,OPS_E_R_READ_FAILED,"Read failed"); - return ops_false; - } - - if(!region->indeterminate && r != length) - { - OPS_ERROR(errors,OPS_E_R_READ_FAILED,"Read failed"); - return ops_false; - } - - region->last_read=r; - do - { - region->length_read+=r; - - if(!(!region->parent || region->length <= region->parent->length)) // ASSERT(!region->parent || region->length <= region->parent->length) - { - OPS_ERROR(errors,OPS_E_R_READ_FAILED,"Read failed"); - return ops_false; - } - } - while((region=region->parent)); - - return ops_true; -} - -/** - \ingroup Core_ReadPackets - \brief Call ops_limited_read on next in stack -*/ -ops_boolean_t ops_stacked_limited_read(void *dest, unsigned length, - ops_region_t *region, - ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo) - { - return ops_limited_read(dest, length, region, errors, rinfo->next, cbinfo); - } - -static ops_boolean_t limited_read(unsigned char *dest,unsigned length, - ops_region_t *region,ops_parse_info_t *info) - { - return ops_limited_read(dest,length,region,&info->errors, - &info->rinfo,&info->cbinfo); - } - -static ops_boolean_t exact_limited_read(unsigned char *dest,unsigned length, - ops_region_t *region, - ops_parse_info_t *pinfo) - { - ops_boolean_t ret; - - pinfo->exact_read=ops_true; - ret=limited_read(dest,length,region,pinfo); - pinfo->exact_read=ops_false; - - return ret; - } - -/** Skip over length bytes of this packet. - * - * Calls limited_read() to skip over some data. - * - * This function makes sure to respect packet boundaries. - * - * \param length How many bytes to skip - * \param *region Pointer to packet region - * \param *pinfo How to parse - * \return 1 on success, 0 on error (calls the cb with OPS_PARSER_ERROR in limited_read()). - */ -static int limited_skip(unsigned length,ops_region_t *region, - ops_parse_info_t *pinfo) - { - unsigned char buf[8192]; - - while(length) - { - int n=length%8192; - if(!limited_read(buf,n,region,pinfo)) - return 0; - length-=n; - } - return 1; - } - -/** Read a scalar. - * - * Read a big-endian scalar of length bytes, respecting packet - * boundaries (by calling limited_read() to read the raw data). - * - * This function makes sure to respect packet boundaries. - * - * \param *dest The scalar value is stored here - * \param length How many bytes make up this scalar (at most 4) - * \param *region Pointer to current packet region - * \param *pinfo How to parse - * \param *cb The callback - * \return 1 on success, 0 on error (calls the cb with OPS_PARSER_ERROR in limited_read()). - * - * \see RFC4880 3.1 - */ -static int limited_read_scalar(unsigned *dest,unsigned length, - ops_region_t *region, - ops_parse_info_t *pinfo) -{ - unsigned char c[4]=""; - unsigned t; - unsigned n; - - if(!(length <= 4)) // ASSERT(length <= 4) - { - fprintf(stderr,"limited_read_scalar: wrong size for scalar %d\n",length) ; - return ops_false ; - } - if(!(sizeof(*dest) >= 4)) // ASSERT(sizeof(*dest) >= 4) - { - fprintf(stderr,"limited_read_scalar: wrong size for dest %lu\n",sizeof(*dest)) ; - return ops_false ; - } - if(!limited_read(c,length,region,pinfo)) - return 0; - - for(t=0,n=0 ; n < length ; ++n) - t=(t << 8)+c[n]; - *dest=t; - - return 1; -} - -/** Read a scalar. - * - * Read a big-endian scalar of length bytes, respecting packet - * boundaries (by calling limited_read() to read the raw data). - * - * The value read is stored in a size_t, which is a different size - * from an unsigned on some platforms. - * - * This function makes sure to respect packet boundaries. - * - * \param *dest The scalar value is stored here - * \param length How many bytes make up this scalar (at most 4) - * \param *region Pointer to current packet region - * \param *pinfo How to parse - * \param *cb The callback - * \return 1 on success, 0 on error (calls the cb with OPS_PARSER_ERROR in limited_read()). - * - * \see RFC4880 3.1 - */ -static int limited_read_size_t_scalar(size_t *dest,unsigned length, - ops_region_t *region, - ops_parse_info_t *pinfo) -{ - unsigned tmp; - - if(!(sizeof(*dest) >= 4)) // ASSERT(sizeof(*dest) >= 4) - { - fprintf(stderr,"limited_read_scalar: wrong dest size for scalar %lu\n",sizeof(*dest)) ; - return ops_false ; - } - - /* Note that because the scalar is at most 4 bytes, we don't care - if size_t is bigger than usigned */ - if(!limited_read_scalar(&tmp,length,region,pinfo)) - return 0; - - *dest=tmp; - return 1; -} - -/** Read a timestamp. - * - * Timestamps in OpenPGP are unix time, i.e. seconds since The Epoch (1.1.1970). They are stored in an unsigned scalar - * of 4 bytes. - * - * This function reads the timestamp using limited_read_scalar(). - * - * This function makes sure to respect packet boundaries. - * - * \param *dest The timestamp is stored here - * \param *ptag Pointer to current packet's Packet Tag. - * \param *reader Our reader - * \param *cb The callback - * \return see limited_read_scalar() - * - * \see RFC4880 3.5 - */ -static int limited_read_time(time_t *dest,ops_region_t *region, - ops_parse_info_t *pinfo) -{ - /* - * Cannot assume that time_t is 4 octets long - - * there is at least one architecture (SunOS 5.10) where it is 8. - */ - if (sizeof(*dest)==4) - { - return limited_read_scalar((unsigned *)dest,4,region,pinfo); - } - else - { - time_t mytime=0; - int i=0; - unsigned char c[1]; - for (i=0; i<4; i++) - { - if (!limited_read(c,1,region,pinfo)) - return 0; - mytime=(mytime << 8) + c[0]; - } - *dest=mytime; - return 1; - } -} - -/** - * \ingroup Core_MPI - * Read a multiprecision integer. - * - * Large numbers (multiprecision integers, MPI) are stored in OpenPGP in two parts. First there is a 2 byte scalar - * indicating the length of the following MPI in Bits. Then follow the bits that make up the actual number, most - * significant bits first (Big Endian). The most significant bit in the MPI is supposed to be 1 (unless the MPI is - * encrypted - then it may be different as the bit count refers to the plain text but the bits are encrypted). - * - * Unused bits (i.e. those filling up the most significant byte from the left to the first bits that counts) are - * supposed to be cleared - I guess. XXX - does anything actually say so? - * - * This function makes sure to respect packet boundaries. - * - * \param **pgn return the integer there - the BIGNUM is created by BN_bin2bn() and probably needs to be freed - * by the caller XXX right ben? - * \param *ptag Pointer to current packet's Packet Tag. - * \param *reader Our reader - * \param *cb The callback - * \return 1 on success, 0 on error (by limited_read_scalar() or limited_read() or if the MPI is not properly formed (XXX - * see comment below - the callback is called with a OPS_PARSER_ERROR in case of an error) - * - * \see RFC4880 3.2 - */ -static int limited_read_mpi(BIGNUM **pbn,ops_region_t *region, - ops_parse_info_t *pinfo) - { - unsigned length; - unsigned nonzero; - unsigned char buf[8192]=""; /* an MPI has a 2 byte length part. Length - is given in bits, so the largest we should - ever need for the buffer is 8192 bytes. */ - ops_boolean_t ret; - - pinfo->reading_mpi_length=ops_true; - ret=limited_read_scalar(&length,2,region,pinfo); - - pinfo->reading_mpi_length=ops_false; - if(!ret) - return 0; - - nonzero=length&7; /* there should be this many zero bits in the MS byte */ - if(!nonzero) - nonzero=8; - length=(length+7)/8; - - if(!(length <= 8192)) // ASSERT(length <= 8192) - { - fprintf(stderr,"limited_read_mpi: wrong size to read %d > 8192",length) ; - return 0 ; - } - - if(!limited_read(buf,length,region,pinfo)) - return 0; - - if((buf[0] >> nonzero) != 0 || !(buf[0]&(1 << (nonzero-1)))) - { - OPS_ERROR(&pinfo->errors,OPS_E_P_MPI_FORMAT_ERROR,"MPI Format error"); /* XXX: Ben, one part of this constraint does not apply to encrypted MPIs the draft says. -- peter */ - return 0; - } - - *pbn=BN_bin2bn(buf,length,NULL); - return 1; - } - -/** Read some data with a New-Format length from reader. - * - * \sa Internet-Draft RFC4880.txt Section 4.2.2 - * - * \param *length Where the decoded length will be put - * \param *pinfo How to parse - * \return ops_true if OK, else ops_false - * - */ - -static ops_boolean_t read_new_length(unsigned *length,ops_parse_info_t *pinfo) - { - unsigned char c[1]; - - if(base_read(c,1,pinfo) != 1) - return ops_false; - if(c[0] < 192) - { - // 1. One-octet packet - *length=c[0]; - return ops_true; - } - - else if (c[0]>=192 && c[0]<=223) - { - // 2. Two-octet packet - unsigned t=(c[0]-192) << 8; - - if(base_read(c,1,pinfo) != 1) - return ops_false; - *length=t+c[0]+192; - return ops_true; - } - - else if (c[0]==255) - { - // 3. Five-Octet packet - return _read_scalar(length,4,pinfo); - } - - else if (c[0]>=224 && c[0]<255) - { - // 4. Partial Body Length - OPS_ERROR(&pinfo->errors,OPS_E_UNIMPLEMENTED, - "New format Partial Body Length fields not yet implemented"); - return ops_false; - } - return ops_false; - } - -/** Read the length information for a new format Packet Tag. - * - * New style Packet Tags encode the length in one to five octets. This function reads the right amount of bytes and - * decodes it to the proper length information. - * - * This function makes sure to respect packet boundaries. - * - * \param *length return the length here - * \param *ptag Pointer to current packet's Packet Tag. - * \param *reader Our reader - * \param *cb The callback - * \return 1 on success, 0 on error (by limited_read_scalar() or limited_read() or if the MPI is not properly formed (XXX - * see comment below) - * - * \see RFC4880 4.2.2 - * \see ops_ptag_t - */ -static int limited_read_new_length(unsigned *length,ops_region_t *region, - ops_parse_info_t *pinfo) - { - unsigned char c[1]=""; - - if(!limited_read(c,1,region,pinfo)) - return 0; - if(c[0] < 192) - { - *length=c[0]; - return 1; - } - if(c[0] < 255) - { - unsigned t=(c[0]-192) << 8; - - if(!limited_read(c,1,region,pinfo)) - return 0; - *length=t+c[0]+192; - return 1; - } - return limited_read_scalar(length,4,region,pinfo); - } - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -static void data_free(ops_data_t *data) - { - free(data->contents); - data->contents=NULL; - data->len=0; - } - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -static void string_free(char **str) - { - free(*str); - *str=NULL; - } - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -/*! Free packet memory, set pointer to NULL */ -void ops_packet_free(ops_packet_t *packet) - { - free(packet->raw); - packet->raw=NULL; - } - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -void ops_headers_free(ops_headers_t *headers) - { - unsigned n; - - for(n=0 ; n < headers->nheaders ; ++n) - { - free(headers->headers[n].key); - free(headers->headers[n].value); - } - free(headers->headers); - headers->headers=NULL; - } - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -void ops_signed_cleartext_trailer_free(ops_signed_cleartext_trailer_t *trailer) - { - free(trailer->hash); - trailer->hash=NULL; - } - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -void ops_cmd_get_passphrase_free(ops_secret_key_passphrase_t *skp) - { - if (skp->passphrase && *skp->passphrase) - { - free(*skp->passphrase); - *skp->passphrase=NULL; - } - } - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -/*! Free any memory allocated when parsing the packet content */ -void ops_parser_content_free(ops_parser_content_t *c) -{ - switch(c->tag) - { - case OPS_PARSER_PTAG: - case OPS_PTAG_CT_COMPRESSED: - case OPS_PTAG_SS_CREATION_TIME: - case OPS_PTAG_SS_EXPIRATION_TIME: - case OPS_PTAG_SS_KEY_EXPIRATION_TIME: - case OPS_PTAG_SS_TRUST: - case OPS_PTAG_SS_ISSUER_KEY_ID: - case OPS_PTAG_CT_ONE_PASS_SIGNATURE: - case OPS_PTAG_SS_PRIMARY_USER_ID: - case OPS_PTAG_SS_REVOCABLE: - case OPS_PTAG_SS_REVOCATION_KEY: - case OPS_PTAG_CT_LITERAL_DATA_HEADER: - case OPS_PTAG_CT_LITERAL_DATA_BODY: - case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY: - case OPS_PTAG_CT_UNARMOURED_TEXT: - case OPS_PTAG_CT_ARMOUR_TRAILER: - case OPS_PTAG_CT_SIGNATURE_HEADER: - case OPS_PTAG_CT_SE_DATA_HEADER: - case OPS_PTAG_CT_SE_IP_DATA_HEADER: - case OPS_PTAG_CT_SE_IP_DATA_BODY: - case OPS_PTAG_CT_MDC: - case OPS_PARSER_CMD_GET_SECRET_KEY: - break; - - case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER: - ops_headers_free(&c->content.signed_cleartext_header.headers); - break; - - case OPS_PTAG_CT_ARMOUR_HEADER: - ops_headers_free(&c->content.armour_header.headers); - break; - - case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER: - ops_signed_cleartext_trailer_free(&c->content.signed_cleartext_trailer); - break; - - case OPS_PTAG_CT_TRUST: - ops_trust_free(&c->content.trust); - break; - - case OPS_PTAG_CT_SIGNATURE: - case OPS_PTAG_CT_SIGNATURE_FOOTER: - ops_signature_free(&c->content.signature); - break; - - case OPS_PTAG_CT_PUBLIC_KEY: - case OPS_PTAG_CT_PUBLIC_SUBKEY: - ops_public_key_free(&c->content.public_key); - break; - - case OPS_PTAG_CT_USER_ID: - ops_user_id_free(&c->content.user_id); - break; - - case OPS_PTAG_SS_SIGNERS_USER_ID: - ops_user_id_free(&c->content.ss_signers_user_id); - break; - - case OPS_PTAG_CT_USER_ATTRIBUTE: - ops_user_attribute_free(&c->content.user_attribute); - break; - - case OPS_PTAG_SS_PREFERRED_SKA: - ops_ss_preferred_ska_free(&c->content.ss_preferred_ska); - break; - - case OPS_PTAG_SS_PREFERRED_HASH: - ops_ss_preferred_hash_free(&c->content.ss_preferred_hash); - break; - - case OPS_PTAG_SS_PREFERRED_COMPRESSION: - ops_ss_preferred_compression_free(&c->content.ss_preferred_compression); - break; - - case OPS_PTAG_SS_KEY_FLAGS: - ops_ss_key_flags_free(&c->content.ss_key_flags); - break; - - case OPS_PTAG_SS_KEY_SERVER_PREFS: - ops_ss_key_server_prefs_free(&c->content.ss_key_server_prefs); - break; - - case OPS_PTAG_SS_FEATURES: - ops_ss_features_free(&c->content.ss_features); - break; - - case OPS_PTAG_SS_NOTATION_DATA: - ops_ss_notation_data_free(&c->content.ss_notation_data); - break; - - case OPS_PTAG_SS_REGEXP: - ops_ss_regexp_free(&c->content.ss_regexp); - break; - - case OPS_PTAG_SS_POLICY_URI: - ops_ss_policy_url_free(&c->content.ss_policy_url); - break; - - case OPS_PTAG_SS_PREFERRED_KEY_SERVER: - ops_ss_preferred_key_server_free(&c->content.ss_preferred_key_server); - break; - - case OPS_PTAG_SS_USERDEFINED00: - case OPS_PTAG_SS_USERDEFINED01: - case OPS_PTAG_SS_USERDEFINED02: - case OPS_PTAG_SS_USERDEFINED03: - case OPS_PTAG_SS_USERDEFINED04: - case OPS_PTAG_SS_USERDEFINED05: - case OPS_PTAG_SS_USERDEFINED06: - case OPS_PTAG_SS_USERDEFINED07: - case OPS_PTAG_SS_USERDEFINED08: - case OPS_PTAG_SS_USERDEFINED09: - case OPS_PTAG_SS_USERDEFINED10: - ops_ss_userdefined_free(&c->content.ss_userdefined); - break; - - case OPS_PTAG_SS_RESERVED: - ops_ss_reserved_free(&c->content.ss_unknown); - break; - - case OPS_PTAG_SS_REVOCATION_REASON: - ops_ss_revocation_reason_free(&c->content.ss_revocation_reason); - break; - - case OPS_PTAG_SS_EMBEDDED_SIGNATURE: - ops_ss_embedded_signature_free(&c->content.ss_embedded_signature); - break; - - case OPS_PARSER_PACKET_END: - ops_packet_free(&c->content.packet); - break; - - case OPS_PARSER_ERROR: - case OPS_PARSER_ERRCODE: - break; - - case OPS_PTAG_CT_SECRET_KEY: - case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY: - ops_secret_key_free(&c->content.secret_key); - break; - - case OPS_PTAG_CT_PK_SESSION_KEY: - case OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY: - ops_pk_session_key_free(&c->content.pk_session_key); - break; - - case OPS_PARSER_CMD_GET_SK_PASSPHRASE: - case OPS_PARSER_CMD_GET_SK_PASSPHRASE_PREV_WAS_BAD: - ops_cmd_get_passphrase_free(&c->content.secret_key_passphrase); - break; - - default: - fprintf(stderr,"Can't free %d (0x%x)\n",c->tag,c->tag); - //ASSERT(0); - } -} - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -static void free_BN(BIGNUM **pp) - { - BN_free(*pp); - *pp=NULL; - } - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -void ops_pk_session_key_free(ops_pk_session_key_t *sk) -{ - switch(sk->algorithm) - { - case OPS_PKA_RSA: - free_BN(&sk->parameters.rsa.encrypted_m); - break; - - case OPS_PKA_ELGAMAL: - free_BN(&sk->parameters.elgamal.g_to_k); - free_BN(&sk->parameters.elgamal.encrypted_m); - break; - - default: - fprintf(stderr,"ops_pk_session_key_free: Unknown algorithm: %d \n",sk->algorithm); - //ASSERT(0); - } -} - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -/*! Free the memory used when parsing a public key */ -void ops_public_key_free(ops_public_key_t *p) -{ - switch(p->algorithm) - { - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: - free_BN(&p->key.rsa.n); - free_BN(&p->key.rsa.e); - break; - - case OPS_PKA_DSA: - free_BN(&p->key.dsa.p); - free_BN(&p->key.dsa.q); - free_BN(&p->key.dsa.g); - free_BN(&p->key.dsa.y); - break; - - case OPS_PKA_ELGAMAL: - case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - free_BN(&p->key.elgamal.p); - free_BN(&p->key.elgamal.g); - free_BN(&p->key.elgamal.y); - break; - - default: - fprintf(stderr,"ops_public_key_free: Unknown algorithm: %d \n",p->algorithm); - //ASSERT(0); - } -} - -void ops_public_key_copy(ops_public_key_t *dst,const ops_public_key_t *src) -{ - *dst = *src ; - - switch(src->algorithm) - { - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: - dst->key.rsa.n = BN_dup(src->key.rsa.n); - dst->key.rsa.e = BN_dup(src->key.rsa.e); - break; - - case OPS_PKA_DSA: - dst->key.dsa.p = BN_dup(src->key.dsa.p); - dst->key.dsa.q = BN_dup(src->key.dsa.q); - dst->key.dsa.g = BN_dup(src->key.dsa.g); - dst->key.dsa.y = BN_dup(src->key.dsa.y); - break; - - case OPS_PKA_ELGAMAL: - case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - dst->key.elgamal.p = BN_dup(src->key.elgamal.p); - dst->key.elgamal.g = BN_dup(src->key.elgamal.g); - dst->key.elgamal.y = BN_dup(src->key.elgamal.y); - break; - - //case 0: - // nothing to free - // break; - - default: - fprintf(stderr,"ops_public_key_copy: Unknown algorithm: %d \n",src->algorithm); - //ASSERT(0); - } -} -/** - \ingroup Core_ReadPackets -*/ -static int parse_public_key_data(ops_public_key_t *key,ops_region_t *region, - ops_parse_info_t *pinfo) -{ - unsigned char c[1]=""; - - if(!(region->length_read == 0)) // ASSERT(region->length_read == 0) /* We should not have read anything so far */ - { - fprintf(stderr,"parse_public_key_data: read length error\n") ; - return 0 ; - } - - if(!limited_read(c,1,region,pinfo)) - return 0; - key->version=c[0]; - if(key->version < 2 || key->version > 4) - { - OPS_ERROR_1(&pinfo->errors,OPS_E_PROTO_BAD_PUBLIC_KEY_VRSN, - "Bad public key version (0x%02x)",key->version); - return 0; - } - - if(!limited_read_time(&key->creation_time,region,pinfo)) - return 0; - - key->days_valid=0; - if((key->version == 2 || key->version == 3) - && !limited_read_scalar(&key->days_valid,2,region,pinfo)) - return 0; - - if(!limited_read(c,1,region,pinfo)) - return 0; - - key->algorithm=c[0]; - - switch(key->algorithm) - { - case OPS_PKA_DSA: - if(!limited_read_mpi(&key->key.dsa.p,region,pinfo) - || !limited_read_mpi(&key->key.dsa.q,region,pinfo) - || !limited_read_mpi(&key->key.dsa.g,region,pinfo) - || !limited_read_mpi(&key->key.dsa.y,region,pinfo)) - return 0; - break; - - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: - if(!limited_read_mpi(&key->key.rsa.n,region,pinfo) - || !limited_read_mpi(&key->key.rsa.e,region,pinfo)) - return 0; - break; - - case OPS_PKA_ELGAMAL: - case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - if(!limited_read_mpi(&key->key.elgamal.p,region,pinfo) - || !limited_read_mpi(&key->key.elgamal.g,region,pinfo) - || !limited_read_mpi(&key->key.elgamal.y,region,pinfo)) - return 0; - break; - - default: - OPS_ERROR_1(&pinfo->errors,OPS_E_ALG_UNSUPPORTED_PUBLIC_KEY_ALG,"Unsupported Public Key algorithm (%s)",ops_show_pka(key->algorithm)); - return 0; - } - - return 1; -} - - -/** - * \ingroup Core_ReadPackets - * \brief Parse a public key packet. - * - * This function parses an entire v3 (== v2) or v4 public key packet for RSA, ElGamal, and DSA keys. - * - * Once the key has been parsed successfully, it is passed to the callback. - * - * \param *ptag Pointer to the current Packet Tag. This function should consume the entire packet. - * \param *reader Our reader - * \param *cb The callback - * \return 1 on success, 0 on error - * - * \see RFC4880 5.5.2 - */ -static int parse_public_key(ops_content_tag_t tag,ops_region_t *region, - ops_parse_info_t *pinfo) - { - ops_parser_content_t content; - - if(!parse_public_key_data(&C.public_key,region,pinfo)) - return 0; - - // XXX: this test should be done for all packets, surely? - if(region->length_read != region->length) - { - OPS_ERROR_1(&pinfo->errors,OPS_E_R_UNCONSUMED_DATA, - "Unconsumed data (%d)", region->length-region->length_read); - return 0; - } - - CBP(pinfo,tag,&content); - - return 1; - } - - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -/*! Free the memory used when parsing this signature sub-packet type */ -void ops_ss_regexp_free(ops_ss_regexp_t *regexp) - { - string_free(®exp->text); - } - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -/*! Free the memory used when parsing this signature sub-packet type */ -void ops_ss_policy_url_free(ops_ss_policy_url_t *policy_url) - { - string_free(&policy_url->text); - } - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -/*! Free the memory used when parsing this signature sub-packet type */ -void ops_ss_preferred_key_server_free(ops_ss_preferred_key_server_t *preferred_key_server) - { - string_free(&preferred_key_server->text); - } - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -/*! Free the memory used when parsing this packet type */ -void ops_user_attribute_free(ops_user_attribute_t *user_att) - { - data_free(&user_att->data); - } - -/** - * \ingroup Core_ReadPackets - * \brief Parse one user attribute packet. - * - * User attribute packets contain one or more attribute subpackets. - * For now, handle the whole packet as raw data. - */ - -static int parse_user_attribute(ops_region_t *region, ops_parse_info_t *pinfo) -{ - - ops_parser_content_t content; - - /* xxx- treat as raw data for now. Could break down further - into attribute sub-packets later - rachel */ - - if(!(region->length_read == 0)) // ASSERT(region->length_read == 0) /* We should not have read anything so far */ - { - fprintf(stderr,"parse_user_attribute: read length error\n") ; - return 0 ; - } - - if(!read_data(&C.user_attribute.data,region,pinfo)) - return 0; - - CBP(pinfo,OPS_PTAG_CT_USER_ATTRIBUTE,&content); - - return 1; -} - -/** -\ingroup Core_Create -\brief Free allocated memory -*/ -/*! Free the memory used when parsing this packet type */ -void ops_user_id_free(ops_user_id_t *id) - { - free(id->user_id); - id->user_id=NULL; - } - -/** - * \ingroup Core_ReadPackets - * \brief Parse a user id. - * - * This function parses an user id packet, which is basically just a char array the size of the packet. - * - * The char array is to be treated as an UTF-8 string. - * - * The userid gets null terminated by this function. Freeing it is the responsibility of the caller. - * - * Once the userid has been parsed successfully, it is passed to the callback. - * - * \param *ptag Pointer to the Packet Tag. This function should consume the entire packet. - * \param *reader Our reader - * \param *cb The callback - * \return 1 on success, 0 on error - * - * \see RFC4880 5.11 - */ -static int parse_user_id(ops_region_t *region,ops_parse_info_t *pinfo) -{ - ops_parser_content_t content; - - if(!(region->length_read == 0)) // ASSERT(region->length_read == 0) /* We should not have read anything so far */ - { - fprintf(stderr,"parse_user_id: region read size should be 0. Corrupted data ?\n") ; - return 0 ; - } - - /* From gnupg parse-packet.c: - Cap the size of a user ID at 2k: a value absurdly large enough - that there is no sane user ID string (which is printable text - as of RFC2440bis) that won't fit in it, but yet small enough to - avoid allocation problems. */ - - if(region->length > 2048) - { - fprintf(stderr,"parse_user_id(): invalid region length (%u)\n",region->length); - return 0; - } - C.user_id.user_id=malloc(region->length +1); /* XXX should we not like check malloc's return value? */ - - if(C.user_id.user_id==NULL) - { - fprintf(stderr,"malloc failed in parse_user_id\n") ; - return 0 ; - } - - if(region->length && !limited_read(C.user_id.user_id,region->length,region, - pinfo)) - return 0; - - C.user_id.user_id[region->length]='\0'; /* terminate the string */ - - CBP(pinfo,OPS_PTAG_CT_USER_ID,&content); - - return 1; -} - -/** - * \ingroup Core_Create - * \brief Free the memory used when parsing a private/experimental PKA signature - * \param unknown_sig - */ -void free_unknown_sig_pka(ops_unknown_signature_t *unknown_sig) - { - data_free(&unknown_sig->data); - } - -/** - * \ingroup Core_Create - * \brief Free the memory used when parsing a signature - * \param sig - */ -void ops_signature_free(ops_signature_t *sig) - { - switch(sig->info.key_algorithm) - { - case OPS_PKA_RSA: - case OPS_PKA_RSA_SIGN_ONLY: - free_BN(&sig->info.signature.rsa.sig); - break; - - case OPS_PKA_DSA: - free_BN(&sig->info.signature.dsa.r); - free_BN(&sig->info.signature.dsa.s); - break; - - case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - free_BN(&sig->info.signature.elgamal.r); - free_BN(&sig->info.signature.elgamal.s); - break; - - case OPS_PKA_PRIVATE00: - case OPS_PKA_PRIVATE01: - case OPS_PKA_PRIVATE02: - case OPS_PKA_PRIVATE03: - case OPS_PKA_PRIVATE04: - case OPS_PKA_PRIVATE05: - case OPS_PKA_PRIVATE06: - case OPS_PKA_PRIVATE07: - case OPS_PKA_PRIVATE08: - case OPS_PKA_PRIVATE09: - case OPS_PKA_PRIVATE10: - free_unknown_sig_pka(&sig->info.signature.unknown); - break; - - default: - fprintf(stderr,"ops_signature_free: Unknown algorithm: %d \n",sig->info.key_algorithm); - //ASSERT(0); - } - free(sig->info.v4_hashed_data); - } - -/** - * \ingroup Core_Parse - * \brief Parse a version 3 signature. - * - * This function parses an version 3 signature packet, handling RSA and DSA signatures. - * - * Once the signature has been parsed successfully, it is passed to the callback. - * - * \param *ptag Pointer to the Packet Tag. This function should consume the entire packet. - * \param *reader Our reader - * \param *cb The callback - * \return 1 on success, 0 on error - * - * \see RFC4880 5.2.2 - */ -static int parse_v3_signature(ops_region_t *region, - ops_parse_info_t *pinfo) - { - unsigned char c[1]=""; - ops_parser_content_t content; - - // clear signature - memset(&C.signature,'\0',sizeof C.signature); - - C.signature.info.version=OPS_V3; - - /* hash info length */ - if(!limited_read(c,1,region,pinfo)) - return 0; - if(c[0] != 5) - ERRP(pinfo,"bad hash info length"); - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.signature.info.type=c[0]; - /* XXX: check signature type */ - - if(!limited_read_time(&C.signature.info.creation_time,region,pinfo)) - return 0; - C.signature.info.creation_time_set=ops_true; - - if(!limited_read(C.signature.info.signer_id,OPS_KEY_ID_SIZE,region,pinfo)) - return 0; - C.signature.info.signer_id_set=ops_true; - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.signature.info.key_algorithm=c[0]; - /* XXX: check algorithm */ - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.signature.info.hash_algorithm=c[0]; - /* XXX: check algorithm */ - - if(!limited_read(C.signature.hash2,2,region,pinfo)) - return 0; - - switch(C.signature.info.key_algorithm) - { - case OPS_PKA_RSA: - case OPS_PKA_RSA_SIGN_ONLY: - if(!limited_read_mpi(&C.signature.info.signature.rsa.sig,region,pinfo)) - return 0; - break; - - case OPS_PKA_DSA: - if(!limited_read_mpi(&C.signature.info.signature.dsa.r,region,pinfo) - || !limited_read_mpi(&C.signature.info.signature.dsa.s,region,pinfo)) - return 0; - break; - - case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - if(!limited_read_mpi(&C.signature.info.signature.elgamal.r,region,pinfo) - || !limited_read_mpi(&C.signature.info.signature.elgamal.s,region,pinfo)) - return 0; - break; - - default: - OPS_ERROR_1(&pinfo->errors,OPS_E_ALG_UNSUPPORTED_SIGNATURE_ALG, - "Unsupported signature key algorithm (%s)", - ops_show_pka(C.signature.info.key_algorithm)); - return 0; - } - - if(region->length_read != region->length) - { - OPS_ERROR_1(&pinfo->errors,OPS_E_R_UNCONSUMED_DATA,"Unconsumed data (%d)",region->length-region->length_read); - return 0; - } - - if(C.signature.info.signer_id_set) - C.signature.hash=ops_parse_hash_find(pinfo,C.signature.info.signer_id); - - CBP(pinfo,OPS_PTAG_CT_SIGNATURE,&content); - - return 1; - } - -/** - * \ingroup Core_ReadPackets - * \brief Parse one signature sub-packet. - * - * Version 4 signatures can have an arbitrary amount of (hashed and unhashed) subpackets. Subpackets are used to hold - * optional attributes of subpackets. - * - * This function parses one such signature subpacket. - * - * Once the subpacket has been parsed successfully, it is passed to the callback. - * - * \param *ptag Pointer to the Packet Tag. This function should consume the entire subpacket. - * \param *reader Our reader - * \param *cb The callback - * \return 1 on success, 0 on error - * - * \see RFC4880 5.2.3 - */ -static int parse_one_signature_subpacket(ops_signature_t *sig, - ops_region_t *region, - ops_parse_info_t *pinfo) - { - ops_region_t subregion; - unsigned char c[1]=""; - ops_parser_content_t content; - unsigned t8,t7; - ops_boolean_t read=ops_true; - unsigned char bool[1]=""; - - ops_init_subregion(&subregion,region); - if(!limited_read_new_length(&subregion.length,region,pinfo)) - return 0; - - if(subregion.length > region->length) - ERRP(pinfo,"Subpacket too long"); - - if(!limited_read(c,1,&subregion,pinfo)) - return 0; - - t8=(c[0]&0x7f)/8; - t7=1 << (c[0]&7); - - content.critical=c[0] >> 7; - content.tag=OPS_PTAG_SIGNATURE_SUBPACKET_BASE+(c[0]&0x7f); - - /* Application wants it delivered raw */ - if(pinfo->ss_raw[t8]&t7) - { - C.ss_raw.tag=content.tag; - C.ss_raw.length=subregion.length-1; - C.ss_raw.raw=malloc(C.ss_raw.length); - - if(C.ss_raw.raw==NULL) - { - fprintf(stderr,"malloc failed in parse_signature_subpackets") ; - return 0 ; - } - if(!limited_read(C.ss_raw.raw,C.ss_raw.length,&subregion,pinfo)) - return 0; - CBP(pinfo,OPS_PTAG_RAW_SS,&content); - return 1; - } - - switch(content.tag) - { - case OPS_PTAG_SS_CREATION_TIME: - case OPS_PTAG_SS_EXPIRATION_TIME: - case OPS_PTAG_SS_KEY_EXPIRATION_TIME: - if(!limited_read_time(&C.ss_time.time,&subregion,pinfo)) - return 0; - if(content.tag == OPS_PTAG_SS_CREATION_TIME) - { - sig->info.creation_time=C.ss_time.time; - sig->info.creation_time_set=ops_true; - } - break; - - case OPS_PTAG_SS_TRUST: - if(!limited_read(&C.ss_trust.level,1,&subregion,pinfo) - || !limited_read(&C.ss_trust.amount,1,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_REVOCABLE: - if(!limited_read(bool,1,&subregion,pinfo)) - return 0; - C.ss_revocable.revocable=!!bool[0]; - break; - - case OPS_PTAG_SS_ISSUER_KEY_ID: - if(!limited_read(C.ss_issuer_key_id.key_id,OPS_KEY_ID_SIZE, - &subregion,pinfo)) - return 0; - memcpy(sig->info.signer_id,C.ss_issuer_key_id.key_id,OPS_KEY_ID_SIZE); - sig->info.signer_id_set=ops_true; - break; - - case OPS_PTAG_SS_PREFERRED_SKA: - if(!read_data(&C.ss_preferred_ska.data,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_PREFERRED_HASH: - if(!read_data(&C.ss_preferred_hash.data,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_PREFERRED_COMPRESSION: - if(!read_data(&C.ss_preferred_compression.data,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_PRIMARY_USER_ID: - if(!limited_read (bool,1,&subregion,pinfo)) - return 0; - C.ss_primary_user_id.primary_user_id = !!bool[0]; - break; - - case OPS_PTAG_SS_KEY_FLAGS: - if(!read_data(&C.ss_key_flags.data,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_KEY_SERVER_PREFS: - if(!read_data(&C.ss_key_server_prefs.data,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_FEATURES: - if(!read_data(&C.ss_features.data,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_SIGNERS_USER_ID: - if(!read_unsigned_string(&C.ss_signers_user_id.user_id,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_EMBEDDED_SIGNATURE: - // \todo should do something with this sig? - if (!read_data(&C.ss_embedded_signature.sig,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_NOTATION_DATA: - if(!limited_read_data(&C.ss_notation_data.flags,4,&subregion,pinfo)) - return 0; - if(!limited_read_size_t_scalar(&C.ss_notation_data.name.len,2, - &subregion,pinfo)) - return 0; - if(!limited_read_size_t_scalar(&C.ss_notation_data.value.len,2, - &subregion,pinfo)) - return 0; - if(!limited_read_data(&C.ss_notation_data.name, - C.ss_notation_data.name.len,&subregion,pinfo)) - return 0; - if(!limited_read_data(&C.ss_notation_data.value, - C.ss_notation_data.value.len,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_POLICY_URI: - if(!read_string(&C.ss_policy_url.text,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_REGEXP: - if(!read_string(&C.ss_regexp.text,&subregion, pinfo)) - return 0; - break; - - case OPS_PTAG_SS_PREFERRED_KEY_SERVER: - if(!read_string(&C.ss_preferred_key_server.text,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_USERDEFINED00: - case OPS_PTAG_SS_USERDEFINED01: - case OPS_PTAG_SS_USERDEFINED02: - case OPS_PTAG_SS_USERDEFINED03: - case OPS_PTAG_SS_USERDEFINED04: - case OPS_PTAG_SS_USERDEFINED05: - case OPS_PTAG_SS_USERDEFINED06: - case OPS_PTAG_SS_USERDEFINED07: - case OPS_PTAG_SS_USERDEFINED08: - case OPS_PTAG_SS_USERDEFINED09: - case OPS_PTAG_SS_USERDEFINED10: - if(!read_data(&C.ss_userdefined.data,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_RESERVED: - if(!read_data(&C.ss_unknown.data,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_REVOCATION_REASON: - /* first byte is the machine-readable code */ - if(!limited_read(&C.ss_revocation_reason.code,1,&subregion,pinfo)) - return 0; - - /* the rest is a human-readable UTF-8 string */ - if(!read_string(&C.ss_revocation_reason.text,&subregion,pinfo)) - return 0; - break; - - case OPS_PTAG_SS_REVOCATION_KEY: - /* octet 0 = clss. Bit 0x80 must be set */ - if(!limited_read (&C.ss_revocation_key.clss,1,&subregion,pinfo)) - return 0; - if(!(C.ss_revocation_key.clss&0x80)) - { - printf("Warning: OPS_PTAG_SS_REVOCATION_KEY class: " - "Bit 0x80 should be set\n"); - return 0; - } - - /* octet 1 = algid */ - if(!limited_read(&C.ss_revocation_key.algid,1,&subregion,pinfo)) - return 0; - - /* octets 2-21 = fingerprint */ - if(!limited_read(&C.ss_revocation_key.fingerprint[0],20,&subregion, - pinfo)) - return 0; - break; - - default: - if(pinfo->ss_parsed[t8]&t7) - OPS_ERROR_1(&pinfo->errors, OPS_E_PROTO_UNKNOWN_SS, - "Unknown signature subpacket type (%d)", c[0]&0x7f); - read=ops_false; - break; - } - - /* Application doesn't want it delivered parsed */ - if(!(pinfo->ss_parsed[t8]&t7)) - { - if(content.critical) - OPS_ERROR_1(&pinfo->errors,OPS_E_PROTO_CRITICAL_SS_IGNORED, - "Critical signature subpacket ignored (%d)", - c[0]&0x7f); - if(!read && !limited_skip(subregion.length-1,&subregion,pinfo)) - return 0; - // printf("skipped %d length %d\n",c[0]&0x7f,subregion.length); - if(read) - ops_parser_content_free(&content); - return 1; - } - - if(read && subregion.length_read != subregion.length) - { - OPS_ERROR_1(&pinfo->errors,OPS_E_R_UNCONSUMED_DATA, - "Unconsumed data (%d)", - subregion.length-subregion.length_read); - return 0; - } - - CBP(pinfo,content.tag,&content); - - return 1; - } - -/** - \ingroup Core_Create - \brief Free the memory used when parsing this signature sub-packet type - \param ss_preferred_ska -*/ -void ops_ss_preferred_ska_free(ops_ss_preferred_ska_t *ss_preferred_ska) - { - data_free(&ss_preferred_ska->data); - } - -/** - \ingroup Core_Create - \brief Free the memory used when parsing this signature sub-packet type - \param ss_preferred_hash -*/ -void ops_ss_preferred_hash_free(ops_ss_preferred_hash_t *ss_preferred_hash) - { - data_free(&ss_preferred_hash->data); - } - -/** - \ingroup Core_Create - \brief Free the memory used when parsing this signature sub-packet type -*/ -void ops_ss_preferred_compression_free(ops_ss_preferred_compression_t *ss_preferred_compression) - { - data_free(&ss_preferred_compression->data); - } - -/** - \ingroup Core_Create - \brief Free the memory used when parsing this signature sub-packet type -*/ -void ops_ss_key_flags_free(ops_ss_key_flags_t *ss_key_flags) - { - data_free(&ss_key_flags->data); - } - -/** - \ingroup Core_Create - \brief Free the memory used when parsing this signature sub-packet type -*/ -void ops_ss_features_free(ops_ss_features_t *ss_features) - { - data_free(&ss_features->data); - } - -/** - \ingroup Core_Create - \brief Free the memory used when parsing this signature sub-packet type -*/ -void ops_ss_key_server_prefs_free(ops_ss_key_server_prefs_t *ss_key_server_prefs) - { - data_free(&ss_key_server_prefs->data); - } - -/** - * \ingroup Core_ReadPackets - * \brief Parse several signature subpackets. - * - * Hashed and unhashed subpacket sets are preceded by an octet count that specifies the length of the complete set. - * This function parses this length and then calls parse_one_signature_subpacket() for each subpacket until the - * entire set is consumed. - * - * This function does not call the callback directly, parse_one_signature_subpacket() does for each subpacket. - * - * \param *ptag Pointer to the Packet Tag. - * \param *reader Our reader - * \param *cb The callback - * \return 1 on success, 0 on error - * - * \see RFC4880 5.2.3 - */ -static int parse_signature_subpackets(ops_signature_t *sig, - ops_region_t *region, - ops_parse_info_t *pinfo) - { - ops_region_t subregion; - ops_parser_content_t content; - - ops_init_subregion(&subregion,region); - if(!limited_read_scalar(&subregion.length,2,region,pinfo)) - return 0; - - if(subregion.length > region->length) - ERRP(pinfo,"Subpacket set too long"); - - while(subregion.length_read < subregion.length) - if(!parse_one_signature_subpacket(sig,&subregion,pinfo)) - return 0; - - if(subregion.length_read != subregion.length) - { - if(!limited_skip(subregion.length-subregion.length_read,&subregion, - pinfo)) - ERRP(pinfo,"Read failed while recovering from subpacket length mismatch"); - ERRP(pinfo,"Subpacket length mismatch"); - } - - return 1; - } - -/** - * \ingroup Core_ReadPackets - * \brief Parse a version 4 signature. - * - * This function parses a version 4 signature including all its hashed and unhashed subpackets. - * - * Once the signature packet has been parsed successfully, it is passed to the callback. - * - * \param *ptag Pointer to the Packet Tag. - * \param *reader Our reader - * \param *cb The callback - * \return 1 on success, 0 on error - * - * \see RFC4880 5.2.3 - */ -static int parse_v4_signature(ops_region_t *region,ops_parse_info_t *pinfo) - { - unsigned char c[1]=""; - ops_parser_content_t content; - - //debug=1; - if (debug) - { fprintf(stderr, "\nparse_v4_signature\n"); } - - // clear signature - memset(&C.signature,'\0',sizeof C.signature); - - /* We need to hash the packet data from version through the hashed subpacket data */ - - C.signature.v4_hashed_data_start=pinfo->rinfo.alength-1; - - /* Set version,type,algorithms */ - - C.signature.info.version=OPS_V4; - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.signature.info.type=c[0]; - if (debug) - { fprintf(stderr, "signature type=%d\n", C.signature.info.type); } - - /* XXX: check signature type */ - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.signature.info.key_algorithm=c[0]; - /* XXX: check algorithm */ - if (debug) - { fprintf(stderr, "key_algorithm=%d\n", C.signature.info.key_algorithm); } - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.signature.info.hash_algorithm=c[0]; - /* XXX: check algorithm */ - if (debug) - { fprintf(stderr, "hash_algorithm=%d %s\n", C.signature.info.hash_algorithm, ops_show_hash_algorithm(C.signature.info.hash_algorithm)); } - - CBP(pinfo,OPS_PTAG_CT_SIGNATURE_HEADER,&content); - - if(!parse_signature_subpackets(&C.signature,region,pinfo)) - return 0; - - C.signature.info.v4_hashed_data_length=pinfo->rinfo.alength - -C.signature.v4_hashed_data_start; - - // copy hashed subpackets - if (C.signature.info.v4_hashed_data) - free(C.signature.info.v4_hashed_data); - C.signature.info.v4_hashed_data=ops_mallocz(C.signature.info.v4_hashed_data_length); - - if (!pinfo->rinfo.accumulate) - { - /* We must accumulate, else we can't check the signature */ - fprintf(stderr,"*** ERROR: must set accumulate to true\n"); - return 0 ; //ASSERT(0); - } - - memcpy(C.signature.info.v4_hashed_data, - pinfo->rinfo.accumulated+C.signature.v4_hashed_data_start, - C.signature.info.v4_hashed_data_length); - - if(!parse_signature_subpackets(&C.signature,region,pinfo)) - return 0; - - if(!limited_read(C.signature.hash2,2,region,pinfo)) - return 0; - - switch(C.signature.info.key_algorithm) - { - case OPS_PKA_RSA: - if(!limited_read_mpi(&C.signature.info.signature.rsa.sig,region,pinfo)) - return 0; - break; - - case OPS_PKA_DSA: - if(!limited_read_mpi(&C.signature.info.signature.dsa.r,region,pinfo)) - ERRP(pinfo,"Error reading DSA r field in signature"); - if (!limited_read_mpi(&C.signature.info.signature.dsa.s,region,pinfo)) - ERRP(pinfo,"Error reading DSA s field in signature"); - break; - - case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - if(!limited_read_mpi(&C.signature.info.signature.elgamal.r,region,pinfo) - || !limited_read_mpi(&C.signature.info.signature.elgamal.s,region,pinfo)) - return 0; - break; - - case OPS_PKA_PRIVATE00: - case OPS_PKA_PRIVATE01: - case OPS_PKA_PRIVATE02: - case OPS_PKA_PRIVATE03: - case OPS_PKA_PRIVATE04: - case OPS_PKA_PRIVATE05: - case OPS_PKA_PRIVATE06: - case OPS_PKA_PRIVATE07: - case OPS_PKA_PRIVATE08: - case OPS_PKA_PRIVATE09: - case OPS_PKA_PRIVATE10: - if (!read_data(&C.signature.info.signature.unknown.data,region,pinfo)) - return 0; - break; - - default: - OPS_ERROR_1(&pinfo->errors,OPS_E_ALG_UNSUPPORTED_SIGNATURE_ALG, - "Bad v4 signature key algorithm (%s)", - ops_show_pka(C.signature.info.key_algorithm)); - return 0; - } - - if(region->length_read != region->length) - { - OPS_ERROR_1(&pinfo->errors,OPS_E_R_UNCONSUMED_DATA, - "Unconsumed data (%d)", - region->length-region->length_read); - return 0; - } - - CBP(pinfo,OPS_PTAG_CT_SIGNATURE_FOOTER,&content); - - return 1; - } - -/** - * \ingroup Core_ReadPackets - * \brief Parse a signature subpacket. - * - * This function calls the appropriate function to handle v3 or v4 signatures. - * - * Once the signature packet has been parsed successfully, it is passed to the callback. - * - * \param *ptag Pointer to the Packet Tag. - * \param *reader Our reader - * \param *cb The callback - * \return 1 on success, 0 on error - */ -static int parse_signature(ops_region_t *region,ops_parse_info_t *pinfo) -{ - unsigned char c[1]=""; - ops_parser_content_t content; - - if(!(region->length_read == 0)) // ASSERT(region->length_read == 0) /* We should not have read anything so far */ - { - fprintf(stderr,"parse_signature: region read is not empty! Data is corrupted?") ; - return 0 ; - } - - memset(&content,'\0',sizeof content); - - if(!limited_read(c,1,region,pinfo)) - return 0; - - if(c[0] == 2 || c[0] == 3) - return parse_v3_signature(region,pinfo); - else if(c[0] == 4) - return parse_v4_signature(region,pinfo); - - OPS_ERROR_1(&pinfo->errors,OPS_E_PROTO_BAD_SIGNATURE_VRSN, - "Bad signature version (%d)",c[0]); - return 0; -} - -/** - \ingroup Core_ReadPackets - \brief Parse Compressed packet -*/ -static int parse_compressed(ops_region_t *region,ops_parse_info_t *pinfo) - { - unsigned char c[1]=""; - ops_parser_content_t content; - - if(pinfo->recursive_compression_depth > MAX_RECURSIVE_COMPRESSION_DEPTH) - { - fprintf(stderr,"Recursive compression down to depth 32. This is weird. Probably a packet crafted to crash PGP. Will be dropped!\n") ; - return 0 ; - } - - if(!limited_read(c,1,region,pinfo)) - return 0; - -pinfo->recursive_compression_depth++ ; - - C.compressed.type=c[0]; - - CBP(pinfo,OPS_PTAG_CT_COMPRESSED,&content); - - /* The content of a compressed data packet is more OpenPGP packets - once decompressed, so recursively handle them */ - - int res = ops_decompress(region,pinfo,C.compressed.type); - -pinfo->recursive_compression_depth-- ; - - return res ; - } - -/** - \ingroup Core_ReadPackets - \brief Parse a One Pass Signature packet -*/ -static int parse_one_pass(ops_region_t *region,ops_parse_info_t *pinfo) - { - unsigned char c[1]=""; - ops_parser_content_t content; - - if(!limited_read(&C.one_pass_signature.version,1,region,pinfo)) - return 0; - if(C.one_pass_signature.version != 3) - { - OPS_ERROR_1(&pinfo->errors,OPS_E_PROTO_BAD_ONE_PASS_SIG_VRSN, - "Bad one-pass signature version (%d)", - C.one_pass_signature.version); - return 0; - } - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.one_pass_signature.sig_type=c[0]; - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.one_pass_signature.hash_algorithm=c[0]; - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.one_pass_signature.key_algorithm=c[0]; - - if(!limited_read(C.one_pass_signature.keyid, - sizeof C.one_pass_signature.keyid,region,pinfo)) - return 0; - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.one_pass_signature.nested=!!c[0]; - - CBP(pinfo,OPS_PTAG_CT_ONE_PASS_SIGNATURE,&content); - - // XXX: we should, perhaps, let the app choose whether to hash or not - ops_parse_hash_init(pinfo,C.one_pass_signature.hash_algorithm, - C.one_pass_signature.keyid); - - return 1; - } - -/** - \ingroup Core_Create - \brief Free the memory used when parsing this signature sub-packet type -*/ -void ops_ss_userdefined_free(ops_ss_userdefined_t *ss_userdefined) - { - data_free(&ss_userdefined->data); - } - -/** - \ingroup Core_Create - \brief Free the memory used when parsing this signature sub-packet type -*/ -void ops_ss_reserved_free(ops_ss_unknown_t *ss_unknown) - { - data_free(&ss_unknown->data); - } - -/** - \ingroup Core_Create - \brief Free the memory used when parsing this signature sub-packet type -*/ -void ops_ss_notation_data_free(ops_ss_notation_data_t *ss_notation_data) - { - data_free(&ss_notation_data->name); - data_free(&ss_notation_data->value); - } - -void ops_ss_embedded_signature_free(ops_ss_embedded_signature_t *ss_embedded_signature) - { - data_free(&ss_embedded_signature->sig); - } - -/** - \ingroup Core_Create - \brief Free the memory used when parsing this signature sub-packet type -*/ -void ops_ss_revocation_reason_free(ops_ss_revocation_reason_t *ss_revocation_reason) - { - string_free(&ss_revocation_reason->text); - } - -/** - \ingroup Core_Create - \brief Free the memory used when parsing this packet type -*/ -void ops_trust_free(ops_trust_t *trust) - { - data_free(&trust->data); - } - -/** - \ingroup Core_ReadPackets - \brief Parse a Trust packet -*/ -static int -parse_trust (ops_region_t *region, ops_parse_info_t *pinfo) - { - ops_parser_content_t content; - - if(!read_data(&C.trust.data,region,pinfo)) - return 0; - - CBP(pinfo,OPS_PTAG_CT_TRUST, &content); - - return 1; - } - -/** - \ingroup Core_ReadPackets - \brief Parse a Literal Data packet -*/ -static int parse_literal_data(ops_region_t *region,ops_parse_info_t *pinfo) - { - ops_parser_content_t content; - unsigned char c[1]=""; - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.literal_data_header.format=c[0]; - - if(!limited_read(c,1,region,pinfo)) - return 0; - if(!limited_read((unsigned char *)C.literal_data_header.filename,c[0], - region,pinfo)) - return 0; - C.literal_data_header.filename[c[0]]='\0'; - - if(!limited_read_time(&C.literal_data_header.modification_time,region,pinfo)) - return 0; - - CBP(pinfo,OPS_PTAG_CT_LITERAL_DATA_HEADER,&content); - - while(region->length_read < region->length) - { - unsigned l=region->length-region->length_read; - - C.literal_data_body.data = (unsigned char *)malloc(l) ; - - if(C.literal_data_body.data == NULL) - { - fprintf(stderr,"parse_literal_data(): cannot malloc for requested size %d.\n",l) ; - return 0 ; - } - - if(!limited_read(C.literal_data_body.data,l,region,pinfo)) - { - free(C.literal_data_body.data); - return 0; - } - - C.literal_data_body.length=l; - - ops_parse_hash_data(pinfo,C.literal_data_body.data,l); - - CBP(pinfo,OPS_PTAG_CT_LITERAL_DATA_BODY,&content); - free(C.literal_data_body.data); - } - - return 1; - } - -/** - * \ingroup Core_Create - * - * ops_secret_key_free() frees the memory associated with "key". Note that - * the key itself is not freed. - * - * \param key - */ - -void ops_secret_key_free(ops_secret_key_t *key) - { - switch(key->public_key.algorithm) - { - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: - free_BN(&key->key.rsa.d); - free_BN(&key->key.rsa.p); - free_BN(&key->key.rsa.q); - free_BN(&key->key.rsa.u); - break; - - case OPS_PKA_DSA: - free_BN(&key->key.dsa.x); - break; - - default: - fprintf(stderr,"ops_secret_key_free: Unknown algorithm: %d (%s)\n",key->public_key.algorithm, ops_show_pka(key->public_key.algorithm)); - //ASSERT(0); - } - - ops_public_key_free(&key->public_key); - } - -void ops_secret_key_copy(ops_secret_key_t *dst,const ops_secret_key_t *src) -{ - *dst = *src ; - ops_public_key_copy(&dst->public_key,&src->public_key); - - switch(src->public_key.algorithm) - { - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: - dst->key.rsa.d = BN_dup(src->key.rsa.d) ; - dst->key.rsa.p = BN_dup(src->key.rsa.p) ; - dst->key.rsa.q = BN_dup(src->key.rsa.q) ; - dst->key.rsa.u = BN_dup(src->key.rsa.u) ; - break; - - case OPS_PKA_DSA: - dst->key.dsa.x = BN_dup(src->key.dsa.x) ; - break; - - default: - fprintf(stderr,"ops_secret_key_copy: Unknown algorithm: %d (%s)\n",src->public_key.algorithm, ops_show_pka(src->public_key.algorithm)); - //ASSERT(0); - } -} -static int consume_packet(ops_region_t *region,ops_parse_info_t *pinfo, - ops_boolean_t warn) - { - ops_data_t remainder; - ops_parser_content_t content; - - if(region->indeterminate) - ERRP(pinfo,"Can't consume indeterminate packets"); - - if(read_data(&remainder,region,pinfo)) - { - /* now throw it away */ - data_free(&remainder); - if(warn) - OPS_ERROR(&pinfo->errors,OPS_E_P_PACKET_CONSUMED,"Warning: packet consumer"); - } - else if(warn) - OPS_ERROR(&pinfo->errors,OPS_E_P_PACKET_NOT_CONSUMED,"Warning: Packet was not consumed"); - else - { - OPS_ERROR(&pinfo->errors,OPS_E_P_PACKET_NOT_CONSUMED,"Packet was not consumed"); - return 0; - } - - return 1; - } - -/** - * \ingroup Core_ReadPackets - * \brief Parse a secret key - */ -static int parse_secret_key(ops_region_t *region,ops_parse_info_t *pinfo) -{ - ops_parser_content_t content; - unsigned char c[1]=""; - ops_crypt_t decrypt; - int ret=1; - ops_region_t encregion; - ops_region_t *saved_region=NULL; - ops_hash_t checkhash; - int blocksize; - ops_boolean_t crypted; - - if (debug) - { fprintf(stderr,"\n---------\nparse_secret_key:\n"); - fprintf(stderr,"region length=%d, length_read=%d, remainder=%d\n", region->length, region->length_read, region->length-region->length_read); - } - - memset(&content,'\0',sizeof content); - if(!parse_public_key_data(&C.secret_key.public_key,region,pinfo)) - return 0; - - if (debug) - { - fprintf(stderr,"parse_secret_key: public key parsed\n"); - ops_print_public_key(&C.secret_key.public_key); - } - - pinfo->reading_v3_secret=C.secret_key.public_key.version != OPS_V4; - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.secret_key.s2k_usage=c[0]; - - if(C.secret_key.s2k_usage == OPS_S2KU_ENCRYPTED - || C.secret_key.s2k_usage == OPS_S2KU_ENCRYPTED_AND_HASHED) - { - if(!limited_read(c,1,region,pinfo)) - return 0; - C.secret_key.algorithm=c[0]; - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.secret_key.s2k_specifier=c[0]; - - if(!(C.secret_key.s2k_specifier == OPS_S2KS_SIMPLE || C.secret_key.s2k_specifier == OPS_S2KS_SALTED || C.secret_key.s2k_specifier == OPS_S2KS_ITERATED_AND_SALTED)) // ASSERT(C.secret_key.s2k_specifier == OPS_S2KS_SIMPLE || C.secret_key.s2k_specifier == OPS_S2KS_SALTED || C.secret_key.s2k_specifier == OPS_S2KS_ITERATED_AND_SALTED) - { - fprintf(stderr,"parse_secret_key: error in secret key format. Bad flags combination.\n") ; - return 0; - } - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.secret_key.hash_algorithm=c[0]; - - if(C.secret_key.s2k_specifier != OPS_S2KS_SIMPLE - && !limited_read(C.secret_key.salt,8,region,pinfo)) - { - return 0; - } - - if(C.secret_key.s2k_specifier == OPS_S2KS_ITERATED_AND_SALTED) - { - if(!limited_read(c,1,region,pinfo)) - return 0; - C.secret_key.octet_count=(16+(c[0]&15)) << ((c[0] >> 4)+6); - } - } - else if(C.secret_key.s2k_usage != OPS_S2KU_NONE) - { - // this is V3 style, looks just like a V4 simple hash - C.secret_key.algorithm=(ops_symmetric_algorithm_t)C.secret_key.s2k_usage; - C.secret_key.s2k_usage=OPS_S2KU_ENCRYPTED; - C.secret_key.s2k_specifier=OPS_S2KS_SIMPLE; - C.secret_key.hash_algorithm=OPS_HASH_MD5; - } - - crypted=C.secret_key.s2k_usage == OPS_S2KU_ENCRYPTED - || C.secret_key.s2k_usage == OPS_S2KU_ENCRYPTED_AND_HASHED; - - if(crypted) - { - int n; - ops_parser_content_t pc; - char *passphrase; - unsigned char key[OPS_MAX_KEY_SIZE+OPS_MAX_HASH_SIZE]; - ops_hash_t hashes[(OPS_MAX_KEY_SIZE+OPS_MIN_HASH_SIZE-1)/OPS_MIN_HASH_SIZE]; - int keysize; - int hashsize; - size_t l; - - blocksize=ops_block_size(C.secret_key.algorithm); - if(!(blocksize > 0 && blocksize <= OPS_MAX_BLOCK_SIZE)) // ASSERT(blocksize > 0 && blocksize <= OPS_MAX_BLOCK_SIZE); - { - fprintf(stderr,"parse_secret_key: block size error. Data seems corrupted.") ; - return 0; - } - - if(!limited_read(C.secret_key.iv,blocksize,region,pinfo)) - return 0; - - memset(&pc,'\0',sizeof pc); - passphrase=NULL; - pc.content.secret_key_passphrase.passphrase=&passphrase; - pc.content.secret_key_passphrase.secret_key=&C.secret_key; - CBP(pinfo,OPS_PARSER_CMD_GET_SK_PASSPHRASE,&pc); - if(!passphrase) - { - if (debug) - { - // \todo make into proper error - fprintf(stderr,"parse_secret_key: can't get passphrase\n"); - } - - if(!consume_packet(region,pinfo,ops_false)) - return 0; - - CBP(pinfo,OPS_PTAG_CT_ENCRYPTED_SECRET_KEY,&content); - - return 1; - } - - keysize=ops_key_size(C.secret_key.algorithm); - if(!(keysize > 0 && keysize <= OPS_MAX_KEY_SIZE)) // ASSERT(keysize > 0 && keysize <= OPS_MAX_KEY_SIZE); - { - fprintf(stderr,"parse_secret_key: keysize %d exceeds maximum allowed size %d\n",keysize,OPS_MAX_KEY_SIZE); - return 0 ; - } - - hashsize=ops_hash_size(C.secret_key.hash_algorithm); - if(!(hashsize > 0 && hashsize <= OPS_MAX_HASH_SIZE)) // ASSERT(hashsize > 0 && hashsize <= OPS_MAX_HASH_SIZE); - { - fprintf(stderr,"parse_secret_key: hashsize %d exceeds maximum allowed size %d\n",keysize,OPS_MAX_HASH_SIZE); - return 0 ; - } - - for(n=0 ; n*hashsize < keysize ; ++n) - { - int i; - - ops_hash_any(&hashes[n],C.secret_key.hash_algorithm); - hashes[n].init(&hashes[n]); - // preload hashes with zeroes... - for(i=0 ; i < n ; ++i) - hashes[n].add(&hashes[n],(unsigned char *)"",1); - } - - l=strlen(passphrase); - - for(n=0 ; n*hashsize < keysize ; ++n) - { - unsigned i; - - switch(C.secret_key.s2k_specifier) - { - case OPS_S2KS_SALTED: - hashes[n].add(&hashes[n],C.secret_key.salt,OPS_SALT_SIZE); - /* fallthrough */ - case OPS_S2KS_SIMPLE: - hashes[n].add(&hashes[n],(unsigned char*)passphrase,l); - break; - - case OPS_S2KS_ITERATED_AND_SALTED: - for(i=0 ; i < C.secret_key.octet_count ; i+=l+OPS_SALT_SIZE) - { - int j=l+OPS_SALT_SIZE; - - if(i+j > C.secret_key.octet_count && i != 0) - j=C.secret_key.octet_count-i; - - hashes[n].add(&hashes[n],C.secret_key.salt, - j > OPS_SALT_SIZE ? OPS_SALT_SIZE : j); - if(j > OPS_SALT_SIZE) - hashes[n].add(&hashes[n],(unsigned char *)passphrase,j-OPS_SALT_SIZE); - } - - } - } - - for(n=0 ; n*hashsize < keysize ; ++n) - { - int r=hashes[n].finish(&hashes[n],key+n*hashsize); - if(!(r == hashsize)) // ASSERT(r == hashsize); - { - fprintf(stderr,"parse_secret_key: read error. Data probably corrupted.") ; - return 0 ; - } - } - - free(passphrase); - - ops_crypt_any(&decrypt,C.secret_key.algorithm); - if (debug) - { - unsigned int i=0; - fprintf(stderr,"\nREADING:\niv="); - for (i=0; ilength-region->length_read; - if(C.secret_key.public_key.version != OPS_V4) - { - encregion.length-=2; - } - saved_region=region; - region=&encregion; - } - - if(C.secret_key.s2k_usage == OPS_S2KU_ENCRYPTED_AND_HASHED) - { - ops_hash_sha1(&checkhash); - ops_reader_push_hash(pinfo,&checkhash); - } - else - { - ops_reader_push_sum16(pinfo); - } - - switch(C.secret_key.public_key.algorithm) - { - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: - if(!limited_read_mpi(&C.secret_key.key.rsa.d,region,pinfo) - || !limited_read_mpi(&C.secret_key.key.rsa.p,region,pinfo) - || !limited_read_mpi(&C.secret_key.key.rsa.q,region,pinfo) - || !limited_read_mpi(&C.secret_key.key.rsa.u,region,pinfo)) - ret=0; - - break; - - case OPS_PKA_DSA: - - if(!limited_read_mpi(&C.secret_key.key.dsa.x,region,pinfo)) - ret=0; - break; - - default: - OPS_ERROR_2(&pinfo->errors,OPS_E_ALG_UNSUPPORTED_PUBLIC_KEY_ALG,"Unsupported Public Key algorithm %d (%s)",C.secret_key.public_key.algorithm,ops_show_pka(C.secret_key.public_key.algorithm)); - ret=0; - // ASSERT(0); - } - - if (debug) - { - fprintf(stderr,"4 MPIs read\n"); - // ops_print_secret_key_verbose(OPS_PTAG_CT_SECRET_KEY, &C.secret_key); - } - - pinfo->reading_v3_secret=ops_false; - - if(C.secret_key.s2k_usage == OPS_S2KU_ENCRYPTED_AND_HASHED) - { - unsigned char hash[20]; - - ops_reader_pop_hash(pinfo); - checkhash.finish(&checkhash,hash); - - if(crypted && C.secret_key.public_key.version != OPS_V4) - { - ops_reader_pop_decrypt(pinfo); - region=saved_region; - } - - if(ret) - { - if(!limited_read(C.secret_key.checkhash,20,region,pinfo)) - return 0; - - if(memcmp(hash,C.secret_key.checkhash,20)) - ERRP(pinfo,"Hash mismatch in secret key"); - } - } - else - { - unsigned short sum; - - sum=ops_reader_pop_sum16(pinfo); - - if(crypted && C.secret_key.public_key.version != OPS_V4) - { - ops_reader_pop_decrypt(pinfo); - region=saved_region; - } - - if(ret) - { - if(!limited_read_scalar(&C.secret_key.checksum,2,region, - pinfo)) - return 0; - - if(sum != C.secret_key.checksum) - ERRP(pinfo,"Checksum mismatch in secret key"); - } - } - - if(crypted && C.secret_key.public_key.version == OPS_V4) - { - ops_reader_pop_decrypt(pinfo); - } - - if(!(!ret || region->length_read == region->length)) // ASSERT(!ret || region->length_read == region->length) - { - fprintf(stderr,"parse_secret_key: read error. data probably corrupted.") ; - return 0 ; - } - - if(!ret) - return 0; - - CBP(pinfo,OPS_PTAG_CT_SECRET_KEY,&content); - - if (debug) - { fprintf(stderr, "--- end of parse_secret_key\n\n"); } - - return 1; -} - -/** - \ingroup Core_ReadPackets - \brief Parse a Public Key Session Key packet -*/ -static int parse_pk_session_key(ops_region_t *region, - ops_parse_info_t *pinfo) - { - unsigned char c[1]=""; - ops_parser_content_t content; - ops_parser_content_t pc; - - int n; - BIGNUM *enc_m; - unsigned k; - const ops_secret_key_t *secret; - unsigned char cs[2]; - unsigned char* iv; - - // Can't rely on it being CAST5 - // \todo FIXME RW - // const size_t sz_unencoded_m_buf=CAST_KEY_LENGTH+1+2; - const size_t sz_unencoded_m_buf=1024; - unsigned char unencoded_m_buf[sz_unencoded_m_buf]; - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.pk_session_key.version=c[0]; - if(C.pk_session_key.version != OPS_PKSK_V3) - { - OPS_ERROR_1(&pinfo->errors, OPS_E_PROTO_BAD_PKSK_VRSN, - "Bad public-key encrypted session key version (%d)", - C.pk_session_key.version); - return 0; - } - - if(!limited_read(C.pk_session_key.key_id, - sizeof C.pk_session_key.key_id,region,pinfo)) - return 0; - - if (debug) - { - int i; - int x=sizeof C.pk_session_key.key_id; - printf("session key: public key id: x=%d\n",x); - for (i=0; ierrors, OPS_E_ALG_UNSUPPORTED_PUBLIC_KEY_ALG, - "Unknown public key algorithm in session key (%s)", - ops_show_pka(C.pk_session_key.algorithm)); - return 0; - } - - memset(&pc,'\0',sizeof pc); - secret=NULL; - pc.content.get_secret_key.secret_key=&secret; - pc.content.get_secret_key.pk_session_key=&C.pk_session_key; - - CBP(pinfo,OPS_PARSER_CMD_GET_SECRET_KEY,&pc); - - if(!secret) - { - CBP(pinfo,OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY,&content); - - return 1; - } - - // n=ops_decrypt_mpi(buf,sizeof buf,enc_m,secret); - n=ops_decrypt_and_unencode_mpi(unencoded_m_buf,sizeof unencoded_m_buf,enc_m,secret); - - if(n < 1) - { - ERRP(pinfo,"decrypted message too short"); - return 0; - } - - // PKA - C.pk_session_key.symmetric_algorithm=unencoded_m_buf[0]; - - if (!ops_is_sa_supported(C.pk_session_key.symmetric_algorithm)) - { - // ERR1P - OPS_ERROR_1(&pinfo->errors,OPS_E_ALG_UNSUPPORTED_SYMMETRIC_ALG, - "Symmetric algorithm %s not supported", - ops_show_symmetric_algorithm(C.pk_session_key.symmetric_algorithm)); - return 0; - } - - k=ops_key_size(C.pk_session_key.symmetric_algorithm); - - if((unsigned)n != k+3) - { - OPS_ERROR_2(&pinfo->errors,OPS_E_PROTO_DECRYPTED_MSG_WRONG_LEN, - "decrypted message wrong length (got %d expected %d)", - n,k+3); - return 0; - } - - if(!(k <= sizeof C.pk_session_key.key)) // ASSERT(k <= sizeof C.pk_session_key.key); - { - fprintf(stderr,"ops_decrypt_se_data: error in session key size. Corrupted data?") ; - return 0 ; - } - - memcpy(C.pk_session_key.key,unencoded_m_buf+1,k); - - if (debug) - { - printf("session key recovered (len=%d):\n",k); - unsigned int j; - for(j=0; jerrors, OPS_E_PROTO_BAD_SK_CHECKSUM, - "Session key checksum wrong: expected %2x %2x, got %2x %2x", - cs[0], cs[1], unencoded_m_buf[k+1], unencoded_m_buf[k+2]); - return 0; - } - - // all is well - CBP(pinfo,OPS_PTAG_CT_PK_SESSION_KEY,&content); - - ops_crypt_any(&pinfo->decrypt,C.pk_session_key.symmetric_algorithm); - iv=ops_mallocz(pinfo->decrypt.blocksize); - pinfo->decrypt.set_iv(&pinfo->decrypt, iv); - pinfo->decrypt.set_key(&pinfo->decrypt,C.pk_session_key.key); - ops_encrypt_init(&pinfo->decrypt); - return 1; - } - -// XXX: make this static? -int ops_decrypt_se_data(ops_content_tag_t tag,ops_region_t *region, ops_parse_info_t *pinfo) -{ - int r=1; - ops_crypt_t *decrypt=ops_parse_get_decrypt(pinfo); - - if(decrypt) - { - unsigned char buf[OPS_MAX_BLOCK_SIZE+2]=""; - size_t b=decrypt->blocksize; - // ops_parser_content_t content; - ops_region_t encregion; - - - ops_reader_push_decrypt(pinfo,decrypt,region); - - ops_init_subregion(&encregion,NULL); - encregion.length=b+2; - - if(!exact_limited_read(buf,b+2,&encregion,pinfo)) - return 0; - - if(buf[b-2] != buf[b] || buf[b-1] != buf[b+1]) - { - ops_reader_pop_decrypt(pinfo); - OPS_ERROR_4(&pinfo->errors, OPS_E_PROTO_BAD_SYMMETRIC_DECRYPT, - "Bad symmetric decrypt (%02x%02x vs %02x%02x)", - buf[b-2],buf[b-1],buf[b],buf[b+1]); - return 0; - } - - if(tag == OPS_PTAG_CT_SE_DATA_BODY) - { - decrypt->decrypt_resync(decrypt); - decrypt->block_encrypt(decrypt,decrypt->civ,decrypt->civ); - } - - - r=ops_parse(pinfo,ops_false); - - ops_reader_pop_decrypt(pinfo); - } - else - { - ops_parser_content_t content; - - while(region->length_read < region->length) - { - unsigned l=region->length-region->length_read; - - if(l > sizeof C.se_data_body.data) - l=sizeof C.se_data_body.data; - - if(!limited_read(C.se_data_body.data,l,region,pinfo)) - return 0; - - C.se_data_body.length=l; - - CBP(pinfo,tag,&content); - } - } - - return r; -} - -int ops_decrypt_se_ip_data(ops_content_tag_t tag,ops_region_t *region, - ops_parse_info_t *pinfo) -{ - int r=1; - ops_crypt_t *decrypt=ops_parse_get_decrypt(pinfo); - - if(decrypt) - { - ops_reader_push_decrypt(pinfo,decrypt,region); - ops_reader_push_se_ip_data(pinfo,decrypt,region); - - r=ops_parse(pinfo,ops_false); - - ops_reader_pop_se_ip_data(pinfo); - ops_reader_pop_decrypt(pinfo); - } - else - { - ops_parser_content_t content; - - while(region->length_read < region->length) - { - unsigned l=region->length-region->length_read; - - if(l > sizeof C.se_data_body.data) - l=sizeof C.se_data_body.data; - - if(!limited_read(C.se_data_body.data,l,region,pinfo)) - return 0; - - C.se_data_body.length=l; - - CBP(pinfo,tag,&content); - } - } - - return r; -} - -/** - \ingroup Core_ReadPackets - \brief Read a Symmetrically Encrypted packet -*/ -static int parse_se_data(ops_region_t *region,ops_parse_info_t *pinfo) - { - ops_parser_content_t content; - - /* there's no info to go with this, so just announce it */ - CBP(pinfo,OPS_PTAG_CT_SE_DATA_HEADER,&content); - - /* The content of an encrypted data packet is more OpenPGP packets - once decrypted, so recursively handle them */ - return ops_decrypt_se_data(OPS_PTAG_CT_SE_DATA_BODY,region,pinfo); - } - -/** - \ingroup Core_ReadPackets - \brief Read a Symmetrically Encrypted Integrity Protected packet -*/ -static int parse_se_ip_data(ops_region_t *region,ops_parse_info_t *pinfo) -{ - unsigned char c[1]=""; - ops_parser_content_t content; - - if(!limited_read(c,1,region,pinfo)) - return 0; - C.se_ip_data_header.version=c[0]; - - if(!(C.se_ip_data_header.version == OPS_SE_IP_V1)) // ASSERT(C.se_ip_data_header.version == OPS_SE_IP_V1); - { - fprintf(stderr,"parse_se_ip_data: packet header version should be %d, it is %d. Packet dropped.",OPS_SE_IP_V1,C.se_ip_data_header.version) ; - return 0 ; - } - - /* The content of an encrypted data packet is more OpenPGP packets - once decrypted, so recursively handle them */ - return ops_decrypt_se_ip_data(OPS_PTAG_CT_SE_IP_DATA_BODY,region,pinfo); -} - -/** - \ingroup Core_ReadPackets - \brief Read a MDC packet -*/ -static int parse_mdc(ops_region_t *region, ops_parse_info_t *pinfo) - { - ops_parser_content_t content; - - if (!limited_read((unsigned char *)&C.mdc,OPS_SHA1_HASH_SIZE,region,pinfo)) - return 0; - - CBP(pinfo,OPS_PTAG_CT_MDC,&content); - - return 1; - } - -/** - * \ingroup Core_ReadPackets - * \brief Parse one packet. - * - * This function parses the packet tag. It computes the value of the - * content tag and then calls the appropriate function to handle the - * content. - * - * \param *pinfo How to parse - * \param *pktlen On return, will contain number of bytes in packet - * \return 1 on success, 0 on error, -1 on EOF */ -static int ops_parse_one_packet(ops_parse_info_t *pinfo, - unsigned long *pktlen) - { - unsigned char ptag[1]; - ops_parser_content_t content; - int r; - ops_region_t region; - ops_boolean_t indeterminate=ops_false; - - C.ptag.position=pinfo->rinfo.position; - - r=base_read(ptag,1,pinfo); - - // errors in the base read are effectively EOF. - if(r <= 0) - return -1; - - *pktlen=0; - - if(!(*ptag&OPS_PTAG_ALWAYS_SET)) - { - C.error.error="Format error (ptag bit not set)"; - CBP(pinfo,OPS_PARSER_ERROR,&content); - OPS_ERROR(&pinfo->errors, OPS_E_P_UNKNOWN_TAG, C.error.error); - return 0; - } - C.ptag.new_format=!!(*ptag&OPS_PTAG_NEW_FORMAT); - if(C.ptag.new_format) - { - C.ptag.content_tag=*ptag&OPS_PTAG_NF_CONTENT_TAG_MASK; - C.ptag.length_type=0; - if(!read_new_length(&C.ptag.length,pinfo)) - return 0; - - } - else - { - ops_boolean_t rb = ops_false; - - C.ptag.content_tag=(*ptag&OPS_PTAG_OF_CONTENT_TAG_MASK) - >> OPS_PTAG_OF_CONTENT_TAG_SHIFT; - C.ptag.length_type=*ptag&OPS_PTAG_OF_LENGTH_TYPE_MASK; - switch(C.ptag.length_type) - { - case OPS_PTAG_OF_LT_ONE_BYTE: - rb=_read_scalar(&C.ptag.length,1,pinfo); - break; - - case OPS_PTAG_OF_LT_TWO_BYTE: - rb=_read_scalar(&C.ptag.length,2,pinfo); - break; - - case OPS_PTAG_OF_LT_FOUR_BYTE: - rb=_read_scalar(&C.ptag.length,4,pinfo); - break; - - case OPS_PTAG_OF_LT_INDETERMINATE: - C.ptag.length=0; - indeterminate=ops_true; - rb=ops_true; - break; - } - if(!rb) - { - OPS_ERROR(&pinfo->errors, OPS_E_P, "Cannot read tag length"); - return 0; - } - } - - CBP(pinfo,OPS_PARSER_PTAG,&content); - - ops_init_subregion(®ion,NULL); - region.length=C.ptag.length; - region.indeterminate=indeterminate; - switch(C.ptag.content_tag) - { - case OPS_PTAG_CT_SIGNATURE: - r=parse_signature(®ion,pinfo); - break; - - case OPS_PTAG_CT_PUBLIC_KEY: - case OPS_PTAG_CT_PUBLIC_SUBKEY: - r=parse_public_key(C.ptag.content_tag,®ion,pinfo); - break; - - case OPS_PTAG_CT_TRUST: - r=parse_trust(®ion, pinfo); - break; - - case OPS_PTAG_CT_USER_ID: - r=parse_user_id(®ion,pinfo); - break; - - case OPS_PTAG_CT_COMPRESSED: - r=parse_compressed(®ion,pinfo); - break; - - case OPS_PTAG_CT_ONE_PASS_SIGNATURE: - r=parse_one_pass(®ion,pinfo); - break; - - case OPS_PTAG_CT_LITERAL_DATA: - r=parse_literal_data(®ion,pinfo); - break; - - case OPS_PTAG_CT_USER_ATTRIBUTE: - r=parse_user_attribute(®ion,pinfo); - break; - - case OPS_PTAG_CT_SECRET_KEY: - r=parse_secret_key(®ion,pinfo); - break; - - case OPS_PTAG_CT_SECRET_SUBKEY: - r=parse_secret_key(®ion,pinfo); - break; - - case OPS_PTAG_CT_PK_SESSION_KEY: - r=parse_pk_session_key(®ion,pinfo); - break; - - case OPS_PTAG_CT_SE_DATA: - r=parse_se_data(®ion,pinfo); - break; - - case OPS_PTAG_CT_SE_IP_DATA: - r=parse_se_ip_data(®ion,pinfo); - break; - - case OPS_PTAG_CT_MDC: - r=parse_mdc(®ion, pinfo); - break; - - default: - OPS_ERROR_1(&pinfo->errors,OPS_E_P_UNKNOWN_TAG, - "Unknown content tag 0x%x", C.ptag.content_tag); - r=0; - } - - /* Ensure that the entire packet has been consumed */ - - if(region.length != region.length_read && !region.indeterminate) - if(!consume_packet(®ion,pinfo,ops_false)) - r=-1; - - // also consume it if there's been an error? - // \todo decide what to do about an error on an - // indeterminate packet - if (r==0) - { - if (!consume_packet(®ion,pinfo,ops_false)) - r=-1; - } - - /* set pktlen */ - - *pktlen=pinfo->rinfo.alength; - - /* do callback on entire packet, if desired and there was no error */ - - if(r > 0 && pinfo->rinfo.accumulate) - { - C.packet.length=pinfo->rinfo.alength; - C.packet.raw=pinfo->rinfo.accumulated; - - CBP(pinfo,OPS_PARSER_PACKET_END,&content); - //free(pinfo->rinfo.accumulated); - pinfo->rinfo.accumulated=NULL; - pinfo->rinfo.asize=0; - } - else - C.packet.raw = NULL ; - - pinfo->rinfo.alength=0; - - if(r < 0) - return -1; - - return r ? 1 : 0; - } - -/** - * \ingroup Core_ReadPackets - * - * \brief Parse packets from an input stream until EOF or error. - * - * \details Setup the necessary parsing configuration in "pinfo" before calling ops_parse(). - * - * That information includes : - * - * - a "reader" function to be used to get the data to be parsed - * - * - a "callback" function to be called when this library has identified - * a parseable object within the data - * - * - whether the calling function wants the signature subpackets returned raw, parsed or not at all. - * - * After returning, pinfo->errors holds any errors encountered while parsing. - * - * \param pinfo Parsing configuration - * \return 1 on success in all packets, 0 on error in any packet - * - * \sa CoreAPI Overview - * - * \sa ops_print_errors(), ops_parse_and_print_errors() - * - * Example code - * \code -ops_parse_cb_t* example_callback(); -void example() - { - int fd=0; - ops_parse_info_t *pinfo=NULL; - char *filename="pubring.gpg"; - - // setup pinfo to read from file with example callback - fd=ops_setup_file_read(&pinfo, filename, NULL, example_callback, ops_false); - - // specify how we handle signature subpackets - ops_parse_options(pinfo, OPS_PTAG_SS_ALL, OPS_PARSE_PARSED); - - if (!ops_parse(pinfo)) - ops_print_errors(pinfo->errors); - - ops_teardown_file_read(pinfo,fd); - } - * \endcode - */ - -int ops_parse(ops_parse_info_t *pinfo,ops_boolean_t limit_packets) -{ - int r; - unsigned long pktlen; - int n_packets = 0 ; - - do - // Parse until we get a return code of 0 (error) or -1 (EOF) - { - r=ops_parse_one_packet(pinfo,&pktlen); - - if(++n_packets > 500 && limit_packets) - { - fprintf(stderr,"More than 500 packets parsed in a row. This is likely to be a buggy certificate.") ; - return 0 ; - } - } while (r > 0); - - return pinfo->errors ? 0 : 1; - //return r == -1 ? 0 : 1; -} - -/** -\ingroup Core_ReadPackets -\brief Parse packets and print any errors - * \param pinfo Parsing configuration - * \return 1 on success in all packets, 0 on error in any packet - * \sa CoreAPI Overview - * \sa ops_parse() -*/ - -int ops_parse_and_print_errors(ops_parse_info_t *pinfo) -{ - ops_parse(pinfo,ops_false); - ops_print_errors(pinfo->errors); - return pinfo->errors ? 0 : 1; -} - -/** - * \ingroup Core_ReadPackets - * - * \brief Specifies whether one or more signature - * subpacket types should be returned parsed; or raw; or ignored. - * - * \param pinfo Pointer to previously allocated structure - * \param tag Packet tag. OPS_PTAG_SS_ALL for all SS tags; or one individual signature subpacket tag - * \param type Parse type - * \todo Make all packet types optional, not just subpackets */ -void ops_parse_options(ops_parse_info_t *pinfo, - ops_content_tag_t tag, - ops_parse_type_t type) -{ - int t8,t7; - - if(tag == OPS_PTAG_SS_ALL) - { - int n; - - for(n=0 ; n < 256 ; ++n) - ops_parse_options(pinfo,OPS_PTAG_SIGNATURE_SUBPACKET_BASE+n, - type); - return; - } - - if(!(tag >= OPS_PTAG_SIGNATURE_SUBPACKET_BASE && tag <= OPS_PTAG_SIGNATURE_SUBPACKET_BASE+NTAGS-1)) // ASSERT(tag >= OPS_PTAG_SIGNATURE_SUBPACKET_BASE && tag <= OPS_PTAG_SIGNATURE_SUBPACKET_BASE+NTAGS-1) - { - fprintf(stderr,"ops_parse_options: format error in options. Will not be parsed. Correct your code!\n") ; - return ; - } - - t8=(tag-OPS_PTAG_SIGNATURE_SUBPACKET_BASE)/8; - t7=1 << ((tag-OPS_PTAG_SIGNATURE_SUBPACKET_BASE)&7); - switch(type) - { - case OPS_PARSE_RAW: - pinfo->ss_raw[t8] |= t7; - pinfo->ss_parsed[t8] &= ~t7; - break; - - case OPS_PARSE_PARSED: - pinfo->ss_raw[t8] &= ~t7; - pinfo->ss_parsed[t8] |= t7; - break; - - case OPS_PARSE_IGNORE: - pinfo->ss_raw[t8] &= ~t7; - pinfo->ss_parsed[t8] &= ~t7; - break; - } -} - -/** -\ingroup Core_ReadPackets -\brief Creates a new zero-ed ops_parse_info_t struct -\sa ops_parse_info_delete() -*/ -ops_parse_info_t *ops_parse_info_new(void) - { return ops_mallocz(sizeof(ops_parse_info_t)); } - -/** -\ingroup Core_ReadPackets -\brief Free ops_parse_info_t struct and its contents -\sa ops_parse_info_new() -*/ -void ops_parse_info_delete(ops_parse_info_t *pinfo) - { - ops_parse_cb_info_t *cbinfo,*next; - - for(cbinfo=pinfo->cbinfo.next ; cbinfo ; cbinfo=next) - { - next=cbinfo->next; - free(cbinfo); - } - if(pinfo->rinfo.destroyer) - pinfo->rinfo.destroyer(&pinfo->rinfo); - ops_free_errors(pinfo->errors); - if(pinfo->rinfo.accumulated) - free(pinfo->rinfo.accumulated); - free(pinfo); - } - -/** -\ingroup Core_ReadPackets -\brief Returns the parse_info's reader_info -\return Pointer to the reader_info inside the parse_info -*/ -ops_reader_info_t *ops_parse_get_rinfo(ops_parse_info_t *pinfo) - { return &pinfo->rinfo; } - -/** -\ingroup Core_ReadPackets -\brief Sets the parse_info's callback -This is used when adding the first callback in a stack of callbacks. -\sa ops_parse_cb_push() -*/ - -void ops_parse_cb_set(ops_parse_info_t *pinfo,ops_parse_cb_t *cb,void *arg) - { - pinfo->cbinfo.cb=cb; - pinfo->cbinfo.arg=arg; - pinfo->cbinfo.errors=&pinfo->errors; - } - -/** -\ingroup Core_ReadPackets -\brief Adds a further callback to a stack of callbacks -\sa ops_parse_cb_set() -*/ -void ops_parse_cb_push(ops_parse_info_t *pinfo,ops_parse_cb_t *cb,void *arg) - { - ops_parse_cb_info_t *cbinfo=malloc(sizeof *cbinfo); - - *cbinfo=pinfo->cbinfo; - pinfo->cbinfo.next=cbinfo; - ops_parse_cb_set(pinfo,cb,arg); - } - -/** -\ingroup Core_ReadPackets -\brief Returns callback's arg -*/ -void *ops_parse_cb_get_arg(ops_parse_cb_info_t *cbinfo) - { return cbinfo->arg; } - -/** -\ingroup Core_ReadPackets -\brief Returns callback's errors -*/ -void *ops_parse_cb_get_errors(ops_parse_cb_info_t *cbinfo) - { return cbinfo->errors; } - -/** -\ingroup Core_ReadPackets -\brief Calls the parse_cb_info's callback if present -\return Return value from callback, if present; else OPS_FINISHED -*/ -ops_parse_cb_return_t ops_parse_cb(const ops_parser_content_t *content, - ops_parse_cb_info_t *cbinfo) - { - if(cbinfo->cb) - return cbinfo->cb(content,cbinfo); - else - return OPS_FINISHED; - } - -/** -\ingroup Core_ReadPackets -\brief Calls the next callback in the stack -\return Return value from callback -*/ -ops_parse_cb_return_t ops_parse_stacked_cb(const ops_parser_content_t *content, - ops_parse_cb_info_t *cbinfo) - { return ops_parse_cb(content,cbinfo->next); } - -/** -\ingroup Core_ReadPackets -\brief Returns the parse_info's errors -\return parse_info's errors -*/ -ops_error_t *ops_parse_info_get_errors(ops_parse_info_t *pinfo) - { return pinfo->errors; } - -ops_crypt_t *ops_parse_get_decrypt(ops_parse_info_t *pinfo) - { - if(pinfo->decrypt.algorithm) - return &pinfo->decrypt; - return NULL; - } - -// XXX: this could be improved by sharing all hashes that are the -// same, then duping them just before checking the signature. -void ops_parse_hash_init(ops_parse_info_t *pinfo,ops_hash_algorithm_t type, - const unsigned char *keyid) - { - ops_parse_hash_info_t *hash; - - pinfo->hashes=realloc(pinfo->hashes, - (pinfo->nhashes+1)*sizeof *pinfo->hashes); - hash=&pinfo->hashes[pinfo->nhashes++]; - - ops_hash_any(&hash->hash,type); - hash->hash.init(&hash->hash); - memcpy(hash->keyid,keyid,sizeof hash->keyid); - } - -void ops_parse_hash_data(ops_parse_info_t *pinfo,const void *data, - size_t length) - { - size_t n; - - for(n=0 ; n < pinfo->nhashes ; ++n) - pinfo->hashes[n].hash.add(&pinfo->hashes[n].hash,data,length); - } - -ops_hash_t *ops_parse_hash_find(ops_parse_info_t *pinfo, - const unsigned char keyid[OPS_KEY_ID_SIZE]) - { - size_t n; - - for(n=0 ; n < pinfo->nhashes ; ++n) - if(!memcmp(pinfo->hashes[n].keyid,keyid,OPS_KEY_ID_SIZE)) - return &pinfo->hashes[n].hash; - return NULL; - } - -/* vim:set textwidth=120: */ -/* vim:set ts=8: */ diff --git a/openpgpsdk/src/openpgpsdk/packet-parse.h b/openpgpsdk/src/openpgpsdk/packet-parse.h deleted file mode 100644 index fe65060c0..000000000 --- a/openpgpsdk/src/openpgpsdk/packet-parse.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - * Parser for OpenPGP packets - headers. - */ - -#ifndef OPS_PACKET_PARSE_H -#define OPS_PACKET_PARSE_H - -#include "types.h" -#include "packet.h" -#include "lists.h" - -/** ops_region_t */ -typedef struct ops_region - { - struct ops_region *parent; - unsigned length; - unsigned length_read; - unsigned last_read; /*!< length of last read, only valid in deepest child */ - ops_boolean_t indeterminate:1; - } ops_region_t; - -void ops_init_subregion(ops_region_t *subregion,ops_region_t *region); - -#if 0 -/** Return values for reader functions e.g. ops_packet_reader_t() */ -enum ops_reader_ret_t - { - OPS_R_OK =0, /*!< success */ - OPS_R_EOF =1, /*!< reached end of file, no data has been returned */ - OPS_R_EARLY_EOF =2, /*!< could not read the requested - number of bytes and either - OPS_RETURN_LENGTH was not set and at - least 1 byte was read, or there was - an abnormal end to the file (or - armoured block) */ - OPS_R_PARTIAL_READ =3, /*!< if OPS_RETURN_LENGTH is set and - the buffer was not filled */ - OPS_R_ERROR =4, /*!< if there was an error reading */ - }; -#endif - -/** ops_parse_callback_return_t */ -typedef enum - { - OPS_RELEASE_MEMORY, - OPS_KEEP_MEMORY, - OPS_FINISHED - } ops_parse_cb_return_t; - -typedef struct ops_parse_cb_info ops_parse_cb_info_t; - -typedef ops_parse_cb_return_t -ops_parse_cb_t(const ops_parser_content_t *content, - ops_parse_cb_info_t *cbinfo); - -typedef struct ops_parse_info ops_parse_info_t; -typedef struct ops_reader_info ops_reader_info_t; -typedef struct ops_crypt_info ops_crypt_info_t; - -/* - A reader MUST read at least one byte if it can, and should read up - to the number asked for. Whether it reads more for efficiency is - its own decision, but if it is a stacked reader it should never - read more than the length of the region it operates in (which it - would have to be given when it is stacked). - - If a read is short because of EOF, then it should return the short - read (obviously this will be zero on the second attempt, if not the - first). Because a reader is not obliged to do a full read, only a - zero return can be taken as an indication of EOF. - - If there is an error, then the callback should be notified, the - error stacked, and -1 should be returned. - - Note that although length is a size_t, a reader will never be asked - to read more than INT_MAX in one go. - - */ - -typedef int ops_reader_t(void *dest,size_t length,ops_error_t **errors, - ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo); - -typedef void ops_reader_destroyer_t(ops_reader_info_t *rinfo); - -ops_parse_info_t *ops_parse_info_new(void); -void ops_parse_info_delete(ops_parse_info_t *pinfo); -ops_error_t *ops_parse_info_get_errors(ops_parse_info_t *pinfo); -ops_crypt_t *ops_parse_get_decrypt(ops_parse_info_t *pinfo); - -void ops_parse_cb_set(ops_parse_info_t *pinfo,ops_parse_cb_t *cb,void *arg); -void ops_parse_cb_push(ops_parse_info_t *pinfo,ops_parse_cb_t *cb,void *arg); -void *ops_parse_cb_get_arg(ops_parse_cb_info_t *cbinfo); -void *ops_parse_cb_get_errors(ops_parse_cb_info_t *cbinfo); -void ops_reader_set(ops_parse_info_t *pinfo,ops_reader_t *reader,ops_reader_destroyer_t *destroyer,void *arg); -void ops_reader_push(ops_parse_info_t *pinfo,ops_reader_t *reader,ops_reader_destroyer_t *destroyer,void *arg); -void ops_reader_pop(ops_parse_info_t *pinfo); -void *ops_reader_get_arg_from_pinfo(ops_parse_info_t *pinfo); - -void *ops_reader_get_arg(ops_reader_info_t *rinfo); - -ops_parse_cb_return_t ops_parse_cb(const ops_parser_content_t *content, - ops_parse_cb_info_t *cbinfo); -ops_parse_cb_return_t ops_parse_stacked_cb(const ops_parser_content_t *content, - ops_parse_cb_info_t *cbinfo); -ops_reader_info_t *ops_parse_get_rinfo(ops_parse_info_t *pinfo); - -int ops_parse(ops_parse_info_t *parse_info,ops_boolean_t limit_packets); -int ops_parse_and_print_errors(ops_parse_info_t *parse_info); -int ops_parse_and_save_errs(ops_parse_info_t *parse_info,ops_ulong_list_t *errs); -int ops_parse_errs(ops_parse_info_t *parse_info,ops_ulong_list_t *errs); - -void ops_parse_and_validate(ops_parse_info_t *parse_info); - -void ops_parse_options(ops_parse_info_t *pinfo,ops_content_tag_t tag, - ops_parse_type_t type); - -ops_boolean_t ops_limited_read(unsigned char *dest,size_t length, - ops_region_t *region,ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo); -ops_boolean_t ops_stacked_limited_read(void *dest,unsigned length, - ops_region_t *region, - ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo); -void ops_parse_hash_init(ops_parse_info_t *pinfo,ops_hash_algorithm_t type, - const unsigned char *keyid); -void ops_parse_hash_data(ops_parse_info_t *pinfo,const void *data, - size_t length); -void ops_parse_hash_finish(ops_parse_info_t *pinfo); -ops_hash_t *ops_parse_hash_find(ops_parse_info_t *pinfo, - const unsigned char keyid[OPS_KEY_ID_SIZE]); - -ops_reader_t ops_stacked_read; - -/* vim:set textwidth=120: */ -/* vim:set ts=8: */ - - -#endif diff --git a/openpgpsdk/src/openpgpsdk/packet-print.c b/openpgpsdk/src/openpgpsdk/packet-print.c deleted file mode 100644 index 012531aab..000000000 --- a/openpgpsdk/src/openpgpsdk/packet-print.c +++ /dev/null @@ -1,1836 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/*! \file - \brief Standard API print functions -*/ - -#include -#include -#include "openpgpsdk/crypto.h" -#include "openpgpsdk/keyring.h" -#include "keyring_local.h" -#include "parse_local.h" -#include "openpgpsdk/packet-show.h" -#include "openpgpsdk/util.h" -#include "openpgpsdk/std_print.h" -#include "openpgpsdk/readerwriter.h" -#include "openpgpsdk/armour.h" - -static int indent=0; - -void print_bn( const char *name, - const BIGNUM *bn); -static void print_hex(const unsigned char *src, - size_t length); -static void print_hexdump(const char *name, - const unsigned char *data, - unsigned int len); -static void print_hexdump_data(const char *name, - const unsigned char *data, - unsigned int len); -static void print_indent(); -static void print_name(const char *name); -static void print_string_and_value(char *name, - const char *str, - unsigned char value); -static void print_tagname(const char *str); -static void print_time( char *name, - time_t time); -static void print_time_short(time_t time); -static void print_unsigned_int(char *name, - unsigned int val); -static void showtime(const char *name,time_t t); -static void showtime_short(time_t t); - -/** - \ingroup Core_Print - - Prints a public key in succinct detail - - \param key Ptr to public key -*/ - -void -ops_print_public_keydata(const ops_keydata_t *key) - { - printf("pub "); - - ops_show_pka(key->key.pkey.algorithm); - printf(" "); - - hexdump(key->key_id, OPS_KEY_ID_SIZE); - printf(" "); - - print_time_short(key->key.pkey.creation_time); - printf(" "); - - if (key->nuids==1) - { - // print on same line as other info - printf ("%s\n", key->uids[0].user_id); - } - else - { - // print all uids on separate line - unsigned int i; - printf("\n"); - for (i=0; inuids; i++) - { - printf("uid %s\n",key->uids[i].user_id); - } - } - } - -/** -\ingroup Core_Print -\param pkey -*/ -void -ops_print_public_key(const ops_public_key_t *pkey) - { - printf("------- PUBLIC KEY ------\n"); - print_unsigned_int("Version",pkey->version); - print_time("Creation Time", pkey->creation_time); - if(pkey->version == OPS_V3) - print_unsigned_int("Days Valid",pkey->days_valid); - - print_string_and_value("Algorithm",ops_show_pka(pkey->algorithm), - pkey->algorithm); - - switch(pkey->algorithm) - { - case OPS_PKA_DSA: - print_bn("p",pkey->key.dsa.p); - print_bn("q",pkey->key.dsa.q); - print_bn("g",pkey->key.dsa.g); - print_bn("y",pkey->key.dsa.y); - break; - - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: - print_bn("n",pkey->key.rsa.n); - print_bn("e",pkey->key.rsa.e); - break; - - case OPS_PKA_ELGAMAL: - case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - print_bn("p",pkey->key.elgamal.p); - print_bn("g",pkey->key.elgamal.g); - print_bn("y",pkey->key.elgamal.y); - break; - - default: - assert(0); - } - - printf("------- end of PUBLIC KEY ------\n"); - } - -/** - \ingroup Core_Print - - Prints a public key in full detail - - \param key Ptr to public key -*/ - -void -ops_print_public_keydata_verbose(const ops_keydata_t *key) - { - const ops_public_key_t* pkey=&key->key.pkey; - - ops_print_public_key(pkey); - } - -/** - \ingroup Core_Print - - Prints a secret key - - \param key Ptr to public key -*/ - -void -ops_print_secret_keydata(const ops_keydata_t *key) - { - printf("sec "); - ops_show_pka(key->key.pkey.algorithm); - printf(" "); - - hexdump(key->key_id, OPS_KEY_ID_SIZE); - printf(" "); - - print_time_short(key->key.pkey.creation_time); - printf(" "); - - if (key->nuids==1) - { - // print on same line as other info - printf ("%s\n", key->uids[0].user_id); - } - else - { - // print all uids on separate line - unsigned int i; - printf("\n"); - for (i=0; inuids; i++) - { - printf("uid %s\n",key->uids[i].user_id); - } - } - } - -/* -void -ops_print_secret_key_verbose(const ops_secret_key_t* skey) - { - if(key->type == OPS_PTAG_CT_SECRET_KEY) - print_tagname("SECRET_KEY"); - else - print_tagname("ENCRYPTED_SECRET_KEY"); - ops_print_secret_key(key->type,skey); - } -*/ - -/** -\ingroup Core_Print -\param type -\param skey -*/ -void -ops_print_secret_key_verbose(const ops_content_tag_t type, const ops_secret_key_t* skey) - { - printf("------- SECRET KEY or ENCRYPTED SECRET KEY ------\n"); - if(type == OPS_PTAG_CT_SECRET_KEY) - print_tagname("SECRET_KEY"); - else - print_tagname("ENCRYPTED_SECRET_KEY"); - // ops_print_public_key(key); - printf("S2K Usage: %d\n",skey->s2k_usage); - if(skey->s2k_usage != OPS_S2KU_NONE) - { - printf("S2K Specifier: %d\n",skey->s2k_specifier); - printf("Symmetric algorithm: %d (%s)\n",skey->algorithm, - ops_show_symmetric_algorithm(skey->algorithm)); - printf("Hash algorithm: %d (%s)\n",skey->hash_algorithm, - ops_show_hash_algorithm(skey->hash_algorithm)); - if(skey->s2k_specifier != OPS_S2KS_SIMPLE) - print_hexdump("Salt",skey->salt,sizeof skey->salt); - if(skey->s2k_specifier == OPS_S2KS_ITERATED_AND_SALTED) - printf("Octet count: %d\n",skey->octet_count); - print_hexdump("IV",skey->iv,ops_block_size(skey->algorithm)); - } - - /* no more set if encrypted */ - if(type == OPS_PTAG_CT_ENCRYPTED_SECRET_KEY) - return; - - switch(skey->public_key.algorithm) - { - case OPS_PKA_RSA: - print_bn("d",skey->key.rsa.d); - print_bn("p",skey->key.rsa.p); - print_bn("q",skey->key.rsa.q); - print_bn("u",skey->key.rsa.u); - break; - - case OPS_PKA_DSA: - print_bn("x",skey->key.dsa.x); - break; - - default: - assert(0); - } - - if(skey->s2k_usage == OPS_S2KU_ENCRYPTED_AND_HASHED) - print_hexdump("Checkhash",skey->checkhash,OPS_CHECKHASH_SIZE); - else - printf("Checksum: %04x\n",skey->checksum); - - printf("------- end of SECRET KEY or ENCRYPTED SECRET KEY ------\n"); - } - -/** -\ingroup Core_Print -\param key -*/ -void -ops_print_secret_keydata_verbose(const ops_keydata_t *key) - { - const ops_secret_key_t* skey=&key->key.skey; - ops_print_public_keydata(key); - ops_print_secret_key_verbose(key->type,skey); - } - -// static functions - -static void print_unsigned_int(char *name, unsigned int val) - { - print_name(name); - printf("%d\n", val); - } - -static void print_time( char *name, time_t time) - { - print_indent(); - printf("%s: ",name); - showtime("time",time); - printf("\n"); - } - -static void print_time_short(time_t time) - { - showtime_short(time); - } - -static void print_string_and_value(char *name,const char *str, - unsigned char value) - { - print_name(name); - - printf("%s", str); - printf(" (0x%x)", value); - printf("\n"); - } - -void print_bn( const char *name, const BIGNUM *bn) - { - print_indent(); - printf("%s=",name); - if(bn) - { - BN_print_fp(stdout,bn); - putchar('\n'); - } - else - puts("(unset)"); - } - -static void print_tagname(const char *str) - { - print_indent(); - printf("%s packet\n", str); - } - -static void print_hexdump(const char *name, - const unsigned char *data, - unsigned int len) - { - print_name(name); - - printf("len=%d, data=0x", len); - print_hex(data,len); - printf("\n"); - } - -static void print_hexdump_data(const char *name, - const unsigned char *data, - unsigned int len) - { - print_name(name); - - printf("0x"); - print_hex(data,len); - printf("\n"); - } - -static void print_data(const char *name,const ops_data_t *data) - { - print_hexdump(name,data->contents,data->len); - } - - -static void print_name(const char *name) - { - print_indent(); - if(name) - printf("%s: ",name); - } - -static void print_indent() - { - int i=0; - - for(i=0 ; i < indent ; i++) - printf(" "); - } - -/* printhex is now print_hex for consistency */ -static void print_hex(const unsigned char *src,size_t length) - { - while(length--) - printf("%02X",*src++); - } - -static void showtime(const char *name,time_t t) - { - printf("%s=" TIME_T_FMT " (%.24s)",name,t,ctime(&t)); - } -static void showtime_short(time_t t) - { - struct tm* tm; - /* - const int maxbuf=512; - char buf[maxbuf+1]; - buf[maxbuf]='\0'; - // this needs to be tm struct - strftime(buf,maxbuf,"%F",&t); - printf(buf); - */ - tm=gmtime(&t); - printf ("%04d-%02d-%02d", tm->tm_year+1900, tm->tm_mon, tm->tm_mday); - } - - -static void print_packet_hex(const ops_packet_t *packet) - { - unsigned char *cur; - int i; - int rem; - int blksz=4; - - printf("\nhexdump of packet contents follows:\n"); - - - for (i=1,cur=packet->raw; cur<(packet->raw+packet->length); cur+=blksz,i++) - { - rem = packet->raw+packet->length-cur; - hexdump(cur,rem<=blksz ? rem : blksz); - printf(" "); - if (!(i%8)) - printf("\n"); - - } - - printf("\n"); - } - -static void print_escaped(const unsigned char *data,size_t length) - { - while(length-- > 0) - { - if((*data >= 0x20 && *data < 0x7f && *data != '%') || *data == '\n') - putchar(*data); - else - printf("%%%02x",*data); - ++data; - } - } - -static void print_string(const char *name,const char *str) - { - print_name(name); - print_escaped((unsigned char *)str,strlen(str)); - putchar('\n'); - } - -static void print_utf8_string(const char *name,const unsigned char *str) - { - // \todo Do this better for non-English character sets - print_string(name,(const char *)str); - } - -static void print_duration(char *name, time_t time) - { - int mins, hours, days, years; - - print_indent(); - printf("%s: ",name); - printf("duration " TIME_T_FMT " seconds",time); - - mins=time/60; - hours=mins/60; - days=hours/24; - years=days/365; - - printf(" (approx. "); - if (years) - printf("%d %s",years,years==1?"year":"years"); - else if (days) - printf("%d %s",days,days==1?"day":"days"); - else if (hours) - printf("%d %s", hours, hours==1?"hour":"hours"); - - printf(")"); - printf("\n"); - } - -static void print_boolean(const char *name, unsigned char bool) - { - print_name(name); - - if(bool) - printf("Yes"); - else - printf("No"); - printf("\n"); - } - -static void print_text_breakdown( ops_text_t *text) - { - unsigned i; - char *prefix=".. "; - - /* these were recognised */ - - for(i=0 ; iknown.used ; i++) - { - print_indent(); - fputs(prefix,stdout); - printf("%s\n",text->known.strings[i]); - } - - /* these were not recognised. the strings will contain the hex value - of the unrecognised value in string format - see process_octet_str() - */ - - if(text->unknown.used) - { - printf("\n"); - print_indent(); - printf("Not Recognised: "); - } - for( i=0; i < text->unknown.used; i++) - { - print_indent(); - fputs(prefix,stdout); - printf("%s\n",text->unknown.strings[i]); - } - - } - -static void print_headers(const ops_headers_t *headers) - { - unsigned n; - - for(n=0 ; n < headers->nheaders ; ++n) - printf("%s=%s\n",headers->headers[n].key,headers->headers[n].value); - } - -static void print_block(const char *name,const unsigned char *str, - size_t length) - { - int o=length; - - print_indent(); - printf(">>>>> %s >>>>>\n",name); - - print_indent(); - for( ; length > 0 ; --length) - { - if(*str >= 0x20 && *str < 0x7f && *str != '%') - putchar(*str); - else if(*str == '\n') - { - putchar(*str); - print_indent(); - } - else - printf("%%%02x",*str); - ++str; - } - if(o && str[-1] != '\n') - { - putchar('\n'); - print_indent(); - fputs("[no newline]",stdout); - } - else - print_indent(); - printf("<<<<< %s <<<<<\n",name); - } - -/** -\ingroup Core_Print -\param tag -\param key -*/ -void ops_print_pk_session_key(ops_content_tag_t tag, - const ops_pk_session_key_t *key) - { - if(tag == OPS_PTAG_CT_PK_SESSION_KEY) - print_tagname("PUBLIC KEY SESSION KEY"); - else - print_tagname("ENCRYPTED PUBLIC KEY SESSION KEY"); - - printf("Version: %d\n",key->version); - print_hexdump("Key ID",key->key_id,sizeof key->key_id); - printf("Algorithm: %d (%s)\n",key->algorithm, - ops_show_pka(key->algorithm)); - switch(key->algorithm) - { - case OPS_PKA_RSA: - print_bn("encrypted_m",key->parameters.rsa.encrypted_m); - break; - - case OPS_PKA_ELGAMAL: - print_bn("g_to_k",key->parameters.elgamal.g_to_k); - print_bn("encrypted_m",key->parameters.elgamal.encrypted_m); - break; - - default: - assert(0); - } - - if(tag != OPS_PTAG_CT_PK_SESSION_KEY) - return; - - printf("Symmetric algorithm: %d (%s)\n",key->symmetric_algorithm, - ops_show_symmetric_algorithm(key->symmetric_algorithm)); - print_hexdump("Key",key->key,ops_key_size(key->symmetric_algorithm)); - printf("Checksum: %04x\n",key->checksum); - } - -static void start_subpacket(unsigned type) - { - indent++; - print_indent(); - printf("-- %s (type 0x%02x)\n", - ops_show_ss_type(type), - type-OPS_PTAG_SIGNATURE_SUBPACKET_BASE); - } - -static void end_subpacket() - { - indent--; - } - -/** -\ingroup Core_Print -\param content_ -*/ -int ops_print_packet(const ops_parser_content_t *content_) - { - const ops_parser_content_union_t *content=&content_->content; - ops_text_t *text; - const char *str; - static ops_boolean_t unarmoured; - - if(unarmoured && content_->tag != OPS_PTAG_CT_UNARMOURED_TEXT) - { - unarmoured=ops_false; - puts("UNARMOURED TEXT ends"); - } - - if (content_->tag==OPS_PARSER_PTAG) - { - printf("=> OPS_PARSER_PTAG: %s\n", ops_show_packet_tag(content->ptag.content_tag)); - } - else - { - printf("=> %s\n", ops_show_packet_tag(content_->tag)); - } - - switch(content_->tag) - { - case OPS_PARSER_ERROR: - printf("parse error: %s\n",content->error.error); - break; - - case OPS_PARSER_ERRCODE: - printf("parse error: %s\n", - ops_errcode(content->errcode.errcode)); - break; - - case OPS_PARSER_PACKET_END: - print_packet_hex(&content->packet); - break; - - case OPS_PARSER_PTAG: - if(content->ptag.content_tag == OPS_PTAG_CT_PUBLIC_KEY) - { - indent=0; - printf("\n*** NEXT KEY ***\n"); - } - - printf("\n"); - print_indent(); - printf("==== ptag new_format=%d content_tag=%d length_type=%d" - " length=0x%x (%d) position=0x%x (%d)\n",content->ptag.new_format, - content->ptag.content_tag,content->ptag.length_type, - content->ptag.length,content->ptag.length, - content->ptag.position,content->ptag.position); - print_tagname(ops_show_packet_tag(content->ptag.content_tag)); - break; - - case OPS_PTAG_CT_SE_DATA_HEADER: - print_tagname("SYMMETRIC ENCRYPTED DATA"); - break; - - case OPS_PTAG_CT_SE_IP_DATA_HEADER: - print_tagname("SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA HEADER"); - printf("Version: %d\n",content->se_ip_data_header.version); - break; - - case OPS_PTAG_CT_SE_IP_DATA_BODY: - print_tagname("SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA BODY"); - printf(" data body length=%d\n", - content->se_data_body.length); - printf(" data="); - hexdump(content->se_data_body.data, - content->se_data_body.length); - printf("\n"); - break; - - case OPS_PTAG_CT_PUBLIC_KEY: - case OPS_PTAG_CT_PUBLIC_SUBKEY: - if (content_->tag == OPS_PTAG_CT_PUBLIC_KEY) - print_tagname("PUBLIC KEY"); - else - print_tagname("PUBLIC SUBKEY"); - ops_print_public_key(&content->public_key); - break; - - case OPS_PTAG_CT_TRUST: - print_tagname("TRUST"); - print_data("Trust",&content->trust.data); - break; - - case OPS_PTAG_CT_USER_ID: - /* XXX: how do we print UTF-8? */ - print_tagname("USER ID"); - print_utf8_string("user_id",content->user_id.user_id); - break; - - case OPS_PTAG_CT_SIGNATURE: - print_tagname("SIGNATURE"); - print_indent(); - print_unsigned_int("Signature Version", - content->signature.info.version); - if (content->signature.info.creation_time_set) - print_time("Signature Creation Time", - content->signature.info.creation_time); - - print_string_and_value("Signature Type", - ops_show_sig_type(content->signature.info.type), - content->signature.info.type); - - if(content->signature.info.signer_id_set) - print_hexdump_data("Signer ID", - content->signature.info.signer_id, - sizeof content->signature.info.signer_id); - - print_string_and_value("Public Key Algorithm", - ops_show_pka(content->signature.info.key_algorithm), - content->signature.info.key_algorithm); - print_string_and_value("Hash Algorithm", - ops_show_hash_algorithm(content->signature.info.hash_algorithm), - content->signature.info.hash_algorithm); - - print_unsigned_int("Hashed data len", content->signature.info.v4_hashed_data_length); - - print_indent(); - print_hexdump_data("hash2",&content->signature.hash2[0],2); - - switch(content->signature.info.key_algorithm) - { - case OPS_PKA_RSA: - case OPS_PKA_RSA_SIGN_ONLY: - print_bn("sig",content->signature.info.signature.rsa.sig); - break; - - case OPS_PKA_DSA: - print_bn("r",content->signature.info.signature.dsa.r); - print_bn("s",content->signature.info.signature.dsa.s); - break; - - case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - print_bn("r",content->signature.info.signature.elgamal.r); - print_bn("s",content->signature.info.signature.elgamal.s); - break; - - default: - assert(0); - } - - if(content->signature.hash) - printf("data hash is set\n"); - - break; - - case OPS_PTAG_CT_COMPRESSED: - print_tagname("COMPRESSED"); - print_unsigned_int("Compressed Data Type", content->compressed.type); - break; - - case OPS_PTAG_CT_ONE_PASS_SIGNATURE: - print_tagname("ONE PASS SIGNATURE"); - - print_unsigned_int("Version",content->one_pass_signature.version); - print_string_and_value("Signature Type", - ops_show_sig_type(content->one_pass_signature.sig_type), - content->one_pass_signature.sig_type); - print_string_and_value("Hash Algorithm", - ops_show_hash_algorithm(content->one_pass_signature.hash_algorithm), - content->one_pass_signature.hash_algorithm); - print_string_and_value("Public Key Algorithm", - ops_show_pka(content->one_pass_signature.key_algorithm), - content->one_pass_signature.key_algorithm); - print_hexdump_data("Signer ID", - content->one_pass_signature.keyid, - sizeof content->one_pass_signature.keyid); - - print_unsigned_int("Nested", - content->one_pass_signature.nested); - break; - - case OPS_PTAG_CT_USER_ATTRIBUTE: - print_tagname("USER ATTRIBUTE"); - print_hexdump("User Attribute", - content->user_attribute.data.contents, - content->user_attribute.data.len); - break; - - case OPS_PTAG_RAW_SS: - assert(!content_->critical); - start_subpacket(content_->tag); - print_unsigned_int("Raw Signature Subpacket: tag", - content->ss_raw.tag-OPS_PTAG_SIGNATURE_SUBPACKET_BASE); - print_hexdump("Raw Data", - content->ss_raw.raw, - content->ss_raw.length); - break; - - case OPS_PTAG_SS_CREATION_TIME: - start_subpacket(content_->tag); - print_time("Signature Creation Time",content->ss_time.time); - end_subpacket(); - break; - - case OPS_PTAG_SS_EXPIRATION_TIME: - start_subpacket(content_->tag); - print_duration("Signature Expiration Time",content->ss_time.time); - end_subpacket(); - break; - - case OPS_PTAG_SS_KEY_EXPIRATION_TIME: - start_subpacket(content_->tag); - print_duration("Key Expiration Time", content->ss_time.time); - end_subpacket(); - break; - - case OPS_PTAG_SS_TRUST: - start_subpacket(content_->tag); - print_string("Trust Signature",""); - print_unsigned_int("Level", - content->ss_trust.level); - print_unsigned_int("Amount", - content->ss_trust.amount); - end_subpacket(); - break; - - case OPS_PTAG_SS_REVOCABLE: - start_subpacket(content_->tag); - print_boolean("Revocable",content->ss_revocable.revocable); - end_subpacket(); - break; - - case OPS_PTAG_SS_REVOCATION_KEY: - start_subpacket(content_->tag); - /* not yet tested */ - printf (" revocation key: class=0x%x", - content->ss_revocation_key.clss); - if (content->ss_revocation_key.clss&0x40) - printf (" (sensitive)"); - printf (", algid=0x%x", content->ss_revocation_key.algid); - printf(", fingerprint="); - hexdump(content->ss_revocation_key.fingerprint,20); - printf("\n"); - end_subpacket(); - break; - - case OPS_PTAG_SS_ISSUER_KEY_ID: - start_subpacket(content_->tag); - print_hexdump("Issuer Key Id", &content->ss_issuer_key_id.key_id[0], - sizeof content->ss_issuer_key_id.key_id); - end_subpacket(); - break; - - case OPS_PTAG_SS_PREFERRED_SKA: - start_subpacket(content_->tag); - print_data( "Preferred Symmetric Algorithms", - &content->ss_preferred_ska.data); - - text = ops_showall_ss_preferred_ska(content->ss_preferred_ska); - print_text_breakdown(text); - ops_text_free(text); - - end_subpacket(); - break; - - case OPS_PTAG_SS_PRIMARY_USER_ID: - start_subpacket(content_->tag); - print_boolean("Primary User ID", - content->ss_primary_user_id.primary_user_id); - end_subpacket(); - break; - - case OPS_PTAG_SS_PREFERRED_HASH: - start_subpacket(content_->tag); - print_data("Preferred Hash Algorithms", - &content->ss_preferred_hash.data); - - text = ops_showall_ss_preferred_hash(content->ss_preferred_hash); - print_text_breakdown(text); - ops_text_free(text); - end_subpacket(); - break; - - case OPS_PTAG_SS_PREFERRED_COMPRESSION: - start_subpacket(content_->tag); - print_data( "Preferred Compression Algorithms", - &content->ss_preferred_compression.data); - - text = ops_showall_ss_preferred_compression(content->ss_preferred_compression); - print_text_breakdown(text); - ops_text_free(text); - end_subpacket(); - break; - - case OPS_PTAG_SS_KEY_FLAGS: - start_subpacket(content_->tag); - print_data( "Key Flags", &content->ss_key_flags.data); - - text = ops_showall_ss_key_flags(content->ss_key_flags); - print_text_breakdown( text); - ops_text_free(text); - - end_subpacket(); - break; - - case OPS_PTAG_SS_KEY_SERVER_PREFS: - start_subpacket(content_->tag); - print_data( "Key Server Preferences", - &content->ss_key_server_prefs.data); - - text = ops_showall_ss_key_server_prefs(content->ss_key_server_prefs); - print_text_breakdown( text); - ops_text_free(text); - - end_subpacket(); - break; - - case OPS_PTAG_SS_FEATURES: - start_subpacket(content_->tag); - print_data( "Features", - &content->ss_features.data); - - text = ops_showall_ss_features(content->ss_features); - print_text_breakdown( text); - ops_text_free(text); - - end_subpacket(); - break; - - case OPS_PTAG_SS_NOTATION_DATA: - start_subpacket(content_->tag); - print_indent(); - printf("Notation Data:\n"); - - indent++; - print_data( "Flags", - &content->ss_notation_data.flags); - text = ops_showall_ss_notation_data_flags(content->ss_notation_data); - print_text_breakdown( text); - ops_text_free(text); - - /* xxx - TODO: print out UTF - rachel */ - - print_data( "Name", - &content->ss_notation_data.name); - - print_data( "Value", - &content->ss_notation_data.value); - - indent--; - end_subpacket(); - break; - - case OPS_PTAG_SS_REGEXP: - start_subpacket(content_->tag); - print_hexdump("Regular Expression", - (unsigned char *)content->ss_regexp.text, - strlen(content->ss_regexp.text)); - print_string(NULL, - content->ss_regexp.text); - end_subpacket(); - break; - - case OPS_PTAG_SS_POLICY_URI: - start_subpacket(content_->tag); - print_string("Policy URL", - content->ss_policy_url.text); - end_subpacket(); - break; - - case OPS_PTAG_SS_SIGNERS_USER_ID: - start_subpacket(content_->tag); - print_utf8_string("Signer's User ID",content->ss_signers_user_id.user_id); - end_subpacket(); - break; - - case OPS_PTAG_SS_PREFERRED_KEY_SERVER: - start_subpacket(content_->tag); - print_string("Preferred Key Server", - content->ss_preferred_key_server.text); - end_subpacket(); - break; - - case OPS_PTAG_SS_EMBEDDED_SIGNATURE: - start_subpacket(content_->tag); - end_subpacket(); // \todo print out contents? - break; - - case OPS_PTAG_SS_USERDEFINED00: - case OPS_PTAG_SS_USERDEFINED01: - case OPS_PTAG_SS_USERDEFINED02: - case OPS_PTAG_SS_USERDEFINED03: - case OPS_PTAG_SS_USERDEFINED04: - case OPS_PTAG_SS_USERDEFINED05: - case OPS_PTAG_SS_USERDEFINED06: - case OPS_PTAG_SS_USERDEFINED07: - case OPS_PTAG_SS_USERDEFINED08: - case OPS_PTAG_SS_USERDEFINED09: - case OPS_PTAG_SS_USERDEFINED10: - start_subpacket(content_->tag); - print_hexdump("Internal or user-defined", - content->ss_userdefined.data.contents, - content->ss_userdefined.data.len); - end_subpacket(); - break; - - case OPS_PTAG_SS_RESERVED: - start_subpacket(content_->tag); - print_hexdump("Reserved", - content->ss_userdefined.data.contents, - content->ss_userdefined.data.len); - end_subpacket(); - break; - - case OPS_PTAG_SS_REVOCATION_REASON: - start_subpacket(content_->tag); - print_hexdump("Revocation Reason", - &content->ss_revocation_reason.code, - 1); - str=ops_show_ss_rr_code(content->ss_revocation_reason.code); - print_string(NULL,str); - /* xxx - todo : output text as UTF-8 string */ - end_subpacket(); - break; - - case OPS_PTAG_CT_LITERAL_DATA_HEADER: - print_tagname("LITERAL DATA HEADER"); - printf(" literal data header format=%c filename='%s'\n", - content->literal_data_header.format, - content->literal_data_header.filename); - showtime(" modification time", - content->literal_data_header.modification_time); - printf("\n"); - break; - - case OPS_PTAG_CT_LITERAL_DATA_BODY: - print_tagname("LITERAL DATA BODY"); - printf(" literal data body length=%d\n", - content->literal_data_body.length); - printf(" data="); - print_escaped(content->literal_data_body.data, - content->literal_data_body.length); - printf("\n"); - break; - - case OPS_PTAG_CT_SIGNATURE_HEADER: - print_tagname("SIGNATURE"); - print_indent(); - print_unsigned_int("Signature Version", - content->signature.info.version); - if(content->signature.info.creation_time_set) - print_time("Signature Creation Time", content->signature.info.creation_time); - - print_string_and_value("Signature Type", - ops_show_sig_type(content->signature.info.type), - content->signature.info.type); - - if(content->signature.info.signer_id_set) - print_hexdump_data("Signer ID", - content->signature.info.signer_id, - sizeof content->signature.info.signer_id); - - print_string_and_value("Public Key Algorithm", - ops_show_pka(content->signature.info.key_algorithm), - content->signature.info.key_algorithm); - print_string_and_value("Hash Algorithm", - ops_show_hash_algorithm(content->signature.info.hash_algorithm), - content->signature.info.hash_algorithm); - - break; - - case OPS_PTAG_CT_SIGNATURE_FOOTER: - print_indent(); - print_hexdump_data("hash2",&content->signature.hash2[0],2); - - switch(content->signature.info.key_algorithm) - { - case OPS_PKA_RSA: - print_bn("sig",content->signature.info.signature.rsa.sig); - break; - - case OPS_PKA_DSA: - print_bn("r",content->signature.info.signature.dsa.r); - print_bn("s",content->signature.info.signature.dsa.s); - break; - - case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - print_bn("r",content->signature.info.signature.elgamal.r); - print_bn("s",content->signature.info.signature.elgamal.s); - break; - - case OPS_PKA_PRIVATE00: - case OPS_PKA_PRIVATE01: - case OPS_PKA_PRIVATE02: - case OPS_PKA_PRIVATE03: - case OPS_PKA_PRIVATE04: - case OPS_PKA_PRIVATE05: - case OPS_PKA_PRIVATE06: - case OPS_PKA_PRIVATE07: - case OPS_PKA_PRIVATE08: - case OPS_PKA_PRIVATE09: - case OPS_PKA_PRIVATE10: - print_data("Private/Experimental", - &content->signature.info.signature.unknown.data); - break; - - default: - assert(0); - } - break; - - case OPS_PARSER_CMD_GET_SK_PASSPHRASE: - print_tagname("OPS_PARSER_CMD_GET_SK_PASSPHRASE"); - /* - if(passphrase_prompt) - { - print_secret_key(OPS_PTAG_CT_ENCRYPTED_SECRET_KEY, - content->secret_key_passphrase.secret_key); - *content->secret_key_passphrase.passphrase=ops_get_passphrase(); - if(!**content->secret_key_passphrase.passphrase) - break; - return OPS_KEEP_MEMORY; - } - else - printf(">>> ASKED FOR PASSPHRASE <<<\n"); - */ - - break; - - case OPS_PTAG_CT_SECRET_KEY: - print_tagname("OPS_PTAG_CT_SECRET_KEY"); - ops_print_secret_key_verbose(content_->tag,&content->secret_key); - break; - - case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY: - // print_secret_key(content_->tag,&content->secret_key); - print_tagname("OPS_PTAG_CT_ENCRYPTED_SECRET_KEY"); - ops_print_secret_key_verbose(content_->tag,&content->secret_key); - break; - - case OPS_PTAG_CT_ARMOUR_HEADER: - print_tagname("ARMOUR HEADER"); - print_string("type",content->armour_header.type); - break; - - case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER: - print_tagname("SIGNED CLEARTEXT HEADER"); - print_headers(&content->signed_cleartext_header.headers); - break; - - case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY: - print_tagname("SIGNED CLEARTEXT BODY"); - print_block("signed cleartext",content->signed_cleartext_body.data, - content->signed_cleartext_body.length); - break; - - case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER: - print_tagname("SIGNED CLEARTEXT TRAILER"); - printf("hash algorithm: %d\n", - content->signed_cleartext_trailer.hash->algorithm); - printf("\n"); - break; - - case OPS_PTAG_CT_UNARMOURED_TEXT: - if(!unarmoured) - { - print_tagname("UNARMOURED TEXT"); - unarmoured=ops_true; - } - putchar('['); - print_escaped(content->unarmoured_text.data, - content->unarmoured_text.length); - putchar(']'); - break; - - case OPS_PTAG_CT_ARMOUR_TRAILER: - print_tagname("ARMOUR TRAILER"); - print_string("type",content->armour_header.type); - break; - - case OPS_PTAG_CT_PK_SESSION_KEY: - case OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY: - ops_print_pk_session_key(content_->tag,&content->pk_session_key); - break; - - case OPS_PARSER_CMD_GET_SECRET_KEY: - ops_print_pk_session_key(OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY, - content->get_secret_key.pk_session_key); - break; - - default: - print_tagname("UNKNOWN PACKET TYPE"); - fprintf(stderr,"ops_print_packet: unknown tag=%d (0x%x)\n",content_->tag, - content_->tag); - exit(1); - } - return 1; - } - -static ops_parse_cb_return_t cb_list_packets(const ops_parser_content_t * content_, ops_parse_cb_info_t *cbinfo) - { - OPS_USED(cbinfo); - - ops_print_packet(content_); -#ifdef XXX - if(unarmoured && content_->tag != OPS_PTAG_CT_UNARMOURED_TEXT) - { - unarmoured=ops_false; - puts("UNARMOURED TEXT ends"); - } - - switch(content_->tag) - { - case OPS_PARSER_ERROR: - printf("parse error: %s\n",content->error.error); - break; - - case OPS_PARSER_ERRCODE: - printf("parse error: %s\n", - ops_errcode(content->errcode.errcode)); - break; - - case OPS_PARSER_PACKET_END: - print_packet_hex(&content->packet); - break; - - case OPS_PARSER_PTAG: - if(content->ptag.content_tag == OPS_PTAG_CT_PUBLIC_KEY) - { - indent=0; - printf("\n*** NEXT KEY ***\n"); - } - - printf("\n"); - print_indent(); - printf("==== ptag new_format=%d content_tag=%d length_type=%d" - " length=0x%x (%d) position=0x%x (%d)\n",content->ptag.new_format, - content->ptag.content_tag,content->ptag.length_type, - content->ptag.length,content->ptag.length, - content->ptag.position,content->ptag.position); - print_tagname(ops_show_packet_tag(content->ptag.content_tag)); - break; - - case OPS_PTAG_CT_SE_DATA_HEADER: - print_tagname("SYMMETRIC ENCRYPTED DATA"); - break; - - case OPS_PTAG_CT_SE_IP_DATA_HEADER: - print_tagname("SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA HEADER"); - printf("Version: %d\n",content->se_ip_data_header.version); - break; - - case OPS_PTAG_CT_SE_IP_DATA_BODY: - print_tagname("SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA BODY"); - printf(" data body length=%d\n", - content->se_data_body.length); - printf(" data="); - hexdump(content->se_data_body.data, - content->se_data_body.length); - printf("\n"); - break; - - case OPS_PTAG_CT_PUBLIC_KEY: - case OPS_PTAG_CT_PUBLIC_SUBKEY: - if (content_->tag == OPS_PTAG_CT_PUBLIC_KEY) - print_tagname("PUBLIC KEY"); - else - print_tagname("PUBLIC SUBKEY"); - - ops_print_public_key(&content->public_key); - break; - - case OPS_PTAG_CT_TRUST: - print_tagname("TRUST"); - print_data("Trust",&content->trust.data); - break; - - case OPS_PTAG_CT_USER_ID: - /* XXX: how do we print UTF-8? */ - print_tagname("USER ID"); - print_utf8_string("user_id",content->user_id.user_id); - break; - - case OPS_PTAG_CT_SIGNATURE: - print_tagname("SIGNATURE"); - print_indent(); - print_unsigned_int("Signature Version", - content->signature.info.version); - if (content->signature.info.creation_time_set) - print_time("Signature Creation Time", - content->signature.info.creation_time); - - print_string_and_value("Signature Type", - ops_show_sig_type(content->signature.info.type), - content->signature.info.type); - - if(content->signature.info.signer_id_set) - print_hexdump_data("Signer ID", - content->signature.info.signer_id, - sizeof content->signature.info.signer_id); - - print_string_and_value("Public Key Algorithm", - ops_show_pka(content->signature.info.key_algorithm), - content->signature.info.key_algorithm); - print_string_and_value("Hash Algorithm", - ops_show_hash_algorithm(content->signature.info.hash_algorithm), - content->signature.info.hash_algorithm); - print_unsigned_int("Hashed data len", content->signature.info.v4_hashed_data_length); - - print_indent(); - print_hexdump_data("hash2",&content->signature.hash2[0],2); - - switch(content->signature.info.key_algorithm) - { - case OPS_PKA_RSA: - case OPS_PKA_RSA_SIGN_ONLY: - print_bn("sig",content->signature.info.signature.rsa.sig); - break; - - case OPS_PKA_DSA: - print_bn("r",content->signature.info.signature.dsa.r); - print_bn("s",content->signature.info.signature.dsa.s); - break; - - case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - print_bn("r",content->signature.info.signature.elgamal.r); - print_bn("s",content->signature.info.signature.elgamal.s); - break; - - default: - assert(0); - } - - if(content->signature.hash) - printf("data hash is set\n"); - - break; - - case OPS_PTAG_CT_COMPRESSED: - print_tagname("COMPRESSED"); - print_unsigned_int("Compressed Data Type", content->compressed.type); - break; - - case OPS_PTAG_CT_ONE_PASS_SIGNATURE: - print_tagname("ONE PASS SIGNATURE"); - - print_unsigned_int("Version",content->one_pass_signature.version); - print_string_and_value("Signature Type", - ops_show_sig_type(content->one_pass_signature.sig_type), - content->one_pass_signature.sig_type); - print_string_and_value("Hash Algorithm", - ops_show_hash_algorithm(content->one_pass_signature.hash_algorithm), - content->one_pass_signature.hash_algorithm); - print_string_and_value("Public Key Algorithm", - ops_show_pka(content->one_pass_signature.key_algorithm), - content->one_pass_signature.key_algorithm); - print_hexdump_data("Signer ID", - content->one_pass_signature.keyid, - sizeof content->one_pass_signature.keyid); - - print_unsigned_int("Nested", - content->one_pass_signature.nested); - break; - - case OPS_PTAG_CT_USER_ATTRIBUTE: - print_tagname("USER ATTRIBUTE"); - print_hexdump("User Attribute", - content->user_attribute.data.contents, - content->user_attribute.data.len); - break; - - case OPS_PTAG_RAW_SS: - assert(!content_->critical); - start_subpacket(content_->tag); - print_unsigned_int("Raw Signature Subpacket: tag", - content->ss_raw.tag-OPS_PTAG_SIGNATURE_SUBPACKET_BASE); - print_hexdump("Raw Data", - content->ss_raw.raw, - content->ss_raw.length); - break; - - case OPS_PTAG_SS_CREATION_TIME: - start_subpacket(content_->tag); - print_time("Signature Creation Time",content->ss_time.time); - end_subpacket(); - break; - - case OPS_PTAG_SS_EXPIRATION_TIME: - start_subpacket(content_->tag); - print_duration("Signature Expiration Time",content->ss_time.time); - end_subpacket(); - break; - - case OPS_PTAG_SS_KEY_EXPIRATION_TIME: - start_subpacket(content_->tag); - print_duration("Key Expiration Time", content->ss_time.time); - end_subpacket(); - break; - - case OPS_PTAG_SS_TRUST: - start_subpacket(content_->tag); - print_string("Trust Signature",""); - print_unsigned_int("Level", - content->ss_trust.level); - print_unsigned_int("Amount", - content->ss_trust.amount); - end_subpacket(); - break; - - case OPS_PTAG_SS_REVOCABLE: - start_subpacket(content_->tag); - print_boolean("Revocable",content->ss_revocable.revocable); - end_subpacket(); - break; - - case OPS_PTAG_SS_REVOCATION_KEY: - start_subpacket(content_->tag); - /* not yet tested */ - printf (" revocation key: class=0x%x", - content->ss_revocation_key.clss); - if (content->ss_revocation_key.clss&0x40) - printf (" (sensitive)"); - printf (", algid=0x%x", content->ss_revocation_key.algid); - printf(", fingerprint="); - hexdump(content->ss_revocation_key.fingerprint,20); - printf("\n"); - end_subpacket(); - break; - - case OPS_PTAG_SS_ISSUER_KEY_ID: - start_subpacket(content_->tag); - print_hexdump("Issuer Key Id", - &content->ss_issuer_key_id.key_id[0], - sizeof content->ss_issuer_key_id.key_id); - end_subpacket(); - break; - - case OPS_PTAG_SS_PREFERRED_SKA: - start_subpacket(content_->tag); - print_data( "Preferred Symmetric Algorithms", - &content->ss_preferred_ska.data); - - text = ops_showall_ss_preferred_ska(content->ss_preferred_ska); - print_text_breakdown(text); - ops_text_free(text); - - end_subpacket(); - break; - - case OPS_PTAG_SS_PRIMARY_USER_ID: - start_subpacket(content_->tag); - print_boolean("Primary User ID", - content->ss_primary_user_id.primary_user_id); - end_subpacket(); - break; - - case OPS_PTAG_SS_PREFERRED_HASH: - start_subpacket(content_->tag); - print_data("Preferred Hash Algorithms", - &content->ss_preferred_hash.data); - - text = ops_showall_ss_preferred_hash(content->ss_preferred_hash); - print_text_breakdown(text); - ops_text_free(text); - end_subpacket(); - break; - - case OPS_PTAG_SS_PREFERRED_COMPRESSION: - start_subpacket(content_->tag); - print_data( "Preferred Compression Algorithms", - &content->ss_preferred_compression.data); - - text = ops_showall_ss_preferred_compression(content->ss_preferred_compression); - print_text_breakdown(text); - ops_text_free(text); - end_subpacket(); - break; - - case OPS_PTAG_SS_KEY_FLAGS: - start_subpacket(content_->tag); - print_data( "Key Flags", &content->ss_key_flags.data); - - text = ops_showall_ss_key_flags(content->ss_key_flags); - print_text_breakdown( text); - ops_text_free(text); - - end_subpacket(); - break; - - case OPS_PTAG_SS_KEY_SERVER_PREFS: - start_subpacket(content_->tag); - print_data( "Key Server Preferences", - &content->ss_key_server_prefs.data); - - text = ops_showall_ss_key_server_prefs(content->ss_key_server_prefs); - print_text_breakdown( text); - ops_text_free(text); - - end_subpacket(); - break; - - case OPS_PTAG_SS_FEATURES: - start_subpacket(content_->tag); - print_data( "Features", - &content->ss_features.data); - - text = ops_showall_ss_features(content->ss_features); - print_text_breakdown( text); - ops_text_free(text); - - end_subpacket(); - break; - - case OPS_PTAG_SS_NOTATION_DATA: - start_subpacket(content_->tag); - print_indent(); - printf("Notation Data:\n"); - - indent++; - print_data( "Flags", - &content->ss_notation_data.flags); - text = ops_showall_ss_notation_data_flags(content->ss_notation_data); - print_text_breakdown( text); - ops_text_free(text); - - /* xxx - TODO: print out UTF - rachel */ - - print_data( "Name", - &content->ss_notation_data.name); - - print_data( "Value", - &content->ss_notation_data.value); - - indent--; - end_subpacket(); - break; - - case OPS_PTAG_SS_REGEXP: - start_subpacket(content_->tag); - print_hexdump("Regular Expression", - (unsigned char *)content->ss_regexp.text, - strlen(content->ss_regexp.text)); - print_string(NULL, - content->ss_regexp.text); - end_subpacket(); - break; - - case OPS_PTAG_SS_POLICY_URL: - start_subpacket(content_->tag); - print_string("Policy URL", - content->ss_policy_url.text); - end_subpacket(); - break; - - case OPS_PTAG_SS_SIGNERS_USER_ID: - start_subpacket(content_->tag); - print_utf8_string("Signer's User ID",content->ss_signers_user_id.user_id); - end_subpacket(); - break; - - case OPS_PTAG_SS_PREFERRED_KEY_SERVER: - start_subpacket(content_->tag); - print_string("Preferred Key Server", - content->ss_preferred_key_server.text); - end_subpacket(); - break; - - case OPS_PTAG_SS_USERDEFINED00: - case OPS_PTAG_SS_USERDEFINED01: - case OPS_PTAG_SS_USERDEFINED02: - case OPS_PTAG_SS_USERDEFINED03: - case OPS_PTAG_SS_USERDEFINED04: - case OPS_PTAG_SS_USERDEFINED05: - case OPS_PTAG_SS_USERDEFINED06: - case OPS_PTAG_SS_USERDEFINED07: - case OPS_PTAG_SS_USERDEFINED08: - case OPS_PTAG_SS_USERDEFINED09: - case OPS_PTAG_SS_USERDEFINED10: - start_subpacket(content_->tag); - print_hexdump("Internal or user-defined", - content->ss_userdefined.data.contents, - content->ss_userdefined.data.len); - end_subpacket(); - break; - - case OPS_PTAG_SS_RESERVED: - start_subpacket(content_->tag); - print_hexdump("Reserved", - content->ss_userdefined.data.contents, - content->ss_userdefined.data.len); - end_subpacket(); - break; - - case OPS_PTAG_SS_REVOCATION_REASON: - start_subpacket(content_->tag); - print_hexdump("Revocation Reason", - &content->ss_revocation_reason.code, - 1); - str=ops_show_ss_rr_code(content->ss_revocation_reason.code); - print_string(NULL,str); - /* xxx - todo : output text as UTF-8 string */ - end_subpacket(); - break; - - case OPS_PTAG_CT_LITERAL_DATA_HEADER: - print_tagname("LITERAL DATA HEADER"); - printf(" literal data header format=%c filename='%s'\n", - content->literal_data_header.format, - content->literal_data_header.filename); - print_time(" modification time", - content->literal_data_header.modification_time); - printf("\n"); - break; - - case OPS_PTAG_CT_LITERAL_DATA_BODY: - print_tagname("LITERAL DATA BODY"); - printf(" literal data body length=%d\n", - content->literal_data_body.length); - printf(" data="); - print_escaped(content->literal_data_body.data, - content->literal_data_body.length); - printf("\n"); - break; - - case OPS_PTAG_CT_SIGNATURE_HEADER: - print_tagname("SIGNATURE"); - print_indent(); - print_unsigned_int("Signature Version", - content->signature.info.version); - if(content->signature.info.creation_time_set) - print_time("Signature Creation Time", content->signature.info.creation_time); - - print_string_and_value("Signature Type", - ops_show_sig_type(content->signature.info.type), - content->signature.info.type); - - if(content->signature.info.signer_id_set) - print_hexdump_data("Signer ID", - content->signature.info.signer_id, - sizeof content->signature.info.signer_id); - - print_string_and_value("Public Key Algorithm", - ops_show_pka(content->signature.info.key_algorithm), - content->signature.info.key_algorithm); - print_string_and_value("Hash Algorithm", - ops_show_hash_algorithm(content->signature.info.hash_algorithm), - content->signature.info.hash_algorithm); - - break; - - case OPS_PTAG_CT_SIGNATURE_FOOTER: - print_indent(); - print_hexdump_data("hash2",&content->signature.hash2[0],2); - - switch(content->signature.info.key_algorithm) - { - case OPS_PKA_RSA: - print_bn("sig",content->signature.info.signature.rsa.sig); - break; - - case OPS_PKA_DSA: - print_bn("r",content->signature.info.signature.dsa.r); - print_bn("s",content->signature.info.signature.dsa.s); - break; - - case OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - print_bn("r",content->signature.info.signature.elgamal.r); - print_bn("s",content->signature.info.signature.elgamal.s); - break; - - case OPS_PKA_PRIVATE00: - case OPS_PKA_PRIVATE01: - case OPS_PKA_PRIVATE02: - case OPS_PKA_PRIVATE03: - case OPS_PKA_PRIVATE04: - case OPS_PKA_PRIVATE05: - case OPS_PKA_PRIVATE06: - case OPS_PKA_PRIVATE07: - case OPS_PKA_PRIVATE08: - case OPS_PKA_PRIVATE09: - case OPS_PKA_PRIVATE10: - print_data("Private/Experimental", - &content->signature.info.signature.unknown.data); - break; - - default: - assert(0); - } - break; - - case OPS_PARSER_CMD_GET_SK_PASSPHRASE: -#ifdef XXX - if(passphrase_prompt) - { - ops_print_secret_key(OPS_PTAG_CT_ENCRYPTED_SECRET_KEY, - content->secret_key_passphrase.secret_key); - *content->secret_key_passphrase.passphrase=ops_get_passphrase(); - if(!**content->secret_key_passphrase.passphrase) - break; - return OPS_KEEP_MEMORY; - } - else - printf(">>> ASKED FOR PASSPHRASE <<<\n"); -#else - if (cbinfo->cryptinfo.cb_get_passphrase) - return cbinfo->cryptinfo.cb_get_passphrase(content_,cbinfo); -#endif /*XXX*/ - break; - - case OPS_PTAG_CT_SECRET_KEY: - case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY: - ops_print_secret_key_verbose(content_->tag,&content->secret_key); - break; - - case OPS_PTAG_CT_ARMOUR_HEADER: - print_tagname("ARMOUR HEADER"); - print_string("type",content->armour_header.type); - break; - - case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER: - print_tagname("SIGNED CLEARTEXT HEADER"); - print_headers(&content->signed_cleartext_header.headers); - break; - - case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY: - print_tagname("SIGNED CLEARTEXT BODY"); - print_block("signed cleartext",content->signed_cleartext_body.data, - content->signed_cleartext_body.length); - break; - - case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER: - print_tagname("SIGNED CLEARTEXT TRAILER"); - printf("hash algorithm: %d\n", - content->signed_cleartext_trailer.hash->algorithm); - printf("\n"); - break; - - case OPS_PTAG_CT_UNARMOURED_TEXT: - if(!unarmoured) - { - print_tagname("UNARMOURED TEXT"); - unarmoured=ops_true; - } - putchar('['); - print_escaped(content->unarmoured_text.data, - content->unarmoured_text.length); - putchar(']'); - break; - - case OPS_PTAG_CT_ARMOUR_TRAILER: - print_tagname("ARMOUR TRAILER"); - print_string("type",content->armour_header.type); - break; - - case OPS_PTAG_CT_PK_SESSION_KEY: - case OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY: - ops_print_pk_session_key(content_->tag,&content->pk_session_key); - break; - - case OPS_PARSER_CMD_GET_SECRET_KEY: - ops_print_pk_session_key(OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY, - content->get_secret_key.pk_session_key); - -#ifdef XXX - decrypter=ops_keyring_find_key_by_id(&keyring, - content->get_secret_key.pk_session_key->key_id); - if(!decrypter || !ops_key_is_secret(decrypter)) - break; - - puts("[Decryption key found in keyring]"); - - secret=ops_get_secret_key_from_data(decrypter); - while(!secret) - { - /* then it must be encrypted */ - char *phrase=ops_get_passphrase(); - secret=ops_decrypt_secret_key_from_data(decrypter,phrase); - free(phrase); - } - - *content->get_secret_key.secret_key=secret; -#else - return callback_cmd_get_secret_key(content_,cbinfo); -#endif /*XXX*/ - break; - - default: - print_tagname("UNKNOWN PACKET TYPE"); - fprintf(stderr,"packet-dump: unknown tag=%d (0x%x)\n",content_->tag, - content_->tag); - exit(1); - } -#endif /*XXX*/ - return OPS_RELEASE_MEMORY; - } - -/** -\ingroup Core_Print -\param filename -\param armour -\param keyring -\param cb_get_passphrase -*/ -void ops_list_packets(char* filename, ops_boolean_t armour, ops_keyring_t* keyring, ops_parse_cb_t* cb_get_passphrase) - { - int fd=0; - ops_parse_info_t *pinfo=NULL; - const ops_boolean_t accumulate=ops_true; - - fd=ops_setup_file_read(&pinfo, filename, NULL, cb_list_packets, accumulate); - ops_parse_options(pinfo,OPS_PTAG_SS_ALL,OPS_PARSE_PARSED); - pinfo->cryptinfo.keyring=keyring; - pinfo->cryptinfo.cb_get_passphrase=cb_get_passphrase; - - if(armour) - ops_reader_push_dearmour(pinfo); - - ops_parse_and_print_errors(pinfo); - - ops_teardown_file_read(pinfo,fd); - } diff --git a/openpgpsdk/src/openpgpsdk/packet-show-cast.h b/openpgpsdk/src/openpgpsdk/packet-show-cast.h deleted file mode 100644 index b5c8b0ab4..000000000 --- a/openpgpsdk/src/openpgpsdk/packet-show-cast.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Generated from packet-show.cast by ../../util/caster.pl, do not edit. */ - -#include "types.h" - -/* (line 4) char *show_packet_tag(ops_packet_tag_t packet_tag, packet_tag_map_t *packet_tag_map) -> char *ops_str_from_map(int packet_tag, ops_map_t *packet_tag_map) */ -char *ops_str_from_map(int packet_tag, ops_map_t *packet_tag_map); -#define show_packet_tag(packet_tag,packet_tag_map) ops_str_from_map(CHECKED_INSTANCE_OF(ops_packet_tag_t , packet_tag),CHECKED_INSTANCE_OF( packet_tag_map_t *, packet_tag_map)) -typedef char * show_packet_tag_t(ops_packet_tag_t , packet_tag_map_t *); - -/* (line 5) char *show_sig_type(ops_sig_type_t sig_type, sig_type_map_t *sig_type_map) -> char *ops_str_from_map(int sig_type, ops_map_t *sig_type_map) */ -char *ops_str_from_map(int sig_type, ops_map_t *sig_type_map); -#define show_sig_type(sig_type,sig_type_map) ops_str_from_map(CHECKED_INSTANCE_OF(ops_sig_type_t , sig_type),CHECKED_INSTANCE_OF( sig_type_map_t *, sig_type_map)) -typedef char * show_sig_type_t(ops_sig_type_t , sig_type_map_t *); - -/* (line 6) char *show_pka(ops_public_key_algorithm_t pka, public_key_algorithm_map_t *pka_map) -> char *ops_str_from_map(int pka, ops_map_t *pka_map) */ -char *ops_str_from_map(int pka, ops_map_t *pka_map); -#define show_pka(pka,pka_map) ops_str_from_map(CHECKED_INSTANCE_OF(ops_public_key_algorithm_t , pka),CHECKED_INSTANCE_OF( public_key_algorithm_map_t *, pka_map)) -typedef char * show_pka_t(ops_public_key_algorithm_t , public_key_algorithm_map_t *); - -/* (line 7) char *show_ss_type(ops_ss_type_t ss_type, ss_type_map_t *ss_type_map) -> char *ops_str_from_map(int ss_type, ops_map_t *ss_type_map) */ -char *ops_str_from_map(int ss_type, ops_map_t *ss_type_map); -#define show_ss_type(ss_type,ss_type_map) ops_str_from_map(CHECKED_INSTANCE_OF(ops_ss_type_t , ss_type),CHECKED_INSTANCE_OF( ss_type_map_t *, ss_type_map)) -typedef char * show_ss_type_t(ops_ss_type_t , ss_type_map_t *); - -/* (line 8) char *show_ss_rr_code(ops_ss_rr_code_t ss_rr_code, ss_rr_code_map_t *ss_rr_code_map) -> char *ops_str_from_map(int ss_rr_code, ops_map_t *ss_rr_code_map) */ -char *ops_str_from_map(int ss_rr_code, ops_map_t *ss_rr_code_map); -#define show_ss_rr_code(ss_rr_code,ss_rr_code_map) ops_str_from_map(CHECKED_INSTANCE_OF(ops_ss_rr_code_t , ss_rr_code),CHECKED_INSTANCE_OF( ss_rr_code_map_t *, ss_rr_code_map)) -typedef char * show_ss_rr_code_t(ops_ss_rr_code_t , ss_rr_code_map_t *); - -/* (line 9) char *show_hash_algorithm(unsigned char hash,+ops_map_t *hash_algorithm_map) -> char *ops_str_from_map(int hash,ops_map_t *hash_algorithm_map) */ -char *ops_str_from_map(int hash,ops_map_t *hash_algorithm_map); -#define show_hash_algorithm(hash) ops_str_from_map(CHECKED_INSTANCE_OF(unsigned char , hash),CHECKED_INSTANCE_OF(ops_map_t *, hash_algorithm_map)) -typedef char * show_hash_algorithm_t(unsigned char ); - -/* (line 10) char *show_symmetric_algorithm(unsigned char hash,+ops_map_t *symmetric_algorithm_map) -> char *ops_str_from_map(int hash,ops_map_t *symmetric_algorithm_map) */ -char *ops_str_from_map(int hash,ops_map_t *symmetric_algorithm_map); -#define show_symmetric_algorithm(hash) ops_str_from_map(CHECKED_INSTANCE_OF(unsigned char , hash),CHECKED_INSTANCE_OF(ops_map_t *, symmetric_algorithm_map)) -typedef char * show_symmetric_algorithm_t(unsigned char ); diff --git a/openpgpsdk/src/openpgpsdk/packet-show.c b/openpgpsdk/src/openpgpsdk/packet-show.c deleted file mode 100644 index 8be6c7563..000000000 --- a/openpgpsdk/src/openpgpsdk/packet-show.c +++ /dev/null @@ -1,857 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - * - * Creates printable text strings from packet contents - * - */ - -#include - -#include -#include - -#include -#include - -#include - -/* - * Arrays of value->text maps - */ - -static ops_map_t packet_tag_map[] = - { - { OPS_PTAG_CT_RESERVED, "Reserved" }, - { OPS_PTAG_CT_PK_SESSION_KEY, "Public-Key Encrypted Session Key" }, - { OPS_PTAG_CT_SIGNATURE, "Signature" }, - { OPS_PTAG_CT_SK_SESSION_KEY, "Symmetric-Key Encrypted Session Key" }, - { OPS_PTAG_CT_ONE_PASS_SIGNATURE, "One-Pass Signature" }, - { OPS_PTAG_CT_SECRET_KEY, "Secret Key" }, - { OPS_PTAG_CT_PUBLIC_KEY, "Public Key" }, - { OPS_PTAG_CT_SECRET_SUBKEY, "Secret Subkey" }, - { OPS_PTAG_CT_COMPRESSED, "Compressed Data" }, - { OPS_PTAG_CT_SE_DATA, "Symmetrically Encrypted Data" }, - { OPS_PTAG_CT_MARKER, "Marker" }, - { OPS_PTAG_CT_LITERAL_DATA, "Literal Data" }, - { OPS_PTAG_CT_TRUST, "Trust" }, - { OPS_PTAG_CT_USER_ID, "User ID" }, - { OPS_PTAG_CT_PUBLIC_SUBKEY, "Public Subkey" }, - { OPS_PTAG_CT_RESERVED2, "reserved" }, - { OPS_PTAG_CT_RESERVED3, "reserved" }, - { OPS_PTAG_CT_USER_ATTRIBUTE, "User Attribute" }, - { OPS_PTAG_CT_SE_IP_DATA, "Sym. Encrypted and Integrity Protected Data" }, - { OPS_PTAG_CT_MDC, "Modification Detection Code" }, - { OPS_PARSER_PTAG, "OPS_PARSER_PTAG" }, - { OPS_PTAG_RAW_SS, "OPS_PTAG_RAW_SS" }, - { OPS_PTAG_SS_ALL, "OPS_PTAG_SS_ALL" }, - { OPS_PARSER_PACKET_END, "OPS_PARSER_PACKET_END" }, - { OPS_PTAG_SIGNATURE_SUBPACKET_BASE, "OPS_PTAG_SIGNATURE_SUBPACKET_BASE" }, - - { OPS_PTAG_SS_CREATION_TIME, "SS: Signature Creation Time" }, - { OPS_PTAG_SS_EXPIRATION_TIME, "SS: Signature Expiration Time" }, - { OPS_PTAG_SS_EXPORTABLE_CERTIFICATION, "SS: Exportable Certification" }, - { OPS_PTAG_SS_TRUST, "SS: Trust Signature" }, - { OPS_PTAG_SS_REGEXP, "SS: Regular Expression" }, - { OPS_PTAG_SS_REVOCABLE, "SS: Revocable" }, - { OPS_PTAG_SS_KEY_EXPIRATION_TIME, "SS: Key Expiration Time" }, - { OPS_PTAG_SS_RESERVED, "SS: Reserved" }, - { OPS_PTAG_SS_PREFERRED_SKA, "SS: Preferred Secret Key Algorithm" }, - { OPS_PTAG_SS_REVOCATION_KEY, "SS: Revocation Key" }, - { OPS_PTAG_SS_ISSUER_KEY_ID, "SS: Issuer Key Id" }, - { OPS_PTAG_SS_NOTATION_DATA, "SS: Notation Data" }, - { OPS_PTAG_SS_PREFERRED_HASH, "SS: Preferred Hash Algorithm" }, - { OPS_PTAG_SS_PREFERRED_COMPRESSION,"SS: Preferred Compression Algorithm" }, - { OPS_PTAG_SS_KEY_SERVER_PREFS, "SS: Key Server Preferences" }, - { OPS_PTAG_SS_PREFERRED_COMPRESSION,"SS: Preferred Key Server" }, - { OPS_PTAG_SS_PRIMARY_USER_ID, "SS: Primary User ID" }, - { OPS_PTAG_SS_POLICY_URI, "SS: Policy URI" }, - { OPS_PTAG_SS_KEY_FLAGS, "SS: Key Flags" }, - { OPS_PTAG_SS_SIGNERS_USER_ID, "SS: Signer's User ID" }, - { OPS_PTAG_SS_REVOCATION_REASON, "SS: Reason for Revocation" }, - { OPS_PTAG_SS_FEATURES, "SS: Features" }, - { OPS_PTAG_SS_SIGNATURE_TARGET, "SS: Signature Target" }, - { OPS_PTAG_SS_EMBEDDED_SIGNATURE, "SS: Embedded Signature" }, - - { OPS_PTAG_CT_LITERAL_DATA_HEADER, "CT: Literal Data Header" }, - { OPS_PTAG_CT_LITERAL_DATA_BODY, "CT: Literal Data Body" }, - { OPS_PTAG_CT_SIGNATURE_HEADER, "CT: Signature Header" }, - { OPS_PTAG_CT_SIGNATURE_FOOTER, "CT: Signature Footer" }, - { OPS_PTAG_CT_ARMOUR_HEADER, "CT: Armour Header" }, - { OPS_PTAG_CT_ARMOUR_TRAILER, "CT: Armour Trailer" }, - { OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER, "CT: Signed Cleartext Header" }, - { OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY, "CT: Signed Cleartext Body" }, - { OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER, "CT: Signed Cleartext Trailer" }, - { OPS_PTAG_CT_UNARMOURED_TEXT, "CT: Unarmoured Text" }, - { OPS_PTAG_CT_ENCRYPTED_SECRET_KEY, "CT: Encrypted Secret Key" }, - { OPS_PTAG_CT_SE_DATA_HEADER, "CT: Sym Encrypted Data Header" }, - { OPS_PTAG_CT_SE_DATA_BODY, "CT: Sym Encrypted Data Body" }, - { OPS_PTAG_CT_SE_IP_DATA_HEADER, "CT: Sym Encrypted IP Data Header" }, - { OPS_PTAG_CT_SE_IP_DATA_BODY, "CT: Sym Encrypted IP Data Body" }, - { OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY, "CT: Encrypted PK Session Key" }, - { OPS_PARSER_CMD_GET_SK_PASSPHRASE, "CMD: Get Secret Key Passphrase" }, - { OPS_PARSER_CMD_GET_SECRET_KEY, "CMD: Get Secret Key" }, - { OPS_PARSER_ERROR, "OPS_PARSER_ERROR" }, - { OPS_PARSER_ERRCODE, "OPS_PARSER_ERRCODE" }, - - { 0x00, NULL }, /* this is the end-of-array marker */ - }; -typedef ops_map_t packet_tag_map_t; - -static ops_map_t ss_type_map[] = - { - { OPS_PTAG_SS_CREATION_TIME, "Signature Creation Time" }, - { OPS_PTAG_SS_EXPIRATION_TIME, "Signature Expiration Time" }, - { OPS_PTAG_SS_TRUST, "Trust Signature" }, - { OPS_PTAG_SS_REGEXP, "Regular Expression" }, - { OPS_PTAG_SS_REVOCABLE, "Revocable" }, - { OPS_PTAG_SS_KEY_EXPIRATION_TIME, "Key Expiration Time" }, - { OPS_PTAG_SS_PREFERRED_SKA, "Preferred Symmetric Algorithms" }, - { OPS_PTAG_SS_REVOCATION_KEY, "Revocation Key" }, - { OPS_PTAG_SS_ISSUER_KEY_ID, "Issuer key ID" }, - { OPS_PTAG_SS_NOTATION_DATA, "Notation Data" }, - { OPS_PTAG_SS_PREFERRED_HASH, "Preferred Hash Algorithms" }, - { OPS_PTAG_SS_PREFERRED_COMPRESSION,"Preferred Compression Algorithms" }, - { OPS_PTAG_SS_KEY_SERVER_PREFS, "Key Server Preferences" }, - { OPS_PTAG_SS_PREFERRED_KEY_SERVER, "Preferred Key Server" }, - { OPS_PTAG_SS_PRIMARY_USER_ID, "Primary User ID" }, - { OPS_PTAG_SS_POLICY_URI, "Policy URI" }, - { OPS_PTAG_SS_KEY_FLAGS, "Key Flags" }, - { OPS_PTAG_SS_REVOCATION_REASON, "Reason for Revocation" }, - { OPS_PTAG_SS_FEATURES, "Features" }, - { 0x00, NULL }, /* this is the end-of-array marker */ - }; -typedef ops_map_t ss_type_map_t; - - -static ops_map_t ss_rr_code_map[] = - { - { 0x00, "No reason specified" }, - { 0x01, "Key is superseded" }, - { 0x02, "Key material has been compromised" }, - { 0x03, "Key is retired and no longer used" }, - { 0x20, "User ID information is no longer valid" }, - { 0x00, NULL }, /* this is the end-of-array marker */ - }; -typedef ops_map_t ss_rr_code_map_t; - -static ops_map_t sig_type_map[] = - { - { OPS_SIG_BINARY, "Signature of a binary document" }, - { OPS_SIG_TEXT, "Signature of a canonical text document" }, - { OPS_SIG_STANDALONE, "Standalone signature" }, - { OPS_CERT_GENERIC, "Generic certification of a User ID and Public Key packet" }, - { OPS_CERT_PERSONA, "Persona certification of a User ID and Public Key packet" }, - { OPS_CERT_CASUAL, "Casual certification of a User ID and Public Key packet" }, - { OPS_CERT_POSITIVE, "Positive certification of a User ID and Public Key packet" }, - { OPS_SIG_SUBKEY, "Subkey Binding Signature" }, - { OPS_SIG_PRIMARY, "Primary Key Binding Signature" }, - { OPS_SIG_DIRECT, "Signature directly on a key" }, - { OPS_SIG_REV_KEY, "Key revocation signature" }, - { OPS_SIG_REV_SUBKEY, "Subkey revocation signature" }, - { OPS_SIG_REV_CERT, "Certification revocation signature" }, - { OPS_SIG_TIMESTAMP, "Timestamp signature" }, - { OPS_SIG_3RD_PARTY, "Third-Party Confirmation signature" }, - { 0x00, NULL }, /* this is the end-of-array marker */ - }; -typedef ops_map_t sig_type_map_t; - -static ops_map_t public_key_algorithm_map[] = - { - { OPS_PKA_RSA, "RSA (Encrypt or Sign)" }, - { OPS_PKA_RSA_ENCRYPT_ONLY, "RSA Encrypt-Only" }, - { OPS_PKA_RSA_SIGN_ONLY, "RSA Sign-Only" }, - { OPS_PKA_ELGAMAL, "Elgamal (Encrypt-Only)" }, - { OPS_PKA_DSA, "DSA" }, - { OPS_PKA_RESERVED_ELLIPTIC_CURVE, "Reserved for Elliptic Curve" }, - { OPS_PKA_RESERVED_ECDSA, "Reserved for ECDSA" }, - { OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN, "Reserved (formerly Elgamal Encrypt or Sign" }, - { OPS_PKA_RESERVED_DH, "Reserved for Diffie-Hellman (X9.42)" }, - { OPS_PKA_PRIVATE00, "Private/Experimental" }, - { OPS_PKA_PRIVATE01, "Private/Experimental" }, - { OPS_PKA_PRIVATE02, "Private/Experimental" }, - { OPS_PKA_PRIVATE03, "Private/Experimental" }, - { OPS_PKA_PRIVATE04, "Private/Experimental" }, - { OPS_PKA_PRIVATE05, "Private/Experimental" }, - { OPS_PKA_PRIVATE06, "Private/Experimental" }, - { OPS_PKA_PRIVATE07, "Private/Experimental" }, - { OPS_PKA_PRIVATE08, "Private/Experimental" }, - { OPS_PKA_PRIVATE09, "Private/Experimental" }, - { OPS_PKA_PRIVATE10, "Private/Experimental" }, - { 0x00, NULL }, /* this is the end-of-array marker */ - }; -typedef ops_map_t public_key_algorithm_map_t; - -static ops_map_t symmetric_algorithm_map[] = - { - { OPS_SA_PLAINTEXT, "Plaintext or unencrypted data" }, - { OPS_SA_IDEA, "IDEA" }, - { OPS_SA_TRIPLEDES, "TripleDES" }, - { OPS_SA_CAST5, "CAST5" }, - { OPS_SA_BLOWFISH, "Blowfish" }, - { OPS_SA_AES_128, "AES (128-bit key)" }, - { OPS_SA_AES_192, "AES (192-bit key)" }, - { OPS_SA_AES_256, "AES (256-bit key)" }, - { OPS_SA_TWOFISH, "Twofish(256-bit key)" }, - { OPS_SA_CAMELLIA_128, "Camellia (128-bit key)" }, - { OPS_SA_CAMELLIA_192, "Camellia (192-bit key)" }, - { OPS_SA_CAMELLIA_256, "Camellia (256-bit key)" }, - { 0x00, NULL }, /* this is the end-of-array marker */ - }; - -static ops_map_t hash_algorithm_map[] = - { - { OPS_HASH_MD5, "MD5" }, - { OPS_HASH_SHA1, "SHA1" }, - { OPS_HASH_RIPEMD, "RIPEMD160" }, - { OPS_HASH_SHA256, "SHA256" }, - { OPS_HASH_SHA384, "SHA384" }, - { OPS_HASH_SHA512, "SHA512" }, - { OPS_HASH_SHA224, "SHA224" }, - { 0x00, NULL }, /* this is the end-of-array marker */ - }; - -static ops_map_t compression_algorithm_map[] = - { - { OPS_C_NONE, "Uncompressed" }, - { OPS_C_ZIP, "ZIP(RFC1951)" }, - { OPS_C_ZLIB, "ZLIB(RFC1950)" }, - { OPS_C_BZIP2, "Bzip2(BZ2)" }, - { 0x00, NULL }, /* this is the end-of-array marker */ - }; - -static ops_bit_map_t ss_notation_data_map_byte0[] = - { - { 0x80, "Human-readable" }, - { 0x00, NULL }, - }; - -static ops_bit_map_t *ss_notation_data_map[] = - { - ss_notation_data_map_byte0, - }; - -static ops_bit_map_t ss_feature_map_byte0[] = - { - { 0x01, "Modification Detection" }, - { 0x00, NULL }, - }; - -static ops_bit_map_t *ss_feature_map[] = - { - ss_feature_map_byte0, - }; - -static ops_bit_map_t ss_key_flags_map[] = - { - { 0x01, "May be used to certify other keys" }, - { 0x02, "May be used to sign data" }, - { 0x04, "May be used to encrypt communications" }, - { 0x08, "May be used to encrypt storage" }, - { 0x10, "Private component may have been split by a secret-sharing mechanism"}, - { 0x80, "Private component may be in possession of more than one person"}, - { 0x00, NULL }, - }; - -static ops_bit_map_t ss_key_server_prefs_map[] = - { - { 0x80, "Key holder requests that this key only be modified or updated by the key holder or an administrator of the key server" }, - { 0x00, NULL }, - }; - -#include - -/* - * Private functions - */ - -static void list_init(ops_list_t *list) - { - list->size=0; - list->used=0; - list->strings=NULL; - } - -static void list_free_strings(ops_list_t *list) - { - unsigned i; - - for(i=0; i < list->used ; i++) - { - free(list->strings[i]); - list->strings[i]=NULL; - } - } - -static void list_free(ops_list_t *list) - { - if (list->strings) - free(list->strings); - list_init(list); - } - -static unsigned int list_resize(ops_list_t *list) - { - /* We only resize in one direction - upwards. - Algorithm used : double the current size then add 1 - */ - - int newsize=0; - - newsize=list->size*2 + 1; - list->strings=realloc(list->strings,newsize*sizeof(char *)); - if (list->strings) - { - list->size=newsize; - return 1; - } - else - { - /* xxx - realloc failed. error message? - rachel */ - return 0; - } - } - -static unsigned int add_str(ops_list_t *list,char *str) - { - if (list->size==list->used) - if (!list_resize(list)) - return 0; - - list->strings[list->used]=str; - list->used++; - return 1; - } - -static char *str_from_bitfield_or_null(unsigned char octet, ops_bit_map_t *map) - { - ops_bit_map_t *row; - - for ( row=map; row->string != NULL; row++ ) - if (row->mask == octet) - return row->string; - - return NULL; - } - -static char *str_from_bitfield(unsigned char octet, ops_bit_map_t *map) - { - char *str; - str=str_from_bitfield_or_null(octet,map); - if (str) - return str; - else - return "Unknown"; - } - -/*! generic function to initialise ops_text_t structure */ -void ops_text_init(ops_text_t *text) - { - list_init(&text->known); - list_init(&text->unknown); - } - -/** - * \ingroup Core_Print - * - * ops_text_free() frees the memory used by an ops_text_t structure - * - * \param text Pointer to a previously allocated structure. This structure and its contents will be freed. - */ -void ops_text_free(ops_text_t *text) - { - /* Strings in "known" array will be constants, so don't free them */ - list_free(&text->known); - - /* Strings in "unknown" array will be dynamically allocated, so do free them */ - list_free_strings(&text->unknown); - list_free(&text->unknown); - - /* finally, free the text structure itself */ - free(text); - } - -// XXX: should this (and many others) be ops_boolean_t? -/*! generic function which adds text derived from single octet map to text */ -static unsigned int add_str_from_octet_map(ops_text_t *text,char *str, - unsigned char octet) - { - if (str && !add_str(&text->known,str)) - { - /* value recognised, but there was a problem adding it to the list */ - /* XXX - should print out error msg here, Ben? - rachel */ - return 0; - } - else if (!str) - { - /* value not recognised and there was a problem adding it to the unknown list */ - unsigned len=2+2+1; /* 2 for "0x", 2 for single octet in hex format, 1 for NULL */ - str=malloc(len); - snprintf(str,len,"0x%x",octet); - if (!add_str(&text->unknown,str)) - return 0; - } - return 1; - } - -/*! generic function which adds text derived from single bit map to text */ -static unsigned int add_str_from_bit_map(ops_text_t *text, char *str, unsigned char bit) - { - char *fmt_unknown="Unknown bit(0x%x)"; - - if (str && !add_str(&text->known,str)) - { - /* value recognised, but there was a problem adding it to the list */ - /* XXX - should print out error msg here, Ben? - rachel */ - return 0; - } - else if (!str) - { - /* value not recognised and there was a problem adding it to the unknown list */ - /* 2 chars of the string are the format definition, - this will be replaced in the output by 2 chars of hex, - so the length will be correct */ - unsigned len=strlen(fmt_unknown)+1; - str=malloc(len); - - snprintf(str,len,fmt_unknown,bit); - if (!add_str(&text->unknown,str)) - return 0; - } - return 1; - } - -/** - * Produce a structure containing human-readable textstrings - * representing the recognised and unrecognised contents - * of this byte array. text_fn() will be called on each octet in turn. - * Each octet will generate one string representing the whole byte. - * - */ - -static ops_text_t *text_from_bytemapped_octets(ops_data_t *data, - const char *(*text_fn)(unsigned char octet)) - { - - ops_text_t *text=NULL; - const char *str; - unsigned i; - - /*! allocate and initialise ops_text_t structure to store derived strings */ - text=malloc(sizeof(ops_text_t)); - if (!text) - return NULL; - - ops_text_init(text); - - /*! for each octet in field ... */ - for(i=0 ; i < data->len ; i++) - { - /*! derive string from octet */ - str=(*text_fn)(data->contents[i]); - - /*! and add to text */ - if (!add_str_from_octet_map(text,strdup(str),data->contents[i])) - { - ops_text_free(text); - return NULL; - } - - } - /*! All values have been added to either the known or the unknown list */ - /*! Return text */ - return text; - } - -/** - * Produce a structure containing human-readable textstrings - * representing the recognised and unrecognised contents - * of this byte array, derived from each bit of each octet. - * - */ -static ops_text_t *showall_octets_bits(ops_data_t *data,ops_bit_map_t **map, - size_t nmap) - { - ops_text_t *text=NULL; - char *str; - unsigned i; - int j=0; - unsigned char mask, bit; - - /*! allocate and initialise ops_text_t structure to store derived strings */ - text=malloc(sizeof(ops_text_t)); - if (!text) - return NULL; - - ops_text_init(text); - - /*! for each octet in field ... */ - for(i=0 ; i < data->len ; i++) - { - /*! for each bit in octet ... */ - for (j=0, mask=0x80; j<8; j++, mask = mask>>1 ) - { - bit = data->contents[i]&mask; - if (bit) - { - if(i >= nmap) - str="Unknown"; - else - str=str_from_bitfield ( bit, map[i] ); - if (!add_str_from_bit_map( text, str, bit)) - { - ops_text_free(text); - return NULL; - } - } - } - } - return text; - } - -/* - * Public Functions - */ - -/** - * \ingroup Core_Print - * returns description of the Packet Tag - * \param packet_tag - * \return string or "Unknown" -*/ -const char *ops_show_packet_tag(ops_packet_tag_t packet_tag) - { - char *rtn=NULL; - rtn=show_packet_tag(packet_tag,packet_tag_map); - - if (!rtn) - rtn="Unknown Tag"; - - return rtn; - } - -/** - * \ingroup Core_Print - * - * returns description of the Signature Sub-Packet type - * \param ss_type Signature Sub-Packet type - * \return string or "Unknown" - */ -const char *ops_show_ss_type(ops_ss_type_t ss_type) - { - return show_ss_type(ss_type,ss_type_map); - } - -/** - * \ingroup Core_Print - * - * returns description of the Revocation Reason code - * \param ss_rr_code Revocation Reason code - * \return string or "Unknown" - */ -const char *ops_show_ss_rr_code(ops_ss_rr_code_t ss_rr_code) - { - return show_ss_rr_code(ss_rr_code,ss_rr_code_map); - } - -/** - * \ingroup Core_Print - * - * returns description of the given Signature type - * \param sig_type Signature type - * \return string or "Unknown" - */ -const char *ops_show_sig_type(ops_sig_type_t sig_type) - { - return show_sig_type(sig_type, sig_type_map); - } - -/** - * \ingroup Core_Print - * - * returns description of the given Public Key Algorithm - * \param pka Public Key Algorithm type - * \return string or "Unknown" - */ -const char *ops_show_pka(ops_public_key_algorithm_t pka) - { - return show_pka(pka, public_key_algorithm_map); - } - -/** - * \ingroup Core_Print - * returns description of the Preferred Compression - * \param octet Preferred Compression - * \return string or "Unknown" -*/ -const char *ops_show_ss_preferred_compression(unsigned char octet) - { - return ops_str_from_map(octet,compression_algorithm_map); - } - -/** - * \ingroup Core_Print - * - * returns set of descriptions of the given Preferred Compression Algorithms - * \param ss_preferred_compression Array of Preferred Compression Algorithms - * \return NULL if cannot allocate memory or other error - * \return pointer to structure, if no error - */ -ops_text_t *ops_showall_ss_preferred_compression(ops_ss_preferred_compression_t ss_preferred_compression) - { - return text_from_bytemapped_octets(&ss_preferred_compression.data, - &ops_show_ss_preferred_compression); - } - - -/** - * \ingroup Core_Print - * - * returns description of the Hash Algorithm type - * \param hash Hash Algorithm type - * \return string or "Unknown" - */ -const char *ops_show_hash_algorithm(unsigned char hash) - { - return show_hash_algorithm(hash); - } - -/** - * \ingroup Core_Print - * - * returns set of descriptions of the given Preferred Hash Algorithms - * \param ss_preferred_hash Array of Preferred Hash Algorithms - * \return NULL if cannot allocate memory or other error - * \return pointer to structure, if no error - */ -ops_text_t *ops_showall_ss_preferred_hash(ops_ss_preferred_hash_t ss_preferred_hash) - { - return text_from_bytemapped_octets(&ss_preferred_hash.data, - &ops_show_hash_algorithm); - } - -const char *ops_show_symmetric_algorithm(unsigned char hash) - { - return show_symmetric_algorithm(hash); - } - -/** - * \ingroup Core_Print - * returns description of the given Preferred Symmetric Key Algorithm - * \param octet - * \return string or "Unknown" -*/ -const char *ops_show_ss_preferred_ska(unsigned char octet) - { - return ops_str_from_map(octet,symmetric_algorithm_map); - } - -/** - * \ingroup Core_Print - * - * returns set of descriptions of the given Preferred Symmetric Key Algorithms - * \param ss_preferred_ska Array of Preferred Symmetric Key Algorithms - * \return NULL if cannot allocate memory or other error - * \return pointer to structure, if no error - */ -ops_text_t *ops_showall_ss_preferred_ska(ops_ss_preferred_ska_t ss_preferred_ska) - { - return text_from_bytemapped_octets(&ss_preferred_ska.data, - &ops_show_ss_preferred_ska); - } - -/** - * \ingroup Core_Print - * returns description of one SS Feature - * \param octet - * \return string or "Unknown" -*/ -static char *ops_show_ss_feature(unsigned char octet,unsigned offset) - { - if(offset >= OPS_ARRAY_SIZE(ss_feature_map)) - return "Unknown"; - return str_from_bitfield(octet,ss_feature_map[offset]); - } - -/** - * \ingroup Core_Print - * - * returns set of descriptions of the given SS Features - * \param ss_features Signature Sub-Packet Features - * \return NULL if cannot allocate memory or other error - * \return pointer to structure, if no error - */ -/* XXX: shouldn't this use show_all_octets_bits? */ -ops_text_t *ops_showall_ss_features(ops_ss_features_t ss_features) - { - ops_text_t *text=NULL; - char *str; - unsigned i; - int j=0; - unsigned char mask, bit; - - text=malloc(sizeof(ops_text_t)); - if (!text) - return NULL; - - ops_text_init(text); - - for(i=0 ; i < ss_features.data.len ; i++) - { - for (j=0, mask=0x80; j<8; j++, mask = mask>>1 ) - { - bit = ss_features.data.contents[i]&mask; - if (bit) - { - str=ops_show_ss_feature ( bit, i ); - if (!add_str_from_bit_map( text, str, bit)) - { - ops_text_free(text); - return NULL; - } - } - } - } - return text; - } - -/** - * \ingroup Core_Print - * returns description of SS Key Flag - * \param octet - * \param map - * \return -*/ -const char *ops_show_ss_key_flag(unsigned char octet, ops_bit_map_t *map) - { - return str_from_bitfield(octet,map); - } - -/** - * \ingroup Core_Print - * - * returns set of descriptions of the given Preferred Key Flags - * \param ss_key_flags Array of Key Flags - * \return NULL if cannot allocate memory or other error - * \return pointer to structure, if no error - */ -ops_text_t *ops_showall_ss_key_flags(ops_ss_key_flags_t ss_key_flags) - { - ops_text_t *text=NULL; - const char *str; - int i=0; - unsigned char mask, bit; - - text=malloc(sizeof(ops_text_t)); - if (!text) - return NULL; - - ops_text_init(text); - - /* xxx - TBD: extend to handle multiple octets of bits - rachel */ - - for (i=0,mask=0x80 ; i < 8 ; i++,mask=mask >> 1) - { - bit=ss_key_flags.data.contents[0]&mask; - if(bit) - { - str=ops_show_ss_key_flag(bit,&ss_key_flags_map[0]); - if(!add_str_from_bit_map(text,strdup(str),bit)) - { - ops_text_free(text); - return NULL; - } - } - } -/* xxx - must add error text if more than one octet. Only one currently specified -- rachel */ - return text; - } - -/** - * \ingroup Core_Print - * - * returns description of one given Key Server Preference - * - * \param prefs Byte containing bitfield of preferences - * \param map - * \return string or "Unknown" - */ -const char *ops_show_ss_key_server_prefs(unsigned char prefs, - ops_bit_map_t *map) - { - return str_from_bitfield(prefs,map); - } - -/** - * \ingroup Core_Print - * returns set of descriptions of given Key Server Preferences - * \param ss_key_server_prefs - * \return NULL if cannot allocate memory or other error - * \return pointer to structure, if no error - * -*/ -ops_text_t *ops_showall_ss_key_server_prefs(ops_ss_key_server_prefs_t ss_key_server_prefs) - { - ops_text_t *text=NULL; - const char *str; - int i=0; - unsigned char mask, bit; - - text=malloc(sizeof(ops_text_t)); - if (!text) - return NULL; - - ops_text_init(text); - - /* xxx - TBD: extend to handle multiple octets of bits - rachel */ - - for (i=0,mask=0x80 ; i < 8 ; i++,mask=mask >> 1) - { - bit=ss_key_server_prefs.data.contents[0]&mask; - if (bit) - { - str=ops_show_ss_key_server_prefs(bit, - &ss_key_server_prefs_map[0]); - if(!add_str_from_bit_map( text, strdup(str), bit)) - { - ops_text_free(text); - return NULL; - } - } - } -/* xxx - must add error text if more than one octet. Only one currently specified -- rachel */ - return text; - } - -/** - * \ingroup Core_Print - * - * returns set of descriptions of the given SS Notation Data Flags - * \param ss_notation_data Signature Sub-Packet Notation Data - * \return NULL if cannot allocate memory or other error - * \return pointer to structure, if no error - */ -ops_text_t *ops_showall_ss_notation_data_flags(ops_ss_notation_data_t ss_notation_data) - { - return showall_octets_bits(&ss_notation_data.flags,ss_notation_data_map, - OPS_ARRAY_SIZE(ss_notation_data_map)); - } diff --git a/openpgpsdk/src/openpgpsdk/packet-show.h b/openpgpsdk/src/openpgpsdk/packet-show.h deleted file mode 100644 index f8dc4050f..000000000 --- a/openpgpsdk/src/openpgpsdk/packet-show.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_PACKET_TO_TEXT_H -#define OPS_PACKET_TO_TEXT_H - -#ifndef OPS_PACKET_H -#include "packet.h" -#endif - -/** ops_list_t - */ -typedef struct - { - unsigned int size;/* num of array slots allocated */ - unsigned int used; /* num of array slots currently used */ - char **strings; - } ops_list_t; - -/** ops_text_t - */ -typedef struct - { - ops_list_t known; - ops_list_t unknown; - } ops_text_t; - -/** ops_bit_map_t - */ -typedef struct - { - unsigned char mask; - char *string; - } ops_bit_map_t; - -void ops_text_init(ops_text_t *text); -void ops_text_free(ops_text_t *text); - -const char *ops_show_packet_tag(ops_packet_tag_t packet_tag); -const char *ops_show_ss_type(ops_ss_type_t ss_type); - -const char *ops_show_sig_type(ops_sig_type_t sig_type); -const char *ops_show_pka(ops_public_key_algorithm_t pka); - -ops_text_t *ops_showall_ss_preferred_compression(ops_ss_preferred_compression_t ss_preferred_compression); -const char *ops_show_ss_preferred_compression(unsigned char octet); - -ops_text_t *ops_showall_ss_preferred_hash(ops_ss_preferred_hash_t ss_preferred_hash); -const char *ops_show_hash_algorithm(unsigned char octet); -const char *ops_show_symmetric_algorithm(unsigned char hash); - -ops_text_t *ops_showall_ss_preferred_ska(ops_ss_preferred_ska_t ss_preferred_ska); -const char *ops_show_ss_preferred_ska(unsigned char octet); - -const char *ops_show_ss_rr_code(ops_ss_rr_code_t ss_rr_code); - -ops_text_t *ops_showall_ss_features(ops_ss_features_t ss_features); - -ops_text_t *ops_showall_ss_key_flags(ops_ss_key_flags_t ss_key_flags); -const char *ops_show_ss_key_flag(unsigned char octet, ops_bit_map_t *map); - -ops_text_t *ops_showall_ss_key_server_prefs(ops_ss_key_server_prefs_t ss_key_server_prefs); -const char *ops_show_ss_key_server_prefs(unsigned char octet, - ops_bit_map_t *map); - -ops_text_t *ops_showall_ss_notation_data_flags(ops_ss_notation_data_t ss_notation_data); - -char *ops_str_from_map(int code, ops_map_t *map); - -/* vim:set textwidth=120: */ -/* vim:set ts=8: */ - -#endif /* OPS_PACKET_TO_TEXT_H */ diff --git a/openpgpsdk/src/openpgpsdk/packet.h b/openpgpsdk/src/openpgpsdk/packet.h deleted file mode 100644 index 49e59a556..000000000 --- a/openpgpsdk/src/openpgpsdk/packet.h +++ /dev/null @@ -1,951 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - * packet related headers. - */ - -#ifndef OPS_PACKET_H -#define OPS_PACKET_H - -#include "configure.h" - -#include -#include -#include -#include "types.h" -#include "errors.h" - -/** General-use structure for variable-length data - */ - -typedef struct - { - size_t len; - unsigned char *contents; - } ops_data_t; - -/************************************/ -/* Packet Tags - RFC4880, 4.2 */ -/************************************/ - -/** Packet Tag - Bit 7 Mask (this bit is always set). - * The first byte of a packet is the "Packet Tag". It always - * has bit 7 set. This is the mask for it. - * - * \see RFC4880 4.2 - */ -#define OPS_PTAG_ALWAYS_SET 0x80 - -/** Packet Tag - New Format Flag. - * Bit 6 of the Packet Tag is the packet format indicator. - * If it is set, the new format is used, if cleared the - * old format is used. - * - * \see RFC4880 4.2 - */ -#define OPS_PTAG_NEW_FORMAT 0x40 - - -/** Old Packet Format: Mask for content tag. - * In the old packet format bits 5 to 2 (including) - * are the content tag. This is the mask to apply - * to the packet tag. Note that you need to - * shift by #OPS_PTAG_OF_CONTENT_TAG_SHIFT bits. - * - * \see RFC4880 4.2 - */ -#define OPS_PTAG_OF_CONTENT_TAG_MASK 0x3c -/** Old Packet Format: Offset for the content tag. - * As described at #OPS_PTAG_OF_CONTENT_TAG_MASK the - * content tag needs to be shifted after being masked - * out from the Packet Tag. - * - * \see RFC4880 4.2 - */ -#define OPS_PTAG_OF_CONTENT_TAG_SHIFT 2 -/** Old Packet Format: Mask for length type. - * Bits 1 and 0 of the packet tag are the length type - * in the old packet format. - * - * See #ops_ptag_of_lt_t for the meaning of the values. - * - * \see RFC4880 4.2 - */ -#define OPS_PTAG_OF_LENGTH_TYPE_MASK 0x03 - - -/** Old Packet Format Lengths. - * Defines the meanings of the 2 bits for length type in the - * old packet format. - * - * \see RFC4880 4.2.1 - */ -typedef enum - { - OPS_PTAG_OF_LT_ONE_BYTE =0x00, /*!< Packet has a 1 byte length - header is 2 bytes long. */ - OPS_PTAG_OF_LT_TWO_BYTE =0x01, /*!< Packet has a 2 byte length - header is 3 bytes long. */ - OPS_PTAG_OF_LT_FOUR_BYTE =0x02, /*!< Packet has a 4 byte length - header is 5 bytes long. */ - OPS_PTAG_OF_LT_INDETERMINATE =0x03 /*!< Packet has a indeterminate length. */ - } ops_ptag_of_lt_t; - - -/** New Packet Format: Mask for content tag. - * In the new packet format the 6 rightmost bits - * are the content tag. This is the mask to apply - * to the packet tag. Note that you need to - * shift by #OPS_PTAG_NF_CONTENT_TAG_SHIFT bits. - * - * \see RFC4880 4.2 - */ -#define OPS_PTAG_NF_CONTENT_TAG_MASK 0x3f -/** New Packet Format: Offset for the content tag. - * As described at #OPS_PTAG_NF_CONTENT_TAG_MASK the - * content tag needs to be shifted after being masked - * out from the Packet Tag. - * - * \see RFC4880 4.2 - */ -#define OPS_PTAG_NF_CONTENT_TAG_SHIFT 0 - - -/** Structure to hold one parse error string. */ -typedef struct - { - const char *error; /*!< error message. */ - } ops_parser_error_t; - -/** Structure to hold one error code */ -typedef struct - { - ops_errcode_t errcode; - } ops_parser_errcode_t; - -/** Structure to hold one packet tag. - * \see RFC4880 4.2 - */ -typedef struct - { - unsigned new_format; /*!< Whether this packet tag is new (true) or old format (false) */ - unsigned content_tag; /*!< content_tag value - See #ops_content_tag_t for meanings */ - ops_ptag_of_lt_t length_type; /*!< Length type (#ops_ptag_of_lt_t) - only if this packet tag is old format. Set to 0 if new format. */ - unsigned length; /*!< The length of the packet. This value is set when we read and compute the - length information, not at the same moment we create the packet tag structure. - Only defined if #length_read is set. */ /* XXX: Ben, is this correct? */ - unsigned position; /*!< The position (within the current reader) of the packet */ - } ops_ptag_t; - -/** Public Key Algorithm Numbers. - * OpenPGP assigns a unique Algorithm Number to each algorithm that is part of OpenPGP. - * - * This lists algorithm numbers for public key algorithms. - * - * \see RFC4880 9.1 - */ -typedef enum - { - OPS_PKA_RSA =1, /*!< RSA (Encrypt or Sign) */ - OPS_PKA_RSA_ENCRYPT_ONLY =2, /*!< RSA Encrypt-Only (deprecated - \see RFC4880 13.5) */ - OPS_PKA_RSA_SIGN_ONLY =3, /*!< RSA Sign-Only (deprecated - \see RFC4880 13.5) */ - OPS_PKA_ELGAMAL =16, /*!< Elgamal (Encrypt-Only) */ - OPS_PKA_DSA =17, /*!< DSA (Digital Signature Algorithm) */ - OPS_PKA_RESERVED_ELLIPTIC_CURVE =18, /*!< Reserved for Elliptic Curve */ - OPS_PKA_RESERVED_ECDSA =19, /*!< Reserved for ECDSA */ - OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN =20, /*!< Deprecated. */ - OPS_PKA_RESERVED_DH =21, /*!< Reserved for Diffie-Hellman (X9.42, as defined for IETF-S/MIME) */ - OPS_PKA_PRIVATE00 =100, /*!< Private/Experimental Algorithm */ - OPS_PKA_PRIVATE01 =101, /*!< Private/Experimental Algorithm */ - OPS_PKA_PRIVATE02 =102, /*!< Private/Experimental Algorithm */ - OPS_PKA_PRIVATE03 =103, /*!< Private/Experimental Algorithm */ - OPS_PKA_PRIVATE04 =104, /*!< Private/Experimental Algorithm */ - OPS_PKA_PRIVATE05 =105, /*!< Private/Experimental Algorithm */ - OPS_PKA_PRIVATE06 =106, /*!< Private/Experimental Algorithm */ - OPS_PKA_PRIVATE07 =107, /*!< Private/Experimental Algorithm */ - OPS_PKA_PRIVATE08 =108, /*!< Private/Experimental Algorithm */ - OPS_PKA_PRIVATE09 =109, /*!< Private/Experimental Algorithm */ - OPS_PKA_PRIVATE10 =110, /*!< Private/Experimental Algorithm */ - } ops_public_key_algorithm_t; - -/** Structure to hold one DSA public key parameters. - * - * \see RFC4880 5.5.2 - */ -typedef struct - { - BIGNUM *p; /*!< DSA prime p */ - BIGNUM *q; /*!< DSA group order q */ - BIGNUM *g; /*!< DSA group generator g */ - BIGNUM *y; /*!< DSA public key value y (= g^x mod p with x being the secret) */ - } ops_dsa_public_key_t; - -/** Structure to hold on RSA public key. - * - * \see RFC4880 5.5.2 - */ -typedef struct - { - BIGNUM *n; /*!< RSA public modulus n */ - BIGNUM *e; /*!< RSA public encryptiong exponent e */ - } ops_rsa_public_key_t; - -/** Structure to hold on ElGamal public key parameters. - * - * \see RFC4880 5.5.2 - */ -typedef struct - { - BIGNUM *p; /*!< ElGamal prime p */ - BIGNUM *g; /*!< ElGamal group generator g */ - BIGNUM *y; /*!< ElGamal public key value y (= g^x mod p with x being the secret) */ - } ops_elgamal_public_key_t; - -/** Union to hold public key parameters of any algorithm */ -typedef union - { - ops_dsa_public_key_t dsa; /*!< A DSA public key */ - ops_rsa_public_key_t rsa; /*!< An RSA public key */ - ops_elgamal_public_key_t elgamal; /*!< An ElGamal public key */ - } ops_public_key_union_t; - -/** Version. - * OpenPGP has two different protocol versions: version 3 and version 4. - * - * \see RFC4880 5.2 - */ -typedef enum - { - OPS_V2=2, /*contents to be a null-terminated list */ - } ops_ss_preferred_ska_t; - -/** Signature Subpacket : Preferrred Hash Algorithm */ -typedef struct - { - ops_data_t data; - } ops_ss_preferred_hash_t; - -/** Signature Subpacket : Preferred Compression */ -typedef struct - { - ops_data_t data; - } ops_ss_preferred_compression_t; - -/** Signature Subpacket : Key Flags */ -typedef struct - { - ops_data_t data; - } ops_ss_key_flags_t; - -/** Signature Subpacket : Key Server Preferences */ -typedef struct - { - ops_data_t data; - } ops_ss_key_server_prefs_t; - -/** Signature Subpacket : Features */ -typedef struct - { - ops_data_t data; - } ops_ss_features_t; - -/** Signature Subpacket : Signature Target */ -typedef struct - { - ops_public_key_algorithm_t pka_alg; - ops_hash_algorithm_t hash_alg; - ops_data_t hash; - } ops_ss_signature_target_t; - -/** Signature Subpacket : Embedded Signature */ -typedef struct - { - ops_data_t sig; - } ops_ss_embedded_signature_t; - -/** ops_packet_t */ - -typedef struct - { - size_t length; - unsigned char *raw; - } ops_packet_t; - -/** Types of Compression */ -typedef enum - { - OPS_C_NONE=0, - OPS_C_ZIP=1, - OPS_C_ZLIB=2, - OPS_C_BZIP2=3, - } ops_compression_type_t; - -/* unlike most structures, this will feed its data as a stream - * to the application instead of directly including it */ -/** ops_compressed_t */ -typedef struct - { - ops_compression_type_t type; - } ops_compressed_t; - -/** ops_one_pass_signature_t */ -typedef struct - { - unsigned char version; - ops_sig_type_t sig_type; - ops_hash_algorithm_t hash_algorithm; - ops_public_key_algorithm_t key_algorithm; - unsigned char keyid[OPS_KEY_ID_SIZE]; - ops_boolean_t nested; - } ops_one_pass_signature_t; - -/** Signature Subpacket : Primary User ID */ -typedef struct - { - ops_boolean_t primary_user_id; - } ops_ss_primary_user_id_t; - -/** Signature Subpacket : Regexp */ -typedef struct - { - char *text; - } ops_ss_regexp_t; - -/** Signature Subpacket : Policy URL */ -typedef struct - { - char *text; - } ops_ss_policy_url_t; - -/** Signature Subpacket : Preferred Key Server */ -typedef struct - { - char *text; - } ops_ss_preferred_key_server_t; - -/** Signature Subpacket : Revocation Key */ -typedef struct - { - unsigned char clss; /* class - name changed for C++ */ - unsigned char algid; - unsigned char fingerprint[20]; - } ops_ss_revocation_key_t; - -/** Signature Subpacket : Revocation Reason */ -typedef struct - { - unsigned char code; - char *text; - } ops_ss_revocation_reason_t; - -/** literal_data_type_t */ -typedef enum - { - OPS_LDT_BINARY='b', - OPS_LDT_TEXT='t', - OPS_LDT_UTF8='u', - OPS_LDT_LOCAL='l', - OPS_LDT_LOCAL2='1' - } ops_literal_data_type_t; - -/** ops_literal_data_header_t */ -typedef struct - { - ops_literal_data_type_t format; - char filename[256]; - time_t modification_time; - } ops_literal_data_header_t; - -/** ops_literal_data_body_t */ -typedef struct - { - unsigned length; - unsigned char *data;//[8192]; - } ops_literal_data_body_t; - -/** ops_mdc_t */ -typedef struct - { - unsigned char data[20]; // size of SHA1 hash - } ops_mdc_t; - -/** ops_armoured_header_value_t */ -typedef struct - { - char *key; - char *value; - } ops_armoured_header_value_t; - -/** ops_headers_t */ -typedef struct - { - ops_armoured_header_value_t *headers; - unsigned nheaders; - } ops_headers_t; - -/** ops_armour_header_t */ -typedef struct - { - const char *type; - ops_headers_t headers; - } ops_armour_header_t; - -/** ops_armour_trailer_t */ -typedef struct - { - const char *type; - } ops_armour_trailer_t; - -/** ops_signed_cleartext_header_t */ -typedef struct - { - ops_headers_t headers; - } ops_signed_cleartext_header_t; - -/** ops_signed_cleartext_body_t */ -typedef struct - { - unsigned length; - unsigned char *data; // \todo fix hard-coded value? - } ops_signed_cleartext_body_t; - -/** ops_signed_cleartext_trailer_t */ -typedef struct - { - struct _ops_hash_t *hash; /*!< This will not have been finalised, but will have seen all the cleartext data in canonical form */ - } ops_signed_cleartext_trailer_t; - -/** ops_unarmoured_text_t */ -typedef struct - { - unsigned length; - unsigned char *data; - } ops_unarmoured_text_t; - -typedef enum - { - SE_IP_DATA_VERSION=1 - } ops_se_ip_data_version_t; - -typedef enum - { - OPS_PKSK_V3=3 - } ops_pk_session_key_version_t; - -/** ops_pk_session_key_parameters_rsa_t */ -typedef struct - { - BIGNUM *encrypted_m; - BIGNUM *m; - } ops_pk_session_key_parameters_rsa_t; - -/** ops_pk_session_key_parameters_elgamal_t */ -typedef struct - { - BIGNUM *g_to_k; - BIGNUM *encrypted_m; - } ops_pk_session_key_parameters_elgamal_t; - -/** ops_pk_session_key_parameters_t */ -typedef union - { - ops_pk_session_key_parameters_rsa_t rsa; - ops_pk_session_key_parameters_elgamal_t elgamal; - } ops_pk_session_key_parameters_t; - -/** ops_pk_session_key_t */ -typedef struct - { - ops_pk_session_key_version_t version; - unsigned char key_id[OPS_KEY_ID_SIZE]; - ops_public_key_algorithm_t algorithm; - ops_pk_session_key_parameters_t parameters; - ops_symmetric_algorithm_t symmetric_algorithm; - unsigned char key[OPS_MAX_KEY_SIZE]; - unsigned short checksum; - } ops_pk_session_key_t; - -/** ops_secret_key_passphrase_t */ -typedef struct - { - const ops_secret_key_t *secret_key; - char **passphrase; /* point somewhere that gets filled in to work around constness of content */ - } ops_secret_key_passphrase_t; - -typedef enum - { - OPS_SE_IP_V1=1 - } ops_se_ip_version_t; - -/** ops_se_ip_data_header_t */ -typedef struct - { - ops_se_ip_version_t version; - } ops_se_ip_data_header_t; - -/** ops_se_ip_data_body_t */ -typedef struct - { - unsigned length; - unsigned char* data; // \todo remember to free this - } ops_se_ip_data_body_t; - -/** ops_se_data_body_t */ -typedef struct - { - unsigned length; - unsigned char data[8192]; // \todo parameterise this! - } ops_se_data_body_t; - -/** ops_get_secret_key_t */ -typedef struct - { - const ops_secret_key_t **secret_key; - const ops_pk_session_key_t *pk_session_key; - } ops_get_secret_key_t; - -/** ops_parser_union_content_t */ -typedef union - { - ops_parser_error_t error; - ops_parser_errcode_t errcode; - ops_ptag_t ptag; - ops_public_key_t public_key; - ops_trust_t trust; - ops_user_id_t user_id; - ops_user_attribute_t user_attribute; - ops_signature_t signature; - ops_ss_raw_t ss_raw; - ops_ss_trust_t ss_trust; - ops_ss_revocable_t ss_revocable; - ops_ss_time_t ss_time; - ops_ss_key_id_t ss_issuer_key_id; - ops_ss_notation_data_t ss_notation_data; - ops_packet_t packet; - ops_compressed_t compressed; - ops_one_pass_signature_t one_pass_signature; - ops_ss_preferred_ska_t ss_preferred_ska; - ops_ss_preferred_hash_t ss_preferred_hash; - ops_ss_preferred_compression_t ss_preferred_compression; - ops_ss_key_flags_t ss_key_flags; - ops_ss_key_server_prefs_t ss_key_server_prefs; - ops_ss_primary_user_id_t ss_primary_user_id; - ops_ss_regexp_t ss_regexp; - ops_ss_policy_url_t ss_policy_url; - ops_ss_preferred_key_server_t ss_preferred_key_server; - ops_ss_revocation_key_t ss_revocation_key; - ops_ss_userdefined_t ss_userdefined; - ops_ss_unknown_t ss_unknown; - ops_literal_data_header_t literal_data_header; - ops_literal_data_body_t literal_data_body; - ops_mdc_t mdc; - ops_ss_features_t ss_features; - ops_ss_signature_target_t ss_signature_target; - ops_ss_embedded_signature_t ss_embedded_signature; - ops_ss_revocation_reason_t ss_revocation_reason; - ops_secret_key_t secret_key; - ops_user_id_t ss_signers_user_id; - ops_armour_header_t armour_header; - ops_armour_trailer_t armour_trailer; - ops_signed_cleartext_header_t signed_cleartext_header; - ops_signed_cleartext_body_t signed_cleartext_body; - ops_signed_cleartext_trailer_t signed_cleartext_trailer; - ops_unarmoured_text_t unarmoured_text; - ops_pk_session_key_t pk_session_key; - ops_secret_key_passphrase_t secret_key_passphrase; - ops_se_ip_data_header_t se_ip_data_header; - ops_se_ip_data_body_t se_ip_data_body; - ops_se_data_body_t se_data_body; - ops_get_secret_key_t get_secret_key; - } ops_parser_content_union_t; - -/** ops_parser_content_t */ -struct ops_parser_content_t - { - ops_content_tag_t tag; - unsigned char critical; /* for signature subpackets */ - ops_parser_content_union_t content; - }; - -/** ops_fingerprint_t */ -typedef struct - { - unsigned char fingerprint[20]; - unsigned length; - } ops_fingerprint_t; - -void ops_init(void); -void ops_finish(void); -void ops_keyid(unsigned char keyid[OPS_KEY_ID_SIZE], - const ops_public_key_t *key); -void ops_fingerprint(ops_fingerprint_t *fp,const ops_public_key_t *key); -void ops_public_key_free(ops_public_key_t *key); -void ops_public_key_copy(ops_public_key_t *dst,const ops_public_key_t *src); -void ops_user_id_free(ops_user_id_t *id); -void ops_user_attribute_free(ops_user_attribute_t *att); -void ops_signature_free(ops_signature_t *sig); -void ops_trust_free(ops_trust_t *trust); -void ops_ss_preferred_ska_free(ops_ss_preferred_ska_t *ss_preferred_ska); -void ops_ss_preferred_hash_free(ops_ss_preferred_hash_t *ss_preferred_hash); -void ops_ss_preferred_compression_free(ops_ss_preferred_compression_t *ss_preferred_compression); -void ops_ss_key_flags_free(ops_ss_key_flags_t *ss_key_flags); -void ops_ss_key_server_prefs_free(ops_ss_key_server_prefs_t *ss_key_server_prefs); -void ops_ss_features_free(ops_ss_features_t *ss_features); -void ops_ss_notation_data_free(ops_ss_notation_data_t *ss_notation_data); -void ops_ss_policy_url_free(ops_ss_policy_url_t *ss_policy_url); -void ops_ss_preferred_key_server_free(ops_ss_preferred_key_server_t *ss_preferred_key_server); -void ops_ss_regexp_free(ops_ss_regexp_t *ss_regexp); -void ops_ss_userdefined_free(ops_ss_userdefined_t *ss_userdefined); -void ops_ss_reserved_free(ops_ss_unknown_t *ss_unknown); -void ops_ss_revocation_reason_free(ops_ss_revocation_reason_t *ss_revocation_reason); -void ops_ss_signature_target_free(ops_ss_signature_target_t *ss_signature_target); -void ops_ss_embedded_signature_free(ops_ss_embedded_signature_t *ss_embedded_signature); - -void ops_packet_free(ops_packet_t *packet); -void ops_parser_content_free(ops_parser_content_t *c); -void ops_secret_key_free(ops_secret_key_t *key); -void ops_secret_key_copy(ops_secret_key_t *dst,const ops_secret_key_t *src); -void ops_pk_session_key_free(ops_pk_session_key_t *sk); - -/* vim:set textwidth=120: */ -/* vim:set ts=8: */ - -#endif diff --git a/openpgpsdk/src/openpgpsdk/parse_local.h b/openpgpsdk/src/openpgpsdk/parse_local.h deleted file mode 100644 index 64fd013b6..000000000 --- a/openpgpsdk/src/openpgpsdk/parse_local.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file */ - -#include -#include - -/** ops_reader_info */ -struct ops_reader_info - { - ops_reader_t *reader; /*!< the reader function to use to get the - data to be parsed */ - ops_reader_destroyer_t *destroyer; - void *arg; /*!< the args to pass to the reader function */ - - ops_boolean_t accumulate:1; /*!< set to accumulate packet data */ - unsigned char *accumulated; /*!< the accumulated data */ - unsigned asize; /*!< size of the buffer */ - unsigned alength; /*!< used buffer */ - /* XXX: what do we do about offsets into compressed packets? */ - unsigned position; /*!< the offset from the beginning (with this reader) */ - - ops_reader_info_t *next; - ops_parse_info_t *pinfo; /*!< A pointer back to the parent parse_info structure */ - }; - - -/** ops_crypt_info - Encrypt/decrypt settings -*/ -struct ops_crypt_info - { - char *passphrase; /* - -#include - -void ops_random(void *dest,size_t length) - { - RAND_bytes(dest,length); - } diff --git a/openpgpsdk/src/openpgpsdk/random.h b/openpgpsdk/src/openpgpsdk/random.h deleted file mode 100644 index 833094353..000000000 --- a/openpgpsdk/src/openpgpsdk/random.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifdef WIN32 -#include -#else -#include -#endif - -void ops_random(void *dest,size_t length); diff --git a/openpgpsdk/src/openpgpsdk/reader.c b/openpgpsdk/src/openpgpsdk/reader.c deleted file mode 100644 index 24fc8a041..000000000 --- a/openpgpsdk/src/openpgpsdk/reader.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#ifndef WIN32 -#include -#else -#include -#endif -#include -#include -#include - -#include -#include - -#include "parse_local.h" - - -/** - * \ingroup Internal_Readers_Generic - * \brief Starts reader stack - * \param pinfo Parse settings - * \param reader Reader to use - * \param destroyer Destroyer to use - * \param arg Reader-specific arg - */ -void ops_reader_set(ops_parse_info_t *pinfo,ops_reader_t *reader,ops_reader_destroyer_t *destroyer,void *arg) - { - pinfo->rinfo.reader=reader; - pinfo->rinfo.destroyer=destroyer; - pinfo->rinfo.arg=arg; - } - -/** - * \ingroup Internal_Readers_Generic - * \brief Adds to reader stack - * \param pinfo Parse settings - * \param reader Reader to use - * \param destroyer Reader's destroyer - * \param arg Reader-specific arg - */ -void ops_reader_push(ops_parse_info_t *pinfo,ops_reader_t *reader,ops_reader_destroyer_t *destroyer,void *arg) - { - ops_reader_info_t *rinfo=malloc(sizeof *rinfo); - - *rinfo=pinfo->rinfo; - memset(&pinfo->rinfo,'\0',sizeof pinfo->rinfo); - pinfo->rinfo.next=rinfo; - pinfo->rinfo.pinfo=pinfo; - - // should copy accumulate flags from other reader? RW - pinfo->rinfo.accumulate=rinfo->accumulate; - - ops_reader_set(pinfo,reader,destroyer,arg); - } - -/** - * \ingroup Internal_Readers_Generic - * \brief Removes from reader stack - * \param pinfo Parse settings - */ -void ops_reader_pop(ops_parse_info_t *pinfo) - { - ops_reader_info_t *next=pinfo->rinfo.next; - // We are about to overwrite pinfo->rinfo, so free any data in the - // old rinfo structure first. - free(pinfo->rinfo.accumulated); - pinfo->rinfo=*next; - free(next); - } - -/** - * \ingroup Internal_Readers_Generic - * \brief Gets arg from reader - * \param rinfo Reader info - * \return Pointer to reader info's arg - */ -void *ops_reader_get_arg(ops_reader_info_t *rinfo) - { return rinfo->arg; } - -/** - * \ingroup Internal_Readers_Generic - * \brief Gets reader's arg from parse_info - * \param pinfo - * \return Pointer to parse_info's reader_info's arg - */ -void *ops_reader_get_arg_from_pinfo(ops_parse_info_t *pinfo) - { return pinfo->rinfo.arg; } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/reader_armoured.c b/openpgpsdk/src/openpgpsdk/reader_armoured.c deleted file mode 100644 index 44ed56592..000000000 --- a/openpgpsdk/src/openpgpsdk/reader_armoured.c +++ /dev/null @@ -1,1101 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - * \brief Code for dealing with ASCII-armoured packets - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "parse_local.h" - -#include - -#include - -static int debug=0; - -#define CRC24_POLY 0x1864cfbL - -/** - * \struct dearmour_arg_t - */ -typedef struct - { - enum - { - OUTSIDE_BLOCK=0, - BASE64, - AT_TRAILER_NAME, - } state; - - enum - { - NONE=0, - BEGIN_PGP_MESSAGE, - BEGIN_PGP_PUBLIC_KEY_BLOCK, - BEGIN_PGP_PRIVATE_KEY_BLOCK, - BEGIN_PGP_MULTI, - BEGIN_PGP_SIGNATURE, - - END_PGP_MESSAGE, - END_PGP_PUBLIC_KEY_BLOCK, - END_PGP_PRIVATE_KEY_BLOCK, - END_PGP_MULTI, - END_PGP_SIGNATURE, - - BEGIN_PGP_SIGNED_MESSAGE - } lastseen; - - ops_parse_info_t *parse_info; - ops_boolean_t seen_nl:1; - ops_boolean_t prev_nl:1; - ops_boolean_t allow_headers_without_gap:1; /*!< allow headers in - armoured data that - are not separated - from the data by a - blank line */ - ops_boolean_t allow_no_gap:1; /*!< allow no blank line at the - start of armoured data */ - ops_boolean_t allow_trailing_whitespace:1; /*!< allow armoured - stuff to have - trailing whitespace - where we wouldn't - strictly expect it */ - - // it is an error to get a cleartext message without a sig - ops_boolean_t expect_sig:1; - ops_boolean_t got_sig:1; - - // base64 stuff - unsigned buffered; - unsigned char buffer[3]; - ops_boolean_t eof64; - unsigned long checksum; - unsigned long read_checksum; - // unarmoured text blocks - unsigned char unarmoured[8192]; - size_t num_unarmoured; - // pushed back data (stored backwards) - unsigned char *pushed_back; - unsigned npushed_back; - // armoured block headers - ops_headers_t headers; - } dearmour_arg_t; - -static void push_back(dearmour_arg_t *arg,const unsigned char *buf, unsigned length) -{ - unsigned n; - - //ASSERT(!arg->pushed_back); // in the least, there will be a memory leak. Not a big issue. - arg->pushed_back=malloc(length); - for(n=0 ; n < length ; ++n) - arg->pushed_back[n]=buf[length-n-1]; - arg->npushed_back=length; -} - -static int set_lastseen_headerline(dearmour_arg_t* arg, char* buf, ops_error_t **errors) - { - char* begin_msg="BEGIN PGP MESSAGE"; - char* begin_public="BEGIN PGP PUBLIC KEY BLOCK"; - char* begin_private="BEGIN PGP PRIVATE KEY BLOCK"; - char* begin_multi="BEGIN PGP MESSAGE, PART "; - char* begin_sig="BEGIN PGP SIGNATURE"; - - char* end_msg="END PGP MESSAGE"; - char* end_public="END PGP PUBLIC KEY BLOCK"; - char* end_private="END PGP PRIVATE KEY BLOCK"; - char* end_multi="END PGP MESSAGE, PART "; - char* end_sig="END PGP SIGNATURE"; - - char* begin_signed_msg="BEGIN PGP SIGNED MESSAGE"; - - int prev=arg->lastseen; - - if (!strncmp(buf,begin_msg,strlen(begin_msg))) - arg->lastseen=BEGIN_PGP_MESSAGE; - else if (!strncmp(buf,begin_public,strlen(begin_public))) - arg->lastseen=BEGIN_PGP_PUBLIC_KEY_BLOCK; - else if (!strncmp(buf,begin_private,strlen(begin_private))) - arg->lastseen=BEGIN_PGP_PRIVATE_KEY_BLOCK; - else if (!strncmp(buf,begin_multi,strlen(begin_multi))) - arg->lastseen=BEGIN_PGP_MULTI; - else if (!strncmp(buf,begin_sig,strlen(begin_sig))) - arg->lastseen=BEGIN_PGP_SIGNATURE; - - else if (!strncmp(buf,end_msg,strlen(end_msg))) - arg->lastseen=END_PGP_MESSAGE; - else if (!strncmp(buf,end_public,strlen(end_public))) - arg->lastseen=END_PGP_PUBLIC_KEY_BLOCK; - else if (!strncmp(buf,end_private,strlen(end_private))) - arg->lastseen=END_PGP_PRIVATE_KEY_BLOCK; - else if (!strncmp(buf,end_multi,strlen(end_multi))) - arg->lastseen=END_PGP_MULTI; - else if (!strncmp(buf,end_sig,strlen(end_sig))) - arg->lastseen=END_PGP_SIGNATURE; - - else if (!strncmp(buf,begin_signed_msg,strlen(begin_signed_msg))) - arg->lastseen=BEGIN_PGP_SIGNED_MESSAGE; - - else - { - OPS_ERROR_1(errors,OPS_E_R_BAD_FORMAT,"Unrecognised Header Line %s", buf); - return 0; - } - - if (debug) - printf("set header: buf=%s, arg->lastseen=%d, prev=%d\n", buf, arg->lastseen, prev); - - switch (arg->lastseen) - { - case NONE: - OPS_ERROR_1(errors,OPS_E_R_BAD_FORMAT,"Unrecognised last seen Header Line %s", buf); - break; - - case END_PGP_MESSAGE: - if (prev!=BEGIN_PGP_MESSAGE) - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Got END PGP MESSAGE, but not after BEGIN"); - break; - - case END_PGP_PUBLIC_KEY_BLOCK: - if (prev!=BEGIN_PGP_PUBLIC_KEY_BLOCK) - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Got END PGP PUBLIC KEY BLOCK, but not after BEGIN"); - break; - - case END_PGP_PRIVATE_KEY_BLOCK: - if (prev!=BEGIN_PGP_PRIVATE_KEY_BLOCK) - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Got END PGP PRIVATE KEY BLOCK, but not after BEGIN"); - break; - - case BEGIN_PGP_MULTI: - case END_PGP_MULTI: - OPS_ERROR(errors,OPS_E_R_UNSUPPORTED,"Multi-part messages are not yet supported"); - break; - - case END_PGP_SIGNATURE: - if (prev!=BEGIN_PGP_SIGNATURE) - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Got END PGP SIGNATURE, but not after BEGIN"); - break; - - case BEGIN_PGP_MESSAGE: - case BEGIN_PGP_PUBLIC_KEY_BLOCK: - case BEGIN_PGP_PRIVATE_KEY_BLOCK: - case BEGIN_PGP_SIGNATURE: - case BEGIN_PGP_SIGNED_MESSAGE: - break; - } - - return 1; - } - -static int read_char(dearmour_arg_t *arg,ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo, - ops_boolean_t skip) - { - unsigned char c[1]; - - do - { - if(arg->npushed_back) - { - c[0]=arg->pushed_back[--arg->npushed_back]; - if(!arg->npushed_back) - { - free(arg->pushed_back); - arg->pushed_back=NULL; - } - } - /* XXX: should ops_stacked_read exist? Shouldn't this be a limited_read? */ - else if(ops_stacked_read(c,1,errors,rinfo,cbinfo) != 1) - return -1; - } - while(skip && c[0] == '\r'); - - arg->prev_nl=arg->seen_nl; - arg->seen_nl=c[0] == '\n'; - - return c[0]; - } - -static int eat_whitespace(int first, - dearmour_arg_t *arg,ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo, - ops_boolean_t skip) - { - int c=first; - - while(c == ' ' || c == '\t') - c=read_char(arg,errors,rinfo,cbinfo,skip); - - return c; - } - -static int read_and_eat_whitespace(dearmour_arg_t *arg, - ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo, - ops_boolean_t skip) - { - int c; - - do - c=read_char(arg,errors,rinfo,cbinfo,skip); - while(c == ' ' || c == '\t'); - - return c; - } - -static void flush(dearmour_arg_t *arg,ops_parse_cb_info_t *cbinfo) - { - ops_parser_content_t content; - - if(arg->num_unarmoured == 0) - return; - - content.content.unarmoured_text.data=arg->unarmoured; - content.content.unarmoured_text.length=arg->num_unarmoured; - CB(cbinfo,OPS_PTAG_CT_UNARMOURED_TEXT,&content); - arg->num_unarmoured=0; - } - -static int unarmoured_read_char(dearmour_arg_t *arg,ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo, - ops_boolean_t skip) - { - int c; - - do - { - c=read_char(arg,errors,rinfo,cbinfo,ops_false); - if(c < 0) - return c; - arg->unarmoured[arg->num_unarmoured++]=c; - if(arg->num_unarmoured == sizeof arg->unarmoured) - flush(arg,cbinfo); - } - while(skip && c == '\r'); - - return c; - } - -/** - * \param headers - * \param key - * - * \return header value if found, otherwise NULL - */ -const char *ops_find_header(ops_headers_t *headers,const char *key) - { - unsigned n; - - for(n=0 ; n < headers->nheaders ; ++n) - if(!strcmp(headers->headers[n].key,key)) - return headers->headers[n].value; - return NULL; - } - -/** - * \param dest - * \param src - */ -void ops_dup_headers(ops_headers_t *dest,const ops_headers_t *src) - { - unsigned n; - - dest->headers=malloc(src->nheaders*sizeof *dest->headers); - dest->nheaders=src->nheaders; - - for(n=0 ; n < src->nheaders ; ++n) - { - dest->headers[n].key=strdup(src->headers[n].key); - dest->headers[n].value=strdup(src->headers[n].value); - } - } - -/* Note that this skips CRs so implementations always see just - straight LFs as line terminators */ -static int process_dash_escaped(dearmour_arg_t *arg,ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo) -{ - ops_parser_content_t content; - ops_parser_content_t content2; - ops_signed_cleartext_body_t *body=&content.content.signed_cleartext_body; - ops_signed_cleartext_trailer_t *trailer - =&content2.content.signed_cleartext_trailer; - const char *hashstr; - ops_hash_t *hash; - int total; - - hash=malloc(sizeof *hash); - hashstr=ops_find_header(&arg->headers,"Hash"); - if(hashstr) - { - ops_hash_algorithm_t alg; - - alg=ops_hash_algorithm_from_text(hashstr); - - if(!ops_is_hash_alg_supported(&alg)) - { - free(hash); - OPS_ERROR_1(errors,OPS_E_R_BAD_FORMAT,"Unsupported hash algorithm '%s'",hashstr); - return -1; - } - if(alg == OPS_HASH_UNKNOWN) - { - free(hash); - OPS_ERROR_1(errors,OPS_E_R_BAD_FORMAT,"Unknown hash algorithm '%s'",hashstr); - return -1; - } - ops_hash_any(hash,alg); - } - else - ops_hash_md5(hash); - - hash->init(hash); - - body->length=0; - total=0; - for( ; ; ) - { - int c; - unsigned count; - - if((c=read_char(arg,errors,rinfo,cbinfo,ops_true)) < 0) - return -1; - if(arg->prev_nl && c == '-') - { - if((c=read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0) - return -1; - if(c != ' ') - { - /* then this had better be a trailer! */ - if(c != '-') - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Bad dash-escaping"); - for(count=2 ; count < 5 ; ++count) - { - if((c=read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0) - return -1; - if(c != '-') - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Bad dash-escaping (2)"); - } - arg->state=AT_TRAILER_NAME; - break; - } - /* otherwise we read the next character */ - if((c=read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0) - return -1; - } - if(c == '\n' && body->length) - { - if(!(memchr(body->data+1,'\n',body->length-1) == NULL)) // ASSERT(memchr(body->data+1,'\n',body->length-1) == NULL); - { - fprintf(stderr,"no \\n in armoured file.") ; - return -1 ; - } - if(body->data[0] == '\n') - hash->add(hash,(unsigned char *)"\r",1); - hash->add(hash,body->data,body->length); - if (debug) - { fprintf(stderr,"Got body:\n%s\n",body->data); } - CB(cbinfo,OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY,&content); - body->length=0; - } - - body->data[body->length++]=c; - ++total; - if(body->length == sizeof body->data) - { - if (debug) - { fprintf(stderr,"Got body (2):\n%s\n",body->data); } - CB(cbinfo,OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY,&content); - body->length=0; - } - } - - if(!(body->data[0] == '\n')) // ASSERT(body->data[0] == '\n'); - { - fprintf(stderr,"Body should end with \\n\n"); - return -1 ; - } - if(!(body->length == 1)) // ASSERT(body->length == 1); - { - fprintf(stderr,"Body length error\n"); - return -1 ; - } - /* don't send that one character, because its part of the trailer. */ - - trailer->hash=hash; - CB(cbinfo,OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER,&content2); - - return total; -} - -static int add_header(dearmour_arg_t *arg,const char *key,const char - *value) - { - /* - * Check that the header is valid - */ - if ( !strcmp(key,"Version") || !strcmp(key,"Comment") - || !strcmp(key,"MessageID") || !strcmp(key,"Hash") - || !strcmp(key,"Charset")) - { - arg->headers.headers=realloc(arg->headers.headers, - (arg->headers.nheaders+1) - *sizeof *arg->headers.headers); - arg->headers.headers[arg->headers.nheaders].key=strdup(key); - arg->headers.headers[arg->headers.nheaders].value=strdup(value); - ++arg->headers.nheaders; - return 1; - } - else - { - return 0; - } - } - -/* \todo what does a return value of 0 indicate? 1 is good, -1 is bad */ -static int parse_headers(dearmour_arg_t *arg,ops_error_t **errors, - ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo) -{ - int rtn=1; - char *buf; - unsigned nbuf; - unsigned size; - ops_boolean_t first=ops_true; - //ops_parser_content_t content; - - buf=NULL; - nbuf=size=0; - - for( ; ; ) - { - int c; - - if((c=read_char(arg,errors,rinfo,cbinfo,ops_true)) < 0) - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Unexpected EOF"); - rtn=-1; - break; - } - - if(c == '\n') - { - char *s; - - if(nbuf == 0) - break; - - if(!(nbuf < size)) // ASSERT(nbuf < size); - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Size error in armour header"); - return -1 ; - } - buf[nbuf]='\0'; - - s=strchr(buf,':'); - if(!s) - if(!first && !arg->allow_headers_without_gap) - { - // then we have seriously malformed armour - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"No colon in armour header"); - rtn=-1; - break; - } - else - { - if(first && - !(arg->allow_headers_without_gap || arg->allow_no_gap)) - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"No colon in armour header (2)"); - // then we have a nasty armoured block with no - // headers, not even a blank line. - buf[nbuf]='\n'; - push_back(arg,(unsigned char *)buf,nbuf+1); - rtn=-1; - break; - } - } - else - { - *s='\0'; - if(s[1] != ' ') - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"No space in armour header"); - rtn=-1; - goto end; - } - if (!add_header(arg,buf,s+2)) - { - OPS_ERROR_1(errors,OPS_E_R_BAD_FORMAT,"Invalid header %s", buf); - rtn=-1; - goto end; - } - nbuf=0; - } - first=ops_false; - } - else - { - if(size <= nbuf+1) - { - size+=size+80; - char *nbuf; - nbuf=realloc(buf,size); - if (nbuf == NULL) - { - free(buf); - buf = NULL ; - rtn=-1; - goto end; - } - buf = nbuf; - } - buf[nbuf++]=c; - } - } - -end: - free(buf); - - return rtn; -} - -static int read4(dearmour_arg_t *arg,ops_error_t **errors, - ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo, - int *pc,unsigned *pn,unsigned long *pl) - { - int n,c; - unsigned long l=0; - - for(n=0 ; n < 4 ; ++n) - { - c=read_char(arg,errors,rinfo,cbinfo,ops_true); - if(c < 0) - { - arg->eof64=ops_true; - return -1; - } - if(c == '-') - break; - if(c == '=') - break; - l <<= 6; - if(c >= 'A' && c <= 'Z') - l+=c-'A'; - else if(c >= 'a' && c <= 'z') - l+=c-'a'+26; - else if(c >= '0' && c <= '9') - l+=c-'0'+52; - else if(c == '+') - l+=62; - else if(c == '/') - l+=63; - else - { - --n; - l >>= 6; - } - } - - *pc=c; - *pn=n; - *pl=l; - - return 4; - } - -unsigned ops_crc24(unsigned checksum,unsigned char c) - { - unsigned i; - - checksum ^= c << 16; - for(i=0 ; i < 8 ; i++) - { - checksum <<= 1; - if(checksum & 0x1000000) - checksum ^= CRC24_POLY; - } - return checksum&0xffffffL; - } - -static int decode64(dearmour_arg_t *arg,ops_error_t **errors, - ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo) -{ - unsigned n; - int n2; - unsigned long l; - int c; - int ret; - - if(!(arg->buffered == 0)) // ASSERT(arg->buffered == 0); - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Badly formed base64"); - return 0; - } - - ret=read4(arg,errors,rinfo,cbinfo,&c,&n,&l); - if(ret < 0) - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Badly formed base64"); - return 0; - } - - if(n == 3) - { - if(c != '=') - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Badly terminated base64 (2)"); - return 0; - } - arg->buffered=2; - arg->eof64=ops_true; - l >>= 2; - } - else if(n == 2) - { - if(c != '=') - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Badly terminated base64 (3)"); - return 0; - } - arg->buffered=1; - arg->eof64=ops_true; - l >>= 4; - c=read_char(arg,errors,rinfo,cbinfo,ops_false); - if(c != '=') - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Badly terminated base64"); - return 0; - } - } - else if(n == 0) - { - if(!arg->prev_nl || c != '=') - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Badly terminated base64 (4)"); - return 0; - } - arg->buffered=0; - } - else - { - if(n != 4) // ASSERT(n == 4); - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"n should be 4"); - return 0; - } - arg->buffered=3; - - if(!(c != '-' && c != '=')) // ASSERT(c != '-' && c != '='); - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Badly terminated Base64 chunk"); - return 0; - } - } - - if(arg->buffered < 3 && arg->buffered > 0) - { - // then we saw padding - if(!(c == '=')) // ASSERT(c == '='); - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Badly terminated Base64 chunk"); - return 0; - } - c=read_and_eat_whitespace(arg,errors,rinfo,cbinfo,ops_true); - if(c != '\n') - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"No newline at base64 end"); - return 0; - } - c=read_char(arg,errors,rinfo,cbinfo,ops_false); - if(c != '=') - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"No checksum at base64 end"); - return 0; - } - } - - if(c == '=') - { - // now we are at the checksum - ret=read4(arg,errors,rinfo,cbinfo,&c,&n,&arg->read_checksum); - if(ret < 0 || n != 4) - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Error in checksum"); - return 0; - } - c=read_char(arg,errors,rinfo,cbinfo,ops_true); - if(arg->allow_trailing_whitespace) - c=eat_whitespace(c,arg,errors,rinfo,cbinfo,ops_true); - if(c != '\n') - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Badly terminated checksum"); - return 0; - } - c=read_char(arg,errors,rinfo,cbinfo,ops_false); - if(c != '-') - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Bad base64 trailer (2)"); - return 0; - } - } - - if(c == '-') - { - for(n=0 ; n < 4 ; ++n) - if(read_char(arg,errors,rinfo,cbinfo,ops_false) != '-') - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Bad base64 trailer"); - return 0; - } - arg->eof64=ops_true; - } - else if(!(arg->buffered)) // ASSERT(arg->buffered); - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Buffer error"); - return 0; - } - - for(n=0 ; n < arg->buffered ; ++n) - { - arg->buffer[n]=l; - l >>= 8; - } - - for(n2=arg->buffered-1 ; n2 >= 0 ; --n2) - arg->checksum=ops_crc24(arg->checksum,arg->buffer[n2]); - - if(arg->eof64 && arg->read_checksum != arg->checksum) - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Checksum mismatch"); - return 0; - } - - return 1; -} - -static void base64(dearmour_arg_t *arg) - { - arg->state=BASE64; - arg->checksum=CRC24_INIT; - arg->eof64=ops_false; - arg->buffered=0; - } - -// This reader is rather strange in that it can generate callbacks for -// content - this is because plaintext is not encapsulated in PGP -// packets... it also calls back for the text between the blocks. - -static int armoured_data_reader(void *dest_,size_t length,ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo) -{ - dearmour_arg_t *arg=ops_reader_get_arg(rinfo); - ops_parser_content_t content; - int ret; - ops_boolean_t first; - unsigned char *dest=dest_; - int saved=length; - - if(arg->eof64 && !arg->buffered) - if(!(arg->state == OUTSIDE_BLOCK || arg->state == AT_TRAILER_NAME)) // ASSERT(arg->state == OUTSIDE_BLOCK || arg->state == AT_TRAILER_NAME); - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Outside block or trailer name expected"); - return -1 ; - } - - while(length > 0) - { - unsigned count; - unsigned n; - char buf[1024]; - int c; - - flush(arg,cbinfo); - switch(arg->state) - { - case OUTSIDE_BLOCK: - /* This code returns EOF rather than EARLY_EOF because if - we don't see a header line at all, then it is just an - EOF (and not a BLOCK_END) */ - while(!arg->seen_nl) - if((c=unarmoured_read_char(arg,errors,rinfo,cbinfo,ops_true)) < 0) - return 0; - - /* flush at this point so we definitely have room for the - header, and so we can easily erase it from the buffer */ - flush(arg,cbinfo); - /* Find and consume the 5 leading '-' */ - for(count=0 ; count < 5 ; ++count) - { - if((c=unarmoured_read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0) - return 0; - if(c != '-') - goto reloop; - } - - /* Now find the block type */ - for(n=0 ; n < sizeof buf-1 ; ) - { - if((c=unarmoured_read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0) - return 0; - if(c == '-') - goto got_minus; - buf[n++]=c; - } - /* then I guess this wasn't a proper header */ - break; - -got_minus: - buf[n]='\0'; - - /* Consume trailing '-' */ - for(count=1 ; count < 5 ; ++count) - { - if((c=unarmoured_read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0) - return 0; - if(c != '-') - /* wasn't a header after all */ - goto reloop; - } - - /* Consume final NL */ - if((c=unarmoured_read_char(arg,errors,rinfo,cbinfo,ops_true)) < 0) - return 0; - if(arg->allow_trailing_whitespace) - if((c=eat_whitespace(c,arg,errors,rinfo,cbinfo, - ops_true)) < 0) - return 0; - if(c != '\n') - /* wasn't a header line after all */ - break; - - /* Now we've seen the header, scrub it from the buffer */ - arg->num_unarmoured=0; - - /* But now we've seen a header line, then errors are - EARLY_EOF */ - if((ret=parse_headers(arg,errors,rinfo,cbinfo)) <= 0) - return -1; - - if (!set_lastseen_headerline(arg,buf,errors)) - return -1; - - if(!strcmp(buf,"BEGIN PGP SIGNED MESSAGE")) - { - ops_dup_headers(&content.content.signed_cleartext_header.headers,&arg->headers); - CB(cbinfo,OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER,&content); - ret=process_dash_escaped(arg,errors,rinfo,cbinfo); - if(ret <= 0) - return ret; - } - else - { - content.content.armour_header.type=buf; - content.content.armour_header.headers=arg->headers; - memset(&arg->headers,'\0',sizeof arg->headers); - CB(cbinfo,OPS_PTAG_CT_ARMOUR_HEADER,&content); - base64(arg); - } - break; - - case BASE64: - first=ops_true; - while(length > 0) - { - if(!arg->buffered) - { - if(!arg->eof64) - { - ret=decode64(arg,errors,rinfo,cbinfo); - if(ret <= 0) - return ret; - } - if(!arg->buffered) - { - if(!(arg->eof64)) // ASSERT(arg->eof64); - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Format error"); - return -1 ; - } - if(first) - { - arg->state=AT_TRAILER_NAME; - goto reloop; - } - return -1; - } - } - - if(!(arg->buffered)) // ASSERT(arg->buffered); - { - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Format error"); - return -1 ; - } - *dest=arg->buffer[--arg->buffered]; - ++dest; - --length; - first=ops_false; - } - if(arg->eof64 && !arg->buffered) - arg->state=AT_TRAILER_NAME; - break; - - case AT_TRAILER_NAME: - for(n=0 ; n < sizeof buf-1 ; ) - { - if((c=read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0) - return -1; - if(c == '-') - goto got_minus2; - buf[n++]=c; - } - /* then I guess this wasn't a proper trailer */ - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Bad ASCII armour trailer"); - break; - -got_minus2: - buf[n]='\0'; - - if (!set_lastseen_headerline(arg,buf,errors)) - return -1; - - /* Consume trailing '-' */ - for(count=1 ; count < 5 ; ++count) - { - if((c=read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0) - return -1; - if(c != '-') - /* wasn't a trailer after all */ - OPS_ERROR(errors, OPS_E_R_BAD_FORMAT,"Bad ASCII armour trailer (2)"); - } - - /* Consume final NL */ - if((c=read_char(arg,errors,rinfo,cbinfo,ops_true)) < 0) - return -1; - if(arg->allow_trailing_whitespace) - if((c=eat_whitespace(c,arg,errors,rinfo,cbinfo, - ops_true)) < 0) - return 0; - if(c != '\n') - /* wasn't a trailer line after all */ - OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Bad ASCII armour trailer (3)"); - - if(!strncmp(buf,"BEGIN ",6)) - { - if (!set_lastseen_headerline(arg,buf,errors)) - return -1; - if((ret=parse_headers(arg,errors,rinfo,cbinfo)) <= 0) - return ret; - content.content.armour_header.type=buf; - content.content.armour_header.headers=arg->headers; - memset(&arg->headers,'\0',sizeof arg->headers); - CB(cbinfo,OPS_PTAG_CT_ARMOUR_HEADER,&content); - base64(arg); - } - else - { - content.content.armour_trailer.type=buf; - CB(cbinfo,OPS_PTAG_CT_ARMOUR_TRAILER,&content); - arg->state=OUTSIDE_BLOCK; - } - break; - } -reloop: - continue; - } - - return saved; -} - -static void armoured_data_destroyer(ops_reader_info_t *rinfo) - { free(ops_reader_get_arg(rinfo)); } - -/** - * \ingroup Core_Readers_Armour - * \brief Pushes dearmouring reader onto stack - * \param parse_info Usual structure containing information about to how to do the parse - * \sa ops_reader_pop_dearmour() - */ -void ops_reader_push_dearmour(ops_parse_info_t *parse_info) - /* - This function originally had these parameters to cater for - packets which didn't strictly match the RFC. - The initial 0.5 release is only going to support - strict checking. - If it becomes desirable to support loose checking of armoured packets - and these params are reinstated, parse_headers() must be fixed - so that these flags work correctly. - - // Allow headers in armoured data that are not separated from the data by a blank line - ops_boolean_t without_gap, - - // Allow no blank line at the start of armoured data - ops_boolean_t no_gap, - - //Allow armoured data to have trailing whitespace where we strictly would not expect it - ops_boolean_t trailing_whitespace - */ - { - dearmour_arg_t *arg; - - arg=ops_mallocz(sizeof *arg); - arg->seen_nl=ops_true; -/* - arg->allow_headers_without_gap=without_gap; - arg->allow_no_gap=no_gap; - arg->allow_trailing_whitespace=trailing_whitespace; -*/ - arg->expect_sig=ops_false; - arg->got_sig=ops_false; - - ops_reader_push(parse_info,armoured_data_reader,armoured_data_destroyer,arg); - } - -/** - * \ingroup Core_Readers_Armour - * \brief Pops dearmour reader from stock - * \param pinfo - * \sa ops_reader_push_dearmour() - */ -void ops_reader_pop_dearmour(ops_parse_info_t *pinfo) - { - dearmour_arg_t *arg=ops_reader_get_arg(ops_parse_get_rinfo(pinfo)); - free(arg); - ops_reader_pop(pinfo); - } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/reader_encrypted_se.c b/openpgpsdk/src/openpgpsdk/reader_encrypted_se.c deleted file mode 100644 index d45fa8108..000000000 --- a/openpgpsdk/src/openpgpsdk/reader_encrypted_se.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#ifndef OPENSSL_NO_IDEA -#include -#endif -#include -#include -#include "parse_local.h" - -#include -#include - -static int debug=0; - -#ifndef ATTRIBUTE_UNUSED - -#ifndef WIN32 -#define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) -#else -#define ATTRIBUTE_UNUSED -#endif // #ifndef WIN32 - -#endif /* ATTRIBUTE_UNUSED */ - - -// \todo there's also a encrypted_arg_t in adv_create.c -// which is used for *encrypting* whereas this is used -// for *decrypting* - -typedef struct - { - unsigned char decrypted[1024]; - size_t decrypted_count; - size_t decrypted_offset; - ops_crypt_t *decrypt; - ops_region_t *region; - ops_boolean_t prev_read_was_plain:1; - } encrypted_arg_t; - -static int encrypted_data_reader(void *dest,size_t length,ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo) -{ - encrypted_arg_t *arg=ops_reader_get_arg(rinfo); - int saved=length; - - // V3 MPIs have the count plain and the cipher is reset after each count - if(arg->prev_read_was_plain && !rinfo->pinfo->reading_mpi_length) - { - if(!(rinfo->pinfo->reading_v3_secret)) // ASSERT(rinfo->pinfo->reading_v3_secret); - { - fprintf(stderr,"encrypted_data_reader: Expected non null value for rinfo->pinfo->reading_v3_secret") ; - return -1 ; - } - arg->decrypt->decrypt_resync(arg->decrypt); - arg->prev_read_was_plain=ops_false; - } - else if(rinfo->pinfo->reading_v3_secret - && rinfo->pinfo->reading_mpi_length) - { - arg->prev_read_was_plain=ops_true; - } - - while(length > 0) - { - if(arg->decrypted_count) - { - - unsigned n; - - // if we are reading v3 we should never read more than - // we're asked for - if(!(length >= arg->decrypted_count || (!rinfo->pinfo->reading_v3_secret && !rinfo->pinfo->exact_read))) // ASSERT(length >= arg->decrypted_count || (!rinfo->pinfo->reading_v3_secret && !rinfo->pinfo->exact_read)); - { - fprintf(stderr,"encrypted_data_reader: inconsistency in packet sizes") ; - return -1 ; - } - - if(length > arg->decrypted_count) - n=arg->decrypted_count; - else - n=length; - - memcpy(dest,arg->decrypted+arg->decrypted_offset,n); - arg->decrypted_count-=n; - arg->decrypted_offset+=n; - length-=n; - dest+=n; - } - else - { - unsigned n=arg->region->length; - unsigned char buffer[1024]; - - if(!n) - { - return -1; - } - - if(!arg->region->indeterminate) - { - n-=arg->region->length_read; - if(n == 0) - return saved-length; - if(n > sizeof buffer) - n=sizeof buffer; - } - else - { - n=sizeof buffer; - } - - // we can only read as much as we're asked for in v3 keys - // because they're partially unencrypted! - if((rinfo->pinfo->reading_v3_secret || rinfo->pinfo->exact_read) - && n > length) - n=length; - - if(!ops_stacked_limited_read(buffer,n,arg->region,errors,rinfo, - cbinfo)) - { - return -1; - } - - if(!rinfo->pinfo->reading_v3_secret - || !rinfo->pinfo->reading_mpi_length) - { - arg->decrypted_count=ops_decrypt_se_ip(arg->decrypt, - arg->decrypted, - buffer,n); - - if (debug) - { - fprintf(stderr,"READING:\nencrypted: "); - int i=0; - for (i=0; i<16; i++) - fprintf(stderr,"%2x ", buffer[i]); - fprintf(stderr,"\n"); - fprintf(stderr,"decrypted: "); - for (i=0; i<16; i++) - fprintf(stderr,"%2x ", arg->decrypted[i]); - fprintf(stderr,"\n"); - } - } - else - { - memcpy(arg->decrypted,buffer,n); - arg->decrypted_count=n; - } - - if(!(arg->decrypted_count > 0)) // ASSERT(arg->decrypted_count > 0); - { - fprintf(stderr,"encrypted_data_reader: inconsistency in decrypted count") ; - return -1 ; - } - - arg->decrypted_offset=0; - } - } - - return saved; -} - -static void encrypted_data_destroyer(ops_reader_info_t *rinfo) - { free(ops_reader_get_arg(rinfo)); } - -/** - * \ingroup Core_Readers_SE - * \brief Pushes decryption reader onto stack - * \sa ops_reader_pop_decrypt() - */ -void ops_reader_push_decrypt(ops_parse_info_t *pinfo,ops_crypt_t *decrypt, - ops_region_t *region) - { - encrypted_arg_t *arg=ops_mallocz(sizeof *arg); - - arg->decrypt=decrypt; - arg->region=region; - - ops_decrypt_init(arg->decrypt); - - ops_reader_push(pinfo,encrypted_data_reader,encrypted_data_destroyer,arg); - } - -/** - * \ingroup Core_Readers_Encrypted - * \brief Pops decryption reader from stack - * \sa ops_reader_push_decrypt() - */ -void ops_reader_pop_decrypt(ops_parse_info_t *pinfo) - { - encrypted_arg_t *arg=ops_reader_get_arg(ops_parse_get_rinfo(pinfo)); - - arg->decrypt->decrypt_finish(arg->decrypt); - free(arg); - - ops_reader_pop(pinfo); - } - -// eof diff --git a/openpgpsdk/src/openpgpsdk/reader_encrypted_seip.c b/openpgpsdk/src/openpgpsdk/reader_encrypted_seip.c deleted file mode 100644 index 4e5251648..000000000 --- a/openpgpsdk/src/openpgpsdk/reader_encrypted_seip.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - * \brief Parser for OpenPGP packets - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "parse_local.h" - -#include -#include -#include -#ifndef WIN32 -#include -#endif -#include -#include - -#include - -static int debug=0; - -typedef struct - { - // boolean: false once we've done the preamble/MDC checks - // and are reading from the plaintext - int passed_checks; - unsigned char *plaintext; - size_t plaintext_available; - size_t plaintext_offset; - ops_region_t *region; - ops_crypt_t *decrypt; - } decrypt_se_ip_arg_t; - -static int se_ip_data_reader(void *dest_, size_t len, ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo) - { - - /* - Gets entire SE_IP data packet. - Verifies leading preamble - Verifies trailing MDC packet - Then passes up plaintext as requested - */ - - unsigned int n=0; - - ops_region_t decrypted_region; - - decrypt_se_ip_arg_t *arg=ops_reader_get_arg(rinfo); - - if (!arg->passed_checks) - { - unsigned char*buf=NULL; - - ops_hash_t hash; - unsigned char hashed[SHA_DIGEST_LENGTH]; - - size_t b; - size_t sz_preamble; - size_t sz_mdc_hash; - size_t sz_mdc; - size_t sz_plaintext; - - unsigned char* preamble; - unsigned char* plaintext; - unsigned char* mdc; - unsigned char* mdc_hash; - - ops_hash_any(&hash,OPS_HASH_SHA1); - hash.init(&hash); - - ops_init_subregion(&decrypted_region,NULL); - decrypted_region.length = arg->region->length - arg->region->length_read; - buf=ops_mallocz(decrypted_region.length); - - // read entire SE IP packet - - if (!ops_stacked_limited_read(buf,decrypted_region.length, &decrypted_region,errors,rinfo,cbinfo)) - { - free (buf); - return -1; - } - - if (debug) - { - unsigned int i=0; - fprintf(stderr,"\n\nentire SE IP packet (len=%d):\n",decrypted_region.length); - for (i=0; idecrypt->blocksize+2;i++) - fprintf(stderr," 0x%02x", buf[i]); - fprintf(stderr,"\n"); - } - - b=arg->decrypt->blocksize; - if(buf[b-2] != buf[b] || buf[b-1] != buf[b+1]) - { - fprintf(stderr,"Bad symmetric decrypt (%02x%02x vs %02x%02x)\n", - buf[b-2],buf[b-1],buf[b],buf[b+1]); - OPS_ERROR(errors, OPS_E_PROTO_BAD_SYMMETRIC_DECRYPT,"Bad symmetric decrypt when parsing SE IP packet"); - free(buf); - return -1; - } - - // Verify trailing MDC hash - - sz_preamble=arg->decrypt->blocksize+2; - sz_mdc_hash=OPS_SHA1_HASH_SIZE; - sz_mdc=1+1+sz_mdc_hash; - sz_plaintext=decrypted_region.length-sz_preamble-sz_mdc; - - preamble=buf; - plaintext=buf+sz_preamble; - mdc=plaintext+sz_plaintext; - mdc_hash=mdc+2; - -#ifdef DEBUG - if (debug) - { - unsigned int i=0; - - fprintf(stderr,"\nplaintext (len=%ld): ",sz_plaintext); - for (i=0; iplaintext) // ASSERT(!arg->plaintext); - { - fprintf(stderr,"se_ip_data_reader: consistency error\n"); - return -1 ; - } - arg->plaintext=ops_mallocz(sz_plaintext); - memcpy(arg->plaintext, plaintext, sz_plaintext); - arg->plaintext_available=sz_plaintext; - - arg->passed_checks=1; - - free(buf); - } - - n=len; - if (n > arg->plaintext_available) - n=arg->plaintext_available; - - memcpy(dest_, arg->plaintext+arg->plaintext_offset, n); - arg->plaintext_available-=n; - arg->plaintext_offset+=n; - len-=n; - - return n; - } - -static void se_ip_data_destroyer(ops_reader_info_t *rinfo) - { - decrypt_se_ip_arg_t* arg=ops_reader_get_arg(rinfo); - free (arg->plaintext); - free (arg); - // free(ops_reader_get_arg(rinfo)); - } - -/** - \ingroup Internal_Readers_SEIP -*/ -void ops_reader_push_se_ip_data(ops_parse_info_t *pinfo, ops_crypt_t *decrypt, - ops_region_t *region) - { - decrypt_se_ip_arg_t *arg=ops_mallocz(sizeof *arg); - arg->region=region; - arg->decrypt=decrypt; - - ops_reader_push(pinfo, se_ip_data_reader, se_ip_data_destroyer,arg); - } - -/** - \ingroup Internal_Readers_SEIP - */ -void ops_reader_pop_se_ip_data(ops_parse_info_t* pinfo) - { - // decrypt_se_ip_arg_t *arg=ops_reader_get_arg(ops_parse_get_rinfo(pinfo)); - // free(arg); - ops_reader_pop(pinfo); - } - -// eof diff --git a/openpgpsdk/src/openpgpsdk/reader_fd.c b/openpgpsdk/src/openpgpsdk/reader_fd.c deleted file mode 100644 index 8681c65d7..000000000 --- a/openpgpsdk/src/openpgpsdk/reader_fd.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include -#include -#include -#include -#include - -#ifndef WIN32 -#include -#endif - -#include - -#include - -/** Arguments for reader_fd - */ -typedef struct - { - int fd; /*!< file descriptor */ - } reader_fd_arg_t; - -/** - * \ingroup Core_Readers - * - * ops_reader_fd() attempts to read up to "plength" bytes from the file - * descriptor in "parse_info" into the buffer starting at "dest" using the - * rules contained in "flags" - * - * \param dest Pointer to previously allocated buffer - * \param plength Number of bytes to try to read - * \param flags Rules about reading to use - * \param parse_info Gets cast to ops_reader_fd_arg_t - * - * \return OPS_R_EOF if no bytes were read - * \return OPS_R_PARTIAL_READ if not enough bytes were read, and OPS_RETURN_LENGTH is set in "flags" - * \return OPS_R_EARLY_EOF if not enough bytes were read, and OPS_RETURN_LENGTH was not set in "flags" - * \return OPS_R_OK if expected length was read - * \return OPS_R_ERROR if cannot read - * - * OPS_R_EARLY_EOF and OPS_R_ERROR push errors on the stack - * - * \sa enum opt_reader_ret_t - * - * \todo change arg_ to typesafe? - */ -static int fd_reader(void *dest,size_t length,ops_error_t **errors, - ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo) - { - reader_fd_arg_t *arg=ops_reader_get_arg(rinfo); - int n=read(arg->fd,dest,length); - - OPS_USED(cbinfo); - - if(n == 0) - return 0; - - if(n < 0) - { - OPS_SYSTEM_ERROR_1(errors,OPS_E_R_READ_FAILED,"read", - "file descriptor %d",arg->fd); - return -1; - } - - return n; - } - -static void fd_destroyer(ops_reader_info_t *rinfo) - { free(ops_reader_get_arg(rinfo)); } - -/** - \ingroup Core_Readers_First - \brief Starts stack with file reader -*/ - -void ops_reader_set_fd(ops_parse_info_t *pinfo,int fd) - { - reader_fd_arg_t *arg=malloc(sizeof *arg); - - arg->fd=fd; - ops_reader_set(pinfo,fd_reader,fd_destroyer,arg); - } - -// eof diff --git a/openpgpsdk/src/openpgpsdk/reader_hashed.c b/openpgpsdk/src/openpgpsdk/reader_hashed.c deleted file mode 100644 index 3cc6d2bc2..000000000 --- a/openpgpsdk/src/openpgpsdk/reader_hashed.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include - -#include - -static int hash_reader(void *dest,size_t length,ops_error_t **errors, - ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo) - { - ops_hash_t *hash=ops_reader_get_arg(rinfo); - int r=ops_stacked_read(dest,length,errors,rinfo,cbinfo); - - if(r <= 0) - return r; - - hash->add(hash,dest,r); - - return r; - } - -/** - \ingroup Internal_Readers_Hash - \brief Push hashed data reader on stack -*/ -void ops_reader_push_hash(ops_parse_info_t *pinfo,ops_hash_t *hash) - { - hash->init(hash); - ops_reader_push(pinfo,hash_reader,NULL,hash); - } - -/** - \ingroup Internal_Readers_Hash - \brief Pop hashed data reader from stack -*/ -void ops_reader_pop_hash(ops_parse_info_t *pinfo) - { ops_reader_pop(pinfo); } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/reader_mem.c b/openpgpsdk/src/openpgpsdk/reader_mem.c deleted file mode 100644 index 2802673c8..000000000 --- a/openpgpsdk/src/openpgpsdk/reader_mem.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include -#include -#include -#include -#include - -#ifndef WIN32 -#include -#endif - -#include - -#include - -typedef struct - { - const unsigned char *buffer; - size_t length; - size_t offset; - } reader_mem_arg_t; - -static int mem_reader(void *dest,size_t length,ops_error_t **errors, - ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo) - { - reader_mem_arg_t *arg=ops_reader_get_arg(rinfo); - unsigned n; - - OPS_USED(cbinfo); - OPS_USED(errors); - - if(arg->offset+length > arg->length) - n=arg->length-arg->offset; - else - n=length; - - if(n == 0) - return 0; - - memcpy(dest,arg->buffer+arg->offset,n); - arg->offset+=n; - - return n; - } - -static void mem_destroyer(ops_reader_info_t *rinfo) - { free(ops_reader_get_arg(rinfo)); } - -/** - \ingroup Core_Readers_First - \brief Starts stack with memory reader -*/ - -void ops_reader_set_memory(ops_parse_info_t *pinfo,const void *buffer, - size_t length) - { - reader_mem_arg_t *arg=malloc(sizeof *arg); - - arg->buffer=buffer; - arg->length=length; - arg->offset=0; - ops_reader_set(pinfo,mem_reader,mem_destroyer,arg); - } - -/* eof */ diff --git a/openpgpsdk/src/openpgpsdk/readerwriter.c b/openpgpsdk/src/openpgpsdk/readerwriter.c deleted file mode 100644 index 78b45e28c..000000000 --- a/openpgpsdk/src/openpgpsdk/readerwriter.c +++ /dev/null @@ -1,519 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#ifndef WIN32 -#include -#include -#else -#include -#endif -#include -#include - -#include -#include -#include - -#include "parse_local.h" - -#ifdef WIN32 -#include -#include - -#define PASS_MAX 512 - -char *getpass (const char *prompt) -{ - static char getpassbuf [PASS_MAX + 1]; - size_t i = 0; - int c; - - if (prompt) { - fputs (prompt, stderr); - fflush (stderr); - } - - for (;;) { - c = _getch (); - if (c == '\r') { - getpassbuf [i] = '\0'; - break; - } - else if (i < PASS_MAX) { - getpassbuf[i++] = c; - } - - if (i >= PASS_MAX) { - getpassbuf [i] = '\0'; - break; - } - } - - if (prompt) { - fputs ("\r\n", stderr); - fflush (stderr); - } - - return getpassbuf; -} -#endif - -/** - \ingroup Core_Writers - \brief Create and initialise cinfo and mem; Set for writing to mem - \param cinfo Address where new cinfo pointer will be set - \param mem Address when new mem pointer will be set - \param bufsz Initial buffer size (will automatically be increased when necessary) - \note It is the caller's responsiblity to free cinfo and mem. - \sa ops_teardown_memory_write() -*/ -void ops_setup_memory_write(ops_create_info_t **cinfo, ops_memory_t **mem, size_t bufsz) - { - /* - * initialise needed structures for writing to memory - */ - - *cinfo=ops_create_info_new(); - *mem=ops_memory_new(); - - ops_memory_init(*mem,bufsz); - - ops_writer_set_memory(*cinfo,*mem); - } - -/** - \ingroup Core_Writers - \brief Closes writer and frees cinfo and mem - \param cinfo - \param mem - \sa ops_setup_memory_write() -*/ -void ops_teardown_memory_write(ops_create_info_t *cinfo, ops_memory_t *mem) - { - ops_writer_close(cinfo); // new - ops_create_info_delete(cinfo); - ops_memory_free(mem); - } - -/** - \ingroup Core_Readers - \brief Create parse_info and sets to read from memory - \param pinfo Address where new parse_info will be set - \param mem Memory to read from - \param arg Reader-specific arg - \param callback Callback to use with reader - \param accumulate Set if we need to accumulate as we read. (Usually false unless doing signature verification) - \note It is the caller's responsiblity to free parse_info - \sa ops_teardown_memory_read() -*/ -void ops_setup_memory_read(ops_parse_info_t **pinfo, ops_memory_t *mem, - void* arg, - ops_parse_cb_return_t callback(const ops_parser_content_t *, ops_parse_cb_info_t *), - ops_boolean_t accumulate) - { - /* - * initialise needed uctures for reading - */ - - *pinfo=ops_parse_info_new(); - ops_parse_cb_set(*pinfo,callback,arg); - ops_reader_set_memory(*pinfo, - ops_memory_get_data(mem), - ops_memory_get_length(mem)); - - if (accumulate) - (*pinfo)->rinfo.accumulate=ops_true; - } - -/** - \ingroup Core_Readers - \brief Frees pinfo and mem - \param pinfo - \param mem - \sa ops_setup_memory_read() -*/ -void ops_teardown_memory_read(ops_parse_info_t *pinfo, ops_memory_t *mem) - { - ops_parse_info_delete(pinfo); - ops_memory_free(mem); - } - -/** - \ingroup Core_Writers - \brief Create and initialise cinfo and mem; Set for writing to file - \param cinfo Address where new cinfo pointer will be set - \param filename File to write to - \param allow_overwrite Allows file to be overwritten, if set. - \return Newly-opened file descriptor - \note It is the caller's responsiblity to free cinfo and to close fd. - \sa ops_teardown_file_write() -*/ -int ops_setup_file_write(ops_create_info_t **cinfo, const char* filename, ops_boolean_t allow_overwrite) - { - int fd=0; - int flags=0; - - /* - * initialise needed structures for writing to file - */ - - flags=O_WRONLY | O_CREAT; - if (allow_overwrite==ops_true) - flags |= O_TRUNC; - else - flags |= O_EXCL; - flags |= O_BINARY; - - fd=ops_open(filename, flags, 0600); - if(fd < 0) - { - perror(filename); - return fd; - } - - *cinfo=ops_create_info_new(); - - ops_writer_set_fd(*cinfo,fd); - - return fd; - } - -/** - \ingroup Core_Writers - \brief Closes writer, frees info, closes fd - \param cinfo - \param fd -*/ -void ops_teardown_file_write(ops_create_info_t *cinfo, int fd) - { - ops_writer_close(cinfo); - close(fd); - ops_create_info_delete(cinfo); - } - -/** - \ingroup Core_Writers - \brief As ops_setup_file_write, but appends to file -*/ -int ops_setup_file_append(ops_create_info_t **cinfo, const char* filename) - { - int fd; - /* - * initialise needed structures for writing to file - */ - - fd=ops_open(filename,O_WRONLY | O_APPEND | O_BINARY | O_CREAT, 0600); - - if(fd < 0) - { - perror(filename); - return fd; - } - - *cinfo=ops_create_info_new(); - - ops_writer_set_fd(*cinfo,fd); - - return fd; - } - -/** - \ingroup Core_Writers - \brief As ops_teardown_file_write() -*/ -void ops_teardown_file_append(ops_create_info_t *cinfo, int fd) - { - ops_teardown_file_write(cinfo,fd); - } - -/** - \ingroup Core_Readers - \brief Creates parse_info, opens file, and sets to read from file - \param pinfo Address where new parse_info will be set - \param filename Name of file to read - \param arg Reader-specific arg - \param callback Callback to use when reading - \param accumulate Set if we need to accumulate as we read. (Usually false unless doing signature verification) - \note It is the caller's responsiblity to free parse_info and to close fd - \sa ops_teardown_file_read() -*/ - -int ops_setup_file_read(ops_parse_info_t **pinfo, const char *filename, - void* arg, - ops_parse_cb_return_t callback(const ops_parser_content_t *, ops_parse_cb_info_t *), - ops_boolean_t accumulate) - { - int fd=0; - /* - * initialise needed structures for reading - */ - - fd=ops_open(filename,O_RDONLY | O_BINARY, 0); - - if (fd < 0) - { - perror(filename); - return fd; - } - - *pinfo=ops_parse_info_new(); - ops_parse_cb_set(*pinfo,callback,arg); - ops_reader_set_fd(*pinfo,fd); - - if (accumulate) - (*pinfo)->rinfo.accumulate=ops_true; - - return fd; - } - -/** - \ingroup Core_Readers - \brief Frees pinfo and closes fd - \param pinfo - \param fd - \sa ops_setup_file_read() -*/ -void ops_teardown_file_read(ops_parse_info_t *pinfo, int fd) - { - close(fd); - ops_parse_info_delete(pinfo); - } - -ops_parse_cb_return_t -callback_literal_data(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo) - { - ops_parser_content_union_t* content=(ops_parser_content_union_t *)&content_->content; - - OPS_USED(cbinfo); - - // ops_print_packet(content_); - - // Read data from packet into static buffer - switch(content_->tag) - { - case OPS_PTAG_CT_LITERAL_DATA_BODY: - // if writer enabled, use it - if (cbinfo->cinfo) - { - ops_write(content->literal_data_body.data, - content->literal_data_body.length, - cbinfo->cinfo); - } - /* - ops_memory_add(mem_literal_data, - content->literal_data_body.data, - content->literal_data_body.length); - */ - break; - - case OPS_PTAG_CT_LITERAL_DATA_HEADER: - // ignore - break; - - default: - // return callback_general(content_,cbinfo); - break; - } - - return OPS_RELEASE_MEMORY; - } - -ops_parse_cb_return_t -callback_pk_session_key(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo) - { - ops_parser_content_union_t* content=(ops_parser_content_union_t *)&content_->content; - - OPS_USED(cbinfo); - - // ops_print_packet(content_); - - // Read data from packet into static buffer - switch(content_->tag) - { - case OPS_PTAG_CT_PK_SESSION_KEY: - // printf ("OPS_PTAG_CT_PK_SESSION_KEY\n"); - if(!(cbinfo->cryptinfo.keyring)) // ASSERT(cbinfo->cryptinfo.keyring); - { - fprintf(stderr,"No keyring supplied!") ; - return 0 ; - } - cbinfo->cryptinfo.keydata=ops_keyring_find_key_by_id(cbinfo->cryptinfo.keyring, - content->pk_session_key.key_id); - if(!cbinfo->cryptinfo.keydata) - break; - break; - - default: - // return callback_general(content_,cbinfo); - break; - } - - return OPS_RELEASE_MEMORY; - } - -/** - \ingroup Core_Callbacks - -\brief Callback to get secret key, decrypting if necessary. - -@verbatim - This callback does the following: - * finds the session key in the keyring - * gets a passphrase if required - * decrypts the secret key, if necessary - * sets the secret_key in the content struct -@endverbatim -*/ - -ops_parse_cb_return_t -callback_cmd_get_secret_key(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo) -{ - ops_parser_content_union_t* content=(ops_parser_content_union_t *)&content_->content; - const ops_secret_key_t *secret; - ops_parser_content_t pc; - - OPS_USED(cbinfo); - - // ops_print_packet(content_); - - switch(content_->tag) - { - case OPS_PARSER_CMD_GET_SECRET_KEY: - cbinfo->cryptinfo.keydata=ops_keyring_find_key_by_id(cbinfo->cryptinfo.keyring,content->get_secret_key.pk_session_key->key_id); - if (!cbinfo->cryptinfo.keydata || !ops_is_key_secret(cbinfo->cryptinfo.keydata)) - return 0; - - /* now get the key from the data */ - secret=ops_get_secret_key_from_data(cbinfo->cryptinfo.keydata); - int tag_to_use = OPS_PARSER_CMD_GET_SK_PASSPHRASE ; - int nbtries = 0 ; - - while( (!secret) && nbtries++ < 3) - { - if (!cbinfo->cryptinfo.passphrase) - { - cbinfo->arg = malloc(sizeof(unsigned char)) ; - *(unsigned char *)cbinfo->arg = 0 ; - - memset(&pc,'\0',sizeof pc); - pc.content.secret_key_passphrase.passphrase=&cbinfo->cryptinfo.passphrase; - CB(cbinfo,tag_to_use,&pc); - - if(*(unsigned char*)(cbinfo->arg) == 1) - { - fprintf(stderr,"passphrase cancelled\n"); - free(cbinfo->arg) ; - cbinfo->arg=NULL ; - return 0 ; // ASSERT(0); - } - if (!cbinfo->cryptinfo.passphrase) - { - free(cbinfo->arg) ; - cbinfo->arg=NULL ; - fprintf(stderr,"can't get passphrase\n"); - return 0 ; // ASSERT(0); - } - free(cbinfo->arg) ; - cbinfo->arg=NULL ; - } - /* then it must be encrypted */ - secret=ops_decrypt_secret_key_from_data(cbinfo->cryptinfo.keydata,cbinfo->cryptinfo.passphrase); - - free(cbinfo->cryptinfo.passphrase) ; - cbinfo->cryptinfo.passphrase = NULL ; - - tag_to_use = OPS_PARSER_CMD_GET_SK_PASSPHRASE_PREV_WAS_BAD ; - } - - if(!secret) - return 0 ; - - *content->get_secret_key.secret_key=secret; - break; - - default: - // return callback_general(content_,cbinfo); - break; - } - - return OPS_RELEASE_MEMORY; -} - -char *ops_get_passphrase(void) - { -#ifndef __ANDROID__ - return ops_malloc_passphrase(getpass("Passphrase: ")); -#else // __ANDROID - // We should never get here on Android, getpass not supported. - abort(); -#endif // __ANDROID__ - } - -char *ops_malloc_passphrase(char *pp) - { - char *passphrase; - size_t n; - - n=strlen(pp); - passphrase=malloc(n+1); - strncpy(passphrase,pp,n+1); - - return passphrase; - } - -/** - \ingroup HighLevel_Callbacks - \brief Callback to use when you need to prompt user for passphrase - \param content_ - \param cbinfo -*/ -ops_parse_cb_return_t -callback_cmd_get_passphrase_from_cmdline(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo) - { - ops_parser_content_union_t* content=(ops_parser_content_union_t *)&content_->content; - - OPS_USED(cbinfo); - -// ops_print_packet(content_); - - switch(content_->tag) - { - case OPS_PARSER_CMD_GET_SK_PASSPHRASE: - *(content->secret_key_passphrase.passphrase)=ops_get_passphrase(); - return OPS_KEEP_MEMORY; - break; - - default: - // return callback_general(content_,cbinfo); - break; - } - - return OPS_RELEASE_MEMORY; - } - -ops_boolean_t ops_reader_set_accumulate(ops_parse_info_t* pinfo, ops_boolean_t state) - { - pinfo->rinfo.accumulate=state; - return state; - } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/readerwriter.h b/openpgpsdk/src/openpgpsdk/readerwriter.h deleted file mode 100644 index 6961bafef..000000000 --- a/openpgpsdk/src/openpgpsdk/readerwriter.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __OPS_READERWRITER_H__ -#define __OPS_READERWRITER_H__ - -#include -#include - - -void ops_reader_set_fd(ops_parse_info_t *pinfo,int fd); -void ops_reader_set_memory(ops_parse_info_t *pinfo,const void *buffer, - size_t length); - -// Do a sum mod 65536 of all bytes read (as needed for secret keys) -void ops_reader_push_sum16(ops_parse_info_t *pinfo); -unsigned short ops_reader_pop_sum16(ops_parse_info_t *pinfo); - -void ops_reader_push_se_ip_data(ops_parse_info_t *pinfo, ops_crypt_t *decrypt, - ops_region_t *region); -void ops_reader_pop_se_ip_data(ops_parse_info_t* pinfo); - -// -ops_boolean_t ops_write_mdc(const unsigned char *hashed, - ops_create_info_t* info); -ops_boolean_t ops_write_se_ip_pktset(const unsigned char *data, - const unsigned int len, - ops_crypt_t *crypt, - ops_create_info_t *info); -void ops_writer_push_encrypt_crypt(ops_create_info_t *cinfo, - ops_crypt_t *crypt); -void ops_writer_push_encrypt_se_ip(ops_create_info_t *cinfo, - const ops_keydata_t *pub_key); -// Secret Key checksum - -void ops_push_skey_checksum_writer(ops_create_info_t *cinfo, ops_secret_key_t *skey); -ops_boolean_t ops_pop_skey_checksum_writer(ops_create_info_t *cinfo); - - -// memory writing -void ops_setup_memory_write(ops_create_info_t **cinfo, ops_memory_t **mem, size_t bufsz); -void ops_teardown_memory_write(ops_create_info_t *cinfo, ops_memory_t *mem); - -// memory reading -void ops_setup_memory_read(ops_parse_info_t **pinfo, ops_memory_t *mem, - void* arg, - ops_parse_cb_return_t callback(const ops_parser_content_t *, ops_parse_cb_info_t *),ops_boolean_t accumulate); -void ops_teardown_memory_read(ops_parse_info_t *pinfo, ops_memory_t *mem); - -// file writing -int ops_setup_file_write(ops_create_info_t **cinfo, const char* filename, ops_boolean_t allow_overwrite); -void ops_teardown_file_write(ops_create_info_t *cinfo, int fd); - -// file appending -int ops_setup_file_append(ops_create_info_t **cinfo, const char* filename); -void ops_teardown_file_append(ops_create_info_t *cinfo, int fd); - -// file reading -int ops_setup_file_read(ops_parse_info_t **pinfo, const char *filename, void* arg, - ops_parse_cb_return_t callback(const ops_parser_content_t *, ops_parse_cb_info_t *), ops_boolean_t accumulate); -void ops_teardown_file_read(ops_parse_info_t *pinfo, int fd); - -ops_boolean_t ops_reader_set_accumulate(ops_parse_info_t* pinfo, ops_boolean_t state); - -// useful callbacks -ops_parse_cb_return_t -callback_literal_data(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo); -ops_parse_cb_return_t -callback_pk_session_key(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo); -ops_parse_cb_return_t -callback_cmd_get_secret_key(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo); -ops_parse_cb_return_t -callback_cmd_get_passphrase_from_cmdline(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo); - -#endif /*OPS_READERWRITER_H__*/ diff --git a/openpgpsdk/src/openpgpsdk/signature.c b/openpgpsdk/src/openpgpsdk/signature.c deleted file mode 100644 index b62ebdb9f..000000000 --- a/openpgpsdk/src/openpgpsdk/signature.c +++ /dev/null @@ -1,1602 +0,0 @@ -/* - * Copyright (c) 2005-2009 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer, Alasdair Mackintosh. - * The Contributors have asserted their moral rights under the - * UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include - -static int debug=0; -#define MAXBUF 1024 /*info); - sig->info=NULL; - free(sig); - } - -static unsigned char prefix_md5[]={ 0x30,0x20,0x30,0x0C,0x06,0x08,0x2A,0x86, - 0x48,0x86,0xF7,0x0D,0x02,0x05,0x05,0x00, - 0x04,0x10 }; - -static unsigned char prefix_sha1[]={ 0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0E, - 0x03,0x02,0x1A,0x05,0x00,0x04,0x14 }; - -static unsigned char prefix_sha224[]={ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, - 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, - 0x00, 0x04, 0x1C }; - -static unsigned char prefix_sha256[]={ 0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86, - 0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05, - 0x00,0x04,0x20 }; - -static unsigned char prefix_sha384[]={ 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, - 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, - 0x00, 0x04, 0x30 }; - -static unsigned char prefix_sha512[]={ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, - 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, - 0x00, 0x04, 0x40 }; - -static unsigned char prefix_ripemd[]={ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, - 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; -/** - \ingroup Core_Create - implementation of EMSA-PKCS1-v1_5, as defined in OpenPGP RFC - \param M - \param mLen - \param hash_alg Hash algorithm to use - \param EM - \return ops_true if OK; else ops_false -*/ -ops_boolean_t encode_hash_buf(const unsigned char *M, size_t mLen, - const ops_hash_algorithm_t hash_alg, - unsigned char* EM) -{ - // implementation of EMSA-PKCS1-v1_5, as defined in OpenPGP RFC - - unsigned i; - int n; - ops_hash_t hash; - int hash_sz=0; - // int encoded_hash_sz=0; - int prefix_sz=0; - unsigned padding_sz=0; - unsigned encoded_msg_sz=0; - unsigned char* prefix=NULL; - - if(hash_alg != OPS_HASH_SHA1) - { - fprintf(stderr,"encode_hash_buf: unsupported hash algorithm %x. Sorry.",hash_alg) ; - return ops_false ; - } - - // 1. Apply hash function to M - - ops_hash_any(&hash, hash_alg); - hash.init(&hash); - hash.add(&hash, M, mLen); - - // \todo combine with rsa_sign - - // 2. Get hash prefix - - switch(hash_alg) - { - case OPS_HASH_SHA1: - prefix=prefix_sha1; - prefix_sz=sizeof prefix_sha1; - hash_sz=OPS_SHA1_HASH_SIZE; - // encoded_hash_sz=hash_sz+prefix_sz; - // \todo why is Ben using a PS size of 90 in rsa_sign? - // (keysize-hashsize-1-2) - padding_sz=90; - break; - - default: - return ops_false ; // according to the test at start, this should never happen, so no error handling is necessary. - } - - // \todo 3. Test for len being too short - - // 4 and 5. Generate PS and EM - - EM[0]=0x00; - EM[1]=0x01; - - for (i=0; ialgorithm) - { - case OPS_HASH_SHA1: hashsize=OPS_SHA1_HASH_SIZE+sizeof prefix_sha1; - hash_length=OPS_SHA1_HASH_SIZE ; - prefix = prefix_sha1; - plen = sizeof prefix_sha1 ; - break ; - - case OPS_HASH_SHA224: hashsize=OPS_SHA224_HASH_SIZE+sizeof prefix_sha224; - hash_length=OPS_SHA224_HASH_SIZE ; - prefix = prefix_sha224; - plen = sizeof prefix_sha224 ; - break ; - - case OPS_HASH_SHA256: hashsize=OPS_SHA256_HASH_SIZE+sizeof prefix_sha256; - hash_length=OPS_SHA256_HASH_SIZE ; - prefix = prefix_sha256; - plen = sizeof prefix_sha256 ; - break ; - - case OPS_HASH_SHA384: hashsize=OPS_SHA384_HASH_SIZE+sizeof prefix_sha384; - hash_length=OPS_SHA384_HASH_SIZE ; - prefix = prefix_sha384; - plen = sizeof prefix_sha384 ; - break ; - - case OPS_HASH_SHA512: hashsize=OPS_SHA512_HASH_SIZE+sizeof prefix_sha512; - hash_length=OPS_SHA512_HASH_SIZE ; - prefix = prefix_sha512; - plen = sizeof prefix_sha512 ; - break ; - - case OPS_HASH_MD5: fprintf(stderr,"(insecure) MD5+RSA signatures not supported in RSA sign") ; - return ops_false ; - - default: fprintf(stderr,"Hash algorithm %d not supported in RSA sign",hash->algorithm) ; - return ops_false ; - } - // XXX: we assume hash is sha-1 for now - - keysize=BN_num_bytes(rsa->n); - - if(keysize > sizeof hashbuf) - { - fprintf(stderr,"Keysize too large. limit is %lu, size was %u",sizeof(hashbuf), keysize) ; - return ops_false ; - } - if(10+hashsize > keysize) - { - fprintf(stderr,"10+hashsize > keysize. Can't sign!") ; - return ops_false ; - } - - hashbuf[0]=0; - hashbuf[1]=1; - if (debug) - printf("rsa_sign: PS is %d\n", keysize-hashsize-1-2); - for(n=2 ; n < keysize-hashsize-1 ; ++n) - hashbuf[n]=0xff; - hashbuf[n++]=0; - - memcpy(&hashbuf[n], prefix, plen); - n+=plen; - - t=hash->finish(hash, &hashbuf[n]); - - if(t != hash_length) - { - fprintf(stderr,"Wrong hash size. Should be 20! can't sign.") ; - return ops_false ; - } - - ops_write(&hashbuf[n], 2, opt); - - n+=t; - - if(n != keysize) - { - fprintf(stderr,"Size error in hashed data. can't sign.") ; - return ops_false ; - } - - t=ops_rsa_private_encrypt(sigbuf, hashbuf, keysize, srsa, rsa); - bn=BN_bin2bn(sigbuf, t, NULL); - ops_write_mpi(bn, opt); - BN_free(bn); - - return ops_true ; -} - -static ops_boolean_t dsa_sign(ops_hash_t *hash, const ops_dsa_public_key_t *dsa, - const ops_dsa_secret_key_t *sdsa, ops_create_info_t *cinfo) -{ - unsigned char hashbuf[8192]; - unsigned hashsize; - unsigned t; - - // hashsize must be "equal in size to the number of bits of q, - // the group generated by the DSA key's generator value - // 160/8 = 20 - - hashsize=20; - - // finalise hash - t=hash->finish(hash, &hashbuf[0]); - - if(t != 20) - { - fprintf(stderr,"Wrong hash size. Should be 20! can't sign.") ; - return ops_false ; - } - - ops_write(&hashbuf[0], 2, cinfo); - - // write signature to buf - DSA_SIG* dsasig; - dsasig=ops_dsa_sign(hashbuf, hashsize, sdsa, dsa); - - // convert and write the sig out to memory -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - ops_write_mpi(dsasig->r, cinfo); - ops_write_mpi(dsasig->s, cinfo); -#else - const BIGNUM *rr=NULL,*ss=NULL ; - - DSA_SIG_get0(dsasig,&rr,&ss) ; - - ops_write_mpi(rr, cinfo); - ops_write_mpi(ss, cinfo); -#endif - - DSA_SIG_free(dsasig); - - return ops_true ; -} - -static ops_boolean_t rsa_verify(ops_hash_algorithm_t type, - const unsigned char *hash, size_t hash_length, - const ops_rsa_signature_t *sig, - const ops_rsa_public_key_t *rsa) -{ - unsigned char sigbuf[8192]; - unsigned char hashbuf_from_sig[8192]; - unsigned n; - unsigned keysize; - unsigned char *prefix; - int plen; - - keysize=BN_num_bytes(rsa->n); - /* RSA key can't be bigger than 65535 bits, so... */ - - if(keysize > sizeof hashbuf_from_sig) - { - fprintf(stderr,"Can't verify signature: keysize too big.") ; - return ops_false ; - } - if((unsigned)BN_num_bits(sig->sig) > 8*sizeof sigbuf) - { - fprintf(stderr,"Can't verify signature: signature too big.") ; - return ops_false ; - } - BN_bn2bin(sig->sig, sigbuf); - - n=ops_rsa_public_decrypt(hashbuf_from_sig, sigbuf, BN_num_bytes(sig->sig), rsa); - int debug_len_decrypted=n; - - if(n != keysize) // obviously, this includes error returns - return ops_false; - - // XXX: why is there a leading 0? The first byte should be 1... - // XXX: because the decrypt should use keysize and not sigsize? - if(hashbuf_from_sig[0] != 0 || hashbuf_from_sig[1] != 1) - return ops_false; - - switch(type) - { - case OPS_HASH_MD5 : prefix=prefix_md5 ; plen=sizeof prefix_md5; break; - case OPS_HASH_SHA1 : prefix=prefix_sha1 ; plen=sizeof prefix_sha1; break; - case OPS_HASH_SHA224 : prefix=prefix_sha224 ; plen=sizeof prefix_sha224; break; - case OPS_HASH_SHA256 : prefix=prefix_sha256 ; plen=sizeof prefix_sha256; break; - case OPS_HASH_SHA384 : prefix=prefix_sha384 ; plen=sizeof prefix_sha384; break; - case OPS_HASH_SHA512 : prefix=prefix_sha512 ; plen=sizeof prefix_sha512; break; - case OPS_HASH_RIPEMD : prefix=prefix_ripemd ; plen=sizeof prefix_ripemd; break; - - default: - fprintf(stderr,"Warning: unhandled hash type in signature verification code: %d\n",type) ; - return ops_false ; - } - - if(keysize-plen-hash_length < 10) - return ops_false; - - for(n=2 ; n < keysize-plen-hash_length-1 ; ++n) - if(hashbuf_from_sig[n] != 0xff) - return ops_false; - - if(hashbuf_from_sig[n++] != 0) - return ops_false; - - if (debug) - { - int zz; - - printf("\n"); - printf("hashbuf_from_sig\n"); - for (zz=0; zzadd(hash, ops_memory_get_data(mem), l); - - ops_memory_free(mem); - } - -static void initialise_hash(ops_hash_t *hash, const ops_signature_t *sig) - { - ops_hash_any(hash, sig->info.hash_algorithm); - hash->init(hash); - } - -static void init_key_signature(ops_hash_t *hash, const ops_signature_t *sig, - const ops_public_key_t *key) - { - initialise_hash(hash, sig); - hash_add_key(hash, key); - } - -static void hash_add_trailer(ops_hash_t *hash, const ops_signature_t *sig, - const unsigned char *raw_packet) - { - if(sig->info.version == OPS_V4) - { - if(raw_packet) - hash->add(hash, raw_packet+sig->v4_hashed_data_start, - sig->info.v4_hashed_data_length); - ops_hash_add_int(hash, sig->info.version, 1); - ops_hash_add_int(hash, 0xff, 1); - ops_hash_add_int(hash, sig->info.v4_hashed_data_length, 4); - } - else - { - ops_hash_add_int(hash, sig->info.type, 1); - ops_hash_add_int(hash, sig->info.creation_time, 4); - } - } - -/** - \ingroup Core_Signature - \brief Checks a signature - \param hash Signature Hash to be checked - \param length Signature Length - \param sig The Signature to be checked - \param signer The signer's public key - \return ops_true if good; else ops_false -*/ -ops_boolean_t ops_check_signature(const unsigned char *hash, unsigned length, - const ops_signature_t *sig, - const ops_public_key_t *signer) -{ - ops_boolean_t ret; - - /* - printf(" hash="); - // hashout[0]=0; - hexdump(hash,length); - */ - - switch(sig->info.key_algorithm) - { - case OPS_PKA_DSA: - ret=ops_dsa_verify(hash, length, &sig->info.signature.dsa, - &signer->key.dsa); - /* fprintf(stderr,"Cannot verify DSA signature. skipping.\n") ; - ret = ops_false ; */ - break; - - case OPS_PKA_RSA: - ret=rsa_verify(sig->info.hash_algorithm, hash, length, - &sig->info.signature.rsa, &signer->key.rsa); - break; - - default: - fprintf(stderr,"Cannot verify signature. Unknown key signing algorithm %d. skipping.\n",sig->info.key_algorithm) ; - ret = ops_false ; - - } - - return ret; -} - -static ops_boolean_t hash_and_check_signature(ops_hash_t *hash, - const ops_signature_t *sig, - const ops_public_key_t *signer) - { - int n; - unsigned char hashout[OPS_MAX_HASH_SIZE]; - - n=hash->finish(hash, hashout); - - return ops_check_signature(hashout, n, sig, signer); - } - -static ops_boolean_t finalise_signature(ops_hash_t *hash, - const ops_signature_t *sig, - const ops_public_key_t *signer, - const unsigned char *raw_packet) - { - hash_add_trailer(hash, sig, raw_packet); - return hash_and_check_signature(hash, sig, signer); - } - -/** - * \ingroup Core_Signature - * - * \brief Verify a certification signature. - * - * \param key The public key that was signed. - * \param id The user ID that was signed - * \param sig The signature. - * \param signer The public key of the signer. - * \param raw_packet The raw signature packet. - * \return ops_true if OK; else ops_false - */ -ops_boolean_t -ops_check_user_id_certification_signature(const ops_public_key_t *key, - const ops_user_id_t *id, - const ops_signature_t *sig, - const ops_public_key_t *signer, - const unsigned char *raw_packet) - { - ops_hash_t hash; - size_t user_id_len=strlen((char *)id->user_id); - - init_key_signature(&hash, sig, key); - - if(sig->info.version == OPS_V4) - { - ops_hash_add_int(&hash, 0xb4, 1); - ops_hash_add_int(&hash, user_id_len, 4); - } - hash.add(&hash, id->user_id, user_id_len); - - return finalise_signature(&hash, sig, signer, raw_packet); - } - -/** - * \ingroup Core_Signature - * - * Verify a certification signature. - * - * \param key The public key that was signed. - * \param attribute The user attribute that was signed - * \param sig The signature. - * \param signer The public key of the signer. - * \param raw_packet The raw signature packet. - * \return ops_true if OK; else ops_false - */ -ops_boolean_t -ops_check_user_attribute_certification_signature(const ops_public_key_t *key, - const ops_user_attribute_t *attribute, - const ops_signature_t *sig, - const ops_public_key_t *signer, - const unsigned char *raw_packet) - { - ops_hash_t hash; - - init_key_signature(&hash, sig, key); - - if(sig->info.version == OPS_V4) - { - ops_hash_add_int(&hash, 0xd1, 1); - ops_hash_add_int(&hash, attribute->data.len, 4); - } - hash.add(&hash, attribute->data.contents, attribute->data.len); - - return finalise_signature(&hash, sig, signer, raw_packet); - } - -/** - * \ingroup Core_Signature - * - * Verify a subkey signature. - * - * \param key The public key whose subkey was signed. - * \param subkey The subkey of the public key that was signed. - * \param sig The signature. - * \param signer The public key of the signer. - * \param raw_packet The raw signature packet. - * \return ops_true if OK; else ops_false - */ -ops_boolean_t -ops_check_subkey_signature(const ops_public_key_t *key, - const ops_public_key_t *subkey, - const ops_signature_t *sig, - const ops_public_key_t *signer, - const unsigned char *raw_packet) - { - ops_hash_t hash; - - init_key_signature(&hash, sig, key); - hash_add_key(&hash, subkey); - - return finalise_signature(&hash, sig, signer, raw_packet); - } - -/** - * \ingroup Core_Signature - * - * Verify a direct signature. - * - * \param key The public key which was signed. - * \param sig The signature. - * \param signer The public key of the signer. - * \param raw_packet The raw signature packet. - * \return ops_true if OK; else ops_false - */ -ops_boolean_t -ops_check_direct_signature(const ops_public_key_t *key, - const ops_signature_t *sig, - const ops_public_key_t *signer, - const unsigned char *raw_packet) - { - ops_hash_t hash; - - init_key_signature(&hash, sig, key); - return finalise_signature(&hash, sig, signer, raw_packet); - } - -/** - * \ingroup Core_Signature - * - * Verify a signature on a hash (the hash will have already been fed - * the material that was being signed, for example signed cleartext). - * - * \param hash A hash structure of appropriate type that has been fed - * the material to be signed. This MUST NOT have been finalised. - * \param sig The signature to be verified. - * \param signer The public key of the signer. - * \return ops_true if OK; else ops_false - */ -ops_boolean_t -ops_check_hash_signature(ops_hash_t *hash, const ops_signature_t *sig, - const ops_public_key_t *signer) - { - if(sig->info.hash_algorithm != hash->algorithm) - return ops_false; - - return finalise_signature(hash, sig, signer, NULL); - } - -static void start_signature_in_mem(ops_create_signature_t *sig) - { - // since this has subpackets and stuff, we have to buffer the whole - // thing to get counts before writing. - sig->mem=ops_memory_new(); - ops_memory_init(sig->mem, 100); - ops_writer_set_memory(sig->info, sig->mem); - - // write nearly up to the first subpacket - ops_write_scalar(sig->sig.info.version, 1, sig->info); - ops_write_scalar(sig->sig.info.type, 1, sig->info); - ops_write_scalar(sig->sig.info.key_algorithm, 1, sig->info); - ops_write_scalar(sig->sig.info.hash_algorithm, 1, sig->info); - - // dummy hashed subpacket count - sig->hashed_count_offset=ops_memory_get_length(sig->mem); - ops_write_scalar(0, 2, sig->info); - } - -/** - * \ingroup Core_Signature - * - * ops_signature_start() creates a V4 public key signature with a SHA1 hash. - * - * \param sig The signature structure to initialise - * \param key The public key to be signed - * \param id The user ID being bound to the key - * \param type Signature type - */ -void ops_signature_start_key_signature(ops_create_signature_t *sig, - const ops_public_key_t *key, - const ops_user_id_t *id, - ops_sig_type_t type) - { - sig->info=ops_create_info_new(); - - // XXX: refactor with check (in several ways - check should probably - // use the buffered writer to construct packets (done), and also should - // share code for hash calculation) - sig->sig.info.version=OPS_V4; - sig->sig.info.hash_algorithm=OPS_HASH_SHA1; - sig->sig.info.key_algorithm=key->algorithm; - sig->sig.info.type=type; - - sig->hashed_data_length=-1; - - init_key_signature(&sig->hash, &sig->sig, key); - - ops_hash_add_int(&sig->hash, 0xb4, 1); - ops_hash_add_int(&sig->hash, strlen((char *)id->user_id), 4); - sig->hash.add(&sig->hash, id->user_id, strlen((char *)id->user_id)); - - start_signature_in_mem(sig); - } - -/** - * \ingroup Core_Signature - * - * Create a V4 public key signature over some cleartext. - * - * \param sig The signature structure to initialise - * \param id - * \param type - * \todo Expand description. Allow other hashes. - */ - -static void ops_signature_start_signature(ops_create_signature_t *sig, - const ops_secret_key_t *key, - const ops_hash_algorithm_t hash, - const ops_sig_type_t type) - { - sig->info=ops_create_info_new(); - - // XXX: refactor with check (in several ways - check should probably - // use the buffered writer to construct packets (done), and also should - // share code for hash calculation) - sig->sig.info.version=OPS_V4; - sig->sig.info.key_algorithm=key->public_key.algorithm; - sig->sig.info.hash_algorithm=hash; - sig->sig.info.type=type; - - sig->hashed_data_length=-1; - - if (debug) - { fprintf(stderr, "initialising hash for sig in mem\n"); } - initialise_hash(&sig->hash, &sig->sig); - start_signature_in_mem(sig); - } - -/** - * \ingroup Core_Signature - * \brief Setup to start a cleartext's signature - */ -void ops_signature_start_cleartext_signature(ops_create_signature_t *sig, - const ops_secret_key_t *key, - const ops_hash_algorithm_t hash, - const ops_sig_type_t type) - { - ops_signature_start_signature(sig, key, hash, type); - } - -/** - * \ingroup Core_Signature - * \brief Setup to start a message's signature - */ -void ops_signature_start_message_signature(ops_create_signature_t *sig, - const ops_secret_key_t *key, - const ops_hash_algorithm_t hash, - const ops_sig_type_t type) - { - ops_signature_start_signature(sig, key, hash, type); - } - -/** - * \ingroup Core_Signature - * - * Add plaintext data to a signature-to-be. - * - * \param sig The signature-to-be. - * \param buf The plaintext data. - * \param length The amount of plaintext data. - */ -void ops_signature_add_data(ops_create_signature_t *sig, const void *buf, - size_t length) - { - if (debug) - { fprintf(stderr, "ops_signature_add_data adds to hash\n"); } - sig->hash.add(&sig->hash, buf, length); - } - -/** - * \ingroup Core_Signature - * - * Mark the end of the hashed subpackets in the signature - * - * \param sig - */ - -ops_boolean_t ops_signature_hashed_subpackets_end(ops_create_signature_t *sig) - { - sig->hashed_data_length=ops_memory_get_length(sig->mem) - -sig->hashed_count_offset-2; - ops_memory_place_int(sig->mem, sig->hashed_count_offset, - sig->hashed_data_length, 2); - // dummy unhashed subpacket count - sig->unhashed_count_offset=ops_memory_get_length(sig->mem); - return ops_write_scalar(0, 2, sig->info); - } - -/** - * \ingroup Core_Signature - * - * Write out a signature - * - * \param sig - * \param key - * \param skey - * \param info - * - */ - -ops_boolean_t ops_write_signature(ops_create_signature_t *sig, - const ops_public_key_t *key, - const ops_secret_key_t *skey, - ops_create_info_t *info) -{ - ops_boolean_t rtn=ops_false; - size_t l=ops_memory_get_length(sig->mem); - - // check key not decrypted - switch (skey->public_key.algorithm) - { - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: - if(skey->key.rsa.d == NULL) - { - fprintf(stderr, "Malformed secret key when signing (rsa.d = 0). Can't sign.\n") ; - return ops_false ; - } - break; - - case OPS_PKA_DSA: - if(skey->key.dsa.x == NULL) - { - fprintf(stderr, "Malformed secret key when signing (dsa.x = 0). Can't sign.\n") ; - return ops_false ; - } - break; - - default: - fprintf(stderr, "Unsupported algorithm %d when signing. Sorry.\n", skey->public_key.algorithm); - return ops_false ; - } - - if(sig->hashed_data_length == (unsigned)-1) - { - fprintf(stderr, "Hashed data not initialized properly when signing. Sorry.\n") ; - return ops_false ; - } - - ops_memory_place_int(sig->mem, sig->unhashed_count_offset, - l-sig->unhashed_count_offset-2, 2); - - // add the packet from version number to end of hashed subpackets - - if (debug) - { fprintf(stderr, "--- Adding packet to hash from version number to" - " hashed subpkts\n"); } - - sig->hash.add(&sig->hash, ops_memory_get_data(sig->mem), - sig->unhashed_count_offset); - - // add final trailer - ops_hash_add_int(&sig->hash, sig->sig.info.version, 1); - ops_hash_add_int(&sig->hash, 0xff, 1); - // +6 for version, type, pk alg, hash alg, hashed subpacket length - ops_hash_add_int(&sig->hash, sig->hashed_data_length+6, 4); - - if (debug) - { fprintf(stderr, "--- Finished adding packet to hash from version" - " number to hashed subpkts\n"); } - - // XXX: technically, we could figure out how big the signature is - // and write it directly to the output instead of via memory. - switch(skey->public_key.algorithm) - { - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: - if(!rsa_sign(&sig->hash, &key->key.rsa, &skey->key.rsa, sig->info)) - { - fprintf(stderr, "error in rsa_sign. Can't produce signature\n") ; - return ops_false; - } - break; - - case OPS_PKA_DSA: - if(!dsa_sign(&sig->hash, &key->key.dsa, &skey->key.dsa, sig->info)) - { - fprintf(stderr, "error in dsa_sign. Can't produce signature\n") ; - return ops_false; - } - break; - - default: - fprintf(stderr, "Unsupported algorithm %d in signature\n", skey->public_key.algorithm); - return ops_false ; - } - - rtn=ops_write_ptag(OPS_PTAG_CT_SIGNATURE, info); - if (rtn) - { - l=ops_memory_get_length(sig->mem); - rtn = ops_write_length(l, info) - && ops_write(ops_memory_get_data(sig->mem), l, info); - } - - ops_memory_free(sig->mem); - - if (!rtn) - OPS_ERROR(&info->errors, OPS_E_W, "Cannot write signature"); - return rtn; -} - -/** - * \ingroup Core_Signature - * - * ops_signature_add_creation_time() adds a creation time to the signature. - * - * \param sig - * \param when - */ -ops_boolean_t ops_signature_add_creation_time(ops_create_signature_t *sig, - time_t when) - { - return ops_write_ss_header(5, OPS_PTAG_SS_CREATION_TIME, sig->info) - && ops_write_scalar(when, 4, sig->info); - } - -/** - * \ingroup Core_Signature - * - * Adds issuer's key ID to the signature - * - * \param sig - * \param keyid - */ - -ops_boolean_t -ops_signature_add_issuer_key_id(ops_create_signature_t *sig, - const unsigned char keyid[OPS_KEY_ID_SIZE]) - { - return ops_write_ss_header(OPS_KEY_ID_SIZE+1, OPS_PTAG_SS_ISSUER_KEY_ID, - sig->info) - && ops_write(keyid, OPS_KEY_ID_SIZE, sig->info); - } - -/** - * \ingroup Core_Signature - * - * Adds primary user ID to the signature - * - * \param sig - * \param primary - */ -void ops_signature_add_primary_user_id(ops_create_signature_t *sig, - ops_boolean_t primary) - { - ops_write_ss_header(2, OPS_PTAG_SS_PRIMARY_USER_ID, sig->info); - ops_write_scalar(primary, 1, sig->info); - } - -/** - * \ingroup Core_Signature - * - * Get the hash structure in use for the signature. - * - * \param sig The signature structure. - * \return The hash structure. - */ -ops_hash_t *ops_signature_get_hash(ops_create_signature_t *sig) - { return &sig->hash; } - -static int open_output_file(ops_create_info_t **cinfo, - const char* input_filename, - const char* output_filename, - const ops_boolean_t use_armour, - const ops_boolean_t overwrite) - { - int fd_out; - - // setup output file - - if (output_filename) - fd_out=ops_setup_file_write(cinfo, output_filename, overwrite); - else - { - char *myfilename=NULL; - unsigned filenamelen=strlen(input_filename)+4+1; - myfilename=ops_mallocz(filenamelen); - if (use_armour) - snprintf(myfilename, filenamelen, "%s.asc", input_filename); - else - snprintf(myfilename, filenamelen, "%s.gpg", input_filename); - fd_out=ops_setup_file_write(cinfo, myfilename, overwrite); - free(myfilename); - } - - return fd_out; - } - -/** - \ingroup HighLevel_Sign - \brief Sign a file with a Cleartext Signature - \param input_filename Name of file to be signed - \param output_filename Filename to be created. If NULL, filename will be constructed from the input_filename. - \param skey Secret Key to sign with - \param overwrite Allow output file to be overwritten, if set - \return ops_true if OK, else ops_false - - Example code: - \code - void example(const ops_secret_key_t *skey, ops_boolean_t overwrite) - { - if (ops_sign_file_as_cleartext("mytestfile.txt",NULL,skey,overwrite)==ops_true) - printf("OK"); - else - printf("ERR"); - } - \endcode -*/ -ops_boolean_t ops_sign_file_as_cleartext(const char* input_filename, - const char* output_filename, - const ops_secret_key_t *skey, - const ops_boolean_t overwrite) -{ - // \todo allow choice of hash algorithams - // enforce use of SHA1 for now - - unsigned char keyid[OPS_KEY_ID_SIZE]; - ops_create_signature_t *sig=NULL; - - int fd_in=0; - int fd_out=0; - ops_create_info_t *cinfo=NULL; - unsigned char buf[MAXBUF]; - //int flags=0; - ops_boolean_t rtn=ops_false; - ops_boolean_t use_armour=ops_true; - - // open file to sign - - fd_in=ops_open(input_filename, O_RDONLY | O_BINARY, 0); - - if(fd_in < 0) - { - return ops_false; - } - - // set up output file - - fd_out=open_output_file(&cinfo, input_filename, output_filename, use_armour, - overwrite); - - if (fd_out < 0) - { - close(fd_in); - return ops_false; - } - - // set up signature - sig=ops_create_signature_new(); - if (!sig) - { - close (fd_in); - ops_teardown_file_write(cinfo, fd_out); - return ops_false; - } - - // \todo could add more error detection here - ops_signature_start_cleartext_signature(sig, skey, OPS_HASH_SHA1, OPS_SIG_BINARY); - - if (!ops_writer_push_clearsigned(cinfo, sig)) - return ops_false; - - // Do the signing - - for (;;) - { - int n=0; - - n=read(fd_in, buf, sizeof(buf)); - if (!n) - break; - - if(n < 0) - { - fprintf(stderr, "Read error in ops_sign_file_as_cleartext\n"); - close(fd_in) ; - ops_teardown_file_write(cinfo, fd_out); - return ops_false ; - } - ops_write(buf, n, cinfo); - } - close(fd_in); - - // add signature with subpackets: - // - creation time - // - key id - rtn = ops_writer_switch_to_armoured_signature(cinfo) - && ops_signature_add_creation_time(sig, time(NULL)); - - if (!rtn) - { - ops_teardown_file_write(cinfo, fd_out); - return ops_false; - } - - ops_keyid(keyid, &skey->public_key); - - rtn = ops_signature_add_issuer_key_id(sig, keyid) - && ops_signature_hashed_subpackets_end(sig) - && ops_write_signature(sig, &skey->public_key, skey, cinfo); - - if (!rtn) - OPS_ERROR(&cinfo->errors, OPS_E_W, "Cannot sign file as cleartext"); - - // we can't get errors in cinfo->errors while closing - // because ops_teardown_file_write frees everything - // it seems that writer finalisers do not report errors anyway - // and ops_teardown_file_write does not have an return value, so we could not bubble something up - ops_teardown_file_write(cinfo, fd_out); - - return rtn; -} - - -/** - * \ingroup HighLevel_Sign - * \brief Sign a buffer with a Cleartext signature - * \param cleartext Text to be signed - * \param len Length of text - * \param signed_cleartext ops_memory_t struct in which to write the signed cleartext - * \param skey Secret key with which to sign the cleartext - * \return ops_true if OK; else ops_false - - * \note It is the calling function's responsibility to free signed_cleartext - * \note signed_cleartext should be a NULL pointer when passed in - - Example code: - \code - void example(const ops_secret_key_t *skey) - { - ops_memory_t* mem=NULL; - const char* buf="Some example text"; - size_t len=strlen(buf); - if (ops_sign_buf_as_cleartext(buf,len, &mem, skey)==ops_true) - printf("OK"); - else - printf("ERR"); - // free signed cleartext after use - ops_memory_free(mem); - } - \endcode - */ -ops_boolean_t ops_sign_buf_as_cleartext(const char* cleartext, const size_t len, - ops_memory_t** signed_cleartext, - const ops_secret_key_t *skey) -{ - ops_boolean_t rtn=ops_false; - - // \todo allow choice of hash algorithams - // enforce use of SHA1 for now - - unsigned char keyid[OPS_KEY_ID_SIZE]; - ops_create_signature_t *sig=NULL; - - ops_create_info_t *cinfo=NULL; - - if(*signed_cleartext != NULL) - { - fprintf(stderr,"ops_sign_buf_as_cleartext: error. Variable signed_cleartext should point to NULL.\n") ; - return ops_false ; - } - - // set up signature - sig=ops_create_signature_new(); - if (!sig) - return ops_false; - - // \todo could add more error detection here - ops_signature_start_cleartext_signature(sig, skey, OPS_HASH_SHA1, OPS_SIG_BINARY); - - // set up output file - ops_setup_memory_write(&cinfo, signed_cleartext, len); - - // Do the signing - // add signature with subpackets: - // - creation time - // - key id - rtn = ops_writer_push_clearsigned(cinfo, sig) - && ops_write(cleartext, len, cinfo) - && ops_writer_switch_to_armoured_signature(cinfo) - && ops_signature_add_creation_time(sig, time(NULL)); - - if (!rtn) - return ops_false; - - ops_keyid(keyid, &skey->public_key); - - rtn = ops_signature_add_issuer_key_id(sig, keyid) - && ops_signature_hashed_subpackets_end(sig) - && ops_write_signature(sig, &skey->public_key, skey, cinfo) - && ops_writer_close(cinfo); - - // Note: the calling function must free signed_cleartext - ops_create_info_delete(cinfo); - - return rtn; -} - -/** -\ingroup HighLevel_Sign -\brief Sign a file -\param input_filename Input filename -\param output_filename Output filename. If NULL, a name is constructed from the input filename. -\param skey Secret Key to use for signing -\param use_armour Write armoured text, if set. -\param overwrite May overwrite existing file, if set. -\return ops_true if OK; else ops_false; - -Example code: -\code -void example(const ops_secret_key_t *skey) -{ - const char* filename="mytestfile"; - const ops_boolean_t use_armour=ops_false; - const ops_boolean_t overwrite=ops_false; - if (ops_sign_file(filename, NULL, skey, use_armour, overwrite)==ops_true) - printf("OK"); - else - printf("ERR"); -} -\endcode -*/ -ops_boolean_t ops_sign_file(const char* input_filename, - const char* output_filename, - const ops_secret_key_t *skey, - const ops_boolean_t use_armour, - const ops_boolean_t overwrite) - { - // \todo allow choice of hash algorithams - // enforce use of SHA1 for now - - unsigned char keyid[OPS_KEY_ID_SIZE]; - ops_create_signature_t *sig=NULL; - - int fd_out=0; - ops_create_info_t *cinfo=NULL; - - ops_hash_algorithm_t hash_alg=OPS_HASH_SHA1; - ops_sig_type_t sig_type=OPS_SIG_BINARY; - - ops_memory_t* mem_buf=NULL; - ops_hash_t* hash=NULL; - - // read input file into buf - - int errnum; - mem_buf=ops_write_mem_from_file(input_filename, &errnum); - if (errnum) - return ops_false; - - // setup output file - - fd_out=open_output_file(&cinfo, input_filename, output_filename, use_armour, - overwrite); - - if (fd_out < 0) - { - ops_memory_free(mem_buf); - return ops_false; - } - - // set up signature - sig=ops_create_signature_new(); - ops_signature_start_message_signature(sig, skey, hash_alg, sig_type); - - // set armoured/not armoured here - if (use_armour) - ops_writer_push_armoured_message(cinfo); - - if (debug) - { fprintf(stderr, "** Writing out one pass sig\n"); } - - // write one_pass_sig - ops_write_one_pass_sig(skey, hash_alg, sig_type, cinfo); - - // hash file contents - hash=ops_signature_get_hash(sig); - hash->add(hash, ops_memory_get_data(mem_buf), - ops_memory_get_length(mem_buf)); - - // output file contents as Literal Data packet - - if (debug) - fprintf(stderr,"** Writing out data now\n"); - - ops_write_literal_data_from_buf(ops_memory_get_data(mem_buf), - ops_memory_get_length(mem_buf), - OPS_LDT_BINARY, cinfo); - - if (debug) - fprintf(stderr, "** After Writing out data now\n"); - - // add subpackets to signature - // - creation time - // - key id - - ops_signature_add_creation_time(sig, time(NULL)); - - ops_keyid(keyid, &skey->public_key); - ops_signature_add_issuer_key_id(sig, keyid); - - ops_signature_hashed_subpackets_end(sig); - - // write out sig - ops_write_signature(sig, &skey->public_key, skey, cinfo); - - ops_teardown_file_write(cinfo, fd_out); - - // tidy up - ops_create_signature_delete(sig); - ops_memory_free(mem_buf); - - return ops_true; - } - -/** -\ingroup HighLevel_Sign -\brief Signs a buffer -\param input Input text to be signed -\param input_len Length of input text -\param sig_type Signature type -\param skey Secret Key -\param use_armour Write armoured text, if set -\param include_data Includes the signed data in the output message. If not, creates a detached signature. -\return New ops_memory_t struct containing signed text -\note It is the caller's responsibility to call ops_memory_free(me) - -Example Code: -\code -void example(const ops_secret_key_t *skey) -{ - const char* buf="Some example text"; - const size_t len=strlen(buf); - const ops_boolean_t use_armour=ops_true; - - ops_memory_t* mem=NULL; - - mem=ops_sign_buf(buf,len,OPS_SIG_BINARY,skey,use_armour); - if (mem) - { - printf ("OK"); - ops_memory_free(mem); - } - else - { - printf("ERR"); - } -} -\endcode -*/ -ops_memory_t* ops_sign_buf(const void* input, const size_t input_len, - const ops_sig_type_t sig_type, - const ops_hash_algorithm_t hash_algorithm, - const ops_secret_key_t *skey, - const ops_boolean_t use_armour, - ops_boolean_t include_data, - ops_boolean_t include_creation_time, - ops_boolean_t include_key_id) - { - // \todo allow choice of hash algorithams - // enforce use of SHA1 for now - - unsigned char keyid[OPS_KEY_ID_SIZE]; - ops_create_signature_t *sig=NULL; - - ops_create_info_t *cinfo=NULL; - ops_memory_t *mem=ops_memory_new(); - - ops_hash_algorithm_t hash_alg=hash_algorithm ; - ops_literal_data_type_t ld_type; - ops_hash_t* hash=NULL; - - // setup literal data packet type - if (sig_type == OPS_SIG_BINARY) - ld_type=OPS_LDT_BINARY; - else - ld_type=OPS_LDT_TEXT; - - // set up signature - sig=ops_create_signature_new(); - ops_signature_start_message_signature(sig, skey, hash_alg, sig_type); - - // setup writer - ops_setup_memory_write(&cinfo, &mem, input_len); - - // set armoured/not armoured here - if (use_armour) - ops_writer_push_armoured_message(cinfo); - - if (debug) - fprintf(stderr, "** Writing out one pass sig\n"); - - // write one_pass_sig - if(include_data) - ops_write_one_pass_sig(skey, hash_alg, sig_type, cinfo); - - // hash file contents - hash=ops_signature_get_hash(sig); - hash->add(hash, input, input_len); - - // output file contents as Literal Data packet - - if (debug) - fprintf(stderr,"** Writing out data now\n"); - - if(include_data) - ops_write_literal_data_from_buf(input, input_len, ld_type, cinfo); - - if (debug) - fprintf(stderr,"** After Writing out data now\n"); - - // add subpackets to signature - // - creation time - // - key id - - if(include_creation_time) - ops_signature_add_creation_time(sig, time(NULL)); - - if(include_key_id) - { - ops_keyid(keyid, &skey->public_key); - ops_signature_add_issuer_key_id(sig, keyid); - } - - ops_signature_hashed_subpackets_end(sig); - - // write out sig - ops_write_signature(sig, &skey->public_key, skey, cinfo); - - // tidy up - ops_writer_close(cinfo); - free(cinfo) ; - ops_create_signature_delete(sig); - - return mem; - } - -typedef struct { - ops_create_signature_t *signature; - const ops_secret_key_t *skey; - ops_hash_algorithm_t hash_alg; - ops_sig_type_t sig_type; -} signature_arg_t; - -static ops_boolean_t stream_signature_writer(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo) - { - signature_arg_t* arg = ops_writer_get_arg(winfo); - // Add the input data to the hash. At the end, we will use the hash - // to generate a signature packet. - ops_hash_t* hash = ops_signature_get_hash(arg->signature); - hash->add(hash, src, length); - - return ops_stacked_write(src, length, errors, winfo); - } - -static ops_boolean_t stream_signature_write_trailer(ops_create_info_t *cinfo, - void *data) - { - signature_arg_t* arg = data; - unsigned char keyid[OPS_KEY_ID_SIZE]; - - // add subpackets to signature - // - creation time - // - key id - ops_signature_add_creation_time(arg->signature,time(NULL)); - ops_keyid(keyid, &arg->skey->public_key); - ops_signature_add_issuer_key_id(arg->signature, keyid); - ops_signature_hashed_subpackets_end(arg->signature); - - // write out signature - return ops_write_signature(arg->signature, &arg->skey->public_key, - arg->skey, cinfo); - } - -static void stream_signature_destroyer(ops_writer_info_t *winfo) - { - signature_arg_t* arg = ops_writer_get_arg(winfo); - ops_create_signature_delete(arg->signature); - free(arg); - } - -/** -\ingroup Core_WritePackets -\brief Pushes a signed writer onto the stack. - -Data written will be encoded as a onepass signature packet, followed -by a literal packet, followed by a signature packet. Once this writer -has been added to the stack, cleartext can be written straight to the -output, and it will be encoded as a literal packet and signed. - -\param cinfo Write settings -\param sig_type the type of input to be signed (text or binary) -\param skey the key used to sign the stream. -\return false if the initial onepass packet could not be created. -*/ -ops_boolean_t ops_writer_push_signed(ops_create_info_t *cinfo, - const ops_sig_type_t sig_type, - const ops_secret_key_t *skey) - { - // \todo allow choice of hash algorithams - // enforce use of SHA1 for now - - // Create arg to be used with this writer - // Remember to free this in the destroyer - signature_arg_t *signature_arg = ops_mallocz(sizeof *signature_arg); - signature_arg->signature = ops_create_signature_new(); - signature_arg->hash_alg = OPS_HASH_SHA1; - signature_arg->skey = skey; - signature_arg->sig_type = sig_type; - ops_signature_start_message_signature(signature_arg->signature, - signature_arg->skey, - signature_arg->hash_alg, - signature_arg->sig_type); - - if (!ops_write_one_pass_sig(signature_arg->skey, - signature_arg->hash_alg, - signature_arg->sig_type, - cinfo)) - return ops_false; - - ops_writer_push_partial_with_trailer(0, cinfo, OPS_PTAG_CT_LITERAL_DATA, - write_literal_header, NULL, - stream_signature_write_trailer, - signature_arg); - // And push writer on stack - ops_writer_push(cinfo, stream_signature_writer, NULL, - stream_signature_destroyer,signature_arg); - return ops_true; - } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/signature.h b/openpgpsdk/src/openpgpsdk/signature.h deleted file mode 100644 index eb87d0ee5..000000000 --- a/openpgpsdk/src/openpgpsdk/signature.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_SIGNATURE_H -#define OPS_SIGNATURE_H - -#include "packet.h" -#include "util.h" -#include "create.h" - -typedef struct ops_create_signature ops_create_signature_t; - -ops_create_signature_t *ops_create_signature_new(void); -void ops_create_signature_delete(ops_create_signature_t *sig); - -ops_boolean_t -ops_check_user_id_certification_signature(const ops_public_key_t *key, - const ops_user_id_t *id, - const ops_signature_t *sig, - const ops_public_key_t *signer, - const unsigned char *raw_packet); -ops_boolean_t -ops_check_user_attribute_certification_signature(const ops_public_key_t *key, - const ops_user_attribute_t *attribute, - const ops_signature_t *sig, - const ops_public_key_t *signer, - const unsigned char *raw_packet); -ops_boolean_t -ops_check_subkey_signature(const ops_public_key_t *key, - const ops_public_key_t *subkey, - const ops_signature_t *sig, - const ops_public_key_t *signer, - const unsigned char *raw_packet); -ops_boolean_t -ops_check_direct_signature(const ops_public_key_t *key, - const ops_signature_t *sig, - const ops_public_key_t *signer, - const unsigned char *raw_packet); -ops_boolean_t -ops_check_hash_signature(ops_hash_t *hash, - const ops_signature_t *sig, - const ops_public_key_t *signer); -void ops_signature_start_key_signature(ops_create_signature_t *sig, - const ops_public_key_t *key, - const ops_user_id_t *id, - ops_sig_type_t type); -void ops_signature_start_cleartext_signature(ops_create_signature_t *sig, - const ops_secret_key_t *key, - const ops_hash_algorithm_t hash, - const ops_sig_type_t type); -void ops_signature_start_message_signature(ops_create_signature_t *sig, - const ops_secret_key_t *key, - const ops_hash_algorithm_t hash, - const ops_sig_type_t type); - -void ops_signature_add_data(ops_create_signature_t *sig,const void *buf, - size_t length); -ops_hash_t *ops_signature_get_hash(ops_create_signature_t *sig); -ops_boolean_t ops_signature_hashed_subpackets_end(ops_create_signature_t *sig); -ops_boolean_t ops_write_signature(ops_create_signature_t *sig,const ops_public_key_t *key, - const ops_secret_key_t *skey, ops_create_info_t *opt); -ops_boolean_t ops_signature_add_creation_time(ops_create_signature_t *sig,time_t when); -ops_boolean_t ops_signature_add_issuer_key_id(ops_create_signature_t *sig, - const unsigned char keyid[OPS_KEY_ID_SIZE]); -void ops_signature_add_primary_user_id(ops_create_signature_t *sig, - ops_boolean_t primary); - -// Standard Interface -ops_boolean_t ops_sign_file_as_cleartext(const char* input_filename, const char* output_filename, const ops_secret_key_t *skey, const ops_boolean_t overwrite); -ops_boolean_t ops_sign_buf_as_cleartext(const char* input, const size_t len, ops_memory_t** output, const ops_secret_key_t *skey); -ops_boolean_t ops_sign_file(const char* input_filename, const char* output_filename, const ops_secret_key_t *skey, const ops_boolean_t use_armour, const ops_boolean_t overwrite); -ops_memory_t * ops_sign_buf(const void* input, const size_t input_len, const ops_sig_type_t sig_type, const ops_hash_algorithm_t hash_algorithm, const ops_secret_key_t *skey, const ops_boolean_t use_armour, ops_boolean_t include_data, ops_boolean_t include_creation_time, ops_boolean_t include_key_id); -ops_boolean_t ops_writer_push_signed(ops_create_info_t *cinfo, const ops_sig_type_t sig_type, const ops_secret_key_t *skey); - -#endif diff --git a/openpgpsdk/src/openpgpsdk/std_print.h b/openpgpsdk/src/openpgpsdk/std_print.h deleted file mode 100644 index f6ae7dba1..000000000 --- a/openpgpsdk/src/openpgpsdk/std_print.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_STD_PRINT_H -#define OPS_STD_PRINT_H - -#include "openpgpsdk/packet.h" -#include "openpgpsdk/packet-parse.h" -#include "openpgpsdk/keyring.h" - -void print_bn( const char *name, - const BIGNUM *bn); -void ops_print_pk_session_key(ops_content_tag_t tag, - const ops_pk_session_key_t *key); -void ops_print_public_keydata(const ops_keydata_t *key); - -void ops_print_public_keydata_verbose(const ops_keydata_t *key); -void ops_print_public_key(const ops_public_key_t *pkey); - -void ops_print_secret_keydata(const ops_keydata_t *key); -void ops_print_secret_keydata_verbose(const ops_keydata_t *key); -//void ops_print_secret_key(const ops_content_tag_t type, const ops_secret_key_t* skey); -int ops_print_packet(const ops_parser_content_t *content_); -void ops_list_packets(char *filename, ops_boolean_t armour, ops_keyring_t* pubring, ops_parse_cb_t* cb_get_passphrase); - -#endif diff --git a/openpgpsdk/src/openpgpsdk/streamwriter.h b/openpgpsdk/src/openpgpsdk/streamwriter.h deleted file mode 100644 index 70f77990d..000000000 --- a/openpgpsdk/src/openpgpsdk/streamwriter.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __OPS_STREAMWRITER_H__ -#define __OPS_STREAMWRITER_H__ - -#include - -void ops_writer_push_stream_encrypt_se_ip(ops_create_info_t *cinfo, - const ops_keydata_t *pub_key); - -#endif /*__OPS_STREAMWRITER_H__*/ diff --git a/openpgpsdk/src/openpgpsdk/symmetric.c b/openpgpsdk/src/openpgpsdk/symmetric.c deleted file mode 100644 index 30dc0b74b..000000000 --- a/openpgpsdk/src/openpgpsdk/symmetric.c +++ /dev/null @@ -1,683 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#ifndef OPENSSL_NO_IDEA -# include -#endif -#include -#ifndef OPENSSL_NO_CAMELLIA -# include -#endif -#include -#include "parse_local.h" - -#include -#include - -//static int debug=0; - -#ifndef ATTRIBUTE_UNUSED - -#ifndef WIN32 -#define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) -#else -#define ATTRIBUTE_UNUSED -#endif // #ifndef WIN32 - -#endif /* ATTRIBUTE_UNUSED */ - -static void std_set_iv(ops_crypt_t *crypt,const unsigned char *iv) - { - memcpy(crypt->iv,iv,crypt->blocksize); - crypt->num=0; - } - -static void std_set_key(ops_crypt_t *crypt,const unsigned char *key) - { memcpy(crypt->key,key,crypt->keysize); } - -static void std_resync(ops_crypt_t *decrypt) - { - if(decrypt->num == decrypt->blocksize) - return; - - memmove(decrypt->civ+decrypt->blocksize-decrypt->num,decrypt->civ, - decrypt->num); - memcpy(decrypt->civ,decrypt->siv+decrypt->num, - decrypt->blocksize-decrypt->num); - decrypt->num=0; - } - -static void std_finish(ops_crypt_t *crypt) - { - if (crypt->encrypt_key) - { - free(crypt->encrypt_key); - crypt->encrypt_key=NULL; - } - if (crypt->decrypt_key) - { - free(crypt->decrypt_key); - crypt->decrypt_key=NULL; - } - } - -static void cast5_init(ops_crypt_t *crypt) - { - if (crypt->encrypt_key) - free(crypt->encrypt_key); - crypt->encrypt_key=malloc(sizeof(CAST_KEY)); - CAST_set_key(crypt->encrypt_key,crypt->keysize,crypt->key); - crypt->decrypt_key=malloc(sizeof(CAST_KEY)); - CAST_set_key(crypt->decrypt_key,crypt->keysize,crypt->key); - } - -static void cast5_block_encrypt(ops_crypt_t *crypt,void *out,const void *in) - { CAST_ecb_encrypt(in,out,crypt->encrypt_key,CAST_ENCRYPT); } - -static void cast5_block_decrypt(ops_crypt_t *crypt,void *out,const void *in) - { CAST_ecb_encrypt(in,out,crypt->encrypt_key,CAST_DECRYPT); } - -static void cast5_cfb_encrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count) - { - CAST_cfb64_encrypt(in,out,count, - crypt->encrypt_key, crypt->iv, (int *)&crypt->num, - CAST_ENCRYPT); - } - -static void cast5_cfb_decrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count) - { - CAST_cfb64_encrypt(in,out,count, - crypt->encrypt_key, crypt->iv, (int *)&crypt->num, - CAST_DECRYPT); - } - -#define TRAILER "","","","",0,NULL,NULL - -static ops_crypt_t cast5= - { - OPS_SA_CAST5, - CAST_BLOCK, - CAST_KEY_LENGTH, - std_set_iv, - std_set_key, - cast5_init, - std_resync, - cast5_block_encrypt, - cast5_block_decrypt, - cast5_cfb_encrypt, - cast5_cfb_decrypt, - std_finish, - TRAILER - }; - -#ifndef OPENSSL_NO_IDEA -static void idea_init(ops_crypt_t *crypt) - { - assert(crypt->keysize == IDEA_KEY_LENGTH); - - if (crypt->encrypt_key) - free(crypt->encrypt_key); - crypt->encrypt_key=malloc(sizeof(IDEA_KEY_SCHEDULE)); - - // note that we don't invert the key when decrypting for CFB mode - idea_set_encrypt_key(crypt->key,crypt->encrypt_key); - - if (crypt->decrypt_key) - free(crypt->decrypt_key); - crypt->decrypt_key=malloc(sizeof(IDEA_KEY_SCHEDULE)); - - idea_set_decrypt_key(crypt->encrypt_key,crypt->decrypt_key); - } - -static void idea_block_encrypt(ops_crypt_t *crypt,void *out,const void *in) - { idea_ecb_encrypt(in,out,crypt->encrypt_key); } - -static void idea_block_decrypt(ops_crypt_t *crypt,void *out,const void *in) - { idea_ecb_encrypt(in,out,crypt->decrypt_key); } - -static void idea_cfb_encrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count) - { - idea_cfb64_encrypt(in,out,count, - crypt->encrypt_key, crypt->iv, (int *)&crypt->num, - CAST_ENCRYPT); - } - -static void idea_cfb_decrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count) - { - idea_cfb64_encrypt(in,out,count, - crypt->decrypt_key, crypt->iv, (int *)&crypt->num, - CAST_DECRYPT); - } - -static const ops_crypt_t idea= - { - OPS_SA_IDEA, - IDEA_BLOCK, - IDEA_KEY_LENGTH, - std_set_iv, - std_set_key, - idea_init, - std_resync, - idea_block_encrypt, - idea_block_decrypt, - idea_cfb_encrypt, - idea_cfb_decrypt, - std_finish, - TRAILER - }; -#endif /* OPENSSL_NO_IDEA */ - -// AES with 128-bit key (AES) - -#define KEYBITS_AES128 128 - -static void aes128_init(ops_crypt_t *crypt) - { - if (crypt->encrypt_key) - free(crypt->encrypt_key); - crypt->encrypt_key=malloc(sizeof(AES_KEY)); - if (AES_set_encrypt_key(crypt->key,KEYBITS_AES128,crypt->encrypt_key)) - fprintf(stderr,"aes128_init: Error setting encrypt_key\n"); - - if (crypt->decrypt_key) - free(crypt->decrypt_key); - crypt->decrypt_key=malloc(sizeof(AES_KEY)); - if (AES_set_decrypt_key(crypt->key,KEYBITS_AES128,crypt->decrypt_key)) - fprintf(stderr,"aes128_init: Error setting decrypt_key\n"); - } - -static void aes_block_encrypt(ops_crypt_t *crypt,void *out,const void *in) - { AES_encrypt(in,out,crypt->encrypt_key); } - -static void aes_block_decrypt(ops_crypt_t *crypt,void *out,const void *in) - { AES_decrypt(in,out,crypt->decrypt_key); } - -static void aes_cfb_encrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count) - { - AES_cfb128_encrypt(in,out,count, - crypt->encrypt_key, crypt->iv, (int *)&crypt->num, - AES_ENCRYPT); - } - -static void aes_cfb_decrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count) - { - AES_cfb128_encrypt(in,out,count, - crypt->encrypt_key, crypt->iv, (int *)&crypt->num, - AES_DECRYPT); - } - -static const ops_crypt_t aes128= - { - OPS_SA_AES_128, - AES_BLOCK_SIZE, - KEYBITS_AES128/8, - std_set_iv, - std_set_key, - aes128_init, - std_resync, - aes_block_encrypt, - aes_block_decrypt, - aes_cfb_encrypt, - aes_cfb_decrypt, - std_finish, - TRAILER - }; - -// AES with 256-bit key - -#define KEYBITS_AES256 256 - -static void aes256_init(ops_crypt_t *crypt) - { - if (crypt->encrypt_key) - free(crypt->encrypt_key); - crypt->encrypt_key=malloc(sizeof(AES_KEY)); - if (AES_set_encrypt_key(crypt->key,KEYBITS_AES256,crypt->encrypt_key)) - fprintf(stderr,"aes256_init: Error setting encrypt_key\n"); - - if (crypt->decrypt_key) - free(crypt->decrypt_key); - crypt->decrypt_key=malloc(sizeof(AES_KEY)); - if (AES_set_decrypt_key(crypt->key,KEYBITS_AES256,crypt->decrypt_key)) - fprintf(stderr,"aes256_init: Error setting decrypt_key\n"); - } - -static const ops_crypt_t aes256= - { - OPS_SA_AES_256, - AES_BLOCK_SIZE, - KEYBITS_AES256/8, - std_set_iv, - std_set_key, - aes256_init, - std_resync, - aes_block_encrypt, - aes_block_decrypt, - aes_cfb_encrypt, - aes_cfb_decrypt, - std_finish, - TRAILER - }; - -#ifndef OPENSSL_NO_CAMELLIA - -// CAMELLIA with 128-bit key - -#define KEYBITS_CAMELLIA128 128 - -static void camellia128_init(ops_crypt_t *crypt) - { - if (crypt->encrypt_key) - free(crypt->encrypt_key); - crypt->encrypt_key=malloc(sizeof(CAMELLIA_KEY)); - if (Camellia_set_key(crypt->key,KEYBITS_CAMELLIA128,crypt->encrypt_key)) - fprintf(stderr,"camellia128_init: Error setting encrypt_key\n"); - - if (crypt->decrypt_key) - free(crypt->decrypt_key); - crypt->decrypt_key=malloc(sizeof(CAMELLIA_KEY)); - if (Camellia_set_key(crypt->key,KEYBITS_CAMELLIA128,crypt->decrypt_key)) - fprintf(stderr,"camellia128_init: Error setting decrypt_key\n"); - } - -static void camellia_block_encrypt(ops_crypt_t *crypt,void *out,const void *in) - { Camellia_encrypt(in,out,crypt->encrypt_key); } - -static void camellia_block_decrypt(ops_crypt_t *crypt,void *out,const void *in) - { Camellia_decrypt(in,out,crypt->decrypt_key); } - -static void camellia_cfb_encrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count) - { - Camellia_cfb128_encrypt(in,out,count, - crypt->encrypt_key, crypt->iv, (int *)&crypt->num, - CAMELLIA_ENCRYPT); - } - -static void camellia_cfb_decrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count) - { - Camellia_cfb128_encrypt(in,out,count, - crypt->encrypt_key, crypt->iv, (int *)&crypt->num, - CAMELLIA_DECRYPT); - } - -static const ops_crypt_t camellia128= - { - OPS_SA_CAMELLIA_128, - CAMELLIA_BLOCK_SIZE, - KEYBITS_CAMELLIA128/8, - std_set_iv, - std_set_key, - camellia128_init, - std_resync, - camellia_block_encrypt, - camellia_block_decrypt, - camellia_cfb_encrypt, - camellia_cfb_decrypt, - std_finish, - TRAILER - }; - -// CAMELLIA with 192-bit key - -#define KEYBITS_CAMELLIA192 192 - -static void camellia192_init(ops_crypt_t *crypt) - { - if (crypt->encrypt_key) - free(crypt->encrypt_key); - crypt->encrypt_key=malloc(sizeof(CAMELLIA_KEY)); - if (Camellia_set_key(crypt->key,KEYBITS_CAMELLIA192,crypt->encrypt_key)) - fprintf(stderr,"camellia192_init: Error setting encrypt_key\n"); - - if (crypt->decrypt_key) - free(crypt->decrypt_key); - crypt->decrypt_key=malloc(sizeof(CAMELLIA_KEY)); - if (Camellia_set_key(crypt->key,KEYBITS_CAMELLIA192,crypt->decrypt_key)) - fprintf(stderr,"camellia192_init: Error setting decrypt_key\n"); - } - -static const ops_crypt_t camellia192= - { - OPS_SA_CAMELLIA_192, - CAMELLIA_BLOCK_SIZE, - KEYBITS_CAMELLIA192/8, - std_set_iv, - std_set_key, - camellia192_init, - std_resync, - camellia_block_encrypt, - camellia_block_decrypt, - camellia_cfb_encrypt, - camellia_cfb_decrypt, - std_finish, - TRAILER - }; - -// CAMELLIA with 256-bit key - -#define KEYBITS_CAMELLIA256 256 - -static void camellia256_init(ops_crypt_t *crypt) - { - if (crypt->encrypt_key) - free(crypt->encrypt_key); - crypt->encrypt_key=malloc(sizeof(CAMELLIA_KEY)); - if (Camellia_set_key(crypt->key,KEYBITS_CAMELLIA256,crypt->encrypt_key)) - fprintf(stderr,"camellia256_init: Error setting encrypt_key\n"); - - if (crypt->decrypt_key) - free(crypt->decrypt_key); - crypt->decrypt_key=malloc(sizeof(CAMELLIA_KEY)); - if (Camellia_set_key(crypt->key,KEYBITS_CAMELLIA256,crypt->decrypt_key)) - fprintf(stderr,"camellia256_init: Error setting decrypt_key\n"); - } - -static const ops_crypt_t camellia256= - { - OPS_SA_CAMELLIA_256, - CAMELLIA_BLOCK_SIZE, - KEYBITS_CAMELLIA256/8, - std_set_iv, - std_set_key, - camellia256_init, - std_resync, - camellia_block_encrypt, - camellia_block_decrypt, - camellia_cfb_encrypt, - camellia_cfb_decrypt, - std_finish, - TRAILER - }; - -#endif // ndef OPENSSL_NO_CAMELLIA - -// Triple DES - -static void tripledes_init(ops_crypt_t *crypt) - { - DES_key_schedule *keys; - int n; - - if (crypt->encrypt_key) - free(crypt->encrypt_key); - keys=crypt->encrypt_key=malloc(3*sizeof(DES_key_schedule)); - - for(n=0 ; n < 3 ; ++n) - DES_set_key((DES_cblock *)(crypt->key+n*8),&keys[n]); - } - -static void tripledes_block_encrypt(ops_crypt_t *crypt,void *out, - const void *in) - { - DES_key_schedule *keys=crypt->encrypt_key; - - DES_ecb3_encrypt((void *)in,out,&keys[0],&keys[1],&keys[2],DES_ENCRYPT); - } - -static void tripledes_block_decrypt(ops_crypt_t *crypt,void *out, - const void *in) - { - DES_key_schedule *keys=crypt->encrypt_key; - - DES_ecb3_encrypt((void *)in,out,&keys[0],&keys[1],&keys[2],DES_DECRYPT); - } - -static void tripledes_cfb_encrypt(ops_crypt_t *crypt ATTRIBUTE_UNUSED, - void *out ATTRIBUTE_UNUSED, - const void *in ATTRIBUTE_UNUSED, - size_t count ATTRIBUTE_UNUSED) - { - DES_key_schedule *keys=crypt->encrypt_key; - DES_ede3_cfb64_encrypt(in,out,count, - &keys[0],&keys[1],&keys[2], - (DES_cblock *)crypt->iv, (int *)&crypt->num, - DES_ENCRYPT); - } - -static void tripledes_cfb_decrypt(ops_crypt_t *crypt ATTRIBUTE_UNUSED, - void *out ATTRIBUTE_UNUSED, - const void *in ATTRIBUTE_UNUSED, - size_t count ATTRIBUTE_UNUSED) - { - DES_key_schedule *keys=crypt->encrypt_key; - DES_ede3_cfb64_encrypt(in,out,count, - &keys[0],&keys[1],&keys[2], - (DES_cblock *)crypt->iv, (int *)&crypt->num, - DES_DECRYPT); - } - -static const ops_crypt_t tripledes= - { - OPS_SA_TRIPLEDES, - 8, - 24, - std_set_iv, - std_set_key, - tripledes_init, - std_resync, - tripledes_block_encrypt, - tripledes_block_decrypt, - tripledes_cfb_encrypt, - tripledes_cfb_decrypt, - std_finish, - TRAILER - }; - -static const ops_crypt_t *get_proto(ops_symmetric_algorithm_t alg) - { - switch(alg) - { - case OPS_SA_CAST5: - return &cast5; - -#ifndef OPENSSL_NO_IDEA - case OPS_SA_IDEA: - return &idea; -#endif /* OPENSSL_NO_IDEA */ - - case OPS_SA_AES_128: - return &aes128; - - case OPS_SA_AES_256: - return &aes256; - -#ifndef OPENSSL_NO_CAMELLIA - case OPS_SA_CAMELLIA_128: - return &camellia128; - - case OPS_SA_CAMELLIA_192: - return &camellia192; - - case OPS_SA_CAMELLIA_256: - return &camellia256; -#endif // ndef OPENSSL_NO_CAMELLIA - - case OPS_SA_TRIPLEDES: - return &tripledes; - - default: - fprintf(stderr,"Unknown algorithm: %d (%s)\n",alg, - ops_show_symmetric_algorithm(alg)); - // assert(0); - } - - return NULL; - } - -int ops_crypt_any(ops_crypt_t *crypt,ops_symmetric_algorithm_t alg) - { - const ops_crypt_t *ptr=get_proto(alg); - if (ptr) - { - *crypt=*ptr; - return 1; - } - else - { - memset(crypt,'\0',sizeof *crypt); - return 0; - } - } - -unsigned ops_block_size(ops_symmetric_algorithm_t alg) - { - const ops_crypt_t *p=get_proto(alg); - - if(!p) - return 0; - - return p->blocksize; - } - -unsigned ops_key_size(ops_symmetric_algorithm_t alg) - { - const ops_crypt_t *p=get_proto(alg); - - if(!p) - return 0; - - return p->keysize; - } - -void ops_encrypt_init(ops_crypt_t * encrypt) - { - // \todo should there be a separate ops_encrypt_init? - ops_decrypt_init(encrypt); - } - -void ops_decrypt_init(ops_crypt_t *decrypt) - { - decrypt->base_init(decrypt); - decrypt->block_encrypt(decrypt,decrypt->siv,decrypt->iv); - memcpy(decrypt->civ,decrypt->siv,decrypt->blocksize); - decrypt->num=0; - } - -size_t ops_decrypt_se -(ops_crypt_t *decrypt,void *out_,const void *in_, - size_t count) - { - unsigned char *out=out_; - const unsigned char *in=in_; - int saved=count; - - /* in order to support v3's weird resyncing we have to implement CFB mode - ourselves */ - while(count-- > 0) - { - unsigned char t; - - if(decrypt->num == decrypt->blocksize) - { - memcpy(decrypt->siv,decrypt->civ,decrypt->blocksize); - decrypt->block_decrypt(decrypt,decrypt->civ,decrypt->civ); - decrypt->num=0; - } - t=decrypt->civ[decrypt->num]; - *out++=t^(decrypt->civ[decrypt->num++]=*in++); - } - - return saved; - } - -size_t ops_encrypt_se(ops_crypt_t *encrypt,void *out_,const void *in_, - size_t count) - { - unsigned char *out=out_; - const unsigned char *in=in_; - int saved=count; - - /* in order to support v3's weird resyncing we have to implement CFB mode - ourselves */ - while(count-- > 0) - { - if(encrypt->num == encrypt->blocksize) - { - memcpy(encrypt->siv,encrypt->civ,encrypt->blocksize); - encrypt->block_encrypt(encrypt,encrypt->civ,encrypt->civ); - encrypt->num=0; - } - encrypt->civ[encrypt->num]=*out++=encrypt->civ[encrypt->num]^*in++; - ++encrypt->num; - } - - return saved; - } - -/** -\ingroup HighLevel_Supported -\brief Is this Symmetric Algorithm supported? -\param alg Symmetric Algorithm to check -\return ops_true if supported; else ops_false -*/ -ops_boolean_t ops_is_sa_supported(ops_symmetric_algorithm_t alg) - { - switch (alg) - { - case OPS_SA_AES_128: - case OPS_SA_AES_256: - case OPS_SA_CAMELLIA_128: - case OPS_SA_CAMELLIA_192: - case OPS_SA_CAMELLIA_256: - case OPS_SA_CAST5: - case OPS_SA_TRIPLEDES: -#ifndef OPENSSL_NO_IDEA - case OPS_SA_IDEA: -#endif - return ops_true; - break; - - default: - fprintf(stderr,"\nWarning: %s not supported\n", - ops_show_symmetric_algorithm(alg)); - return ops_false; - } - } - -size_t ops_encrypt_se_ip(ops_crypt_t *crypt,void *out_,const void *in_, - size_t count) - { - if (!ops_is_sa_supported(crypt->algorithm)) - return -1; - - crypt->cfb_encrypt(crypt, out_, in_, count); - - // \todo test this number was encrypted - return count; - } - -size_t ops_decrypt_se_ip(ops_crypt_t *crypt,void *out_,const void *in_, - size_t count) - { - if (!ops_is_sa_supported(crypt->algorithm)) - return -1; - - crypt->cfb_decrypt(crypt, out_, in_, count); - - // \todo check this number was in fact decrypted - return count; - } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/types.h b/openpgpsdk/src/openpgpsdk/types.h deleted file mode 100644 index 50d4107a0..000000000 --- a/openpgpsdk/src/openpgpsdk/types.h +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_TYPES_H -#define OPS_TYPES_H - -/** Special type for intermediate function casting, avoids warnings on - some platforms -*/ -typedef void (*ops_void_fptr)(void); -#define ops_fcast(f) ((ops_void_fptr)f) - -/** ops_map_t - */ -typedef struct - { - int type; - char *string; - } ops_map_t; - -/** Boolean type */ -typedef unsigned ops_boolean_t; - -/** ops_content_tag_t */ - -/* PTag Content Tags */ -/***************************/ - -/** Package Tags (aka Content Tags) and signature subpacket types. - * This enumerates all rfc-defined packet tag values and the - * signature subpacket type values that we understand. - * - * \see RFC4880 4.3 - * \see RFC4880 5.2.3.1 - */ - -#ifndef __cplusplus -typedef enum ops_content_tag_t ops_content_tag_t ; -#endif - -enum ops_content_tag_t - { - OPS_PTAG_CT_RESERVED = 0, /*!< Reserved - a packet tag must not have this value */ - OPS_PTAG_CT_PK_SESSION_KEY = 1, /*!< Public-Key Encrypted Session Key Packet */ - OPS_PTAG_CT_SIGNATURE = 2, /*!< Signature Packet */ - OPS_PTAG_CT_SK_SESSION_KEY = 3, /*!< Symmetric-Key Encrypted Session Key Packet */ - OPS_PTAG_CT_ONE_PASS_SIGNATURE = 4, /*!< One-Pass Signature Packet */ - OPS_PTAG_CT_SECRET_KEY = 5, /*!< Secret Key Packet */ - OPS_PTAG_CT_PUBLIC_KEY = 6, /*!< Public Key Packet */ - OPS_PTAG_CT_SECRET_SUBKEY = 7, /*!< Secret Subkey Packet */ - OPS_PTAG_CT_COMPRESSED = 8, /*!< Compressed Data Packet */ - OPS_PTAG_CT_SE_DATA = 9, /*!< Symmetrically Encrypted Data Packet */ - OPS_PTAG_CT_MARKER =10, /*!< Marker Packet */ - OPS_PTAG_CT_LITERAL_DATA =11, /*!< Literal Data Packet */ - OPS_PTAG_CT_TRUST =12, /*!< Trust Packet */ - OPS_PTAG_CT_USER_ID =13, /*!< User ID Packet */ - OPS_PTAG_CT_PUBLIC_SUBKEY =14, /*!< Public Subkey Packet */ - OPS_PTAG_CT_RESERVED2 =15, /*!< reserved */ - OPS_PTAG_CT_RESERVED3 =16, /*!< reserved */ - OPS_PTAG_CT_USER_ATTRIBUTE =17, /*!< User Attribute Packet */ - OPS_PTAG_CT_SE_IP_DATA =18, /*!< Sym. Encrypted and Integrity Protected Data Packet */ - OPS_PTAG_CT_MDC =19, /*!< Modification Detection Code Packet */ - - OPS_PARSER_PTAG =0x100, /*!< Internal Use: The packet is the "Packet Tag" itself - used when - callback sends back the PTag. */ - OPS_PTAG_RAW_SS =0x101, /*!< Internal Use: content is raw sig subtag */ - OPS_PTAG_SS_ALL =0x102, /*!< Internal Use: select all subtags */ - OPS_PARSER_PACKET_END =0x103, - - /* signature subpackets (0x200-2ff) (type+0x200) */ - /* only those we can parse are listed here */ - OPS_PTAG_SIGNATURE_SUBPACKET_BASE =0x200, /*!< Base for signature subpacket types - All signature type - values are relative to this value. */ - OPS_PTAG_SS_CREATION_TIME =0x200+2, /*!< signature creation time */ - OPS_PTAG_SS_EXPIRATION_TIME =0x200+3, /*!< signature expiration time */ - - OPS_PTAG_SS_EXPORTABLE_CERTIFICATION =0x200+4, /*!< exportable certification */ - OPS_PTAG_SS_TRUST =0x200+5, /*!< trust signature */ - OPS_PTAG_SS_REGEXP =0x200+6, /*!< regular expression */ - OPS_PTAG_SS_REVOCABLE =0x200+7, /*!< revocable */ - OPS_PTAG_SS_KEY_EXPIRATION_TIME =0x200+9, /*!< key expiration time */ - OPS_PTAG_SS_RESERVED =0x200+10, /*!< reserved */ - OPS_PTAG_SS_PREFERRED_SKA =0x200+11, /*!< preferred symmetric algorithms */ - OPS_PTAG_SS_REVOCATION_KEY =0x200+12, /*!< revocation key */ - OPS_PTAG_SS_ISSUER_KEY_ID =0x200+16, /*!< issuer key ID */ - OPS_PTAG_SS_NOTATION_DATA =0x200+20, /*!< notation data */ - OPS_PTAG_SS_PREFERRED_HASH =0x200+21, /*!< preferred hash algorithms */ - OPS_PTAG_SS_PREFERRED_COMPRESSION =0x200+22, /*!< preferred compression algorithms */ - OPS_PTAG_SS_KEY_SERVER_PREFS =0x200+23, /*!< key server preferences */ - OPS_PTAG_SS_PREFERRED_KEY_SERVER =0x200+24, /*!< Preferred Key Server */ - OPS_PTAG_SS_PRIMARY_USER_ID =0x200+25, /*!< primary User ID */ - OPS_PTAG_SS_POLICY_URI =0x200+26, /*!< Policy URI */ - OPS_PTAG_SS_KEY_FLAGS =0x200+27, /*!< key flags */ - OPS_PTAG_SS_SIGNERS_USER_ID =0x200+28, /*!< Signer's User ID */ - OPS_PTAG_SS_REVOCATION_REASON =0x200+29, /*!< reason for revocation */ - OPS_PTAG_SS_FEATURES =0x200+30, /*!< features */ - OPS_PTAG_SS_SIGNATURE_TARGET =0x200+31, /*!< signature target */ - OPS_PTAG_SS_EMBEDDED_SIGNATURE=0x200+32, /*!< embedded signature */ - - OPS_PTAG_SS_USERDEFINED00 =0x200+100, /*!< internal or user-defined */ - OPS_PTAG_SS_USERDEFINED01 =0x200+101, - OPS_PTAG_SS_USERDEFINED02 =0x200+102, - OPS_PTAG_SS_USERDEFINED03 =0x200+103, - OPS_PTAG_SS_USERDEFINED04 =0x200+104, - OPS_PTAG_SS_USERDEFINED05 =0x200+105, - OPS_PTAG_SS_USERDEFINED06 =0x200+106, - OPS_PTAG_SS_USERDEFINED07 =0x200+107, - OPS_PTAG_SS_USERDEFINED08 =0x200+108, - OPS_PTAG_SS_USERDEFINED09 =0x200+109, - OPS_PTAG_SS_USERDEFINED10 =0x200+110, - - - /* pseudo content types */ - OPS_PTAG_CT_LITERAL_DATA_HEADER =0x300, - OPS_PTAG_CT_LITERAL_DATA_BODY =0x300+1, - OPS_PTAG_CT_SIGNATURE_HEADER =0x300+2, - OPS_PTAG_CT_SIGNATURE_FOOTER =0x300+3, - OPS_PTAG_CT_ARMOUR_HEADER =0x300+4, - OPS_PTAG_CT_ARMOUR_TRAILER =0x300+5, - OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER =0x300+6, - OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY =0x300+7, - OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER=0x300+8, - OPS_PTAG_CT_UNARMOURED_TEXT =0x300+9, - OPS_PTAG_CT_ENCRYPTED_SECRET_KEY =0x300+10, // In this case the algorithm specific fields will not be initialised - OPS_PTAG_CT_SE_DATA_HEADER =0x300+11, - OPS_PTAG_CT_SE_DATA_BODY =0x300+12, - OPS_PTAG_CT_SE_IP_DATA_HEADER =0x300+13, - OPS_PTAG_CT_SE_IP_DATA_BODY =0x300+14, - OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY=0x300+15, - - /* commands to the callback */ - OPS_PARSER_CMD_GET_SK_PASSPHRASE =0x400, - OPS_PARSER_CMD_GET_SECRET_KEY =0x400+1, - OPS_PARSER_CMD_GET_SK_PASSPHRASE_PREV_WAS_BAD =0x400+2, - - /* Errors */ - OPS_PARSER_ERROR =0x500, /*!< Internal Use: Parser Error */ - OPS_PARSER_ERRCODE =0x500+1, /*! < Internal Use: Parser Error with errcode returned */ - }; - -/** Used to specify whether subpackets should be returned raw, parsed or ignored. - */ - -enum ops_parse_type_t - { - OPS_PARSE_RAW, /*!< Callback Raw */ - OPS_PARSE_PARSED, /*!< Callback Parsed */ - OPS_PARSE_IGNORE, /*!< Don't callback */ - }; - -typedef struct _ops_crypt_t ops_crypt_t; - -/** ops_hash_t */ -typedef struct _ops_hash_t ops_hash_t; - -/** - keep both ops_content_tag_t and ops_packet_tag_t because we might - want to introduce some bounds checking i.e. is this really a valid value - for a packet tag? -*/ -typedef enum ops_content_tag_t ops_packet_tag_t; -/** SS types are a subset of all content types. -*/ -typedef enum ops_content_tag_t ops_ss_type_t; -/* typedef enum ops_sig_type_t ops_sig_type_t; */ - -/** Revocation Reason type */ -typedef unsigned char ops_ss_rr_code_t; - -/** ops_parse_type_t */ - -/** Used to specify whether subpackets should be returned raw, parsed or ignored. - */ - -typedef enum ops_parse_type_t ops_parse_type_t; - -/** ops_parser_content_t */ -typedef struct ops_parser_content_t ops_parser_content_t; - -/** Reader Flags */ -/* -typedef enum - { - OPS_RETURN_LENGTH=1, - } ops_reader_flags_t; -typedef enum ops_reader_ret_t ops_reader_ret_t; -*/ - -/** Writer flags */ -typedef enum - { - OPS_WF_DUMMY, - } ops_writer_flags_t; - -/** - * \ingroup Create - * Contains the required information about how to write - */ -typedef struct ops_create_info ops_create_info_t; - -#endif diff --git a/openpgpsdk/src/openpgpsdk/util.c b/openpgpsdk/src/openpgpsdk/util.c deleted file mode 100644 index 2dced1ff0..000000000 --- a/openpgpsdk/src/openpgpsdk/util.c +++ /dev/null @@ -1,179 +0,0 @@ - /* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include -#include -#include -#include -#include - -#ifndef WIN32 -#include -#endif - -#include - -#include - -/** - * Searches the given map for the given type. - * Returns a human-readable descriptive string if found, - * returns NULL if not found - * - * It is the responsibility of the calling function to handle the - * error case sensibly (i.e. don't just print out the return string. - * - */ -static char *str_from_map_or_null(int type, ops_map_t *map) - { - ops_map_t *row; - - for ( row=map; row->string != NULL; row++ ) - if (row->type == type) - return row->string; - return NULL; - } - -/** - * \ingroup Core_Print - * - * Searches the given map for the given type. - * Returns a readable string if found, "Unknown" if not. - */ - -char *ops_str_from_map(int type, ops_map_t *map) - { - char *str; - str=str_from_map_or_null(type,map); - if (str) - return(str); - else - return("Unknown"); - } - -void hexdump(const unsigned char *src,size_t length) - { - while(length--) - printf("%02X",*src++); - } - -/** - * \ingroup HighLevel_Functions - * \brief Initialises OpenPGP::SDK. To be called before any other OPS function. - * - * Initialises OpenPGP::SDK and the underlying openssl library. - */ - -void ops_init(void) - { - ops_crypto_init(); - } - -/** - * \ingroup HighLevel_Functions - * \brief Closes down OpenPGP::SDK. - * - * Close down OpenPGP:SDK, release any resources under the control of - * the library. No OpenPGP:SDK function other than ops_init() should - * be called after this function. - */ - -void ops_finish(void) - { - ops_crypto_finish(); - } - -/** - \ingroup HighLevel_Misc - \brief mallocs and zeros memory - \param n Number of bytes to be alloc-ed. - \return Pointer to new memory. - \note Should be freed after use with free(). -*/ -void *ops_mallocz(size_t n) -{ - void *m=malloc(n); - - if(m == NULL) - fprintf(stderr,"(EE) Cannot allocate %lu bytes of memory in %s\n",n,__PRETTY_FUNCTION__) ; - else - memset(m,'\0',n); - - return m; -} - -typedef struct - { - unsigned short sum; - } sum16_arg_t; - -static int sum16_reader(void *dest_,size_t length,ops_error_t **errors, - ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo) - { - const unsigned char *dest=dest_; - sum16_arg_t *arg=ops_reader_get_arg(rinfo); - int r=ops_stacked_read(dest_,length,errors,rinfo,cbinfo); - int n; - - if(r < 0) - return r; - - for(n=0 ; n < r ; ++n) - arg->sum=(arg->sum+dest[n])&0xffff; - - return r; - } - -static void sum16_destroyer(ops_reader_info_t *rinfo) - { free(ops_reader_get_arg(rinfo)); } - -/** - \ingroup Internal_Readers_Sum16 - \param pinfo Parse settings -*/ - -void ops_reader_push_sum16(ops_parse_info_t *pinfo) - { - sum16_arg_t *arg=ops_mallocz(sizeof *arg); - - ops_reader_push(pinfo,sum16_reader,sum16_destroyer,arg); - } - -/** - \ingroup Internal_Readers_Sum16 - \param pinfo Parse settings - \return sum -*/ -unsigned short ops_reader_pop_sum16(ops_parse_info_t *pinfo) - { - sum16_arg_t *arg=ops_reader_get_arg(ops_parse_get_rinfo(pinfo)); - unsigned short sum=arg->sum; - - ops_reader_pop(pinfo); - free(arg); - - return sum; - } diff --git a/openpgpsdk/src/openpgpsdk/util.h b/openpgpsdk/src/openpgpsdk/util.h deleted file mode 100644 index 88d7b10a8..000000000 --- a/openpgpsdk/src/openpgpsdk/util.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_UTIL_H -#define OPS_UTIL_H - -#include "openpgpsdk/types.h" -#include "openpgpsdk/create.h" -#include "openpgpsdk/packet-parse.h" -#include - -#define ops_false 0 -#define ops_true 1 - -void hexdump(const unsigned char *src,size_t length); - -/* - * These macros code ensures that you are casting what you intend to cast. - * It works because in "a ? b : c", b and c must have the same type. - * This is a copy of the macro defined in openssl/asn1.h. - */ -#ifndef CHECKED_PTR_OF -#define CHECKED_PTR_OF(type, p) ((void*) (1 ? p : (type *)0)) -#endif -#define CHECKED_INSTANCE_OF(type, p) (1 ? p : (type)0) -#define DECONST(type,p) ((type *)CHECKED_PTR_OF(const type, p)) - -/* number of elements in an array */ -#define OPS_ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a))) - -void *ops_mallocz(size_t n); - -#endif diff --git a/openpgpsdk/src/openpgpsdk/validate.c b/openpgpsdk/src/openpgpsdk/validate.c deleted file mode 100644 index d42d6becd..000000000 --- a/openpgpsdk/src/openpgpsdk/validate.c +++ /dev/null @@ -1,844 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include "keyring_local.h" -#include "parse_local.h" -#include -#include -#include -#include -#include -#include -#include - -#include - -static int debug=0; - -static ops_boolean_t check_binary_signature(const unsigned len, - const unsigned char *data, - const ops_signature_t *sig, - const ops_public_key_t *signer __attribute__((unused))) -{ - // Does the signed hash match the given hash? - - int n=0; - ops_hash_t hash; - unsigned char hashout[OPS_MAX_HASH_SIZE]; - unsigned char trailer[6]; - unsigned int hashedlen; - - //common_init_signature(&hash,sig); - ops_hash_any(&hash,sig->info.hash_algorithm); - hash.init(&hash); - hash.add(&hash,data,len); - switch (sig->info.version) - { - case OPS_V3: - trailer[0]=sig->info.type; - trailer[1]=sig->info.creation_time >> 24; - trailer[2]=sig->info.creation_time >> 16; - trailer[3]=sig->info.creation_time >> 8; - trailer[4]=sig->info.creation_time; - hash.add(&hash,&trailer[0],5); - break; - - case OPS_V4: - hash.add(&hash,sig->info.v4_hashed_data,sig->info.v4_hashed_data_length); - - trailer[0]=0x04; // version - trailer[1]=0xFF; - hashedlen=sig->info.v4_hashed_data_length; - trailer[2]=hashedlen >> 24; - trailer[3]=hashedlen >> 16; - trailer[4]=hashedlen >> 8; - trailer[5]=hashedlen; - hash.add(&hash,&trailer[0],6); - - break; - - default: - fprintf(stderr,"Invalid signature version %d\n", sig->info.version); - return ops_false; - } - - n=hash.finish(&hash,hashout); - - // return ops_false; - return ops_check_signature(hashout,n,sig,signer); -} - -static int keydata_reader(void *dest,size_t length,ops_error_t **errors, - ops_reader_info_t *rinfo, - ops_parse_cb_info_t *cbinfo) -{ - validate_reader_arg_t *arg=ops_reader_get_arg(rinfo); - - OPS_USED(errors); - OPS_USED(cbinfo); - if(arg->offset == arg->key->packets[arg->packet].length) - { - ++arg->packet; - arg->offset=0; - } - - if(arg->packet == arg->key->npackets) - return 0; - - // we should never be asked to cross a packet boundary in a single read - // - if(arg->key->packets[arg->packet].length >= arg->offset+length) - { - memcpy(dest,&arg->key->packets[arg->packet].raw[arg->offset],length); - arg->offset+=length; - - return length; - } - else - { - // If that happens, we set the offet to the total length and return 0. - // - fprintf(stderr,"WARNING: keydata_reader: packet length %lu goes beyond actual data size %lu. Consistency error!",arg->offset+length,arg->key->packets[arg->packet].length) ; - - arg->offset = arg->key->packets[arg->packet].length ; - return 0 ; - } -} - -static void free_signature_info(ops_signature_info_t *sig,int n) -{ - int i ; - for(i=0;iv4_hashed_data=ops_mallocz(src->v4_hashed_data_length); - memcpy(dst->v4_hashed_data,src->v4_hashed_data,src->v4_hashed_data_length); -} - -static void add_sig_to_valid_list(ops_validate_result_t * result, const ops_signature_info_t* sig) -{ - size_t newsize; - - // increment count - ++result->valid_count; - - // increase size of array - newsize=(sizeof *sig) * result->valid_count; - if (!result->valid_sigs) - result->valid_sigs=malloc(newsize); - else - result->valid_sigs=realloc(result->valid_sigs, newsize); - - // copy key ptr to array - copy_signature_info(&result->valid_sigs[result->valid_count-1],sig); -} - -static void add_sig_to_invalid_list(ops_validate_result_t * result, const ops_signature_info_t *sig) -{ - size_t newsize; - - // increment count - ++result->invalid_count; - - // increase size of array - newsize=(sizeof *sig) * result->invalid_count; - if (!result->invalid_sigs) - result->invalid_sigs=malloc(newsize); - else - result->invalid_sigs=realloc(result->invalid_sigs, newsize); - - // copy key ptr to array - copy_signature_info(&result->invalid_sigs[result->invalid_count-1],sig); -} - -static void add_sig_to_unknown_list(ops_validate_result_t * result, const ops_signature_info_t *sig) -{ - size_t newsize; - - // increment count - ++result->unknown_signer_count; - - // increase size of array - newsize=(sizeof *sig) * result->unknown_signer_count; - if (!result->unknown_sigs) - result->unknown_sigs=malloc(newsize); - else - result->unknown_sigs=realloc(result->unknown_sigs, newsize); - - // copy key id to array - copy_signature_info(&result->unknown_sigs[result->unknown_signer_count-1],sig); -} - - ops_parse_cb_return_t -ops_validate_key_cb(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo) -{ - const ops_parser_content_union_t *content=&content_->content; - validate_key_cb_arg_t *arg=ops_parse_cb_get_arg(cbinfo); - ops_error_t **errors=ops_parse_cb_get_errors(cbinfo); - const ops_keydata_t *signer; - ops_boolean_t valid=ops_false; - - if (debug) - printf("%s\n",ops_show_packet_tag(content_->tag)); - - switch(content_->tag) - { - case OPS_PTAG_CT_PUBLIC_KEY: - if(arg->pkey.version != 0) - { - fprintf(stderr,"arg->pkey.version should be 0! It's %d. Giving up.",arg->pkey.version) ; - return OPS_RELEASE_MEMORY ; - } - arg->pkey=content->public_key; - return OPS_KEEP_MEMORY; - - case OPS_PTAG_CT_PUBLIC_SUBKEY: - if(arg->subkey.version) - ops_public_key_free(&arg->subkey); - arg->subkey=content->public_key; - return OPS_KEEP_MEMORY; - - case OPS_PTAG_CT_SECRET_KEY: - arg->skey=content->secret_key; - arg->pkey=arg->skey.public_key; - return OPS_KEEP_MEMORY; - - case OPS_PTAG_CT_USER_ID: - if(arg->user_id.user_id) - ops_user_id_free(&arg->user_id); - arg->user_id=content->user_id; - arg->last_seen=ID; - return OPS_KEEP_MEMORY; - - case OPS_PTAG_CT_USER_ATTRIBUTE: - if(!content->user_attribute.data.len) - { - fprintf(stderr,"User attribute length is 0. Not possible! Giving up.") ; - return OPS_RELEASE_MEMORY ; - } - printf("user attribute, length=%d\n",(int)content->user_attribute.data.len); - if(arg->user_attribute.data.len) - ops_user_attribute_free(&arg->user_attribute); - arg->user_attribute=content->user_attribute; - arg->last_seen=ATTRIBUTE; - return OPS_KEEP_MEMORY; - - case OPS_PTAG_CT_SIGNATURE: // V3 sigs - case OPS_PTAG_CT_SIGNATURE_FOOTER: // V4 sigs - - if(debug) - { - printf(" type=%02x signer_id=",content->signature.info.type); - hexdump(content->signature.info.signer_id, - sizeof content->signature.info.signer_id); - printf("\n"); - } - - signer=ops_keyring_find_key_by_id(arg->keyring, - content->signature.info.signer_id); - if(!signer) - { - add_sig_to_unknown_list(arg->result, &content->signature.info); - break; - } - - switch(content->signature.info.type) - { - case OPS_CERT_GENERIC: - case OPS_CERT_PERSONA: - case OPS_CERT_CASUAL: - case OPS_CERT_POSITIVE: - case OPS_SIG_REV_CERT: - if(arg->last_seen == ID) - valid=ops_check_user_id_certification_signature(&arg->pkey, - &arg->user_id, - &content->signature, - ops_get_public_key_from_data(signer), - arg->rarg->key->packets[arg->rarg->packet].raw); - else - valid=ops_check_user_attribute_certification_signature(&arg->pkey, - &arg->user_attribute, - &content->signature, - ops_get_public_key_from_data(signer), - arg->rarg->key->packets[arg->rarg->packet].raw); - - break; - - case OPS_SIG_SUBKEY: - // XXX: we should also check that the signer is the key we are validating, I think. - valid=ops_check_subkey_signature(&arg->pkey,&arg->subkey, - &content->signature, - ops_get_public_key_from_data(signer), - arg->rarg->key->packets[arg->rarg->packet].raw); - break; - - case OPS_SIG_DIRECT: - valid=ops_check_direct_signature(&arg->pkey,&content->signature, - ops_get_public_key_from_data(signer), - arg->rarg->key->packets[arg->rarg->packet].raw); - break; - - case OPS_SIG_STANDALONE: - case OPS_SIG_PRIMARY: - case OPS_SIG_REV_KEY: - case OPS_SIG_REV_SUBKEY: - case OPS_SIG_TIMESTAMP: - case OPS_SIG_3RD_PARTY: - OPS_ERROR_1(errors, OPS_E_UNIMPLEMENTED, - "Verification of signature type 0x%02x not yet implemented\n", content->signature.info.type); - break; - - default: - OPS_ERROR_1(errors, OPS_E_UNIMPLEMENTED, - "Unexpected signature type 0x%02x\n", content->signature.info.type); - } - - if(valid) - { - // printf(" validated\n"); - //++arg->result->valid_count; - add_sig_to_valid_list(arg->result, &content->signature.info); - } - else - { - OPS_ERROR(errors,OPS_E_V_BAD_SIGNATURE,"Bad Signature"); - // printf(" BAD SIGNATURE\n"); - // ++arg->result->invalid_count; - add_sig_to_invalid_list(arg->result, &content->signature.info); - } - break; - - // ignore these - case OPS_PARSER_PTAG: - case OPS_PTAG_CT_SIGNATURE_HEADER: - case OPS_PARSER_PACKET_END: - case OPS_PTAG_CT_TRUST: - break; - - case OPS_PARSER_CMD_GET_SK_PASSPHRASE: - if (arg->cb_get_passphrase) - { - return arg->cb_get_passphrase(content_,cbinfo); - } - break; - - default: - fprintf(stderr,"unexpected tag=0x%x\n",content_->tag); - //assert(0); - OPS_ERROR_1(errors, OPS_E_V_NO_SIGNATURE, "Unknown PTAG 0x%02x in validation packet\n",content_->tag); - break; - } - return OPS_RELEASE_MEMORY; -} - - ops_parse_cb_return_t -validate_data_cb(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo) -{ - const ops_parser_content_union_t *content=&content_->content; - validate_data_cb_arg_t *arg=ops_parse_cb_get_arg(cbinfo); - ops_error_t **errors=ops_parse_cb_get_errors(cbinfo); - const ops_keydata_t *signer; - ops_boolean_t valid=ops_false; - ops_memory_t* mem=NULL; - - if (debug) - printf("%s\n",ops_show_packet_tag(content_->tag)); - - switch(content_->tag) - { - case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER: - // ignore - this gives us the "Armor Header" line "Hash: SHA1" or similar - break; - - case OPS_PTAG_CT_LITERAL_DATA_HEADER: - // ignore - break; - - case OPS_PTAG_CT_LITERAL_DATA_BODY: - arg->literal_data_body=content->literal_data_body; - arg->use=LITERAL_DATA; - return OPS_KEEP_MEMORY; - break; - - case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY: - arg->signed_cleartext_body=content->signed_cleartext_body; - arg->use=SIGNED_CLEARTEXT; - return OPS_KEEP_MEMORY; - break; - - case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER: - // this gives us an ops_hash_t struct - break; - - case OPS_PTAG_CT_SIGNATURE: // V3 sigs - case OPS_PTAG_CT_SIGNATURE_FOOTER: // V4 sigs - - if (debug) - { - printf("\n*** hashed data:\n"); - unsigned int zzz=0; - for (zzz=0; zzzsignature.info.v4_hashed_data_length; zzz++) - printf("0x%02x ", content->signature.info.v4_hashed_data[zzz]); - printf("\n"); - printf(" type=%02x signer_id=",content->signature.info.type); - hexdump(content->signature.info.signer_id, - sizeof content->signature.info.signer_id); - } - - signer=ops_keyring_find_key_by_id(arg->keyring, - content->signature.info.signer_id); - if(!signer) - { - OPS_ERROR(errors,OPS_E_V_UNKNOWN_SIGNER,"Unknown Signer"); - add_sig_to_unknown_list(arg->result, &content->signature.info); - break; - } - - mem=ops_memory_new(); - ops_memory_init(mem,128); - - switch(content->signature.info.type) - { - case OPS_SIG_BINARY: - case OPS_SIG_TEXT: - switch(arg->use) - { - case LITERAL_DATA: - ops_memory_add(mem, - arg->literal_data_body.data, - arg->literal_data_body.length); - break; - - case SIGNED_CLEARTEXT: - ops_memory_add(mem, - arg->signed_cleartext_body.data, - arg->signed_cleartext_body.length); - break; - - default: - OPS_ERROR_1(errors,OPS_E_UNIMPLEMENTED,"Unimplemented Sig Use %d", arg->use); - printf(" Unimplemented Sig Use %d\n", arg->use); - break; - } - - valid=check_binary_signature(ops_memory_get_length(mem), - ops_memory_get_data(mem), - &content->signature, - ops_get_public_key_from_data(signer)); - break; - - default: - OPS_ERROR_1(errors, OPS_E_UNIMPLEMENTED, - "Verification of signature type 0x%02x not yet implemented\n", content->signature.info.type); - break; - - } - ops_memory_free(mem); - - if(valid) - { - add_sig_to_valid_list(arg->result, &content->signature.info); - } - else - { - OPS_ERROR(errors,OPS_E_V_BAD_SIGNATURE,"Bad Signature"); - add_sig_to_invalid_list(arg->result, &content->signature.info); - } - break; - - // ignore these - case OPS_PARSER_PTAG: - case OPS_PTAG_CT_SIGNATURE_HEADER: - case OPS_PTAG_CT_ARMOUR_HEADER: - case OPS_PTAG_CT_ARMOUR_TRAILER: - case OPS_PTAG_CT_ONE_PASS_SIGNATURE: - case OPS_PARSER_PACKET_END: - break; - - default: - fprintf(stderr,"unexpected tag=0x%x\n",content_->tag); - //assert(0); - OPS_ERROR_1(errors, OPS_E_V_NO_SIGNATURE, "Unknown PTAG 0x%02x in validation packet\n",content_->tag); - break; - } - return OPS_RELEASE_MEMORY; -} - -static void keydata_destroyer(ops_reader_info_t *rinfo) -{ free(ops_reader_get_arg(rinfo)); } - -void ops_keydata_reader_set(ops_parse_info_t *pinfo,const ops_keydata_t *key) -{ - validate_reader_arg_t *arg=malloc(sizeof *arg); - - memset(arg,'\0',sizeof *arg); - - arg->key=key; - arg->packet=0; - arg->offset=0; - - ops_reader_set(pinfo,keydata_reader,keydata_destroyer,arg); -} - -/** - * \ingroup HighLevel_Verify - * \brief Indicicates whether any errors were found - * \param result Validation result to check - * \return ops_false if any invalid signatures or unknown signers or no valid signatures; else ops_true - */ -ops_boolean_t validate_result_status(ops_validate_result_t* result) -{ - if (result->invalid_count || result->unknown_signer_count || !result->valid_count) - return ops_false; - else - return ops_true; -} - -/** - * \ingroup HighLevel_Verify - * \brief Validate all signatures on a single key against the given keyring - * \param result Where to put the result - * \param key Key to validate - * \param keyring Keyring to use for validation - * \param cb_get_passphrase Callback to use to get passphrase - * \return ops_true if all signatures OK; else ops_false - * \note It is the caller's responsiblity to free result after use. - * \sa ops_validate_result_free() - - Example Code: - \code - void example(const ops_keydata_t* key, const ops_keyring_t *keyring) - { - ops_validate_result_t *result=NULL; - if (ops_validate_key_signatures(result, key, keyring, callback_cmd_get_passphrase_from_cmdline)==ops_true) - printf("OK"); - else - printf("ERR"); - printf("valid=%d, invalid=%d, unknown=%d\n", - result->valid_count, - result->invalid_count, - result->unknown_signer_count); - ops_validate_result_free(result); - } - - \endcode - */ -ops_boolean_t ops_validate_key_signatures(ops_validate_result_t *result,const ops_keydata_t *key, - const ops_keyring_t *keyring, - ops_parse_cb_return_t cb_get_passphrase (const ops_parser_content_t *, ops_parse_cb_info_t *) - ) -{ - ops_parse_info_t *pinfo; - validate_key_cb_arg_t carg; - - memset(&carg,'\0',sizeof carg); - carg.result=result; - carg.cb_get_passphrase=cb_get_passphrase; - - pinfo=ops_parse_info_new(); - // ops_parse_options(&opt,OPS_PTAG_CT_SIGNATURE,OPS_PARSE_PARSED); - - carg.keyring=keyring; - - ops_parse_cb_set(pinfo,ops_validate_key_cb,&carg); - pinfo->rinfo.accumulate=ops_true; - ops_keydata_reader_set(pinfo,key); - - // Note: Coverity incorrectly reports an error that carg.rarg - // is never used. - carg.rarg=ops_reader_get_arg_from_pinfo(pinfo); - - ops_parse(pinfo,ops_true); - - ops_public_key_free(&carg.pkey); - if(carg.subkey.version) - ops_public_key_free(&carg.subkey); - ops_user_id_free(&carg.user_id); - ops_user_attribute_free(&carg.user_attribute); - - ops_parse_info_delete(pinfo); - -/* if(carg.literal_data_body.data != NULL) - free(carg.literal_data_body.data) ; */ - - if (result->invalid_count || result->unknown_signer_count || !result->valid_count) - return ops_false; - else - return ops_true; -} - -/** - \ingroup HighLevel_Verify - \param result Where to put the result - \param ring Keyring to use - \param cb_get_passphrase Callback to use to get passphrase - \note It is the caller's responsibility to free result after use. - \sa ops_validate_result_free() - */ -ops_boolean_t ops_validate_all_signatures(ops_validate_result_t *result, - const ops_keyring_t *ring, - ops_parse_cb_return_t cb_get_passphrase (const ops_parser_content_t *, ops_parse_cb_info_t *) - ) -{ - int n; - - memset(result,'\0',sizeof *result); - for(n=0 ; n < ring->nkeys ; ++n) - ops_validate_key_signatures(result,&ring->keys[n],ring, cb_get_passphrase); - return validate_result_status(result); -} - -/** - \ingroup HighLevel_Verify - \brief Frees validation result and associated memory - \param result Struct to be freed - \note Must be called after validation functions - */ -void ops_validate_result_free(ops_validate_result_t *result) -{ - if (!result) - return; - - if (result->valid_sigs) - free_signature_info(result->valid_sigs,result->valid_count); - if (result->invalid_sigs) - free_signature_info(result->invalid_sigs,result->invalid_count); - if (result->unknown_sigs) - free_signature_info(result->unknown_sigs,result->unknown_signer_count); - - free(result); - result=NULL; -} - -/** - \ingroup HighLevel_Verify - \brief Verifies the signatures in a signed file - \param result Where to put the result - \param filename Name of file to be validated - \param armoured Treat file as armoured, if set - \param keyring Keyring to use - \return ops_true if signatures validate successfully; ops_false if signatures fail or there are no signatures - \note After verification, result holds the details of all keys which - have passed, failed and not been recognised. - \note It is the caller's responsiblity to call ops_validate_result_free(result) after use. - - Example code: - \code - void example(const char* filename, const int armoured, const ops_keyring_t* keyring) - { - ops_validate_result_t* result=ops_mallocz(sizeof *result); - - if (ops_validate_file(result, filename, armoured, keyring)==ops_true) - { - printf("OK"); -// look at result for details of keys with good signatures -} -else -{ -printf("ERR"); -// look at result for details of failed signatures or unknown signers -} - -ops_validate_result_free(result); -} -\endcode - */ -ops_boolean_t ops_validate_file(ops_validate_result_t *result, const char* filename, const int armoured, const ops_keyring_t* keyring) -{ - ops_parse_info_t *pinfo=NULL; - validate_data_cb_arg_t validate_arg; - - int fd=0; - - // - fd=ops_setup_file_read(&pinfo, filename, &validate_arg, validate_data_cb, ops_true); - if (fd < 0) - return ops_false; - - // Set verification reader and handling options - - memset(&validate_arg,'\0',sizeof validate_arg); - validate_arg.result=result; - validate_arg.keyring=keyring; - // Note: Coverity incorrectly reports an error that carg.rarg - // is never used. - validate_arg.rarg=ops_reader_get_arg_from_pinfo(pinfo); - - if (armoured) - ops_reader_push_dearmour(pinfo); - - // Do the verification - - ops_parse(pinfo,ops_true); - - if (debug) - { - printf("valid=%d, invalid=%d, unknown=%d\n", - result->valid_count, - result->invalid_count, - result->unknown_signer_count); - } - - // Tidy up - if (armoured) - ops_reader_pop_dearmour(pinfo); - ops_teardown_file_read(pinfo, fd); - - if(validate_arg.literal_data_body.data != NULL) free(validate_arg.literal_data_body.data) ; - - return validate_result_status(result); -} - -/** - \ingroup HighLevel_Verify - \brief Verifies the signatures in a ops_memory_t struct - \param result Where to put the result - \param mem Memory to be validated - \param armoured Treat data as armoured, if set - \param keyring Keyring to use - \return ops_true if signature validates successfully; ops_false if not - \note After verification, result holds the details of all keys which - have passed, failed and not been recognised. - \note It is the caller's responsiblity to call ops_validate_result_free(result) after use. - */ - -ops_boolean_t ops_validate_mem(ops_validate_result_t *result, ops_memory_t* mem, const int armoured, const ops_keyring_t* keyring) -{ - ops_parse_info_t *pinfo=NULL; - validate_data_cb_arg_t validate_arg; - - // - ops_setup_memory_read(&pinfo, mem, &validate_arg, validate_data_cb, ops_true); - - // Set verification reader and handling options - - memset(&validate_arg,'\0',sizeof validate_arg); - validate_arg.result=result; - validate_arg.keyring=keyring; - // Note: Coverity incorrectly reports an error that carg.rarg - // is never used. - validate_arg.rarg=ops_reader_get_arg_from_pinfo(pinfo); - - if (armoured) - ops_reader_push_dearmour(pinfo); - - // Do the verification - - ops_parse(pinfo,ops_true); - - if (debug) - { - printf("valid=%d, invalid=%d, unknown=%d\n", - result->valid_count, - result->invalid_count, - result->unknown_signer_count); - } - - // Tidy up - if (armoured) - ops_reader_pop_dearmour(pinfo); - ops_teardown_memory_read(pinfo, mem); - - if(validate_arg.literal_data_body.data != NULL) free(validate_arg.literal_data_body.data) ; - if(validate_arg.signed_cleartext_body.data != NULL) free(validate_arg.signed_cleartext_body.data) ; - - return validate_result_status(result); -} - -/** - \ingroup HighLevel_Verify - \brief Verifies the signature in a detached signature data packet, given the literal data - \param literal_data Literal data that is signed - \param literal_data_length length of the literal data that is signed - \param signature_packet signature packet in binary PGP format - \param signature_packet_length length of the signature packet - \param signers_key Public key of the signer to check the signature for. - \return ops_true if signature validates successfully; ops_false if not - */ - -ops_boolean_t ops_validate_detached_signature(const void *literal_data, unsigned int literal_data_length, const unsigned char *signature_packet, unsigned int signature_packet_length,const ops_keydata_t *signers_key) -{ - ops_validate_result_t *result = (ops_validate_result_t*)ops_mallocz(sizeof(ops_validate_result_t)); - - ops_memory_t *mem = ops_memory_new() ; - ops_memory_add(mem,signature_packet,signature_packet_length) ; - - ops_parse_info_t *pinfo=NULL; - validate_data_cb_arg_t validate_arg; - - ops_setup_memory_read(&pinfo, mem, &validate_arg, validate_data_cb, ops_true); - - // Set verification reader and handling options - - ops_keyring_t tmp_keyring ; - tmp_keyring.nkeys = 1 ; - tmp_keyring.nkeys_allocated = 1 ; - tmp_keyring.keys = (ops_keydata_t *)signers_key ; // this is a const_cast, somehow - - memset(&validate_arg,'\0',sizeof validate_arg); - - validate_arg.result=result; - validate_arg.keyring=&tmp_keyring; - - int length = literal_data_length ; - - validate_arg.literal_data_body.data = (unsigned char *)malloc(length) ; - memcpy(validate_arg.literal_data_body.data, literal_data, length) ; - validate_arg.literal_data_body.length = length ; - - // Note: Coverity incorrectly reports an error that carg.rarg - // is never used. - validate_arg.rarg=ops_reader_get_arg_from_pinfo(pinfo); - - //if (armoured) - // ops_reader_push_dearmour(pinfo); - - // Do the verification - - ops_parse(pinfo,ops_true); - - if(debug) - printf("valid=%d, invalid=%d, unknown=%d\n", result->valid_count, result->invalid_count, result->unknown_signer_count); - - // Tidy up - //if (armoured) - // ops_reader_pop_dearmour(pinfo); - - ops_teardown_memory_read(pinfo, mem); - - ops_boolean_t res = validate_result_status(result); - ops_validate_result_free(result) ; - - if(validate_arg.literal_data_body.data != NULL) free(validate_arg.literal_data_body.data) ; - if(validate_arg.signed_cleartext_body.data != NULL) free(validate_arg.signed_cleartext_body.data) ; - - return res ; -} - -// eof diff --git a/openpgpsdk/src/openpgpsdk/validate.h b/openpgpsdk/src/openpgpsdk/validate.h deleted file mode 100644 index a078b7916..000000000 --- a/openpgpsdk/src/openpgpsdk/validate.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -typedef struct - { - unsigned int valid_count; - ops_signature_info_t * valid_sigs; - unsigned int invalid_count; - ops_signature_info_t * invalid_sigs; - unsigned int unknown_signer_count; - ops_signature_info_t * unknown_sigs; - } ops_validate_result_t; - -void ops_validate_result_free(ops_validate_result_t *result); - -ops_boolean_t ops_validate_key_signatures(ops_validate_result_t *result, - const ops_keydata_t* keydata, - const ops_keyring_t *ring, - ops_parse_cb_return_t cb (const ops_parser_content_t *, ops_parse_cb_info_t *)); -ops_boolean_t ops_validate_all_signatures(ops_validate_result_t *result, - const ops_keyring_t *ring, - ops_parse_cb_return_t (const ops_parser_content_t *, ops_parse_cb_info_t *)); - -void ops_keydata_reader_set(ops_parse_info_t *pinfo, - const ops_keydata_t *key); - -typedef struct - { - const ops_keydata_t *key; - unsigned packet; - unsigned offset; - } validate_reader_arg_t; - -/** Struct used with the validate_key_cb callback */ -typedef struct - { - ops_public_key_t pkey; - ops_public_key_t subkey; - ops_secret_key_t skey; - enum - { - ATTRIBUTE=1, - ID, - } last_seen; - ops_user_id_t user_id; - ops_user_attribute_t user_attribute; - unsigned char hash[OPS_MAX_HASH_SIZE]; - const ops_keyring_t *keyring; - validate_reader_arg_t *rarg; - ops_validate_result_t *result; - ops_parse_cb_return_t (*cb_get_passphrase) (const ops_parser_content_t *, ops_parse_cb_info_t *); - } validate_key_cb_arg_t; - -/** Struct use with the validate_data_cb callback */ -typedef struct validate_data_cb_arg - { - enum - { - LITERAL_DATA, - SIGNED_CLEARTEXT - } use; /* - -#include -#include -#include -#include -#include -#include -#include "keyring_local.h" -#include -#include -#include -#include -#include -#include -#ifndef WIN32 -#include -#endif - -#include - -//static int debug=0; - -/* - * return true if OK, otherwise false - */ -static ops_boolean_t base_write(const void *src,unsigned length, - ops_create_info_t *info) - { - return info->winfo.writer(src,length,&info->errors,&info->winfo); - } - -/** - * \ingroup Core_WritePackets - * - * \param src - * \param length - * \param info - * \return 1 if OK, otherwise 0 - */ - -ops_boolean_t ops_write(const void *src,unsigned length, - ops_create_info_t *info) - { - return base_write(src,length,info); - } - -/** - * \ingroup Core_WritePackets - * \param n - * \param length - * \param info - * \return ops_true if OK, otherwise ops_false - */ - -ops_boolean_t ops_write_scalar(unsigned n,unsigned length, - ops_create_info_t *info) - { - while(length-- > 0) - { - unsigned char c[1]; - - c[0]=n >> (length*8); - if(!base_write(c,1,info)) - return ops_false; - } - return ops_true; - } - -/** - * \ingroup Core_WritePackets - * \param bn - * \param info - * \return 1 if OK, otherwise 0 - */ - -ops_boolean_t ops_write_mpi(const BIGNUM *bn,ops_create_info_t *info) - { - unsigned char buf[8192]; - int bits=BN_num_bits(bn); - - assert(bits <= 65535); - BN_bn2bin(bn,buf); - return ops_write_scalar(bits,2,info) - && ops_write(buf,(bits+7)/8,info); - } - -/** - * \ingroup Core_WritePackets - * \param tag - * \param info - * \return 1 if OK, otherwise 0 - */ - -ops_boolean_t ops_write_ptag(ops_content_tag_t tag,ops_create_info_t *info) - { - unsigned char c[1]; - - c[0]=tag|OPS_PTAG_ALWAYS_SET|OPS_PTAG_NEW_FORMAT; - - return base_write(c,1,info); - } - -/** - * \ingroup Core_WritePackets - * \param length - * \param info - * \return 1 if OK, otherwise 0 - */ - -ops_boolean_t ops_write_length(unsigned length,ops_create_info_t *info) - { - unsigned char c[2]; - - if(length < 192) - { - c[0]=length; - return base_write(c,1,info); - } - else if(length < 8384) - { - c[0]=((length-192) >> 8)+192; - c[1]=(length-192)%256; - return base_write(c,2,info); - } - return ops_write_scalar(0xff,1,info) && ops_write_scalar(length,4,info); - } - -/* Note that we finalise from the top down, so we don't use writers below - * that have already been finalised - */ -ops_boolean_t writer_info_finalise(ops_error_t **errors, - ops_writer_info_t *winfo) - { - ops_boolean_t ret=ops_true; - - if(winfo->finaliser) - { - ret=winfo->finaliser(errors,winfo); - winfo->finaliser=NULL; - } - if(winfo->next && !writer_info_finalise(errors,winfo->next)) - { - winfo->finaliser=NULL; - return ops_false; - } - return ret; - } - -void writer_info_delete(ops_writer_info_t *winfo) - { - // we should have finalised before deleting - assert(!winfo->finaliser); - if(winfo->next) - { - writer_info_delete(winfo->next); - free(winfo->next); - winfo->next=NULL; - } - if(winfo->destroyer) - { - winfo->destroyer(winfo); - winfo->destroyer=NULL; - } - winfo->writer=NULL; - } - -/** - * \ingroup Core_Writers - * - * Set a writer in info. There should not be another writer set. - * - * \param info The info structure - * \param writer - * \param finaliser - * \param destroyer - * \param arg The argument for the writer and destroyer - */ -void ops_writer_set(ops_create_info_t *info, - ops_writer_t *writer, - ops_writer_finaliser_t *finaliser, - ops_writer_destroyer_t *destroyer, - void *arg) - { - assert(!info->winfo.writer); - info->winfo.writer=writer; - info->winfo.finaliser=finaliser; - info->winfo.destroyer=destroyer; - info->winfo.arg=arg; - } - -/** - * \ingroup Core_Writers - * - * Push a writer in info. There must already be another writer set. - * - * \param info The info structure - * \param writer - * \param finaliser - * \param destroyer - * \param arg The argument for the writer and destroyer - */ -void ops_writer_push(ops_create_info_t *info, - ops_writer_t *writer, - ops_writer_finaliser_t *finaliser, - ops_writer_destroyer_t *destroyer, - void *arg) - { - ops_writer_info_t *copy=ops_mallocz(sizeof *copy); - - assert(info->winfo.writer); - *copy=info->winfo; - info->winfo.next=copy; - - info->winfo.writer=writer; - info->winfo.finaliser=finaliser; - info->winfo.destroyer=destroyer; - info->winfo.arg=arg; - } - -void ops_writer_pop(ops_create_info_t *info) - { - ops_writer_info_t *next; - - // Make sure the finaliser has been called. - assert(!info->winfo.finaliser); - // Make sure this is a stacked writer - assert(info->winfo.next); - if(info->winfo.destroyer) - info->winfo.destroyer(&info->winfo); - - next=info->winfo.next; - info->winfo=*next; - - free(next); - } - -/** - * \ingroup Core_Writers - * - * Close the writer currently set in info. - * - * \param info The info structure - */ -ops_boolean_t ops_writer_close(ops_create_info_t *info) - { - ops_boolean_t ret=writer_info_finalise(&info->errors,&info->winfo); - - writer_info_delete(&info->winfo); - - return ret; - } - -/** - * \ingroup Core_Writers - * - * Get the arg supplied to ops_create_info_set_writer(). - * - * \param winfo The writer_info structure - * \return The arg - */ -void *ops_writer_get_arg(ops_writer_info_t *winfo) - { return winfo->arg; } - -/** - * \ingroup Core_Writers - * - * Write to the next writer down in the stack. - * - * \param src The data to write. - * \param length The length of src. - * \param errors A place to store errors. - * \param winfo The writer_info structure. - * \return Success - if ops_false, then errors should contain the error. - */ -ops_boolean_t ops_stacked_write(const void *src,unsigned length, - ops_error_t **errors,ops_writer_info_t *winfo) - { - return winfo->next->writer(src,length,errors,winfo->next); - } - -/** - * \ingroup Core_Writers - * - * Free the arg. Many writers just have a malloc()ed lump of storage, this - * function releases it. - * - * \param winfo the info structure. - */ -void ops_writer_generic_destroyer(ops_writer_info_t *winfo) - { free(ops_writer_get_arg(winfo)); } - -/** - * \ingroup Core_Writers - * - * A writer that just writes to the next one down. Useful for when you - * want to insert just a finaliser into the stack. - */ -ops_boolean_t ops_writer_passthrough(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo) - { return ops_stacked_write(src,length,errors,winfo); } - - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/writer.h b/openpgpsdk/src/openpgpsdk/writer.h deleted file mode 100644 index 2b15c8206..000000000 --- a/openpgpsdk/src/openpgpsdk/writer.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef OPS_WRITER_H -#define OPS_WRITER_H - -#include "types.h" -#include "packet.h" -#include "crypto.h" -#include "memory.h" -#include "errors.h" -#include "keyring.h" - -/** - * \ingroup Create - * This struct contains the required information about one writer - */ -/** - * \ingroup Writer - * the writer function prototype - */ - -typedef struct ops_writer_info ops_writer_info_t; -typedef ops_boolean_t ops_writer_t(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo); -typedef ops_boolean_t ops_writer_finaliser_t(ops_error_t **errors, - ops_writer_info_t *winfo); -typedef void ops_writer_destroyer_t(ops_writer_info_t *winfo); -/** Writer settings */ -struct ops_writer_info - { - ops_writer_t *writer; /*!< the writer itself */ - ops_writer_finaliser_t *finaliser; /*!< the writer's finaliser */ - ops_writer_destroyer_t *destroyer; /*!< the writer's destroyer */ - void *arg; /* writer-specific argument */ - ops_writer_info_t *next; /*!< next writer in the stack */ - }; - - -void *ops_writer_get_arg(ops_writer_info_t *winfo); -ops_boolean_t ops_stacked_write(const void *src,unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo); - -void ops_writer_set(ops_create_info_t *info, - ops_writer_t *writer, - ops_writer_finaliser_t *finaliser, - ops_writer_destroyer_t *destroyer, - void *arg); -void ops_writer_push(ops_create_info_t *info, - ops_writer_t *writer, - ops_writer_finaliser_t *finaliser, - ops_writer_destroyer_t *destroyer, - void *arg); -void ops_writer_pop(ops_create_info_t *info); -void ops_writer_generic_destroyer(ops_writer_info_t *winfo); -ops_boolean_t ops_writer_passthrough(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo); - -void ops_writer_set_fd(ops_create_info_t *info,int fd); -ops_boolean_t ops_writer_close(ops_create_info_t *info); - -ops_boolean_t ops_write(const void *src,unsigned length, - ops_create_info_t *opt); -ops_boolean_t ops_write_length(unsigned length,ops_create_info_t *opt); -ops_boolean_t ops_write_ptag(ops_content_tag_t tag,ops_create_info_t *opt); -ops_boolean_t ops_write_scalar(unsigned n,unsigned length, - ops_create_info_t *opt); -ops_boolean_t ops_write_mpi(const BIGNUM *bn,ops_create_info_t *opt); -ops_boolean_t ops_write_encrypted_mpi(const BIGNUM *bn, ops_crypt_t* crypt, ops_create_info_t *info); - -void writer_info_delete(ops_writer_info_t *winfo); -ops_boolean_t writer_info_finalise(ops_error_t **errors, ops_writer_info_t *winfo); - -#endif diff --git a/openpgpsdk/src/openpgpsdk/writer_armour.c b/openpgpsdk/src/openpgpsdk/writer_armour.c deleted file mode 100644 index cd828e6a6..000000000 --- a/openpgpsdk/src/openpgpsdk/writer_armour.c +++ /dev/null @@ -1,517 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include - -#include -#include -#include -#include - -#include - -static int debug=0; - -#define LINE_LENGTH 64 - -static const char newline[] = "\r\n"; - -/** - * \struct dash_escaped_arg_t - */ -typedef struct - { - ops_boolean_t seen_nl:1; - ops_boolean_t seen_cr:1; - ops_create_signature_t *sig; - ops_memory_t *trailing; - } dash_escaped_arg_t; - -static ops_boolean_t dash_escaped_writer(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo) - { - dash_escaped_arg_t *arg=ops_writer_get_arg(winfo); - unsigned n; - - if (debug) - { - unsigned int i=0; - fprintf(stderr,"dash_escaped_writer writing %d:\n", length); - for (i=0; iseen_nl) - { - if(src[n] == '-' && !ops_stacked_write("- ",2,errors,winfo)) - return ops_false; - arg->seen_nl=ops_false; - } - - arg->seen_nl=src[n] == '\n'; - - if(arg->seen_nl && !arg->seen_cr) - { - if(!ops_stacked_write("\r",1,errors,winfo)) - return ops_false; - ops_signature_add_data(arg->sig,"\r",1); - } - - arg->seen_cr=src[n] == '\r'; - - if(!ops_stacked_write(&src[n],1,errors,winfo)) - return ops_false; - - /* trailing whitespace isn't included in the signature */ - if(src[n] == ' ' || src[n] == '\t') - ops_memory_add(arg->trailing,&src[n],1); - else - { - if((l=ops_memory_get_length(arg->trailing))) - { - if(!arg->seen_nl && !arg->seen_cr) - ops_signature_add_data(arg->sig, - ops_memory_get_data(arg->trailing), - l); - ops_memory_clear(arg->trailing); - } - ops_signature_add_data(arg->sig,&src[n],1); - } - } - - return ops_true; - } - -/** - * \param winfo - */ -static void dash_escaped_destroyer(ops_writer_info_t *winfo) - { - dash_escaped_arg_t *arg=ops_writer_get_arg(winfo); - - ops_memory_free(arg->trailing); - free(arg); - } - -/** - * \ingroup Core_WritersNext - * \brief Push Clearsigned Writer onto stack - * \param info - * \param sig - */ -ops_boolean_t ops_writer_push_clearsigned(ops_create_info_t *info, - ops_create_signature_t *sig) - { - static char header[]="-----BEGIN PGP SIGNED MESSAGE-----\r\nHash: "; - const char *hash=ops_text_from_hash(ops_signature_get_hash(sig)); - dash_escaped_arg_t *arg=ops_mallocz(sizeof *arg); - - ops_boolean_t rtn; - - rtn= ( ops_write(header,sizeof header-1,info) - && ops_write(hash,strlen(hash),info) - && ops_write("\r\n\r\n",4,info)); - - if (rtn==ops_false) - { - OPS_ERROR(&info->errors, OPS_E_W, "Error pushing clearsigned header"); - free(arg); - return rtn; - } - - arg->seen_nl=ops_true; - arg->sig=sig; - arg->trailing=ops_memory_new(); - ops_writer_push(info,dash_escaped_writer,NULL,dash_escaped_destroyer,arg); - return rtn; - } - - -/** - * \struct base64_arg_t - */ -typedef struct - { - size_t chars_written; - ops_boolean_t writing_trailer; - unsigned pos; - unsigned char t; - unsigned checksum; - } base64_arg_t; - -static char b64map[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" -"0123456789+/"; - -static ops_boolean_t check_newline(base64_arg_t* arg, - ops_error_t **errors, - ops_writer_info_t *winfo) - { - arg->chars_written++; - if (!arg->writing_trailer && arg->chars_written % LINE_LENGTH == 0) - if (!ops_stacked_write(newline, strlen(newline), errors, winfo)) - return ops_false; - return ops_true; - } - -static ops_boolean_t base64_writer(const unsigned char *src, - unsigned length,ops_error_t **errors, - ops_writer_info_t *winfo) - { - base64_arg_t *arg=ops_writer_get_arg(winfo); - unsigned n; - - for(n=0 ; n < length ; ) - { - arg->checksum=ops_crc24(arg->checksum,src[n]); - if(arg->pos == 0) - { - /* XXXXXX00 00000000 00000000 */ - if(!ops_stacked_write(&b64map[src[n] >> 2],1,errors,winfo)) - return ops_false; - - /* 000000XX xxxx0000 00000000 */ - arg->t=(src[n++]&3) << 4; - arg->pos=1; - } - else if(arg->pos == 1) - { - /* 000000xx XXXX0000 00000000 */ - arg->t+=src[n] >> 4; - if(!ops_stacked_write(&b64map[arg->t],1,errors,winfo)) - return ops_false; - - /* 00000000 0000XXXX xx000000 */ - arg->t=(src[n++]&0xf) << 2; - arg->pos=2; - } - else if(arg->pos == 2) - { - /* 00000000 0000xxxx XX000000 */ - arg->t+=src[n] >> 6; - if(!ops_stacked_write(&b64map[arg->t],1,errors,winfo)) - return ops_false; - if(!check_newline(arg, errors, winfo)) - return ops_false; - - /* 00000000 00000000 00XXXXXX */ - if(!ops_stacked_write(&b64map[src[n++]&0x3f],1,errors,winfo)) - return ops_false; - - arg->pos=0; - } - if (!check_newline(arg, errors, winfo)) - return ops_false; - } - return ops_true; - } - -static ops_boolean_t signature_finaliser(ops_error_t **errors, - ops_writer_info_t *winfo) - { - base64_arg_t *arg=ops_writer_get_arg(winfo); - static char trailer[]="\r\n-----END PGP SIGNATURE-----\r\n"; - unsigned char c[3]; - - if(arg->pos) - { - if(!ops_stacked_write(&b64map[arg->t],1,errors,winfo)) - return ops_false; - if(arg->pos == 1 && !ops_stacked_write("==",2,errors,winfo)) - return ops_false; - if(arg->pos == 2 && !ops_stacked_write("=",1,errors,winfo)) - return ops_false; - } - /* Ready for the checksum */ - if(!ops_stacked_write("\r\n=",3,errors,winfo)) - return ops_false; - - arg->pos=0; /* get ready to write the checksum */ - - c[0]=arg->checksum >> 16; - c[1]=arg->checksum >> 8; - c[2]=arg->checksum; - /* push the checksum through our own writer. Turn off the - writing_body flag so we don't put a newline in the trailer. - */ - arg->writing_trailer = ops_true; - if(!base64_writer(c,3,errors,winfo)) - return ops_false; - - return ops_stacked_write(trailer,sizeof trailer-1,errors,winfo); - } - -/** - * \struct linebreak_arg_t - */ -typedef struct - { - unsigned pos; - } linebreak_arg_t; - -#define BREAKPOS 65 - -static ops_boolean_t linebreak_writer(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo) - { - linebreak_arg_t *arg=ops_writer_get_arg(winfo); - unsigned n; - - for(n=0 ; n < length ; ++n,++arg->pos) - { - if(src[n] == '\r' || src[n] == '\n') - arg->pos=0; - - if(arg->pos == BREAKPOS) - { - if(!ops_stacked_write(newline,strlen(newline),errors,winfo)) - return ops_false; - arg->pos=0; - } - if(!ops_stacked_write(&src[n],1,errors,winfo)) - return ops_false; - } - - return ops_true; - } - -/** - * \ingroup Core_WritersNext - * \brief Push armoured signature on stack - * \param info - */ -ops_boolean_t ops_writer_switch_to_armoured_signature(ops_create_info_t *info) - { - static char header[]="\r\n-----BEGIN PGP SIGNATURE-----\r\nVersion: " - OPS_VERSION_STRING "\r\n\r\n"; - base64_arg_t *base64; - - ops_writer_pop(info); - if (ops_write(header,sizeof header-1,info)==ops_false) - { - OPS_ERROR(&info->errors, OPS_E_W, "Error switching to armoured signature"); - return ops_false; - } - - ops_writer_push(info,linebreak_writer,NULL,ops_writer_generic_destroyer, - ops_mallocz(sizeof(linebreak_arg_t))); - - base64=ops_mallocz(sizeof *base64); - if (!base64) - { - OPS_MEMORY_ERROR(&info->errors); - return ops_false; - } - base64->checksum=CRC24_INIT; - ops_writer_push(info,base64_writer,signature_finaliser, - ops_writer_generic_destroyer,base64); - return ops_true; - } - -static ops_boolean_t armoured_message_finaliser(ops_error_t **errors, - ops_writer_info_t *winfo) - { - // TODO: This is same as signature_finaliser apart from trailer. - base64_arg_t *arg=ops_writer_get_arg(winfo); - static char trailer[]="\r\n-----END PGP MESSAGE-----\r\n"; - unsigned char c[3]; - - if(arg->pos) - { - if(!ops_stacked_write(&b64map[arg->t],1,errors,winfo)) - return ops_false; - if(arg->pos == 1 && !ops_stacked_write("==",2,errors,winfo)) - return ops_false; - if(arg->pos == 2 && !ops_stacked_write("=",1,errors,winfo)) - return ops_false; - } - /* Ready for the checksum */ - if(!ops_stacked_write("\r\n=",3,errors,winfo)) - return ops_false; - - arg->pos=0; /* get ready to write the checksum */ - - c[0]=arg->checksum >> 16; - c[1]=arg->checksum >> 8; - c[2]=arg->checksum; - /* push the checksum through our own writer. Turn off the - writing_body flag so we don't put a newline in the trailer. - */ - arg->writing_trailer = ops_true; - if(!base64_writer(c,3,errors,winfo)) - return ops_false; - - return ops_stacked_write(trailer,sizeof trailer-1,errors,winfo); - } - -/** - \ingroup Core_WritersNext - \brief Write a PGP MESSAGE - \todo replace with generic function -*/ -void ops_writer_push_armoured_message(ops_create_info_t *info) -// ops_create_signature_t *sig) - { - static char header[]="-----BEGIN PGP MESSAGE-----\r\n"; - - base64_arg_t *base64; - - ops_write(header,sizeof header-1,info); - ops_write(newline,strlen(newline),info); - base64=ops_mallocz(sizeof *base64); - base64->checksum=CRC24_INIT; - ops_writer_push(info,base64_writer,armoured_message_finaliser,ops_writer_generic_destroyer,base64); - } - -static ops_boolean_t armoured_finaliser(ops_armor_type_t type, ops_error_t **errors, - ops_writer_info_t *winfo) - { - static char tail_public_key[]="\r\n-----END PGP PUBLIC KEY BLOCK-----\r\n"; - static char tail_private_key[]="\r\n-----END PGP PRIVATE KEY BLOCK-----\r\n"; - - char* tail=NULL; - unsigned int sz_tail=0; - - switch(type) - { - case OPS_PGP_PUBLIC_KEY_BLOCK: - tail=tail_public_key; - sz_tail=sizeof tail_public_key-1; - break; - - case OPS_PGP_PRIVATE_KEY_BLOCK: - tail=tail_private_key; - sz_tail=sizeof tail_private_key-1; - break; - - default: - assert(0); - } - - base64_arg_t *arg=ops_writer_get_arg(winfo); - unsigned char c[3]; - - if(arg->pos) - { - if(!ops_stacked_write(&b64map[arg->t],1,errors,winfo)) - return ops_false; - if(arg->pos == 1 && !ops_stacked_write("==",2,errors,winfo)) - return ops_false; - if(arg->pos == 2 && !ops_stacked_write("=",1,errors,winfo)) - return ops_false; - } - - /* Ready for the checksum */ - if(!ops_stacked_write("\r\n=",3,errors,winfo)) - return ops_false; - - arg->pos=0; /* get ready to write the checksum */ - - c[0]=arg->checksum >> 16; - c[1]=arg->checksum >> 8; - c[2]=arg->checksum; - /* push the checksum through our own writer. Turn off the - writing_body flag so we don't put a newline in the trailer. - */ - arg->writing_trailer = ops_true; - if(!base64_writer(c,3,errors,winfo)) - return ops_false; - - return ops_stacked_write(tail,sz_tail,errors,winfo); - } - -static ops_boolean_t armoured_public_key_finaliser(ops_error_t **errors, - ops_writer_info_t *winfo) - { - return armoured_finaliser(OPS_PGP_PUBLIC_KEY_BLOCK,errors,winfo); - } - -static ops_boolean_t armoured_private_key_finaliser(ops_error_t **errors, - ops_writer_info_t *winfo) - { - return armoured_finaliser(OPS_PGP_PRIVATE_KEY_BLOCK,errors,winfo); - } - -// \todo use this for other armoured types -/** - \ingroup Core_WritersNext - \brief Push Armoured Writer on stack (generic) -*/ -void ops_writer_push_armoured(ops_create_info_t *info, ops_armor_type_t type) - { - static char hdr_public_key[]="-----BEGIN PGP PUBLIC KEY BLOCK-----\r\nVersion: " - OPS_VERSION_STRING "\r\n\r\n"; - static char hdr_private_key[]="-----BEGIN PGP PRIVATE KEY BLOCK-----\r\nVersion: " - OPS_VERSION_STRING "\r\n\r\n"; - - char* header=NULL; - unsigned int sz_hdr=0; - ops_boolean_t (* finaliser)(ops_error_t **errors, ops_writer_info_t *winfo); - - switch(type) - { - case OPS_PGP_PUBLIC_KEY_BLOCK: - header=hdr_public_key; - sz_hdr=sizeof hdr_public_key-1; - finaliser=armoured_public_key_finaliser; - break; - - case OPS_PGP_PRIVATE_KEY_BLOCK: - header=hdr_private_key; - sz_hdr=sizeof hdr_private_key-1; - finaliser=armoured_private_key_finaliser; - break; - - default: - assert(0); - } - - ops_write(header,sz_hdr,info); - - ops_writer_push(info,linebreak_writer,NULL,ops_writer_generic_destroyer, - ops_mallocz(sizeof(linebreak_arg_t))); - - base64_arg_t *arg=ops_mallocz(sizeof *arg); - arg->checksum=CRC24_INIT; - ops_writer_push(info,base64_writer,finaliser,ops_writer_generic_destroyer,arg); - } - - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/writer_armoured.h b/openpgpsdk/src/openpgpsdk/writer_armoured.h deleted file mode 100644 index bf81141b8..000000000 --- a/openpgpsdk/src/openpgpsdk/writer_armoured.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -ops_boolean_t ops_writer_push_clearsigned(ops_create_info_t *info, - ops_create_signature_t *sig); -void ops_writer_push_armoured_message(ops_create_info_t *info); -ops_boolean_t ops_writer_switch_to_armoured_signature(ops_create_info_t *info); - -void ops_writer_push_armoured(ops_create_info_t *info, ops_armor_type_t type); - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/writer_encrypt.c b/openpgpsdk/src/openpgpsdk/writer_encrypt.c deleted file mode 100644 index 4224fca42..000000000 --- a/openpgpsdk/src/openpgpsdk/writer_encrypt.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include - -static int debug=0; - -typedef struct - { - ops_crypt_t* crypt; - int free_crypt; - } crypt_arg_t; - -/* - * This writer simply takes plaintext as input, - * encrypts it with the given key - * and outputs the resulting encrypted text - */ -static ops_boolean_t encrypt_writer(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo) - { - -#define BUFSZ 1024 // arbitrary number - unsigned char encbuf[BUFSZ]; - unsigned remaining=length; - unsigned done=0; - - crypt_arg_t *arg=(crypt_arg_t *)ops_writer_get_arg(winfo); - - if (!ops_is_sa_supported(arg->crypt->algorithm)) - assert(0); // \todo proper error handling - - while (remaining) - { - unsigned len = remaining < BUFSZ ? remaining : BUFSZ; - // memcpy(buf,src,len); // \todo copy needed here? - - arg->crypt->cfb_encrypt(arg->crypt, encbuf, src+done, len); - - if (debug) - { - int i=0; - fprintf(stderr,"WRITING:\nunencrypted: "); - for (i=0; i<16; i++) - fprintf(stderr,"%2x ", src[done+i]); - fprintf(stderr,"\n"); - fprintf(stderr,"encrypted: "); - for (i=0; i<16; i++) - fprintf(stderr,"%2x ", encbuf[i]); - fprintf(stderr,"\n"); - } - - if (!ops_stacked_write(encbuf,len,errors,winfo)) - { - if (debug) - { fprintf(stderr, "encrypted_writer got error from stacked write, returning\n"); } - return ops_false; - } - remaining-=len; - done+=len; - } - - return ops_true; - } - -static void encrypt_destroyer (ops_writer_info_t *winfo) - - { - crypt_arg_t *arg=(crypt_arg_t *)ops_writer_get_arg(winfo); - if (arg->free_crypt) - free(arg->crypt); - free (arg); - } - -/** -\ingroup Core_WritersNext -\brief Push Encrypted Writer onto stack (create SE packets) -*/ -void ops_writer_push_encrypt_crypt(ops_create_info_t *cinfo, - ops_crypt_t *crypt) - { - // Create arg to be used with this writer - // Remember to free this in the destroyer - - crypt_arg_t *arg=ops_mallocz(sizeof *arg); - - // Setup the arg - - arg->crypt=crypt; - arg->free_crypt=0; - - // And push writer on stack - ops_writer_push(cinfo,encrypt_writer,NULL,encrypt_destroyer,arg); - - } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/writer_encrypt_se_ip.c b/openpgpsdk/src/openpgpsdk/writer_encrypt_se_ip.c deleted file mode 100644 index 0c1b2c78d..000000000 --- a/openpgpsdk/src/openpgpsdk/writer_encrypt_se_ip.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include - -#ifndef WIN32 - #include -#endif - -#include - -#include "keyring_local.h" -#include -#include -#include -#include -#include -#include - -static int debug=0; - -typedef struct - { - ops_crypt_t* crypt; - } encrypt_se_ip_arg_t; - -static ops_boolean_t encrypt_se_ip_writer(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo); -static void encrypt_se_ip_destroyer(ops_writer_info_t *winfo); - -// - -/** -\ingroup Core_WritersNext -\brief Push Encrypted SE IP Writer onto stack -*/ -void ops_writer_push_encrypt_se_ip(ops_create_info_t *cinfo, - const ops_keydata_t *pub_key) - { - ops_crypt_t *encrypt; - unsigned char *iv=NULL; - - // Create arg to be used with this writer - // Remember to free this in the destroyer - encrypt_se_ip_arg_t *arg=ops_mallocz(sizeof *arg); - - // Create and write encrypted PK session key - ops_pk_session_key_t *encrypted_pk_session_key; - encrypted_pk_session_key=ops_create_pk_session_key(pub_key); - ops_write_pk_session_key(cinfo, encrypted_pk_session_key); - - // Setup the arg - encrypt=ops_mallocz(sizeof *encrypt); - ops_crypt_any(encrypt, encrypted_pk_session_key->symmetric_algorithm); - iv=ops_mallocz(encrypt->blocksize); - encrypt->set_iv(encrypt, iv); - encrypt->set_key(encrypt, &encrypted_pk_session_key->key[0]); - ops_encrypt_init(encrypt); - - arg->crypt=encrypt; - - // And push writer on stack - ops_writer_push(cinfo, encrypt_se_ip_writer, NULL, encrypt_se_ip_destroyer, - arg); - // tidy up - ops_pk_session_key_free(encrypted_pk_session_key); - free(encrypted_pk_session_key); - free(iv); - } - -static ops_boolean_t encrypt_se_ip_writer(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo) - { - encrypt_se_ip_arg_t *arg=ops_writer_get_arg(winfo); - - ops_boolean_t rtn=ops_true; - - ops_memory_t *mem_literal; - ops_create_info_t *cinfo_literal; - - ops_memory_t *mem_compressed; - ops_create_info_t *cinfo_compressed; - - ops_memory_t *my_mem; - ops_create_info_t *my_cinfo; - - const unsigned int bufsz=128; // initial value; gets expanded as necessary - ops_setup_memory_write(&cinfo_literal, &mem_literal, bufsz); - ops_setup_memory_write(&cinfo_compressed, &mem_compressed, bufsz); - ops_setup_memory_write(&my_cinfo, &my_mem, bufsz); - - // create literal data packet from source data - ops_write_literal_data_from_buf(src, length, OPS_LDT_BINARY, cinfo_literal); - assert(ops_memory_get_length(mem_literal) > length); - - // create compressed packet from literal data packet - ops_write_compressed(ops_memory_get_data(mem_literal), - ops_memory_get_length(mem_literal), - cinfo_compressed); - - // create SE IP packet set from this compressed literal data - ops_write_se_ip_pktset(ops_memory_get_data(mem_compressed), - ops_memory_get_length(mem_compressed), - arg->crypt, my_cinfo); - assert(ops_memory_get_length(my_mem) - > ops_memory_get_length(mem_compressed)); - - // now write memory to next writer - rtn=ops_stacked_write(ops_memory_get_data(my_mem), - ops_memory_get_length(my_mem), - errors, winfo); - - ops_memory_free(my_mem); - ops_memory_free(mem_compressed); - ops_memory_free(mem_literal); - - return rtn; - } - -static void encrypt_se_ip_destroyer (ops_writer_info_t *winfo) - - { - encrypt_se_ip_arg_t *arg=ops_writer_get_arg(winfo); - - free(arg->crypt); - free(arg); - } - -ops_boolean_t ops_write_se_ip_pktset(const unsigned char *data, - const unsigned int len, - ops_crypt_t *crypt, - ops_create_info_t *cinfo) - { - unsigned char hashed[SHA_DIGEST_LENGTH]; - const size_t sz_mdc=1+1+SHA_DIGEST_LENGTH; - - size_t sz_preamble=crypt->blocksize+2; - unsigned char* preamble=ops_mallocz(sz_preamble); - - size_t sz_buf=sz_preamble+len+sz_mdc; - - ops_memory_t *mem_mdc; - ops_create_info_t *cinfo_mdc; - - if (!ops_write_ptag(OPS_PTAG_CT_SE_IP_DATA, cinfo) - || !ops_write_length(1+sz_buf, cinfo) - || !ops_write_scalar(SE_IP_DATA_VERSION, 1, cinfo)) - { - free (preamble); - return 0; - } - - ops_random(preamble, crypt->blocksize); - preamble[crypt->blocksize]=preamble[crypt->blocksize-2]; - preamble[crypt->blocksize+1]=preamble[crypt->blocksize-1]; - - if (debug) - { - unsigned int i=0; - fprintf(stderr,"\npreamble: "); - for (i=0; i -#include -#include -#endif - -#include - -#include - -typedef struct - { - int fd; - } writer_fd_arg_t; - -static ops_boolean_t fd_writer(const unsigned char *src,unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo) - { - writer_fd_arg_t *arg=ops_writer_get_arg(winfo); - int n=write(arg->fd,src,length); - - if(n == -1) - { - OPS_SYSTEM_ERROR_1(errors,OPS_E_W_WRITE_FAILED,"write", - "file descriptor %d",arg->fd); - return ops_false; - } - - if((unsigned)n != length) - { - OPS_ERROR_1(errors,OPS_E_W_WRITE_TOO_SHORT, - "file descriptor %d",arg->fd); - return ops_false; - } - - return ops_true; - } - -static void fd_destroyer(ops_writer_info_t *winfo) - { - free(ops_writer_get_arg(winfo)); - } - -/** - * \ingroup Core_WritersFirst - * \brief Write to a File - * - * Set the writer in info to be a stock writer that writes to a file - * descriptor. If another writer has already been set, then that is - * first destroyed. - * - * \param info The info structure - * \param fd The file descriptor - * - */ - -void ops_writer_set_fd(ops_create_info_t *info,int fd) - { - writer_fd_arg_t *arg=malloc(sizeof *arg); - - arg->fd=fd; - ops_writer_set(info,fd_writer,NULL,fd_destroyer,arg); - } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/writer_literal.c b/openpgpsdk/src/openpgpsdk/writer_literal.c deleted file mode 100644 index 64b3f650c..000000000 --- a/openpgpsdk/src/openpgpsdk/writer_literal.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2005-2009 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer, Alasdair Mackintosh. - * The Contributors have asserted their moral rights under the - * UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** Writes a literal data packet, using the partial data length encoding. - */ - -#include -#include - -#ifndef WIN32 -#include -#endif - -#include -#include -#include - -//#define MIN_PARTIAL_DATA_LENGTH 512 // now defined in partial.h -#define MAX_PARTIAL_DATA_LENGTH 1073741824 - - -ops_boolean_t write_literal_header(ops_create_info_t *info, - void *header_data) - { - OPS_USED(header_data); - // \todo add the literal type as a header_data argument - // \todo add filename - // \todo add date - // \todo do we need to check text data for line endings ? - - ops_write_scalar(OPS_LDT_BINARY, 1, info); // data type - ops_write_scalar(0, 1, info); // Filename (length = 0) - ops_write_scalar(0, 4, info); // Date (unspecified) - return ops_true; - } - -/** - * \ingroup InternalAPI - * \brief Pushes a literal writer onto the stack. - * \param cinfo the writer info - * \param buf_size the size of the internal buffer. For best - * throughput, write data in multiples of buf_size - */ -void ops_writer_push_literal_with_opts(ops_create_info_t *cinfo, - unsigned int buf_size) - { - // The literal writer doesn't need to transform the data, so we just - // push a partial packet writer onto the stack. This will handle - // the packet length encoding. All we need to provide is a function - // to write the header. - ops_writer_push_partial(buf_size, cinfo, OPS_PTAG_CT_LITERAL_DATA, - write_literal_header, NULL); - -} - -/** - * \ingroup InternalAPI - * \brief Pushes a literal writer onto the stack. - * \param cinfo the writer info - */ -void ops_writer_push_literal(ops_create_info_t *cinfo) - { - ops_writer_push_literal_with_opts(cinfo, 0); - } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/writer_memory.c b/openpgpsdk/src/openpgpsdk/writer_memory.c deleted file mode 100644 index 0c8fa57c4..000000000 --- a/openpgpsdk/src/openpgpsdk/writer_memory.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include -#include -#include - -#include - -static ops_boolean_t memory_writer(const unsigned char *src,unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo) - { - ops_memory_t *mem=ops_writer_get_arg(winfo); - - OPS_USED(errors); - ops_memory_add(mem,src,length); - return ops_true; - } - -/** - * \ingroup Core_WritersFirst - * \brief Write to memory - * - * Set a memory writer. - * - * \param info The info structure - * \param mem The memory structure - * \note It is the caller's responsiblity to call ops_memory_free(mem) - * \sa ops_memory_free() - */ - -void ops_writer_set_memory(ops_create_info_t *info,ops_memory_t *mem) - { - ops_writer_set(info,memory_writer,NULL,NULL,mem); - } - - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/writer_partial.c b/openpgpsdk/src/openpgpsdk/writer_partial.c deleted file mode 100644 index 9c59c27f9..000000000 --- a/openpgpsdk/src/openpgpsdk/writer_partial.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright (c) 2005-2009 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer, Alasdair Mackintosh. - * The Contributors have asserted their moral rights under the - * UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** Writes data using a series of partial body length headers. - * (See RFC 4880 4.2.2.4). This is normally used in conjunction - * with a streaming writer of some kind that needs to write out - * data packets of unknown length. - */ - -#include -#include - -#ifndef WIN32 -#include -#endif - -#include -#include -#include -#include - -static const int debug = 0; - -#define MAX_PARTIAL_DATA_LENGTH 1073741824 - -typedef struct - { - size_t packet_size; // size of packets - ops_memory_t *buffer; // Data is buffered here until written - ops_content_tag_t tag; // Packet tag - ops_memory_t *header; // Header is written here - ops_boolean_t written_first; // Has the first packet been written? - ops_write_partial_trailer_t *trailer_fn; // Custom end-of-packet fn - void *trailer_data; // data for end-of-packet fn - } stream_partial_arg_t; - - - -static unsigned int ops_calc_partial_data_length(unsigned int len) - { - int i; - unsigned int mask = MAX_PARTIAL_DATA_LENGTH; - assert( len > 0 ); - - if (len > MAX_PARTIAL_DATA_LENGTH) - return MAX_PARTIAL_DATA_LENGTH; - - for (i = 0 ; i <= 30 ; i++) - { - if (mask & len) - break; - mask >>= 1; - } - - return mask; - } - -static ops_boolean_t ops_write_partial_data_length(unsigned int len, - ops_create_info_t *info) - { - // len must be a power of 2 from 0 to 30 - unsigned i; - unsigned char c[1]; - - for (i = 0 ; i <= 30 ; i++) - if ((len >> i) & 1) - break; - - assert((1u << i) == len); - - c[0] = 224 + i; - - return ops_write(c, 1, info); - } - -static ops_boolean_t write_partial_data(const unsigned char *data, - size_t len, - ops_create_info_t *info) - { - if (debug) - fprintf(stderr, "Writing %zu bytes\n", len); - while (len > 0) - { - size_t pdlen = ops_calc_partial_data_length(len); - ops_write_partial_data_length(pdlen, info); - ops_write(data, pdlen, info); - data += pdlen; - len -= pdlen; - } - return ops_true; - } - -static ops_boolean_t write_partial_data_first(stream_partial_arg_t *arg, - const unsigned char *data, - unsigned int len, - ops_create_info_t *info) - { - size_t header_len = ops_memory_get_length(arg->header); - - size_t sz_towrite = len + header_len; - size_t sz_pd = ops_calc_partial_data_length(sz_towrite); - size_t first_data_len = (sz_pd - header_len); - assert(sz_pd >= MIN_PARTIAL_DATA_LENGTH); - - if (debug) - fprintf(stderr, "Writing first packet of len %zu (%zu + %u)\n", - sz_towrite, header_len, len); - - // Write the packet tag, the partial size and the header, followed - // by the first chunk of data and then the remainder of the data. - // (We have to do this in two chunks, as the partial length may not - // match the number of bytes to write.) - return ops_write_ptag(arg->tag, info) && - ops_write_partial_data_length(sz_pd, info) && - ops_write(ops_memory_get_data(arg->header), header_len, info) && - ops_write(data, first_data_len, info) && - write_partial_data(data + first_data_len, len - first_data_len, info); - } - -/* - * Writes out the last packet. The length is encoded as a fixed-length - * packet. Note that even if there is no data accumulated in the - * buffer, we stil lneed to write out a packet, as the final packet in - * a partially-encoded stream must be a fixed-lngth packet. - */ -static ops_boolean_t write_partial_data_last(stream_partial_arg_t *arg, - ops_create_info_t *info) - { - size_t buffer_length = ops_memory_get_length(arg->buffer); - if (debug) - fprintf(stderr, "writing final packet of %zu bytes\n", buffer_length); - return ops_write_length(buffer_length, info) && - ops_write(ops_memory_get_data(arg->buffer), buffer_length, info); - } - -/* - * Writes out the data accumulated in the in-memory buffer. - */ -static ops_boolean_t flush_buffer(stream_partial_arg_t *arg, - ops_create_info_t *info) - { - ops_boolean_t result = ops_true; - size_t buffer_length = ops_memory_get_length(arg->buffer); - if (buffer_length > 0) - { - if (debug) - fprintf(stderr, "Flushing %zu bytes\n", buffer_length); - - result = write_partial_data(ops_memory_get_data(arg->buffer), - buffer_length, - info); - ops_memory_clear(arg->buffer); - } - return result; - } - -static ops_boolean_t stream_partial_writer(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo) - { - stream_partial_arg_t *arg = ops_writer_get_arg(winfo); - - // For the first write operation, we need to write out the header - // plus the data. The total size that we write out must be at least - // MIN_PARTIAL_DATA_LENGTH bytes. (See RFC 4880, sec 4.2.2.4, - // Partial Body Lengths.) If we are given less than this, - // then we need to store the data in the buffer until we have the - // minumum - if (!arg->written_first) - { - ops_memory_add(arg->buffer, src, length); - size_t buffer_length = ops_memory_get_length(arg->buffer); - size_t header_length = ops_memory_get_length(arg->header); - if (header_length + buffer_length < MIN_PARTIAL_DATA_LENGTH) - { - if (debug) - fprintf(stderr, "Storing %zu (%zu + %zu) bytes\n", - header_length + buffer_length, header_length, - buffer_length); - return ops_true; // will wait for more data or end of stream - } - arg->written_first = ops_true; - - // Create a writer that will write to the parent stream. Allows - // useage of ops_write_ptag, etc. - ops_create_info_t parent_info; - ops_prepare_parent_info(&parent_info, winfo); - ops_boolean_t result = - write_partial_data_first(arg, ops_memory_get_data(arg->buffer), - buffer_length, &parent_info); - ops_memory_clear(arg->buffer); - ops_move_errors(&parent_info, errors); - return result; - } - else - { - size_t buffer_length = ops_memory_get_length(arg->buffer); - if (buffer_length + length < arg->packet_size) - { - ops_memory_add(arg->buffer, src, length); - if (debug) - fprintf(stderr, "Storing %u bytes (total %zu)\n", - length, buffer_length); - return ops_true; - } - else - { - ops_create_info_t parent_info; - parent_info.winfo = *winfo->next; - parent_info.errors = *errors; - return flush_buffer(arg, &parent_info) && - write_partial_data(src, length, &parent_info); - } - } - return ops_true; - } - -/* - * Invoked when the total packet size is less than - * MIN_PARTIAL_DATA_LENGTH. In that case, we write out the whole - * packet in a single operation, without using partial body length - * packets. - */ -static ops_boolean_t write_complete_packet(stream_partial_arg_t *arg, - ops_create_info_t *info) - { - size_t data_len = ops_memory_get_length(arg->buffer); - size_t header_len = ops_memory_get_length(arg->header); - - // Write the header tag, the length of the packet, and the - // packet. Note that the packet includes the header - // bytes. - size_t total = data_len + header_len; - if (debug) - fprintf(stderr, "writing entire packet with length %zu (%zu + %zu)\n", - total, data_len, header_len); - return ops_write_ptag(arg->tag, info) && - ops_write_length(total, info) && - ops_write(ops_memory_get_data(arg->header), header_len, info) && - ops_write(ops_memory_get_data(arg->buffer), data_len, info); - } - -static ops_boolean_t stream_partial_finaliser(ops_error_t **errors, - ops_writer_info_t *winfo) - { - stream_partial_arg_t *arg = ops_writer_get_arg(winfo); - // write last chunk of data - - // Create a writer that will write to the parent stream. Allows - // useage of ops_write_ptag, etc. - ops_create_info_t parent_info; - ops_prepare_parent_info(&parent_info, winfo); - ops_boolean_t result; - if (!arg->written_first) - result = write_complete_packet(arg, &parent_info); - else - // finish writing - result = write_partial_data_last(arg, &parent_info); - if (result && arg->trailer_fn != NULL) - result = arg->trailer_fn(&parent_info, arg->trailer_data); - ops_move_errors(&parent_info, errors); - return result; - } - -static void stream_partial_destroyer(ops_writer_info_t *winfo) - { - stream_partial_arg_t *arg = ops_writer_get_arg(winfo); - ops_memory_free(arg->buffer); - ops_memory_free(arg->header); - free(arg); - } - -/** - * \ingroup InternalAPI - * \brief Pushes a partial packet writer onto the stack. - * - * This writer is used in conjunction with another writer that - * generates streaming data of unknown length. The partial writer - * handles the various partial body length packets. When writing the - * initial packet header, the partial writer will write out the given - * tag, write out an initial length, and then invoke the 'header' - * function to write the remainder of the header. Note that the header - * function should not write a packet tag or a length. - * - * \param packet_size the expected size of the incoming packets. Must - * be >= 512 bytes. Must be a power of 2. The partial writer - * will buffer incoming writes into packets of this size. Note - * that writes will be most efficient if done in chunks of - * packet_size. If the packet size is unknown, specify 0, and - * the default size will be used. - * \param cinfo the writer info - * \param tag the packet tag - * \param header_writer a function that writes the packet header. - * \param header_data passed into header_writer - */ -void ops_writer_push_partial(size_t packet_size, - ops_create_info_t *cinfo, - ops_content_tag_t tag, - ops_write_partial_header_t *header_writer, - void *header_data) - { - ops_writer_push_partial_with_trailer(packet_size, cinfo, tag, header_writer, - header_data, NULL, NULL); - } - -/** - * \ingroup InternalAPI - * \brief Pushes a partial packet writer onto the stack. Adds a trailer - * function that will be invoked after writing out the partial - * packet. - * - * This writer is primarily used by the signature writer, which needs - * to append a signature packet after the literal data packet. - * - * \param trailer_writer a function that writes the trailer - * \param trailer_data passed into trailer_data - * \see ops_writer_push_partial - * \see ops_writer_push_signed - */ -void ops_writer_push_partial_with_trailer( - size_t packet_size, - ops_create_info_t *cinfo, - ops_content_tag_t tag, - ops_write_partial_header_t *header_writer, - void *header_data, - ops_write_partial_trailer_t *trailer_writer, - void *trailer_data) - { - if (packet_size == 0) - packet_size = MIN_PARTIAL_DATA_LENGTH; - assert(packet_size >= MIN_PARTIAL_DATA_LENGTH); - // Verify that the packet size is a valid power of 2. - assert(ops_calc_partial_data_length(packet_size) == packet_size); - - // Create arg to be used with this writer - // Remember to free this in the destroyer - stream_partial_arg_t *arg = ops_mallocz(sizeof *arg); - arg->tag = tag; - arg->written_first = ops_false; - arg->packet_size = packet_size; - arg->buffer = ops_memory_new(); - ops_memory_init(arg->buffer, arg->packet_size); - arg->trailer_fn = trailer_writer; - arg->trailer_data = trailer_data; - - // Write out the header into the memory buffer. Later we will write - // this buffer to the underlying output stream. - ops_create_info_t *header_info; - ops_setup_memory_write(&header_info, &arg->header, 128); - header_writer(header_info, header_data); - ops_writer_close(header_info); - ops_create_info_delete(header_info); - - // And push writer on stack - ops_writer_push(cinfo, stream_partial_writer, stream_partial_finaliser, - stream_partial_destroyer, arg); - } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/writer_skey_checksum.c b/openpgpsdk/src/openpgpsdk/writer_skey_checksum.c deleted file mode 100644 index 6b8a480de..000000000 --- a/openpgpsdk/src/openpgpsdk/writer_skey_checksum.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include - -#include - -//static int debug=0; - -typedef struct - { - ops_hash_algorithm_t hash_algorithm; - ops_hash_t hash; - unsigned char *hashed; - } skey_checksum_arg_t; - -static ops_boolean_t skey_checksum_writer(const unsigned char *src, const unsigned length, ops_error_t **errors, ops_writer_info_t *winfo) - { - skey_checksum_arg_t *arg=ops_writer_get_arg(winfo); - ops_boolean_t rtn=ops_true; - - // add contents to hash - arg->hash.add(&arg->hash, src, length); - - // write to next stacked writer - rtn=ops_stacked_write(src,length,errors,winfo); - - // tidy up and return - return rtn; - } - -static ops_boolean_t skey_checksum_finaliser(ops_error_t **errors __attribute__((unused)), ops_writer_info_t *winfo) - { - skey_checksum_arg_t *arg=ops_writer_get_arg(winfo); - arg->hash.finish(&arg->hash, arg->hashed); - return ops_true; - } - -static void skey_checksum_destroyer(ops_writer_info_t* winfo) - { - skey_checksum_arg_t *arg=ops_writer_get_arg(winfo); - free(arg); - } - -/** -\ingroup Core_WritersNext -\param cinfo -\param skey -*/ -void ops_push_skey_checksum_writer(ops_create_info_t *cinfo, ops_secret_key_t *skey) - { - // OPS_USED(info); - // XXX: push a SHA-1 checksum writer (and change s2k to 254). - skey_checksum_arg_t *arg=ops_mallocz(sizeof *arg); - - // configure the arg - arg->hash_algorithm=skey->hash_algorithm; - arg->hashed=&skey->checkhash[0]; - - // init the hash - ops_hash_any(&arg->hash, arg->hash_algorithm); - arg->hash.init(&arg->hash); - - ops_writer_push(cinfo, skey_checksum_writer, skey_checksum_finaliser, skey_checksum_destroyer, arg); - } - -// EOF diff --git a/openpgpsdk/src/openpgpsdk/writer_stream_encrypt_se_ip.c b/openpgpsdk/src/openpgpsdk/writer_stream_encrypt_se_ip.c deleted file mode 100644 index d882e9022..000000000 --- a/openpgpsdk/src/openpgpsdk/writer_stream_encrypt_se_ip.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (c) 2005-2009 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer, Alasdair Mackintosh. - * The Contributors have asserted their moral rights under the - * UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#include -#include - -#ifndef WIN32 -#include -#endif - -#include - -#include "keyring_local.h" -#include -#include -#include -#include -#include - -typedef struct - { - ops_crypt_t*crypt; - ops_memory_t *mem_se_ip; - ops_create_info_t *cinfo_se_ip; - ops_hash_t hash; - } stream_encrypt_se_ip_arg_t; - -static ops_boolean_t write_encrypt_se_ip_header(ops_create_info_t *info, - void *header_data); - - -static ops_boolean_t stream_encrypt_se_ip_writer(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo); - -static ops_boolean_t stream_encrypt_se_ip_finaliser(ops_error_t **errors, - ops_writer_info_t *winfo); - -static void stream_encrypt_se_ip_destroyer (ops_writer_info_t *winfo); - - -/** -\ingroup Core_WritersNext -\brief Pushes a streaming encryption writer onto the stack. - -Data written to the stream will be encoded in a Symmetrically -Encrypted Integrity Protected packet. Note that this writer must be -used in conjunction with a literal writer or a signed writer. - -\param cinfo -\param pub_key -Example Code: -\code - ops_writer_push_stream_encrypt_se_ip(cinfo, public_key); - if (compress) - ops_writer_push_compressed(cinfo); - if (sign) - ops_writer_push_signed(cinfo, OPS_SIG_BINARY, secret_key); - else - ops_writer_push_literal(cinfo); -\endcode -*/ - -void ops_writer_push_stream_encrypt_se_ip(ops_create_info_t *cinfo, - const ops_keydata_t *pub_key) - { - ops_crypt_t *encrypt; - unsigned char *iv=NULL; - const unsigned int bufsz=1024; // initial value; gets expanded as necessary - - // Create arg to be used with this writer - // Remember to free this in the destroyer - stream_encrypt_se_ip_arg_t *arg=ops_mallocz(sizeof *arg); - - // Create and write encrypted PK session key - ops_pk_session_key_t *encrypted_pk_session_key; - encrypted_pk_session_key=ops_create_pk_session_key(pub_key); - ops_write_pk_session_key(cinfo, encrypted_pk_session_key); - - // Setup the arg - encrypt=ops_mallocz(sizeof *encrypt); - ops_crypt_any(encrypt, encrypted_pk_session_key->symmetric_algorithm); - iv=ops_mallocz(encrypt->blocksize); - encrypt->set_iv(encrypt, iv); - encrypt->set_key(encrypt, &encrypted_pk_session_key->key[0]); - ops_encrypt_init(encrypt); - - arg->crypt=encrypt; - - ops_setup_memory_write(&arg->cinfo_se_ip, &arg->mem_se_ip, bufsz); - - ops_hash_any(&arg->hash, OPS_HASH_SHA1); - arg->hash.init(&arg->hash); - - // This is a streaming writer, so we don't know the length in - // advance. Use a partial writer to handle the partial body - // packet lengths. - ops_writer_push_partial(PARTIAL_PACKET_SIZE, cinfo, OPS_PTAG_CT_SE_IP_DATA, - write_encrypt_se_ip_header, arg); - - // And push encryption writer on stack - ops_writer_push(cinfo, - stream_encrypt_se_ip_writer, - stream_encrypt_se_ip_finaliser, - stream_encrypt_se_ip_destroyer, arg); - // tidy up - ops_pk_session_key_free(encrypted_pk_session_key); - free(encrypted_pk_session_key); - free(iv); - } - -static ops_boolean_t ops_stream_write_se_ip(const unsigned char *data, - unsigned int len, - stream_encrypt_se_ip_arg_t *arg, - ops_create_info_t *cinfo) - { - ops_writer_push_encrypt_crypt(cinfo, arg->crypt); - ops_write(data, len, cinfo); - ops_writer_pop(cinfo); - arg->hash.add(&arg->hash, data, len); - return ops_true; - } - -// Writes out the header for the encrypted packet. Invoked by the -// partial stream writer. Note that writing the packet tag and the -// packet length is handled by the partial stream writer. -static ops_boolean_t write_encrypt_se_ip_header(ops_create_info_t *cinfo, - void *data) - { - stream_encrypt_se_ip_arg_t *arg = data; - size_t sz_preamble = arg->crypt->blocksize + 2; - unsigned char* preamble = ops_mallocz(sz_preamble); - - ops_write_scalar(SE_IP_DATA_VERSION, 1, cinfo); - - ops_writer_push_encrypt_crypt(cinfo, arg->crypt); - - ops_random(preamble, arg->crypt->blocksize); - preamble[arg->crypt->blocksize]=preamble[arg->crypt->blocksize-2]; - preamble[arg->crypt->blocksize+1]=preamble[arg->crypt->blocksize-1]; - - ops_write(preamble, sz_preamble, cinfo); - arg->hash.add(&arg->hash, preamble, sz_preamble); - ops_writer_pop(cinfo); - free(preamble); - - return ops_true; - } - -static ops_boolean_t -ops_stream_write_se_ip_last(stream_encrypt_se_ip_arg_t *arg, - ops_create_info_t *cinfo) - { - unsigned char c[1]; - unsigned char hashed[SHA_DIGEST_LENGTH]; - const size_t sz_mdc = 1 + 1 + SHA_DIGEST_LENGTH; - - ops_memory_t *mem_mdc; - ops_create_info_t *cinfo_mdc; - - // MDC packet tag - c[0]=0xD3; - arg->hash.add(&arg->hash, &c[0], 1); - - // MDC packet len - c[0]=0x14; - arg->hash.add(&arg->hash, &c[0], 1); - - //finish - arg->hash.finish(&arg->hash, hashed); - - ops_setup_memory_write(&cinfo_mdc, &mem_mdc, sz_mdc); - ops_write_mdc(hashed, cinfo_mdc); - - // encode everthing - ops_writer_push_encrypt_crypt(cinfo, arg->crypt); - - ops_write(ops_memory_get_data(mem_mdc), ops_memory_get_length(mem_mdc), - cinfo); - - ops_writer_pop(cinfo); - - ops_teardown_memory_write(cinfo_mdc, mem_mdc); - - return ops_true; - } - -static ops_boolean_t stream_encrypt_se_ip_writer(const unsigned char *src, - unsigned length, - ops_error_t **errors, - ops_writer_info_t *winfo) - { - stream_encrypt_se_ip_arg_t *arg=ops_writer_get_arg(winfo); - - ops_boolean_t rtn=ops_true; - - ops_stream_write_se_ip(src, length, - arg, arg->cinfo_se_ip); - // now write memory to next writer - rtn=ops_stacked_write(ops_memory_get_data(arg->mem_se_ip), - ops_memory_get_length(arg->mem_se_ip), - errors, winfo); - - ops_memory_clear(arg->mem_se_ip); - - return rtn; - } - -static ops_boolean_t stream_encrypt_se_ip_finaliser(ops_error_t **errors, - ops_writer_info_t *winfo) - { - stream_encrypt_se_ip_arg_t *arg=ops_writer_get_arg(winfo); - // write trailer - ops_stream_write_se_ip_last(arg, arg->cinfo_se_ip); - // now write memory to next writer - return ops_stacked_write(ops_memory_get_data(arg->mem_se_ip), - ops_memory_get_length(arg->mem_se_ip), - errors, winfo); - } - -static void stream_encrypt_se_ip_destroyer(ops_writer_info_t *winfo) - - { - stream_encrypt_se_ip_arg_t *arg=ops_writer_get_arg(winfo); - - ops_teardown_memory_write(arg->cinfo_se_ip, arg->mem_se_ip); - arg->crypt->decrypt_finish(arg->crypt); - - free(arg->crypt); - free(arg); - } - -// EOF diff --git a/openpgpsdk/src/use_openpgpsdk.pri b/openpgpsdk/src/use_openpgpsdk.pri deleted file mode 100644 index ba82100d8..000000000 --- a/openpgpsdk/src/use_openpgpsdk.pri +++ /dev/null @@ -1,23 +0,0 @@ -# SPDX-FileCopyrightText: (C) 2004-2019 Retroshare Team -# SPDX-License-Identifier: CC0-1.0 - -DEPENDPATH *= $$system_path($$clean_path($${PWD}/../../openpgpsdk/src)) -INCLUDEPATH *= $$system_path($$clean_path($${PWD}/../../openpgpsdk/src)) -LIBS *= -L$$system_path($$clean_path($${OUT_PWD}/../../openpgpsdk/src/lib/)) -lops - -!equals(TARGET, ops):PRE_TARGETDEPS *= $$system_path($$clean_path($${OUT_PWD}/../../openpgpsdk/src/lib/libops.a)) - -sLibs = -mLibs = ssl crypto z bz2 -dLibs = - -static { - sLibs *= $$mLibs -} else { - dLibs *= $$mLibs -} - -LIBS += $$linkStaticLibs(sLibs) -PRE_TARGETDEPS += $$pretargetStaticLibs(sLibs) - -LIBS += $$linkDynamicLibs(dLibs)