Merge branch 'master' into maxgolov/cs4_support

This commit is contained in:
Max Golovanov 2020-05-06 15:31:27 -07:00 коммит произвёл GitHub
Родитель c1a92a4b5b 64b66f6657
Коммит d6b377852b
63 изменённых файлов: 1018 добавлений и 368 удалений

2
.github/CODEOWNERS поставляемый
Просмотреть файл

@ -2,4 +2,4 @@
# This file controls who is tagged for review for any given pull request.
# For anything not explicitly taken by someone else:
* @kindbe @maxgolov @mkoscumb @reyang
* @kindbe @maxgolov @mkoscumb @reyang @bliptec @larvacea

10
.gitmodules поставляемый
Просмотреть файл

@ -1,7 +1,13 @@
[submodule "vcpkg"]
path = vcpkg
[submodule "tools/vcpkg"]
path = tools/vcpkg
url = https://github.com/Microsoft/vcpkg
[submodule "lib/modules"]
path = lib/modules
url = https://github.com/Microsoft/cpp_client_telemetry_modules.git
branch = master
[submodule "third_party/krabsetw"]
path = third_party/krabsetw
url = https://github.com/microsoft/krabsetw
branch = master

Просмотреть файл

@ -35,31 +35,26 @@ Issues and feature requests are tracked on [GitHub](https://github.com/microsoft
### How to Send Pull Requests
Everyone is welcome to contribute code to `1DS C++ SDK` via GitHub
pull requests (PRs).
Everyone is welcome to contribute code to `1DS C++ SDK` via GitHub pull requests (PRs).
To create a new PR, fork the project in GitHub and clone the upstream repo:
Please do not fork. Our CI is setup to accept PRs only from the main *microsoft/cpp_client_telemetry* repo.
To create a new PR, clone the upstream repo:
```sh
$ git clone --recurse-submodules https://github.com/microsoft/cpp_client_telemetry.git
```
Add your fork as an origin:
Check out a new branch, make modifications and push the branch on the main repository:
```sh
$ git remote add fork https://github.com/YOUR_GITHUB_USERNAME/cpp_client_telemetry.git
```
Check out a new branch, make modifications and push the branch to your fork:
```sh
$ git checkout -b feature_branch_name
$ git checkout -b ${USERNAME}/feature_branch_name
# edit files
$ git commit
$ git push fork feature_branch_name
$ git commit -m "Description"
$ git push ${USERNAME}/feature_branch_name
```
Open a pull request against the main `cpp_client_telemetry` repo.
Then open a PR against the main `microsoft/cpp_client_telemetry` repo.
### How to Receive Comments
@ -75,15 +70,16 @@ Open a pull request against the main `cpp_client_telemetry` repo.
### How to Get PR Merged
A PR is considered to be **ready to merge** when:
* It has received one approval from Maintainers.
* It has received at least one approval from Maintainers.
* Major feedbacks are resolved.
* It has been open for review for at least one working day. This gives people
reasonable time to review.
* It has been open for review for at least one working day. This gives people reasonable time to review.
* Trivial change (typo, cosmetic, doc, etc.) doesn't have to wait for one day.
* Urgent fix can take exception as long as it has been actively communicated.
* Any dependent submodule changes have updated the submodule commit id (`git add lib/modules`)
* Any Collaborator/Maintainer can merge the PR once it is **ready to merge**.
* In exceptional scenarios (build break, privacy issue, GitHub actions failure, CI failure), when other Approvers are unavailable - Administrators may exercise their right to Merge notifying the other Approvers in a comment to PR.
Any Collaborator/Maintainer can merge the PR once it is **ready to merge**.
Do not push directly to the *master*.
## Style Guidelines
@ -93,14 +89,15 @@ _Please note that we are rapidly evolving product with many different contributo
Some modules have been written following platform-specific coding style.
Please try to keep your changes consistent with the coding style of a module you are modifying._
There is a *.clang-format* file included in the repo. Please use your favourite IDE with Clang Format tooling installed.
## Become a Collaborator
Collaborators have write access to the repo.
To become a Collaborator:
* Become an active Contributor by working on PRs.
* Actively participate in the community meeting, design discussion, PR review
and issue discussion.
* Actively participate in the community meeting, design discussion, PR review and issue discussion.
* Contact the Maintainers, express the willingness and commitment.
* Acknowledged and approved by two Maintainers.

Просмотреть файл

@ -2,6 +2,15 @@
cd %~dp0
if "%~1"=="" goto help
WHERE choco >NUL 2>NUL
IF %ERRORLEVEL% NEQ 0 call tools\setup-choco.cmd
WHERE docker >NUL 2>NUL
IF "%ERRORLEVEL%"=="0" goto docker_ok
choco install -y docker-desktop
choco install -y docker-cli
:docker_ok
del .buildtools 2>NUL
docker info
docker version

Просмотреть файл

@ -1,17 +1,40 @@
#!/usr/bin/env bash
if [ "$1" == "ios" ]; then
IOS_BUILD="YES"
# Skip building tests on iOS as there is no way to run them
BUILD_TESTS="OFF"
else
IOS_BUILD="NO"
BUILD_TESTS="ON"
fi
cd `dirname $0`
# Use latest Google Test
if [ -f /etc/os-release ]; then
source /etc/os-release
# Use new Google Test on latest Ubuntu 20.04 : old one no longer compiles on 20
if [ "$VERSION_ID" == "20.04" ]; then
echo Running on Ubuntu 20.04
echo Clone googletest from google/googletest:master ...
rm -rf googletest
git clone https://github.com/google/googletest
fi
fi
cd googletest
set -evx
env | sort
rm -rf build
mkdir -p build || true
cd build
cmake -Dgtest_build_samples=ON \
-Dgmock_build_samples=ON \
-Dgtest_build_tests=ON \
-Dgmock_build_tests=ON \
cmake -Dgtest_build_samples=OFF \
-Dgmock_build_samples=OFF \
-Dgtest_build_tests=$BUILD_TESTS \
-Dgmock_build_tests=$BUILD_TESTS \
-DCMAKE_CXX_FLAGS="-fPIC $CXX_FLAGS" \
-DBUILD_IOS=$IOS_BUILD \
..
make
CTEST_OUTPUT_ON_FAILURE=1 make test
#make install
# CTEST_OUTPUT_ON_FAILURE=1 make test
# make install

Просмотреть файл

@ -1,16 +1,23 @@
#!/bin/sh
if [ "$1" == "release" ]; then
if [ "$1" == "clean" ]; then
rm -f CMakeCache.txt *.cmake
rm -rf out
rm -rf .buildtools
# make clean
fi
if [ "$1" == "release" ] || [ "$2" == "release" ]; then
BUILD_TYPE="Release"
else
BUILD_TYPE="Debug"
fi
if [ "$2" == "arm64" ]; then
if [ "$2" == "arm64" ] || [ "$3" == "arm64" ]; then
IOS_ARCH="arm64"
elif [ "$2" == "arm64e" ]; then
elif [ "$2" == "arm64e" ] || [ "$3" == "arm64e" ]; then
IOS_ARCH="arm64e"
elif [ "$2" == "x86_64" ] || "$2" == "simulator" ]; then
elif [ "$2" == "x86_64" ] || [ "$2" == "simulator" ] || [ "$3" == "x86_64" ] || [ "$3" == "simulator" ]; then
IOS_ARCH="x86_64"
else
IOS_ARCH="x86_64"
@ -23,7 +30,7 @@ IOS_DEPLOYMENT_TARGET=10.0
FILE=.buildtools
OS_NAME=`uname -a`
if [ ! -f $FILE ]; then
tools/setup-buildtools-mac.sh
tools/setup-buildtools-apple.sh ios
# Assume that the build tools have been successfully installed
echo > $FILE
fi

Просмотреть файл

@ -43,7 +43,7 @@ FILE=.buildtools
OS_NAME=`uname -a`
if [ ! -f $FILE ]; then
case "$OS_NAME" in
*Darwin*) tools/setup-buildtools-mac.sh ;;
*Darwin*) tools/setup-buildtools-apple.sh ;;
*Linux*) [[ -z "$NOROOT" ]] && sudo tools/setup-buildtools.sh || echo "No root: skipping build tools installation." ;;
*) echo "WARNING: unsupported OS $OS_NAME , skipping build tools installation.."
esac

Просмотреть файл

@ -0,0 +1,22 @@
FROM ubuntu:20.04
ENV DEBIAN_FRONTEND noninteractive
# Package installation
RUN apt-get update
## Common packages for linux build environment
RUN apt install -y clang python pkg-config git curl bzip2 unzip make wget cmake sudo
RUN adduser --disabled-password --gecos '' docker
RUN adduser docker sudo
RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
## RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo
## USER docker
# this is where I was running into problems with the other approaches
RUN sudo apt-get update
CMD /bin/bash
# ENTRYPOINT bash

Просмотреть файл

@ -177,7 +177,7 @@ Markdown documentation
- GitHub Flavored Markdown
- Trailing white space (two spaces at end of line) is allowed as an
official means to insert a hard line break.
- Everything in English, with clear full sentences, without colloquial
- Everything is in English, with clear full sentences and without colloquial
phrases.
- See existing .md files for reference.

Просмотреть файл

@ -0,0 +1,80 @@
# Custom Transmit Profiles
The SDK packages and uploads most events periodically. As long as there are events waiting and uploading is not disabled or paused, this process runs on a fixed cadence, set by the current transmit profile. A client may either choose one of the built-in profiles named `REAL_TIME`, `NEAR_REAL_TIME`, or `BEST_EFFORT`, or it can provide and select a custom profile. The built-in profiles are defined near the beginning of `lib/tpm/TransmitProfiles.cpp` if you wish to see how they are defined.
A profile can include multiple rules to determine how it behaves based on the current state of device network and device power. For instance, a profile can (and the default profiles do) cause the SDK to upload less often when the device is charging or on a higher-cost network.
To load custom profiles, pass a JSON string containing the profiles (described below) to `TransmitProfiles::load()`. To select a profile by name, pass the name (as a string) to `TransmitProfiles::setProfile()`. The name may be the name of one of the built-in profiles or the name of a profile previously passed to `TransmitProfiles::load()`. Both `load` and `setProfile` return a boolean, where true indicates success and false indicates failure.
## Example Json
```json
[
{
"name": "Fred",
"rules": [
{
"netcost": "metered",
"timers": [-1, -1, 60]
},
{
"powerState": "battery",
"timers": [ 60, 60, 30 ]
},
{
"timers": [ 10, 10, 5 ]
}
]
}
]
```
This defines a single profile named Fred. This JSON contains a one-element array; the `load` method will parse one or more profiles from a single string as a JSON array. In this case we are defining a single profile with three rules. Each rule is a hash with two optional members (`netcost` and `powerState`) and one required member (`timers`).
## Example Decoded
The `Fred` profile has three rules. The first is selected whenever the device is on a metered network. It turns off upload for `EventLatency_Normal` and `EventLatency_CostDeferred` events, and accumulates and uploads `EventLatency_RealTime` events 60 seconds at a time.
The second rule is selected if the first rule does not match and the device is running on battery. It uploads `EventLatency_RealTime` events every 30 seconds, and lower priority events every 60 seconds.
The final rule is selected if no earlier rule matched. It uploads `EventLatency_RealTime` events every 5 seconds, and other events every 10 seconds.
### Netcost selector
A rule may include a `"netcost":"value"` key-value pair. Including this will restrict the rule by network cost:
Selector | Meaning
-------- | -------
roaming | Network marked as roaming (highest cost). Some platforms do not report this cost.
restricted | Synonym for roaming
metered | Network marked as higher cost
high | Synonym for metered
unmetered | Lower-cost network
low | Synonym for unmetered
unknown | Device has not determined network cost
any | Matches any network cost (omitting the selector also matches any network cost)
### PowerState selector
A rule may include a `"powerState":"value"` key-value pair. Including this will restrict the rule by power state:
Selector | Meaning
-------- | -------
battery | Device is operating on battery power
charging | Device is connected to outside power
unknown | Device has not determined its power state.
any | Matches any power state (omitting the selector also matches any power state)
### Selectors and Rule Precedence
If a rule includes selectors, all selectors must match in order to choose the rule. The first rule that matches will be chosen. The example JSON includes a default rule that will always match (because it has no selectors). A match-everything default rule should always be the last rule (rules following it can never be selected since it matches everything, and the first matching rule wins).
### Timers
Each rule must include a timers array. The timers array should contain three values. The first value controls upload of `EventLatency_Normal` and `EventLatency_CostDeferred` events. The second value is not used and is retained for backwards compatibility. The third value controls and sets the cadence for `EventLatency_RealTime` events. For example, if it is 5, the SDK will accumulate and upload `EventLatency_RealTime` events every 5 seconds.
#### Negative Timer Values
If the first timer value is negative, no `EventLatency_Normal` or `EventLatency_CostDeferred` events will be uploaded. If the third timer value is negative, only `EventLatency_Max` events will be uploaded.
#### Cadence And EventLatency
When the first and third timer values are both positive, the value of the first value does not matter (as of this writing). `EventLatency_Normal` and `EventLatency_CostDeferred` events will be collected and uploaded half as often as `EventLatency_RealTime` events.
#### Best Practice
Following these suggestions will help make the rule definition and SDK behavior clear:
* The first and second timer values should be equal. The SDK ignores the second timer value, but it once controlled `EventLatency_CostDeferred` events. Setting the two numbers to the same value documents that the two latencies are treated identically.
* If the first and third timer values are positive, the first and second should be twice the third. For example, `[4, 4, 2]` follows this rule. This matches the SDK's behavior: lower priority events are uploaded half as often as `EventLatency_RealTime` events.
* If the third timer value is negative, the first and second should also be negative. The SDK will not upload any of these events if the third timer value is negative, so setting all three to the same negative value matches this behavior.
* Use -1 consistently to disable upload and avoid the appearance of any special meaning for other negative values.

Просмотреть файл

@ -1,5 +1,22 @@
cmake_minimum_required(VERSION 2.6.4)
# If building for iOS, set all the iOS options
if(BUILD_IOS)
set(TARGET_ARCH "APPLE")
set(IOS True)
set(APPLE True)
set(CMAKE_OSX_DEPLOYMENT_TARGET "" CACHE STRING "Force unset of the deployment target for iOS" FORCE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -miphoneos-version-min=10.0")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -miphoneos-version-min=10.0 -std=c++11")
set(IOS_PLATFORM "iphonesimulator")
set(CMAKE_SYSTEM_PROCESSOR x86_64)
execute_process(COMMAND xcodebuild -version -sdk ${IOS_PLATFORM} Path
OUTPUT_VARIABLE CMAKE_OSX_SYSROOT
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
message("-- CMAKE_OSX_SYSROOT ${CMAKE_OSX_SYSROOT}")
endif()
project( googletest-distribution )
enable_testing()

Просмотреть файл

@ -7,7 +7,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.2'
classpath 'com.android.tools.build:gradle:3.6.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files

Просмотреть файл

@ -215,8 +215,11 @@ public class HttpClient {
String app_language = getLanguageTag(context.getResources().getConfiguration().locale);
String os_major_version = Build.VERSION.RELEASE;
String os_full_version = os_major_version + " " + Build.VERSION.INCREMENTAL;
setSystemInfo(app_id, app_version, app_language, os_major_version, os_full_version);
if (os_major_version == null) {
os_major_version = "GECOS III"; // unexpected except in Java unit tests
}
String os_full_version = String.format("%s %s", os_major_version, Build.VERSION.INCREMENTAL);
setSystemInfo(String.format("A:%s", app_id), app_version, app_language, os_major_version, os_full_version);
}
private String calculateID(android.content.Context context)

Просмотреть файл

@ -4,6 +4,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
@ -39,6 +40,7 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.isA;
@ -86,6 +88,9 @@ public class EventsUnitTest {
@Mock
Configuration mockConfiguration;
@Mock
PackageInfo mockPackageInfo;
static private byte[] body_bytes;
static final private AtomicInteger dispatchCount = new AtomicInteger(0);
static private boolean expectedMetered = false;
@ -172,11 +177,11 @@ public class EventsUnitTest {
String os_full_version
)
{
assertNull(app_id);
assertEquals("", app_version);
assertEquals("A:com.microsoft.nemotronics.doodad", app_id);
assertEquals("FunTimes.3", app_version);
assertEquals("foobar", app_language);
assertNull(os_major_version);
assertEquals("null null", os_full_version);
assertEquals("GECOS III", os_major_version);
assertEquals("GECOS III null", os_full_version);
}
}
@ -192,12 +197,19 @@ public class EventsUnitTest {
}
public void connectMocks() throws PackageManager.NameNotFoundException {
when(mockContext.getPackageName()).thenReturn("com.microsoft.nemotronics.doodad");
when(mockContext.registerReceiver(isA(BroadcastReceiver.class), isA(IntentFilter.class))).thenReturn(mockIntent);
when(mockContext.getPackageManager()).thenReturn(mockPackageManager);
when(mockPackageManager.getPackageInfo(isA(String.class), anyInt())).thenReturn(mockPackageInfo);
mockPackageInfo.versionName = "FunTimes.3";
when(mockContext.getResources()).thenReturn(mockResources);
mockConfiguration.locale = new Locale("foobar");
when(mockResources.getConfiguration()).thenReturn(mockConfiguration);
assertEquals(mockPackageManager, mockContext.getPackageManager());
assertEquals(mockPackageInfo, mockPackageManager.getPackageInfo("foobar", 0));
assertEquals("FunTimes.3", mockPackageInfo.versionName);
}
@Test
public void canInstantiate() throws java.io.IOException, PackageManager.NameNotFoundException {
int previousDispatch = dispatchCount.get();

Просмотреть файл

@ -121,7 +121,11 @@ namespace ARIASDK_NS_BEGIN
{
std::string tenantId = (const char *)m_logConfiguration[CFG_STR_PRIMARY_TOKEN];
tenantId = MAT::tenantTokenToId(tenantId);
if ((!cacheFilePath.empty()) && (cacheFilePath.back() != PATH_SEPARATOR_CHAR))
{
// append path separator if required
cacheFilePath += PATH_SEPARATOR_CHAR;
}
cacheFilePath += tenantId;
cacheFilePath += ".db";
}
@ -338,6 +342,7 @@ namespace ARIASDK_NS_BEGIN
status_t LogManagerImpl::UploadNow()
{
LOCKGUARD(m_lock);
if (GetSystem())
{
GetSystem()->upload();
@ -349,6 +354,7 @@ namespace ARIASDK_NS_BEGIN
status_t LogManagerImpl::PauseTransmission()
{
LOG_INFO("Pausing transmission, cancelling any outstanding uploads...");
LOCKGUARD(m_lock);
if (GetSystem())
{
GetSystem()->pause();
@ -360,6 +366,7 @@ namespace ARIASDK_NS_BEGIN
status_t LogManagerImpl::ResumeTransmission()
{
LOG_INFO("Resuming transmission...");
LOCKGUARD(m_lock);
if (GetSystem())
{
GetSystem()->resume();
@ -399,6 +406,13 @@ namespace ARIASDK_NS_BEGIN
return (result) ? STATUS_SUCCESS : STATUS_EFAIL;
}
status_t LogManagerImpl::LoadTransmitProfiles(const std::vector<TransmitProfileRules>& profiles) noexcept
{
LOG_INFO("LoadTransmitProfiles");
bool result = TransmitProfiles::load(profiles);
return (result) ? STATUS_SUCCESS : STATUS_EFAIL;
}
/// <summary>
/// Reset transmission profiles to default settings
/// </summary>
@ -584,6 +598,7 @@ namespace ARIASDK_NS_BEGIN
void LogManagerImpl::sendEvent(IncomingEventContextPtr const& event)
{
LOCKGUARD(m_lock);
if (GetSystem())
{
if (m_customDecorator)
@ -636,7 +651,6 @@ namespace ARIASDK_NS_BEGIN
std::unique_ptr<ITelemetrySystem>& LogManagerImpl::GetSystem()
{
LOCKGUARD(m_lock);
if (m_system == nullptr || m_isSystemStarted)
return m_system;

Просмотреть файл

@ -149,6 +149,7 @@ namespace ARIASDK_NS_BEGIN
virtual status_t SetTransmitProfile(TransmitProfile profile) override;
virtual status_t SetTransmitProfile(const std::string& profile) override;
virtual status_t LoadTransmitProfiles(const std::string& profiles_json) override;
virtual status_t LoadTransmitProfiles(const std::vector<TransmitProfileRules>& profiles) noexcept override;
virtual status_t ResetTransmitProfiles() override;
virtual const std::string& GetTransmitProfileName() override;

Просмотреть файл

@ -99,6 +99,13 @@ namespace ARIASDK_NS_BEGIN
/// <returns>A boolean value that indicates success (true) or failure (false) if the configuration is invalid.</returns>
virtual status_t LoadTransmitProfiles(const std::string& profiles_json) = 0;
/// <summary>
/// Loads transmit profiles.
/// </summary>
/// <param name="profiles">A collection of transmit profiles</param>
/// <returns>A boolean value that indicates success (true) or failure (false) if the configuration is invalid.</returns>
virtual status_t LoadTransmitProfiles(const std::vector<TransmitProfileRules>& profiles) noexcept = 0;
/// <summary>
/// Resets transmission profiles to default settings.
/// </summary>

Просмотреть файл

@ -203,6 +203,12 @@ namespace ARIASDK_NS_BEGIN
return STATUS_ENOSYS;
}
virtual status_t LoadTransmitProfiles(const std::vector<TransmitProfileRules>& profiles) noexcept override
{
UNREFERENCED_PARAMETER(profiles);
return STATUS_ENOSYS;
}
virtual status_t ResetTransmitProfiles() override
{
return STATUS_ENOSYS;

Просмотреть файл

@ -130,6 +130,10 @@ namespace ARIASDK_NS_BEGIN
/// </summary>
static bool isTimerUpdated;
static void UpdateProfiles(const std::vector<TransmitProfileRules>& newProfiles) noexcept;
static void EnsureDefaultProfiles() noexcept;
public:
@ -174,9 +178,16 @@ namespace ARIASDK_NS_BEGIN
/// Loads customer-supplied transmit profiles.
/// </summary>
/// <param name="profiles_json">A string that contains the the transmit profiles in JSON.</param>
/// <returns>A boolean value that indicates success (true) or failure (false).</returns>
/// <returns>A boolean value that indicates success (true) or failure (false) if at least one transmit profile parses correctly.</returns>
static bool load(const std::string& profiles_json);
/// <summary>
/// Loads caller-supplied transmit profiles.
/// </summary>
/// <param name="profiles">A map of the caller-supplied profiles.</param>
/// <returns>A boolean value that indicates success (true) if all transmit profiles are valid, false otherwise.</returns>
static bool load(const std::vector<TransmitProfileRules>& profiles) noexcept;
/// <summary>
/// Resets transmit profiles to default values.
/// </summary>

@ -1 +1 @@
Subproject commit 9e82bf4fb4a863c96b6ec0c6ec8fb1314b25daef
Subproject commit 1af0c670a40be2cfd1e809351562bcb125576f40

Просмотреть файл

@ -16,7 +16,7 @@ namespace PAL_NS_BEGIN {
class DeviceInformationImpl : public IDeviceInformation
{
public:
static IDeviceInformation* Create();
static std::shared_ptr<IDeviceInformation> Create();
virtual int RegisterInformationChangedCallback(PAL::IPropertyChangedCallback* pCallback) override
{
@ -38,6 +38,10 @@ namespace PAL_NS_BEGIN {
virtual PowerSource GetPowerSource() const override { return m_powerSource; }
virtual std::string GetDeviceTicket() const override;
DeviceInformationImpl();
virtual ~DeviceInformationImpl();
// Disable copy constructor and assignment operator.
DeviceInformationImpl(DeviceInformationImpl const& other) = delete;
DeviceInformationImpl& operator=(DeviceInformationImpl const& other) = delete;
@ -52,10 +56,6 @@ namespace PAL_NS_BEGIN {
std::string m_model;
private:
size_t m_registeredCount;
protected:
DeviceInformationImpl();
virtual ~DeviceInformationImpl();
};
} PAL_NS_END

Просмотреть файл

@ -18,7 +18,7 @@ namespace PAL_NS_BEGIN {
class NetworkInformationImpl : public INetworkInformation
{
public:
static INetworkInformation* Create(bool isNetDetectEnabled);
static std::shared_ptr<INetworkInformation> Create(bool isNetDetectEnabled);
// IInformationProvider API
virtual int RegisterInformationChangedCallback(IPropertyChangedCallback* pCallback) { m_registeredCount++; return m_info_helper.RegisterInformationChangedCallback(pCallback); }
@ -36,6 +36,10 @@ namespace PAL_NS_BEGIN {
NetworkInformationImpl(bool isNetDetectEnabled);
virtual ~NetworkInformationImpl();
// Disable copy constructor and assignment operator.
NetworkInformationImpl(NetworkInformationImpl const& other) = delete;
NetworkInformationImpl& operator=(NetworkInformationImpl const& other) = delete;
protected:
std::string m_provider;
NetworkType m_type;
@ -44,10 +48,6 @@ namespace PAL_NS_BEGIN {
InformatonProviderImpl m_info_helper;
int m_registeredCount;
bool m_isNetDetectEnabled;
// Disable copy constructor and assignment operator.
NetworkInformationImpl(NetworkInformationImpl const& other) = delete;
NetworkInformationImpl& operator=(NetworkInformationImpl const& other) = delete;
};
} PAL_NS_END

Просмотреть файл

@ -82,12 +82,12 @@ namespace PAL_NS_BEGIN {
#endif
bool isLoggingInited = false;
#ifdef HAVE_MAT_LOGGING
std::recursive_mutex debugLogMutex;
std::string debugLogPath;
std::unique_ptr<std::fstream> debugLogStream;
bool log_init(bool isTraceEnabled, const std::string& traceFolderPath)
{
if (!isTraceEnabled)
@ -118,7 +118,7 @@ namespace PAL_NS_BEGIN {
debugLogMutex.unlock();
return result;
}
void log_done()
{
debugLogMutex.lock();
@ -243,11 +243,11 @@ namespace PAL_NS_BEGIN {
std::shared_ptr<ITaskDispatcher> PlatformAbstractionLayer::getDefaultTaskDispatcher()
{
if (m_taskDispatcher == nullptr)
if (!m_taskDispatcher)
{
// Default implementation of task dispatcher is a single-threaded worker thread task queue
LOG_TRACE("Initializing PAL worker thread");
m_taskDispatcher.reset(PAL::WorkerThreadFactory::Create());
m_taskDispatcher = PAL::WorkerThreadFactory::Create();
}
return m_taskDispatcher;
}
@ -478,9 +478,9 @@ namespace PAL_NS_BEGIN {
}
}
INetworkInformation* PlatformAbstractionLayer::GetNetworkInformation() const noexcept { return m_NetworkInformation; }
IDeviceInformation* PlatformAbstractionLayer::GetDeviceInformation() const noexcept { return m_DeviceInformation; }
ISystemInformation* PlatformAbstractionLayer::GetSystemInformation() const noexcept { return m_SystemInformation; }
std::shared_ptr<INetworkInformation> PlatformAbstractionLayer::GetNetworkInformation() const noexcept { return m_NetworkInformation; }
std::shared_ptr<IDeviceInformation> PlatformAbstractionLayer::GetDeviceInformation() const noexcept { return m_DeviceInformation; }
std::shared_ptr<ISystemInformation> PlatformAbstractionLayer::GetSystemInformation() const noexcept { return m_SystemInformation; }
void PlatformAbstractionLayer::shutdown()
{
@ -494,9 +494,9 @@ namespace PAL_NS_BEGIN {
{
LOG_TRACE("Shutting down...");
if (m_taskDispatcher) { m_taskDispatcher = nullptr; }
if (m_SystemInformation) { delete m_SystemInformation; m_SystemInformation = nullptr; }
if (m_DeviceInformation) { delete m_DeviceInformation; m_DeviceInformation = nullptr; }
if (m_NetworkInformation) { delete m_NetworkInformation; m_NetworkInformation = nullptr; }
if (m_SystemInformation) { m_SystemInformation = nullptr; }
if (m_DeviceInformation) { m_DeviceInformation = nullptr; }
if (m_NetworkInformation) { m_NetworkInformation = nullptr; }
LOG_INFO("Shut down");
detail::log_done();
}

Просмотреть файл

@ -51,6 +51,7 @@
#include <climits>
#include <chrono>
#include <thread>
#include <memory>
#include "api/IRuntimeConfig.hpp"
#include "typename.hpp"
@ -95,10 +96,10 @@ namespace PAL_NS_BEGIN
void initialize(IRuntimeConfig& configuration);
void shutdown();
INetworkInformation* GetNetworkInformation() const noexcept;
IDeviceInformation* GetDeviceInformation() const noexcept;
ISystemInformation* GetSystemInformation() const noexcept;
std::shared_ptr<INetworkInformation> GetNetworkInformation() const noexcept;
std::shared_ptr<IDeviceInformation> GetDeviceInformation() const noexcept;
std::shared_ptr<ISystemInformation> GetSystemInformation() const noexcept;
bool IsUtcRegistrationEnabledinWindows() const noexcept;
@ -109,9 +110,9 @@ namespace PAL_NS_BEGIN
private:
volatile std::atomic<long> m_palStarted { 0 };
std::shared_ptr<ITaskDispatcher> m_taskDispatcher;
ISystemInformation* m_SystemInformation;
INetworkInformation* m_NetworkInformation;
IDeviceInformation* m_DeviceInformation;
std::shared_ptr<ISystemInformation> m_SystemInformation;
std::shared_ptr<INetworkInformation> m_NetworkInformation;
std::shared_ptr<IDeviceInformation> m_DeviceInformation;
};
PlatformAbstractionLayer& GetPAL() noexcept;
@ -211,15 +212,15 @@ namespace PAL_NS_BEGIN
GetPAL().shutdown();
}
inline INetworkInformation* GetNetworkInformation() noexcept
inline std::shared_ptr<INetworkInformation> GetNetworkInformation() noexcept
{
return GetPAL().GetNetworkInformation();
}
inline IDeviceInformation* GetDeviceInformation() noexcept
inline std::shared_ptr<IDeviceInformation> GetDeviceInformation() noexcept
{
return GetPAL().GetDeviceInformation();
}
inline ISystemInformation* GetSystemInformation() noexcept
inline std::shared_ptr<ISystemInformation> GetSystemInformation() noexcept
{
return GetPAL().GetSystemInformation();
}

Просмотреть файл

@ -17,7 +17,7 @@ namespace PAL_NS_BEGIN {
class SystemInformationImpl : public ISystemInformation
{
public:
static ISystemInformation* Create();
static std::shared_ptr<ISystemInformation> Create();
// IInformationProvider API
virtual int RegisterInformationChangedCallback(IPropertyChangedCallback* pCallback) override;
@ -39,6 +39,13 @@ namespace PAL_NS_BEGIN {
virtual std::string const& GetDeviceClass() const override { return m_device_class; };
virtual std::string const& GetCommercialId() const override { return m_commercial_id; };
SystemInformationImpl();
~SystemInformationImpl() override;
// Disable copy constructor and assignment operator.
SystemInformationImpl(SystemInformationImpl const& other);
SystemInformationImpl& operator=(SystemInformationImpl const& other);
private:
std::string m_app_id;
std::string m_app_version;
@ -56,13 +63,6 @@ namespace PAL_NS_BEGIN {
std::string m_commercial_id;
InformatonProviderImpl m_info_helper;
// Disable copy constructor and assignment operator.
SystemInformationImpl(SystemInformationImpl const& other);
SystemInformationImpl& operator=(SystemInformationImpl const& other);
SystemInformationImpl();
~SystemInformationImpl();
};
} PAL_NS_END

Просмотреть файл

@ -37,7 +37,7 @@ namespace PAL_NS_BEGIN {
Event m_event;
MAT::Task* m_itemInProgress;
int count = 0;
public:
WorkerThread()
@ -117,7 +117,7 @@ namespace PAL_NS_BEGIN {
// TODO: current callers of this API do not check the status code.
// Refactor this code to return the following cancellation status:
// - TASK_NOTFOUND - task not found
// - TASK_CANCELLED - task found and cancelled without execution
// - TASK_CANCELLED - task found and cancelled without execution
// - TASK_COMPLETED - task found and ran to completion
// - TASK_RUNNING - task is still running (insufficient waitTime)
//
@ -228,7 +228,7 @@ namespace PAL_NS_BEGIN {
self->m_itemInProgress = nullptr;
break;
}
LOG_TRACE("%10llu Execute item=%p type=%s\n", wakeupCount, item.get(), item.get()->TypeName.c_str() );
(*item)();
self->m_itemInProgress = nullptr;
@ -242,9 +242,9 @@ namespace PAL_NS_BEGIN {
};
namespace WorkerThreadFactory {
ITaskDispatcher* Create()
std::shared_ptr<ITaskDispatcher> Create()
{
return new WorkerThread();
return std::make_shared<WorkerThread>();
}
}

Просмотреть файл

@ -10,6 +10,7 @@
#include <condition_variable>
#include <climits>
#include <algorithm>
#include <memory>
#include "ITaskDispatcher.hpp"
#include "Version.hpp"
@ -74,9 +75,9 @@ namespace PAL_NS_BEGIN {
};
namespace WorkerThreadFactory {
MAT::ITaskDispatcher* Create();
std::shared_ptr<MAT::ITaskDispatcher> Create();
}
} PAL_NS_END
#endif
#endif

Просмотреть файл

@ -143,10 +143,9 @@ namespace PAL_NS_BEGIN {
{
}
IDeviceInformation* DeviceInformationImpl::Create()
std::shared_ptr<IDeviceInformation> DeviceInformationImpl::Create()
{
return new DeviceInformationImpl();
return std::make_shared<DeviceInformationImpl>();
}
} PAL_NS_END

Просмотреть файл

@ -115,10 +115,9 @@ namespace PAL_NS_BEGIN {
#endif
}
INetworkInformation* NetworkInformationImpl::Create(bool isNetDetectEnabled)
std::shared_ptr<INetworkInformation> NetworkInformationImpl::Create(bool isNetDetectEnabled)
{
return new Win32NetworkInformation(isNetDetectEnabled);
return std::make_shared<Win32NetworkInformation>(isNetDetectEnabled);
}
} PAL_NS_END
#endif

Просмотреть файл

@ -10,7 +10,7 @@
/* Ref. https://docs.microsoft.com/en-us/windows/desktop/apiindex/windows-8-api-sets
*
* Compatibility with Windows 7, Windows Server 2008 R2 and older operating systems:
* Binaries that link to MinCore.lib or MinCore_Downlevel.lib are not designed to work
* Binaries that link to MinCore.lib or MinCore_Downlevel.lib are not designed to work
* on Windows 7, Windows Server 2008 R2 or earlier. Binaries that need to run on earlier
* versions of Windows or Windows Server must not use either MinCore.lib or MinCore_Downlevel.lib.
*/
@ -33,9 +33,9 @@ namespace PAL_NS_BEGIN {
const std::string WindowsOSName = "Windows Desktop";
ISystemInformation* SystemInformationImpl::Create()
std::shared_ptr<ISystemInformation> SystemInformationImpl::Create()
{
return new SystemInformationImpl();
return std::make_shared<SystemInformationImpl>();
}
/**
@ -57,7 +57,7 @@ namespace PAL_NS_BEGIN {
if (::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, nullptr, &handle) == FALSE)
{
LOG_ERROR("Failed to get module handle with error: %d", ::GetLastError());
return {};
return {};
}
DWORD result = ::GetModuleFileName(handle, &curExeFullPathBuffer[0], curBufferLength);
@ -102,7 +102,7 @@ namespace PAL_NS_BEGIN {
// Get the filename of the current process
std::wstring applicationFullPath = getAppFullPath();
// Get the product version information from the current process filename
// Get the product version information from the current process filename
dwVersionInfoSize = GetFileVersionInfoSize(applicationFullPath.data(), &dwUnused);
if (dwVersionInfoSize == 0)
@ -199,7 +199,7 @@ namespace PAL_NS_BEGIN {
appId = app_name;
}
}
else
else
{
LOG_ERROR("Failed to get module handle with error: %d", ::GetLastError());
}

Просмотреть файл

@ -10,7 +10,7 @@
#include <locale>
#include <codecvt>
#include "sysinfo_sources.hpp"
#include "sysinfo_sources_impl.hpp"
#define DEFAULT_DEVICE_ID "{deadbeef-fade-dead-c0de-cafebabefeed}"
@ -36,12 +36,13 @@ namespace PAL_NS_BEGIN {
m_os_architecture = OsArchitectureType_Unknown;
#endif
std::string devId = aria_hwinfo.get("devId");
auto sysInfo = sysinfo_sources_impl::GetSysInfo();
std::string devId = sysInfo.get("devId");
m_device_id = (devId.empty()) ? DEFAULT_DEVICE_ID : devId;
m_manufacturer = aria_hwinfo.get("devMake");
m_manufacturer = sysInfo.get("devMake");
m_model = aria_hwinfo.get("devModel");
m_model = sysInfo.get("devModel");
m_powerSource = GetCurrentPowerSource();
@ -59,9 +60,9 @@ namespace PAL_NS_BEGIN {
}
#endif
IDeviceInformation* DeviceInformationImpl::Create()
std::shared_ptr<IDeviceInformation> DeviceInformationImpl::Create()
{
return new DeviceInformationImpl();
return std::make_shared<DeviceInformationImpl>();
}
DeviceInformationImpl::~DeviceInformationImpl() {}

Просмотреть файл

@ -11,7 +11,7 @@
#include <locale>
#include <codecvt>
#include "sysinfo_sources.hpp"
#include "sysinfo_sources_impl.hpp"
#define DEFAULT_DEVICE_ID "{deadbeef-fade-dead-c0de-cafebabefeed}"
@ -28,7 +28,7 @@ namespace PAL_NS_BEGIN {
static std::string s_model;
static std::mutex s_registered_mutex;
static std::vector<AndroidDeviceInformation *> s_registered;
public:
static void registerDI(AndroidDeviceInformation &di);
@ -90,9 +90,9 @@ namespace PAL_NS_BEGIN {
}
};
IDeviceInformation* DeviceInformationImpl::Create()
std::shared_ptr<IDeviceInformation> DeviceInformationImpl::Create()
{
return new AndroidDeviceInformation();
return std::make_shared<AndroidDeviceInformation>();
}
DeviceInformationImpl::~DeviceInformationImpl() {}
@ -154,7 +154,7 @@ JNIEXPORT void
JNICALL
Java_com_microsoft_applications_events_HttpClient_onPowerChange(JNIEnv* env,
jobject /* java_client */,
jboolean isCharging,
jboolean isCharging,
jboolean isLow)
{
PowerSource new_power_source = PowerSource_Charging;
@ -194,4 +194,4 @@ Java_com_microsoft_applications_events_HttpClient_onPowerChange(JNIEnv* env,
end = start + env->GetStringUTFLength(model);
PAL::AndroidDeviceInformationConnector::setModel(std::string(start, end));
env->ReleaseStringUTFChars(model, start);
}
}

Просмотреть файл

@ -72,9 +72,9 @@ namespace PAL_NS_BEGIN {
{
}
INetworkInformation* NetworkInformationImpl::Create(bool isNetDetectEnabled)
std::shared_ptr<INetworkInformation> NetworkInformationImpl::Create(bool isNetDetectEnabled)
{
return new NetworkInformation(isNetDetectEnabled);
return std::make_shared<NetworkInformation>(isNetDetectEnabled);
}
} PAL_NS_END

Просмотреть файл

@ -14,7 +14,8 @@ namespace PAL_NS_BEGIN {
NetworkInformationImpl::~NetworkInformationImpl() {};
class NetworkInformation : public NetworkInformationImpl
class NetworkInformation : public NetworkInformationImpl,
public std::enable_shared_from_this<NetworkInformation>
{
public:
/// <summary>
@ -52,6 +53,12 @@ namespace PAL_NS_BEGIN {
return m_cost;
}
/// <summary>
/// Setup initial network information and start net monitor if requested.
/// This cannot be put in constructor because we need to use shared_from_this.
/// </summary>
void SetupNetDetect();
private:
void UpdateType(NetworkType type) noexcept;
void UpdateCost(NetworkCost cost) noexcept;
@ -70,6 +77,30 @@ namespace PAL_NS_BEGIN {
{
m_type = NetworkType_Unknown;
m_cost = NetworkCost_Unknown;
}
NetworkInformation::~NetworkInformation() noexcept
{
if (@available(iOS 12.0, *))
{
if (m_isNetDetectEnabled)
{
nw_path_monitor_cancel(m_monitor);
}
}
else
{
if (m_isNetDetectEnabled)
{
[[NSNotificationCenter defaultCenter] removeObserver:m_notificationId];
[m_reach stopNotifier];
}
}
}
void NetworkInformation::SetupNetDetect()
{
auto weak_this = std::weak_ptr<NetworkInformation>(shared_from_this());
if (@available(iOS 12.0, *))
{
@ -77,6 +108,12 @@ namespace PAL_NS_BEGIN {
nw_path_monitor_set_queue(m_monitor, dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0));
nw_path_monitor_set_update_handler(m_monitor, ^(nw_path_t path)
{
auto strong_this = weak_this.lock();
if (!strong_this)
{
return;
}
NetworkType type = NetworkType_Unknown;
NetworkCost cost = NetworkCost_Unknown;
nw_path_status_t status = nw_path_get_status(path);
@ -104,15 +141,15 @@ namespace PAL_NS_BEGIN {
}
}
}
UpdateType(type);
UpdateCost(cost);
strong_this->UpdateType(type);
strong_this->UpdateCost(cost);
});
nw_path_monitor_start(m_monitor);
// nw_path_monitor_start will invoke the callback for once. So if
// we don't want to listen for changes, we can just start the
// monitor and stop it right away.
if (!isNetDetectEnabled)
if (!m_isNetDetectEnabled)
{
nw_path_monitor_cancel(m_monitor);
}
@ -122,26 +159,32 @@ namespace PAL_NS_BEGIN {
m_reach = [Reachability reachabilityForInternetConnection];
void (^block)(NSNotification*) = ^(NSNotification*)
{
auto strong_this = weak_this.lock();
if (!strong_this)
{
return;
}
// NetworkCost information is not available until iOS 12.
// Just make the best guess here.
switch (m_reach.currentReachabilityStatus)
{
case NotReachable:
UpdateType(NetworkType_Unknown);
UpdateCost(NetworkCost_Unknown);
strong_this->UpdateType(NetworkType_Unknown);
strong_this->UpdateCost(NetworkCost_Unknown);
break;
case ReachableViaWiFi:
UpdateType(NetworkType_Wifi);
UpdateCost(NetworkCost_Unmetered);
strong_this->UpdateType(NetworkType_Wifi);
strong_this->UpdateCost(NetworkCost_Unmetered);
break;
case ReachableViaWWAN:
UpdateType(NetworkType_WWAN);
UpdateCost(NetworkCost_Metered);
strong_this->UpdateType(NetworkType_WWAN);
strong_this->UpdateCost(NetworkCost_Metered);
break;
}
};
block(nil); // Update the initial status.
if (isNetDetectEnabled)
if (m_isNetDetectEnabled)
{
m_notificationId =
[[NSNotificationCenter defaultCenter]
@ -154,25 +197,6 @@ namespace PAL_NS_BEGIN {
}
}
NetworkInformation::~NetworkInformation() noexcept
{
if (@available(iOS 12.0, *))
{
if (m_isNetDetectEnabled)
{
nw_path_monitor_cancel(m_monitor);
}
}
else
{
if (m_isNetDetectEnabled)
{
[[NSNotificationCenter defaultCenter] removeObserver:m_notificationId];
[m_reach stopNotifier];
}
}
}
void NetworkInformation::UpdateType(NetworkType type) noexcept
{
if (type != m_type)
@ -191,9 +215,11 @@ namespace PAL_NS_BEGIN {
}
}
INetworkInformation* NetworkInformationImpl::Create(bool isNetDetectEnabled)
std::shared_ptr<INetworkInformation> NetworkInformationImpl::Create(bool isNetDetectEnabled)
{
return new NetworkInformation(isNetDetectEnabled);
auto networkInformation = std::make_shared<NetworkInformation>(isNetDetectEnabled);
networkInformation->SetupNetDetect();
return networkInformation;
}
} PAL_NS_END

Просмотреть файл

@ -136,9 +136,9 @@ namespace PAL_NS_BEGIN {
AndroidNetcostConnector::UnregisterNI(*this);
}
INetworkInformation* NetworkInformationImpl::Create(bool isNetDetectEnabled)
std::shared_ptr<INetworkInformation> NetworkInformationImpl::Create(bool isNetDetectEnabled)
{
return new NetworkInformation(isNetDetectEnabled);
return std::make_shared<NetworkInformation>(isNetDetectEnabled);
}
} PAL_NS_END

Просмотреть файл

@ -3,18 +3,19 @@
#include "pal/SystemInformationImpl.hpp"
#include <sys/utsname.h>
#include "sysinfo_sources.hpp"
#include "sysinfo_sources_impl.hpp"
#include <string>
namespace PAL_NS_BEGIN {
SystemInformationImpl::SystemInformationImpl() : m_info_helper()
{
m_user_timezone = aria_hwinfo.get("tz");
m_app_id = aria_hwinfo.get("appId");
m_os_name = aria_hwinfo.get("osName");
m_os_major_version = aria_hwinfo.get("osVer");
m_os_full_version = aria_hwinfo.get("osRel");
auto sysInfo = sysinfo_sources_impl::GetSysInfo();
m_user_timezone = sysInfo.get("tz");
m_app_id = sysInfo.get("appId");
m_os_name = sysInfo.get("osName");
m_os_major_version = sysInfo.get("osVer");
m_os_full_version = sysInfo.get("osRel");
}
SystemInformationImpl::~SystemInformationImpl()
@ -31,9 +32,9 @@ namespace PAL_NS_BEGIN {
m_info_helper.UnRegisterInformationChangedCallback(callbackToken);
}
ISystemInformation* SystemInformationImpl::Create()
std::shared_ptr<ISystemInformation> SystemInformationImpl::Create()
{
return new SystemInformationImpl();
return std::make_shared<SystemInformationImpl>();
}
} PAL_NS_END

Просмотреть файл

@ -60,9 +60,9 @@ namespace PAL_NS_BEGIN {
m_info_helper.UnRegisterInformationChangedCallback(callbackToken);
}
ISystemInformation* SystemInformationImpl::Create()
std::shared_ptr<ISystemInformation> SystemInformationImpl::Create()
{
return new SystemInformationImpl();
return std::make_shared<SystemInformationImpl>();
}
} PAL_NS_END

Просмотреть файл

@ -6,7 +6,7 @@
* Author: Max Golovanov <maxgolov@microsoft.com>
*/
#include "sysinfo_sources.hpp"
#include "sysinfo_sources_impl.hpp"
#include <cstdio>
#include <cstdlib>
@ -192,121 +192,113 @@ const std::string& sysinfo_sources::get(std::string key)
return cache[key];
}
class sysinfo_sources_impl: public sysinfo_sources {
public:
/**
* Obtain system hardware and application information
*/
sysinfo_sources_impl() : sysinfo_sources()
{
struct utsname buf;
uname(&buf);
/**
* Obtain system hardware and application information
*/
sysinfo_sources_impl::sysinfo_sources_impl() : sysinfo_sources()
{
struct utsname buf;
uname(&buf);
#if defined(__linux__)
// Obtain Linux system information from filesystem
add("devId", { "/etc/machine-id", "*"});
add("osName", {"/etc/os-release", ".*ID=(.*)[\n]+"});
add("osVer", {"/etc/os-release", ".*VERSION_ID=\"(.*)\".*"});
add("osRel", {"/etc/os-release", ".*VERSION=\"(.*)\".*"});
add("osBuild", {"/proc/version", "(.*)[\n]+"});
// add("proc_loadavg", {"/proc/loadavg", "(.*)[\n]*"});
// add("proc_uptime", {"/proc/uptime", "(.*)[\n]*"});
// Obtain Linux system information from filesystem
add("devId", { "/etc/machine-id", "*"});
add("osName", {"/etc/os-release", ".*ID=(.*)[\n]+"});
add("osVer", {"/etc/os-release", ".*VERSION_ID=\"(.*)\".*"});
add("osRel", {"/etc/os-release", ".*VERSION=\"(.*)\".*"});
add("osBuild", {"/proc/version", "(.*)[\n]+"});
// add("proc_loadavg", {"/proc/loadavg", "(.*)[\n]*"});
// add("proc_uptime", {"/proc/uptime", "(.*)[\n]*"});
#endif
#if defined(__MINGW32__) || defined(__MSYS__)
// Obtain MinGW Device ID from registry
add("devId", { "/proc/registry/HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/SystemInformation/ComputerHardwareId", "*"});
add("devMake", { "/proc/registry/HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/SystemInformation/SystemManufacturer", "*"});
add("devModel", { "/proc/registry/HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/SystemInformation/SystemProductName", "*"});
// Obtain MinGW Device ID from registry
add("devId", { "/proc/registry/HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/SystemInformation/ComputerHardwareId", "*"});
add("devMake", { "/proc/registry/HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/SystemInformation/SystemManufacturer", "*"});
add("devModel", { "/proc/registry/HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/SystemInformation/SystemProductName", "*"});
#endif
#if defined(__APPLE__)
// FIXME: [MG] - This is not the most elegant way of obtaining it
cache["devMake"] = "Apple";
// FIXME: [MG] - This is not the most elegant way of obtaining it
cache["devMake"] = "Apple";
#if TARGET_OS_IPHONE
cache["devModel"] = GetDeviceModel();
cache["devModel"] = GetDeviceModel();
#else
cache["devModel"] = Exec("sysctl hw.model | awk '{ print $2 }'");
cache["devModel"] = Exec("sysctl hw.model | awk '{ print $2 }'");
#endif // TARGET_OS_IPHONE
cache["osName"] = GetDeviceOsName();
cache["osVer"] = GetDeviceOsVersion();
cache["osRel"] = GetDeviceOsRelease();
cache["osBuild"] = GetDeviceOsBuild();
cache["osName"] = GetDeviceOsName();
cache["osVer"] = GetDeviceOsVersion();
cache["osRel"] = GetDeviceOsRelease();
cache["osBuild"] = GetDeviceOsBuild();
// Populate user timezone as hh:mm offset from UTC timezone. Example for PST: "-08:00"
CFTimeZoneRef tz = CFTimeZoneCopySystem();
CFTimeInterval minsFromGMT = CFTimeZoneGetSecondsFromGMT(tz, CFAbsoluteTimeGetCurrent()) / 60.0;
CFRelease(tz);
std::ostringstream oss;
int hh = std::abs((int)minsFromGMT / 60);
int mm = std::abs((int)minsFromGMT % 60);
if (minsFromGMT<0)
{
oss << "-";
}
oss << std::setw(2) << std::setfill('0') << hh;
oss << std::setw(1) << ":";
oss << std::setw(2) << std::setfill('0') << mm;
cache["tz"] = oss.str();
// Populate user timezone as hh:mm offset from UTC timezone. Example for PST: "-08:00"
CFTimeZoneRef tz = CFTimeZoneCopySystem();
CFTimeInterval minsFromGMT = CFTimeZoneGetSecondsFromGMT(tz, CFAbsoluteTimeGetCurrent()) / 60.0;
CFRelease(tz);
std::ostringstream oss;
int hh = std::abs((int)minsFromGMT / 60);
int mm = std::abs((int)minsFromGMT % 60);
if (minsFromGMT<0)
{
oss << "-";
}
oss << std::setw(2) << std::setfill('0') << hh;
oss << std::setw(1) << ":";
oss << std::setw(2) << std::setfill('0') << mm;
cache["tz"] = oss.str();
#endif
// Fallback to uname if above methods failed
if (!get("osVer").compare(""))
{
cache["osVer"] = (const char *)(buf.version);
}
if (!get("osName").compare(""))
{
cache["osName"] = (const char *)(buf.sysname);
}
if (!get("osRel").compare(""))
{
cache["osRel"] = (const char *)(buf.release);
}
#ifndef __APPLE__
add("appId", {"/proc/self/cmdline", "(.*)[ ]*.*[\n]*"});
#else
cache["appId"] = get_app_name(); // TODO: [MG] - verify this path
#endif
if (!get("devId").compare(""))
{
#ifdef __APPLE__
#if TARGET_OS_IPHONE
cache["devId"] = "i:";
std::string contents = GetDeviceId();
#else
// Microsoft Edge bug 21528330
// We were unable to use get_platform_uuid to obtain Device Id
// in render processes.
std::string contents = Exec(R"(ioreg -d2 -c IOPlatformExpertDevice | awk -F\" '/IOPlatformUUID/{print $(NF-1)}')");
cache["devId"] = "u:";
#endif // TARGET_OS_IPHONE
cache["devId"] += MAT::GUID_t(contents.c_str()).to_string();
#else
// We were unable to obtain Device Id using standard means.
// Try to use hash of blkid + hostname instead. Both blkid
// and hostname would rarely change, as well as guarantee
// at least some protection from cloned VM images.
std::string contents = Exec("echo `blkid; hostname`");
if (!contents.empty())
{
uint8_t guid_bytes[16] = { 0 };
for(size_t i=0; i<contents.length(); i++)
{ // Simple XOR of contents to generate a UUID
guid_bytes[i % 16] ^= contents.at(i);
}
cache["devId"] = MAT::GUID_t(guid_bytes).to_string();
}
#endif
}
// Fallback to uname if above methods failed
if (!get("osVer").compare(""))
{
cache["osVer"] = (const char *)(buf.version);
}
};
if (!get("osName").compare(""))
{
cache["osName"] = (const char *)(buf.sysname);
}
sysinfo_sources aria_hwinfo = sysinfo_sources_impl();
if (!get("osRel").compare(""))
{
cache["osRel"] = (const char *)(buf.release);
}
#ifndef __APPLE__
add("appId", {"/proc/self/cmdline", "(.*)[ ]*.*[\n]*"});
#else
cache["appId"] = get_app_name(); // TODO: [MG] - verify this path
#endif
if (!get("devId").compare(""))
{
#ifdef __APPLE__
#if TARGET_OS_IPHONE
cache["devId"] = "i:";
std::string contents = GetDeviceId();
#else
// Microsoft Edge bug 21528330
// We were unable to use get_platform_uuid to obtain Device Id
// in render processes.
std::string contents = Exec(R"(ioreg -d2 -c IOPlatformExpertDevice | awk -F\" '/IOPlatformUUID/{print $(NF-1)}')");
cache["devId"] = "u:";
#endif // TARGET_OS_IPHONE
cache["devId"] += MAT::GUID_t(contents.c_str()).to_string();
#else
// We were unable to obtain Device Id using standard means.
// Try to use hash of blkid + hostname instead. Both blkid
// and hostname would rarely change, as well as guarantee
// at least some protection from cloned VM images.
std::string contents = Exec("echo `blkid; hostname`");
if (!contents.empty())
{
uint8_t guid_bytes[16] = { 0 };
for(size_t i=0; i<contents.length(); i++)
{ // Simple XOR of contents to generate a UUID
guid_bytes[i % 16] ^= contents.at(i);
}
cache["devId"] = MAT::GUID_t(guid_bytes).to_string();
}
#endif
}
}

Просмотреть файл

@ -56,6 +56,4 @@ public:
};
extern sysinfo_sources aria_hwinfo;
#endif /* LIB_PAL_POSIX_SYSINFO_SOURCES_HPP_ */

Просмотреть файл

@ -0,0 +1,23 @@
#ifndef LIB_PAL_POSIX_SYSINFO_SOURCES_IMPL_HPP_
#define LIB_PAL_POSIX_SYSINFO_SOURCES_IMPL_HPP_
// Copyright (c) Microsoft Corporation. All rights reserved.
#include "sysinfo_sources.hpp"
class sysinfo_sources_impl: public sysinfo_sources {
public:
sysinfo_sources_impl();
/**
* Get instance for serving all singleton calls
*/
static sysinfo_sources_impl& GetSysInfo()
{
static sysinfo_sources_impl instance;
return instance;
}
};
#endif /* LIB_PAL_POSIX_SYSINFO_SOURCES_IMPL_HPP_ */

Просмотреть файл

@ -6,7 +6,7 @@
#include "pal/desktop/WindowsEnvironmentInfo.hpp"
#include "PlatformHelpers.h"
#include <exception>
#include <exception>
#define LOG_MODULE DBG_PAL
@ -119,9 +119,9 @@ namespace PAL_NS_BEGIN {
::Windows::System::Power::PowerManager::PowerSupplyStatusChanged -= token2;
}
IDeviceInformation* DeviceInformationImpl::Create()
std::shared_ptr<IDeviceInformation> DeviceInformationImpl::Create()
{
return new DeviceInformationImpl();
return std::make_shared<DeviceInformationImpl>();
}
} PAL_NS_END

Просмотреть файл

@ -1,6 +1,6 @@
#include <windows.h>
#include "pal/NetworkInformationImpl.hpp"
#include <exception>
#include <exception>
using namespace ::Windows::Networking::Connectivity;
@ -122,14 +122,14 @@ namespace PAL_NS_BEGIN {
}
NetworkInformationImpl::~NetworkInformationImpl()
NetworkInformationImpl::~NetworkInformationImpl()
{
NetworkInformation::NetworkStatusChanged -= token;
};
INetworkInformation* NetworkInformationImpl::Create(bool isNetDetectEnabled)
std::shared_ptr<INetworkInformation> NetworkInformationImpl::Create(bool isNetDetectEnabled)
{
return new NetworkInformationImpl(isNetDetectEnabled);
return std::make_shared<NetworkInformationImpl>(isNetDetectEnabled);
}
} PAL_NS_END

Просмотреть файл

@ -21,9 +21,9 @@ namespace PAL_NS_BEGIN {
const string WindowsPhoneOSName = "Windows for Phones";
const string DeviceFamily_Mobile = "Windows.Mobile";
ISystemInformation* SystemInformationImpl::Create()
std::shared_ptr<ISystemInformation> SystemInformationImpl::Create()
{
return new SystemInformationImpl();
return std::make_shared<SystemInformationImpl>();
}
SystemInformationImpl::SystemInformationImpl()

Просмотреть файл

@ -20,11 +20,11 @@ using namespace PAL;
*
******************************************************************************/
void DeviceStateHandler::Start()
{
{
// TRACE("_RetrieveAndRegisterForDeviceConditionChange");
m_networkInformation = PAL::GetNetworkInformation();
if (m_networkInformation != nullptr)
if (m_networkInformation)
{
m_networkType = m_networkInformation->GetNetworkType();
m_networkCost = m_networkInformation->GetNetworkCost();
@ -36,7 +36,7 @@ void DeviceStateHandler::Start()
}
m_deviceInformation = PAL::GetDeviceInformation();
if (m_deviceInformation != nullptr)
if (m_deviceInformation)
{
m_powerSource = m_deviceInformation->GetPowerSource();
@ -45,7 +45,7 @@ void DeviceStateHandler::Start()
}
// Based on the network connectivity and power state info we just retrieved from system
// update the default device condition if necessary.
// update the default device condition if necessary.
_UpdateDeviceCondition();
}
@ -60,17 +60,17 @@ void DeviceStateHandler::Stop()
{
// TRACE("Enter stop transmission policy manager");
m_networkInformation = PAL::GetNetworkInformation();
m_deviceInformation = PAL::GetDeviceInformation();
// 4. Stop listening to platform network, power and device info changes
if (m_networkInformation != nullptr)
if (m_networkInformation)
{
m_networkInformation->UnRegisterInformationChangedCallback(m_networkInformationToken);
m_networkInformation = nullptr;
}
if (m_deviceInformation != nullptr)
if (m_deviceInformation)
{
m_deviceInformation->UnRegisterInformationChangedCallback(m_deviceInformationToken);
m_deviceInformation = nullptr;
}
}
@ -85,10 +85,10 @@ void DeviceStateHandler::OnChanged(
std::string const& propertyName,
std::string const& propertyValue)
{
// TRACE("OnChanged: Platform network callback with Name=%s, Val=%s",
// TRACE("OnChanged: Platform network callback with Name=%s, Val=%s",
// propertyName.c_str(), propertyValue.c_str());
if (propertyName.compare(NETWORK_TYPE) == 0)
{
m_networkType = static_cast<NetworkType>(strtol(propertyValue.c_str(), nullptr, 10));
@ -114,7 +114,7 @@ void DeviceStateHandler::OnChanged(
void DeviceStateHandler::_UpdateDeviceCondition()
{
#ifdef _WIN32
if (m_networkInformation != nullptr)
if (m_networkInformation)
{
m_networkType = m_networkInformation->GetNetworkType();
m_networkCost = m_networkInformation->GetNetworkCost();
@ -124,7 +124,7 @@ void DeviceStateHandler::OnChanged(
m_networkCost = NetworkCost_Unknown;
}
if (m_deviceInformation != nullptr)
if (m_deviceInformation)
{
m_powerSource = m_deviceInformation->GetPowerSource();
}
@ -141,6 +141,5 @@ void DeviceStateHandler::OnChanged(
//do we need to stop current timer?? and restart
}
} ARIASDK_NS_END
} ARIASDK_NS_END

Просмотреть файл

@ -11,10 +11,9 @@
#include <map>
#include <string>
namespace ARIASDK_NS_BEGIN {
class DeviceStateHandler
class DeviceStateHandler
: public PAL::IPropertyChangedCallback
{
public:
@ -23,7 +22,7 @@ public:
// Callback functions
// IPropertyChangedCallback::OnChanged from platform on any connectivity, power, device system changes
virtual void OnChanged(std::string const& propertyName, std::string const& propertyValue) override;
void OnChanged(std::string const& propertyName, std::string const& propertyValue) override;
protected:
NetworkType m_networkType;
@ -33,13 +32,13 @@ protected:
virtual void _UpdateDeviceCondition();
private:
// Platform network, power, device info changes
PAL::INetworkInformation *m_networkInformation;
int m_networkInformationToken;
PAL::IDeviceInformation *m_deviceInformation;
int m_deviceInformationToken;
// Platform network, power, device info changes
std::shared_ptr<PAL::INetworkInformation> m_networkInformation;
int m_networkInformationToken;
std::shared_ptr<PAL::IDeviceInformation> m_deviceInformation;
int m_deviceInformationToken;
};

Просмотреть файл

@ -21,7 +21,7 @@ using nlohmann::json;
/// <summary>
/// Default JSON config for Transmit Profiles
/// </summary>
static string defaultProfiles = R"(
static const char* const defaultProfiles = R"(
[{
"name": "REAL_TIME",
"rules": [
@ -219,6 +219,49 @@ namespace ARIASDK_NS_BEGIN {
}
}
void TransmitProfiles::UpdateProfiles(const std::vector<TransmitProfileRules>& newProfiles) noexcept
{
{
LOCK_PROFILES;
removeCustomProfiles();
// Add new profiles
for (const auto& profile : newProfiles)
{
profiles[profile.name] = profile;
}
// Check if profile is still valid. If no such profile loaded anymore, then switch to default.
auto it = profiles.find(currProfileName);
if (it == profiles.end())
{
currProfileName = DEFAULT_PROFILE;
LOG_TRACE("Switched to profile %s", currProfileName.c_str());
}
#ifdef HAVE_MAT_LOGGING
// Print combined list of profiles: default + custom
LOG_TRACE("Profiles:");
size_t i = 0;
for (const auto& kv : profiles)
{
LOG_TRACE("[%d] %s%s", i, kv.first.c_str(),
(!kv.first.compare(currProfileName)) ? " [active]" : "");
i++;
}
#endif
currRule = 0;
} // Unlock here because updateStates performs its own LOCK_PROFILES
updateStates(currNetCost, currPowState);
}
void TransmitProfiles::EnsureDefaultProfiles() noexcept
{
if (profiles.size() == 0)
{
LOG_TRACE("Loading default profiles...");
reset();
}
}
/// <summary>
/// Parse JSON configration describing transmit profiles
/// </summary>
@ -318,36 +361,7 @@ namespace ARIASDK_NS_BEGIN {
}
numProfilesParsed = newProfiles.size();
{
LOCK_PROFILES;
removeCustomProfiles();
// Add new profiles
for (const auto& profile : newProfiles) {
profiles[profile.name] = profile;
}
// Check if profile is still valid. If no such profile loaded anymore, then switch to default.
auto it = profiles.find(currProfileName);
if (it == profiles.end()) {
currProfileName = DEFAULT_PROFILE;
LOG_TRACE("Switched to profile %s", currProfileName.c_str());
}
#ifdef HAVE_MAT_LOGGING
// Print combined list of profiles: default + custom
LOG_TRACE("Profiles:");
size_t i = 0;
for (const auto &kv : profiles) {
LOG_TRACE("[%d] %s%s", i, kv.first.c_str(),
(!kv.first.compare(currProfileName)) ?
" [active]" : ""
);
i++;
}
#endif
currRule = 0;
} // Unlock here because updateStates performs its own LOCK_PROFILES
updateStates(currNetCost, currPowState);
UpdateProfiles(newProfiles);
LOG_INFO("JSON parsing completed successfully [%d]", numProfilesParsed);
@ -364,10 +378,7 @@ namespace ARIASDK_NS_BEGIN {
/// <param name="profiles_json"></param>
/// <returns></returns>
bool TransmitProfiles::load(const std::string& profiles_json) {
if (!profiles.size()) {
LOG_TRACE("Loading default profiles...");
reset();
}
EnsureDefaultProfiles();
// Check if custom profile is valid
LOG_TRACE("Loading custom profiles...");
bool result = (parse(profiles_json) != 0);
@ -376,6 +387,51 @@ namespace ARIASDK_NS_BEGIN {
return result;
}
/// <summary>
/// Load customer supplied transmit profiles
/// </summary>
/// <param name="profiles"></param>
/// <returns></returns>
bool TransmitProfiles::load(const std::vector<TransmitProfileRules>& profileCandidates) noexcept
{
EnsureDefaultProfiles();
LOG_TRACE("Loading custom profiles...");
if (profileCandidates.size() > MAX_TRANSMIT_PROFILES)
{
LOG_ERROR("Exceeded max transmit profiles %d>%d.", profileCandidates.size(), MAX_TRANSMIT_PROFILES);
return false;
}
for (const auto& profile : profileCandidates)
{
const auto ruleCount = profile.rules.size();
if (ruleCount > MAX_TRANSMIT_RULES)
{
LOG_ERROR("Exceeded max transmit rules %d>%d for profile", ruleCount, MAX_TRANSMIT_RULES);
return false;
}
else if (ruleCount == 0)
{
LOG_ERROR("Profile must have at least one rule");
return false;
}
for (const auto& rule : profile.rules)
{
if (rule.timers.size() != 3)
{
LOG_ERROR("Rule must have three timer values.");
return false;
}
}
}
UpdateProfiles(profileCandidates);
dump();
return true;
}
/// <summary>
/// Reset transmit profiles to defaults.
/// </summary>

Просмотреть файл

@ -49,17 +49,17 @@ namespace PAL_NS_BEGIN
return PAL::GetPAL().m_taskDispatcher;
};
static ISystemInformation* GetSystemInformation()
static std::shared_ptr<ISystemInformation> GetSystemInformation()
{
return PAL::GetPAL().m_SystemInformation;
}
static INetworkInformation* GetNetworkInformation()
static std::shared_ptr<INetworkInformation> GetNetworkInformation()
{
return PAL::GetPAL().m_NetworkInformation;
}
static IDeviceInformation* GetDeviceInformation()
static std::shared_ptr<IDeviceInformation> GetDeviceInformation()
{
return PAL::GetPAL().m_DeviceInformation;
}
@ -1038,7 +1038,7 @@ public :
numHttpError(0),
numHttpOK(0),
numHttpFailure(0),
numCached(0)
numCached(0)
{
}
@ -1192,7 +1192,7 @@ TEST_F(BasicFuncTests, killSwitchWorks)
server.clearKilledTokens();
}
TEST_F(BasicFuncTests, killIsTemporary)
TEST_F(BasicFuncTests, killIsTemporary)
{
CleanStorage();
// Create the configuration to send to fake server
@ -1212,7 +1212,7 @@ TEST_F(BasicFuncTests, killIsTemporary)
configuration["name"] = __FILE__;
configuration["version"] = "1.0.0";
configuration["config"] = { { "host", __FILE__ } }; // Host instance
// set the killed token on the server
server.setKilledToken(KILLED_TOKEN, 10);
KillSwitchListener listener;

Просмотреть файл

@ -72,9 +72,24 @@ else()
message("--- Linking libraries! ")
message("Current Dir: ${CMAKE_CURRENT_SOURCE_DIR}")
message("Binary Dir: ${CMAKE_BINARY_DIR}")
find_file(LIBGTEST
NAMES libgtest.a
PATHS
${CMAKE_CURRENT_SOURCE_DIR}/../../googletest/build/googlemock/gtest/
${CMAKE_CURRENT_SOURCE_DIR}/../../googletest/build/lib/
)
find_file(LIBGMOCK
NAMES libgmock.a
PATHS
${CMAKE_CURRENT_SOURCE_DIR}/../../googletest/build/googlemock/
${CMAKE_CURRENT_SOURCE_DIR}/../../googletest/build/lib/
)
target_link_libraries(FuncTests
${CMAKE_CURRENT_SOURCE_DIR}/../../googletest/build/googlemock/gtest/libgtest.a
${CMAKE_CURRENT_SOURCE_DIR}/../../googletest/build/googlemock/libgmock.a
${LIBGTEST}
${LIBGMOCK}
mat
${ZLIB_LIBRARIES}
${SQLITE3_LIB}

Просмотреть файл

@ -37,6 +37,7 @@ set(SRCS
StringUtilsTests.cpp
TaskDispatcherCAPITests.cpp
TransmissionPolicyManagerTests.cpp
TransmitProfilesTests.cpp
UtilsTests.cpp
)
@ -102,9 +103,23 @@ else()
include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/ )
find_file(LIBGTEST
NAMES libgtest.a
PATHS
${CMAKE_CURRENT_SOURCE_DIR}/../../googletest/build/googlemock/gtest/
${CMAKE_CURRENT_SOURCE_DIR}/../../googletest/build/lib/
)
find_file(LIBGMOCK
NAMES libgmock.a
PATHS
${CMAKE_CURRENT_SOURCE_DIR}/../../googletest/build/googlemock/
${CMAKE_CURRENT_SOURCE_DIR}/../../googletest/build/lib/
)
target_link_libraries(UnitTests
${CMAKE_CURRENT_SOURCE_DIR}/../../googletest/build/googlemock/gtest/libgtest.a
${CMAKE_CURRENT_SOURCE_DIR}/../../googletest/build/googlemock/libgmock.a
${LIBGTEST}
${LIBGMOCK}
mat
${ZLIB_LIBRARIES}
${SQLITE3_LIB}

Просмотреть файл

@ -0,0 +1,206 @@
// Copyright (c) Microsoft. All rights reserved.
#include "common/Common.hpp"
#include <TransmitProfiles.hpp>
using namespace testing;
using namespace MAT;
class TransmitProfilesTests : public TransmitProfiles, public ::testing::Test
{
virtual void SetUp() override
{
TransmitProfiles::profiles.clear();
}
virtual void TearDown() override
{
TransmitProfiles::profiles.clear();
}
};
TEST_F(TransmitProfilesTests, EnsureDefaultProfiles_NeverCalledBefore_ProfilesSizeIsThree)
{
ASSERT_EQ(TransmitProfiles::profiles.size(), size_t{0});
TransmitProfiles::EnsureDefaultProfiles();
ASSERT_EQ(TransmitProfiles::profiles.size(), size_t{3});
}
TEST_F(TransmitProfilesTests, EnsureDefaultProfiles_CalledTwice_ProfilesSizeIsThree)
{
ASSERT_EQ(TransmitProfiles::profiles.size(), size_t{0});
TransmitProfiles::EnsureDefaultProfiles();
TransmitProfiles::EnsureDefaultProfiles();
ASSERT_EQ(TransmitProfiles::profiles.size(), size_t{3});
}
TEST_F(TransmitProfilesTests, UpdateProfiles_ProfileAlreadyAddedAndNotInNewProfiles_PreviousCustomProfilesRemoved)
{
const std::string previousRuleName = "previousRule";
TransmitProfileRules previousRule{previousRuleName, {}};
TransmitProfiles::profiles[previousRuleName] = previousRule;
TransmitProfiles::UpdateProfiles(std::vector<TransmitProfileRules>{});
ASSERT_TRUE(TransmitProfiles::profiles.find(previousRuleName) == TransmitProfiles::profiles.end());
}
TEST_F(TransmitProfilesTests, UpdateProfiles_NewRule_NewRuleAddedToProfiles)
{
const std::string newRuleName = "newRule";
TransmitProfileRules newRule{newRuleName, {}};
TransmitProfiles::UpdateProfiles(std::vector<TransmitProfileRules>{newRule});
ASSERT_TRUE(TransmitProfiles::profiles.find(newRuleName) != TransmitProfiles::profiles.end());
}
TEST_F(TransmitProfilesTests, UpdateProfiles_OldCurrentProfileDoesntExistInNewRules_SetCurrentProfileToDefault)
{
TransmitProfiles::currProfileName = std::string{"newRule"};
TransmitProfiles::UpdateProfiles(std::vector<TransmitProfileRules>{});
ASSERT_EQ(TransmitProfiles::currProfileName, std::string{"REAL_TIME"});
}
TEST_F(TransmitProfilesTests, UpdateProfiles_OldCurrentProfileExistsInNewRules_CurrentProfileNotChanged)
{
const std::string newRuleName = "newRule";
TransmitProfiles::currProfileName = newRuleName;
TransmitProfileRule rule;
rule.timers = {1, 2, 3};
TransmitProfileRules newRule{newRuleName, {rule}};
TransmitProfiles::UpdateProfiles(std::vector<TransmitProfileRules>{newRule});
ASSERT_EQ(TransmitProfiles::currProfileName, newRuleName);
}
TEST_F(TransmitProfilesTests, load_VectorIsLargerThanMaxTransmitProfiles_ReturnsFalseAndSizeThree)
{
std::vector<TransmitProfileRules> newProfiles{MAX_TRANSMIT_PROFILES + 1};
ASSERT_FALSE(TransmitProfiles::load(newProfiles));
ASSERT_EQ(TransmitProfiles::profiles.size(), 3);
}
TEST_F(TransmitProfilesTests, load_OneProfileTooManyRules_ReturnsFalseAndSizeThree)
{
TransmitProfileRules profile;
profile.rules = std::vector<TransmitProfileRule>{MAX_TRANSMIT_RULES + 1};
std::vector<TransmitProfileRules> newProfiles{profile};
ASSERT_FALSE(TransmitProfiles::load(newProfiles));
ASSERT_EQ(TransmitProfiles::profiles.size(), 3);
}
TEST_F(TransmitProfilesTests, load_OneProfileNoRules_ReturnsFalseAndSizeThree)
{
TransmitProfileRules profile{"testProfile", { }};
std::vector<TransmitProfileRules> newProfiles{profile};
ASSERT_FALSE(TransmitProfiles::load(newProfiles));
ASSERT_EQ(TransmitProfiles::profiles.size(), 3);
}
TEST_F(TransmitProfilesTests, load_OneProfileOneRuleNoTimers_ReturnsFalseAndSizeThree)
{
TransmitProfileRule rule;
TransmitProfileRules profile{"testProfile", { rule }};
std::vector<TransmitProfileRules> newProfiles{profile};
ASSERT_FALSE(TransmitProfiles::load(newProfiles));
ASSERT_EQ(TransmitProfiles::profiles.size(), 3);
}
TEST_F(TransmitProfilesTests, load_OneRule_ReturnsTrueAndSizeFour)
{
TransmitProfileRule rule;
rule.timers = std::vector<int>{1, 2, 3};
TransmitProfileRules profile{"testProfile", { rule }};
std::vector<TransmitProfileRules> newProfiles{profile};
ASSERT_TRUE(TransmitProfiles::load(newProfiles));
ASSERT_EQ(TransmitProfiles::profiles.size(), 4);
}
TEST_F(TransmitProfilesTests, load_Json_EmptyJsonArray_FailsToParse)
{
const std::string badRule = R"([])";
ASSERT_FALSE(TransmitProfiles::load(badRule));
}
TEST_F(TransmitProfilesTests, load_Json_JsonArrayContainsOneEmtpyObject_FailsToParse)
{
const std::string badRule = R"([{ }])";
ASSERT_FALSE(TransmitProfiles::load(badRule));
}
TEST_F(TransmitProfilesTests, load_Json_OneValidAndOneInvalidRule_ReturnsTrue)
{
const std::string badRule =
R"([{
"name": "GoodRule",
"rules": [
{ "netCost": "restricted", "timers": [ -1, -1, -1 ] }
]
},
{
}])";
ASSERT_TRUE(TransmitProfiles::load(badRule));
}
/*
The following tests probably should not pass.
But they do.
Right now these are useful as pinning tests.
*/
TEST_F(TransmitProfilesTests, load_Json_ProfileWithInvalidTimers_ReturnsTrue)
{
const std::string badRule =
R"([{
"name": "EmptyTimersArrayRule",
"rules": [
{ "timers": [ "a", "b", "c" ] }
]
}])";
ASSERT_TRUE(TransmitProfiles::load(badRule));
}
TEST_F(TransmitProfilesTests, load_Json_ProfileWithEmptyTimerArray_ReturnsTrue)
{
const std::string badRule =
R"([{
"name": "EmptyTimersArrayRule",
"rules": [
{ "timers": [ ] }
]
}])";
ASSERT_TRUE(TransmitProfiles::load(badRule));
}
TEST_F(TransmitProfilesTests, load_Json_RuleWithoutTimers_ReturnsTrue)
{
const std::string badRule =
R"([{
"name": "EmptyRule",
"rules": [
{ }
]
}])";
ASSERT_TRUE(TransmitProfiles::load(badRule));
}
TEST_F(TransmitProfilesTests, load_Json_EmptyRulesArray_ReturnsTrue)
{
const std::string badRule =
R"([{
"name": "EmptyRule",
"rules": [
]
}])";
ASSERT_TRUE(TransmitProfiles::load(badRule));
}
TEST_F(TransmitProfilesTests, load_Json_ProfileWithoutRules_ReturnsTrue)
{
const std::string badRule =
R"([{
"name": "EmptyRule"
}])";
ASSERT_TRUE(TransmitProfiles::load(badRule));
}

Просмотреть файл

@ -455,6 +455,7 @@
<ClCompile Include="$(ProjectDir)\StringUtilsTests.cpp" />
<ClCompile Include="$(ProjectDir)\TaskDispatcherCAPITests.cpp" />
<ClCompile Include="$(ProjectDir)\TransmissionPolicyManagerTests.cpp" />
<ClCompile Include="$(ProjectDir)\TransmitProfilesTests.cpp" />
<ClCompile Include="$(ProjectDir)\UtilsTests.cpp" />
<ClInclude Include="$(ProjectDir)..\common\Common.hpp" />
<ClInclude Include="$(ProjectDir)..\common\HttpServer.hpp" />

Просмотреть файл

@ -34,6 +34,7 @@
<ClCompile Include="$(ProjectDir)\StringUtilsTests.cpp" />
<ClCompile Include="$(ProjectDir)\TaskDispatcherCAPITests.cpp" />
<ClCompile Include="$(ProjectDir)\TransmissionPolicyManagerTests.cpp" />
<ClCompile Include="$(ProjectDir)\TransmitProfilesTests.cpp" />
<ClCompile Include="$(ProjectDir)\UtilsTests.cpp" />
<ClCompile Include="$(ProjectDir)..\common\Common.cpp">
<Filter>common</Filter>

1
third_party/krabsetw поставляемый Submodule

@ -0,0 +1 @@
Subproject commit 5dc8b9c3f6d34d3f1e2a770398863541e508b848

15
tools/build-krabsetw.cmd Normal file
Просмотреть файл

@ -0,0 +1,15 @@
@echo off
echo Building KrabsETW (test only and debug tool dependency)...
@setlocal ENABLEEXTENSIONS
set ROOT=%~dp0\..
echo Using Visual Studio 2019 tools...
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\VsDevCmd.bat"
set MAXCPUCOUNT=%NUMBER_OF_PROCESSORS%
set platform=
set SOLUTION=%ROOT%\third_party\krabsetw\krabs\krabs.sln
msbuild %SOLUTION% /maxcpucount:%MAXCPUCOUNT% /p:Configuration=Debug /p:Platform=x64
msbuild %SOLUTION% /maxcpucount:%MAXCPUCOUNT% /p:Configuration=Release /p:Platform=x64

Просмотреть файл

@ -31,6 +31,7 @@ namespace OneDSInspector
using Bond;
using Bond.Protocols;
using Bond.IO.Safe;
using Fiddler.WebFormats;
public class EventInspector : Inspector2, IRequestInspector2
{
@ -201,11 +202,11 @@ namespace OneDSInspector
String[] headerKeyAndValue = header.Split('=');
if (headerKeyAndValue.Length == 2)
{
if (headerKeyAndValue[0].Equals("client-id"))
if (headerKeyAndValue[0].Equals("client-id", StringComparison.OrdinalIgnoreCase))
{
this.ClientId = headerKeyAndValue[1];
}
else if (headerKeyAndValue[0].Equals("content-type"))
else if (headerKeyAndValue[0].Equals("content-type", StringComparison.OrdinalIgnoreCase))
{
this.ContentType = Uri.UnescapeDataString(headerKeyAndValue[1]);
}
@ -276,9 +277,16 @@ namespace OneDSInspector
outputBuffer.SetLength(0);
} while (true);
}
catch (Exception)
catch (EndOfStreamException)
{
// end of input
// That's OK, we no longer have anything to decode.
}
catch (Exception ex)
{
// Decoding failed: show the message in decoder
jsonList.Add(ex.Message);
jsonList.Add(ex.StackTrace);
return jsonList;
}
// consider sending jsonList one-by-one over UDP to remote monitor
@ -307,9 +315,13 @@ namespace OneDSInspector
json = JToken.Parse(json).ToString(Formatting.Indented);
}
}
catch (Exception)
catch (Exception ex)
{
// ignore invalid JSON contents here
// Failed to parse JSON for indented view:
// Well, something went wrong...
// Uncheck the pretty-printing checkbox.
json = ex.Message;
json += ex.StackTrace;
}
return json.Split(new string[] { Environment.NewLine }, StringSplitOptions.None).ToList();
}

Просмотреть файл

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<generatePublisherEvidence enabled="false"/>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="11.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<appSettings>
<add key="EnableWindowsFormsHighDpiAutoResizing" value="true" />
</appSettings>
</configuration>

Просмотреть файл

@ -0,0 +1,52 @@
# 1DS Bond Inspector for Fiddler
This is 1DS Common Schema / Bond decoder for Fiddler.
Please build and deploy to *%LOCALAPPDATA%\Programs\Fiddler\Inspectors*
# How to use
- download and install Fiddler
- make sure SSL decoding is enabled (Collector uses TLS 1.2+)
- ingest some 1DS test traffic from a test app, e.g. EventSender example
- navigate to the list of HTTP requests
- filter by your collector end-point or your test app name
- click on collector HTTP request of interest
- click on *Inspectors* tab -> *1DS Events* tab
- enjoy an event decoded from Bond to human-readable JSON
- copy-paste JSON to pretty-print, OR
- use the built-in indented format
# Fiddler.exe.config
You may occasionally encounter a `Newtonsoft.JSON` assembly loading issue with a specific version of Newtonsoft/Fiddler.
If and when that happens - 1DS inspector should show an exception in the decoded output window.
This could happen when a more recent Fiddler is installed with a version of Newtonsoft that differs from the one used by 1DS Bond Inspector plugin.
Exit Fiddler first.
Then use the Binding Redirect feature as follows in *Fiddler.exe.config* to redirect to the currently deployed version:
```
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<generatePublisherEvidence enabled="false"/>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="11.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<appSettings>
<add key="EnableWindowsFormsHighDpiAutoResizing" value="true" />
</appSettings>
</configuration>
```
In example above - we redirected the Newtonsoft.Json assembly version from 0-12 to 11 used by Fiddler.
Please make sure you redirect to version employed by your Fiddler installation.
Place this file above (Fiddler.exe.config) to %LOCALAPPDATA%\Programs\Fiddler\ next to Fiddler.exe
Then restart Fiddler.exe . This should solve the Newtonsoft loading issue.
Happy Fiddling!

Просмотреть файл

@ -4,7 +4,7 @@
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="11.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>

Просмотреть файл

@ -26,6 +26,6 @@ cd $SQLITE_PKG
cd ..
## Build Google Test framework
./build-gtest.sh
./build-gtest.sh $1
## Install dotnet for test server

1
tools/vcpkg Submodule

@ -0,0 +1 @@
Subproject commit 7db401cb1ef1fc559ec9f9ce814d064c328fd767

Просмотреть файл

@ -1,4 +1,5 @@
#include "objc_begin.h"
#import "ODWLogger.h"
NS_ASSUME_NONNULL_BEGIN
@ -22,7 +23,7 @@ NS_ASSUME_NONNULL_BEGIN
@param tenantToken A string that contains the tenant token.
@return An ODWLogger instance
*/
+(nullable id)loggerWithTenant:(NSString *)tenantToken;
+(nullable ODWLogger *)loggerWithTenant:(NSString *)tenantToken;
/*!
@brief Initializes the telemetry logging system with the default configuration, using the specified tenant token and source.
@ -30,7 +31,7 @@ NS_ASSUME_NONNULL_BEGIN
@param source A string that contains the name of the source of events.
@return An ODWLogger pointer that points to the logger for the specified tenantToken and source.
*/
+(nullable id)loggerWithTenant:(NSString *)tenantToken
+(nullable ODWLogger *)loggerWithTenant:(NSString *)tenantToken
source:(NSString *)source;
/*!
@ -38,7 +39,7 @@ NS_ASSUME_NONNULL_BEGIN
@param source A string that contains the name of the source of events sent by this logger instance.
@return An ODWLogger instance that points to the logger for source.
*/
+(nullable id)loggerForSource:(NSString *)source;
+(nullable ODWLogger *)loggerForSource:(NSString *)source;
/*!
@brief Attempts to send any pending telemetry events that are currently cached either in memory, or on disk. Use this method if your event can't wait for automatic timed upload

Просмотреть файл

@ -10,29 +10,32 @@ LOGMANAGER_INSTANCE
@implementation ODWLogManager
+(nullable id)loggerWithTenant:(nonnull NSString *)tenantToken
+(nullable ODWLogger *)loggerWithTenant:(nonnull NSString *)tenantToken
{
ILogger* logger = [ODWLogManager initializeLogManager:tenantToken];
if(!logger) return nil;
return [[ODWLogger alloc] initWithILogger: logger];
return [ODWLogManager loggerWithTenant:tenantToken source:@""];
}
+(nullable id)loggerWithTenant:(nonnull NSString *)tenantToken
+(nullable ODWLogger *)loggerWithTenant:(nonnull NSString *)tenantToken
source:(nonnull NSString *)source
{
ILogger* logger = [ODWLogManager initializeLogManager:tenantToken];
if(!logger) return nil;
static const BOOL initialized = [ODWLogManager initializeLogManager:tenantToken];
if(!initialized) return nil;
std::string strToken = std::string([tenantToken UTF8String]);
std::string strSource = std::string([source UTF8String]);
logger = LogManager::GetLogger(strToken, strSource);
ILogger* logger = LogManager::GetLogger(strToken, strSource);
if(!logger) return nil;
return [[ODWLogger alloc] initWithILogger: logger];
}
+(ILogger *)initializeLogManager:(nonnull NSString *)tenantToken
+(BOOL)initializeLogManager:(nonnull NSString *)tenantToken
{
// Turn off statistics
auto& config = LogManager::GetLogConfiguration();
config["stats"]["interval"] = 0;
// Initialize SDK Log Manager
std::string strToken = std::string([tenantToken UTF8String]);
ILogger* logger = LogManager::Initialize(strToken);
@ -61,10 +64,10 @@ LOGMANAGER_INSTANCE
semanticContext->SetAppLanguage(strBundleLocale);
semanticContext->SetUserLanguage(strUserLocale);
return logger;
return logger != NULL;
}
+(nullable id)loggerForSource:(nonnull NSString *)source
+(nullable ODWLogger *)loggerForSource:(nonnull NSString *)source
{
std::string strSource = std::string([source UTF8String]);
ILogger* logger = LogManager::GetLogger(strSource);

Просмотреть файл

@ -6,7 +6,9 @@
using namespace MAT;
@implementation ODWLogger
{
ILogger* _wrappedLogger;
}
-(instancetype)initWithILogger:(ILogger*)logger
{