Friday, September 6, 2013

RxC++ ReactiveCommand

I rewrote the ReactiveCommand class (from Paul Betts ReactiveUI library for C#) to demonstrate how to bind async commands to Xaml Buttons. This is a work in progress (it does not use data binding yet, is missing some error handling and there is no reason that it should be specific to the Xaml UI framework - should work with WIN32 button etc..), but I did build it for use in this Windows 8.1 sample.

ReactiveCommand models calls to the Execute function as a Sequence of the value passed to each Execute. All subscriptions to it are called on the UI thread. There can be many subscriptions directly to ReactiveCommand, there can also be many async functions registered.

Each async function registered takes the value passed to Execute does work and returns a result. Each call to RegisterAsyncCommand returns a new Sequence of the results from each call to the registered function. All subscriptions to the Sequence of results are called on the UI thread.

ReactiveCommand also provides Sequences of bools, that can be subscribed, that represent its state. When the CanExecute Sequence is bound to the enabled property of the button the state of the ReactiveCommand is communicated into the ui.

By default ReactiveCommand will ignore Execute until all the subscribers (sync and async) to the previous Execute call have finished. This can be changed during construction.

Here is some (out-of-order) usage from the sample.

Subscription - async version (Scenario1.Xaml.cpp):

Subscription - sync version (Scenario1.Xaml.cpp):

Binding (Scenario1.Xaml.cpp):

Creation (Scenario1.Xaml.cpp):

Create state sequences that are used by these ReactiveCommand (Scenario1.Xaml.cpp):

Thursday, September 5, 2013

DeferOperation

I have been working on RxC++ for a few months now. I have added Schedulers and lots of operators. Now I am trying to apply Rx to a C++ Windows Store app.

I was told that Deferrals did not compose well with Rx. This motivated me to design the DeferOperation operator.

DeferOperation demonstrates how Rx can be extended by a few engineers to provide services for many. Another way to say this is that Rx allows Async Algorithms to be written once, carefully, so that many others can re-use them.


These are all references to the Windows 8.1 Accelerometer sample I am modifying.

Usage (App.Xaml.Cpp):

DeferOperation defaults to the ui thread by reading the context off of the Window, but when the suspending event is fired the Window is not valid, so this uses the current thread scheduler explicitly. publish and connect_forever ensure that the work is done even if nothing subscribes the result.


The implementation follows.

The core of the DeferOperation operator is (cpprx/rx-winrt.hpp):

sop is the first lambda from the usage (cpprx/rx-winrt.hpp):

sob is the second lambda from the usage (the OperationPattern is passed so that the SuspendingOperation and the Deferral are available to the sequence if it wants to see the Deadline or Complete early, for example) (cpprx/rx-winrt.hpp)
Using will retrieve the resource (OperationPattern), subscribe to the result of sob and Dispose the resource when the subscription completes or errors.

OperationPattern provides the abstraction needed by Using. It will call get and complete the deferral (cpprx/rx-winrt.hpp):
 

Friday, August 30, 2013

Reactive Extensions for C++

I get excited when I can compose asynchronous code without using thread or lock API's

A C++/CX Windows 8.1 sample app that demonstrates using the accelerometer.

Now see it transformed using Rx++
https://github.com/kirkshoop/rxaccelerometer

Examples 

Create a ReactiveCommand and bind it to a Xaml button


Transform SaveAsync method to ReactiveSave

Introduction to Rx
Reactive Extensions Rx were born as a transformation of LINQ expressions which pull from a data source through a set of operators into an Rx expression where the data source pushes through a set of operators.

Personally, I recognized them as the generalization I wanted to make of a pattern I had popularized in a previous project. We called them Sender/Receiver, Rx calls them Observable/Observer

Observable and Observer
An Observable is a source of data. An Observer operates on data as the source provides it. An Observer connects to an Observable by Subscribing to it. Many Observers can connect to the same Observable. 

A Subject is both an Observable and an Observer and will pass the data sent to the Observable on to each of the Observers that are Subscribed to the Observable.

An Operator is a function that takes at least one Observable argument and returns a new Observable.

Web Resources
There is a lot of information about Rx. Most of the information is focused on the .Net version as that came first. More recently there have been other versions built.

A partial list of Rx implementations:
Aaron Lahmann, a friend (and one-time co-worker in the team where I was working on Sender/Receiver) wrote Rx++ and was talking to me about it at the time. I still did not know enough about it to jump on it at the time.


Eventually, I saw an article by Jafar Husain that linked to an RxJS tutorial that got me excited. I highly recommend taking the time to follow through the examples.


Saturday, May 12, 2012

ZeroMQ and C++ without exceptions

my comment in reply to martin_sustrik.

I wanted to post some code into the comment but I finally gave up. I will post it here instead. Disclaimer: this code has not been compiled.

class foo
{
public:
  ~foo() {}
  foo(foo&& other) {
    guts.a = std::move(other.a); // no-fail
  }
  foo& operator=(foo other) { // no-fail
    using std::swap; 
    swap(guts.a, other.guts.a); 
    return *this;
  } 
  static optional<foo> init() {
    optional<foo> result; 
    type guts = {}; // ~type() cleans up on exit
    guts.a.reset(new(std::nothrow) int(5));
    if (!guts.a) {return result;} // no foo constructed 
    result.reset(foo(guts)); //no-fail move construction
    return std::move(result); // no-fail move of result
  }
  int do() {return guts.a.get();} // a cannot be empty
private:
  struct type { std::unique_ptr<int> a; };
  type guts;
  foo(); // disabled
  foo(const foo&); // disabled
  foo(type&& gutsArg) {guts.a = std::move(gutsArg.a);} // no-fail
};

auto MyFoo = foo::init();
if (!MyFoo) return;
MyFoo->do();

if you want to return a detailed error from init() change init() to return a tuple:

  static std::tuple<error, optional<foo>> init();
and use tie to break the result into local vars:
  optional<foo> MyFoo;
  error MyError;
  std::tie(MyError, MyFoo) = foo::init();

Tuesday, April 17, 2012

console app that monitors smart cards

Here is a console app that demonstrates how to tie the smart card functions already covered into a working monitor that prints reader state changes and the certs and subject names for the cards that are present.

#pragma once

// Exclude rarely-used stuff from
// Windows headers
#define WIN32_LEAN_AND_MEAN
// skip min/max macros from
// Windows Headers
#define NOMINMAX
// Windows Header Files:
#include <windows.h>
#include <Unknwn.h>
#include <winscard.h>
#include <ncrypt.h>
#include <Wincrypt.h>
#include <credentialprovider.h>

// C++ library header files:
#include <type_traits>
#include <algorithm>
#include <new>
#include <memory>
#include <utility>
#include <limits>
#include <iterator>
#include <thread>
#include <future>
#include <mutex>
#include <vector>
#include <iostream>
#include <iomanip>

// local header files:
#define LIBRARIES_NAMESPACE nslib
#include <libraries.h>
namespace lib = LIBRARIES_NAMESPACE;

#include "..\win32project1\scard_monitor.h"

Set a breakpoint in each of these functions and see where error codes first make an appearance in this module. the static anchor is a device to make sure that the compiler does not eliminate or fold them together.

void unique_error_report_initiated(
  HRESULT value, 
  unique_hresult_def::tag &&)
{
  static HRESULT anchor;
  anchor = value;
}

void unique_error_report_reset(
  HRESULT value, 
  unique_hresult_def::tag &&)
{
  static HRESULT anchor;
  anchor = value;
}

void unique_error_report_initiated(
  DWORD value, 
  unique_winerror_def::tag &&)
{
  static DWORD anchor;
  anchor = value;
}

void unique_error_report_reset(
  DWORD value, 
  unique_winerror_def::tag &&)
{
  static DWORD anchor;
  anchor = value;
}

Helper functions to print status and certificate properties.

template<typename Certificate>
void printCertificates(
  lib::rng::range<Certificate> certificates)
{
  for (auto & key : certificates) {
    unique_winerror winerror;

    PCCERT_CONTEXT certcontext = (
      CertCreateCertificateContext(
        X509_ASN_ENCODING | 
          PKCS_7_ASN_ENCODING,
        &key.cert[0],
        key.cert.size()
      )
    );
    winerror = make_winerror_if(!certcontext);

    if (!winerror) {
      std::wcout 
        << L"could not get cert context" 
        << std::endl;
      continue;
    }

    DWORD sizesubject = 0;
    std::wstring subjectname;
    for (bool getsize = true; ; getsize = false) {
      sizesubject = CertGetNameString(
        certcontext,
        CERT_NAME_FRIENDLY_DISPLAY_TYPE,
        0,
        NULL,
        getsize ? nullptr : &subjectname[0],
        sizesubject
      );
      if (sizesubject == 1) {
        std::wcout 
          << L"could not get subject name" 
          << std::endl;
        break;
      }
      if (getsize) {
        subjectname.resize(sizesubject - 1);
      } else {
        std::wcout 
          << L"key name: " << key.key.c_str() 
          << L" subject name: " << subjectname.c_str() 
          << std::endl;
        break;
      }
    }
  }
}

template<typename Stream>
Stream& printSCardState(Stream& stream, DWORD state)
{
  stream
    << ((state == SCARD_STATE_UNAWARE)  ? 
      L" SCARD_STATE_UNAWARE" : L"")
    << ((state & SCARD_STATE_PRESENT)  ? 
      L" SCARD_STATE_PRESENT" : L"")
    << ((state & SCARD_STATE_ATRMATCH)  ? 
      L" SCARD_STATE_ATRMATCH" : L"")
    << ((state & SCARD_STATE_CHANGED)  ? 
      L" SCARD_STATE_CHANGED" : L"")
    << ((state & SCARD_STATE_EMPTY)  ? 
      L" SCARD_STATE_EMPTY" : L"")
    << ((state & SCARD_STATE_EXCLUSIVE)  ? 
      L" SCARD_STATE_EXCLUSIVE" : L"")
    << ((state & SCARD_STATE_IGNORE)  ? 
      L" SCARD_STATE_IGNORE" : L"")
    << ((state & SCARD_STATE_INUSE)  ? 
      L" SCARD_STATE_INUSE" : L"")
    << ((state & SCARD_STATE_MUTE)  ? 
      L" SCARD_STATE_MUTE" : L"")
    << ((state & SCARD_STATE_UNAVAILABLE)  ? 
      L" SCARD_STATE_UNAVAILABLE" : L"")
    << ((state & SCARD_STATE_UNKNOWN)  ? 
      L" SCARD_STATE_UNKNOWN" : L"")
    << ((state & SCARD_STATE_UNPOWERED)  ? 
      L" SCARD_STATE_UNPOWERED" : L"")
  ;
  return stream;
}

int wmain(int argc, WCHAR* argv[])
{
  unique_winerror winerror;
  for (;;) {
    SCARDCONTEXT context = NULL;

    HANDLE waitfor[] = {SCardAccessStartedEvent()};
    ON_UNWIND_AUTO([] {SCardReleaseStartedEvent();});

    winerror = smart_card::monitor_smartcard_readers(
      [&](SCARDCONTEXT context) {
        context = context;
      },
      [&]() {
        context = NULL;
      },
      [&]() -> bool {
        if (WAIT_OBJECT_0 != WaitForMultipleObjects(
          lib::rng::size(waitfor), 
          waitfor, 
          FALSE, 
          INFINITE)
        ) {
          // monitor_smardcard_readers will return 
          // SCARD_E_CANCELLED
          return false;
        }
        return true;
      },
      [&](
        lib::rng::range<SCARD_READERSTATE*> readersrange
      ) {
        for (auto & state : readersrange) {
          auto stateChanges = (
            (state.dwCurrentState ^ state.dwEventState) & 
              std::numeric_limits<unsigned short>::max()
          );
          std::wcout
            << L"nothread - "
            << state.szReader
            << L" changes: " 
            << std::hex 
            << std::showbase 
            << stateChanges
            << L"["
          ;
          printSCardState(std::wcout, stateChanges)
            << L"] state: " 
            << std::hex 
            << std::showbase 
            << state.dwEventState
            << L"["
          ;
          printSCardState(std::wcout, state.dwEventState)
            << L"]"
            << std::endl
          ;

          if (
            state.dwCurrentState != 
              SCARD_STATE_UNAWARE &&
            ((state.dwEventState & 
              SCARD_STATE_PRESENT) != 
                SCARD_STATE_PRESENT ||
              stateChanges == SCARD_STATE_INUSE ||
              stateChanges == SCARD_STATE_UNPOWERED ||
              (state.dwEventState & (
                SCARD_STATE_UNPOWERED | 
                SCARD_STATE_EMPTY | 
                SCARD_STATE_IGNORE | 
                SCARD_STATE_UNKNOWN | 
                SCARD_STATE_UNAVAILABLE | 
                SCARD_STATE_MUTE)) ||
            state.cbAtr == 0)
          ) {
            // we have seen this reader before 
            // and one of:
            // no card
            // only flipped INUSE
            // only flipped UNPOWERED
            // UNPOWERED EMPTY UNKNOWN UNAVAILABLE MUTE
            // no atr
            //
            // don't try to read the card
            continue;
          }

          CardWithProvider card;
          std::tie(winerror, card) = 
            smart_card::smartcard_name_and_provider(
              lib::rng::make_range_raw(state.rgbAtr)
          );
          if (!winerror) {
            continue;
          }

          KeyWithCertificateVector certificates;
          std::tie(winerror, certificates) = 
            smart_card::smartcard_certificates(
              card.kspname);
          if (!winerror) {
            continue;
          }

          std::wcout << L"nothread -"
          << L" kspname: " << card.kspname.c_str()
          << std::endl;

          printCertificates(
            lib::rng::make_range_raw(certificates)
          );
        }
      }
    );
    winerror.suppress();
  }

  return 0;
}

Thursday, April 12, 2012

smartcard_certificates implementation

Given a provider name NCryptEnumKeys can be used to retrieve all the keys known to that provider. Since the KSP provider is shared across all cards associated to it, the keys from all associated cards will be returned.

Here is a function that uses NCryptEnumKeys and NCryptGetProperty to retrieve the keys and certificates from a KSP provider name.

struct KeyWithCertificate {
  std::wstring key;
  std::vector<BYTE> cert;
};
typedef
  std::vector<KeyWithCertificate>
KeyWithCertificateVector;

inline
std::pair<unique_winerror, KeyWithCertificateVector>
smartcard_certificates(
  const std::wstring& kspstring
)
{
  unique_winerror winerror;
  KeyWithCertificateVector output;

  NCRYPT_PROV_HANDLE provider = NULL;
  ON_UNWIND_AUTO(
    [&] { 
      if (provider) {
        NCryptFreeObject(provider);
      }
    }
  );
  winerror.reset(
    NCryptOpenStorageProvider(
        &provider,
        kspstring.c_str(),
        0
    )
  );
  if (!winerror) {
    return std::make_pair(winerror, std::move(output));
  }

  NCryptKeyName* keyname = nullptr;
  ON_UNWIND_AUTO(
    [&] { 
      if (keyname) {
        NCryptFreeBuffer(keyname);
      }
    }
  );
  void* enumstate = nullptr;
  ON_UNWIND_AUTO(
    [&] { 
      if (enumstate) {
        NCryptFreeBuffer(enumstate);
      }
    }
  );
  for (;;) {
    winerror.reset(
      NCryptEnumKeys(
          provider,
          NULL,
          &keyname,
          &enumstate,
          NCRYPT_SILENT_FLAG
      )
    );
    if (winerror == winerror_cast(NTE_NO_MORE_ITEMS)) {
      winerror.suppress().release();
      break;
    }
    if (!winerror) {
      return std::make_pair(winerror, std::move(output));
    }

    KeyWithCertificate keystate;
    keystate.key = keyname->pszName;

    NCRYPT_KEY_HANDLE key = NULL;
    ON_UNWIND_AUTO(
      [&] { 
        if (key) {
          NCryptFreeObject(key);
        }
      }
    );
    winerror.reset(
      NCryptOpenKey(
          provider,
          &key,
          keyname->pszName,
          keyname->dwLegacyKeySpec,
          NCRYPT_SILENT_FLAG
      )
    );
    if (!winerror) {
      return std::make_pair(winerror, std::move(output));
    }

    DWORD sizecert = 0;
    for (bool getsize = true; ; getsize = false) {
      winerror.reset(
        NCryptGetProperty(
            key,
            NCRYPT_CERTIFICATE_PROPERTY,
            getsize ? nullptr : &keystate.cert[0],
            sizecert,
            &sizecert,
            0
        )
      );
      if (!winerror) {
        return std::make_pair(winerror, std::move(output));
      }
      if (getsize) {
        keystate.cert.resize(sizecert);
      } else {
        break;
      }
    }

    output.push_back(keystate);
  }

  return std::make_pair(winerror, std::move(output));
}

Tuesday, April 10, 2012

smartcard_name_and_provider implementation

Once the reader monitor has reported the ATR for the card in a reader, it can be used to access the card.

Windows has a model that gives card manufacturers three options for providing access to a smart card through the crypto apis.

  • KSP/CSP - the manufacturer can supply a full KSP(Key Storage Provider) and CSP (Cryptographic Service Provider) and associate it with an ATR.
  • Smart Card Minidriver - the manufacturer can supply a minidriver dll that the built-in Smart Card KSP and CSP will load to provide access and associate it with an ATR.
  • PICS/GIDS - the manufacturer can provide a card that implements the GIDS or PICS card standard. Windows has built-in minidrivers for these.

Because of the first option, once an ATR is in hand, SCardGetCardTypeProviderName must be called to retrieve the KSP or CSP provider name that should be used for the card.

SCardListCards will retrieve the card name from an ATR, which is then passed to SCardGetCardTypeProviderName. Windows only supports one KSP/CSP for an ATR, so even though SCardListCards returns a list of card names any one of them can be used to retrieve the provider names.

Here is the code to get a card name and the KSP provider name.

struct CardWithProvider {
  std::wstring cardname;
  std::wstring kspname;
};

inline
std::pair<unique_winerror, CardWithProvider>
smartcard_name_and_provider(
  lib::rng::range<const BYTE*> atr
)
{
  unique_winerror winerror;
  unique_close_scardcontext context;

  CardWithProvider output;

  winerror.reset(
    SCardEstablishContext(
        SCARD_SCOPE_USER,
        NULL,
        NULL,
        context.replace()
    )
  );
  if (!winerror) {
    return std::make_pair(winerror, std::move(output));
  }

  LPWSTR kspstring = nullptr;
  ON_UNWIND(
    unwind_kspstring,
    [&] { 
      if (kspstring) {
        SCardFreeMemory(context.get(), kspstring);
      }
    }
  );
  DWORD ksplength = SCARD_AUTOALLOCATE;

  LPWSTR cardsstring = nullptr;
  ON_UNWIND_AUTO(
    [&] { 
      if (cardsstring) {
        SCardFreeMemory(context.get(), cardsstring);
      }
    }
  );
  DWORD cardslength = SCARD_AUTOALLOCATE;

  winerror.reset(
    SCardListCards(
        context.get(),
        atr.begin(),
        NULL,
        NULL,
        reinterpret_cast<LPWSTR>(&cardsstring),
        &cardslength
    )
  );
  if (winerror == 
      winerror_cast(SCARD_E_READER_UNAVAILABLE)) {
    winerror.suppress();
    // don't free the static string we are 
    // about to assign
    unwind_kspstring.dismiss();
    kspstring = MS_SMART_CARD_KEY_STORAGE_PROVIDER;
    ksplength = wcslen(kspstring);
  } else if (!winerror) {
    return std::make_pair(winerror, std::move(output));
  } else {
    winerror.reset(
      SCardGetCardTypeProviderName(
          context.get(),
          cardsstring,
          SCARD_PROVIDER_KSP,
          reinterpret_cast<LPWSTR>(&kspstring),
          &ksplength
      )
    );
    if (!winerror) {
      return std::make_pair(winerror, std::move(output));
    }
  }

  if (cardsstring) {
    output.cardname = cardsstring;
  }
  output.kspname = kspstring;

  return std::make_pair(winerror, std::move(output));
}