1 /**
2  * Copyright (c) 2017, Andrew Gault, Nick Chadwick and Guillaume Egles.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *    * Redistributions of source code must retain the above copyright
8  *      notice, this list of conditions and the following disclaimer.
9  *    * Redistributions in binary form must reproduce the above copyright
10  *      notice, this list of conditions and the following disclaimer in the
11  *      documentation and/or other materials provided with the distribution.
12  *    * Neither the name of the <organization> nor the
13  *      names of its contributors may be used to endorse or promote products
14  *      derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #pragma once
29 
30 /**
31  * Wrapper around usrsctp.
32  */
33 
34 #include "ChunkQueue.hpp"
35 #include "PeerConnection.hpp"
36 
37 #include <thread>
38 
39 #include <usrsctp.h>
40 
41 namespace rtcdcpp {
42 
43 #define MAX_OUT_STREAM 256
44 #define MAX_IN_STREAM 256
45 
46 class SCTPWrapper {
47  public:
48   using MsgReceivedCallbackPtr = std::function<void(ChunkPtr chunk, uint16_t sid, uint32_t ppid)>;
49   using DTLSEncryptCallbackPtr = std::function<void(ChunkPtr)>;
50 
51   SCTPWrapper(DTLSEncryptCallbackPtr dtlsEncryptCB, MsgReceivedCallbackPtr msgReceivedCB);
52   virtual ~SCTPWrapper();
53 
54   bool Initialize();
55   void Start();
56   void Stop();
57   //  int GetStreamCursor();
58   //  void SetStreamCursor(int i);
59 
60   // Handle a decrypted SCTP packet
61   void DTLSForSCTP(ChunkPtr chunk);
62 
63   // Send a message to the remote connection
64   // Note, this will cause 1+ DTLSEncrypt callback calls
65   void GSForSCTP(ChunkPtr chunk, uint16_t sid, uint32_t ppid);
66 
67  private:
68   //  PeerConnection *peer_connection;
69   bool started{false};
70   struct socket *sock;
71   uint16_t local_port;
72   uint16_t remote_port;
73   int stream_cursor;
74 
75   bool connectSentData{false};
76   std::mutex connectMtx;
77   std::condition_variable connectCV;
78 
79   ChunkQueue send_queue;
80   ChunkQueue recv_queue;
81 
82   const DTLSEncryptCallbackPtr dtlsEncryptCallback;
83   const MsgReceivedCallbackPtr msgReceivedCallback;
84 
85   std::atomic<bool> should_stop{false};
86   std::thread recv_thread;
87   std::thread connect_thread;
88 
89   void RunConnect();
90   void RecvLoop();
91 
92   // SCTP has output a packet ready for DTLS
93   int OnSCTPForDTLS(void *data, size_t len, uint8_t tos, uint8_t set_df);
94 
95   // SCTP has received a packet for GameSurge
96   int OnSCTPForGS(struct socket *sock, union sctp_sockstore addr, void *data, size_t len, struct sctp_rcvinfo recv_info, int flags);
97 
98   void OnMsgReceived(const uint8_t *data, size_t len, int ppid, int sid);
99   void OnNotification(union sctp_notification *notify, size_t len);
100 
101   // usrsctp callbacks
102   static int _OnSCTPForDTLS(void *sctp_ptr, void *data, size_t len, uint8_t tos, uint8_t set_df);
103   static void _DebugLog(const char *format, ...);
104   static int _OnSCTPForGS(struct socket *sock, union sctp_sockstore addr, void *data, size_t len, struct sctp_rcvinfo recv_info, int flags,
105                           void *user_data);
106 
107   std::shared_ptr<Logger> logger = GetLogger("rtcdcpp.SCTP");
108 };
109 }
110