<commit_before>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "voe_network_impl.h"

#include "channel.h"
#include "critical_section_wrapper.h"
#include "trace.h"
#include "voe_errors.h"
#include "voice_engine_impl.h"

namespace webrtc
{

VoENetwork* VoENetwork::GetInterface(VoiceEngine* voiceEngine)
{
    if (NULL == voiceEngine)
    {
        return NULL;
    }
    VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
    s->AddRef();
    return s;
}

VoENetworkImpl::VoENetworkImpl(voe::SharedData* shared) : _shared(shared)
{
    WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "VoENetworkImpl() - ctor");
}

VoENetworkImpl::~VoENetworkImpl()
{
    WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "~VoENetworkImpl() - dtor");
}

int VoENetworkImpl::RegisterExternalTransport(int channel,
                                              Transport& transport)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "SetExternalTransport(channel=%d, transport=0x%x)",
                 channel, &transport);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "SetExternalTransport() failed to locate channel");
        return -1;
    }
    return channelPtr->RegisterExternalTransport(transport);
}

int VoENetworkImpl::DeRegisterExternalTransport(int channel)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "DeRegisterExternalTransport(channel=%d)", channel);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "DeRegisterExternalTransport() failed to locate channel");
        return -1;
    }
    return channelPtr->DeRegisterExternalTransport();
}

int VoENetworkImpl::ReceivedRTPPacket(int channel,
                                      const void* data,
                                      unsigned int length)
{
    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "ReceivedRTPPacket(channel=%d, length=%u)", channel, length);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    if ((length < 12) || (length > 807))
    {
        _shared->SetLastError(VE_INVALID_PACKET, kTraceError,
            "ReceivedRTPPacket() invalid packet length");
        return -1;
    }
    if (NULL == data)
    {
        _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
            "ReceivedRTPPacket() invalid data vector");
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "ReceivedRTPPacket() failed to locate channel");
        return -1;
    }

    if (!channelPtr->ExternalTransport())
    {
        _shared->SetLastError(VE_INVALID_OPERATION, kTraceError,
            "ReceivedRTPPacket() external transport is not enabled");
        return -1;
    }
    return channelPtr->ReceivedRTPPacket((const int8_t*) data, length);
}

int VoENetworkImpl::ReceivedRTCPPacket(int channel, const void* data,
                                       unsigned int length)
{
    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "ReceivedRTCPPacket(channel=%d, length=%u)", channel, length);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    if (length < 4)
    {
        _shared->SetLastError(VE_INVALID_PACKET, kTraceError,
            "ReceivedRTCPPacket() invalid packet length");
        return -1;
    }
    if (NULL == data)
    {
        _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
            "ReceivedRTCPPacket() invalid data vector");
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "ReceivedRTCPPacket() failed to locate channel");
        return -1;
    }
    if (!channelPtr->ExternalTransport())
    {
        _shared->SetLastError(VE_INVALID_OPERATION, kTraceError,
            "ReceivedRTCPPacket() external transport is not enabled");
        return -1;
    }
    return channelPtr->ReceivedRTCPPacket((const int8_t*) data, length);
}

int VoENetworkImpl::SetPacketTimeoutNotification(int channel,
                                                 bool enable,
                                                 int timeoutSeconds)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "SetPacketTimeoutNotification(channel=%d, enable=%d, "
                 "timeoutSeconds=%d)",
                 channel, (int) enable, timeoutSeconds);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    if (enable &&
        ((timeoutSeconds < kVoiceEngineMinPacketTimeoutSec) ||
        (timeoutSeconds > kVoiceEngineMaxPacketTimeoutSec)))
    {
        _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
            "SetPacketTimeoutNotification() invalid timeout size");
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "SetPacketTimeoutNotification() failed to locate channel");
        return -1;
    }
    return channelPtr->SetPacketTimeoutNotification(enable, timeoutSeconds);
}

int VoENetworkImpl::GetPacketTimeoutNotification(int channel,
                                                 bool& enabled,
                                                 int& timeoutSeconds)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "GetPacketTimeoutNotification(channel=%d, enabled=?,"
                 " timeoutSeconds=?)", channel);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "GetPacketTimeoutNotification() failed to locate channel");
        return -1;
    }
    return channelPtr->GetPacketTimeoutNotification(enabled, timeoutSeconds);
}

int VoENetworkImpl::RegisterDeadOrAliveObserver(int channel,
                                                VoEConnectionObserver&
                                                observer)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "RegisterDeadOrAliveObserver(channel=%d, observer=0x%x)",
                 channel, &observer);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "RegisterDeadOrAliveObserver() failed to locate channel");
        return -1;
    }
    return channelPtr->RegisterDeadOrAliveObserver(observer);
}

int VoENetworkImpl::DeRegisterDeadOrAliveObserver(int channel)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "DeRegisterDeadOrAliveObserver(channel=%d)", channel);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "DeRegisterDeadOrAliveObserver() failed to locate channel");
        return -1;
    }
    return channelPtr->DeRegisterDeadOrAliveObserver();
}

int VoENetworkImpl::SetPeriodicDeadOrAliveStatus(int channel, bool enable,
                                                 int sampleTimeSeconds)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "SetPeriodicDeadOrAliveStatus(channel=%d, enable=%d,"
                 " sampleTimeSeconds=%d)",
                 channel, enable, sampleTimeSeconds);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    if (enable &&
        ((sampleTimeSeconds < kVoiceEngineMinSampleTimeSec) ||
        (sampleTimeSeconds > kVoiceEngineMaxSampleTimeSec)))
    {
        _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
            "SetPeriodicDeadOrAliveStatus() invalid sample time");
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "SetPeriodicDeadOrAliveStatus() failed to locate channel");
        return -1;
    }
    return channelPtr->SetPeriodicDeadOrAliveStatus(enable, sampleTimeSeconds);
}

int VoENetworkImpl::GetPeriodicDeadOrAliveStatus(int channel,
                                                 bool& enabled,
                                                 int& sampleTimeSeconds)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "GetPeriodicDeadOrAliveStatus(channel=%d, enabled=?,"
                 " sampleTimeSeconds=?)", channel);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "GetPeriodicDeadOrAliveStatus() failed to locate channel");
        return -1;
    }
    return channelPtr->GetPeriodicDeadOrAliveStatus(enabled,
                                                    sampleTimeSeconds);
}

} // namespace webrtc
<commit_msg>Relax VoE's max packet length threshold.<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/voice_engine/voe_network_impl.h"

#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/logging.h"
#include "webrtc/system_wrappers/interface/trace.h"
#include "webrtc/voice_engine/channel.h"
#include "webrtc/voice_engine/include/voe_errors.h"
#include "webrtc/voice_engine/voice_engine_impl.h"

namespace webrtc
{

VoENetwork* VoENetwork::GetInterface(VoiceEngine* voiceEngine)
{
    if (NULL == voiceEngine)
    {
        return NULL;
    }
    VoiceEngineImpl* s = static_cast<VoiceEngineImpl*>(voiceEngine);
    s->AddRef();
    return s;
}

VoENetworkImpl::VoENetworkImpl(voe::SharedData* shared) : _shared(shared)
{
    WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "VoENetworkImpl() - ctor");
}

VoENetworkImpl::~VoENetworkImpl()
{
    WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "~VoENetworkImpl() - dtor");
}

int VoENetworkImpl::RegisterExternalTransport(int channel,
                                              Transport& transport)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "SetExternalTransport(channel=%d, transport=0x%x)",
                 channel, &transport);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "SetExternalTransport() failed to locate channel");
        return -1;
    }
    return channelPtr->RegisterExternalTransport(transport);
}

int VoENetworkImpl::DeRegisterExternalTransport(int channel)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "DeRegisterExternalTransport(channel=%d)", channel);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "DeRegisterExternalTransport() failed to locate channel");
        return -1;
    }
    return channelPtr->DeRegisterExternalTransport();
}

int VoENetworkImpl::ReceivedRTPPacket(int channel,
                                      const void* data,
                                      unsigned int length)
{
    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "ReceivedRTPPacket(channel=%d, length=%u)", channel, length);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    // L16 at 32 kHz, stereo, 10 ms frames (+12 byte RTP header) -> 1292 bytes
    if ((length < 12) || (length > 1292))
    {
        _shared->SetLastError(VE_INVALID_PACKET);
        LOG(LS_ERROR) << "Invalid packet length: " << length;
        return -1;
    }
    if (NULL == data)
    {
        _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
            "ReceivedRTPPacket() invalid data vector");
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "ReceivedRTPPacket() failed to locate channel");
        return -1;
    }

    if (!channelPtr->ExternalTransport())
    {
        _shared->SetLastError(VE_INVALID_OPERATION, kTraceError,
            "ReceivedRTPPacket() external transport is not enabled");
        return -1;
    }
    return channelPtr->ReceivedRTPPacket((const int8_t*) data, length);
}

int VoENetworkImpl::ReceivedRTCPPacket(int channel, const void* data,
                                       unsigned int length)
{
    WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "ReceivedRTCPPacket(channel=%d, length=%u)", channel, length);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    if (length < 4)
    {
        _shared->SetLastError(VE_INVALID_PACKET, kTraceError,
            "ReceivedRTCPPacket() invalid packet length");
        return -1;
    }
    if (NULL == data)
    {
        _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
            "ReceivedRTCPPacket() invalid data vector");
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "ReceivedRTCPPacket() failed to locate channel");
        return -1;
    }
    if (!channelPtr->ExternalTransport())
    {
        _shared->SetLastError(VE_INVALID_OPERATION, kTraceError,
            "ReceivedRTCPPacket() external transport is not enabled");
        return -1;
    }
    return channelPtr->ReceivedRTCPPacket((const int8_t*) data, length);
}

int VoENetworkImpl::SetPacketTimeoutNotification(int channel,
                                                 bool enable,
                                                 int timeoutSeconds)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "SetPacketTimeoutNotification(channel=%d, enable=%d, "
                 "timeoutSeconds=%d)",
                 channel, (int) enable, timeoutSeconds);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    if (enable &&
        ((timeoutSeconds < kVoiceEngineMinPacketTimeoutSec) ||
        (timeoutSeconds > kVoiceEngineMaxPacketTimeoutSec)))
    {
        _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
            "SetPacketTimeoutNotification() invalid timeout size");
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "SetPacketTimeoutNotification() failed to locate channel");
        return -1;
    }
    return channelPtr->SetPacketTimeoutNotification(enable, timeoutSeconds);
}

int VoENetworkImpl::GetPacketTimeoutNotification(int channel,
                                                 bool& enabled,
                                                 int& timeoutSeconds)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "GetPacketTimeoutNotification(channel=%d, enabled=?,"
                 " timeoutSeconds=?)", channel);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "GetPacketTimeoutNotification() failed to locate channel");
        return -1;
    }
    return channelPtr->GetPacketTimeoutNotification(enabled, timeoutSeconds);
}

int VoENetworkImpl::RegisterDeadOrAliveObserver(int channel,
                                                VoEConnectionObserver&
                                                observer)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "RegisterDeadOrAliveObserver(channel=%d, observer=0x%x)",
                 channel, &observer);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "RegisterDeadOrAliveObserver() failed to locate channel");
        return -1;
    }
    return channelPtr->RegisterDeadOrAliveObserver(observer);
}

int VoENetworkImpl::DeRegisterDeadOrAliveObserver(int channel)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "DeRegisterDeadOrAliveObserver(channel=%d)", channel);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "DeRegisterDeadOrAliveObserver() failed to locate channel");
        return -1;
    }
    return channelPtr->DeRegisterDeadOrAliveObserver();
}

int VoENetworkImpl::SetPeriodicDeadOrAliveStatus(int channel, bool enable,
                                                 int sampleTimeSeconds)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "SetPeriodicDeadOrAliveStatus(channel=%d, enable=%d,"
                 " sampleTimeSeconds=%d)",
                 channel, enable, sampleTimeSeconds);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    if (enable &&
        ((sampleTimeSeconds < kVoiceEngineMinSampleTimeSec) ||
        (sampleTimeSeconds > kVoiceEngineMaxSampleTimeSec)))
    {
        _shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
            "SetPeriodicDeadOrAliveStatus() invalid sample time");
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "SetPeriodicDeadOrAliveStatus() failed to locate channel");
        return -1;
    }
    return channelPtr->SetPeriodicDeadOrAliveStatus(enable, sampleTimeSeconds);
}

int VoENetworkImpl::GetPeriodicDeadOrAliveStatus(int channel,
                                                 bool& enabled,
                                                 int& sampleTimeSeconds)
{
    WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
                 "GetPeriodicDeadOrAliveStatus(channel=%d, enabled=?,"
                 " sampleTimeSeconds=?)", channel);
    if (!_shared->statistics().Initialized())
    {
        _shared->SetLastError(VE_NOT_INITED, kTraceError);
        return -1;
    }
    voe::ScopedChannel sc(_shared->channel_manager(), channel);
    voe::Channel* channelPtr = sc.ChannelPtr();
    if (channelPtr == NULL)
    {
        _shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
            "GetPeriodicDeadOrAliveStatus() failed to locate channel");
        return -1;
    }
    return channelPtr->GetPeriodicDeadOrAliveStatus(enabled,
                                                    sampleTimeSeconds);
}

} // namespace webrtc
<|endoftext|>


<commit_before>/* ****************************************************************************** *\

Copyright (C) 2012-2017 Intel Corporation.  All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- 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.
- Neither the name of Intel Corporation nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "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 INTEL CORPORATION 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.

File Name: mfx_win_reg_key.cpp

\* ****************************************************************************** */

#if defined(_WIN32) || defined(_WIN64)  || defined(__CYGWIN__)

#include "mfx_win_reg_key.h"
#include "mfx_dispatcher_log.h"

#define TRACE_WINREG_ERROR(str, ...) DISPATCHER_LOG_ERROR((("[WINREG]: " str), __VA_ARGS__))

namespace MFX
{

WinRegKey::WinRegKey(void)
{
    m_hKey = (HKEY) 0;

} // WinRegKey::WinRegKey(void)

WinRegKey::~WinRegKey(void)
{
    Release();

} // WinRegKey::~WinRegKey(void)

void WinRegKey::Release(void)
{
    // close the opened key
    if (m_hKey)
    {
        RegCloseKey(m_hKey);
    }

    m_hKey = (HKEY) 0;

} // void WinRegKey::Release(void)

bool WinRegKey::Open(HKEY hRootKey, const wchar_t *pSubKey, REGSAM samDesired)
{
    LONG lRes;
    HKEY hTemp;

    //
    // All operation are performed in this order by intention.
    // It makes possible to reopen the keys, using itself as a base.
    //

    // try to the open registry key
    lRes = RegOpenKeyExW(hRootKey, pSubKey, 0, samDesired, &hTemp);
    if (ERROR_SUCCESS != lRes)
    {
        DISPATCHER_LOG_OPERATION(SetLastError(lRes));
        TRACE_WINREG_ERROR("Opening key \"%s\\%S\" : RegOpenKeyExW()==0x%x\n"
            , (HKEY_LOCAL_MACHINE == hRootKey) ? ("HKEY_LOCAL_MACHINE")
            : (HKEY_CURRENT_USER == hRootKey)  ? ("HKEY_CURRENT_USER")
            : "UNSUPPORTED_KEY", pSubKey, GetLastError());
        return false;
    }

    // release the object before initialization
    Release();

    // save the handle
    m_hKey = hTemp;

    return true;

} // bool WinRegKey::Open(HKEY hRootKey, const wchar_t *pSubKey, REGSAM samDesired)

bool WinRegKey::Open(WinRegKey &rootKey, const wchar_t *pSubKey, REGSAM samDesired)
{
    return Open(rootKey.m_hKey, pSubKey, samDesired);

} // bool WinRegKey::Open(WinRegKey &rootKey, const wchar_t *pSubKey, REGSAM samDesired)

bool WinRegKey::QueryValueSize(const wchar_t *pValueName, DWORD type, LPDWORD pcbData) {
    DWORD keyType = type;
    LONG lRes;

    // query the value
    lRes = RegQueryValueExW(m_hKey, pValueName, NULL, &keyType, 0, pcbData);
    if (ERROR_SUCCESS != lRes)
    {
        DISPATCHER_LOG_OPERATION(SetLastError(lRes));
        TRACE_WINREG_ERROR("Querying \"%S\" : RegQueryValueExA()==0x%x\n", pValueName, GetLastError());
        return false;
    }

    return true;
}

bool WinRegKey::Query(const wchar_t *pValueName, DWORD type, LPBYTE pData, LPDWORD pcbData)
{
    DWORD keyType = type;
    LONG lRes;
    DWORD dstSize = (pcbData) ? (*pcbData) : (0);

    // query the value
    lRes = RegQueryValueExW(m_hKey, pValueName, NULL, &keyType, pData, pcbData);
    if (ERROR_SUCCESS != lRes)
    {
        DISPATCHER_LOG_OPERATION(SetLastError(lRes));
        TRACE_WINREG_ERROR("Querying \"%S\" : RegQueryValueExA()==0x%x\n", pValueName, GetLastError());
        return false;
    }

    // check the type
    if (keyType != type)
    {
        TRACE_WINREG_ERROR("Querying \"%S\" : expectedType=%d, returned=%d\n", pValueName, type, keyType);
        return false;
    }

    // terminate the string only if pointers not NULL
    if ((REG_SZ == type || REG_EXPAND_SZ == type) && NULL != pData && NULL != pcbData)
    {
        wchar_t *pString = (wchar_t *) pData;
        size_t NullEndingSizeBytes = sizeof(wchar_t); // size of string termination null character
        if (dstSize < NullEndingSizeBytes)
        {
            TRACE_WINREG_ERROR("Querying \"%S\" : buffer is too small for null-terminated string", pValueName);
            return false;
        }
        size_t maxStringLengthBytes = dstSize - NullEndingSizeBytes;
        size_t maxStringIndex = dstSize / sizeof(wchar_t) - 1;

        size_t lastIndex = (maxStringLengthBytes < *pcbData) ? (maxStringIndex) : (*pcbData) / sizeof(wchar_t);

        pString[lastIndex] = (wchar_t) 0;
    }
    else if(REG_MULTI_SZ == type && NULL != pData && NULL != pcbData)
    {
        wchar_t *pString = (wchar_t *) pData;
        size_t NullEndingSizeBytes = sizeof(wchar_t)*2; // size of string termination null characters
        if (dstSize < NullEndingSizeBytes)
        {
            TRACE_WINREG_ERROR("Querying \"%S\" : buffer is too small for multi-line null-terminated string", pValueName);
            return false;
        }
        size_t maxStringLengthBytes = dstSize - NullEndingSizeBytes;
        size_t maxStringIndex = dstSize / sizeof(wchar_t) - 1;

        size_t lastIndex = (maxStringLengthBytes < *pcbData) ? (maxStringIndex) : (*pcbData) / sizeof(wchar_t) + 1;

        // last 2 bytes should be 0 in case of REG_MULTI_SZ
        pString[lastIndex] = pString[lastIndex - 1] = (wchar_t) 0;
    }

    return true;

} // bool WinRegKey::Query(const wchar_t *pValueName, DWORD type, LPBYTE pData, LPDWORD pcbData)

bool WinRegKey::EnumValue(DWORD index, wchar_t *pValueName, LPDWORD pcchValueName, LPDWORD pType)
{
    LONG lRes;

    // enum the values
    lRes = RegEnumValueW(m_hKey, index, pValueName, pcchValueName, 0, pType, NULL, NULL);
    if (ERROR_SUCCESS != lRes)
    {
        DISPATCHER_LOG_OPERATION(SetLastError(lRes));
        return false;
    }

    return true;

} // bool WinRegKey::EnumValue(DWORD index, wchar_t *pValueName, LPDWORD pcchValueName, LPDWORD pType)

bool WinRegKey::EnumKey(DWORD index, wchar_t *pValueName, LPDWORD pcchValueName)
{
    LONG lRes;

    // enum the keys
    lRes = RegEnumKeyExW(m_hKey, index, pValueName, pcchValueName, NULL, NULL, NULL, NULL);
    if (ERROR_SUCCESS != lRes)
    {
        DISPATCHER_LOG_OPERATION(SetLastError(lRes));
        TRACE_WINREG_ERROR("EnumKey with index=%d: RegEnumKeyExW()==0x%x\n", index, GetLastError());
        return false;
    }

    return true;

} // bool WinRegKey::EnumKey(DWORD index, wchar_t *pValueName, LPDWORD pcchValueName)

bool WinRegKey::QueryInfo(LPDWORD lpcSubkeys)
{
    LONG lRes;

    lRes = RegQueryInfoKeyW(m_hKey, NULL, 0, 0, lpcSubkeys, 0, 0, 0, 0, 0, 0, 0);
    if (ERROR_SUCCESS != lRes) {
        TRACE_WINREG_ERROR("RegQueryInfoKeyW()==0x%x\n", lRes);
        return false;
    }
    return true;

} //bool QueryInfo(LPDWORD lpcSubkeys);

} // namespace MFX

#endif // #if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
<commit_msg>do not call registry APIs if MEDIASDK_USE_REGISTRY is not set<commit_after>/* ****************************************************************************** *\

Copyright (C) 2012-2017 Intel Corporation.  All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- 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.
- Neither the name of Intel Corporation nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "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 INTEL CORPORATION 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.

File Name: mfx_win_reg_key.cpp

\* ****************************************************************************** */

#if defined(_WIN32) || defined(_WIN64)  || defined(__CYGWIN__)

#include "mfx_win_reg_key.h"
#include "mfx_dispatcher_log.h"

#define TRACE_WINREG_ERROR(str, ...) DISPATCHER_LOG_ERROR((("[WINREG]: " str), __VA_ARGS__))

namespace MFX
{

WinRegKey::WinRegKey(void)
{
    m_hKey = (HKEY) 0;

} // WinRegKey::WinRegKey(void)

WinRegKey::~WinRegKey(void)
{
    Release();

} // WinRegKey::~WinRegKey(void)

void WinRegKey::Release(void)
{
    // close the opened key
    if (m_hKey)
    {
#if defined(MEDIASDK_USE_REGISTRY) || (!defined(MEDIASDK_UWP_LOADER) && !defined(MEDIASDK_UWP_PROCTABLE))
        RegCloseKey(m_hKey);
#endif
    }

    m_hKey = (HKEY) 0;

} // void WinRegKey::Release(void)

bool WinRegKey::Open(HKEY hRootKey, const wchar_t *pSubKey, REGSAM samDesired)
{
#if defined(MEDIASDK_USE_REGISTRY) || (!defined(MEDIASDK_UWP_LOADER) && !defined(MEDIASDK_UWP_PROCTABLE))
    LONG lRes;
    HKEY hTemp;

    //
    // All operation are performed in this order by intention.
    // It makes possible to reopen the keys, using itself as a base.
    //

    // try to the open registry key
    lRes = RegOpenKeyExW(hRootKey, pSubKey, 0, samDesired, &hTemp);
    if (ERROR_SUCCESS != lRes)
    {
        DISPATCHER_LOG_OPERATION(SetLastError(lRes));
        TRACE_WINREG_ERROR("Opening key \"%s\\%S\" : RegOpenKeyExW()==0x%x\n"
            , (HKEY_LOCAL_MACHINE == hRootKey) ? ("HKEY_LOCAL_MACHINE")
            : (HKEY_CURRENT_USER == hRootKey)  ? ("HKEY_CURRENT_USER")
            : "UNSUPPORTED_KEY", pSubKey, GetLastError());
        return false;
    }

    // release the object before initialization
    Release();

    // save the handle
    m_hKey = hTemp;

    return true;
#else
    return false;
#endif

} // bool WinRegKey::Open(HKEY hRootKey, const wchar_t *pSubKey, REGSAM samDesired)

bool WinRegKey::Open(WinRegKey &rootKey, const wchar_t *pSubKey, REGSAM samDesired)
{
    return Open(rootKey.m_hKey, pSubKey, samDesired);

} // bool WinRegKey::Open(WinRegKey &rootKey, const wchar_t *pSubKey, REGSAM samDesired)

bool WinRegKey::QueryValueSize(const wchar_t *pValueName, DWORD type, LPDWORD pcbData) {
#if defined(MEDIASDK_USE_REGISTRY) || (!defined(MEDIASDK_UWP_LOADER) && !defined(MEDIASDK_UWP_PROCTABLE))
    DWORD keyType = type;
    LONG lRes;

    // query the value
    lRes = RegQueryValueExW(m_hKey, pValueName, NULL, &keyType, 0, pcbData);
    if (ERROR_SUCCESS != lRes)
    {
        DISPATCHER_LOG_OPERATION(SetLastError(lRes));
        TRACE_WINREG_ERROR("Querying \"%S\" : RegQueryValueExA()==0x%x\n", pValueName, GetLastError());
        return false;
    }

    return true;
#else
    return false;
#endif
}

bool WinRegKey::Query(const wchar_t *pValueName, DWORD type, LPBYTE pData, LPDWORD pcbData)
{
#if defined(MEDIASDK_USE_REGISTRY) || (!defined(MEDIASDK_UWP_LOADER) && !defined(MEDIASDK_UWP_PROCTABLE))
    DWORD keyType = type;
    LONG lRes;
    DWORD dstSize = (pcbData) ? (*pcbData) : (0);

    // query the value
    lRes = RegQueryValueExW(m_hKey, pValueName, NULL, &keyType, pData, pcbData);
    if (ERROR_SUCCESS != lRes)
    {
        DISPATCHER_LOG_OPERATION(SetLastError(lRes));
        TRACE_WINREG_ERROR("Querying \"%S\" : RegQueryValueExA()==0x%x\n", pValueName, GetLastError());
        return false;
    }

    // check the type
    if (keyType != type)
    {
        TRACE_WINREG_ERROR("Querying \"%S\" : expectedType=%d, returned=%d\n", pValueName, type, keyType);
        return false;
    }

    // terminate the string only if pointers not NULL
    if ((REG_SZ == type || REG_EXPAND_SZ == type) && NULL != pData && NULL != pcbData)
    {
        wchar_t *pString = (wchar_t *) pData;
        size_t NullEndingSizeBytes = sizeof(wchar_t); // size of string termination null character
        if (dstSize < NullEndingSizeBytes)
        {
            TRACE_WINREG_ERROR("Querying \"%S\" : buffer is too small for null-terminated string", pValueName);
            return false;
        }
        size_t maxStringLengthBytes = dstSize - NullEndingSizeBytes;
        size_t maxStringIndex = dstSize / sizeof(wchar_t) - 1;

        size_t lastIndex = (maxStringLengthBytes < *pcbData) ? (maxStringIndex) : (*pcbData) / sizeof(wchar_t);

        pString[lastIndex] = (wchar_t) 0;
    }
    else if(REG_MULTI_SZ == type && NULL != pData && NULL != pcbData)
    {
        wchar_t *pString = (wchar_t *) pData;
        size_t NullEndingSizeBytes = sizeof(wchar_t)*2; // size of string termination null characters
        if (dstSize < NullEndingSizeBytes)
        {
            TRACE_WINREG_ERROR("Querying \"%S\" : buffer is too small for multi-line null-terminated string", pValueName);
            return false;
        }
        size_t maxStringLengthBytes = dstSize - NullEndingSizeBytes;
        size_t maxStringIndex = dstSize / sizeof(wchar_t) - 1;

        size_t lastIndex = (maxStringLengthBytes < *pcbData) ? (maxStringIndex) : (*pcbData) / sizeof(wchar_t) + 1;

        // last 2 bytes should be 0 in case of REG_MULTI_SZ
        pString[lastIndex] = pString[lastIndex - 1] = (wchar_t) 0;
    }

    return true;
#else
    return false;
#endif

} // bool WinRegKey::Query(const wchar_t *pValueName, DWORD type, LPBYTE pData, LPDWORD pcbData)

bool WinRegKey::EnumValue(DWORD index, wchar_t *pValueName, LPDWORD pcchValueName, LPDWORD pType)
{
#if defined(MEDIASDK_USE_REGISTRY) || (!defined(MEDIASDK_UWP_LOADER) && !defined(MEDIASDK_UWP_PROCTABLE))
    LONG lRes;

    // enum the values
    lRes = RegEnumValueW(m_hKey, index, pValueName, pcchValueName, 0, pType, NULL, NULL);
    if (ERROR_SUCCESS != lRes)
    {
        DISPATCHER_LOG_OPERATION(SetLastError(lRes));
        return false;
    }

    return true;
#else
    return false;
#endif

} // bool WinRegKey::EnumValue(DWORD index, wchar_t *pValueName, LPDWORD pcchValueName, LPDWORD pType)

bool WinRegKey::EnumKey(DWORD index, wchar_t *pValueName, LPDWORD pcchValueName)
{
#if defined(MEDIASDK_USE_REGISTRY) || (!defined(MEDIASDK_UWP_LOADER) && !defined(MEDIASDK_UWP_PROCTABLE))
    LONG lRes;

    // enum the keys
    lRes = RegEnumKeyExW(m_hKey, index, pValueName, pcchValueName, NULL, NULL, NULL, NULL);
    if (ERROR_SUCCESS != lRes)
    {
        DISPATCHER_LOG_OPERATION(SetLastError(lRes));
        TRACE_WINREG_ERROR("EnumKey with index=%d: RegEnumKeyExW()==0x%x\n", index, GetLastError());
        return false;
    }

    return true;
#else
    return false;
#endif

} // bool WinRegKey::EnumKey(DWORD index, wchar_t *pValueName, LPDWORD pcchValueName)

bool WinRegKey::QueryInfo(LPDWORD lpcSubkeys)
{
#if defined(MEDIASDK_USE_REGISTRY) || (!defined(MEDIASDK_UWP_LOADER) && !defined(MEDIASDK_UWP_PROCTABLE))
    LONG lRes;

    lRes = RegQueryInfoKeyW(m_hKey, NULL, 0, 0, lpcSubkeys, 0, 0, 0, 0, 0, 0, 0);
    if (ERROR_SUCCESS != lRes) {
        TRACE_WINREG_ERROR("RegQueryInfoKeyW()==0x%x\n", lRes);
        return false;
    }
    return true;
#else
    return false;
#endif

} //bool QueryInfo(LPDWORD lpcSubkeys);

} // namespace MFX

#endif // #if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
<|endoftext|>


<commit_before>// Copyright (c) 2020 by Robert Bosch GmbH. All rights reserved.
// Copyright (c) 2020 - 2021 by Apex.AI 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.
//
// SPDX-License-Identifier: Apache-2.0

#ifndef IOX_POSH_GW_GATEWAY_GENERIC_INL
#define IOX_POSH_GW_GATEWAY_GENERIC_INL

#include "iceoryx_dust/cxx/file_reader.hpp"
#include "iceoryx_posh/gateway/gateway_generic.hpp"
#include "iceoryx_posh/internal/log/posh_logging.hpp"

// ================================================== Public ================================================== //

namespace iox
{
namespace gw
{
template <typename channel_t, typename gateway_t>
inline GatewayGeneric<channel_t, gateway_t>::~GatewayGeneric() noexcept
{
    shutdown();
}

template <typename channel_t, typename gateway_t>
inline void GatewayGeneric<channel_t, gateway_t>::runMultithreaded() noexcept
{
    m_isRunning.store(true, std::memory_order_relaxed);
    m_discoveryThread = std::thread([this] { this->discoveryLoop(); });
    m_forwardingThread = std::thread([this] { this->forwardingLoop(); });
}

template <typename channel_t, typename gateway_t>
inline void GatewayGeneric<channel_t, gateway_t>::shutdown() noexcept
{
    if (m_isRunning.load(std::memory_order_relaxed))
    {
        m_isRunning.store(false, std::memory_order_relaxed);

        m_discoveryThread.join();
        m_forwardingThread.join();
    }
}

template <typename channel_t, typename gateway_t>
inline uint64_t GatewayGeneric<channel_t, gateway_t>::getNumberOfChannels() const noexcept
{
    return m_channels->size();
}

// ================================================== Protected ================================================== //

template <typename channel_t, typename gateway_t>
inline GatewayGeneric<channel_t, gateway_t>::GatewayGeneric(capro::Interfaces interface,
                                                            units::Duration discoveryPeriod,
                                                            units::Duration forwardingPeriod) noexcept
    : gateway_t(interface)
    , m_discoveryPeriod(discoveryPeriod)
    , m_forwardingPeriod(forwardingPeriod)
{
}

template <typename channel_t, typename gateway_t>
template <typename IceoryxPubSubOptions>
inline cxx::expected<channel_t, GatewayError>
GatewayGeneric<channel_t, gateway_t>::addChannel(const capro::ServiceDescription& service,
                                                 const IceoryxPubSubOptions& options) noexcept
{
    // Filter out wildcard services
    if (service.getServiceIDString() == capro::IdString_t(cxx::TruncateToCapacity, "*")
        || service.getInstanceIDString() == capro::IdString_t(cxx::TruncateToCapacity, "*")
        || service.getEventIDString() == capro::IdString_t(cxx::TruncateToCapacity, "*"))
    {
        return cxx::error<GatewayError>(GatewayError::UNSUPPORTED_SERVICE_TYPE);
    }

    // Return existing channel if one for the service already exists, otherwise create a new one
    auto existingChannel = findChannel(service);
    if (existingChannel.has_value())
    {
        return cxx::success<channel_t>(existingChannel.value());
    }
    else
    {
        auto result = channel_t::create({service.getServiceIDString(),
                                         service.getInstanceIDString(),
                                         service.getEventIDString(),
                                         {0U, 0U, 0U, 0U},
                                         this->getInterface()},
                                        options);
        if (result.has_error())
        {
            return cxx::error<GatewayError>(GatewayError::UNSUCCESSFUL_CHANNEL_CREATION);
        }
        else
        {
            auto channel = result.value();
            m_channels->push_back(channel);
            return cxx::success<channel_t>(channel);
        }
    }
}

template <typename channel_t, typename gateway_t>
inline cxx::optional<channel_t>
GatewayGeneric<channel_t, gateway_t>::findChannel(const iox::capro::ServiceDescription& service) const noexcept
{
    auto guardedVector = this->m_channels.getScopeGuard();
    auto channel = std::find_if(guardedVector->begin(), guardedVector->end(), [&service](const channel_t& channel) {
        return channel.getServiceDescription() == service;
    });
    if (channel == guardedVector->end())
    {
        return cxx::nullopt_t();
    }
    else
    {
        return cxx::make_optional<channel_t>(*channel);
    }
}

template <typename channel_t, typename gateway_t>
inline void
GatewayGeneric<channel_t, gateway_t>::forEachChannel(const cxx::function_ref<void(channel_t&)> f) const noexcept
{
    auto guardedVector = m_channels.getScopeGuard();
    for (auto channel = guardedVector->begin(); channel != guardedVector->end(); ++channel)
    {
        f(*channel);
    }
}

template <typename channel_t, typename gateway_t>
inline cxx::expected<GatewayError>
GatewayGeneric<channel_t, gateway_t>::discardChannel(const capro::ServiceDescription& service) noexcept
{
    auto guardedVector = this->m_channels.getScopeGuard();
    auto channel = std::find_if(guardedVector->begin(), guardedVector->end(), [&service](const channel_t& channel) {
        return channel.getServiceDescription() == service;
    });
    if (channel != guardedVector->end())
    {
        guardedVector->erase(channel);
        return cxx::success<void>();
    }
    else
    {
        return cxx::error<GatewayError>(GatewayError::NONEXISTANT_CHANNEL);
    }
}

// ================================================== Private ================================================== //

template <typename channel_t, typename gateway_t>
inline void GatewayGeneric<channel_t, gateway_t>::discoveryLoop() noexcept
{
    while (m_isRunning.load(std::memory_order_relaxed))
    {
        auto startTime = std::chrono::steady_clock::now();
        capro::CaproMessage msg;
        while (this->getCaProMessage(msg))
        {
            discover(msg);
        }
        std::this_thread::sleep_until(startTime + std::chrono::milliseconds(m_discoveryPeriod.toMilliseconds()));
    }
}

template <typename channel_t, typename gateway_t>
inline void GatewayGeneric<channel_t, gateway_t>::forwardingLoop() noexcept
{
    while (m_isRunning.load(std::memory_order_relaxed))
    {
        auto startTime = std::chrono::steady_clock::now();
        forEachChannel([this](channel_t channel) { this->forward(channel); });
        std::this_thread::sleep_until(startTime + std::chrono::milliseconds(m_forwardingPeriod.toMilliseconds()));
    };
}

} // namespace gw
} // namespace iox

#endif // IOX_POSH_GW_GATEWAY_GENERIC_INL
<commit_msg>iox-#1666 Fix GatewayGeneric::shutdown & add copyright<commit_after>// Copyright (c) 2020 by Robert Bosch GmbH. All rights reserved.
// Copyright (c) 2020 - 2021 by Apex.AI Inc. All rights reserved.
// Copyright (c) 2022 by NXP. 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.
//
// SPDX-License-Identifier: Apache-2.0

#ifndef IOX_POSH_GW_GATEWAY_GENERIC_INL
#define IOX_POSH_GW_GATEWAY_GENERIC_INL

#include "iceoryx_dust/cxx/file_reader.hpp"
#include "iceoryx_posh/gateway/gateway_generic.hpp"
#include "iceoryx_posh/internal/log/posh_logging.hpp"

// ================================================== Public ================================================== //

namespace iox
{
namespace gw
{
template <typename channel_t, typename gateway_t>
inline GatewayGeneric<channel_t, gateway_t>::~GatewayGeneric() noexcept
{
    shutdown();
}

template <typename channel_t, typename gateway_t>
inline void GatewayGeneric<channel_t, gateway_t>::runMultithreaded() noexcept
{
    m_isRunning.store(true);
    m_discoveryThread = std::thread([this] { this->discoveryLoop(); });
    m_forwardingThread = std::thread([this] { this->forwardingLoop(); });
}

template <typename channel_t, typename gateway_t>
inline void GatewayGeneric<channel_t, gateway_t>::shutdown() noexcept
{
    m_isRunning.store(false);
    if (m_discoveryThread.joinable())
    {
        m_discoveryThread.join();
    }
    if (m_forwardingThread.joinable())
    {
        m_forwardingThread.join();
    }
}

template <typename channel_t, typename gateway_t>
inline uint64_t GatewayGeneric<channel_t, gateway_t>::getNumberOfChannels() const noexcept
{
    return m_channels->size();
}

// ================================================== Protected ================================================== //

template <typename channel_t, typename gateway_t>
inline GatewayGeneric<channel_t, gateway_t>::GatewayGeneric(capro::Interfaces interface,
                                                            units::Duration discoveryPeriod,
                                                            units::Duration forwardingPeriod) noexcept
    : gateway_t(interface)
    , m_discoveryPeriod(discoveryPeriod)
    , m_forwardingPeriod(forwardingPeriod)
{
}

template <typename channel_t, typename gateway_t>
template <typename IceoryxPubSubOptions>
inline cxx::expected<channel_t, GatewayError>
GatewayGeneric<channel_t, gateway_t>::addChannel(const capro::ServiceDescription& service,
                                                 const IceoryxPubSubOptions& options) noexcept
{
    // Filter out wildcard services
    if (service.getServiceIDString() == capro::IdString_t(cxx::TruncateToCapacity, "*")
        || service.getInstanceIDString() == capro::IdString_t(cxx::TruncateToCapacity, "*")
        || service.getEventIDString() == capro::IdString_t(cxx::TruncateToCapacity, "*"))
    {
        return cxx::error<GatewayError>(GatewayError::UNSUPPORTED_SERVICE_TYPE);
    }

    // Return existing channel if one for the service already exists, otherwise create a new one
    auto existingChannel = findChannel(service);
    if (existingChannel.has_value())
    {
        return cxx::success<channel_t>(existingChannel.value());
    }
    else
    {
        auto result = channel_t::create({service.getServiceIDString(),
                                         service.getInstanceIDString(),
                                         service.getEventIDString(),
                                         {0U, 0U, 0U, 0U},
                                         this->getInterface()},
                                        options);
        if (result.has_error())
        {
            return cxx::error<GatewayError>(GatewayError::UNSUCCESSFUL_CHANNEL_CREATION);
        }
        else
        {
            auto channel = result.value();
            m_channels->push_back(channel);
            return cxx::success<channel_t>(channel);
        }
    }
}

template <typename channel_t, typename gateway_t>
inline cxx::optional<channel_t>
GatewayGeneric<channel_t, gateway_t>::findChannel(const iox::capro::ServiceDescription& service) const noexcept
{
    auto guardedVector = this->m_channels.getScopeGuard();
    auto channel = std::find_if(guardedVector->begin(), guardedVector->end(), [&service](const channel_t& channel) {
        return channel.getServiceDescription() == service;
    });
    if (channel == guardedVector->end())
    {
        return cxx::nullopt_t();
    }
    else
    {
        return cxx::make_optional<channel_t>(*channel);
    }
}

template <typename channel_t, typename gateway_t>
inline void
GatewayGeneric<channel_t, gateway_t>::forEachChannel(const cxx::function_ref<void(channel_t&)> f) const noexcept
{
    auto guardedVector = m_channels.getScopeGuard();
    for (auto channel = guardedVector->begin(); channel != guardedVector->end(); ++channel)
    {
        f(*channel);
    }
}

template <typename channel_t, typename gateway_t>
inline cxx::expected<GatewayError>
GatewayGeneric<channel_t, gateway_t>::discardChannel(const capro::ServiceDescription& service) noexcept
{
    auto guardedVector = this->m_channels.getScopeGuard();
    auto channel = std::find_if(guardedVector->begin(), guardedVector->end(), [&service](const channel_t& channel) {
        return channel.getServiceDescription() == service;
    });
    if (channel != guardedVector->end())
    {
        guardedVector->erase(channel);
        return cxx::success<void>();
    }
    else
    {
        return cxx::error<GatewayError>(GatewayError::NONEXISTANT_CHANNEL);
    }
}

// ================================================== Private ================================================== //

template <typename channel_t, typename gateway_t>
inline void GatewayGeneric<channel_t, gateway_t>::discoveryLoop() noexcept
{
    while (m_isRunning.load(std::memory_order_relaxed))
    {
        auto startTime = std::chrono::steady_clock::now();
        capro::CaproMessage msg;
        while (this->getCaProMessage(msg))
        {
            discover(msg);
        }
        std::this_thread::sleep_until(startTime + std::chrono::milliseconds(m_discoveryPeriod.toMilliseconds()));
    }
}

template <typename channel_t, typename gateway_t>
inline void GatewayGeneric<channel_t, gateway_t>::forwardingLoop() noexcept
{
    while (m_isRunning.load(std::memory_order_relaxed))
    {
        auto startTime = std::chrono::steady_clock::now();
        forEachChannel([this](channel_t channel) { this->forward(channel); });
        std::this_thread::sleep_until(startTime + std::chrono::milliseconds(m_forwardingPeriod.toMilliseconds()));
    };
}

} // namespace gw
} // namespace iox

#endif // IOX_POSH_GW_GATEWAY_GENERIC_INL
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>

int regul(std::vector<int> v) {
  while (v.vector::back() == 0) {
    v.vector::pop_back();
  }
  return 0;
}

class zzbar{

  public:
    zzbar(int d, int n) {
      if (d > 1 && n <d) {
        deg = d;
        num = n;
      }
    }
    // set deg and num
    void set_dg(int d, int n) {
      deg = d;
      num = n;
    }
    // Function finding \alpha
    int alpha() {
      int alp, halfnum;
      halfnum = (1 + num) / 2;
      alp = deg - halfnum;
      return alp;
    }
    // Function finding \beta
    int beta() {
      int bet;
      bet = (1 + num) / 2;
      return bet;
    }
    // Function finding prefix
    int prefix() {
      int prefix;
      if (deg%2==0 && num==deg-1) {
                     prefix = 3;    // without prefix
      }
      else {
        if(num%2==1) prefix = 1;    // prefix = Re
        if(num%2==0) prefix = 2;    // prefix = Im
      }
      return prefix;
    }
    // Operator < comparing two monoms zzbar
    bool operator<(zzbar ob2) {
      bool answ;
      if (deg < ob2.deg) {
        answ = true;
      }
      else if (deg == ob2.deg && num > ob2.num) {
        answ = true;
      }
      else answ = false;

      return answ;
    }
    // Operator == comparing two monoms zzbar
    bool operator==(zzbar ob2) {
      bool answ;
      if (deg == ob2.deg && num == ob2.num) {
        answ = true;
      }
      else answ = false;

      return answ;
    }
    // Function printing monom zzbar
    void print_zzbar() {
      int alp, bet, pr;
      pr  = prefix();
      alp = alpha();
      bet = beta();
      if (pr == 1) {
        std::cout << "\\mathrm{Re}\\left(";
      }
      else if (pr == 2) {
        std::cout << "\\mathrm{Im}\\left(";
      }
      if (alp == 1) {
        std::cout << "z";
      }
      else {
        std::cout << "z^{" << alp << "}";
      }
      if (bet == 1) {
        std::cout << "\\bar{z}";
      }
      else {
        std::cout << "\\bar{z}^{" << bet << "}";
      }
      if(pr < 3) {
        std::cout << "\\right)";
      }
    }
  private:
    int deg;  // degree of monom z^{\alpha}\bar{z}^{\beta}
    int num;  // numer of monom among all monoms degree deg
};

class monom : public zzbar{
  public:
    monom(int d, int n, std::vector<int> vec):zzbar(d, n) {
      degu = vec;
    }
/*    // Operator < comparing two monoms zzbar
    bool operator<(monom ob2) {
      bool answ;
      if (deg < ob2.deg) {
        answ = true;
      }
      else if (deg == ob2.deg && num > ob2.num) {
        answ = true;
      }
      else answ = false;

      return answ;
    }
    // Operator == comparing two monoms zzbar
    bool operator==(zzbar ob2) {
      bool answ;
      if (deg == ob2.deg && num == ob2.num) {

        if () {

        }
        else answ = false;
      }
      else answ = false;

      return answ;
    }   */
    // Function printing monom
    void print_monom() {
      int i, n = degu.vector::size();
      print_zzbar();
      for (i=0; i<n; ++i) {
        if (degu[i] > 1) {
          std::cout << "u_{" << i+1 << "}^{" << degu[i] << "}";
        }
        else if (degu[i] == 1) {
          std::cout << "u_{" << i+1 << "}";
        }
      }
      std::cout << "\n";
    }
  private:
    std::vector<int> degu;
};

int main()
{

  std::vector<int> vect;
  vect.vector::push_back(1);
  vect.vector::push_back(7);
  vect.vector::push_back(4);
  vect.vector::push_back(0);
  vect.vector::push_back(12);
  vect.vector::push_back(0);
  vect.vector::push_back(0);
  vect.vector::push_back(0);
  vect.vector::push_back(0);
  vect.vector::push_back(0);

  monom mon(8,5,vect);
  mon.print_monom();

  int i, j;

//  for (i=2; i<7; ++i) {
//    for (j=1; j<i; ++j) {
//      mon.set_dg(i, j);
//      mon.print_monom();
//    }
//  }

  return 0;
}
<commit_msg>Final version of program<commit_after>#include <iostream>
#include <vector>
#include <cmath>
#include <ctime>

//////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////// zzbar /////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////

class zzbar {
  public:
    zzbar();
    zzbar(int d, int n);
    zzbar(const zzbar& copy);
    void set_dg(int d, int n);
    int  alpha();
    int  beta();
    int  prefix();
    int  get_deg();
    int  get_num();
    void print_zzbar();
    bool operator<(zzbar ob2);
    bool operator==(zzbar ob2);
  protected:
    int deg;  // degree of monom z^{\alpha}\bar{z}^{\beta}
    int num;  // numer of monom among all monoms degree deg
};

zzbar::zzbar() {
  deg = 2;
  num = 1;
}

zzbar::zzbar(int d, int n) {
  if (d > 1 && n < d) {
    deg = d;
    num = n;
  }
}

zzbar::zzbar(const zzbar& copy) {
  deg = copy.deg;
  num = copy.num;
}

// set deg and num
void zzbar::set_dg(int d, int n) {
  deg = d;
  num = n;
}

// Function finding \alpha
int zzbar::alpha() {
  int halfnum = (1 + num) / 2;
  int alp = deg - halfnum;
  return alp;
}

// Function finding \beta
int zzbar::beta() {
  int bet = (1 + num) / 2;
  return bet;
}

// Function finding prefix
int zzbar::prefix() {
  int prefix;
  if (deg%2 == 0 && num == deg-1)
          prefix = 3;    // without prefix
  else {
    if(num%2 == 1)
          prefix = 1;    // prefix = Re
    if(num%2 == 0)
          prefix = 2;    // prefix = Im
  }
  return  prefix;
}

int zzbar::get_deg() {
  return deg;
}

int zzbar::get_num() {
  return num;
}

// Operator < comparing two monoms zzbar
bool zzbar::operator<(zzbar ob2) {
  bool answ = true;
  if (deg < ob2.deg)
    answ = true;
  else if (deg == ob2.deg && num > ob2.num)
    answ = true;
  else
    answ = false;

  return answ;
}

// Operator == comparing two monoms zzbar
bool zzbar::operator==(zzbar ob2) {
  bool answ = true;
  if (deg == ob2.deg && num == ob2.num) {
    answ = true;
  }
  else answ = false;

  return answ;
}

// Function printing monom zzbar
void zzbar::print_zzbar() {
  int pr  = prefix();
  int alp = alpha();
  int bet = beta();

  if (pr == 1)
    std::cout << "2\\mathrm{Re}\\left(";
  else if (pr == 2)
    std::cout << "2\\mathrm{Im}\\left(";

  if (alp == 1)
    std::cout << "z";
  else
    std::cout << "z^{" << alp << "}";

  if (bet == 1)
    std::cout << "\\bar{z}";
  else
    std::cout << "\\bar{z}^{" << bet << "}";

  if(pr < 3)
    std::cout << "\\right)";
}

//////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////// monom /////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////

class monom : public zzbar {
  public:
    monom();
    monom(int d, int n, const std::vector<int> &vec);
    monom(int d, int n, const std::vector<int> &vec, const std::vector<int> &deg_wei);
    monom(const monom& copy);
    void set(int d, int n, const std::vector<int> &vec);
    void print_monom();
    void set_index(int ind);
    void set_weight(int wei);
    void regul();
    bool operator<(const monom &ob2) const;
    bool operator==(const monom &ob2) const;
    int  get_index();
    int  get_weight();
    int  get_deguwei(const int i);
    void get_deguwei(std::vector<int> &vec);
    void get_degu(std::vector<int> &vec);
    int  get_degusize();

  private:
    int index;
    int weight;
    std::vector<int> degu;      // degu = <g_1, ..., g_s>, where monom = zzbar * u_1^{g_1} * ... * u_s^{g_s}
    std::vector<int> degu_wei;  // degu_wei = <w_0, w_1, ..., w_s>, where w_i = weight of cutting monom = zzbar * u_1^{g_1} * ... * u_s^{g_i}

    static bool less_vector(const std::vector<int> &v1, const std::vector<int> &v2);
};

monom::monom() {
  deg    = 2;
  num    = 1;
  index  = 1;
  weight = 2;
  degu_wei.push_back(2);
}

monom::monom(int d, int n, const std::vector<int> &vec)
    : zzbar(d, n) {
  degu = vec;
  while (!degu.empty() && degu.back() == 0) {
    degu.pop_back();
  }
  index  = 1;
  weight = 2;
}

monom::monom(int d, int n, const std::vector<int> &vec, const std::vector<int> &deg_wei)
    : zzbar(d, n) {
  degu = vec;
  while (!degu.empty() && degu.back() == 0) {
    degu.pop_back();
  }
  degu_wei = deg_wei;
  index    = 1;
  weight   = 2;
}

monom::monom(const monom& copy) {
  deg      = copy.deg;
  num      = copy.num;
  index    = copy.index;
  weight   = copy.weight;
  degu     = copy.degu;
  degu_wei = copy.degu_wei;
}

void monom::set(int d, int n, const std::vector<int> &vec) {
  degu = vec;
  while (!degu.empty() && degu.back() == 0) {
    degu.pop_back();
  }
  index  = 1;
  weight = 2;
  deg = d;
  num = n;
}

void monom::set_index(int ind) {
  index = ind;
}

void monom::set_weight(int wei) {
  weight = wei;
}

bool monom::less_vector(const std::vector<int> &v1, const std::vector<int> &v2) {
  bool answ = true;
  int i = 0;
  int flag = 0;
  int n = std::min(v1.size(), v2.size());

  while (flag == 0 && i<n) {
    if (v1[i] < v2[i]) flag = 1;
    ++i;
  }

  if (flag == 1) answ = true;
  else           answ = false;

  return answ;
}

void monom::regul() {
  while (!degu.empty() && degu.back() == 0) {
    degu.pop_back();
  }
  int n = degu.size();
  int m = degu_wei.size();
  if(m > n+1) {
    int k = m-n-1;
    for(int i = 0; i < k; ++i) {
      degu_wei.pop_back();
    }
  }
}

// Operator < comparing two monoms
bool monom::operator<(const monom &ob2) const {
  bool answ = true;

  if (deg < ob2.deg)
    answ = true;
  else if (deg == ob2.deg && num > ob2.num)
    answ = true;
  else if (deg == ob2.deg && num == ob2.num && less_vector(degu, ob2.degu))
    answ = true;
  else
    answ = false;

  return answ;
}

// Operator == comparing two monoms
bool monom::operator==(const monom &ob2) const {
  bool answ = true;
  std::vector<int> vec_l = degu;
  std::vector<int> vec_r = ob2.degu;

  while (!vec_l.empty() && vec_l.back() == 0) {
    vec_l.pop_back();
  }
  while (!vec_r.empty() && vec_r.back() == 0) {
    vec_r.pop_back();
  }

  if (deg == ob2.deg && num == ob2.num && vec_r == vec_l)
    answ = true;
  else
    answ = false;

  return answ;
}

// Function printing monom
void monom::print_monom() {
  int n = degu.size();

  std::cout << "$$v_{" << index << "} = ";
  print_zzbar();
  for (int i = 0; i < n; ++i) {
    if (degu[i] > 1)
      std::cout << "u_{" << i+1 << "}^{" << degu[i] << "}";
    else if (degu[i] == 1)
      std::cout << "u_{" << i+1 << "}";
  }
  std::cout << "$$";
  std::cout << "\n";
}

int monom::get_index() {
  return index;
}

int monom::get_weight() {
  return weight;
}

int monom::get_deguwei(int i) {
  if( i < degu_wei.size() && i >= 0) {
    return degu_wei[i];
  }
  else {
    std::cout << "error. monom::get_deguwei. i >= degu_wei.size()";
    return 0;
  }
}

void monom::get_deguwei(std::vector<int> &vec) {
  vec = degu_wei;
}

void monom::get_degu(std::vector<int> &vec) {
  vec = degu;
}

int monom::get_degusize() {
  return degu.size();
}

//////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////// H_n ////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////

class H_n {
  public:
    H_n();
    H_n(int n, const std::vector<int> &dim);
    int get_size();
    void print_space();
    void print_space(int i);
    monom get_space(int i);
    std::vector<monom> get_space();

  private:
    int period_num;                  // number of period \in {2, 3, ...}
    std::vector<monom> space;        // all monoms of weight period_num
    std::vector<int>   dimensions;   // dimensions of spaces CH_2, ... CH_{n-1}

    static int smartloop_inc (const std::vector<int> &weight, std::vector<int> &vec, int summa);
    void spacecreator(int n, const std::vector<int> &dim);
};

H_n::H_n() {
  std::vector<int> dim;
  spacecreator(2, dim);
}

H_n::H_n(int n, const std::vector<int> &dim) {
  spacecreator(n, dim);
}

int H_n::get_size() {
  return space.size();
}

void H_n::print_space() {
  for (int i = 0; i < space.size(); ++i) {
    space[i].print_monom();
  }
}

monom H_n::get_space(int i) {
  if (space.size() > i)
    return space[i];
}

std::vector<monom> H_n::get_space() {
  return space;
}

void H_n::print_space(int i) {
  if (i < space.size())
    space[i].print_monom();
}

void H_n::spacecreator(int n, const std::vector<int> &dim) {
  if( n-2 != dim.size() )
    std::cout << "error. n-2 != dim.size()";

  int i    = 0;
  int flag = 0;
  int iwei = 0;
  int lim  = (n-4) / 2;

  period_num = n;
  dimensions = dim;

  int sumdim = 0;
  for(i=0; i<=lim; ++i) {
    sumdim += dimensions[i];
  }

  std::vector<int> weights;
  for(i = 0; i < sumdim; ++i) {
    flag = 0;
    iwei = 0;
    while (i+1 > flag) {
      flag += dimensions[iwei];
      ++iwei;
    }
    weights.push_back(iwei+1);
  }
//======== creation of vector space ========
  std::vector<int> loopv(sumdim, 0);
  for(int ideg = period_num; ideg > 1; --ideg) {
    int diff = period_num - ideg;
    for(int inum = 1; inum < ideg; ++inum) {
      loopv.assign(sumdim, 0);
      int fl = 0;
      if (diff > 0) {
        fl = smartloop_inc(weights, loopv, diff);
      }
      while (fl == 0) {
        int sum = ideg;
        std::vector<int> deg_wei;
        deg_wei.push_back(sum);
        for (int ive = 0; ive < sumdim; ++ive) {
          sum += (loopv[ive] * weights[ive]);
          deg_wei.push_back(sum);
        }
        monom temp(ideg, inum, loopv, deg_wei);
        temp.set_weight(n);
        temp.regul();
        space.push_back(temp);
        fl = smartloop_inc(weights, loopv, diff);
      }
    }
  }
//==========================================
}

int H_n::smartloop_inc (const std::vector<int> &weight, std::vector<int> &vec, int summa) {
  if (weight.size() != vec.size())
    std::cout << "error. weight.size != vec.size";

  int end = 0;
  int n   = weight.size();

  if(n > 0) {
    int fl  = 0;
    vec[0] += 1;

    while ( fl == 0 ) {
      int sum = 0;
      for(int i = 0; i < n; ++i) {
        sum += weight[i] * vec[i];
      }

      if(sum < summa)
        vec[0] += 1;
      else if (sum == summa)
        fl = 1;
      else {
        int fl2  = 0;
        int ivec = 0;
        while (fl2 == 0 && ivec < n) {
          vec[ivec]==0 ? ++ivec : fl2=1;
        }
        if( ivec == n || ivec == n-1 ) {
          fl  = 1;
          end = 1;
        }
        else {
          vec[ivec] = 0;
          vec[1+ivec] += 1;
        }
      }

    }
  }

  if(n == 0)
    end = 1;

  return end;
}

//////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////// CH_n /////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////

class CH_n {
  public:
    CH_n();
    CH_n(int n);
    void print_megaspace();
    void print_info();

  private:
    std::vector< std::vector<monom> > megaspace;
    std::vector<int> dim;

    int  monom_index(const monom &mon);
    bool monom_check(const monom &mon);
};

CH_n::CH_n() {
  H_n H;
  megaspace.push_back( H.get_space() );
}

CH_n::CH_n(int n) {
  if(n < 2 )
    std::cout << "error. n < 2";

  int ind = 0;

  for(int i = 2; i < n+1; ++i) {
    H_n H(i, dim);
    dim.push_back(0);
    std::vector<monom> sp;
    for (int j = 0; j < H.get_size(); ++j) {
      if(  monom_check( H.get_space(j) )  )  {
        ind++;
        dim[i-2] += 1;
        sp.push_back( H.get_space(j) );
        sp.back().set_index(ind);
      }
    }
    megaspace.push_back( sp );
  }
}

void CH_n::print_megaspace() {
  for(int i = 0; i < megaspace.size(); ++i) {
    std::cout << "$$========== period \\ " << i+2 << " ==========$$ \n";
    for(int j = 0; j < megaspace[i].size(); ++j) {
      megaspace[i][j].print_monom();
    }
  }
}

void CH_n::print_info() {
  std::cout << "\n";
  for(int i = 0; i < megaspace.size(); ++i) {
    std::cout << "$$\\dim(CH_{" << i+2 << "}) = " << megaspace[i].size() << "$$ \n";
  }
  std::cout << "\n";
  for(int i = 0; i < megaspace.size(); ++i) {
    int max  = 0;
    int jmax = 0;
    for(int j = 0; j < megaspace[i].size(); j++) {
      if( megaspace[i][j].get_degusize() > max ) {
        max  = megaspace[i][j].get_degusize();
        jmax = j;
      }
    }
    std::cout << "$$\\dim(U, \\ CH_{" << i+2 << "}) = " << max << ", \\ \\ \\text{for example}:$$ \n";
    megaspace[i][jmax].print_monom();
  }
  std::cout << "\n";
}

int CH_n::monom_index(const monom &mon) {
  int ind  = 0;

  monom mono(mon);
  std::vector<int> deg_u;
  mono.get_degu(deg_u);

  int wei  = mono.get_deguwei( deg_u.size() ) - 2;

  int fl = 0;
  int i  = 0;

  while( fl == 0 && i < megaspace[wei].size() ) {
    if(megaspace[wei][i] == mon) {
      ind = megaspace[wei][i].get_index();
      fl = 1;
    }
    ++i;
  }

  return  ind;
}

bool CH_n::monom_check(const monom &mon) {
  int answ = true;
  int fl   = 0;
  monom mono(mon);
  std::vector<int> degu_w;
  mono.get_deguwei(degu_w);
  std::vector<int> deg_u;
  mono.get_degu(deg_u);

  if( 2*mono.get_deg() <= mono.get_weight() ) {
    int i = 0;
    int detailed_check = 0;
    std::vector<int> vec;
    while (fl == 0 && i < deg_u.size() ) {
      monom temp_mon(mono.get_deg(), mono.get_num(), vec, degu_w);
      vec.push_back(deg_u[i]);
      if(deg_u[i] > 0 && monom_index(temp_mon) <= i+1) {
        fl = 1;
      }
      ++i;
    }
  }

  if(fl == 0)
    answ = true;
  else
    answ = false;

  return answ;
}

//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////

int main()
{

  time_t sec1 = time(NULL);

  CH_n ch6(8);

  time_t sec2 = time(NULL);
  time_t dsec = sec2 - sec1;

  ch6.print_info();
  ch6.print_megaspace();

  std::cout << "Elapsed time: " << dsec << " sec" << std::endl;

  return 0;
}
<|endoftext|>


<commit_before>#pragma once

#include "../std/vector.hpp"

template <class T>
class SimpleTree
{
  typedef std::vector<SimpleTree<T> > internal_container_type;

  T m_value;
  internal_container_type m_siblings;

public:
  SimpleTree(T const & value = T()) : m_value(value)
  {
  }

  /// @return reference is valid only up to the next tree structure modification
  T const & Value() const
  {
    return m_value;
  }

  /// @return reference is valid only up to the next tree structure modification
  T & Value()
  {
    return m_value;
  }

  /// @return reference is valid only up to the next tree structure modification
  T & AddAtDepth(int level, T const & value)
  {
    SimpleTree<T> * node = this;
    while (level-- > 0 && !node->m_siblings.empty())
      node = &node->m_siblings.back();
    return node->Add(value);
  }

  /// @return reference is valid only up to the next tree structure modification
  T & Add(T const & value)
  {
    m_siblings.push_back(SimpleTree(value));
    return m_siblings.back().Value();
  }

  /// Deletes all children and makes tree empty
  void Clear()
  {
    m_siblings.clear();
  }

  bool operator<(SimpleTree<T> const & other) const
  {
    return Value() < other.Value();
  }

  /// sorts siblings independently on each level by default
  void Sort(bool onlySiblings = false)
  {
    std::sort(m_siblings.begin(), m_siblings.end());
    if (!onlySiblings)
      for (typename internal_container_type::iterator it = m_siblings.begin(); it != m_siblings.end(); ++it)
        it->Sort(false);
  }

  SimpleTree<T> const & operator[](size_t index) const
  {
    return m_siblings.at(index);
  }

  size_t SiblingsCount() const
  {
    return m_siblings.size();
  }

  template <class TFunctor>
  void ForEachSibling(TFunctor & f)
  {
    for (typename internal_container_type::iterator it = m_siblings.begin(); it != m_siblings.end(); ++it)
      f(*it);
  }

  template <class TFunctor>
  void ForEachSibling(TFunctor & f) const
  {
    for (typename internal_container_type::const_iterator it = m_siblings.begin(); it != m_siblings.end(); ++it)
      f(*it);
  }

  template <class TFunctor>
  void ForEachChildren(TFunctor & f)
  {
    for (typename internal_container_type::iterator it = m_siblings.begin(); it != m_siblings.end(); ++it)
    {
      it->ForEachChildren(f);
      f(*it);
    }
  }

  template <class TFunctor>
  void ForEachChildren(TFunctor & f) const
  {
    for (typename internal_container_type::const_iterator it = m_siblings.begin(); it != m_siblings.end(); ++it)
    {
      it->ForEachChildren(f);
      f(*it);
    }
  }
};
<commit_msg>Fixed missed include<commit_after>#pragma once

#include "../std/vector.hpp"
#include "../std/algorithm.hpp"

template <class T>
class SimpleTree
{
  typedef std::vector<SimpleTree<T> > internal_container_type;

  T m_value;
  internal_container_type m_siblings;

public:
  SimpleTree(T const & value = T()) : m_value(value)
  {
  }

  /// @return reference is valid only up to the next tree structure modification
  T const & Value() const
  {
    return m_value;
  }

  /// @return reference is valid only up to the next tree structure modification
  T & Value()
  {
    return m_value;
  }

  /// @return reference is valid only up to the next tree structure modification
  T & AddAtDepth(int level, T const & value)
  {
    SimpleTree<T> * node = this;
    while (level-- > 0 && !node->m_siblings.empty())
      node = &node->m_siblings.back();
    return node->Add(value);
  }

  /// @return reference is valid only up to the next tree structure modification
  T & Add(T const & value)
  {
    m_siblings.push_back(SimpleTree(value));
    return m_siblings.back().Value();
  }

  /// Deletes all children and makes tree empty
  void Clear()
  {
    m_siblings.clear();
  }

  bool operator<(SimpleTree<T> const & other) const
  {
    return Value() < other.Value();
  }

  /// sorts siblings independently on each level by default
  void Sort(bool onlySiblings = false)
  {
    std::sort(m_siblings.begin(), m_siblings.end());
    if (!onlySiblings)
      for (typename internal_container_type::iterator it = m_siblings.begin(); it != m_siblings.end(); ++it)
        it->Sort(false);
  }

  SimpleTree<T> const & operator[](size_t index) const
  {
    return m_siblings.at(index);
  }

  size_t SiblingsCount() const
  {
    return m_siblings.size();
  }

  template <class TFunctor>
  void ForEachSibling(TFunctor & f)
  {
    for (typename internal_container_type::iterator it = m_siblings.begin(); it != m_siblings.end(); ++it)
      f(*it);
  }

  template <class TFunctor>
  void ForEachSibling(TFunctor & f) const
  {
    for (typename internal_container_type::const_iterator it = m_siblings.begin(); it != m_siblings.end(); ++it)
      f(*it);
  }

  template <class TFunctor>
  void ForEachChildren(TFunctor & f)
  {
    for (typename internal_container_type::iterator it = m_siblings.begin(); it != m_siblings.end(); ++it)
    {
      it->ForEachChildren(f);
      f(*it);
    }
  }

  template <class TFunctor>
  void ForEachChildren(TFunctor & f) const
  {
    for (typename internal_container_type::const_iterator it = m_siblings.begin(); it != m_siblings.end(); ++it)
    {
      it->ForEachChildren(f);
      f(*it);
    }
  }
};
<|endoftext|>


<commit_before>
#include <s2sinputstream.h>
#include <s2soutputstream.h>
#include <virtualhost.h>
#include <nanosoft/asyncdns.h>
#include <iostream>

using namespace std;

/**
* Конструктор потока
*/
S2SInputStream::S2SInputStream(XMPPServer *srv, int sock): XMPPStream(srv, sock)
{
}

/**
* Деструктор потока
*/
S2SInputStream::~S2SInputStream()
{
}

/**
* Событие: начало потока
*/
void S2SInputStream::onStartStream(const std::string &name, const attributes_t &attributes)
{
	fprintf(stderr, "#%d new s2s stream\n", getWorkerId());
	initXML();
	startElement("stream:stream");
	setAttribute("xmlns:stream", "http://etherx.jabber.org/streams");
	setAttribute("xmlns", "jabber:server");
	setAttribute("xmlns:db", "jabber:server:dialback");
	setAttribute("id", id = "123456"); // Требования к id — непредсказуемость и уникальность
	setAttribute("xml:lang", "en");
	flush();
}

/**
* Событие: конец потока
*/
void S2SInputStream::onEndStream()
{
	fprintf(stderr, "#%d: [S2SInputStream: %d] end of stream\n", getWorkerId(), fd);
	terminate();
}

/**
* Обработчик станзы
*/
void S2SInputStream::onStanza(Stanza stanza)
{
	fprintf(stderr, "#%d s2s-input stanza: %s\n", getWorkerId(), stanza->name().c_str());
	if ( stanza->name() == "verify" ) onDBVerifyStanza(stanza);
	else if ( stanza->name() == "result" ) onDBResultStanza(stanza);
	else if ( state != authorized )
	{
		fprintf(stderr, "#%d unexpected s2s-input stanza: %s\n", getWorkerId(), stanza->name().c_str());
		Stanza error = Stanza::streamError("not-authoized");
		sendStanza(error);
		delete error;
		terminate();
	}
	else if ( stanza.from().hostname() != remote_host )
	{
		fprintf(stderr, "#%d [s2s-input: %s] invalid from: %s\n", getWorkerId(), remote_host.c_str(), stanza->getAttribute("from").c_str());
		Stanza error = Stanza::streamError("improper-addressing");
		sendStanza(error);
		delete error;
		terminate();
	}
	else
	{
		// доставить станзу по назначению
		XMPPDomain *vhost = server->getHostByName(stanza.to().hostname());
		if ( ! vhost )
		{
			fprintf(stderr, "#%d [s2s-input: %s] invalid to: %s\n", getWorkerId(), remote_host.c_str(), stanza->getAttribute("to").c_str());
			Stanza error = Stanza::streamError("improper-addressing");
			sendStanza(error);
			delete error;
			terminate();
		}
		vhost->routeStanza(stanza);
	}
}

/**
* Обработка <db:verify>
*/
void S2SInputStream::onDBVerifyStanza(Stanza stanza)
{
	Stanza verify = new ATXmlTag("db:verify");
	verify->setAttribute("from", stanza->getAttribute("to"));
	verify->setAttribute("to", stanza->getAttribute("from"));
	verify->setAttribute("type", "valid");
	verify->setAttribute("id", stanza->getAttribute("id"));
	sendStanza(verify);
	delete verify;
}

/**
* Резолвер s2s хоста, запись A (IPv4)
*/
static void on_s2s_a4(struct dns_ctx *ctx, struct dns_rr_a4 *result, void *data)
{
  printf("on_s2s_a4\n");
  if ( result )
  for(int i = 0; i < result->dnsa4_nrr; i++)
  {
    char buf[40];
    printf("  addr: %s\n", dns_ntop(AF_INET, &result->dnsa4_addr[i], buf, sizeof(buf)));
  }
  printf("\n");
}

/**
* Резолвер s2s хоста, запись SRV (_jabber._tcp)
*/
static void on_s2s_srv_jabber(struct dns_ctx *ctx, struct dns_rr_srv *result, void *data)
{
  printf("on_s2s_srv_jabber\n");
  if ( result )
  for(int i = 0; i < result->dnssrv_nrr; i++)
  {
    char buf[40];
    printf("  SRV priority: %d, weight: %d, port: %d, name: %s\n",
      result->dnssrv_srv[i].priority,
      result->dnssrv_srv[i].weight,
      result->dnssrv_srv[i].port,
      result->dnssrv_srv[i].name);
  }
  printf("\n");
}

/**
* Резолвер s2s хоста, запись SRV (_xmpp-server._tcp)
*/
static void on_srv_xmpp_server(struct dns_ctx *ctx, struct dns_rr_srv *result, void *data)
{
  printf("on_srv_xmpp_server\n");
  if ( result )
  for(int i = 0; i < result->dnssrv_nrr; i++)
  {
    char buf[40];
    printf("  SRV priority: %d, weight: %d, port: %d, name: %s\n",
      result->dnssrv_srv[i].priority,
      result->dnssrv_srv[i].weight,
      result->dnssrv_srv[i].port,
      result->dnssrv_srv[i].name);
  }
  printf("\n");
}

/**
* Резолвер s2s хоста, запись RBL
*/
static void on_s2s_rbl(struct dns_ctx *ctx, struct dns_rr_a4 *result, void *data)
{
  printf("on_s2s_rbl\n");
  if ( result ) {
  for(int i = 0; i < result->dnsa4_nrr; i++)
  {
    char buf[40];
    printf("  addr: %s\n", dns_ntop(AF_INET, &result->dnsa4_addr[i], buf, sizeof(buf)));
  }
  }
  printf("\n");
}

/**
* Обработка <db:result>
*/
void S2SInputStream::onDBResultStanza(Stanza stanza)
{
	string to = stanza->getAttribute("to");
	string from = stanza->getAttribute("from");
	cerr << "[s2s-input] db:result to: " << to << ", from: " << from << endl;

	// Шаг 1. проверка: "to" должен быть нашим виртуальным хостом
	XMPPDomain *host = server->getHostByName(to);
	if ( ! host || dynamic_cast<S2SOutputStream*>(host) )
	{
		Stanza stanza = Stanza::streamError("host-unknown");
		sendStanza(stanza);
		delete stanza;
		terminate();
		return;
	}

	// Шаг 2. проверка "from"
	//
	// RFC 3920 не запрещает делать повторные коннекты (8.3.4).
	//
	// До завершения авторизации нужно поддерживать старое соединение,
	// пока не авторизуется новое. Но можно блокировать повторные
	// коннекты с ошибкой <not-authorized />, что мы и делаем.
	//
	// NOTE: В любом случае, логично блокировать попытки представиться
	// нашим хостом - мы сами к себе никогда не коннектимся.
	// Так что, если будете открывать повторные коннекты, то забудьте
	// блокировать попытки коннекта к самим себе.
	if ( server->getHostByName(from) )
	{
		Stanza stanza = Stanza::streamError("not-authorized");
		sendStanza(stanza);
		delete stanza;
		terminate();
		return;
	}
	remote_host = from;

	// Шаг 3. резолвим DNS записи сервера
	// NOTE для оптимизации отправляем все DNS (асинхронные) запросы сразу
	server->adns->a4(from.c_str(), on_s2s_a4, this);
	server->adns->srv(from.c_str(), "jabber", "tcp", on_s2s_srv_jabber, this);
	server->adns->srv(from.c_str(), "xmpp-server", "tcp", on_srv_xmpp_server, this);
	// TODO извлекать список DNSBL из конфига
	server->adns->a4((from + ".dnsbl.jabber.ru").c_str(), on_s2s_rbl, this);

	// Шаг X. костыль - ответить сразу "authorized"
	state = authorized;
	Stanza result = new ATXmlTag("db:result");
	result->setAttribute("to", from);
	result->setAttribute("from", to);
	result->setAttribute("type", "valid");
	sendStanza(result);
	delete result;
}

/**
* Сигнал завершения работы
*
* Сервер решил закрыть соединение, здесь ещё есть время
* корректно попрощаться с пиром (peer).
*/
void S2SInputStream::onTerminate()
{
	fprintf(stderr, "#%d: [S2SInputStream: %d] onTerminate\n", getWorkerId(), fd);

	// if ( state == authorized ) server->onOffline(this);

	mutex.lock();
		endElement("stream:stream");
		flush();
		shutdown(WRITE);
	mutex.unlock();
}
<commit_msg>ID on s2s<commit_after>
#include <s2sinputstream.h>
#include <s2soutputstream.h>
#include <virtualhost.h>
#include <functions.h>
#include <nanosoft/asyncdns.h>
#include <iostream>

using namespace std;

/**
* Конструктор потока
*/
S2SInputStream::S2SInputStream(XMPPServer *srv, int sock): XMPPStream(srv, sock)
{
}

/**
* Деструктор потока
*/
S2SInputStream::~S2SInputStream()
{
}

/**
* Событие: начало потока
*/
void S2SInputStream::onStartStream(const std::string &name, const attributes_t &attributes)
{
	fprintf(stderr, "#%d new s2s stream\n", getWorkerId());
	initXML();
	startElement("stream:stream");
	setAttribute("xmlns:stream", "http://etherx.jabber.org/streams");
	setAttribute("xmlns", "jabber:server");
	setAttribute("xmlns:db", "jabber:server:dialback");
	setAttribute("id", id = getUniqueId());
	setAttribute("xml:lang", "en");
	flush();
}

/**
* Событие: конец потока
*/
void S2SInputStream::onEndStream()
{
	fprintf(stderr, "#%d: [S2SInputStream: %d] end of stream\n", getWorkerId(), fd);
	terminate();
}

/**
* Обработчик станзы
*/
void S2SInputStream::onStanza(Stanza stanza)
{
	fprintf(stderr, "#%d s2s-input stanza: %s\n", getWorkerId(), stanza->name().c_str());
	if ( stanza->name() == "verify" ) onDBVerifyStanza(stanza);
	else if ( stanza->name() == "result" ) onDBResultStanza(stanza);
	else if ( state != authorized )
	{
		fprintf(stderr, "#%d unexpected s2s-input stanza: %s\n", getWorkerId(), stanza->name().c_str());
		Stanza error = Stanza::streamError("not-authoized");
		sendStanza(error);
		delete error;
		terminate();
	}
	else if ( stanza.from().hostname() != remote_host )
	{
		fprintf(stderr, "#%d [s2s-input: %s] invalid from: %s\n", getWorkerId(), remote_host.c_str(), stanza->getAttribute("from").c_str());
		Stanza error = Stanza::streamError("improper-addressing");
		sendStanza(error);
		delete error;
		terminate();
	}
	else
	{
		// доставить станзу по назначению
		XMPPDomain *vhost = server->getHostByName(stanza.to().hostname());
		if ( ! vhost )
		{
			fprintf(stderr, "#%d [s2s-input: %s] invalid to: %s\n", getWorkerId(), remote_host.c_str(), stanza->getAttribute("to").c_str());
			Stanza error = Stanza::streamError("improper-addressing");
			sendStanza(error);
			delete error;
			terminate();
		}
		vhost->routeStanza(stanza);
	}
}

/**
* Обработка <db:verify>
*/
void S2SInputStream::onDBVerifyStanza(Stanza stanza)
{
	Stanza verify = new ATXmlTag("db:verify");
	verify->setAttribute("from", stanza->getAttribute("to"));
	verify->setAttribute("to", stanza->getAttribute("from"));
	verify->setAttribute("type", "valid");
	verify->setAttribute("id", stanza->getAttribute("id"));
	sendStanza(verify);
	delete verify;
}

/**
* Резолвер s2s хоста, запись A (IPv4)
*/
static void on_s2s_a4(struct dns_ctx *ctx, struct dns_rr_a4 *result, void *data)
{
  printf("on_s2s_a4\n");
  if ( result )
  for(int i = 0; i < result->dnsa4_nrr; i++)
  {
    char buf[40];
    printf("  addr: %s\n", dns_ntop(AF_INET, &result->dnsa4_addr[i], buf, sizeof(buf)));
  }
  printf("\n");
}

/**
* Резолвер s2s хоста, запись SRV (_jabber._tcp)
*/
static void on_s2s_srv_jabber(struct dns_ctx *ctx, struct dns_rr_srv *result, void *data)
{
  printf("on_s2s_srv_jabber\n");
  if ( result )
  for(int i = 0; i < result->dnssrv_nrr; i++)
  {
    char buf[40];
    printf("  SRV priority: %d, weight: %d, port: %d, name: %s\n",
      result->dnssrv_srv[i].priority,
      result->dnssrv_srv[i].weight,
      result->dnssrv_srv[i].port,
      result->dnssrv_srv[i].name);
  }
  printf("\n");
}

/**
* Резолвер s2s хоста, запись SRV (_xmpp-server._tcp)
*/
static void on_srv_xmpp_server(struct dns_ctx *ctx, struct dns_rr_srv *result, void *data)
{
  printf("on_srv_xmpp_server\n");
  if ( result )
  for(int i = 0; i < result->dnssrv_nrr; i++)
  {
    char buf[40];
    printf("  SRV priority: %d, weight: %d, port: %d, name: %s\n",
      result->dnssrv_srv[i].priority,
      result->dnssrv_srv[i].weight,
      result->dnssrv_srv[i].port,
      result->dnssrv_srv[i].name);
  }
  printf("\n");
}

/**
* Резолвер s2s хоста, запись RBL
*/
static void on_s2s_rbl(struct dns_ctx *ctx, struct dns_rr_a4 *result, void *data)
{
  printf("on_s2s_rbl\n");
  if ( result ) {
  for(int i = 0; i < result->dnsa4_nrr; i++)
  {
    char buf[40];
    printf("  addr: %s\n", dns_ntop(AF_INET, &result->dnsa4_addr[i], buf, sizeof(buf)));
  }
  }
  printf("\n");
}

/**
* Обработка <db:result>
*/
void S2SInputStream::onDBResultStanza(Stanza stanza)
{
	string to = stanza->getAttribute("to");
	string from = stanza->getAttribute("from");
	cerr << "[s2s-input] db:result to: " << to << ", from: " << from << endl;

	// Шаг 1. проверка: "to" должен быть нашим виртуальным хостом
	XMPPDomain *host = server->getHostByName(to);
	if ( ! host || dynamic_cast<S2SOutputStream*>(host) )
	{
		Stanza stanza = Stanza::streamError("host-unknown");
		sendStanza(stanza);
		delete stanza;
		terminate();
		return;
	}

	// Шаг 2. проверка "from"
	//
	// RFC 3920 не запрещает делать повторные коннекты (8.3.4).
	//
	// До завершения авторизации нужно поддерживать старое соединение,
	// пока не авторизуется новое. Но можно блокировать повторные
	// коннекты с ошибкой <not-authorized />, что мы и делаем.
	//
	// NOTE: В любом случае, логично блокировать попытки представиться
	// нашим хостом - мы сами к себе никогда не коннектимся.
	// Так что, если будете открывать повторные коннекты, то забудьте
	// блокировать попытки коннекта к самим себе.
	if ( server->getHostByName(from) )
	{
		Stanza stanza = Stanza::streamError("not-authorized");
		sendStanza(stanza);
		delete stanza;
		terminate();
		return;
	}
	remote_host = from;

	// Шаг 3. резолвим DNS записи сервера
	// NOTE для оптимизации отправляем все DNS (асинхронные) запросы сразу
	server->adns->a4(from.c_str(), on_s2s_a4, this);
	server->adns->srv(from.c_str(), "jabber", "tcp", on_s2s_srv_jabber, this);
	server->adns->srv(from.c_str(), "xmpp-server", "tcp", on_srv_xmpp_server, this);
	// TODO извлекать список DNSBL из конфига
	server->adns->a4((from + ".dnsbl.jabber.ru").c_str(), on_s2s_rbl, this);

	// Шаг X. костыль - ответить сразу "authorized"
	state = authorized;
	Stanza result = new ATXmlTag("db:result");
	result->setAttribute("to", from);
	result->setAttribute("from", to);
	result->setAttribute("type", "valid");
	sendStanza(result);
	delete result;
}

/**
* Сигнал завершения работы
*
* Сервер решил закрыть соединение, здесь ещё есть время
* корректно попрощаться с пиром (peer).
*/
void S2SInputStream::onTerminate()
{
	fprintf(stderr, "#%d: [S2SInputStream: %d] onTerminate\n", getWorkerId(), fd);

	// if ( state == authorized ) server->onOffline(this);

	mutex.lock();
		endElement("stream:stream");
		flush();
		shutdown(WRITE);
	mutex.unlock();
}
<|endoftext|>