| 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 |