generic_io.h 4.7 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
 *
 *  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

23 24
#include "ip_utils.h"

25 26
#include <functional>
#include <vector>
27
#include <chrono>
28 29 30 31 32 33 34 35
#include <system_error>
#include <cstdint>

#if defined(_MSC_VER)
#include <BaseTsd.h>
using ssize_t = SSIZE_T;
#endif

Adrien Béraud's avatar
Adrien Béraud committed
36
namespace jami {
37 38 39 40 41 42 43

template <typename T>
class GenericSocket
{
public:
    using ValueType = T;

44
    virtual ~GenericSocket() { shutdown(); }
45 46 47

    using RecvCb = std::function<ssize_t(const ValueType* buf, std::size_t len)>;

48
    /// Close established connection
Hugo Lefeuvre's avatar
Hugo Lefeuvre committed
49
    /// \note Terminate outstanding blocking read operations with an empty error code, but a 0 read size.
50 51
    virtual void shutdown() {}

52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
    /// Set Rx callback
    /// \warning This method is here for backward compatibility
    /// and because async IO are not implemented yet.
    virtual void setOnRecv(RecvCb&& cb) = 0;

    virtual bool isReliable() const = 0;

    virtual bool isInitiator() const = 0;

    /// Return maximum application payload size.
    /// This value is negative if the session is not ready to give a valid answer.
    /// The value is 0 if such information is irrelevant for the session.
    /// If stricly positive, the user must use send() with an input buffer size below or equals
    /// to this value if it want to be sure that the transport sent it in an atomic way.
    /// Example: in case of non-reliable transport using packet oriented IO,
    /// this value gives the maximal size used to send one packet.
    virtual int maxPayload() const = 0;

70 71 72 73 74 75
    /// Wait until data to read available, timeout or io error
    /// \param ec error code set in case of error (if return value is < 0)
    /// \return positive number if data ready for read, 0 in case of timeout or error.
    /// \note error code is not set in case of timeout, but set only in case of io error
    /// (i.e. socket deconnection).
    /// \todo make a std::chrono version for the timeout
76
    virtual int waitForData(std::chrono::milliseconds timeout, std::error_code& ec) const = 0;
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110

    /// Write a given amount of data.
    /// \param buf data to write.
    /// \param len number of bytes to write.
    /// \param ec error code set in case of error.
    /// \return number of bytes written, 0 is valid.
    /// \warning error checking consists in checking if \a !ec is true, not if returned size is 0
    /// as a write of 0 could be considered a valid operation.
    virtual std::size_t write(const ValueType* buf, std::size_t len, std::error_code& ec) = 0;

    /// Read a given amount of data.
    /// \param buf data to read.
    /// \param len number of bytes to read.
    /// \param ec error code set in case of error.
    /// \return number of bytes read, 0 is valid.
    /// \warning error checking consists in checking if \a !ec is true, not if returned size is 0
    /// as a read of 0 could be considered a valid operation (i.e. non-blocking IO).
    virtual std::size_t read(ValueType* buf, std::size_t len, std::error_code& ec) = 0;

    /// write() adaptor for STL containers
    template <typename U>
    std::size_t write(const U& obj, std::error_code& ec) {
        return write(obj.data(), obj.size() * sizeof(typename U::value_type), ec);
    }

    /// read() adaptor for STL containers
    template <typename U>
    std::size_t read(U& storage, std::error_code& ec) {
        auto res = read(storage.data(), storage.size() * sizeof(typename U::value_type), ec);
        if (!ec)
            storage.resize(res);
        return res;
    }

111 112 113 114 115 116 117 118 119 120
    /// Return the local IP address if known.
    /// \note The address is not valid (addr.isUnspecified() returns true) if it's not known
    /// or not available.
    virtual IpAddr localAddr() const { return {}; }

    /// Return the remote IP address if known.
    /// \note The address is not valid (addr.isUnspecified() returns true) if it's not known
    /// or not available.
    virtual IpAddr remoteAddr() const { return {}; }

121 122 123 124
protected:
    GenericSocket() = default;
};

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