blob: e0528a7001bbac641adfea57b0c88cd17a6b6649 [file] [log] [blame]
/*
* 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