void SecureTunnelingFeature::OnSubscribeToTunnelsNotifyResponse()

in source/tunneling/SecureTunnelingFeature.cpp [144:223]


                void SecureTunnelingFeature::OnSubscribeToTunnelsNotifyResponse(
                    SecureTunnelingNotifyResponse *response,
                    int ioErr)
                {
                    LOG_DEBUG(TAG, "Received MQTT Tunnel Notification");

                    if (ioErr || !response)
                    {
                        LOGM_ERROR(TAG, "OnSubscribeToTunnelsNotifyResponse received error. ioErr=%d", ioErr);
                        return;
                    }

                    for (auto &c : mContexts)
                    {
                        if (c->IsDuplicateNotification(*response))
                        {
                            LOG_INFO(TAG, "Received duplicate MQTT Tunnel Notification. Ignoring...");
                            return;
                        }
                    }

                    string clientMode = response->ClientMode->c_str();
                    if (clientMode != "destination")
                    {
                        LOGM_ERROR(TAG, "Unexpected client mode: %s", clientMode.c_str());
                        return;
                    }

                    size_t nServices = response->Services->size();
                    if (nServices == 0)
                    {
                        LOG_ERROR(TAG, "no service requested");
                        return;
                    }
                    if (nServices > 1)
                    {
                        LOG_ERROR(
                            TAG,
                            "Received a multi-port tunnel request, but multi-port tunneling is not currently supported "
                            "by Device Client.");
                        return;
                    }

                    string accessToken = response->ClientAccessToken->c_str();
                    if (accessToken.empty())
                    {
                        LOG_ERROR(TAG, "access token cannot be empty");
                        return;
                    }

                    string region = response->Region->c_str();
                    if (region.empty())
                    {
                        LOG_ERROR(TAG, "region cannot be empty");
                        return;
                    }

                    string service = response->Services->at(0).c_str();
                    uint16_t port = GetPortFromService(service);
                    if (!IsValidPort(port))
                    {
                        LOGM_ERROR(TAG, "Requested service is not supported: %s", service.c_str());
                        return;
                    }

                    LOGM_DEBUG(TAG, "Region=%s, Service=%s", region.c_str(), service.c_str());

                    std::unique_ptr<SecureTunnelingContext> context =
                        unique_ptr<SecureTunnelingContext>(new SecureTunnelingContext(
                            mSharedCrtResourceManager,
                            mRootCa,
                            accessToken,
                            GetEndpoint(region),
                            port,
                            bind(&SecureTunnelingFeature::OnConnectionShutdown, this, placeholders::_1)));
                    if (context->ConnectToSecureTunnel())
                    {
                        mContexts.push_back(std::move(context));
                    }
                }