Transport.hpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #pragma once
  2. #include "mumlib/CryptState.hpp"
  3. #include "mumlib/VarInt.hpp"
  4. #include "enums.hpp"
  5. #include <boost/noncopyable.hpp>
  6. #include <boost/asio/ssl.hpp>
  7. #include <boost/asio.hpp>
  8. #include <boost/bind.hpp>
  9. #include <boost/pool/pool.hpp>
  10. #include <log4cpp/Category.hh>
  11. #include <google/protobuf/message.h>
  12. #include <chrono>
  13. #include <utility>
  14. namespace mumlib {
  15. constexpr int MAX_UDP_LENGTH = 1024;
  16. constexpr int MAX_TCP_LENGTH = 129 * 1024; // 128 kB + some reserve
  17. using namespace std;
  18. using namespace boost::asio;
  19. using namespace boost::asio::ip;
  20. typedef function<bool(MessageType, uint8_t *, int)> ProcessControlMessageFunction;
  21. typedef function<bool(AudioPacketType, uint8_t *, int)> ProcessEncodedAudioPacketFunction;
  22. class TransportException : public MumlibException {
  23. public:
  24. TransportException(string message) : MumlibException(std::move(message)) { }
  25. };
  26. /* This helper is needed because the sslContext and sslSocket are initialized in
  27. * the Transport constructor and there wasn't an easier way of passing these two
  28. * arguments.
  29. * TODO: add support for password callback.
  30. */
  31. class SslContextHelper : boost::noncopyable {
  32. public:
  33. SslContextHelper(boost::asio::ssl::context &ctx,
  34. std::string cert_file, std::string privkey_file);
  35. ~SslContextHelper() { };
  36. };
  37. class Transport : boost::noncopyable {
  38. public:
  39. Transport(io_service &ioService,
  40. ProcessControlMessageFunction processControlMessageFunc,
  41. ProcessEncodedAudioPacketFunction processEncodedAudioPacketFunction,
  42. bool noUdp = false,
  43. std::string cert_file = "",
  44. std::string privkey_file = "");
  45. ~Transport();
  46. void connect(string host,
  47. int port,
  48. string user,
  49. string password);
  50. void connect(string host,
  51. int port,
  52. string user,
  53. string password,
  54. string cert_file,
  55. string privkey_file);
  56. void disconnect();
  57. ConnectionState getConnectionState() {
  58. return state;
  59. }
  60. bool isUdpActive();
  61. void sendControlMessage(MessageType type, google::protobuf::Message &message);
  62. void sendEncodedAudioPacket(uint8_t *buffer, int length);
  63. private:
  64. log4cpp::Category &logger;
  65. io_service &ioService;
  66. pair<string, int> connectionParams;
  67. pair<string, string> credentials;
  68. ProcessControlMessageFunction processMessageFunction;
  69. ProcessEncodedAudioPacketFunction processEncodedAudioPacketFunction;
  70. const bool noUdp;
  71. volatile bool udpActive;
  72. ConnectionState state;
  73. udp::socket udpSocket;
  74. ip::udp::endpoint udpReceiverEndpoint;
  75. uint8_t udpIncomingBuffer[MAX_UDP_LENGTH];
  76. CryptState cryptState;
  77. ssl::context sslContext;
  78. SslContextHelper sslContextHelper;
  79. ssl::stream<tcp::socket> sslSocket;
  80. uint8_t *sslIncomingBuffer;
  81. deadline_timer pingTimer;
  82. std::chrono::time_point<std::chrono::system_clock> lastReceivedUdpPacketTimestamp;
  83. boost::pool<> asyncBufferPool;
  84. void pingTimerTick(const boost::system::error_code &e);
  85. void sslConnectHandler(const boost::system::error_code &error);
  86. void sslHandshakeHandler(const boost::system::error_code &error);
  87. void doReceiveSsl();
  88. void sendSsl(uint8_t *buff, int length);
  89. void sendSslAsync(uint8_t *buff, int length);
  90. void sendControlMessagePrivate(MessageType type, google::protobuf::Message &message);
  91. void sendSslPing();
  92. void sendVersion();
  93. void sendAuthentication();
  94. void processMessageInternal(MessageType messageType, uint8_t *buffer, int length);
  95. void doReceiveUdp();
  96. void sendUdpAsync(uint8_t *buff, int length);
  97. void sendUdpPing();
  98. void throwTransportException(string message);
  99. void processAudioPacket(uint8_t *buff, int length);
  100. };
  101. }