Skip to content

Commit

Permalink
[coap] return unexpected coap response code as error (#176)
Browse files Browse the repository at this point in the history
  • Loading branch information
wgtdkp authored Apr 12, 2021
1 parent 89af74f commit 6e766ce
Show file tree
Hide file tree
Showing 8 changed files with 170 additions and 36 deletions.
7 changes: 6 additions & 1 deletion include/commissioner/error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,15 @@ enum class ErrorCode : int
*/
kRejected = 16,

/**
* The operation was failed because with a CoAP error.
*/
kCoapError = 17,

/**
* The error is out of the address space of OT Commissioner.
*/
kUnknown = 17,
kUnknown = 18,
};

/**
Expand Down
2 changes: 2 additions & 0 deletions src/common/error.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ static std::string ErrorCodeToString(ErrorCode code)
return "INVALID_STATE";
case ErrorCode::kRejected:
return "REJECTED";
case ErrorCode::kCoapError:
return "COAP_ERROR";
case ErrorCode::kUnknown:
return "UNKNOWN";

Expand Down
2 changes: 2 additions & 0 deletions src/common/error_macros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@
Error { ErrorCode::kInvalidState, fmt::format(FMT_STRING((aFormat)), ##__VA_ARGS__) }
#define ERROR_REJECTED(aFormat, ...) \
Error { ErrorCode::kRejected, fmt::format(FMT_STRING((aFormat)), ##__VA_ARGS__) }
#define ERROR_COAP_ERROR(aFormat, ...) \
Error { ErrorCode::kCoapError, fmt::format(FMT_STRING((aFormat)), ##__VA_ARGS__) }
#define ERROR_UNKNOWN(aFormat, ...) \
Error { ErrorCode::kUnknown, fmt::format(FMT_STRING((aFormat)), ##__VA_ARGS__) }

Expand Down
1 change: 1 addition & 0 deletions src/common/error_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ TEST_CASE("error-to-string", "[error]")
CHECK_ERROR_STR_STARTS_WITH_ERROR_NAME(ABORTED);
CHECK_ERROR_STR_STARTS_WITH_ERROR_NAME(INVALID_STATE);
CHECK_ERROR_STR_STARTS_WITH_ERROR_NAME(REJECTED);
CHECK_ERROR_STR_STARTS_WITH_ERROR_NAME(COAP_ERROR);
CHECK_ERROR_STR_STARTS_WITH_ERROR_NAME(UNKNOWN);

#undef CHECK_ERROR_STR_STARTS_WITH_ERROR_NAME
Expand Down
126 changes: 125 additions & 1 deletion src/library/coap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,115 @@ namespace commissioner {

namespace coap {

std::string CodeToString(Code aCode)
{
std::string str;

switch (aCode)
{
/*
* Methods (0.XX).
*/
case Code::kEmpty:
str = "EMPTY";
break;
case Code::kGet:
str = "GET";
break;
case Code::kPost:
str = "POST";
break;

case Code::kPut:
str = "PUT";
break;

case Code::kDelete:
str = "DELETE";
break;

/*
* Success (2.XX).
*/
case Code::kCreated:
str = "CREATED";
break;
case Code::kDeleted:
str = "DELETED";
break;
case Code::kValid:
str = "VALID";
break;
case Code::kChanged:
str = "CHANGED";
break;
case Code::kContent:
str = "CONTENT";
break;

/*
* Client side errors (4.XX).
*/
case Code::kBadRequest:
str = "BAD_REQUEST";
break;
case Code::kUnauthorized:
str = "UNAUTHORIZED";
break;
case Code::kBadOption:
str = "BAD_OPTION";
break;
case Code::kForBidden:
str = "FORBIDDEN";
break;
case Code::kNotFound:
str = "NOT_FOUND";
break;
case Code::kMethodNotAllowed:
str = "METHOD_NOT_ALLOWED";
break;
case Code::kNotAcceptable:
str = "NOT_ACCEPTABLE";
break;
case Code::kPreconditionFailed:
str = "PRECONDITIONFAILED";
break;
case Code::kRequestTooLarge:
str = "REQUEST_TOOL_LARGE";
break;
case Code::kUnsupportedFormat:
str = "UNSUPPORTED_FORMAT";
break;

/*
* Server side errors (5.XX).
*/
case Code::kInternalError:
str = "INTERNAL_ERROR";
break;
case Code::kNotImplemented:
str = "NOT_IMPLEMENTED";
break;
case Code::kBadGateway:
str = "BAD_GATEWAY";
break;
case Code::kServiceUnavailable:
str = "SERVICE_UNAVAILABLE";
break;
case Code::kGatewayTimeout:
str = "BATEWAY_TIMEOUT";
break;
case Code::kProxyNotSupported:
str = "PROXY_NOT_SUPPORTED";
break;
default:
str = "UNKNOWN";
break;
}

return "CoAP::" + str;
}

Message::Message(Type aType, Code aCode)
: Message()
{
Expand Down Expand Up @@ -567,7 +676,7 @@ void Coap::HandleRequest(const Request &aRequest)
return;
}

void Coap::HandleResponse(const Response &aResponse)
void Coap::HandleResponse(Response &aResponse)
{
const RequestHolder *requestHolder = nullptr;
std::string requestUri = "UNKNOWN_URI";
Expand All @@ -583,6 +692,7 @@ void Coap::HandleResponse(const Response &aResponse)
}

requestHolder->mRequest->GetUriPath(requestUri).IgnoreError();
aResponse.SetRequestUri(requestUri);
switch (aResponse.GetType())
{
case Type::kReset:
Expand Down Expand Up @@ -1154,6 +1264,20 @@ void Message::SetToken(uint8_t aTokenLength)
random::non_crypto::FillBuffer(mHeader.mToken, aTokenLength);
}

void Message::SetRequestUri(const std::string &aUri)
{
ASSERT(IsResponse());

mRequestUri = aUri;
}

std::string Message::GetRequestUri(void) const
{
ASSERT(IsResponse());

return mRequestUri;
}

} // namespace coap

} // namespace commissioner
Expand Down
11 changes: 10 additions & 1 deletion src/library/coap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ enum class Code : uint8_t

#undef OT_COAP_CODE

std::string CodeToString(Code aCode);

/**
* CoAP Option Numbers
*/
Expand Down Expand Up @@ -508,6 +510,9 @@ class Message

static Error NormalizeUriPath(std::string &uriPath);

void SetRequestUri(const std::string &aUri);
std::string GetRequestUri(void) const;

protected:
Error Serialize(const Header &aHeader, ByteArray &aBuf) const;
static Error Deserialize(Header &aHeader, const ByteArray &aBuf, size_t &aOffset);
Expand Down Expand Up @@ -545,6 +550,10 @@ class Message
std::map<OptionType, OptionValue> mOptions;
ByteArray mPayload;

// The URI of the request to which this response messages
// is associated. Should only be set/get by a response message.
std::string mRequestUri;

MessageSubType mSubType;

mutable Endpoint *mEndpoint = nullptr;
Expand Down Expand Up @@ -746,7 +755,7 @@ class Coap
void HandleRequest(const Request &aRequest);

// Handle empty and response message
void HandleResponse(const Response &aResponse);
void HandleResponse(Response &aResponse);

Error SendEmptyMessage(Type aType, const Request &aRequest);

Expand Down
56 changes: 23 additions & 33 deletions src/library/commissioner_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,10 +368,7 @@ void CommissionerImpl::GetCommissionerDataset(Handler<CommissionerDataset> aHand
CommissionerDataset dataset;

SuccessOrExit(error = aError);
ASSERT(aResponse != nullptr);

VerifyOrExit(aResponse->GetCode() == coap::Code::kChanged,
error = ERROR_BAD_FORMAT("expect CoAP::CHANGED for MGMT_COMM_GET.rsp message"));
SuccessOrExit(error = CheckCoapResponseCode(*aResponse));

SuccessOrExit(error = DecodeCommissionerDataset(dataset, *aResponse));

Expand Down Expand Up @@ -473,8 +470,7 @@ void CommissionerImpl::GetRawActiveDataset(Handler<ByteArray> aHandler, uint16_t
Error error;

SuccessOrExit(error = aError);
VerifyOrExit(aResponse->GetCode() == coap::Code::kChanged,
error = ERROR_BAD_FORMAT("expect CoAP::CHANGED for MGMT_ACTIVE_GET.rsp message"));
SuccessOrExit(error = CheckCoapResponseCode(*aResponse));

aHandler(&aResponse->GetPayload(), error);

Expand Down Expand Up @@ -579,8 +575,7 @@ void CommissionerImpl::GetPendingDataset(Handler<PendingOperationalDataset> aHan
PendingOperationalDataset dataset;

SuccessOrExit(error = aError);
VerifyOrExit(aResponse->GetCode() == coap::Code::kChanged,
error = ERROR_BAD_FORMAT("expect CoAP::CHANGED for MGMT_PENDING_GET.rsp message"));
SuccessOrExit(error = CheckCoapResponseCode(*aResponse));

SuccessOrExit(error = DecodePendingOperationalDataset(dataset, *aResponse));
if (dataset.mPresentFlags != 0)
Expand Down Expand Up @@ -715,8 +710,7 @@ void CommissionerImpl::GetBbrDataset(Handler<BbrDataset> aHandler, uint16_t aDat
BbrDataset dataset;

SuccessOrExit(error = aError);
VerifyOrExit(aResponse->GetCode() == coap::Code::kChanged,
error = ERROR_BAD_FORMAT("expect CoAP::CHANGED for MGMT_BBR_GET.rsp message"));
SuccessOrExit(error = CheckCoapResponseCode(*aResponse));

SuccessOrExit(error = DecodeBbrDataset(dataset, *aResponse));

Expand Down Expand Up @@ -968,10 +962,7 @@ void CommissionerImpl::RegisterMulticastListener(Handler<uint8_t>
uint8_t status;

SuccessOrExit(error = aError);
VerifyOrExit(aResponse->GetCode() != coap::Code::kUnauthorized,
error = ERROR_SECURITY("response code is CoAP::UNAUTHORIZED"));
VerifyOrExit(aResponse->GetCode() == coap::Code::kChanged,
error = ERROR_BAD_FORMAT("expect response code as CoAP::CHANGED"));
SuccessOrExit(error = CheckCoapResponseCode(*aResponse));

statusTlv = GetTlv(tlv::Type::kThreadStatus, *aResponse, tlv::Scope::kThread);
VerifyOrExit(statusTlv != nullptr, error = ERROR_BAD_FORMAT("no valid State TLV found in response"));
Expand Down Expand Up @@ -1037,10 +1028,7 @@ void CommissionerImpl::AnnounceBegin(ErrorHandler aHandler,
Error error;

SuccessOrExit(error = aError);
VerifyOrExit(aResponse->GetCode() != coap::Code::kUnauthorized,
error = ERROR_SECURITY("response code is CoAP::UNAUTHORIZED"));
VerifyOrExit(aResponse->GetCode() == coap::Code::kChanged,
error = ERROR_BAD_FORMAT("expect response code as CoAP::CHANGED"));
SuccessOrExit(error = CheckCoapResponseCode(*aResponse));

exit:
aHandler(error);
Expand Down Expand Up @@ -1091,10 +1079,7 @@ void CommissionerImpl::PanIdQuery(ErrorHandler aHandler,
Error error;

SuccessOrExit(error = aError);
VerifyOrExit(aResponse->GetCode() != coap::Code::kUnauthorized,
error = ERROR_SECURITY("response code is CoAP::UNAUTHORIZED"));
VerifyOrExit(aResponse->GetCode() == coap::Code::kChanged,
error = ERROR_BAD_FORMAT("expect response code as CoAP::CHANGED"));
SuccessOrExit(error = CheckCoapResponseCode(*aResponse));

exit:
aHandler(error);
Expand Down Expand Up @@ -1146,10 +1131,7 @@ void CommissionerImpl::EnergyScan(ErrorHandler aHandler,
Error error;

SuccessOrExit(error = aError);
VerifyOrExit(aResponse->GetCode() != coap::Code::kUnauthorized,
error = ERROR_SECURITY("response code is CoAP::UNAUTHORIZED"));
VerifyOrExit(aResponse->GetCode() == coap::Code::kChanged,
error = ERROR_BAD_FORMAT("expect response code as CoAP::CHANGED"));
SuccessOrExit(error = CheckCoapResponseCode(*aResponse));

exit:
aHandler(error);
Expand Down Expand Up @@ -1201,9 +1183,7 @@ void CommissionerImpl::SendPetition(PetitionHandler aHandler)
std::string existingCommissionerId;

SuccessOrExit(error = aError);

VerifyOrExit(aResponse->GetCode() == coap::Code::kChanged,
error = ERROR_BAD_FORMAT("expect response code as CoAP::CHANGED"));
SuccessOrExit(error = CheckCoapResponseCode(*aResponse));

SuccessOrExit(error = GetTlvSet(tlvSet, *aResponse));

Expand Down Expand Up @@ -1361,16 +1341,26 @@ tlv::TlvPtr GetTlv(tlv::Type aTlvType, const coap::Message &aMessage, tlv::Scope
return tlv::GetTlv(aTlvType, aMessage.GetPayload(), aScope);
}

Error CommissionerImpl::CheckCoapResponseCode(const coap::Response &aResponse)
{
Error error = ERROR_NONE;

VerifyOrExit(aResponse.GetCode() == coap::Code::kChanged,
error = ERROR_COAP_ERROR("request for {} failed: {}", aResponse.GetRequestUri(),
coap::CodeToString(aResponse.GetCode())));

exit:
return error;
}

Error CommissionerImpl::HandleStateResponse(const coap::Response *aResponse, Error aError, bool aStateTlvIsMandatory)
{
Error error;
tlv::TlvPtr stateTlv = nullptr;

SuccessOrExit(error = aError);
VerifyOrExit(aResponse->GetCode() != coap::Code::kUnauthorized,
error = ERROR_SECURITY("response code is CoAP::UNAUTHORIZED"));
VerifyOrExit(aResponse->GetCode() == coap::Code::kChanged,
error = ERROR_BAD_FORMAT("expect response code as CoAP::CHANGED"));
SuccessOrExit(error = CheckCoapResponseCode(*aResponse));

stateTlv = GetTlv(tlv::Type::kState, *aResponse);
VerifyOrExit((stateTlv != nullptr || !aStateTlvIsMandatory),
error = ERROR_BAD_FORMAT("no valid State TLV found in response"));
Expand Down
1 change: 1 addition & 0 deletions src/library/commissioner_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ class CommissionerImpl : public Commissioner
static Error ValidateConfig(const Config &aConfig);
void LoggingConfig();

static Error CheckCoapResponseCode(const coap::Response &aResponse);
static Error HandleStateResponse(const coap::Response *aResponse, Error aError, bool aStateTlvIsMandatory = true);

static ByteArray GetActiveOperationalDatasetTlvs(uint16_t aDatasetFlags);
Expand Down

0 comments on commit 6e766ce

Please sign in to comment.