OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #ifndef WEBRTC_LIBJINGLE_SESSION_SESSIONMANAGER_H_ | |
12 #define WEBRTC_LIBJINGLE_SESSION_SESSIONMANAGER_H_ | |
13 | |
14 #include <map> | |
15 #include <string> | |
16 #include <utility> | |
17 #include <vector> | |
18 | |
19 #include "webrtc/base/sigslot.h" | |
20 #include "webrtc/base/thread.h" | |
21 #include "webrtc/libjingle/session/parsing.h" | |
22 #include "webrtc/libjingle/session/sessionclient.h" | |
23 #include "webrtc/libjingle/session/sessionmessages.h" | |
24 #include "webrtc/libjingle/xmllite/xmlelement.h" | |
25 #include "webrtc/libjingle/xmpp/constants.h" | |
26 #include "webrtc/p2p/base/portallocator.h" | |
27 #include "webrtc/p2p/base/session.h" | |
28 #include "webrtc/p2p/base/transportdescriptionfactory.h" | |
29 | |
30 namespace buzz { | |
31 class QName; | |
32 class XmlElement; | |
33 } | |
34 | |
35 namespace cricket { | |
36 | |
37 class BaseSession; | |
38 class SessionClient; | |
39 class SessionManager; | |
40 | |
41 // Used for errors that will send back a specific error message to the | |
42 // remote peer. We add "type" to the errors because it's needed for | |
43 // SignalErrorMessage. | |
44 struct MessageError : ParseError { | |
45 buzz::QName type; | |
46 | |
47 // if unset, assume type is a parse error | |
48 MessageError() : ParseError(), type(buzz::QN_STANZA_BAD_REQUEST) {} | |
49 | |
50 void SetType(const buzz::QName type) { | |
51 this->type = type; | |
52 } | |
53 }; | |
54 | |
55 // Used for errors that may be returned by public session methods that | |
56 // can fail. | |
57 // TODO: Use this error in Session::Initiate and | |
58 // Session::Accept. | |
59 struct SessionError : WriteError { | |
60 }; | |
61 | |
62 // A specific Session created by the SessionManager, using XMPP for protocol. | |
63 class Session : public BaseSession { | |
64 public: | |
65 // Returns the manager that created and owns this session. | |
66 SessionManager* session_manager() const { return session_manager_; } | |
67 | |
68 // Returns the client that is handling the application data of this session. | |
69 SessionClient* client() const { return client_; } | |
70 | |
71 // Returns the JID of this client. | |
72 const std::string& local_name() const { return local_name_; } | |
73 | |
74 // Returns the JID of the other peer in this session. | |
75 const std::string& remote_name() const { return remote_name_; } | |
76 | |
77 // Set the JID of the other peer in this session. | |
78 // Typically the remote_name_ is set when the session is initiated. | |
79 // However, sometimes (e.g when a proxy is used) the peer name is | |
80 // known after the BaseSession has been initiated and it must be updated | |
81 // explicitly. | |
82 void set_remote_name(const std::string& name) { remote_name_ = name; } | |
83 | |
84 // Set the JID of the initiator of this session. Allows for the overriding | |
85 // of the initiator to be a third-party, eg. the MUC JID when creating p2p | |
86 // sessions. | |
87 void set_initiator_name(const std::string& name) { initiator_name_ = name; } | |
88 | |
89 // Indicates the JID of the entity who initiated this session. | |
90 // In special cases, may be different than both local_name and remote_name. | |
91 const std::string& initiator_name() const { return initiator_name_; } | |
92 | |
93 SignalingProtocol current_protocol() const { return current_protocol_; } | |
94 | |
95 void set_current_protocol(SignalingProtocol protocol) { | |
96 current_protocol_ = protocol; | |
97 } | |
98 | |
99 // Updates the error state, signaling if necessary. | |
100 virtual void SetError(Error error, const std::string& error_desc); | |
101 | |
102 // When the session needs to send signaling messages, it beings by requesting | |
103 // signaling. The client should handle this by calling OnSignalingReady once | |
104 // it is ready to send the messages. | |
105 // (These are called only by SessionManager.) | |
106 sigslot::signal1<Session*> SignalRequestSignaling; | |
107 void OnSignalingReady() { BaseSession::OnSignalingReady(); } | |
108 | |
109 // Takes ownership of session description. | |
110 // TODO: Add an error argument to pass back to the caller. | |
111 bool Initiate(const std::string& to, | |
112 const SessionDescription* sdesc); | |
113 | |
114 // When we receive an initiate, we create a session in the | |
115 // RECEIVEDINITIATE state and respond by accepting or rejecting. | |
116 // Takes ownership of session description. | |
117 // TODO: Add an error argument to pass back to the caller. | |
118 bool Accept(const SessionDescription* sdesc); | |
119 bool Reject(const std::string& reason); | |
120 bool Terminate() { | |
121 return TerminateWithReason(STR_TERMINATE_SUCCESS); | |
122 } | |
123 bool TerminateWithReason(const std::string& reason); | |
124 // Fired whenever we receive a terminate message along with a reason | |
125 sigslot::signal2<Session*, const std::string&> SignalReceivedTerminateReason; | |
126 | |
127 // The two clients in the session may also send one another | |
128 // arbitrary XML messages, which are called "info" messages. Sending | |
129 // takes ownership of the given elements. The signal does not; the | |
130 // parent element will be deleted after the signal. | |
131 bool SendInfoMessage(const XmlElements& elems, | |
132 const std::string& remote_name); | |
133 bool SendDescriptionInfoMessage(const ContentInfos& contents); | |
134 sigslot::signal2<Session*, const buzz::XmlElement*> SignalInfoMessage; | |
135 | |
136 private: | |
137 // Creates or destroys a session. (These are called only SessionManager.) | |
138 Session(SessionManager *session_manager, | |
139 const std::string& local_name, const std::string& initiator_name, | |
140 const std::string& sid, const std::string& content_type, | |
141 SessionClient* client); | |
142 ~Session(); | |
143 // For each transport info, create a transport proxy. Can fail for | |
144 // incompatible transport types. | |
145 bool CreateTransportProxies(const TransportInfos& tinfos, | |
146 SessionError* error); | |
147 bool OnRemoteCandidates(const TransportInfos& tinfos, | |
148 ParseError* error); | |
149 // Returns a TransportInfo without candidates for each content name. | |
150 // Uses the transport_type_ of the session. | |
151 TransportInfos GetEmptyTransportInfos(const ContentInfos& contents) const; | |
152 | |
153 // Maps passed to serialization functions. | |
154 TransportParserMap GetTransportParsers(); | |
155 ContentParserMap GetContentParsers(); | |
156 CandidateTranslatorMap GetCandidateTranslators(); | |
157 | |
158 virtual void OnTransportRequestSignaling(Transport* transport); | |
159 virtual void OnTransportConnecting(Transport* transport); | |
160 virtual void OnTransportWritable(Transport* transport); | |
161 virtual void OnTransportProxyCandidatesReady(TransportProxy* proxy, | |
162 const Candidates& candidates); | |
163 virtual void OnMessage(rtc::Message *pmsg); | |
164 | |
165 // Send various kinds of session messages. | |
166 bool SendInitiateMessage(const SessionDescription* sdesc, | |
167 SessionError* error); | |
168 bool SendAcceptMessage(const SessionDescription* sdesc, SessionError* error); | |
169 bool SendRejectMessage(const std::string& reason, SessionError* error); | |
170 bool SendTerminateMessage(const std::string& reason, SessionError* error); | |
171 bool SendTransportInfoMessage(const TransportInfo& tinfo, | |
172 SessionError* error); | |
173 bool SendTransportInfoMessage(const TransportProxy* transproxy, | |
174 const Candidates& candidates, | |
175 SessionError* error); | |
176 | |
177 bool ResendAllTransportInfoMessages(SessionError* error); | |
178 bool SendAllUnsentTransportInfoMessages(SessionError* error); | |
179 | |
180 // All versions of SendMessage send a message of the given type to | |
181 // the other client. Can pass either a set of elements or an | |
182 // "action", which must have a WriteSessionAction method to go along | |
183 // with it. Sending with an action supports sending a "hybrid" | |
184 // message. Sending with elements must be sent as Jingle or Gingle. | |
185 | |
186 // When passing elems, must be either Jingle or Gingle protocol. | |
187 // Takes ownership of action_elems. | |
188 bool SendMessage(ActionType type, const XmlElements& action_elems, | |
189 SessionError* error); | |
190 // Sends a messge, but overrides the remote name. | |
191 bool SendMessage(ActionType type, const XmlElements& action_elems, | |
192 const std::string& remote_name, | |
193 SessionError* error); | |
194 // When passing an action, may be Hybrid protocol. | |
195 template <typename Action> | |
196 bool SendMessage(ActionType type, const Action& action, | |
197 SessionError* error); | |
198 | |
199 // Helper methods to write the session message stanza. | |
200 template <typename Action> | |
201 bool WriteActionMessage(ActionType type, const Action& action, | |
202 buzz::XmlElement* stanza, WriteError* error); | |
203 template <typename Action> | |
204 bool WriteActionMessage(SignalingProtocol protocol, | |
205 ActionType type, const Action& action, | |
206 buzz::XmlElement* stanza, WriteError* error); | |
207 | |
208 // Sending messages in hybrid form requires being able to write them | |
209 // on a per-protocol basis with a common method signature, which all | |
210 // of these have. | |
211 bool WriteSessionAction(SignalingProtocol protocol, | |
212 const SessionInitiate& init, | |
213 XmlElements* elems, WriteError* error); | |
214 bool WriteSessionAction(SignalingProtocol protocol, | |
215 const TransportInfo& tinfo, | |
216 XmlElements* elems, WriteError* error); | |
217 bool WriteSessionAction(SignalingProtocol protocol, | |
218 const SessionTerminate& term, | |
219 XmlElements* elems, WriteError* error); | |
220 | |
221 // Sends a message back to the other client indicating that we have received | |
222 // and accepted their message. | |
223 void SendAcknowledgementMessage(const buzz::XmlElement* stanza); | |
224 | |
225 // Once signaling is ready, the session will use this signal to request the | |
226 // sending of each message. When messages are received by the other client, | |
227 // they should be handed to OnIncomingMessage. | |
228 // (These are called only by SessionManager.) | |
229 sigslot::signal2<Session* , const buzz::XmlElement*> SignalOutgoingMessage; | |
230 void OnIncomingMessage(const SessionMessage& msg); | |
231 | |
232 void OnIncomingResponse(const buzz::XmlElement* orig_stanza, | |
233 const buzz::XmlElement* response_stanza, | |
234 const SessionMessage& msg); | |
235 void OnInitiateAcked(); | |
236 void OnFailedSend(const buzz::XmlElement* orig_stanza, | |
237 const buzz::XmlElement* error_stanza); | |
238 | |
239 // Invoked when an error is found in an incoming message. This is translated | |
240 // into the appropriate XMPP response by SessionManager. | |
241 sigslot::signal6<BaseSession*, | |
242 const buzz::XmlElement*, | |
243 const buzz::QName&, | |
244 const std::string&, | |
245 const std::string&, | |
246 const buzz::XmlElement*> SignalErrorMessage; | |
247 | |
248 // Handlers for the various types of messages. These functions may take | |
249 // pointers to the whole stanza or to just the session element. | |
250 bool OnInitiateMessage(const SessionMessage& msg, MessageError* error); | |
251 bool OnAcceptMessage(const SessionMessage& msg, MessageError* error); | |
252 bool OnRejectMessage(const SessionMessage& msg, MessageError* error); | |
253 bool OnInfoMessage(const SessionMessage& msg); | |
254 bool OnTerminateMessage(const SessionMessage& msg, MessageError* error); | |
255 bool OnTransportInfoMessage(const SessionMessage& msg, MessageError* error); | |
256 bool OnTransportAcceptMessage(const SessionMessage& msg, MessageError* error); | |
257 bool OnDescriptionInfoMessage(const SessionMessage& msg, MessageError* error); | |
258 bool OnRedirectError(const SessionRedirect& redirect, SessionError* error); | |
259 | |
260 // Verifies that we are in the appropriate state to receive this message. | |
261 bool CheckState(State state, MessageError* error); | |
262 | |
263 SessionManager* session_manager_; | |
264 bool initiate_acked_; | |
265 std::string local_name_; | |
266 std::string initiator_name_; | |
267 std::string remote_name_; | |
268 SessionClient* client_; | |
269 TransportParser* transport_parser_; | |
270 // Keeps track of what protocol we are speaking. | |
271 SignalingProtocol current_protocol_; | |
272 | |
273 friend class SessionManager; // For access to constructor, destructor, | |
274 // and signaling related methods. | |
275 }; | |
276 | |
277 // SessionManager manages session instances. | |
278 class SessionManager : public sigslot::has_slots<> { | |
279 public: | |
280 SessionManager(PortAllocator *allocator, | |
281 rtc::Thread *worker_thread = NULL); | |
282 virtual ~SessionManager(); | |
283 | |
284 PortAllocator *port_allocator() const { return allocator_; } | |
285 rtc::Thread *worker_thread() const { return worker_thread_; } | |
286 rtc::Thread *signaling_thread() const { return signaling_thread_; } | |
287 | |
288 int session_timeout() const { return timeout_; } | |
289 void set_session_timeout(int timeout) { timeout_ = timeout; } | |
290 | |
291 // Set what transport protocol we want to default to. | |
292 void set_transport_protocol(TransportProtocol proto) { | |
293 transport_desc_factory_.set_protocol(proto); | |
294 } | |
295 | |
296 // Control use of DTLS. An identity must be supplied if DTLS is enabled. | |
297 void set_secure(SecurePolicy policy) { | |
298 transport_desc_factory_.set_secure(policy); | |
299 } | |
300 void set_identity(rtc::SSLIdentity* identity) { | |
301 transport_desc_factory_.set_identity(identity); | |
302 } | |
303 const TransportDescriptionFactory* transport_desc_factory() const { | |
304 return &transport_desc_factory_; | |
305 } | |
306 | |
307 // Registers support for the given client. If we receive an initiate | |
308 // describing a session of the given type, we will automatically create a | |
309 // Session object and notify this client. The client may then accept or | |
310 // reject the session. | |
311 void AddClient(const std::string& content_type, SessionClient* client); | |
312 void RemoveClient(const std::string& content_type); | |
313 SessionClient* GetClient(const std::string& content_type); | |
314 | |
315 // Creates a new session. The given name is the JID of the client on whose | |
316 // behalf we initiate the session. | |
317 Session *CreateSession(const std::string& local_name, | |
318 const std::string& content_type); | |
319 | |
320 Session *CreateSession(const std::string& id, | |
321 const std::string& local_name, | |
322 const std::string& content_type); | |
323 | |
324 // Destroys the given session. | |
325 void DestroySession(Session *session); | |
326 | |
327 // Returns the session with the given ID or NULL if none exists. | |
328 Session *GetSession(const std::string& sid); | |
329 | |
330 // Terminates all of the sessions created by this manager. | |
331 void TerminateAll(); | |
332 | |
333 // These are signaled whenever the set of existing sessions changes. | |
334 sigslot::signal2<Session *, bool> SignalSessionCreate; | |
335 sigslot::signal1<Session *> SignalSessionDestroy; | |
336 | |
337 // Determines whether the given stanza is intended for some session. | |
338 bool IsSessionMessage(const buzz::XmlElement* stanza); | |
339 | |
340 // Given a sid, initiator, and remote_name, this finds the matching Session | |
341 Session* FindSession(const std::string& sid, | |
342 const std::string& remote_name); | |
343 | |
344 // Called when we receive a stanza for which IsSessionMessage is true. | |
345 void OnIncomingMessage(const buzz::XmlElement* stanza); | |
346 | |
347 // Called when we get a response to a message that we sent. | |
348 void OnIncomingResponse(const buzz::XmlElement* orig_stanza, | |
349 const buzz::XmlElement* response_stanza); | |
350 | |
351 // Called if an attempted to send times out or an error is returned. In the | |
352 // timeout case error_stanza will be NULL | |
353 void OnFailedSend(const buzz::XmlElement* orig_stanza, | |
354 const buzz::XmlElement* error_stanza); | |
355 | |
356 // Signalled each time a session generates a signaling message to send. | |
357 // Also signalled on errors, but with a NULL session. | |
358 sigslot::signal2<SessionManager*, | |
359 const buzz::XmlElement*> SignalOutgoingMessage; | |
360 | |
361 // Signaled before sessions try to send certain signaling messages. The | |
362 // client should call OnSignalingReady once it is safe to send them. These | |
363 // steps are taken so that we don't send signaling messages trying to | |
364 // re-establish the connectivity of a session when the client cannot send | |
365 // the messages (and would probably just drop them on the floor). | |
366 // | |
367 // Note: you can connect this directly to OnSignalingReady(), if a signalling | |
368 // check is not supported. | |
369 sigslot::signal0<> SignalRequestSignaling; | |
370 void OnSignalingReady(); | |
371 | |
372 // Signaled when this SessionManager is deleted. | |
373 sigslot::signal0<> SignalDestroyed; | |
374 | |
375 private: | |
376 typedef std::map<std::string, Session*> SessionMap; | |
377 typedef std::map<std::string, SessionClient*> ClientMap; | |
378 | |
379 // Helper function for CreateSession. This is also invoked when we receive | |
380 // a message attempting to initiate a session with this client. | |
381 Session *CreateSession(const std::string& local_name, | |
382 const std::string& initiator, | |
383 const std::string& sid, | |
384 const std::string& content_type, | |
385 bool received_initiate); | |
386 | |
387 // Attempts to find a registered session type whose description appears as | |
388 // a child of the session element. Such a child should be present indicating | |
389 // the application they hope to initiate. | |
390 std::string FindClient(const buzz::XmlElement* session); | |
391 | |
392 // Sends a message back to the other client indicating that we found an error | |
393 // in the stanza they sent. name identifies the error, type is one of the | |
394 // standard XMPP types (cancel, continue, modify, auth, wait), and text is a | |
395 // description for debugging purposes. | |
396 void SendErrorMessage(const buzz::XmlElement* stanza, | |
397 const buzz::QName& name, | |
398 const std::string& type, | |
399 const std::string& text, | |
400 const buzz::XmlElement* extra_info); | |
401 | |
402 // Creates and returns an error message from the given components. The | |
403 // caller is responsible for deleting this. | |
404 buzz::XmlElement* CreateErrorMessage( | |
405 const buzz::XmlElement* stanza, | |
406 const buzz::QName& name, | |
407 const std::string& type, | |
408 const std::string& text, | |
409 const buzz::XmlElement* extra_info); | |
410 | |
411 // Called each time a session requests signaling. | |
412 void OnRequestSignaling(Session* session); | |
413 | |
414 // Called each time a session has an outgoing message. | |
415 void OnOutgoingMessage(Session* session, const buzz::XmlElement* stanza); | |
416 | |
417 // Called each time a session has an error to send. | |
418 void OnErrorMessage(BaseSession* session, | |
419 const buzz::XmlElement* stanza, | |
420 const buzz::QName& name, | |
421 const std::string& type, | |
422 const std::string& text, | |
423 const buzz::XmlElement* extra_info); | |
424 | |
425 PortAllocator *allocator_; | |
426 rtc::Thread *signaling_thread_; | |
427 rtc::Thread *worker_thread_; | |
428 int timeout_; | |
429 TransportDescriptionFactory transport_desc_factory_; | |
430 SessionMap session_map_; | |
431 ClientMap client_map_; | |
432 }; | |
433 | |
434 } // namespace cricket | |
435 | |
436 #endif // WEBRTC_LIBJINGLE_SESSION_SESSIONMANAGER_H_ | |
OLD | NEW |