| /* |
| * libjingle |
| * Copyright 2011, Google Inc. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * 3. The name of the author may not be used to endorse or promote products |
| * derived from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
| * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
| * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "talk/app/webrtc/roapmessages.h" |
| |
| #include "talk/app/webrtc/webrtcsdp.h" |
| #include "talk/base/json.h" |
| |
| namespace webrtc { |
| |
| using cricket::Candidate; |
| using cricket::SessionDescription; |
| |
| // ROAP message types. Must match the enum RoapMessageType. |
| static const char* kMessageTypes[] = { |
| "OFFER", |
| "ANSWER", |
| "OK", |
| "SHUTDOWN", |
| "ERROR", |
| }; |
| |
| // ROAP error messages. Must match the enum RoapErrorCode. |
| static const char* kErrorMessages[] = { |
| "NOMATCH", |
| "TIMEOUT", |
| "REFUSED", |
| "CONFLICT", |
| "DOUBLECONFLICT", |
| "FAILED", |
| }; |
| |
| // ROAP json keys. |
| static const char kOffererSessionId[] = "offererSessionId"; |
| static const char kAnswererSessionId[] = "answererSessionId"; |
| static const char kSetSessionToken[] = "setSessionToken"; |
| static const char kSetResponseToken[] = "setResponseToken"; |
| static const char kResponseToken[] = "responseToken"; |
| static const char kSessionToken[] = "sessionToken"; |
| static const char kMessageType[] = "messageType"; |
| static const char kSequenceNumber[] = "seq"; |
| static const char kSessionDescription[] = "sdp"; |
| static const char kErrorType[] = "errorType"; |
| static const char kTieBreaker[] = "tieBreaker"; |
| static const char kMoreComing[] = "moreComing"; |
| |
| RoapMessageBase::RoapMessageBase() : type_(kInvalid), seq_(0) { |
| } |
| |
| RoapMessageBase::RoapMessageBase(RoapMessageType type, |
| const std::string& offer_session_id, |
| const std::string& answer_session_id, |
| const std::string& session_token, |
| const std::string& response_token, |
| uint32 seq) |
| : type_(type), |
| offer_session_id_(offer_session_id), |
| answer_session_id_(answer_session_id), |
| session_token_(session_token), |
| response_token_(response_token), |
| seq_(seq) { |
| } |
| |
| bool RoapMessageBase::Parse(const std::string& message) { |
| Json::Reader reader; |
| if (!reader.parse(message, jmessage_)) |
| return false; |
| |
| std::string message_type; |
| GetStringFromJsonObject(jmessage_, kMessageType, &message_type); |
| if (message_type.empty()) |
| return false; |
| bool valid_message_type = false; |
| for (int i = 0; i < kInvalid; i++) { |
| if (message_type == kMessageTypes[i]) { |
| type_ = static_cast<RoapMessageType>(i); |
| valid_message_type = true; |
| break; |
| } |
| } |
| if (!valid_message_type) |
| return false; |
| |
| if (!GetStringFromJsonObject(jmessage_, kOffererSessionId, |
| &offer_session_id_) || |
| offer_session_id_.empty()) { |
| // Parse offererSessionId. Allow error messages to not have an |
| // offererSessionId. |
| if (type_ != kError) |
| return false; |
| } |
| |
| // answererSessionId does not necessarily need to exist in MessageBase. |
| GetStringFromJsonObject(jmessage_, kAnswererSessionId, &answer_session_id_); |
| // setSessionToken and setResponseToken is not required. |
| GetStringFromJsonObject(jmessage_, kSetSessionToken, &session_token_); |
| GetStringFromJsonObject(jmessage_, kSetResponseToken, &response_token_); |
| |
| unsigned int temp_seq; |
| if (!GetUIntFromJsonObject(jmessage_, kSequenceNumber, &temp_seq)) { |
| return false; |
| } |
| if (temp_seq > 0xFFFFFFFF) |
| return false; |
| seq_ = static_cast<uint32>(temp_seq); |
| |
| return true; |
| } |
| |
| std::string RoapMessageBase::Serialize() { |
| Json::Value message; |
| SerializeElement(&message); |
| Json::StyledWriter writer; |
| return writer.write(message); |
| } |
| |
| void RoapMessageBase::SerializeElement(Json::Value* message) { |
| ASSERT(message != NULL); |
| (*message)[kMessageType] = kMessageTypes[type_]; |
| (*message)[kOffererSessionId] = offer_session_id_; |
| if (!answer_session_id_.empty()) |
| (*message)[kAnswererSessionId] = answer_session_id_; |
| if (!session_token_.empty()) |
| (*message)[kSessionToken] = session_token_; |
| if (!response_token_.empty()) |
| (*message)[kResponseToken] = response_token_; |
| (*message)[kSequenceNumber] = seq_; |
| } |
| |
| RoapOffer::RoapOffer(const std::string& offer_session_id, |
| const std::string& answer_session_id, |
| const std::string& session_token, |
| uint32 seq, |
| uint32 tie_breaker, |
| const SessionDescription* desc, |
| const std::vector<cricket::Candidate>& candidates) |
| : RoapMessageBase(kOffer, offer_session_id, answer_session_id, |
| session_token, "", seq), |
| tie_breaker_(tie_breaker), |
| desc_(desc), |
| candidates_(candidates) { |
| } |
| |
| RoapOffer::RoapOffer(const RoapMessageBase& base) |
| : RoapMessageBase(base), |
| desc_(NULL) {} |
| |
| bool RoapOffer::Parse() { |
| if (!GetUIntFromJsonObject(jmessage_, kTieBreaker, &tie_breaker_)) { |
| return false; |
| } |
| |
| std::string sdp_message; |
| if (!GetStringFromJsonObject(jmessage_, kSessionDescription, &sdp_message)) |
| return false; |
| |
| parsed_desc_.reset(new cricket::SessionDescription()); |
| return SdpDeserialize(sdp_message, parsed_desc_.get(), |
| &candidates_); |
| } |
| |
| void RoapOffer::SerializeElement(Json::Value* message) { |
| ASSERT(message != NULL); |
| RoapMessageBase::SerializeElement(message); |
| (*message)[kTieBreaker] = tie_breaker_; |
| (*message)[kSessionDescription] = SdpSerialize(*desc_, candidates_); |
| } |
| |
| RoapAnswer::RoapAnswer(const std::string& offer_session_id, |
| const std::string& answer_session_id, |
| const std::string& session_token, |
| const std::string& response_token, |
| uint32 seq, |
| const SessionDescription* desc, |
| const std::vector<Candidate>& candidates) |
| : RoapMessageBase(kAnswer, offer_session_id, answer_session_id, |
| session_token, response_token, seq), |
| desc_(desc), |
| candidates_(candidates) { |
| } |
| |
| RoapAnswer::RoapAnswer(const RoapMessageBase& base) |
| : RoapMessageBase(base), |
| more_coming_(false), |
| desc_(NULL) {} |
| |
| bool RoapAnswer::Parse() { |
| std::string more; |
| if (GetStringFromJsonObject(jmessage_, kMoreComing, &more) && more == "true") |
| more_coming_ = true; |
| |
| std::string sdp_message; |
| if (!GetStringFromJsonObject(jmessage_, kSessionDescription, &sdp_message)) |
| return false; |
| |
| parsed_desc_.reset(new cricket::SessionDescription()); |
| return SdpDeserialize(sdp_message, parsed_desc_.get(), &candidates_); |
| } |
| |
| void RoapAnswer::SerializeElement(Json::Value* message) { |
| ASSERT(message != NULL); |
| RoapMessageBase::SerializeElement(message); |
| |
| (*message)[kSessionDescription] = SdpSerialize(*desc_, candidates_); |
| } |
| |
| RoapError::RoapError(const RoapMessageBase& base) |
| : RoapMessageBase(base), error_(kFailed) { |
| } |
| |
| RoapError::RoapError(const std::string& offer_session_id, |
| const std::string& answer_session_id, |
| const std::string& session_token, |
| const std::string& response_token, |
| uint32 seq, |
| RoapErrorCode error) |
| : RoapMessageBase(kError, offer_session_id, answer_session_id, |
| session_token, response_token, seq), |
| error_(error) { |
| } |
| |
| bool RoapError::Parse() { |
| std::string error_string; |
| GetStringFromJsonObject(jmessage_, kErrorType, &error_string); |
| if (error_string.empty()) |
| return false; |
| for (int i = 0; i < ARRAY_SIZE(kErrorMessages); i++) { |
| if (error_string == kErrorMessages[i]) { |
| error_ = static_cast<RoapErrorCode>(i); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| void RoapError::SerializeElement(Json::Value* message) { |
| ASSERT(message != NULL); |
| ASSERT(error_< ARRAY_SIZE(kErrorMessages)); |
| RoapMessageBase::SerializeElement(message); |
| |
| (*message)[kErrorType] = kErrorMessages[error_]; |
| } |
| |
| RoapOk::RoapOk(const RoapMessageBase& base) |
| : RoapMessageBase(base) { |
| } |
| |
| RoapOk::RoapOk(const std::string& offer_session_id, |
| const std::string& answer_session_id, |
| const std::string& session_token, |
| const std::string& response_token, |
| uint32 seq) |
| : RoapMessageBase(kOk, offer_session_id, answer_session_id, session_token, |
| response_token, seq) { |
| } |
| |
| RoapShutdown::RoapShutdown(const RoapMessageBase& base) |
| : RoapMessageBase(base) { |
| } |
| |
| RoapShutdown::RoapShutdown(const std::string& offer_session_id, |
| const std::string& answer_session_id, |
| const std::string& session_token, |
| uint32 seq) |
| : RoapMessageBase(kShutdown, offer_session_id, answer_session_id, |
| session_token, "", seq) { |
| } |
| |
| } // namespace webrtc |