blob: 921ac3a62883711e54a9567e43f9eb4ca289a820 [file] [log] [blame]
/*
*
* Copyright (c) 2013-2017 Nest Labs, Inc.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file
* This file implements an unsolicited initiator (i.e., client) for
* the Weave Software Update (SWU) profile used for functional
* testing of the implementation of core message handlers for
* that profile.
*
*/
#include "ToolCommon.h"
#include "nlweaveswuclient.h"
namespace nl {
namespace Weave {
namespace Profiles {
using namespace nl::Weave::Profiles::SoftwareUpdate;
SoftwareUpdateClient::SoftwareUpdateClient()
{
FabricState = NULL;
ExchangeMgr = NULL;
}
SoftwareUpdateClient::~SoftwareUpdateClient()
{
FabricState = NULL;
ExchangeMgr = NULL;
}
WEAVE_ERROR SoftwareUpdateClient::Init(WeaveExchangeManager *exchangeMgr)
{
// Error if already initialized.
if (ExchangeMgr != NULL)
return WEAVE_ERROR_INCORRECT_STATE;
ExchangeMgr = exchangeMgr;
FabricState = exchangeMgr->FabricState;
return WEAVE_NO_ERROR;
}
WEAVE_ERROR SoftwareUpdateClient::Shutdown()
{
ExchangeMgr = NULL;
FabricState = NULL;
return WEAVE_NO_ERROR;
}
WEAVE_ERROR SoftwareUpdateClient::SendImageQueryRequest(WeaveConnection *con)
{
// Discard any existing exchange context.
// Effectively we can only have one SWU exchange with a single node at any one time.
if (ExchangeCtx != NULL)
{
ExchangeCtx->Close();
ExchangeCtx = NULL;
}
// Create a new exchange context.
ExchangeCtx = ExchangeMgr->NewContext(con, this);
if (ExchangeCtx == NULL)
return WEAVE_ERROR_NO_MEMORY;
return SendImageQueryRequest();
}
WEAVE_ERROR SoftwareUpdateClient::SendImageQueryRequest(uint64_t nodeId, IPAddress nodeAddr)
{
return SendImageQueryRequest(nodeId, nodeAddr, WEAVE_PORT);
}
WEAVE_ERROR SoftwareUpdateClient::SendImageQueryRequest(uint64_t nodeId, IPAddress nodeAddr, uint16_t port)
{
// Discard any existing exchange context. Effectively we can only have one SWU exchange with
// a single node at any one time.
if (ExchangeCtx != NULL)
{
ExchangeCtx->Close();
ExchangeCtx = NULL;
}
if (nodeAddr == IPAddress::Any)
nodeAddr = FabricState->SelectNodeAddress(nodeId);
// Create a new exchange context.
ExchangeCtx = ExchangeMgr->NewContext(nodeId, nodeAddr, this);
if (ExchangeCtx == NULL)
return WEAVE_ERROR_NO_MEMORY;
return SendImageQueryRequest();
}
WEAVE_ERROR SoftwareUpdateClient::SendImageQueryRequest()
{
printf("0 SendImageQueryRequest entering\n");
// Configure the encryption and signature types to be used to send the request.
ExchangeCtx->EncryptionType = EncryptionType;
ExchangeCtx->KeyId = KeyId;
// Arrange for messages in this exchange to go to our response handler.
ExchangeCtx->OnMessageReceived = HandleImageQueryResponse;
/*
* Build the ImageQuery request
*/
ProductSpec aProductSpec(0x235A /*vendorId*/, 1 /*productId*/, 1 /*productRev*/);
ReferencedString aVersion;
char aVersionStr[] = "1.0d1";
aVersion.init((uint8_t)(strlen(aVersionStr)), aVersionStr);
IntegrityTypeList aTypeList;
uint8_t updateTypeList[] = { kIntegrityType_SHA256 };
aTypeList.init(sizeof(updateTypeList), updateTypeList);
UpdateSchemeList aSchemeList;
uint8_t updateSchemeList[] = { kUpdateScheme_BDX };
aSchemeList.init(sizeof(updateSchemeList), updateSchemeList);
ImageQuery imageQuery;
imageQuery.init(aProductSpec, aVersion, aTypeList, aSchemeList,
NULL /*package*/, NULL /*locale*/, 0 /*target node id*/, NULL /*metadata*/);
PacketBuffer* imageQueryPayload = PacketBuffer::New();
imageQuery.pack(imageQueryPayload);
// Send an ImageQuery Request message. Discard the exchange context if the send fails.
WEAVE_ERROR err = ExchangeCtx->SendMessage(kWeaveProfile_SWU, kMsgType_ImageQuery, imageQueryPayload);
imageQueryPayload = NULL;
if (err != WEAVE_NO_ERROR)
{
printf(" 1 ExchangeCtx->Sendmessage(ImageQuery) FAILED\n");
ExchangeCtx->Close();
ExchangeCtx = NULL;
}
printf("2 SendImageQueryRequest exiting\n");
return err;
}
//ImageQuery response received
void SoftwareUpdateClient::HandleImageQueryResponse(ExchangeContext *ec, const IPPacketInfo *packetInfo, const WeaveMessageInfo *msgInfo, uint32_t profileId, uint8_t msgType, PacketBuffer *payloadImageQueryResponse)
{
printf("0 HandleImageQueryResponse entering\n");
SoftwareUpdateClient *swuApp = (SoftwareUpdateClient *)ec->AppState;
// Verify that the message is an ImageQuery Response.
if (profileId != kWeaveProfile_SWU)
{
printf(" 1 response is NOT a valid response\n");
// TODO: handle unexpected response
return;
}
else if (profileId == kWeaveProfile_SWU && msgType == kMsgType_ImageQueryStatus)
{
printf("Got an Image Query Status\n");
StatusReport statusReport;
StatusReport::parse(payloadImageQueryResponse, statusReport);
printf("Status Report -> Profile: 0x%X, Status: 0x%X\n", statusReport.mProfileId, statusReport.mStatusCode);
if (statusReport.mProfileId == kWeaveProfile_SWU && statusReport.mStatusCode == kStatus_NoUpdateAvailable)
{
printf("No Update Available\n");
}
return;
}
// Verify that the exchange context matches our current context. Bail if not.
if (ec != swuApp->ExchangeCtx)
{
printf(" 2 HandleImageQueryResponse exchange doesn't match\n");
return;
}
//print the contents of the ImageQuery response
ImageQueryResponse imageQueryResponse;
printf("err: %d\n", imageQueryResponse.parse(payloadImageQueryResponse, imageQueryResponse));
printf("====\n");
DumpMemory(payloadImageQueryResponse->Start(), payloadImageQueryResponse->DataLength(), "==> ", 16);
printf("====\n");
printf("uri.theLength: %d\n", imageQueryResponse.uri.theLength);
printf("uri.theString: %s\n", imageQueryResponse.uri.theString);
printf("versionSpec.theLength: %d\n", imageQueryResponse.versionSpec.theLength);
printf("versionSpec.theString: %s\n", imageQueryResponse.versionSpec.printString());
printf("integritySpec.type: %d\n", imageQueryResponse.integritySpec.type);
printf("updateScheme: %d\n", imageQueryResponse.updateScheme);
printf("updatePriority: %d\n", imageQueryResponse.updatePriority);
printf("updateCondition: %d\n", imageQueryResponse.updateCondition);
printf("reportStatus: %d\n", imageQueryResponse.reportStatus);
printf("====\n");
// Free the payload buffer.
PacketBuffer::Free(payloadImageQueryResponse);
// Discard the exchange context.
swuApp->ExchangeCtx->Close();
swuApp->ExchangeCtx = NULL;
printf("3 HandleImageQueryResponse exiting\n");
Done = true;
}
// Set the exchange context for the most recently started SWU exchange.
void SoftwareUpdateClient::SetExchangeCtx(ExchangeContext *ec)
{
ExchangeCtx = ec;
}
} // namespace Profiles
} // namespace Weave
} // namespace nl