Alexa SDK庖丁解牛-第九回:connect server过程

1.

class HTTP2Transport

: public TransportInterface

, public PostConnectObserverInterface

, public PostConnectSendMessageInterface

, public std::enable_shared_from_this<HTTP2Transport> {

bool connect() override;

}

overide(重写)基类的成员函数,派生类重定义基类的虚函数,即会覆盖基类的虚函数,参考overload(重载),new(重定义)

std::shared_ptr<alexaClientSDK::authDelegate::AuthDelegate> authDelegate =

alexaClientSDK::authDelegate::AuthDelegate::create();

authDelegate 的实例过程会初始化一个httppost实例,authDelegate 的初始化会用httppost去请求refresh token;

bool AuthDelegate::init() {

m_refreshAndNotifyThread = std::thread(&AuthDelegate::refreshAndNotifyThreadFunction, this);

}

//完成refresh token的获取成功

client->connect(endpoint);

=>

void AVSConnectionManager::enable() {

m_isEnabled = true;

m_messageRouter->enable();

}

=>

void MessageRouter::enable() {

//通知观察者状态更新

setConnectionStatusLocked();

//HTTP2Transport::create(),connect服务器

createActiveTransportLocked();

}

void MessageRouter::createActiveTransportLocked() {

//http2transport的初始化,

auto transport =

createTransport(m_authDelegate, m_attachmentManager, m_avsEndpoint, shared_from_this(), shared_from_this());

if (transport && transport->connect()) {

m_transports.push_back(transport);

m_activeTransport = transport;

} else {

safelyResetActiveTransportLocked();

setConnectionStatusLocked(

ConnectionStatusObserverInterface::Status::DISCONNECTED,

ConnectionStatusObserverInterface::ChangedReason::INTERNAL_ERROR);

ACSDK_ERROR(

LX("createActiveTransportLockedFailed").d("reason", transport ? "internalError" : "createTransportFailed"));

}

}

 

bool HTTP2Transport::connect() {

m_multi = avsCommon::utils::libcurlUtils::CurlMultiHandleWrapper::create();

if (curl_multi_setopt(m_multi->getCurlHandle(), CURLMOPT_PIPELINING, 2L) != CURLM_OK)

 

1) setupDownchannelStream(&reason);

2) m_postConnectObject->doPostConnect(shared_from_this());

3) m_networkThread = std::thread(&HTTP2Transport::networkLoop, this);

}

 

1) 设置DownchannelStream

bool HTTP2Transport::setupDownchannelStream(ConnectionStatusObserverInterface::ChangedReason* reason) {

std::string authToken = m_authDelegate->getAuthToken();

std::string url = m_avsEndpoint + AVS_DOWNCHANNEL_URL_PATH_EXTENSION;

m_downchannelStream = m_streamPool.createGetStream(url, authToken, m_messageConsumer);

m_downchannelStream->setConnectionTimeout(ESTABLISH_CONNECTION_TIMEOUT);

m_multi->addHandle(m_downchannelStream->getCurlHandle());

m_activeStreams.insert(ActiveTransferEntry(m_downchannelStream->getCurlHandle(), m_downchannelStream));

}

std::shared_ptr<HTTP2Stream> HTTP2StreamPool::createGetStream() {

stream->initGet(url, authToken);

}

bool HTTP2Stream::initGet(const std::string& url, const std::string& authToken) {

setCommonOptions(url, authToken)() {

m_transfer.setURL(url);

m_transfer.addHTTPHeader(authHeader.str());

m_transfer.setWriteCallback(&HTTP2Stream::writeCallback, this);

m_transfer.setHeaderCallback(&HTTP2Stream::headerCallback, this);

setopt(CURLOPT_TCP_KEEPALIVE, "CURLOPT_TCP_KEEPALIVE", 1);

}

}

2) 监听post是否成功:先更新m_contextManager->getContext,notify线程void ContextManager::updateStatesLoop(),request请求入队列,为downchannel连接成功后,postconnect做准备;

bool PostConnectSynchronizer::doPostConnect(std::shared_ptr<HTTP2Transport> transport) {

m_postConnectThread = std::thread(&PostConnectSynchronizer::postConnectLoop, this);

//监听post是否成功,void HTTP2Transport::cleanupFinishedStreams()函数的观察者会发送

it->second->notifyRequestObserver()-》void HTTP2Stream::notifyRequestObserver()=》

void MessageRequest::sendCompleted()=>void PostConnectSynchronizer::onSendCompleted()

}

void PostConnectSynchronizer::postConnectLoop() {

while (!isStopping() && !isPostConnected()) {

{

std::unique_lock<std::mutex> lock(m_mutex);

if (!m_contextFetchInProgress) {

//notify线程void ContextManager::updateStatesLoop(),细节见备注

PostConnectObject::m_contextManager->getContext(shared_from_this());

m_contextFetchInProgress = true;

}

}

m_wakeRetryTrigger.wait_for(lock, retryBackoff, [this] { return m_isPostConnected || m_isStopping; });

}

}

备注

requestStatesLocked(stateProviderLock);

=>

void ContextManager::sendContextAndClearQueue()

=>

void PostConnectSynchronizer::onContextAvailable(const std::string& jsonContext) {}

=>

void HTTP2Transport::sendPostConnectMessage(std::shared_ptr<MessageRequest> request) {

enqueueRequest(request, true);

}

题外话

std::shared_ptr<PostConnectObject> PostConnectObject::create() {

if (!m_contextManager) {

ACSDK_ERROR(LX("postCreateFailed").d("reason", "contextManagerNullData"));

return nullptr;

}

 

return std::shared_ptr<PostConnectObject>(new PostConnectSynchronizer());

}

std::shared_ptr<HTTP2Transport> HTTP2Transport::create(

std::shared_ptr<AuthDelegateInterface> authDelegate,

const std::string& avsEndpoint,

std::shared_ptr<MessageConsumerInterface> messageConsumerInterface,

std::shared_ptr<AttachmentManager> attachmentManager,

std::shared_ptr<TransportObserverInterface> observer) {

std::shared_ptr<PostConnectObject> postConnectObject = PostConnectObject::create();

 

if (!postConnectObject) {

ACSDK_ERROR(LX("HTTP2Transport::createFailed").d("reason", "nullPostConnectObject"));

return nullptr;

}

 

return std::shared_ptr<HTTP2Transport>(new HTTP2Transport(

authDelegate, avsEndpoint, messageConsumerInterface, attachmentManager, postConnectObject, observer));

}

3) m_networkThread = std::thread(&HTTP2Transport::networkLoop, this);

void HTTP2Transport::networkLoop() {

(1)与服务器建连,当收到200退出while循环;

(2)处理response(......)

}

这里介绍下get方式连接服务器,连接成功跳出

 

这里分析下get,post:

1)networkLoop函数有两个while循环,第一个循环使用m_downchannelStream来完成与服务器的连接,其中m_downchannelStream初始化了initGet,连接服务器后用它来接收指令消息;

2)连接成功后状态更新,networkLoop跳出第一个循环,进入第二个while循环,cleanupFinishedStreams没有查询到downchannel之类的对象对downchannel进行notifyObserversOnServerSideDisconnect

3)在第二个循环中processNextOutgoingMessage=》dequeueRequest获取post connect request请求

-》createPostStream

(!m_transfer.setReadCallback(HTTP2Stream::readCallback, this))

(!setCommonOptions(url, authToken))

 

downchannel 定义:The downchannel remains open in a half-closed state from the device and open from AVS for the life of the connection. The downchannel is primarily used to send cloud-initiated directives and audio attachments to your client.

1.先通过GET request to /{{API version}}/directives建立downchannel通道;

2.通过POST request to /{{API version}}/events on a new event stream on the existing connection ,至此与服务器建立connect连接;

3.随后的连接如下:

1)Send events to and receive directives from AVS

2)Receive cloud-initiated directives on the downchannel stream

 

client发起请求的规则:Requests are handled sequentially. Therefore, new requests should be sent after Alexa has started responding to your previous request (once the previous request returns headers).

并发请求规则:

  1. Your product opens a stream and sends a multipart message consisting of one JSON-formatted event and up to one binary audio attachment (zero or one). For more information, see Structuring an HTTP/2 Request.
  2. AVS returns multipart messages consisting of one more JSON-formatted directives and corresponding audio attachments on the same stream, potentially before streaming is complete. The url attribute that follows cid: in a Play or Speak directive will also appear in the header of the associated audio attachment.
  3. Following a response from AVS the event stream should be closed.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值