turn_transport.h 5.8 KB
Newer Older
1
/*
2
 *  Copyright (C) 2017-2019 Savoir-faire Linux Inc.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 *
 *  Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
 *
 *  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 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that 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 "ip_utils.h"
24
#include "generic_io.h"
25 26 27 28 29

#include <string>
#include <memory>
#include <functional>
#include <map>
30
#include <stdexcept>
31

Adrien Béraud's avatar
Adrien Béraud committed
32
namespace jami {
33 34 35

class TurnTransportPimpl;

36 37
struct TurnTransportParams
{
38 39 40 41 42 43 44
    IpAddr server;

    // Plain Credentials
    std::string realm;
    std::string username;
    std::string password;

45 46
    pj_uint16_t authorized_family {0};

47 48
    bool isPeerConnection {false};
    uint32_t connectionId {0};
49
    std::function<void(uint32_t conn_id, const IpAddr& peer_addr, bool success)> onPeerConnection;
50

51
    std::size_t maxPacketSize {4096}; ///< size of one "logical" packet
52 53
};

54 55
class TurnTransport
{
56 57 58 59 60 61 62 63 64 65 66 67 68
public:
    /// Constructs a TurnTransport connected by TCP to given server.
    ///
    /// Throw std::invalid_argument of peer address is invalid.
    ///
    /// \param param parameters to setup the transport
    ///
    /// \note If TURN server port is not set, the default TURN port 3478 (RFC5766) is used.
    ///
    TurnTransport(const TurnTransportParams& param);

    ~TurnTransport();

69 70
    void shutdown(const IpAddr& addr);

71 72
    bool isInitiator() const;

73 74 75 76 77 78 79
    /// Wait for successful connection on the TURN server.
    ///
    /// TurnTransport constructor connects asynchronously on the TURN server.
    /// You need to wait the READY state before calling any other APIs.
    ///
    void waitServerReady();

80
    /// \return true if the TURN server is connected and ready to accept peers.
81 82
    bool isReady() const;

83
    /// \return socket address (IP/port) where peers should connect to before doing IO with this client.
84
    const IpAddr& peerRelayAddr() const;
85 86

    /// \return public address of this client as seen by the TURN server.
87 88
    const IpAddr& mappedAddr() const;

89 90 91
    /// \return a vector of connected peer addresses
    std::vector<IpAddr> peerAddresses() const;

92 93 94 95 96 97 98 99 100 101 102 103 104
    /// Gives server access permission to given peer by its address.
    ///
    /// Throw std::invalid_argument of peer address is invalid.
    /// Throw std::runtime_error if case of backend errors.
    ///
    /// \param addr peer address
    ///
    /// \note The peer address family must be same as the turn server.
    /// \note Must be called only if server is ready.
    /// \see waitServerReady
    ///
    void permitPeer(const IpAddr& addr);

105 106
    /// Collect pending data from a given peer.
    ///
107 108 109 110
    /// Data are read from given \a peer incoming buffer until EOF or \a data size() is reached.
    /// \a data is resized with exact number of characters read.
    /// If \a peer is not connected this function raise an exception.
    /// If \a peer exists but no data are available this method blocks until TURN deconnection
111
    /// or at first incoming character.
112
    ///
113 114
    /// \param [in] peer target peer address where data are read
    /// \param [in,out] pre-dimensionned character vector to write incoming data
115
    /// \exception std::out_of_range \a peer is not connected yet
116
    ///
117
    void recvfrom(const IpAddr& peer, std::vector<char>& data);
118

119
    /// Works as recvfrom() vector version but accept a simple char array.
120
    ///
121
    std::size_t recvfrom(const IpAddr& peer, char* buffer, std::size_t size);
122 123 124

    /// Send data to given peer through the TURN tunnel.
    ///
125 126
    /// This method blocks until all given characters in \a data are sent to the given \a peer.
    /// If \a peer is not connected this function raise an exception.
127 128 129
    ///
    /// \param [in] peer target peer address where data are read
    /// \param [in,out] pre-dimensionned character vector to write incoming data
130
    /// \exception std::out_of_range \a peer is not connected yet
131 132 133
    ///
    bool sendto(const IpAddr& peer, const std::vector<char>& data);

134 135
    /// Works as sendto() vector version but accept a simple char array.
    ///
136
    bool sendto(const IpAddr& peer, const char* const buffer, std::size_t size);
137

138
    int waitForData(const IpAddr& peer, std::chrono::milliseconds timeout, std::error_code& ec) const;
139

140
public:
141
    // Move semantic only, not copiable
142 143 144 145 146 147 148 149
    TurnTransport(TurnTransport&&) = default;
    TurnTransport& operator=(TurnTransport&&) = default;

private:
    TurnTransport() = delete;
    std::unique_ptr<TurnTransportPimpl> pimpl_;
};

150 151 152 153 154 155 156
class ConnectedTurnTransport final : public GenericSocket<uint8_t>
{
public:
    using SocketType = GenericSocket<uint8_t>;

    ConnectedTurnTransport(TurnTransport& turn, const IpAddr& peer);

157
    void shutdown() override;
158 159 160 161
    bool isReliable() const override { return true; }
    bool isInitiator() const override { return turn_.isInitiator(); }
    int maxPayload() const override { return 3000; }

162
    int waitForData(std::chrono::milliseconds timeout, std::error_code& ec) const override;
163 164 165 166 167 168 169 170 171 172
    std::size_t read(ValueType* buf, std::size_t length, std::error_code& ec) override;
    std::size_t write(const ValueType* buf, std::size_t length, std::error_code& ec) override;

    void setOnRecv(RecvCb&&) override { throw std::logic_error("ConnectedTurnTransport bad call"); }

private:
    TurnTransport& turn_;
    const IpAddr peer_;
};

Adrien Béraud's avatar
Adrien Béraud committed
173
} // namespace jami