<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/socket/dns_cert_provenance_check.h"

#include <nspr.h>
#include <hasht.h>
#include <sechash.h>

#include <string>

#include "base/non_thread_safe.h"
#include "net/base/completion_callback.h"
#include "net/base/dns_util.h"
#include "net/base/dnsrr_resolver.h"
#include "net/base/net_log.h"
#include "net/base/net_errors.h"

namespace net {

namespace {

class DNSCertProvenanceChecker : public NonThreadSafe {
 public:
  DNSCertProvenanceChecker(const std::string hostname,
                           DnsRRResolver* dnsrr_resolver,
                           const std::vector<base::StringPiece>& der_certs)
      : hostname_(hostname),
        dnsrr_resolver_(dnsrr_resolver),
        der_certs_(der_certs.size()),
        handle_(DnsRRResolver::kInvalidHandle),
        ALLOW_THIS_IN_INITIALIZER_LIST(callback_(
              this, &DNSCertProvenanceChecker::ResolutionComplete)) {
    for (size_t i = 0; i < der_certs.size(); i++)
      der_certs_[i] = der_certs[i].as_string();
  }

  void Start() {
    DCHECK(CalledOnValidThread());

    if (der_certs_.empty())
      return;

    uint8 fingerprint[SHA1_LENGTH];
    SECStatus rv = HASH_HashBuf(
        HASH_AlgSHA1, fingerprint, (uint8*) der_certs_[0].data(),
        der_certs_[0].size());
    DCHECK_EQ(SECSuccess, rv);
    char fingerprint_hex[SHA1_LENGTH * 2 + 1];
    for (unsigned i = 0; i < sizeof(fingerprint); i++) {
      static const char hextable[] = "0123456789abcdef";
      fingerprint_hex[i*2] = hextable[fingerprint[i] >> 4];
      fingerprint_hex[i*2 + 1] = hextable[fingerprint[i] & 15];
    }
    fingerprint_hex[SHA1_LENGTH * 2] = 0;

    static const char kBaseCertName[] = ".certs.links.org";
    domain_.assign(fingerprint_hex);
    domain_.append(kBaseCertName);

    handle_ = dnsrr_resolver_->Resolve(
        domain_, kDNS_TXT, 0 /* flags */, &callback_, &response_,
        0 /* priority */, BoundNetLog());
    if (handle_ == DnsRRResolver::kInvalidHandle) {
      LOG(ERROR) << "Failed to resolve " << domain_ << " for " << hostname_;
      delete this;
    }
  }

 private:
  void ResolutionComplete(int status) {
    DCHECK(CalledOnValidThread());

    if (status == ERR_NAME_NOT_RESOLVED ||
        (status == OK && response_.rrdatas.empty())) {
      LOG(ERROR) << "FAILED"
                 << " hostname:" << hostname_
                 << " domain:" << domain_;
    } else if (status == OK) {
      LOG(ERROR) << "GOOD"
                 << " hostname:" << hostname_
                 << " resp:" << response_.rrdatas[0];
    } else {
      LOG(ERROR) << "Unknown error " << status << " for " << domain_;
    }

    delete this;
  }

  const std::string hostname_;
  std::string domain_;
  DnsRRResolver* const dnsrr_resolver_;
  std::vector<std::string> der_certs_;
  RRResponse response_;
  DnsRRResolver::Handle handle_;
  CompletionCallbackImpl<DNSCertProvenanceChecker> callback_;
};

}  // anonymous namespace

void DoAsyncDNSCertProvenanceVerification(
    const std::string& hostname,
    DnsRRResolver* dnsrr_resolver,
    const std::vector<base::StringPiece>& der_certs) {
  DNSCertProvenanceChecker* c(new DNSCertProvenanceChecker(
      hostname, dnsrr_resolver, der_certs));
  c->Start();
}

}  // namespace net
<commit_msg>net: add code for encrypting DNS cert check uploads.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/socket/dns_cert_provenance_check.h"

#include <nspr.h>

#include <hasht.h>
#include <keyhi.h>
#include <pk11pub.h>
#include <sechash.h>

#include <string>

#include "base/crypto/encryptor.h"
#include "base/crypto/symmetric_key.h"
#include "base/non_thread_safe.h"
#include "base/pickle.h"
#include "net/base/completion_callback.h"
#include "net/base/dns_util.h"
#include "net/base/dnsrr_resolver.h"
#include "net/base/net_errors.h"
#include "net/base/net_log.h"

namespace net {

namespace {

// A DER encoded SubjectPublicKeyInfo structure containing the server's public
// key.
const uint8 kServerPublicKey[] = {
  0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01,
  0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00,
  0x04, 0xc7, 0xea, 0x88, 0x60, 0x52, 0xe3, 0xa3, 0x3e, 0x39, 0x92, 0x0f, 0xa4,
  0x3d, 0xba, 0xd8, 0x02, 0x2d, 0x06, 0x4d, 0x64, 0x98, 0x66, 0xb4, 0x82, 0xf0,
  0x23, 0xa6, 0xd8, 0x37, 0x55, 0x7c, 0x01, 0xbf, 0x18, 0xd8, 0x16, 0x9e, 0x66,
  0xdc, 0x49, 0xbf, 0x2e, 0x86, 0xe3, 0x99, 0xbd, 0xb3, 0x75, 0x25, 0x61, 0x04,
  0x6c, 0x2e, 0xfb, 0x32, 0x42, 0x27, 0xe4, 0x23, 0xea, 0xcd, 0x81, 0x62, 0xc1,
};

class DNSCertProvenanceChecker : public NonThreadSafe {
 public:
  DNSCertProvenanceChecker(const std::string hostname,
                           DnsRRResolver* dnsrr_resolver,
                           const std::vector<base::StringPiece>& der_certs)
      : hostname_(hostname),
        dnsrr_resolver_(dnsrr_resolver),
        der_certs_(der_certs.size()),
        handle_(DnsRRResolver::kInvalidHandle),
        ALLOW_THIS_IN_INITIALIZER_LIST(callback_(
              this, &DNSCertProvenanceChecker::ResolutionComplete)) {
    for (size_t i = 0; i < der_certs.size(); i++)
      der_certs_[i] = der_certs[i].as_string();
  }

  void Start() {
    DCHECK(CalledOnValidThread());

    if (der_certs_.empty())
      return;

    uint8 fingerprint[SHA1_LENGTH];
    SECStatus rv = HASH_HashBuf(
        HASH_AlgSHA1, fingerprint, (uint8*) der_certs_[0].data(),
        der_certs_[0].size());
    DCHECK_EQ(SECSuccess, rv);
    char fingerprint_hex[SHA1_LENGTH * 2 + 1];
    for (unsigned i = 0; i < sizeof(fingerprint); i++) {
      static const char hextable[] = "0123456789abcdef";
      fingerprint_hex[i*2] = hextable[fingerprint[i] >> 4];
      fingerprint_hex[i*2 + 1] = hextable[fingerprint[i] & 15];
    }
    fingerprint_hex[SHA1_LENGTH * 2] = 0;

    static const char kBaseCertName[] = ".certs.links.org";
    domain_.assign(fingerprint_hex);
    domain_.append(kBaseCertName);

    handle_ = dnsrr_resolver_->Resolve(
        domain_, kDNS_TXT, 0 /* flags */, &callback_, &response_,
        0 /* priority */, BoundNetLog());
    if (handle_ == DnsRRResolver::kInvalidHandle) {
      LOG(ERROR) << "Failed to resolve " << domain_ << " for " << hostname_;
      delete this;
    }
  }

 private:
  void ResolutionComplete(int status) {
    DCHECK(CalledOnValidThread());

    if (status == ERR_NAME_NOT_RESOLVED ||
        (status == OK && response_.rrdatas.empty())) {
      LOG(ERROR) << "FAILED"
                 << " hostname:" << hostname_
                 << " domain:" << domain_;
      BuildRecord();
    } else if (status == OK) {
      LOG(ERROR) << "GOOD"
                 << " hostname:" << hostname_
                 << " resp:" << response_.rrdatas[0];
    } else {
      LOG(ERROR) << "Unknown error " << status << " for " << domain_;
    }

    delete this;
  }

  // BuildRecord encrypts the certificate chain to a fixed public key and
  // returns the encrypted blob. Since this code is reporting a possible HTTPS
  // failure, it would seem silly to use HTTPS to protect the uploaded report.
  std::string BuildRecord() {
    static const int kVersion = 0;
    static const unsigned kKeySizeInBytes = 16;  // AES-128
    static const unsigned kIVSizeInBytes = 16;  // AES's block size
    static const unsigned kPadSize = 4096; // we pad up to 4KB,
    // This is a DER encoded, ANSI X9.62 CurveParams object which simply
    // specifies P256.
    static const uint8 kANSIX962CurveParams[] = {
      0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07
    };

    DCHECK(CalledOnValidThread());

    Pickle p;
    p.WriteString(hostname_);
    p.WriteInt(der_certs_.size());
    for (std::vector<std::string>::const_iterator
         i = der_certs_.begin(); i != der_certs_.end(); i++) {
      p.WriteString(*i);
    }
    // We pad to eliminate the possibility that someone could see the size of
    // an upload and use that information to reduce the anonymity set of the
    // certificate chain.
    // The "2*sizeof(uint32)" here covers the padding length which we add next
    // and Pickle's internal length which it includes at the beginning of the
    // data.
    unsigned pad_bytes = kPadSize - ((p.size() + 2*sizeof(uint32)) % kPadSize);
    p.WriteUInt32(pad_bytes);
    char* padding = new char[pad_bytes];
    memset(padding, 0, pad_bytes);
    p.WriteData(padding, pad_bytes);
    delete[] padding;

    // We generate a random public value and perform a DH key agreement with
    // the server's fixed value.
    SECKEYPublicKey* pub_key = NULL;
    SECKEYPrivateKey* priv_key = NULL;
    SECItem ec_der_params;
    memset(&ec_der_params, 0, sizeof(ec_der_params));
    ec_der_params.data = const_cast<uint8*>(kANSIX962CurveParams);
    ec_der_params.len = sizeof(kANSIX962CurveParams);
    priv_key = SECKEY_CreateECPrivateKey(&ec_der_params, &pub_key, NULL);
    SECKEYPublicKey* server_pub_key = GetServerPubKey();

    // This extracts the big-endian, x value of the shared point.
    // The values of the arguments match ssl3_SendECDHClientKeyExchange in NSS
    // 3.12.8's lib/ssl/ssl3ecc.c
    PK11SymKey* pms = PK11_PubDeriveWithKDF(
        priv_key, server_pub_key, PR_FALSE /* is sender */,
        NULL /* random a */, NULL /* random b */, CKM_ECDH1_DERIVE,
        CKM_TLS_MASTER_KEY_DERIVE_DH, CKA_DERIVE, 0 /* key size */,
        CKD_NULL /* KDF */, NULL /* shared data */, NULL /* wincx */);
    SECKEY_DestroyPublicKey(server_pub_key);
    SECStatus rv = PK11_ExtractKeyValue(pms);
    DCHECK_EQ(SECSuccess, rv);
    SECItem* x_data = PK11_GetKeyData(pms);

    // The key and IV are 128-bits and generated from a SHA256 hash of the x
    // value.
    char key_data[SHA256_LENGTH];
    HASH_HashBuf(HASH_AlgSHA256, reinterpret_cast<uint8*>(key_data),
                 x_data->data, x_data->len);
    PK11_FreeSymKey(pms);

    DCHECK_GE(sizeof(key_data), kKeySizeInBytes + kIVSizeInBytes);
    std::string raw_key(key_data, kKeySizeInBytes);

    scoped_ptr<base::SymmetricKey> symkey(
        base::SymmetricKey::Import(base::SymmetricKey::AES, raw_key));
    std::string iv(key_data + kKeySizeInBytes, kIVSizeInBytes);

    base::Encryptor encryptor;
    bool r = encryptor.Init(symkey.get(), base::Encryptor::CBC, iv);
    CHECK(r);

    std::string plaintext(reinterpret_cast<const char*>(p.data()), p.size());
    std::string ciphertext;
    encryptor.Encrypt(plaintext, &ciphertext);

    // We use another Pickle object to serialise the 'outer' wrapping of the
    // plaintext.
    Pickle outer;
    outer.WriteInt(kVersion);

    SECItem* pub_key_serialized = SECKEY_EncodeDERSubjectPublicKeyInfo(pub_key);
    outer.WriteString(
        std::string(reinterpret_cast<char*>(pub_key_serialized->data),
                    pub_key_serialized->len));
    SECITEM_FreeItem(pub_key_serialized, PR_TRUE);

    outer.WriteString(ciphertext);

    SECKEY_DestroyPublicKey(pub_key);
    SECKEY_DestroyPrivateKey(priv_key);

    return std::string(reinterpret_cast<const char*>(outer.data()),
                       outer.size());
  }

  SECKEYPublicKey* GetServerPubKey() {
    DCHECK(CalledOnValidThread());

    SECItem der;
    memset(&der, 0, sizeof(der));
    der.data = const_cast<uint8*>(kServerPublicKey);
    der.len = sizeof(kServerPublicKey);

    CERTSubjectPublicKeyInfo* spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&der);
    SECKEYPublicKey* public_key = SECKEY_ExtractPublicKey(spki);
    SECKEY_DestroySubjectPublicKeyInfo(spki);

    return public_key;
  }

  const std::string hostname_;
  std::string domain_;
  DnsRRResolver* const dnsrr_resolver_;
  std::vector<std::string> der_certs_;
  RRResponse response_;
  DnsRRResolver::Handle handle_;
  CompletionCallbackImpl<DNSCertProvenanceChecker> callback_;
};

}  // anonymous namespace

void DoAsyncDNSCertProvenanceVerification(
    const std::string& hostname,
    DnsRRResolver* dnsrr_resolver,
    const std::vector<base::StringPiece>& der_certs) {
  DNSCertProvenanceChecker* c(new DNSCertProvenanceChecker(
      hostname, dnsrr_resolver, der_certs));
  c->Start();
}

}  // namespace net
<|endoftext|>


<commit_before>/************************************************************************************
 * Copyright (C) 2017, Copyright Holders of the ALICE Collaboration                 *
 * All rights reserved.                                                             *
 *                                                                                *
 * Redistribution and use in source and binary forms, with or without               *
 * modification, are permitted provided that the following conditions are met:      *
 *     * Redistributions of source code must retain the above copyright             *
 *       notice, this list of conditions and the following disclaimer.              *
 *     * Redistributions in binary form must reproduce the above copyright          *
 *       notice, this list of conditions and the following disclaimer in the        *
 *       documentation and/or other materials provided with the distribution.       *
 *     * Neither the name of the <organization> nor the                             *
 *       names of its contributors may be used to endorse or promote products       *
 *       derived from this software without specific prior written permission.      *
 *                                                                                *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND  *
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED    *
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE           *
 * DISCLAIMED. IN NO EVENT SHALL ALICE COLLABORATION BE LIABLE FOR ANY              *
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES       *
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;     *
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND      *
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT       *
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS    *
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                     *
 ************************************************************************************/
#include <iostream>
#include <string>
#include <unordered_map>
#include "AliEmcalTriggerSelectionCuts.h"
#include "AliEMCALTriggerPatchInfo.h"

ClassImp(PWG::EMCAL::AliEmcalTriggerSelectionCuts)

namespace PWG {
namespace EMCAL {

AliEmcalTriggerSelectionCuts::AliEmcalTriggerSelectionCuts() :
  TObject(),
  fSelectionMethod(kADC),
  fPatchType(kAnyPatch),
  fAcceptanceType(kEMCALDCALAcceptance),
  fThreshold(0),
  fUseSimpleOffline(kFALSE),
  fUseRecalc(kFALSE)
{
}

Bool_t AliEmcalTriggerSelectionCuts::IsSelected(const AliEMCALTriggerPatchInfo * const patch) const {
  //if(fUseSimpleOffline && !patch->IsOfflineSimple()) return kFALSE;
  //else if(!fUseSimpleOffline && patch->IsOfflineSimple()) return kFALSE;
  if(!SelectAcceptance(patch)) return kFALSE;
  if(!SelectPatchType(patch)) return kFALSE;
  if(GetCutPrimitive(patch) < fThreshold) return kFALSE;
  return kTRUE;
}

Int_t AliEmcalTriggerSelectionCuts::CompareTriggerPatches(const AliEMCALTriggerPatchInfo *first, const AliEMCALTriggerPatchInfo *second) const {
  Double_t valfirst = GetCutPrimitive(first), valsecond = GetCutPrimitive(second);
  if(valfirst == valsecond) return 0;
  if(valfirst > valsecond) return 1;
  return -1;
}

Double_t AliEmcalTriggerSelectionCuts::GetCutPrimitive(const AliEMCALTriggerPatchInfo * const patch) const{
  double energy(0);
  switch(fSelectionMethod){
  case kADC: energy = static_cast<Double_t>(patch->GetADCAmp()); break;
  case kEnergyRough: energy = patch->GetADCAmpGeVRough(); break;
  case kEnergyOfflineSmeared: energy = patch->GetSmearedEnergy(); break;
  case kEnergyOffline: energy = patch->GetPatchE(); break;
  default: energy = -1.;
  };
  return energy;
}

Bool_t AliEmcalTriggerSelectionCuts::SelectPatchType(const AliEMCALTriggerPatchInfo * const patch) const{
  if(fPatchType == kAnyPatch) return kTRUE;
  if(fUseSimpleOffline){
    if(patch->IsJetLowSimple() && ((fPatchType == kL1JetPatch) || (fPatchType == kL1JetLowPatch))) return kTRUE;
    if(patch->IsJetHighSimple() && ((fPatchType == kL1JetPatch) || (fPatchType == kL1JetHighPatch))) return kTRUE;
    if(patch->IsGammaLowSimple() && ((fPatchType == kL1GammaPatch) || (fPatchType == kL1GammaLowPatch))) return kTRUE;
    if(patch->IsGammaHighSimple() && ((fPatchType == kL1GammaPatch) || (fPatchType == kL1GammaHighPatch))) return kTRUE;
  } else if(fUseRecalc) {
    if(patch->IsJetLowRecalc() && ((fPatchType == kL1JetPatch) || (fPatchType == kL1JetLowPatch))) return kTRUE;
    if(patch->IsJetHighRecalc() && ((fPatchType == kL1JetPatch) || (fPatchType == kL1JetHighPatch))) return kTRUE;
    if(patch->IsGammaLowRecalc() && ((fPatchType == kL1GammaPatch) || (fPatchType == kL1GammaLowPatch))) return kTRUE;
    if(patch->IsGammaHighRecalc() && ((fPatchType == kL1GammaPatch) || (fPatchType == kL1GammaHighPatch))) return kTRUE;
  } else {
    if(patch->IsJetLow() && ((fPatchType == kL1JetPatch) || (fPatchType == kL1JetLowPatch))) return kTRUE;
    if(patch->IsJetHigh() && ((fPatchType == kL1JetPatch) || (fPatchType == kL1JetHighPatch))) return kTRUE;
    if(patch->IsGammaLow() && ((fPatchType == kL1GammaPatch) || (fPatchType == kL1GammaLowPatch))) return kTRUE;
    if(patch->IsGammaHigh() && ((fPatchType == kL1GammaPatch) || (fPatchType == kL1GammaHighPatch))) return kTRUE;
    if(patch->IsLevel0() && fPatchType == kL0Patch) return kTRUE;
  }
  return kFALSE;
}

Bool_t AliEmcalTriggerSelectionCuts::SelectAcceptance(const AliEMCALTriggerPatchInfo * const patch) const {
  Bool_t selected(false);
  switch(fAcceptanceType){
  case kEMCALAcceptance: selected = patch->IsEMCal(); break;
  case kDCALAcceptance: selected = patch->IsDCalPHOS(); break;
  case kEMCALDCALAcceptance: selected = patch->IsEMCal() || patch->IsDCalPHOS(); break;
  default: selected = false;
  };
  return selected;
}

void AliEmcalTriggerSelectionCuts::PrintStream(std::ostream &stream) const {
  std::unordered_map<AcceptanceType_t, std::string> acceptancetext = {{kEMCALAcceptance, "EMCAL"},
                                                                      {kDCALAcceptance, "DCAL"},
                                                                      {kEMCALDCALAcceptance, "EMCAL-DCAL"}};
  std::unordered_map<PatchType_t, std::string> patchtypetext = {{kL0Patch, "Level0"},
                                                                {kL1GammaPatch, "L1-gamma"},
                                                                {kL1GammaHighPatch, "L1-gamma, high threshold"},
                                                                {kL1GammaLowPatch, "L1-gamma, low threshold"},
                                                                {kL1JetPatch, "L1-jet"},
                                                                {kL1JetHighPatch, "L1-jet, high threshold"},
                                                                {kL1JetLowPatch, "L1-jet, low threshold"}};
  std::unordered_map<SelectionMethod_t, std::string> selmodetext = {{kADC, "FastOR ADC"},
                                                                    {kEnergyRough, "FastOR Energy"},
                                                                    {kEnergyOffline, "FEE Energy"},
                                                                    {kEnergyOfflineSmeared, "FEE Energy, decalibrated"}};
  stream << "  Cut settings:" << std::endl;
  stream << "    acceptance:      " << acceptancetext.find(fAcceptanceType)->second << std::endl;
  stream << "    patchtype:       " << patchtypetext.find(fPatchType)->second << std::endl;
  stream << "    sel mode:        " << selmodetext.find(fSelectionMethod)->second << std::endl;
  stream << "    Offline Patches: " << (fUseSimpleOffline ? "yes" : "no") << std::endl;
  stream << "    Recalc Patches:  " << (fUseRecalc ? "yes" : "no") << std::endl;
  stream << "    Threshold:       " << fThreshold << std::endl;
}

}
}

std::ostream &operator<<(std::ostream &stream, const PWG::EMCAL::AliEmcalTriggerSelectionCuts &cuts){
  cuts.PrintStream(stream);
  return stream;
}
<commit_msg>This fix is only needed because ALICE uses too old compilers!<commit_after>/************************************************************************************
 * Copyright (C) 2017, Copyright Holders of the ALICE Collaboration                 *
 * All rights reserved.                                                             *
 *                                                                                *
 * Redistribution and use in source and binary forms, with or without               *
 * modification, are permitted provided that the following conditions are met:      *
 *     * Redistributions of source code must retain the above copyright             *
 *       notice, this list of conditions and the following disclaimer.              *
 *     * Redistributions in binary form must reproduce the above copyright          *
 *       notice, this list of conditions and the following disclaimer in the        *
 *       documentation and/or other materials provided with the distribution.       *
 *     * Neither the name of the <organization> nor the                             *
 *       names of its contributors may be used to endorse or promote products       *
 *       derived from this software without specific prior written permission.      *
 *                                                                                *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND  *
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED    *
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE           *
 * DISCLAIMED. IN NO EVENT SHALL ALICE COLLABORATION BE LIABLE FOR ANY              *
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES       *
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;     *
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND      *
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT       *
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS    *
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                     *
 ************************************************************************************/
#include <iostream>
#include <string>
#include <map>
#include "AliEmcalTriggerSelectionCuts.h"
#include "AliEMCALTriggerPatchInfo.h"

ClassImp(PWG::EMCAL::AliEmcalTriggerSelectionCuts)

namespace PWG {
namespace EMCAL {

AliEmcalTriggerSelectionCuts::AliEmcalTriggerSelectionCuts() :
  TObject(),
  fSelectionMethod(kADC),
  fPatchType(kAnyPatch),
  fAcceptanceType(kEMCALDCALAcceptance),
  fThreshold(0),
  fUseSimpleOffline(kFALSE),
  fUseRecalc(kFALSE)
{
}

Bool_t AliEmcalTriggerSelectionCuts::IsSelected(const AliEMCALTriggerPatchInfo * const patch) const {
  //if(fUseSimpleOffline && !patch->IsOfflineSimple()) return kFALSE;
  //else if(!fUseSimpleOffline && patch->IsOfflineSimple()) return kFALSE;
  if(!SelectAcceptance(patch)) return kFALSE;
  if(!SelectPatchType(patch)) return kFALSE;
  if(GetCutPrimitive(patch) < fThreshold) return kFALSE;
  return kTRUE;
}

Int_t AliEmcalTriggerSelectionCuts::CompareTriggerPatches(const AliEMCALTriggerPatchInfo *first, const AliEMCALTriggerPatchInfo *second) const {
  Double_t valfirst = GetCutPrimitive(first), valsecond = GetCutPrimitive(second);
  if(valfirst == valsecond) return 0;
  if(valfirst > valsecond) return 1;
  return -1;
}

Double_t AliEmcalTriggerSelectionCuts::GetCutPrimitive(const AliEMCALTriggerPatchInfo * const patch) const{
  double energy(0);
  switch(fSelectionMethod){
  case kADC: energy = static_cast<Double_t>(patch->GetADCAmp()); break;
  case kEnergyRough: energy = patch->GetADCAmpGeVRough(); break;
  case kEnergyOfflineSmeared: energy = patch->GetSmearedEnergy(); break;
  case kEnergyOffline: energy = patch->GetPatchE(); break;
  default: energy = -1.;
  };
  return energy;
}

Bool_t AliEmcalTriggerSelectionCuts::SelectPatchType(const AliEMCALTriggerPatchInfo * const patch) const{
  if(fPatchType == kAnyPatch) return kTRUE;
  if(fUseSimpleOffline){
    if(patch->IsJetLowSimple() && ((fPatchType == kL1JetPatch) || (fPatchType == kL1JetLowPatch))) return kTRUE;
    if(patch->IsJetHighSimple() && ((fPatchType == kL1JetPatch) || (fPatchType == kL1JetHighPatch))) return kTRUE;
    if(patch->IsGammaLowSimple() && ((fPatchType == kL1GammaPatch) || (fPatchType == kL1GammaLowPatch))) return kTRUE;
    if(patch->IsGammaHighSimple() && ((fPatchType == kL1GammaPatch) || (fPatchType == kL1GammaHighPatch))) return kTRUE;
  } else if(fUseRecalc) {
    if(patch->IsJetLowRecalc() && ((fPatchType == kL1JetPatch) || (fPatchType == kL1JetLowPatch))) return kTRUE;
    if(patch->IsJetHighRecalc() && ((fPatchType == kL1JetPatch) || (fPatchType == kL1JetHighPatch))) return kTRUE;
    if(patch->IsGammaLowRecalc() && ((fPatchType == kL1GammaPatch) || (fPatchType == kL1GammaLowPatch))) return kTRUE;
    if(patch->IsGammaHighRecalc() && ((fPatchType == kL1GammaPatch) || (fPatchType == kL1GammaHighPatch))) return kTRUE;
  } else {
    if(patch->IsJetLow() && ((fPatchType == kL1JetPatch) || (fPatchType == kL1JetLowPatch))) return kTRUE;
    if(patch->IsJetHigh() && ((fPatchType == kL1JetPatch) || (fPatchType == kL1JetHighPatch))) return kTRUE;
    if(patch->IsGammaLow() && ((fPatchType == kL1GammaPatch) || (fPatchType == kL1GammaLowPatch))) return kTRUE;
    if(patch->IsGammaHigh() && ((fPatchType == kL1GammaPatch) || (fPatchType == kL1GammaHighPatch))) return kTRUE;
    if(patch->IsLevel0() && fPatchType == kL0Patch) return kTRUE;
  }
  return kFALSE;
}

Bool_t AliEmcalTriggerSelectionCuts::SelectAcceptance(const AliEMCALTriggerPatchInfo * const patch) const {
  Bool_t selected(false);
  switch(fAcceptanceType){
  case kEMCALAcceptance: selected = patch->IsEMCal(); break;
  case kDCALAcceptance: selected = patch->IsDCalPHOS(); break;
  case kEMCALDCALAcceptance: selected = patch->IsEMCal() || patch->IsDCalPHOS(); break;
  default: selected = false;
  };
  return selected;
}

void AliEmcalTriggerSelectionCuts::PrintStream(std::ostream &stream) const {
  std::map<AcceptanceType_t, std::string> acceptancetext = {{kEMCALAcceptance, "EMCAL"},
                                                                      {kDCALAcceptance, "DCAL"},
                                                                      {kEMCALDCALAcceptance, "EMCAL-DCAL"}};
  std::map<PatchType_t, std::string> patchtypetext = {{kL0Patch, "Level0"},
                                                                {kL1GammaPatch, "L1-gamma"},
                                                                {kL1GammaHighPatch, "L1-gamma, high threshold"},
                                                                {kL1GammaLowPatch, "L1-gamma, low threshold"},
                                                                {kL1JetPatch, "L1-jet"},
                                                                {kL1JetHighPatch, "L1-jet, high threshold"},
                                                                {kL1JetLowPatch, "L1-jet, low threshold"}};
  std::map<SelectionMethod_t, std::string> selmodetext = {{kADC, "FastOR ADC"},
                                                                    {kEnergyRough, "FastOR Energy"},
                                                                    {kEnergyOffline, "FEE Energy"},
                                                                    {kEnergyOfflineSmeared, "FEE Energy, decalibrated"}};
  stream << "  Cut settings:" << std::endl;
  stream << "    acceptance:      " << acceptancetext.find(fAcceptanceType)->second << std::endl;
  stream << "    patchtype:       " << patchtypetext.find(fPatchType)->second << std::endl;
  stream << "    sel mode:        " << selmodetext.find(fSelectionMethod)->second << std::endl;
  stream << "    Offline Patches: " << (fUseSimpleOffline ? "yes" : "no") << std::endl;
  stream << "    Recalc Patches:  " << (fUseRecalc ? "yes" : "no") << std::endl;
  stream << "    Threshold:       " << fThreshold << std::endl;
}

}
}

std::ostream &operator<<(std::ostream &stream, const PWG::EMCAL::AliEmcalTriggerSelectionCuts &cuts){
  cuts.PrintStream(stream);
  return stream;
}
<|endoftext|>


<commit_before><commit_msg>Try uncommenting these now, I don't think the FIXME holds any more<commit_after><|endoftext|>


<commit_before><commit_msg>-Typo: falback -> fallback<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: unohelp2.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-02-01 08:37:40 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _VCL_UNOHELP2_HXX
#include <unohelp2.hxx>
#endif

#ifndef _SOT_EXCHANGE_HXX
#include <sot/exchange.hxx>
#endif

#ifndef _SOT_FORMATS_HXX
#include <sot/formats.hxx>
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef _SV_SVAPP_HXX
#include <svapp.hxx>
#endif
#ifndef _COM_SUN_STAR_DATATRANSFER_CLIPBOARD_XCLIPBOARD_HPP_
#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
#endif
#ifndef _COM_SUN_STAR_DATATRANSFER_CLIPBOARD_XFLUSHABLECLIPBOARD_HPP_
#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
#endif

using namespace ::com::sun::star;

namespace vcl { namespace unohelper {

    TextDataObject::TextDataObject( const String& rText ) : maText( rText )
    {
    }

    TextDataObject::~TextDataObject()
    {
    }

    void TextDataObject::CopyStringTo( const String& rContent,
        const uno::Reference< datatransfer::clipboard::XClipboard >& rxClipboard )
    {
        DBG_ASSERT( rxClipboard.is(), "TextDataObject::CopyStringTo: invalid clipboard!" );
        if ( !rxClipboard.is() )
            return;

        TextDataObject* pDataObj = new TextDataObject( rContent );

        const sal_uInt32 nRef = Application::ReleaseSolarMutex();
        try
        {
            rxClipboard->setContents( pDataObj, NULL );

            uno::Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( rxClipboard, uno::UNO_QUERY );
            if( xFlushableClipboard.is() )
                xFlushableClipboard->flushClipboard();
        }
        catch( const uno::Exception& )
        {
        }
        Application::AcquireSolarMutex( nRef );
    }

    // ::com::sun::star::uno::XInterface
    uno::Any TextDataObject::queryInterface( const uno::Type & rType ) throw(uno::RuntimeException)
    {
        uno::Any aRet = ::cppu::queryInterface( rType, SAL_STATIC_CAST( datatransfer::XTransferable*, this ) );
        return (aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ));
    }

    // ::com::sun::star::datatransfer::XTransferable
    uno::Any TextDataObject::getTransferData( const datatransfer::DataFlavor& rFlavor ) throw(datatransfer::UnsupportedFlavorException, io::IOException, uno::RuntimeException)
    {
        uno::Any aAny;

        ULONG nT = SotExchange::GetFormat( rFlavor );
        if ( nT == SOT_FORMAT_STRING )
        {
            aAny <<= (::rtl::OUString)GetString();
        }
        else
        {
            throw datatransfer::UnsupportedFlavorException();
        }
        return aAny;
    }

    uno::Sequence< datatransfer::DataFlavor > TextDataObject::getTransferDataFlavors(  ) throw(uno::RuntimeException)
    {
        uno::Sequence< datatransfer::DataFlavor > aDataFlavors(1);
        SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aDataFlavors.getArray()[0] );
        return aDataFlavors;
    }

    sal_Bool TextDataObject::isDataFlavorSupported( const datatransfer::DataFlavor& rFlavor ) throw(uno::RuntimeException)
    {
        ULONG nT = SotExchange::GetFormat( rFlavor );
        return ( nT == SOT_FORMAT_STRING );
    }

}}  // namespace vcl::unohelper
<commit_msg>INTEGRATION: CWS ooo19126 (1.3.246); FILE MERGED 2005/09/05 14:44:39 rt 1.3.246.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: unohelp2.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 11:44:18 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _VCL_UNOHELP2_HXX
#include <unohelp2.hxx>
#endif

#ifndef _SOT_EXCHANGE_HXX
#include <sot/exchange.hxx>
#endif

#ifndef _SOT_FORMATS_HXX
#include <sot/formats.hxx>
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef _SV_SVAPP_HXX
#include <svapp.hxx>
#endif
#ifndef _COM_SUN_STAR_DATATRANSFER_CLIPBOARD_XCLIPBOARD_HPP_
#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
#endif
#ifndef _COM_SUN_STAR_DATATRANSFER_CLIPBOARD_XFLUSHABLECLIPBOARD_HPP_
#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
#endif

using namespace ::com::sun::star;

namespace vcl { namespace unohelper {

    TextDataObject::TextDataObject( const String& rText ) : maText( rText )
    {
    }

    TextDataObject::~TextDataObject()
    {
    }

    void TextDataObject::CopyStringTo( const String& rContent,
        const uno::Reference< datatransfer::clipboard::XClipboard >& rxClipboard )
    {
        DBG_ASSERT( rxClipboard.is(), "TextDataObject::CopyStringTo: invalid clipboard!" );
        if ( !rxClipboard.is() )
            return;

        TextDataObject* pDataObj = new TextDataObject( rContent );

        const sal_uInt32 nRef = Application::ReleaseSolarMutex();
        try
        {
            rxClipboard->setContents( pDataObj, NULL );

            uno::Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( rxClipboard, uno::UNO_QUERY );
            if( xFlushableClipboard.is() )
                xFlushableClipboard->flushClipboard();
        }
        catch( const uno::Exception& )
        {
        }
        Application::AcquireSolarMutex( nRef );
    }

    // ::com::sun::star::uno::XInterface
    uno::Any TextDataObject::queryInterface( const uno::Type & rType ) throw(uno::RuntimeException)
    {
        uno::Any aRet = ::cppu::queryInterface( rType, SAL_STATIC_CAST( datatransfer::XTransferable*, this ) );
        return (aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ));
    }

    // ::com::sun::star::datatransfer::XTransferable
    uno::Any TextDataObject::getTransferData( const datatransfer::DataFlavor& rFlavor ) throw(datatransfer::UnsupportedFlavorException, io::IOException, uno::RuntimeException)
    {
        uno::Any aAny;

        ULONG nT = SotExchange::GetFormat( rFlavor );
        if ( nT == SOT_FORMAT_STRING )
        {
            aAny <<= (::rtl::OUString)GetString();
        }
        else
        {
            throw datatransfer::UnsupportedFlavorException();
        }
        return aAny;
    }

    uno::Sequence< datatransfer::DataFlavor > TextDataObject::getTransferDataFlavors(  ) throw(uno::RuntimeException)
    {
        uno::Sequence< datatransfer::DataFlavor > aDataFlavors(1);
        SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aDataFlavors.getArray()[0] );
        return aDataFlavors;
    }

    sal_Bool TextDataObject::isDataFlavorSupported( const datatransfer::DataFlavor& rFlavor ) throw(uno::RuntimeException)
    {
        ULONG nT = SotExchange::GetFormat( rFlavor );
        return ( nT == SOT_FORMAT_STRING );
    }

}}  // namespace vcl::unohelper
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: impanmvw.hxx,v $
 *
 *  $Revision: 1.1.1.1 $
 *
 *  last change: $Author: hr $ $Date: 2000-09-18 17:05:37 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SV_IMPANMVW_HXX
#define _SV_IMPANMVW_HXX

#include "animate.hxx"

// ----------------
// - ImplAnimView -
// ----------------

class Animation;
class OutputDevice;
class VirtualDevice;
struct AnimationBitmap;

class ImplAnimView
{
private:

    Animation*      mpParent;
    OutputDevice*   mpOut;
    long            mnExtraData;
    Point           maPt;
    Point           maDispPt;
    Point           maRestPt;
    Size            maSz;
    Size            maSzPix;
    Size            maDispSz;
    Size            maRestSz;
    MapMode         maMap;
    Region          maClip;
    VirtualDevice*  mpBackground;
    VirtualDevice*  mpRestore;
    ULONG           mnActPos;
    Disposal        meLastDisposal;
    BOOL            mbPause;
    BOOL            mbFirst;
    BOOL            mbMarked;
    BOOL            mbHMirr;
    BOOL            mbVMirr;

    void            ImplGetPosSize( const AnimationBitmap& rAnm, Point& rPosPix, Size& rSizePix );
    void            ImplDraw( ULONG nPos, VirtualDevice* pVDev );

public:

                    ImplAnimView( Animation* pParent, OutputDevice* pOut,
                                  const Point& rPt, const Size& rSz, ULONG nExtraData,
                                  OutputDevice* pFirstFrameOutDev = NULL );
                    ~ImplAnimView();

    BOOL            ImplMatches( OutputDevice* pOut, long nExtraData ) const;
    void            ImplDrawToPos( ULONG nPos );
    void            ImplDraw( ULONG nPos );
    void            ImplRepaint();
    AInfo*          ImplCreateAInfo() const;

    const Point&    ImplGetOutPos() const { return maPt; }

    const Size&     ImplGetOutSize() const { return maSz; }
    const Size&     ImplGetOutSizePix() const { return maSzPix; }

    void            ImplPause( BOOL bPause ) { mbPause = bPause; }
    BOOL            ImplIsPause() const { return mbPause; }

    void            ImplSetMarked( BOOL bMarked ) { mbMarked = bMarked; }
    BOOL            ImplIsMarked() const { return mbMarked; }
};

#endif
<commit_msg>INTEGRATION: CWS ooo19126 (1.1.1.1.994); FILE MERGED 2005/09/05 14:44:51 rt 1.1.1.1.994.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: impanmvw.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 12:00:41 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _SV_IMPANMVW_HXX
#define _SV_IMPANMVW_HXX

#include "animate.hxx"

// ----------------
// - ImplAnimView -
// ----------------

class Animation;
class OutputDevice;
class VirtualDevice;
struct AnimationBitmap;

class ImplAnimView
{
private:

    Animation*      mpParent;
    OutputDevice*   mpOut;
    long            mnExtraData;
    Point           maPt;
    Point           maDispPt;
    Point           maRestPt;
    Size            maSz;
    Size            maSzPix;
    Size            maDispSz;
    Size            maRestSz;
    MapMode         maMap;
    Region          maClip;
    VirtualDevice*  mpBackground;
    VirtualDevice*  mpRestore;
    ULONG           mnActPos;
    Disposal        meLastDisposal;
    BOOL            mbPause;
    BOOL            mbFirst;
    BOOL            mbMarked;
    BOOL            mbHMirr;
    BOOL            mbVMirr;

    void            ImplGetPosSize( const AnimationBitmap& rAnm, Point& rPosPix, Size& rSizePix );
    void            ImplDraw( ULONG nPos, VirtualDevice* pVDev );

public:

                    ImplAnimView( Animation* pParent, OutputDevice* pOut,
                                  const Point& rPt, const Size& rSz, ULONG nExtraData,
                                  OutputDevice* pFirstFrameOutDev = NULL );
                    ~ImplAnimView();

    BOOL            ImplMatches( OutputDevice* pOut, long nExtraData ) const;
    void            ImplDrawToPos( ULONG nPos );
    void            ImplDraw( ULONG nPos );
    void            ImplRepaint();
    AInfo*          ImplCreateAInfo() const;

    const Point&    ImplGetOutPos() const { return maPt; }

    const Size&     ImplGetOutSize() const { return maSz; }
    const Size&     ImplGetOutSizePix() const { return maSzPix; }

    void            ImplPause( BOOL bPause ) { mbPause = bPause; }
    BOOL            ImplIsPause() const { return mbPause; }

    void            ImplSetMarked( BOOL bMarked ) { mbMarked = bMarked; }
    BOOL            ImplIsMarked() const { return mbMarked; }
};

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007-2010 Digital Bazaar, Inc. All rights reserved.
 */
#define __STDC_CONSTANT_MACROS

#include "monarch/net/SocketTools.h"

#include "monarch/net/WindowsSupport.h"
#include "monarch/rt/Thread.h"
#include "monarch/rt/System.h"

#include <limits.h>
#ifndef WIN32
#include <poll.h>
#endif

using namespace monarch::net;
using namespace monarch::rt;

#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 255
#endif

int SocketTools::poll(bool read, int fd, int64_t timeout)
{
#ifdef WIN32
   return select(read, fd, timeout);
#else
   int rval = 0;

   // create poll set
   struct pollfd fds;
   fds.fd = fd;
   fds.events = read ? POLLIN : POLLOUT;

   // "n" parameter is the highest numbered descriptor plus 1
   int n = fd + 1;

   // set 20 millisecond interrupt check timeout (currently necessary to
   // enable thread interruptions)
   int intck = INT32_C(20);

   // keep selecting (polling) until timeout is reached
   int64_t remaining = (timeout <= 0) ? intck : timeout;

   int to;
   if(timeout < 0)
   {
      // create instant timeout (polling)
      to = 0;
   }
   else
   {
      // create intck millisecond timeout
      to = (remaining < intck ? (int)remaining : intck);
   }

   uint64_t start = System::getCurrentMilliseconds();
   uint64_t end;

   Thread* t = Thread::currentThread();
   while(remaining > 0 && rval == 0 && !t->isInterrupted())
   {
      // wait for file descriptors to be updated
      rval = ::poll(&fds, n, to);

      // check for error events
      if(rval > 0)
      {
         // remote side hung up
         if(fds.revents & POLLHUP)
         {
            rval = -1;
            errno = EPIPE;
         }
         // file descriptor not open
         else if(fds.revents & POLLNVAL)
         {
            rval = -1;
            errno = EBADF;
         }
         // error
         else if(fds.revents & POLLERR)
         {
            // some kind of IO error
            rval = -1;
            errno = EIO;
         }
      }
      else if(rval == -1 && errno == EINTR)
      {
         // no error, syscall interrupted
         rval = 0;
      }

      // decrement timeout
      if(rval == 0 && timeout != 0)
      {
         // decrement remaining time
         end = System::getCurrentMilliseconds();
         remaining -= (end - start);
         start = end;
         to = (remaining < intck ? (int)remaining : intck);
      }
   }

   if(rval > 0)
   {
      if(t->isInterrupted())
      {
         rval = -1;
         errno = EINTR;

         // set interrupted exception
         ExceptionRef e = t->createInterruptedException();
         Exception::set(e);
      }
   }

   return rval;
#endif
}

#ifdef WIN32
int SocketTools::select(bool read, unsigned int fd, int64_t timeout)
#else
int SocketTools::select(bool read, int fd, int64_t timeout)
#endif
{
   int rval = 0;

   // create a file descriptor set to read on
   fd_set rfds;
   FD_ZERO(&rfds);

   // create a file descriptor set to write on
   fd_set wfds;
   FD_ZERO(&wfds);

   // create a file descriptor set to check for exceptions on
   fd_set exfds;
   FD_ZERO(&exfds);

   // add file descriptor to sets
   FD_SET(fd, &rfds);
   FD_SET(fd, &wfds);
   FD_SET(fd, &exfds);

   // "n" parameter is the highest numbered descriptor plus 1
#ifdef WIN32
   unsigned int n = fd + 1;
#else
   int n = fd + 1;
#endif

   // set 20 millisecond interrupt check timeout (necessary because
   // windows lacks SIGNAL support to do interruptions properly)
   int64_t intck = INT64_C(20);

   // keep selecting (polling) until timeout is reached
   int64_t remaining = (timeout <= 0) ? intck : timeout;

   struct timeval to;
   to.tv_sec = 0;
   if(timeout < 0)
   {
      // create instant timeout (polling)
      to.tv_usec = 0;
   }
   else
   {
      // create intck millisecond timeout (1 millisecond is 1000 microseconds)
      to.tv_usec = (remaining < intck ? remaining : intck) * INT64_C(1000);
   }

   uint64_t start = System::getCurrentMilliseconds();
   uint64_t end;

   Thread* t = Thread::currentThread();
   while(remaining > 0 && rval == 0 && !t->isInterrupted())
   {
      // wait for file descriptors to be updated
      if(read)
      {
         // wait for readability
         rval = ::select(n, &rfds, NULL, &exfds, &to);
      }
      else
      {
         // wait for readability and writability
         //
         // Note: We must test to see if the pipe is broken by
         // testing for readability -- as it will occur if the
         // connection closes due to TCP sending an RST to the
         // socket ... and this will cause recv() to return 0
         rval = ::select(n, &rfds, &wfds, &exfds, &to);
         if(rval > 0 && !FD_ISSET(fd, &wfds) && FD_ISSET(fd, &rfds))
         {
            // readability flag switched, check to see if the connection has
            // been shutdown, by seeing if recv() will return 0 (do a peek so
            // as not to disturb real data)
            char buf;
            int flags = MSG_PEEK;
#ifdef MSG_DONTWAIT
            flags |= MSG_DONTWAIT;
#endif
            rval = SOCKET_MACRO_recv(fd, &buf, 1, flags);
            if(rval == 0)
            {
               // connection closed
               rval = -1;
               errno = EPIPE;
            }
            else if(rval > 0)
            {
               // connection not closed, but write timed out/was not detected
               // (bytes are readable but we weren't looking for that)
               rval = 0;
            }
         }
      }

      if(rval < 0 && (errno == 0 || errno == EINPROGRESS || errno == EINTR))
      {
         // no error, just timed out, operation in progress,
         // or syscall interrupted
         rval = 0;

         // Note: handling EINTR could be changed to interrupt the current
         // thread if appropriate
      }

      // select() implementation may alter sets or timeout, so reset them
      // if calling select() again (not interrupted and timeout >= 0)
      if(rval == 0)
      {
         // clear sets and re-add file descriptor
         FD_ZERO(&rfds);
         FD_ZERO(&wfds);
         FD_ZERO(&exfds);
         FD_SET(fd, &rfds);
         FD_SET(fd, &wfds);
         FD_SET(fd, &exfds);

         // reset timeout
         to.tv_sec = 0;
         if(timeout < 0)
         {
            to.tv_usec = 0;
         }
         else
         {
            to.tv_usec = intck * INT64_C(1000);
         }
      }

      if(timeout != 0)
      {
         // decrement remaining time
         end = System::getCurrentMilliseconds();
         remaining -= (end - start);
         start = end;
         to.tv_usec = (remaining < intck ? remaining : intck) * INT64_C(1000);
      }
   }

   if(rval > 0)
   {
      if(t->isInterrupted())
      {
         rval = -1;
         errno = EINTR;

         // set interrupted exception
         ExceptionRef e = t->createInterruptedException();
         Exception::set(e);
      }
      else if(FD_ISSET(fd, &exfds) != 0)
      {
         // exception occurred with file descriptor, consider pipe broken,
         // cannot mark it as a bad file descriptor here or else it won't
         // be closed
         rval = -1;
         errno = EPIPE;
      }
   }

   return rval;
}

int SocketTools::select(
   int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds,
   int64_t timeout, const sigset_t* sigmask)
{
   int rval = 0;

// Note: disabled due to a lack of support in windows
//   // create timeout
//   struct timeval* tv = NULL;
//   struct timeval to;
//   if(timeout > 0)
//   {
//      // set timeout (1 millisecond is 1000 microseconds)
//      to.tv_sec = timeout / INT64_C(1000);
//      to.tv_usec = (timeout % INT64_C(1000)) * INT64_C(1000);
//      tv = &to;
//   }
//
//   // FIXME: signals supposedly don't make select() return in windows
//   // this needs to be tested and potentially remedied somehow
//
//   // FIXME: furthermore, even if we block SIGINT (interruption signal) up
//   // until we reach the select call -- and then unblock right before it
//   // the signal could still sneak in right before select() is called and
//   // control is transferred to the kernel, and therefore we'd handle the
//   // SIGINT before the select() call and select() wouldn't get interrupted
//   // (there is pselect() for doing that unblocking atomically, but
//   // it's UNIX only) -- this may be solved by writing to another file
//   // descriptor when we receive SIGINTs and checking that file descriptor
//   // as well as the one we are waiting on -- but this might not be a
//   // viable solution for windows
//
//   // block SIGINTs
//   blockSignal(SIGINT);
//
//   Thread* t = Thread::currentThread();
//   if(!t->isInterrupted())
//   {
//      // FIXME: pselect() required here to do atomic unblocking & selecting
//
//      // wait for file descriptors to be updated
//      unblockSignal(SIGINT);
//      rval = ::select(nfds, readfds, writefds, exceptfds, timeout);
//      if(rval < 0)
//      {
//         if(errno == EINTR)
//         {
//            // interrupt thread
//            t->interrupt();
//         }
//      }
//   }
//   else
//   {
//      rval = -1;
//      errno = EINTR;
//   }

   // clone file descriptor sets
   fd_set readfds2;
   fd_set writefds2;
   fd_set exceptfds2;

   if(readfds != NULL)
   {
      readfds2 = *readfds;
   }

   if(writefds != NULL)
   {
      writefds2 = *writefds;
   }

   if(exceptfds != NULL)
   {
      exceptfds2 = *exceptfds;
   }

   // set 20 millisecond interrupt check timeout (necessary because
   // windows lacks SIGNAL support to do interruptions properly)
   int64_t intck = INT64_C(20);

   // keep selecting (polling) until timeout is reached
   int64_t remaining = (timeout <= 0) ? intck : timeout;

   struct timeval to;
   if(timeout < 0)
   {
      // create instant timeout (polling)
      to.tv_sec = 0;
      to.tv_usec = 0;
   }
   else
   {
      // create 20 millisecond timeout (1 millisecond is 1000 microseconds)
      to.tv_sec = 0;
      to.tv_usec = (remaining < intck ? remaining : intck) * INT64_C(1000);
   }

   uint64_t start = System::getCurrentMilliseconds();
   uint64_t end;

   Thread* t = Thread::currentThread();
   while(remaining > 0 && rval == 0 && !t->isInterrupted())
   {
      // wait for file descriptors to be updated
      rval = ::select(nfds, readfds, writefds, exceptfds, &to);

      if(rval < 0 && (errno == 0 || errno == EINPROGRESS || errno == EINTR))
      {
         // no error, just timed out, operation in progress,
         // or syscall interrupted
         rval = 0;

         // Note: handling EINTR could be changed to interrupt the current
         // thread if appropriate
      }

      // select() implementation may alter sets or timeout, so reset them
      // if calling select() again (not interrupted and timeout >= 0)
      if(rval == 0 && timeout >= 0)
      {
         // reset file descriptor sets
         if(readfds != NULL)
         {
            *readfds = readfds2;
         }

         if(writefds != NULL)
         {
            *writefds = writefds2;
         }

         if(exceptfds != NULL)
         {
            *exceptfds = exceptfds2;
         }

         // reset timeout
         to.tv_sec = 0;
         to.tv_usec = intck * INT64_C(1000);
      }

      if(timeout != 0)
      {
         // decrement remaining time
         end = System::getCurrentMilliseconds();
         remaining -= (end - start);
         start = end;
         to.tv_usec = (remaining < intck ? remaining : intck) * INT64_C(1000);
      }
   }

   if(t->isInterrupted())
   {
      rval = -1;
      errno = EINTR;

      // set interrupted exception
      ExceptionRef e = t->createInterruptedException();
      Exception::set(e);
   }

   return rval;
}

std::string SocketTools::getHostname()
{
   char tmp[HOST_NAME_MAX + 1];
   memset(tmp, 0, HOST_NAME_MAX + 1);
   gethostname(tmp, HOST_NAME_MAX);
   return tmp;
}
<commit_msg>Fixed bug with specifying number of fd structs to poll.<commit_after>/*
 * Copyright (c) 2007-2010 Digital Bazaar, Inc. All rights reserved.
 */
#define __STDC_CONSTANT_MACROS

#include "monarch/net/SocketTools.h"

#include "monarch/net/WindowsSupport.h"
#include "monarch/rt/Thread.h"
#include "monarch/rt/System.h"

#include <limits.h>
#ifndef WIN32
#include <poll.h>
#endif

using namespace monarch::net;
using namespace monarch::rt;

#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 255
#endif

int SocketTools::poll(bool read, int fd, int64_t timeout)
{
#ifdef WIN32
   return select(read, fd, timeout);
#else
   int rval = 0;

   // create poll set
   struct pollfd fds;
   fds.fd = fd;
   fds.events = read ? POLLIN : POLLOUT;

   // set 20 millisecond interrupt check timeout (currently necessary to
   // enable thread interruptions)
   int intck = INT32_C(20);

   // keep selecting (polling) until timeout is reached
   int64_t remaining = (timeout <= 0) ? intck : timeout;

   int to;
   if(timeout < 0)
   {
      // create instant timeout (polling)
      to = 0;
   }
   else
   {
      // create intck millisecond timeout
      to = (remaining < intck ? (int)remaining : intck);
   }

   uint64_t start = System::getCurrentMilliseconds();
   uint64_t end;

   Thread* t = Thread::currentThread();
   while(remaining > 0 && rval == 0 && !t->isInterrupted())
   {
      // wait for file descriptor to be updated
      rval = ::poll(&fds, 1, to);

      // check for error events
      if(rval > 0)
      {
         // remote side hung up
         if(fds.revents & POLLHUP)
         {
            rval = -1;
            errno = EPIPE;
         }
         // file descriptor not open
         else if(fds.revents & POLLNVAL)
         {
            rval = -1;
            errno = EBADF;
         }
         // error
         else if(fds.revents & POLLERR)
         {
            // some kind of IO error
            rval = -1;
            errno = EIO;
         }
      }
      else if(rval == -1 && errno == EINTR)
      {
         // no error, syscall interrupted
         rval = 0;
      }

      // decrement timeout
      if(rval == 0 && timeout != 0)
      {
         // decrement remaining time
         end = System::getCurrentMilliseconds();
         remaining -= (end - start);
         start = end;
         to = (remaining < intck ? (int)remaining : intck);
      }
   }

   if(rval > 0)
   {
      if(t->isInterrupted())
      {
         rval = -1;
         errno = EINTR;

         // set interrupted exception
         ExceptionRef e = t->createInterruptedException();
         Exception::set(e);
      }
   }

   return rval;
#endif
}

#ifdef WIN32
int SocketTools::select(bool read, unsigned int fd, int64_t timeout)
#else
int SocketTools::select(bool read, int fd, int64_t timeout)
#endif
{
   int rval = 0;

   // create a file descriptor set to read on
   fd_set rfds;
   FD_ZERO(&rfds);

   // create a file descriptor set to write on
   fd_set wfds;
   FD_ZERO(&wfds);

   // create a file descriptor set to check for exceptions on
   fd_set exfds;
   FD_ZERO(&exfds);

   // add file descriptor to sets
   FD_SET(fd, &rfds);
   FD_SET(fd, &wfds);
   FD_SET(fd, &exfds);

   // "n" parameter is the highest numbered descriptor plus 1
#ifdef WIN32
   unsigned int n = fd + 1;
#else
   int n = fd + 1;
#endif

   // set 20 millisecond interrupt check timeout (necessary because
   // windows lacks SIGNAL support to do interruptions properly)
   int64_t intck = INT64_C(20);

   // keep selecting (polling) until timeout is reached
   int64_t remaining = (timeout <= 0) ? intck : timeout;

   struct timeval to;
   to.tv_sec = 0;
   if(timeout < 0)
   {
      // create instant timeout (polling)
      to.tv_usec = 0;
   }
   else
   {
      // create intck millisecond timeout (1 millisecond is 1000 microseconds)
      to.tv_usec = (remaining < intck ? remaining : intck) * INT64_C(1000);
   }

   uint64_t start = System::getCurrentMilliseconds();
   uint64_t end;

   Thread* t = Thread::currentThread();
   while(remaining > 0 && rval == 0 && !t->isInterrupted())
   {
      // wait for file descriptors to be updated
      if(read)
      {
         // wait for readability
         rval = ::select(n, &rfds, NULL, &exfds, &to);
      }
      else
      {
         // wait for readability and writability
         //
         // Note: We must test to see if the pipe is broken by
         // testing for readability -- as it will occur if the
         // connection closes due to TCP sending an RST to the
         // socket ... and this will cause recv() to return 0
         rval = ::select(n, &rfds, &wfds, &exfds, &to);
         if(rval > 0 && !FD_ISSET(fd, &wfds) && FD_ISSET(fd, &rfds))
         {
            // readability flag switched, check to see if the connection has
            // been shutdown, by seeing if recv() will return 0 (do a peek so
            // as not to disturb real data)
            char buf;
            int flags = MSG_PEEK;
#ifdef MSG_DONTWAIT
            flags |= MSG_DONTWAIT;
#endif
            rval = SOCKET_MACRO_recv(fd, &buf, 1, flags);
            if(rval == 0)
            {
               // connection closed
               rval = -1;
               errno = EPIPE;
            }
            else if(rval > 0)
            {
               // connection not closed, but write timed out/was not detected
               // (bytes are readable but we weren't looking for that)
               rval = 0;
            }
         }
      }

      if(rval < 0 && (errno == 0 || errno == EINPROGRESS || errno == EINTR))
      {
         // no error, just timed out, operation in progress,
         // or syscall interrupted
         rval = 0;

         // Note: handling EINTR could be changed to interrupt the current
         // thread if appropriate
      }

      // select() implementation may alter sets or timeout, so reset them
      // if calling select() again (not interrupted and timeout >= 0)
      if(rval == 0)
      {
         // clear sets and re-add file descriptor
         FD_ZERO(&rfds);
         FD_ZERO(&wfds);
         FD_ZERO(&exfds);
         FD_SET(fd, &rfds);
         FD_SET(fd, &wfds);
         FD_SET(fd, &exfds);

         // reset timeout
         to.tv_sec = 0;
         if(timeout < 0)
         {
            to.tv_usec = 0;
         }
         else
         {
            to.tv_usec = intck * INT64_C(1000);
         }
      }

      if(timeout != 0)
      {
         // decrement remaining time
         end = System::getCurrentMilliseconds();
         remaining -= (end - start);
         start = end;
         to.tv_usec = (remaining < intck ? remaining : intck) * INT64_C(1000);
      }
   }

   if(rval > 0)
   {
      if(t->isInterrupted())
      {
         rval = -1;
         errno = EINTR;

         // set interrupted exception
         ExceptionRef e = t->createInterruptedException();
         Exception::set(e);
      }
      else if(FD_ISSET(fd, &exfds) != 0)
      {
         // exception occurred with file descriptor, consider pipe broken,
         // cannot mark it as a bad file descriptor here or else it won't
         // be closed
         rval = -1;
         errno = EPIPE;
      }
   }

   return rval;
}

int SocketTools::select(
   int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds,
   int64_t timeout, const sigset_t* sigmask)
{
   int rval = 0;

// Note: disabled due to a lack of support in windows
//   // create timeout
//   struct timeval* tv = NULL;
//   struct timeval to;
//   if(timeout > 0)
//   {
//      // set timeout (1 millisecond is 1000 microseconds)
//      to.tv_sec = timeout / INT64_C(1000);
//      to.tv_usec = (timeout % INT64_C(1000)) * INT64_C(1000);
//      tv = &to;
//   }
//
//   // FIXME: signals supposedly don't make select() return in windows
//   // this needs to be tested and potentially remedied somehow
//
//   // FIXME: furthermore, even if we block SIGINT (interruption signal) up
//   // until we reach the select call -- and then unblock right before it
//   // the signal could still sneak in right before select() is called and
//   // control is transferred to the kernel, and therefore we'd handle the
//   // SIGINT before the select() call and select() wouldn't get interrupted
//   // (there is pselect() for doing that unblocking atomically, but
//   // it's UNIX only) -- this may be solved by writing to another file
//   // descriptor when we receive SIGINTs and checking that file descriptor
//   // as well as the one we are waiting on -- but this might not be a
//   // viable solution for windows
//
//   // block SIGINTs
//   blockSignal(SIGINT);
//
//   Thread* t = Thread::currentThread();
//   if(!t->isInterrupted())
//   {
//      // FIXME: pselect() required here to do atomic unblocking & selecting
//
//      // wait for file descriptors to be updated
//      unblockSignal(SIGINT);
//      rval = ::select(nfds, readfds, writefds, exceptfds, timeout);
//      if(rval < 0)
//      {
//         if(errno == EINTR)
//         {
//            // interrupt thread
//            t->interrupt();
//         }
//      }
//   }
//   else
//   {
//      rval = -1;
//      errno = EINTR;
//   }

   // clone file descriptor sets
   fd_set readfds2;
   fd_set writefds2;
   fd_set exceptfds2;

   if(readfds != NULL)
   {
      readfds2 = *readfds;
   }

   if(writefds != NULL)
   {
      writefds2 = *writefds;
   }

   if(exceptfds != NULL)
   {
      exceptfds2 = *exceptfds;
   }

   // set 20 millisecond interrupt check timeout (necessary because
   // windows lacks SIGNAL support to do interruptions properly)
   int64_t intck = INT64_C(20);

   // keep selecting (polling) until timeout is reached
   int64_t remaining = (timeout <= 0) ? intck : timeout;

   struct timeval to;
   if(timeout < 0)
   {
      // create instant timeout (polling)
      to.tv_sec = 0;
      to.tv_usec = 0;
   }
   else
   {
      // create 20 millisecond timeout (1 millisecond is 1000 microseconds)
      to.tv_sec = 0;
      to.tv_usec = (remaining < intck ? remaining : intck) * INT64_C(1000);
   }

   uint64_t start = System::getCurrentMilliseconds();
   uint64_t end;

   Thread* t = Thread::currentThread();
   while(remaining > 0 && rval == 0 && !t->isInterrupted())
   {
      // wait for file descriptors to be updated
      rval = ::select(nfds, readfds, writefds, exceptfds, &to);

      if(rval < 0 && (errno == 0 || errno == EINPROGRESS || errno == EINTR))
      {
         // no error, just timed out, operation in progress,
         // or syscall interrupted
         rval = 0;

         // Note: handling EINTR could be changed to interrupt the current
         // thread if appropriate
      }

      // select() implementation may alter sets or timeout, so reset them
      // if calling select() again (not interrupted and timeout >= 0)
      if(rval == 0 && timeout >= 0)
      {
         // reset file descriptor sets
         if(readfds != NULL)
         {
            *readfds = readfds2;
         }

         if(writefds != NULL)
         {
            *writefds = writefds2;
         }

         if(exceptfds != NULL)
         {
            *exceptfds = exceptfds2;
         }

         // reset timeout
         to.tv_sec = 0;
         to.tv_usec = intck * INT64_C(1000);
      }

      if(timeout != 0)
      {
         // decrement remaining time
         end = System::getCurrentMilliseconds();
         remaining -= (end - start);
         start = end;
         to.tv_usec = (remaining < intck ? remaining : intck) * INT64_C(1000);
      }
   }

   if(t->isInterrupted())
   {
      rval = -1;
      errno = EINTR;

      // set interrupted exception
      ExceptionRef e = t->createInterruptedException();
      Exception::set(e);
   }

   return rval;
}

std::string SocketTools::getHostname()
{
   char tmp[HOST_NAME_MAX + 1];
   memset(tmp, 0, HOST_NAME_MAX + 1);
   gethostname(tmp, HOST_NAME_MAX);
   return tmp;
}
<|endoftext|>


<commit_before>/*
 * BLEServer.cpp
 *
 *  Created on: Apr 16, 2017
 *      Author: kolban
 */

#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include <esp_log.h>
#include <esp_bt.h>
#include <esp_bt_main.h>
#include <esp_gap_ble_api.h>
//#include <esp_gatts_api.h>
#include "BLEDevice.h"
#include "BLEServer.h"
#include "BLEService.h"
#include "BLEUtils.h"
#include <string.h>
#include <string>
#include <gatt_api.h>
#include <unordered_set>
#ifdef ARDUINO_ARCH_ESP32
#include "esp32-hal-log.h"
#endif

static const char* LOG_TAG = "BLEServer";

/**
 * @brief Construct a %BLE Server
 *
 * This class is not designed to be individually instantiated.  Instead one should create a server by asking
 * the BLEDevice class.
 */
BLEServer::BLEServer() {
	m_appId            = -1;
	m_gatts_if         = -1;
	m_connectedCount   = 0;
	m_connId           = -1;
	m_pServerCallbacks = nullptr;

	//createApp(0);
} // BLEServer

void BLEServer::createApp(uint16_t appId) {
	m_appId = appId;
	registerApp();
} // createApp

/**
 * @brief Create a %BLE Service.
 *
 * With a %BLE server, we can host one or more services.  Invoking this function causes the creation of a definition
 * of a new service.  Every service must have a unique UUID.
 * @param [in] uuid The UUID of the new service.
 * @return A reference to the new service object.
 */
BLEService* BLEServer::createService(const char* uuid) {
	return createService(BLEUUID(uuid));
}

/**
 * @brief Create a %BLE Service.
 *
 * With a %BLE server, we can host one or more services.  Invoking this function causes the creation of a definition
 * of a new service.  Every service must have a unique UUID.
 * @param [in] uuid The UUID of the new service.
 * @param [in] numHandles The maximum number of handles associated with this service.
 * @return A reference to the new service object.
 */
BLEService* BLEServer::createService(BLEUUID uuid, uint32_t numHandles) {
	ESP_LOGD(LOG_TAG, ">> createService - %s", uuid.toString().c_str());
	m_semaphoreCreateEvt.take("createService");

	// Check that a service with the supplied UUID does not already exist.
	if (m_serviceMap.getByUUID(uuid) != nullptr) {
		ESP_LOGE(LOG_TAG, "<< Attempt to create a new service with uuid %s but a service with that UUID already exists.",
			uuid.toString().c_str());
		m_semaphoreCreateEvt.give();
		return nullptr;
	}

	BLEService* pService = new BLEService(uuid, numHandles);
	m_serviceMap.setByUUID(uuid, pService); // Save a reference to this service being on this server.
	pService->executeCreate(this);          // Perform the API calls to actually create the service.

	m_semaphoreCreateEvt.wait("createService");

	ESP_LOGD(LOG_TAG, "<< createService");
	return pService;
} // createService

/**
 * @brief Retrieve the advertising object that can be used to advertise the existence of the server.
 *
 * @return An advertising object.
 */
BLEAdvertising* BLEServer::getAdvertising() {
	return &m_bleAdvertising;
}

uint16_t BLEServer::getConnId() {
	return m_connId;
}

/**
 * @brief Return the number of connected clients.
 * @return The number of connected clients.
 */
uint32_t BLEServer::getConnectedCount() {
	return m_connectedCount;
} // getConnectedCount

uint16_t BLEServer::getGattsIf() {
	return m_gatts_if;
}

/**
 * @brief Handle a received GAP event.
 *
 * @param [in] event
 * @param [in] param
 */
void BLEServer::handleGAPEvent(
		esp_gap_ble_cb_event_t  event,
		esp_ble_gap_cb_param_t* param) {
	ESP_LOGD(LOG_TAG, "BLEServer ... handling GAP event!");
	switch(event) {
		case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: {
			/*
			esp_ble_adv_params_t adv_params;
			adv_params.adv_int_min       = 0x20;
			adv_params.adv_int_max       = 0x40;
			adv_params.adv_type          = ADV_TYPE_IND;
			adv_params.own_addr_type     = BLE_ADDR_TYPE_PUBLIC;
			adv_params.channel_map       = ADV_CHNL_ALL;
			adv_params.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY;
			ESP_LOGD(tag, "Starting advertising");
			esp_err_t errRc = ::esp_ble_gap_start_advertising(&adv_params);
			if (errRc != ESP_OK) {
				ESP_LOGE(tag, "esp_ble_gap_start_advertising: rc=%d %s", errRc, espToString(errRc));
				return;
			}
			*/
			break;
		}

		default:
			break;
	}
} // handleGAPEvent

/**
 * @brief Handle a GATT Server Event.
 *
 * @param [in] event
 * @param [in] gatts_if
 * @param [in] param
 *
 */
void BLEServer::handleGATTServerEvent(
		esp_gatts_cb_event_t      event,
		esp_gatt_if_t             gatts_if,
		esp_ble_gatts_cb_param_t* param) {

	ESP_LOGD(LOG_TAG, ">> handleGATTServerEvent: %s",
		BLEUtils::gattServerEventTypeToString(event).c_str());

	// Invoke the handler for every Service we have.
	m_serviceMap.handleGATTServerEvent(event, gatts_if, param);

	switch(event) {
		// ESP_GATTS_ADD_CHAR_EVT - Indicate that a characteristic was added to the service.
		// add_char:
		// - esp_gatt_status_t status
		// - uint16_t          attr_handle
		// - uint16_t          service_handle
		// - esp_bt_uuid_t     char_uuid
		//
		case ESP_GATTS_ADD_CHAR_EVT: {
			break;
		} // ESP_GATTS_ADD_CHAR_EVT

		// ESP_GATTS_CONNECT_EVT
		// connect:
		// - uint16_t      conn_id
		// - esp_bd_addr_t remote_bda
		// - bool          is_connected
		//
		case ESP_GATTS_CONNECT_EVT: {
			m_connId = param->connect.conn_id; // Save the connection id.
			if (m_pServerCallbacks != nullptr) {
				m_pServerCallbacks->onConnect(this);
			}
			m_connectedCount++;   // Increment the number of connected devices count.
			break;
		} // ESP_GATTS_CONNECT_EVT

		// ESP_GATTS_CREATE_EVT
		// Called when a new service is registered as having been created.
		//
		// create:
		// * esp_gatt_status_t  status
		// * uint16_t           service_handle
		// * esp_gatt_srvc_id_t service_id
		//
		case ESP_GATTS_CREATE_EVT: {
			BLEService* pService = m_serviceMap.getByUUID(param->create.service_id.id.uuid);
			m_serviceMap.setByHandle(param->create.service_handle, pService);
			m_semaphoreCreateEvt.give();
			break;
		} // ESP_GATTS_CREATE_EVT

		// ESP_GATTS_DISCONNECT_EVT
		//
		// disconnect
		// - uint16_t      conn_id
		// - esp_bd_addr_t remote_bda
		// - bool          is_connected
		//
		// If we receive a disconnect event then invoke the callback for disconnects (if one is present).
		// we also want to start advertising again.
		case ESP_GATTS_DISCONNECT_EVT: {
			m_connectedCount--;                          // Decrement the number of connected devices count.
			if (m_pServerCallbacks != nullptr) {         // If we have callbacks, call now.
				m_pServerCallbacks->onDisconnect(this);
			}
			startAdvertising(); //- do this with some delay from the loop()
			break;
		} // ESP_GATTS_DISCONNECT_EVT

		// ESP_GATTS_READ_EVT - A request to read the value of a characteristic has arrived.
		//
		// read:
		// - uint16_t      conn_id
		// - uint32_t      trans_id
		// - esp_bd_addr_t bda
		// - uint16_t      handle
		// - uint16_t      offset
		// - bool          is_long
		// - bool          need_rsp
		//
		case ESP_GATTS_READ_EVT: {
			break;
		} // ESP_GATTS_READ_EVT

		// ESP_GATTS_REG_EVT
		// reg:
		// - esp_gatt_status_t status
		// - uint16_t app_id
		//
		case ESP_GATTS_REG_EVT: {
			m_gatts_if = gatts_if;
			m_semaphoreRegisterAppEvt.give(); // Unlock the mutex waiting for the registration of the app.
			break;
		} // ESP_GATTS_REG_EVT

		// ESP_GATTS_WRITE_EVT - A request to write the value of a characteristic has arrived.
		//
		// write:
		// - uint16_t      conn_id
		// - uint16_t      trans_id
		// - esp_bd_addr_t bda
		// - uint16_t      handle
		// - uint16_t      offset
		// - bool          need_rsp
		// - bool          is_prep
		// - uint16_t      len
		// - uint8_t*      value
		//
		case ESP_GATTS_WRITE_EVT: {
			break;
		}

		default: {
			break;
		}
	}
	ESP_LOGD(LOG_TAG, "<< handleGATTServerEvent");
} // handleGATTServerEvent

/**
 * @brief Register the app.
 *
 * @return N/A
 */
void BLEServer::registerApp() {
	ESP_LOGD(LOG_TAG, ">> registerApp - %d", m_appId);
	m_semaphoreRegisterAppEvt.take("registerApp"); // Take the mutex, will be released by ESP_GATTS_REG_EVT event.
	::esp_ble_gatts_app_register(m_appId);
	m_semaphoreRegisterAppEvt.wait("registerApp");
	ESP_LOGD(LOG_TAG, "<< registerApp");
} // registerApp

/**
 * @brief Set the server callbacks.
 *
 * As a %BLE server operates, it will generate server level events such as a new client connecting or a previous client
 * disconnecting.  This function can be called to register a callback handler that will be invoked when these
 * events are detected.
 *
 * @param [in] pCallbacks The callbacks to be invoked.
 */
void BLEServer::setCallbacks(BLEServerCallbacks* pCallbacks) {
	m_pServerCallbacks = pCallbacks;
} // setCallbacks

/**
 * @brief Start advertising.
 *
 * Start the server advertising its existence.  This is a convenience function and is equivalent to
 * retrieving the advertising object and invoking start upon it.
 */
void BLEServer::startAdvertising() {
	ESP_LOGD(LOG_TAG, ">> startAdvertising");
	m_bleAdvertising.start();
	ESP_LOGD(LOG_TAG, "<< startAdvertising");
} // startAdvertising

void BLEServerCallbacks::onConnect(BLEServer* pServer) {
	ESP_LOGD("BLEServerCallbacks", ">> onConnect(): Default");
	ESP_LOGD("BLEServerCallbacks", "Device: %s", BLEDevice::toString().c_str());
	ESP_LOGD("BLEServerCallbacks", "<< onConnect()");
} // onConnect

void BLEServerCallbacks::onDisconnect(BLEServer* pServer) {
	ESP_LOGD("BLEServerCallbacks", ">> onDisconnect(): Default");
	ESP_LOGD("BLEServerCallbacks", "Device: %s", BLEDevice::toString().c_str());
	ESP_LOGD("BLEServerCallbacks", "<< onDisconnect()");
} // onDisconnect

#endif // CONFIG_BT_ENABLED
<commit_msg>Update BLEServer.cpp<commit_after>/*
 * BLEServer.cpp
 *
 *  Created on: Apr 16, 2017
 *      Author: kolban
 */

#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include <esp_log.h>
#include <esp_bt.h>
#include <esp_bt_main.h>
#include <esp_gap_ble_api.h>
//#include <esp_gatts_api.h>
#include "BLEDevice.h"
#include "BLEServer.h"
#include "BLEService.h"
#include "BLEUtils.h"
#include <string.h>
#include <string>
#include <unordered_set>
#ifdef ARDUINO_ARCH_ESP32
#include "esp32-hal-log.h"
#endif

static const char* LOG_TAG = "BLEServer";

/**
 * @brief Construct a %BLE Server
 *
 * This class is not designed to be individually instantiated.  Instead one should create a server by asking
 * the BLEDevice class.
 */
BLEServer::BLEServer() {
	m_appId            = -1;
	m_gatts_if         = -1;
	m_connectedCount   = 0;
	m_connId           = -1;
	m_pServerCallbacks = nullptr;

	//createApp(0);
} // BLEServer

void BLEServer::createApp(uint16_t appId) {
	m_appId = appId;
	registerApp();
} // createApp

/**
 * @brief Create a %BLE Service.
 *
 * With a %BLE server, we can host one or more services.  Invoking this function causes the creation of a definition
 * of a new service.  Every service must have a unique UUID.
 * @param [in] uuid The UUID of the new service.
 * @return A reference to the new service object.
 */
BLEService* BLEServer::createService(const char* uuid) {
	return createService(BLEUUID(uuid));
}

/**
 * @brief Create a %BLE Service.
 *
 * With a %BLE server, we can host one or more services.  Invoking this function causes the creation of a definition
 * of a new service.  Every service must have a unique UUID.
 * @param [in] uuid The UUID of the new service.
 * @param [in] numHandles The maximum number of handles associated with this service.
 * @return A reference to the new service object.
 */
BLEService* BLEServer::createService(BLEUUID uuid, uint32_t numHandles) {
	ESP_LOGD(LOG_TAG, ">> createService - %s", uuid.toString().c_str());
	m_semaphoreCreateEvt.take("createService");

	// Check that a service with the supplied UUID does not already exist.
	if (m_serviceMap.getByUUID(uuid) != nullptr) {
		ESP_LOGE(LOG_TAG, "<< Attempt to create a new service with uuid %s but a service with that UUID already exists.",
			uuid.toString().c_str());
		m_semaphoreCreateEvt.give();
		return nullptr;
	}

	BLEService* pService = new BLEService(uuid, numHandles);
	m_serviceMap.setByUUID(uuid, pService); // Save a reference to this service being on this server.
	pService->executeCreate(this);          // Perform the API calls to actually create the service.

	m_semaphoreCreateEvt.wait("createService");

	ESP_LOGD(LOG_TAG, "<< createService");
	return pService;
} // createService

/**
 * @brief Retrieve the advertising object that can be used to advertise the existence of the server.
 *
 * @return An advertising object.
 */
BLEAdvertising* BLEServer::getAdvertising() {
	return &m_bleAdvertising;
}

uint16_t BLEServer::getConnId() {
	return m_connId;
}

/**
 * @brief Return the number of connected clients.
 * @return The number of connected clients.
 */
uint32_t BLEServer::getConnectedCount() {
	return m_connectedCount;
} // getConnectedCount

uint16_t BLEServer::getGattsIf() {
	return m_gatts_if;
}

/**
 * @brief Handle a received GAP event.
 *
 * @param [in] event
 * @param [in] param
 */
void BLEServer::handleGAPEvent(
		esp_gap_ble_cb_event_t  event,
		esp_ble_gap_cb_param_t* param) {
	ESP_LOGD(LOG_TAG, "BLEServer ... handling GAP event!");
	switch(event) {
		case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: {
			/*
			esp_ble_adv_params_t adv_params;
			adv_params.adv_int_min       = 0x20;
			adv_params.adv_int_max       = 0x40;
			adv_params.adv_type          = ADV_TYPE_IND;
			adv_params.own_addr_type     = BLE_ADDR_TYPE_PUBLIC;
			adv_params.channel_map       = ADV_CHNL_ALL;
			adv_params.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY;
			ESP_LOGD(tag, "Starting advertising");
			esp_err_t errRc = ::esp_ble_gap_start_advertising(&adv_params);
			if (errRc != ESP_OK) {
				ESP_LOGE(tag, "esp_ble_gap_start_advertising: rc=%d %s", errRc, espToString(errRc));
				return;
			}
			*/
			break;
		}

		default:
			break;
	}
} // handleGAPEvent

/**
 * @brief Handle a GATT Server Event.
 *
 * @param [in] event
 * @param [in] gatts_if
 * @param [in] param
 *
 */
void BLEServer::handleGATTServerEvent(
		esp_gatts_cb_event_t      event,
		esp_gatt_if_t             gatts_if,
		esp_ble_gatts_cb_param_t* param) {

	ESP_LOGD(LOG_TAG, ">> handleGATTServerEvent: %s",
		BLEUtils::gattServerEventTypeToString(event).c_str());

	// Invoke the handler for every Service we have.
	m_serviceMap.handleGATTServerEvent(event, gatts_if, param);

	switch(event) {
		// ESP_GATTS_ADD_CHAR_EVT - Indicate that a characteristic was added to the service.
		// add_char:
		// - esp_gatt_status_t status
		// - uint16_t          attr_handle
		// - uint16_t          service_handle
		// - esp_bt_uuid_t     char_uuid
		//
		case ESP_GATTS_ADD_CHAR_EVT: {
			break;
		} // ESP_GATTS_ADD_CHAR_EVT

		// ESP_GATTS_CONNECT_EVT
		// connect:
		// - uint16_t      conn_id
		// - esp_bd_addr_t remote_bda
		// - bool          is_connected
		//
		case ESP_GATTS_CONNECT_EVT: {
			m_connId = param->connect.conn_id; // Save the connection id.
			if (m_pServerCallbacks != nullptr) {
				m_pServerCallbacks->onConnect(this);
			}
			m_connectedCount++;   // Increment the number of connected devices count.
			break;
		} // ESP_GATTS_CONNECT_EVT

		// ESP_GATTS_CREATE_EVT
		// Called when a new service is registered as having been created.
		//
		// create:
		// * esp_gatt_status_t  status
		// * uint16_t           service_handle
		// * esp_gatt_srvc_id_t service_id
		//
		case ESP_GATTS_CREATE_EVT: {
			BLEService* pService = m_serviceMap.getByUUID(param->create.service_id.id.uuid);
			m_serviceMap.setByHandle(param->create.service_handle, pService);
			m_semaphoreCreateEvt.give();
			break;
		} // ESP_GATTS_CREATE_EVT

		// ESP_GATTS_DISCONNECT_EVT
		//
		// disconnect
		// - uint16_t      conn_id
		// - esp_bd_addr_t remote_bda
		// - bool          is_connected
		//
		// If we receive a disconnect event then invoke the callback for disconnects (if one is present).
		// we also want to start advertising again.
		case ESP_GATTS_DISCONNECT_EVT: {
			m_connectedCount--;                          // Decrement the number of connected devices count.
			if (m_pServerCallbacks != nullptr) {         // If we have callbacks, call now.
				m_pServerCallbacks->onDisconnect(this);
			}
			startAdvertising(); //- do this with some delay from the loop()
			break;
		} // ESP_GATTS_DISCONNECT_EVT

		// ESP_GATTS_READ_EVT - A request to read the value of a characteristic has arrived.
		//
		// read:
		// - uint16_t      conn_id
		// - uint32_t      trans_id
		// - esp_bd_addr_t bda
		// - uint16_t      handle
		// - uint16_t      offset
		// - bool          is_long
		// - bool          need_rsp
		//
		case ESP_GATTS_READ_EVT: {
			break;
		} // ESP_GATTS_READ_EVT

		// ESP_GATTS_REG_EVT
		// reg:
		// - esp_gatt_status_t status
		// - uint16_t app_id
		//
		case ESP_GATTS_REG_EVT: {
			m_gatts_if = gatts_if;
			m_semaphoreRegisterAppEvt.give(); // Unlock the mutex waiting for the registration of the app.
			break;
		} // ESP_GATTS_REG_EVT

		// ESP_GATTS_WRITE_EVT - A request to write the value of a characteristic has arrived.
		//
		// write:
		// - uint16_t      conn_id
		// - uint16_t      trans_id
		// - esp_bd_addr_t bda
		// - uint16_t      handle
		// - uint16_t      offset
		// - bool          need_rsp
		// - bool          is_prep
		// - uint16_t      len
		// - uint8_t*      value
		//
		case ESP_GATTS_WRITE_EVT: {
			break;
		}

		default: {
			break;
		}
	}
	ESP_LOGD(LOG_TAG, "<< handleGATTServerEvent");
} // handleGATTServerEvent

/**
 * @brief Register the app.
 *
 * @return N/A
 */
void BLEServer::registerApp() {
	ESP_LOGD(LOG_TAG, ">> registerApp - %d", m_appId);
	m_semaphoreRegisterAppEvt.take("registerApp"); // Take the mutex, will be released by ESP_GATTS_REG_EVT event.
	::esp_ble_gatts_app_register(m_appId);
	m_semaphoreRegisterAppEvt.wait("registerApp");
	ESP_LOGD(LOG_TAG, "<< registerApp");
} // registerApp

/**
 * @brief Set the server callbacks.
 *
 * As a %BLE server operates, it will generate server level events such as a new client connecting or a previous client
 * disconnecting.  This function can be called to register a callback handler that will be invoked when these
 * events are detected.
 *
 * @param [in] pCallbacks The callbacks to be invoked.
 */
void BLEServer::setCallbacks(BLEServerCallbacks* pCallbacks) {
	m_pServerCallbacks = pCallbacks;
} // setCallbacks

/**
 * @brief Start advertising.
 *
 * Start the server advertising its existence.  This is a convenience function and is equivalent to
 * retrieving the advertising object and invoking start upon it.
 */
void BLEServer::startAdvertising() {
	ESP_LOGD(LOG_TAG, ">> startAdvertising");
	m_bleAdvertising.start();
	ESP_LOGD(LOG_TAG, "<< startAdvertising");
} // startAdvertising

void BLEServerCallbacks::onConnect(BLEServer* pServer) {
	ESP_LOGD("BLEServerCallbacks", ">> onConnect(): Default");
	ESP_LOGD("BLEServerCallbacks", "Device: %s", BLEDevice::toString().c_str());
	ESP_LOGD("BLEServerCallbacks", "<< onConnect()");
} // onConnect

void BLEServerCallbacks::onDisconnect(BLEServer* pServer) {
	ESP_LOGD("BLEServerCallbacks", ">> onDisconnect(): Default");
	ESP_LOGD("BLEServerCallbacks", "Device: %s", BLEDevice::toString().c_str());
	ESP_LOGD("BLEServerCallbacks", "<< onDisconnect()");
} // onDisconnect

#endif // CONFIG_BT_ENABLED
<|endoftext|>