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 libnice and NiceAgent.
32  */
33 
34 #include "ChunkQueue.hpp"
35 #include "PeerConnection.hpp"
36 #include "Logging.hpp"
37 
38 #include <thread>
39 
40 extern "C" {
41 #include <nice/agent.h>
42 }
43 
44 namespace rtcdcpp {
45 
46 /**
47  * Nice Wrapper broh.
48  */
49 class NiceWrapper {
50  public:
51   // TODO: Remove reference to handler
52   // TODO: Add callback for candidates
53   NiceWrapper(PeerConnection *peer_connection);
54   virtual ~NiceWrapper();
55 
56   // Setup libnice
57   bool Initialize();
58 
59   // Start sending packets XXX: recv just happens once candidates are set
60   void StartSendLoop();
61 
62   // Shutdown nice and stop the send thread
63   void Stop();
64 
65   // Parse the remote SDP
66   void ParseRemoteSDP(std::string remote_sdp);
67 
68   // void SetRemoteCredentials(std::string username, std::string password);
69 
70   // Generate the local SDP
71   std::string GenerateLocalSDP();
72 
73   // Add a single remote ice candidate (supports trickling)
74   bool SetRemoteIceCandidate(std::string candidate_sdp);
75 
76   // Set the remote ice candidates
77   bool SetRemoteIceCandidates(std::vector<std::string> candidate_sdps);
78 
79   // Callback to call when we receive local ice candidates
80   // void SetLocalCandidatesCallback(std::vector<std::string> candidate_sdps);
81 
82   // Callback to call when we receive remote data
83   void SetDataReceivedCallback(std::function<void(ChunkPtr)>);
84 
85   // Send data over the nice channel
86   void SendData(ChunkPtr chunk);
87 
88  private:
89   PeerConnection *peer_connection;
90   int packets_sent;
91 
92   std::unique_ptr<NiceAgent, void (*)(gpointer)> agent;
93   std::unique_ptr<GMainLoop, void (*)(GMainLoop *)> loop;
94   uint32_t stream_id;
95   std::mutex send_lock;
96 
97   bool gathering_done;
98   bool negotiation_done;
99 
100   ChunkQueue send_queue;
101 
102   std::function<void(ChunkPtr)> data_received_callback;
103 
104   // Send data thread
105   void SendLoop();
106   std::thread send_thread;
107   std::thread g_main_loop_thread;
108   std::atomic<bool> should_stop;
109 
110   // Callback methods
111   void OnStateChange(uint32_t stream_id, uint32_t component_id, uint32_t state);
112   void OnGatheringDone();
113   void OnCandidate(std::string candidate);
114   void OnSelectedPair();
115   void OnDataReceived(const uint8_t *buf, int len);
116   void OnIceReady();
117   void LogMessage(const gchar *message);
118 
119   // Helper functions
120   friend void candidate_gathering_done(NiceAgent *agent, guint stream_id, gpointer user_data);
121   friend void component_state_changed(NiceAgent *agent, guint stream_id, guint component_id, guint state, gpointer user_data);
122   friend void new_local_candidate(NiceAgent *agent, NiceCandidate *candidate, gpointer user_data);
123   friend void new_selected_pair(NiceAgent *agent, guint stream_id, guint component_id, NiceCandidate *lcandidate, NiceCandidate *rcandidate,
124                                 gpointer user_data);
125   friend void data_received(NiceAgent *agent, guint stream_id, guint component_id, guint len, gchar *buf, gpointer user_data);
126   friend void nice_log_handler(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data);
127 
128   std::shared_ptr<Logger> logger = GetLogger("rtcdcpp.Nice");
129 };
130 }
131